@copilotkit/aimock 1.15.0 → 1.16.0

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 (148) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +33 -15
  3. package/README.md +1 -1
  4. package/dist/bedrock-converse.cjs +133 -25
  5. package/dist/bedrock-converse.cjs.map +1 -1
  6. package/dist/bedrock-converse.d.cts.map +1 -1
  7. package/dist/bedrock-converse.d.ts.map +1 -1
  8. package/dist/bedrock-converse.js +135 -27
  9. package/dist/bedrock-converse.js.map +1 -1
  10. package/dist/bedrock.cjs +262 -48
  11. package/dist/bedrock.cjs.map +1 -1
  12. package/dist/bedrock.d.cts.map +1 -1
  13. package/dist/bedrock.d.ts.map +1 -1
  14. package/dist/bedrock.js +263 -50
  15. package/dist/bedrock.js.map +1 -1
  16. package/dist/chaos.cjs +9 -35
  17. package/dist/chaos.cjs.map +1 -1
  18. package/dist/chaos.d.cts +2 -17
  19. package/dist/chaos.d.cts.map +1 -1
  20. package/dist/chaos.d.ts +2 -17
  21. package/dist/chaos.d.ts.map +1 -1
  22. package/dist/chaos.js +10 -35
  23. package/dist/chaos.js.map +1 -1
  24. package/dist/cohere.cjs +289 -33
  25. package/dist/cohere.cjs.map +1 -1
  26. package/dist/cohere.d.cts +9 -0
  27. package/dist/cohere.d.cts.map +1 -1
  28. package/dist/cohere.d.ts +9 -0
  29. package/dist/cohere.d.ts.map +1 -1
  30. package/dist/cohere.js +290 -34
  31. package/dist/cohere.js.map +1 -1
  32. package/dist/config-loader.d.cts.map +1 -1
  33. package/dist/embeddings.cjs +22 -4
  34. package/dist/embeddings.cjs.map +1 -1
  35. package/dist/embeddings.d.cts +2 -2
  36. package/dist/embeddings.d.cts.map +1 -1
  37. package/dist/embeddings.d.ts +2 -2
  38. package/dist/embeddings.d.ts.map +1 -1
  39. package/dist/embeddings.js +22 -4
  40. package/dist/embeddings.js.map +1 -1
  41. package/dist/fixture-loader.cjs +19 -4
  42. package/dist/fixture-loader.cjs.map +1 -1
  43. package/dist/fixture-loader.d.cts.map +1 -1
  44. package/dist/fixture-loader.d.ts.map +1 -1
  45. package/dist/fixture-loader.js +19 -4
  46. package/dist/fixture-loader.js.map +1 -1
  47. package/dist/gemini.cjs +48 -45
  48. package/dist/gemini.cjs.map +1 -1
  49. package/dist/gemini.d.cts.map +1 -1
  50. package/dist/gemini.d.ts.map +1 -1
  51. package/dist/gemini.js +48 -45
  52. package/dist/gemini.js.map +1 -1
  53. package/dist/helpers.cjs +9 -0
  54. package/dist/helpers.cjs.map +1 -1
  55. package/dist/helpers.d.cts.map +1 -1
  56. package/dist/helpers.d.ts.map +1 -1
  57. package/dist/helpers.js +9 -0
  58. package/dist/helpers.js.map +1 -1
  59. package/dist/images.cjs +21 -3
  60. package/dist/images.cjs.map +1 -1
  61. package/dist/images.js +21 -3
  62. package/dist/images.js.map +1 -1
  63. package/dist/index.cjs +2 -0
  64. package/dist/index.d.cts +2 -2
  65. package/dist/index.d.ts +2 -2
  66. package/dist/index.js +3 -3
  67. package/dist/jest.cjs +10 -3
  68. package/dist/jest.cjs.map +1 -1
  69. package/dist/jest.js +10 -3
  70. package/dist/jest.js.map +1 -1
  71. package/dist/journal.cjs +1 -1
  72. package/dist/journal.cjs.map +1 -1
  73. package/dist/journal.d.cts.map +1 -1
  74. package/dist/journal.d.ts.map +1 -1
  75. package/dist/journal.js +1 -1
  76. package/dist/journal.js.map +1 -1
  77. package/dist/llmock.cjs +6 -0
  78. package/dist/llmock.cjs.map +1 -1
  79. package/dist/llmock.d.cts +1 -0
  80. package/dist/llmock.d.cts.map +1 -1
  81. package/dist/llmock.d.ts +1 -0
  82. package/dist/llmock.d.ts.map +1 -1
  83. package/dist/llmock.js +6 -0
  84. package/dist/llmock.js.map +1 -1
  85. package/dist/messages.cjs +5 -4
  86. package/dist/messages.cjs.map +1 -1
  87. package/dist/messages.js +5 -4
  88. package/dist/messages.js.map +1 -1
  89. package/dist/ollama.cjs +129 -8
  90. package/dist/ollama.cjs.map +1 -1
  91. package/dist/ollama.d.cts.map +1 -1
  92. package/dist/ollama.d.ts.map +1 -1
  93. package/dist/ollama.js +130 -9
  94. package/dist/ollama.js.map +1 -1
  95. package/dist/recorder.cjs +234 -69
  96. package/dist/recorder.cjs.map +1 -1
  97. package/dist/recorder.d.cts +5 -50
  98. package/dist/recorder.d.cts.map +1 -1
  99. package/dist/recorder.d.ts +5 -50
  100. package/dist/recorder.d.ts.map +1 -1
  101. package/dist/recorder.js +234 -69
  102. package/dist/recorder.js.map +1 -1
  103. package/dist/responses.cjs +12 -3
  104. package/dist/responses.cjs.map +1 -1
  105. package/dist/responses.d.cts +2 -1
  106. package/dist/responses.d.cts.map +1 -1
  107. package/dist/responses.d.ts +2 -1
  108. package/dist/responses.d.ts.map +1 -1
  109. package/dist/responses.js +12 -4
  110. package/dist/responses.js.map +1 -1
  111. package/dist/router.cjs +19 -6
  112. package/dist/router.cjs.map +1 -1
  113. package/dist/router.js +19 -6
  114. package/dist/router.js.map +1 -1
  115. package/dist/server.cjs +150 -94
  116. package/dist/server.cjs.map +1 -1
  117. package/dist/server.d.cts.map +1 -1
  118. package/dist/server.d.ts.map +1 -1
  119. package/dist/server.js +152 -96
  120. package/dist/server.js.map +1 -1
  121. package/dist/speech.cjs +21 -3
  122. package/dist/speech.cjs.map +1 -1
  123. package/dist/speech.js +21 -3
  124. package/dist/speech.js.map +1 -1
  125. package/dist/transcription.cjs +10 -6
  126. package/dist/transcription.cjs.map +1 -1
  127. package/dist/transcription.d.cts.map +1 -1
  128. package/dist/transcription.d.ts.map +1 -1
  129. package/dist/transcription.js +10 -6
  130. package/dist/transcription.js.map +1 -1
  131. package/dist/types.d.cts +5 -16
  132. package/dist/types.d.cts.map +1 -1
  133. package/dist/types.d.ts +5 -16
  134. package/dist/types.d.ts.map +1 -1
  135. package/dist/video.cjs +66 -10
  136. package/dist/video.cjs.map +1 -1
  137. package/dist/video.d.cts +16 -3
  138. package/dist/video.d.cts.map +1 -1
  139. package/dist/video.d.ts +16 -3
  140. package/dist/video.d.ts.map +1 -1
  141. package/dist/video.js +66 -11
  142. package/dist/video.js.map +1 -1
  143. package/dist/vitest.cjs +10 -3
  144. package/dist/vitest.cjs.map +1 -1
  145. package/dist/vitest.js +10 -3
  146. package/dist/vitest.js.map +1 -1
  147. package/package.json +1 -1
  148. package/skills/write-fixtures/SKILL.md +75 -49
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","names":[],"sources":["../src/messages.ts"],"sourcesContent":["/**\n * Anthropic Claude Messages API support.\n *\n * Translates incoming /v1/messages requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the Claude Messages API streaming (or non-streaming) format.\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 generateMessageId,\n generateToolUseId,\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 type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Claude Messages API request types ──────────────────────────────────────\n\ninterface ClaudeContentBlock {\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"image\" | \"document\";\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | ClaudeContentBlock[];\n is_error?: boolean;\n}\n\ninterface ClaudeMessage {\n role: \"user\" | \"assistant\";\n content: string | ClaudeContentBlock[];\n}\n\ninterface ClaudeToolDef {\n name: string;\n description?: string;\n input_schema?: object;\n}\n\ninterface ClaudeRequest {\n model: string;\n messages: ClaudeMessage[];\n system?: string | ClaudeContentBlock[];\n tools?: ClaudeToolDef[];\n tool_choice?: unknown;\n stream?: boolean;\n max_tokens: number;\n temperature?: number;\n [key: string]: unknown;\n}\n\n// ─── Input conversion: Claude → ChatCompletions messages ────────────────────\n\nfunction extractClaudeTextContent(content: string | ClaudeContentBlock[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n}\n\nexport function claudeToCompletionRequest(req: ClaudeRequest): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system) {\n const systemText =\n typeof req.system === \"string\"\n ? req.system\n : req.system\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n if (systemText) {\n messages.push({ role: \"system\", content: systemText });\n }\n }\n\n for (const msg of req.messages) {\n if (msg.role === \"user\") {\n // Check for tool_result blocks\n if (typeof msg.content !== \"string\" && Array.isArray(msg.content)) {\n const toolResults = msg.content.filter((b) => b.type === \"tool_result\");\n const textBlocks = msg.content.filter((b) => b.type === \"text\");\n\n if (toolResults.length > 0) {\n // Each tool_result → tool message\n for (const tr of toolResults) {\n const resultContent =\n typeof tr.content === \"string\"\n ? tr.content\n : Array.isArray(tr.content)\n ? tr.content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\")\n : \"\";\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.tool_use_id,\n });\n }\n // Any accompanying text blocks → user message\n if (textBlocks.length > 0) {\n messages.push({\n role: \"user\",\n content: textBlocks.map((b) => b.text ?? \"\").join(\"\"),\n });\n }\n continue;\n }\n }\n // Regular user message\n messages.push({\n role: \"user\",\n content: extractClaudeTextContent(msg.content),\n });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolUseBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n const textContent = extractClaudeTextContent(msg.content);\n\n if (toolUseBlocks.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent || null,\n tool_calls: toolUseBlocks.map((b) => ({\n id: b.id ?? generateToolUseId(),\n type: \"function\" as const,\n function: {\n name: b.name ?? \"\",\n arguments: typeof b.input === \"string\" ? b.input : JSON.stringify(b.input ?? {}),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n // null/undefined content — tool-only assistant turn\n messages.push({ role: \"assistant\", content: null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n return {\n model: req.model,\n messages,\n stream: req.stream,\n temperature: req.temperature,\n tools,\n };\n}\n\n// ─── Response building: fixture → Claude Messages API format ────────────────\n\nfunction claudeStopReason(finishReason: string | undefined, defaultReason: string): string {\n if (!finishReason) return defaultReason;\n if (finishReason === \"stop\") return \"end_turn\";\n if (finishReason === \"tool_calls\") return \"tool_use\";\n if (finishReason === \"length\") return \"max_tokens\";\n return finishReason;\n}\n\nfunction claudeUsage(overrides?: ResponseOverrides): {\n input_tokens: number;\n output_tokens: number;\n} {\n if (!overrides?.usage) return { input_tokens: 0, output_tokens: 0 };\n return {\n input_tokens: overrides.usage.input_tokens ?? 0,\n output_tokens: overrides.usage.output_tokens ?? 0,\n };\n}\n\ninterface ClaudeSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\nfunction buildClaudeTextStreamEvents(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): ClaudeSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const effectiveModel = overrides?.model ?? model;\n const events: ClaudeSSEEvent[] = [];\n\n // message_start\n events.push({\n type: \"message_start\",\n message: {\n id: msgId,\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: [],\n model: effectiveModel,\n stop_reason: null,\n stop_sequence: null,\n usage: claudeUsage(overrides),\n },\n });\n\n let blockIndex = 0;\n\n // Thinking block (emitted before text when reasoning is present)\n if (reasoning) {\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"thinking\", thinking: \"\" },\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: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n }\n\n // content_block_start (text)\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"text\", text: \"\" },\n });\n\n // content_block_delta — text chunks\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"text_delta\", text: slice },\n });\n }\n\n // content_block_stop\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n // message_delta\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: claudeStopReason(overrides?.finishReason, \"end_turn\"),\n stop_sequence: null,\n },\n usage: { output_tokens: claudeUsage(overrides).output_tokens },\n });\n\n // message_stop\n events.push({ type: \"message_stop\" });\n\n return events;\n}\n\nfunction buildClaudeToolCallStreamEvents(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n logger: Logger,\n overrides?: ResponseOverrides,\n): ClaudeSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const effectiveModel = overrides?.model ?? model;\n const events: ClaudeSSEEvent[] = [];\n\n // message_start\n events.push({\n type: \"message_start\",\n message: {\n id: msgId,\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: [],\n model: effectiveModel,\n stop_reason: null,\n stop_sequence: null,\n usage: claudeUsage(overrides),\n },\n });\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const toolUseId = tc.id || generateToolUseId();\n\n // Parse arguments to JSON object (Claude uses objects, not strings)\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n const argsJson = JSON.stringify(argsObj);\n\n // content_block_start\n events.push({\n type: \"content_block_start\",\n index: idx,\n content_block: {\n type: \"tool_use\",\n id: toolUseId,\n name: tc.name,\n input: {},\n },\n });\n\n // content_block_delta — input_json_delta chunks\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: idx,\n delta: { type: \"input_json_delta\", partial_json: slice },\n });\n }\n\n // content_block_stop\n events.push({\n type: \"content_block_stop\",\n index: idx,\n });\n }\n\n // message_delta\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n },\n usage: { output_tokens: claudeUsage(overrides).output_tokens },\n });\n\n // message_stop\n events.push({ type: \"message_stop\" });\n\n return events;\n}\n\n// Non-streaming response builders\n\nfunction buildClaudeTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: overrides?.id ?? generateMessageId(),\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: contentBlocks,\n model: overrides?.model ?? model,\n stop_reason: claudeStopReason(overrides?.finishReason, \"end_turn\"),\n stop_sequence: null,\n usage: claudeUsage(overrides),\n };\n}\n\nfunction buildClaudeToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n overrides?: ResponseOverrides,\n): object {\n return {\n id: overrides?.id ?? generateMessageId(),\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n };\n }),\n model: overrides?.model ?? model,\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n usage: claudeUsage(overrides),\n };\n}\n\nfunction buildClaudeContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): ClaudeSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const effectiveModel = overrides?.model ?? model;\n const events: ClaudeSSEEvent[] = [];\n\n // message_start\n events.push({\n type: \"message_start\",\n message: {\n id: msgId,\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: [],\n model: effectiveModel,\n stop_reason: null,\n stop_sequence: null,\n usage: claudeUsage(overrides),\n },\n });\n\n let blockIndex = 0;\n\n // Optional thinking block\n if (reasoning) {\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"thinking\", thinking: \"\" },\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: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n }\n\n // Text content block\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"text\", text: \"\" },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"text_delta\", text: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n\n // Tool use blocks\n for (const tc of toolCalls) {\n const toolUseId = tc.id || generateToolUseId();\n\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n const argsJson = JSON.stringify(argsObj);\n\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolUseId,\n name: tc.name,\n input: {},\n },\n });\n\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"input_json_delta\", partial_json: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n }\n\n // message_delta\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n },\n usage: { output_tokens: claudeUsage(overrides).output_tokens },\n });\n\n // message_stop\n events.push({ type: \"message_stop\" });\n\n return events;\n}\n\nfunction buildClaudeContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n\n contentBlocks.push({ type: \"text\", text: content });\n\n for (const tc of toolCalls) {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n contentBlocks.push({\n type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n });\n }\n\n return {\n id: overrides?.id ?? generateMessageId(),\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: contentBlocks,\n model: overrides?.model ?? model,\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n usage: claudeUsage(overrides),\n };\n}\n\n// ─── SSE writer for Claude Messages API ─────────────────────────────────────\n\ninterface ClaudeStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeClaudeSSEStream(\n res: http.ServerResponse,\n events: ClaudeSSEEvent[],\n optionsOrLatency?: number | ClaudeStreamOptions,\n): Promise<boolean> {\n const opts: ClaudeStreamOptions =\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 handleMessages(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let claudeReq: ClaudeRequest;\n try {\n claudeReq = JSON.parse(raw) as ClaudeRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = claudeToCompletionRequest(claudeReq);\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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"anthropic\",\n req.url ?? \"/v1/messages\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null },\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 logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/messages\"}`,\n );\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\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 },\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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n // Anthropic-style error format: { type: \"error\", error: { type, message } }\n const anthropicError = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"api_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(anthropicError));\n return;\n }\n\n // Content + tool calls response (must be checked before text/tool-only branches)\n if (isContentWithToolCallsResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Claude Messages API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (claudeReq.stream !== true) {\n const body = buildClaudeContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n completionReq.model,\n logger,\n response.reasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildClaudeContentWithToolCallsStreamEvents(\n response.content,\n response.toolCalls,\n completionReq.model,\n chunkSize,\n logger,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeClaudeSSEStream(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 if (response.webSearches?.length) {\n defaults.logger.warn(\n \"webSearches in fixture response are not supported for Claude Messages API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (claudeReq.stream !== true) {\n const body = buildClaudeTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildClaudeTextStreamEvents(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeClaudeSSEStream(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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (claudeReq.stream !== true) {\n const body = buildClaudeToolCallResponse(\n response.toolCalls,\n completionReq.model,\n logger,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildClaudeToolCallStreamEvents(\n response.toolCalls,\n completionReq.model,\n chunkSize,\n logger,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeClaudeSSEStream(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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"messages.js","names":[],"sources":["../src/messages.ts"],"sourcesContent":["/**\n * Anthropic Claude Messages API support.\n *\n * Translates incoming /v1/messages requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the Claude Messages API streaming (or non-streaming) format.\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 generateMessageId,\n generateToolUseId,\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 type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Claude Messages API request types ──────────────────────────────────────\n\ninterface ClaudeContentBlock {\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"image\" | \"document\";\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | ClaudeContentBlock[];\n is_error?: boolean;\n}\n\ninterface ClaudeMessage {\n role: \"user\" | \"assistant\";\n content: string | ClaudeContentBlock[];\n}\n\ninterface ClaudeToolDef {\n name: string;\n description?: string;\n input_schema?: object;\n}\n\ninterface ClaudeRequest {\n model: string;\n messages: ClaudeMessage[];\n system?: string | ClaudeContentBlock[];\n tools?: ClaudeToolDef[];\n tool_choice?: unknown;\n stream?: boolean;\n max_tokens: number;\n temperature?: number;\n [key: string]: unknown;\n}\n\n// ─── Input conversion: Claude → ChatCompletions messages ────────────────────\n\nfunction extractClaudeTextContent(content: string | ClaudeContentBlock[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n}\n\nexport function claudeToCompletionRequest(req: ClaudeRequest): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system) {\n const systemText =\n typeof req.system === \"string\"\n ? req.system\n : req.system\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n if (systemText) {\n messages.push({ role: \"system\", content: systemText });\n }\n }\n\n for (const msg of req.messages) {\n if (msg.role === \"user\") {\n // Check for tool_result blocks\n if (typeof msg.content !== \"string\" && Array.isArray(msg.content)) {\n const toolResults = msg.content.filter((b) => b.type === \"tool_result\");\n const textBlocks = msg.content.filter((b) => b.type === \"text\");\n\n if (toolResults.length > 0) {\n // Each tool_result → tool message\n for (const tr of toolResults) {\n const resultContent =\n typeof tr.content === \"string\"\n ? tr.content\n : Array.isArray(tr.content)\n ? tr.content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\")\n : \"\";\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.tool_use_id,\n });\n }\n // Any accompanying text blocks → user message\n if (textBlocks.length > 0) {\n messages.push({\n role: \"user\",\n content: textBlocks.map((b) => b.text ?? \"\").join(\"\"),\n });\n }\n continue;\n }\n }\n // Regular user message\n messages.push({\n role: \"user\",\n content: extractClaudeTextContent(msg.content),\n });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolUseBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n const textContent = extractClaudeTextContent(msg.content);\n\n if (toolUseBlocks.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent || null,\n tool_calls: toolUseBlocks.map((b) => ({\n id: b.id ?? generateToolUseId(),\n type: \"function\" as const,\n function: {\n name: b.name ?? \"\",\n arguments: typeof b.input === \"string\" ? b.input : JSON.stringify(b.input ?? {}),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n // null/undefined content — tool-only assistant turn\n messages.push({ role: \"assistant\", content: null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n return {\n model: req.model,\n messages,\n stream: req.stream,\n temperature: req.temperature,\n tools,\n };\n}\n\n// ─── Response building: fixture → Claude Messages API format ────────────────\n\nfunction claudeStopReason(finishReason: string | undefined, defaultReason: string): string {\n if (!finishReason) return defaultReason;\n if (finishReason === \"stop\") return \"end_turn\";\n if (finishReason === \"tool_calls\") return \"tool_use\";\n if (finishReason === \"length\") return \"max_tokens\";\n return finishReason;\n}\n\nfunction claudeUsage(overrides?: ResponseOverrides): {\n input_tokens: number;\n output_tokens: number;\n} {\n if (!overrides?.usage) return { input_tokens: 0, output_tokens: 0 };\n return {\n input_tokens: overrides.usage.input_tokens ?? 0,\n output_tokens: overrides.usage.output_tokens ?? 0,\n };\n}\n\ninterface ClaudeSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\nfunction buildClaudeTextStreamEvents(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): ClaudeSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const effectiveModel = overrides?.model ?? model;\n const events: ClaudeSSEEvent[] = [];\n\n // message_start\n events.push({\n type: \"message_start\",\n message: {\n id: msgId,\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: [],\n model: effectiveModel,\n stop_reason: null,\n stop_sequence: null,\n usage: claudeUsage(overrides),\n },\n });\n\n let blockIndex = 0;\n\n // Thinking block (emitted before text when reasoning is present)\n if (reasoning) {\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"thinking\", thinking: \"\" },\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: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n }\n\n // content_block_start (text)\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"text\", text: \"\" },\n });\n\n // content_block_delta — text chunks\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"text_delta\", text: slice },\n });\n }\n\n // content_block_stop\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n // message_delta\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: claudeStopReason(overrides?.finishReason, \"end_turn\"),\n stop_sequence: null,\n },\n usage: { output_tokens: claudeUsage(overrides).output_tokens },\n });\n\n // message_stop\n events.push({ type: \"message_stop\" });\n\n return events;\n}\n\nfunction buildClaudeToolCallStreamEvents(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n logger: Logger,\n overrides?: ResponseOverrides,\n): ClaudeSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const effectiveModel = overrides?.model ?? model;\n const events: ClaudeSSEEvent[] = [];\n\n // message_start\n events.push({\n type: \"message_start\",\n message: {\n id: msgId,\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: [],\n model: effectiveModel,\n stop_reason: null,\n stop_sequence: null,\n usage: claudeUsage(overrides),\n },\n });\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const toolUseId = tc.id || generateToolUseId();\n\n // Parse arguments to JSON object (Claude uses objects, not strings)\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n const argsJson = JSON.stringify(argsObj);\n\n // content_block_start\n events.push({\n type: \"content_block_start\",\n index: idx,\n content_block: {\n type: \"tool_use\",\n id: toolUseId,\n name: tc.name,\n input: {},\n },\n });\n\n // content_block_delta — input_json_delta chunks\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: idx,\n delta: { type: \"input_json_delta\", partial_json: slice },\n });\n }\n\n // content_block_stop\n events.push({\n type: \"content_block_stop\",\n index: idx,\n });\n }\n\n // message_delta\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n },\n usage: { output_tokens: claudeUsage(overrides).output_tokens },\n });\n\n // message_stop\n events.push({ type: \"message_stop\" });\n\n return events;\n}\n\n// Non-streaming response builders\n\nfunction buildClaudeTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: overrides?.id ?? generateMessageId(),\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: contentBlocks,\n model: overrides?.model ?? model,\n stop_reason: claudeStopReason(overrides?.finishReason, \"end_turn\"),\n stop_sequence: null,\n usage: claudeUsage(overrides),\n };\n}\n\nfunction buildClaudeToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n overrides?: ResponseOverrides,\n): object {\n return {\n id: overrides?.id ?? generateMessageId(),\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n };\n }),\n model: overrides?.model ?? model,\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n usage: claudeUsage(overrides),\n };\n}\n\nfunction buildClaudeContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): ClaudeSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const effectiveModel = overrides?.model ?? model;\n const events: ClaudeSSEEvent[] = [];\n\n // message_start\n events.push({\n type: \"message_start\",\n message: {\n id: msgId,\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: [],\n model: effectiveModel,\n stop_reason: null,\n stop_sequence: null,\n usage: claudeUsage(overrides),\n },\n });\n\n let blockIndex = 0;\n\n // Optional thinking block\n if (reasoning) {\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"thinking\", thinking: \"\" },\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: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n }\n\n // Text content block\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: { type: \"text\", text: \"\" },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"text_delta\", text: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n\n // Tool use blocks\n for (const tc of toolCalls) {\n const toolUseId = tc.id || generateToolUseId();\n\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n const argsJson = JSON.stringify(argsObj);\n\n events.push({\n type: \"content_block_start\",\n index: blockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolUseId,\n name: tc.name,\n input: {},\n },\n });\n\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"content_block_delta\",\n index: blockIndex,\n delta: { type: \"input_json_delta\", partial_json: slice },\n });\n }\n\n events.push({\n type: \"content_block_stop\",\n index: blockIndex,\n });\n\n blockIndex++;\n }\n\n // message_delta\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n },\n usage: { output_tokens: claudeUsage(overrides).output_tokens },\n });\n\n // message_stop\n events.push({ type: \"message_stop\" });\n\n return events;\n}\n\nfunction buildClaudeContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n\n contentBlocks.push({ type: \"text\", text: content });\n\n for (const tc of toolCalls) {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n contentBlocks.push({\n type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n });\n }\n\n return {\n id: overrides?.id ?? generateMessageId(),\n type: \"message\",\n role: overrides?.role ?? \"assistant\",\n content: contentBlocks,\n model: overrides?.model ?? model,\n stop_reason: claudeStopReason(overrides?.finishReason, \"tool_use\"),\n stop_sequence: null,\n usage: claudeUsage(overrides),\n };\n}\n\n// ─── SSE writer for Claude Messages API ─────────────────────────────────────\n\ninterface ClaudeStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeClaudeSSEStream(\n res: http.ServerResponse,\n events: ClaudeSSEEvent[],\n optionsOrLatency?: number | ClaudeStreamOptions,\n): Promise<boolean> {\n const opts: ClaudeStreamOptions =\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 handleMessages(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let claudeReq: ClaudeRequest;\n try {\n claudeReq = JSON.parse(raw) as ClaudeRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = claudeToCompletionRequest(claudeReq);\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/messages\",\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 \"anthropic\",\n req.url ?? \"/v1/messages\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\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 logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/messages\"}`,\n );\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\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 },\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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n // Anthropic-style error format: { type: \"error\", error: { type, message } }\n const anthropicError = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"api_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(anthropicError));\n return;\n }\n\n // Content + tool calls response (must be checked before text/tool-only branches)\n if (isContentWithToolCallsResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Claude Messages API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (claudeReq.stream !== true) {\n const body = buildClaudeContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n completionReq.model,\n logger,\n response.reasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildClaudeContentWithToolCallsStreamEvents(\n response.content,\n response.toolCalls,\n completionReq.model,\n chunkSize,\n logger,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeClaudeSSEStream(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 if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Claude Messages API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (claudeReq.stream !== true) {\n const body = buildClaudeTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildClaudeTextStreamEvents(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeClaudeSSEStream(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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (claudeReq.stream !== true) {\n const body = buildClaudeToolCallResponse(\n response.toolCalls,\n completionReq.model,\n logger,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildClaudeToolCallStreamEvents(\n response.toolCalls,\n completionReq.model,\n chunkSize,\n logger,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeClaudeSSEStream(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/messages\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n"],"mappings":";;;;;;;;AA4EA,SAAS,yBAAyB,SAAgD;AAChF,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,QAAO,QACJ,QAAQ,MAAM,EAAE,SAAS,OAAO,CAChC,KAAK,MAAM,EAAE,QAAQ,GAAG,CACxB,KAAK,GAAG;;AAGb,SAAgB,0BAA0B,KAA2C;CACnF,MAAM,WAA0B,EAAE;AAGlC,KAAI,IAAI,QAAQ;EACd,MAAM,aACJ,OAAO,IAAI,WAAW,WAClB,IAAI,SACJ,IAAI,OACD,QAAQ,MAAM,EAAE,SAAS,OAAO,CAChC,KAAK,MAAM,EAAE,QAAQ,GAAG,CACxB,KAAK,GAAG;AACjB,MAAI,WACF,UAAS,KAAK;GAAE,MAAM;GAAU,SAAS;GAAY,CAAC;;AAI1D,MAAK,MAAM,OAAO,IAAI,SACpB,KAAI,IAAI,SAAS,QAAQ;AAEvB,MAAI,OAAO,IAAI,YAAY,YAAY,MAAM,QAAQ,IAAI,QAAQ,EAAE;GACjE,MAAM,cAAc,IAAI,QAAQ,QAAQ,MAAM,EAAE,SAAS,cAAc;GACvE,MAAM,aAAa,IAAI,QAAQ,QAAQ,MAAM,EAAE,SAAS,OAAO;AAE/D,OAAI,YAAY,SAAS,GAAG;AAE1B,SAAK,MAAM,MAAM,aAAa;KAC5B,MAAM,gBACJ,OAAO,GAAG,YAAY,WAClB,GAAG,UACH,MAAM,QAAQ,GAAG,QAAQ,GACvB,GAAG,QACA,QAAQ,MAAM,EAAE,SAAS,OAAO,CAChC,KAAK,MAAM,EAAE,QAAQ,GAAG,CACxB,KAAK,GAAG,GACX;AACR,cAAS,KAAK;MACZ,MAAM;MACN,SAAS;MACT,cAAc,GAAG;MAClB,CAAC;;AAGJ,QAAI,WAAW,SAAS,EACtB,UAAS,KAAK;KACZ,MAAM;KACN,SAAS,WAAW,KAAK,MAAM,EAAE,QAAQ,GAAG,CAAC,KAAK,GAAG;KACtD,CAAC;AAEJ;;;AAIJ,WAAS,KAAK;GACZ,MAAM;GACN,SAAS,yBAAyB,IAAI,QAAQ;GAC/C,CAAC;YACO,IAAI,SAAS,YACtB,KAAI,OAAO,IAAI,YAAY,SACzB,UAAS,KAAK;EAAE,MAAM;EAAa,SAAS,IAAI;EAAS,CAAC;UACjD,MAAM,QAAQ,IAAI,QAAQ,EAAE;EACrC,MAAM,gBAAgB,IAAI,QAAQ,QAAQ,MAAM,EAAE,SAAS,WAAW;EACtE,MAAM,cAAc,yBAAyB,IAAI,QAAQ;AAEzD,MAAI,cAAc,SAAS,EACzB,UAAS,KAAK;GACZ,MAAM;GACN,SAAS,eAAe;GACxB,YAAY,cAAc,KAAK,OAAO;IACpC,IAAI,EAAE,MAAM,mBAAmB;IAC/B,MAAM;IACN,UAAU;KACR,MAAM,EAAE,QAAQ;KAChB,WAAW,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ,KAAK,UAAU,EAAE,SAAS,EAAE,CAAC;KACjF;IACF,EAAE;GACJ,CAAC;MAEF,UAAS,KAAK;GAAE,MAAM;GAAa,SAAS,eAAe;GAAM,CAAC;OAIpE,UAAS,KAAK;EAAE,MAAM;EAAa,SAAS;EAAM,CAAC;CAMzD,IAAI;AACJ,KAAI,IAAI,SAAS,IAAI,MAAM,SAAS,EAClC,SAAQ,IAAI,MAAM,KAAK,OAAO;EAC5B,MAAM;EACN,UAAU;GACR,MAAM,EAAE;GACR,aAAa,EAAE;GACf,YAAY,EAAE;GACf;EACF,EAAE;AAGL,QAAO;EACL,OAAO,IAAI;EACX;EACA,QAAQ,IAAI;EACZ,aAAa,IAAI;EACjB;EACD;;AAKH,SAAS,iBAAiB,cAAkC,eAA+B;AACzF,KAAI,CAAC,aAAc,QAAO;AAC1B,KAAI,iBAAiB,OAAQ,QAAO;AACpC,KAAI,iBAAiB,aAAc,QAAO;AAC1C,KAAI,iBAAiB,SAAU,QAAO;AACtC,QAAO;;AAGT,SAAS,YAAY,WAGnB;AACA,KAAI,CAAC,WAAW,MAAO,QAAO;EAAE,cAAc;EAAG,eAAe;EAAG;AACnE,QAAO;EACL,cAAc,UAAU,MAAM,gBAAgB;EAC9C,eAAe,UAAU,MAAM,iBAAiB;EACjD;;AAQH,SAAS,4BACP,SACA,OACA,WACA,WACA,WACkB;CAClB,MAAM,QAAQ,WAAW,MAAM,mBAAmB;CAClD,MAAM,iBAAiB,WAAW,SAAS;CAC3C,MAAM,SAA2B,EAAE;AAGnC,QAAO,KAAK;EACV,MAAM;EACN,SAAS;GACP,IAAI;GACJ,MAAM;GACN,MAAM,WAAW,QAAQ;GACzB,SAAS,EAAE;GACX,OAAO;GACP,aAAa;GACb,eAAe;GACf,OAAO,YAAY,UAAU;GAC9B;EACF,CAAC;CAEF,IAAI,aAAa;AAGjB,KAAI,WAAW;AACb,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACP,eAAe;IAAE,MAAM;IAAY,UAAU;IAAI;GAClD,CAAC;AAEF,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;GACpD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,UAAU;AAC/C,UAAO,KAAK;IACV,MAAM;IACN,OAAO;IACP,OAAO;KAAE,MAAM;KAAkB,UAAU;KAAO;IACnD,CAAC;;AAGJ,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACR,CAAC;AAEF;;AAIF,QAAO,KAAK;EACV,MAAM;EACN,OAAO;EACP,eAAe;GAAE,MAAM;GAAQ,MAAM;GAAI;EAC1C,CAAC;AAGF,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;EAClD,MAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,UAAU;AAC7C,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACP,OAAO;IAAE,MAAM;IAAc,MAAM;IAAO;GAC3C,CAAC;;AAIJ,QAAO,KAAK;EACV,MAAM;EACN,OAAO;EACR,CAAC;AAGF,QAAO,KAAK;EACV,MAAM;EACN,OAAO;GACL,aAAa,iBAAiB,WAAW,cAAc,WAAW;GAClE,eAAe;GAChB;EACD,OAAO,EAAE,eAAe,YAAY,UAAU,CAAC,eAAe;EAC/D,CAAC;AAGF,QAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,QAAO;;AAGT,SAAS,gCACP,WACA,OACA,WACA,QACA,WACkB;CAClB,MAAM,QAAQ,WAAW,MAAM,mBAAmB;CAClD,MAAM,iBAAiB,WAAW,SAAS;CAC3C,MAAM,SAA2B,EAAE;AAGnC,QAAO,KAAK;EACV,MAAM;EACN,SAAS;GACP,IAAI;GACJ,MAAM;GACN,MAAM,WAAW,QAAQ;GACzB,SAAS,EAAE;GACX,OAAO;GACP,aAAa;GACb,eAAe;GACf,OAAO,YAAY,UAAU;GAC9B;EACF,CAAC;AAEF,MAAK,IAAI,MAAM,GAAG,MAAM,UAAU,QAAQ,OAAO;EAC/C,MAAM,KAAK,UAAU;EACrB,MAAM,YAAY,GAAG,MAAM,mBAAmB;EAG9C,IAAI;AACJ,MAAI;AACF,aAAU,KAAK,MAAM,GAAG,aAAa,KAAK;UACpC;AACN,UAAO,KACL,sDAAsD,GAAG,KAAK,KAAK,GAAG,YACvE;AACD,aAAU,EAAE;;EAEd,MAAM,WAAW,KAAK,UAAU,QAAQ;AAGxC,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACP,eAAe;IACb,MAAM;IACN,IAAI;IACJ,MAAM,GAAG;IACT,OAAO,EAAE;IACV;GACF,CAAC;AAGF,OAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,WAAW;GACnD,MAAM,QAAQ,SAAS,MAAM,GAAG,IAAI,UAAU;AAC9C,UAAO,KAAK;IACV,MAAM;IACN,OAAO;IACP,OAAO;KAAE,MAAM;KAAoB,cAAc;KAAO;IACzD,CAAC;;AAIJ,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACR,CAAC;;AAIJ,QAAO,KAAK;EACV,MAAM;EACN,OAAO;GACL,aAAa,iBAAiB,WAAW,cAAc,WAAW;GAClE,eAAe;GAChB;EACD,OAAO,EAAE,eAAe,YAAY,UAAU,CAAC,eAAe;EAC/D,CAAC;AAGF,QAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,QAAO;;AAKT,SAAS,wBACP,SACA,OACA,WACA,WACQ;CACR,MAAM,gBAA0B,EAAE;AAElC,KAAI,UACF,eAAc,KAAK;EAAE,MAAM;EAAY,UAAU;EAAW,CAAC;AAG/D,eAAc,KAAK;EAAE,MAAM;EAAQ,MAAM;EAAS,CAAC;AAEnD,QAAO;EACL,IAAI,WAAW,MAAM,mBAAmB;EACxC,MAAM;EACN,MAAM,WAAW,QAAQ;EACzB,SAAS;EACT,OAAO,WAAW,SAAS;EAC3B,aAAa,iBAAiB,WAAW,cAAc,WAAW;EAClE,eAAe;EACf,OAAO,YAAY,UAAU;EAC9B;;AAGH,SAAS,4BACP,WACA,OACA,QACA,WACQ;AACR,QAAO;EACL,IAAI,WAAW,MAAM,mBAAmB;EACxC,MAAM;EACN,MAAM,WAAW,QAAQ;EACzB,SAAS,UAAU,KAAK,OAAO;GAC7B,IAAI;AACJ,OAAI;AACF,cAAU,KAAK,MAAM,GAAG,aAAa,KAAK;WACpC;AACN,WAAO,KACL,sDAAsD,GAAG,KAAK,KAAK,GAAG,YACvE;AACD,cAAU,EAAE;;AAEd,UAAO;IACL,MAAM;IACN,IAAI,GAAG,MAAM,mBAAmB;IAChC,MAAM,GAAG;IACT,OAAO;IACR;IACD;EACF,OAAO,WAAW,SAAS;EAC3B,aAAa,iBAAiB,WAAW,cAAc,WAAW;EAClE,eAAe;EACf,OAAO,YAAY,UAAU;EAC9B;;AAGH,SAAS,4CACP,SACA,WACA,OACA,WACA,QACA,WACA,WACkB;CAClB,MAAM,QAAQ,WAAW,MAAM,mBAAmB;CAClD,MAAM,iBAAiB,WAAW,SAAS;CAC3C,MAAM,SAA2B,EAAE;AAGnC,QAAO,KAAK;EACV,MAAM;EACN,SAAS;GACP,IAAI;GACJ,MAAM;GACN,MAAM,WAAW,QAAQ;GACzB,SAAS,EAAE;GACX,OAAO;GACP,aAAa;GACb,eAAe;GACf,OAAO,YAAY,UAAU;GAC9B;EACF,CAAC;CAEF,IAAI,aAAa;AAGjB,KAAI,WAAW;AACb,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACP,eAAe;IAAE,MAAM;IAAY,UAAU;IAAI;GAClD,CAAC;AAEF,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;GACpD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,UAAU;AAC/C,UAAO,KAAK;IACV,MAAM;IACN,OAAO;IACP,OAAO;KAAE,MAAM;KAAkB,UAAU;KAAO;IACnD,CAAC;;AAGJ,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACR,CAAC;AAEF;;AAIF,QAAO,KAAK;EACV,MAAM;EACN,OAAO;EACP,eAAe;GAAE,MAAM;GAAQ,MAAM;GAAI;EAC1C,CAAC;AAEF,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;EAClD,MAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,UAAU;AAC7C,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACP,OAAO;IAAE,MAAM;IAAc,MAAM;IAAO;GAC3C,CAAC;;AAGJ,QAAO,KAAK;EACV,MAAM;EACN,OAAO;EACR,CAAC;AAEF;AAGA,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG,MAAM,mBAAmB;EAE9C,IAAI;AACJ,MAAI;AACF,aAAU,KAAK,MAAM,GAAG,aAAa,KAAK;UACpC;AACN,UAAO,KACL,sDAAsD,GAAG,KAAK,KAAK,GAAG,YACvE;AACD,aAAU,EAAE;;EAEd,MAAM,WAAW,KAAK,UAAU,QAAQ;AAExC,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACP,eAAe;IACb,MAAM;IACN,IAAI;IACJ,MAAM,GAAG;IACT,OAAO,EAAE;IACV;GACF,CAAC;AAEF,OAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,WAAW;GACnD,MAAM,QAAQ,SAAS,MAAM,GAAG,IAAI,UAAU;AAC9C,UAAO,KAAK;IACV,MAAM;IACN,OAAO;IACP,OAAO;KAAE,MAAM;KAAoB,cAAc;KAAO;IACzD,CAAC;;AAGJ,SAAO,KAAK;GACV,MAAM;GACN,OAAO;GACR,CAAC;AAEF;;AAIF,QAAO,KAAK;EACV,MAAM;EACN,OAAO;GACL,aAAa,iBAAiB,WAAW,cAAc,WAAW;GAClE,eAAe;GAChB;EACD,OAAO,EAAE,eAAe,YAAY,UAAU,CAAC,eAAe;EAC/D,CAAC;AAGF,QAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,QAAO;;AAGT,SAAS,wCACP,SACA,WACA,OACA,QACA,WACA,WACQ;CACR,MAAM,gBAA0B,EAAE;AAElC,KAAI,UACF,eAAc,KAAK;EAAE,MAAM;EAAY,UAAU;EAAW,CAAC;AAG/D,eAAc,KAAK;EAAE,MAAM;EAAQ,MAAM;EAAS,CAAC;AAEnD,MAAK,MAAM,MAAM,WAAW;EAC1B,IAAI;AACJ,MAAI;AACF,aAAU,KAAK,MAAM,GAAG,aAAa,KAAK;UACpC;AACN,UAAO,KACL,sDAAsD,GAAG,KAAK,KAAK,GAAG,YACvE;AACD,aAAU,EAAE;;AAEd,gBAAc,KAAK;GACjB,MAAM;GACN,IAAI,GAAG,MAAM,mBAAmB;GAChC,MAAM,GAAG;GACT,OAAO;GACR,CAAC;;AAGJ,QAAO;EACL,IAAI,WAAW,MAAM,mBAAmB;EACxC,MAAM;EACN,MAAM,WAAW,QAAQ;EACzB,SAAS;EACT,OAAO,WAAW,SAAS;EAC3B,aAAa,iBAAiB,WAAW,cAAc,WAAW;EAClE,eAAe;EACf,OAAO,YAAY,UAAU;EAC9B;;AAYH,eAAe,qBACb,KACA,QACA,kBACkB;CAClB,MAAM,OACJ,OAAO,qBAAqB,WAAW,EAAE,SAAS,kBAAkB,GAAI,oBAAoB,EAAE;CAChG,MAAM,UAAU,KAAK,WAAW;CAChC,MAAM,UAAU,KAAK;CACrB,MAAM,SAAS,KAAK;CACpB,MAAM,cAAc,KAAK;AAEzB,KAAI,IAAI,cAAe,QAAO;AAC9B,KAAI,UAAU,gBAAgB,oBAAoB;AAClD,KAAI,UAAU,iBAAiB,WAAW;AAC1C,KAAI,UAAU,cAAc,aAAa;CAEzC,IAAI,aAAa;AACjB,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,aAAa,eAAe,YAAY,SAAS,QAAQ;AAC/D,MAAI,aAAa,EAAG,OAAM,MAAM,YAAY,OAAO;AACnD,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,IAAI,cAAe,QAAO;AAC9B,MAAI,MAAM,UAAU,MAAM,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,MAAM;AACrE,iBAAe;AACf,MAAI,QAAQ,QAAS,QAAO;AAC5B;;AAGF,KAAI,CAAC,IAAI,cACP,KAAI,KAAK;AAEX,QAAO;;AAKT,eAAsB,eACpB,KACA,KACA,KACA,UACA,SACA,UACA,gBACe;CACf,MAAM,EAAE,WAAW;AACnB,gBAAe,IAAI;CAEnB,IAAI;AACJ,KAAI;AACF,cAAY,KAAK,MAAM,IAAI;SACrB;AACN,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK,SAAS;IAAM;GACzC,CAAC;AACF,qBACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;GACL,SAAS;GACT,MAAM;GACP,EACF,CAAC,CACH;AACD;;CAIF,MAAM,gBAAgB,0BAA0B,UAAU;AAC1D,eAAc,gBAAgB;CAE9B,MAAM,SAAS,UAAU,IAAI;CAC7B,MAAM,UAAU,aACd,UACA,eACA,QAAQ,6BAA6B,OAAO,EAC5C,SAAS,iBACV;AAED,KAAI,QACF,SAAQ,2BAA2B,SAAS,UAAU,OAAO;AAG/D,KACE,WACE,KACA,SACA,SAAS,OACT,IAAI,SACJ,SACA;EACE,QAAQ,IAAI,UAAU;EACtB,MAAM,IAAI,OAAO;EACjB,SAAS,eAAe,IAAI,QAAQ;EACpC,MAAM;EACP,EACD,SAAS,UACT,SAAS,OACV,CAED;AAEF,KAAI,CAAC,SAAS;AACZ,MAAI,SAAS,QAWX;OAVgB,MAAM,eACpB,KACA,KACA,eACA,aACA,IAAI,OAAO,gBACX,UACA,UACA,IACD,EACY;AACX,YAAQ,IAAI;KACV,QAAQ,IAAI,UAAU;KACtB,MAAM,IAAI,OAAO;KACjB,SAAS,eAAe,IAAI,QAAQ;KACpC,MAAM;KACN,UAAU;MAAE,QAAQ,IAAI,cAAc;MAAK,SAAS;MAAM,QAAQ;MAAS;KAC5E,CAAC;AACF;;;EAGJ,MAAM,eAAe,SAAS,SAAS,MAAM;EAC7C,MAAM,gBAAgB,SAAS,SAC3B,oCACA;AACJ,MAAI,SAAS,OACX,QAAO,MACL,kCAAkC,IAAI,UAAU,OAAO,GAAG,IAAI,OAAO,iBACtE;AAEH,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAc,SAAS;IAAM;GAClD,CAAC;AACF,qBACE,KACA,cACA,KAAK,UAAU,EACb,OAAO;GACL,SAAS;GACT,MAAM;GACP,EACF,CAAC,CACH;AACD;;CAGF,MAAM,WAAW,QAAQ;CACzB,MAAM,UAAU,QAAQ,WAAW,SAAS;CAC5C,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,SAAS,UAAU;AAGtE,KAAI,gBAAgB,SAAS,EAAE;EAC7B,MAAM,SAAS,SAAS,UAAU;AAClC,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE;IAAQ;IAAS;GAC9B,CAAC;EAEF,MAAM,iBAAiB;GACrB,MAAM;GACN,OAAO;IACL,MAAM,SAAS,MAAM,QAAQ;IAC7B,SAAS,SAAS,MAAM;IACzB;GACF;AACD,qBAAmB,KAAK,QAAQ,KAAK,UAAU,eAAe,CAAC;AAC/D;;AAIF,KAAI,+BAA+B,SAAS,EAAE;AAC5C,MAAI,SAAS,aAAa,OACxB,QAAO,KACL,uFACD;EAEH,MAAM,YAAY,iBAAiB,SAAS;EAC5C,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,UAAU,WAAW,MAAM;GAC7B,MAAM,OAAO,wCACX,SAAS,SACT,SAAS,WACT,cAAc,OACd,QACA,SAAS,WACT,UACD;AACD,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,4CACb,SAAS,SACT,SAAS,WACT,cAAc,OACd,WACA,QACA,SAAS,WACT,UACD;GACD,MAAM,eAAe,yBAAyB,QAAQ;AAOtD,OAAI,CANc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,KAAI,eAAe,SAAS,EAAE;AAC5B,MAAI,SAAS,aAAa,OACxB,QAAO,KACL,uFACD;EAEH,MAAM,YAAY,iBAAiB,SAAS;EAC5C,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,UAAU,WAAW,MAAM;GAC7B,MAAM,OAAO,wBACX,SAAS,SACT,cAAc,OACd,SAAS,WACT,UACD;AACD,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,4BACb,SAAS,SACT,cAAc,OACd,WACA,SAAS,WACT,UACD;GACD,MAAM,eAAe,yBAAyB,QAAQ;AAOtD,OAAI,CANc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,KAAI,mBAAmB,SAAS,EAAE;EAChC,MAAM,YAAY,iBAAiB,SAAS;EAC5C,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;AACF,MAAI,UAAU,WAAW,MAAM;GAC7B,MAAM,OAAO,4BACX,SAAS,WACT,cAAc,OACd,QACA,UACD;AACD,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,KAAK,CAAC;SACxB;GACL,MAAM,SAAS,gCACb,SAAS,WACT,cAAc,OACd,WACA,QACA,UACD;GACD,MAAM,eAAe,yBAAyB,QAAQ;AAOtD,OAAI,CANc,MAAM,qBAAqB,KAAK,QAAQ;IACxD;IACA,kBAAkB,QAAQ;IAC1B,QAAQ,cAAc;IACtB,aAAa,cAAc;IAC5B,CAAC,EACc;AACd,QAAI,CAAC,IAAI,cAAe,KAAI,SAAS;AACrC,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;;AAEhE,iBAAc,SAAS;;AAEzB;;AAIF,SAAQ,IAAI;EACV,QAAQ,IAAI,UAAU;EACtB,MAAM,IAAI,OAAO;EACjB,SAAS,eAAe,IAAI,QAAQ;EACpC,MAAM;EACN,UAAU;GAAE,QAAQ;GAAK;GAAS;EACnC,CAAC;AACF,oBACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;EACL,SAAS;EACT,MAAM;EACP,EACF,CAAC,CACH"}
package/dist/ollama.cjs CHANGED
@@ -34,7 +34,7 @@ function ollamaToCompletionRequest(req) {
34
34
  return {
35
35
  model: req.model,
36
36
  messages,
37
- stream: req.stream,
37
+ stream: req.stream ?? true,
38
38
  temperature: req.options?.temperature,
39
39
  max_tokens: req.options?.num_predict,
40
40
  tools
@@ -47,7 +47,7 @@ function ollamaGenerateToCompletionRequest(req) {
47
47
  role: "user",
48
48
  content: req.prompt
49
49
  }],
50
- stream: req.stream,
50
+ stream: req.stream ?? true,
51
51
  temperature: req.options?.temperature,
52
52
  max_tokens: req.options?.num_predict
53
53
  };
@@ -159,6 +159,76 @@ function buildOllamaChatToolCallResponse(toolCalls, model, logger) {
159
159
  ...DURATION_FIELDS
160
160
  };
161
161
  }
162
+ function buildOllamaChatContentWithToolCallsChunks(content, toolCalls, model, chunkSize, logger) {
163
+ const chunks = [];
164
+ for (let i = 0; i < content.length; i += chunkSize) {
165
+ const slice = content.slice(i, i + chunkSize);
166
+ chunks.push({
167
+ model,
168
+ message: {
169
+ role: "assistant",
170
+ content: slice
171
+ },
172
+ done: false
173
+ });
174
+ }
175
+ const ollamaToolCalls = toolCalls.map((tc) => {
176
+ let argsObj;
177
+ try {
178
+ argsObj = JSON.parse(tc.arguments || "{}");
179
+ } catch {
180
+ logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
181
+ argsObj = {};
182
+ }
183
+ return { function: {
184
+ name: tc.name,
185
+ arguments: argsObj
186
+ } };
187
+ });
188
+ chunks.push({
189
+ model,
190
+ message: {
191
+ role: "assistant",
192
+ content: "",
193
+ tool_calls: ollamaToolCalls
194
+ },
195
+ done: false
196
+ });
197
+ chunks.push({
198
+ model,
199
+ message: {
200
+ role: "assistant",
201
+ content: ""
202
+ },
203
+ done: true,
204
+ ...DURATION_FIELDS
205
+ });
206
+ return chunks;
207
+ }
208
+ function buildOllamaChatContentWithToolCallsResponse(content, toolCalls, model, logger) {
209
+ return {
210
+ model,
211
+ message: {
212
+ role: "assistant",
213
+ content,
214
+ tool_calls: toolCalls.map((tc) => {
215
+ let argsObj;
216
+ try {
217
+ argsObj = JSON.parse(tc.arguments || "{}");
218
+ } catch {
219
+ logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
220
+ argsObj = {};
221
+ }
222
+ return { function: {
223
+ name: tc.name,
224
+ arguments: argsObj
225
+ } };
226
+ })
227
+ },
228
+ done: true,
229
+ ...DURATION_FIELDS
230
+ };
231
+ }
162
232
  function buildOllamaGenerateTextChunks(content, model, chunkSize, reasoning) {
163
233
  const chunks = [];
164
234
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -253,10 +323,10 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
253
323
  path: urlPath,
254
324
  headers: require_helpers.flattenHeaders(req.headers),
255
325
  body: completionReq
256
- }, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
326
+ }, defaults.registry, defaults.logger)) return;
257
327
  if (!fixture) {
258
328
  if (defaults.record) {
259
- if (await require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw) !== "not_configured") {
329
+ if (await require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw)) {
260
330
  journal.add({
261
331
  method: req.method ?? "POST",
262
332
  path: urlPath,
@@ -264,7 +334,8 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
264
334
  body: completionReq,
265
335
  response: {
266
336
  status: res.statusCode ?? 200,
267
- fixture: null
337
+ fixture: null,
338
+ source: "proxy"
268
339
  }
269
340
  });
270
341
  return;
@@ -308,6 +379,38 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
308
379
  require_sse_writer.writeErrorResponse(res, status, JSON.stringify(response));
309
380
  return;
310
381
  }
382
+ if (require_helpers.isContentWithToolCallsResponse(response)) {
383
+ const journalEntry = journal.add({
384
+ method: req.method ?? "POST",
385
+ path: urlPath,
386
+ headers: require_helpers.flattenHeaders(req.headers),
387
+ body: completionReq,
388
+ response: {
389
+ status: 200,
390
+ fixture
391
+ }
392
+ });
393
+ if (!streaming) {
394
+ const body = buildOllamaChatContentWithToolCallsResponse(response.content, response.toolCalls, completionReq.model, logger);
395
+ res.writeHead(200, { "Content-Type": "application/json" });
396
+ res.end(JSON.stringify(body));
397
+ } else {
398
+ const chunks = buildOllamaChatContentWithToolCallsChunks(response.content, response.toolCalls, completionReq.model, chunkSize, logger);
399
+ const interruption = require_interruption.createInterruptionSignal(fixture);
400
+ if (!await require_ndjson_writer.writeNDJSONStream(res, chunks, {
401
+ latency,
402
+ streamingProfile: fixture.streamingProfile,
403
+ signal: interruption?.signal,
404
+ onChunkSent: interruption?.tick
405
+ })) {
406
+ if (!res.writableEnded) res.destroy();
407
+ journalEntry.response.interrupted = true;
408
+ journalEntry.response.interruptReason = interruption?.reason();
409
+ }
410
+ interruption?.cleanup();
411
+ }
412
+ return;
413
+ }
311
414
  if (require_helpers.isTextResponse(response)) {
312
415
  const journalEntry = journal.add({
313
416
  method: req.method ?? "POST",
@@ -437,10 +540,10 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
437
540
  path: urlPath,
438
541
  headers: require_helpers.flattenHeaders(req.headers),
439
542
  body: completionReq
440
- }, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
543
+ }, defaults.registry, defaults.logger)) return;
441
544
  if (!fixture) {
442
545
  if (defaults.record) {
443
- if (await require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw) !== "not_configured") {
546
+ if (await require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw)) {
444
547
  journal.add({
445
548
  method: req.method ?? "POST",
446
549
  path: urlPath,
@@ -448,7 +551,8 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
448
551
  body: completionReq,
449
552
  response: {
450
553
  status: res.statusCode ?? 200,
451
- fixture: null
554
+ fixture: null,
555
+ source: "proxy"
452
556
  }
453
557
  });
454
558
  return;
@@ -524,6 +628,23 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
524
628
  }
525
629
  return;
526
630
  }
631
+ if (require_helpers.isToolCallResponse(response) || require_helpers.isContentWithToolCallsResponse(response)) {
632
+ journal.add({
633
+ method: req.method ?? "POST",
634
+ path: urlPath,
635
+ headers: require_helpers.flattenHeaders(req.headers),
636
+ body: completionReq,
637
+ response: {
638
+ status: 400,
639
+ fixture
640
+ }
641
+ });
642
+ require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
643
+ message: "Tool call fixtures are not supported on /api/generate — use /api/chat instead",
644
+ type: "invalid_request_error"
645
+ } }));
646
+ return;
647
+ }
527
648
  journal.add({
528
649
  method: req.method ?? "POST",
529
650
  path: urlPath,
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.cjs","names":["flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isTextResponse","createInterruptionSignal","writeNDJSONStream","isToolCallResponse"],"sources":["../src/ollama.ts"],"sourcesContent":["/**\n * Ollama API endpoint support.\n *\n * Translates incoming /api/chat and /api/generate requests into the\n * ChatCompletionRequest format used by the fixture router, and converts\n * fixture responses back into Ollama's NDJSON streaming or non-streaming format.\n *\n * Key differences from OpenAI:\n * - Ollama defaults to stream: true (opposite of OpenAI)\n * - Streaming uses NDJSON, not SSE\n * - Tool call arguments are objects, not JSON strings\n * - Tool calls have no id field\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n isTextResponse,\n isToolCallResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport { writeNDJSONStream } from \"./ndjson-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Ollama request types ────────────────────────────────────────────────────\n\ninterface OllamaMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n}\n\ninterface OllamaToolDef {\n type: string;\n function: {\n name: string;\n description?: string;\n parameters?: object;\n };\n}\n\ninterface OllamaRequest {\n model: string;\n messages: OllamaMessage[];\n stream?: boolean; // default true!\n options?: { temperature?: number; num_predict?: number };\n tools?: OllamaToolDef[];\n}\n\ninterface OllamaGenerateRequest {\n model: string;\n prompt: string;\n stream?: boolean; // default true!\n options?: { temperature?: number; num_predict?: number };\n}\n\n// ─── Duration fields (zeroed, required on final/non-streaming responses) ────\n\nconst DURATION_FIELDS = {\n done_reason: \"stop\" as const,\n total_duration: 0,\n load_duration: 0,\n prompt_eval_count: 0,\n prompt_eval_duration: 0,\n eval_count: 0,\n eval_duration: 0,\n};\n\n// ─── Input conversion: Ollama → ChatCompletionRequest ────────────────────────\n\nexport function ollamaToCompletionRequest(req: OllamaRequest): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n for (const msg of req.messages) {\n messages.push({\n role: msg.role as ChatMessage[\"role\"],\n content: msg.content,\n });\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.function.name,\n description: t.function.description,\n parameters: t.function.parameters,\n },\n }));\n }\n\n return {\n model: req.model,\n messages,\n stream: req.stream,\n temperature: req.options?.temperature,\n max_tokens: req.options?.num_predict,\n tools,\n };\n}\n\nfunction ollamaGenerateToCompletionRequest(req: OllamaGenerateRequest): ChatCompletionRequest {\n return {\n model: req.model,\n messages: [{ role: \"user\", content: req.prompt }],\n stream: req.stream,\n temperature: req.options?.temperature,\n max_tokens: req.options?.num_predict,\n };\n}\n\n// ─── Response builders: /api/chat ────────────────────────────────────────────\n\nfunction buildOllamaChatTextChunks(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n): object[] {\n const chunks: object[] = [];\n\n // Reasoning chunks (before content)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\", reasoning_content: slice },\n done: false,\n });\n }\n }\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n model,\n message: { role: \"assistant\", content: slice },\n done: false,\n });\n }\n\n // Final chunk with done: true and all duration fields\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\" },\n done: true,\n ...DURATION_FIELDS,\n });\n\n return chunks;\n}\n\nfunction buildOllamaChatTextResponse(content: string, model: string, reasoning?: string): object {\n return {\n model,\n message: {\n role: \"assistant\",\n content,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n },\n done: true,\n ...DURATION_FIELDS,\n };\n}\n\nfunction buildOllamaChatToolCallChunks(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object[] {\n const ollamaToolCalls = toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n function: {\n name: tc.name,\n arguments: argsObj,\n },\n };\n });\n\n // Tool calls are sent in a single chunk (no streaming of individual args)\n const chunks: object[] = [];\n chunks.push({\n model,\n message: {\n role: \"assistant\",\n content: \"\",\n tool_calls: ollamaToolCalls,\n },\n done: false,\n });\n\n // Final chunk\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\" },\n done: true,\n ...DURATION_FIELDS,\n });\n\n return chunks;\n}\n\nfunction buildOllamaChatToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n const ollamaToolCalls = toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n function: {\n name: tc.name,\n arguments: argsObj,\n },\n };\n });\n\n return {\n model,\n message: {\n role: \"assistant\",\n content: \"\",\n tool_calls: ollamaToolCalls,\n },\n done: true,\n ...DURATION_FIELDS,\n };\n}\n\n// ─── Response builders: /api/generate ────────────────────────────────────────\n\nfunction buildOllamaGenerateTextChunks(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n): object[] {\n const chunks: object[] = [];\n const createdAt = new Date().toISOString();\n\n // Reasoning chunks (before content)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n model,\n created_at: createdAt,\n response: \"\",\n reasoning_content: slice,\n done: false,\n });\n }\n }\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n model,\n created_at: createdAt,\n response: slice,\n done: false,\n });\n }\n\n // Final chunk\n chunks.push({\n model,\n created_at: createdAt,\n response: \"\",\n done: true,\n ...DURATION_FIELDS,\n context: [],\n });\n\n return chunks;\n}\n\nfunction buildOllamaGenerateTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n): object {\n return {\n model,\n created_at: new Date().toISOString(),\n response: content,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n done: true,\n ...DURATION_FIELDS,\n context: [],\n };\n}\n\n// ─── Request handler: /api/chat ──────────────────────────────────────────────\n\nexport async function handleOllama(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? \"/api/chat\";\n\n let ollamaReq: OllamaRequest;\n try {\n ollamaReq = JSON.parse(raw) as OllamaRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!ollamaReq.messages || !Array.isArray(ollamaReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = ollamaToCompletionRequest(ollamaReq);\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: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"ollama\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null },\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 logger.error(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\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 },\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 // Ollama defaults to streaming when stream is absent or true\n const streaming = ollamaReq.stream !== false;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaChatTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaChatTextChunks(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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 journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaChatToolCallResponse(response.toolCalls, completionReq.model, logger);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaChatToolCallChunks(response.toolCalls, completionReq.model, logger);\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n\n// ─── Request handler: /api/generate ──────────────────────────────────────────\n\nexport async function handleOllamaGenerate(\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 const urlPath = req.url ?? \"/api/generate\";\n\n let generateReq: OllamaGenerateRequest;\n try {\n generateReq = JSON.parse(raw) as OllamaGenerateRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!generateReq.prompt || typeof generateReq.prompt !== \"string\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: prompt field is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = ollamaGenerateToCompletionRequest(generateReq);\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: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"ollama\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null },\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(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\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 },\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 // Ollama defaults to streaming when stream is absent or true\n const streaming = generateReq.stream !== false;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response (only type supported for /api/generate)\n if (isTextResponse(response)) {\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaGenerateTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaGenerateTextChunks(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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 responses not supported for /api/generate — fall through to error\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ollama.cjs","names":["flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isContentWithToolCallsResponse","createInterruptionSignal","writeNDJSONStream","isTextResponse","isToolCallResponse"],"sources":["../src/ollama.ts"],"sourcesContent":["/**\n * Ollama API endpoint support.\n *\n * Translates incoming /api/chat and /api/generate requests into the\n * ChatCompletionRequest format used by the fixture router, and converts\n * fixture responses back into Ollama's NDJSON streaming or non-streaming format.\n *\n * Key differences from OpenAI:\n * - Ollama defaults to stream: true (opposite of OpenAI)\n * - Streaming uses NDJSON, not SSE\n * - Tool call arguments are objects, not JSON strings\n * - Tool calls have no id field\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport { writeNDJSONStream } from \"./ndjson-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Ollama request types ────────────────────────────────────────────────────\n\ninterface OllamaMessage {\n role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n content: string;\n}\n\ninterface OllamaToolDef {\n type: string;\n function: {\n name: string;\n description?: string;\n parameters?: object;\n };\n}\n\ninterface OllamaRequest {\n model: string;\n messages: OllamaMessage[];\n stream?: boolean; // default true!\n options?: { temperature?: number; num_predict?: number };\n tools?: OllamaToolDef[];\n}\n\ninterface OllamaGenerateRequest {\n model: string;\n prompt: string;\n stream?: boolean; // default true!\n options?: { temperature?: number; num_predict?: number };\n}\n\n// ─── Duration fields (zeroed, required on final/non-streaming responses) ────\n\nconst DURATION_FIELDS = {\n done_reason: \"stop\" as const,\n total_duration: 0,\n load_duration: 0,\n prompt_eval_count: 0,\n prompt_eval_duration: 0,\n eval_count: 0,\n eval_duration: 0,\n};\n\n// ─── Input conversion: Ollama → ChatCompletionRequest ────────────────────────\n\nexport function ollamaToCompletionRequest(req: OllamaRequest): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n for (const msg of req.messages) {\n messages.push({\n role: msg.role as ChatMessage[\"role\"],\n content: msg.content,\n });\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.function.name,\n description: t.function.description,\n parameters: t.function.parameters,\n },\n }));\n }\n\n return {\n model: req.model,\n messages,\n stream: req.stream ?? true,\n temperature: req.options?.temperature,\n max_tokens: req.options?.num_predict,\n tools,\n };\n}\n\nfunction ollamaGenerateToCompletionRequest(req: OllamaGenerateRequest): ChatCompletionRequest {\n return {\n model: req.model,\n messages: [{ role: \"user\", content: req.prompt }],\n stream: req.stream ?? true,\n temperature: req.options?.temperature,\n max_tokens: req.options?.num_predict,\n };\n}\n\n// ─── Response builders: /api/chat ────────────────────────────────────────────\n\nfunction buildOllamaChatTextChunks(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n): object[] {\n const chunks: object[] = [];\n\n // Reasoning chunks (before content)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\", reasoning_content: slice },\n done: false,\n });\n }\n }\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n model,\n message: { role: \"assistant\", content: slice },\n done: false,\n });\n }\n\n // Final chunk with done: true and all duration fields\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\" },\n done: true,\n ...DURATION_FIELDS,\n });\n\n return chunks;\n}\n\nfunction buildOllamaChatTextResponse(content: string, model: string, reasoning?: string): object {\n return {\n model,\n message: {\n role: \"assistant\",\n content,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n },\n done: true,\n ...DURATION_FIELDS,\n };\n}\n\nfunction buildOllamaChatToolCallChunks(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object[] {\n const ollamaToolCalls = toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n function: {\n name: tc.name,\n arguments: argsObj,\n },\n };\n });\n\n // Tool calls are sent in a single chunk (no streaming of individual args)\n const chunks: object[] = [];\n chunks.push({\n model,\n message: {\n role: \"assistant\",\n content: \"\",\n tool_calls: ollamaToolCalls,\n },\n done: false,\n });\n\n // Final chunk\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\" },\n done: true,\n ...DURATION_FIELDS,\n });\n\n return chunks;\n}\n\nfunction buildOllamaChatToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n const ollamaToolCalls = toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n function: {\n name: tc.name,\n arguments: argsObj,\n },\n };\n });\n\n return {\n model,\n message: {\n role: \"assistant\",\n content: \"\",\n tool_calls: ollamaToolCalls,\n },\n done: true,\n ...DURATION_FIELDS,\n };\n}\n\n// ─── Response builders: /api/chat — content + tool calls ────────────────────\n\nfunction buildOllamaChatContentWithToolCallsChunks(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n logger: Logger,\n): object[] {\n const chunks: object[] = [];\n\n // Content chunks first\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n model,\n message: { role: \"assistant\", content: slice },\n done: false,\n });\n }\n\n // Tool calls in a single chunk (same as tool-call-only path)\n const ollamaToolCalls = toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n function: {\n name: tc.name,\n arguments: argsObj,\n },\n };\n });\n\n chunks.push({\n model,\n message: {\n role: \"assistant\",\n content: \"\",\n tool_calls: ollamaToolCalls,\n },\n done: false,\n });\n\n // Final chunk\n chunks.push({\n model,\n message: { role: \"assistant\", content: \"\" },\n done: true,\n ...DURATION_FIELDS,\n });\n\n return chunks;\n}\n\nfunction buildOllamaChatContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n const ollamaToolCalls = toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n function: {\n name: tc.name,\n arguments: argsObj,\n },\n };\n });\n\n return {\n model,\n message: {\n role: \"assistant\",\n content,\n tool_calls: ollamaToolCalls,\n },\n done: true,\n ...DURATION_FIELDS,\n };\n}\n\n// ─── Response builders: /api/generate ────────────────────────────────────────\n\nfunction buildOllamaGenerateTextChunks(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n): object[] {\n const chunks: object[] = [];\n const createdAt = new Date().toISOString();\n\n // Reasoning chunks (before content)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n model,\n created_at: createdAt,\n response: \"\",\n reasoning_content: slice,\n done: false,\n });\n }\n }\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n model,\n created_at: createdAt,\n response: slice,\n done: false,\n });\n }\n\n // Final chunk\n chunks.push({\n model,\n created_at: createdAt,\n response: \"\",\n done: true,\n ...DURATION_FIELDS,\n context: [],\n });\n\n return chunks;\n}\n\nfunction buildOllamaGenerateTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n): object {\n return {\n model,\n created_at: new Date().toISOString(),\n response: content,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n done: true,\n ...DURATION_FIELDS,\n context: [],\n };\n}\n\n// ─── Request handler: /api/chat ──────────────────────────────────────────────\n\nexport async function handleOllama(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? \"/api/chat\";\n\n let ollamaReq: OllamaRequest;\n try {\n ollamaReq = JSON.parse(raw) as OllamaRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!ollamaReq.messages || !Array.isArray(ollamaReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = ollamaToCompletionRequest(ollamaReq);\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: urlPath,\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 \"ollama\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\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 logger.error(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\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 },\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 // Ollama defaults to streaming when stream is absent or true\n const streaming = ollamaReq.stream !== false;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Content + tool calls response (must be checked before text/tool-only branches)\n if (isContentWithToolCallsResponse(response)) {\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaChatContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n completionReq.model,\n logger,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaChatContentWithToolCallsChunks(\n response.content,\n response.toolCalls,\n completionReq.model,\n chunkSize,\n logger,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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 journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaChatTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaChatTextChunks(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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 journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaChatToolCallResponse(response.toolCalls, completionReq.model, logger);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaChatToolCallChunks(response.toolCalls, completionReq.model, logger);\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n\n// ─── Request handler: /api/generate ──────────────────────────────────────────\n\nexport async function handleOllamaGenerate(\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 const urlPath = req.url ?? \"/api/generate\";\n\n let generateReq: OllamaGenerateRequest;\n try {\n generateReq = JSON.parse(raw) as OllamaGenerateRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!generateReq.prompt || typeof generateReq.prompt !== \"string\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: prompt field is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = ollamaGenerateToCompletionRequest(generateReq);\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: urlPath,\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 \"ollama\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\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(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\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 },\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 // Ollama defaults to streaming when stream is absent or true\n const streaming = generateReq.stream !== false;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response (only type supported for /api/generate)\n if (isTextResponse(response)) {\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (!streaming) {\n const body = buildOllamaGenerateTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const chunks = buildOllamaGenerateTextChunks(\n response.content,\n completionReq.model,\n chunkSize,\n response.reasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeNDJSONStream(res, chunks, {\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 fixtures matched but not supported on /api/generate\n if (isToolCallResponse(response) || isContentWithToolCallsResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 400, fixture },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Tool call fixtures are not supported on /api/generate — use /api/chat instead\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.d.cts","names":[],"sources":["../src/ollama.ts"],"sourcesContent":[],"mappings":";;;;;;UAyCU,aAAA,CA2C0E;EAqP9D,IAAA,EAAA,QAAA,GAAY,MAAA,GAAA,WAAA,GAAA,MAAA;EAAA,OAAA,EAAA,MAAA;;UA3RxB,aAAA,CA6RE;MAEA,EAAA,MAAA;UACD,EAAA;IACC,IAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;IAC1B,UAAA,CAAA,EAAA,MAAA;EAAO,CAAA;AA6PV;UAvhBU,aAAA,CAuhBgC;OACnC,EAAA,MAAK;UACA,EAvhBA,aAuhBA,EAAA;QAEA,CAAA,EAAA,OAAA;SACD,CAAA,EAAA;IACC,WAAA,CAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;;EACnB,KAAA,CAAA,EA1hBA,aA0hBA,EAAA;;iBAlgBM,yBAAA,MAA+B,gBAAgB;iBAqPzC,YAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBA6PmB,oBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
1
+ {"version":3,"file":"ollama.d.cts","names":[],"sources":["../src/ollama.ts"],"sourcesContent":[],"mappings":";;;;;;UA0CU,aAAA,CA2C0E;EAsV9D,IAAA,EAAA,QAAA,GAAY,MAAA,GAAA,WAAA,GAAA,MAAA;EAAA,OAAA,EAAA,MAAA;;UA5XxB,aAAA,CA8XE;MAEA,EAAA,MAAA;UACD,EAAA;IACC,IAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;IAC1B,UAAA,CAAA,EAAA,MAAA;EAAO,CAAA;AAuSV;UAlqBU,aAAA,CAkqBgC;OACnC,EAAA,MAAK;UACA,EAlqBA,aAkqBA,EAAA;QAEA,CAAA,EAAA,OAAA;SACD,CAAA,EAAA;IACC,WAAA,CAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;;EACnB,KAAA,CAAA,EArqBA,aAqqBA,EAAA;;iBA7oBM,yBAAA,MAA+B,gBAAgB;iBAsVzC,YAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBAuSmB,oBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.d.ts","names":[],"sources":["../src/ollama.ts"],"sourcesContent":[],"mappings":";;;;;;UAyCU,aAAA,CA2C0E;EAqP9D,IAAA,EAAA,QAAA,GAAY,MAAA,GAAA,WAAA,GAAA,MAAA;EAAA,OAAA,EAAA,MAAA;;UA3RxB,aAAA,CA6RE;MAEA,EAAA,MAAA;UACD,EAAA;IACC,IAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;IAC1B,UAAA,CAAA,EAAA,MAAA;EAAO,CAAA;AA6PV;UAvhBU,aAAA,CAuhBgC;OACnC,EAAA,MAAK;UACA,EAvhBA,aAuhBA,EAAA;QAEA,CAAA,EAAA,OAAA;SACD,CAAA,EAAA;IACC,WAAA,CAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;;EACnB,KAAA,CAAA,EA1hBA,aA0hBA,EAAA;;iBAlgBM,yBAAA,MAA+B,gBAAgB;iBAqPzC,YAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBA6PmB,oBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
1
+ {"version":3,"file":"ollama.d.ts","names":[],"sources":["../src/ollama.ts"],"sourcesContent":[],"mappings":";;;;;;UA0CU,aAAA,CA2C0E;EAsV9D,IAAA,EAAA,QAAA,GAAY,MAAA,GAAA,WAAA,GAAA,MAAA;EAAA,OAAA,EAAA,MAAA;;UA5XxB,aAAA,CA8XE;MAEA,EAAA,MAAA;UACD,EAAA;IACC,IAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;IAC1B,UAAA,CAAA,EAAA,MAAA;EAAO,CAAA;AAuSV;UAlqBU,aAAA,CAkqBgC;OACnC,EAAA,MAAK;UACA,EAlqBA,aAkqBA,EAAA;QAEA,CAAA,EAAA,OAAA;SACD,CAAA,EAAA;IACC,WAAA,CAAA,EAAA,MAAA;IACY,WAAK,CAAA,EAAA,MAAA;;EACnB,KAAA,CAAA,EArqBA,aAqqBA,EAAA;;iBA7oBM,yBAAA,MAA+B,gBAAgB;iBAsVzC,YAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBAuSmB,oBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}