From 6b66aad74f5afd7fbfe1aa0ef876887ed2952fc0 Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:00:00 -0700 Subject: [PATCH] Simplify tab occupant agent resolution to use unified label only Remove the recordTitle parameter and rely solely on the unified title, which already carries live OSC titles. The terminal record's own title can stay stale (e.g., "Terminal N") while the unified label reflects the current state, eliminating duplication and simplifying the contract. --- .../components/tab-bar/TabBarCreateEntryRow.test.tsx | 2 ++ src/renderer/src/lib/open-tab-occupant-agent.test.ts | 4 +--- src/renderer/src/lib/open-tab-occupant-agent.ts | 11 ++++++----- .../src/lib/workspace-tab-palette-search.test.ts | 9 +++++++++ src/renderer/src/lib/workspace-tab-palette-search.ts | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/components/tab-bar/TabBarCreateEntryRow.test.tsx b/src/renderer/src/components/tab-bar/TabBarCreateEntryRow.test.tsx index b56930f9029..f8801ae6122 100644 --- a/src/renderer/src/components/tab-bar/TabBarCreateEntryRow.test.tsx +++ b/src/renderer/src/components/tab-bar/TabBarCreateEntryRow.test.tsx @@ -147,6 +147,8 @@ describe('EntryActionRow', () => { }) expect(container.querySelector('[data-agent-icon]')).toBeNull() + // Guard against the row rendering no icon at all, which "no agent icon" alone would pass. + expect(container.querySelector('svg.lucide-square-terminal')).toBeTruthy() expect(container.textContent).toContain('Switch to tab') }) }) diff --git a/src/renderer/src/lib/open-tab-occupant-agent.test.ts b/src/renderer/src/lib/open-tab-occupant-agent.test.ts index f5d524f8b10..85ab0f4cb49 100644 --- a/src/renderer/src/lib/open-tab-occupant-agent.test.ts +++ b/src/renderer/src/lib/open-tab-occupant-agent.test.ts @@ -111,7 +111,6 @@ describe('resolveOpenTabOccupantAgent', () => { }) it('uses the tab-strip title identity when hooks have not reported yet', () => { - expect(resolve({ recordTitle: 'grok' })).toBe('grok') expect(resolve({ title: 'grok' })).toBe('grok') }) @@ -119,14 +118,13 @@ describe('resolveOpenTabOccupantAgent', () => { expect( resolve({ launchAgent: 'claude', - recordTitle: 'fix grok parser', title: 'fix grok parser' }) ).toBe('claude') }) it('does not treat a hyphenated grok mention as occupancy', () => { - expect(resolve({ recordTitle: 'session-scanner-grok-parser' })).toBeNull() + expect(resolve({ title: 'session-scanner-grok-parser' })).toBeNull() }) it('uses the focused sleeping session, matching useTabAgent', () => { diff --git a/src/renderer/src/lib/open-tab-occupant-agent.ts b/src/renderer/src/lib/open-tab-occupant-agent.ts index 6a4562ba55c..40d4f0df74e 100644 --- a/src/renderer/src/lib/open-tab-occupant-agent.ts +++ b/src/renderer/src/lib/open-tab-occupant-agent.ts @@ -18,10 +18,12 @@ import { resolveTabAgentFromSignals } from './use-tab-agent' export type OpenTabOccupantAgentInput = { tabId: string - /** Visible search/tab-strip label. Used only when the terminal record title is empty. */ + /** + * Resolved unified tab label — the same string the tab strip feeds `useTabAgent`. + * The terminal record's own title is not used: it can stay a stale "Terminal N" + * while the unified label already carries the live OSC title. + */ title?: string - /** OSC title `useTabAgent` reads. */ - recordTitle?: string defaultTitle?: string launchAgent?: TuiAgent layout?: TerminalLayoutSnapshot @@ -38,7 +40,6 @@ export type OpenTabOccupantAgentInput = { export function resolveOpenTabOccupantAgent({ tabId, title, - recordTitle, defaultTitle, launchAgent, layout, @@ -61,7 +62,7 @@ export function resolveOpenTabOccupantAgent({ const sleepingSessionAgent = focusedPaneKey ? (sleepingAgentSessionsByPaneKey[focusedPaneKey]?.agent ?? null) : null - const oscTitle = recordTitle?.trim() || title?.trim() || '' + const oscTitle = title?.trim() || '' const explicitTitleAgent = resolveExplicitTerminalTitleAgentType(oscTitle) const fallbackAgentSignal = launchAgent ? explicitTitleAgent === launchAgent diff --git a/src/renderer/src/lib/workspace-tab-palette-search.test.ts b/src/renderer/src/lib/workspace-tab-palette-search.test.ts index 68053539caa..7570213dd6a 100644 --- a/src/renderer/src/lib/workspace-tab-palette-search.test.ts +++ b/src/renderer/src/lib/workspace-tab-palette-search.test.ts @@ -569,6 +569,15 @@ describe('workspace-tab-palette-search', () => { expect(searchWorkspaceTabs(titledOnly, 'grok')[0]?.occupantAgent).toBe('grok') }) + it('stamps occupancy from the live unified label when the terminal record title is stale', () => { + const staleRecord = buildEntries({ + tabsByWorktree: { 'wt-1': [makeTerminalTab({ title: 'Terminal 1' })] }, + unifiedTabsByWorktree: { 'wt-1': [makeUnifiedTab({ label: 'grok' })] } + }) + expect(staleRecord[0]?.title).toBe('grok') + expect(staleRecord[0]?.occupantAgent).toBe('grok') + }) + it('does not stamp grok occupancy from a hyphenated filename-style title', () => { const hyphenated = buildEntries({ tabsByWorktree: { 'wt-1': [makeTerminalTab({ title: 'session-scanner-grok-parser' })] }, diff --git a/src/renderer/src/lib/workspace-tab-palette-search.ts b/src/renderer/src/lib/workspace-tab-palette-search.ts index 85ec837a2ed..b35e1154b23 100644 --- a/src/renderer/src/lib/workspace-tab-palette-search.ts +++ b/src/renderer/src/lib/workspace-tab-palette-search.ts @@ -275,8 +275,8 @@ export function buildSearchableWorkspaceTabs({ agentMetadata: collectAgentMetadataFromIndex(agentIndex, tab.entityId, worktree.id), occupantAgent: resolveOpenTabOccupantAgent({ tabId: tab.entityId, + // The unified label, not terminalTab.title: the record can lag it (see above). title, - recordTitle: terminalTab?.title, defaultTitle: terminalTab?.defaultTitle, launchAgent: terminalTab?.launchAgent, layout: terminalLayoutsByTabId?.[tab.entityId],