agent-eval-opencode 0.10.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/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +590 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agents/claude-code.d.ts +12 -0
- package/dist/lib/agents/claude-code.d.ts.map +1 -0
- package/dist/lib/agents/claude-code.js +231 -0
- package/dist/lib/agents/claude-code.js.map +1 -0
- package/dist/lib/agents/codex.d.ts +12 -0
- package/dist/lib/agents/codex.d.ts.map +1 -0
- package/dist/lib/agents/codex.js +267 -0
- package/dist/lib/agents/codex.js.map +1 -0
- package/dist/lib/agents/cursor.d.ts +10 -0
- package/dist/lib/agents/cursor.d.ts.map +1 -0
- package/dist/lib/agents/cursor.js +204 -0
- package/dist/lib/agents/cursor.js.map +1 -0
- package/dist/lib/agents/gemini.d.ts +10 -0
- package/dist/lib/agents/gemini.d.ts.map +1 -0
- package/dist/lib/agents/gemini.js +207 -0
- package/dist/lib/agents/gemini.js.map +1 -0
- package/dist/lib/agents/index.d.ts +7 -0
- package/dist/lib/agents/index.d.ts.map +1 -0
- package/dist/lib/agents/index.js +20 -0
- package/dist/lib/agents/index.js.map +1 -0
- package/dist/lib/agents/opencode.d.ts +11 -0
- package/dist/lib/agents/opencode.d.ts.map +1 -0
- package/dist/lib/agents/opencode.js +245 -0
- package/dist/lib/agents/opencode.js.map +1 -0
- package/dist/lib/agents/registry.d.ts +23 -0
- package/dist/lib/agents/registry.d.ts.map +1 -0
- package/dist/lib/agents/registry.js +35 -0
- package/dist/lib/agents/registry.js.map +1 -0
- package/dist/lib/agents/shared.d.ts +83 -0
- package/dist/lib/agents/shared.d.ts.map +1 -0
- package/dist/lib/agents/shared.js +192 -0
- package/dist/lib/agents/shared.js.map +1 -0
- package/dist/lib/agents/types.d.ts +73 -0
- package/dist/lib/agents/types.d.ts.map +1 -0
- package/dist/lib/agents/types.js +5 -0
- package/dist/lib/agents/types.js.map +1 -0
- package/dist/lib/classifier.d.ts +89 -0
- package/dist/lib/classifier.d.ts.map +1 -0
- package/dist/lib/classifier.js +285 -0
- package/dist/lib/classifier.js.map +1 -0
- package/dist/lib/config.d.ts +37 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +187 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/dashboard.d.ts +65 -0
- package/dist/lib/dashboard.d.ts.map +1 -0
- package/dist/lib/dashboard.js +237 -0
- package/dist/lib/dashboard.js.map +1 -0
- package/dist/lib/docker-sandbox.d.ts +92 -0
- package/dist/lib/docker-sandbox.d.ts.map +1 -0
- package/dist/lib/docker-sandbox.js +375 -0
- package/dist/lib/docker-sandbox.js.map +1 -0
- package/dist/lib/fingerprint.d.ts +15 -0
- package/dist/lib/fingerprint.d.ts.map +1 -0
- package/dist/lib/fingerprint.js +59 -0
- package/dist/lib/fingerprint.js.map +1 -0
- package/dist/lib/fixture.d.ts +55 -0
- package/dist/lib/fixture.d.ts.map +1 -0
- package/dist/lib/fixture.js +215 -0
- package/dist/lib/fixture.js.map +1 -0
- package/dist/lib/housekeeping.d.ts +26 -0
- package/dist/lib/housekeeping.d.ts.map +1 -0
- package/dist/lib/housekeeping.js +170 -0
- package/dist/lib/housekeeping.js.map +1 -0
- package/dist/lib/init.d.ts +21 -0
- package/dist/lib/init.d.ts.map +1 -0
- package/dist/lib/init.js +275 -0
- package/dist/lib/init.js.map +1 -0
- package/dist/lib/o11y/index.d.ts +13 -0
- package/dist/lib/o11y/index.d.ts.map +1 -0
- package/dist/lib/o11y/index.js +13 -0
- package/dist/lib/o11y/index.js.map +1 -0
- package/dist/lib/o11y/parsers/claude-code.d.ts +18 -0
- package/dist/lib/o11y/parsers/claude-code.d.ts.map +1 -0
- package/dist/lib/o11y/parsers/claude-code.js +343 -0
- package/dist/lib/o11y/parsers/claude-code.js.map +1 -0
- package/dist/lib/o11y/parsers/codex.d.ts +17 -0
- package/dist/lib/o11y/parsers/codex.d.ts.map +1 -0
- package/dist/lib/o11y/parsers/codex.js +364 -0
- package/dist/lib/o11y/parsers/codex.js.map +1 -0
- package/dist/lib/o11y/parsers/cursor.d.ts +21 -0
- package/dist/lib/o11y/parsers/cursor.d.ts.map +1 -0
- package/dist/lib/o11y/parsers/cursor.js +226 -0
- package/dist/lib/o11y/parsers/cursor.js.map +1 -0
- package/dist/lib/o11y/parsers/gemini.d.ts +21 -0
- package/dist/lib/o11y/parsers/gemini.d.ts.map +1 -0
- package/dist/lib/o11y/parsers/gemini.js +241 -0
- package/dist/lib/o11y/parsers/gemini.js.map +1 -0
- package/dist/lib/o11y/parsers/index.d.ts +55 -0
- package/dist/lib/o11y/parsers/index.d.ts.map +1 -0
- package/dist/lib/o11y/parsers/index.js +284 -0
- package/dist/lib/o11y/parsers/index.js.map +1 -0
- package/dist/lib/o11y/parsers/opencode.d.ts +17 -0
- package/dist/lib/o11y/parsers/opencode.d.ts.map +1 -0
- package/dist/lib/o11y/parsers/opencode.js +320 -0
- package/dist/lib/o11y/parsers/opencode.js.map +1 -0
- package/dist/lib/o11y/types.d.ts +113 -0
- package/dist/lib/o11y/types.d.ts.map +1 -0
- package/dist/lib/o11y/types.js +6 -0
- package/dist/lib/o11y/types.js.map +1 -0
- package/dist/lib/results.d.ts +91 -0
- package/dist/lib/results.d.ts.map +1 -0
- package/dist/lib/results.js +361 -0
- package/dist/lib/results.js.map +1 -0
- package/dist/lib/runner.d.ts +71 -0
- package/dist/lib/runner.d.ts.map +1 -0
- package/dist/lib/runner.js +267 -0
- package/dist/lib/runner.js.map +1 -0
- package/dist/lib/sandbox.d.ts +173 -0
- package/dist/lib/sandbox.d.ts.map +1 -0
- package/dist/lib/sandbox.js +337 -0
- package/dist/lib/sandbox.js.map +1 -0
- package/dist/lib/types.d.ts +258 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +15 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/test-setup.d.ts +2 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +6 -0
- package/dist/test-setup.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker-based sandbox implementation for isolated eval execution.
|
|
3
|
+
* Uses dockerode to manage Docker containers as sandboxes.
|
|
4
|
+
*/
|
|
5
|
+
import Docker from 'dockerode';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
import * as tar from 'tar-stream';
|
|
8
|
+
/**
|
|
9
|
+
* Docker images for each Node.js runtime.
|
|
10
|
+
* Using -slim variants for faster downloads while maintaining compatibility.
|
|
11
|
+
*/
|
|
12
|
+
const DOCKER_IMAGES = {
|
|
13
|
+
node20: 'node:20-slim',
|
|
14
|
+
node24: 'node:24-slim',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Default timeout for container operations (10 minutes).
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_TIMEOUT = 600000;
|
|
20
|
+
/**
|
|
21
|
+
* Working directory inside the container.
|
|
22
|
+
*/
|
|
23
|
+
const CONTAINER_WORKDIR = '/home/sandbox/workspace';
|
|
24
|
+
/**
|
|
25
|
+
* Non-root user configuration.
|
|
26
|
+
* Running as non-root is important for security and compatibility
|
|
27
|
+
* (e.g., Claude Code refuses --dangerously-skip-permissions as root).
|
|
28
|
+
* Node.js images already have a 'node' user with UID/GID 1000.
|
|
29
|
+
*/
|
|
30
|
+
const SANDBOX_UID = 1000;
|
|
31
|
+
const SANDBOX_GID = 1000;
|
|
32
|
+
/**
|
|
33
|
+
* Directory for npm global packages (non-root install location).
|
|
34
|
+
*/
|
|
35
|
+
const NPM_GLOBAL_DIR = '/home/node/.npm-global';
|
|
36
|
+
function resolveDockerHost() {
|
|
37
|
+
if (process.env.DOCKER_HOST) {
|
|
38
|
+
return process.env.DOCKER_HOST;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
return execSync('docker context inspect --format {{.Endpoints.docker.Host}}', {
|
|
42
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
43
|
+
timeout: 5000,
|
|
44
|
+
})
|
|
45
|
+
.toString()
|
|
46
|
+
.trim();
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function resolveDockerOptions() {
|
|
53
|
+
const host = resolveDockerHost();
|
|
54
|
+
if (host?.startsWith('unix://')) {
|
|
55
|
+
return { socketPath: host.slice('unix://'.length) };
|
|
56
|
+
}
|
|
57
|
+
if (host) {
|
|
58
|
+
return { host };
|
|
59
|
+
}
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Docker-based sandbox manager.
|
|
64
|
+
* Creates isolated containers for running evals.
|
|
65
|
+
*/
|
|
66
|
+
export class DockerSandboxManager {
|
|
67
|
+
docker;
|
|
68
|
+
container = null;
|
|
69
|
+
_containerId = '';
|
|
70
|
+
timeout;
|
|
71
|
+
runtime;
|
|
72
|
+
constructor(options = {}) {
|
|
73
|
+
this.docker = new Docker(resolveDockerOptions());
|
|
74
|
+
this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
75
|
+
this.runtime = options.runtime ?? 'node24';
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create and start a new Docker sandbox.
|
|
79
|
+
*/
|
|
80
|
+
static async create(options = {}) {
|
|
81
|
+
const manager = new DockerSandboxManager(options);
|
|
82
|
+
await manager.initialize();
|
|
83
|
+
return manager;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Initialize the sandbox by pulling image and creating container.
|
|
87
|
+
*/
|
|
88
|
+
async initialize() {
|
|
89
|
+
const imageName = DOCKER_IMAGES[this.runtime];
|
|
90
|
+
if (!imageName) {
|
|
91
|
+
throw new Error(`Unsupported runtime: ${this.runtime}`);
|
|
92
|
+
}
|
|
93
|
+
// Ensure the image is available
|
|
94
|
+
await this.ensureImage(imageName);
|
|
95
|
+
this.container = await this.docker.createContainer({
|
|
96
|
+
Image: imageName,
|
|
97
|
+
Cmd: ['sleep', 'infinity'],
|
|
98
|
+
WorkingDir: CONTAINER_WORKDIR,
|
|
99
|
+
Tty: true,
|
|
100
|
+
HostConfig: {
|
|
101
|
+
AutoRemove: true,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
this._containerId = this.container.id;
|
|
105
|
+
// Start the container
|
|
106
|
+
await this.container.start();
|
|
107
|
+
// Install CA certificates and git (slim images may not include them)
|
|
108
|
+
await this.runCommandAsRoot('bash', ['-c', 'apt-get update -qq && apt-get install -y -qq ca-certificates git > /dev/null 2>&1']);
|
|
109
|
+
// Create workspace directory owned by the non-root user (node:node in Node.js images)
|
|
110
|
+
// The node user (UID 1000) already exists in node:*-slim images
|
|
111
|
+
await this.runCommandAsRoot('mkdir', ['-p', CONTAINER_WORKDIR]);
|
|
112
|
+
await this.runCommandAsRoot('chown', ['-R', `${SANDBOX_UID}:${SANDBOX_GID}`, CONTAINER_WORKDIR]);
|
|
113
|
+
// Configure npm for non-root global installs
|
|
114
|
+
// Create a user-local directory for global packages
|
|
115
|
+
await this.runCommandAsRoot('mkdir', ['-p', NPM_GLOBAL_DIR]);
|
|
116
|
+
await this.runCommandAsRoot('chown', ['-R', `${SANDBOX_UID}:${SANDBOX_GID}`, NPM_GLOBAL_DIR]);
|
|
117
|
+
// Configure npm to use this directory
|
|
118
|
+
await this.runCommand('npm', ['config', 'set', 'prefix', NPM_GLOBAL_DIR]);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Ensure the Docker image is available locally, pulling if needed.
|
|
122
|
+
*/
|
|
123
|
+
async ensureImage(imageName) {
|
|
124
|
+
try {
|
|
125
|
+
// Check if image exists
|
|
126
|
+
const image = this.docker.getImage(imageName);
|
|
127
|
+
await image.inspect();
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Image doesn't exist, pull it
|
|
131
|
+
console.log(`Pulling Docker image: ${imageName}...`);
|
|
132
|
+
await this.pullImage(imageName);
|
|
133
|
+
console.log(`Docker image ready: ${imageName}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Pull a Docker image with progress output.
|
|
138
|
+
*/
|
|
139
|
+
async pullImage(imageName) {
|
|
140
|
+
return new Promise((resolve, reject) => {
|
|
141
|
+
this.docker.pull(imageName, (err, stream) => {
|
|
142
|
+
if (err) {
|
|
143
|
+
reject(err);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
// Follow the pull progress
|
|
147
|
+
this.docker.modem.followProgress(stream, (err) => {
|
|
148
|
+
if (err) {
|
|
149
|
+
reject(err);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
resolve();
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
// Progress callback (optional, could add progress bar here)
|
|
156
|
+
() => { });
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get the container ID.
|
|
162
|
+
*/
|
|
163
|
+
get sandboxId() {
|
|
164
|
+
return this._containerId.slice(0, 12); // Short ID like Docker CLI
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Run a command in the container as the sandbox (non-root) user.
|
|
168
|
+
*/
|
|
169
|
+
async runCommand(command, args = [], options = {}) {
|
|
170
|
+
// Ensure npm global binaries are in PATH
|
|
171
|
+
const env = {
|
|
172
|
+
...options.env,
|
|
173
|
+
PATH: `${NPM_GLOBAL_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,
|
|
174
|
+
};
|
|
175
|
+
return this.execCommand(command, args, {
|
|
176
|
+
env,
|
|
177
|
+
user: `${SANDBOX_UID}:${SANDBOX_GID}`,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Run a command in the container as root.
|
|
182
|
+
* Used internally for setup tasks.
|
|
183
|
+
*/
|
|
184
|
+
async runCommandAsRoot(command, args = [], options = {}) {
|
|
185
|
+
return this.execCommand(command, args, {
|
|
186
|
+
...options,
|
|
187
|
+
user: 'root',
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Execute a command in the container.
|
|
192
|
+
*/
|
|
193
|
+
async execCommand(command, args = [], options = {}) {
|
|
194
|
+
if (!this.container) {
|
|
195
|
+
throw new Error('Container not initialized');
|
|
196
|
+
}
|
|
197
|
+
const cmd = [command, ...args];
|
|
198
|
+
const env = options.env
|
|
199
|
+
? Object.entries(options.env).map(([k, v]) => `${k}=${v}`)
|
|
200
|
+
: undefined;
|
|
201
|
+
const exec = await this.container.exec({
|
|
202
|
+
Cmd: cmd,
|
|
203
|
+
AttachStdout: true,
|
|
204
|
+
AttachStderr: true,
|
|
205
|
+
WorkingDir: CONTAINER_WORKDIR,
|
|
206
|
+
Env: env,
|
|
207
|
+
User: options.user,
|
|
208
|
+
});
|
|
209
|
+
const stream = await exec.start({ hijack: true, stdin: false });
|
|
210
|
+
return new Promise((resolve, reject) => {
|
|
211
|
+
let stdout = '';
|
|
212
|
+
let stderr = '';
|
|
213
|
+
// Docker multiplexes stdout/stderr in the stream
|
|
214
|
+
// We need to demux it
|
|
215
|
+
const stdoutChunks = [];
|
|
216
|
+
const stderrChunks = [];
|
|
217
|
+
stream.on('data', (chunk) => {
|
|
218
|
+
// Docker stream format: 8-byte header + payload
|
|
219
|
+
// Header: [stream_type (1 byte), 0, 0, 0, size (4 bytes)]
|
|
220
|
+
// stream_type: 1 = stdout, 2 = stderr
|
|
221
|
+
let offset = 0;
|
|
222
|
+
while (offset < chunk.length) {
|
|
223
|
+
if (offset + 8 > chunk.length) {
|
|
224
|
+
// Incomplete header, treat rest as stdout
|
|
225
|
+
stdoutChunks.push(chunk.slice(offset));
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
const streamType = chunk[offset];
|
|
229
|
+
const size = chunk.readUInt32BE(offset + 4);
|
|
230
|
+
if (offset + 8 + size > chunk.length) {
|
|
231
|
+
// Incomplete payload, treat rest as stdout
|
|
232
|
+
stdoutChunks.push(chunk.slice(offset + 8));
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
const payload = chunk.slice(offset + 8, offset + 8 + size);
|
|
236
|
+
if (streamType === 1) {
|
|
237
|
+
stdoutChunks.push(payload);
|
|
238
|
+
}
|
|
239
|
+
else if (streamType === 2) {
|
|
240
|
+
stderrChunks.push(payload);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
// Unknown type, assume stdout
|
|
244
|
+
stdoutChunks.push(payload);
|
|
245
|
+
}
|
|
246
|
+
offset += 8 + size;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
stream.on('end', async () => {
|
|
250
|
+
stdout = Buffer.concat(stdoutChunks).toString('utf-8');
|
|
251
|
+
stderr = Buffer.concat(stderrChunks).toString('utf-8');
|
|
252
|
+
try {
|
|
253
|
+
const inspection = await exec.inspect();
|
|
254
|
+
resolve({
|
|
255
|
+
stdout,
|
|
256
|
+
stderr,
|
|
257
|
+
exitCode: inspection.ExitCode ?? 0,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
reject(error);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
stream.on('error', reject);
|
|
265
|
+
// Timeout handling
|
|
266
|
+
const timeoutId = setTimeout(() => {
|
|
267
|
+
stream.destroy();
|
|
268
|
+
reject(new Error(`Command timed out after ${this.timeout}ms`));
|
|
269
|
+
}, this.timeout);
|
|
270
|
+
stream.on('end', () => clearTimeout(timeoutId));
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Run a shell command (through bash).
|
|
275
|
+
*/
|
|
276
|
+
async runShell(command, env) {
|
|
277
|
+
return this.runCommand('bash', ['-c', command], { env });
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Read a file from the container.
|
|
281
|
+
*/
|
|
282
|
+
async readFile(path) {
|
|
283
|
+
const result = await this.runCommand('cat', [path]);
|
|
284
|
+
if (result.exitCode !== 0) {
|
|
285
|
+
throw new Error(`Failed to read file ${path}: ${result.stderr}`);
|
|
286
|
+
}
|
|
287
|
+
return result.stdout;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Check if a file exists in the container.
|
|
291
|
+
*/
|
|
292
|
+
async fileExists(path) {
|
|
293
|
+
const result = await this.runCommand('test', ['-f', path]);
|
|
294
|
+
return result.exitCode === 0;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Write files to the container.
|
|
298
|
+
*/
|
|
299
|
+
async writeFiles(files) {
|
|
300
|
+
const sandboxFiles = Object.entries(files).map(([path, content]) => ({
|
|
301
|
+
path,
|
|
302
|
+
content: Buffer.from(content, 'utf-8'),
|
|
303
|
+
}));
|
|
304
|
+
await this.uploadFiles(sandboxFiles);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Upload files to the container using tar archive.
|
|
308
|
+
*/
|
|
309
|
+
async uploadFiles(files) {
|
|
310
|
+
if (!this.container) {
|
|
311
|
+
throw new Error('Container not initialized');
|
|
312
|
+
}
|
|
313
|
+
if (files.length === 0) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// Create a tar archive
|
|
317
|
+
const pack = tar.pack();
|
|
318
|
+
for (const file of files) {
|
|
319
|
+
const content = typeof file.content === 'string'
|
|
320
|
+
? Buffer.from(file.content, 'utf-8')
|
|
321
|
+
: file.content;
|
|
322
|
+
pack.entry({ name: file.path }, content);
|
|
323
|
+
}
|
|
324
|
+
pack.finalize();
|
|
325
|
+
// Upload to container
|
|
326
|
+
await this.container.putArchive(pack, { path: CONTAINER_WORKDIR });
|
|
327
|
+
// Fix ownership - putArchive uploads as root, but we need files owned by node user
|
|
328
|
+
// so that OpenCode and other agents can edit them
|
|
329
|
+
await this.runCommandAsRoot('chown', ['-R', `${SANDBOX_UID}:${SANDBOX_GID}`, CONTAINER_WORKDIR]);
|
|
330
|
+
}
|
|
331
|
+
async uploadFilesToPath(containerDir, files) {
|
|
332
|
+
if (!this.container) {
|
|
333
|
+
throw new Error('Container not initialized');
|
|
334
|
+
}
|
|
335
|
+
await this.runCommandAsRoot('mkdir', ['-p', containerDir]);
|
|
336
|
+
await this.runCommandAsRoot('chown', ['-R', `${SANDBOX_UID}:${SANDBOX_GID}`, containerDir]);
|
|
337
|
+
if (files.length === 0) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
const pack = tar.pack();
|
|
341
|
+
for (const file of files) {
|
|
342
|
+
const content = typeof file.content === 'string'
|
|
343
|
+
? Buffer.from(file.content, 'utf-8')
|
|
344
|
+
: file.content;
|
|
345
|
+
pack.entry({ name: file.path }, content);
|
|
346
|
+
}
|
|
347
|
+
pack.finalize();
|
|
348
|
+
await this.container.putArchive(pack, { path: containerDir });
|
|
349
|
+
await this.runCommandAsRoot('chown', ['-R', `${SANDBOX_UID}:${SANDBOX_GID}`, containerDir]);
|
|
350
|
+
}
|
|
351
|
+
async ensureUserOwnership(containerDir) {
|
|
352
|
+
await this.runCommandAsRoot('chown', ['-R', `${SANDBOX_UID}:${SANDBOX_GID}`, containerDir]);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get the working directory.
|
|
356
|
+
*/
|
|
357
|
+
getWorkingDirectory() {
|
|
358
|
+
return CONTAINER_WORKDIR;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Stop and clean up the container.
|
|
362
|
+
*/
|
|
363
|
+
async stop() {
|
|
364
|
+
if (this.container) {
|
|
365
|
+
try {
|
|
366
|
+
await this.container.stop({ t: 0 }); // Immediate stop
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
// Container may already be stopped or removed
|
|
370
|
+
}
|
|
371
|
+
this.container = null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
//# sourceMappingURL=docker-sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-sandbox.js","sourceRoot":"","sources":["../../src/lib/docker-sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content fingerprinting for eval result reuse.
|
|
3
|
+
*
|
|
4
|
+
* A fingerprint captures the eval files + config fields that affect results.
|
|
5
|
+
* If the fingerprint matches and the result is valid, the eval can be skipped.
|
|
6
|
+
*/
|
|
7
|
+
import type { RunnableExperimentConfig } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Compute a fingerprint for an (eval, config) pair.
|
|
10
|
+
*
|
|
11
|
+
* Hashes: all eval directory files + config fields that affect results.
|
|
12
|
+
* Returns a hex SHA-256 digest.
|
|
13
|
+
*/
|
|
14
|
+
export declare function computeFingerprint(evalPath: string, config: RunnableExperimentConfig): string;
|
|
15
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAuC3D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAuB7F"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content fingerprinting for eval result reuse.
|
|
3
|
+
*
|
|
4
|
+
* A fingerprint captures the eval files + config fields that affect results.
|
|
5
|
+
* If the fingerprint matches and the result is valid, the eval can be skipped.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
/**
|
|
11
|
+
* Recursively collects all files in a directory, sorted for deterministic hashing.
|
|
12
|
+
* Skips node_modules and .git.
|
|
13
|
+
*/
|
|
14
|
+
function collectFiles(dir, basePath = '') {
|
|
15
|
+
const files = [];
|
|
16
|
+
const entries = readdirSync(dir).sort();
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
if (entry === 'node_modules' || entry === '.git')
|
|
19
|
+
continue;
|
|
20
|
+
const fullPath = join(dir, entry);
|
|
21
|
+
const relativePath = basePath ? `${basePath}/${entry}` : entry;
|
|
22
|
+
const stat = statSync(fullPath);
|
|
23
|
+
if (stat.isDirectory()) {
|
|
24
|
+
files.push(...collectFiles(fullPath, relativePath));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
files.push({ relativePath, content: readFileSync(fullPath, 'utf-8') });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compute a fingerprint for an (eval, config) pair.
|
|
34
|
+
*
|
|
35
|
+
* Hashes: all eval directory files + config fields that affect results.
|
|
36
|
+
* Returns a hex SHA-256 digest.
|
|
37
|
+
*/
|
|
38
|
+
export function computeFingerprint(evalPath, config) {
|
|
39
|
+
const hash = createHash('sha256');
|
|
40
|
+
// Hash all files in the eval directory (sorted for determinism)
|
|
41
|
+
const files = collectFiles(evalPath);
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
hash.update(`file:${file.relativePath}\n`);
|
|
44
|
+
hash.update(file.content);
|
|
45
|
+
hash.update('\0');
|
|
46
|
+
}
|
|
47
|
+
// Hash config fields that affect results
|
|
48
|
+
const configForHash = {
|
|
49
|
+
agent: config.agent,
|
|
50
|
+
model: config.model,
|
|
51
|
+
scripts: [...config.scripts].sort(),
|
|
52
|
+
timeout: config.timeout,
|
|
53
|
+
earlyExit: config.earlyExit,
|
|
54
|
+
runs: config.runs,
|
|
55
|
+
};
|
|
56
|
+
hash.update(`config:${JSON.stringify(configForHash)}`);
|
|
57
|
+
return hash.digest('hex');
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAgB5B;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAW,EAAE,WAAmB,EAAE;IACtD,MAAM,KAAK,GAAqD,EAAE,CAAC;IACnE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAExC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,cAAc,IAAI,KAAK,KAAK,MAAM;YAAE,SAAS;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEhC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,MAAgC;IACnF,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAElC,gEAAgE;IAChE,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,yCAAyC;IACzC,MAAM,aAAa,GAA0B;QAC3C,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE;QACnC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAEvD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eval fixture discovery and validation.
|
|
3
|
+
*/
|
|
4
|
+
import type { EvalFixture } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Error thrown when an eval fixture is invalid.
|
|
7
|
+
*/
|
|
8
|
+
export declare class FixtureValidationError extends Error {
|
|
9
|
+
fixtureName: string;
|
|
10
|
+
constructor(fixtureName: string, message: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Discovers all eval fixtures in a directory.
|
|
14
|
+
* Recursively searches for directories containing PROMPT.md.
|
|
15
|
+
* Supports nested organization like "vercel-cli/deploy" or "flags/create-flag".
|
|
16
|
+
*/
|
|
17
|
+
export declare function discoverFixtures(evalsDir: string): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Validates that a fixture has all required files with correct case.
|
|
20
|
+
* Returns an array of missing file names, or empty array if valid.
|
|
21
|
+
* Note: Accepts either EVAL.ts or EVAL.tsx for the eval file.
|
|
22
|
+
* Case-sensitive: 'prompt.md' will fail even on Mac/Windows.
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateFixtureFiles(fixturePath: string): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Validates the package.json of a fixture.
|
|
27
|
+
* Ensures it has "type": "module".
|
|
28
|
+
*/
|
|
29
|
+
export declare function validatePackageJson(fixturePath: string): {
|
|
30
|
+
isModule: boolean;
|
|
31
|
+
error?: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Loads a single eval fixture with full validation.
|
|
35
|
+
*/
|
|
36
|
+
export declare function loadFixture(evalsDir: string, name: string): EvalFixture;
|
|
37
|
+
/**
|
|
38
|
+
* Discovers and loads all valid eval fixtures from a directory.
|
|
39
|
+
* Returns both valid fixtures and any validation errors encountered.
|
|
40
|
+
*/
|
|
41
|
+
export declare function loadAllFixtures(evalsDir: string): {
|
|
42
|
+
fixtures: EvalFixture[];
|
|
43
|
+
errors: FixtureValidationError[];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Gets a list of all files in a fixture directory.
|
|
47
|
+
* Excludes PROMPT.md, EVAL.ts, node_modules, and .git.
|
|
48
|
+
*/
|
|
49
|
+
export declare function getFixtureFiles(fixturePath: string, excludePatterns?: readonly string[]): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Reads all fixture files into a map.
|
|
52
|
+
* Keys are relative paths, values are file contents.
|
|
53
|
+
*/
|
|
54
|
+
export declare function readFixtureFiles(fixturePath: string, excludePatterns?: readonly string[]): Map<string, string>;
|
|
55
|
+
//# sourceMappingURL=fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/lib/fixture.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAEtC,WAAW,EAAE,MAAM;gBAAnB,WAAW,EAAE,MAAM,EAC1B,OAAO,EAAE,MAAM;CAKlB;AAeD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAuC3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAmBlE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAwB9F;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAmCvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG;IACjD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC,CAmBA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,eAAe,GAAE,SAAS,MAAM,EAAmB,GAClD,MAAM,EAAE,CA2BV;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAUrB"}
|