noumen 0.4.0 → 0.5.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/README.md +63 -8
- package/dist/a2a/index.d.ts +4 -2
- package/dist/acp/index.d.ts +5 -3
- package/dist/{agent-1nFVUP9E.d.ts → agent-C3eDRsxs.d.ts} +19 -508
- package/dist/chunk-I5SBSOS6.js +40 -0
- package/dist/chunk-I5SBSOS6.js.map +1 -0
- package/dist/{chunk-4HW6LN6D.js → chunk-WPCYGZOE.js} +58 -1228
- package/dist/chunk-WPCYGZOE.js.map +1 -0
- package/dist/{chunk-5JN4SPI7.js → chunk-WTLK2ZAR.js} +1 -1
- package/dist/{chunk-HL6JCRZJ.js → chunk-XZN4QZLK.js} +4 -4
- package/dist/cli/index.js +10 -10
- package/dist/computer-BPdxSo6X.d.ts +88 -0
- package/dist/docker.d.ts +129 -0
- package/dist/docker.js +401 -0
- package/dist/docker.js.map +1 -0
- package/dist/e2b.d.ts +157 -0
- package/dist/e2b.js +202 -0
- package/dist/e2b.js.map +1 -0
- package/dist/freestyle.d.ts +174 -0
- package/dist/freestyle.js +240 -0
- package/dist/freestyle.js.map +1 -0
- package/dist/index.d.ts +9 -201
- package/dist/index.js +24 -48
- package/dist/lsp/index.d.ts +3 -2
- package/dist/mcp/index.d.ts +4 -3
- package/dist/mcp/index.js +2 -2
- package/dist/{provider-factory-KCLIF34X.js → provider-factory-KI7OZUY3.js} +2 -2
- package/dist/{resolve-4JA2BBDA.js → resolve-GDSHNMG6.js} +2 -2
- package/dist/sandbox-9qeMTNrD.d.ts +126 -0
- package/dist/server/index.d.ts +4 -2
- package/dist/{server-CHMxuWKq.d.ts → server-Cu9gv1dk.d.ts} +1 -1
- package/dist/sprites.d.ts +136 -0
- package/dist/sprites.js +334 -0
- package/dist/sprites.js.map +1 -0
- package/dist/ssh.d.ts +187 -0
- package/dist/ssh.js +392 -0
- package/dist/ssh.js.map +1 -0
- package/dist/{types-RPKUTu1k.d.ts → types-BA87bHPV.d.ts} +2 -88
- package/package.json +25 -1
- package/dist/chunk-4HW6LN6D.js.map +0 -1
- /package/dist/{chunk-5JN4SPI7.js.map → chunk-WTLK2ZAR.js.map} +0 -0
- /package/dist/{chunk-HL6JCRZJ.js.map → chunk-XZN4QZLK.js.map} +0 -0
- /package/dist/{provider-factory-KCLIF34X.js.map → provider-factory-KI7OZUY3.js.map} +0 -0
- /package/dist/{resolve-4JA2BBDA.js.map → resolve-GDSHNMG6.js.map} +0 -0
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applySnipRemovals
|
|
3
3
|
} from "./chunk-42PHHZUA.js";
|
|
4
|
+
import {
|
|
5
|
+
ToolRegistry,
|
|
6
|
+
createToolSearchTool,
|
|
7
|
+
isPathInWorkingDirectories,
|
|
8
|
+
resolvePermission,
|
|
9
|
+
resolveToolFlag
|
|
10
|
+
} from "./chunk-XZN4QZLK.js";
|
|
4
11
|
import {
|
|
5
12
|
getAutoCompactThreshold,
|
|
6
13
|
getEffectiveContextWindow,
|
|
@@ -12,13 +19,6 @@ import {
|
|
|
12
19
|
import {
|
|
13
20
|
generateUUID
|
|
14
21
|
} from "./chunk-3HEYCV26.js";
|
|
15
|
-
import {
|
|
16
|
-
ToolRegistry,
|
|
17
|
-
createToolSearchTool,
|
|
18
|
-
isPathInWorkingDirectories,
|
|
19
|
-
resolvePermission,
|
|
20
|
-
resolveToolFlag
|
|
21
|
-
} from "./chunk-HL6JCRZJ.js";
|
|
22
22
|
import {
|
|
23
23
|
contentToString,
|
|
24
24
|
hasImageContent,
|
|
@@ -178,7 +178,7 @@ var LocalComputer = class {
|
|
|
178
178
|
this.defaultTimeout = opts?.defaultTimeout ?? 3e4;
|
|
179
179
|
}
|
|
180
180
|
executeCommand(command, opts) {
|
|
181
|
-
return new Promise((
|
|
181
|
+
return new Promise((resolve3) => {
|
|
182
182
|
const child = execCb(
|
|
183
183
|
command,
|
|
184
184
|
{
|
|
@@ -189,7 +189,7 @@ var LocalComputer = class {
|
|
|
189
189
|
shell: process.env.SHELL || "/bin/sh"
|
|
190
190
|
},
|
|
191
191
|
(error, stdout, stderr) => {
|
|
192
|
-
|
|
192
|
+
resolve3({
|
|
193
193
|
exitCode: error && "code" in error ? typeof error.code === "number" ? error.code : 1 : child.exitCode ?? 0,
|
|
194
194
|
stdout: stdout ?? "",
|
|
195
195
|
stderr: stderr ?? ""
|
|
@@ -250,7 +250,7 @@ var SandboxedLocalComputer = class {
|
|
|
250
250
|
async executeCommand(command, opts) {
|
|
251
251
|
await this.ensureInitialized();
|
|
252
252
|
const wrappedCommand = await SandboxManager.wrapWithSandbox(command);
|
|
253
|
-
return new Promise((
|
|
253
|
+
return new Promise((resolve3) => {
|
|
254
254
|
const child = execCb2(
|
|
255
255
|
wrappedCommand,
|
|
256
256
|
{
|
|
@@ -266,7 +266,7 @@ var SandboxedLocalComputer = class {
|
|
|
266
266
|
stdout: stdout ?? "",
|
|
267
267
|
stderr: stderr ?? ""
|
|
268
268
|
};
|
|
269
|
-
Promise.resolve(SandboxManager.cleanupAfterCommand()).then(() =>
|
|
269
|
+
Promise.resolve(SandboxManager.cleanupAfterCommand()).then(() => resolve3(result)).catch(() => resolve3(result));
|
|
270
270
|
}
|
|
271
271
|
);
|
|
272
272
|
});
|
|
@@ -283,813 +283,7 @@ var SandboxedLocalComputer = class {
|
|
|
283
283
|
}
|
|
284
284
|
};
|
|
285
285
|
|
|
286
|
-
// src/virtual/sprites-fs.ts
|
|
287
|
-
import * as path2 from "path";
|
|
288
|
-
var SpritesFs = class {
|
|
289
|
-
token;
|
|
290
|
-
spriteName;
|
|
291
|
-
baseURL;
|
|
292
|
-
workingDir;
|
|
293
|
-
constructor(opts) {
|
|
294
|
-
this.token = opts.token;
|
|
295
|
-
this.spriteName = opts.spriteName;
|
|
296
|
-
this.baseURL = (opts.baseURL ?? "https://api.sprites.dev").replace(
|
|
297
|
-
/\/$/,
|
|
298
|
-
""
|
|
299
|
-
);
|
|
300
|
-
this.workingDir = opts.workingDir ?? "/home/sprite";
|
|
301
|
-
}
|
|
302
|
-
fsUrl(endpoint, params) {
|
|
303
|
-
const url = new URL(
|
|
304
|
-
`${this.baseURL}/v1/sprites/${this.spriteName}/fs${endpoint}`
|
|
305
|
-
);
|
|
306
|
-
if (params) {
|
|
307
|
-
for (const [k, v] of Object.entries(params)) {
|
|
308
|
-
url.searchParams.set(k, v);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
return url.toString();
|
|
312
|
-
}
|
|
313
|
-
resolvePath(p) {
|
|
314
|
-
const normalizedBase = this.workingDir.endsWith("/") ? this.workingDir : this.workingDir + "/";
|
|
315
|
-
if (p.startsWith("/")) {
|
|
316
|
-
if (p !== this.workingDir && !p.startsWith(normalizedBase)) {
|
|
317
|
-
throw new Error(`Absolute path "${p}" is outside working directory "${this.workingDir}"`);
|
|
318
|
-
}
|
|
319
|
-
return p;
|
|
320
|
-
}
|
|
321
|
-
const resolved = path2.resolve(this.workingDir, p);
|
|
322
|
-
if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {
|
|
323
|
-
throw new Error(`Path "${p}" escapes working directory "${this.workingDir}"`);
|
|
324
|
-
}
|
|
325
|
-
return resolved;
|
|
326
|
-
}
|
|
327
|
-
headers() {
|
|
328
|
-
return {
|
|
329
|
-
Authorization: `Bearer ${this.token}`
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
async readFile(filePath, _opts) {
|
|
333
|
-
const url = this.fsUrl("/read", { path: this.resolvePath(filePath) });
|
|
334
|
-
const res = await fetch(url, { headers: this.headers() });
|
|
335
|
-
if (!res.ok) {
|
|
336
|
-
throw new Error(
|
|
337
|
-
`SpritesFs readFile failed (${res.status}): ${await res.text()}`
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
return res.text();
|
|
341
|
-
}
|
|
342
|
-
async readFileBytes(filePath, maxBytes) {
|
|
343
|
-
const url = this.fsUrl("/read", {
|
|
344
|
-
path: this.resolvePath(filePath),
|
|
345
|
-
binary: "true"
|
|
346
|
-
});
|
|
347
|
-
const res = await fetch(url, { headers: this.headers() });
|
|
348
|
-
if (!res.ok) {
|
|
349
|
-
throw new Error(
|
|
350
|
-
`SpritesFs readFileBytes failed (${res.status}): ${await res.text()}`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
const arrayBuf = await res.arrayBuffer();
|
|
354
|
-
const buf = Buffer.from(arrayBuf);
|
|
355
|
-
if (maxBytes !== void 0 && buf.length > maxBytes) {
|
|
356
|
-
return buf.subarray(0, maxBytes);
|
|
357
|
-
}
|
|
358
|
-
return buf;
|
|
359
|
-
}
|
|
360
|
-
async writeFile(filePath, content) {
|
|
361
|
-
const url = this.fsUrl("/write");
|
|
362
|
-
const res = await fetch(url, {
|
|
363
|
-
method: "POST",
|
|
364
|
-
headers: {
|
|
365
|
-
...this.headers(),
|
|
366
|
-
"Content-Type": "application/json"
|
|
367
|
-
},
|
|
368
|
-
body: JSON.stringify({
|
|
369
|
-
path: this.resolvePath(filePath),
|
|
370
|
-
content
|
|
371
|
-
})
|
|
372
|
-
});
|
|
373
|
-
if (!res.ok) {
|
|
374
|
-
throw new Error(
|
|
375
|
-
`SpritesFs writeFile failed (${res.status}): ${await res.text()}`
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* @warning Not atomic. Concurrent appends may lose data due to
|
|
381
|
-
* read-then-write TOCTOU. The Sprites API does not expose an append primitive.
|
|
382
|
-
*/
|
|
383
|
-
async appendFile(filePath, content) {
|
|
384
|
-
let existing = "";
|
|
385
|
-
try {
|
|
386
|
-
existing = await this.readFile(filePath);
|
|
387
|
-
} catch {
|
|
388
|
-
}
|
|
389
|
-
await this.writeFile(filePath, existing + content);
|
|
390
|
-
}
|
|
391
|
-
async deleteFile(filePath, opts) {
|
|
392
|
-
const url = this.fsUrl("/remove");
|
|
393
|
-
const res = await fetch(url, {
|
|
394
|
-
method: "POST",
|
|
395
|
-
headers: {
|
|
396
|
-
...this.headers(),
|
|
397
|
-
"Content-Type": "application/json"
|
|
398
|
-
},
|
|
399
|
-
body: JSON.stringify({
|
|
400
|
-
path: this.resolvePath(filePath),
|
|
401
|
-
recursive: opts?.recursive ?? false
|
|
402
|
-
})
|
|
403
|
-
});
|
|
404
|
-
if (!res.ok) {
|
|
405
|
-
throw new Error(
|
|
406
|
-
`SpritesFs deleteFile failed (${res.status}): ${await res.text()}`
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
async mkdir(dirPath, opts) {
|
|
411
|
-
const url = this.fsUrl("/mkdir");
|
|
412
|
-
const res = await fetch(url, {
|
|
413
|
-
method: "POST",
|
|
414
|
-
headers: {
|
|
415
|
-
...this.headers(),
|
|
416
|
-
"Content-Type": "application/json"
|
|
417
|
-
},
|
|
418
|
-
body: JSON.stringify({
|
|
419
|
-
path: this.resolvePath(dirPath),
|
|
420
|
-
recursive: opts?.recursive ?? false
|
|
421
|
-
})
|
|
422
|
-
});
|
|
423
|
-
if (!res.ok) {
|
|
424
|
-
throw new Error(
|
|
425
|
-
`SpritesFs mkdir failed (${res.status}): ${await res.text()}`
|
|
426
|
-
);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
async readdir(dirPath, _opts) {
|
|
430
|
-
const url = this.fsUrl("/readdir", { path: this.resolvePath(dirPath) });
|
|
431
|
-
const res = await fetch(url, { headers: this.headers() });
|
|
432
|
-
if (!res.ok) {
|
|
433
|
-
throw new Error(
|
|
434
|
-
`SpritesFs readdir failed (${res.status}): ${await res.text()}`
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
const data = await res.json();
|
|
438
|
-
return data.map((entry) => ({
|
|
439
|
-
name: entry.name,
|
|
440
|
-
path: entry.path,
|
|
441
|
-
isDirectory: entry.is_dir,
|
|
442
|
-
isFile: !entry.is_dir,
|
|
443
|
-
size: entry.size
|
|
444
|
-
}));
|
|
445
|
-
}
|
|
446
|
-
async exists(filePath) {
|
|
447
|
-
try {
|
|
448
|
-
await this.stat(filePath);
|
|
449
|
-
return true;
|
|
450
|
-
} catch {
|
|
451
|
-
return false;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
async stat(filePath) {
|
|
455
|
-
const url = this.fsUrl("/stat", { path: this.resolvePath(filePath) });
|
|
456
|
-
const res = await fetch(url, { headers: this.headers() });
|
|
457
|
-
if (!res.ok) {
|
|
458
|
-
throw new Error(
|
|
459
|
-
`SpritesFs stat failed (${res.status}): ${await res.text()}`
|
|
460
|
-
);
|
|
461
|
-
}
|
|
462
|
-
const data = await res.json();
|
|
463
|
-
return {
|
|
464
|
-
size: data.size,
|
|
465
|
-
isDirectory: data.is_dir,
|
|
466
|
-
isFile: !data.is_dir,
|
|
467
|
-
createdAt: data.created_at ? new Date(data.created_at) : void 0,
|
|
468
|
-
modifiedAt: data.modified_at ? new Date(data.modified_at) : void 0
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
// src/virtual/sprites-computer.ts
|
|
474
|
-
var SpritesComputer = class {
|
|
475
|
-
token;
|
|
476
|
-
spriteName;
|
|
477
|
-
baseURL;
|
|
478
|
-
workingDir;
|
|
479
|
-
constructor(opts) {
|
|
480
|
-
this.token = opts.token;
|
|
481
|
-
this.spriteName = opts.spriteName;
|
|
482
|
-
this.baseURL = (opts.baseURL ?? "https://api.sprites.dev").replace(
|
|
483
|
-
/\/$/,
|
|
484
|
-
""
|
|
485
|
-
);
|
|
486
|
-
this.workingDir = opts.workingDir ?? "/home/sprite";
|
|
487
|
-
}
|
|
488
|
-
headers() {
|
|
489
|
-
return {
|
|
490
|
-
Authorization: `Bearer ${this.token}`,
|
|
491
|
-
"Content-Type": "application/json"
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
async executeCommand(command, opts) {
|
|
495
|
-
const cwd = opts?.cwd ?? this.workingDir;
|
|
496
|
-
const wrappedCommand = `cd ${this.shellEscape(cwd)} && ${command}`;
|
|
497
|
-
const url = `${this.baseURL}/v1/sprites/${this.spriteName}/exec`;
|
|
498
|
-
const res = await fetch(url, {
|
|
499
|
-
method: "POST",
|
|
500
|
-
headers: this.headers(),
|
|
501
|
-
body: JSON.stringify({
|
|
502
|
-
command: ["bash", "-c", wrappedCommand],
|
|
503
|
-
timeout: opts?.timeout ?? 3e4,
|
|
504
|
-
env: opts?.env
|
|
505
|
-
})
|
|
506
|
-
});
|
|
507
|
-
if (!res.ok) {
|
|
508
|
-
const text = await res.text();
|
|
509
|
-
return {
|
|
510
|
-
exitCode: 1,
|
|
511
|
-
stdout: "",
|
|
512
|
-
stderr: `Sprites exec failed (${res.status}): ${text}`
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
const data = await res.json();
|
|
516
|
-
return {
|
|
517
|
-
exitCode: data.exit_code,
|
|
518
|
-
stdout: data.stdout ?? "",
|
|
519
|
-
stderr: data.stderr ?? ""
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
shellEscape(s) {
|
|
523
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
524
|
-
}
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
// src/virtual/docker-fs.ts
|
|
528
|
-
import * as path3 from "path";
|
|
529
|
-
var DockerFs = class {
|
|
530
|
-
container;
|
|
531
|
-
workingDir;
|
|
532
|
-
constructor(opts) {
|
|
533
|
-
this.container = opts.container;
|
|
534
|
-
this.workingDir = opts.workingDir ?? "/";
|
|
535
|
-
}
|
|
536
|
-
resolvePath(p) {
|
|
537
|
-
if (p.includes("\0")) {
|
|
538
|
-
throw new Error("Path contains null bytes");
|
|
539
|
-
}
|
|
540
|
-
const normalizedBase = this.workingDir.endsWith("/") ? this.workingDir : this.workingDir + "/";
|
|
541
|
-
if (p.startsWith("/")) {
|
|
542
|
-
const normalized = path3.normalize(p);
|
|
543
|
-
if (normalized !== this.workingDir && !normalized.startsWith(normalizedBase)) {
|
|
544
|
-
throw new Error(`Absolute path "${p}" is outside working directory "${this.workingDir}"`);
|
|
545
|
-
}
|
|
546
|
-
return normalized;
|
|
547
|
-
}
|
|
548
|
-
const resolved = path3.resolve(this.workingDir, p);
|
|
549
|
-
if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {
|
|
550
|
-
throw new Error(`Path "${p}" escapes working directory "${this.workingDir}"`);
|
|
551
|
-
}
|
|
552
|
-
return resolved;
|
|
553
|
-
}
|
|
554
|
-
async exec(cmd) {
|
|
555
|
-
const execInstance = await this.container.exec({
|
|
556
|
-
Cmd: cmd,
|
|
557
|
-
AttachStdout: true,
|
|
558
|
-
AttachStderr: true,
|
|
559
|
-
Tty: false
|
|
560
|
-
});
|
|
561
|
-
const stream = await execInstance.start({ hijack: true, stdin: false });
|
|
562
|
-
const result = await collectExecStream(stream);
|
|
563
|
-
const inspection = await execInstance.inspect();
|
|
564
|
-
return { exitCode: inspection.ExitCode, ...result };
|
|
565
|
-
}
|
|
566
|
-
async readFile(path6, _opts) {
|
|
567
|
-
const resolved = this.resolvePath(path6);
|
|
568
|
-
const { exitCode, stdout, stderr } = await this.exec([
|
|
569
|
-
"cat",
|
|
570
|
-
resolved
|
|
571
|
-
]);
|
|
572
|
-
if (exitCode !== 0) {
|
|
573
|
-
throw new Error(`DockerFs readFile failed: ${stderr.trim() || `exit code ${exitCode}`}`);
|
|
574
|
-
}
|
|
575
|
-
return stdout;
|
|
576
|
-
}
|
|
577
|
-
async readFileBytes(path6, maxBytes) {
|
|
578
|
-
const resolved = this.resolvePath(path6);
|
|
579
|
-
const cmd = maxBytes !== void 0 ? ["head", "-c", String(maxBytes), resolved] : ["cat", resolved];
|
|
580
|
-
const { exitCode, stdout, stderr } = await this.exec([
|
|
581
|
-
"bash",
|
|
582
|
-
"-c",
|
|
583
|
-
`${cmd.map(shellEscape).join(" ")} | base64`
|
|
584
|
-
]);
|
|
585
|
-
if (exitCode !== 0) {
|
|
586
|
-
throw new Error(`DockerFs readFileBytes failed: ${stderr.trim() || `exit code ${exitCode}`}`);
|
|
587
|
-
}
|
|
588
|
-
return Buffer.from(stdout.trim(), "base64");
|
|
589
|
-
}
|
|
590
|
-
async writeFile(path6, content) {
|
|
591
|
-
const resolved = this.resolvePath(path6);
|
|
592
|
-
const dir = resolved.substring(0, resolved.lastIndexOf("/"));
|
|
593
|
-
if (dir) {
|
|
594
|
-
await this.exec(["mkdir", "-p", dir]);
|
|
595
|
-
}
|
|
596
|
-
const encoded = Buffer.from(content, "utf-8").toString("base64");
|
|
597
|
-
const MAX_INLINE_LEN = 1e5;
|
|
598
|
-
if (encoded.length <= MAX_INLINE_LEN) {
|
|
599
|
-
const { exitCode, stderr } = await this.exec([
|
|
600
|
-
"bash",
|
|
601
|
-
"-c",
|
|
602
|
-
`echo ${shellEscape(encoded)} | base64 -d > ${shellEscape(resolved)}`
|
|
603
|
-
]);
|
|
604
|
-
if (exitCode !== 0) {
|
|
605
|
-
throw new Error(`DockerFs writeFile failed: ${stderr.trim()}`);
|
|
606
|
-
}
|
|
607
|
-
} else {
|
|
608
|
-
const execInstance = await this.container.exec({
|
|
609
|
-
Cmd: ["bash", "-c", `base64 -d > ${shellEscape(resolved)}`],
|
|
610
|
-
AttachStdout: true,
|
|
611
|
-
AttachStderr: true,
|
|
612
|
-
AttachStdin: true,
|
|
613
|
-
Tty: false
|
|
614
|
-
});
|
|
615
|
-
const stream = await execInstance.start({ hijack: true, stdin: true });
|
|
616
|
-
const writable = stream;
|
|
617
|
-
writable.write(encoded);
|
|
618
|
-
writable.end();
|
|
619
|
-
const result = await collectExecStream(stream);
|
|
620
|
-
const inspection = await execInstance.inspect();
|
|
621
|
-
if (inspection.ExitCode !== 0) {
|
|
622
|
-
throw new Error(`DockerFs writeFile failed: ${result.stderr.trim()}`);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
async appendFile(path6, content) {
|
|
627
|
-
const resolved = this.resolvePath(path6);
|
|
628
|
-
const dir = resolved.substring(0, resolved.lastIndexOf("/"));
|
|
629
|
-
if (dir) {
|
|
630
|
-
await this.exec(["mkdir", "-p", dir]);
|
|
631
|
-
}
|
|
632
|
-
const encoded = Buffer.from(content, "utf-8").toString("base64");
|
|
633
|
-
const { exitCode, stderr } = await this.exec([
|
|
634
|
-
"bash",
|
|
635
|
-
"-c",
|
|
636
|
-
`echo ${shellEscape(encoded)} | base64 -d >> ${shellEscape(resolved)}`
|
|
637
|
-
]);
|
|
638
|
-
if (exitCode !== 0) {
|
|
639
|
-
throw new Error(`DockerFs appendFile failed: ${stderr.trim()}`);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
async deleteFile(path6, opts) {
|
|
643
|
-
const resolved = this.resolvePath(path6);
|
|
644
|
-
const args = opts?.recursive ? ["rm", "-rf", resolved] : ["rm", "-f", resolved];
|
|
645
|
-
await this.exec(args);
|
|
646
|
-
}
|
|
647
|
-
async mkdir(path6, opts) {
|
|
648
|
-
const resolved = this.resolvePath(path6);
|
|
649
|
-
const args = opts?.recursive ? ["mkdir", "-p", resolved] : ["mkdir", resolved];
|
|
650
|
-
await this.exec(args);
|
|
651
|
-
}
|
|
652
|
-
async readdir(path6, _opts) {
|
|
653
|
-
const resolved = this.resolvePath(path6);
|
|
654
|
-
const { exitCode, stdout, stderr } = await this.exec([
|
|
655
|
-
"bash",
|
|
656
|
-
"-c",
|
|
657
|
-
`find ${shellEscape(resolved)} -maxdepth 1 -mindepth 1 -printf '%y %p\\n' 2>/dev/null`
|
|
658
|
-
]);
|
|
659
|
-
if (exitCode !== 0 && stderr.trim()) {
|
|
660
|
-
throw new Error(`DockerFs readdir failed: ${stderr.trim()}`);
|
|
661
|
-
}
|
|
662
|
-
const entries = [];
|
|
663
|
-
for (const line of stdout.trim().split("\n")) {
|
|
664
|
-
if (!line) continue;
|
|
665
|
-
const spaceIdx = line.indexOf(" ");
|
|
666
|
-
const type = line.substring(0, spaceIdx);
|
|
667
|
-
const fullPath = line.substring(spaceIdx + 1);
|
|
668
|
-
const name = fullPath.substring(fullPath.lastIndexOf("/") + 1);
|
|
669
|
-
entries.push({
|
|
670
|
-
name,
|
|
671
|
-
path: fullPath,
|
|
672
|
-
isDirectory: type === "d",
|
|
673
|
-
isFile: type === "f"
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
return entries;
|
|
677
|
-
}
|
|
678
|
-
async exists(path6) {
|
|
679
|
-
const resolved = this.resolvePath(path6);
|
|
680
|
-
const { exitCode } = await this.exec(["test", "-e", resolved]);
|
|
681
|
-
return exitCode === 0;
|
|
682
|
-
}
|
|
683
|
-
async stat(path6) {
|
|
684
|
-
const resolved = this.resolvePath(path6);
|
|
685
|
-
const { exitCode, stdout, stderr } = await this.exec([
|
|
686
|
-
"stat",
|
|
687
|
-
"-c",
|
|
688
|
-
"%s %F %W %Y",
|
|
689
|
-
resolved
|
|
690
|
-
]);
|
|
691
|
-
if (exitCode !== 0) {
|
|
692
|
-
throw new Error(`DockerFs stat failed: ${stderr.trim() || `exit code ${exitCode}`}`);
|
|
693
|
-
}
|
|
694
|
-
const parts = stdout.trim().split(" ");
|
|
695
|
-
const size = parseInt(parts[0], 10);
|
|
696
|
-
const fileType = parts[1];
|
|
697
|
-
const createdEpoch = parseInt(parts[2], 10);
|
|
698
|
-
const modifiedEpoch = parseInt(parts[3], 10);
|
|
699
|
-
return {
|
|
700
|
-
size,
|
|
701
|
-
isDirectory: fileType === "directory",
|
|
702
|
-
isFile: fileType.startsWith("regular"),
|
|
703
|
-
createdAt: createdEpoch > 0 ? new Date(createdEpoch * 1e3) : void 0,
|
|
704
|
-
modifiedAt: modifiedEpoch > 0 ? new Date(modifiedEpoch * 1e3) : void 0
|
|
705
|
-
};
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
function shellEscape(s) {
|
|
709
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
710
|
-
}
|
|
711
|
-
function collectExecStream(stream) {
|
|
712
|
-
return new Promise((resolve7, reject) => {
|
|
713
|
-
const stdoutBufs = [];
|
|
714
|
-
const stderrBufs = [];
|
|
715
|
-
let pending = Buffer.alloc(0);
|
|
716
|
-
stream.on("data", (chunk) => {
|
|
717
|
-
let buf = pending.length > 0 ? Buffer.concat([pending, chunk]) : chunk;
|
|
718
|
-
let offset = 0;
|
|
719
|
-
while (offset + 8 <= buf.length) {
|
|
720
|
-
const payloadLen = buf.readUInt32BE(offset + 4);
|
|
721
|
-
if (offset + 8 + payloadLen > buf.length) break;
|
|
722
|
-
const streamType = buf[offset];
|
|
723
|
-
const payload = buf.subarray(offset + 8, offset + 8 + payloadLen);
|
|
724
|
-
if (streamType === 2) {
|
|
725
|
-
stderrBufs.push(payload);
|
|
726
|
-
} else {
|
|
727
|
-
stdoutBufs.push(payload);
|
|
728
|
-
}
|
|
729
|
-
offset += 8 + payloadLen;
|
|
730
|
-
}
|
|
731
|
-
pending = offset < buf.length ? buf.subarray(offset) : Buffer.alloc(0);
|
|
732
|
-
});
|
|
733
|
-
stream.on("end", () => {
|
|
734
|
-
resolve7({
|
|
735
|
-
stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
|
|
736
|
-
stderr: Buffer.concat(stderrBufs).toString("utf-8")
|
|
737
|
-
});
|
|
738
|
-
});
|
|
739
|
-
stream.on("error", (err) => reject(err));
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
// src/virtual/docker-computer.ts
|
|
744
|
-
var DockerComputer = class {
|
|
745
|
-
container;
|
|
746
|
-
defaultCwd;
|
|
747
|
-
defaultTimeout;
|
|
748
|
-
constructor(opts) {
|
|
749
|
-
this.container = opts.container;
|
|
750
|
-
this.defaultCwd = opts.defaultCwd ?? "/";
|
|
751
|
-
this.defaultTimeout = opts.defaultTimeout ?? 3e4;
|
|
752
|
-
}
|
|
753
|
-
async executeCommand(command, opts) {
|
|
754
|
-
const cwd = opts?.cwd ?? this.defaultCwd;
|
|
755
|
-
const timeout = opts?.timeout ?? this.defaultTimeout;
|
|
756
|
-
const execOpts = {
|
|
757
|
-
Cmd: ["bash", "-c", `cd ${shellEscape2(cwd)} && ${command}`],
|
|
758
|
-
AttachStdout: true,
|
|
759
|
-
AttachStderr: true,
|
|
760
|
-
Tty: false
|
|
761
|
-
};
|
|
762
|
-
if (opts?.env) {
|
|
763
|
-
execOpts.Env = Object.entries(opts.env).map(
|
|
764
|
-
([k, v]) => `${k}=${v}`
|
|
765
|
-
);
|
|
766
|
-
}
|
|
767
|
-
const exec = await this.container.exec(execOpts);
|
|
768
|
-
const stream = await exec.start({ hijack: true, stdin: false });
|
|
769
|
-
const { stdout, stderr } = await collectStream(stream, timeout);
|
|
770
|
-
const inspection = await exec.inspect();
|
|
771
|
-
return {
|
|
772
|
-
exitCode: inspection.ExitCode,
|
|
773
|
-
stdout,
|
|
774
|
-
stderr
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
};
|
|
778
|
-
function shellEscape2(s) {
|
|
779
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
780
|
-
}
|
|
781
|
-
function collectStream(stream, timeout) {
|
|
782
|
-
return new Promise((resolve7, reject) => {
|
|
783
|
-
const stdoutBufs = [];
|
|
784
|
-
const stderrBufs = [];
|
|
785
|
-
let pending = Buffer.alloc(0);
|
|
786
|
-
const timer = setTimeout(() => {
|
|
787
|
-
stream.destroy?.();
|
|
788
|
-
resolve7({
|
|
789
|
-
stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
|
|
790
|
-
stderr: Buffer.concat(stderrBufs).toString("utf-8") + "\n[timeout after " + timeout + "ms]"
|
|
791
|
-
});
|
|
792
|
-
}, timeout);
|
|
793
|
-
stream.on("data", (chunk) => {
|
|
794
|
-
let buf = pending.length > 0 ? Buffer.concat([pending, chunk]) : chunk;
|
|
795
|
-
let offset = 0;
|
|
796
|
-
while (offset + 8 <= buf.length) {
|
|
797
|
-
const payloadLen = buf.readUInt32BE(offset + 4);
|
|
798
|
-
if (offset + 8 + payloadLen > buf.length) break;
|
|
799
|
-
const streamType = buf[offset];
|
|
800
|
-
const payload = buf.subarray(offset + 8, offset + 8 + payloadLen);
|
|
801
|
-
if (streamType === 2) {
|
|
802
|
-
stderrBufs.push(payload);
|
|
803
|
-
} else {
|
|
804
|
-
stdoutBufs.push(payload);
|
|
805
|
-
}
|
|
806
|
-
offset += 8 + payloadLen;
|
|
807
|
-
}
|
|
808
|
-
pending = offset < buf.length ? buf.subarray(offset) : Buffer.alloc(0);
|
|
809
|
-
});
|
|
810
|
-
stream.on("end", () => {
|
|
811
|
-
clearTimeout(timer);
|
|
812
|
-
resolve7({
|
|
813
|
-
stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
|
|
814
|
-
stderr: Buffer.concat(stderrBufs).toString("utf-8")
|
|
815
|
-
});
|
|
816
|
-
});
|
|
817
|
-
stream.on("error", (err) => {
|
|
818
|
-
clearTimeout(timer);
|
|
819
|
-
reject(err);
|
|
820
|
-
});
|
|
821
|
-
});
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
// src/virtual/e2b-fs.ts
|
|
825
|
-
import * as path4 from "path";
|
|
826
|
-
var E2BFs = class {
|
|
827
|
-
sandbox;
|
|
828
|
-
workingDir;
|
|
829
|
-
constructor(opts) {
|
|
830
|
-
this.sandbox = opts.sandbox;
|
|
831
|
-
this.workingDir = opts.workingDir;
|
|
832
|
-
}
|
|
833
|
-
resolvePath(p) {
|
|
834
|
-
if (!this.workingDir) return p;
|
|
835
|
-
const normalizedBase = this.workingDir.endsWith("/") ? this.workingDir : this.workingDir + "/";
|
|
836
|
-
if (p.startsWith("/")) {
|
|
837
|
-
if (p !== this.workingDir && !p.startsWith(normalizedBase)) {
|
|
838
|
-
throw new Error(`Absolute path "${p}" is outside working directory "${this.workingDir}"`);
|
|
839
|
-
}
|
|
840
|
-
return p;
|
|
841
|
-
}
|
|
842
|
-
const resolved = path4.resolve(this.workingDir, p);
|
|
843
|
-
if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {
|
|
844
|
-
throw new Error(`Path "${p}" escapes working directory "${this.workingDir}"`);
|
|
845
|
-
}
|
|
846
|
-
return resolved;
|
|
847
|
-
}
|
|
848
|
-
async readFile(path6, _opts) {
|
|
849
|
-
return this.sandbox.files.read(this.resolvePath(path6), {
|
|
850
|
-
format: "text"
|
|
851
|
-
});
|
|
852
|
-
}
|
|
853
|
-
async readFileBytes(path6, maxBytes) {
|
|
854
|
-
const data = await this.sandbox.files.read(this.resolvePath(path6), {
|
|
855
|
-
format: "bytes"
|
|
856
|
-
});
|
|
857
|
-
const buf = Buffer.from(data);
|
|
858
|
-
if (maxBytes !== void 0 && buf.length > maxBytes) {
|
|
859
|
-
return buf.subarray(0, maxBytes);
|
|
860
|
-
}
|
|
861
|
-
return buf;
|
|
862
|
-
}
|
|
863
|
-
async writeFile(path6, content) {
|
|
864
|
-
await this.sandbox.files.write(this.resolvePath(path6), content);
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* @warning Not atomic. Concurrent appends may lose data due to
|
|
868
|
-
* read-then-write TOCTOU. The E2B SDK does not expose an append primitive.
|
|
869
|
-
*/
|
|
870
|
-
async appendFile(path6, content) {
|
|
871
|
-
let existing = "";
|
|
872
|
-
try {
|
|
873
|
-
existing = await this.readFile(path6);
|
|
874
|
-
} catch {
|
|
875
|
-
}
|
|
876
|
-
await this.writeFile(path6, existing + content);
|
|
877
|
-
}
|
|
878
|
-
async deleteFile(path6, _opts) {
|
|
879
|
-
await this.sandbox.files.remove(this.resolvePath(path6));
|
|
880
|
-
}
|
|
881
|
-
async mkdir(path6, _opts) {
|
|
882
|
-
await this.sandbox.files.makeDir(this.resolvePath(path6));
|
|
883
|
-
}
|
|
884
|
-
async readdir(path6, _opts) {
|
|
885
|
-
const entries = await this.sandbox.files.list(this.resolvePath(path6));
|
|
886
|
-
return entries.map((entry) => ({
|
|
887
|
-
name: entry.name,
|
|
888
|
-
path: entry.path,
|
|
889
|
-
isDirectory: entry.type === "dir",
|
|
890
|
-
isFile: entry.type === "file",
|
|
891
|
-
size: entry.size
|
|
892
|
-
}));
|
|
893
|
-
}
|
|
894
|
-
async exists(path6) {
|
|
895
|
-
return this.sandbox.files.exists(this.resolvePath(path6));
|
|
896
|
-
}
|
|
897
|
-
async stat(path6) {
|
|
898
|
-
const info = await this.sandbox.files.getInfo(this.resolvePath(path6));
|
|
899
|
-
return {
|
|
900
|
-
size: info.size ?? 0,
|
|
901
|
-
isDirectory: info.type === "dir",
|
|
902
|
-
isFile: info.type === "file",
|
|
903
|
-
modifiedAt: info.modifiedTime
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
|
|
908
|
-
// src/virtual/e2b-computer.ts
|
|
909
|
-
var E2BComputer = class {
|
|
910
|
-
sandbox;
|
|
911
|
-
defaultCwd;
|
|
912
|
-
defaultTimeout;
|
|
913
|
-
constructor(opts) {
|
|
914
|
-
this.sandbox = opts.sandbox;
|
|
915
|
-
this.defaultCwd = opts.defaultCwd;
|
|
916
|
-
this.defaultTimeout = opts.defaultTimeout ?? 3e4;
|
|
917
|
-
}
|
|
918
|
-
async executeCommand(command, opts) {
|
|
919
|
-
const result = await this.sandbox.commands.run(command, {
|
|
920
|
-
cwd: opts?.cwd ?? this.defaultCwd,
|
|
921
|
-
timeout: opts?.timeout ?? this.defaultTimeout,
|
|
922
|
-
envs: opts?.env
|
|
923
|
-
});
|
|
924
|
-
return {
|
|
925
|
-
exitCode: result.exitCode,
|
|
926
|
-
stdout: result.stdout ?? "",
|
|
927
|
-
stderr: result.stderr ?? ""
|
|
928
|
-
};
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
|
|
932
|
-
// src/virtual/freestyle-fs.ts
|
|
933
|
-
import * as path5 from "path";
|
|
934
|
-
var FreestyleFs = class {
|
|
935
|
-
vm;
|
|
936
|
-
workingDir;
|
|
937
|
-
constructor(opts) {
|
|
938
|
-
this.vm = opts.vm;
|
|
939
|
-
this.workingDir = opts.workingDir;
|
|
940
|
-
}
|
|
941
|
-
resolvePath(p) {
|
|
942
|
-
if (p.includes("\0")) {
|
|
943
|
-
throw new Error("Path contains null bytes");
|
|
944
|
-
}
|
|
945
|
-
if (!this.workingDir) return p;
|
|
946
|
-
const normalizedBase = this.workingDir.endsWith("/") ? this.workingDir : this.workingDir + "/";
|
|
947
|
-
if (p.startsWith("/")) {
|
|
948
|
-
const normalized = path5.normalize(p);
|
|
949
|
-
if (normalized !== this.workingDir && !normalized.startsWith(normalizedBase)) {
|
|
950
|
-
throw new Error(`Absolute path "${p}" is outside working directory "${this.workingDir}"`);
|
|
951
|
-
}
|
|
952
|
-
return normalized;
|
|
953
|
-
}
|
|
954
|
-
const resolved = path5.resolve(this.workingDir, p);
|
|
955
|
-
if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {
|
|
956
|
-
throw new Error(`Path "${p}" escapes working directory "${this.workingDir}"`);
|
|
957
|
-
}
|
|
958
|
-
return resolved;
|
|
959
|
-
}
|
|
960
|
-
async readFile(filePath, _opts) {
|
|
961
|
-
return this.vm.fs.readTextFile(this.resolvePath(filePath));
|
|
962
|
-
}
|
|
963
|
-
async readFileBytes(filePath, maxBytes) {
|
|
964
|
-
const resolved = this.resolvePath(filePath);
|
|
965
|
-
const cmd = maxBytes !== void 0 ? `head -c ${maxBytes} ${shellEscape3(resolved)} | base64` : `base64 ${shellEscape3(resolved)}`;
|
|
966
|
-
const { statusCode, stdout, stderr } = await this.vm.exec(cmd);
|
|
967
|
-
if (statusCode !== 0) {
|
|
968
|
-
throw new Error(`FreestyleFs readFileBytes failed: ${stderr?.trim() || `exit code ${statusCode}`}`);
|
|
969
|
-
}
|
|
970
|
-
return Buffer.from((stdout ?? "").trim(), "base64");
|
|
971
|
-
}
|
|
972
|
-
async writeFile(filePath, content) {
|
|
973
|
-
await this.vm.fs.writeTextFile(this.resolvePath(filePath), content);
|
|
974
|
-
}
|
|
975
|
-
async appendFile(filePath, content) {
|
|
976
|
-
const resolved = this.resolvePath(filePath);
|
|
977
|
-
const encoded = Buffer.from(content, "utf-8").toString("base64");
|
|
978
|
-
const { statusCode, stderr } = await this.vm.exec(
|
|
979
|
-
`echo ${shellEscape3(encoded)} | base64 -d >> ${shellEscape3(resolved)}`
|
|
980
|
-
);
|
|
981
|
-
if (statusCode !== 0) {
|
|
982
|
-
throw new Error(`FreestyleFs appendFile failed: ${stderr?.trim() || `exit code ${statusCode}`}`);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
async deleteFile(filePath, opts) {
|
|
986
|
-
const resolved = this.resolvePath(filePath);
|
|
987
|
-
const flag = opts?.recursive ? "-rf" : "-f";
|
|
988
|
-
await this.vm.exec(`rm ${flag} ${shellEscape3(resolved)}`);
|
|
989
|
-
}
|
|
990
|
-
async mkdir(filePath, opts) {
|
|
991
|
-
const resolved = this.resolvePath(filePath);
|
|
992
|
-
const flag = opts?.recursive ? "-p " : "";
|
|
993
|
-
await this.vm.exec(`mkdir ${flag}${shellEscape3(resolved)}`);
|
|
994
|
-
}
|
|
995
|
-
async readdir(dirPath, _opts) {
|
|
996
|
-
const resolved = this.resolvePath(dirPath);
|
|
997
|
-
const items = await this.vm.fs.readDir(resolved);
|
|
998
|
-
return items.map((entry) => ({
|
|
999
|
-
name: entry.name,
|
|
1000
|
-
path: resolved === "/" ? `/${entry.name}` : `${resolved}/${entry.name}`,
|
|
1001
|
-
isDirectory: entry.kind === "dir" || entry.kind === "directory",
|
|
1002
|
-
isFile: entry.kind === "file"
|
|
1003
|
-
}));
|
|
1004
|
-
}
|
|
1005
|
-
async exists(filePath) {
|
|
1006
|
-
const resolved = this.resolvePath(filePath);
|
|
1007
|
-
const { statusCode } = await this.vm.exec(`test -e ${shellEscape3(resolved)}`);
|
|
1008
|
-
return statusCode === 0;
|
|
1009
|
-
}
|
|
1010
|
-
async stat(filePath) {
|
|
1011
|
-
const resolved = this.resolvePath(filePath);
|
|
1012
|
-
const { statusCode, stdout, stderr } = await this.vm.exec(
|
|
1013
|
-
`stat -c '%s %F %W %Y' ${shellEscape3(resolved)}`
|
|
1014
|
-
);
|
|
1015
|
-
if (statusCode !== 0) {
|
|
1016
|
-
throw new Error(`FreestyleFs stat failed: ${stderr?.trim() || `exit code ${statusCode}`}`);
|
|
1017
|
-
}
|
|
1018
|
-
const parts = (stdout ?? "").trim().split(" ");
|
|
1019
|
-
const size = parseInt(parts[0], 10);
|
|
1020
|
-
const fileType = parts[1];
|
|
1021
|
-
const createdEpoch = parseInt(parts[2], 10);
|
|
1022
|
-
const modifiedEpoch = parseInt(parts[3], 10);
|
|
1023
|
-
return {
|
|
1024
|
-
size,
|
|
1025
|
-
isDirectory: fileType === "directory",
|
|
1026
|
-
isFile: fileType.startsWith("regular"),
|
|
1027
|
-
createdAt: createdEpoch > 0 ? new Date(createdEpoch * 1e3) : void 0,
|
|
1028
|
-
modifiedAt: modifiedEpoch > 0 ? new Date(modifiedEpoch * 1e3) : void 0
|
|
1029
|
-
};
|
|
1030
|
-
}
|
|
1031
|
-
};
|
|
1032
|
-
function shellEscape3(s) {
|
|
1033
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
// src/virtual/freestyle-computer.ts
|
|
1037
|
-
var FreestyleComputer = class {
|
|
1038
|
-
vm;
|
|
1039
|
-
defaultCwd;
|
|
1040
|
-
defaultTimeout;
|
|
1041
|
-
constructor(opts) {
|
|
1042
|
-
this.vm = opts.vm;
|
|
1043
|
-
this.defaultCwd = opts.defaultCwd;
|
|
1044
|
-
this.defaultTimeout = opts.defaultTimeout ?? 3e4;
|
|
1045
|
-
}
|
|
1046
|
-
async executeCommand(command, opts) {
|
|
1047
|
-
const result = await this.vm.exec(command, {
|
|
1048
|
-
cwd: opts?.cwd ?? this.defaultCwd,
|
|
1049
|
-
timeout: opts?.timeout ?? this.defaultTimeout
|
|
1050
|
-
});
|
|
1051
|
-
return {
|
|
1052
|
-
exitCode: result.statusCode ?? 1,
|
|
1053
|
-
stdout: result.stdout ?? "",
|
|
1054
|
-
stderr: result.stderr ?? ""
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
};
|
|
1058
|
-
|
|
1059
286
|
// src/virtual/sandbox.ts
|
|
1060
|
-
function uninitError() {
|
|
1061
|
-
throw new Error(
|
|
1062
|
-
"Sandbox not initialized \u2014 call init() or pass a pre-created resource"
|
|
1063
|
-
);
|
|
1064
|
-
}
|
|
1065
|
-
function createFsProxy() {
|
|
1066
|
-
let inner = null;
|
|
1067
|
-
const get = () => inner ?? uninitError();
|
|
1068
|
-
return {
|
|
1069
|
-
setTarget(target) {
|
|
1070
|
-
inner = target;
|
|
1071
|
-
},
|
|
1072
|
-
readFile: (...args) => get().readFile(...args),
|
|
1073
|
-
readFileBytes: (...args) => get().readFileBytes?.(...args),
|
|
1074
|
-
writeFile: (...args) => get().writeFile(...args),
|
|
1075
|
-
appendFile: (...args) => get().appendFile(...args),
|
|
1076
|
-
deleteFile: (...args) => get().deleteFile(...args),
|
|
1077
|
-
mkdir: (...args) => get().mkdir(...args),
|
|
1078
|
-
readdir: (...args) => get().readdir(...args),
|
|
1079
|
-
exists: (...args) => get().exists(...args),
|
|
1080
|
-
stat: (...args) => get().stat(...args)
|
|
1081
|
-
};
|
|
1082
|
-
}
|
|
1083
|
-
function createComputerProxy() {
|
|
1084
|
-
let inner = null;
|
|
1085
|
-
const get = () => inner ?? uninitError();
|
|
1086
|
-
return {
|
|
1087
|
-
setTarget(target) {
|
|
1088
|
-
inner = target;
|
|
1089
|
-
},
|
|
1090
|
-
executeCommand: (...args) => get().executeCommand(...args)
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
287
|
function UnsandboxedLocal(opts) {
|
|
1094
288
|
const cwd = opts?.cwd;
|
|
1095
289
|
return {
|
|
@@ -1121,358 +315,6 @@ function LocalSandbox(opts) {
|
|
|
1121
315
|
dispose: () => computer.dispose()
|
|
1122
316
|
};
|
|
1123
317
|
}
|
|
1124
|
-
function SpritesSandbox(opts) {
|
|
1125
|
-
const baseURL = (opts.baseURL ?? "https://api.sprites.dev").replace(/\/$/, "");
|
|
1126
|
-
const userProvidedName = opts.spriteName;
|
|
1127
|
-
if (userProvidedName) {
|
|
1128
|
-
const fsOpts = { ...opts, spriteName: userProvidedName };
|
|
1129
|
-
return {
|
|
1130
|
-
fs: new SpritesFs(fsOpts),
|
|
1131
|
-
computer: new SpritesComputer(fsOpts),
|
|
1132
|
-
sandboxId: () => userProvidedName
|
|
1133
|
-
};
|
|
1134
|
-
}
|
|
1135
|
-
const fsProxy = createFsProxy();
|
|
1136
|
-
const computerProxy = createComputerProxy();
|
|
1137
|
-
let resolvedName;
|
|
1138
|
-
let autoCreated = false;
|
|
1139
|
-
let initPromise = null;
|
|
1140
|
-
async function doInit(reconnectId) {
|
|
1141
|
-
let name = reconnectId ?? `${opts.namePrefix ?? "noumen-"}${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1142
|
-
let needsCreate = !reconnectId;
|
|
1143
|
-
if (reconnectId) {
|
|
1144
|
-
const check = await fetch(`${baseURL}/v1/sprites/${reconnectId}`, {
|
|
1145
|
-
method: "GET",
|
|
1146
|
-
headers: { Authorization: `Bearer ${opts.token}` }
|
|
1147
|
-
});
|
|
1148
|
-
if (!check.ok) {
|
|
1149
|
-
name = `${opts.namePrefix ?? "noumen-"}${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1150
|
-
needsCreate = true;
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
if (needsCreate) {
|
|
1154
|
-
const res = await fetch(`${baseURL}/v1/sprites`, {
|
|
1155
|
-
method: "POST",
|
|
1156
|
-
headers: {
|
|
1157
|
-
Authorization: `Bearer ${opts.token}`,
|
|
1158
|
-
"Content-Type": "application/json"
|
|
1159
|
-
},
|
|
1160
|
-
body: JSON.stringify({ name })
|
|
1161
|
-
});
|
|
1162
|
-
if (!res.ok) {
|
|
1163
|
-
throw new Error(`Sprites auto-create failed (${res.status}): ${await res.text()}`);
|
|
1164
|
-
}
|
|
1165
|
-
autoCreated = true;
|
|
1166
|
-
}
|
|
1167
|
-
resolvedName = name;
|
|
1168
|
-
const childOpts = { ...opts, spriteName: name };
|
|
1169
|
-
fsProxy.setTarget(new SpritesFs(childOpts));
|
|
1170
|
-
computerProxy.setTarget(new SpritesComputer(childOpts));
|
|
1171
|
-
}
|
|
1172
|
-
return {
|
|
1173
|
-
fs: fsProxy,
|
|
1174
|
-
computer: computerProxy,
|
|
1175
|
-
sandboxId: () => resolvedName,
|
|
1176
|
-
init(sandboxId) {
|
|
1177
|
-
if (!initPromise) {
|
|
1178
|
-
initPromise = doInit(sandboxId).catch((err) => {
|
|
1179
|
-
initPromise = null;
|
|
1180
|
-
throw err;
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1183
|
-
return initPromise;
|
|
1184
|
-
},
|
|
1185
|
-
async dispose() {
|
|
1186
|
-
if (initPromise) {
|
|
1187
|
-
await initPromise.catch(() => {
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
if (!autoCreated || !resolvedName) return;
|
|
1191
|
-
try {
|
|
1192
|
-
const res = await fetch(`${baseURL}/v1/sprites/${resolvedName}`, {
|
|
1193
|
-
method: "DELETE",
|
|
1194
|
-
headers: { Authorization: `Bearer ${opts.token}` }
|
|
1195
|
-
});
|
|
1196
|
-
if (!res.ok && res.status !== 404) {
|
|
1197
|
-
throw new Error(`Sprites dispose failed (${res.status}): ${await res.text()}`);
|
|
1198
|
-
}
|
|
1199
|
-
} catch {
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
};
|
|
1203
|
-
}
|
|
1204
|
-
function DockerSandbox(opts) {
|
|
1205
|
-
if (opts.container) {
|
|
1206
|
-
const c = opts.container;
|
|
1207
|
-
return {
|
|
1208
|
-
fs: new DockerFs({ container: c, workingDir: opts.cwd }),
|
|
1209
|
-
computer: new DockerComputer({
|
|
1210
|
-
container: c,
|
|
1211
|
-
defaultCwd: opts.cwd,
|
|
1212
|
-
defaultTimeout: opts.defaultTimeout
|
|
1213
|
-
}),
|
|
1214
|
-
sandboxId: () => c.id
|
|
1215
|
-
};
|
|
1216
|
-
}
|
|
1217
|
-
if (!opts.image) {
|
|
1218
|
-
throw new Error("DockerSandbox requires either `container` or `image`");
|
|
1219
|
-
}
|
|
1220
|
-
const fsProxy = createFsProxy();
|
|
1221
|
-
const computerProxy = createComputerProxy();
|
|
1222
|
-
let containerId;
|
|
1223
|
-
let containerRef;
|
|
1224
|
-
let autoCreated = false;
|
|
1225
|
-
let initPromise = null;
|
|
1226
|
-
async function doInit(reconnectId) {
|
|
1227
|
-
const Docker = (await import("dockerode")).default;
|
|
1228
|
-
const docker = new Docker();
|
|
1229
|
-
let container;
|
|
1230
|
-
if (reconnectId) {
|
|
1231
|
-
container = docker.getContainer(reconnectId);
|
|
1232
|
-
try {
|
|
1233
|
-
await container.inspect();
|
|
1234
|
-
} catch {
|
|
1235
|
-
container = await docker.createContainer({
|
|
1236
|
-
Image: opts.image,
|
|
1237
|
-
Cmd: opts.cmd ?? ["sleep", "infinity"],
|
|
1238
|
-
Env: opts.env,
|
|
1239
|
-
Tty: false,
|
|
1240
|
-
...opts.dockerOptions
|
|
1241
|
-
});
|
|
1242
|
-
await container.start();
|
|
1243
|
-
autoCreated = true;
|
|
1244
|
-
}
|
|
1245
|
-
} else {
|
|
1246
|
-
container = await docker.createContainer({
|
|
1247
|
-
Image: opts.image,
|
|
1248
|
-
Cmd: opts.cmd ?? ["sleep", "infinity"],
|
|
1249
|
-
Env: opts.env,
|
|
1250
|
-
Tty: false,
|
|
1251
|
-
...opts.dockerOptions
|
|
1252
|
-
});
|
|
1253
|
-
await container.start();
|
|
1254
|
-
autoCreated = true;
|
|
1255
|
-
}
|
|
1256
|
-
containerRef = container;
|
|
1257
|
-
containerId = container.id;
|
|
1258
|
-
fsProxy.setTarget(new DockerFs({ container, workingDir: opts.cwd }));
|
|
1259
|
-
computerProxy.setTarget(new DockerComputer({
|
|
1260
|
-
container,
|
|
1261
|
-
defaultCwd: opts.cwd,
|
|
1262
|
-
defaultTimeout: opts.defaultTimeout
|
|
1263
|
-
}));
|
|
1264
|
-
}
|
|
1265
|
-
return {
|
|
1266
|
-
fs: fsProxy,
|
|
1267
|
-
computer: computerProxy,
|
|
1268
|
-
sandboxId: () => containerId,
|
|
1269
|
-
init(sandboxId) {
|
|
1270
|
-
if (!initPromise) {
|
|
1271
|
-
initPromise = doInit(sandboxId).catch((err) => {
|
|
1272
|
-
initPromise = null;
|
|
1273
|
-
throw err;
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
return initPromise;
|
|
1277
|
-
},
|
|
1278
|
-
async dispose() {
|
|
1279
|
-
if (initPromise) {
|
|
1280
|
-
await initPromise.catch(() => {
|
|
1281
|
-
});
|
|
1282
|
-
}
|
|
1283
|
-
if (!autoCreated || !containerRef) return;
|
|
1284
|
-
try {
|
|
1285
|
-
await containerRef.stop();
|
|
1286
|
-
} catch {
|
|
1287
|
-
}
|
|
1288
|
-
try {
|
|
1289
|
-
await containerRef.remove();
|
|
1290
|
-
} catch {
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
};
|
|
1294
|
-
}
|
|
1295
|
-
function E2BSandbox(opts) {
|
|
1296
|
-
if (opts.sandbox) {
|
|
1297
|
-
const s = opts.sandbox;
|
|
1298
|
-
return {
|
|
1299
|
-
fs: new E2BFs({ sandbox: s, workingDir: opts.cwd }),
|
|
1300
|
-
computer: new E2BComputer({
|
|
1301
|
-
sandbox: s,
|
|
1302
|
-
defaultCwd: opts.cwd,
|
|
1303
|
-
defaultTimeout: opts.defaultTimeout
|
|
1304
|
-
}),
|
|
1305
|
-
sandboxId: () => s.sandboxId
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
const fsProxy = createFsProxy();
|
|
1309
|
-
const computerProxy = createComputerProxy();
|
|
1310
|
-
let resolvedId;
|
|
1311
|
-
let sandboxRef;
|
|
1312
|
-
let autoCreated = false;
|
|
1313
|
-
let initPromise = null;
|
|
1314
|
-
async function doInit(reconnectId) {
|
|
1315
|
-
const e2b = await import("e2b");
|
|
1316
|
-
const SandboxClass = e2b.Sandbox ?? e2b.default?.Sandbox;
|
|
1317
|
-
if (!SandboxClass) {
|
|
1318
|
-
throw new Error("Could not resolve Sandbox class from 'e2b' package");
|
|
1319
|
-
}
|
|
1320
|
-
let sandbox;
|
|
1321
|
-
if (reconnectId) {
|
|
1322
|
-
try {
|
|
1323
|
-
sandbox = await SandboxClass.connect(reconnectId, {
|
|
1324
|
-
apiKey: opts.apiKey
|
|
1325
|
-
});
|
|
1326
|
-
} catch {
|
|
1327
|
-
sandbox = await SandboxClass.create({
|
|
1328
|
-
template: opts.template ?? "base",
|
|
1329
|
-
apiKey: opts.apiKey,
|
|
1330
|
-
timeoutMs: opts.timeoutMs
|
|
1331
|
-
});
|
|
1332
|
-
autoCreated = true;
|
|
1333
|
-
}
|
|
1334
|
-
} else {
|
|
1335
|
-
sandbox = await SandboxClass.create({
|
|
1336
|
-
template: opts.template ?? "base",
|
|
1337
|
-
apiKey: opts.apiKey,
|
|
1338
|
-
timeoutMs: opts.timeoutMs
|
|
1339
|
-
});
|
|
1340
|
-
autoCreated = true;
|
|
1341
|
-
}
|
|
1342
|
-
sandboxRef = sandbox;
|
|
1343
|
-
resolvedId = sandbox.sandboxId ?? reconnectId;
|
|
1344
|
-
fsProxy.setTarget(new E2BFs({ sandbox, workingDir: opts.cwd }));
|
|
1345
|
-
computerProxy.setTarget(new E2BComputer({
|
|
1346
|
-
sandbox,
|
|
1347
|
-
defaultCwd: opts.cwd,
|
|
1348
|
-
defaultTimeout: opts.defaultTimeout
|
|
1349
|
-
}));
|
|
1350
|
-
}
|
|
1351
|
-
return {
|
|
1352
|
-
fs: fsProxy,
|
|
1353
|
-
computer: computerProxy,
|
|
1354
|
-
sandboxId: () => resolvedId,
|
|
1355
|
-
init(sandboxId) {
|
|
1356
|
-
if (!initPromise) {
|
|
1357
|
-
initPromise = doInit(sandboxId).catch((err) => {
|
|
1358
|
-
initPromise = null;
|
|
1359
|
-
throw err;
|
|
1360
|
-
});
|
|
1361
|
-
}
|
|
1362
|
-
return initPromise;
|
|
1363
|
-
},
|
|
1364
|
-
async dispose() {
|
|
1365
|
-
if (initPromise) {
|
|
1366
|
-
await initPromise.catch(() => {
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
if (!autoCreated || !sandboxRef) return;
|
|
1370
|
-
if (typeof sandboxRef.kill === "function") {
|
|
1371
|
-
await sandboxRef.kill();
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
};
|
|
1375
|
-
}
|
|
1376
|
-
function FreestyleSandbox(opts) {
|
|
1377
|
-
if (opts.vm) {
|
|
1378
|
-
const v = opts.vm;
|
|
1379
|
-
return {
|
|
1380
|
-
fs: new FreestyleFs({ vm: v, workingDir: opts.cwd }),
|
|
1381
|
-
computer: new FreestyleComputer({
|
|
1382
|
-
vm: v,
|
|
1383
|
-
defaultCwd: opts.cwd,
|
|
1384
|
-
defaultTimeout: opts.defaultTimeout
|
|
1385
|
-
}),
|
|
1386
|
-
sandboxId: () => v.vmId
|
|
1387
|
-
};
|
|
1388
|
-
}
|
|
1389
|
-
const fsProxy = createFsProxy();
|
|
1390
|
-
const computerProxy = createComputerProxy();
|
|
1391
|
-
let resolvedId;
|
|
1392
|
-
let vmRef = null;
|
|
1393
|
-
let autoCreated = false;
|
|
1394
|
-
let initPromise = null;
|
|
1395
|
-
async function doInit(reconnectId) {
|
|
1396
|
-
const mod = await import("freestyle-sandboxes");
|
|
1397
|
-
const freestyle = mod.freestyle ?? mod.default?.freestyle;
|
|
1398
|
-
if (!freestyle?.vms) {
|
|
1399
|
-
throw new Error("Could not resolve freestyle client from 'freestyle-sandboxes' package");
|
|
1400
|
-
}
|
|
1401
|
-
let vm;
|
|
1402
|
-
if (reconnectId) {
|
|
1403
|
-
try {
|
|
1404
|
-
const result = await freestyle.vms.get({ vmId: reconnectId });
|
|
1405
|
-
vm = result.vm;
|
|
1406
|
-
resolvedId = reconnectId;
|
|
1407
|
-
} catch {
|
|
1408
|
-
const result = await freestyle.vms.create({
|
|
1409
|
-
...opts.spec ? { spec: opts.spec } : {},
|
|
1410
|
-
snapshotId: opts.snapshotId,
|
|
1411
|
-
workdir: opts.cwd,
|
|
1412
|
-
idleTimeoutSeconds: opts.idleTimeoutSeconds ?? 600,
|
|
1413
|
-
additionalFiles: opts.additionalFiles,
|
|
1414
|
-
gitRepos: opts.gitRepos
|
|
1415
|
-
});
|
|
1416
|
-
vm = result.vm;
|
|
1417
|
-
resolvedId = result.vmId ?? result.id;
|
|
1418
|
-
autoCreated = true;
|
|
1419
|
-
}
|
|
1420
|
-
} else {
|
|
1421
|
-
const result = await freestyle.vms.create({
|
|
1422
|
-
...opts.spec ? { spec: opts.spec } : {},
|
|
1423
|
-
snapshotId: opts.snapshotId,
|
|
1424
|
-
workdir: opts.cwd,
|
|
1425
|
-
idleTimeoutSeconds: opts.idleTimeoutSeconds ?? 600,
|
|
1426
|
-
additionalFiles: opts.additionalFiles,
|
|
1427
|
-
gitRepos: opts.gitRepos
|
|
1428
|
-
});
|
|
1429
|
-
vm = result.vm;
|
|
1430
|
-
resolvedId = result.vmId ?? result.id;
|
|
1431
|
-
autoCreated = true;
|
|
1432
|
-
}
|
|
1433
|
-
vmRef = vm;
|
|
1434
|
-
fsProxy.setTarget(new FreestyleFs({ vm, workingDir: opts.cwd }));
|
|
1435
|
-
computerProxy.setTarget(new FreestyleComputer({
|
|
1436
|
-
vm,
|
|
1437
|
-
defaultCwd: opts.cwd,
|
|
1438
|
-
defaultTimeout: opts.defaultTimeout
|
|
1439
|
-
}));
|
|
1440
|
-
}
|
|
1441
|
-
return {
|
|
1442
|
-
fs: fsProxy,
|
|
1443
|
-
computer: computerProxy,
|
|
1444
|
-
sandboxId: () => resolvedId,
|
|
1445
|
-
init(sandboxId) {
|
|
1446
|
-
if (!initPromise) {
|
|
1447
|
-
initPromise = doInit(sandboxId).catch((err) => {
|
|
1448
|
-
initPromise = null;
|
|
1449
|
-
throw err;
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
|
-
return initPromise;
|
|
1453
|
-
},
|
|
1454
|
-
async dispose() {
|
|
1455
|
-
if (initPromise) {
|
|
1456
|
-
await initPromise.catch(() => {
|
|
1457
|
-
});
|
|
1458
|
-
}
|
|
1459
|
-
if (!autoCreated || !vmRef || !resolvedId) return;
|
|
1460
|
-
try {
|
|
1461
|
-
const strategy = opts.disposeStrategy ?? "suspend";
|
|
1462
|
-
if (strategy === "suspend") {
|
|
1463
|
-
await vmRef.suspend();
|
|
1464
|
-
} else {
|
|
1465
|
-
const mod = await import("freestyle-sandboxes");
|
|
1466
|
-
const freestyle = mod.freestyle ?? mod.default?.freestyle;
|
|
1467
|
-
if (freestyle?.vms) {
|
|
1468
|
-
await freestyle.vms.delete({ vmId: resolvedId });
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
} catch {
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
};
|
|
1475
|
-
}
|
|
1476
318
|
|
|
1477
319
|
// src/checkpoint/manager.ts
|
|
1478
320
|
import { createHash } from "crypto";
|
|
@@ -1704,8 +546,8 @@ var FileCheckpointManager = class {
|
|
|
1704
546
|
restoreStateFromEntries(snapshots) {
|
|
1705
547
|
const trackedFiles = /* @__PURE__ */ new Set();
|
|
1706
548
|
for (const snap of snapshots) {
|
|
1707
|
-
for (const
|
|
1708
|
-
trackedFiles.add(
|
|
549
|
+
for (const path2 of Object.keys(snap.trackedFileBackups)) {
|
|
550
|
+
trackedFiles.add(path2);
|
|
1709
551
|
}
|
|
1710
552
|
}
|
|
1711
553
|
this.state = {
|
|
@@ -1719,7 +561,7 @@ var FileCheckpointManager = class {
|
|
|
1719
561
|
// src/hooks/runner.ts
|
|
1720
562
|
var DEFAULT_HOOK_TIMEOUT_MS = 3e4;
|
|
1721
563
|
function withTimeout(promise, timeoutMs, label) {
|
|
1722
|
-
return new Promise((
|
|
564
|
+
return new Promise((resolve3, reject) => {
|
|
1723
565
|
const timer = setTimeout(
|
|
1724
566
|
() => reject(new Error(`Hook "${label}" timed out after ${timeoutMs}ms`)),
|
|
1725
567
|
timeoutMs
|
|
@@ -1727,7 +569,7 @@ function withTimeout(promise, timeoutMs, label) {
|
|
|
1727
569
|
promise.then(
|
|
1728
570
|
(v) => {
|
|
1729
571
|
clearTimeout(timer);
|
|
1730
|
-
|
|
572
|
+
resolve3(v);
|
|
1731
573
|
},
|
|
1732
574
|
(e) => {
|
|
1733
575
|
clearTimeout(timer);
|
|
@@ -2991,10 +1833,10 @@ var SessionStorage = class {
|
|
|
2991
1833
|
}
|
|
2992
1834
|
}
|
|
2993
1835
|
async loadMessages(sessionId) {
|
|
2994
|
-
const
|
|
2995
|
-
const exists = await this.fs.exists(
|
|
1836
|
+
const path2 = this.getTranscriptPath(sessionId);
|
|
1837
|
+
const exists = await this.fs.exists(path2);
|
|
2996
1838
|
if (!exists) return [];
|
|
2997
|
-
const content = await this.fs.readFile(
|
|
1839
|
+
const content = await this.fs.readFile(path2);
|
|
2998
1840
|
const entries = parseJSONL(content);
|
|
2999
1841
|
let lastBoundaryIdx = -1;
|
|
3000
1842
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
@@ -3029,10 +1871,10 @@ var SessionStorage = class {
|
|
|
3029
1871
|
return messages;
|
|
3030
1872
|
}
|
|
3031
1873
|
async loadAllEntries(sessionId) {
|
|
3032
|
-
const
|
|
3033
|
-
const exists = await this.fs.exists(
|
|
1874
|
+
const path2 = this.getTranscriptPath(sessionId);
|
|
1875
|
+
const exists = await this.fs.exists(path2);
|
|
3034
1876
|
if (!exists) return [];
|
|
3035
|
-
const content = await this.fs.readFile(
|
|
1877
|
+
const content = await this.fs.readFile(path2);
|
|
3036
1878
|
return parseJSONL(content);
|
|
3037
1879
|
}
|
|
3038
1880
|
async sessionExists(sessionId) {
|
|
@@ -3402,17 +2244,17 @@ function walkAncestors(cwd) {
|
|
|
3402
2244
|
}
|
|
3403
2245
|
return dirs;
|
|
3404
2246
|
}
|
|
3405
|
-
async function tryLoadFile(fs2,
|
|
3406
|
-
if (isExcluded(
|
|
3407
|
-
const file = await loadContextFile(fs2,
|
|
2247
|
+
async function tryLoadFile(fs2, path2, scope, out, maxDepth, excludes) {
|
|
2248
|
+
if (isExcluded(path2, excludes)) return;
|
|
2249
|
+
const file = await loadContextFile(fs2, path2, scope, /* @__PURE__ */ new Set(), 0, maxDepth);
|
|
3408
2250
|
if (file) out.push(file);
|
|
3409
2251
|
}
|
|
3410
|
-
async function loadContextFile(fs2,
|
|
3411
|
-
const normalized = normalizePath(
|
|
2252
|
+
async function loadContextFile(fs2, path2, scope, visited, depth, maxDepth) {
|
|
2253
|
+
const normalized = normalizePath(path2);
|
|
3412
2254
|
if (visited.has(normalized)) return null;
|
|
3413
2255
|
let raw;
|
|
3414
2256
|
try {
|
|
3415
|
-
raw = await fs2.readFile(
|
|
2257
|
+
raw = await fs2.readFile(path2);
|
|
3416
2258
|
} catch {
|
|
3417
2259
|
return null;
|
|
3418
2260
|
}
|
|
@@ -3421,9 +2263,9 @@ async function loadContextFile(fs2, path6, scope, visited, depth, maxDepth) {
|
|
|
3421
2263
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
3422
2264
|
const globs = parsePaths(frontmatter.paths);
|
|
3423
2265
|
const content = stripHtmlComments(body);
|
|
3424
|
-
const includes = await resolveIncludes(fs2, content,
|
|
2266
|
+
const includes = await resolveIncludes(fs2, content, path2, visited, depth, maxDepth);
|
|
3425
2267
|
return {
|
|
3426
|
-
path:
|
|
2268
|
+
path: path2,
|
|
3427
2269
|
scope,
|
|
3428
2270
|
content,
|
|
3429
2271
|
...globs.length > 0 ? { globs } : {},
|
|
@@ -3489,15 +2331,15 @@ function stripHtmlComments(content) {
|
|
|
3489
2331
|
if (!content.includes("<!--")) return content;
|
|
3490
2332
|
return content.replace(/<!--[\s\S]*?-->/g, "");
|
|
3491
2333
|
}
|
|
3492
|
-
function isExcluded(
|
|
2334
|
+
function isExcluded(path2, excludes) {
|
|
3493
2335
|
if (excludes.length === 0) return false;
|
|
3494
2336
|
return excludes.some((pattern) => {
|
|
3495
|
-
if (
|
|
2337
|
+
if (path2 === pattern) return true;
|
|
3496
2338
|
if (pattern.includes("*")) {
|
|
3497
2339
|
const regex = simpleGlobToRegex(pattern);
|
|
3498
|
-
return regex.test(
|
|
2340
|
+
return regex.test(path2);
|
|
3499
2341
|
}
|
|
3500
|
-
return
|
|
2342
|
+
return path2.includes(pattern);
|
|
3501
2343
|
});
|
|
3502
2344
|
}
|
|
3503
2345
|
function simpleGlobToRegex(glob) {
|
|
@@ -6231,7 +5073,7 @@ async function executeToolsStep(toolCalls, streamingExec, streamingResults, exec
|
|
|
6231
5073
|
}
|
|
6232
5074
|
|
|
6233
5075
|
// src/file-state/cache.ts
|
|
6234
|
-
import { normalize as
|
|
5076
|
+
import { normalize as normalize2 } from "path";
|
|
6235
5077
|
var DEFAULT_MAX_ENTRIES = 100;
|
|
6236
5078
|
var DEFAULT_MAX_BYTES = 25 * 1024 * 1024;
|
|
6237
5079
|
var FileStateCache = class {
|
|
@@ -6243,14 +5085,14 @@ var FileStateCache = class {
|
|
|
6243
5085
|
this.maxEntries = config?.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
6244
5086
|
this.maxBytes = config?.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
6245
5087
|
}
|
|
6246
|
-
key(
|
|
6247
|
-
return
|
|
5088
|
+
key(path2) {
|
|
5089
|
+
return normalize2(path2);
|
|
6248
5090
|
}
|
|
6249
5091
|
byteSize(state) {
|
|
6250
5092
|
return Math.max(1, Buffer.byteLength(state.content, "utf8"));
|
|
6251
5093
|
}
|
|
6252
|
-
set(
|
|
6253
|
-
const k = this.key(
|
|
5094
|
+
set(path2, state) {
|
|
5095
|
+
const k = this.key(path2);
|
|
6254
5096
|
const existing = this.entries.get(k);
|
|
6255
5097
|
if (existing) {
|
|
6256
5098
|
this.currentBytes -= this.byteSize(existing);
|
|
@@ -6266,19 +5108,19 @@ var FileStateCache = class {
|
|
|
6266
5108
|
this.entries.set(k, state);
|
|
6267
5109
|
this.currentBytes += size;
|
|
6268
5110
|
}
|
|
6269
|
-
get(
|
|
6270
|
-
const k = this.key(
|
|
5111
|
+
get(path2) {
|
|
5112
|
+
const k = this.key(path2);
|
|
6271
5113
|
const state = this.entries.get(k);
|
|
6272
5114
|
if (!state) return void 0;
|
|
6273
5115
|
this.entries.delete(k);
|
|
6274
5116
|
this.entries.set(k, state);
|
|
6275
5117
|
return state;
|
|
6276
5118
|
}
|
|
6277
|
-
has(
|
|
6278
|
-
return this.entries.has(this.key(
|
|
5119
|
+
has(path2) {
|
|
5120
|
+
return this.entries.has(this.key(path2));
|
|
6279
5121
|
}
|
|
6280
|
-
delete(
|
|
6281
|
-
const k = this.key(
|
|
5122
|
+
delete(path2) {
|
|
5123
|
+
const k = this.key(path2);
|
|
6282
5124
|
const existing = this.entries.get(k);
|
|
6283
5125
|
if (existing) {
|
|
6284
5126
|
this.currentBytes -= this.byteSize(existing);
|
|
@@ -6320,8 +5162,8 @@ function getActiveSkills(allSkills, activatedNames) {
|
|
|
6320
5162
|
return activatedNames.has(skill.name);
|
|
6321
5163
|
});
|
|
6322
5164
|
}
|
|
6323
|
-
function matchesAnyGlob(
|
|
6324
|
-
return patterns.some((pattern) => globMatch(pattern,
|
|
5165
|
+
function matchesAnyGlob(path2, patterns) {
|
|
5166
|
+
return patterns.some((pattern) => globMatch(pattern, path2));
|
|
6325
5167
|
}
|
|
6326
5168
|
function globMatch(pattern, str) {
|
|
6327
5169
|
const regex = globToRegex(pattern);
|
|
@@ -6803,8 +5645,8 @@ var StreamingToolExecutor = class {
|
|
|
6803
5645
|
}
|
|
6804
5646
|
if (this.hasExecuting() && !this.hasCompleted()) {
|
|
6805
5647
|
const executingPromises = this.tools.filter((t) => t.status === "executing" && t.promise).map((t) => t.promise);
|
|
6806
|
-
const progressPromise = new Promise((
|
|
6807
|
-
this.progressResolve =
|
|
5648
|
+
const progressPromise = new Promise((resolve3) => {
|
|
5649
|
+
this.progressResolve = resolve3;
|
|
6808
5650
|
});
|
|
6809
5651
|
if (executingPromises.length > 0) {
|
|
6810
5652
|
await Promise.race([...executingPromises, progressPromise]);
|
|
@@ -6847,7 +5689,7 @@ function getRetryDelay(attempt, retryAfterHeader, maxDelayMs = 32e3, baseDelayMs
|
|
|
6847
5689
|
return baseDelay + jitter;
|
|
6848
5690
|
}
|
|
6849
5691
|
function sleep(ms, signal) {
|
|
6850
|
-
return new Promise((
|
|
5692
|
+
return new Promise((resolve3, reject) => {
|
|
6851
5693
|
if (signal?.aborted) {
|
|
6852
5694
|
reject(new DOMException("Aborted", "AbortError"));
|
|
6853
5695
|
return;
|
|
@@ -6858,7 +5700,7 @@ function sleep(ms, signal) {
|
|
|
6858
5700
|
};
|
|
6859
5701
|
const timer = setTimeout(() => {
|
|
6860
5702
|
signal?.removeEventListener("abort", onAbort);
|
|
6861
|
-
|
|
5703
|
+
resolve3();
|
|
6862
5704
|
}, ms);
|
|
6863
5705
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
6864
5706
|
});
|
|
@@ -9216,7 +8058,7 @@ var Agent = class {
|
|
|
9216
8058
|
if (this.resolvedProvider) return this.resolvedProvider;
|
|
9217
8059
|
if (!this.providerPromise) {
|
|
9218
8060
|
this.providerPromise = (async () => {
|
|
9219
|
-
const { resolveProvider: resolveProvider2 } = await import("./resolve-
|
|
8061
|
+
const { resolveProvider: resolveProvider2 } = await import("./resolve-GDSHNMG6.js");
|
|
9220
8062
|
return resolveProvider2(this.providerInput, { model: this.model });
|
|
9221
8063
|
})();
|
|
9222
8064
|
}
|
|
@@ -10161,18 +9003,18 @@ var FileMemoryProvider = class {
|
|
|
10161
9003
|
return "";
|
|
10162
9004
|
}
|
|
10163
9005
|
}
|
|
10164
|
-
async loadEntry(
|
|
10165
|
-
const fullPath =
|
|
9006
|
+
async loadEntry(path2) {
|
|
9007
|
+
const fullPath = path2.startsWith(this.dir) ? path2 : this.dir + path2;
|
|
10166
9008
|
try {
|
|
10167
9009
|
const raw = await this.fs.readFile(fullPath);
|
|
10168
9010
|
const fm = parseFrontmatter2(raw);
|
|
10169
9011
|
const stat2 = await this.fs.stat(fullPath).catch(() => null);
|
|
10170
9012
|
return {
|
|
10171
|
-
name: fm.name ?? pathToName(
|
|
9013
|
+
name: fm.name ?? pathToName(path2),
|
|
10172
9014
|
description: fm.description ?? "",
|
|
10173
9015
|
type: fm.type ?? "project",
|
|
10174
9016
|
content: fm.rest,
|
|
10175
|
-
path:
|
|
9017
|
+
path: path2.startsWith(this.dir) ? path2.slice(this.dir.length) : path2,
|
|
10176
9018
|
updatedAt: stat2?.modifiedAt?.toISOString()
|
|
10177
9019
|
};
|
|
10178
9020
|
} catch {
|
|
@@ -10187,8 +9029,8 @@ var FileMemoryProvider = class {
|
|
|
10187
9029
|
await this.fs.writeFile(fullPath, content);
|
|
10188
9030
|
await this.rebuildIndex();
|
|
10189
9031
|
}
|
|
10190
|
-
async removeEntry(
|
|
10191
|
-
const fullPath =
|
|
9032
|
+
async removeEntry(path2) {
|
|
9033
|
+
const fullPath = path2.startsWith(this.dir) ? path2 : this.dir + path2;
|
|
10192
9034
|
try {
|
|
10193
9035
|
await this.fs.deleteFile(fullPath);
|
|
10194
9036
|
} catch {
|
|
@@ -10237,20 +9079,8 @@ export {
|
|
|
10237
9079
|
LocalFs,
|
|
10238
9080
|
LocalComputer,
|
|
10239
9081
|
SandboxedLocalComputer,
|
|
10240
|
-
SpritesFs,
|
|
10241
|
-
SpritesComputer,
|
|
10242
|
-
DockerFs,
|
|
10243
|
-
DockerComputer,
|
|
10244
|
-
E2BFs,
|
|
10245
|
-
E2BComputer,
|
|
10246
|
-
FreestyleFs,
|
|
10247
|
-
FreestyleComputer,
|
|
10248
9082
|
UnsandboxedLocal,
|
|
10249
9083
|
LocalSandbox,
|
|
10250
|
-
SpritesSandbox,
|
|
10251
|
-
DockerSandbox,
|
|
10252
|
-
E2BSandbox,
|
|
10253
|
-
FreestyleSandbox,
|
|
10254
9084
|
createCheckpointState,
|
|
10255
9085
|
FileCheckpointManager,
|
|
10256
9086
|
runPreToolUseHooks,
|
|
@@ -10362,4 +9192,4 @@ export {
|
|
|
10362
9192
|
truncateIndex,
|
|
10363
9193
|
FileMemoryProvider
|
|
10364
9194
|
};
|
|
10365
|
-
//# sourceMappingURL=chunk-
|
|
9195
|
+
//# sourceMappingURL=chunk-WPCYGZOE.js.map
|