diff options
| author | Adam <[email protected]> | 2026-01-19 11:28:18 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-19 11:28:24 -0600 |
| commit | fc50b2962c24dc37fa131759cd56460fbc1f43fa (patch) | |
| tree | 3ef005297437f003777c4639e48e64e94862a384 | |
| parent | dd0906be8c52d460d856ed4cf89e5fe193aa06db (diff) | |
| download | opencode-fc50b2962c24dc37fa131759cd56460fbc1f43fa.tar.gz opencode-fc50b2962c24dc37fa131759cd56460fbc1f43fa.zip | |
fix(app): make terminal sessions scoped to workspace
| -rw-r--r-- | packages/app/src/context/terminal.tsx | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/packages/app/src/context/terminal.tsx b/packages/app/src/context/terminal.tsx index a7753069c..709d7b899 100644 --- a/packages/app/src/context/terminal.tsx +++ b/packages/app/src/context/terminal.tsx @@ -25,11 +25,11 @@ type TerminalCacheEntry = { dispose: VoidFunction } -function createTerminalSession(sdk: ReturnType<typeof useSDK>, dir: string, id: string | undefined) { - const legacy = `${dir}/terminal${id ? "/" + id : ""}.v1` +function createTerminalSession(sdk: ReturnType<typeof useSDK>, dir: string, session?: string) { + const legacy = session ? [`${dir}/terminal/${session}.v1`, `${dir}/terminal.v1`] : [`${dir}/terminal.v1`] const [store, setStore, _, ready] = persisted( - Persist.scoped(dir, id, "terminal", [legacy]), + Persist.workspace(dir, "terminal", legacy), createStore<{ active?: string all: LocalPTY[] @@ -43,17 +43,28 @@ function createTerminalSession(sdk: ReturnType<typeof useSDK>, dir: string, id: all: createMemo(() => Object.values(store.all)), active: createMemo(() => store.active), new() { + const parse = (title: string) => { + const match = title.match(/^Terminal (\d+)$/) + if (!match) return + const value = Number(match[1]) + if (!Number.isFinite(value) || value <= 0) return + return value + } + const existingTitleNumbers = new Set( - store.all.map((pty) => { - const match = pty.titleNumber - return match + store.all.flatMap((pty) => { + const direct = Number.isFinite(pty.titleNumber) && pty.titleNumber > 0 ? pty.titleNumber : undefined + if (direct !== undefined) return [direct] + const parsed = parse(pty.title) + if (parsed === undefined) return [] + return [parsed] }), ) - let nextNumber = 1 - while (existingTitleNumbers.has(nextNumber)) { - nextNumber++ - } + const nextNumber = + Array.from({ length: existingTitleNumbers.size + 1 }, (_, index) => index + 1).find( + (number) => !existingTitleNumbers.has(number), + ) ?? 1 sdk.client.pty .create({ title: `Terminal ${nextNumber}` }) @@ -166,8 +177,8 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont } } - const load = (dir: string, id: string | undefined) => { - const key = `${dir}:${id ?? WORKSPACE_KEY}` + const load = (dir: string, session?: string) => { + const key = `${dir}:${WORKSPACE_KEY}` const existing = cache.get(key) if (existing) { cache.delete(key) @@ -176,7 +187,7 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont } const entry = createRoot((dispose) => ({ - value: createTerminalSession(sdk, dir, id), + value: createTerminalSession(sdk, dir, session), dispose, })) @@ -185,18 +196,18 @@ export const { use: useTerminal, provider: TerminalProvider } = createSimpleCont return entry.value } - const session = createMemo(() => load(params.dir!, params.id)) + const workspace = createMemo(() => load(params.dir!, params.id)) return { - ready: () => session().ready(), - all: () => session().all(), - active: () => session().active(), - new: () => session().new(), - update: (pty: Partial<LocalPTY> & { id: string }) => session().update(pty), - clone: (id: string) => session().clone(id), - open: (id: string) => session().open(id), - close: (id: string) => session().close(id), - move: (id: string, to: number) => session().move(id, to), + ready: () => workspace().ready(), + all: () => workspace().all(), + active: () => workspace().active(), + new: () => workspace().new(), + update: (pty: Partial<LocalPTY> & { id: string }) => workspace().update(pty), + clone: (id: string) => workspace().clone(id), + open: (id: string) => workspace().open(id), + close: (id: string) => workspace().close(id), + move: (id: string, to: number) => workspace().move(id, to), } }, }) |
