diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index f651a5b91aaf..c784c4f8e3ca 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -51,27 +51,27 @@ export namespace ProviderTransform { model: Provider.Model, options: Record, ): ModelMessage[] { - // Anthropic rejects messages with empty content - filter out empty string messages - // and remove empty text/reasoning parts from array content - if (model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/amazon-bedrock") { - msgs = msgs - .map((msg) => { - if (typeof msg.content === "string") { - if (msg.content === "") return undefined - return msg + // Filter out messages with empty content - many providers (Anthropic, Bedrock, + // Moonshot/Kimi, OpenAI-compatible) reject empty assistant messages. + // Apply unconditionally since no provider accepts truly empty messages. + // See: https://github.com/anomalyco/opencode/issues/6056 + msgs = msgs + .map((msg) => { + if (typeof msg.content === "string") { + if (msg.content === "") return undefined + return msg + } + if (!Array.isArray(msg.content)) return msg + const filtered = msg.content.filter((part) => { + if (part.type === "text" || part.type === "reasoning") { + return part.text !== "" } - if (!Array.isArray(msg.content)) return msg - const filtered = msg.content.filter((part) => { - if (part.type === "text" || part.type === "reasoning") { - return part.text !== "" - } - return true - }) - if (filtered.length === 0) return undefined - return { ...msg, content: filtered } + return true }) - .filter((msg): msg is ModelMessage => msg !== undefined && msg.content !== "") - } + if (filtered.length === 0) return undefined + return { ...msg, content: filtered } + }) + .filter((msg): msg is ModelMessage => msg !== undefined && msg.content !== "") if (model.api.id.includes("claude")) { const scrub = (id: string) => id.replace(/[^a-zA-Z0-9_-]/g, "_")