diff --git a/src/shared/agent-status-types.test.ts b/src/shared/agent-status-types.test.ts index f042921fc04..05584e32526 100644 --- a/src/shared/agent-status-types.test.ts +++ b/src/shared/agent-status-types.test.ts @@ -15,6 +15,8 @@ import { AGENT_STATUS_STATES, AGENT_TYPE_MAX_LENGTH } from './agent-status-types' +import type { AgentType, WellKnownAgentType } from './agent-status-types' +import type { TuiAgent } from './tui-agent' afterEach(() => { vi.restoreAllMocks() @@ -674,3 +676,32 @@ describe('normalizeAgentStatusPayload matches the JSON round trip', () => { } }) }) + +describe('WellKnownAgentType', () => { + // Compile-time proof the union is derived from TuiAgent rather than hand-copied: + // a literal list that misses any launchable agent id fails to typecheck here. + const widenTuiAgent = (agent: TuiAgent): WellKnownAgentType => agent + + it('covers every TuiAgent id plus the unknown sentinel', () => { + // ids the previous 22-member hand-written union had drifted past + const formerlyMissing: WellKnownAgentType[] = [ + 'qwen-code', + 'mistral-vibe', + 'claude-agent-teams' + ] + const sentinel: WellKnownAgentType = 'unknown' + + expect([...formerlyMissing, sentinel, widenTuiAgent('rovo')]).toEqual([ + 'qwen-code', + 'mistral-vibe', + 'claude-agent-teams', + 'unknown', + 'rovo' + ]) + }) + + it('keeps AgentType open to custom agent names', () => { + const custom: AgentType = 'some-in-house-agent' + expect(custom).toBe('some-in-house-agent') + }) +}) diff --git a/src/shared/agent-status-types.ts b/src/shared/agent-status-types.ts index 128e2f80f82..5c94d05ca5e 100644 --- a/src/shared/agent-status-types.ts +++ b/src/shared/agent-status-types.ts @@ -5,6 +5,7 @@ import type { AgentProviderSessionMetadata } from './agent-session-resume' import type { OrchestrationFleetAttention } from './orchestration-fleet-attention' import type { AgentStatusRowFacets } from './agent-status-observation' +import type { TuiAgent } from './tui-agent' import { normalizeInteractivePromptField, normalizeOptionalField, @@ -26,30 +27,9 @@ export const AGENT_STATUS_STATES = ['working', 'blocked', 'waiting', 'done'] as export type AgentStatusState = (typeof AGENT_STATUS_STATES)[number] export type AgentWorkingMode = 'monitoring' // Why: agent types aren't a fixed set (custom agents exist); any non-empty string is -// accepted — these well-known names are just a convenience union for pattern-matching. -export type WellKnownAgentType = - | 'claude' - | 'openclaude' - | 'codex' - | 'gemini' - | 'antigravity' - | 'amp' - | 'opencode' - | 'mimo-code' - | 'cursor' - | 'copilot' - | 'aider' - | 'pi' - | 'omp' - | 'prime-agent' - | 'droid' - | 'command-code' - | 'grok' - | 'hermes' - | 'devin' - | 'ante' - | 'trae' - | 'unknown' +// accepted — the well-known names are the launchable TuiAgent ids plus the 'unknown' +// sentinel (no agent identified yet), a convenience union for pattern-matching. +export type WellKnownAgentType = TuiAgent | 'unknown' export type AgentType = WellKnownAgentType | (string & {}) /** A snapshot of a previous agent state, used to render activity blocks.