Procházet zdrojové kódy

fix(opencode): omit unsupported MCP blobs

Aiden Cline před 2 měsíci
rodič
revize
08609209bb

+ 17 - 1
packages/opencode/src/session/prompt.ts

@@ -742,7 +742,8 @@ 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.split(";")[0]?.trim().toLowerCase() === "text/plain") {
+                  const mediaType = mime.split(";")[0]?.trim().toLowerCase()
+                  if (mediaType === "text/plain") {
                     pieces.push({
                       messageID: info.id,
                       sessionID: input.sessionID,
@@ -751,6 +752,20 @@ export const layer = Layer.effect(
                       text: decodeDataUrl(url),
                     })
                   }
+                  const supported =
+                    mediaType?.startsWith("image/") ||
+                    mediaType?.startsWith("audio/") ||
+                    mediaType?.startsWith("video/") ||
+                    mediaType === "application/pdf"
+                  if (mediaType !== "text/plain" && !supported) {
+                    pieces.push({
+                      messageID: info.id,
+                      sessionID: input.sessionID,
+                      type: "text",
+                      synthetic: true,
+                      text: `[Binary content: ${mime}]`,
+                    })
+                  }
                   pieces.push({
                     messageID: info.id,
                     sessionID: input.sessionID,
@@ -758,6 +773,7 @@ export const layer = Layer.effect(
                     mime,
                     filename: part.filename,
                     url,
+                    source: supported || mediaType === "text/plain" ? undefined : part.source,
                   })
                 }
               }

+ 13 - 0
packages/opencode/test/session/message-v2.test.ts

@@ -351,6 +351,19 @@ describe("session.message-v2.toModelMessage", () => {
             filename: "guide.txt",
             url: "data:text/plain; charset=utf-8;base64,IyBSZXNvdXJjZSBjb250ZW50cw==",
           },
+          {
+            ...basePart(messageID, "p4"),
+            type: "file",
+            mime: "application/octet-stream",
+            filename: "resource.bin",
+            url: "data:application/octet-stream;base64,AAEC",
+            source: {
+              type: "resource",
+              clientName: "resource-only-fixture",
+              uri: "opencode-fixture://binary",
+              text: { value: "@fixture-binary", start: 15, end: 30 },
+            },
+          },
         ] as SessionV1.Part[],
       },
     ]

+ 34 - 0
packages/opencode/test/session/prompt.test.ts

@@ -266,6 +266,14 @@ const resourceNoLLMServer = testEffect(
                     blob: Buffer.from("MCP text blob fixture").toString("base64"),
                   },
                 ]
+            : uri === "opencode-fixture://binary"
+              ? [
+                  {
+                    uri,
+                    mimeType: "application/octet-stream",
+                    blob: "AAEC",
+                  },
+                ]
             : [
                 {
                   uri,
@@ -2095,6 +2103,18 @@ resourceNoLLMServer.instance(
               text: { value: "@fixture-text-blob", start: 15, end: 33 },
             },
           },
+          {
+            type: "file",
+            mime: "application/octet-stream",
+            url: "opencode-fixture://binary",
+            filename: "fixture-binary",
+            source: {
+              type: "resource",
+              clientName: "resource-only-fixture",
+              uri: "opencode-fixture://binary",
+              text: { value: "@fixture-binary", start: 34, end: 49 },
+            },
+          },
           {
             type: "file",
             mime: "image/png",
@@ -2112,6 +2132,11 @@ resourceNoLLMServer.instance(
 
       expect(message.parts.some((part) => part.type === "text" && part.text === "# MCP resource fixture")).toBe(true)
       expect(message.parts.some((part) => part.type === "text" && part.text === "MCP text blob fixture")).toBe(true)
+      expect(
+        message.parts.some(
+          (part) => part.type === "text" && part.text === "[Binary content: application/octet-stream]",
+        ),
+      ).toBe(true)
       expect(
         message.parts.some(
           (part) =>
@@ -2121,6 +2146,15 @@ resourceNoLLMServer.instance(
             part.url.startsWith("data:text/plain; charset=utf-8;base64,"),
         ),
       ).toBe(true)
+      expect(
+        message.parts.some(
+          (part) =>
+            part.type === "file" &&
+            part.source?.type === "resource" &&
+            part.mime === "application/octet-stream" &&
+            part.url.startsWith("data:application/octet-stream;base64,"),
+        ),
+      ).toBe(true)
       expect(
         message.parts.some(
           (part) => part.type === "file" && part.source?.type === "resource" && part.url === "opencode-fixture://pixel",