@vercel/agent-eval 1.1.1 → 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.
- package/dist/lib/agents/claude-code/agent.d.ts +30 -0
- package/dist/lib/agents/claude-code/agent.d.ts.map +1 -0
- package/dist/lib/agents/claude-code/agent.js +80 -0
- package/dist/lib/agents/claude-code/agent.js.map +1 -0
- package/dist/lib/agents/claude-code/run.mjs +217 -0
- package/dist/lib/agents/codex/agent.d.ts +61 -0
- package/dist/lib/agents/codex/agent.d.ts.map +1 -0
- package/dist/lib/agents/codex/agent.js +221 -0
- package/dist/lib/agents/codex/agent.js.map +1 -0
- package/dist/lib/agents/codex/run.mjs +365 -0
- package/dist/lib/agents/cursor/agent.d.ts +32 -0
- package/dist/lib/agents/cursor/agent.d.ts.map +1 -0
- package/dist/lib/agents/cursor/agent.js +86 -0
- package/dist/lib/agents/cursor/agent.js.map +1 -0
- package/dist/lib/agents/cursor/run.mjs +183 -0
- package/dist/lib/agents/eval-helper.mjs +222 -0
- package/dist/lib/agents/gemini/agent.d.ts +27 -0
- package/dist/lib/agents/gemini/agent.d.ts.map +1 -0
- package/dist/lib/agents/gemini/agent.js +69 -0
- package/dist/lib/agents/gemini/agent.js.map +1 -0
- package/dist/lib/agents/gemini/run.mjs +180 -0
- package/dist/lib/agents/index.js +5 -5
- package/dist/lib/agents/index.js.map +1 -1
- package/dist/lib/agents/opencode/agent.d.ts +68 -0
- package/dist/lib/agents/opencode/agent.d.ts.map +1 -0
- package/dist/lib/agents/opencode/agent.js +165 -0
- package/dist/lib/agents/opencode/agent.js.map +1 -0
- package/dist/lib/agents/opencode/run.mjs +308 -0
- package/dist/lib/agents/plugin/contract.d.ts +157 -0
- package/dist/lib/agents/plugin/contract.d.ts.map +1 -0
- package/dist/lib/agents/plugin/contract.js +22 -0
- package/dist/lib/agents/plugin/contract.js.map +1 -0
- package/dist/lib/agents/plugin/orchestrator.d.ts +22 -0
- package/dist/lib/agents/plugin/orchestrator.d.ts.map +1 -0
- package/dist/lib/agents/plugin/orchestrator.js +286 -0
- package/dist/lib/agents/plugin/orchestrator.js.map +1 -0
- package/dist/lib/agents/shared.d.ts +7 -1
- package/dist/lib/agents/shared.d.ts.map +1 -1
- package/dist/lib/agents/shared.js +30 -3
- package/dist/lib/agents/shared.js.map +1 -1
- package/package.json +2 -2
- package/dist/lib/agents/claude-code.d.ts +0 -33
- package/dist/lib/agents/claude-code.d.ts.map +0 -1
- package/dist/lib/agents/claude-code.js +0 -310
- package/dist/lib/agents/claude-code.js.map +0 -1
- package/dist/lib/agents/codex.d.ts +0 -23
- package/dist/lib/agents/codex.d.ts.map +0 -1
- package/dist/lib/agents/codex.js +0 -364
- package/dist/lib/agents/codex.js.map +0 -1
- package/dist/lib/agents/cursor.d.ts +0 -10
- package/dist/lib/agents/cursor.d.ts.map +0 -1
- package/dist/lib/agents/cursor.js +0 -207
- package/dist/lib/agents/cursor.js.map +0 -1
- package/dist/lib/agents/gemini.d.ts +0 -10
- package/dist/lib/agents/gemini.d.ts.map +0 -1
- package/dist/lib/agents/gemini.js +0 -208
- package/dist/lib/agents/gemini.js.map +0 -1
- package/dist/lib/agents/opencode.d.ts +0 -46
- package/dist/lib/agents/opencode.d.ts.map +0 -1
- package/dist/lib/agents/opencode.js +0 -365
- package/dist/lib/agents/opencode.js.map +0 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode 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
|
+
* OpenCode only supports the Vercel AI Gateway (no direct provider APIs), so there
|
|
10
|
+
* is a single variant: `vercel-ai-gateway/opencode`.
|
|
11
|
+
*
|
|
12
|
+
* `generateOpenCodeConfig` (the pure host-side config generator) STAYS in this file
|
|
13
|
+
* and is exported so the existing unit tests keep importing it. The transcript /
|
|
14
|
+
* observed-model parsing helpers (`extractObservedModelFromOpenCodeOutput`,
|
|
15
|
+
* `extractSessionIdFromTranscript`, `extractObservedModelFromSessionExport`) moved
|
|
16
|
+
* INTO ./run.mjs (so the tested logic is exactly what the sandbox runs) and the
|
|
17
|
+
* test now imports them from there — see the test import change in the migration
|
|
18
|
+
* notes.
|
|
19
|
+
*/
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import { AI_GATEWAY } from '../shared.js';
|
|
22
|
+
import { runWithDefinition } from '../plugin/orchestrator.js';
|
|
23
|
+
/**
|
|
24
|
+
* Generate OpenCode config file content.
|
|
25
|
+
* Configures the Vercel AI Gateway provider, plus any additional providers.
|
|
26
|
+
*
|
|
27
|
+
* STAYS host-side + exported (the unit test imports it). The content is written
|
|
28
|
+
* verbatim into `opencode.json` in the sandbox by the orchestrator. Behavior is
|
|
29
|
+
* identical to the old adapter, including writing the resolved apiKey into the
|
|
30
|
+
* config (falling back to the `{env:AI_GATEWAY_API_KEY}` placeholder).
|
|
31
|
+
*/
|
|
32
|
+
export function generateOpenCodeConfig(extraProviders, apiKey, timeoutMs, webResearch) {
|
|
33
|
+
const vercelBase = {
|
|
34
|
+
options: {
|
|
35
|
+
apiKey: apiKey || '{env:AI_GATEWAY_API_KEY}',
|
|
36
|
+
...(timeoutMs ? { timeout: timeoutMs } : {}),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const { vercel: vercelExtra, ...otherProviders } = extraProviders || {};
|
|
40
|
+
const providers = {
|
|
41
|
+
vercel: {
|
|
42
|
+
...vercelBase,
|
|
43
|
+
...vercelExtra,
|
|
44
|
+
options: { ...vercelBase.options, ...vercelExtra?.options },
|
|
45
|
+
},
|
|
46
|
+
...otherProviders,
|
|
47
|
+
};
|
|
48
|
+
return JSON.stringify({
|
|
49
|
+
$schema: 'https://opencode.ai/config.json',
|
|
50
|
+
provider: providers,
|
|
51
|
+
permission: {
|
|
52
|
+
write: 'allow',
|
|
53
|
+
edit: 'allow',
|
|
54
|
+
bash: 'allow',
|
|
55
|
+
// OpenCode has no native web search; Exa-backed search is enabled via
|
|
56
|
+
// OPENCODE_ENABLE_EXA=1 alongside these tool permissions.
|
|
57
|
+
...(webResearch ? { webfetch: 'allow', websearch: 'allow' } : {}),
|
|
58
|
+
},
|
|
59
|
+
}, null, 2);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build the OpenCode plugin definition.
|
|
63
|
+
*
|
|
64
|
+
* Auth is single-mode: the Vercel AI Gateway. authEnv() also carries the Exa
|
|
65
|
+
* websearch toggle (OPENCODE_ENABLE_EXA) when webResearch is on — it rides in
|
|
66
|
+
* process.env alongside the gateway key, exactly as the old adapter set it on the
|
|
67
|
+
* CLI's spawn env. The matching tool permissions are written into opencode.json by
|
|
68
|
+
* generateOpenCodeConfig.
|
|
69
|
+
*/
|
|
70
|
+
export function createOpenCodeDefinition() {
|
|
71
|
+
return {
|
|
72
|
+
name: 'vercel-ai-gateway/opencode',
|
|
73
|
+
displayName: 'OpenCode (Vercel AI Gateway)',
|
|
74
|
+
defaultModel: 'vercel/anthropic/claude-sonnet-4',
|
|
75
|
+
o11yAgentName: 'vercel-ai-gateway/opencode',
|
|
76
|
+
// Resolve run.mjs next to this file (works in src during dev and in dist after
|
|
77
|
+
// the build copies run.mjs alongside the compiled agent.js).
|
|
78
|
+
runnerPath: fileURLToPath(new URL('./run.mjs', import.meta.url)),
|
|
79
|
+
// OpenCode only supports the Vercel AI Gateway, never direct provider APIs.
|
|
80
|
+
getApiKeyEnvVar() {
|
|
81
|
+
return AI_GATEWAY.apiKeyEnvVar;
|
|
82
|
+
},
|
|
83
|
+
install(options) {
|
|
84
|
+
// Project deps (retried once, last-10-lines wording), then the OpenCode CLI.
|
|
85
|
+
// The CLI has two mutually-exclusive install paths preserved from the old
|
|
86
|
+
// adapter:
|
|
87
|
+
// - binaryUrl set → curl a custom binary into $HOME/.local/bin (e.g. a
|
|
88
|
+
// patched build for unreleased models). Error body is stdout+stderr.
|
|
89
|
+
// - otherwise → `npm install -g opencode-ai`. Error body is stderr.
|
|
90
|
+
const binaryUrl = options.agentOptions?.binaryUrl;
|
|
91
|
+
const steps = [
|
|
92
|
+
{
|
|
93
|
+
kind: 'command',
|
|
94
|
+
cmd: 'npm',
|
|
95
|
+
args: ['install'],
|
|
96
|
+
retryOnce: true,
|
|
97
|
+
errorPrefix: 'npm install failed',
|
|
98
|
+
errorBody: 'last10',
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
if (binaryUrl) {
|
|
102
|
+
// Download a custom binary (e.g. a patched build for unreleased models).
|
|
103
|
+
// Invoked as the old adapter did: `bash -c "<line>"` via a 'command' step,
|
|
104
|
+
// so the curl line is byte-identical. On failure the orchestrator renders
|
|
105
|
+
// `OpenCode CLI install failed: <stderr>`; the old adapter rendered
|
|
106
|
+
// `OpenCode CLI install failed: <stdout> <stderr>` — for `curl -fsSL`
|
|
107
|
+
// stdout is empty on failure, so the only difference is a dropped leading
|
|
108
|
+
// space (see behaviorNotes / contractAdditions for the exact-parity option).
|
|
109
|
+
steps.push({
|
|
110
|
+
kind: 'command',
|
|
111
|
+
cmd: 'bash',
|
|
112
|
+
args: [
|
|
113
|
+
'-c',
|
|
114
|
+
`mkdir -p $HOME/.local/bin && curl -fsSL "${binaryUrl}" -o $HOME/.local/bin/opencode && chmod +x $HOME/.local/bin/opencode`,
|
|
115
|
+
],
|
|
116
|
+
errorPrefix: 'OpenCode CLI install failed',
|
|
117
|
+
errorBody: 'stderr',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
steps.push({
|
|
122
|
+
kind: 'command',
|
|
123
|
+
cmd: 'npm',
|
|
124
|
+
args: ['install', '-g', 'opencode-ai'],
|
|
125
|
+
errorPrefix: 'OpenCode CLI install failed',
|
|
126
|
+
errorBody: 'stderr',
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return steps;
|
|
130
|
+
},
|
|
131
|
+
// OpenCode is configured via a project-local opencode.json (writeFiles target,
|
|
132
|
+
// relative to cwd — not a `~` path, so no viaShell heredoc needed).
|
|
133
|
+
configFiles(options) {
|
|
134
|
+
const extraProviders = options.agentOptions?.extraProviders;
|
|
135
|
+
const content = generateOpenCodeConfig(extraProviders, options.apiKey, options.timeout, options.webResearch);
|
|
136
|
+
return [{ path: 'opencode.json', content }];
|
|
137
|
+
},
|
|
138
|
+
authEnv(options) {
|
|
139
|
+
return {
|
|
140
|
+
[AI_GATEWAY.apiKeyEnvVar]: options.apiKey,
|
|
141
|
+
// Exa-backed websearch is gated behind this env var in the OpenCode CLI;
|
|
142
|
+
// the matching tool permissions are written into opencode.json by
|
|
143
|
+
// generateOpenCodeConfig.
|
|
144
|
+
...(options.webResearch ? { OPENCODE_ENABLE_EXA: '1' } : {}),
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Create the OpenCode Agent. Thin wrapper over the generic orchestrator so the
|
|
151
|
+
* Agent interface (and thus registry.ts / index.ts / runner.ts) is unchanged.
|
|
152
|
+
*/
|
|
153
|
+
export function createOpenCodeAgent() {
|
|
154
|
+
const definition = createOpenCodeDefinition();
|
|
155
|
+
return {
|
|
156
|
+
name: definition.name,
|
|
157
|
+
displayName: definition.displayName,
|
|
158
|
+
getApiKeyEnvVar: definition.getApiKeyEnvVar,
|
|
159
|
+
getDefaultModel() {
|
|
160
|
+
return definition.defaultModel;
|
|
161
|
+
},
|
|
162
|
+
run: (fixturePath, options) => runWithDefinition(definition, fixturePath, options),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../../src/lib/agents/opencode/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode 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 `opencode` CLI — it cannot import anything
|
|
8
|
+
* from 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
|
+
* The pure helpers below are exported (not just `runAgent`) so they can be
|
|
17
|
+
* unit-tested directly — the same code the sandbox runs (see opencode.test.ts).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { spawnSync } from 'node:child_process';
|
|
21
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { dirname } from 'node:path';
|
|
23
|
+
import { fileURLToPath } from 'node:url';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build the OpenCode CLI argument list.
|
|
27
|
+
*
|
|
28
|
+
* Preserved verbatim from the old adapter:
|
|
29
|
+
* - `run <prompt> --format json` is always emitted (`--format json` gives the
|
|
30
|
+
* structured JSON event stream we parse for the transcript).
|
|
31
|
+
* - `--model <model>` is appended when a model override is present.
|
|
32
|
+
* - else, when modelPolicy === 'native-default', `--print-logs --log-level INFO`
|
|
33
|
+
* is appended so older OpenCode versions print the CLI-selected model (the
|
|
34
|
+
* log-scrape path) without a follow-up export call.
|
|
35
|
+
*
|
|
36
|
+
* @param {{prompt:string, model?:string, modelPolicy?:string}} input
|
|
37
|
+
* @returns {string[]}
|
|
38
|
+
*/
|
|
39
|
+
export function buildOpenCodeCliArgs(input) {
|
|
40
|
+
const cliArgs = ['run', input.prompt, '--format', 'json'];
|
|
41
|
+
if (input.model) {
|
|
42
|
+
cliArgs.push('--model', input.model);
|
|
43
|
+
} else if (input.modelPolicy === 'native-default') {
|
|
44
|
+
cliArgs.push('--print-logs', '--log-level', 'INFO');
|
|
45
|
+
}
|
|
46
|
+
return cliArgs;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Extract transcript from OpenCode JSON output.
|
|
51
|
+
* When run with --format json, OpenCode outputs JSON events to stdout.
|
|
52
|
+
* Preserved verbatim from the old adapter.
|
|
53
|
+
*
|
|
54
|
+
* @param {string|undefined|null} output
|
|
55
|
+
* @returns {string|undefined}
|
|
56
|
+
*/
|
|
57
|
+
export function extractTranscriptFromOutput(output) {
|
|
58
|
+
if (!output || !output.trim()) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The --format json output contains JSON events, one per line.
|
|
63
|
+
// Filter to only include lines that look like JSON objects.
|
|
64
|
+
const lines = output.split('\n').filter((line) => {
|
|
65
|
+
const trimmed = line.trim();
|
|
66
|
+
return trimmed.startsWith('{') && trimmed.endsWith('}');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (lines.length === 0) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return lines.join('\n');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Scrape the OpenCode printed logs for the primary build model.
|
|
78
|
+
* Works on OpenCode <= 1.16.x, whose INFO log lines carry providerID/modelID.
|
|
79
|
+
* Preserved verbatim from the old adapter.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} output
|
|
82
|
+
* @returns {string|undefined}
|
|
83
|
+
*/
|
|
84
|
+
export function extractObservedModelFromOpenCodeOutput(output) {
|
|
85
|
+
let observedModel;
|
|
86
|
+
|
|
87
|
+
for (const line of output.split('\n')) {
|
|
88
|
+
if (!line.includes('service=llm') || !line.includes('small=false') || !line.includes('agent=build')) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const providerMatch = line.match(/providerID=([^\s]+)/);
|
|
93
|
+
const modelMatch = line.match(/modelID=([^\s]+)/);
|
|
94
|
+
const providerID = providerMatch?.[1];
|
|
95
|
+
const modelID = modelMatch?.[1];
|
|
96
|
+
if (providerID && modelID) {
|
|
97
|
+
observedModel = `${providerID}/${modelID}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return observedModel;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Extract the session id from the `--format json` event stream.
|
|
106
|
+
* Every emitted event carries a `sessionID` field.
|
|
107
|
+
* Preserved verbatim from the old adapter.
|
|
108
|
+
*
|
|
109
|
+
* @param {string|undefined} transcript
|
|
110
|
+
* @returns {string|undefined}
|
|
111
|
+
*/
|
|
112
|
+
export function extractSessionIdFromTranscript(transcript) {
|
|
113
|
+
if (!transcript) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
for (const line of transcript.split('\n')) {
|
|
118
|
+
try {
|
|
119
|
+
const event = JSON.parse(line);
|
|
120
|
+
if (typeof event.sessionID === 'string' && event.sessionID) {
|
|
121
|
+
return event.sessionID;
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
// Skip non-JSON lines
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Extract the observed model from `opencode export <sessionID>` output.
|
|
133
|
+
* Assistant messages carry `providerID` and `modelID` in their info.
|
|
134
|
+
* Preserved verbatim from the old adapter.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} exportOutput
|
|
137
|
+
* @returns {string|undefined}
|
|
138
|
+
*/
|
|
139
|
+
export function extractObservedModelFromSessionExport(exportOutput) {
|
|
140
|
+
const start = exportOutput.indexOf('{');
|
|
141
|
+
if (start === -1) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = JSON.parse(exportOutput.slice(start));
|
|
148
|
+
} catch {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const messages = parsed.messages;
|
|
153
|
+
if (!Array.isArray(messages)) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
for (const message of messages) {
|
|
158
|
+
const info = message.info;
|
|
159
|
+
if (info?.role !== 'assistant') {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (
|
|
163
|
+
typeof info.providerID === 'string' && info.providerID &&
|
|
164
|
+
typeof info.modelID === 'string' && info.modelID
|
|
165
|
+
) {
|
|
166
|
+
return `${info.providerID}/${info.modelID}`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Run OpenCode over the workspace at `input.cwd` and return a RunnerResult.
|
|
175
|
+
*
|
|
176
|
+
* Auth (AI_GATEWAY_API_KEY, and OPENCODE_ENABLE_EXA when web research is on)
|
|
177
|
+
* arrives via process.env — the orchestrator sets it on the `node run.mjs`
|
|
178
|
+
* invocation, and we pass process.env straight through to the CLI. The runner
|
|
179
|
+
* never handles secrets itself.
|
|
180
|
+
*
|
|
181
|
+
* @param {import('../plugin/contract.js').AgentRunInput} input
|
|
182
|
+
* @returns {Promise<import('../plugin/contract.js').RunnerResult>}
|
|
183
|
+
*/
|
|
184
|
+
export async function runAgent(input) {
|
|
185
|
+
const args = buildOpenCodeCliArgs(input);
|
|
186
|
+
|
|
187
|
+
// spawnSync (not a shell string): the prompt is a plain argv element, so there
|
|
188
|
+
// is no shell quoting/escaping to get wrong. Blocking is fine — the runner has
|
|
189
|
+
// nothing else to do while the agent works. The sandbox-level timeout bounds it.
|
|
190
|
+
const res = spawnSync('opencode', args, {
|
|
191
|
+
cwd: input.cwd,
|
|
192
|
+
env: process.env,
|
|
193
|
+
encoding: 'utf8',
|
|
194
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const stdout = res.stdout || '';
|
|
198
|
+
const stderr = res.stderr || '';
|
|
199
|
+
// Preserve the old concatenation order: stdout THEN stderr.
|
|
200
|
+
const output = stdout + stderr;
|
|
201
|
+
// spawnSync sets status=null + error when the binary can't be spawned at all.
|
|
202
|
+
const agentExitCode = res.status == null ? -1 : res.status;
|
|
203
|
+
|
|
204
|
+
// Capture the transcript from the combined output (old: over stdout+stderr).
|
|
205
|
+
const transcript = extractTranscriptFromOutput(output) ?? null;
|
|
206
|
+
|
|
207
|
+
// Resolve the model OpenCode actually used. The `--format json` events never
|
|
208
|
+
// include it, so first try scraping the printed logs (works on OpenCode <=
|
|
209
|
+
// 1.16.x), then fall back to `opencode export <sessionID>`, whose assistant
|
|
210
|
+
// messages carry providerID/modelID (OpenCode 1.17.0 changed the log format,
|
|
211
|
+
// which broke the scrape). Observation must never fail the run.
|
|
212
|
+
let observedModel = extractObservedModelFromOpenCodeOutput(output);
|
|
213
|
+
if (!observedModel) {
|
|
214
|
+
const sessionId = extractSessionIdFromTranscript(transcript ?? undefined);
|
|
215
|
+
if (sessionId) {
|
|
216
|
+
try {
|
|
217
|
+
const exportRes = spawnSync('opencode', ['export', sessionId], {
|
|
218
|
+
cwd: input.cwd,
|
|
219
|
+
env: process.env,
|
|
220
|
+
encoding: 'utf8',
|
|
221
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
222
|
+
});
|
|
223
|
+
if ((exportRes.status == null ? -1 : exportRes.status) === 0) {
|
|
224
|
+
observedModel = extractObservedModelFromSessionExport(exportRes.stdout || '');
|
|
225
|
+
}
|
|
226
|
+
} catch {
|
|
227
|
+
// Leave observedModel undefined.
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const observedModelOrNull = observedModel ?? null;
|
|
232
|
+
|
|
233
|
+
if (res.error || agentExitCode !== 0) {
|
|
234
|
+
// Mirror the old error string: last 5 lines of output, else a coded fallback.
|
|
235
|
+
const errorLines = output.trim().split('\n').slice(-5).join('\n');
|
|
236
|
+
const fallback = res.error
|
|
237
|
+
? `Failed to run opencode: ${res.error.message}`
|
|
238
|
+
: `OpenCode CLI exited with code ${agentExitCode}`;
|
|
239
|
+
return {
|
|
240
|
+
ok: false,
|
|
241
|
+
output,
|
|
242
|
+
transcript,
|
|
243
|
+
observedModel: observedModelOrNull,
|
|
244
|
+
error: errorLines || fallback,
|
|
245
|
+
agentExitCode,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
ok: true,
|
|
251
|
+
output,
|
|
252
|
+
transcript,
|
|
253
|
+
observedModel: observedModelOrNull,
|
|
254
|
+
error: null,
|
|
255
|
+
agentExitCode,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* ─────────────────────────── runnable (CLI) entry ─────────────────────────── */
|
|
260
|
+
|
|
261
|
+
// True when this file is executed directly (`node run.mjs ...`), false when imported.
|
|
262
|
+
const isMain = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
|
|
263
|
+
|
|
264
|
+
if (isMain) {
|
|
265
|
+
// argv[2] is the AgentRunInput JSON (never contains secrets).
|
|
266
|
+
const input = JSON.parse(process.argv[2]);
|
|
267
|
+
|
|
268
|
+
// Always produce a RunnerResult, even if the runner itself throws, so the host
|
|
269
|
+
// always has a result file to read (node exit code stays 0 except on a truly
|
|
270
|
+
// unrecoverable crash before we can write).
|
|
271
|
+
let result;
|
|
272
|
+
try {
|
|
273
|
+
result = await runAgent(input);
|
|
274
|
+
} catch (e) {
|
|
275
|
+
result = {
|
|
276
|
+
ok: false,
|
|
277
|
+
output: '',
|
|
278
|
+
transcript: null,
|
|
279
|
+
observedModel: null,
|
|
280
|
+
error: e && e.message ? e.message : String(e),
|
|
281
|
+
agentExitCode: -1,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Source of truth: the result file the host reads back via sandbox.readFile.
|
|
286
|
+
try {
|
|
287
|
+
mkdirSync(dirname(input.resultPath), { recursive: true });
|
|
288
|
+
writeFileSync(input.resultPath, JSON.stringify(result));
|
|
289
|
+
} catch {
|
|
290
|
+
// If the file can't be written, the host falls back to the marker line below.
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Fallback channel: a compact status line (no transcript — it can be huge).
|
|
294
|
+
process.stdout.write(
|
|
295
|
+
'__AGENT_RESULT__ ' +
|
|
296
|
+
JSON.stringify({
|
|
297
|
+
ok: result.ok,
|
|
298
|
+
observedModel: result.observedModel,
|
|
299
|
+
error: result.error,
|
|
300
|
+
agentExitCode: result.agentExitCode,
|
|
301
|
+
}) +
|
|
302
|
+
'\n'
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// Exit 0: "the runner ran". Agent success/failure is conveyed via result.ok, not
|
|
306
|
+
// the node exit code (the host distinguishes the two).
|
|
307
|
+
process.exit(0);
|
|
308
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent plugin contract.
|
|
3
|
+
*
|
|
4
|
+
* An agent is described in two halves:
|
|
5
|
+
*
|
|
6
|
+
* 1. an {@link AgentDefinition} — HOST-side data + tiny pure functions that say
|
|
7
|
+
* *how to set up and authenticate* the agent (install commands, config files,
|
|
8
|
+
* auth env). It performs NO sandbox lifecycle and NO CLI invocation itself.
|
|
9
|
+
*
|
|
10
|
+
* 2. a `run.mjs` — a SANDBOX-side script (one per agent) that actually invokes
|
|
11
|
+
* the CLI and captures its transcript, returning a {@link RunnerResult}.
|
|
12
|
+
*
|
|
13
|
+
* The generic {@link runWithDefinition} orchestrator (orchestrator.ts) consumes a
|
|
14
|
+
* definition, drives the shared sandbox lifecycle, ships the agent's `run.mjs` into
|
|
15
|
+
* the sandbox, invokes it, and assembles the final `AgentRunResult`.
|
|
16
|
+
*
|
|
17
|
+
* This split exists so the invocation logic lives *in the sandbox* (where a future
|
|
18
|
+
* in-sandbox judge can `import { runAgent }` and reuse it) rather than only on the
|
|
19
|
+
* host. See the migration notes in the PR for the full rationale.
|
|
20
|
+
*/
|
|
21
|
+
import type { ModelTier } from '../../types.js';
|
|
22
|
+
import type { AgentRunOptions } from '../types.js';
|
|
23
|
+
/**
|
|
24
|
+
* One install action the orchestrator runs in the sandbox before invocation.
|
|
25
|
+
*
|
|
26
|
+
* Each step carries its own failure policy so the per-agent install error
|
|
27
|
+
* messages are preserved verbatim (e.g. claude throws `Claude Code install
|
|
28
|
+
* failed: <stderr>`, the project `npm install` throws `npm install failed
|
|
29
|
+
* (exit code N):\n<last 10 lines>` and is retried once).
|
|
30
|
+
*/
|
|
31
|
+
export interface InstallStep {
|
|
32
|
+
/** 'command' → sandbox.runCommand(cmd, args); 'shell' → sandbox.runShell(script). */
|
|
33
|
+
kind: 'command' | 'shell';
|
|
34
|
+
/** For kind:'command'. */
|
|
35
|
+
cmd?: string;
|
|
36
|
+
args?: string[];
|
|
37
|
+
/** For kind:'shell'. */
|
|
38
|
+
script?: string;
|
|
39
|
+
/** Retry once on a non-zero exit before failing (the project `npm install`). */
|
|
40
|
+
retryOnce?: boolean;
|
|
41
|
+
/** Prefix of the thrown Error on final failure, e.g. 'Claude Code install failed'. */
|
|
42
|
+
errorPrefix: string;
|
|
43
|
+
/**
|
|
44
|
+
* How the failure body is rendered in the thrown Error, to match today's wording:
|
|
45
|
+
* - 'last10': `${errorPrefix} (exit code N):\n<last 10 lines of stdout+stderr>`
|
|
46
|
+
* - 'stderr': `${errorPrefix}: <stderr>`
|
|
47
|
+
*/
|
|
48
|
+
errorBody: 'last10' | 'stderr';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* One config file an agent writes into the sandbox before invocation.
|
|
52
|
+
* Either a writeFiles target (relative to cwd) or a shell snippet — the latter is
|
|
53
|
+
* the escape hatch for absolute `~` paths that writeFiles cannot target (codex's
|
|
54
|
+
* `~/.codex/default.config.toml`).
|
|
55
|
+
*/
|
|
56
|
+
export interface ConfigFile {
|
|
57
|
+
/** writeFiles target path (relative to cwd). Mutually exclusive with viaShell. */
|
|
58
|
+
path?: string;
|
|
59
|
+
content?: string;
|
|
60
|
+
/** Exact shell to run instead, e.g. `mkdir -p ~/.codex && cat > ~/.codex/... << 'EOF' ...`. */
|
|
61
|
+
viaShell?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Host-side plugin description for one agent. Pure data + tiny pure functions —
|
|
65
|
+
* no sandbox calls, no CLI invocation.
|
|
66
|
+
*/
|
|
67
|
+
export interface AgentDefinition {
|
|
68
|
+
/** Registry name, unchanged: 'claude-code' | 'vercel-ai-gateway/claude-code' | ... */
|
|
69
|
+
name: string;
|
|
70
|
+
/** Human-readable name (logs/UI), unchanged from the old adapter. */
|
|
71
|
+
displayName: string;
|
|
72
|
+
/** Default model tier when none is provided (old getDefaultModel()). */
|
|
73
|
+
defaultModel: ModelTier;
|
|
74
|
+
/** Parser name handed to parseTranscript() on the host ('claude-code'|'codex'|...). */
|
|
75
|
+
o11yAgentName: string;
|
|
76
|
+
/** Absolute path to this agent's run.mjs (resolved from the definition's import.meta.url). */
|
|
77
|
+
runnerPath: string;
|
|
78
|
+
/**
|
|
79
|
+
* Which host env var the apiKey is read from. Mirrors the old getApiKeyEnvVar()
|
|
80
|
+
* EXACTLY, including claude-code's 3-way runtime branch (gateway →
|
|
81
|
+
* CLAUDE_CODE_OAUTH_TOKEN → ANTHROPIC_API_KEY). Stays a function because it reads
|
|
82
|
+
* process.env at call time.
|
|
83
|
+
*/
|
|
84
|
+
getApiKeyEnvVar(): string;
|
|
85
|
+
/** Ordered install steps (project deps + the agent CLI), run by the orchestrator. */
|
|
86
|
+
install(options: AgentRunOptions): InstallStep[];
|
|
87
|
+
/** Config files written before invocation (codex TOML, opencode.json). [] for most. */
|
|
88
|
+
configFiles(options: AgentRunOptions): ConfigFile[];
|
|
89
|
+
/**
|
|
90
|
+
* The agent-specific auth/env handed to the run.mjs process (merged with the
|
|
91
|
+
* neutral-workspace env by the orchestrator). This is the ONLY place provider
|
|
92
|
+
* auth branching lives. Receives the resolved apiKey via options.apiKey.
|
|
93
|
+
*/
|
|
94
|
+
authEnv(options: AgentRunOptions): Record<string, string>;
|
|
95
|
+
/**
|
|
96
|
+
* OPTIONAL host-computed values threaded into the runner as `input.extra`.
|
|
97
|
+
*
|
|
98
|
+
* Use this when run.mjs needs a value that MUST be derived on the host (e.g.
|
|
99
|
+
* codex's parseModelString output — the resolved `--model`, reasoning effort,
|
|
100
|
+
* and verbosity — which must match the TOML config written by configFiles()).
|
|
101
|
+
* Keeping the derivation host-side avoids re-implementing host-only parsing in
|
|
102
|
+
* the zero-dependency runner. Must contain NO secrets (it rides in the argv
|
|
103
|
+
* JSON). Omit (or return undefined) for agents that don't need it.
|
|
104
|
+
*/
|
|
105
|
+
runnerExtra?(options: AgentRunOptions): Record<string, unknown>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* What the host passes INTO run.mjs (serialized as argv[2] JSON).
|
|
109
|
+
*
|
|
110
|
+
* SECURITY: the apiKey is intentionally NOT here — it travels only via process.env
|
|
111
|
+
* (and, for codex, the CLI's stdin login). Never put secrets in argv (they show up
|
|
112
|
+
* in process listings).
|
|
113
|
+
*/
|
|
114
|
+
export interface AgentRunInput {
|
|
115
|
+
/** The prompt to run, verbatim (any host-side editPrompt was already applied upstream). */
|
|
116
|
+
prompt: string;
|
|
117
|
+
/** Model override, or undefined for the CLI's native default. */
|
|
118
|
+
model?: string;
|
|
119
|
+
/** 'agent-default' | 'native-default' (opencode toggles --print-logs on native). */
|
|
120
|
+
modelPolicy?: string;
|
|
121
|
+
/** Web-research toggle (claude --allowedTools, opencode permissions/env). */
|
|
122
|
+
webResearch?: boolean;
|
|
123
|
+
/** Passthrough of agentOptions (e.g. claude effort). Secrets must NOT be in here. */
|
|
124
|
+
agentOptions?: Record<string, unknown>;
|
|
125
|
+
/** Absolute sandbox cwd AFTER neutral-workspace relocation (transcript paths use it). */
|
|
126
|
+
cwd: string;
|
|
127
|
+
/** Where run.mjs writes its RunnerResult JSON (host reads it back). */
|
|
128
|
+
resultPath: string;
|
|
129
|
+
/**
|
|
130
|
+
* OPTIONAL host-computed values from {@link AgentDefinition.runnerExtra} — see
|
|
131
|
+
* there for what belongs here and the no-secrets constraint.
|
|
132
|
+
*/
|
|
133
|
+
extra?: Record<string, unknown>;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Host↔sandbox result contract. run.mjs writes this JSON to `input.resultPath`
|
|
137
|
+
* AND prints one `__AGENT_RESULT__ <json>` status line to stdout (a fallback the
|
|
138
|
+
* host uses only if the result file can't be read).
|
|
139
|
+
*
|
|
140
|
+
* The `ok` (agent CLI succeeded) vs the node exit code (the runner itself crashed)
|
|
141
|
+
* are deliberately separate signals — see the orchestrator's READ RESULT step.
|
|
142
|
+
*/
|
|
143
|
+
export interface RunnerResult {
|
|
144
|
+
/** True iff the agent CLI exited 0. */
|
|
145
|
+
ok: boolean;
|
|
146
|
+
/** Combined stdout + stderr of the agent CLI (old `agentOutput`). */
|
|
147
|
+
output: string;
|
|
148
|
+
/** Raw transcript string the runner located (JSONL/JSON), or null. */
|
|
149
|
+
transcript: string | null;
|
|
150
|
+
/** Observed model extracted by the runner (claude/codex/opencode), or null. */
|
|
151
|
+
observedModel: string | null;
|
|
152
|
+
/** Error message when !ok (old "last 5 lines" / "<Agent> exited with code N"). */
|
|
153
|
+
error: string | null;
|
|
154
|
+
/** The agent CLI's exit code (diagnostics; -1 if it could not be spawned). */
|
|
155
|
+
agentExitCode: number;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../../src/lib/agents/plugin/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,qFAAqF;IACrF,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,0BAA0B;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,YAAY,EAAE,SAAS,CAAC;IACxB,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;;OAKG;IACH,eAAe,IAAI,MAAM,CAAC;IAE1B,qFAAqF;IACrF,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,EAAE,CAAC;IAEjD,uFAAuF;IACvF,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,UAAU,EAAE,CAAC;IAEpD;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1D;;;;;;;;;OASG;IACH,WAAW,CAAC,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,yFAAyF;IACzF,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,+EAA+E;IAC/E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kFAAkF;IAClF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;CACvB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent plugin contract.
|
|
3
|
+
*
|
|
4
|
+
* An agent is described in two halves:
|
|
5
|
+
*
|
|
6
|
+
* 1. an {@link AgentDefinition} — HOST-side data + tiny pure functions that say
|
|
7
|
+
* *how to set up and authenticate* the agent (install commands, config files,
|
|
8
|
+
* auth env). It performs NO sandbox lifecycle and NO CLI invocation itself.
|
|
9
|
+
*
|
|
10
|
+
* 2. a `run.mjs` — a SANDBOX-side script (one per agent) that actually invokes
|
|
11
|
+
* the CLI and captures its transcript, returning a {@link RunnerResult}.
|
|
12
|
+
*
|
|
13
|
+
* The generic {@link runWithDefinition} orchestrator (orchestrator.ts) consumes a
|
|
14
|
+
* definition, drives the shared sandbox lifecycle, ships the agent's `run.mjs` into
|
|
15
|
+
* the sandbox, invokes it, and assembles the final `AgentRunResult`.
|
|
16
|
+
*
|
|
17
|
+
* This split exists so the invocation logic lives *in the sandbox* (where a future
|
|
18
|
+
* in-sandbox judge can `import { runAgent }` and reuse it) rather than only on the
|
|
19
|
+
* host. See the migration notes in the PR for the full rationale.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../../src/lib/agents/plugin/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|