diff --git a/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.test.ts b/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.test.ts index 86e1eb67ab6..becaafb3e4c 100644 --- a/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.test.ts +++ b/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.test.ts @@ -138,20 +138,27 @@ describe('buildTitleDerivedAgentRows', () => { expect(rows).toHaveLength(0) }) - it('does not add title-derived rows for the Claude agents management screen', () => { - const rows = buildWorktreeAgentRows({ - tabs: [makeTab('tab-1')], - entries: [], - retained: [], - runtimePaneTitlesByTabId: { - 'tab-1': { 1: 'claude agents' } - }, - ptyIdsByTabId: { 'tab-1': ['pty-claude-agents'] }, - terminalLayoutsByTabId: { 'tab-1': makeSingleLayout(LEAF_ID_1) }, - now: 2000 - }) + it('adds an idle Claude row for the Claude agents surface', () => { + for (const title of [ + 'claude agents', + String.raw`C:\Users\dev\AppData\Roaming\npm\claude.cmd agents` + ]) { + const rows = buildWorktreeAgentRows({ + tabs: [makeTab('tab-1')], + entries: [], + retained: [], + runtimePaneTitlesByTabId: { + 'tab-1': { 1: title } + }, + ptyIdsByTabId: { 'tab-1': ['pty-claude-agents'] }, + terminalLayoutsByTabId: { 'tab-1': makeSingleLayout(LEAF_ID_1) }, + now: 2000 + }) - expect(rows).toHaveLength(0) + expect(rows.map((row) => [row.agentType, row.state, row.entry.lastAssistantMessage])).toEqual( + [['claude', 'idle', 'Idle']] + ) + } }) it('does not turn generic Codex-launched task titles into Claude Code rows', () => { diff --git a/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.ts b/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.ts index 3e41fb49d7d..5b37123b0e8 100644 --- a/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.ts +++ b/src/renderer/src/components/sidebar/worktree-title-derived-agent-rows.ts @@ -1,5 +1,9 @@ import type { DashboardAgentRow } from '@/components/dashboard/useDashboardData' -import { detectAgentStatusFromTitle, getAgentLabel } from '@/lib/agent-status' +import { + detectAgentStatusFromTitle, + getAgentLabel, + isClaudeManagementTitle +} from '@/lib/agent-status' import { tabHasLivePty } from '@/lib/tab-has-live-pty' import { type AgentStatusEntry, @@ -117,8 +121,12 @@ function buildTitleDerivedAgentRow(args: { now: number runtimeAgentOrchestrationByPaneKey?: Record }): DashboardAgentRow | null { - const status = detectAgentStatusFromTitle(args.title) - const label = getAgentLabel(args.title) + const isClaudeAgentsTitle = isClaudeManagementTitle(args.title) + // Why: `claude agents` is a live Claude Code Agent Teams surface, but the + // shared detector keeps it neutral so runtime liveness probes do not treat + // the management/list screen as active work. + const status = isClaudeAgentsTitle ? 'idle' : detectAgentStatusFromTitle(args.title) + const label = isClaudeAgentsTitle ? 'Claude Code' : getAgentLabel(args.title) if (!status || !label) { return null } @@ -127,7 +135,7 @@ function buildTitleDerivedAgentRow(args: { } const paneKey = makePaneKey(args.tab.id, args.leafId) const orchestration = args.runtimeAgentOrchestrationByPaneKey?.[paneKey] - const agentType = resolveTitleDerivedAgentType(args.title, label) + const agentType = isClaudeAgentsTitle ? 'claude' : resolveTitleDerivedAgentType(args.title, label) if (!agentType) { return null }