{"version":3,"file":"gemini.cjs","names":["formatToMime","calculateDelay","delay","flattenHeaders","getContext","getTestId","matchFixtureDiagnostic","recordMatchOptions","applyChaos","resolveStrictMode","strictNoMatchMessage","strictNoMatchLogLine","strictOverrideField","proxyAndRecord","resolveResponse","isErrorResponse","isAudioResponse","resolveReasoningForModel","createInterruptionSignal","isContentWithToolCallsResponse","extractOverrides","isTextResponse","isToolCallResponse"],"sources":["../src/gemini.ts"],"sourcesContent":["/**\n * Google Gemini GenerateContent API support.\n *\n * Translates incoming Gemini requests into the ChatCompletionRequest format\n * used by the fixture router, and converts fixture responses back into the\n * Gemini GenerateContent streaming (or non-streaming) format.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n  AudioResponse,\n  ChatCompletionRequest,\n  ChatMessage,\n  Fixture,\n  HandlerDefaults,\n  RecordedTimings,\n  RecordProviderKey,\n  ResponseOverrides,\n  StreamingProfile,\n  ToolCall,\n  ToolDefinition,\n} from \"./types.js\";\nimport {\n  isTextResponse,\n  isToolCallResponse,\n  isContentWithToolCallsResponse,\n  isErrorResponse,\n  isAudioResponse,\n  extractOverrides,\n  formatToMime,\n  flattenHeaders,\n  getContext,\n  getTestId,\n  resolveResponse,\n  resolveStrictMode,\n  resolveReasoningForModel,\n  strictOverrideField,\n  strictNoMatchMessage,\n  strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { matchFixtureDiagnostic, recordMatchOptions } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Gemini request types ───────────────────────────────────────────────────\n\ninterface GeminiPart {\n  text?: string;\n  thought?: boolean;\n  functionCall?: { name: string; args: Record<string, unknown>; id?: string };\n  functionResponse?: { name: string; response: unknown; id?: string };\n  inlineData?: { mimeType: string; data: string };\n}\n\ninterface GeminiContent {\n  role?: string;\n  parts: GeminiPart[];\n}\n\ninterface GeminiFunctionDeclaration {\n  name: string;\n  description?: string;\n  parameters?: object;\n}\n\ninterface GeminiToolDef {\n  functionDeclarations?: GeminiFunctionDeclaration[];\n}\n\ninterface GeminiRequest {\n  contents?: GeminiContent[];\n  systemInstruction?: GeminiContent;\n  tools?: GeminiToolDef[];\n  generationConfig?: {\n    temperature?: number;\n    maxOutputTokens?: number;\n    [key: string]: unknown;\n  };\n  [key: string]: unknown;\n}\n\n// ─── Input conversion: Gemini → ChatCompletions messages ────────────────────\n\nexport function geminiToCompletionRequest(\n  req: GeminiRequest,\n  model: string,\n  stream: boolean,\n): ChatCompletionRequest {\n  const messages: ChatMessage[] = [];\n\n  // systemInstruction → system message\n  if (req.systemInstruction) {\n    const text = req.systemInstruction.parts\n      .filter((p) => p.text !== undefined)\n      .map((p) => p.text!)\n      .join(\"\");\n    if (text) {\n      messages.push({ role: \"system\", content: text });\n    }\n  }\n\n  if (req.contents) {\n    let callCounter = 0;\n    for (const content of req.contents) {\n      const role = content.role ?? \"user\";\n\n      if (role === \"user\") {\n        // Check for functionResponse parts\n        const funcResponses = content.parts.filter((p) => p.functionResponse);\n        const textParts = content.parts.filter((p) => p.text !== undefined && !p.thought);\n\n        if (funcResponses.length > 0) {\n          // functionResponse → tool message; match IDs from the preceding assistant's tool_calls\n          const lastAssistant = [...messages]\n            .reverse()\n            .find((m) => m.role === \"assistant\" && m.tool_calls);\n          const matchedToolCallIds = new Set<string>();\n          for (const part of funcResponses) {\n            const matchingCall = lastAssistant?.tool_calls?.find(\n              (tc) =>\n                tc.function.name === part.functionResponse!.name && !matchedToolCallIds.has(tc.id),\n            );\n            if (matchingCall) matchedToolCallIds.add(matchingCall.id);\n            const toolCallId =\n              matchingCall?.id ?? `call_gemini_${part.functionResponse!.name}_${callCounter++}`;\n            messages.push({\n              role: \"tool\",\n              content:\n                typeof part.functionResponse!.response === \"string\"\n                  ? part.functionResponse!.response\n                  : JSON.stringify(part.functionResponse!.response),\n              tool_call_id: toolCallId,\n            });\n          }\n          // Any text parts alongside → user message\n          if (textParts.length > 0) {\n            messages.push({\n              role: \"user\",\n              content: textParts.map((p) => p.text!).join(\"\"),\n            });\n          }\n        } else {\n          // Regular user text\n          const text = textParts.map((p) => p.text!).join(\"\");\n          messages.push({ role: \"user\", content: text });\n        }\n      } else if (role === \"model\") {\n        // Check for functionCall parts\n        const funcCalls = content.parts.filter((p) => p.functionCall);\n        const textParts = content.parts.filter((p) => p.text !== undefined && !p.thought);\n\n        if (funcCalls.length > 0) {\n          const text = textParts.map((p) => p.text!).join(\"\");\n          messages.push({\n            role: \"assistant\",\n            content: text || null,\n            tool_calls: funcCalls.map((fc, i) => ({\n              id: fc.functionCall!.id ?? `call_gemini_${fc.functionCall!.name}_${i}`,\n              type: \"function\" as const,\n              function: {\n                name: fc.functionCall!.name,\n                arguments: JSON.stringify(fc.functionCall!.args ?? {}),\n              },\n            })),\n          });\n        } else {\n          const text = textParts.map((p) => p.text!).join(\"\");\n          messages.push({ role: \"assistant\", content: text });\n        }\n      }\n      // Unrecognized roles (not \"user\" or \"model\") are silently dropped.\n      // Gemini only defines \"user\" and \"model\"; any other value indicates\n      // a malformed request or an unsupported future role.\n    }\n  }\n\n  // Convert tools\n  let tools: ToolDefinition[] | undefined;\n  if (req.tools && req.tools.length > 0) {\n    const decls = req.tools.flatMap((t) => t.functionDeclarations ?? []);\n    if (decls.length > 0) {\n      tools = decls.map((d) => ({\n        type: \"function\" as const,\n        function: {\n          name: d.name,\n          description: d.description,\n          parameters: d.parameters,\n        },\n      }));\n    }\n  }\n\n  return {\n    model,\n    messages,\n    stream,\n    temperature: req.generationConfig?.temperature,\n    max_tokens: req.generationConfig?.maxOutputTokens,\n    top_p: req.generationConfig?.topP as number | undefined,\n    top_k: req.generationConfig?.topK as number | undefined,\n    tools,\n  };\n}\n\n// ─── Response building: fixture → Gemini format ─────────────────────────────\n\nfunction geminiFinishReason(finishReason: string | undefined, defaultReason: string): string {\n  if (!finishReason) return defaultReason;\n  if (finishReason === \"stop\") return \"STOP\";\n  if (finishReason === \"tool_calls\") return \"FUNCTION_CALL\";\n  if (finishReason === \"length\") return \"MAX_TOKENS\";\n  if (finishReason === \"content_filter\") return \"SAFETY\";\n  // Pass through unrecognized values as-is\n  return finishReason;\n}\n\nfunction geminiUsageMetadata(overrides?: ResponseOverrides): {\n  promptTokenCount: number;\n  candidatesTokenCount: number;\n  totalTokenCount: number;\n} {\n  if (!overrides?.usage)\n    return { promptTokenCount: 0, candidatesTokenCount: 0, totalTokenCount: 0 };\n  const prompt =\n    overrides.usage.promptTokenCount ??\n    overrides.usage.prompt_tokens ??\n    overrides.usage.input_tokens ??\n    0;\n  const candidates =\n    overrides.usage.candidatesTokenCount ??\n    overrides.usage.completion_tokens ??\n    overrides.usage.output_tokens ??\n    0;\n  const total = overrides.usage.totalTokenCount ?? prompt + candidates;\n  return {\n    promptTokenCount: prompt,\n    candidatesTokenCount: candidates,\n    totalTokenCount: total,\n  };\n}\n\ninterface GeminiResponseChunk {\n  candidates: {\n    content: { role: string; parts: GeminiPart[] };\n    finishReason?: string;\n    index: number;\n  }[];\n  usageMetadata?: {\n    promptTokenCount: number;\n    candidatesTokenCount: number;\n    totalTokenCount: number;\n  };\n}\n\nfunction buildGeminiTextStreamChunks(\n  content: string,\n  chunkSize: number,\n  reasoning?: string,\n  overrides?: ResponseOverrides,\n): GeminiResponseChunk[] {\n  const chunks: GeminiResponseChunk[] = [];\n  const effectiveFinish = geminiFinishReason(overrides?.finishReason, \"STOP\");\n  const usage = geminiUsageMetadata(overrides);\n\n  // Reasoning chunks (thought: true)\n  if (reasoning) {\n    for (let i = 0; i < reasoning.length; i += chunkSize) {\n      const slice = reasoning.slice(i, i + chunkSize);\n      chunks.push({\n        candidates: [\n          {\n            content: { role: \"model\", parts: [{ text: slice, thought: true }] },\n            index: 0,\n          },\n        ],\n      });\n    }\n  }\n\n  // Content chunks\n  for (let i = 0; i < content.length; i += chunkSize) {\n    const slice = content.slice(i, i + chunkSize);\n    const isLast = i + chunkSize >= content.length;\n    const chunk: GeminiResponseChunk = {\n      candidates: [\n        {\n          content: { role: \"model\", parts: [{ text: slice }] },\n          index: 0,\n          ...(isLast ? { finishReason: effectiveFinish } : {}),\n        },\n      ],\n      ...(isLast ? { usageMetadata: usage } : {}),\n    };\n    chunks.push(chunk);\n  }\n\n  // Handle empty content\n  if (content.length === 0) {\n    chunks.push({\n      candidates: [\n        {\n          content: { role: \"model\", parts: [{ text: \"\" }] },\n          finishReason: effectiveFinish,\n          index: 0,\n        },\n      ],\n      usageMetadata: usage,\n    });\n  }\n\n  return chunks;\n}\n\nfunction parseToolCallPart(tc: ToolCall, logger: Logger): GeminiPart {\n  let argsObj: Record<string, unknown>;\n  try {\n    argsObj = JSON.parse(tc.arguments || \"{}\") as Record<string, unknown>;\n  } catch {\n    logger.warn(`Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`);\n    argsObj = {};\n  }\n  // Surface the fixture's tool_call.id on the Gemini functionCall response\n  // so clients can preserve it across the round-trip and any\n  // toolCallId-keyed follow-up fixtures match. Pairs with v1.23.1's\n  // INGEST-direction fix (#196) which preserves the id when aimock parses\n  // an incoming Gemini request — that fix only helps if the id was in the\n  // response body to begin with. Without this egress fix, aimock emits\n  // `{ functionCall: { name, args } }` (no id), so even clients that\n  // diligently preserve `functionCall.id` across the round-trip never see\n  // an id to preserve. Backward-compatible: fixtures that don't pin a\n  // tc.id continue to serialize without one (the ingest path's fallback\n  // generator handles those).\n  const functionCall: GeminiPart[\"functionCall\"] = {\n    name: tc.name,\n    args: argsObj,\n  };\n  if (tc.id) {\n    functionCall.id = tc.id;\n  }\n  return { functionCall };\n}\n\nfunction buildGeminiToolCallStreamChunks(\n  toolCalls: ToolCall[],\n  chunkSize: number,\n  logger: Logger,\n  reasoning?: string,\n  overrides?: ResponseOverrides,\n): GeminiResponseChunk[] {\n  const chunks: GeminiResponseChunk[] = [];\n\n  // Reasoning chunks (thought: true) — mirror the content+tool / text paths so a\n  // tool-only fixture on a reasoning-capable model still emits its thought channel.\n  if (reasoning) {\n    for (let i = 0; i < reasoning.length; i += chunkSize) {\n      const slice = reasoning.slice(i, i + chunkSize);\n      chunks.push({\n        candidates: [\n          {\n            content: { role: \"model\", parts: [{ text: slice, thought: true }] },\n            index: 0,\n          },\n        ],\n      });\n    }\n  }\n\n  const parts: GeminiPart[] = toolCalls.map((tc) => parseToolCallPart(tc, logger));\n\n  // Gemini sends all tool calls in a single response chunk\n  chunks.push({\n    candidates: [\n      {\n        content: { role: \"model\", parts },\n        finishReason: geminiFinishReason(overrides?.finishReason, \"FUNCTION_CALL\"),\n        index: 0,\n      },\n    ],\n    usageMetadata: geminiUsageMetadata(overrides),\n  });\n\n  return chunks;\n}\n\n// Non-streaming response builders\n\nfunction buildGeminiTextResponse(\n  content: string,\n  reasoning?: string,\n  overrides?: ResponseOverrides,\n): GeminiResponseChunk {\n  const parts: GeminiPart[] = [];\n  if (reasoning) {\n    parts.push({ text: reasoning, thought: true });\n  }\n  parts.push({ text: content });\n\n  return {\n    candidates: [\n      {\n        content: { role: \"model\", parts },\n        finishReason: geminiFinishReason(overrides?.finishReason, \"STOP\"),\n        index: 0,\n      },\n    ],\n    usageMetadata: geminiUsageMetadata(overrides),\n  };\n}\n\nfunction buildGeminiToolCallResponse(\n  toolCalls: ToolCall[],\n  logger: Logger,\n  reasoning?: string,\n  overrides?: ResponseOverrides,\n): GeminiResponseChunk {\n  const parts: GeminiPart[] = [];\n  if (reasoning) {\n    parts.push({ text: reasoning, thought: true });\n  }\n  parts.push(...toolCalls.map((tc) => parseToolCallPart(tc, logger)));\n\n  return {\n    candidates: [\n      {\n        content: { role: \"model\", parts },\n        finishReason: geminiFinishReason(overrides?.finishReason, \"FUNCTION_CALL\"),\n        index: 0,\n      },\n    ],\n    usageMetadata: geminiUsageMetadata(overrides),\n  };\n}\n\nfunction buildGeminiContentWithToolCallsStreamChunks(\n  content: string,\n  toolCalls: ToolCall[],\n  chunkSize: number,\n  logger: Logger,\n  reasoning?: string,\n  overrides?: ResponseOverrides,\n): GeminiResponseChunk[] {\n  const chunks: GeminiResponseChunk[] = [];\n\n  // Reasoning chunks (thought: true)\n  if (reasoning) {\n    for (let i = 0; i < reasoning.length; i += chunkSize) {\n      const slice = reasoning.slice(i, i + chunkSize);\n      chunks.push({\n        candidates: [\n          {\n            content: { role: \"model\", parts: [{ text: slice, thought: true }] },\n            index: 0,\n          },\n        ],\n      });\n    }\n  }\n\n  if (content.length === 0) {\n    chunks.push({\n      candidates: [\n        {\n          content: { role: \"model\", parts: [{ text: \"\" }] },\n          index: 0,\n        },\n      ],\n    });\n  } else {\n    for (let i = 0; i < content.length; i += chunkSize) {\n      const slice = content.slice(i, i + chunkSize);\n      chunks.push({\n        candidates: [\n          {\n            content: { role: \"model\", parts: [{ text: slice }] },\n            index: 0,\n          },\n        ],\n      });\n    }\n  }\n\n  const parts: GeminiPart[] = toolCalls.map((tc) => parseToolCallPart(tc, logger));\n\n  chunks.push({\n    candidates: [\n      {\n        content: { role: \"model\", parts },\n        finishReason: geminiFinishReason(overrides?.finishReason, \"FUNCTION_CALL\"),\n        index: 0,\n      },\n    ],\n    usageMetadata: geminiUsageMetadata(overrides),\n  });\n\n  return chunks;\n}\n\nfunction buildGeminiContentWithToolCallsResponse(\n  content: string,\n  toolCalls: ToolCall[],\n  logger: Logger,\n  reasoning?: string,\n  overrides?: ResponseOverrides,\n): GeminiResponseChunk {\n  const parts: GeminiPart[] = [];\n  if (reasoning) {\n    parts.push({ text: reasoning, thought: true });\n  }\n  parts.push({ text: content });\n  parts.push(...toolCalls.map((tc) => parseToolCallPart(tc, logger)));\n\n  return {\n    candidates: [\n      {\n        content: { role: \"model\", parts },\n        finishReason: geminiFinishReason(overrides?.finishReason, \"FUNCTION_CALL\"),\n        index: 0,\n      },\n    ],\n    usageMetadata: geminiUsageMetadata(overrides),\n  };\n}\n\n// ─── Audio response builders ────────────────────────────────────────────────\n\nfunction resolveAudioInlineData(audio: AudioResponse): { mimeType: string; data: string } {\n  if (typeof audio.audio === \"string\") {\n    return { mimeType: formatToMime(audio.format ?? \"mp3\"), data: audio.audio };\n  }\n  return {\n    mimeType: audio.audio.contentType ?? \"audio/mpeg\",\n    data: audio.audio.b64Json,\n  };\n}\n\n// Build the ordered Gemini parts for an audio turn: inlineData audio first,\n// then any companion modalities (reasoning/thought, text content, tool calls)\n// the recorder preserved on the AudioResponse. Without this, a recorded turn\n// that interleaves audio with a functionCall and/or text silently drops the\n// companions on replay.\n// NOTE: audio companions are only re-emitted on this Gemini replay path because\n// `audioB64` collapse is currently Gemini-only — a cross-provider audio fixture\n// would not replay its companions.\n// `effReasoning` is the capability-gated reasoning string (already passed\n// through resolveReasoningForModel at the dispatch). When the requested model\n// is not reasoning-capable (and strict mode is on), it is undefined and the\n// companion `thought` part is suppressed — mirroring the text/content+tool\n// branches so the audio path does not replay reasoning a real Gemini model\n// would never emit.\nfunction buildGeminiAudioParts(\n  audio: AudioResponse,\n  logger: Logger,\n  effReasoning: string | undefined,\n): GeminiPart[] {\n  const inlineData = resolveAudioInlineData(audio);\n  const parts: GeminiPart[] = [{ inlineData }];\n  if (effReasoning) {\n    parts.push({ text: effReasoning, thought: true });\n  }\n  if (audio.content) {\n    parts.push({ text: audio.content });\n  }\n  if (audio.toolCalls?.length) {\n    parts.push(...audio.toolCalls.map((tc) => parseToolCallPart(tc, logger)));\n  }\n  return parts;\n}\n\nfunction buildGeminiAudioResponse(\n  audio: AudioResponse,\n  logger: Logger,\n  effReasoning: string | undefined,\n): GeminiResponseChunk {\n  return {\n    candidates: [\n      {\n        content: { role: \"model\", parts: buildGeminiAudioParts(audio, logger, effReasoning) },\n        finishReason: audio.toolCalls?.length ? \"FUNCTION_CALL\" : \"STOP\",\n        index: 0,\n      },\n    ],\n    usageMetadata: { promptTokenCount: 0, candidatesTokenCount: 0, totalTokenCount: 0 },\n  };\n}\n\nfunction buildGeminiAudioStreamChunks(\n  audio: AudioResponse,\n  logger: Logger,\n  effReasoning: string | undefined,\n): GeminiResponseChunk[] {\n  return [\n    {\n      candidates: [\n        {\n          content: { role: \"model\", parts: buildGeminiAudioParts(audio, logger, effReasoning) },\n          finishReason: audio.toolCalls?.length ? \"FUNCTION_CALL\" : \"STOP\",\n          index: 0,\n        },\n      ],\n      usageMetadata: { promptTokenCount: 0, candidatesTokenCount: 0, totalTokenCount: 0 },\n    },\n  ];\n}\n\n// ─── SSE writer for Gemini streaming ────────────────────────────────────────\n\ninterface GeminiStreamOptions {\n  latency?: number;\n  streamingProfile?: StreamingProfile;\n  recordedTimings?: RecordedTimings;\n  replaySpeed?: number;\n  signal?: AbortSignal;\n  onChunkSent?: () => void;\n}\n\nasync function writeGeminiSSEStream(\n  res: http.ServerResponse,\n  chunks: GeminiResponseChunk[],\n  optionsOrLatency?: number | GeminiStreamOptions,\n): Promise<boolean> {\n  const opts: GeminiStreamOptions =\n    typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n  const latency = opts.latency ?? 0;\n  const profile = opts.streamingProfile;\n  const { recordedTimings, replaySpeed } = opts;\n  const signal = opts.signal;\n  const onChunkSent = opts.onChunkSent;\n\n  if (res.writableEnded) return true;\n  res.setHeader(\"Content-Type\", \"text/event-stream\");\n  res.setHeader(\"Cache-Control\", \"no-cache\");\n  res.setHeader(\"Connection\", \"keep-alive\");\n\n  let chunkIndex = 0;\n  for (const chunk of chunks) {\n    const chunkDelay = calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);\n    if (chunkDelay > 0) await delay(chunkDelay, signal);\n    if (signal?.aborted) return false;\n    if (res.writableEnded) return true;\n    // Gemini uses data-only SSE (no event: prefix, no [DONE])\n    res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n    onChunkSent?.();\n    if (signal?.aborted) return false;\n    chunkIndex++;\n  }\n\n  if (!res.writableEnded) {\n    res.end();\n  }\n  return true;\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleGemini(\n  req: http.IncomingMessage,\n  res: http.ServerResponse,\n  raw: string,\n  model: string,\n  streaming: boolean,\n  fixtures: Fixture[],\n  journal: Journal,\n  defaults: HandlerDefaults,\n  setCorsHeaders: (res: http.ServerResponse) => void,\n  providerKey: RecordProviderKey = \"gemini\",\n): Promise<void> {\n  const { logger } = defaults;\n  setCorsHeaders(res);\n\n  let geminiReq: GeminiRequest;\n  try {\n    geminiReq = JSON.parse(raw) as GeminiRequest;\n  } catch (parseErr) {\n    const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n    journal.add({\n      method: req.method ?? \"POST\",\n      path: req.url ?? `/v1beta/models/${model}:generateContent`,\n      headers: flattenHeaders(req.headers),\n      body: null,\n      response: { status: 400, fixture: null },\n    });\n    writeErrorResponse(\n      res,\n      400,\n      JSON.stringify({\n        error: {\n          message: `Malformed JSON body: ${detail}`,\n          code: 400,\n          status: \"INVALID_ARGUMENT\",\n        },\n      }),\n    );\n    return;\n  }\n\n  // Convert to ChatCompletionRequest for fixture matching\n  const completionReq = geminiToCompletionRequest(geminiReq, model, streaming);\n  completionReq._endpointType = \"chat\";\n  completionReq._context = getContext(req);\n\n  const testId = getTestId(req);\n  const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n    fixtures,\n    completionReq,\n    journal.getFixtureMatchCountsForTest(testId),\n    defaults.requestTransform,\n    // Record mode proxies on a miss to capture a fresh turn (see record gate\n    // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n    // shadowing a longer request and skipping the new turn's recording.\n    recordMatchOptions(!!defaults.record, defaults.logger),\n  );\n  const path = req.url ?? `/v1beta/models/${model}:generateContent`;\n\n  if (fixture) {\n    logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n  } else {\n    logger.debug(`No fixture matched for request`);\n  }\n\n  if (fixture) {\n    journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n  }\n\n  if (\n    applyChaos(\n      res,\n      fixture,\n      defaults.chaos,\n      req.headers,\n      journal,\n      {\n        method: req.method ?? \"POST\",\n        path,\n        headers: flattenHeaders(req.headers),\n        body: completionReq,\n      },\n      fixture ? \"fixture\" : \"proxy\",\n      defaults.registry,\n      defaults.logger,\n    )\n  )\n    return;\n\n  if (!fixture) {\n    const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n    if (effectiveStrict) {\n      const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n      logger.error(strictNoMatchLogLine(req.method ?? \"POST\", path, skippedBySequenceOrTurn));\n      journal.add({\n        method: req.method ?? \"POST\",\n        path,\n        headers: flattenHeaders(req.headers),\n        body: completionReq,\n        response: {\n          status: 503,\n          fixture: null,\n          ...strictOverrideField(defaults.strict, req.headers),\n        },\n      });\n      writeErrorResponse(\n        res,\n        503,\n        JSON.stringify({\n          error: {\n            message: strictMessage,\n            code: 503,\n            status: \"UNAVAILABLE\",\n          },\n        }),\n      );\n      return;\n    }\n\n    if (defaults.record) {\n      const outcome = await proxyAndRecord(\n        req,\n        res,\n        completionReq,\n        providerKey,\n        path,\n        fixtures,\n        defaults,\n        raw,\n      );\n      if (outcome === \"handled_by_hook\") return;\n      if (outcome !== \"not_configured\") {\n        journal.add({\n          method: req.method ?? \"POST\",\n          path,\n          headers: flattenHeaders(req.headers),\n          body: completionReq,\n          response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n        });\n        return;\n      }\n    }\n    journal.add({\n      method: req.method ?? \"POST\",\n      path,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: {\n        status: 404,\n        fixture: null,\n        ...strictOverrideField(defaults.strict, req.headers),\n      },\n    });\n    writeErrorResponse(\n      res,\n      404,\n      JSON.stringify({\n        error: {\n          message: \"No fixture matched\",\n          code: 404,\n          status: \"NOT_FOUND\",\n        },\n      }),\n    );\n    return;\n  }\n\n  const response = await resolveResponse(fixture, completionReq);\n  const latency = fixture.latency ?? defaults.latency;\n  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n  const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;\n\n  // Error response\n  if (isErrorResponse(response)) {\n    const status = response.status ?? 500;\n    journal.add({\n      method: req.method ?? \"POST\",\n      path,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status, fixture },\n    });\n    // Gemini-style error format: { error: { code, message, status } }\n    const geminiError = {\n      error: {\n        code: status,\n        message: response.error.message,\n        status: response.error.type ?? \"ERROR\",\n      },\n    };\n    writeErrorResponse(res, status, JSON.stringify(geminiError), {\n      retryAfter: response.retryAfter,\n    });\n    return;\n  }\n\n  // Audio response\n  if (isAudioResponse(response)) {\n    const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n    const effReasoning = resolveReasoningForModel(\n      response.reasoning,\n      model,\n      effectiveStrict,\n      defaults.logger,\n    );\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildGeminiAudioResponse(response, logger, effReasoning);\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const chunks = buildGeminiAudioStreamChunks(response, logger, effReasoning);\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiSSEStream(res, chunks, {\n        latency,\n        streamingProfile: fixture.streamingProfile,\n        recordedTimings: fixture.recordedTimings,\n        replaySpeed,\n        signal: interruption?.signal,\n        onChunkSent: interruption?.tick,\n      });\n      if (!completed) {\n        if (!res.writableEnded) res.destroy();\n        journalEntry.response.interrupted = true;\n        journalEntry.response.interruptReason = interruption?.reason();\n      }\n      interruption?.cleanup();\n    }\n    return;\n  }\n\n  // Content + tool calls response (must be checked before isTextResponse / isToolCallResponse)\n  if (isContentWithToolCallsResponse(response)) {\n    if (response.webSearches?.length) {\n      logger.warn(\"webSearches in fixture response are not supported for Gemini API — ignoring\");\n    }\n    const overrides = extractOverrides(response);\n    const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n    const effReasoning = resolveReasoningForModel(\n      response.reasoning,\n      model,\n      effectiveStrict,\n      defaults.logger,\n    );\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildGeminiContentWithToolCallsResponse(\n        response.content,\n        response.toolCalls,\n        logger,\n        effReasoning,\n        overrides,\n      );\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const chunks = buildGeminiContentWithToolCallsStreamChunks(\n        response.content,\n        response.toolCalls,\n        chunkSize,\n        logger,\n        effReasoning,\n        overrides,\n      );\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiSSEStream(res, chunks, {\n        latency,\n        streamingProfile: fixture.streamingProfile,\n        recordedTimings: fixture.recordedTimings,\n        replaySpeed,\n        signal: interruption?.signal,\n        onChunkSent: interruption?.tick,\n      });\n      if (!completed) {\n        if (!res.writableEnded) res.destroy();\n        journalEntry.response.interrupted = true;\n        journalEntry.response.interruptReason = interruption?.reason();\n      }\n      interruption?.cleanup();\n    }\n    return;\n  }\n\n  // Text response\n  if (isTextResponse(response)) {\n    if (response.webSearches?.length) {\n      logger.warn(\"webSearches in fixture response are not supported for Gemini API — ignoring\");\n    }\n    const overrides = extractOverrides(response);\n    const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n    const effReasoning = resolveReasoningForModel(\n      response.reasoning,\n      model,\n      effectiveStrict,\n      defaults.logger,\n    );\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildGeminiTextResponse(response.content, effReasoning, overrides);\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const chunks = buildGeminiTextStreamChunks(\n        response.content,\n        chunkSize,\n        effReasoning,\n        overrides,\n      );\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiSSEStream(res, chunks, {\n        latency,\n        streamingProfile: fixture.streamingProfile,\n        recordedTimings: fixture.recordedTimings,\n        replaySpeed,\n        signal: interruption?.signal,\n        onChunkSent: interruption?.tick,\n      });\n      if (!completed) {\n        if (!res.writableEnded) res.destroy();\n        journalEntry.response.interrupted = true;\n        journalEntry.response.interruptReason = interruption?.reason();\n      }\n      interruption?.cleanup();\n    }\n    return;\n  }\n\n  // Tool call response\n  if (isToolCallResponse(response)) {\n    if (response.webSearches?.length) {\n      logger.warn(\"webSearches in fixture response are not supported for Gemini API — ignoring\");\n    }\n    const overrides = extractOverrides(response);\n    const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n    const effReasoning = resolveReasoningForModel(\n      response.reasoning,\n      model,\n      effectiveStrict,\n      defaults.logger,\n    );\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildGeminiToolCallResponse(response.toolCalls, logger, effReasoning, overrides);\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const chunks = buildGeminiToolCallStreamChunks(\n        response.toolCalls,\n        chunkSize,\n        logger,\n        effReasoning,\n        overrides,\n      );\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiSSEStream(res, chunks, {\n        latency,\n        streamingProfile: fixture.streamingProfile,\n        recordedTimings: fixture.recordedTimings,\n        replaySpeed,\n        signal: interruption?.signal,\n        onChunkSent: interruption?.tick,\n      });\n      if (!completed) {\n        if (!res.writableEnded) res.destroy();\n        journalEntry.response.interrupted = true;\n        journalEntry.response.interruptReason = interruption?.reason();\n      }\n      interruption?.cleanup();\n    }\n    return;\n  }\n\n  // Unknown response type\n  journal.add({\n    method: req.method ?? \"POST\",\n    path,\n    headers: flattenHeaders(req.headers),\n    body: completionReq,\n    response: { status: 500, fixture },\n  });\n  writeErrorResponse(\n    res,\n    500,\n    JSON.stringify({\n      error: {\n        message: \"Fixture response did not match any known type\",\n        code: 500,\n        status: \"INTERNAL\",\n      },\n    }),\n  );\n}\n"],"mappings":";;;;;;;;AAuFA,SAAgB,0BACd,KACA,OACA,QACuB;CACvB,MAAM,WAA0B,EAAE;AAGlC,KAAI,IAAI,mBAAmB;EACzB,MAAM,OAAO,IAAI,kBAAkB,MAChC,QAAQ,MAAM,EAAE,SAAS,OAAU,CACnC,KAAK,MAAM,EAAE,KAAM,CACnB,KAAK,GAAG;AACX,MAAI,KACF,UAAS,KAAK;GAAE,MAAM;GAAU,SAAS;GAAM,CAAC;;AAIpD,KAAI,IAAI,UAAU;EAChB,IAAI,cAAc;AAClB,OAAK,MAAM,WAAW,IAAI,UAAU;GAClC,MAAM,OAAO,QAAQ,QAAQ;AAE7B,OAAI,SAAS,QAAQ;IAEnB,MAAM,gBAAgB,QAAQ,MAAM,QAAQ,MAAM,EAAE,iBAAiB;IACrE,MAAM,YAAY,QAAQ,MAAM,QAAQ,MAAM,EAAE,SAAS,UAAa,CAAC,EAAE,QAAQ;AAEjF,QAAI,cAAc,SAAS,GAAG;KAE5B,MAAM,gBAAgB,CAAC,GAAG,SAAS,CAChC,SAAS,CACT,MAAM,MAAM,EAAE,SAAS,eAAe,EAAE,WAAW;KACtD,MAAM,qCAAqB,IAAI,KAAa;AAC5C,UAAK,MAAM,QAAQ,eAAe;MAChC,MAAM,eAAe,eAAe,YAAY,MAC7C,OACC,GAAG,SAAS,SAAS,KAAK,iBAAkB,QAAQ,CAAC,mBAAmB,IAAI,GAAG,GAAG,CACrF;AACD,UAAI,aAAc,oBAAmB,IAAI,aAAa,GAAG;MACzD,MAAM,aACJ,cAAc,MAAM,eAAe,KAAK,iBAAkB,KAAK,GAAG;AACpE,eAAS,KAAK;OACZ,MAAM;OACN,SACE,OAAO,KAAK,iBAAkB,aAAa,WACvC,KAAK,iBAAkB,WACvB,KAAK,UAAU,KAAK,iBAAkB,SAAS;OACrD,cAAc;OACf,CAAC;;AAGJ,SAAI,UAAU,SAAS,EACrB,UAAS,KAAK;MACZ,MAAM;MACN,SAAS,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;MAChD,CAAC;WAEC;KAEL,MAAM,OAAO,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;AACnD,cAAS,KAAK;MAAE,MAAM;MAAQ,SAAS;MAAM,CAAC;;cAEvC,SAAS,SAAS;IAE3B,MAAM,YAAY,QAAQ,MAAM,QAAQ,MAAM,EAAE,aAAa;IAC7D,MAAM,YAAY,QAAQ,MAAM,QAAQ,MAAM,EAAE,SAAS,UAAa,CAAC,EAAE,QAAQ;AAEjF,QAAI,UAAU,SAAS,GAAG;KACxB,MAAM,OAAO,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;AACnD,cAAS,KAAK;MACZ,MAAM;MACN,SAAS,QAAQ;MACjB,YAAY,UAAU,KAAK,IAAI,OAAO;OACpC,IAAI,GAAG,aAAc,MAAM,eAAe,GAAG,aAAc,KAAK,GAAG;OACnE,MAAM;OACN,UAAU;QACR,MAAM,GAAG,aAAc;QACvB,WAAW,KAAK,UAAU,GAAG,aAAc,QAAQ,EAAE,CAAC;QACvD;OACF,EAAE;MACJ,CAAC;WACG;KACL,MAAM,OAAO,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;AACnD,cAAS,KAAK;MAAE,MAAM;MAAa,SAAS;MAAM,CAAC;;;;;CAU3D,IAAI;AACJ,KAAI,IAAI,SAAS,IAAI,MAAM,SAAS,GAAG;EACrC,MAAM,QAAQ,IAAI,MAAM,SAAS,MAAM,EAAE,wBAAwB,EAAE,CAAC;AACpE,MAAI,MAAM,SAAS,EACjB,SAAQ,MAAM,KAAK,OAAO;GACxB,MAAM;GACN,UAAU;IACR,MAAM,EAAE;IACR,aAAa,EAAE;IACf,YAAY,EAAE;IACf;GACF,EAAE;;AAIP,QAAO;EACL;EACA;EACA;EACA,aAAa,IAAI,kBAAkB;EACnC,YAAY,IAAI,kBAAkB;EAClC,OAAO,IAAI,kBAAkB;EAC7B,OAAO,IAAI,kBAAkB;EAC7B;EACD;;AAKH,SAAS,mBAAmB,cAAkC,eAA+B;AAC3F,KAAI,CAAC,aAAc,QAAO;AAC1B,KAAI,iBAAiB,OAAQ,QAAO;AACpC,KAAI,iBAAiB,aAAc,QAAO;AAC1C,KAAI,iBAAiB,SAAU,QAAO;AACtC,KAAI,iBAAiB,iBAAkB,QAAO;AAE9C,QAAO;;AAGT,SAAS,oBAAoB,WAI3B;AACA,KAAI,CAAC,WAAW,MACd,QAAO;EAAE,kBAAkB;EAAG,sBAAsB;EAAG,iBAAiB;EAAG;CAC7E,MAAM,SACJ,UAAU,MAAM,oBAChB,UAAU,MAAM,iBAChB,UAAU,MAAM,gBAChB;CACF,MAAM,aACJ,UAAU,MAAM,wBAChB,UAAU,MAAM,qBAChB,UAAU,MAAM,iBAChB;AAEF,QAAO;EACL,kBAAkB;EAClB,sBAAsB;EACtB,iBAJY,UAAU,MAAM,mBAAmB,SAAS;EAKzD;;AAgBH,SAAS,4BACP,SACA,WACA,WACA,WACuB;CACvB,MAAM,SAAgC,EAAE;CACxC,MAAM,kBAAkB,mBAAmB,WAAW,cAAc,OAAO;CAC3E,MAAM,QAAQ,oBAAoB,UAAU;AAG5C,KAAI,UACF,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;EACpD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,UAAU;AAC/C,SAAO,KAAK,EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,CAAC;KAAE,MAAM;KAAO,SAAS;KAAM,CAAC;IAAE;GACnE,OAAO;GACR,CACF,EACF,CAAC;;AAKN,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;EAClD,MAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,UAAU;EAC7C,MAAM,SAAS,IAAI,aAAa,QAAQ;EACxC,MAAM,QAA6B;GACjC,YAAY,CACV;IACE,SAAS;KAAE,MAAM;KAAS,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;KAAE;IACpD,OAAO;IACP,GAAI,SAAS,EAAE,cAAc,iBAAiB,GAAG,EAAE;IACpD,CACF;GACD,GAAI,SAAS,EAAE,eAAe,OAAO,GAAG,EAAE;GAC3C;AACD,SAAO,KAAK,MAAM;;AAIpB,KAAI,QAAQ,WAAW,EACrB,QAAO,KAAK;EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAAE;GACjD,cAAc;GACd,OAAO;GACR,CACF;EACD,eAAe;EAChB,CAAC;AAGJ,QAAO;;AAGT,SAAS,kBAAkB,IAAc,QAA4B;CACnE,IAAI;AACJ,KAAI;AACF,YAAU,KAAK,MAAM,GAAG,aAAa,KAAK;SACpC;AACN,SAAO,KAAK,sDAAsD,GAAG,KAAK,KAAK,GAAG,YAAY;AAC9F,YAAU,EAAE;;CAad,MAAM,eAA2C;EAC/C,MAAM,GAAG;EACT,MAAM;EACP;AACD,KAAI,GAAG,GACL,cAAa,KAAK,GAAG;AAEvB,QAAO,EAAE,cAAc;;AAGzB,SAAS,gCACP,WACA,WACA,QACA,WACA,WACuB;CACvB,MAAM,SAAgC,EAAE;AAIxC,KAAI,UACF,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;EACpD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,UAAU;AAC/C,SAAO,KAAK,EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,CAAC;KAAE,MAAM;KAAO,SAAS;KAAM,CAAC;IAAE;GACnE,OAAO;GACR,CACF,EACF,CAAC;;CAIN,MAAM,QAAsB,UAAU,KAAK,OAAO,kBAAkB,IAAI,OAAO,CAAC;AAGhF,QAAO,KAAK;EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS;IAAO;GACjC,cAAc,mBAAmB,WAAW,cAAc,gBAAgB;GAC1E,OAAO;GACR,CACF;EACD,eAAe,oBAAoB,UAAU;EAC9C,CAAC;AAEF,QAAO;;AAKT,SAAS,wBACP,SACA,WACA,WACqB;CACrB,MAAM,QAAsB,EAAE;AAC9B,KAAI,UACF,OAAM,KAAK;EAAE,MAAM;EAAW,SAAS;EAAM,CAAC;AAEhD,OAAM,KAAK,EAAE,MAAM,SAAS,CAAC;AAE7B,QAAO;EACL,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS;IAAO;GACjC,cAAc,mBAAmB,WAAW,cAAc,OAAO;GACjE,OAAO;GACR,CACF;EACD,eAAe,oBAAoB,UAAU;EAC9C;;AAGH,SAAS,4BACP,WACA,QACA,WACA,WACqB;CACrB,MAAM,QAAsB,EAAE;AAC9B,KAAI,UACF,OAAM,KAAK;EAAE,MAAM;EAAW,SAAS;EAAM,CAAC;AAEhD,OAAM,KAAK,GAAG,UAAU,KAAK,OAAO,kBAAkB,IAAI,OAAO,CAAC,CAAC;AAEnE,QAAO;EACL,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS;IAAO;GACjC,cAAc,mBAAmB,WAAW,cAAc,gBAAgB;GAC1E,OAAO;GACR,CACF;EACD,eAAe,oBAAoB,UAAU;EAC9C;;AAGH,SAAS,4CACP,SACA,WACA,WACA,QACA,WACA,WACuB;CACvB,MAAM,SAAgC,EAAE;AAGxC,KAAI,UACF,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;EACpD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,UAAU;AAC/C,SAAO,KAAK,EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,CAAC;KAAE,MAAM;KAAO,SAAS;KAAM,CAAC;IAAE;GACnE,OAAO;GACR,CACF,EACF,CAAC;;AAIN,KAAI,QAAQ,WAAW,EACrB,QAAO,KAAK,EACV,YAAY,CACV;EACE,SAAS;GAAE,MAAM;GAAS,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;GAAE;EACjD,OAAO;EACR,CACF,EACF,CAAC;KAEF,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;EAClD,MAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,UAAU;AAC7C,SAAO,KAAK,EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;IAAE;GACpD,OAAO;GACR,CACF,EACF,CAAC;;CAIN,MAAM,QAAsB,UAAU,KAAK,OAAO,kBAAkB,IAAI,OAAO,CAAC;AAEhF,QAAO,KAAK;EACV,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS;IAAO;GACjC,cAAc,mBAAmB,WAAW,cAAc,gBAAgB;GAC1E,OAAO;GACR,CACF;EACD,eAAe,oBAAoB,UAAU;EAC9C,CAAC;AAEF,QAAO;;AAGT,SAAS,wCACP,SACA,WACA,QACA,WACA,WACqB;CACrB,MAAM,QAAsB,EAAE;AAC9B,KAAI,UACF,OAAM,KAAK;EAAE,MAAM;EAAW,SAAS;EAAM,CAAC;AAEhD,OAAM,KAAK,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAM,KAAK,GAAG,UAAU,KAAK,OAAO,kBAAkB,IAAI,OAAO,CAAC,CAAC;AAEnE,QAAO;EACL,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS;IAAO;GACjC,cAAc,mBAAmB,WAAW,cAAc,gBAAgB;GAC1E,OAAO;GACR,CACF;EACD,eAAe,oBAAoB,UAAU;EAC9C;;AAKH,SAAS,uBAAuB,OAA0D;AACxF,KAAI,OAAO,MAAM,UAAU,SACzB,QAAO;EAAE,UAAUA,6BAAa,MAAM,UAAU,MAAM;EAAE,MAAM,MAAM;EAAO;AAE7E,QAAO;EACL,UAAU,MAAM,MAAM,eAAe;EACrC,MAAM,MAAM,MAAM;EACnB;;AAiBH,SAAS,sBACP,OACA,QACA,cACc;CAEd,MAAM,QAAsB,CAAC,EAAE,YADZ,uBAAuB,MAAM,EACL,CAAC;AAC5C,KAAI,aACF,OAAM,KAAK;EAAE,MAAM;EAAc,SAAS;EAAM,CAAC;AAEnD,KAAI,MAAM,QACR,OAAM,KAAK,EAAE,MAAM,MAAM,SAAS,CAAC;AAErC,KAAI,MAAM,WAAW,OACnB,OAAM,KAAK,GAAG,MAAM,UAAU,KAAK,OAAO,kBAAkB,IAAI,OAAO,CAAC,CAAC;AAE3E,QAAO;;AAGT,SAAS,yBACP,OACA,QACA,cACqB;AACrB,QAAO;EACL,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,sBAAsB,OAAO,QAAQ,aAAa;IAAE;GACrF,cAAc,MAAM,WAAW,SAAS,kBAAkB;GAC1D,OAAO;GACR,CACF;EACD,eAAe;GAAE,kBAAkB;GAAG,sBAAsB;GAAG,iBAAiB;GAAG;EACpF;;AAGH,SAAS,6BACP,OACA,QACA,cACuB;AACvB,QAAO,CACL;EACE,YAAY,CACV;GACE,SAAS;IAAE,MAAM;IAAS,OAAO,sBAAsB,OAAO,QAAQ,aAAa;IAAE;GACrF,cAAc,MAAM,WAAW,SAAS,kBAAkB;GAC1D,OAAO;GACR,CACF;EACD,eAAe;GAAE,kBAAkB;GAAG,sBAAsB;GAAG,iBAAiB;GAAG;EACpF,CACF;;AAcH,eAAe,qBACb,KACA,QACA,kBACkB;CAClB,MAAM,OACJ,OAAO,qBAAqB,WAAW,EAAE,SAAS,kBAAkB,GAAI,oBAAoB,EAAE;CAChG,MAAM,UAAU,KAAK,WAAW;CAChC,MAAM,UAAU,KAAK;CACrB,MAAM,EAAE,iBAAiB,gBAAgB;CACzC,MAAM,SAAS,KAAK;CACpB,MAAM,cAAc,KAAK;AAEzB,KAAI,IAAI,cAAe,QAAO;AAC9B,KAAI,UAAU,gBAAgB,oBAAoB;AAClD,KAAI,UAAU,iBAAiB,WAAW;AAC1C,KAAI,UAAU,cAAc,aAAa;CAEzC,IAAI,aAAa;AACjB,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,aAAaC,kCAAe,YAAY,SAAS,SAAS,iBAAiB,YAAY;AAC7F,MAAI,aAAa,EAAG,OAAMC,yBAAM,YAAY,OAAO;AACnD,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,IAAI,cAAe,QAAO;AAE9B,MAAI,MAAM,SAAS,KAAK,UAAU,MAAM,CAAC,MAAM;AAC/C,iBAAe;AACf,MAAI,QAAQ,QAAS,QAAO;AAC5B;;AAGF,KAAI,CAAC,IAAI,cACP,KAAI,KAAK;AAEX,QAAO;;AAKT,eAAsB,aACpB,KACA,KACA,KACA,OACA,WACA,UACA,SACA,UACA,gBACA,cAAiC,UAClB;CACf,MAAM,EAAE,WAAW;AACnB,gBAAe,IAAI;CAEnB,IAAI;AACJ,KAAI;AACF,cAAY,KAAK,MAAM,IAAI;UACpB,UAAU;EACjB,MAAM,SAAS,oBAAoB,QAAQ,SAAS,UAAU;AAC9D,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO,kBAAkB,MAAM;GACzC,SAASC,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK,SAAS;IAAM;GACzC,CAAC;AACF,wCACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;GACL,SAAS,wBAAwB;GACjC,MAAM;GACN,QAAQ;GACT,EACF,CAAC,CACH;AACD;;CAIF,MAAM,gBAAgB,0BAA0B,WAAW,OAAO,UAAU;AAC5E,eAAc,gBAAgB;AAC9B,eAAc,WAAWC,2BAAW,IAAI;CAExC,MAAM,SAASC,0BAAU,IAAI;CAC7B,MAAM,EAAE,SAAS,4BAA4BC,sCAC3C,UACA,eACA,QAAQ,6BAA6B,OAAO,EAC5C,SAAS,kBAITC,kCAAmB,CAAC,CAAC,SAAS,QAAQ,SAAS,OAAO,CACvD;CACD,MAAM,OAAO,IAAI,OAAO,kBAAkB,MAAM;AAEhD,KAAI,QACF,QAAO,MAAM,oBAAoB,KAAK,UAAU,QAAQ,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG;KAE/E,QAAO,MAAM,iCAAiC;AAGhD,KAAI,QACF,SAAQ,2BAA2B,SAAS,UAAU,OAAO;AAG/D,KACEC,yBACE,KACA,SACA,SAAS,OACT,IAAI,SACJ,SACA;EACE,QAAQ,IAAI,UAAU;EACtB;EACA,SAASL,+BAAe,IAAI,QAAQ;EACpC,MAAM;EACP,EACD,UAAU,YAAY,SACtB,SAAS,UACT,SAAS,OACV,CAED;AAEF,KAAI,CAAC,SAAS;AAEZ,MADwBM,kCAAkB,SAAS,QAAQ,IAAI,QAAQ,EAClD;GACnB,MAAM,gBAAgBC,qCAAqB,wBAAwB;AACnE,UAAO,MAAMC,qCAAqB,IAAI,UAAU,QAAQ,MAAM,wBAAwB,CAAC;AACvF,WAAQ,IAAI;IACV,QAAQ,IAAI,UAAU;IACtB;IACA,SAASR,+BAAe,IAAI,QAAQ;IACpC,MAAM;IACN,UAAU;KACR,QAAQ;KACR,SAAS;KACT,GAAGS,oCAAoB,SAAS,QAAQ,IAAI,QAAQ;KACrD;IACF,CAAC;AACF,yCACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;IACL,SAAS;IACT,MAAM;IACN,QAAQ;IACT,EACF,CAAC,CACH;AACD;;AAGF,MAAI,SAAS,QAAQ;GACnB,MAAM,UAAU,MAAMC,gCACpB,KACA,KACA,eACA,aACA,MACA,UACA,UACA,IACD;AACD,OAAI,YAAY,kBAAmB;AACnC,OAAI,YAAY,kBAAkB;AAChC,YAAQ,IAAI;KACV,QAAQ,IAAI,UAAU;KACtB;KACA,SAASV,+BAAe,IAAI,QAAQ;KACpC,MAAM;KACN,UAAU;MAAE,QAAQ,IAAI,cAAc;MAAK,SAAS;MAAM,QAAQ;MAAS;KAC5E,CAAC;AACF;;;AAGJ,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB;GACA,SAASA,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IACR,QAAQ;IACR,SAAS;IACT,GAAGS,oCAAoB,SAAS,QAAQ,IAAI,QAAQ;IACrD;GACF,CAAC;AACF,wCACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;GACL,SAAS;GACT,MAAM;GACN,QAAQ;GACT,EACF,CAAC,CACH;AACD;;CAGF,MAAM,WAAW,MAAME,gCAAgB,SAAS,cAAc;CAC9D,MAAM,UAAU,QAAQ,WAAW,SAAS;CAC5C,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,SAAS,UAAU;CACtE,MAAM,cAAc,QAAQ,eAAe,SAAS;AAGpD,KAAIC,gCAAgB,SAAS,EAAE;EAC7B,MAAM,SAAS,SAAS,UAAU;AAClC,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB;GACA,SAASZ,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE;IAAQ;IAAS;GAC9B,CAAC;EAEF,MAAM,cAAc,EAClB,OAAO;GACL,MAAM;GACN,SAAS,SAAS,MAAM;GACxB,QAAQ,SAAS,MAAM,QAAQ;GAChC,EACF;AACD,wCAAmB,KAAK,QAAQ,KAAK,UAAU,YAAY,EAAE,EAC3D,YAAY,SAAS,YACtB,CAAC;AACF;;AAIF,KAAIa,gCAAgB,SAAS,EAAE;EAC7B,MAAM,kBAAkBP,kCAAkB,SAAS,QAAQ,IAAI,QAAQ;EACvE,MAAM,eAAeQ,yCACnB,SAAS,WACT,OACA,iBACA,SAAS,OACV;EACD,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB;GACA,SAASd,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,CAAC,WAAW;GACd,MAAM,OAAO,yBAAyB,UAAU,QAAQ,aAAa;AACrE,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,6BAA6B,UAAU,QAAQ,aAAa;GAC3E,MAAM,eAAee,8CAAyB,QAAQ;AAStD,OAAI,CARc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,iBAAiB,QAAQ;IACzB;IACA,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,KAAIC,+CAA+B,SAAS,EAAE;AAC5C,MAAI,SAAS,aAAa,OACxB,QAAO,KAAK,8EAA8E;EAE5F,MAAM,YAAYC,iCAAiB,SAAS;EAC5C,MAAM,kBAAkBX,kCAAkB,SAAS,QAAQ,IAAI,QAAQ;EACvE,MAAM,eAAeQ,yCACnB,SAAS,WACT,OACA,iBACA,SAAS,OACV;EACD,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB;GACA,SAASd,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,CAAC,WAAW;GACd,MAAM,OAAO,wCACX,SAAS,SACT,SAAS,WACT,QACA,cACA,UACD;AACD,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,4CACb,SAAS,SACT,SAAS,WACT,WACA,QACA,cACA,UACD;GACD,MAAM,eAAee,8CAAyB,QAAQ;AAStD,OAAI,CARc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,iBAAiB,QAAQ;IACzB;IACA,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,KAAIG,+BAAe,SAAS,EAAE;AAC5B,MAAI,SAAS,aAAa,OACxB,QAAO,KAAK,8EAA8E;EAE5F,MAAM,YAAYD,iCAAiB,SAAS;EAC5C,MAAM,kBAAkBX,kCAAkB,SAAS,QAAQ,IAAI,QAAQ;EACvE,MAAM,eAAeQ,yCACnB,SAAS,WACT,OACA,iBACA,SAAS,OACV;EACD,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB;GACA,SAASd,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,CAAC,WAAW;GACd,MAAM,OAAO,wBAAwB,SAAS,SAAS,cAAc,UAAU;AAC/E,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,4BACb,SAAS,SACT,WACA,cACA,UACD;GACD,MAAM,eAAee,8CAAyB,QAAQ;AAStD,OAAI,CARc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,iBAAiB,QAAQ;IACzB;IACA,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,KAAII,mCAAmB,SAAS,EAAE;AAChC,MAAI,SAAS,aAAa,OACxB,QAAO,KAAK,8EAA8E;EAE5F,MAAM,YAAYF,iCAAiB,SAAS;EAC5C,MAAM,kBAAkBX,kCAAkB,SAAS,QAAQ,IAAI,QAAQ;EACvE,MAAM,eAAeQ,yCACnB,SAAS,WACT,OACA,iBACA,SAAS,OACV;EACD,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB;GACA,SAASd,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,CAAC,WAAW;GACd,MAAM,OAAO,4BAA4B,SAAS,WAAW,QAAQ,cAAc,UAAU;AAC7F,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,gCACb,SAAS,WACT,WACA,QACA,cACA,UACD;GACD,MAAM,eAAee,8CAAyB,QAAQ;AAStD,OAAI,CARc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,iBAAiB,QAAQ;IACzB;IACA,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,SAAQ,IAAI;EACV,QAAQ,IAAI,UAAU;EACtB;EACA,SAASf,+BAAe,IAAI,QAAQ;EACpC,MAAM;EACN,UAAU;GAAE,QAAQ;GAAK;GAAS;EACnC,CAAC;AACF,uCACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;EACL,SAAS;EACT,MAAM;EACN,QAAQ;EACT,EACF,CAAC,CACH"}