From f6a00292e68c771836a5d0392e77a29e67f96b4d Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 11 Jun 2026 20:31:40 -0500 Subject: [PATCH] fix(opencode): normalize MCP text MIME types --- packages/opencode/src/session/message-v2.ts | 2 +- packages/opencode/src/session/prompt.ts | 2 +- packages/opencode/test/session/message-v2.test.ts | 7 +++++++ packages/opencode/test/session/prompt.test.ts | 6 +++--- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 951c6a7cfb0..3cff392a12b 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -222,7 +222,7 @@ export const toModelMessagesEffect = Effect.fnUntraced(function* ( // Text, directories, and MCP references are resolved before provider conversion. if ( part.type === "file" && - part.mime !== "text/plain" && + part.mime.split(";")[0]?.trim().toLowerCase() !== "text/plain" && part.mime !== "application/x-directory" && part.source?.type !== "resource" ) { diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 77a7b6c0cc8..9c6949ebcbf 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -742,7 +742,7 @@ export const layer = Layer.effect( } else if ("blob" in c && c.blob) { const mime = ("mimeType" in c ? c.mimeType : undefined) ?? part.mime const url = `data:${mime};base64,${c.blob}` - if (mime === "text/plain") { + if (mime.split(";")[0]?.trim().toLowerCase() === "text/plain") { pieces.push({ messageID: info.id, sessionID: input.sessionID, diff --git a/packages/opencode/test/session/message-v2.test.ts b/packages/opencode/test/session/message-v2.test.ts index 2cbf55d5858..a1d3a7e31f7 100644 --- a/packages/opencode/test/session/message-v2.test.ts +++ b/packages/opencode/test/session/message-v2.test.ts @@ -344,6 +344,13 @@ describe("session.message-v2.toModelMessage", () => { text: { value: "@fixture-guide", start: 0, end: 14 }, }, }, + { + ...basePart(messageID, "p3"), + type: "file", + mime: "text/plain; charset=utf-8", + filename: "guide.txt", + url: "data:text/plain; charset=utf-8;base64,IyBSZXNvdXJjZSBjb250ZW50cw==", + }, ] as SessionV1.Part[], }, ] diff --git a/packages/opencode/test/session/prompt.test.ts b/packages/opencode/test/session/prompt.test.ts index 1a77bb03309..00d58d923c1 100644 --- a/packages/opencode/test/session/prompt.test.ts +++ b/packages/opencode/test/session/prompt.test.ts @@ -262,7 +262,7 @@ const resourceNoLLMServer = testEffect( ? [ { uri, - mimeType: "text/plain", + mimeType: "text/plain; charset=utf-8", blob: Buffer.from("MCP text blob fixture").toString("base64"), }, ] @@ -2117,8 +2117,8 @@ resourceNoLLMServer.instance( (part) => part.type === "file" && !part.source && - part.mime === "text/plain" && - part.url.startsWith("data:text/plain;base64,"), + part.mime === "text/plain; charset=utf-8" && + part.url.startsWith("data:text/plain; charset=utf-8;base64,"), ), ).toBe(true) expect(