import { detectAgent, isCI } from '../src/agent.js'; const originalIsTTY = process.stdout.isTTY; afterEach(() => { process.stdout.isTTY = originalIsTTY; }); describe('detectAgent', () => { it('returns undefined with no agent env', () => { expect(detectAgent({})).toBeUndefined(); }); it.each([ [{ CLAUDECODE: '1' }, 'claude_code'], [{ TERM_PROGRAM: 'claude' }, 'claude_code'], [{ CLAUDECODE: '1', CLAUDE_CODE_IS_COWORK: '1' }, 'cowork'], [{ CODEX_THREAD_ID: 'abc' }, 'codex_cli'], [{ GEMINI_CLI: '1' }, 'gemini_cli'], [{ CURSOR_AGENT: '1' }, 'cursor-cli'], [{ OPENCODE: '1' }, 'open_code'], [{ PATH: '/usr/bin:/home/me/.pi/agent/bin' }, 'pi'], [{ EDITOR: '/opt/devin/bin/code' }, 'devin'], ])('detects %o as %s', (env, expected) => { expect(detectAgent(env)).toBe(expected); }); it('prefers explicit AI_AGENT and AGENT', () => { expect(detectAgent({ AI_AGENT: 'Amp', CLAUDECODE: '1' })).toBe('amp'); expect(detectAgent({ AGENT: 'goose' })).toBe('goose'); }); it('prefers CLI agents over IDE hosts', () => { process.stdout.isTTY = false; expect(detectAgent({ CLAUDECODE: '1', CURSOR_TRACE_ID: 'x' })).toBe('claude_code'); expect(detectAgent({ CURSOR_TRACE_ID: 'x' })).toBe('cursor'); }); it('ignores IDE and config markers when a human is at a TTY', () => { process.stdout.isTTY = true; expect( detectAgent({ CURSOR_TRACE_ID: 'x', REPL_ID: 'y', TERM_PROGRAM: 'kiro', GOOSE_PROVIDER: 'openai', COPILOT_MODEL: 'gpt', OPENCODE_CLIENT: 'desktop', }) ).toBeUndefined(); }); }); describe('isCI', () => { it.each([ [{}, false], [{ CI: 'true' }, true], [{ CI: '1' }, true], [{ CI: 'false' }, false], [{ CI: '0' }, false], ])('%o -> %s', (env, expected) => { expect(isCI(env)).toBe(expected); }); });