summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2025-11-04 17:29:27 -0600
committerAiden Cline <[email protected]>2025-11-04 17:30:58 -0600
commit01b9148c04d9812c43843b867c1a9ded8f186a68 (patch)
treef2ab5f99fcc6115103dbf926586e12f9e0a4d5f9
parentd3e080894ca9eb6432fb93d85d2e74d230921e14 (diff)
downloadopencode-01b9148c04d9812c43843b867c1a9ded8f186a68.tar.gz
opencode-01b9148c04d9812c43843b867c1a9ded8f186a68.zip
fix: image reading error, also add error toast for event bus
-rw-r--r--packages/opencode/src/cli/cmd/tui/app.tsx21
-rw-r--r--packages/opencode/src/session/prompt.ts76
2 files changed, 72 insertions, 25 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx
index e57ef8cd6..1fba51cb9 100644
--- a/packages/opencode/src/cli/cmd/tui/app.tsx
+++ b/packages/opencode/src/cli/cmd/tui/app.tsx
@@ -367,6 +367,27 @@ function App() {
}
})
+ event.on(SessionApi.Event.Error.type, (evt) => {
+ const error = evt.properties.error
+ const message = (() => {
+ if (!error) return "An error occured"
+
+ if (typeof error === "object") {
+ const data = error.data
+ if ("message" in data && typeof data.message === "string") {
+ return data.message
+ }
+ }
+ return String(error)
+ })()
+
+ toast.show({
+ variant: "error",
+ message,
+ duration: 5000,
+ })
+ })
+
return (
<box
width={dimensions().width}
diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts
index 5cbfb8b5a..ea43fa264 100644
--- a/packages/opencode/src/session/prompt.ts
+++ b/packages/opencode/src/session/prompt.ts
@@ -51,6 +51,7 @@ import { $, fileURLToPath } from "bun"
import { ConfigMarkdown } from "../config/markdown"
import { SessionSummary } from "./summary"
import { Config } from "@/config/config"
+import { NamedError } from "@/util/error"
export namespace SessionPrompt {
const log = Log.create({ service: "session.prompt" })
@@ -735,17 +736,8 @@ export namespace SessionPrompt {
}
}
const args = { filePath: filepath, offset, limit }
- const result = await ReadTool.init().then((t) =>
- t.execute(args, {
- sessionID: input.sessionID,
- abort: new AbortController().signal,
- agent: input.agent!,
- messageID: info.id,
- extra: { bypassCwdCheck: true },
- metadata: async () => {},
- }),
- )
- return [
+
+ const pieces: MessageV2.Part[] = [
{
id: Identifier.ascending("part"),
messageID: info.id,
@@ -754,21 +746,55 @@ export namespace SessionPrompt {
synthetic: true,
text: `Called the Read tool with the following input: ${JSON.stringify(args)}`,
},
- {
- id: Identifier.ascending("part"),
- messageID: info.id,
- sessionID: input.sessionID,
- type: "text",
- synthetic: true,
- text: result.output,
- },
- {
- ...part,
- id: part.id ?? Identifier.ascending("part"),
- messageID: info.id,
- sessionID: input.sessionID,
- },
]
+
+ await ReadTool.init()
+ .then(async (t) => {
+ const result = await t.execute(args, {
+ sessionID: input.sessionID,
+ abort: new AbortController().signal,
+ agent: input.agent!,
+ messageID: info.id,
+ extra: { bypassCwdCheck: true },
+ metadata: async () => {},
+ })
+ pieces.push(
+ {
+ id: Identifier.ascending("part"),
+ messageID: info.id,
+ sessionID: input.sessionID,
+ type: "text",
+ synthetic: true,
+ text: result.output,
+ },
+ {
+ ...part,
+ id: part.id ?? Identifier.ascending("part"),
+ messageID: info.id,
+ sessionID: input.sessionID,
+ },
+ )
+ })
+ .catch((error) => {
+ log.error("failed to read file", { error })
+ const message = error instanceof Error ? error.message : error.toString()
+ Bus.publish(Session.Event.Error, {
+ sessionID: input.sessionID,
+ error: new NamedError.Unknown({
+ message,
+ }).toObject(),
+ })
+ pieces.push({
+ id: Identifier.ascending("part"),
+ messageID: info.id,
+ sessionID: input.sessionID,
+ type: "text",
+ synthetic: true,
+ text: `Read tool failed to read ${filepath} with the following error: ${message}`,
+ })
+ })
+
+ return pieces
}
if (part.mime === "application/x-directory") {