From b5799cbd18b71e18a10af90989616b95b3c7be28 Mon Sep 17 00:00:00 2001 From: saladday <1203511142@qq.com> Date: Thu, 3 Sep 2026 00:45:52 +0800 Subject: [PATCH] fix: detect embedded agent runtimes --- src/agent/availability.ts | 11 +++++++++++ test/agent/availability.test.ts | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/agent/availability.ts b/src/agent/availability.ts index 6e6c7c6..8b99561 100644 --- a/src/agent/availability.ts +++ b/src/agent/availability.ts @@ -12,6 +12,13 @@ const AGENT_EXECUTABLES: Record = { pi: ['pi'], }; +const AGENT_RUNTIME_MARKERS: Partial> = { + 'claude-code': ['CLAUDE_CODE_CHILD_SESSION', '1'], + opencode: ['OPENCODE_CLIENT', 'desktop'], + hermes: ['HERMES_AGENT', 'true'], + pi: ['PI_CODING_AGENT', 'true'], +}; + export function detectAgentsOnPath(env: NodeJS.ProcessEnv = process.env): Set { const pathValue = process.platform === 'win32' ? env.PATH ?? env.Path : env.PATH; if (pathValue === undefined) return new Set(); @@ -40,5 +47,9 @@ export function detectAgentsOnPath(env: NodeJS.ProcessEnv = process.env): Set { const agents = detectAgentsOnPath(env); if (env.CODEX_THREAD_ID?.trim()) agents.add('codex'); + for (const agent of AGENT_IDS) { + const marker = AGENT_RUNTIME_MARKERS[agent]; + if (marker !== undefined && env[marker[0]] === marker[1]) agents.add(agent); + } return agents; } diff --git a/test/agent/availability.test.ts b/test/agent/availability.test.ts index 3123a55..ab8d0df 100644 --- a/test/agent/availability.test.ts +++ b/test/agent/availability.test.ts @@ -65,6 +65,17 @@ describe('agent availability', () => { expect(detectAvailableAgents({ CODEX_THREAD_ID: 'thread-id' })).toEqual(new Set(['codex'])); }); + it('recognizes supported agent runtimes from their exact markers', () => { + for (const [env, agent] of [ + [{ CLAUDE_CODE_CHILD_SESSION: '1' }, 'claude-code'], + [{ OPENCODE_CLIENT: 'desktop' }, 'opencode'], + [{ HERMES_AGENT: 'true' }, 'hermes'], + [{ PI_CODING_AGENT: 'true' }, 'pi'], + ] as const) { + expect(detectAvailableAgents(env)).toEqual(new Set([agent])); + } + }); + it('keeps PATH detection when recognizing the active Codex runtime', () => { const root = executableDirectory('pi'); expect(detectAvailableAgents({ @@ -82,4 +93,15 @@ describe('agent availability', () => { expect(detectAvailableAgents({ CODEX_THREAD_ID: '' })).toEqual(new Set()); expect(detectAvailableAgents({ CODEX_THREAD_ID: ' ' })).toEqual(new Set()); }); + + it('does not infer runtimes from broad or near-match markers', () => { + expect(detectAvailableAgents({ + CLAUDECODE: '1', + CLAUDE_CODE_CHILD_SESSION: 'true', + OPENCODE_CLIENT: 'cli', + HERMES_AGENT: '1', + PI_CODING_AGENT: '1', + AI_AGENT: 'pi', + })).toEqual(new Set()); + }); });