@jecruz/merc-ai 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +34 -7
  2. package/dist/env-api-keys.d.ts.map +1 -1
  3. package/dist/env-api-keys.js +1 -1
  4. package/dist/env-api-keys.js.map +1 -1
  5. package/dist/image-models.generated.d.ts +345 -0
  6. package/dist/image-models.generated.d.ts.map +1 -1
  7. package/dist/image-models.generated.js +348 -3
  8. package/dist/image-models.generated.js.map +1 -1
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/models.d.ts.map +1 -1
  14. package/dist/models.generated.d.ts +15282 -3882
  15. package/dist/models.generated.d.ts.map +1 -1
  16. package/dist/models.generated.js +18368 -10964
  17. package/dist/models.generated.js.map +1 -1
  18. package/dist/models.js +4 -1
  19. package/dist/models.js.map +1 -1
  20. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  21. package/dist/providers/amazon-bedrock.js +188 -19
  22. package/dist/providers/amazon-bedrock.js.map +1 -1
  23. package/dist/providers/anthropic.d.ts.map +1 -1
  24. package/dist/providers/anthropic.js +101 -34
  25. package/dist/providers/anthropic.js.map +1 -1
  26. package/dist/providers/azure-openai-responses.d.ts +2 -0
  27. package/dist/providers/azure-openai-responses.d.ts.map +1 -1
  28. package/dist/providers/azure-openai-responses.js +8 -3
  29. package/dist/providers/azure-openai-responses.js.map +1 -1
  30. package/dist/providers/google-shared.d.ts +15 -4
  31. package/dist/providers/google-shared.d.ts.map +1 -1
  32. package/dist/providers/google-shared.js +80 -15
  33. package/dist/providers/google-shared.js.map +1 -1
  34. package/dist/providers/google-vertex.d.ts.map +1 -1
  35. package/dist/providers/google-vertex.js +23 -60
  36. package/dist/providers/google-vertex.js.map +1 -1
  37. package/dist/providers/google.d.ts.map +1 -1
  38. package/dist/providers/google.js +19 -68
  39. package/dist/providers/google.js.map +1 -1
  40. package/dist/providers/mistral.d.ts +1 -1
  41. package/dist/providers/mistral.d.ts.map +1 -1
  42. package/dist/providers/mistral.js +44 -60
  43. package/dist/providers/mistral.js.map +1 -1
  44. package/dist/providers/openai-codex-responses.d.ts.map +1 -1
  45. package/dist/providers/openai-codex-responses.js +250 -124
  46. package/dist/providers/openai-codex-responses.js.map +1 -1
  47. package/dist/providers/openai-completions.d.ts.map +1 -1
  48. package/dist/providers/openai-completions.js +94 -46
  49. package/dist/providers/openai-completions.js.map +1 -1
  50. package/dist/providers/openai-prompt-cache.d.ts +3 -0
  51. package/dist/providers/openai-prompt-cache.d.ts.map +1 -0
  52. package/dist/providers/openai-prompt-cache.js +10 -0
  53. package/dist/providers/openai-prompt-cache.js.map +1 -0
  54. package/dist/providers/openai-responses-shared.d.ts.map +1 -1
  55. package/dist/providers/openai-responses-shared.js +154 -211
  56. package/dist/providers/openai-responses-shared.js.map +1 -1
  57. package/dist/providers/openai-responses.d.ts.map +1 -1
  58. package/dist/providers/openai-responses.js +15 -9
  59. package/dist/providers/openai-responses.js.map +1 -1
  60. package/dist/providers/openrouter-images.d.ts.map +1 -1
  61. package/dist/providers/openrouter-images.js +5 -2
  62. package/dist/providers/openrouter-images.js.map +1 -1
  63. package/dist/providers/simple-options.d.ts +15 -3
  64. package/dist/providers/simple-options.d.ts.map +1 -1
  65. package/dist/providers/simple-options.js +36 -4
  66. package/dist/providers/simple-options.js.map +1 -1
  67. package/dist/types.d.ts +35 -2
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/utils/error-body.d.ts +5 -0
  71. package/dist/utils/error-body.d.ts.map +1 -1
  72. package/dist/utils/error-body.js +53 -5
  73. package/dist/utils/error-body.js.map +1 -1
  74. package/dist/utils/estimate.d.ts +22 -0
  75. package/dist/utils/estimate.d.ts.map +1 -0
  76. package/dist/utils/estimate.js +104 -0
  77. package/dist/utils/estimate.js.map +1 -0
  78. package/dist/utils/event-stream.d.ts.map +1 -1
  79. package/dist/utils/event-stream.js +25 -7
  80. package/dist/utils/event-stream.js.map +1 -1
  81. package/dist/utils/json-parse.d.ts +3 -0
  82. package/dist/utils/json-parse.d.ts.map +1 -1
  83. package/dist/utils/json-parse.js +15 -0
  84. package/dist/utils/json-parse.js.map +1 -1
  85. package/dist/utils/oauth/anthropic.d.ts.map +1 -1
  86. package/dist/utils/oauth/anthropic.js +16 -10
  87. package/dist/utils/oauth/anthropic.js.map +1 -1
  88. package/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  89. package/dist/utils/oauth/github-copilot.js +57 -21
  90. package/dist/utils/oauth/github-copilot.js.map +1 -1
  91. package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  92. package/dist/utils/oauth/openai-codex.js +73 -16
  93. package/dist/utils/oauth/openai-codex.js.map +1 -1
  94. package/dist/utils/oauth/types.d.ts +2 -0
  95. package/dist/utils/oauth/types.d.ts.map +1 -1
  96. package/dist/utils/oauth/types.js.map +1 -1
  97. package/dist/utils/overflow.d.ts +10 -1
  98. package/dist/utils/overflow.d.ts.map +1 -1
  99. package/dist/utils/overflow.js +47 -7
  100. package/dist/utils/overflow.js.map +1 -1
  101. package/dist/utils/provider-env.d.ts.map +1 -1
  102. package/dist/utils/provider-env.js +45 -10
  103. package/dist/utils/provider-env.js.map +1 -1
  104. package/dist/utils/tool-call-id.d.ts +11 -0
  105. package/dist/utils/tool-call-id.d.ts.map +1 -0
  106. package/dist/utils/tool-call-id.js +96 -0
  107. package/dist/utils/tool-call-id.js.map +1 -0
  108. package/dist/utils/validation.d.ts.map +1 -1
  109. package/dist/utils/validation.js +9 -0
  110. package/dist/utils/validation.js.map +1 -1
  111. package/package.json +6 -3
@@ -1 +1 @@
1
- {"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype GenerateContentConfig,\n\ttype GenerateContentParameters,\n\tGoogleGenAI,\n\ttype ThinkingConfig,\n} from \"@google/genai\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport { calculateCost, clampThinkingLevel } from \"../models.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingBudgets,\n\tThinkingContent,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport type { GoogleThinkingLevel } from \"./google-shared.js\";\nimport {\n\tconvertMessages,\n\tconvertTools,\n\tisThinkingPart,\n\tmapStopReason,\n\tmapToolChoice,\n\tretainThoughtSignature,\n} from \"./google-shared.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\n\nexport interface GoogleOptions extends StreamOptions {\n\ttoolChoice?: \"auto\" | \"none\" | \"any\";\n\tthinking?: {\n\t\tenabled: boolean;\n\t\tbudgetTokens?: number; // -1 for dynamic, 0 to disable\n\t\tlevel?: GoogleThinkingLevel;\n\t};\n}\n\n// Counter for generating unique tool call IDs\nlet toolCallCounter = 0;\n\nexport const streamGoogle: StreamFunction<\"google-generative-ai\", GoogleOptions> = (\n\tmodel: Model<\"google-generative-ai\">,\n\tcontext: Context,\n\toptions?: GoogleOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"google-generative-ai\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env) || \"\";\n\t\t\tconst client = createClient(model, apiKey, options?.headers, options?.env);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as GenerateContentParameters;\n\t\t\t}\n\t\t\tconst googleStream = await client.models.generateContentStream(params);\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\t\t\tlet currentBlock: TextContent | ThinkingContent | null = null;\n\t\t\tconst blocks = output.content;\n\t\t\tconst blockIndex = () => blocks.length - 1;\n\t\t\tfor await (const chunk of googleStream) {\n\t\t\t\t// @google/genai documents GenerateContentResponse.responseId as an output-only field\n\t\t\t\t// used to identify each response. Keep the first non-empty one from the stream.\n\t\t\t\toutput.responseId ||= chunk.responseId;\n\t\t\t\tconst candidate = chunk.candidates?.[0];\n\t\t\t\tif (candidate?.content?.parts) {\n\t\t\t\t\tfor (const part of candidate.content.parts) {\n\t\t\t\t\t\tif (part.text !== undefined) {\n\t\t\t\t\t\t\tconst isThinking = isThinkingPart(part);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!currentBlock ||\n\t\t\t\t\t\t\t\t(isThinking && currentBlock.type !== \"thinking\") ||\n\t\t\t\t\t\t\t\t(!isThinking && currentBlock.type !== \"text\")\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tif (currentBlock) {\n\t\t\t\t\t\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: blocks.length - 1,\n\t\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isThinking) {\n\t\t\t\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\", thinkingSignature: undefined };\n\t\t\t\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (currentBlock.type === \"thinking\") {\n\t\t\t\t\t\t\t\tcurrentBlock.thinking += part.text;\n\t\t\t\t\t\t\t\tcurrentBlock.thinkingSignature = retainThoughtSignature(\n\t\t\t\t\t\t\t\t\tcurrentBlock.thinkingSignature,\n\t\t\t\t\t\t\t\t\tpart.thoughtSignature,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\tdelta: part.text,\n\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcurrentBlock.text += part.text;\n\t\t\t\t\t\t\t\tcurrentBlock.textSignature = retainThoughtSignature(\n\t\t\t\t\t\t\t\t\tcurrentBlock.textSignature,\n\t\t\t\t\t\t\t\t\tpart.thoughtSignature,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\tdelta: part.text,\n\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (part.inlineData) {\n\t\t\t\t\t\t\tif (currentBlock) {\n\t\t\t\t\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (part.inlineData.data && part.inlineData.mimeType) {\n\t\t\t\t\t\t\t\tconst imageBlock: ImageContent = {\n\t\t\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\t\t\tdata: part.inlineData.data,\n\t\t\t\t\t\t\t\t\tmimeType: part.inlineData.mimeType,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\toutput.content.push(imageBlock);\n\t\t\t\t\t\t\t\tstream.push({ type: \"image_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\ttype: \"image_end\",\n\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\timage: imageBlock,\n\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (part.functionCall) {\n\t\t\t\t\t\t\tif (currentBlock) {\n\t\t\t\t\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Generate unique ID if not provided or if it's a duplicate\n\t\t\t\t\t\t\tconst providedId = part.functionCall.id;\n\t\t\t\t\t\t\tconst needsNewId =\n\t\t\t\t\t\t\t\t!providedId || output.content.some((b) => b.type === \"toolCall\" && b.id === providedId);\n\t\t\t\t\t\t\tconst toolCallId = needsNewId\n\t\t\t\t\t\t\t\t? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`\n\t\t\t\t\t\t\t\t: providedId;\n\n\t\t\t\t\t\t\tconst toolCall: ToolCall = {\n\t\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\t\tid: toolCallId,\n\t\t\t\t\t\t\t\tname: part.functionCall.name || \"\",\n\t\t\t\t\t\t\t\targuments: (part.functionCall.args as Record<string, any>) ?? {},\n\t\t\t\t\t\t\t\t...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\toutput.content.push(toolCall);\n\t\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: JSON.stringify(toolCall.arguments),\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (candidate?.finishReason) {\n\t\t\t\t\toutput.stopReason = mapStopReason(candidate.finishReason);\n\t\t\t\t\tif (output.content.some((b) => b.type === \"toolCall\")) {\n\t\t\t\t\t\toutput.stopReason = \"toolUse\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (chunk.usageMetadata) {\n\t\t\t\t\toutput.usage = {\n\t\t\t\t\t\tinput:\n\t\t\t\t\t\t\t(chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),\n\t\t\t\t\t\toutput:\n\t\t\t\t\t\t\t(chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),\n\t\t\t\t\t\tcacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: chunk.usageMetadata.totalTokenCount || 0,\n\t\t\t\t\t\tcost: {\n\t\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotal: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentBlock) {\n\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\t// Remove internal index property used during streaming\n\t\t\tfor (const block of output.content) {\n\t\t\t\tif (\"index\" in block) {\n\t\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t}\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimpleGoogle: StreamFunction<\"google-generative-ai\", SimpleStreamOptions> = (\n\tmodel: Model<\"google-generative-ai\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, options, apiKey);\n\tif (!options?.reasoning) {\n\t\treturn streamGoogle(model, context, { ...base, thinking: { enabled: false } } satisfies GoogleOptions);\n\t}\n\n\tconst clampedReasoning = clampThinkingLevel(model, options.reasoning);\n\tconst effort = (clampedReasoning === \"off\" ? \"high\" : clampedReasoning) as ClampedThinkingLevel;\n\tconst googleModel = model as Model<\"google-generative-ai\">;\n\n\tif (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel) || isGemma4Model(googleModel)) {\n\t\treturn streamGoogle(model, context, {\n\t\t\t...base,\n\t\t\tthinking: {\n\t\t\t\tenabled: true,\n\t\t\t\tlevel: getThinkingLevel(effort, googleModel),\n\t\t\t},\n\t\t} satisfies GoogleOptions);\n\t}\n\n\treturn streamGoogle(model, context, {\n\t\t...base,\n\t\tthinking: {\n\t\t\tenabled: true,\n\t\t\tbudgetTokens: getGoogleBudget(googleModel, effort, options.thinkingBudgets),\n\t\t},\n\t} satisfies GoogleOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"google-generative-ai\">,\n\tapiKey?: string,\n\toptionsHeaders?: Record<string, string>,\n\t_env?: ProviderEnv,\n): GoogleGenAI {\n\tconst httpOptions: { baseUrl?: string; apiVersion?: string; headers?: Record<string, string> } = {};\n\tif (model.baseUrl) {\n\t\thttpOptions.baseUrl = model.baseUrl;\n\t\thttpOptions.apiVersion = \"\"; // baseUrl already includes version path, don't append\n\t}\n\tif (model.headers || optionsHeaders) {\n\t\thttpOptions.headers = { ...model.headers, ...optionsHeaders };\n\t}\n\n\treturn new GoogleGenAI({\n\t\tapiKey,\n\t\thttpOptions: Object.keys(httpOptions).length > 0 ? httpOptions : undefined,\n\t});\n}\n\nfunction buildParams(\n\tmodel: Model<\"google-generative-ai\">,\n\tcontext: Context,\n\toptions: GoogleOptions = {},\n): GenerateContentParameters {\n\tconst contents = convertMessages(model, context);\n\n\tconst generationConfig: GenerateContentConfig = {};\n\tif (options.temperature !== undefined) {\n\t\tgenerationConfig.temperature = options.temperature;\n\t}\n\tif (options.maxTokens !== undefined) {\n\t\tgenerationConfig.maxOutputTokens = options.maxTokens;\n\t}\n\n\tconst config: GenerateContentConfig = {\n\t\t...(Object.keys(generationConfig).length > 0 && generationConfig),\n\t\t...(context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) }),\n\t\t...(context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }),\n\t};\n\n\tif (context.tools && context.tools.length > 0 && options.toolChoice) {\n\t\tconfig.toolConfig = {\n\t\t\tfunctionCallingConfig: {\n\t\t\t\tmode: mapToolChoice(options.toolChoice),\n\t\t\t},\n\t\t};\n\t} else {\n\t\tconfig.toolConfig = undefined;\n\t}\n\n\tif (options.thinking?.enabled && model.reasoning) {\n\t\tconst thinkingConfig: ThinkingConfig = { includeThoughts: true };\n\t\tif (options.thinking.level !== undefined) {\n\t\t\t// Cast to any since our GoogleThinkingLevel mirrors Google's ThinkingLevel enum values\n\t\t\tthinkingConfig.thinkingLevel = options.thinking.level as any;\n\t\t} else if (options.thinking.budgetTokens !== undefined) {\n\t\t\tthinkingConfig.thinkingBudget = options.thinking.budgetTokens;\n\t\t}\n\t\tconfig.thinkingConfig = thinkingConfig;\n\t} else if (model.reasoning && options.thinking && !options.thinking.enabled) {\n\t\tconfig.thinkingConfig = getDisabledThinkingConfig(model);\n\t}\n\n\tif (options.signal) {\n\t\tif (options.signal.aborted) {\n\t\t\tthrow new Error(\"Request aborted\");\n\t\t}\n\t\tconfig.abortSignal = options.signal;\n\t}\n\n\tconst params: GenerateContentParameters = {\n\t\tmodel: model.id,\n\t\tcontents,\n\t\tconfig,\n\t};\n\n\treturn params;\n}\n\ntype ClampedThinkingLevel = Exclude<ThinkingLevel, \"xhigh\" | \"max\">;\n\nfunction isGemma4Model(model: Model<\"google-generative-ai\">): boolean {\n\treturn /gemma-?4/.test(model.id.toLowerCase());\n}\n\nfunction isGemini3ProModel(model: Model<\"google-generative-ai\">): boolean {\n\treturn /gemini-3(?:\\.\\d+)?-pro/.test(model.id.toLowerCase());\n}\n\nfunction isGemini3FlashModel(model: Model<\"google-generative-ai\">): boolean {\n\treturn /gemini-3(?:\\.\\d+)?-flash/.test(model.id.toLowerCase());\n}\n\nfunction getDisabledThinkingConfig(model: Model<\"google-generative-ai\">): ThinkingConfig {\n\t// Google docs: Gemini 3.1 Pro cannot disable thinking, and Gemini 3 Flash / Flash-Lite\n\t// do not support full thinking-off either. For Gemini 3 models, use the lowest supported\n\t// thinkingLevel without includeThoughts so hidden thinking remains invisible to pi.\n\tif (isGemini3ProModel(model)) {\n\t\treturn { thinkingLevel: \"LOW\" as any };\n\t}\n\tif (isGemini3FlashModel(model)) {\n\t\treturn { thinkingLevel: \"MINIMAL\" as any };\n\t}\n\tif (isGemma4Model(model)) {\n\t\treturn { thinkingLevel: \"MINIMAL\" as any };\n\t}\n\n\t// Gemini 2.x supports disabling via thinkingBudget = 0.\n\treturn { thinkingBudget: 0 };\n}\n\nfunction getThinkingLevel(effort: ClampedThinkingLevel, model: Model<\"google-generative-ai\">): GoogleThinkingLevel {\n\tif (isGemini3ProModel(model)) {\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\tif (isGemma4Model(model)) {\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"MINIMAL\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGoogleBudget(\n\tmodel: Model<\"google-generative-ai\">,\n\teffort: ClampedThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): number {\n\tif (customBudgets?.[effort] !== undefined) {\n\t\treturn customBudgets[effort]!;\n\t}\n\n\tif (model.id.includes(\"2.5-pro\")) {\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 32768,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash-lite\")) {\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 512,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash\")) {\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\treturn -1;\n}\n"]}
1
+ {"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype GenerateContentConfig,\n\ttype GenerateContentParameters,\n\tGoogleGenAI,\n\ttype ThinkingConfig,\n} from \"@google/genai\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport { calculateCost, clampThinkingLevel } from \"../models.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingBudgets,\n\tThinkingContent,\n\tToolCall,\n} from \"../types.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport type { GoogleThinkingLevel, ResolvedGoogleThinkingLevel } from \"./google-shared.js\";\nimport {\n\tconvertMessages,\n\tconvertTools,\n\tgetDisabledGoogleThinkingConfig,\n\tisThinkingPart,\n\tmapStopReason,\n\tmapToolChoice,\n\tresolveGoogleThinkingLevel,\n\tretainThoughtSignature,\n\ttoGoogleSdkThinkingLevel,\n\ttoGoogleThinkingLevel,\n\tusesGoogleThinkingLevel,\n} from \"./google-shared.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\n\nexport interface GoogleOptions extends StreamOptions {\n\ttoolChoice?: \"auto\" | \"none\" | \"any\";\n\tthinking?: {\n\t\tenabled: boolean;\n\t\tbudgetTokens?: number; // -1 for dynamic, 0 to disable\n\t\tlevel?: GoogleThinkingLevel;\n\t};\n}\n\n// Counter for generating unique tool call IDs\nlet toolCallCounter = 0;\n\nexport const streamGoogle: StreamFunction<\"google-generative-ai\", GoogleOptions> = (\n\tmodel: Model<\"google-generative-ai\">,\n\tcontext: Context,\n\toptions?: GoogleOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"google-generative-ai\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env) || \"\";\n\t\t\tconst client = createClient(model, apiKey, options?.headers, options?.env);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as GenerateContentParameters;\n\t\t\t}\n\t\t\tconst googleStream = await client.models.generateContentStream(params);\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\t\t\tlet currentBlock: TextContent | ThinkingContent | null = null;\n\t\t\tconst blocks = output.content;\n\t\t\tconst blockIndex = () => blocks.length - 1;\n\t\t\tfor await (const chunk of googleStream) {\n\t\t\t\t// @google/genai documents GenerateContentResponse.responseId as an output-only field\n\t\t\t\t// used to identify each response. Keep the first non-empty one from the stream.\n\t\t\t\toutput.responseId ||= chunk.responseId;\n\t\t\t\tconst candidate = chunk.candidates?.[0];\n\t\t\t\tif (candidate?.content?.parts) {\n\t\t\t\t\tfor (const part of candidate.content.parts) {\n\t\t\t\t\t\tif (part.text !== undefined) {\n\t\t\t\t\t\t\tconst isThinking = isThinkingPart(part);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!currentBlock ||\n\t\t\t\t\t\t\t\t(isThinking && currentBlock.type !== \"thinking\") ||\n\t\t\t\t\t\t\t\t(!isThinking && currentBlock.type !== \"text\")\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tif (currentBlock) {\n\t\t\t\t\t\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: blocks.length - 1,\n\t\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isThinking) {\n\t\t\t\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\", thinkingSignature: undefined };\n\t\t\t\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (currentBlock.type === \"thinking\") {\n\t\t\t\t\t\t\t\tcurrentBlock.thinking += part.text;\n\t\t\t\t\t\t\t\tcurrentBlock.thinkingSignature = retainThoughtSignature(\n\t\t\t\t\t\t\t\t\tcurrentBlock.thinkingSignature,\n\t\t\t\t\t\t\t\t\tpart.thoughtSignature,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\tdelta: part.text,\n\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcurrentBlock.text += part.text;\n\t\t\t\t\t\t\t\tcurrentBlock.textSignature = retainThoughtSignature(\n\t\t\t\t\t\t\t\t\tcurrentBlock.textSignature,\n\t\t\t\t\t\t\t\t\tpart.thoughtSignature,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\tdelta: part.text,\n\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (part.inlineData) {\n\t\t\t\t\t\t\tif (currentBlock) {\n\t\t\t\t\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (part.inlineData.data && part.inlineData.mimeType) {\n\t\t\t\t\t\t\t\tconst imageBlock: ImageContent = {\n\t\t\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\t\t\tdata: part.inlineData.data,\n\t\t\t\t\t\t\t\t\tmimeType: part.inlineData.mimeType,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\toutput.content.push(imageBlock);\n\t\t\t\t\t\t\t\tstream.push({ type: \"image_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\ttype: \"image_end\",\n\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\timage: imageBlock,\n\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (part.functionCall) {\n\t\t\t\t\t\t\tif (currentBlock) {\n\t\t\t\t\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Generate unique ID if not provided or if it's a duplicate\n\t\t\t\t\t\t\tconst providedId = part.functionCall.id;\n\t\t\t\t\t\t\tconst needsNewId =\n\t\t\t\t\t\t\t\t!providedId || output.content.some((b) => b.type === \"toolCall\" && b.id === providedId);\n\t\t\t\t\t\t\tconst toolCallId = needsNewId\n\t\t\t\t\t\t\t\t? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`\n\t\t\t\t\t\t\t\t: providedId;\n\n\t\t\t\t\t\t\tconst toolCall: ToolCall = {\n\t\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\t\tid: toolCallId,\n\t\t\t\t\t\t\t\tname: part.functionCall.name || \"\",\n\t\t\t\t\t\t\t\targuments: (part.functionCall.args as Record<string, any>) ?? {},\n\t\t\t\t\t\t\t\t...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\toutput.content.push(toolCall);\n\t\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: JSON.stringify(toolCall.arguments),\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (candidate?.finishReason) {\n\t\t\t\t\toutput.rawStopReason = candidate.finishReason;\n\t\t\t\t\toutput.stopReason = mapStopReason(candidate.finishReason);\n\t\t\t\t\tif (output.content.some((b) => b.type === \"toolCall\") && output.stopReason === \"stop\") {\n\t\t\t\t\t\toutput.stopReason = \"toolUse\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (chunk.usageMetadata) {\n\t\t\t\t\toutput.usage = {\n\t\t\t\t\t\tinput:\n\t\t\t\t\t\t\t(chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),\n\t\t\t\t\t\toutput:\n\t\t\t\t\t\t\t(chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),\n\t\t\t\t\t\tcacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,\n\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\ttotalTokens: chunk.usageMetadata.totalTokenCount || 0,\n\t\t\t\t\t\tcost: {\n\t\t\t\t\t\t\tinput: 0,\n\t\t\t\t\t\t\toutput: 0,\n\t\t\t\t\t\t\tcacheRead: 0,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotal: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentBlock) {\n\t\t\t\tif (currentBlock.type === \"text\") {\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tconst errorMessage = output.rawStopReason\n\t\t\t\t\t? `Gemini stopped with ${output.rawStopReason}`\n\t\t\t\t\t: \"An unknown error occurred\";\n\t\t\t\tthrow new Error(errorMessage);\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\t// Remove internal index property used during streaming\n\t\t\tfor (const block of output.content) {\n\t\t\t\tif (\"index\" in block) {\n\t\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t}\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\tconst normalized = normalizeProviderError(error);\n\t\t\toutput.errorMetadata = normalized.errorMetadata;\n\t\t\toutput.errorMessage = formatProviderError(normalized);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimpleGoogle: StreamFunction<\"google-generative-ai\", SimpleStreamOptions> = (\n\tmodel: Model<\"google-generative-ai\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, context, options, apiKey);\n\tif (!options?.reasoning) {\n\t\treturn streamGoogle(model, context, { ...base, thinking: { enabled: false } } satisfies GoogleOptions);\n\t}\n\n\tconst clampedReasoning = clampThinkingLevel(model, options.reasoning);\n\tif (clampedReasoning === \"off\") {\n\t\treturn streamGoogle(model, context, { ...base, thinking: { enabled: false } } satisfies GoogleOptions);\n\t}\n\tconst effort = resolveGoogleThinkingLevel(model, clampedReasoning);\n\tconst googleModel = model as Model<\"google-generative-ai\">;\n\n\tif (usesGoogleThinkingLevel(model)) {\n\t\treturn streamGoogle(model, context, {\n\t\t\t...base,\n\t\t\tthinking: {\n\t\t\t\tenabled: true,\n\t\t\t\tlevel: toGoogleThinkingLevel(effort),\n\t\t\t},\n\t\t} satisfies GoogleOptions);\n\t}\n\n\treturn streamGoogle(model, context, {\n\t\t...base,\n\t\tthinking: {\n\t\t\tenabled: true,\n\t\t\tbudgetTokens: getGoogleBudget(googleModel, effort, options.thinkingBudgets),\n\t\t},\n\t} satisfies GoogleOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"google-generative-ai\">,\n\tapiKey?: string,\n\toptionsHeaders?: Record<string, string>,\n\t_env?: ProviderEnv,\n): GoogleGenAI {\n\tconst httpOptions: { baseUrl?: string; apiVersion?: string; headers?: Record<string, string> } = {};\n\tif (model.baseUrl) {\n\t\thttpOptions.baseUrl = model.baseUrl;\n\t\thttpOptions.apiVersion = \"\"; // baseUrl already includes version path, don't append\n\t}\n\tif (model.headers || optionsHeaders) {\n\t\thttpOptions.headers = { ...model.headers, ...optionsHeaders };\n\t}\n\n\treturn new GoogleGenAI({\n\t\tapiKey,\n\t\thttpOptions: Object.keys(httpOptions).length > 0 ? httpOptions : undefined,\n\t});\n}\n\nfunction buildParams(\n\tmodel: Model<\"google-generative-ai\">,\n\tcontext: Context,\n\toptions: GoogleOptions = {},\n): GenerateContentParameters {\n\tconst contents = convertMessages(model, context);\n\n\tconst generationConfig: GenerateContentConfig = {};\n\tif (options.temperature !== undefined) {\n\t\tgenerationConfig.temperature = options.temperature;\n\t}\n\tif (options.maxTokens !== undefined) {\n\t\tgenerationConfig.maxOutputTokens = options.maxTokens;\n\t}\n\n\tconst config: GenerateContentConfig = {\n\t\t...(Object.keys(generationConfig).length > 0 && generationConfig),\n\t\t...(context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) }),\n\t\t...(context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }),\n\t};\n\n\tif (context.tools && context.tools.length > 0 && options.toolChoice) {\n\t\tconfig.toolConfig = {\n\t\t\tfunctionCallingConfig: {\n\t\t\t\tmode: mapToolChoice(options.toolChoice),\n\t\t\t},\n\t\t};\n\t} else {\n\t\tconfig.toolConfig = undefined;\n\t}\n\n\tif (options.thinking?.enabled && model.reasoning) {\n\t\tconst thinkingConfig: ThinkingConfig = { includeThoughts: true };\n\t\tif (options.thinking.level !== undefined) {\n\t\t\tthinkingConfig.thinkingLevel = toGoogleSdkThinkingLevel(options.thinking.level);\n\t\t} else if (options.thinking.budgetTokens !== undefined) {\n\t\t\tthinkingConfig.thinkingBudget = options.thinking.budgetTokens;\n\t\t}\n\t\tconfig.thinkingConfig = thinkingConfig;\n\t} else if (model.reasoning && options.thinking && !options.thinking.enabled) {\n\t\tconfig.thinkingConfig = getDisabledGoogleThinkingConfig(model);\n\t}\n\n\tif (options.signal) {\n\t\tif (options.signal.aborted) {\n\t\t\tthrow new Error(\"Request aborted\");\n\t\t}\n\t\tconfig.abortSignal = options.signal;\n\t}\n\n\tconst params: GenerateContentParameters = {\n\t\tmodel: model.id,\n\t\tcontents,\n\t\tconfig,\n\t};\n\n\treturn params;\n}\n\nfunction getGoogleBudget(\n\tmodel: Model<\"google-generative-ai\">,\n\teffort: ResolvedGoogleThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): number {\n\tif (customBudgets?.[effort] !== undefined) {\n\t\treturn customBudgets[effort]!;\n\t}\n\n\tif (model.id.includes(\"2.5-pro\")) {\n\t\tconst budgets: Record<ResolvedGoogleThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 32768,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash-lite\")) {\n\t\tconst budgets: Record<ResolvedGoogleThinkingLevel, number> = {\n\t\t\tminimal: 512,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash\")) {\n\t\tconst budgets: Record<ResolvedGoogleThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\treturn -1;\n}\n"]}
@@ -2,7 +2,7 @@ import type { SimpleStreamOptions, StreamFunction, StreamOptions } from "../type
2
2
  /**
3
3
  * Provider-specific options for the Mistral API.
4
4
  */
5
- type MistralReasoningEffort = "none" | "high";
5
+ type MistralReasoningEffort = "none" | "low" | "medium" | "high" | "max";
6
6
  export interface MistralOptions extends StreamOptions {
7
7
  toolChoice?: "auto" | "none" | "any" | "required" | {
8
8
  type: "function";
@@ -1 +1 @@
1
- {"version":3,"file":"mistral.d.ts","sourceRoot":"","sources":["../../src/providers/mistral.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAKX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAKb,MAAM,aAAa,CAAC;AAWrB;;GAEG;AACH,KAAK,sBAAsB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C,MAAM,WAAW,cAAe,SAAQ,aAAa;IACpD,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACrG,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,eAAe,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,cAAc,CAAC,uBAAuB,EAAE,cAAc,CAyDjF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,uBAAuB,EAAE,mBAAmB,CAqB5F,CAAC","sourcesContent":["import { Mistral } from \"@mistralai/mistralai\";\nimport type {\n\tChatCompletionStreamRequest,\n\tChatCompletionStreamRequestMessage,\n\tCompletionEvent,\n\tContentChunk,\n\tFunctionTool,\n} from \"@mistralai/mistralai/models/components\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport { calculateCost, clampThinkingLevel } from \"../models.js\";\nimport type {\n\tAssistantMessage,\n\tContext,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { shortHash } from \"../utils/hash.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\nimport { transformMessages } from \"./transform-messages.js\";\n\nconst MISTRAL_TOOL_CALL_ID_LENGTH = 9;\nconst MAX_MISTRAL_ERROR_BODY_CHARS = 4000;\n\n/**\n * Provider-specific options for the Mistral API.\n */\ntype MistralReasoningEffort = \"none\" | \"high\";\n\nexport interface MistralOptions extends StreamOptions {\n\ttoolChoice?: \"auto\" | \"none\" | \"any\" | \"required\" | { type: \"function\"; function: { name: string } };\n\tpromptMode?: \"reasoning\";\n\treasoningEffort?: MistralReasoningEffort;\n}\n\n/**\n * Stream responses from Mistral using `chat.stream`.\n */\nexport const streamMistral: StreamFunction<\"mistral-conversations\", MistralOptions> = (\n\tmodel: Model<\"mistral-conversations\">,\n\tcontext: Context,\n\toptions?: MistralOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output = createOutput(model);\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t\t}\n\n\t\t\t// Intentionally per-request: avoids shared SDK mutable state across concurrent consumers.\n\t\t\tconst mistral = new Mistral({\n\t\t\t\tapiKey,\n\t\t\t\tserverURL: model.baseUrl,\n\t\t\t});\n\n\t\t\tconst normalizeMistralToolCallId = createMistralToolCallIdNormalizer();\n\t\t\tconst transformedMessages = transformMessages(context.messages, model, (id) => normalizeMistralToolCallId(id));\n\n\t\t\tlet payload = buildChatPayload(model, context, transformedMessages, options);\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload as ChatCompletionStreamRequest;\n\t\t\t}\n\t\t\tconst mistralStream = await mistral.chat.stream(payload, buildRequestOptions(model, options));\n\t\t\tstream.push({ type: \"start\", partial: output });\n\t\t\tawait consumeChatStream(model, output, stream, mistralStream);\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\t// partialArgs is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialArgs?: string }).partialArgs;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatMistralError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\n/**\n * Maps provider-agnostic `SimpleStreamOptions` to Mistral options.\n */\nexport const streamSimpleMistral: StreamFunction<\"mistral-conversations\", SimpleStreamOptions> = (\n\tmodel: Model<\"mistral-conversations\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, options, apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoning = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\tconst shouldUseReasoning = model.reasoning && reasoning !== undefined;\n\n\treturn streamMistral(model, context, {\n\t\t...base,\n\t\tpromptMode: shouldUseReasoning && usesPromptModeReasoning(model) ? \"reasoning\" : undefined,\n\t\treasoningEffort:\n\t\t\tshouldUseReasoning && usesReasoningEffort(model) ? mapReasoningEffort(model, reasoning) : undefined,\n\t} satisfies MistralOptions);\n};\n\nfunction createOutput(model: Model<\"mistral-conversations\">): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createMistralToolCallIdNormalizer(): (id: string) => string {\n\tconst idMap = new Map<string, string>();\n\tconst reverseMap = new Map<string, string>();\n\n\treturn (id: string): string => {\n\t\tconst existing = idMap.get(id);\n\t\tif (existing) return existing;\n\n\t\tlet attempt = 0;\n\t\twhile (true) {\n\t\t\tconst candidate = deriveMistralToolCallId(id, attempt);\n\t\t\tconst owner = reverseMap.get(candidate);\n\t\t\tif (!owner || owner === id) {\n\t\t\t\tidMap.set(id, candidate);\n\t\t\t\treverseMap.set(candidate, id);\n\t\t\t\treturn candidate;\n\t\t\t}\n\t\t\tattempt++;\n\t\t}\n\t};\n}\n\nfunction deriveMistralToolCallId(id: string, attempt: number): string {\n\tconst normalized = id.replace(/[^a-zA-Z0-9]/g, \"\");\n\tif (attempt === 0 && normalized.length === MISTRAL_TOOL_CALL_ID_LENGTH) return normalized;\n\tconst seedBase = normalized || id;\n\tconst seed = attempt === 0 ? seedBase : `${seedBase}:${attempt}`;\n\treturn shortHash(seed)\n\t\t.replace(/[^a-zA-Z0-9]/g, \"\")\n\t\t.slice(0, MISTRAL_TOOL_CALL_ID_LENGTH);\n}\n\nfunction formatMistralError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst sdkError = error as Error & { statusCode?: unknown; body?: unknown };\n\t\tconst statusCode = typeof sdkError.statusCode === \"number\" ? sdkError.statusCode : undefined;\n\t\tconst bodyText = typeof sdkError.body === \"string\" ? sdkError.body.trim() : undefined;\n\t\tif (statusCode !== undefined && bodyText) {\n\t\t\treturn `Mistral API error (${statusCode}): ${truncateErrorText(bodyText, MAX_MISTRAL_ERROR_BODY_CHARS)}`;\n\t\t}\n\t\tif (statusCode !== undefined) return `Mistral API error (${statusCode}): ${error.message}`;\n\t\treturn error.message;\n\t}\n\treturn safeJsonStringify(error);\n}\n\nfunction truncateErrorText(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;\n}\n\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\tconst serialized = JSON.stringify(value);\n\t\treturn serialized === undefined ? String(value) : serialized;\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n\nfunction buildRequestOptions(model: Model<\"mistral-conversations\">, options?: MistralOptions) {\n\tconst requestOptions: {\n\t\tsignal?: AbortSignal;\n\t\tretries: { strategy: \"none\" };\n\t\theaders?: Record<string, string>;\n\t} = {\n\t\tretries: { strategy: \"none\" },\n\t};\n\tif (options?.signal) requestOptions.signal = options.signal;\n\n\tconst headers: Record<string, string> = {};\n\tif (model.headers) Object.assign(headers, model.headers);\n\tif (options?.headers) Object.assign(headers, options.headers);\n\n\t// Mistral infrastructure uses `x-affinity` for KV-cache reuse (prefix caching).\n\t// Respect explicit caller-provided header values.\n\tif (options?.sessionId && !headers[\"x-affinity\"]) {\n\t\theaders[\"x-affinity\"] = options.sessionId;\n\t}\n\n\tif (Object.keys(headers).length > 0) {\n\t\trequestOptions.headers = headers;\n\t}\n\n\treturn requestOptions;\n}\n\nfunction buildChatPayload(\n\tmodel: Model<\"mistral-conversations\">,\n\tcontext: Context,\n\tmessages: Message[],\n\toptions?: MistralOptions,\n): ChatCompletionStreamRequest {\n\tconst payload: ChatCompletionStreamRequest = {\n\t\tmodel: model.id,\n\t\tstream: true,\n\t\tmessages: toChatMessages(messages, model.input.includes(\"image\")),\n\t};\n\n\tif (context.tools?.length) payload.tools = toFunctionTools(context.tools);\n\tif (options?.temperature !== undefined) payload.temperature = options.temperature;\n\tif (options?.maxTokens !== undefined) payload.maxTokens = options.maxTokens;\n\tif (options?.toolChoice) payload.toolChoice = mapToolChoice(options.toolChoice);\n\tif (options?.promptMode) payload.promptMode = options.promptMode;\n\tif (options?.reasoningEffort) payload.reasoningEffort = options.reasoningEffort;\n\n\tif (context.systemPrompt) {\n\t\tpayload.messages.unshift({\n\t\t\trole: \"system\",\n\t\t\tcontent: sanitizeSurrogates(context.systemPrompt),\n\t\t});\n\t}\n\n\treturn payload;\n}\n\nasync function consumeChatStream(\n\tmodel: Model<\"mistral-conversations\">,\n\toutput: AssistantMessage,\n\tstream: AssistantMessageEventStream,\n\tmistralStream: AsyncIterable<CompletionEvent>,\n): Promise<void> {\n\tlet currentBlock: TextContent | ThinkingContent | null = null;\n\tconst blocks = output.content;\n\tconst blockIndex = () => blocks.length - 1;\n\tconst toolBlocksByKey = new Map<string, number>();\n\n\tconst finishCurrentBlock = (block?: typeof currentBlock) => {\n\t\tif (!block) return;\n\t\tif (block.type === \"text\") {\n\t\t\tstream.push({\n\t\t\t\ttype: \"text_end\",\n\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\tcontent: block.text,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (block.type === \"thinking\") {\n\t\t\tstream.push({\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\tcontent: block.thinking,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t}\n\t};\n\n\tfor await (const event of mistralStream) {\n\t\tconst chunk = event.data;\n\t\t// Mistral's streamed CompletionChunk carries an id field. Keep the first non-empty one,\n\t\t// mirroring how OpenAI-style streaming exposes a stable response identifier per stream.\n\t\toutput.responseId ||= chunk.id;\n\n\t\tif (chunk.usage) {\n\t\t\toutput.usage.input = chunk.usage.promptTokens || 0;\n\t\t\toutput.usage.output = chunk.usage.completionTokens || 0;\n\t\t\toutput.usage.cacheRead = 0;\n\t\t\toutput.usage.cacheWrite = 0;\n\t\t\toutput.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output;\n\t\t\tcalculateCost(model, output.usage);\n\t\t}\n\n\t\tconst choice = chunk.choices[0];\n\t\tif (!choice) continue;\n\n\t\tif (choice.finishReason) {\n\t\t\toutput.stopReason = mapChatStopReason(choice.finishReason);\n\t\t}\n\n\t\tconst delta = choice.delta;\n\t\tif (delta.content !== null && delta.content !== undefined) {\n\t\t\tconst contentItems = typeof delta.content === \"string\" ? [delta.content] : delta.content;\n\t\t\tfor (const item of contentItems) {\n\t\t\t\tif (typeof item === \"string\") {\n\t\t\t\t\tconst textDelta = sanitizeSurrogates(item);\n\t\t\t\t\tif (!currentBlock || currentBlock.type !== \"text\") {\n\t\t\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t\tcurrentBlock.text += textDelta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: textDelta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (item.type === \"thinking\") {\n\t\t\t\t\tconst deltaText = item.thinking\n\t\t\t\t\t\t.map((part) => (\"text\" in part ? part.text : \"\"))\n\t\t\t\t\t\t.filter((text) => text.length > 0)\n\t\t\t\t\t\t.join(\"\");\n\t\t\t\t\tconst thinkingDelta = sanitizeSurrogates(deltaText);\n\t\t\t\t\tif (!thinkingDelta) continue;\n\t\t\t\t\tif (!currentBlock || currentBlock.type !== \"thinking\") {\n\t\t\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t\tcurrentBlock.thinking += thinkingDelta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: thinkingDelta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\tconst textDelta = sanitizeSurrogates(item.text);\n\t\t\t\t\tif (!currentBlock || currentBlock.type !== \"text\") {\n\t\t\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t\tcurrentBlock.text += textDelta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: textDelta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst toolCalls = delta.toolCalls || [];\n\t\tfor (const toolCall of toolCalls) {\n\t\t\tif (currentBlock) {\n\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\tcurrentBlock = null;\n\t\t\t}\n\t\t\tconst callId =\n\t\t\t\ttoolCall.id && toolCall.id !== \"null\"\n\t\t\t\t\t? toolCall.id\n\t\t\t\t\t: deriveMistralToolCallId(`toolcall:${toolCall.index ?? 0}`, 0);\n\t\t\tconst key = `${callId}:${toolCall.index || 0}`;\n\t\t\tconst existingIndex = toolBlocksByKey.get(key);\n\t\t\tlet block: (ToolCall & { partialArgs?: string }) | undefined;\n\n\t\t\tif (existingIndex !== undefined) {\n\t\t\t\tconst existing = output.content[existingIndex];\n\t\t\t\tif (existing?.type === \"toolCall\") {\n\t\t\t\t\tblock = existing as ToolCall & { partialArgs?: string };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!block) {\n\t\t\t\tblock = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: callId,\n\t\t\t\t\tname: toolCall.function.name,\n\t\t\t\t\targuments: {},\n\t\t\t\t\tpartialArgs: \"\",\n\t\t\t\t};\n\t\t\t\toutput.content.push(block);\n\t\t\t\ttoolBlocksByKey.set(key, output.content.length - 1);\n\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t}\n\n\t\t\tconst argsDelta =\n\t\t\t\ttypeof toolCall.function.arguments === \"string\"\n\t\t\t\t\t? toolCall.function.arguments\n\t\t\t\t\t: JSON.stringify(toolCall.function.arguments || {});\n\t\t\tblock.partialArgs = (block.partialArgs || \"\") + argsDelta;\n\t\t\tblock.arguments = parseStreamingJson<Record<string, unknown>>(block.partialArgs);\n\t\t\tstream.push({\n\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\tcontentIndex: toolBlocksByKey.get(key)!,\n\t\t\t\tdelta: argsDelta,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t}\n\t}\n\n\tfinishCurrentBlock(currentBlock);\n\tfor (const index of toolBlocksByKey.values()) {\n\t\tconst block = output.content[index];\n\t\tif (block.type !== \"toolCall\") continue;\n\t\tconst toolBlock = block as ToolCall & { partialArgs?: string };\n\t\ttoolBlock.arguments = parseStreamingJson<Record<string, unknown>>(toolBlock.partialArgs);\n\t\t// Finalize in-place and strip the scratch buffer so replay only\n\t\t// carries parsed arguments.\n\t\tdelete toolBlock.partialArgs;\n\t\tstream.push({\n\t\t\ttype: \"toolcall_end\",\n\t\t\tcontentIndex: index,\n\t\t\ttoolCall: toolBlock,\n\t\t\tpartial: output,\n\t\t});\n\t}\n}\n\nfunction toFunctionTools(tools: Tool[]): Array<FunctionTool & { type: \"function\" }> {\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\",\n\t\tfunction: {\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: stripSymbolKeys(tool.parameters) as Record<string, unknown>,\n\t\t\tstrict: false,\n\t\t},\n\t}));\n}\n\nfunction stripSymbolKeys(value: unknown): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => stripSymbolKeys(item));\n\t}\n\n\tif (value && typeof value === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, entry] of Object.entries(value)) {\n\t\t\tresult[key] = stripSymbolKeys(entry);\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn value;\n}\n\nfunction toChatMessages(messages: Message[], supportsImages: boolean): ChatCompletionStreamRequestMessage[] {\n\tconst result: ChatCompletionStreamRequestMessage[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tresult.push({ role: \"user\", content: sanitizeSurrogates(msg.content) });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst hadImages = msg.content.some((item) => item.type === \"image\");\n\t\t\tconst content: ContentChunk[] = msg.content\n\t\t\t\t.filter((item) => item.type === \"text\" || supportsImages)\n\t\t\t\t.map((item) => {\n\t\t\t\t\tif (item.type === \"text\") return { type: \"text\", text: sanitizeSurrogates(item.text) };\n\t\t\t\t\treturn { type: \"image_url\", imageUrl: `data:${item.mimeType};base64,${item.data}` };\n\t\t\t\t});\n\t\t\tif (content.length > 0) {\n\t\t\t\tresult.push({ role: \"user\", content });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (hadImages && !supportsImages) {\n\t\t\t\tresult.push({ role: \"user\", content: \"(image omitted: model does not support images)\" });\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst contentParts: ContentChunk[] = [];\n\t\t\tconst toolCalls: Array<{ id: string; type: \"function\"; function: { name: string; arguments: string } }> = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (block.text.trim().length > 0) {\n\t\t\t\t\t\tcontentParts.push({ type: \"text\", text: sanitizeSurrogates(block.text) });\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinking.trim().length > 0) {\n\t\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: [{ type: \"text\", text: sanitizeSurrogates(block.thinking) }],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (block.type !== \"toolCall\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttoolCalls.push({\n\t\t\t\t\tid: block.id,\n\t\t\t\t\ttype: \"function\",\n\t\t\t\t\tfunction: { name: block.name, arguments: JSON.stringify(block.arguments || {}) },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst assistantMessage: ChatCompletionStreamRequestMessage = { role: \"assistant\" };\n\t\t\tif (contentParts.length > 0) assistantMessage.content = contentParts;\n\t\t\tif (toolCalls.length > 0) assistantMessage.toolCalls = toolCalls;\n\t\t\tif (contentParts.length > 0 || toolCalls.length > 0) result.push(assistantMessage);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst toolContent: ContentChunk[] = [];\n\t\tconst textResult = msg.content\n\t\t\t.filter((part) => part.type === \"text\")\n\t\t\t.map((part) => (part.type === \"text\" ? sanitizeSurrogates(part.text) : \"\"))\n\t\t\t.join(\"\\n\");\n\t\tconst hasImages = msg.content.some((part) => part.type === \"image\");\n\t\tconst toolText = buildToolResultText(textResult, hasImages, supportsImages, msg.isError);\n\t\ttoolContent.push({ type: \"text\", text: toolText });\n\t\tfor (const part of msg.content) {\n\t\t\tif (!supportsImages) continue;\n\t\t\tif (part.type !== \"image\") continue;\n\t\t\ttoolContent.push({\n\t\t\t\ttype: \"image_url\",\n\t\t\t\timageUrl: `data:${part.mimeType};base64,${part.data}`,\n\t\t\t});\n\t\t}\n\t\tresult.push({\n\t\t\trole: \"tool\",\n\t\t\ttoolCallId: msg.toolCallId,\n\t\t\tname: msg.toolName,\n\t\t\tcontent: toolContent,\n\t\t});\n\t}\n\n\treturn result;\n}\n\nfunction buildToolResultText(text: string, hasImages: boolean, supportsImages: boolean, isError: boolean): string {\n\tconst trimmed = text.trim();\n\tconst errorPrefix = isError ? \"[tool error] \" : \"\";\n\n\tif (trimmed.length > 0) {\n\t\tconst imageSuffix = hasImages && !supportsImages ? \"\\n[tool image omitted: model does not support images]\" : \"\";\n\t\treturn `${errorPrefix}${trimmed}${imageSuffix}`;\n\t}\n\n\tif (hasImages) {\n\t\tif (supportsImages) {\n\t\t\treturn isError ? \"[tool error] (see attached image)\" : \"(see attached image)\";\n\t\t}\n\t\treturn isError\n\t\t\t? \"[tool error] (image omitted: model does not support images)\"\n\t\t\t: \"(image omitted: model does not support images)\";\n\t}\n\n\treturn isError ? \"[tool error] (no tool output)\" : \"(no tool output)\";\n}\n\nfunction usesReasoningEffort(model: Model<\"mistral-conversations\">): boolean {\n\treturn model.id === \"mistral-small-2603\" || model.id === \"mistral-small-latest\" || model.id === \"mistral-medium-3.5\";\n}\n\nfunction usesPromptModeReasoning(model: Model<\"mistral-conversations\">): boolean {\n\treturn model.reasoning && !usesReasoningEffort(model);\n}\n\nfunction mapReasoningEffort(\n\tmodel: Model<\"mistral-conversations\">,\n\tlevel: Exclude<SimpleStreamOptions[\"reasoning\"], undefined>,\n): MistralReasoningEffort {\n\treturn (model.thinkingLevelMap?.[level] ?? \"high\") as MistralReasoningEffort;\n}\n\nfunction mapToolChoice(\n\tchoice: MistralOptions[\"toolChoice\"],\n): \"auto\" | \"none\" | \"any\" | \"required\" | { type: \"function\"; function: { name: string } } | undefined {\n\tif (!choice) return undefined;\n\tif (choice === \"auto\" || choice === \"none\" || choice === \"any\" || choice === \"required\") {\n\t\treturn choice as any;\n\t}\n\treturn {\n\t\ttype: \"function\",\n\t\tfunction: { name: choice.function.name },\n\t};\n}\n\nfunction mapChatStopReason(reason: string | null): StopReason {\n\tif (reason === null) return \"stop\";\n\tswitch (reason) {\n\t\tcase \"stop\":\n\t\t\treturn \"stop\";\n\t\tcase \"length\":\n\t\tcase \"model_length\":\n\t\t\treturn \"length\";\n\t\tcase \"tool_calls\":\n\t\t\treturn \"toolUse\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tdefault:\n\t\t\treturn \"stop\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"mistral.d.ts","sourceRoot":"","sources":["../../src/providers/mistral.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAKX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAKb,MAAM,aAAa,CAAC;AAWrB;;GAEG;AACH,KAAK,sBAAsB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAEzE,MAAM,WAAW,cAAe,SAAQ,aAAa;IACpD,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACrG,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,eAAe,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,cAAc,CAAC,uBAAuB,EAAE,cAAc,CA0DjF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,uBAAuB,EAAE,mBAAmB,CA0B5F,CAAC","sourcesContent":["import { Mistral } from \"@mistralai/mistralai\";\nimport type {\n\tChatCompletionStreamRequest,\n\tChatCompletionStreamRequestMessage,\n\tCompletionEvent,\n\tContentChunk,\n\tFunctionTool,\n} from \"@mistralai/mistralai/models/components\";\nimport { unrecognized } from \"@mistralai/mistralai/types\";\nimport { getEnvApiKey } from \"../env-api-keys.js\";\nimport { calculateCost, clampThinkingLevel } from \"../models.js\";\nimport type {\n\tAssistantMessage,\n\tContext,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n} from \"../types.js\";\nimport { normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { finalizeToolCallArguments, parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport { createProviderToolCallIdNormalizer } from \"../utils/tool-call-id.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\nimport { transformMessages } from \"./transform-messages.js\";\n\nconst MAX_MISTRAL_ERROR_BODY_CHARS = 4000;\n\n/**\n * Provider-specific options for the Mistral API.\n */\ntype MistralReasoningEffort = \"none\" | \"low\" | \"medium\" | \"high\" | \"max\";\n\nexport interface MistralOptions extends StreamOptions {\n\ttoolChoice?: \"auto\" | \"none\" | \"any\" | \"required\" | { type: \"function\"; function: { name: string } };\n\tpromptMode?: \"reasoning\";\n\treasoningEffort?: MistralReasoningEffort;\n}\n\n/**\n * Stream responses from Mistral using `chat.stream`.\n */\nexport const streamMistral: StreamFunction<\"mistral-conversations\", MistralOptions> = (\n\tmodel: Model<\"mistral-conversations\">,\n\tcontext: Context,\n\toptions?: MistralOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output = createOutput(model);\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t\t}\n\n\t\t\t// Intentionally per-request: avoids shared SDK mutable state across concurrent consumers.\n\t\t\tconst mistral = new Mistral({\n\t\t\t\tapiKey,\n\t\t\t\tserverURL: model.baseUrl,\n\t\t\t});\n\n\t\t\tconst normalizeMistralToolCallId = createProviderToolCallIdNormalizer(model);\n\t\t\tconst transformedMessages = transformMessages(context.messages, model, (id) => normalizeMistralToolCallId(id));\n\n\t\t\tlet payload = buildChatPayload(model, context, transformedMessages, options);\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload as ChatCompletionStreamRequest;\n\t\t\t}\n\t\t\tconst mistralStream = await mistral.chat.stream(payload, buildRequestOptions(model, options));\n\t\t\tstream.push({ type: \"start\", partial: output });\n\t\t\tawait consumeChatStream(model, output, stream, mistralStream);\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(output.errorMessage || \"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\t// partialArgs is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialArgs?: string }).partialArgs;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMetadata = normalizeProviderError(error).errorMetadata;\n\t\t\toutput.errorMessage = formatMistralError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\n/**\n * Maps provider-agnostic `SimpleStreamOptions` to Mistral options.\n */\nexport const streamSimpleMistral: StreamFunction<\"mistral-conversations\", SimpleStreamOptions> = (\n\tmodel: Model<\"mistral-conversations\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider, options?.env);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst base = buildBaseOptions(model, context, options, apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoning = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\t// Effort metadata selects reasoning_effort; unmapped reasoning models use prompt_mode.\n\tconst effortMap = model.reasoning ? model.thinkingLevelMap : undefined;\n\tconst reasoningEffort = effortMap\n\t\t? reasoning\n\t\t\t? (effortMap[reasoning] ?? \"high\")\n\t\t\t: (effortMap.off ?? undefined)\n\t\t: undefined;\n\n\treturn streamMistral(model, context, {\n\t\t...base,\n\t\tpromptMode: model.reasoning && !effortMap && reasoning ? \"reasoning\" : undefined,\n\t\treasoningEffort: reasoningEffort as MistralReasoningEffort | undefined,\n\t} satisfies MistralOptions);\n};\n\nfunction createOutput(model: Model<\"mistral-conversations\">): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction formatMistralError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst sdkError = error as Error & { statusCode?: unknown; body?: unknown };\n\t\tconst statusCode = typeof sdkError.statusCode === \"number\" ? sdkError.statusCode : undefined;\n\t\tconst bodyText = typeof sdkError.body === \"string\" ? sdkError.body.trim() : undefined;\n\t\tif (statusCode !== undefined && bodyText) {\n\t\t\treturn `Mistral API error (${statusCode}): ${truncateErrorText(bodyText, MAX_MISTRAL_ERROR_BODY_CHARS)}`;\n\t\t}\n\t\tif (statusCode !== undefined) return `Mistral API error (${statusCode}): ${error.message}`;\n\t\treturn error.message;\n\t}\n\treturn safeJsonStringify(error);\n}\n\nfunction truncateErrorText(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;\n}\n\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\tconst serialized = JSON.stringify(value);\n\t\treturn serialized === undefined ? String(value) : serialized;\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n\nfunction buildRequestOptions(model: Model<\"mistral-conversations\">, options?: MistralOptions) {\n\tconst requestOptions: {\n\t\tsignal?: AbortSignal;\n\t\tretries: { strategy: \"none\" };\n\t\theaders?: Record<string, string>;\n\t} = {\n\t\tretries: { strategy: \"none\" },\n\t};\n\tif (options?.signal) requestOptions.signal = options.signal;\n\n\tconst headers: Record<string, string> = {};\n\tif (model.headers) Object.assign(headers, model.headers);\n\tif (options?.headers) Object.assign(headers, options.headers);\n\n\t// Mistral infrastructure uses `x-affinity` for KV-cache reuse (prefix caching).\n\t// Respect explicit caller-provided header values.\n\tif (options?.sessionId && !headers[\"x-affinity\"]) {\n\t\theaders[\"x-affinity\"] = options.sessionId;\n\t}\n\n\tif (Object.keys(headers).length > 0) {\n\t\trequestOptions.headers = headers;\n\t}\n\n\treturn requestOptions;\n}\n\nfunction buildChatPayload(\n\tmodel: Model<\"mistral-conversations\">,\n\tcontext: Context,\n\tmessages: Message[],\n\toptions?: MistralOptions,\n): ChatCompletionStreamRequest {\n\tconst payload: ChatCompletionStreamRequest = {\n\t\tmodel: model.id,\n\t\tstream: true,\n\t\tmessages: toChatMessages(messages, model.input.includes(\"image\")),\n\t};\n\n\tif (context.tools?.length) payload.tools = toFunctionTools(context.tools);\n\tif (options?.temperature !== undefined) payload.temperature = options.temperature;\n\tif (options?.maxTokens !== undefined) payload.maxTokens = options.maxTokens;\n\tif (options?.toolChoice) payload.toolChoice = mapToolChoice(options.toolChoice);\n\tif (options?.promptMode) payload.promptMode = options.promptMode;\n\tif (options?.reasoningEffort) {\n\t\t// The SDK's forward-compatible open enum supports catalog efforts not yet named by its types.\n\t\tpayload.reasoningEffort = options.reasoningEffort === \"max\" ? unrecognized(\"max\") : options.reasoningEffort;\n\t}\n\n\tif (context.systemPrompt) {\n\t\tpayload.messages.unshift({\n\t\t\trole: \"system\",\n\t\t\tcontent: sanitizeSurrogates(context.systemPrompt),\n\t\t});\n\t}\n\n\treturn payload;\n}\n\nasync function consumeChatStream(\n\tmodel: Model<\"mistral-conversations\">,\n\toutput: AssistantMessage,\n\tstream: AssistantMessageEventStream,\n\tmistralStream: AsyncIterable<CompletionEvent>,\n): Promise<void> {\n\tlet currentBlock: TextContent | ThinkingContent | null = null;\n\tconst blocks = output.content;\n\tconst blockIndex = () => blocks.length - 1;\n\tconst toolBlocksByKey = new Map<string | number, number>();\n\tconst normalizeGeneratedToolCallId = createProviderToolCallIdNormalizer(model);\n\n\tconst finishCurrentBlock = (block?: typeof currentBlock) => {\n\t\tif (!block) return;\n\t\tif (block.type === \"text\") {\n\t\t\tstream.push({\n\t\t\t\ttype: \"text_end\",\n\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\tcontent: block.text,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (block.type === \"thinking\") {\n\t\t\tstream.push({\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\tcontent: block.thinking,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t}\n\t};\n\n\tfor await (const event of mistralStream) {\n\t\tconst chunk = event.data;\n\t\t// Mistral's streamed CompletionChunk carries an id field. Keep the first non-empty one,\n\t\t// mirroring how OpenAI-style streaming exposes a stable response identifier per stream.\n\t\toutput.responseId ||= chunk.id;\n\n\t\tif (chunk.usage) {\n\t\t\toutput.usage.input = chunk.usage.promptTokens || 0;\n\t\t\toutput.usage.output = chunk.usage.completionTokens || 0;\n\t\t\toutput.usage.cacheRead = 0;\n\t\t\toutput.usage.cacheWrite = 0;\n\t\t\toutput.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output;\n\t\t\tcalculateCost(model, output.usage);\n\t\t}\n\n\t\tconst choice = chunk.choices[0];\n\t\tif (!choice) continue;\n\n\t\tif (choice.finishReason) {\n\t\t\toutput.rawStopReason = choice.finishReason;\n\t\t\tconst stopReasonResult = mapChatStopReason(choice.finishReason);\n\t\t\toutput.stopReason = stopReasonResult.stopReason;\n\t\t\tif (stopReasonResult.errorMessage) {\n\t\t\t\toutput.errorMessage = stopReasonResult.errorMessage;\n\t\t\t}\n\t\t}\n\n\t\tconst delta = choice.delta;\n\t\tif (delta.content !== null && delta.content !== undefined) {\n\t\t\tconst contentItems = typeof delta.content === \"string\" ? [delta.content] : delta.content;\n\t\t\tfor (const item of contentItems) {\n\t\t\t\tif (typeof item === \"string\") {\n\t\t\t\t\tconst textDelta = sanitizeSurrogates(item);\n\t\t\t\t\t// GLM models on Mistral send empty content deltas around thinking and tool calls.\n\t\t\t\t\t// Opening a block for them splits thinking into multiple blocks, which Mistral rejects on replay.\n\t\t\t\t\tif (!textDelta) continue;\n\t\t\t\t\tif (!currentBlock || currentBlock.type !== \"text\") {\n\t\t\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t\tcurrentBlock.text += textDelta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: textDelta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (item.type === \"thinking\") {\n\t\t\t\t\tconst deltaText = item.thinking\n\t\t\t\t\t\t.map((part) => (\"text\" in part ? part.text : \"\"))\n\t\t\t\t\t\t.filter((text) => text.length > 0)\n\t\t\t\t\t\t.join(\"\");\n\t\t\t\t\tconst thinkingDelta = sanitizeSurrogates(deltaText);\n\t\t\t\t\tif (!thinkingDelta) continue;\n\t\t\t\t\tif (!currentBlock || currentBlock.type !== \"thinking\") {\n\t\t\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t\tcurrentBlock.thinking += thinkingDelta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: thinkingDelta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\tconst textDelta = sanitizeSurrogates(item.text);\n\t\t\t\t\tif (!textDelta) continue;\n\t\t\t\t\tif (!currentBlock || currentBlock.type !== \"text\") {\n\t\t\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t\tcurrentBlock.text += textDelta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: textDelta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst toolCalls = delta.toolCalls || [];\n\t\tfor (const toolCall of toolCalls) {\n\t\t\tif (currentBlock) {\n\t\t\t\tfinishCurrentBlock(currentBlock);\n\t\t\t\tcurrentBlock = null;\n\t\t\t}\n\t\t\tconst callId =\n\t\t\t\ttoolCall.id && toolCall.id !== \"null\"\n\t\t\t\t\t? toolCall.id\n\t\t\t\t\t: normalizeGeneratedToolCallId(`toolcall:${toolCall.index ?? 0}`);\n\t\t\tconst key = toolCall.index ?? callId;\n\t\t\tconst existingIndex = toolBlocksByKey.get(key);\n\t\t\tlet block: (ToolCall & { partialArgs?: string }) | undefined;\n\n\t\t\tif (existingIndex !== undefined) {\n\t\t\t\tconst existing = output.content[existingIndex];\n\t\t\t\tif (existing?.type === \"toolCall\") {\n\t\t\t\t\tblock = existing as ToolCall & { partialArgs?: string };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!block) {\n\t\t\t\tblock = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: callId,\n\t\t\t\t\tname: toolCall.function.name,\n\t\t\t\t\targuments: {},\n\t\t\t\t\tpartialArgs: \"\",\n\t\t\t\t};\n\t\t\t\toutput.content.push(block);\n\t\t\t\ttoolBlocksByKey.set(key, output.content.length - 1);\n\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t}\n\n\t\t\tconst argsDelta =\n\t\t\t\ttypeof toolCall.function.arguments === \"string\"\n\t\t\t\t\t? toolCall.function.arguments\n\t\t\t\t\t: JSON.stringify(toolCall.function.arguments || {});\n\t\t\tblock.partialArgs = (block.partialArgs || \"\") + argsDelta;\n\t\t\tblock.arguments = parseStreamingJson<Record<string, unknown>>(block.partialArgs);\n\t\t\tstream.push({\n\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\tcontentIndex: toolBlocksByKey.get(key)!,\n\t\t\t\tdelta: argsDelta,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t}\n\t}\n\n\tfinishCurrentBlock(currentBlock);\n\tfor (const index of toolBlocksByKey.values()) {\n\t\tconst block = output.content[index];\n\t\tif (block.type !== \"toolCall\") continue;\n\t\tconst toolBlock = block as ToolCall & { partialArgs?: string };\n\t\tfinalizeToolCallArguments(toolBlock, toolBlock.partialArgs);\n\t\t// Finalize in-place and strip the scratch buffer so replay only\n\t\t// carries parsed arguments.\n\t\tdelete toolBlock.partialArgs;\n\t\tstream.push({\n\t\t\ttype: \"toolcall_end\",\n\t\t\tcontentIndex: index,\n\t\t\ttoolCall: toolBlock,\n\t\t\tpartial: output,\n\t\t});\n\t}\n}\n\nfunction toFunctionTools(tools: Tool[]): Array<FunctionTool & { type: \"function\" }> {\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\",\n\t\tfunction: {\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: stripSymbolKeys(tool.parameters) as Record<string, unknown>,\n\t\t\tstrict: false,\n\t\t},\n\t}));\n}\n\nfunction stripSymbolKeys(value: unknown): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => stripSymbolKeys(item));\n\t}\n\n\tif (value && typeof value === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, entry] of Object.entries(value)) {\n\t\t\tresult[key] = stripSymbolKeys(entry);\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn value;\n}\n\nfunction toChatMessages(messages: Message[], supportsImages: boolean): ChatCompletionStreamRequestMessage[] {\n\tconst result: ChatCompletionStreamRequestMessage[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tresult.push({ role: \"user\", content: sanitizeSurrogates(msg.content) });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst hadImages = msg.content.some((item) => item.type === \"image\");\n\t\t\tconst content: ContentChunk[] = msg.content\n\t\t\t\t.filter((item) => item.type === \"text\" || supportsImages)\n\t\t\t\t.map((item) => {\n\t\t\t\t\tif (item.type === \"text\") return { type: \"text\", text: sanitizeSurrogates(item.text) };\n\t\t\t\t\treturn { type: \"image_url\", imageUrl: `data:${item.mimeType};base64,${item.data}` };\n\t\t\t\t});\n\t\t\tif (content.length > 0) {\n\t\t\t\tresult.push({ role: \"user\", content });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (hadImages && !supportsImages) {\n\t\t\t\tresult.push({ role: \"user\", content: \"(image omitted: model does not support images)\" });\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst contentParts: ContentChunk[] = [];\n\t\t\tconst toolCalls: Array<{ id: string; type: \"function\"; function: { name: string; arguments: string } }> = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (block.text.trim().length > 0) {\n\t\t\t\t\t\tcontentParts.push({ type: \"text\", text: sanitizeSurrogates(block.text) });\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinking.trim().length > 0) {\n\t\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: [{ type: \"text\", text: sanitizeSurrogates(block.thinking) }],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (block.type !== \"toolCall\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttoolCalls.push({\n\t\t\t\t\tid: block.id,\n\t\t\t\t\ttype: \"function\",\n\t\t\t\t\tfunction: { name: block.name, arguments: JSON.stringify(block.arguments || {}) },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst assistantMessage: ChatCompletionStreamRequestMessage = { role: \"assistant\" };\n\t\t\tif (contentParts.length > 0) assistantMessage.content = contentParts;\n\t\t\tif (toolCalls.length > 0) assistantMessage.toolCalls = toolCalls;\n\t\t\tif (contentParts.length > 0 || toolCalls.length > 0) result.push(assistantMessage);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst toolContent: ContentChunk[] = [];\n\t\tconst textResult = msg.content\n\t\t\t.filter((part) => part.type === \"text\")\n\t\t\t.map((part) => (part.type === \"text\" ? sanitizeSurrogates(part.text) : \"\"))\n\t\t\t.join(\"\\n\");\n\t\tconst hasImages = msg.content.some((part) => part.type === \"image\");\n\t\tconst toolText = buildToolResultText(textResult, hasImages, supportsImages, msg.isError);\n\t\ttoolContent.push({ type: \"text\", text: toolText });\n\t\tfor (const part of msg.content) {\n\t\t\tif (!supportsImages) continue;\n\t\t\tif (part.type !== \"image\") continue;\n\t\t\ttoolContent.push({\n\t\t\t\ttype: \"image_url\",\n\t\t\t\timageUrl: `data:${part.mimeType};base64,${part.data}`,\n\t\t\t});\n\t\t}\n\t\tresult.push({\n\t\t\trole: \"tool\",\n\t\t\ttoolCallId: msg.toolCallId,\n\t\t\tname: msg.toolName,\n\t\t\tcontent: toolContent,\n\t\t});\n\t}\n\n\treturn result;\n}\n\nfunction buildToolResultText(text: string, hasImages: boolean, supportsImages: boolean, isError: boolean): string {\n\tconst trimmed = text.trim();\n\tconst errorPrefix = isError ? \"[tool error] \" : \"\";\n\n\tif (trimmed.length > 0) {\n\t\tconst imageSuffix = hasImages && !supportsImages ? \"\\n[tool image omitted: model does not support images]\" : \"\";\n\t\treturn `${errorPrefix}${trimmed}${imageSuffix}`;\n\t}\n\n\tif (hasImages) {\n\t\tif (supportsImages) {\n\t\t\treturn isError ? \"[tool error] (see attached image)\" : \"(see attached image)\";\n\t\t}\n\t\treturn isError\n\t\t\t? \"[tool error] (image omitted: model does not support images)\"\n\t\t\t: \"(image omitted: model does not support images)\";\n\t}\n\n\treturn isError ? \"[tool error] (no tool output)\" : \"(no tool output)\";\n}\n\nfunction mapToolChoice(\n\tchoice: MistralOptions[\"toolChoice\"],\n): \"auto\" | \"none\" | \"any\" | \"required\" | { type: \"function\"; function: { name: string } } | undefined {\n\tif (!choice) return undefined;\n\tif (choice === \"auto\" || choice === \"none\" || choice === \"any\" || choice === \"required\") {\n\t\treturn choice as any;\n\t}\n\treturn {\n\t\ttype: \"function\",\n\t\tfunction: { name: choice.function.name },\n\t};\n}\n\nfunction mapChatStopReason(reason: string | null): { stopReason: StopReason; errorMessage?: string } {\n\tif (reason === null) return { stopReason: \"stop\" };\n\tswitch (reason) {\n\t\tcase \"stop\":\n\t\t\treturn { stopReason: \"stop\" };\n\t\tcase \"length\":\n\t\tcase \"model_length\":\n\t\t\treturn { stopReason: \"length\" };\n\t\tcase \"tool_calls\":\n\t\t\treturn { stopReason: \"toolUse\" };\n\t\tcase \"error\":\n\t\t\t// Mistral reports transient server failures this way; \"server error\" makes the message retryable.\n\t\t\treturn { stopReason: \"error\", errorMessage: \"Mistral stopped with: error (server error)\" };\n\t\tdefault:\n\t\t\treturn { stopReason: \"error\", errorMessage: `Mistral stopped with: ${reason}` };\n\t}\n}\n"]}
@@ -1,13 +1,14 @@
1
1
  import { Mistral } from "@mistralai/mistralai";
2
+ import { unrecognized } from "@mistralai/mistralai/types";
2
3
  import { getEnvApiKey } from "../env-api-keys.js";
3
4
  import { calculateCost, clampThinkingLevel } from "../models.js";
5
+ import { normalizeProviderError } from "../utils/error-body.js";
4
6
  import { AssistantMessageEventStream } from "../utils/event-stream.js";
5
- import { shortHash } from "../utils/hash.js";
6
- import { parseStreamingJson } from "../utils/json-parse.js";
7
+ import { finalizeToolCallArguments, parseStreamingJson } from "../utils/json-parse.js";
7
8
  import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
9
+ import { createProviderToolCallIdNormalizer } from "../utils/tool-call-id.js";
8
10
  import { buildBaseOptions } from "./simple-options.js";
9
11
  import { transformMessages } from "./transform-messages.js";
10
- const MISTRAL_TOOL_CALL_ID_LENGTH = 9;
11
12
  const MAX_MISTRAL_ERROR_BODY_CHARS = 4000;
12
13
  /**
13
14
  * Stream responses from Mistral using `chat.stream`.
@@ -26,7 +27,7 @@ export const streamMistral = (model, context, options) => {
26
27
  apiKey,
27
28
  serverURL: model.baseUrl,
28
29
  });
29
- const normalizeMistralToolCallId = createMistralToolCallIdNormalizer();
30
+ const normalizeMistralToolCallId = createProviderToolCallIdNormalizer(model);
30
31
  const transformedMessages = transformMessages(context.messages, model, (id) => normalizeMistralToolCallId(id));
31
32
  let payload = buildChatPayload(model, context, transformedMessages, options);
32
33
  const nextPayload = await options?.onPayload?.(payload, model);
@@ -40,7 +41,7 @@ export const streamMistral = (model, context, options) => {
40
41
  throw new Error("Request was aborted");
41
42
  }
42
43
  if (output.stopReason === "aborted" || output.stopReason === "error") {
43
- throw new Error("An unknown error occurred");
44
+ throw new Error(output.errorMessage || "An unknown error occurred");
44
45
  }
45
46
  stream.push({ type: "done", reason: output.stopReason, message: output });
46
47
  stream.end();
@@ -51,6 +52,7 @@ export const streamMistral = (model, context, options) => {
51
52
  delete block.partialArgs;
52
53
  }
53
54
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
55
+ output.errorMetadata = normalizeProviderError(error).errorMetadata;
54
56
  output.errorMessage = formatMistralError(error);
55
57
  stream.push({ type: "error", reason: output.stopReason, error: output });
56
58
  stream.end();
@@ -66,14 +68,20 @@ export const streamSimpleMistral = (model, context, options) => {
66
68
  if (!apiKey) {
67
69
  throw new Error(`No API key for provider: ${model.provider}`);
68
70
  }
69
- const base = buildBaseOptions(model, options, apiKey);
71
+ const base = buildBaseOptions(model, context, options, apiKey);
70
72
  const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;
71
73
  const reasoning = clampedReasoning === "off" ? undefined : clampedReasoning;
72
- const shouldUseReasoning = model.reasoning && reasoning !== undefined;
74
+ // Effort metadata selects reasoning_effort; unmapped reasoning models use prompt_mode.
75
+ const effortMap = model.reasoning ? model.thinkingLevelMap : undefined;
76
+ const reasoningEffort = effortMap
77
+ ? reasoning
78
+ ? (effortMap[reasoning] ?? "high")
79
+ : (effortMap.off ?? undefined)
80
+ : undefined;
73
81
  return streamMistral(model, context, {
74
82
  ...base,
75
- promptMode: shouldUseReasoning && usesPromptModeReasoning(model) ? "reasoning" : undefined,
76
- reasoningEffort: shouldUseReasoning && usesReasoningEffort(model) ? mapReasoningEffort(model, reasoning) : undefined,
83
+ promptMode: model.reasoning && !effortMap && reasoning ? "reasoning" : undefined,
84
+ reasoningEffort: reasoningEffort,
77
85
  });
78
86
  };
79
87
  function createOutput(model) {
@@ -95,36 +103,6 @@ function createOutput(model) {
95
103
  timestamp: Date.now(),
96
104
  };
97
105
  }
98
- function createMistralToolCallIdNormalizer() {
99
- const idMap = new Map();
100
- const reverseMap = new Map();
101
- return (id) => {
102
- const existing = idMap.get(id);
103
- if (existing)
104
- return existing;
105
- let attempt = 0;
106
- while (true) {
107
- const candidate = deriveMistralToolCallId(id, attempt);
108
- const owner = reverseMap.get(candidate);
109
- if (!owner || owner === id) {
110
- idMap.set(id, candidate);
111
- reverseMap.set(candidate, id);
112
- return candidate;
113
- }
114
- attempt++;
115
- }
116
- };
117
- }
118
- function deriveMistralToolCallId(id, attempt) {
119
- const normalized = id.replace(/[^a-zA-Z0-9]/g, "");
120
- if (attempt === 0 && normalized.length === MISTRAL_TOOL_CALL_ID_LENGTH)
121
- return normalized;
122
- const seedBase = normalized || id;
123
- const seed = attempt === 0 ? seedBase : `${seedBase}:${attempt}`;
124
- return shortHash(seed)
125
- .replace(/[^a-zA-Z0-9]/g, "")
126
- .slice(0, MISTRAL_TOOL_CALL_ID_LENGTH);
127
- }
128
106
  function formatMistralError(error) {
129
107
  if (error instanceof Error) {
130
108
  const sdkError = error;
@@ -190,8 +168,10 @@ function buildChatPayload(model, context, messages, options) {
190
168
  payload.toolChoice = mapToolChoice(options.toolChoice);
191
169
  if (options?.promptMode)
192
170
  payload.promptMode = options.promptMode;
193
- if (options?.reasoningEffort)
194
- payload.reasoningEffort = options.reasoningEffort;
171
+ if (options?.reasoningEffort) {
172
+ // The SDK's forward-compatible open enum supports catalog efforts not yet named by its types.
173
+ payload.reasoningEffort = options.reasoningEffort === "max" ? unrecognized("max") : options.reasoningEffort;
174
+ }
195
175
  if (context.systemPrompt) {
196
176
  payload.messages.unshift({
197
177
  role: "system",
@@ -205,6 +185,7 @@ async function consumeChatStream(model, output, stream, mistralStream) {
205
185
  const blocks = output.content;
206
186
  const blockIndex = () => blocks.length - 1;
207
187
  const toolBlocksByKey = new Map();
188
+ const normalizeGeneratedToolCallId = createProviderToolCallIdNormalizer(model);
208
189
  const finishCurrentBlock = (block) => {
209
190
  if (!block)
210
191
  return;
@@ -243,7 +224,12 @@ async function consumeChatStream(model, output, stream, mistralStream) {
243
224
  if (!choice)
244
225
  continue;
245
226
  if (choice.finishReason) {
246
- output.stopReason = mapChatStopReason(choice.finishReason);
227
+ output.rawStopReason = choice.finishReason;
228
+ const stopReasonResult = mapChatStopReason(choice.finishReason);
229
+ output.stopReason = stopReasonResult.stopReason;
230
+ if (stopReasonResult.errorMessage) {
231
+ output.errorMessage = stopReasonResult.errorMessage;
232
+ }
247
233
  }
248
234
  const delta = choice.delta;
249
235
  if (delta.content !== null && delta.content !== undefined) {
@@ -251,6 +237,10 @@ async function consumeChatStream(model, output, stream, mistralStream) {
251
237
  for (const item of contentItems) {
252
238
  if (typeof item === "string") {
253
239
  const textDelta = sanitizeSurrogates(item);
240
+ // GLM models on Mistral send empty content deltas around thinking and tool calls.
241
+ // Opening a block for them splits thinking into multiple blocks, which Mistral rejects on replay.
242
+ if (!textDelta)
243
+ continue;
254
244
  if (!currentBlock || currentBlock.type !== "text") {
255
245
  finishCurrentBlock(currentBlock);
256
246
  currentBlock = { type: "text", text: "" };
@@ -291,6 +281,8 @@ async function consumeChatStream(model, output, stream, mistralStream) {
291
281
  }
292
282
  if (item.type === "text") {
293
283
  const textDelta = sanitizeSurrogates(item.text);
284
+ if (!textDelta)
285
+ continue;
294
286
  if (!currentBlock || currentBlock.type !== "text") {
295
287
  finishCurrentBlock(currentBlock);
296
288
  currentBlock = { type: "text", text: "" };
@@ -315,8 +307,8 @@ async function consumeChatStream(model, output, stream, mistralStream) {
315
307
  }
316
308
  const callId = toolCall.id && toolCall.id !== "null"
317
309
  ? toolCall.id
318
- : deriveMistralToolCallId(`toolcall:${toolCall.index ?? 0}`, 0);
319
- const key = `${callId}:${toolCall.index || 0}`;
310
+ : normalizeGeneratedToolCallId(`toolcall:${toolCall.index ?? 0}`);
311
+ const key = toolCall.index ?? callId;
320
312
  const existingIndex = toolBlocksByKey.get(key);
321
313
  let block;
322
314
  if (existingIndex !== undefined) {
@@ -356,7 +348,7 @@ async function consumeChatStream(model, output, stream, mistralStream) {
356
348
  if (block.type !== "toolCall")
357
349
  continue;
358
350
  const toolBlock = block;
359
- toolBlock.arguments = parseStreamingJson(toolBlock.partialArgs);
351
+ finalizeToolCallArguments(toolBlock, toolBlock.partialArgs);
360
352
  // Finalize in-place and strip the scratch buffer so replay only
361
353
  // carries parsed arguments.
362
354
  delete toolBlock.partialArgs;
@@ -498,15 +490,6 @@ function buildToolResultText(text, hasImages, supportsImages, isError) {
498
490
  }
499
491
  return isError ? "[tool error] (no tool output)" : "(no tool output)";
500
492
  }
501
- function usesReasoningEffort(model) {
502
- return model.id === "mistral-small-2603" || model.id === "mistral-small-latest" || model.id === "mistral-medium-3.5";
503
- }
504
- function usesPromptModeReasoning(model) {
505
- return model.reasoning && !usesReasoningEffort(model);
506
- }
507
- function mapReasoningEffort(model, level) {
508
- return (model.thinkingLevelMap?.[level] ?? "high");
509
- }
510
493
  function mapToolChoice(choice) {
511
494
  if (!choice)
512
495
  return undefined;
@@ -520,19 +503,20 @@ function mapToolChoice(choice) {
520
503
  }
521
504
  function mapChatStopReason(reason) {
522
505
  if (reason === null)
523
- return "stop";
506
+ return { stopReason: "stop" };
524
507
  switch (reason) {
525
508
  case "stop":
526
- return "stop";
509
+ return { stopReason: "stop" };
527
510
  case "length":
528
511
  case "model_length":
529
- return "length";
512
+ return { stopReason: "length" };
530
513
  case "tool_calls":
531
- return "toolUse";
514
+ return { stopReason: "toolUse" };
532
515
  case "error":
533
- return "error";
516
+ // Mistral reports transient server failures this way; "server error" makes the message retryable.
517
+ return { stopReason: "error", errorMessage: "Mistral stopped with: error (server error)" };
534
518
  default:
535
- return "stop";
519
+ return { stopReason: "error", errorMessage: `Mistral stopped with: ${reason}` };
536
520
  }
537
521
  }
538
522
  //# sourceMappingURL=mistral.js.map