diff --git a/src/renderer/src/lib/launch-agent-background-session.ts b/src/renderer/src/lib/launch-agent-background-session.ts index 6fd30efde21..947cabb317b 100644 --- a/src/renderer/src/lib/launch-agent-background-session.ts +++ b/src/renderer/src/lib/launch-agent-background-session.ts @@ -11,7 +11,7 @@ import { resolveTuiAgentLaunchArgs, resolveTuiAgentLaunchEnv } from '../../../shared/tui-agent-launch-defaults' -import { TUI_AGENT_CONFIG } from '../../../shared/tui-agent-config' +import { requireTuiAgentConfig } from '../../../shared/require-tui-agent-config' import { resolveAgentBackgroundLaunchHost } from '@/lib/agent-background-session-launch-host' import { makePaneKey } from '../../../shared/stable-pane-id' import { @@ -62,7 +62,7 @@ export async function launchAgentBackgroundSession( worktreePath: worktree.path, repo }) - const preflight = TUI_AGENT_CONFIG[agent].preflightTrust + const preflight = requireTuiAgentConfig(agent).preflightTrust if (preflight && worktree.path && window.api.agentTrust?.markTrusted) { try { await window.api.agentTrust.markTrusted({ @@ -82,7 +82,7 @@ export async function launchAgentBackgroundSession( }) const trimmedPrompt = prompt?.trim() ?? '' const hasPrompt = trimmedPrompt.length > 0 - const isFollowupPath = TUI_AGENT_CONFIG[agent].promptInjectionMode === 'stdin-after-start' + const isFollowupPath = requireTuiAgentConfig(agent).promptInjectionMode === 'stdin-after-start' const pasteDraftAfterLaunch = hasPrompt && isFollowupPath ? trimmedPrompt : null const startupPlan = buildAgentStartupPlan({ diff --git a/src/shared/require-tui-agent-config.test.ts b/src/shared/require-tui-agent-config.test.ts new file mode 100644 index 00000000000..a399fffd954 --- /dev/null +++ b/src/shared/require-tui-agent-config.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest' +import type { TuiAgent } from './tui-agent' +import { requireTuiAgentConfig } from './require-tui-agent-config' + +describe('requireTuiAgentConfig', () => { + it('returns the config for a known agent', () => { + expect(requireTuiAgentConfig('codex').preflightTrust).toBe('codex') + }) + + it('names the unknown id instead of throwing a property-of-undefined error', () => { + // A custom-agent id persisted by a branch build, read back by one without the feature. + const stale = 'custom-agent:codex:b2e1ff6f-8932-413a-9133-edffa44e0ee9' as TuiAgent + expect(() => requireTuiAgentConfig(stale)).toThrow( + `Unknown agent "${stale}". This version of Orca has no such agent — pick a different agent and try again.` + ) + }) + + it('rejects a prototype key that Object.hasOwn keeps off the config', () => { + expect(() => requireTuiAgentConfig('toString' as TuiAgent)).toThrow(/Unknown agent "toString"/) + }) +}) diff --git a/src/shared/require-tui-agent-config.ts b/src/shared/require-tui-agent-config.ts new file mode 100644 index 00000000000..78f3f14b6df --- /dev/null +++ b/src/shared/require-tui-agent-config.ts @@ -0,0 +1,15 @@ +import type { TuiAgent } from './tui-agent' +import { isTuiAgent, TUI_AGENT_CONFIG, type TuiAgentConfig } from './tui-agent-config' + +/** Why: agent ids persist in automations and settings, so they outlive the build that + * wrote them — an id a branch build understood reads back as unknown here. Name the id + * instead of letting a bare `TUI_AGENT_CONFIG[agent].x` lookup fail with the unreadable + * "Cannot read properties of undefined (reading 'preflightTrust')". */ +export function requireTuiAgentConfig(agent: TuiAgent): TuiAgentConfig { + if (!isTuiAgent(agent)) { + throw new Error( + `Unknown agent "${String(agent)}". This version of Orca has no such agent — pick a different agent and try again.` + ) + } + return TUI_AGENT_CONFIG[agent] +}