@copilotkit/aimock 1.15.1 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +23 -0
  4. package/README.md +1 -1
  5. package/dist/bedrock-converse.cjs +4 -0
  6. package/dist/bedrock-converse.cjs.map +1 -1
  7. package/dist/bedrock-converse.d.cts.map +1 -1
  8. package/dist/bedrock-converse.d.ts.map +1 -1
  9. package/dist/bedrock-converse.js +4 -0
  10. package/dist/bedrock-converse.js.map +1 -1
  11. package/dist/bedrock.cjs +4 -0
  12. package/dist/bedrock.cjs.map +1 -1
  13. package/dist/bedrock.d.cts.map +1 -1
  14. package/dist/bedrock.d.ts.map +1 -1
  15. package/dist/bedrock.js +4 -0
  16. package/dist/bedrock.js.map +1 -1
  17. package/dist/cohere.cjs +4 -1
  18. package/dist/cohere.cjs.map +1 -1
  19. package/dist/cohere.js +4 -1
  20. package/dist/cohere.js.map +1 -1
  21. package/dist/config-loader.d.cts.map +1 -1
  22. package/dist/config-loader.d.ts.map +1 -1
  23. package/dist/embeddings.cjs +4 -1
  24. package/dist/embeddings.cjs.map +1 -1
  25. package/dist/embeddings.js +4 -1
  26. package/dist/embeddings.js.map +1 -1
  27. package/dist/fixture-loader.cjs +19 -4
  28. package/dist/fixture-loader.cjs.map +1 -1
  29. package/dist/fixture-loader.d.cts.map +1 -1
  30. package/dist/fixture-loader.d.ts.map +1 -1
  31. package/dist/fixture-loader.js +19 -4
  32. package/dist/fixture-loader.js.map +1 -1
  33. package/dist/gemini.cjs +2 -0
  34. package/dist/gemini.cjs.map +1 -1
  35. package/dist/gemini.js +2 -0
  36. package/dist/gemini.js.map +1 -1
  37. package/dist/images.cjs +4 -1
  38. package/dist/images.cjs.map +1 -1
  39. package/dist/images.js +4 -1
  40. package/dist/images.js.map +1 -1
  41. package/dist/journal.cjs +1 -1
  42. package/dist/journal.cjs.map +1 -1
  43. package/dist/journal.d.cts.map +1 -1
  44. package/dist/journal.d.ts.map +1 -1
  45. package/dist/journal.js +1 -1
  46. package/dist/journal.js.map +1 -1
  47. package/dist/llmock.cjs +6 -0
  48. package/dist/llmock.cjs.map +1 -1
  49. package/dist/llmock.d.cts +1 -0
  50. package/dist/llmock.d.cts.map +1 -1
  51. package/dist/llmock.d.ts +1 -0
  52. package/dist/llmock.d.ts.map +1 -1
  53. package/dist/llmock.js +6 -0
  54. package/dist/llmock.js.map +1 -1
  55. package/dist/messages.cjs +8 -1
  56. package/dist/messages.cjs.map +1 -1
  57. package/dist/messages.js +8 -1
  58. package/dist/messages.js.map +1 -1
  59. package/dist/ollama.cjs +8 -2
  60. package/dist/ollama.cjs.map +1 -1
  61. package/dist/ollama.d.cts.map +1 -1
  62. package/dist/ollama.d.ts.map +1 -1
  63. package/dist/ollama.js +8 -2
  64. package/dist/ollama.js.map +1 -1
  65. package/dist/responses.cjs +87 -13
  66. package/dist/responses.cjs.map +1 -1
  67. package/dist/responses.d.cts.map +1 -1
  68. package/dist/responses.d.ts.map +1 -1
  69. package/dist/responses.js +87 -13
  70. package/dist/responses.js.map +1 -1
  71. package/dist/router.cjs +6 -0
  72. package/dist/router.cjs.map +1 -1
  73. package/dist/router.js +6 -0
  74. package/dist/router.js.map +1 -1
  75. package/dist/server.cjs +8 -1
  76. package/dist/server.cjs.map +1 -1
  77. package/dist/server.d.cts.map +1 -1
  78. package/dist/server.d.ts.map +1 -1
  79. package/dist/server.js +8 -1
  80. package/dist/server.js.map +1 -1
  81. package/dist/speech.cjs +4 -1
  82. package/dist/speech.cjs.map +1 -1
  83. package/dist/speech.js +4 -1
  84. package/dist/speech.js.map +1 -1
  85. package/dist/transcription.cjs +4 -1
  86. package/dist/transcription.cjs.map +1 -1
  87. package/dist/transcription.js +4 -1
  88. package/dist/transcription.js.map +1 -1
  89. package/dist/types.d.cts +4 -0
  90. package/dist/types.d.cts.map +1 -1
  91. package/dist/types.d.ts +4 -0
  92. package/dist/types.d.ts.map +1 -1
  93. package/dist/video.cjs +4 -1
  94. package/dist/video.cjs.map +1 -1
  95. package/dist/video.d.cts.map +1 -1
  96. package/dist/video.d.ts.map +1 -1
  97. package/dist/video.js +4 -1
  98. package/dist/video.js.map +1 -1
  99. package/package.json +1 -1
  100. package/skills/write-fixtures/SKILL.md +75 -49
@@ -1 +1 @@
1
- {"version":3,"file":"responses.cjs","names":["generateToolCallId","generateId","calculateDelay","delay","flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isContentWithToolCallsResponse","extractOverrides","createInterruptionSignal","isTextResponse","isToolCallResponse"],"sources":["../src/responses.ts"],"sourcesContent":["/**\n * OpenAI Responses API support for aimock.\n *\n * Translates incoming /v1/responses requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the Responses API streaming (or non-streaming) format expected by @ai-sdk/openai.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ResponseOverrides,\n StreamingProfile,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateId,\n generateToolCallId,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Responses API request types ────────────────────────────────────────────\n\ninterface ResponsesInputItem {\n role?: string;\n type?: string;\n content?: string | ResponsesContentPart[];\n call_id?: string;\n name?: string;\n arguments?: string;\n output?: string;\n id?: string;\n}\n\ninterface ResponsesContentPart {\n type: string;\n text?: string;\n}\n\ninterface ResponsesRequest {\n model: string;\n input: string | ResponsesInputItem[];\n instructions?: string;\n tools?: ResponsesToolDef[];\n tool_choice?: string | object;\n stream?: boolean;\n temperature?: number;\n max_output_tokens?: number;\n [key: string]: unknown;\n}\n\ninterface ResponsesToolDef {\n type: \"function\";\n name: string;\n description?: string;\n parameters?: object;\n strict?: boolean;\n}\n\n// ─── Input conversion: Responses → ChatCompletions messages ─────────────────\n\nfunction extractTextContent(content: string | ResponsesContentPart[] | undefined): string {\n if (!content) return \"\";\n if (typeof content === \"string\") return content;\n return content\n .filter((p) => p.type === \"input_text\" || p.type === \"output_text\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n}\n\nexport function responsesInputToMessages(req: ResponsesRequest): ChatMessage[] {\n const messages: ChatMessage[] = [];\n\n // instructions field → system message\n if (req.instructions) {\n messages.push({ role: \"system\", content: req.instructions });\n }\n\n // The OpenAI Responses API accepts either a plain string or an array of input items.\n // When a string is passed, treat it as a single user message.\n if (typeof req.input === \"string\") {\n messages.push({ role: \"user\", content: req.input });\n return messages;\n }\n\n for (const item of req.input) {\n if (item.role === \"system\" || item.role === \"developer\") {\n messages.push({ role: \"system\", content: extractTextContent(item.content) });\n } else if (item.role === \"user\") {\n messages.push({ role: \"user\", content: extractTextContent(item.content) });\n } else if (item.role === \"assistant\") {\n messages.push({ role: \"assistant\", content: extractTextContent(item.content) });\n } else if (item.type === \"function_call\") {\n // Previous assistant tool call — emit as assistant message with tool_calls\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: item.name ?? \"\", arguments: item.arguments ?? \"\" },\n },\n ],\n });\n } else if (item.type === \"function_call_output\") {\n messages.push({\n role: \"tool\",\n content: item.output ?? \"\",\n tool_call_id: item.call_id,\n });\n } else {\n // Skip item_reference, local_shell_call, mcp_list_tools, etc. — not needed\n // for fixture matching. Logging is not threaded into this pure conversion\n // function; callers can inspect the returned messages if needed.\n }\n }\n\n return messages;\n}\n\nfunction responsesToolsToCompletionsTools(\n tools?: ResponsesToolDef[],\n): ToolDefinition[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n return tools\n .filter((t) => t.type === \"function\")\n .map((t) => ({\n type: \"function\" as const,\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n}\n\nexport function responsesToCompletionRequest(req: ResponsesRequest): ChatCompletionRequest {\n return {\n model: req.model,\n messages: responsesInputToMessages(req),\n stream: req.stream,\n temperature: req.temperature,\n tools: responsesToolsToCompletionsTools(req.tools),\n tool_choice: req.tool_choice,\n };\n}\n\n// ─── Response building: fixture → Responses API format ──────────────────────\n\nfunction responsesStatus(finishReason: string | undefined, defaultStatus: string): string {\n if (!finishReason) return defaultStatus;\n if (finishReason === \"stop\") return \"completed\";\n if (finishReason === \"tool_calls\") return \"completed\";\n if (finishReason === \"length\") return \"incomplete\";\n if (finishReason === \"content_filter\") return \"failed\";\n return finishReason;\n}\n\nfunction responsesUsage(overrides?: ResponseOverrides): {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n} {\n if (!overrides?.usage) return { input_tokens: 0, output_tokens: 0, total_tokens: 0 };\n return {\n input_tokens: overrides.usage.input_tokens ?? 0,\n output_tokens: overrides.usage.output_tokens ?? 0,\n total_tokens:\n overrides.usage.total_tokens ??\n (overrides.usage.input_tokens ?? 0) + (overrides.usage.output_tokens ?? 0),\n };\n}\n\nfunction responseId(): string {\n return generateId(\"resp\");\n}\n\nfunction itemId(): string {\n return generateId(\"msg\");\n}\n\n// Streaming events for Responses API\n\nexport interface ResponsesSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport function buildTextStreamEvents(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n );\n\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, msgItem],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nexport function buildToolCallStreamEvents(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n overrides?: ResponseOverrides,\n): ResponsesSSEEvent[] {\n const respId = overrides?.id ?? responseId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const events: ResponsesSSEEvent[] = [];\n\n // response.created\n events.push({\n type: \"response.created\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n events.push({\n type: \"response.in_progress\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n const outputItems: object[] = [];\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n\n // output_item.added (function_call)\n events.push({\n type: \"response.output_item.added\",\n output_index: idx,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n // function_call_arguments.delta\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: idx,\n delta: slice,\n });\n }\n\n // function_call_arguments.done\n events.push({\n type: \"response.function_call_arguments.done\",\n output_index: idx,\n arguments: args,\n });\n\n const doneItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: args,\n status: \"completed\",\n };\n\n // output_item.done\n events.push({\n type: \"response.output_item.done\",\n output_index: idx,\n item: doneItem,\n });\n\n outputItems.push(doneItem);\n }\n\n // response.completed\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: outputItems,\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildReasoningStreamEvents(\n reasoning: string,\n model: string,\n chunkSize: number,\n): ResponsesSSEEvent[] {\n const reasoningId = generateId(\"rs\");\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: 0,\n item: {\n type: \"reasoning\",\n id: reasoningId,\n summary: [],\n },\n });\n\n events.push({\n type: \"response.reasoning_summary_part.added\",\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: \"\" },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n type: \"response.reasoning_summary_text.delta\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n delta: slice,\n });\n }\n\n events.push({\n type: \"response.reasoning_summary_text.done\",\n output_index: 0,\n summary_index: 0,\n text: reasoning,\n });\n\n events.push({\n type: \"response.reasoning_summary_part.done\",\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: reasoning },\n });\n\n events.push({\n type: \"response.output_item.done\",\n output_index: 0,\n item: {\n type: \"reasoning\",\n id: reasoningId,\n summary: [{ type: \"summary_text\", text: reasoning }],\n },\n });\n\n return events;\n}\n\nfunction buildWebSearchStreamEvents(\n queries: string[],\n startOutputIndex: number,\n): ResponsesSSEEvent[] {\n const events: ResponsesSSEEvent[] = [];\n\n for (let i = 0; i < queries.length; i++) {\n const searchId = generateId(\"ws\");\n const outputIndex = startOutputIndex + i;\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"in_progress\",\n action: { query: queries[i] },\n },\n });\n\n events.push({\n type: \"response.output_item.done\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"completed\",\n action: { query: queries[i] },\n },\n });\n }\n\n return events;\n}\n\n// ─── Shared streaming helpers ────────────────────────────────────────────────\n\ninterface PreambleResult {\n respId: string;\n created: number;\n events: ResponsesSSEEvent[];\n prefixOutputItems: object[];\n nextOutputIndex: number;\n}\n\nfunction buildResponsePreamble(\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): PreambleResult {\n const respId = overrides?.id ?? responseId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const events: ResponsesSSEEvent[] = [];\n const prefixOutputItems: object[] = [];\n let nextOutputIndex = 0;\n\n events.push({\n type: \"response.created\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n events.push({\n type: \"response.in_progress\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n if (reasoning) {\n const reasoningEvents = buildReasoningStreamEvents(reasoning, model, chunkSize);\n events.push(...reasoningEvents);\n const doneEvent = reasoningEvents.find(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"reasoning\",\n );\n if (doneEvent) prefixOutputItems.push(doneEvent.item as object);\n nextOutputIndex++;\n }\n\n if (webSearches && webSearches.length > 0) {\n const searchEvents = buildWebSearchStreamEvents(webSearches, nextOutputIndex);\n events.push(...searchEvents);\n const doneEvents = searchEvents.filter(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"web_search_call\",\n );\n for (const de of doneEvents) prefixOutputItems.push(de.item as object);\n nextOutputIndex += webSearches.length;\n }\n\n return { respId, created, events, prefixOutputItems, nextOutputIndex };\n}\n\ninterface MessageBlockResult {\n events: ResponsesSSEEvent[];\n msgItem: object;\n}\n\nfunction buildMessageOutputEvents(\n content: string,\n chunkSize: number,\n outputIndex: number,\n): MessageBlockResult {\n const msgId = itemId();\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: { type: \"message\", id: msgId, status: \"in_progress\", role: \"assistant\", content: [] },\n });\n events.push({\n type: \"response.content_part.added\",\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: \"\" },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n events.push({\n type: \"response.output_text.delta\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n delta: content.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.output_text.done\",\n output_index: outputIndex,\n content_index: 0,\n text: content,\n });\n events.push({\n type: \"response.content_part.done\",\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: content },\n });\n\n const msgItem = {\n type: \"message\",\n id: msgId,\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content }],\n };\n\n events.push({ type: \"response.output_item.done\", output_index: outputIndex, item: msgItem });\n\n return { events, msgItem };\n}\n\n// ─── Non-streaming response builders ────────────────────────────────────────\n\nfunction buildOutputPrefix(content: string, reasoning?: string, webSearches?: string[]): object[] {\n const output: object[] = [];\n\n if (reasoning) {\n output.push({\n type: \"reasoning\",\n id: generateId(\"rs\"),\n summary: [{ type: \"summary_text\", text: reasoning }],\n });\n }\n\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { query },\n });\n }\n }\n\n output.push({\n type: \"message\",\n id: itemId(),\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content }],\n });\n\n return output;\n}\n\nfunction buildResponseEnvelope(\n model: string,\n output: object[],\n overrides?: ResponseOverrides,\n): object {\n return {\n id: overrides?.id ?? responseId(),\n object: \"response\",\n created_at: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output,\n usage: responsesUsage(overrides),\n };\n}\n\nfunction buildTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): object {\n return buildResponseEnvelope(\n model,\n buildOutputPrefix(content, reasoning, webSearches),\n overrides,\n );\n}\n\nfunction buildToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n overrides?: ResponseOverrides,\n): object {\n return buildResponseEnvelope(\n model,\n toolCalls.map((tc) => ({\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: tc.arguments,\n status: \"completed\",\n })),\n overrides,\n );\n}\n\nexport function buildContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n );\n\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n\n const fcOutputItems: object[] = [];\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n const fcOutputIndex = nextOutputIndex + 1 + idx;\n const args = tc.arguments;\n\n events.push({\n type: \"response.output_item.added\",\n output_index: fcOutputIndex,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n for (let i = 0; i < args.length; i += chunkSize) {\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: fcOutputIndex,\n delta: args.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.function_call_arguments.done\",\n output_index: fcOutputIndex,\n arguments: args,\n });\n\n const doneItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: args,\n status: \"completed\",\n };\n events.push({ type: \"response.output_item.done\", output_index: fcOutputIndex, item: doneItem });\n fcOutputItems.push(doneItem);\n }\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, msgItem, ...fcOutputItems],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): object {\n const output = buildOutputPrefix(content, reasoning, webSearches);\n for (const tc of toolCalls) {\n output.push({\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: tc.arguments,\n status: \"completed\",\n });\n }\n return buildResponseEnvelope(model, output, overrides);\n}\n\n// ─── SSE writer for Responses API ───────────────────────────────────────────\n\ninterface ResponsesStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeResponsesSSEStream(\n res: http.ServerResponse,\n events: ResponsesSSEEvent[],\n optionsOrLatency?: number | ResponsesStreamOptions,\n): Promise<boolean> {\n const opts: ResponsesStreamOptions =\n typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n const latency = opts.latency ?? 0;\n const profile = opts.streamingProfile;\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);\n if (chunkDelay > 0) await delay(chunkDelay, signal);\n if (signal?.aborted) return false;\n if (res.writableEnded) return true;\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\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 handleResponses(\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 setCorsHeaders(res);\n\n let responsesReq: ResponsesRequest;\n try {\n responsesReq = JSON.parse(raw) as ResponsesRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\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: { message: \"Malformed JSON\", type: \"invalid_request_error\", code: \"invalid_json\" },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = responsesToCompletionRequest(responsesReq);\n completionReq._endpointType = \"chat\";\n\n const testId = getTestId(req);\n const fixture = matchFixture(\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: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"openai\",\n req.url ?? \"/v1/responses\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n const strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\n defaults.logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: strictStatus, fixture: null },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n const response = fixture.response;\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Combined content + tool calls response\n if (isContentWithToolCallsResponse(response)) {\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n completionReq.model,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildContentWithToolCallsStreamEvents(\n response.content,\n response.toolCalls,\n completionReq.model,\n chunkSize,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\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 const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildTextStreamEvents(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\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 const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildToolCallResponse(response.toolCalls, completionReq.model, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildToolCallStreamEvents(\n response.toolCalls,\n completionReq.model,\n chunkSize,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\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: req.url ?? \"/v1/responses\",\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: { message: \"Fixture response did not match any known type\", type: \"server_error\" },\n }),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"responses.cjs","names":["generateToolCallId","generateId","calculateDelay","delay","flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isContentWithToolCallsResponse","extractOverrides","createInterruptionSignal","isTextResponse","isToolCallResponse"],"sources":["../src/responses.ts"],"sourcesContent":["/**\n * OpenAI Responses API support for aimock.\n *\n * Translates incoming /v1/responses requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the Responses API streaming (or non-streaming) format expected by @ai-sdk/openai.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ResponseOverrides,\n StreamingProfile,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateId,\n generateToolCallId,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Responses API request types ────────────────────────────────────────────\n\ninterface ResponsesInputItem {\n role?: string;\n type?: string;\n content?: string | ResponsesContentPart[];\n call_id?: string;\n name?: string;\n arguments?: string;\n output?: string;\n id?: string;\n}\n\ninterface ResponsesContentPart {\n type: string;\n text?: string;\n}\n\ninterface ResponsesRequest {\n model: string;\n input: string | ResponsesInputItem[];\n instructions?: string;\n tools?: ResponsesToolDef[];\n tool_choice?: string | object;\n stream?: boolean;\n temperature?: number;\n max_output_tokens?: number;\n [key: string]: unknown;\n}\n\ninterface ResponsesToolDef {\n type: \"function\";\n name: string;\n description?: string;\n parameters?: object;\n strict?: boolean;\n}\n\n// ─── Input conversion: Responses → ChatCompletions messages ─────────────────\n\nfunction extractTextContent(content: string | ResponsesContentPart[] | undefined): string {\n if (!content) return \"\";\n if (typeof content === \"string\") return content;\n return content\n .filter((p) => p.type === \"input_text\" || p.type === \"output_text\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n}\n\nexport function responsesInputToMessages(req: ResponsesRequest): ChatMessage[] {\n const messages: ChatMessage[] = [];\n // Track item_reference placeholders so we can upgrade or clean them up\n const itemReferencePlaceholders = new WeakSet<ChatMessage>();\n\n // instructions field → system message\n if (req.instructions) {\n messages.push({ role: \"system\", content: req.instructions });\n }\n\n // The OpenAI Responses API accepts either a plain string or an array of input items.\n // When a string is passed, treat it as a single user message.\n if (typeof req.input === \"string\") {\n messages.push({ role: \"user\", content: req.input });\n return messages;\n }\n\n for (const item of req.input) {\n if (item.role === \"system\" || item.role === \"developer\") {\n messages.push({ role: \"system\", content: extractTextContent(item.content) });\n } else if (item.role === \"user\") {\n messages.push({ role: \"user\", content: extractTextContent(item.content) });\n } else if (item.role === \"assistant\") {\n messages.push({ role: \"assistant\", content: extractTextContent(item.content) });\n } else if (item.type === \"function_call\") {\n // Previous assistant tool call — emit as assistant message with tool_calls\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: item.name ?? \"\", arguments: item.arguments ?? \"\" },\n },\n ],\n });\n } else if (item.type === \"function_call_output\") {\n // Bug 1 fix: If there's no preceding assistant message with a matching\n // tool_call for this call_id, synthesize one. This happens when the AI SDK\n // sends [user, item_reference, function_call_output] — the item_reference\n // placeholder (see below) has no tool_calls, so we need a real assistant\n // message with the tool_call for turnIndex counting.\n const hasMatchingToolCall = messages.some(\n (m) => m.role === \"assistant\" && m.tool_calls?.some((tc) => tc.id === item.call_id),\n );\n if (!hasMatchingToolCall) {\n // Check if the last message is an item_reference placeholder — if so,\n // upgrade it to carry the tool_call instead of synthesizing a duplicate.\n const lastMsg = messages[messages.length - 1];\n if (\n lastMsg &&\n lastMsg.role === \"assistant\" &&\n itemReferencePlaceholders.has(lastMsg) &&\n !lastMsg.tool_calls\n ) {\n lastMsg.content = null;\n lastMsg.tool_calls = [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n },\n ];\n itemReferencePlaceholders.delete(lastMsg);\n } else {\n // Multi-fco case: look for a recent assistant with tool_calls that\n // belongs to the same turn. After the first fco upgrades a placeholder,\n // subsequent fco's see [assistant(call_A), tool(call_A)] — the last\n // assistant with tool_calls (right before the trailing tool messages)\n // is the correct target.\n let appended = false;\n for (let k = messages.length - 1; k >= 0; k--) {\n const m = messages[k];\n if (m.role === \"assistant\" && m.tool_calls) {\n m.tool_calls.push({\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n });\n appended = true;\n break;\n }\n // Stop scanning if we hit a user message — different turn\n if (m.role === \"user\") break;\n }\n if (!appended) {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n },\n ],\n });\n }\n }\n }\n messages.push({\n role: \"tool\",\n content: item.output ?? \"\",\n tool_call_id: item.call_id,\n });\n } else if (item.type === \"item_reference\") {\n // Bug 6 fix: item_reference items represent prior assistant turns (text\n // or function_call). Push a placeholder so they count in assistantCount.\n // If a subsequent function_call_output arrives, the handler above will\n // upgrade this placeholder to carry tool_calls (avoiding double-count).\n const placeholder: ChatMessage = { role: \"assistant\", content: \"\" };\n itemReferencePlaceholders.add(placeholder);\n messages.push(placeholder);\n } else {\n // Skip local_shell_call, mcp_list_tools, etc. — not needed for fixture\n // matching.\n }\n }\n\n return messages;\n}\n\nfunction responsesToolsToCompletionsTools(\n tools?: ResponsesToolDef[],\n): ToolDefinition[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n return tools\n .filter((t) => t.type === \"function\")\n .map((t) => ({\n type: \"function\" as const,\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n}\n\nexport function responsesToCompletionRequest(req: ResponsesRequest): ChatCompletionRequest {\n return {\n model: req.model,\n messages: responsesInputToMessages(req),\n stream: req.stream,\n temperature: req.temperature,\n tools: responsesToolsToCompletionsTools(req.tools),\n tool_choice: req.tool_choice,\n };\n}\n\n// ─── Response building: fixture → Responses API format ──────────────────────\n\nfunction responsesStatus(finishReason: string | undefined, defaultStatus: string): string {\n if (!finishReason) return defaultStatus;\n if (finishReason === \"stop\") return \"completed\";\n if (finishReason === \"tool_calls\") return \"completed\";\n if (finishReason === \"length\") return \"incomplete\";\n if (finishReason === \"content_filter\") return \"failed\";\n return finishReason;\n}\n\nfunction responsesUsage(overrides?: ResponseOverrides): {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n} {\n if (!overrides?.usage) return { input_tokens: 0, output_tokens: 0, total_tokens: 0 };\n return {\n input_tokens: overrides.usage.input_tokens ?? 0,\n output_tokens: overrides.usage.output_tokens ?? 0,\n total_tokens:\n overrides.usage.total_tokens ??\n (overrides.usage.input_tokens ?? 0) + (overrides.usage.output_tokens ?? 0),\n };\n}\n\nfunction responseId(): string {\n return generateId(\"resp\");\n}\n\nfunction itemId(): string {\n return generateId(\"msg\");\n}\n\n// Streaming events for Responses API\n\nexport interface ResponsesSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport function buildTextStreamEvents(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n );\n\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, msgItem],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nexport function buildToolCallStreamEvents(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n overrides?: ResponseOverrides,\n): ResponsesSSEEvent[] {\n const respId = overrides?.id ?? responseId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const events: ResponsesSSEEvent[] = [];\n\n // response.created\n events.push({\n type: \"response.created\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n events.push({\n type: \"response.in_progress\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n const outputItems: object[] = [];\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n\n // output_item.added (function_call)\n events.push({\n type: \"response.output_item.added\",\n output_index: idx,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n // function_call_arguments.delta\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: idx,\n delta: slice,\n });\n }\n\n // function_call_arguments.done\n events.push({\n type: \"response.function_call_arguments.done\",\n output_index: idx,\n arguments: args,\n });\n\n const doneItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: args,\n status: \"completed\",\n };\n\n // output_item.done\n events.push({\n type: \"response.output_item.done\",\n output_index: idx,\n item: doneItem,\n });\n\n outputItems.push(doneItem);\n }\n\n // response.completed\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: outputItems,\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildReasoningStreamEvents(\n reasoning: string,\n model: string,\n chunkSize: number,\n): ResponsesSSEEvent[] {\n const reasoningId = generateId(\"rs\");\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: 0,\n item: {\n type: \"reasoning\",\n id: reasoningId,\n summary: [],\n },\n });\n\n events.push({\n type: \"response.reasoning_summary_part.added\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: \"\" },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n type: \"response.reasoning_summary_text.delta\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n delta: slice,\n });\n }\n\n events.push({\n type: \"response.reasoning_summary_text.done\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n text: reasoning,\n });\n\n events.push({\n type: \"response.reasoning_summary_part.done\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: reasoning },\n });\n\n events.push({\n type: \"response.output_item.done\",\n output_index: 0,\n item: {\n type: \"reasoning\",\n id: reasoningId,\n summary: [{ type: \"summary_text\", text: reasoning }],\n },\n });\n\n return events;\n}\n\nfunction buildWebSearchStreamEvents(\n queries: string[],\n startOutputIndex: number,\n): ResponsesSSEEvent[] {\n const events: ResponsesSSEEvent[] = [];\n\n for (let i = 0; i < queries.length; i++) {\n const searchId = generateId(\"ws\");\n const outputIndex = startOutputIndex + i;\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"in_progress\",\n action: { type: \"search\", query: queries[i] },\n },\n });\n\n events.push({\n type: \"response.output_item.done\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"completed\",\n action: { type: \"search\", query: queries[i] },\n },\n });\n }\n\n return events;\n}\n\n// ─── Shared streaming helpers ────────────────────────────────────────────────\n\ninterface PreambleResult {\n respId: string;\n created: number;\n events: ResponsesSSEEvent[];\n prefixOutputItems: object[];\n nextOutputIndex: number;\n}\n\nfunction buildResponsePreamble(\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): PreambleResult {\n const respId = overrides?.id ?? responseId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const events: ResponsesSSEEvent[] = [];\n const prefixOutputItems: object[] = [];\n let nextOutputIndex = 0;\n\n events.push({\n type: \"response.created\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n events.push({\n type: \"response.in_progress\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n if (reasoning) {\n const reasoningEvents = buildReasoningStreamEvents(reasoning, model, chunkSize);\n events.push(...reasoningEvents);\n const doneEvent = reasoningEvents.find(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"reasoning\",\n );\n if (doneEvent) prefixOutputItems.push(doneEvent.item as object);\n nextOutputIndex++;\n }\n\n if (webSearches && webSearches.length > 0) {\n const searchEvents = buildWebSearchStreamEvents(webSearches, nextOutputIndex);\n events.push(...searchEvents);\n const doneEvents = searchEvents.filter(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"web_search_call\",\n );\n for (const de of doneEvents) prefixOutputItems.push(de.item as object);\n nextOutputIndex += webSearches.length;\n }\n\n return { respId, created, events, prefixOutputItems, nextOutputIndex };\n}\n\ninterface MessageBlockResult {\n events: ResponsesSSEEvent[];\n msgItem: object;\n}\n\nfunction buildMessageOutputEvents(\n content: string,\n chunkSize: number,\n outputIndex: number,\n): MessageBlockResult {\n const msgId = itemId();\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: { type: \"message\", id: msgId, status: \"in_progress\", role: \"assistant\", content: [] },\n });\n events.push({\n type: \"response.content_part.added\",\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n events.push({\n type: \"response.output_text.delta\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n delta: content.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.output_text.done\",\n output_index: outputIndex,\n content_index: 0,\n text: content,\n });\n events.push({\n type: \"response.content_part.done\",\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: content, annotations: [] },\n });\n\n const msgItem = {\n type: \"message\",\n id: msgId,\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n };\n\n events.push({ type: \"response.output_item.done\", output_index: outputIndex, item: msgItem });\n\n return { events, msgItem };\n}\n\n// ─── Non-streaming response builders ────────────────────────────────────────\n\nfunction buildOutputPrefix(content: string, reasoning?: string, webSearches?: string[]): object[] {\n const output: object[] = [];\n\n if (reasoning) {\n output.push({\n type: \"reasoning\",\n id: generateId(\"rs\"),\n summary: [{ type: \"summary_text\", text: reasoning }],\n });\n }\n\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n\n output.push({\n type: \"message\",\n id: itemId(),\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n });\n\n return output;\n}\n\nfunction buildResponseEnvelope(\n model: string,\n output: object[],\n overrides?: ResponseOverrides,\n): object {\n return {\n id: overrides?.id ?? responseId(),\n object: \"response\",\n created_at: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output,\n usage: responsesUsage(overrides),\n };\n}\n\nfunction buildTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): object {\n return buildResponseEnvelope(\n model,\n buildOutputPrefix(content, reasoning, webSearches),\n overrides,\n );\n}\n\nfunction buildToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n overrides?: ResponseOverrides,\n): object {\n return buildResponseEnvelope(\n model,\n toolCalls.map((tc) => ({\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: tc.arguments,\n status: \"completed\",\n })),\n overrides,\n );\n}\n\nexport function buildContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n );\n\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n\n const fcOutputItems: object[] = [];\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n const fcOutputIndex = nextOutputIndex + 1 + idx;\n const args = tc.arguments;\n\n events.push({\n type: \"response.output_item.added\",\n output_index: fcOutputIndex,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n for (let i = 0; i < args.length; i += chunkSize) {\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: fcOutputIndex,\n delta: args.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.function_call_arguments.done\",\n output_index: fcOutputIndex,\n arguments: args,\n });\n\n const doneItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: args,\n status: \"completed\",\n };\n events.push({ type: \"response.output_item.done\", output_index: fcOutputIndex, item: doneItem });\n fcOutputItems.push(doneItem);\n }\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, msgItem, ...fcOutputItems],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n): object {\n const output = buildOutputPrefix(content, reasoning, webSearches);\n for (const tc of toolCalls) {\n output.push({\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: tc.arguments,\n status: \"completed\",\n });\n }\n return buildResponseEnvelope(model, output, overrides);\n}\n\n// ─── SSE writer for Responses API ───────────────────────────────────────────\n\ninterface ResponsesStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeResponsesSSEStream(\n res: http.ServerResponse,\n events: ResponsesSSEEvent[],\n optionsOrLatency?: number | ResponsesStreamOptions,\n): Promise<boolean> {\n const opts: ResponsesStreamOptions =\n typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n const latency = opts.latency ?? 0;\n const profile = opts.streamingProfile;\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);\n if (chunkDelay > 0) await delay(chunkDelay, signal);\n if (signal?.aborted) return false;\n if (res.writableEnded) return true;\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\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 handleResponses(\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 setCorsHeaders(res);\n\n let responsesReq: ResponsesRequest;\n try {\n responsesReq = JSON.parse(raw) as ResponsesRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\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: { message: \"Malformed JSON\", type: \"invalid_request_error\", code: \"invalid_json\" },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = responsesToCompletionRequest(responsesReq);\n completionReq._endpointType = \"chat\";\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n defaults.logger.debug(\n `Responses fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n } else {\n defaults.logger.debug(\n `No responses fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\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: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"openai\",\n req.url ?? \"/v1/responses\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n const strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\n defaults.logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: strictStatus, fixture: null },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n const response = fixture.response;\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Combined content + tool calls response\n if (isContentWithToolCallsResponse(response)) {\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n completionReq.model,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildContentWithToolCallsStreamEvents(\n response.content,\n response.toolCalls,\n completionReq.model,\n chunkSize,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\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 const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildTextStreamEvents(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n response.webSearches,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\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 const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildToolCallResponse(response.toolCalls, completionReq.model, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildToolCallStreamEvents(\n response.toolCalls,\n completionReq.model,\n chunkSize,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\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: req.url ?? \"/v1/responses\",\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: { message: \"Fixture response did not match any known type\", type: \"server_error\" },\n }),\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"responses.d.cts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UAoMiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,oBACX;iBAgCa,yBAAA,YACH,0DAGC,oBACX;iBAyaa,qCAAA,6BAEH,sGAKC,oBACX;iBAoJmB,eAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
1
+ {"version":3,"file":"responses.d.cts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UA4QiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,oBACX;iBAgCa,yBAAA,YACH,0DAGC,oBACX;iBA4aa,qCAAA,6BAEH,sGAKC,oBACX;iBAoJmB,eAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"responses.d.ts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UAoMiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,oBACX;iBAgCa,yBAAA,YACH,0DAGC,oBACX;iBAyaa,qCAAA,6BAEH,sGAKC,oBACX;iBAoJmB,eAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
1
+ {"version":3,"file":"responses.d.ts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UA4QiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,oBACX;iBAgCa,yBAAA,YACH,0DAGC,oBACX;iBA4aa,qCAAA,6BAEH,sGAKC,oBACX;iBAoJmB,eAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
package/dist/responses.js CHANGED
@@ -13,6 +13,7 @@ function extractTextContent(content) {
13
13
  }
14
14
  function responsesInputToMessages(req) {
15
15
  const messages = [];
16
+ const itemReferencePlaceholders = /* @__PURE__ */ new WeakSet();
16
17
  if (req.instructions) messages.push({
17
18
  role: "system",
18
19
  content: req.instructions
@@ -48,11 +49,65 @@ function responsesInputToMessages(req) {
48
49
  }
49
50
  }]
50
51
  });
51
- else if (item.type === "function_call_output") messages.push({
52
- role: "tool",
53
- content: item.output ?? "",
54
- tool_call_id: item.call_id
55
- });
52
+ else if (item.type === "function_call_output") {
53
+ if (!messages.some((m) => m.role === "assistant" && m.tool_calls?.some((tc) => tc.id === item.call_id))) {
54
+ const lastMsg = messages[messages.length - 1];
55
+ if (lastMsg && lastMsg.role === "assistant" && itemReferencePlaceholders.has(lastMsg) && !lastMsg.tool_calls) {
56
+ lastMsg.content = null;
57
+ lastMsg.tool_calls = [{
58
+ id: item.call_id ?? generateToolCallId(),
59
+ type: "function",
60
+ function: {
61
+ name: "",
62
+ arguments: ""
63
+ }
64
+ }];
65
+ itemReferencePlaceholders.delete(lastMsg);
66
+ } else {
67
+ let appended = false;
68
+ for (let k = messages.length - 1; k >= 0; k--) {
69
+ const m = messages[k];
70
+ if (m.role === "assistant" && m.tool_calls) {
71
+ m.tool_calls.push({
72
+ id: item.call_id ?? generateToolCallId(),
73
+ type: "function",
74
+ function: {
75
+ name: "",
76
+ arguments: ""
77
+ }
78
+ });
79
+ appended = true;
80
+ break;
81
+ }
82
+ if (m.role === "user") break;
83
+ }
84
+ if (!appended) messages.push({
85
+ role: "assistant",
86
+ content: null,
87
+ tool_calls: [{
88
+ id: item.call_id ?? generateToolCallId(),
89
+ type: "function",
90
+ function: {
91
+ name: "",
92
+ arguments: ""
93
+ }
94
+ }]
95
+ });
96
+ }
97
+ }
98
+ messages.push({
99
+ role: "tool",
100
+ content: item.output ?? "",
101
+ tool_call_id: item.call_id
102
+ });
103
+ } else if (item.type === "item_reference") {
104
+ const placeholder = {
105
+ role: "assistant",
106
+ content: ""
107
+ };
108
+ itemReferencePlaceholders.add(placeholder);
109
+ messages.push(placeholder);
110
+ }
56
111
  return messages;
57
112
  }
58
113
  function responsesToolsToCompletionsTools(tools) {
@@ -222,6 +277,7 @@ function buildReasoningStreamEvents(reasoning, model, chunkSize) {
222
277
  });
223
278
  events.push({
224
279
  type: "response.reasoning_summary_part.added",
280
+ item_id: reasoningId,
225
281
  output_index: 0,
226
282
  summary_index: 0,
227
283
  part: {
@@ -241,12 +297,14 @@ function buildReasoningStreamEvents(reasoning, model, chunkSize) {
241
297
  }
242
298
  events.push({
243
299
  type: "response.reasoning_summary_text.done",
300
+ item_id: reasoningId,
244
301
  output_index: 0,
245
302
  summary_index: 0,
246
303
  text: reasoning
247
304
  });
248
305
  events.push({
249
306
  type: "response.reasoning_summary_part.done",
307
+ item_id: reasoningId,
250
308
  output_index: 0,
251
309
  summary_index: 0,
252
310
  part: {
@@ -280,7 +338,10 @@ function buildWebSearchStreamEvents(queries, startOutputIndex) {
280
338
  type: "web_search_call",
281
339
  id: searchId,
282
340
  status: "in_progress",
283
- action: { query: queries[i] }
341
+ action: {
342
+ type: "search",
343
+ query: queries[i]
344
+ }
284
345
  }
285
346
  });
286
347
  events.push({
@@ -290,7 +351,10 @@ function buildWebSearchStreamEvents(queries, startOutputIndex) {
290
351
  type: "web_search_call",
291
352
  id: searchId,
292
353
  status: "completed",
293
- action: { query: queries[i] }
354
+ action: {
355
+ type: "search",
356
+ query: queries[i]
357
+ }
294
358
  }
295
359
  });
296
360
  }
@@ -367,7 +431,8 @@ function buildMessageOutputEvents(content, chunkSize, outputIndex) {
367
431
  content_index: 0,
368
432
  part: {
369
433
  type: "output_text",
370
- text: ""
434
+ text: "",
435
+ annotations: []
371
436
  }
372
437
  });
373
438
  for (let i = 0; i < content.length; i += chunkSize) events.push({
@@ -389,7 +454,8 @@ function buildMessageOutputEvents(content, chunkSize, outputIndex) {
389
454
  content_index: 0,
390
455
  part: {
391
456
  type: "output_text",
392
- text: content
457
+ text: content,
458
+ annotations: []
393
459
  }
394
460
  });
395
461
  const msgItem = {
@@ -399,7 +465,8 @@ function buildMessageOutputEvents(content, chunkSize, outputIndex) {
399
465
  role: "assistant",
400
466
  content: [{
401
467
  type: "output_text",
402
- text: content
468
+ text: content,
469
+ annotations: []
403
470
  }]
404
471
  };
405
472
  events.push({
@@ -426,7 +493,10 @@ function buildOutputPrefix(content, reasoning, webSearches) {
426
493
  type: "web_search_call",
427
494
  id: generateId("ws"),
428
495
  status: "completed",
429
- action: { query }
496
+ action: {
497
+ type: "search",
498
+ query
499
+ }
430
500
  });
431
501
  output.push({
432
502
  type: "message",
@@ -435,7 +505,8 @@ function buildOutputPrefix(content, reasoning, webSearches) {
435
505
  role: "assistant",
436
506
  content: [{
437
507
  type: "output_text",
438
- text: content
508
+ text: content,
509
+ annotations: []
439
510
  }]
440
511
  });
441
512
  return output;
@@ -594,7 +665,10 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
594
665
  completionReq._endpointType = "chat";
595
666
  const testId = getTestId(req);
596
667
  const fixture = matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
597
- if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
668
+ if (fixture) {
669
+ defaults.logger.debug(`Responses fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/responses"}`);
670
+ journal.incrementFixtureMatchCount(fixture, fixtures, testId);
671
+ } else defaults.logger.debug(`No responses fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/responses"}`);
598
672
  if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
599
673
  method: req.method ?? "POST",
600
674
  path: req.url ?? "/v1/responses",