{"version":3,"file":"gemini-interactions.cjs","names":["generateToolCallId","calculateDelay","delay","flattenHeaders","getContext","getTestId","matchFixtureDiagnostic","applyChaos","resolveStrictMode","strictNoMatchMessage","strictNoMatchLogLine","strictOverrideField","proxyAndRecord","resolveResponse","isErrorResponse","isContentWithToolCallsResponse","extractOverrides","createInterruptionSignal","isTextResponse","isToolCallResponse"],"sources":["../src/gemini-interactions.ts"],"sourcesContent":["/**\n * Google Gemini Interactions API support.\n *\n * Translates incoming Interactions requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back\n * into the Gemini Interactions format — either a single JSON response or\n * an SSE stream with event_type-based framing.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n  ChatCompletionRequest,\n  ChatMessage,\n  Fixture,\n  HandlerDefaults,\n  RecordedTimings,\n  ResponseOverrides,\n  StreamingProfile,\n  ToolCall,\n  ToolDefinition,\n} from \"./types.js\";\nimport {\n  isTextResponse,\n  isToolCallResponse,\n  isContentWithToolCallsResponse,\n  isErrorResponse,\n  extractOverrides,\n  generateToolCallId,\n  flattenHeaders,\n  getTestId,\n  getContext,\n  resolveResponse,\n  resolveStrictMode,\n  strictOverrideField,\n  strictNoMatchMessage,\n  strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { matchFixtureDiagnostic } 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// ─── Interactions request types ────────────────────────────────────────────\n\ninterface InteractionsContentBlock {\n  type: string;\n  text?: string;\n  name?: string;\n  call_id?: string;\n  id?: string;\n  arguments?: Record<string, unknown>;\n  output?: unknown;\n  result?: unknown;\n}\n\ninterface InteractionsTurn {\n  role: string;\n  content?: InteractionsContentBlock[];\n  parts?: InteractionsContentBlock[];\n}\n\n/**\n * Top-level Step envelope accepted by the live Gemini Interactions API.\n * The SDK's TypeScript union does not include Step[], but the wire contract\n * does — clients following the live API send these at the top level of `input`.\n * Discriminated by `type`; no `role` field (distinguishes from Turn[]).\n */\ninterface InteractionsStep {\n  type: string;\n  content?: InteractionsContentBlock[];\n  call_id?: string;\n  id?: string;\n  name?: string;\n  result?: unknown;\n  output?: unknown;\n  is_error?: boolean;\n  signature?: string;\n}\n\n/** Step types whose payload is a tool/agent result keyed by call_id. */\nconst STEP_RESULT_TYPES = new Set<string>([\n  \"function_result\",\n  \"code_execution_result\",\n  \"url_context_result\",\n  \"google_search_result\",\n  \"google_maps_result\",\n  \"mcp_server_tool_result\",\n  \"file_search_result\",\n]);\n\n/** All recognized top-level Step types (used as the Step[] discriminator). */\nconst STEP_TYPES = new Set<string>([\"user_input\", \"model_output\", ...STEP_RESULT_TYPES]);\n\ninterface InteractionsFunctionTool {\n  type: \"function\";\n  name: string;\n  description?: string;\n  parameters?: object;\n}\n\ninterface InteractionsRequest {\n  model?: string;\n  input?: string | InteractionsTurn[] | InteractionsStep[] | InteractionsContentBlock[];\n  system_instruction?: string;\n  tools?: InteractionsFunctionTool[];\n  generation_config?: {\n    temperature?: number;\n    max_output_tokens?: number;\n    [key: string]: unknown;\n  };\n  stream?: boolean;\n  previous_interaction_id?: string;\n  [key: string]: unknown;\n}\n\n// ─── Input conversion: Interactions → ChatCompletionRequest ───────────────\n\nexport function geminiInteractionsToCompletionRequest(\n  req: InteractionsRequest,\n): ChatCompletionRequest {\n  const messages: ChatMessage[] = [];\n  const model = req.model ?? \"gemini-2.5-flash\";\n\n  // system_instruction → system message\n  if (req.system_instruction) {\n    messages.push({ role: \"system\", content: req.system_instruction });\n  }\n\n  // Parse input\n  if (req.input !== undefined) {\n    if (typeof req.input === \"string\") {\n      // Simple string input → single user message\n      messages.push({ role: \"user\", content: req.input });\n    } else if (Array.isArray(req.input)) {\n      // Could be Turn[], Step[], or Content[]\n      const firstItem = req.input[0] as\n        | InteractionsTurn\n        | InteractionsStep\n        | InteractionsContentBlock\n        | undefined;\n      const isStepArray =\n        !!firstItem &&\n        !(\"role\" in firstItem) &&\n        typeof firstItem.type === \"string\" &&\n        STEP_TYPES.has(firstItem.type);\n\n      if (firstItem && \"role\" in firstItem) {\n        // Turn[] format\n        for (const turn of req.input as InteractionsTurn[]) {\n          const role = turn.role === \"model\" ? \"assistant\" : turn.role;\n          const blocks = turn.content ?? turn.parts;\n          if (!blocks || blocks.length === 0) {\n            if (role === \"user\" || role === \"assistant\") {\n              messages.push({ role: role as \"user\" | \"assistant\", content: \"\" });\n            }\n            continue;\n          }\n\n          // Check for function_call or function_result parts\n          const funcCallParts = blocks.filter((p) => p.type === \"function_call\");\n          const funcResultParts = blocks.filter((p) => p.type === \"function_result\");\n          const textParts = blocks.filter((p) => p.type === \"text\");\n\n          if (funcCallParts.length > 0) {\n            // Assistant tool call message\n            const textContent = textParts.map((p) => p.text ?? \"\").join(\"\");\n            messages.push({\n              role: \"assistant\",\n              content: textContent || null,\n              tool_calls: funcCallParts.map((p) => ({\n                id: p.id ?? p.call_id ?? generateToolCallId(),\n                type: \"function\" as const,\n                function: {\n                  name: p.name ?? \"\",\n                  arguments: JSON.stringify(p.arguments ?? {}),\n                },\n              })),\n            });\n          } else if (funcResultParts.length > 0) {\n            // Tool response messages\n            for (const part of funcResultParts) {\n              const resultValue = part.result ?? part.output;\n              messages.push({\n                role: \"tool\",\n                content:\n                  typeof resultValue === \"string\" ? resultValue : JSON.stringify(resultValue ?? \"\"),\n                tool_call_id: part.call_id ?? part.id ?? \"\",\n              });\n            }\n            // Any text parts alongside → separate user message\n            if (textParts.length > 0) {\n              const text = textParts.map((p) => p.text ?? \"\").join(\"\");\n              if (text) {\n                messages.push({ role: \"user\", content: text });\n              }\n            }\n          } else {\n            // Text-only turn\n            const text = textParts.map((p) => p.text ?? \"\").join(\"\");\n            if (role === \"user\" || role === \"assistant\" || role === \"system\") {\n              messages.push({\n                role: role as \"user\" | \"assistant\" | \"system\",\n                content: text,\n              });\n            }\n          }\n        }\n      } else if (isStepArray) {\n        // Step[] format — the wire contract Google's /v1beta/interactions accepts.\n        for (const step of req.input as InteractionsStep[]) {\n          if (step.type === \"user_input\") {\n            const text = (step.content ?? [])\n              .filter((p) => p.type === \"text\")\n              .map((p) => p.text ?? \"\")\n              .join(\"\");\n            messages.push({ role: \"user\", content: text });\n          } else if (step.type === \"model_output\") {\n            const blocks = step.content ?? [];\n            const funcCallParts = blocks.filter((p) => p.type === \"function_call\");\n            const textParts = blocks.filter((p) => p.type === \"text\");\n            const textContent = textParts.map((p) => p.text ?? \"\").join(\"\");\n\n            if (funcCallParts.length > 0) {\n              messages.push({\n                role: \"assistant\",\n                content: textContent || null,\n                tool_calls: funcCallParts.map((p) => ({\n                  id: p.id ?? p.call_id ?? generateToolCallId(),\n                  type: \"function\" as const,\n                  function: {\n                    name: p.name ?? \"\",\n                    arguments: JSON.stringify(p.arguments ?? {}),\n                  },\n                })),\n              });\n            } else {\n              messages.push({ role: \"assistant\", content: textContent });\n            }\n          } else if (STEP_RESULT_TYPES.has(step.type)) {\n            const resultValue = step.result ?? step.output;\n            messages.push({\n              role: \"tool\",\n              content:\n                typeof resultValue === \"string\" ? resultValue : JSON.stringify(resultValue ?? \"\"),\n              tool_call_id: step.call_id ?? step.id ?? \"\",\n            });\n          }\n        }\n      } else {\n        // Content[] format — single user message with content blocks\n        const textParts = (req.input as InteractionsContentBlock[]).filter(\n          (p) => p.type === \"text\",\n        );\n        const text = textParts.map((p) => p.text ?? \"\").join(\"\");\n        messages.push({ role: \"user\", content: text || \"\" });\n      }\n    }\n  }\n\n  // Convert tools\n  let tools: ToolDefinition[] | undefined;\n  if (req.tools && req.tools.length > 0) {\n    const funcTools = req.tools.filter((t) => t.type === \"function\");\n    if (funcTools.length > 0) {\n      tools = funcTools.map((t) => ({\n        type: \"function\" as const,\n        function: {\n          name: t.name,\n          description: t.description,\n          parameters: t.parameters,\n        },\n      }));\n    }\n  }\n\n  return {\n    model,\n    messages,\n    stream: req.stream !== false, // default true\n    temperature: req.generation_config?.temperature,\n    max_tokens: req.generation_config?.max_output_tokens,\n    tools,\n  };\n}\n\n// ─── Interaction ID generation ────────────────────────────────────────────\n\nlet interactionCounter = 0;\n\nexport function resetInteractionCounter(): void {\n  interactionCounter = 0;\n}\n\nfunction nextInteractionId(): string {\n  return `aimock-int-${interactionCounter++}`;\n}\n\n// ─── Usage helpers ────────────────────────────────────────────────────────\n\nfunction interactionsUsage(overrides?: ResponseOverrides): {\n  total_input_tokens: number;\n  total_output_tokens: number;\n  total_tokens: number;\n} {\n  if (!overrides?.usage) return { total_input_tokens: 0, total_output_tokens: 0, total_tokens: 0 };\n  const input =\n    overrides.usage.input_tokens ??\n    overrides.usage.prompt_tokens ??\n    overrides.usage.promptTokenCount ??\n    0;\n  const output =\n    overrides.usage.output_tokens ??\n    overrides.usage.completion_tokens ??\n    overrides.usage.candidatesTokenCount ??\n    0;\n  const total = overrides.usage.total_tokens ?? overrides.usage.totalTokenCount ?? input + output;\n  return {\n    total_input_tokens: input,\n    total_output_tokens: output,\n    total_tokens: total,\n  };\n}\n\n// ─── Response building: fixture → Interactions format ─────────────────────\n\nexport function buildInteractionsTextResponse(\n  content: string,\n  model: string,\n  interactionId: string,\n  overrides?: ResponseOverrides,\n): object {\n  return {\n    id: interactionId,\n    status: \"completed\",\n    model: overrides?.model ?? model,\n    role: \"model\",\n    output_text: content,\n    steps: [{ type: \"model_output\", content: [{ type: \"text\", text: content }] }],\n    usage: interactionsUsage(overrides),\n  };\n}\n\n// Build a single SDK 2.x function_call step from a fixture tool call,\n// reusing the existing malformed-arguments guard (logger.warn + {} fallback).\nfunction buildFunctionCallStep(tc: ToolCall, logger: Logger): object {\n  let argsObj: unknown;\n  try {\n    argsObj = JSON.parse(tc.arguments || \"{}\");\n  } catch {\n    logger.warn(`Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`);\n    argsObj = {};\n  }\n  return {\n    type: \"function_call\",\n    id: tc.id || generateToolCallId(),\n    name: tc.name,\n    arguments: argsObj,\n  };\n}\n\nexport function buildInteractionsToolCallResponse(\n  toolCalls: ToolCall[],\n  model: string,\n  interactionId: string,\n  logger: Logger,\n  overrides?: ResponseOverrides,\n): object {\n  return {\n    id: interactionId,\n    status: \"requires_action\",\n    model: overrides?.model ?? model,\n    role: \"model\",\n    steps: toolCalls.map((tc) => buildFunctionCallStep(tc, logger)),\n    usage: interactionsUsage(overrides),\n  };\n}\n\nexport function buildInteractionsContentWithToolCallsResponse(\n  content: string,\n  toolCalls: ToolCall[],\n  model: string,\n  interactionId: string,\n  logger: Logger,\n  overrides?: ResponseOverrides,\n): object {\n  const steps: object[] = [{ type: \"model_output\", content: [{ type: \"text\", text: content }] }];\n  for (const tc of toolCalls) {\n    steps.push(buildFunctionCallStep(tc, logger));\n  }\n\n  return {\n    id: interactionId,\n    status: \"requires_action\",\n    model: overrides?.model ?? model,\n    role: \"model\",\n    output_text: content,\n    steps,\n    usage: interactionsUsage(overrides),\n  };\n}\n\nfunction buildInteractionsErrorResponse(message: string, code?: string): object {\n  return {\n    error: {\n      code: code ?? \"INVALID_ARGUMENT\",\n      message,\n    },\n  };\n}\n\n// ─── SSE event builders ──────────────────────────────────────────────────\n\ninterface InteractionsSSEEvent {\n  event_type: string;\n  [key: string]: unknown;\n}\n\nlet eventIdCounter = 0;\n\nexport function resetEventIdCounter(): void {\n  eventIdCounter = 0;\n}\n\nfunction nextEventId(): string {\n  return `evt_${++eventIdCounter}`;\n}\n\nexport function buildInteractionsTextSSEEvents(\n  content: string,\n  interactionId: string,\n  chunkSize: number,\n  overrides?: ResponseOverrides,\n): InteractionsSSEEvent[] {\n  const events: InteractionsSSEEvent[] = [];\n\n  // interaction.created\n  events.push({\n    event_type: \"interaction.created\",\n    interaction: { id: interactionId, status: \"in_progress\" },\n    event_id: nextEventId(),\n  });\n\n  // step.start — text step is the model_output\n  events.push({\n    event_type: \"step.start\",\n    index: 0,\n    step: { type: \"model_output\" },\n    event_id: nextEventId(),\n  });\n\n  // step.delta(s) — inner delta shape is unchanged ({ type: \"text\", text })\n  if (content.length === 0) {\n    events.push({\n      event_type: \"step.delta\",\n      index: 0,\n      delta: { type: \"text\", text: \"\" },\n      event_id: nextEventId(),\n    });\n  } else {\n    for (let i = 0; i < content.length; i += chunkSize) {\n      const slice = content.slice(i, i + chunkSize);\n      events.push({\n        event_type: \"step.delta\",\n        index: 0,\n        delta: { type: \"text\", text: slice },\n        event_id: nextEventId(),\n      });\n    }\n  }\n\n  // step.stop\n  events.push({\n    event_type: \"step.stop\",\n    index: 0,\n    event_id: nextEventId(),\n  });\n\n  // interaction.completed\n  events.push({\n    event_type: \"interaction.completed\",\n    interaction: {\n      id: interactionId,\n      status: \"completed\",\n      usage: interactionsUsage(overrides),\n    },\n    event_id: nextEventId(),\n  });\n\n  return events;\n}\n\nexport function buildInteractionsToolCallSSEEvents(\n  toolCalls: ToolCall[],\n  interactionId: string,\n  logger: Logger,\n  overrides?: ResponseOverrides,\n): InteractionsSSEEvent[] {\n  const events: InteractionsSSEEvent[] = [];\n\n  // interaction.created\n  events.push({\n    event_type: \"interaction.created\",\n    interaction: { id: interactionId, status: \"in_progress\" },\n    event_id: nextEventId(),\n  });\n\n  // Each tool call gets its own step.start/delta/stop bracket. In SDK 2.x the\n  // call identity (id, name) lives on step.start; the arguments stream as a\n  // dedicated `arguments_delta` carrying a JSON-string fragment, and step.start\n  // carries an empty `arguments: {}` placeholder.\n  for (let idx = 0; idx < toolCalls.length; idx++) {\n    const tc = toolCalls[idx];\n    let argsObj: unknown;\n    try {\n      argsObj = JSON.parse(tc.arguments || \"{}\");\n    } catch {\n      logger.warn(\n        `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n      );\n      argsObj = {};\n    }\n\n    events.push({\n      event_type: \"step.start\",\n      index: idx,\n      step: {\n        type: \"function_call\",\n        id: tc.id || generateToolCallId(),\n        name: tc.name,\n        arguments: {},\n      },\n      event_id: nextEventId(),\n    });\n\n    // arguments_delta.arguments is a string fragment. The real SDK may split\n    // the args across several fragments that concatenate into valid JSON; the\n    // mock emits the whole serialized object as one fragment (a valid\n    // degenerate case the collapser handles identically).\n    events.push({\n      event_type: \"step.delta\",\n      index: idx,\n      delta: {\n        type: \"arguments_delta\",\n        arguments: JSON.stringify(argsObj),\n      },\n      event_id: nextEventId(),\n    });\n\n    events.push({\n      event_type: \"step.stop\",\n      index: idx,\n      event_id: nextEventId(),\n    });\n  }\n\n  // interaction.completed\n  events.push({\n    event_type: \"interaction.completed\",\n    interaction: {\n      id: interactionId,\n      status: \"requires_action\",\n      usage: interactionsUsage(overrides),\n    },\n    event_id: nextEventId(),\n  });\n\n  return events;\n}\n\nexport function buildInteractionsContentWithToolCallsSSEEvents(\n  content: string,\n  toolCalls: ToolCall[],\n  interactionId: string,\n  chunkSize: number,\n  logger: Logger,\n  overrides?: ResponseOverrides,\n): InteractionsSSEEvent[] {\n  const events: InteractionsSSEEvent[] = [];\n\n  // interaction.created\n  events.push({\n    event_type: \"interaction.created\",\n    interaction: { id: interactionId, status: \"in_progress\" },\n    event_id: nextEventId(),\n  });\n\n  // Text content at index 0 (model_output step)\n  events.push({\n    event_type: \"step.start\",\n    index: 0,\n    step: { type: \"model_output\" },\n    event_id: nextEventId(),\n  });\n\n  if (content.length === 0) {\n    events.push({\n      event_type: \"step.delta\",\n      index: 0,\n      delta: { type: \"text\", text: \"\" },\n      event_id: nextEventId(),\n    });\n  } else {\n    for (let i = 0; i < content.length; i += chunkSize) {\n      const slice = content.slice(i, i + chunkSize);\n      events.push({\n        event_type: \"step.delta\",\n        index: 0,\n        delta: { type: \"text\", text: slice },\n        event_id: nextEventId(),\n      });\n    }\n  }\n\n  events.push({\n    event_type: \"step.stop\",\n    index: 0,\n    event_id: nextEventId(),\n  });\n\n  // Tool calls at index 1+ (identity on step.start, args as arguments_delta)\n  for (let i = 0; i < toolCalls.length; i++) {\n    const tc = toolCalls[i];\n    const idx = i + 1; // offset by 1 because text is index 0\n    let argsObj: unknown;\n    try {\n      argsObj = JSON.parse(tc.arguments || \"{}\");\n    } catch {\n      logger.warn(\n        `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n      );\n      argsObj = {};\n    }\n\n    events.push({\n      event_type: \"step.start\",\n      index: idx,\n      step: {\n        type: \"function_call\",\n        id: tc.id || generateToolCallId(),\n        name: tc.name,\n        arguments: {},\n      },\n      event_id: nextEventId(),\n    });\n\n    events.push({\n      event_type: \"step.delta\",\n      index: idx,\n      delta: {\n        type: \"arguments_delta\",\n        arguments: JSON.stringify(argsObj),\n      },\n      event_id: nextEventId(),\n    });\n\n    events.push({\n      event_type: \"step.stop\",\n      index: idx,\n      event_id: nextEventId(),\n    });\n  }\n\n  // interaction.completed\n  events.push({\n    event_type: \"interaction.completed\",\n    interaction: {\n      id: interactionId,\n      status: \"requires_action\",\n      usage: interactionsUsage(overrides),\n    },\n    event_id: nextEventId(),\n  });\n\n  return events;\n}\n\n// ─── SSE writer for Interactions streaming ────────────────────────────────\n\ninterface InteractionsStreamOptions {\n  latency?: number;\n  streamingProfile?: StreamingProfile;\n  recordedTimings?: RecordedTimings;\n  replaySpeed?: number;\n  signal?: AbortSignal;\n  onChunkSent?: () => void;\n}\n\nexport async function writeGeminiInteractionsSSEStream(\n  res: http.ServerResponse,\n  events: InteractionsSSEEvent[],\n  optionsOrLatency?: number | InteractionsStreamOptions,\n): Promise<boolean> {\n  const opts: InteractionsStreamOptions =\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 event of events) {\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    // Data-only SSE (no event: prefix, no [DONE])\n    res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n    // Only count step deltas for truncateAfterChunks — framing events\n    // (interaction.created, step.start, step.stop, interaction.completed)\n    // should not consume chunk budget or trigger the chunk-sent callback.\n    if (event.event_type === \"step.delta\") {\n      onChunkSent?.();\n      chunkIndex++;\n    }\n    if (signal?.aborted) return false;\n  }\n\n  if (!res.writableEnded) {\n    res.end();\n  }\n  return true;\n}\n\n// ─── Request handler ──────────────────────────────────────────────────────\n\nexport async function handleGeminiInteractions(\n  req: http.IncomingMessage,\n  res: http.ServerResponse,\n  raw: string,\n  fixtures: Fixture[],\n  journal: Journal,\n  defaults: HandlerDefaults,\n  setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n  const { logger } = defaults;\n  setCorsHeaders(res);\n\n  const urlPath = req.url ?? \"/v1beta/interactions\";\n\n  let interactionsReq: InteractionsRequest;\n  try {\n    interactionsReq = JSON.parse(raw) as InteractionsRequest;\n  } catch (parseErr) {\n    const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n    journal.add({\n      method: req.method ?? \"POST\",\n      path: urlPath,\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        buildInteractionsErrorResponse(`Malformed JSON body: ${detail}`, \"INVALID_ARGUMENT\"),\n      ),\n    );\n    return;\n  }\n\n  // Convert to ChatCompletionRequest for fixture matching\n  const completionReq = geminiInteractionsToCompletionRequest(interactionsReq);\n  // Keep \"chat\" rather than \"gemini-interactions\" — the router's endpoint\n  // compatibility filter (router.ts) treats \"chat\" as a pass-through that\n  // matches any unendpointed fixture.  Switching to \"gemini-interactions\"\n  // would make the request fall into the multimedia guard branch, preventing\n  // generic chat fixtures from matching and breaking existing users.  The\n  // recorder would also start emitting `endpoint: \"gemini-interactions\"` in\n  // recorded fixtures, creating a one-way compatibility break.\n  completionReq._endpointType = \"chat\";\n  completionReq._context = getContext(req);\n\n  const streaming = interactionsReq.stream !== false; // default true\n  const model = completionReq.model;\n\n  const testId = getTestId(req);\n  const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n    fixtures,\n    completionReq,\n    journal.getFixtureMatchCountsForTest(testId),\n    defaults.requestTransform,\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: urlPath,\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 strictStatus = 503;\n      const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n      logger.error(strictNoMatchLogLine(req.method ?? \"POST\", urlPath, skippedBySequenceOrTurn));\n      journal.add({\n        method: req.method ?? \"POST\",\n        path: urlPath,\n        headers: flattenHeaders(req.headers),\n        body: completionReq,\n        response: {\n          status: strictStatus,\n          fixture: null,\n          ...strictOverrideField(defaults.strict, req.headers),\n        },\n      });\n      writeErrorResponse(\n        res,\n        strictStatus,\n        JSON.stringify(buildInteractionsErrorResponse(strictMessage, \"UNAVAILABLE\")),\n      );\n      return;\n    }\n    if (defaults.record) {\n      const outcome = await proxyAndRecord(\n        req,\n        res,\n        completionReq,\n        \"gemini-interactions\",\n        urlPath,\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: urlPath,\n          headers: flattenHeaders(req.headers),\n          body: completionReq,\n          response: {\n            status: res.statusCode ?? 200,\n            fixture: null,\n            source: \"proxy\",\n          },\n        });\n        return;\n      }\n    }\n    journal.add({\n      method: req.method ?? \"POST\",\n      path: urlPath,\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(buildInteractionsErrorResponse(\"No fixture matched\", \"NOT_FOUND\")),\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: urlPath,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status, fixture },\n    });\n    writeErrorResponse(\n      res,\n      status,\n      JSON.stringify(\n        buildInteractionsErrorResponse(response.error.message, response.error.type ?? \"ERROR\"),\n      ),\n      { retryAfter: response.retryAfter },\n    );\n    return;\n  }\n\n  const interactionId = nextInteractionId();\n\n  // Content + tool calls response\n  if (isContentWithToolCallsResponse(response)) {\n    if (response.webSearches?.length) {\n      logger.warn(\n        \"webSearches in fixture response are not supported for Gemini Interactions API — ignoring\",\n      );\n    }\n    const overrides = extractOverrides(response);\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path: urlPath,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildInteractionsContentWithToolCallsResponse(\n        response.content,\n        response.toolCalls,\n        model,\n        interactionId,\n        logger,\n        overrides,\n      );\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const events = buildInteractionsContentWithToolCallsSSEEvents(\n        response.content,\n        response.toolCalls,\n        interactionId,\n        chunkSize,\n        logger,\n        overrides,\n      );\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiInteractionsSSEStream(res, events, {\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(\n        \"webSearches in fixture response are not supported for Gemini Interactions API — ignoring\",\n      );\n    }\n    const overrides = extractOverrides(response);\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path: urlPath,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildInteractionsTextResponse(response.content, model, interactionId, overrides);\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const events = buildInteractionsTextSSEEvents(\n        response.content,\n        interactionId,\n        chunkSize,\n        overrides,\n      );\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiInteractionsSSEStream(res, events, {\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(\n        \"webSearches in fixture response are not supported for Gemini Interactions API — ignoring\",\n      );\n    }\n    const overrides = extractOverrides(response);\n    const journalEntry = journal.add({\n      method: req.method ?? \"POST\",\n      path: urlPath,\n      headers: flattenHeaders(req.headers),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n    if (!streaming) {\n      const body = buildInteractionsToolCallResponse(\n        response.toolCalls,\n        model,\n        interactionId,\n        logger,\n        overrides,\n      );\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(body));\n    } else {\n      const events = buildInteractionsToolCallSSEEvents(\n        response.toolCalls,\n        interactionId,\n        logger,\n        overrides,\n      );\n      const interruption = createInterruptionSignal(fixture);\n      const completed = await writeGeminiInteractionsSSEStream(res, events, {\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: urlPath,\n    headers: flattenHeaders(req.headers),\n    body: completionReq,\n    response: { status: 500, fixture },\n  });\n  writeErrorResponse(\n    res,\n    500,\n    JSON.stringify(\n      buildInteractionsErrorResponse(\"Fixture response did not match any known type\", \"INTERNAL\"),\n    ),\n  );\n}\n"],"mappings":"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"}