diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index e57ef8cd..1fba51cb 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 ( - 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") {