feat(ai): add Mistral Medium 3.5 model (#4009)

This commit is contained in:
Johannes Ebeling
2026-04-30 12:18:17 +02:00
committed by GitHub
parent 904b843fee
commit 779d0ef39d
4 changed files with 63 additions and 28 deletions

View File

@@ -1279,6 +1279,27 @@ async function generateModels() {
});
}
// Add missing Mistral Medium 3.5 model until models.dev includes it
if (!allModels.some(m => m.provider === "mistral" && m.id === "mistral-medium-3.5")) {
allModels.push({
id: "mistral-medium-3.5",
name: "Mistral Medium 3.5",
api: "mistral-conversations",
provider: "mistral",
baseUrl: "https://api.mistral.ai",
reasoning: true,
input: ["text", "image"],
cost: {
input: 1.5,
output: 7.5,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 262144, // 256k tokens
maxTokens: 262144,
});
}
// Add "auto" alias for openrouter/auto
if (!allModels.some(m => m.provider === "openrouter" && m.id === "auto")) {
allModels.push({

View File

@@ -5822,6 +5822,23 @@ export const MODELS = {
contextWindow: 262144,
maxTokens: 262144,
} satisfies Model<"mistral-conversations">,
"mistral-medium-3.5": {
id: "mistral-medium-3.5",
name: "Mistral Medium 3.5",
api: "mistral-conversations",
provider: "mistral",
baseUrl: "https://api.mistral.ai",
reasoning: true,
input: ["text", "image"],
cost: {
input: 1.5,
output: 7.5,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 262144,
maxTokens: 262144,
} satisfies Model<"mistral-conversations">,
"mistral-medium-latest": {
id: "mistral-medium-latest",
name: "Mistral Medium (latest)",
@@ -9423,23 +9440,6 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"mistralai/mistral-small-creative": {
id: "mistralai/mistral-small-creative",
name: "Mistral: Mistral Small Creative",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.09999999999999999,
output: 0.3,
cacheRead: 0.01,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"mistralai/mixtral-8x22b-instruct": {
id: "mistralai/mixtral-8x22b-instruct",
name: "Mistral: Mixtral 8x22B Instruct",
@@ -9585,13 +9585,13 @@ export const MODELS = {
reasoning: true,
input: ["text", "image"],
cost: {
input: 0.7448,
output: 4.655,
cacheRead: 0.1463,
input: 0.75,
output: 3.5,
cacheRead: 0.15,
cacheWrite: 0,
},
contextWindow: 256000,
maxTokens: 65536,
contextWindow: 262144,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"nex-agi/deepseek-v3.1-nex-n1": {
id: "nex-agi/deepseek-v3.1-nex-n1",
@@ -12339,13 +12339,13 @@ export const MODELS = {
reasoning: true,
input: ["text", "image"],
cost: {
input: 0.7448,
output: 4.655,
cacheRead: 0.1463,
input: 0.75,
output: 3.5,
cacheRead: 0.15,
cacheWrite: 0,
},
contextWindow: 256000,
maxTokens: 65536,
contextWindow: 262144,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"~openai/gpt-latest": {
id: "~openai/gpt-latest",

View File

@@ -587,7 +587,7 @@ function buildToolResultText(text: string, hasImages: boolean, supportsImages: b
}
function usesReasoningEffort(model: Model<"mistral-conversations">): boolean {
return model.id === "mistral-small-2603" || model.id === "mistral-small-latest";
return model.id === "mistral-small-2603" || model.id === "mistral-small-latest" || model.id === "mistral-medium-3.5";
}
function usesPromptModeReasoning(model: Model<"mistral-conversations">): boolean {

View File

@@ -63,4 +63,18 @@ describe("Mistral reasoning mode selection", () => {
expect(payload.promptMode).toBe("reasoning");
expect(payload.reasoningEffort).toBeUndefined();
});
it("uses reasoning_effort for Mistral Medium 3.5", async () => {
const payload = await capturePayload(getModel("mistral", "mistral-medium-3.5"), { reasoning: "medium" });
expect(payload.reasoningEffort).toBe("high");
expect(payload.promptMode).toBeUndefined();
});
it("omits reasoning controls for Mistral Medium 3.5 when thinking is off", async () => {
const payload = await capturePayload(getModel("mistral", "mistral-medium-3.5"));
expect(payload.reasoningEffort).toBeUndefined();
expect(payload.promptMode).toBeUndefined();
});
});