{"version":3,"file":"llmock.cjs","names":["loadFixtureFile","loadFixturesFromDir","entryToFixture","validateFixtures","normalizeResponse","imageResponseToFalJson","videoResponseToFalJson","createServer"],"sources":["../src/llmock.ts"],"sourcesContent":["import type {\n  AudioResponse,\n  ChaosConfig,\n  EmbeddingFixtureOpts,\n  FalQueueOpts,\n  Fixture,\n  FixtureFileEntry,\n  FixtureFileResponse,\n  FixtureMatch,\n  FixtureOpts,\n  FixtureResponse,\n  ImageResponse,\n  MockServerOptions,\n  Mountable,\n  RecordConfig,\n  ResponseFactory,\n  TranscriptionResponse,\n  VideoResponse,\n} from \"./types.js\";\nimport { createServer, type ServerInstance } from \"./server.js\";\nimport {\n  loadFixtureFile,\n  loadFixturesFromDir,\n  entryToFixture,\n  normalizeResponse,\n  validateFixtures,\n} from \"./fixture-loader.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\nimport { falJobs } from \"./fal-audio.js\";\nimport { falQueueStates, imageResponseToFalJson, videoResponseToFalJson } from \"./fal.js\";\n\nexport class LLMock {\n  private fixtures: Fixture[] = [];\n  private searchFixtures: SearchFixture[] = [];\n  private rerankFixtures: RerankFixture[] = [];\n  private moderationFixtures: ModerationFixture[] = [];\n  private mounts: Array<{ path: string; handler: Mountable }> = [];\n  private serverInstance: ServerInstance | null = null;\n  private options: MockServerOptions;\n\n  constructor(options?: MockServerOptions) {\n    this.options = options ?? {};\n  }\n\n  // ---- Fixture management ----\n\n  addFixture(fixture: Fixture): this {\n    this.fixtures.push(fixture);\n    return this;\n  }\n\n  addFixtures(fixtures: Fixture[]): this {\n    this.fixtures.push(...fixtures);\n    return this;\n  }\n\n  prependFixture(fixture: Fixture): this {\n    this.fixtures.unshift(fixture);\n    return this;\n  }\n\n  getFixtures(): readonly Fixture[] {\n    return this.fixtures;\n  }\n\n  loadFixtureFile(filePath: string): this {\n    this.fixtures.push(...loadFixtureFile(filePath));\n    return this;\n  }\n\n  loadFixtureDir(dirPath: string): this {\n    this.fixtures.push(...loadFixturesFromDir(dirPath));\n    return this;\n  }\n\n  /**\n   * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n   * Validates all fixtures and throws if any have severity \"error\".\n   */\n  addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n    let entries: FixtureFileEntry[];\n    if (typeof input === \"string\") {\n      try {\n        entries = JSON.parse(input);\n      } catch (err) {\n        throw new Error(\n          `addFixturesFromJSON: invalid JSON — ${err instanceof Error ? err.message : String(err)}`,\n        );\n      }\n    } else {\n      entries = input;\n    }\n    const converted = entries.map((e) => entryToFixture(e));\n    const issues = validateFixtures(converted);\n    const errors = issues.filter((i) => i.severity === \"error\");\n    if (errors.length > 0) {\n      throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n    }\n    this.fixtures.push(...converted);\n    return this;\n  }\n\n  // Uses length = 0 to preserve array reference identity — the running\n  // server reads this same array on every request.\n  clearFixtures(): this {\n    this.fixtures.length = 0;\n    return this;\n  }\n\n  // ---- Convenience ----\n\n  on(\n    match: FixtureMatch,\n    response: FixtureFileResponse | ResponseFactory,\n    opts?: FixtureOpts,\n  ): this {\n    return this.addFixture({\n      match,\n      response: typeof response === \"function\" ? response : normalizeResponse(response),\n      ...opts,\n    });\n  }\n\n  onMessage(\n    pattern: string | RegExp,\n    response: FixtureFileResponse | ResponseFactory,\n    opts?: FixtureOpts,\n  ): this {\n    return this.on({ userMessage: pattern }, response, opts);\n  }\n\n  onEmbedding(\n    pattern: string | RegExp,\n    response: FixtureFileResponse | ResponseFactory,\n    opts?: EmbeddingFixtureOpts,\n  ): this {\n    return this.on({ inputText: pattern }, response, opts);\n  }\n\n  onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n    const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n    return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n  }\n\n  onToolCall(\n    name: string,\n    response: FixtureFileResponse | ResponseFactory,\n    opts?: FixtureOpts,\n  ): this {\n    return this.on({ toolName: name }, response, opts);\n  }\n\n  onToolResult(\n    id: string,\n    response: FixtureFileResponse | ResponseFactory,\n    opts?: FixtureOpts,\n  ): this {\n    return this.on({ toolCallId: id }, response, opts);\n  }\n\n  onTurn(\n    turn: number,\n    pattern: string | RegExp,\n    response: FixtureFileResponse | ResponseFactory,\n    opts?: FixtureOpts,\n  ): this {\n    return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n  }\n\n  onImage(prompt: string | RegExp, response: ImageResponse): this {\n    return this.addFixture({\n      match: { userMessage: prompt, endpoint: \"image\" },\n      response,\n    });\n  }\n\n  onSpeech(input: string | RegExp, response: AudioResponse): this {\n    return this.addFixture({\n      match: { userMessage: input, endpoint: \"speech\" },\n      response,\n    });\n  }\n\n  onTranscription(response: TranscriptionResponse): this {\n    return this.addFixture({\n      match: { endpoint: \"transcription\" },\n      response,\n    });\n  }\n\n  onTranslation(response: TranscriptionResponse): this {\n    return this.addFixture({\n      match: { endpoint: \"translation\" },\n      response,\n    });\n  }\n\n  onVideo(prompt: string | RegExp, response: VideoResponse): this {\n    return this.addFixture({\n      match: { userMessage: prompt, endpoint: \"video\" },\n      response,\n    });\n  }\n\n  onAudio(input: string | RegExp, response: AudioResponse): this {\n    return this.addFixture({ match: { userMessage: input }, response });\n  }\n\n  onSoundEffect(text: string | RegExp, response: AudioResponse): this {\n    return this.addFixture({\n      match: { userMessage: text, endpoint: \"audio-gen\" },\n      response,\n    });\n  }\n\n  onMusic(prompt: string | RegExp, response: AudioResponse): this {\n    return this.addFixture({\n      match: { userMessage: prompt, endpoint: \"audio-gen\" },\n      response,\n    });\n  }\n\n  onElevenLabsTTS(text: string | RegExp, response: AudioResponse): this {\n    return this.addFixture({\n      match: { userMessage: text, endpoint: \"elevenlabs-tts\" },\n      response,\n    });\n  }\n\n  onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this {\n    return this.addFixture({\n      match: { userMessage: prompt, endpoint: \"fal-audio\", ...(model ? { model } : {}) },\n      response,\n    });\n  }\n\n  // fal.queue.* is the dominant client API; onFalRun is a sync alias.\n  //\n  // `opts.billableUnits` rides through to the completed `queue-result`\n  // response's `x-fal-billable-units` header (emitted alongside\n  // `x-fal-request-id`), letting consumers like `@tanstack/ai-fal` surface a\n  // billed-units value on replay. Omit it to preserve the header-less default.\n  onFalQueue(modelOrPrompt: string | RegExp, response: unknown, opts?: FalQueueOpts): this {\n    const { billableUnits, ...fixtureOpts } = opts ?? {};\n    return this.addFixture({\n      match: { model: modelOrPrompt, endpoint: \"fal\" },\n      response: { json: response, ...(billableUnits != null ? { billableUnits } : {}) },\n      ...fixtureOpts,\n    });\n  }\n\n  onFalRun(modelOrPrompt: string | RegExp, response: unknown, opts?: FalQueueOpts): this {\n    return this.onFalQueue(modelOrPrompt, response, opts);\n  }\n\n  /**\n   * Register a fal.ai image fixture. Wraps an `ImageResponse` (the shape used\n   * by `onImage` and OpenAI/Azure image fixtures) into fal's image envelope\n   * before storing it as a `RawJSONResponse`. Defaults `width`/`height` to\n   * 1024 when the fixture's `ImageItem` doesn't carry them.\n   */\n  onFalImage(modelOrPrompt: string | RegExp, response: ImageResponse, opts?: FalQueueOpts): this {\n    return this.onFalQueue(modelOrPrompt, imageResponseToFalJson(response), opts);\n  }\n\n  /**\n   * Register a fal.ai video fixture. Wraps a `VideoResponse` into fal's video\n   * envelope (`{ video: { url, content_type, file_name, file_size }, seed }`)\n   * before storing it as a `RawJSONResponse`.\n   */\n  onFalVideo(modelOrPrompt: string | RegExp, response: VideoResponse, opts?: FalQueueOpts): this {\n    return this.onFalQueue(modelOrPrompt, videoResponseToFalJson(response), opts);\n  }\n\n  // ---- Service mock convenience methods ----\n\n  onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n    this.searchFixtures.push({ match: pattern, results });\n    return this;\n  }\n\n  onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n    this.rerankFixtures.push({ match: pattern, results });\n    return this;\n  }\n\n  onModerate(pattern: string | RegExp, result: ModerationResult): this {\n    this.moderationFixtures.push({ match: pattern, result });\n    return this;\n  }\n\n  /**\n   * Queue a one-shot error that will be returned for the next matching\n   * request, then automatically removed. Implemented as an internal fixture\n   * with a `predicate` that always matches (so it fires first) and spliced\n   * at the front of the fixture list.\n   */\n  nextRequestError(\n    status: number,\n    errorBody?: { message?: string; type?: string; code?: string },\n  ): this {\n    const errorResponse: FixtureResponse = {\n      error: {\n        message: errorBody?.message ?? \"Injected error\",\n        type: errorBody?.type ?? \"server_error\",\n        code: errorBody?.code,\n      },\n      status,\n    };\n    // An injected error is only a valid response for endpoints that can carry\n    // an error envelope. Mirror the router's endpoint-compat table\n    // (matchFixtureDiagnostic in router.ts): error responses are compatible\n    // with chat / embedding / realtime* / fal and with requests that carry no\n    // endpoint type, but NOT with multimedia endpoints (image, speech, video,\n    // transcription, …). Gating consumption on this prevents an incompatible\n    // request from matching the predicate and splicing — and thereby\n    // destroying — a one-shot error intended for a different endpoint before\n    // the router's own compat check would have skipped it.\n    const errorEndpointCompatible = (req: import(\"./types.js\").ChatCompletionRequest) => {\n      const reqEndpoint = req._endpointType as string | undefined;\n      if (\n        reqEndpoint === undefined ||\n        reqEndpoint === \"chat\" ||\n        reqEndpoint === \"embedding\" ||\n        reqEndpoint.startsWith(\"realtime\") ||\n        reqEndpoint === \"fal\"\n      ) {\n        return true;\n      }\n      return false;\n    };\n    const fixture: Fixture = {\n      match: { predicate: errorEndpointCompatible },\n      response: errorResponse,\n    };\n    // Insert at front so it matches before everything else\n    this.fixtures.unshift(fixture);\n    // Remove after first match — the journal records it so tests can assert.\n    // Only consume (and splice) when the request endpoint is compatible; an\n    // incompatible request returns false here, falls through to other\n    // fixtures, and leaves this error pending for its intended endpoint.\n    const original = fixture.match.predicate!;\n    fixture.match.predicate = (req) => {\n      const result = original(req);\n      if (result) {\n        // Remove synchronously on first match to prevent race conditions\n        const idx = this.fixtures.indexOf(fixture);\n        if (idx !== -1) this.fixtures.splice(idx, 1);\n      }\n      return result;\n    };\n    return this;\n  }\n\n  // ---- Mounts ----\n\n  mount(path: string, handler: Mountable): this {\n    this.mounts.push({ path, handler });\n\n    // If server is already running, wire up journal, registry, and baseUrl immediately\n    // so late mounts behave identically to pre-start mounts.\n    if (this.serverInstance) {\n      if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n      if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n      const registry = this.serverInstance.defaults.registry;\n      if (registry && handler.setRegistry) handler.setRegistry(registry);\n    }\n\n    return this;\n  }\n\n  // ---- Journal proxies ----\n\n  getRequests(): import(\"./types.js\").JournalEntry[] {\n    return this.journal.getAll();\n  }\n\n  getLastRequest(): import(\"./types.js\").JournalEntry | null {\n    return this.journal.getLast();\n  }\n\n  clearRequests(): void {\n    this.journal.clear();\n  }\n\n  resetMatchCounts(testId?: string): this {\n    if (this.serverInstance) {\n      this.serverInstance.journal.clearMatchCounts(testId);\n    }\n    return this;\n  }\n\n  // ---- Chaos ----\n\n  setChaos(config: ChaosConfig): this {\n    this.options.chaos = config;\n    return this;\n  }\n\n  clearChaos(): this {\n    delete this.options.chaos;\n    return this;\n  }\n\n  // ---- Recording ----\n\n  enableRecording(config: RecordConfig): this {\n    this.options.record = config;\n    return this;\n  }\n\n  disableRecording(): this {\n    delete this.options.record;\n    return this;\n  }\n\n  // ---- Reset ----\n\n  reset(): this {\n    this.clearFixtures();\n    this.searchFixtures.length = 0;\n    this.rerankFixtures.length = 0;\n    this.moderationFixtures.length = 0;\n    falJobs.clear();\n    falQueueStates.clear();\n    if (this.serverInstance) {\n      this.serverInstance.journal.clear();\n      this.serverInstance.videoStates.clear();\n      this.serverInstance.openRouterVideoJobs.clear();\n    }\n    return this;\n  }\n\n  // ---- Server lifecycle ----\n\n  async start(): Promise<string> {\n    if (this.serverInstance) {\n      throw new Error(\"Server already started\");\n    }\n    this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {\n      search: this.searchFixtures,\n      rerank: this.rerankFixtures,\n      moderation: this.moderationFixtures,\n    });\n    return this.serverInstance.url;\n  }\n\n  async stop(): Promise<void> {\n    if (!this.serverInstance) {\n      throw new Error(\"Server not started\");\n    }\n    const { server } = this.serverInstance;\n    await new Promise<void>((resolve, reject) => {\n      server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n    });\n    this.serverInstance = null;\n  }\n\n  // ---- Accessors ----\n\n  get journal(): Journal {\n    if (!this.serverInstance) {\n      throw new Error(\"Server not started\");\n    }\n    return this.serverInstance.journal;\n  }\n\n  get url(): string {\n    if (!this.serverInstance) {\n      throw new Error(\"Server not started\");\n    }\n    return this.serverInstance.url;\n  }\n\n  get baseUrl(): string {\n    return this.url;\n  }\n\n  get port(): number {\n    const parsed = new URL(this.url); // this.url throws if not started\n    if (!parsed.port) {\n      throw new Error(`Server URL has no explicit port: ${this.url}`);\n    }\n    return parseInt(parsed.port, 10);\n  }\n\n  // ---- Static factory ----\n\n  static async create(options?: MockServerOptions): Promise<LLMock> {\n    const instance = new LLMock(options);\n    await instance.start();\n    return instance;\n  }\n}\n"],"mappings":"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"}