From fa23fb5d385661f371394e4a08062da990652fc2 Mon Sep 17 00:00:00 2001 From: James Long Date: Mon, 1 Jun 2026 15:47:37 -0400 Subject: [PATCH] fix(tui): handle events across workspaces (#30281) --- packages/opencode/src/cli/cmd/tui/app.tsx | 12 ++++++++---- .../src/cli/cmd/tui/component/prompt/index.tsx | 3 ++- packages/opencode/src/cli/cmd/tui/context/event.ts | 5 ++--- packages/opencode/test/cli/tui/use-event.test.tsx | 13 ------------- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 95321f71b2..c889817be2 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -958,11 +958,13 @@ function App(props: { onSnapshot?: () => Promise }) { bindings: tuiConfig.keybinds.gather("app_exit", ["app.exit"]), })) - event.on(TuiEvent.CommandExecute.type, (evt) => { + event.on(TuiEvent.CommandExecute.type, (evt, { workspace }) => { + if (workspace !== project.workspace.current()) return keymap.dispatchCommand(evt.properties.command) }) - event.on(TuiEvent.ToastShow.type, (evt) => { + event.on(TuiEvent.ToastShow.type, (evt, { workspace }) => { + if (workspace !== project.workspace.current()) return toast.show({ title: evt.properties.title, message: evt.properties.message, @@ -971,7 +973,8 @@ function App(props: { onSnapshot?: () => Promise }) { }) }) - event.on(TuiEvent.SessionSelect.type, (evt) => { + event.on(TuiEvent.SessionSelect.type, (evt, { workspace }) => { + if (workspace !== project.workspace.current()) return route.navigate({ type: "session", sessionID: evt.properties.sessionID, @@ -988,7 +991,8 @@ function App(props: { onSnapshot?: () => Promise }) { } }) - event.on("session.error", (evt) => { + event.on("session.error", (evt, { workspace }) => { + if (workspace !== project.workspace.current()) return const error = evt.properties.error if (error && typeof error === "object" && error.name === "MessageAbortedError") return const message = errorMessage(error) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index d2877dd77f..f287ea25c5 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -319,7 +319,8 @@ export function Prompt(props: PromptProps) { let promptPartTypeId = 0 const event = useEvent() - event.on(TuiEvent.PromptAppend.type, (evt) => { + event.on(TuiEvent.PromptAppend.type, (evt, { workspace }) => { + if (workspace !== project.workspace.current()) return if (!input || input.isDestroyed) return input.insertText(evt.properties.text) setTimeout(() => { diff --git a/packages/opencode/src/cli/cmd/tui/context/event.ts b/packages/opencode/src/cli/cmd/tui/context/event.ts index 5d814ecdca..077e160b60 100644 --- a/packages/opencode/src/cli/cmd/tui/context/event.ts +++ b/packages/opencode/src/cli/cmd/tui/context/event.ts @@ -1,4 +1,5 @@ import type { Event } from "@opencode-ai/sdk/v2" +import * as Log from "@opencode-ai/core/util/log" import { useProject } from "./project" import { useSDK } from "./sdk" @@ -16,9 +17,7 @@ export function useEvent() { return } - if (event.directory === "global" || event.project === project.project()) { - handler(event.payload, { workspace: event.workspace }) - } + handler(event.payload, { workspace: event.workspace }) }) } diff --git a/packages/opencode/test/cli/tui/use-event.test.tsx b/packages/opencode/test/cli/tui/use-event.test.tsx index 2aa3e97812..1ec5d499af 100644 --- a/packages/opencode/test/cli/tui/use-event.test.tsx +++ b/packages/opencode/test/cli/tui/use-event.test.tsx @@ -113,19 +113,6 @@ describe("useEvent", () => { } }) - test("ignores events for other projects", async () => { - const { app, emit, seen } = await mount() - - try { - emit(event(vcs("other"), { directory, project: "proj_other" })) - await Bun.sleep(30) - - expect(seen).toHaveLength(0) - } finally { - app.renderer.destroy() - } - }) - test("delivers current project events regardless of active workspace", async () => { const { app, emit, project, seen } = await mount()