diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 9a955f5c..94d2861c 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -3,77 +3,21 @@ import { unique } from "remeda" import type { JSONSchema } from "zod/v4/core" export namespace ProviderTransform { - function normalizeMessages( - msgs: ModelMessage[], - providerID: string, - modelID: string, - ): ModelMessage[] { - if (modelID.includes("claude")) { - return msgs.map((msg) => { - if ((msg.role === "assistant" || msg.role === "tool") && Array.isArray(msg.content)) { - msg.content = msg.content.map((part) => { - if ( - (part.type === "tool-call" || part.type === "tool-result") && - "toolCallId" in part - ) { - return { - ...part, - toolCallId: part.toolCallId.replace(/[^a-zA-Z0-9_-]/g, "_"), - } + function normalizeToolCallIds(msgs: ModelMessage[]): ModelMessage[] { + return msgs.map((msg) => { + if ((msg.role === "assistant" || msg.role === "tool") && Array.isArray(msg.content)) { + msg.content = msg.content.map((part) => { + if ((part.type === "tool-call" || part.type === "tool-result") && "toolCallId" in part) { + return { + ...part, + toolCallId: part.toolCallId.replace(/[^a-zA-Z0-9_-]/g, "_"), } - return part - }) - } - return msg - }) - } - if (providerID === "mistral" || modelID.toLowerCase().includes("mistral")) { - const result: ModelMessage[] = [] - for (let i = 0; i < msgs.length; i++) { - const msg = msgs[i] - const prevMsg = msgs[i - 1] - const nextMsg = msgs[i + 1] - - if ((msg.role === "assistant" || msg.role === "tool") && Array.isArray(msg.content)) { - msg.content = msg.content.map((part) => { - if ( - (part.type === "tool-call" || part.type === "tool-result") && - "toolCallId" in part - ) { - // Mistral requires alphanumeric tool call IDs with exactly 9 characters - const normalizedId = part.toolCallId - .replace(/[^a-zA-Z0-9]/g, "") // Remove non-alphanumeric characters - .substring(0, 9) // Take first 9 characters - .padEnd(9, "0") // Pad with zeros if less than 9 characters - - return { - ...part, - toolCallId: normalizedId, - } - } - return part - }) - } - - result.push(msg) - - // Fix message sequence: tool messages cannot be followed by user messages - if (msg.role === "tool" && nextMsg?.role === "user") { - result.push({ - role: "assistant", - content: [ - { - type: "text", - text: "Done.", - }, - ], - }) - } + } + return part + }) } - return result - } - - return msgs + return msg + }) } function applyCaching(msgs: ModelMessage[], providerID: string): ModelMessage[] { @@ -120,7 +64,9 @@ export namespace ProviderTransform { } export function message(msgs: ModelMessage[], providerID: string, modelID: string) { - msgs = normalizeMessages(msgs, providerID, modelID) + if (modelID.includes("claude")) { + msgs = normalizeToolCallIds(msgs) + } if (providerID === "anthropic" || modelID.includes("anthropic") || modelID.includes("claude")) { msgs = applyCaching(msgs, providerID) } @@ -151,12 +97,12 @@ export namespace ProviderTransform { } if (modelID.includes("gpt-5") && !modelID.includes("gpt-5-chat")) { - if (!modelID.includes("codex") && !modelID.includes("gpt-5-pro")) { - result["reasoningEffort"] = "medium" + if (modelID.includes("codex")) { + result["store"] = false } - if (providerID !== "azure") { - result["textVerbosity"] = modelID.includes("codex") ? "medium" : "low" + if (!modelID.includes("codex") && !modelID.includes("gpt-5-pro")) { + result["reasoningEffort"] = "medium" } if (providerID === "opencode") {