@vercel/agent-eval 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/lib/agents/claude-code/agent.d.ts +30 -0
  2. package/dist/lib/agents/claude-code/agent.d.ts.map +1 -0
  3. package/dist/lib/agents/claude-code/agent.js +80 -0
  4. package/dist/lib/agents/claude-code/agent.js.map +1 -0
  5. package/dist/lib/agents/claude-code/run.mjs +217 -0
  6. package/dist/lib/agents/codex/agent.d.ts +61 -0
  7. package/dist/lib/agents/codex/agent.d.ts.map +1 -0
  8. package/dist/lib/agents/codex/agent.js +221 -0
  9. package/dist/lib/agents/codex/agent.js.map +1 -0
  10. package/dist/lib/agents/codex/run.mjs +365 -0
  11. package/dist/lib/agents/cursor/agent.d.ts +32 -0
  12. package/dist/lib/agents/cursor/agent.d.ts.map +1 -0
  13. package/dist/lib/agents/cursor/agent.js +86 -0
  14. package/dist/lib/agents/cursor/agent.js.map +1 -0
  15. package/dist/lib/agents/cursor/run.mjs +183 -0
  16. package/dist/lib/agents/eval-helper.mjs +222 -0
  17. package/dist/lib/agents/gemini/agent.d.ts +27 -0
  18. package/dist/lib/agents/gemini/agent.d.ts.map +1 -0
  19. package/dist/lib/agents/gemini/agent.js +69 -0
  20. package/dist/lib/agents/gemini/agent.js.map +1 -0
  21. package/dist/lib/agents/gemini/run.mjs +180 -0
  22. package/dist/lib/agents/index.js +5 -5
  23. package/dist/lib/agents/index.js.map +1 -1
  24. package/dist/lib/agents/opencode/agent.d.ts +68 -0
  25. package/dist/lib/agents/opencode/agent.d.ts.map +1 -0
  26. package/dist/lib/agents/opencode/agent.js +165 -0
  27. package/dist/lib/agents/opencode/agent.js.map +1 -0
  28. package/dist/lib/agents/opencode/run.mjs +308 -0
  29. package/dist/lib/agents/plugin/contract.d.ts +157 -0
  30. package/dist/lib/agents/plugin/contract.d.ts.map +1 -0
  31. package/dist/lib/agents/plugin/contract.js +22 -0
  32. package/dist/lib/agents/plugin/contract.js.map +1 -0
  33. package/dist/lib/agents/plugin/orchestrator.d.ts +22 -0
  34. package/dist/lib/agents/plugin/orchestrator.d.ts.map +1 -0
  35. package/dist/lib/agents/plugin/orchestrator.js +286 -0
  36. package/dist/lib/agents/plugin/orchestrator.js.map +1 -0
  37. package/dist/lib/agents/shared.d.ts +7 -1
  38. package/dist/lib/agents/shared.d.ts.map +1 -1
  39. package/dist/lib/agents/shared.js +30 -3
  40. package/dist/lib/agents/shared.js.map +1 -1
  41. package/package.json +2 -2
  42. package/dist/lib/agents/claude-code.d.ts +0 -23
  43. package/dist/lib/agents/claude-code.d.ts.map +0 -1
  44. package/dist/lib/agents/claude-code.js +0 -300
  45. package/dist/lib/agents/claude-code.js.map +0 -1
  46. package/dist/lib/agents/codex.d.ts +0 -23
  47. package/dist/lib/agents/codex.d.ts.map +0 -1
  48. package/dist/lib/agents/codex.js +0 -364
  49. package/dist/lib/agents/codex.js.map +0 -1
  50. package/dist/lib/agents/cursor.d.ts +0 -10
  51. package/dist/lib/agents/cursor.d.ts.map +0 -1
  52. package/dist/lib/agents/cursor.js +0 -207
  53. package/dist/lib/agents/cursor.js.map +0 -1
  54. package/dist/lib/agents/gemini.d.ts +0 -10
  55. package/dist/lib/agents/gemini.d.ts.map +0 -1
  56. package/dist/lib/agents/gemini.js +0 -208
  57. package/dist/lib/agents/gemini.js.map +0 -1
  58. package/dist/lib/agents/opencode.d.ts +0 -46
  59. package/dist/lib/agents/opencode.d.ts.map +0 -1
  60. package/dist/lib/agents/opencode.js +0 -365
  61. package/dist/lib/agents/opencode.js.map +0 -1
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Claude Code agent — host-side definition + the thin Agent wrapper.
3
+ *
4
+ * The definition is pure data/auth; the actual CLI invocation + transcript capture
5
+ * live in ./run.mjs (shipped into the sandbox by the orchestrator). The wrapper
6
+ * keeps the public Agent interface identical so the registry / runner are untouched.
7
+ */
8
+ import type { Agent } from '../types.js';
9
+ import type { AgentDefinition } from '../plugin/contract.js';
10
+ /**
11
+ * Build the Claude Code plugin definition.
12
+ *
13
+ * Auth has three mutually-exclusive modes, preserved exactly from the old adapter:
14
+ * 1. Vercel AI Gateway → ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN (+ empty ANTHROPIC_API_KEY)
15
+ * 2. OAuth (CLAUDE_CODE_OAUTH_TOKEN present in the host env) → CLAUDE_CODE_OAUTH_TOKEN
16
+ * 3. Direct API (fallback) → ANTHROPIC_API_KEY
17
+ * getApiKeyEnvVar() and authEnv() must agree on the mode — both read process.env at
18
+ * call time, so the host's key resolution and the sandbox env stay consistent.
19
+ */
20
+ export declare function createClaudeCodeDefinition({ useVercelAiGateway }: {
21
+ useVercelAiGateway: boolean;
22
+ }): AgentDefinition;
23
+ /**
24
+ * Create the Claude Code Agent. Thin wrapper over the generic orchestrator so the
25
+ * Agent interface (and thus registry.ts / index.ts / runner.ts) is unchanged.
26
+ */
27
+ export declare function createClaudeCodeAgent({ useVercelAiGateway }: {
28
+ useVercelAiGateway: boolean;
29
+ }): Agent;
30
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../../src/lib/agents/claude-code/agent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAmB,MAAM,aAAa,CAAC;AAG1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,kBAAkB,EAAE,EAAE;IAAE,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAAG,eAAe,CA4CnH;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,kBAAkB,EAAE,EAAE;IAAE,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAWpG"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Claude Code agent — host-side definition + the thin Agent wrapper.
3
+ *
4
+ * The definition is pure data/auth; the actual CLI invocation + transcript capture
5
+ * live in ./run.mjs (shipped into the sandbox by the orchestrator). The wrapper
6
+ * keeps the public Agent interface identical so the registry / runner are untouched.
7
+ */
8
+ import { fileURLToPath } from 'node:url';
9
+ import { AI_GATEWAY, ANTHROPIC_DIRECT } from '../shared.js';
10
+ import { runWithDefinition } from '../plugin/orchestrator.js';
11
+ /**
12
+ * Build the Claude Code plugin definition.
13
+ *
14
+ * Auth has three mutually-exclusive modes, preserved exactly from the old adapter:
15
+ * 1. Vercel AI Gateway → ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN (+ empty ANTHROPIC_API_KEY)
16
+ * 2. OAuth (CLAUDE_CODE_OAUTH_TOKEN present in the host env) → CLAUDE_CODE_OAUTH_TOKEN
17
+ * 3. Direct API (fallback) → ANTHROPIC_API_KEY
18
+ * getApiKeyEnvVar() and authEnv() must agree on the mode — both read process.env at
19
+ * call time, so the host's key resolution and the sandbox env stay consistent.
20
+ */
21
+ export function createClaudeCodeDefinition({ useVercelAiGateway }) {
22
+ return {
23
+ name: useVercelAiGateway ? 'vercel-ai-gateway/claude-code' : 'claude-code',
24
+ displayName: useVercelAiGateway ? 'Claude Code (Vercel AI Gateway)' : 'Claude Code',
25
+ defaultModel: 'opus',
26
+ o11yAgentName: 'claude-code',
27
+ // Resolve run.mjs next to this file (works in src during dev and in dist after
28
+ // the build copies run.mjs alongside the compiled agent.js).
29
+ runnerPath: fileURLToPath(new URL('./run.mjs', import.meta.url)),
30
+ getApiKeyEnvVar() {
31
+ if (useVercelAiGateway)
32
+ return AI_GATEWAY.apiKeyEnvVar;
33
+ if (process.env.CLAUDE_CODE_OAUTH_TOKEN)
34
+ return 'CLAUDE_CODE_OAUTH_TOKEN';
35
+ return ANTHROPIC_DIRECT.apiKeyEnvVar;
36
+ },
37
+ install(options) {
38
+ // Project deps (retried once), then the Claude Code CLI globally.
39
+ const cliPackage = options.agentOptions?.cliPackage || '@anthropic-ai/claude-code';
40
+ return [
41
+ { kind: 'command', cmd: 'npm', args: ['install'], retryOnce: true, errorPrefix: 'npm install failed', errorBody: 'last10' },
42
+ { kind: 'command', cmd: 'npm', args: ['install', '-g', cliPackage], errorPrefix: 'Claude Code install failed', errorBody: 'stderr' },
43
+ ];
44
+ },
45
+ // Claude Code is configured purely via env — no config files.
46
+ configFiles() {
47
+ return [];
48
+ },
49
+ authEnv(options) {
50
+ if (useVercelAiGateway) {
51
+ return {
52
+ ANTHROPIC_BASE_URL: AI_GATEWAY.baseUrl,
53
+ ANTHROPIC_AUTH_TOKEN: options.apiKey,
54
+ ANTHROPIC_API_KEY: '',
55
+ };
56
+ }
57
+ if (process.env.CLAUDE_CODE_OAUTH_TOKEN) {
58
+ return { CLAUDE_CODE_OAUTH_TOKEN: options.apiKey };
59
+ }
60
+ return { ANTHROPIC_API_KEY: options.apiKey };
61
+ },
62
+ };
63
+ }
64
+ /**
65
+ * Create the Claude Code Agent. Thin wrapper over the generic orchestrator so the
66
+ * Agent interface (and thus registry.ts / index.ts / runner.ts) is unchanged.
67
+ */
68
+ export function createClaudeCodeAgent({ useVercelAiGateway }) {
69
+ const definition = createClaudeCodeDefinition({ useVercelAiGateway });
70
+ return {
71
+ name: definition.name,
72
+ displayName: definition.displayName,
73
+ getApiKeyEnvVar: definition.getApiKeyEnvVar,
74
+ getDefaultModel() {
75
+ return definition.defaultModel;
76
+ },
77
+ run: (fixturePath, options) => runWithDefinition(definition, fixturePath, options),
78
+ };
79
+ }
80
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../../src/lib/agents/claude-code/agent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CAAC,EAAE,kBAAkB,EAAmC;IAChG,OAAO;QACL,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,aAAa;QAC1E,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,aAAa;QACnF,YAAY,EAAE,MAAM;QACpB,aAAa,EAAE,aAAa;QAC5B,+EAA+E;QAC/E,6DAA6D;QAC7D,UAAU,EAAE,aAAa,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEhE,eAAe;YACb,IAAI,kBAAkB;gBAAE,OAAO,UAAU,CAAC,YAAY,CAAC;YACvD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB;gBAAE,OAAO,yBAAyB,CAAC;YAC1E,OAAO,gBAAgB,CAAC,YAAY,CAAC;QACvC,CAAC;QAED,OAAO,CAAC,OAAwB;YAC9B,kEAAkE;YAClE,MAAM,UAAU,GAAI,OAAO,CAAC,YAAY,EAAE,UAAqB,IAAI,2BAA2B,CAAC;YAC/F,OAAO;gBACL,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,SAAS,EAAE,QAAQ,EAAE;gBAC3H,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,SAAS,EAAE,QAAQ,EAAE;aACrI,CAAC;QACJ,CAAC;QAED,8DAA8D;QAC9D,WAAW;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,CAAC,OAAwB;YAC9B,IAAI,kBAAkB,EAAE,CAAC;gBACvB,OAAO;oBACL,kBAAkB,EAAE,UAAU,CAAC,OAAO;oBACtC,oBAAoB,EAAE,OAAO,CAAC,MAAM;oBACpC,iBAAiB,EAAE,EAAE;iBACtB,CAAC;YACJ,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;gBACxC,OAAO,EAAE,uBAAuB,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YACrD,CAAC;YACD,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,EAAE,kBAAkB,EAAmC;IAC3F,MAAM,UAAU,GAAG,0BAA0B,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACtE,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,eAAe;YACb,OAAO,UAAU,CAAC,YAAY,CAAC;QACjC,CAAC;QACD,GAAG,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC;KACnF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Claude Code in-sandbox runner.
3
+ *
4
+ * This file is shipped INTO the sandbox by the orchestrator and executed there as
5
+ * `node __agent_eval__/run.mjs '<AgentRunInput JSON>'`. It is intentionally
6
+ * ZERO-DEPENDENCY (only `node:*` builtins) because the sandbox only has the
7
+ * fixture's own deps + the installed `claude` CLI — it cannot import anything from
8
+ * the @vercel/agent-eval package.
9
+ *
10
+ * Dual mode:
11
+ * - runnable: invoked directly → reads argv, runs the agent, writes the result
12
+ * file + prints a status line, exits 0.
13
+ * - importable: `import { runAgent } from './run.mjs'` → returns a RunnerResult
14
+ * (no file write, no exit). This is what a future in-sandbox judge reuses.
15
+ *
16
+ * `buildClaudeCodeCliArgs` and `extractObservedModelFromClaudeTranscript` are
17
+ * exported so the host unit tests can verify them directly (the test imports them
18
+ * from this very file, so there is no risk of the tested logic drifting from the
19
+ * logic the sandbox actually runs).
20
+ */
21
+
22
+ import { spawnSync } from 'node:child_process';
23
+ import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
24
+ import { homedir } from 'node:os';
25
+ import { dirname, join } from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+
28
+ /**
29
+ * Build the Claude Code CLI argument list.
30
+ *
31
+ * Order is regression-sensitive (preserved verbatim from the old adapter):
32
+ * `--allowedTools` is variadic — it keeps consuming positional tokens until the
33
+ * next flag. So (1) the tools must be a single comma-separated value, and (2)
34
+ * `--allowedTools` must be followed by another flag, never directly by the prompt.
35
+ * `--dangerously-skip-permissions` is always emitted and terminates the variadic
36
+ * capture before the trailing positional prompt (the #141 regression).
37
+ *
38
+ * @param {{prompt:string, model?:string, webResearch?:boolean, agentOptions?:Record<string,unknown>}} input
39
+ * @returns {string[]}
40
+ */
41
+ export function buildClaudeCodeCliArgs(input) {
42
+ const cliArgs = ['--print'];
43
+ if (input.webResearch) {
44
+ cliArgs.push('--allowedTools', 'WebSearch,WebFetch');
45
+ }
46
+ if (input.model) {
47
+ cliArgs.push('--model', input.model);
48
+ }
49
+ cliArgs.push('--dangerously-skip-permissions');
50
+ const effort = input.agentOptions?.effort;
51
+ if (effort) {
52
+ cliArgs.push('--effort', String(effort));
53
+ }
54
+ cliArgs.push(input.prompt);
55
+ return cliArgs;
56
+ }
57
+
58
+ /**
59
+ * Scan a Claude Code transcript (JSONL) for the last `message.model` seen.
60
+ * Preserved verbatim from the old adapter. Non-JSON lines are ignored.
61
+ *
62
+ * @param {string|undefined|null} transcript
63
+ * @returns {string|undefined}
64
+ */
65
+ export function extractObservedModelFromClaudeTranscript(transcript) {
66
+ if (!transcript) return undefined;
67
+
68
+ let observedModel;
69
+ for (const line of transcript.split('\n')) {
70
+ if (!line.trim()) continue;
71
+ try {
72
+ const event = JSON.parse(line);
73
+ if (typeof event.message?.model === 'string') {
74
+ observedModel = event.message.model;
75
+ }
76
+ } catch {
77
+ // Ignore non-JSON transcript lines.
78
+ }
79
+ }
80
+ return observedModel;
81
+ }
82
+
83
+ /**
84
+ * Locate + read the Claude Code transcript file.
85
+ *
86
+ * Claude Code writes JSONL transcripts to
87
+ * `~/.claude/projects/{cwd-with-slashes-as-dashes}/{session}.jsonl`. We pick the
88
+ * newest `.jsonl` by mtime — the equivalent of the old adapter's
89
+ * `ls -t ~/.claude/projects/<path>/*.jsonl | head -1`.
90
+ *
91
+ * Best-effort: any failure → null (never throws).
92
+ *
93
+ * @param {string} cwd post-relocation sandbox cwd (e.g. /workspace)
94
+ * @returns {string|null}
95
+ */
96
+ function captureClaudeTranscript(cwd) {
97
+ try {
98
+ const projectPath = cwd.replace(/\//g, '-');
99
+ const dir = join(homedir(), '.claude', 'projects', projectPath);
100
+ const newest = readdirSync(dir)
101
+ .filter((f) => f.endsWith('.jsonl'))
102
+ .map((f) => {
103
+ const full = join(dir, f);
104
+ return { full, mtime: statSync(full).mtimeMs };
105
+ })
106
+ .sort((a, b) => b.mtime - a.mtime)[0];
107
+ if (!newest) return null;
108
+ return readFileSync(newest.full, 'utf8') || null;
109
+ } catch {
110
+ return null;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Run Claude Code over the workspace at `input.cwd` and return a RunnerResult.
116
+ *
117
+ * Auth (ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/...) arrives via process.env — the
118
+ * orchestrator sets it on the `node run.mjs` invocation, and we pass process.env
119
+ * straight through to the CLI. The runner never handles secrets itself.
120
+ *
121
+ * @param {import('../plugin/contract.js').AgentRunInput} input
122
+ * @returns {Promise<import('../plugin/contract.js').RunnerResult>}
123
+ */
124
+ export async function runAgent(input) {
125
+ const args = buildClaudeCodeCliArgs(input);
126
+
127
+ // spawnSync (not a shell string): the prompt is a plain argv element, so there is
128
+ // no shell quoting/escaping to get wrong. Blocking is fine — the runner has
129
+ // nothing else to do while the agent works. The sandbox-level timeout bounds it.
130
+ const res = spawnSync('claude', args, {
131
+ cwd: input.cwd,
132
+ env: process.env,
133
+ encoding: 'utf8',
134
+ maxBuffer: 64 * 1024 * 1024,
135
+ });
136
+
137
+ const stdout = res.stdout || '';
138
+ const stderr = res.stderr || '';
139
+ // Preserve the old concatenation order: stdout THEN stderr.
140
+ const output = stdout + stderr;
141
+ // spawnSync sets status=null + error when the binary can't be spawned at all.
142
+ const agentExitCode = res.status == null ? -1 : res.status;
143
+
144
+ // Capture transcript + observed model regardless of success (the old adapter did
145
+ // this even on the non-zero-exit path).
146
+ const transcript = captureClaudeTranscript(input.cwd);
147
+ const observedModel = extractObservedModelFromClaudeTranscript(transcript) ?? null;
148
+
149
+ if (res.error || agentExitCode !== 0) {
150
+ // Mirror the old error string: last 5 lines of output, else a coded fallback.
151
+ const errorLines = output.trim().split('\n').slice(-5).join('\n');
152
+ const fallback = res.error
153
+ ? `Failed to run claude: ${res.error.message}`
154
+ : `Claude Code exited with code ${agentExitCode}`;
155
+ return {
156
+ ok: false,
157
+ output,
158
+ transcript,
159
+ observedModel,
160
+ error: errorLines || fallback,
161
+ agentExitCode,
162
+ };
163
+ }
164
+
165
+ return { ok: true, output, transcript, observedModel, error: null, agentExitCode };
166
+ }
167
+
168
+ /* ─────────────────────────── runnable (CLI) entry ─────────────────────────── */
169
+
170
+ // True when this file is executed directly (`node run.mjs ...`), false when imported.
171
+ const isMain = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
172
+
173
+ if (isMain) {
174
+ // argv[2] is the AgentRunInput JSON (never contains secrets).
175
+ const input = JSON.parse(process.argv[2]);
176
+
177
+ // Always produce a RunnerResult, even if the runner itself throws, so the host
178
+ // always has a result file to read (node exit code stays 0 except on a truly
179
+ // unrecoverable crash before we can write).
180
+ let result;
181
+ try {
182
+ result = await runAgent(input);
183
+ } catch (e) {
184
+ result = {
185
+ ok: false,
186
+ output: '',
187
+ transcript: null,
188
+ observedModel: null,
189
+ error: e && e.message ? e.message : String(e),
190
+ agentExitCode: -1,
191
+ };
192
+ }
193
+
194
+ // Source of truth: the result file the host reads back via sandbox.readFile.
195
+ try {
196
+ mkdirSync(dirname(input.resultPath), { recursive: true });
197
+ writeFileSync(input.resultPath, JSON.stringify(result));
198
+ } catch {
199
+ // If the file can't be written, the host falls back to the marker line below.
200
+ }
201
+
202
+ // Fallback channel: a compact status line (no transcript — it can be huge).
203
+ process.stdout.write(
204
+ '__AGENT_RESULT__ ' +
205
+ JSON.stringify({
206
+ ok: result.ok,
207
+ observedModel: result.observedModel,
208
+ error: result.error,
209
+ agentExitCode: result.agentExitCode,
210
+ }) +
211
+ '\n'
212
+ );
213
+
214
+ // Exit 0: "the runner ran". Agent success/failure is conveyed via result.ok, not
215
+ // the node exit code (the host distinguishes the two).
216
+ process.exit(0);
217
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * OpenAI Codex agent — host-side definition + the thin Agent wrapper.
3
+ *
4
+ * The definition is pure data/auth/config; the actual CLI invocation + transcript
5
+ * capture live in ./run.mjs (shipped into the sandbox by the orchestrator). The
6
+ * wrapper keeps the public Agent interface identical so the registry / runner are
7
+ * untouched.
8
+ *
9
+ * Codex is the one agent that needs BOTH a config file (a TOML profile written to
10
+ * the absolute path `~/.codex/default.config.toml`) AND a host-computed value that
11
+ * the runner must reproduce verbatim on the CLI (`-c model_reasoning_effort=...`,
12
+ * `-c model_verbosity=...`, `--model ...`). Those CLI values MUST match the values
13
+ * baked into the TOML, so they are derived ONCE on the host (from parseModelString)
14
+ * and handed to the runner via `runnerExtra()` → `input.extra`. parseModelString
15
+ * stays host-side (and exported) so the unit tests keep importing it.
16
+ */
17
+ import type { Agent } from '../types.js';
18
+ import type { AgentDefinition } from '../plugin/contract.js';
19
+ /**
20
+ * Parse model string with optional query parameters.
21
+ * e.g. "gpt-5.2-codex?reasoningEffort=high" → { model: "gpt-5.2-codex", reasoningEffort: "high" }
22
+ *
23
+ * Stays host-side (and exported) — the unit tests import it, and the resulting
24
+ * values must be baked into BOTH the TOML config (configFiles) and the runner CLI
25
+ * args (runnerExtra), so it must be computed exactly once on the host.
26
+ */
27
+ export declare function parseModelString(model: string): {
28
+ model: string;
29
+ reasoningEffort?: string;
30
+ };
31
+ /**
32
+ * Generate Codex profile config content.
33
+ *
34
+ * `reasoningEffort` and `model_verbosity` are written into the profile so a
35
+ * fresh `codex exec` doesn't pick up the CLI defaults of `"low"`, which are
36
+ * rejected by `gpt-5.2-codex`. Defaults to `"medium"` when `reasoningEffort`
37
+ * is omitted.
38
+ *
39
+ * Stays host-side (and exported) — the unit tests import it directly.
40
+ */
41
+ export declare function generateCodexConfig(model: string | undefined, useVercelAiGateway: boolean, reasoningEffort?: string, webResearch?: boolean): string;
42
+ /**
43
+ * Build the Codex plugin definition.
44
+ *
45
+ * Auth is two mutually-exclusive modes, preserved exactly from the old adapter:
46
+ * 1. Vercel AI Gateway → AI_GATEWAY_API_KEY (the gateway "vercel" provider's env_key)
47
+ * 2. Direct OpenAI API → OPENAI_API_KEY (the built-in "openai" provider's env_key)
48
+ * The runner additionally pipes the same key into `codex login --with-api-key` over
49
+ * stdin (reading it from process.env, never from the argv JSON).
50
+ */
51
+ export declare function createCodexDefinition({ useVercelAiGateway }: {
52
+ useVercelAiGateway: boolean;
53
+ }): AgentDefinition;
54
+ /**
55
+ * Create the Codex Agent. Thin wrapper over the generic orchestrator so the Agent
56
+ * interface (and thus registry.ts / index.ts / runner.ts) is unchanged.
57
+ */
58
+ export declare function createCodexAgent({ useVercelAiGateway }: {
59
+ useVercelAiGateway: boolean;
60
+ }): Agent;
61
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../../src/lib/agents/codex/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAmB,MAAM,aAAa,CAAC;AAG1D,OAAO,KAAK,EAAE,eAAe,EAA2B,MAAM,uBAAuB,CAAC;AAGtF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAmB3F;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,kBAAkB,EAAE,OAAO,EAC3B,eAAe,CAAC,EAAE,MAAM,EACxB,WAAW,CAAC,EAAE,OAAO,GACpB,MAAM,CA4BR;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,kBAAkB,EAAE,EAAE;IAAE,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAAG,eAAe,CAsF9G;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,kBAAkB,EAAE,EAAE;IAAE,kBAAkB,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAW/F"}
@@ -0,0 +1,221 @@
1
+ /**
2
+ * OpenAI Codex agent — host-side definition + the thin Agent wrapper.
3
+ *
4
+ * The definition is pure data/auth/config; the actual CLI invocation + transcript
5
+ * capture live in ./run.mjs (shipped into the sandbox by the orchestrator). The
6
+ * wrapper keeps the public Agent interface identical so the registry / runner are
7
+ * untouched.
8
+ *
9
+ * Codex is the one agent that needs BOTH a config file (a TOML profile written to
10
+ * the absolute path `~/.codex/default.config.toml`) AND a host-computed value that
11
+ * the runner must reproduce verbatim on the CLI (`-c model_reasoning_effort=...`,
12
+ * `-c model_verbosity=...`, `--model ...`). Those CLI values MUST match the values
13
+ * baked into the TOML, so they are derived ONCE on the host (from parseModelString)
14
+ * and handed to the runner via `runnerExtra()` → `input.extra`. parseModelString
15
+ * stays host-side (and exported) so the unit tests keep importing it.
16
+ */
17
+ import { fileURLToPath } from 'node:url';
18
+ import { AI_GATEWAY, OPENAI_DIRECT } from '../shared.js';
19
+ import { runWithDefinition } from '../plugin/orchestrator.js';
20
+ /**
21
+ * Parse model string with optional query parameters.
22
+ * e.g. "gpt-5.2-codex?reasoningEffort=high" → { model: "gpt-5.2-codex", reasoningEffort: "high" }
23
+ *
24
+ * Stays host-side (and exported) — the unit tests import it, and the resulting
25
+ * values must be baked into BOTH the TOML config (configFiles) and the runner CLI
26
+ * args (runnerExtra), so it must be computed exactly once on the host.
27
+ */
28
+ export function parseModelString(model) {
29
+ const qIndex = model.indexOf('?');
30
+ if (qIndex === -1)
31
+ return { model };
32
+ const base = model.slice(0, qIndex);
33
+ const query = model.slice(qIndex + 1);
34
+ let reasoningEffort;
35
+ for (const pair of query.split('&')) {
36
+ const eqIndex = pair.indexOf('=');
37
+ if (eqIndex === -1)
38
+ continue;
39
+ const key = pair.slice(0, eqIndex);
40
+ const value = decodeURIComponent(pair.slice(eqIndex + 1));
41
+ if (key === 'reasoningEffort') {
42
+ reasoningEffort = value;
43
+ }
44
+ }
45
+ return { model: base, reasoningEffort };
46
+ }
47
+ /**
48
+ * Parse the run's model option into { model, reasoningEffort }, or all-undefined
49
+ * for native-default runs. Used by BOTH configFiles() (the TOML profile) and
50
+ * runnerExtra() (the CLI args), which MUST agree — so the parse happens once.
51
+ */
52
+ function parseOptionsModel(options) {
53
+ return options.model ? parseModelString(options.model) : { model: undefined, reasoningEffort: undefined };
54
+ }
55
+ /**
56
+ * Default reasoning effort and verbosity baked into the generated Codex
57
+ * profile.
58
+ *
59
+ * The Codex CLI itself defaults both `model_reasoning_effort` and
60
+ * `model_verbosity` to `"low"`, but the default Codex model
61
+ * (`gpt-5.2-codex`) only accepts `"medium"` for both — so an out-of-the-box
62
+ * `codex exec` against the AI Gateway fails with:
63
+ * "Unsupported value: 'low' is not supported with the 'gpt-5.2-codex'
64
+ * model. Supported values are: 'medium'."
65
+ * (the error covers both the `reasoning.effort` and `text.verbosity` request
66
+ * parameters, depending on which the model rejected first).
67
+ *
68
+ * `"medium"` is also a valid value for the non-codex GPT-5.x models, so it's
69
+ * a safe default. Callers can override reasoning effort per-run via
70
+ * `model: "gpt-5.2-codex?reasoningEffort=high"`.
71
+ */
72
+ const DEFAULT_REASONING_EFFORT = 'medium';
73
+ const DEFAULT_MODEL_VERBOSITY = 'medium';
74
+ /**
75
+ * Generate Codex profile config content.
76
+ *
77
+ * `reasoningEffort` and `model_verbosity` are written into the profile so a
78
+ * fresh `codex exec` doesn't pick up the CLI defaults of `"low"`, which are
79
+ * rejected by `gpt-5.2-codex`. Defaults to `"medium"` when `reasoningEffort`
80
+ * is omitted.
81
+ *
82
+ * Stays host-side (and exported) — the unit tests import it directly.
83
+ */
84
+ export function generateCodexConfig(model, useVercelAiGateway, reasoningEffort, webResearch) {
85
+ // Opt-in web research. Note: through the AI Gateway (`wire_api =
86
+ // "responses"`), no `web_search` items have been observed — Codex instead
87
+ // researches via shell commands when it decides to. The setting is still
88
+ // written so direct-OpenAI runs and future gateway support pick it up; it
89
+ // is harmless when the server-side tool is unavailable.
90
+ const toolsSection = webResearch ? `\n[tools]\nweb_search = true\n` : '';
91
+ if (useVercelAiGateway) {
92
+ // AI Gateway uses prefixed model names like "openai/gpt-5.2-codex".
93
+ // Native-default runs intentionally omit model and reasoning overrides.
94
+ const fullModel = model ? (model.includes('/') ? model : `openai/${model}`) : undefined;
95
+ return `# Codex configuration for Vercel AI Gateway
96
+ model_provider = "vercel"
97
+ ${fullModel ? `model = "${fullModel}"\n` : ''}${model ? `model_reasoning_effort = "${reasoningEffort ?? DEFAULT_REASONING_EFFORT}"\nmodel_verbosity = "${DEFAULT_MODEL_VERBOSITY}"\n` : ''}
98
+ [model_providers.vercel]
99
+ name = "Vercel AI Gateway"
100
+ base_url = "${AI_GATEWAY.openAiBaseUrl}"
101
+ env_key = "${AI_GATEWAY.apiKeyEnvVar}"
102
+ wire_api = "responses"
103
+ ${toolsSection}`;
104
+ }
105
+ else {
106
+ // Direct OpenAI API — use the built-in "openai" provider (no custom provider needed).
107
+ // Native-default runs intentionally omit model and reasoning overrides.
108
+ const directModel = model ? (model.includes('/') ? model.split('/').pop() : model) : undefined;
109
+ return `# Direct OpenAI API configuration
110
+ model_provider = "openai"
111
+ ${directModel ? `model = "${directModel}"\n` : ''}${model ? `model_reasoning_effort = "${reasoningEffort ?? DEFAULT_REASONING_EFFORT}"\nmodel_verbosity = "${DEFAULT_MODEL_VERBOSITY}"\n` : ''}${toolsSection}`;
112
+ }
113
+ }
114
+ /**
115
+ * Build the Codex plugin definition.
116
+ *
117
+ * Auth is two mutually-exclusive modes, preserved exactly from the old adapter:
118
+ * 1. Vercel AI Gateway → AI_GATEWAY_API_KEY (the gateway "vercel" provider's env_key)
119
+ * 2. Direct OpenAI API → OPENAI_API_KEY (the built-in "openai" provider's env_key)
120
+ * The runner additionally pipes the same key into `codex login --with-api-key` over
121
+ * stdin (reading it from process.env, never from the argv JSON).
122
+ */
123
+ export function createCodexDefinition({ useVercelAiGateway }) {
124
+ return {
125
+ name: useVercelAiGateway ? 'vercel-ai-gateway/codex' : 'codex',
126
+ displayName: useVercelAiGateway ? 'OpenAI Codex (Vercel AI Gateway)' : 'OpenAI Codex',
127
+ defaultModel: 'openai/gpt-5.2-codex',
128
+ o11yAgentName: 'codex',
129
+ // Resolve run.mjs next to this file (works in src during dev and in dist after
130
+ // the build copies run.mjs alongside the compiled agent.js).
131
+ runnerPath: fileURLToPath(new URL('./run.mjs', import.meta.url)),
132
+ getApiKeyEnvVar() {
133
+ return useVercelAiGateway ? AI_GATEWAY.apiKeyEnvVar : OPENAI_DIRECT.apiKeyEnvVar;
134
+ },
135
+ install(_options) {
136
+ // Project deps (retried once), then the Codex CLI globally. Error wording is
137
+ // preserved verbatim: 'npm install failed (exit code N):\n<last 10>' and
138
+ // 'Codex CLI install failed: <stderr>'.
139
+ return [
140
+ { kind: 'command', cmd: 'npm', args: ['install'], retryOnce: true, errorPrefix: 'npm install failed', errorBody: 'last10' },
141
+ { kind: 'command', cmd: 'npm', args: ['install', '-g', '@openai/codex'], errorPrefix: 'Codex CLI install failed', errorBody: 'stderr' },
142
+ ];
143
+ },
144
+ configFiles(options) {
145
+ // Recent Codex CLI versions reject the old top-level `profile = "default"`
146
+ // key in config.toml and instead load `$CODEX_HOME/<profile>.config.toml`
147
+ // when `--profile <profile>` is set. For explicit models, reasoning_effort
148
+ // is baked into the profile (rather than passed via -c at runtime) so the
149
+ // value is visible in saved configs and so the CLI's own default of "low"
150
+ // can't sneak through. For native-default runs we omit these settings.
151
+ const parsed = parseOptionsModel(options);
152
+ const configContent = generateCodexConfig(parsed.model, useVercelAiGateway, parsed.reasoningEffort, options.webResearch);
153
+ // Absolute `~` path writeFiles can't target → heredoc via shell. Combines the
154
+ // old `mkdir -p ~/.codex` + `cat > ~/.codex/default.config.toml << 'EOF'`.
155
+ return [
156
+ {
157
+ viaShell: `mkdir -p ~/.codex && cat > ~/.codex/default.config.toml << 'EOF'\n${configContent}\nEOF`,
158
+ },
159
+ ];
160
+ },
161
+ authEnv(options) {
162
+ // env_key the generated TOML expects: AI_GATEWAY_API_KEY for the "vercel"
163
+ // provider, OPENAI_API_KEY for the built-in "openai" provider. The runner
164
+ // also reads this same env to pipe the key into `codex login`.
165
+ const envVar = useVercelAiGateway ? AI_GATEWAY.apiKeyEnvVar : OPENAI_DIRECT.apiKeyEnvVar;
166
+ return { [envVar]: options.apiKey };
167
+ },
168
+ /**
169
+ * Host-computed values the runner must reproduce verbatim on the CLI. These
170
+ * derive from parseModelString and MUST match the TOML written in
171
+ * configFiles(), so they are computed here (host-side) and threaded into the
172
+ * runner via input.extra rather than re-deriving parseModelString in run.mjs.
173
+ *
174
+ * - cliModel: value for `--model` (gateway keeps the prefix,
175
+ * direct OpenAI strips it), or null to omit.
176
+ * - reasoningEffort: value for `-c model_reasoning_effort=...`, or null.
177
+ * - verbosity: value for `-c model_verbosity=...` (only when a
178
+ * model is set), or null to omit.
179
+ *
180
+ * (The login env var is chosen inside run.mjs from process.env — AI_GATEWAY_API_KEY
181
+ * else OPENAI_API_KEY — since authEnv() sets exactly one, so no flag is needed here.)
182
+ */
183
+ runnerExtra(options) {
184
+ const parsed = parseOptionsModel(options);
185
+ const baseModel = parsed.model;
186
+ // Direct OpenAI API needs unprefixed model names (e.g. "gpt-5.2-codex" not
187
+ // "openai/gpt-5.2-codex"); the gateway keeps the prefix as-is.
188
+ const cliModel = baseModel
189
+ ? (useVercelAiGateway ? baseModel : (baseModel.includes('/') ? baseModel.split('/').pop() : baseModel))
190
+ : undefined;
191
+ // Pass reasoning effort and verbosity via -c too; CLI flags have the highest
192
+ // precedence and we've observed Codex CLI silently falling back to its "low"
193
+ // defaults for both fields even when the profile sets them. Both default to
194
+ // "medium" for compatibility with gpt-5.2-codex. Omitted on native-default.
195
+ const reasoningEffort = baseModel ? (parsed.reasoningEffort ?? DEFAULT_REASONING_EFFORT) : undefined;
196
+ const verbosity = baseModel ? DEFAULT_MODEL_VERBOSITY : undefined;
197
+ return {
198
+ cliModel: cliModel ?? null,
199
+ reasoningEffort: reasoningEffort ?? null,
200
+ verbosity: verbosity ?? null,
201
+ };
202
+ },
203
+ };
204
+ }
205
+ /**
206
+ * Create the Codex Agent. Thin wrapper over the generic orchestrator so the Agent
207
+ * interface (and thus registry.ts / index.ts / runner.ts) is unchanged.
208
+ */
209
+ export function createCodexAgent({ useVercelAiGateway }) {
210
+ const definition = createCodexDefinition({ useVercelAiGateway });
211
+ return {
212
+ name: definition.name,
213
+ displayName: definition.displayName,
214
+ getApiKeyEnvVar: definition.getApiKeyEnvVar,
215
+ getDefaultModel() {
216
+ return definition.defaultModel;
217
+ },
218
+ run: (fixturePath, options) => runWithDefinition(definition, fixturePath, options),
219
+ };
220
+ }
221
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../../src/lib/agents/codex/agent.ts"],"names":[],"mappings":"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"}