From db45026c6c241361fea18c15230972112c426f7e Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 31 Jul 2026 10:15:53 -0400 Subject: [PATCH] fix(tui): default tabs to global scope (#39783) --- packages/tui/src/component/dialog-config.tsx | 2 +- packages/tui/src/context/session-tabs.tsx | 6 ++--- .../tui/test/context/session-tabs.test.tsx | 24 ++++++++++++++----- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/packages/tui/src/component/dialog-config.tsx b/packages/tui/src/component/dialog-config.tsx index 9eaba22bc2..ed0bf78867 100644 --- a/packages/tui/src/component/dialog-config.tsx +++ b/packages/tui/src/component/dialog-config.tsx @@ -105,7 +105,7 @@ export const settings: Setting[] = [ title: "Scope", category: "Tabs", path: ["tabs", "scope"], - default: "cwd", + default: "global", values: ["cwd", "global"], labels: ["current directory", "global"], }, diff --git a/packages/tui/src/context/session-tabs.tsx b/packages/tui/src/context/session-tabs.tsx index b0f0ec54e8..519dc2f578 100644 --- a/packages/tui/src/context/session-tabs.tsx +++ b/packages/tui/src/context/session-tabs.tsx @@ -66,12 +66,12 @@ export const { use: useSessionTabs, provider: SessionTabsProvider } = createSimp let closedTabs: ClosedSessionTab[] = [] function state() { - if (config.tabs?.scope === "global") return store.global - return store.cwd[paths.cwd] ?? fallback + if (config.tabs?.scope === "cwd") return store.cwd[paths.cwd] ?? fallback + return store.global } function update(mutation: (draft: TabsState) => void) { - const scope = config.tabs?.scope ?? "cwd" + const scope = config.tabs?.scope ?? "global" void updateStore((draft) => mutation(scope === "cwd" ? (draft.cwd[paths.cwd] ??= empty()) : draft.global)).catch( () => {}, ) diff --git a/packages/tui/test/context/session-tabs.test.tsx b/packages/tui/test/context/session-tabs.test.tsx index c3bd2e70a6..d8ddae518a 100644 --- a/packages/tui/test/context/session-tabs.test.tsx +++ b/packages/tui/test/context/session-tabs.test.tsx @@ -64,6 +64,7 @@ async function renderSessionTabs(initialSessionID: string) { return { tabs, route, + state, emit: (event: OpenCodeEvent) => events.emit({ ...event, location: { directory } }), destroy() { app.renderer.destroy() @@ -72,6 +73,21 @@ async function renderSessionTabs(initialSessionID: string) { } } +test("stores session tabs globally by default", async () => { + const setup = await renderSessionTabs("first") + + try { + const file = path.join(setup.state, "test", "tui", "tabs.json") + await wait(() => Bun.file(file).size > 0) + expect(await Bun.file(file).json()).toEqual({ + global: { tabs: [{ sessionID: "first" }], unread: {} }, + cwd: {}, + }) + } finally { + setup.destroy() + } +}) + test("user prompt admissions pulse an already-busy background tab", async () => { const setup = await renderSessionTabs("background") const admitted = (sessionID: string, inputID: string): OpenCodeEvent => ({ @@ -106,9 +122,7 @@ test("user prompt admissions pulse an already-busy background tab", async () => expect(setup.tabs.status("background").promptPulse).toBe(0) setup.emit(admitted("background", "msg_1")) - await wait( - () => setup.tabs.status("background").promptPulse === 1 && setup.tabs.status("background").busy, - ) + await wait(() => setup.tabs.status("background").promptPulse === 1 && setup.tabs.status("background").busy) setup.emit(admitted("background", "msg_2")) await wait(() => setup.tabs.status("background").promptPulse === 2) @@ -144,9 +158,7 @@ test("tracks a temporary new session tab across close and creation", async () => await wait(() => setup.tabs.newTab()) setup.route.navigate({ type: "session", sessionID: "third" }) expect(setup.tabs.newTab()).toBe(true) - await wait( - () => setup.tabs.current() === "third" && setup.tabs.tabs().some((tab) => tab.sessionID === "third"), - ) + await wait(() => setup.tabs.current() === "third" && setup.tabs.tabs().some((tab) => tab.sessionID === "third")) expect(setup.tabs.newTab()).toBe(false) expect(setup.tabs.tabs().find((tab) => tab.sessionID === "third")?.title).toBe(NEW_SESSION_TAB_TITLE)