From 0cf5179487f164fef4ed514b72cf77c259491cb0 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Tue, 11 Aug 2026 01:20:30 -0700 Subject: [PATCH] fix: preserve structured tabs during activation --- src/renderer/src/store/slices/tabs.test.ts | 77 ++++++++++++++++++++++ src/renderer/src/store/slices/tabs.ts | 2 +- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/store/slices/tabs.test.ts b/src/renderer/src/store/slices/tabs.test.ts index c7bab81ff81..8ac7205f884 100644 --- a/src/renderer/src/store/slices/tabs.test.ts +++ b/src/renderer/src/store/slices/tabs.test.ts @@ -2194,6 +2194,83 @@ describe('TabsSlice', () => { }) }) + it('keeps a structured session activation target during worktree reconciliation', () => { + const groupId = 'g-structured' + store.setState({ + unifiedTabsByWorktree: { + [WT]: [ + { + id: 'terminal-1', + entityId: 'terminal-1', + groupId, + worktreeId: WT, + contentType: 'terminal', + label: 'Terminal 1', + customLabel: null, + color: null, + sortOrder: 0, + createdAt: 1 + }, + { + id: 'structured-session-1', + entityId: 'session-1', + groupId, + worktreeId: WT, + contentType: 'agent-session', + label: 'Codex Chat', + customLabel: null, + color: null, + sortOrder: 1, + createdAt: 2, + agentSessionAgent: 'codex' + } + ] + }, + groupsByWorktree: { + [WT]: [ + { + id: groupId, + worktreeId: WT, + activeTabId: 'structured-session-1', + tabOrder: ['terminal-1', 'structured-session-1'] + } + ] + }, + activeGroupIdByWorktree: { [WT]: groupId }, + tabsByWorktree: { + [WT]: [ + { + id: 'terminal-1', + ptyId: 'pty-1', + worktreeId: WT, + title: 'Terminal 1', + customTitle: null, + color: null, + sortOrder: 0, + createdAt: 1 + } + ] + }, + ptyIdsByTabId: { 'terminal-1': ['pty-1'] } + }) + + const result = store.getState().reconcileWorktreeTabModel(WT) + const state = store.getState() + + expect(result).toEqual({ + renderableTabCount: 2, + activeRenderableTabId: 'structured-session-1' + }) + expect(state.unifiedTabsByWorktree[WT].map((tab) => tab.id)).toEqual([ + 'terminal-1', + 'structured-session-1' + ]) + expect(state.groupsByWorktree[WT][0]).toMatchObject({ + activeTabId: 'structured-session-1', + tabOrder: ['terminal-1', 'structured-session-1'] + }) + }) + it('collapses empty split groups when reconciliation drops a stale tab', () => { const terminalGroupId = 'g-terminal' const staleGroupId = 'g-stale' diff --git a/src/renderer/src/store/slices/tabs.ts b/src/renderer/src/store/slices/tabs.ts index 3f95da7d64f..17955e2a8ad 100644 --- a/src/renderer/src/store/slices/tabs.ts +++ b/src/renderer/src/store/slices/tabs.ts @@ -714,7 +714,7 @@ export function projectWorktreeTabModelReconciliation( if (tab.contentType === 'browser') { return liveBrowserIds.has(tab.entityId) } - if (tab.contentType === 'simulator') { + if (tab.contentType === 'simulator' || tab.contentType === 'agent-session') { return true } return liveEditorIds.has(tab.entityId)