@copilotkit/aimock 1.34.0 → 1.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +22 -0
- package/README.md +2 -1
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/bedrock-converse.cjs +110 -8
- package/dist/bedrock-converse.cjs.map +1 -1
- package/dist/bedrock-converse.d.cts.map +1 -1
- package/dist/bedrock-converse.d.ts.map +1 -1
- package/dist/bedrock-converse.js +111 -9
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +141 -4
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts.map +1 -1
- package/dist/bedrock.d.ts.map +1 -1
- package/dist/bedrock.js +142 -5
- package/dist/bedrock.js.map +1 -1
- package/dist/cohere.cjs +89 -7
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +90 -8
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/fixture-loader.cjs +121 -20
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +121 -20
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-interactions.cjs +97 -60
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +98 -61
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +71 -6
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.d.cts.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +72 -7
- package/dist/gemini.js.map +1 -1
- package/dist/grok-video.cjs +834 -0
- package/dist/grok-video.cjs.map +1 -0
- package/dist/grok-video.d.cts +74 -0
- package/dist/grok-video.d.cts.map +1 -0
- package/dist/grok-video.d.ts +74 -0
- package/dist/grok-video.d.ts.map +1 -0
- package/dist/grok-video.js +829 -0
- package/dist/grok-video.js.map +1 -0
- package/dist/helpers.cjs +181 -2
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +33 -3
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +33 -3
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +181 -3
- package/dist/helpers.js.map +1 -1
- package/dist/index.cjs +11 -0
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/messages.cjs +99 -10
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.d.cts.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +100 -11
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +11 -1
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +8 -1
- package/dist/metrics.js.map +1 -1
- package/dist/ollama.cjs +74 -4
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +75 -5
- package/dist/ollama.js.map +1 -1
- package/dist/openrouter-video.cjs +19 -138
- package/dist/openrouter-video.cjs.map +1 -1
- package/dist/openrouter-video.d.cts.map +1 -1
- package/dist/openrouter-video.d.ts.map +1 -1
- package/dist/openrouter-video.js +1 -120
- package/dist/openrouter-video.js.map +1 -1
- package/dist/recorder.cjs +36 -20
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.js +36 -20
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +136 -58
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts +2 -2
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts +2 -2
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +137 -59
- package/dist/responses.js.map +1 -1
- package/dist/server.cjs +162 -20
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +4 -0
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +164 -22
- package/dist/server.js.map +1 -1
- package/dist/stream-collapse.cjs +300 -74
- package/dist/stream-collapse.cjs.map +1 -1
- package/dist/stream-collapse.d.cts +17 -1
- package/dist/stream-collapse.d.cts.map +1 -1
- package/dist/stream-collapse.d.ts +17 -1
- package/dist/stream-collapse.d.ts.map +1 -1
- package/dist/stream-collapse.js +300 -74
- package/dist/stream-collapse.js.map +1 -1
- package/dist/types.d.cts +104 -7
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +104 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-types.d.cts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/dist/veo-video.cjs +794 -0
- package/dist/veo-video.cjs.map +1 -0
- package/dist/veo-video.d.cts +50 -0
- package/dist/veo-video.d.cts.map +1 -0
- package/dist/veo-video.d.ts +50 -0
- package/dist/veo-video.d.ts.map +1 -0
- package/dist/veo-video.js +789 -0
- package/dist/veo-video.js.map +1 -0
- package/dist/video-proxy-shared.cjs +145 -0
- package/dist/video-proxy-shared.cjs.map +1 -0
- package/dist/video-proxy-shared.js +140 -0
- package/dist/video-proxy-shared.js.map +1 -0
- package/dist/ws-gemini-live.cjs +96 -3
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +97 -4
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +281 -4
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +282 -5
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +1 -1
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.js +1 -1
- package/dist/ws-responses.js.map +1 -1
- package/fixtures/examples/llm/blocks-tool-first.json +13 -0
- package/package.json +1 -1
- package/skills/write-fixtures/SKILL.md +19 -1
package/dist/cohere.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cohere.js","names":[],"sources":["../src/cohere.ts"],"sourcesContent":["/**\n * Cohere v2 Chat API endpoint support.\n *\n * Translates incoming /v2/chat requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * Cohere's typed SSE streaming (or non-streaming) format.\n *\n * Cohere uses typed SSE events (event: + data: lines), similar to the\n * Claude Messages handler in messages.ts.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n RecordedTimings,\n ResponseOverrides,\n StreamingProfile,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateMessageId,\n generateToolCallId,\n generateDeterministicEmbedding,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isEmbeddingResponse,\n isErrorResponse,\n serializeErrorResponse,\n flattenHeaders,\n getTestId,\n resolveResponse,\n resolveStrictMode,\n resolveReasoningForModel,\n strictOverrideField,\n getContext,\n strictNoMatchMessage,\n strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { matchFixtureDiagnostic, recordMatchOptions } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Cohere v2 Chat request types ───────────────────────────────────────────\n\ninterface CohereToolCallDef {\n id?: string;\n type: string;\n function: {\n name: string;\n arguments: string;\n };\n}\n\ninterface CohereContentPart {\n type: string;\n text?: string;\n}\n\ninterface CohereMessage {\n role: \"user\" | \"assistant\" | \"system\" | \"tool\";\n content: string | CohereContentPart[];\n tool_call_id?: string;\n tool_calls?: CohereToolCallDef[];\n}\n\n// OpenAI-style tool definition (wrapped in { type: \"function\", function: { ... } })\ninterface CohereToolDefOpenAI {\n type: string;\n function: {\n name: string;\n description?: string;\n parameters?: object;\n };\n}\n\n// Cohere v2 native tool definition (flat: { name, description, parameter_definitions })\ninterface CohereToolDefNative {\n name: string;\n description?: string;\n parameter_definitions?: object;\n}\n\ntype CohereToolDef = CohereToolDefOpenAI | CohereToolDefNative;\n\ninterface CohereRequest {\n model: string;\n messages: CohereMessage[];\n stream?: boolean;\n tools?: CohereToolDef[];\n response_format?: { type: string; json_schema?: object };\n temperature?: number;\n max_tokens?: number;\n}\n\n// ─── Cohere SSE event types ─────────────────────────────────────────────────\n\ninterface CohereSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\n// ─── Zero-value usage block ─────────────────────────────────────────────────\n\nconst ZERO_USAGE = {\n billed_units: { input_tokens: 0, output_tokens: 0, search_units: 0, classifications: 0 },\n tokens: { input_tokens: 0, output_tokens: 0 },\n};\n\n// ─── Cohere finish reason / usage mapping ──────────────────────────────────\n\nfunction cohereFinishReason(\n overrideFinishReason: string | undefined,\n defaultReason: string,\n): string {\n if (!overrideFinishReason) return defaultReason;\n if (overrideFinishReason === \"stop\") return \"COMPLETE\";\n if (overrideFinishReason === \"tool_calls\") return \"TOOL_CALL\";\n if (overrideFinishReason === \"length\") return \"MAX_TOKENS\";\n return overrideFinishReason;\n}\n\nfunction cohereUsage(overrides?: ResponseOverrides): typeof ZERO_USAGE {\n if (!overrides?.usage) return ZERO_USAGE;\n const inputTokens = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;\n const outputTokens = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;\n return {\n billed_units: {\n input_tokens: inputTokens,\n output_tokens: outputTokens,\n search_units: 0,\n classifications: 0,\n },\n tokens: { input_tokens: inputTokens, output_tokens: outputTokens },\n };\n}\n\n// ─── Input conversion: Cohere → ChatCompletionRequest ───────────────────────\n\n/** Extract plain text from structured content (array of { type, text } parts) or passthrough string. */\nfunction extractTextContent(content: string | CohereContentPart[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((part) => part.type === \"text\" && part.text !== undefined)\n .map((part) => part.text!)\n .join(\"\");\n}\n\n/** Type guard: is this an OpenAI-style tool definition (has `function` key)? */\nfunction isOpenAIToolDef(t: CohereToolDef): t is CohereToolDefOpenAI {\n return \"function\" in t && typeof (t as CohereToolDefOpenAI).function === \"object\";\n}\n\nexport function cohereToCompletionRequest(req: CohereRequest): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n for (const msg of req.messages) {\n const textContent = extractTextContent(msg.content);\n if (msg.role === \"system\") {\n messages.push({ role: \"system\", content: textContent });\n } else if (msg.role === \"user\") {\n messages.push({ role: \"user\", content: textContent });\n } else if (msg.role === \"assistant\") {\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent || null,\n tool_calls: msg.tool_calls.map((tc) => ({\n id: tc.id ?? generateToolCallId(),\n type: \"function\" as const,\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent });\n }\n } else if (msg.role === \"tool\") {\n messages.push({\n role: \"tool\",\n content: textContent,\n tool_call_id: msg.tool_call_id,\n });\n }\n }\n\n // Convert tools — accept both OpenAI format and Cohere v2 native format\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => {\n if (isOpenAIToolDef(t)) {\n return {\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 // Cohere v2 native format: { name, description, parameter_definitions }\n return {\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameter_definitions,\n },\n };\n });\n }\n\n return {\n model: req.model,\n messages,\n stream: req.stream,\n tools,\n ...(req.response_format && { response_format: req.response_format }),\n ...(req.temperature !== undefined && { temperature: req.temperature }),\n ...(req.max_tokens !== undefined && { max_tokens: req.max_tokens }),\n };\n}\n\n// ─── Response building: fixture → Cohere v2 Chat format ─────────────────────\n\n// Non-streaming text response\nfunction buildCohereTextResponse(\n content: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: { type: string; text: string }[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"text\", text: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: overrides?.id ?? generateMessageId(),\n finish_reason: cohereFinishReason(overrides?.finishReason, \"COMPLETE\"),\n message: {\n role: \"assistant\",\n content: contentBlocks,\n tool_calls: [],\n tool_plan: \"\",\n citations: [],\n },\n usage: cohereUsage(overrides),\n };\n}\n\n// Non-streaming tool call response\nfunction buildCohereToolCallResponse(\n toolCalls: ToolCall[],\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const cohereCalls = toolCalls.map((tc) => {\n // Validate arguments JSON\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n return {\n id: tc.id || generateToolCallId(),\n type: \"function\",\n function: {\n name: tc.name,\n arguments: argsJson,\n },\n };\n });\n\n // Reasoning as a leading text block (Cohere has no native reasoning type)\n const contentBlocks: { type: string; text: string }[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"text\", text: reasoning });\n }\n\n return {\n id: overrides?.id ?? generateMessageId(),\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n message: {\n role: \"assistant\",\n content: contentBlocks,\n tool_calls: cohereCalls,\n tool_plan: \"\",\n citations: [],\n },\n usage: cohereUsage(overrides),\n };\n}\n\n// Non-streaming content + tool calls response\nfunction buildCohereContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const cohereCalls = toolCalls.map((tc) => {\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n return {\n id: tc.id || generateToolCallId(),\n type: \"function\",\n function: {\n name: tc.name,\n arguments: argsJson,\n },\n };\n });\n\n const contentBlocks: { type: string; text: string }[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"text\", text: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: overrides?.id ?? generateMessageId(),\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n message: {\n role: \"assistant\",\n content: contentBlocks,\n tool_calls: cohereCalls,\n tool_plan: \"\",\n citations: [],\n },\n usage: cohereUsage(overrides),\n };\n}\n\n// ─── Streaming event builders ───────────────────────────────────────────────\n\nfunction buildCohereTextStreamEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): CohereSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const events: CohereSSEEvent[] = [];\n\n // message-start\n events.push({\n id: msgId,\n type: \"message-start\",\n delta: {\n message: {\n role: \"assistant\",\n content: [],\n tool_plan: \"\",\n tool_calls: [],\n citations: [],\n },\n },\n });\n\n let contentIndex = 0;\n\n // Reasoning as a text block before main content (Cohere has no native reasoning type)\n if (reasoning) {\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\" } } },\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-delta\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\", text: slice } } },\n });\n }\n events.push({ type: \"content-end\", index: contentIndex });\n contentIndex++;\n }\n\n // content-start (type: \"text\" only, no text field)\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\" },\n },\n },\n });\n\n // content-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-delta\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\", text: slice },\n },\n },\n });\n }\n\n // content-end\n events.push({\n type: \"content-end\",\n index: contentIndex,\n });\n\n // message-end\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"COMPLETE\"),\n usage: cohereUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildCohereToolCallStreamEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): CohereSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const events: CohereSSEEvent[] = [];\n\n // message-start\n events.push({\n id: msgId,\n type: \"message-start\",\n delta: {\n message: {\n role: \"assistant\",\n content: [],\n tool_plan: \"\",\n tool_calls: [],\n citations: [],\n },\n },\n });\n\n // Reasoning as a text block before the tool plan (Cohere has no native reasoning type)\n if (reasoning) {\n events.push({\n type: \"content-start\",\n index: 0,\n delta: { message: { content: { type: \"text\" } } },\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-delta\",\n index: 0,\n delta: { message: { content: { type: \"text\", text: slice } } },\n });\n }\n events.push({ type: \"content-end\", index: 0 });\n }\n\n // tool-plan-delta\n events.push({\n type: \"tool-plan-delta\",\n delta: {\n message: {\n tool_plan: \"I will use the requested tool.\",\n },\n },\n });\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n\n // Validate arguments JSON\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n\n // tool-call-start\n events.push({\n type: \"tool-call-start\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n id: callId,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: \"\",\n },\n },\n },\n },\n });\n\n // tool-call-delta — chunked arguments\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"tool-call-delta\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n function: {\n arguments: slice,\n },\n },\n },\n },\n });\n }\n\n // tool-call-end\n events.push({\n type: \"tool-call-end\",\n index: idx,\n });\n }\n\n // message-end\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n usage: cohereUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildCohereContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): CohereSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const events: CohereSSEEvent[] = [];\n\n // message-start\n events.push({\n id: msgId,\n type: \"message-start\",\n delta: {\n message: {\n role: \"assistant\",\n content: [],\n tool_plan: \"\",\n tool_calls: [],\n citations: [],\n },\n },\n });\n\n let contentIndex = 0;\n\n // Reasoning as a text block before main content\n if (reasoning) {\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\" } } },\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-delta\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\", text: slice } } },\n });\n }\n events.push({ type: \"content-end\", index: contentIndex });\n contentIndex++;\n }\n\n // content-start (type: \"text\" only, no text field)\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\" },\n },\n },\n });\n\n // content-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-delta\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\", text: slice },\n },\n },\n });\n }\n\n // content-end\n events.push({\n type: \"content-end\",\n index: contentIndex,\n });\n\n // tool-plan-delta\n events.push({\n type: \"tool-plan-delta\",\n delta: {\n message: {\n tool_plan: \"I will use the requested tool.\",\n },\n },\n });\n\n // Tool call events\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n\n // tool-call-start\n events.push({\n type: \"tool-call-start\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n id: callId,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: \"\",\n },\n },\n },\n },\n });\n\n // tool-call-delta — chunked arguments\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"tool-call-delta\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n function: {\n arguments: slice,\n },\n },\n },\n },\n });\n }\n\n // tool-call-end\n events.push({\n type: \"tool-call-end\",\n index: idx,\n });\n }\n\n // message-end\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n usage: cohereUsage(overrides),\n },\n });\n\n return events;\n}\n\n// ─── SSE writer for Cohere typed events ─────────────────────────────────────\n\ninterface CohereStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n recordedTimings?: RecordedTimings;\n replaySpeed?: number;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeCohereSSEStream(\n res: http.ServerResponse,\n events: CohereSSEEvent[],\n optionsOrLatency?: number | CohereStreamOptions,\n): Promise<boolean> {\n const opts: CohereStreamOptions =\n typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n const latency = opts.latency ?? 0;\n const profile = opts.streamingProfile;\n const { recordedTimings, replaySpeed } = opts;\n const signal = opts.signal;\n const onChunkSent = opts.onChunkSent;\n\n if (res.writableEnded) return true;\n res.setHeader(\"Content-Type\", \"text/event-stream\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n\n let chunkIndex = 0;\n for (const event of events) {\n const chunkDelay = calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);\n if (chunkDelay > 0) await delay(chunkDelay, signal);\n if (signal?.aborted) return false;\n if (res.writableEnded) return true;\n 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 handleCohere(\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 cohereReq: CohereRequest;\n try {\n cohereReq = JSON.parse(raw) as CohereRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON body: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Validate required model field\n if (!cohereReq.model) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\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: \"model is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!cohereReq.messages || !Array.isArray(cohereReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\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 = cohereToCompletionRequest(cohereReq);\n completionReq._endpointType = \"chat\";\n completionReq._context = getContext(req);\n\n const testId = getTestId(req);\n const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n // Record mode proxies on a miss to capture a fresh turn (see record gate\n // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n // shadowing a longer request and skipping the new turn's recording.\n recordMatchOptions(!!defaults.record, defaults.logger),\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n if (effectiveStrict) {\n const strictStatus = 503;\n const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n logger.error(\n strictNoMatchLogLine(req.method ?? \"POST\", req.url ?? \"/v2/chat\", skippedBySequenceOrTurn),\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"cohere\",\n req.url ?? \"/v2/chat\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: 404,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 404,\n JSON.stringify({\n error: {\n message: \"No fixture matched\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\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 ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, serializeErrorResponse(response), {\n retryAfter: response.retryAfter,\n });\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 Cohere v2 Chat API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n cohereReq.model,\n effectiveStrict,\n logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (cohereReq.stream !== true) {\n const body = buildCohereContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n logger,\n effReasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildCohereContentWithToolCallsStreamEvents(\n response.content,\n response.toolCalls,\n chunkSize,\n logger,\n effReasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeCohereSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n cohereReq.model,\n effectiveStrict,\n logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (cohereReq.stream !== true) {\n const body = buildCohereTextResponse(response.content, effReasoning, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildCohereTextStreamEvents(\n response.content,\n chunkSize,\n effReasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeCohereSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n cohereReq.model,\n effectiveStrict,\n logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (cohereReq.stream !== true) {\n const body = buildCohereToolCallResponse(response.toolCalls, logger, effReasoning, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildCohereToolCallStreamEvents(\n response.toolCalls,\n chunkSize,\n logger,\n effReasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeCohereSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\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// ─── Cohere v2 Embed API types ────────────────────────────────────────────\n\ninterface CohereEmbedRequest {\n texts: string[];\n model: string;\n input_type?: string;\n embedding_types?: string[];\n truncate?: string;\n}\n\ninterface CohereEmbedResponse {\n id: string;\n texts: string[];\n embeddings: Record<string, number[][]>;\n meta: { api_version: { version: string } };\n}\n\n// ─── Cohere Embed handler ─────────────────────────────────────────────────\n\nexport async function handleCohereEmbed(\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 embedReq: CohereEmbedRequest;\n try {\n embedReq = JSON.parse(raw) as CohereEmbedRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON body: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Validate required fields\n if (!embedReq.model) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\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: \"model is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!embedReq.texts || !Array.isArray(embedReq.texts)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\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: texts array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Concatenate all texts for fixture matching\n const combinedInput = embedReq.texts.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router\n const syntheticReq: ChatCompletionRequest = {\n model: embedReq.model,\n messages: [],\n embeddingInput: combinedInput,\n _endpointType: \"embedding\",\n _context: getContext(req),\n };\n\n const testId = getTestId(req);\n const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n // Record mode proxies on a miss to capture a fresh turn (see record gate\n // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n // shadowing a longer request and skipping the new turn's recording.\n recordMatchOptions(!!defaults.record, defaults.logger),\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n // Determine requested embedding types (default to float)\n const embeddingTypes =\n embedReq.embedding_types && embedReq.embedding_types.length > 0\n ? embedReq.embedding_types\n : [\"float\"];\n\n if (fixture) {\n const response = await resolveResponse(fixture, syntheticReq);\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 ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, serializeErrorResponse(response), {\n retryAfter: response.retryAfter,\n });\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input text\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const vectors = embedReq.texts.map(() => [...response.embedding]);\n const embeddings: Record<string, number[][]> = {};\n for (const t of embeddingTypes) {\n embeddings[t] = vectors;\n }\n const body: CohereEmbedResponse = {\n id: generateMessageId(),\n texts: embedReq.texts,\n embeddings,\n meta: { api_version: { version: \"2\" } },\n };\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — check strict mode\n if (resolveStrictMode(defaults.strict, req.headers)) {\n const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n logger.error(\n strictNoMatchLogLine(req.method ?? \"POST\", req.url ?? \"/v2/embed\", skippedBySequenceOrTurn),\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: {\n status: 503,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Try record-and-replay proxy\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"cohere\",\n req.url ?? \"/v2/embed\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n\n // No fixture match — generate deterministic embeddings from input texts\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = 1024; // Cohere embed-v4.0 default\n const vectors = embedReq.texts.map((text) => generateDeterministicEmbedding(text, dimensions));\n const embeddings: Record<string, number[][]> = {};\n for (const t of embeddingTypes) {\n embeddings[t] = vectors;\n }\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body: CohereEmbedResponse = {\n id: generateMessageId(),\n texts: embedReq.texts,\n embeddings,\n meta: { api_version: { version: \"2\" } },\n };\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cohere.js","names":[],"sources":["../src/cohere.ts"],"sourcesContent":["/**\n * Cohere v2 Chat API endpoint support.\n *\n * Translates incoming /v2/chat requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * Cohere's typed SSE streaming (or non-streaming) format.\n *\n * Cohere uses typed SSE events (event: + data: lines), similar to the\n * Claude Messages handler in messages.ts.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n FixtureBlock,\n HandlerDefaults,\n RecordedTimings,\n ResponseOverrides,\n StreamingProfile,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateMessageId,\n generateToolCallId,\n generateDeterministicEmbedding,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isEmbeddingResponse,\n isErrorResponse,\n serializeErrorResponse,\n flattenHeaders,\n getTestId,\n resolveFixtureBlocks,\n resolveResponse,\n resolveStrictMode,\n resolveReasoningForModel,\n strictOverrideField,\n getContext,\n strictNoMatchMessage,\n strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { matchFixtureDiagnostic, recordMatchOptions } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Cohere v2 Chat request types ───────────────────────────────────────────\n\ninterface CohereToolCallDef {\n id?: string;\n type: string;\n function: {\n name: string;\n arguments: string;\n };\n}\n\ninterface CohereContentPart {\n type: string;\n text?: string;\n}\n\ninterface CohereMessage {\n role: \"user\" | \"assistant\" | \"system\" | \"tool\";\n content: string | CohereContentPart[];\n tool_call_id?: string;\n tool_calls?: CohereToolCallDef[];\n}\n\n// OpenAI-style tool definition (wrapped in { type: \"function\", function: { ... } })\ninterface CohereToolDefOpenAI {\n type: string;\n function: {\n name: string;\n description?: string;\n parameters?: object;\n };\n}\n\n// Cohere v2 native tool definition (flat: { name, description, parameter_definitions })\ninterface CohereToolDefNative {\n name: string;\n description?: string;\n parameter_definitions?: object;\n}\n\ntype CohereToolDef = CohereToolDefOpenAI | CohereToolDefNative;\n\ninterface CohereRequest {\n model: string;\n messages: CohereMessage[];\n stream?: boolean;\n tools?: CohereToolDef[];\n response_format?: { type: string; json_schema?: object };\n temperature?: number;\n max_tokens?: number;\n}\n\n// ─── Cohere SSE event types ─────────────────────────────────────────────────\n\ninterface CohereSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\n// ─── Zero-value usage block ─────────────────────────────────────────────────\n\nconst ZERO_USAGE = {\n billed_units: { input_tokens: 0, output_tokens: 0, search_units: 0, classifications: 0 },\n tokens: { input_tokens: 0, output_tokens: 0 },\n};\n\n// ─── Cohere finish reason / usage mapping ──────────────────────────────────\n\nfunction cohereFinishReason(\n overrideFinishReason: string | undefined,\n defaultReason: string,\n): string {\n if (!overrideFinishReason) return defaultReason;\n if (overrideFinishReason === \"stop\") return \"COMPLETE\";\n if (overrideFinishReason === \"tool_calls\") return \"TOOL_CALL\";\n if (overrideFinishReason === \"length\") return \"MAX_TOKENS\";\n return overrideFinishReason;\n}\n\nfunction cohereUsage(overrides?: ResponseOverrides): typeof ZERO_USAGE {\n if (!overrides?.usage) return ZERO_USAGE;\n const inputTokens = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;\n const outputTokens = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;\n return {\n billed_units: {\n input_tokens: inputTokens,\n output_tokens: outputTokens,\n search_units: 0,\n classifications: 0,\n },\n tokens: { input_tokens: inputTokens, output_tokens: outputTokens },\n };\n}\n\n// ─── Input conversion: Cohere → ChatCompletionRequest ───────────────────────\n\n/** Extract plain text from structured content (array of { type, text } parts) or passthrough string. */\nfunction extractTextContent(content: string | CohereContentPart[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((part) => part.type === \"text\" && part.text !== undefined)\n .map((part) => part.text!)\n .join(\"\");\n}\n\n/** Type guard: is this an OpenAI-style tool definition (has `function` key)? */\nfunction isOpenAIToolDef(t: CohereToolDef): t is CohereToolDefOpenAI {\n return \"function\" in t && typeof (t as CohereToolDefOpenAI).function === \"object\";\n}\n\nexport function cohereToCompletionRequest(req: CohereRequest): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n for (const msg of req.messages) {\n const textContent = extractTextContent(msg.content);\n if (msg.role === \"system\") {\n messages.push({ role: \"system\", content: textContent });\n } else if (msg.role === \"user\") {\n messages.push({ role: \"user\", content: textContent });\n } else if (msg.role === \"assistant\") {\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent || null,\n tool_calls: msg.tool_calls.map((tc) => ({\n id: tc.id ?? generateToolCallId(),\n type: \"function\" as const,\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent });\n }\n } else if (msg.role === \"tool\") {\n messages.push({\n role: \"tool\",\n content: textContent,\n tool_call_id: msg.tool_call_id,\n });\n }\n }\n\n // Convert tools — accept both OpenAI format and Cohere v2 native format\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => {\n if (isOpenAIToolDef(t)) {\n return {\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 // Cohere v2 native format: { name, description, parameter_definitions }\n return {\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameter_definitions,\n },\n };\n });\n }\n\n return {\n model: req.model,\n messages,\n stream: req.stream,\n tools,\n ...(req.response_format && { response_format: req.response_format }),\n ...(req.temperature !== undefined && { temperature: req.temperature }),\n ...(req.max_tokens !== undefined && { max_tokens: req.max_tokens }),\n };\n}\n\n// ─── Response building: fixture → Cohere v2 Chat format ─────────────────────\n\n// Non-streaming text response\nfunction buildCohereTextResponse(\n content: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: { type: string; text: string }[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"text\", text: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: overrides?.id ?? generateMessageId(),\n finish_reason: cohereFinishReason(overrides?.finishReason, \"COMPLETE\"),\n message: {\n role: \"assistant\",\n content: contentBlocks,\n tool_calls: [],\n tool_plan: \"\",\n citations: [],\n },\n usage: cohereUsage(overrides),\n };\n}\n\n// Non-streaming tool call response\nfunction buildCohereToolCallResponse(\n toolCalls: ToolCall[],\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const cohereCalls = toolCalls.map((tc) => {\n // Validate arguments JSON\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n return {\n id: tc.id || generateToolCallId(),\n type: \"function\",\n function: {\n name: tc.name,\n arguments: argsJson,\n },\n };\n });\n\n // Reasoning as a leading text block (Cohere has no native reasoning type)\n const contentBlocks: { type: string; text: string }[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"text\", text: reasoning });\n }\n\n return {\n id: overrides?.id ?? generateMessageId(),\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n message: {\n role: \"assistant\",\n content: contentBlocks,\n tool_calls: cohereCalls,\n tool_plan: \"\",\n citations: [],\n },\n usage: cohereUsage(overrides),\n };\n}\n\n// Non-streaming content + tool calls response\nfunction buildCohereContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n blocks?: FixtureBlock[],\n): object {\n // Cohere's non-streaming response keeps text in `message.content[]` and tool\n // calls in the SEPARATE `message.tool_calls[]` field, so the relative ORDER\n // of a text vs. toolCall block is NOT observable on the wire (unlike the\n // ordered streaming events, or Anthropic/Gemini's single ordered array).\n // When `blocks` is present we therefore derive both fields FROM the blocks\n // (so a blocks-only fixture still produces correct output) but make no\n // ordering guarantee between the two fields. Legacy fixtures use the\n // `content` + `toolCalls` inputs unchanged.\n // Resolve the blocks exactly once (pure: validate + copy, no id-gen) and\n // reuse the single result for BOTH the tool-call and text derivation below.\n const resolvedBlocks = blocks && blocks.length > 0 ? resolveFixtureBlocks(blocks) : undefined;\n\n const effectiveToolCalls: ToolCall[] = resolvedBlocks\n ? resolvedBlocks\n .filter((b): b is Extract<FixtureBlock, { type: \"toolCall\" }> => b.type === \"toolCall\")\n .map((b) => ({ name: b.name, arguments: b.arguments, id: b.id }))\n : toolCalls;\n\n const cohereCalls = effectiveToolCalls.map((tc) => {\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n return {\n id: tc.id || generateToolCallId(),\n type: \"function\",\n function: {\n name: tc.name,\n arguments: argsJson,\n },\n };\n });\n\n // For the blocks path, derive text only from actual text blocks. A tool-only\n // blocks fixture has no text block, so it must NOT emit a spurious empty\n // `{ type: \"text\", text: \"\" }` entry (real Cohere wouldn't). The legacy\n // (no-blocks) path is unchanged: it always emits the `content` text entry.\n const textBlocks = resolvedBlocks?.filter(\n (b): b is Extract<FixtureBlock, { type: \"text\" }> => b.type === \"text\",\n );\n const hasTextEntry = resolvedBlocks ? (textBlocks?.length ?? 0) > 0 : true;\n const effectiveContent: string = resolvedBlocks\n ? (textBlocks ?? []).map((b) => b.text).join(\"\")\n : content;\n\n const contentBlocks: { type: string; text: string }[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"text\", text: reasoning });\n }\n if (hasTextEntry) {\n contentBlocks.push({ type: \"text\", text: effectiveContent });\n }\n\n return {\n id: overrides?.id ?? generateMessageId(),\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n message: {\n role: \"assistant\",\n content: contentBlocks,\n tool_calls: cohereCalls,\n tool_plan: \"\",\n citations: [],\n },\n usage: cohereUsage(overrides),\n };\n}\n\n// ─── Streaming event builders ───────────────────────────────────────────────\n\nfunction buildCohereTextStreamEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): CohereSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const events: CohereSSEEvent[] = [];\n\n // message-start\n events.push({\n id: msgId,\n type: \"message-start\",\n delta: {\n message: {\n role: \"assistant\",\n content: [],\n tool_plan: \"\",\n tool_calls: [],\n citations: [],\n },\n },\n });\n\n let contentIndex = 0;\n\n // Reasoning as a text block before main content (Cohere has no native reasoning type)\n if (reasoning) {\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\" } } },\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-delta\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\", text: slice } } },\n });\n }\n events.push({ type: \"content-end\", index: contentIndex });\n contentIndex++;\n }\n\n // content-start (type: \"text\" only, no text field)\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\" },\n },\n },\n });\n\n // content-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-delta\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\", text: slice },\n },\n },\n });\n }\n\n // content-end\n events.push({\n type: \"content-end\",\n index: contentIndex,\n });\n\n // message-end\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"COMPLETE\"),\n usage: cohereUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildCohereToolCallStreamEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): CohereSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const events: CohereSSEEvent[] = [];\n\n // message-start\n events.push({\n id: msgId,\n type: \"message-start\",\n delta: {\n message: {\n role: \"assistant\",\n content: [],\n tool_plan: \"\",\n tool_calls: [],\n citations: [],\n },\n },\n });\n\n // Reasoning as a text block before the tool plan (Cohere has no native reasoning type)\n if (reasoning) {\n events.push({\n type: \"content-start\",\n index: 0,\n delta: { message: { content: { type: \"text\" } } },\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-delta\",\n index: 0,\n delta: { message: { content: { type: \"text\", text: slice } } },\n });\n }\n events.push({ type: \"content-end\", index: 0 });\n }\n\n // tool-plan-delta\n events.push({\n type: \"tool-plan-delta\",\n delta: {\n message: {\n tool_plan: \"I will use the requested tool.\",\n },\n },\n });\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n\n // Validate arguments JSON\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n\n // tool-call-start\n events.push({\n type: \"tool-call-start\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n id: callId,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: \"\",\n },\n },\n },\n },\n });\n\n // tool-call-delta — chunked arguments\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"tool-call-delta\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n function: {\n arguments: slice,\n },\n },\n },\n },\n });\n }\n\n // tool-call-end\n events.push({\n type: \"tool-call-end\",\n index: idx,\n });\n }\n\n // message-end\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n usage: cohereUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildCohereContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n blocks?: FixtureBlock[],\n): CohereSSEEvent[] {\n const msgId = overrides?.id ?? generateMessageId();\n const events: CohereSSEEvent[] = [];\n\n // message-start\n events.push({\n id: msgId,\n type: \"message-start\",\n delta: {\n message: {\n role: \"assistant\",\n content: [],\n tool_plan: \"\",\n tool_calls: [],\n citations: [],\n },\n },\n });\n\n let contentIndex = 0;\n\n // Reasoning as a text block before main content\n if (reasoning) {\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\" } } },\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-delta\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\", text: slice } } },\n });\n }\n events.push({ type: \"content-end\", index: contentIndex });\n contentIndex++;\n }\n\n if (blocks && blocks.length > 0) {\n // NEW path (#274): emit Cohere SSE events in the blocks' ARRAY ORDER so a\n // tool-first / interleaved fixture streams its tool call before its text.\n // Cohere v2 events are ordered, so tool-first is wire-expressible. The\n // tool-plan-delta is emitted once before the first toolCall block (Cohere\n // requires it preceding tool calls). Legacy fixtures (no blocks) skip this.\n const resolved = resolveFixtureBlocks(blocks);\n let toolPlanEmitted = false;\n let toolIdx = 0;\n resolved.forEach((block) => {\n if (block.type === \"toolCall\") {\n if (!toolPlanEmitted) {\n events.push({\n type: \"tool-plan-delta\",\n delta: { message: { tool_plan: \"I will use the requested tool.\" } },\n });\n toolPlanEmitted = true;\n }\n const callId = block.id || generateToolCallId();\n let argsJson: string;\n try {\n JSON.parse(block.arguments || \"{}\");\n argsJson = block.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${block.name}\": ${block.arguments}`,\n );\n argsJson = \"{}\";\n }\n events.push({\n type: \"tool-call-start\",\n index: toolIdx,\n delta: {\n message: {\n tool_calls: {\n id: callId,\n type: \"function\",\n function: { name: block.name, arguments: \"\" },\n },\n },\n },\n });\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n events.push({\n type: \"tool-call-delta\",\n index: toolIdx,\n delta: {\n message: {\n tool_calls: { function: { arguments: argsJson.slice(i, i + chunkSize) } },\n },\n },\n });\n }\n events.push({ type: \"tool-call-end\", index: toolIdx });\n toolIdx++;\n } else {\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: { message: { content: { type: \"text\" } } },\n });\n for (let i = 0; i < block.text.length; i += chunkSize) {\n events.push({\n type: \"content-delta\",\n index: contentIndex,\n delta: {\n message: { content: { type: \"text\", text: block.text.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({ type: \"content-end\", index: contentIndex });\n contentIndex++;\n }\n });\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n usage: cohereUsage(overrides),\n },\n });\n return events;\n }\n\n // content-start (type: \"text\" only, no text field)\n events.push({\n type: \"content-start\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\" },\n },\n },\n });\n\n // content-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-delta\",\n index: contentIndex,\n delta: {\n message: {\n content: { type: \"text\", text: slice },\n },\n },\n });\n }\n\n // content-end\n events.push({\n type: \"content-end\",\n index: contentIndex,\n });\n\n // tool-plan-delta\n events.push({\n type: \"tool-plan-delta\",\n delta: {\n message: {\n tool_plan: \"I will use the requested tool.\",\n },\n },\n });\n\n // Tool call events\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n\n let argsJson: string;\n try {\n JSON.parse(tc.arguments || \"{}\");\n argsJson = tc.arguments || \"{}\";\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsJson = \"{}\";\n }\n\n // tool-call-start\n events.push({\n type: \"tool-call-start\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n id: callId,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: \"\",\n },\n },\n },\n },\n });\n\n // tool-call-delta — chunked arguments\n for (let i = 0; i < argsJson.length; i += chunkSize) {\n const slice = argsJson.slice(i, i + chunkSize);\n events.push({\n type: \"tool-call-delta\",\n index: idx,\n delta: {\n message: {\n tool_calls: {\n function: {\n arguments: slice,\n },\n },\n },\n },\n });\n }\n\n // tool-call-end\n events.push({\n type: \"tool-call-end\",\n index: idx,\n });\n }\n\n // message-end\n events.push({\n type: \"message-end\",\n delta: {\n finish_reason: cohereFinishReason(overrides?.finishReason, \"TOOL_CALL\"),\n usage: cohereUsage(overrides),\n },\n });\n\n return events;\n}\n\n// ─── SSE writer for Cohere typed events ─────────────────────────────────────\n\ninterface CohereStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n recordedTimings?: RecordedTimings;\n replaySpeed?: number;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeCohereSSEStream(\n res: http.ServerResponse,\n events: CohereSSEEvent[],\n optionsOrLatency?: number | CohereStreamOptions,\n): Promise<boolean> {\n const opts: CohereStreamOptions =\n typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n const latency = opts.latency ?? 0;\n const profile = opts.streamingProfile;\n const { recordedTimings, replaySpeed } = opts;\n const signal = opts.signal;\n const onChunkSent = opts.onChunkSent;\n\n if (res.writableEnded) return true;\n res.setHeader(\"Content-Type\", \"text/event-stream\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n\n let chunkIndex = 0;\n for (const event of events) {\n const chunkDelay = calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);\n if (chunkDelay > 0) await delay(chunkDelay, signal);\n if (signal?.aborted) return false;\n if (res.writableEnded) return true;\n 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 handleCohere(\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 cohereReq: CohereRequest;\n try {\n cohereReq = JSON.parse(raw) as CohereRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON body: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Validate required model field\n if (!cohereReq.model) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\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: \"model is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!cohereReq.messages || !Array.isArray(cohereReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\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 = cohereToCompletionRequest(cohereReq);\n completionReq._endpointType = \"chat\";\n completionReq._context = getContext(req);\n\n const testId = getTestId(req);\n const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n // Record mode proxies on a miss to capture a fresh turn (see record gate\n // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n // shadowing a longer request and skipping the new turn's recording.\n recordMatchOptions(!!defaults.record, defaults.logger),\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n if (effectiveStrict) {\n const strictStatus = 503;\n const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n logger.error(\n strictNoMatchLogLine(req.method ?? \"POST\", req.url ?? \"/v2/chat\", skippedBySequenceOrTurn),\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"cohere\",\n req.url ?? \"/v2/chat\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: 404,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 404,\n JSON.stringify({\n error: {\n message: \"No fixture matched\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\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 ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, serializeErrorResponse(response), {\n retryAfter: response.retryAfter,\n });\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 Cohere v2 Chat API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n cohereReq.model,\n effectiveStrict,\n logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (cohereReq.stream !== true) {\n const body = buildCohereContentWithToolCallsResponse(\n response.content ?? \"\",\n response.toolCalls ?? [],\n logger,\n effReasoning,\n overrides,\n response.blocks,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildCohereContentWithToolCallsStreamEvents(\n response.content ?? \"\",\n response.toolCalls ?? [],\n chunkSize,\n logger,\n effReasoning,\n overrides,\n response.blocks,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeCohereSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n cohereReq.model,\n effectiveStrict,\n logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (cohereReq.stream !== true) {\n const body = buildCohereTextResponse(response.content, effReasoning, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildCohereTextStreamEvents(\n response.content,\n chunkSize,\n effReasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeCohereSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n cohereReq.model,\n effectiveStrict,\n logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (cohereReq.stream !== true) {\n const body = buildCohereToolCallResponse(response.toolCalls, logger, effReasoning, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildCohereToolCallStreamEvents(\n response.toolCalls,\n chunkSize,\n logger,\n effReasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeCohereSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/chat\",\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// ─── Cohere v2 Embed API types ────────────────────────────────────────────\n\ninterface CohereEmbedRequest {\n texts: string[];\n model: string;\n input_type?: string;\n embedding_types?: string[];\n truncate?: string;\n}\n\ninterface CohereEmbedResponse {\n id: string;\n texts: string[];\n embeddings: Record<string, number[][]>;\n meta: { api_version: { version: string } };\n}\n\n// ─── Cohere Embed handler ─────────────────────────────────────────────────\n\nexport async function handleCohereEmbed(\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 embedReq: CohereEmbedRequest;\n try {\n embedReq = JSON.parse(raw) as CohereEmbedRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON body: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Validate required fields\n if (!embedReq.model) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\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: \"model is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!embedReq.texts || !Array.isArray(embedReq.texts)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\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: texts array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Concatenate all texts for fixture matching\n const combinedInput = embedReq.texts.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router\n const syntheticReq: ChatCompletionRequest = {\n model: embedReq.model,\n messages: [],\n embeddingInput: combinedInput,\n _endpointType: \"embedding\",\n _context: getContext(req),\n };\n\n const testId = getTestId(req);\n const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n // Record mode proxies on a miss to capture a fresh turn (see record gate\n // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n // shadowing a longer request and skipping the new turn's recording.\n recordMatchOptions(!!defaults.record, defaults.logger),\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n // Determine requested embedding types (default to float)\n const embeddingTypes =\n embedReq.embedding_types && embedReq.embedding_types.length > 0\n ? embedReq.embedding_types\n : [\"float\"];\n\n if (fixture) {\n const response = await resolveResponse(fixture, syntheticReq);\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 ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, serializeErrorResponse(response), {\n retryAfter: response.retryAfter,\n });\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input text\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const vectors = embedReq.texts.map(() => [...response.embedding]);\n const embeddings: Record<string, number[][]> = {};\n for (const t of embeddingTypes) {\n embeddings[t] = vectors;\n }\n const body: CohereEmbedResponse = {\n id: generateMessageId(),\n texts: embedReq.texts,\n embeddings,\n meta: { api_version: { version: \"2\" } },\n };\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — check strict mode\n if (resolveStrictMode(defaults.strict, req.headers)) {\n const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n logger.error(\n strictNoMatchLogLine(req.method ?? \"POST\", req.url ?? \"/v2/embed\", skippedBySequenceOrTurn),\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: {\n status: 503,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Try record-and-replay proxy\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"cohere\",\n req.url ?? \"/v2/embed\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n\n // No fixture match — generate deterministic embeddings from input texts\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = 1024; // Cohere embed-v4.0 default\n const vectors = embedReq.texts.map((text) => generateDeterministicEmbedding(text, dimensions));\n const embeddings: Record<string, number[][]> = {};\n for (const t of embeddingTypes) {\n embeddings[t] = vectors;\n }\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v2/embed\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body: CohereEmbedResponse = {\n id: generateMessageId(),\n texts: embedReq.texts,\n embeddings,\n meta: { api_version: { version: \"2\" } },\n };\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.cts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAeiB,aAAA,SAAsB;;AAAvC;AAIiB,UAAA,iBAAA,CAAiB;EASjB,GAAA,EAAA,MAAA;EAAgB,IAAA,EAAA,MAAA;UAEnB,CAAA,EAAA,MAAA;aAF2B,CAAA,EAAA,MAAA;EAAmB,IAAA,CAAA,EAAA,MAAA;EAM3C,IAAA,CAAA,EAAA,MAAS;;AAGhB,UATO,eAAA,SAAwB,mBAS/B,CAAA;QACI,CAAA,EAAA;IACF,QAAA,EATE,KASF,CAAA;MAAe,IAAA,EAAA,MAAA;MAGV,OAAA,EAAA;QAAgB,IAAA,EAAA,MAAA;QAEvB,IAAA,EAAA,MAAA;MACI,CAAA;IACH,CAAA,CAAA;EAAc,CAAA;AAIzB;AAAgC,UAhBf,SAAA,CAgBe;MACnB,CAAA,EAAA,MAAA;YACH,CAAA,EAAA;IACS,IAAA,EAAA,MAAA;IAHqB,OAAA,EAAA,MAAA;EAAkB,CAAA;EAMzC,KAAA,CAAA,EAnBP,aAmBgB,
|
|
1
|
+
{"version":3,"file":"config-loader.d.cts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAeiB,aAAA,SAAsB;;AAAvC;AAIiB,UAAA,iBAAA,CAAiB;EASjB,GAAA,EAAA,MAAA;EAAgB,IAAA,EAAA,MAAA;UAEnB,CAAA,EAAA,MAAA;aAF2B,CAAA,EAAA,MAAA;EAAmB,IAAA,CAAA,EAAA,MAAA;EAM3C,IAAA,CAAA,EAAA,MAAS;;AAGhB,UATO,eAAA,SAAwB,mBAS/B,CAAA;QACI,CAAA,EAAA;IACF,QAAA,EATE,KASF,CAAA;MAAe,IAAA,EAAA,MAAA;MAGV,OAAA,EAAA;QAAgB,IAAA,EAAA,MAAA;QAEvB,IAAA,EAAA,MAAA;MACI,CAAA;IACH,CAAA,CAAA;EAAc,CAAA;AAIzB;AAAgC,UAhBf,SAAA,CAgBe;MACnB,CAAA,EAAA,MAAA;YACH,CAAA,EAAA;IACS,IAAA,EAAA,MAAA;IAHqB,OAAA,EAAA,MAAA;EAAkB,CAAA;EAMzC,KAAA,CAAA,EAnBP,aAmBgB,EAEf;EAGM,SAAA,CAAA,EAvBH,iBAuBoB,EAGvB;EAIM,OAAA,CAAA,EA7BL,eA+BC,EAAA;AAGb;AAAuC,UA/BtB,gBAAA,CA+BsB;SAMxB,EAAA,MAAA;OAHH,CAAA,EAhCF,OAgCE,EAAA;WAKK,CAAA,EApCH,WAoCG,EAAA;EAAW,MAAA,CAAA,EAnCjB,cAmCiB,EAAA;EAGX,OAAA,CAAA,EAAA,MAAY;AAK7B;AAA6B,UAvCZ,cAAA,SAAuB,kBAuCX,CAAA;UAGjB,CAAA,EAzCC,gBAyCD,EAAA;OACC,CAAA,EAzCH,gBAyCG,EAAA;gBAEL,CAAA,EA1CW,gBA0CX,EAAA;;AAEC,UAzCQ,SAAA,CAyCR;MACE,CAAA,EAAA,MAAA;EAAY,MAAA,CAAA,EAxCZ,cAwCY,EAAA;AAQvB;AAKsB,UAlDL,iBAAA,CAkDoB;EAAA,KAAA,EAAA;IAC3B,OAAA,CAAA,EAAA,MAAA;IAEW,UAAA,CAAA,EAAA,MAAA;IAAlB,QAAA,CAAA,EAAA,MAAA;IAAO,QAAA,CAAA,EAAA,MAAA;;;WAlDC;;;UAIM,UAAA;;aAEJ;;UAGI,sBAAA;;;YAGL;;;eAGG;;iBAEE;;UAGA,YAAA;;gBAED;;UAGC,YAAA;;;YAGL;aACC;;QAEL;QACA;SACC;WACE;;;;;;;;;;;iBAQK,UAAA,sBAAgC;iBAK1B,eAAA,SACZ;;;IAEP;UAAkB"}
|
package/dist/fixture-loader.cjs
CHANGED
|
@@ -19,6 +19,13 @@ function normalizeResponse(raw) {
|
|
|
19
19
|
};
|
|
20
20
|
return tc;
|
|
21
21
|
});
|
|
22
|
+
if (Array.isArray(response.blocks)) response.blocks = response.blocks.map((block) => {
|
|
23
|
+
if (block != null && block.type === "toolCall" && typeof block.arguments === "object" && block.arguments !== null) return {
|
|
24
|
+
...block,
|
|
25
|
+
arguments: JSON.stringify(block.arguments)
|
|
26
|
+
};
|
|
27
|
+
return block;
|
|
28
|
+
});
|
|
22
29
|
return response;
|
|
23
30
|
}
|
|
24
31
|
function entryToFixture(entry, logger) {
|
|
@@ -159,6 +166,94 @@ function validateWebSearches(response, fixtureIndex, results) {
|
|
|
159
166
|
});
|
|
160
167
|
}
|
|
161
168
|
}
|
|
169
|
+
function validateBlocks(response, fixtureIndex, results) {
|
|
170
|
+
if (response.blocks === void 0) return;
|
|
171
|
+
if (!Array.isArray(response.blocks)) {
|
|
172
|
+
results.push({
|
|
173
|
+
severity: "error",
|
|
174
|
+
fixtureIndex,
|
|
175
|
+
message: `blocks must be an array, got ${typeof response.blocks}`
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
for (let j = 0; j < response.blocks.length; j++) {
|
|
180
|
+
const block = response.blocks[j];
|
|
181
|
+
if (typeof block !== "object" || block === null) {
|
|
182
|
+
results.push({
|
|
183
|
+
severity: "error",
|
|
184
|
+
fixtureIndex,
|
|
185
|
+
message: `blocks[${j}] must be an object`
|
|
186
|
+
});
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (block.type !== "text" && block.type !== "toolCall") {
|
|
190
|
+
results.push({
|
|
191
|
+
severity: "error",
|
|
192
|
+
fixtureIndex,
|
|
193
|
+
message: `blocks[${j}].type must be "text" or "toolCall", got ${JSON.stringify(block.type)}`
|
|
194
|
+
});
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (block.type === "text") {
|
|
198
|
+
if (typeof block.text !== "string") results.push({
|
|
199
|
+
severity: "error",
|
|
200
|
+
fixtureIndex,
|
|
201
|
+
message: `blocks[${j}].text must be a string, got ${typeof block.text}`
|
|
202
|
+
});
|
|
203
|
+
else if (block.text === "") results.push({
|
|
204
|
+
severity: "error",
|
|
205
|
+
fixtureIndex,
|
|
206
|
+
message: `blocks[${j}].text is empty string`
|
|
207
|
+
});
|
|
208
|
+
} else {
|
|
209
|
+
if (typeof block.name !== "string" || block.name === "") results.push({
|
|
210
|
+
severity: "error",
|
|
211
|
+
fixtureIndex,
|
|
212
|
+
message: `blocks[${j}].name must be a non-empty string`
|
|
213
|
+
});
|
|
214
|
+
if (typeof block.arguments === "string") try {
|
|
215
|
+
JSON.parse(block.arguments);
|
|
216
|
+
} catch {
|
|
217
|
+
results.push({
|
|
218
|
+
severity: "error",
|
|
219
|
+
fixtureIndex,
|
|
220
|
+
message: `blocks[${j}].arguments is not valid JSON: ${block.arguments}`
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
else if (typeof block.arguments !== "object" || block.arguments === null) results.push({
|
|
224
|
+
severity: "error",
|
|
225
|
+
fixtureIndex,
|
|
226
|
+
message: `blocks[${j}].arguments must be a JSON string or object, got ${typeof block.arguments}`
|
|
227
|
+
});
|
|
228
|
+
if (block.id !== void 0 && typeof block.id !== "string") results.push({
|
|
229
|
+
severity: "error",
|
|
230
|
+
fixtureIndex,
|
|
231
|
+
message: `blocks[${j}].id must be a string, got ${typeof block.id}`
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const hasLegacyContent = typeof response.content === "string";
|
|
236
|
+
const hasLegacyToolCalls = Array.isArray(response.toolCalls);
|
|
237
|
+
if ((hasLegacyContent || hasLegacyToolCalls) && Array.isArray(response.blocks)) {
|
|
238
|
+
const textBlocks = response.blocks.filter((b) => b != null && typeof b === "object" && b.type === "text" && typeof b.text === "string");
|
|
239
|
+
const toolCallBlockNames = response.blocks.filter((b) => b != null && typeof b === "object" && b.type === "toolCall" && typeof b.name === "string").map((b) => b.name);
|
|
240
|
+
if (hasLegacyContent) {
|
|
241
|
+
if (textBlocks.map((b) => b.text).join("") !== response.content) results.push({
|
|
242
|
+
severity: "warning",
|
|
243
|
+
fixtureIndex,
|
|
244
|
+
message: "blocks text diverges from content — builders stream blocks and ignore the redundant content field"
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (hasLegacyToolCalls) {
|
|
248
|
+
const legacyNames = response.toolCalls.map((tc) => typeof tc?.name === "string" ? tc.name : void 0);
|
|
249
|
+
if (!(legacyNames.length === toolCallBlockNames.length && legacyNames.every((n, k) => n === toolCallBlockNames[k]))) results.push({
|
|
250
|
+
severity: "warning",
|
|
251
|
+
fixtureIndex,
|
|
252
|
+
message: "blocks toolCalls diverge from toolCalls — builders stream blocks and ignore the redundant toolCalls field"
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
162
257
|
function validateFixtures(fixtures) {
|
|
163
258
|
const results = [];
|
|
164
259
|
const seenUserMessages = /* @__PURE__ */ new Map();
|
|
@@ -171,8 +266,9 @@ function validateFixtures(fixtures) {
|
|
|
171
266
|
fixtureIndex: i,
|
|
172
267
|
message: "response is not a recognized type (must have content, toolCalls, error, embedding, image, audio, transcription, video, or json)"
|
|
173
268
|
});
|
|
269
|
+
const hasNonEmptyBlocks = Array.isArray(response.blocks) && response.blocks.length > 0;
|
|
174
270
|
if (require_helpers.isTextResponse(response)) {
|
|
175
|
-
if (response.content === "") results.push({
|
|
271
|
+
if (response.content === "" && !hasNonEmptyBlocks) results.push({
|
|
176
272
|
severity: "error",
|
|
177
273
|
fixtureIndex: i,
|
|
178
274
|
message: "content is empty string"
|
|
@@ -181,36 +277,41 @@ function validateFixtures(fixtures) {
|
|
|
181
277
|
validateWebSearches(response, i, results);
|
|
182
278
|
}
|
|
183
279
|
if (require_helpers.isContentWithToolCallsResponse(response)) {
|
|
184
|
-
if (response.content === "")
|
|
185
|
-
|
|
186
|
-
fixtureIndex: i,
|
|
187
|
-
message: "content is empty string"
|
|
188
|
-
});
|
|
189
|
-
if (response.toolCalls.length === 0) results.push({
|
|
190
|
-
severity: "warning",
|
|
191
|
-
fixtureIndex: i,
|
|
192
|
-
message: "toolCalls array is empty — fixture will never produce tool calls"
|
|
193
|
-
});
|
|
194
|
-
for (let j = 0; j < response.toolCalls.length; j++) {
|
|
195
|
-
const tc = response.toolCalls[j];
|
|
196
|
-
if (!tc.name) results.push({
|
|
280
|
+
if (typeof response.content === "string") {
|
|
281
|
+
if (response.content === "" && !hasNonEmptyBlocks) results.push({
|
|
197
282
|
severity: "error",
|
|
198
283
|
fixtureIndex: i,
|
|
199
|
-
message:
|
|
284
|
+
message: "content is empty string"
|
|
200
285
|
});
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
286
|
+
}
|
|
287
|
+
if (Array.isArray(response.toolCalls)) {
|
|
288
|
+
if (response.toolCalls.length === 0) results.push({
|
|
289
|
+
severity: "warning",
|
|
290
|
+
fixtureIndex: i,
|
|
291
|
+
message: "toolCalls array is empty — fixture will never produce tool calls"
|
|
292
|
+
});
|
|
293
|
+
for (let j = 0; j < response.toolCalls.length; j++) {
|
|
294
|
+
const tc = response.toolCalls[j];
|
|
295
|
+
if (!tc.name) results.push({
|
|
205
296
|
severity: "error",
|
|
206
297
|
fixtureIndex: i,
|
|
207
|
-
message: `toolCalls[${j}].
|
|
298
|
+
message: `toolCalls[${j}].name is empty`
|
|
208
299
|
});
|
|
300
|
+
try {
|
|
301
|
+
JSON.parse(tc.arguments);
|
|
302
|
+
} catch {
|
|
303
|
+
results.push({
|
|
304
|
+
severity: "error",
|
|
305
|
+
fixtureIndex: i,
|
|
306
|
+
message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}`
|
|
307
|
+
});
|
|
308
|
+
}
|
|
209
309
|
}
|
|
210
310
|
}
|
|
211
311
|
validateReasoning(response, i, results);
|
|
212
312
|
validateWebSearches(response, i, results);
|
|
213
313
|
}
|
|
314
|
+
validateBlocks(response, i, results);
|
|
214
315
|
if (require_helpers.isToolCallResponse(response)) {
|
|
215
316
|
if (response.toolCalls.length === 0) results.push({
|
|
216
317
|
severity: "warning",
|