{"version":3,"file":"ws-realtime.cjs","names":["generateToolCallId","DEFAULT_TEST_ID","matchFixtureDiagnostic","resolveStrictMode","strictNoMatchMessage","strictNoMatchLogLine","flattenHeaders","strictOverrideField","resolveResponse","isErrorResponse","isContentWithToolCallsResponse","createInterruptionSignal","calculateDelay","delay","isTextResponse","isToolCallResponse"],"sources":["../src/ws-realtime.ts"],"sourcesContent":["/**\n * WebSocket handler for OpenAI Realtime API.\n *\n * Accepts Realtime API messages (session.update, conversation.item.create,\n * response.create) over WebSocket and sends back Realtime API events as\n * individual WebSocket text frames.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport type { ChatCompletionRequest, ChatMessage, Fixture } from \"./types.js\";\nimport { matchFixtureDiagnostic } from \"./router.js\";\nimport {\n  generateToolCallId,\n  flattenHeaders,\n  isTextResponse,\n  isToolCallResponse,\n  isContentWithToolCallsResponse,\n  isErrorResponse,\n  resolveResponse,\n  resolveStrictMode,\n  strictOverrideField,\n  strictNoMatchMessage,\n  strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport { delay, calculateDelay } from \"./sse-writer.js\";\nimport { DEFAULT_TEST_ID, type Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport type { WebSocketConnection } from \"./ws-framing.js\";\n\n/** Generate a Realtime-API-style ID with underscore separator (e.g. event_xxx, item_xxx). */\nfunction realtimeId(prefix: string): string {\n  return `${prefix}_${randomBytes(12).toString(\"base64url\")}`;\n}\n\n// ─── Realtime protocol types ────────────────────────────────────────────────\n\ninterface RealtimeItem {\n  type: \"message\" | \"function_call\" | \"function_call_output\";\n  id?: string;\n  role?: \"user\" | \"assistant\" | \"system\";\n  content?: Array<{ type: string; text?: string; url?: string; transcript?: string | null }>;\n  name?: string;\n  call_id?: string;\n  arguments?: string;\n  output?: string;\n}\n\ninterface SessionConfig {\n  model: string;\n  modalities: string[];\n  instructions: string;\n  tools: unknown[];\n  voice: string | null;\n  input_audio_format: string | null;\n  output_audio_format: string | null;\n  input_audio_noise_reduction: { type: string } | null;\n  input_audio_transcription: { model: string } | null;\n  turn_detection: unknown | null;\n  temperature: number;\n  type: \"conversation\" | \"transcription\" | \"translation\";\n  reasoning: { effort: string } | null;\n}\n\ninterface RealtimeMessage {\n  type: string;\n  event_id?: string;\n  session?: Partial<SessionConfig>;\n  item?: RealtimeItem;\n  response?: {\n    modalities?: string[];\n    instructions?: string;\n    [key: string]: unknown;\n  };\n}\n\n// ─── Conversion helpers ─────────────────────────────────────────────────────\n\nexport function realtimeItemsToMessages(\n  items: RealtimeItem[],\n  instructions?: string,\n  logger?: Logger,\n): ChatMessage[] {\n  const messages: ChatMessage[] = [];\n\n  if (instructions) {\n    messages.push({ role: \"system\", content: instructions });\n  }\n\n  for (const item of items) {\n    if (item.type === \"message\") {\n      const role =\n        item.role === \"assistant\" ? \"assistant\" : item.role === \"system\" ? \"system\" : \"user\";\n\n      // Check if content contains multimodal input types (input_text, input_image, input_audio)\n      const hasMultimodal = item.content?.some(\n        (p) => p.type === \"input_text\" || p.type === \"input_image\" || p.type === \"input_audio\",\n      );\n\n      if (hasMultimodal && item.content) {\n        // Map realtime input content types to ChatMessage content parts\n        const mappedContent = item.content.map((part) => {\n          if (part.type === \"input_text\") {\n            return { type: \"text\" as const, text: part.text ?? \"\" };\n          }\n          if (part.type === \"input_image\") {\n            return {\n              type: \"image_url\" as const,\n              image_url: { url: part.url ?? \"\" },\n            };\n          }\n          if (part.type === \"input_audio\") {\n            return { type: \"text\" as const, text: \"[audio input]\" };\n          }\n          // Pass through unknown content types as-is\n          return part;\n        });\n        messages.push({ role, content: mappedContent });\n      } else {\n        // Join all text content parts (not just the first)\n        const text =\n          item.content\n            ?.map((c) => c.text)\n            .filter(Boolean)\n            .join(\"\") ?? \"\";\n        messages.push({ role, content: text });\n      }\n    } else if (item.type === \"function_call\") {\n      if (!item.name) {\n        logger?.warn(\"Realtime function_call item missing 'name'\");\n      }\n      messages.push({\n        role: \"assistant\",\n        content: null,\n        tool_calls: [\n          {\n            id: item.call_id ?? generateToolCallId(),\n            type: \"function\",\n            function: {\n              name: item.name ?? \"\",\n              arguments: item.arguments ?? \"\",\n            },\n          },\n        ],\n      });\n    } else if (item.type === \"function_call_output\") {\n      if (!item.output) {\n        logger?.warn(\"Realtime function_call_output item missing 'output'\");\n      }\n      messages.push({\n        role: \"tool\",\n        content: item.output ?? \"\",\n        tool_call_id: item.call_id,\n      });\n    }\n  }\n\n  return messages;\n}\n\n// ─── GA -> Beta translation ─────────────────────────────────────────────────\n\n/** GA -> Beta event name mapping */\nconst GA_TO_BETA_EVENT: Record<string, string> = {\n  \"response.output_text.delta\": \"response.text.delta\",\n  \"response.output_text.done\": \"response.text.done\",\n  \"response.output_audio.delta\": \"response.audio.delta\",\n  \"response.output_audio.done\": \"response.audio.done\",\n  \"response.output_audio_transcript.delta\": \"response.audio_transcript.delta\",\n  \"response.output_audio_transcript.done\": \"response.audio_transcript.done\",\n  \"conversation.item.added\": \"conversation.item.created\",\n};\n\n/** GA -> Beta content type mapping */\nconst GA_TO_BETA_CONTENT_TYPE: Record<string, string> = {\n  output_text: \"text\",\n  output_audio: \"audio\",\n};\n\n/** Events suppressed in Beta mode (GA-only events) */\nconst BETA_SUPPRESSED_EVENTS = new Set([\"conversation.item.done\"]);\n\nfunction translateGAToBeta(event: Record<string, unknown>): Record<string, unknown> | null {\n  const type = event.type as string;\n  if (BETA_SUPPRESSED_EVENTS.has(type)) return null;\n\n  const translated = { ...event };\n  if (GA_TO_BETA_EVENT[type]) {\n    translated.type = GA_TO_BETA_EVENT[type];\n  }\n\n  // Translate content types in nested structures\n  if (translated.part && typeof translated.part === \"object\") {\n    const part = { ...(translated.part as Record<string, unknown>) };\n    if (typeof part.type === \"string\" && GA_TO_BETA_CONTENT_TYPE[part.type]) {\n      part.type = GA_TO_BETA_CONTENT_TYPE[part.type];\n    }\n    translated.part = part;\n  }\n  if (translated.content_part && typeof translated.content_part === \"object\") {\n    const cp = { ...(translated.content_part as Record<string, unknown>) };\n    if (typeof cp.type === \"string\" && GA_TO_BETA_CONTENT_TYPE[cp.type]) {\n      cp.type = GA_TO_BETA_CONTENT_TYPE[cp.type];\n    }\n    translated.content_part = cp;\n  }\n  // Translate content arrays\n  if (Array.isArray(translated.content)) {\n    translated.content = (translated.content as Record<string, unknown>[]).map((c) => {\n      if (typeof c.type === \"string\" && GA_TO_BETA_CONTENT_TYPE[c.type]) {\n        return { ...c, type: GA_TO_BETA_CONTENT_TYPE[c.type] };\n      }\n      return c;\n    });\n  }\n  // Translate item.content arrays (response.output_item.added/done, conversation.item.added)\n  if (translated.item && typeof translated.item === \"object\") {\n    const item = { ...(translated.item as Record<string, unknown>) };\n    delete item.phase; // GA-only field\n    if (Array.isArray(item.content)) {\n      item.content = (item.content as Record<string, unknown>[]).map((c) => {\n        if (typeof c.type === \"string\" && GA_TO_BETA_CONTENT_TYPE[c.type]) {\n          return { ...c, type: GA_TO_BETA_CONTENT_TYPE[c.type] };\n        }\n        return c;\n      });\n    }\n    translated.item = item;\n  }\n  // Translate response.output[].content arrays (response.done)\n  if (translated.response && typeof translated.response === \"object\") {\n    const resp = { ...(translated.response as Record<string, unknown>) };\n    if (Array.isArray(resp.output)) {\n      resp.output = (resp.output as Record<string, unknown>[]).map((outItem) => {\n        const o = { ...(outItem as Record<string, unknown>) };\n        if (Array.isArray(o.content)) {\n          o.content = (o.content as Record<string, unknown>[]).map((c) =>\n            typeof c.type === \"string\" && GA_TO_BETA_CONTENT_TYPE[c.type]\n              ? { ...c, type: GA_TO_BETA_CONTENT_TYPE[c.type] }\n              : c,\n          );\n        }\n        return o;\n      });\n    }\n    translated.response = resp;\n  }\n\n  // Flatten GA session config for Beta (session.created / session.updated)\n  if (type === \"session.created\" || type === \"session.updated\") {\n    if (translated.session && typeof translated.session === \"object\") {\n      const session = { ...(translated.session as Record<string, unknown>) };\n      if (session.audio && typeof session.audio === \"object\") {\n        const audio = session.audio as Record<string, unknown>;\n        session.voice = audio.voice;\n        session.input_audio_format = audio.input_audio_format;\n        session.output_audio_format = audio.output_audio_format;\n        session.input_audio_transcription = audio.input_audio_transcription;\n        delete session.audio;\n      }\n      delete session.type;\n      delete session.reasoning;\n      translated.session = session;\n    }\n  }\n\n  return translated;\n}\n\n// ─── Event sending ──────────────────────────────────────────────────────────\n\nfunction sendEvent(ws: WebSocketConnection, event: Record<string, unknown>, isBeta: boolean): void {\n  const out = { ...event, event_id: event.event_id ?? realtimeId(\"event\") };\n  if (isBeta) {\n    const translated = translateGAToBeta(out);\n    if (translated === null) return; // suppressed in Beta mode\n    ws.send(JSON.stringify(translated));\n  } else {\n    ws.send(JSON.stringify(out));\n  }\n}\n\nfunction buildErrorRealtimeEvent(\n  ws: WebSocketConnection,\n  message: string,\n  isBeta: boolean,\n  type = \"invalid_request_error\",\n  code?: string,\n): void {\n  sendEvent(ws, { type: \"error\", error: { message, type, code } }, isBeta);\n}\n\n// ─── Main handler ───────────────────────────────────────────────────────────\n\nexport function handleWebSocketRealtime(\n  ws: WebSocketConnection,\n  fixtures: Fixture[],\n  journal: Journal,\n  defaults: {\n    latency: number;\n    chunkSize: number;\n    replaySpeed?: number;\n    model: string;\n    logger: Logger;\n    strict?: boolean;\n    requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n    testId?: string;\n    upgradeHeaders?: import(\"node:http\").IncomingHttpHeaders;\n  },\n): void {\n  const { logger } = defaults;\n  const sessionId = realtimeId(\"sess\");\n\n  const isBeta = defaults.upgradeHeaders?.[\"openai-beta\"]\n    ? String(defaults.upgradeHeaders[\"openai-beta\"]).includes(\"realtime=v1\")\n    : false;\n\n  const session: SessionConfig = {\n    model: defaults.model,\n    modalities: [\"text\"],\n    instructions: \"\",\n    tools: [],\n    voice: null,\n    input_audio_format: null,\n    output_audio_format: null,\n    input_audio_noise_reduction: null,\n    input_audio_transcription: null,\n    turn_detection: null,\n    temperature: 0.8,\n    type: \"conversation\",\n    reasoning: null,\n  };\n\n  const conversationItems: RealtimeItem[] = [];\n\n  // Send session.created immediately on connect (GA format — shim flattens for Beta)\n  sendEvent(\n    ws,\n    {\n      type: \"session.created\",\n      session: {\n        id: sessionId,\n        object: \"realtime.session\",\n        model: session.model,\n        expires_at: Math.floor(Date.now() / 1000) + 3600,\n        modalities: session.modalities,\n        instructions: session.instructions,\n        tools: session.tools,\n        tool_choice: \"auto\",\n        temperature: session.temperature,\n        max_response_output_tokens: \"inf\",\n        audio: {\n          voice: session.voice,\n          input_audio_format: session.input_audio_format,\n          output_audio_format: session.output_audio_format,\n          input_audio_noise_reduction: session.input_audio_noise_reduction,\n          input_audio_transcription: session.input_audio_transcription,\n        },\n        turn_detection: session.turn_detection,\n        type: session.type,\n        reasoning: session.reasoning,\n      },\n    },\n    isBeta,\n  );\n\n  // Serialize message processing to prevent event interleaving\n  let pending = Promise.resolve();\n  ws.on(\"message\", (raw: string) => {\n    pending = pending.then(() =>\n      processMessage(\n        raw,\n        ws,\n        fixtures,\n        journal,\n        defaults,\n        session,\n        conversationItems,\n        isBeta,\n      ).catch((err: unknown) => {\n        const msg = err instanceof Error ? err.message : \"Internal error\";\n        logger.error(`WebSocket realtime error: ${msg}`);\n        try {\n          buildErrorRealtimeEvent(ws, msg, isBeta, \"server_error\");\n        } catch (sendErr) {\n          defaults.logger.debug(\n            `Failed to send error to client: ${sendErr instanceof Error ? sendErr.message : \"unknown\"}`,\n          );\n        }\n      }),\n    );\n  });\n}\n\nasync function processMessage(\n  raw: string,\n  ws: WebSocketConnection,\n  fixtures: Fixture[],\n  journal: Journal,\n  defaults: {\n    latency: number;\n    chunkSize: number;\n    replaySpeed?: number;\n    model: string;\n    logger: Logger;\n    strict?: boolean;\n    requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n    testId?: string;\n    upgradeHeaders?: import(\"node:http\").IncomingHttpHeaders;\n  },\n  session: SessionConfig,\n  conversationItems: RealtimeItem[],\n  isBeta: boolean,\n): Promise<void> {\n  let parsed: RealtimeMessage;\n  try {\n    parsed = JSON.parse(raw) as RealtimeMessage;\n  } catch (parseErr) {\n    const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n    buildErrorRealtimeEvent(\n      ws,\n      `Malformed JSON: ${detail}`,\n      isBeta,\n      \"invalid_request_error\",\n      \"invalid_json\",\n    );\n    return;\n  }\n\n  const msgType = parsed.type;\n\n  // ── session.update ────────────────────────────────────────────────────\n  if (msgType === \"session.update\") {\n    if (parsed.session) {\n      const s = parsed.session;\n\n      // Validate session.type value before applying any mutations\n      const validTypes = new Set([\"conversation\", \"transcription\", \"translation\"]);\n      if ((s as Record<string, unknown>).type !== undefined) {\n        if (!validTypes.has((s as Record<string, unknown>).type as string)) {\n          sendEvent(\n            ws,\n            {\n              type: \"error\",\n              error: {\n                message: `Invalid session type: ${(s as Record<string, unknown>).type}`,\n                type: \"invalid_request_error\",\n                code: \"invalid_session_config\",\n              },\n            },\n            isBeta,\n          );\n          return;\n        }\n      }\n\n      // Capture full pre-mutation snapshot for rollback on validation failure\n      const prevSession = { ...session };\n\n      if (s.instructions !== undefined) session.instructions = s.instructions;\n      if (s.tools !== undefined) session.tools = s.tools;\n      if (s.modalities !== undefined) session.modalities = s.modalities;\n      if (s.model !== undefined) session.model = s.model;\n      if (s.temperature !== undefined) session.temperature = s.temperature;\n      if ((s as Record<string, unknown>).type !== undefined)\n        session.type = (s as Record<string, unknown>).type as SessionConfig[\"type\"];\n      // GA nested audio config\n      if ((s as Record<string, unknown>).audio) {\n        const audio = (s as Record<string, unknown>).audio as Record<string, unknown>;\n        if (audio.voice !== undefined) session.voice = audio.voice as string | null;\n        if (audio.input_audio_format !== undefined)\n          session.input_audio_format = audio.input_audio_format as string | null;\n        if (audio.output_audio_format !== undefined)\n          session.output_audio_format = audio.output_audio_format as string | null;\n        if (audio.input_audio_noise_reduction !== undefined)\n          session.input_audio_noise_reduction = audio.input_audio_noise_reduction as {\n            type: string;\n          } | null;\n        if (audio.input_audio_transcription !== undefined)\n          session.input_audio_transcription = audio.input_audio_transcription as {\n            model: string;\n          } | null;\n      }\n      // Beta flat fields (backward compat)\n      if (s.voice !== undefined) session.voice = s.voice;\n      if (s.input_audio_format !== undefined) session.input_audio_format = s.input_audio_format;\n      if (s.output_audio_format !== undefined) session.output_audio_format = s.output_audio_format;\n      if (s.input_audio_noise_reduction !== undefined)\n        session.input_audio_noise_reduction = s.input_audio_noise_reduction;\n      if (s.input_audio_transcription !== undefined)\n        session.input_audio_transcription = s.input_audio_transcription;\n      // turn_detection config\n      if (s.turn_detection !== undefined) session.turn_detection = s.turn_detection;\n      // reasoning config\n      if ((s as Record<string, unknown>).reasoning !== undefined)\n        session.reasoning = (s as Record<string, unknown>).reasoning as {\n          effort: string;\n        } | null;\n\n      // Validate model+type combinations (rollback on failure)\n      const transcriptionModels = new Set([\n        \"gpt-4o-transcribe\",\n        \"gpt-4o-mini-transcribe\",\n        \"gpt-realtime-whisper\",\n        \"whisper-1\",\n      ]);\n      const translationModels = new Set([\n        \"gpt-4o-transcribe\",\n        \"gpt-4o-mini-transcribe\",\n        \"gpt-realtime-translate\",\n      ]);\n\n      if (session.type === \"transcription\" && !transcriptionModels.has(session.model)) {\n        Object.assign(session, prevSession);\n        sendEvent(\n          ws,\n          {\n            type: \"error\",\n            error: {\n              message: `Model ${s.model ?? prevSession.model} does not support session type transcription`,\n              type: \"invalid_request_error\",\n              code: \"invalid_session_config\",\n            },\n          },\n          isBeta,\n        );\n        return;\n      }\n      if (session.type === \"translation\" && !translationModels.has(session.model)) {\n        Object.assign(session, prevSession);\n        sendEvent(\n          ws,\n          {\n            type: \"error\",\n            error: {\n              message: `Model ${s.model ?? prevSession.model} does not support session type translation`,\n              type: \"invalid_request_error\",\n              code: \"invalid_session_config\",\n            },\n          },\n          isBeta,\n        );\n        return;\n      }\n    }\n\n    sendEvent(\n      ws,\n      {\n        type: \"session.updated\",\n        session: {\n          object: \"realtime.session\",\n          model: session.model,\n          expires_at: Math.floor(Date.now() / 1000) + 3600,\n          modalities: session.modalities,\n          instructions: session.instructions,\n          tools: session.tools,\n          tool_choice: \"auto\",\n          temperature: session.temperature,\n          max_response_output_tokens: \"inf\",\n          audio: {\n            voice: session.voice,\n            input_audio_format: session.input_audio_format,\n            output_audio_format: session.output_audio_format,\n            input_audio_noise_reduction: session.input_audio_noise_reduction,\n            input_audio_transcription: session.input_audio_transcription,\n          },\n          turn_detection: session.turn_detection,\n          type: session.type,\n          reasoning: session.reasoning,\n        },\n      },\n      isBeta,\n    );\n    return;\n  }\n\n  // ── conversation.item.create ──────────────────────────────────────────\n  if (msgType === \"conversation.item.create\") {\n    if (!parsed.item) {\n      buildErrorRealtimeEvent(\n        ws,\n        \"Missing 'item' in conversation.item.create\",\n        isBeta,\n        \"invalid_request_error\",\n      );\n      return;\n    }\n    const item = parsed.item;\n    if (!item.id) {\n      item.id = realtimeId(\"item\");\n    }\n    const previousId =\n      conversationItems.length > 0\n        ? (conversationItems[conversationItems.length - 1].id ?? null)\n        : null;\n    conversationItems.push(item);\n    sendEvent(ws, { type: \"conversation.item.added\", previous_item_id: previousId, item }, isBeta);\n    return;\n  }\n\n  // ── response.create ───────────────────────────────────────────────────\n  if (msgType === \"response.create\") {\n    await handleResponseCreate(\n      ws,\n      fixtures,\n      journal,\n      defaults,\n      session,\n      conversationItems,\n      isBeta,\n      parsed.response,\n    );\n    return;\n  }\n\n  // ── input_audio_buffer.append ────────────────────────────────────────\n  if (msgType === \"input_audio_buffer.append\") {\n    // Accept silently — aimock doesn't process actual audio\n    return;\n  }\n\n  // ── input_audio_buffer.commit ──────────────────────────────────────\n  if (msgType === \"input_audio_buffer.commit\") {\n    sendEvent(ws, { type: \"input_audio_buffer.committed\" }, isBeta);\n    // In transcription/translation mode, add a placeholder user item\n    if (session.type === \"transcription\" || session.type === \"translation\") {\n      const audioItem: RealtimeItem = {\n        type: \"message\",\n        id: realtimeId(\"item\"),\n        role: \"user\",\n        content: [{ type: \"input_audio\", transcript: null }],\n      };\n      conversationItems.push(audioItem);\n      sendEvent(\n        ws,\n        {\n          type: \"conversation.item.added\",\n          item: audioItem,\n        },\n        isBeta,\n      );\n    }\n    return;\n  }\n\n  // ── input_audio_buffer.clear ───────────────────────────────────────\n  if (msgType === \"input_audio_buffer.clear\") {\n    sendEvent(ws, { type: \"input_audio_buffer.cleared\" }, isBeta);\n    return;\n  }\n\n  // ── response.cancel ────────────────────────────────────────────────\n  if (msgType === \"response.cancel\") {\n    sendEvent(ws, { type: \"response.cancelled\" }, isBeta);\n    return;\n  }\n\n  // Unknown message type — ignore silently (matches OpenAI behavior)\n}\n\nasync function handleResponseCreate(\n  ws: WebSocketConnection,\n  fixtures: Fixture[],\n  journal: Journal,\n  defaults: {\n    latency: number;\n    chunkSize: number;\n    replaySpeed?: number;\n    model: string;\n    logger: Logger;\n    strict?: boolean;\n    requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n    testId?: string;\n    upgradeHeaders?: import(\"node:http\").IncomingHttpHeaders;\n  },\n  session: SessionConfig,\n  conversationItems: RealtimeItem[],\n  isBeta: boolean,\n  responseOverrides?: { instructions?: string; [key: string]: unknown },\n): Promise<void> {\n  const instructions = (responseOverrides?.instructions ?? session.instructions) || undefined;\n  const messages = realtimeItemsToMessages(conversationItems, instructions, defaults.logger);\n\n  const endpointTypeMap: Record<string, string> = {\n    conversation: \"realtime\",\n    transcription: \"realtime-transcription\",\n    translation: \"realtime-translation\",\n  };\n  const endpointType = endpointTypeMap[session.type] ?? \"realtime\";\n\n  const realtimeContextHeader = defaults.upgradeHeaders?.[\"x-aimock-context\"];\n  const realtimeContext =\n    typeof realtimeContextHeader === \"string\"\n      ? realtimeContextHeader\n      : Array.isArray(realtimeContextHeader) && realtimeContextHeader.length > 0\n        ? realtimeContextHeader[0]\n        : undefined;\n\n  const completionReq: ChatCompletionRequest = {\n    model: session.model,\n    messages,\n    _endpointType: endpointType,\n    _context: realtimeContext,\n  };\n\n  const testId = defaults.testId ?? DEFAULT_TEST_ID;\n  const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n    fixtures,\n    completionReq,\n    journal.getFixtureMatchCountsForTest(testId),\n    defaults.requestTransform,\n  );\n  const responseId = realtimeId(\"resp\");\n\n  if (fixture) {\n    journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n  }\n\n  if (!fixture) {\n    if (resolveStrictMode(defaults.strict, defaults.upgradeHeaders)) {\n      const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n      defaults.logger.error(strictNoMatchLogLine(\"WS\", \"/v1/realtime\", skippedBySequenceOrTurn));\n      journal.add({\n        method: \"WS\",\n        path: \"/v1/realtime\",\n        headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n        body: completionReq,\n        response: {\n          status: 503,\n          fixture: null,\n          ...strictOverrideField(defaults.strict, defaults.upgradeHeaders),\n        },\n      });\n      ws.close(1008, strictMessage);\n      return;\n    }\n    journal.add({\n      method: \"WS\",\n      path: \"/v1/realtime\",\n      headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n      body: completionReq,\n      response: {\n        status: 404,\n        fixture: null,\n        ...strictOverrideField(defaults.strict, defaults.upgradeHeaders),\n      },\n    });\n    // Send response.created with failed status then response.done with error\n    sendEvent(\n      ws,\n      {\n        type: \"response.created\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"failed\",\n          status_details: null,\n          output: [],\n          usage: null,\n        },\n      },\n      isBeta,\n    );\n    sendEvent(\n      ws,\n      {\n        type: \"response.done\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"failed\",\n          output: [],\n          status_details: {\n            type: \"error\",\n            error: {\n              message: \"No fixture matched\",\n              type: \"invalid_request_error\",\n              code: \"no_fixture_match\",\n            },\n          },\n          usage: { total_tokens: 0, input_tokens: 0, output_tokens: 0 },\n        },\n      },\n      isBeta,\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\n  // ── Error fixture ───────────────────────────────────────────────────\n  if (isErrorResponse(response)) {\n    const status = response.status ?? 500;\n    journal.add({\n      method: \"WS\",\n      path: \"/v1/realtime\",\n      headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n      body: completionReq,\n      response: { status, fixture },\n    });\n    sendEvent(\n      ws,\n      {\n        type: \"response.created\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"failed\",\n          status_details: null,\n          output: [],\n          usage: null,\n        },\n      },\n      isBeta,\n    );\n    sendEvent(\n      ws,\n      {\n        type: \"response.done\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"failed\",\n          output: [],\n          status_details: {\n            type: \"error\",\n            error: {\n              message: response.error.message,\n              type: response.error.type,\n              code: response.error.code,\n            },\n          },\n          usage: { total_tokens: 0, input_tokens: 0, output_tokens: 0 },\n        },\n      },\n      isBeta,\n    );\n    return;\n  }\n\n  // ── Content + tool calls response ──────────────────────────────────\n  if (isContentWithToolCallsResponse(response)) {\n    const journalEntry = journal.add({\n      method: \"WS\",\n      path: \"/v1/realtime\",\n      headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n\n    // response.created\n    sendEvent(\n      ws,\n      {\n        type: \"response.created\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"in_progress\",\n          status_details: null,\n          output: [],\n          usage: null,\n        },\n      },\n      isBeta,\n    );\n\n    const interruption = createInterruptionSignal(fixture);\n    let interrupted = false;\n    const allOutputItems: unknown[] = [];\n\n    // ── Text content part ──────────────────────────────────────────\n    const textItemId = realtimeId(\"item\");\n    const contentIndex = 0;\n    const textOutputIndex = 0;\n\n    const textOutputItem = {\n      id: textItemId,\n      type: \"message\",\n      role: \"assistant\",\n      status: \"completed\",\n      content: [{ type: \"output_text\", text: response.content }],\n    };\n\n    // Determine phase: text is \"commentary\" when tool calls are also present\n    const hasToolCalls = response.toolCalls && response.toolCalls.length > 0;\n    const textPhase = hasToolCalls ? \"commentary\" : \"final_answer\";\n\n    // response.output_item.added (text)\n    sendEvent(\n      ws,\n      {\n        type: \"response.output_item.added\",\n        response_id: responseId,\n        output_index: textOutputIndex,\n        item: {\n          id: textItemId,\n          type: \"message\",\n          role: \"assistant\",\n          status: \"in_progress\",\n          content: [],\n          phase: textPhase,\n        },\n      },\n      isBeta,\n    );\n\n    // response.content_part.added\n    sendEvent(\n      ws,\n      {\n        type: \"response.content_part.added\",\n        response_id: responseId,\n        item_id: textItemId,\n        output_index: textOutputIndex,\n        content_index: contentIndex,\n        part: { type: \"output_text\", text: \"\" },\n      },\n      isBeta,\n    );\n\n    // response.output_text.delta (chunked) — GA name\n    const content = response.content;\n    const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;\n    const { recordedTimings } = fixture;\n    let eventIndex = 0;\n    for (let i = 0; i < content.length; i += chunkSize) {\n      if (ws.isClosed) break;\n      const chunkDelay = calculateDelay(\n        eventIndex,\n        undefined,\n        latency,\n        recordedTimings,\n        replaySpeed,\n      );\n      if (chunkDelay > 0) await delay(chunkDelay, interruption?.signal);\n      if (interruption?.signal.aborted) {\n        interrupted = true;\n        break;\n      }\n      if (ws.isClosed) break;\n      const chunk = content.slice(i, i + chunkSize);\n      try {\n        sendEvent(\n          ws,\n          {\n            type: \"response.output_text.delta\",\n            response_id: responseId,\n            item_id: textItemId,\n            output_index: textOutputIndex,\n            content_index: contentIndex,\n            delta: chunk,\n          },\n          isBeta,\n        );\n      } catch (err) {\n        defaults.logger.debug(\"[ws-realtime] send failed during text streaming, closing\", err);\n        break;\n      }\n      eventIndex++;\n      interruption?.tick();\n      if (interruption?.signal.aborted) {\n        interrupted = true;\n        break;\n      }\n    }\n\n    if (interrupted) {\n      ws.destroy();\n      journalEntry.response.interrupted = true;\n      journalEntry.response.interruptReason = interruption?.reason();\n      interruption?.cleanup();\n      return;\n    }\n\n    if (ws.isClosed) {\n      interruption?.cleanup();\n      return;\n    }\n\n    // response.output_text.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.output_text.done\",\n        response_id: responseId,\n        item_id: textItemId,\n        output_index: textOutputIndex,\n        content_index: contentIndex,\n        text: content,\n      },\n      isBeta,\n    );\n\n    if (ws.isClosed) {\n      interruption?.cleanup();\n      return;\n    }\n\n    // response.content_part.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.content_part.done\",\n        response_id: responseId,\n        item_id: textItemId,\n        output_index: textOutputIndex,\n        content_index: contentIndex,\n        part: { type: \"output_text\", text: content },\n      },\n      isBeta,\n    );\n\n    if (ws.isClosed) {\n      interruption?.cleanup();\n      return;\n    }\n\n    // response.output_item.done (text)\n    sendEvent(\n      ws,\n      {\n        type: \"response.output_item.done\",\n        response_id: responseId,\n        output_index: textOutputIndex,\n        item: { ...textOutputItem, phase: textPhase },\n      },\n      isBeta,\n    );\n\n    // conversation.item.done (text message)\n    sendEvent(\n      ws,\n      {\n        type: \"conversation.item.done\",\n        item: {\n          id: textItemId,\n          object: \"realtime.item\",\n          type: \"message\",\n          role: \"assistant\",\n          status: \"completed\",\n          content: textOutputItem.content,\n        },\n      },\n      isBeta,\n    );\n\n    if (ws.isClosed) {\n      interruption?.cleanup();\n      return;\n    }\n\n    allOutputItems.push(textOutputItem);\n\n    // ── Tool call parts ────────────────────────────────────────────\n    for (let tcIdx = 0; tcIdx < response.toolCalls.length; tcIdx++) {\n      const tc = response.toolCalls[tcIdx];\n      const callId = tc.id ?? generateToolCallId();\n      const itemId = realtimeId(\"item\");\n      const outputIndex = tcIdx + 1; // offset by 1 for the text item\n\n      const toolOutputItem = {\n        id: itemId,\n        type: \"function_call\",\n        status: \"completed\",\n        call_id: callId,\n        name: tc.name,\n        arguments: tc.arguments,\n      };\n\n      // response.output_item.added\n      sendEvent(\n        ws,\n        {\n          type: \"response.output_item.added\",\n          response_id: responseId,\n          output_index: outputIndex,\n          item: {\n            id: itemId,\n            type: \"function_call\",\n            status: \"in_progress\",\n            call_id: callId,\n            name: tc.name,\n            arguments: \"\",\n            phase: \"final_answer\",\n          },\n        },\n        isBeta,\n      );\n\n      // response.function_call_arguments.delta (chunked)\n      // Continue eventIndex from content chunks to avoid re-triggering TTFT\n      const args = tc.arguments;\n      for (let i = 0; i < args.length; i += chunkSize) {\n        if (ws.isClosed) break;\n        const chunkDelay = calculateDelay(\n          eventIndex,\n          undefined,\n          latency,\n          recordedTimings,\n          replaySpeed,\n        );\n        if (chunkDelay > 0) await delay(chunkDelay, interruption?.signal);\n        if (interruption?.signal.aborted) {\n          interrupted = true;\n          break;\n        }\n        if (ws.isClosed) break;\n        const chunk = args.slice(i, i + chunkSize);\n        try {\n          sendEvent(\n            ws,\n            {\n              type: \"response.function_call_arguments.delta\",\n              response_id: responseId,\n              item_id: itemId,\n              output_index: outputIndex,\n              call_id: callId,\n              delta: chunk,\n            },\n            isBeta,\n          );\n        } catch (err) {\n          defaults.logger.debug(\n            \"[ws-realtime] send failed during tool call streaming, closing\",\n            err,\n          );\n          break;\n        }\n        eventIndex++;\n        interruption?.tick();\n        if (interruption?.signal.aborted) {\n          interrupted = true;\n          break;\n        }\n      }\n\n      if (interrupted) break;\n\n      if (ws.isClosed) break;\n\n      // response.function_call_arguments.done\n      sendEvent(\n        ws,\n        {\n          type: \"response.function_call_arguments.done\",\n          response_id: responseId,\n          item_id: itemId,\n          output_index: outputIndex,\n          call_id: callId,\n          arguments: args,\n        },\n        isBeta,\n      );\n\n      if (ws.isClosed) break;\n\n      // response.output_item.done\n      sendEvent(\n        ws,\n        {\n          type: \"response.output_item.done\",\n          response_id: responseId,\n          output_index: outputIndex,\n          item: { ...toolOutputItem, phase: \"final_answer\" },\n        },\n        isBeta,\n      );\n\n      // conversation.item.done (tool call)\n      sendEvent(\n        ws,\n        {\n          type: \"conversation.item.done\",\n          item: {\n            id: itemId,\n            object: \"realtime.item\",\n            type: \"function_call\",\n            status: \"completed\",\n            call_id: callId,\n            name: tc.name,\n            arguments: args,\n          },\n        },\n        isBeta,\n      );\n\n      if (ws.isClosed) break;\n\n      allOutputItems.push(toolOutputItem);\n    }\n\n    if (interrupted) {\n      ws.destroy();\n      journalEntry.response.interrupted = true;\n      journalEntry.response.interruptReason = interruption?.reason();\n      interruption?.cleanup();\n      return;\n    }\n\n    interruption?.cleanup();\n\n    if (ws.isClosed) return;\n\n    // response.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.done\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"completed\",\n          output: allOutputItems,\n          usage: { total_tokens: 0, input_tokens: 0, output_tokens: 0 },\n        },\n      },\n      isBeta,\n    );\n\n    // Accumulate into conversation for multi-turn\n    conversationItems.push({\n      type: \"message\",\n      id: textItemId,\n      role: \"assistant\",\n      content: [{ type: \"text\", text: content }],\n    });\n    for (const item of allOutputItems.slice(1)) {\n      conversationItems.push(item as RealtimeItem);\n    }\n    return;\n  }\n\n  // ── Text response ───────────────────────────────────────────────────\n  if (isTextResponse(response)) {\n    const journalEntry = journal.add({\n      method: \"WS\",\n      path: \"/v1/realtime\",\n      headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n\n    const itemId = realtimeId(\"item\");\n    const contentIndex = 0;\n    const outputIndex = 0;\n\n    const outputItem = {\n      id: itemId,\n      type: \"message\",\n      role: \"assistant\",\n      status: \"completed\",\n      content: [{ type: \"output_text\", text: response.content }],\n    };\n\n    // response.created\n    sendEvent(\n      ws,\n      {\n        type: \"response.created\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"in_progress\",\n          status_details: null,\n          output: [],\n          usage: null,\n        },\n      },\n      isBeta,\n    );\n\n    // response.output_item.added\n    sendEvent(\n      ws,\n      {\n        type: \"response.output_item.added\",\n        response_id: responseId,\n        output_index: outputIndex,\n        item: {\n          id: itemId,\n          type: \"message\",\n          role: \"assistant\",\n          status: \"in_progress\",\n          content: [],\n          phase: \"final_answer\",\n        },\n      },\n      isBeta,\n    );\n\n    // response.content_part.added\n    sendEvent(\n      ws,\n      {\n        type: \"response.content_part.added\",\n        response_id: responseId,\n        item_id: itemId,\n        output_index: outputIndex,\n        content_index: contentIndex,\n        part: { type: \"output_text\", text: \"\" },\n      },\n      isBeta,\n    );\n\n    // response.output_text.delta (chunked) — GA name\n    const content = response.content;\n    const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;\n    const { recordedTimings } = fixture;\n    const interruption = createInterruptionSignal(fixture);\n    let interrupted = false;\n    let eventIndex = 0;\n\n    for (let i = 0; i < content.length; i += chunkSize) {\n      if (ws.isClosed) break;\n      const chunkDelay = calculateDelay(\n        eventIndex,\n        undefined,\n        latency,\n        recordedTimings,\n        replaySpeed,\n      );\n      if (chunkDelay > 0) await delay(chunkDelay, interruption?.signal);\n      if (interruption?.signal.aborted) {\n        interrupted = true;\n        break;\n      }\n      if (ws.isClosed) break;\n      const chunk = content.slice(i, i + chunkSize);\n      try {\n        sendEvent(\n          ws,\n          {\n            type: \"response.output_text.delta\",\n            response_id: responseId,\n            item_id: itemId,\n            output_index: outputIndex,\n            content_index: contentIndex,\n            delta: chunk,\n          },\n          isBeta,\n        );\n      } catch (err) {\n        defaults.logger.debug(\"[ws-realtime] send failed during text streaming, closing\", err);\n        break;\n      }\n      eventIndex++;\n      interruption?.tick();\n      if (interruption?.signal.aborted) {\n        interrupted = true;\n        break;\n      }\n    }\n\n    if (interrupted) {\n      ws.destroy();\n      journalEntry.response.interrupted = true;\n      journalEntry.response.interruptReason = interruption?.reason();\n      interruption?.cleanup();\n      return;\n    }\n\n    interruption?.cleanup();\n\n    if (ws.isClosed) return;\n\n    // response.output_text.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.output_text.done\",\n        response_id: responseId,\n        item_id: itemId,\n        output_index: outputIndex,\n        content_index: contentIndex,\n        text: content,\n      },\n      isBeta,\n    );\n\n    // response.content_part.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.content_part.done\",\n        response_id: responseId,\n        item_id: itemId,\n        output_index: outputIndex,\n        content_index: contentIndex,\n        part: { type: \"output_text\", text: content },\n      },\n      isBeta,\n    );\n\n    // response.output_item.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.output_item.done\",\n        response_id: responseId,\n        output_index: outputIndex,\n        item: { ...outputItem, phase: \"final_answer\" },\n      },\n      isBeta,\n    );\n\n    // conversation.item.done (text message)\n    sendEvent(\n      ws,\n      {\n        type: \"conversation.item.done\",\n        item: {\n          id: itemId,\n          object: \"realtime.item\",\n          type: \"message\",\n          role: \"assistant\",\n          status: \"completed\",\n          content: outputItem.content,\n        },\n      },\n      isBeta,\n    );\n\n    // response.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.done\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"completed\",\n          output: [outputItem],\n          usage: { total_tokens: 0, input_tokens: 0, output_tokens: 0 },\n        },\n      },\n      isBeta,\n    );\n\n    // Accumulate assistant response into conversation for multi-turn\n    conversationItems.push({\n      type: \"message\",\n      id: itemId,\n      role: \"assistant\",\n      content: [{ type: \"text\", text: content }],\n    });\n    return;\n  }\n\n  // ── Tool call response ──────────────────────────────────────────────\n  if (isToolCallResponse(response)) {\n    const journalEntry = journal.add({\n      method: \"WS\",\n      path: \"/v1/realtime\",\n      headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n      body: completionReq,\n      response: { status: 200, fixture },\n    });\n\n    // response.created\n    sendEvent(\n      ws,\n      {\n        type: \"response.created\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"in_progress\",\n          status_details: null,\n          output: [],\n          usage: null,\n        },\n      },\n      isBeta,\n    );\n\n    const outputItems: unknown[] = [];\n    const interruption = createInterruptionSignal(fixture);\n    const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;\n    const { recordedTimings } = fixture;\n    let interrupted = false;\n    let eventIndex = 0;\n\n    for (let tcIdx = 0; tcIdx < response.toolCalls.length; tcIdx++) {\n      const tc = response.toolCalls[tcIdx];\n      const callId = tc.id ?? generateToolCallId();\n      const itemId = realtimeId(\"item\");\n\n      const outputItem = {\n        id: itemId,\n        type: \"function_call\",\n        status: \"completed\",\n        call_id: callId,\n        name: tc.name,\n        arguments: tc.arguments,\n      };\n\n      // response.output_item.added\n      sendEvent(\n        ws,\n        {\n          type: \"response.output_item.added\",\n          response_id: responseId,\n          output_index: tcIdx,\n          item: {\n            id: itemId,\n            type: \"function_call\",\n            status: \"in_progress\",\n            call_id: callId,\n            name: tc.name,\n            arguments: \"\",\n            phase: \"final_answer\",\n          },\n        },\n        isBeta,\n      );\n\n      // response.function_call_arguments.delta (chunked)\n      // eventIndex is continuous across all tool calls to avoid re-triggering TTFT\n      const args = tc.arguments;\n      for (let i = 0; i < args.length; i += chunkSize) {\n        if (ws.isClosed) break;\n        const chunkDelay = calculateDelay(\n          eventIndex,\n          undefined,\n          latency,\n          recordedTimings,\n          replaySpeed,\n        );\n        if (chunkDelay > 0) await delay(chunkDelay, interruption?.signal);\n        if (interruption?.signal.aborted) {\n          interrupted = true;\n          break;\n        }\n        if (ws.isClosed) break;\n        const chunk = args.slice(i, i + chunkSize);\n        try {\n          sendEvent(\n            ws,\n            {\n              type: \"response.function_call_arguments.delta\",\n              response_id: responseId,\n              item_id: itemId,\n              output_index: tcIdx,\n              call_id: callId,\n              delta: chunk,\n            },\n            isBeta,\n          );\n        } catch (err) {\n          defaults.logger.debug(\n            \"[ws-realtime] send failed during tool call streaming, closing\",\n            err,\n          );\n          break;\n        }\n        eventIndex++;\n        interruption?.tick();\n        if (interruption?.signal.aborted) {\n          interrupted = true;\n          break;\n        }\n      }\n\n      if (interrupted) break;\n\n      if (ws.isClosed) break;\n\n      // response.function_call_arguments.done\n      sendEvent(\n        ws,\n        {\n          type: \"response.function_call_arguments.done\",\n          response_id: responseId,\n          item_id: itemId,\n          output_index: tcIdx,\n          call_id: callId,\n          arguments: args,\n        },\n        isBeta,\n      );\n\n      // response.output_item.done\n      sendEvent(\n        ws,\n        {\n          type: \"response.output_item.done\",\n          response_id: responseId,\n          output_index: tcIdx,\n          item: { ...outputItem, phase: \"final_answer\" },\n        },\n        isBeta,\n      );\n\n      // conversation.item.done (tool call)\n      sendEvent(\n        ws,\n        {\n          type: \"conversation.item.done\",\n          item: {\n            id: itemId,\n            object: \"realtime.item\",\n            type: \"function_call\",\n            status: \"completed\",\n            call_id: callId,\n            name: tc.name,\n            arguments: args,\n          },\n        },\n        isBeta,\n      );\n\n      outputItems.push(outputItem);\n    }\n\n    if (interrupted) {\n      ws.destroy();\n      journalEntry.response.interrupted = true;\n      journalEntry.response.interruptReason = interruption?.reason();\n      interruption?.cleanup();\n      return;\n    }\n\n    interruption?.cleanup();\n\n    if (ws.isClosed) return;\n\n    // response.done\n    sendEvent(\n      ws,\n      {\n        type: \"response.done\",\n        response: {\n          id: responseId,\n          object: \"realtime.response\",\n          status: \"completed\",\n          output: outputItems,\n          usage: { total_tokens: 0, input_tokens: 0, output_tokens: 0 },\n        },\n      },\n      isBeta,\n    );\n\n    // Accumulate assistant tool calls into conversation for multi-turn\n    // Reuse outputItems (which already have the correct call_id) to avoid generating divergent IDs\n    for (const item of outputItems) {\n      conversationItems.push(item as RealtimeItem);\n    }\n    return;\n  }\n\n  // Unknown response type\n  journal.add({\n    method: \"WS\",\n    path: \"/v1/realtime\",\n    headers: flattenHeaders(defaults.upgradeHeaders ?? {}),\n    body: completionReq,\n    response: { status: 500, fixture },\n  });\n  buildErrorRealtimeEvent(\n    ws,\n    \"Fixture response did not match any known type\",\n    isBeta,\n    \"server_error\",\n  );\n}\n"],"mappings":"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"}