From fada1a538f4eb11d617229f15f23aaa8cfbd2d2a Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:53:51 -0500 Subject: [PATCH] fix(provider): serialize Mistral prompt cache keys (#38448) --- bun.lock | 17 ++++- package.json | 1 + packages/core/package.json | 2 +- packages/core/test/provider-mistral.test.ts | 28 +++++++ packages/opencode/package.json | 2 +- patches/@ai-sdk%2Fmistral@3.0.34.patch | 84 +++++++++++++++++++++ 6 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 packages/core/test/provider-mistral.test.ts create mode 100644 patches/@ai-sdk%2Fmistral@3.0.34.patch diff --git a/bun.lock b/bun.lock index 5c7a792abc0..5114ec200db 100644 --- a/bun.lock +++ b/bun.lock @@ -302,7 +302,7 @@ "@ai-sdk/google": "3.0.73", "@ai-sdk/google-vertex": "4.0.128", "@ai-sdk/groq": "3.0.31", - "@ai-sdk/mistral": "3.0.27", + "@ai-sdk/mistral": "3.0.34", "@ai-sdk/openai": "3.0.84", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/perplexity": "3.0.26", @@ -577,7 +577,7 @@ "@ai-sdk/google": "3.0.73", "@ai-sdk/google-vertex": "4.0.128", "@ai-sdk/groq": "3.0.31", - "@ai-sdk/mistral": "3.0.27", + "@ai-sdk/mistral": "3.0.34", "@ai-sdk/openai": "3.0.84", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/perplexity": "3.0.26", @@ -1079,6 +1079,7 @@ "solid-js@1.9.10": "patches/solid-js@1.9.10.patch", "@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch", "pacote@21.5.0": "patches/pacote@21.5.0.patch", + "@ai-sdk/mistral@3.0.34": "patches/@ai-sdk%2Fmistral@3.0.34.patch", }, "overrides": { "@opentui/core": "catalog:", @@ -1199,7 +1200,7 @@ "@ai-sdk/groq": ["@ai-sdk/groq@3.0.31", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XbbugpnFmXGu2TlXiq8KUJskP6/VVbuFcnFIGDzDIB/Chg6XHsNnqrTF80Zxkh0Pd3+NvbM+2Uqrtsndk6bDAg=="], - "@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZXe7nZQgliDdjz5ufH5RKpHWxbN72AzmzzKGbF/z+0K9GN5tUCnftrQRvTRFHA5jAzTapcm2BEevmGLVbMkW+A=="], + "@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.34", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.26" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-HpK28sWGdIfg1vTSScJNtzVdvNRfA4mfCmPmPR+j/MGJ0oAuEJMqxWkL96ZnGPdhZt5KdW09aKovdIe+q2zQ7A=="], "@ai-sdk/openai": ["@ai-sdk/openai@3.0.48", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ALmj/53EXpcRqMbGpPJPP4UOSWw0q4VGpnDo7YctvsynjkrKDmoneDG/1a7VQnSPYHnJp6tTRMf5ZdxZ5whulg=="], @@ -5699,7 +5700,9 @@ "@ai-sdk/groq/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], - "@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], + "@ai-sdk/mistral/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + + "@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.26", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CsKNLKsOpvPujRlIYvoz+Ybw+kGn7J4/fIZa/58+R7iWLLfwn6ifE2G6Yq8K9XvH/I/3bzaDAJ3NhRwEMsLBKQ=="], "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], @@ -6173,6 +6176,8 @@ "ai-gateway-provider/@ai-sdk/deepseek": ["@ai-sdk/deepseek@2.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9DhYurbAvcurOEGN6u2myYDybrrzGfcrkG8hwmFjwTrePW6KCMggm0YxP7e8RkLYcQKqCEMgFlyEB4BM6EmiKg=="], + "ai-gateway-provider/@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZXe7nZQgliDdjz5ufH5RKpHWxbN72AzmzzKGbF/z+0K9GN5tUCnftrQRvTRFHA5jAzTapcm2BEevmGLVbMkW+A=="], + "ai-gateway-provider/@ai-sdk/openai": ["@ai-sdk/openai@3.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Wld+Rbc05KaUn08uBt06eEuwcgalcIFtIl32Yp+GxuZXUQwOb6YeAuq+C6da4ch6BurFoqEaLemJVwjBb7x+PQ=="], "ai-gateway-provider/@ai-sdk/xai": ["@ai-sdk/xai@3.0.82", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-A0VFMufnVf4wODcT3SPQUUzvYXiIO1VhFuXj9r6z/vP4rlo+QRDPw3WSTchcz93ROQWSfBE3I6Szqz342OHi5w=="], @@ -6989,6 +6994,8 @@ "ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], + "ai-gateway-provider/@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], + "ai-gateway-provider/@ai-sdk/xai/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], @@ -7415,6 +7422,8 @@ "ai-gateway-provider/@ai-sdk/deepseek/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "ai-gateway-provider/@ai-sdk/mistral/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], diff --git a/package.json b/package.json index 332d7520a65..372335d724e 100644 --- a/package.json +++ b/package.json @@ -149,6 +149,7 @@ "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", "solid-js@1.9.10": "patches/solid-js@1.9.10.patch", "@ai-sdk/xai@3.0.102": "patches/@ai-sdk%2Fxai@3.0.102.patch", + "@ai-sdk/mistral@3.0.34": "patches/@ai-sdk%2Fmistral@3.0.34.patch", "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", "pacote@21.5.0": "patches/pacote@21.5.0.patch", "@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch", diff --git a/packages/core/package.json b/packages/core/package.json index 17708d29550..e0445e616f5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -72,7 +72,7 @@ "@ai-sdk/google": "3.0.73", "@ai-sdk/google-vertex": "4.0.128", "@ai-sdk/groq": "3.0.31", - "@ai-sdk/mistral": "3.0.27", + "@ai-sdk/mistral": "3.0.34", "@ai-sdk/openai": "3.0.84", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/perplexity": "3.0.26", diff --git a/packages/core/test/provider-mistral.test.ts b/packages/core/test/provider-mistral.test.ts new file mode 100644 index 00000000000..58904ad3b12 --- /dev/null +++ b/packages/core/test/provider-mistral.test.ts @@ -0,0 +1,28 @@ +import { createMistral } from "@ai-sdk/mistral" +import { expect, test } from "bun:test" + +test("Mistral sends promptCacheKey as prompt_cache_key", async () => { + let body: Record | undefined + const mockFetch = Object.assign( + async (_input: Parameters[0], init?: RequestInit) => { + body = JSON.parse(String(init?.body)) + return Response.json({ + id: "response-1", + created: 0, + model: "mistral-large-latest", + object: "chat.completion", + choices: [{ index: 0, message: { role: "assistant", content: "Hello" }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }) + }, + { preconnect: fetch.preconnect }, + ) + const model = createMistral({ apiKey: "test", fetch: mockFetch })("mistral-large-latest") + + await model.doGenerate({ + prompt: [{ role: "user", content: [{ type: "text", text: "Hello" }] }], + providerOptions: { mistral: { promptCacheKey: "session-123" } }, + }) + + expect(body?.prompt_cache_key).toBe("session-123") +}) diff --git a/packages/opencode/package.json b/packages/opencode/package.json index e702acf8cfa..6781bf488e5 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -66,7 +66,7 @@ "@ai-sdk/google": "3.0.73", "@ai-sdk/google-vertex": "4.0.128", "@ai-sdk/groq": "3.0.31", - "@ai-sdk/mistral": "3.0.27", + "@ai-sdk/mistral": "3.0.34", "@ai-sdk/openai": "3.0.84", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/perplexity": "3.0.26", diff --git a/patches/@ai-sdk%2Fmistral@3.0.34.patch b/patches/@ai-sdk%2Fmistral@3.0.34.patch new file mode 100644 index 00000000000..1d771f4fd9f --- /dev/null +++ b/patches/@ai-sdk%2Fmistral@3.0.34.patch @@ -0,0 +1,84 @@ +diff --git a/dist/index.d.ts b/dist/index.d.ts +index 1ca9113bed2728a616db773a8e08d8d6957447d7..15408ec429dc210b5fa43589d81b69c93bf27b2d 100644 +--- a/dist/index.d.ts ++++ b/dist/index.d.ts +@@ -14,6 +14,7 @@ declare const mistralLanguageModelOptions: z.ZodObject<{ + none: "none"; + high: "high"; + }>>; ++ promptCacheKey: z.ZodOptional; + }, z.core.$strip>; + type MistralLanguageModelOptions = z.infer; + +diff --git a/dist/index.js b/dist/index.js +index 45735e524aaff54ea058c99c729c5ffd3c507058..6aca5f6f13da0054ede31c1f1a692e4eaed37d34 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -268,7 +268,8 @@ var mistralLanguageModelOptions = import_v4.z.object({ + * - `'high'`: Enable reasoning + * - `'none'`: Disable reasoning + */ +- reasoningEffort: import_v4.z.enum(["high", "none"]).optional() ++ reasoningEffort: import_v4.z.enum(["high", "none"]).optional(), ++ promptCacheKey: import_v4.z.string().optional() + }); + + // src/mistral-error.ts +@@ -413,6 +414,7 @@ var MistralChatLanguageModel = class { + top_p: topP, + random_seed: seed, + reasoning_effort: options.reasoningEffort, ++ prompt_cache_key: options.promptCacheKey, + // response format: + response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? structuredOutputs && (responseFormat == null ? void 0 : responseFormat.schema) != null ? { + type: "json_schema", +diff --git a/dist/index.mjs b/dist/index.mjs +index 4c22df1cd78a1ba81309c8a86ceecefef4ba4aea..30cd3b1f503860109b7fa2107cd1eb17b70c96be 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -256,7 +256,8 @@ var mistralLanguageModelOptions = z.object({ + * - `'high'`: Enable reasoning + * - `'none'`: Disable reasoning + */ +- reasoningEffort: z.enum(["high", "none"]).optional() ++ reasoningEffort: z.enum(["high", "none"]).optional(), ++ promptCacheKey: z.string().optional() + }); + + // src/mistral-error.ts +@@ -403,6 +404,7 @@ var MistralChatLanguageModel = class { + top_p: topP, + random_seed: seed, + reasoning_effort: options.reasoningEffort, ++ prompt_cache_key: options.promptCacheKey, + // response format: + response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? structuredOutputs && (responseFormat == null ? void 0 : responseFormat.schema) != null ? { + type: "json_schema", +diff --git a/src/mistral-chat-language-model.ts b/src/mistral-chat-language-model.ts +index 480c472d534bedbe8897979673453bd1c29a70b7..e46496da94f7d4af9822897202ca6baae67dae3a 100644 +--- a/src/mistral-chat-language-model.ts ++++ b/src/mistral-chat-language-model.ts +@@ -129,6 +129,7 @@ export class MistralChatLanguageModel implements LanguageModelV3 { + top_p: topP, + random_seed: seed, + reasoning_effort: options.reasoningEffort, ++ prompt_cache_key: options.promptCacheKey, + + // response format: + response_format: +diff --git a/src/mistral-chat-options.ts b/src/mistral-chat-options.ts +index 80fff45fba2c378fa06962f071946bcd2b882a0b..b4fdfa51f3bf11a4220e010c8aca92482cb0c3db 100644 +--- a/src/mistral-chat-options.ts ++++ b/src/mistral-chat-options.ts +@@ -62,6 +62,11 @@ export const mistralLanguageModelOptions = z.object({ + * - `'none'`: Disable reasoning + */ + reasoningEffort: z.enum(['high', 'none']).optional(), ++ ++ /** ++ * A stable identifier used to route requests with shared prompt prefixes. ++ */ ++ promptCacheKey: z.string().optional(), + }); + + export type MistralLanguageModelOptions = z.infer<