Procházet zdrojové kódy

fix(core): session errors when attachment file not found

Adam před 2 týdny
rodič
revize
1721c6efdf

+ 5 - 3
packages/opencode/src/session/prompt.ts

@@ -968,9 +968,11 @@ export namespace SessionPrompt {
               // have to normalize, symbol search returns absolute paths
               // have to normalize, symbol search returns absolute paths
               // Decode the pathname since URL constructor doesn't automatically decode it
               // Decode the pathname since URL constructor doesn't automatically decode it
               const filepath = fileURLToPath(part.url)
               const filepath = fileURLToPath(part.url)
-              const stat = await Bun.file(filepath).stat()
+              const stat = await Bun.file(filepath)
+                .stat()
+                .catch(() => undefined)
 
 
-              if (stat.isDirectory()) {
+              if (stat?.isDirectory()) {
                 part.mime = "application/x-directory"
                 part.mime = "application/x-directory"
               }
               }
 
 
@@ -989,7 +991,7 @@ export namespace SessionPrompt {
                   // workspace/symbol searches, so we'll try to find the
                   // workspace/symbol searches, so we'll try to find the
                   // symbol in the document to get the full range
                   // symbol in the document to get the full range
                   if (start === end) {
                   if (start === end) {
-                    const symbols = await LSP.documentSymbol(filePathURI)
+                    const symbols = await LSP.documentSymbol(filePathURI).catch(() => [])
                     for (const symbol of symbols) {
                     for (const symbol of symbols) {
                       let range: LSP.Range | undefined
                       let range: LSP.Range | undefined
                       if ("range" in symbol) {
                       if ("range" in symbol) {

+ 53 - 0
packages/opencode/test/session/prompt-missing-file.test.ts

@@ -0,0 +1,53 @@
+import path from "path"
+import { describe, expect, test } from "bun:test"
+import { Instance } from "../../src/project/instance"
+import { Session } from "../../src/session"
+import { SessionPrompt } from "../../src/session/prompt"
+import { tmpdir } from "../fixture/fixture"
+
+describe("session.prompt missing file", () => {
+  test("does not fail the prompt when a file part is missing", async () => {
+    await using tmp = await tmpdir({
+      git: true,
+      config: {
+        agent: {
+          build: {
+            model: "openai/gpt-5.2",
+          },
+        },
+      },
+    })
+
+    await Instance.provide({
+      directory: tmp.path,
+      fn: async () => {
+        const session = await Session.create({})
+
+        const missing = path.join(tmp.path, "does-not-exist.ts")
+        const msg = await SessionPrompt.prompt({
+          sessionID: session.id,
+          agent: "build",
+          noReply: true,
+          parts: [
+            { type: "text", text: "please review @does-not-exist.ts" },
+            {
+              type: "file",
+              mime: "text/plain",
+              url: `file://${missing}`,
+              filename: "does-not-exist.ts",
+            },
+          ],
+        })
+
+        if (msg.info.role !== "user") throw new Error("expected user message")
+
+        const hasFailure = msg.parts.some(
+          (part) => part.type === "text" && part.synthetic && part.text.includes("Read tool failed to read"),
+        )
+        expect(hasFailure).toBe(true)
+
+        await Session.remove(session.id)
+      },
+    })
+  })
+})