@madarco/agentbox 0.11.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/dist/{_cloud-attach-XWCVLO5V.js → _cloud-attach-XKO4SHR3.js} +3 -3
  3. package/dist/{chunk-ZGVMN54V.js → chunk-2LF5YILI.js} +21 -3
  4. package/dist/chunk-2LF5YILI.js.map +1 -0
  5. package/dist/{chunk-MXXXKJYS.js → chunk-DHJ7OMIP.js} +234 -83
  6. package/dist/chunk-DHJ7OMIP.js.map +1 -0
  7. package/dist/{chunk-GYJ62GFL.js → chunk-HFV6THYG.js} +6 -6
  8. package/dist/{chunk-ZJXTIH6C.js → chunk-IZXPJPPV.js} +1347 -852
  9. package/dist/chunk-IZXPJPPV.js.map +1 -0
  10. package/dist/{dist-RAZP76VX.js → dist-24PY2ZMO.js} +3 -3
  11. package/dist/{dist-PTJ6CEQY.js → dist-47LVLYUV.js} +4 -4
  12. package/dist/{dist-ASLPRUQR.js → dist-RZZSSUNB.js} +28 -2
  13. package/dist/{dist-WMQDMTWS.js → dist-SWUOU34W.js} +8 -5
  14. package/dist/dist-SWUOU34W.js.map +1 -0
  15. package/dist/index.js +1351 -731
  16. package/dist/index.js.map +1 -1
  17. package/package.json +6 -6
  18. package/runtime/docker/packages/ctl/dist/bin.cjs +335 -4
  19. package/runtime/docker/packages/sandbox-docker/scripts/gh-shim +86 -5
  20. package/runtime/hetzner/ctl.cjs +335 -4
  21. package/runtime/hetzner/gh-shim +86 -5
  22. package/runtime/relay/bin.cjs +285 -2
  23. package/runtime/vercel/ctl.cjs +335 -4
  24. package/runtime/vercel/gh-shim +86 -5
  25. package/share/host-skills/agentbox/SKILL.md +16 -5
  26. package/share/host-skills/agentbox-info/SKILL.md +29 -7
  27. package/dist/chunk-MXXXKJYS.js.map +0 -1
  28. package/dist/chunk-ZGVMN54V.js.map +0 -1
  29. package/dist/chunk-ZJXTIH6C.js.map +0 -1
  30. package/dist/dist-WMQDMTWS.js.map +0 -1
  31. /package/dist/{_cloud-attach-XWCVLO5V.js.map → _cloud-attach-XKO4SHR3.js.map} +0 -0
  32. /package/dist/{chunk-GYJ62GFL.js.map → chunk-HFV6THYG.js.map} +0 -0
  33. /package/dist/{dist-RAZP76VX.js.map → dist-24PY2ZMO.js.map} +0 -0
  34. /package/dist/{dist-PTJ6CEQY.js.map → dist-47LVLYUV.js.map} +0 -0
  35. /package/dist/{dist-ASLPRUQR.js.map → dist-RZZSSUNB.js.map} +0 -0
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ BOX_DYNAMIC_SYNC_MANIFEST,
4
+ BOX_MEMORY_DIR,
5
+ BOX_WORKFLOWS_DIR,
3
6
  CLAUDE_FORWARDED_ENV_KEYS,
4
7
  CODEX_CREDENTIALS_BACKUP_FILE,
5
8
  CODEX_FORWARDED_ENV_KEYS,
@@ -7,7 +10,9 @@ import {
7
10
  OPENCODE_CREDENTIALS_BACKUP_FILE,
8
11
  OPENCODE_FORWARDED_ENV_KEYS,
9
12
  buildHostEnvFindArgs,
13
+ buildHostSyncManifest,
10
14
  buildTmuxConfigShellSnippet,
15
+ computeSyncDelta,
11
16
  ensureRelay,
12
17
  forgetBoxFromRelay,
13
18
  generateBoxId,
@@ -25,13 +30,16 @@ import {
25
30
  stageClaudeStaticForUpload,
26
31
  stageCodexCredentialsForUpload,
27
32
  stageCodexStaticForUpload,
33
+ stageDynamicSyncTarball,
28
34
  stageOpencodeCredentialsForUpload,
29
35
  stageOpencodeStateForUpload,
30
36
  stageOpencodeStaticForUpload
31
- } from "./chunk-ZJXTIH6C.js";
37
+ } from "./chunk-IZXPJPPV.js";
32
38
  import {
33
39
  allocateProjectIndex,
34
40
  detectGitRepos,
41
+ readCliStamp,
42
+ readPreparedStateRaw,
35
43
  readState,
36
44
  recordBox,
37
45
  removeBoxRecord
@@ -41,24 +49,28 @@ import {
41
49
  import { basename as basename2 } from "path";
42
50
  import { chmod, mkdir, writeFile } from "fs/promises";
43
51
  import { dirname } from "path";
44
- import { mkdir as mkdir2, readFile, readdir, rm, writeFile as writeFile2 } from "fs/promises";
45
- import { homedir } from "os";
46
- import { basename, join } from "path";
47
- import { mkdtemp, rm as rm2, writeFile as writeFile3 } from "fs/promises";
52
+ import { mkdtemp, rm, writeFile as writeFile2 } from "fs/promises";
48
53
  import { tmpdir } from "os";
49
- import { join as join2 } from "path";
54
+ import { dirname as dirname2, join } from "path";
50
55
  import { execa } from "execa";
51
- import { mkdtemp as mkdtemp2, rm as rm3 } from "fs/promises";
56
+ import { mkdir as mkdir2, readFile, readdir, rm as rm2, writeFile as writeFile3 } from "fs/promises";
57
+ import { homedir } from "os";
58
+ import { basename, join as join2 } from "path";
59
+ import { mkdtemp as mkdtemp2, rm as rm3, writeFile as writeFile4 } from "fs/promises";
52
60
  import { tmpdir as tmpdir2 } from "os";
53
61
  import { join as join3 } from "path";
54
62
  import { execa as execa2 } from "execa";
55
- import { readFile as readFile2 } from "fs/promises";
63
+ import { mkdtemp as mkdtemp3, rm as rm4 } from "fs/promises";
64
+ import { tmpdir as tmpdir3 } from "os";
56
65
  import { join as join4 } from "path";
57
- import { parse as parseYaml } from "yaml";
58
66
  import { execa as execa3 } from "execa";
67
+ import { readFile as readFile2 } from "fs/promises";
68
+ import { join as join5 } from "path";
69
+ import { parse as parseYaml } from "yaml";
70
+ import { execa as execa4 } from "execa";
59
71
  import { existsSync, mkdirSync, renameSync, statSync } from "fs";
60
- import { mkdtemp as mkdtemp3, rm as rm4 } from "fs/promises";
61
- import { tmpdir as tmpdir3 } from "os";
72
+ import { mkdtemp as mkdtemp4, rm as rm5 } from "fs/promises";
73
+ import { tmpdir as tmpdir4 } from "os";
62
74
  import {
63
75
  basename as hostBasename,
64
76
  dirname as hostDirname,
@@ -66,10 +78,10 @@ import {
66
78
  resolve as hostResolve
67
79
  } from "path";
68
80
  import { posix } from "path";
69
- import { execa as execa4 } from "execa";
70
- import { mkdtemp as mkdtemp4, rm as rm5, stat } from "fs/promises";
71
- import { tmpdir as tmpdir4 } from "os";
72
- import { join as join5 } from "path";
81
+ import { execa as execa5 } from "execa";
82
+ import { mkdtemp as mkdtemp5, rm as rm6, stat } from "fs/promises";
83
+ import { tmpdir as tmpdir5 } from "os";
84
+ import { join as join6 } from "path";
73
85
  var CREDENTIALS_VOLUME = "agentbox-credentials";
74
86
  var AGENT_SPECS = [
75
87
  {
@@ -267,30 +279,132 @@ async function extractCloudAgentCredentials(backend, handle, opts = {}) {
267
279
  }
268
280
  return extracted;
269
281
  }
270
- var CLOUD_CHECKPOINTS_ROOT = join(homedir(), ".agentbox", "cloud-checkpoints");
282
+ function sq(p) {
283
+ return `'${p.replace(/'/g, `'\\''`)}'`;
284
+ }
285
+ var REMOTE_TAR = "/tmp/agentbox-dynsync.tar.gz";
286
+ var BOX_STAGE = "/tmp/agentbox-dynsync-stage";
287
+ async function seedDynamicConfig(backend, handle, opts) {
288
+ const log = opts.onLog ?? (() => {
289
+ });
290
+ try {
291
+ let boxManifest = null;
292
+ try {
293
+ const res = await backend.exec(handle, `cat ${BOX_DYNAMIC_SYNC_MANIFEST} 2>/dev/null || true`);
294
+ const out = res.stdout.trim();
295
+ if (res.exitCode === 0 && out.length > 0) {
296
+ boxManifest = JSON.parse(out);
297
+ }
298
+ } catch {
299
+ boxManifest = null;
300
+ }
301
+ const host = await buildHostSyncManifest(opts.workspacePath);
302
+ const delta = computeSyncDelta(host, boxManifest);
303
+ if (delta.uploads.length === 0 && delta.deletions.length === 0) {
304
+ log("claude workflows + memory already up to date in box");
305
+ return;
306
+ }
307
+ delta.nextManifest.syncedAt = (/* @__PURE__ */ new Date()).toISOString();
308
+ const staged = await stageDynamicSyncTarball(delta.uploads);
309
+ const manifestDir = await mkdtemp(join(tmpdir(), "agentbox-dynsync-manifest-"));
310
+ const manifestTmp = join(manifestDir, "dynamic-sync.json");
311
+ await writeFile2(manifestTmp, JSON.stringify(delta.nextManifest, null, 2));
312
+ try {
313
+ const steps = [
314
+ "set -e",
315
+ `mkdir -p /home/vscode/.agentbox ${BOX_WORKFLOWS_DIR} ${BOX_MEMORY_DIR}`
316
+ ];
317
+ if (staged.tarballPath) {
318
+ await backend.uploadFile(handle, staged.tarballPath, REMOTE_TAR);
319
+ steps.push(
320
+ `rm -rf ${BOX_STAGE}`,
321
+ `mkdir -p ${BOX_STAGE}`,
322
+ `tar -xzf ${REMOTE_TAR} -C ${BOX_STAGE}`,
323
+ `if [ -d ${BOX_STAGE}/workflows ]; then cp -a ${BOX_STAGE}/workflows/. ${BOX_WORKFLOWS_DIR}/; fi`,
324
+ `if [ -d ${BOX_STAGE}/memory ]; then cp -a ${BOX_STAGE}/memory/. ${BOX_MEMORY_DIR}/; fi`,
325
+ `rm -rf ${BOX_STAGE} ${REMOTE_TAR}`
326
+ );
327
+ }
328
+ for (const d of delta.deletions) {
329
+ steps.push(`rm -f ${sq(d.dst)}`);
330
+ }
331
+ const res = await backend.exec(handle, steps.join("; "));
332
+ if (res.exitCode !== 0) {
333
+ log(
334
+ `dynamic config seed failed (exit ${String(res.exitCode)}): ${res.stderr.slice(-200)}`
335
+ );
336
+ return;
337
+ }
338
+ await backend.uploadFile(handle, manifestTmp, BOX_DYNAMIC_SYNC_MANIFEST);
339
+ log(
340
+ `seeded claude workflows + memory: ${String(delta.uploads.length)} file(s) updated, ${String(delta.deletions.length)} removed`
341
+ );
342
+ } finally {
343
+ await staged.cleanup();
344
+ await rm(dirname2(manifestTmp), { recursive: true, force: true });
345
+ }
346
+ } catch (err) {
347
+ log(
348
+ `claude workflows + memory seed skipped (non-fatal): ${err instanceof Error ? err.message : String(err)}`
349
+ );
350
+ }
351
+ }
352
+ function quoteShellArgv(argv) {
353
+ return argv.map(quoteShellArg).join(" ");
354
+ }
355
+ function quoteShellArg(arg) {
356
+ if (arg.length === 0) return "''";
357
+ if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)) return arg;
358
+ return "'" + arg.replace(/'/g, "'\\''") + "'";
359
+ }
360
+ function bashScript(body) {
361
+ return `bash -c ${quoteShellArg(body)}`;
362
+ }
363
+ var FALLBACK_NAME = "agentbox";
364
+ var FALLBACK_EMAIL = "agentbox@users.noreply.github.com";
365
+ async function seedGitIdentity(backend, handle, opts = {}) {
366
+ const log = opts.onLog ?? (() => {
367
+ });
368
+ const name = await readHostGitConfig("user.name", opts.hostRepo) ?? FALLBACK_NAME;
369
+ const email = await readHostGitConfig("user.email", opts.hostRepo) ?? FALLBACK_EMAIL;
370
+ const script = `git config --global user.name ${quoteShellArg(name)} && git config --global user.email ${quoteShellArg(email)}`;
371
+ const r = await backend.exec(handle, bashScript(script));
372
+ if (r.exitCode !== 0) {
373
+ log(`git: identity config failed (exit ${String(r.exitCode)}): ${(r.stderr || r.stdout).trim()}`);
374
+ return;
375
+ }
376
+ log(`git: configured committer identity ${name} <${email}>`);
377
+ }
378
+ async function readHostGitConfig(key, hostRepo) {
379
+ const args = hostRepo ? ["-C", hostRepo, "config", key] : ["config", key];
380
+ const r = await execa("git", args, { reject: false });
381
+ if (r.exitCode !== 0) return null;
382
+ const value = (r.stdout ?? "").trim();
383
+ return value.length > 0 ? value : null;
384
+ }
385
+ var CLOUD_CHECKPOINTS_ROOT = join2(homedir(), ".agentbox", "cloud-checkpoints");
271
386
  var CLOUD_SNAPSHOT_NAME_PREFIX = "agentbox-ckpt-";
272
387
  function cloudSnapshotName(projectRoot, name) {
273
388
  const mnemonic = sanitizeMnemonic(basename(projectRoot));
274
389
  return `${CLOUD_SNAPSHOT_NAME_PREFIX}${hashProjectPath(projectRoot)}_${mnemonic}-${name}`;
275
390
  }
276
391
  function backendDir(backend, projectRoot) {
277
- return join(CLOUD_CHECKPOINTS_ROOT, backend, projectDirSegment(projectRoot));
392
+ return join2(CLOUD_CHECKPOINTS_ROOT, backend, projectDirSegment(projectRoot));
278
393
  }
279
394
  function checkpointDir(backend, projectRoot, name) {
280
- return join(backendDir(backend, projectRoot), name);
395
+ return join2(backendDir(backend, projectRoot), name);
281
396
  }
282
397
  async function readManifest(dir) {
283
398
  try {
284
- const raw = await readFile(join(dir, "manifest.json"), "utf8");
399
+ const raw = await readFile(join2(dir, "manifest.json"), "utf8");
285
400
  const m = JSON.parse(raw);
286
- if (m.schema !== 1) return null;
401
+ if (m.schema !== 1 && m.schema !== 2) return null;
287
402
  return m;
288
403
  } catch {
289
404
  return null;
290
405
  }
291
406
  }
292
- async function listCloudCheckpoints(projectRoot, backend) {
293
- const root = backendDir(backend, projectRoot);
407
+ async function listCloudCheckpointsInDir(root) {
294
408
  let entries;
295
409
  try {
296
410
  entries = (await readdir(root, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
@@ -299,13 +413,31 @@ async function listCloudCheckpoints(projectRoot, backend) {
299
413
  }
300
414
  const out = [];
301
415
  for (const name of entries) {
302
- const dir = join(root, name);
416
+ const dir = join2(root, name);
303
417
  const manifest = await readManifest(dir);
304
418
  if (manifest) out.push({ name, dir, manifest });
305
419
  }
306
420
  out.sort((a, b) => a.manifest.createdAt.localeCompare(b.manifest.createdAt));
307
421
  return out;
308
422
  }
423
+ async function listCloudCheckpoints(projectRoot, backend) {
424
+ return listCloudCheckpointsInDir(backendDir(backend, projectRoot));
425
+ }
426
+ async function listAllCloudCheckpoints(backend) {
427
+ const backendRoot = join2(CLOUD_CHECKPOINTS_ROOT, backend);
428
+ let segments;
429
+ try {
430
+ segments = (await readdir(backendRoot, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
431
+ } catch {
432
+ return [];
433
+ }
434
+ const out = [];
435
+ for (const segment of segments) {
436
+ const items = await listCloudCheckpointsInDir(join2(backendRoot, segment));
437
+ if (items.length > 0) out.push({ segment, items });
438
+ }
439
+ return out;
440
+ }
309
441
  async function resolveCloudCheckpoint(projectRoot, backend, ref) {
310
442
  const dir = checkpointDir(backend, projectRoot, ref);
311
443
  const manifest = await readManifest(dir);
@@ -316,22 +448,33 @@ async function writeCloudCheckpointManifest(projectRoot, backend, name, fields)
316
448
  const dir = checkpointDir(backend, projectRoot, name);
317
449
  await mkdir2(dir, { recursive: true });
318
450
  const manifest = {
319
- schema: 1,
451
+ schema: 2,
320
452
  name,
321
453
  backend,
322
454
  snapshotName: fields.snapshotName,
323
455
  sourceBoxId: fields.sourceBoxId,
324
456
  sourceBoxName: fields.sourceBoxName,
457
+ baseProvider: fields.baseProvider,
458
+ baseFingerprint: fields.baseFingerprint,
459
+ cliVersion: fields.cliVersion,
325
460
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
326
461
  };
327
- await writeFile2(join(dir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
462
+ await writeFile3(join2(dir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
328
463
  return { name, dir, manifest };
329
464
  }
465
+ function currentCloudBaseFingerprint(provider) {
466
+ try {
467
+ const raw = readPreparedStateRaw(provider);
468
+ return raw?.base?.contextSha256;
469
+ } catch {
470
+ return void 0;
471
+ }
472
+ }
330
473
  async function removeCloudCheckpointDir(projectRoot, backend, name) {
331
474
  const dir = checkpointDir(backend, projectRoot, name);
332
475
  const existed = await readManifest(dir) !== null;
333
476
  if (!existed) return false;
334
- await rm(dir, { recursive: true, force: true });
477
+ await rm2(dir, { recursive: true, force: true });
335
478
  return true;
336
479
  }
337
480
  async function probeCloudCheckpoint(backend, projectRoot, ref) {
@@ -362,7 +505,7 @@ async function uploadEnvFiles(args) {
362
505
  });
363
506
  if (args.files.length === 0) return { copied: 0 };
364
507
  const workspaceDir = args.workspaceDir ?? WORKSPACE_DIR_DEFAULT;
365
- const found = await execa("find", buildHostEnvFindArgs(args.files).slice(1), {
508
+ const found = await execa2("find", buildHostEnvFindArgs(args.files).slice(1), {
366
509
  cwd: args.workspacePath,
367
510
  reject: false
368
511
  });
@@ -372,10 +515,10 @@ async function uploadEnvFiles(args) {
372
515
  }
373
516
  const list = String(found.stdout).split("\0").filter((p) => p.length > 0);
374
517
  if (list.length === 0) return { copied: 0 };
375
- const stage = await mkdtemp(join2(tmpdir(), "agentbox-envfiles-"));
376
- const localTar = join2(stage, "envfiles.tar");
518
+ const stage = await mkdtemp2(join3(tmpdir2(), "agentbox-envfiles-"));
519
+ const localTar = join3(stage, "envfiles.tar");
377
520
  try {
378
- const packed = await execa(
521
+ const packed = await execa2(
379
522
  "tar",
380
523
  ["-C", args.workspacePath, "--null", "-T", "-", "-cf", localTar],
381
524
  { input: list.join("\0"), reject: false }
@@ -384,7 +527,7 @@ async function uploadEnvFiles(args) {
384
527
  log(`env-file tar pack failed: ${String(packed.stderr).slice(0, 300)}`);
385
528
  return { copied: 0 };
386
529
  }
387
- await writeFile3(join2(stage, ".marker"), "").catch(() => {
530
+ await writeFile4(join3(stage, ".marker"), "").catch(() => {
388
531
  });
389
532
  await args.backend.uploadFile(args.handle, localTar, REMOTE_TAR_PATH);
390
533
  const extract = await args.backend.exec(
@@ -398,7 +541,7 @@ async function uploadEnvFiles(args) {
398
541
  return { copied: 0 };
399
542
  }
400
543
  } finally {
401
- await rm2(stage, { recursive: true, force: true });
544
+ await rm3(stage, { recursive: true, force: true });
402
545
  }
403
546
  return { copied: list.length };
404
547
  }
@@ -409,7 +552,7 @@ async function uploadCarryPaths(args) {
409
552
  if (args.entries.length === 0) {
410
553
  return { copied: 0, errors: [], applied: [] };
411
554
  }
412
- const stage = await mkdtemp2(join3(tmpdir2(), "agentbox-carry-"));
555
+ const stage = await mkdtemp3(join4(tmpdir3(), "agentbox-carry-"));
413
556
  const errors = [];
414
557
  const applied = [];
415
558
  let copied = 0;
@@ -437,7 +580,7 @@ async function uploadCarryPaths(args) {
437
580
  }
438
581
  }
439
582
  } finally {
440
- await rm3(stage, { recursive: true, force: true });
583
+ await rm4(stage, { recursive: true, force: true });
441
584
  }
442
585
  return { copied, errors, applied };
443
586
  }
@@ -447,9 +590,9 @@ async function uploadOneEntry(args) {
447
590
  const boxDest = entry.absDest.startsWith("~/") ? `${BOX_HOME}/${entry.absDest.slice(2)}` : entry.absDest;
448
591
  const isDir = entry.kind === "dir";
449
592
  const parentDir = isDir ? boxDest : dirnameUnix(boxDest);
450
- const localTar = join3(args.stageDir, `carry-${String(args.index)}.tar`);
593
+ const localTar = join4(args.stageDir, `carry-${String(args.index)}.tar`);
451
594
  const tarArgs = isDir ? ["-C", entry.absSrc, "-cf", localTar, "."] : ["-C", dirnameUnix(entry.absSrc), "-cf", localTar, basenameUnix(entry.absSrc)];
452
- const packed = await execa2("tar", tarArgs, { reject: false });
595
+ const packed = await execa3("tar", tarArgs, { reject: false });
453
596
  if (packed.exitCode !== 0) {
454
597
  throw new Error(`tar pack failed: ${String(packed.stderr).slice(0, 300)}`);
455
598
  }
@@ -501,7 +644,7 @@ function shellQuote(s) {
501
644
  async function readExposedServicePorts(workspacePath) {
502
645
  let text;
503
646
  try {
504
- text = await readFile2(join4(workspacePath, "agentbox.yaml"), "utf8");
647
+ text = await readFile2(join5(workspacePath, "agentbox.yaml"), "utf8");
505
648
  } catch {
506
649
  return [];
507
650
  }
@@ -529,17 +672,6 @@ async function readExposedServicePorts(workspacePath) {
529
672
  function isPlainObject(v) {
530
673
  return typeof v === "object" && v !== null && !Array.isArray(v);
531
674
  }
532
- function quoteShellArgv(argv) {
533
- return argv.map(quoteShellArg).join(" ");
534
- }
535
- function quoteShellArg(arg) {
536
- if (arg.length === 0) return "''";
537
- if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)) return arg;
538
- return "'" + arg.replace(/'/g, "'\\''") + "'";
539
- }
540
- function bashScript(body) {
541
- return `bash -c ${quoteShellArg(body)}`;
542
- }
543
675
  var REMOTE_UP_TAR = "/tmp/agentbox-cp-up.tar.gz";
544
676
  var REMOTE_DOWN_TAR = "/tmp/agentbox-cp-down.tar.gz";
545
677
  async function uploadToCloudBox(backend, handle, hostSrc, boxDst) {
@@ -557,10 +689,10 @@ async function uploadToCloudBox(backend, handle, hostSrc, boxDst) {
557
689
  finalName = posix.basename(boxDst);
558
690
  }
559
691
  const finalPath = boxParent === "/" ? `/${finalName}` : `${boxParent}/${finalName}`;
560
- const stage = await mkdtemp3(hostJoin(tmpdir3(), "agentbox-cp-up-"));
692
+ const stage = await mkdtemp4(hostJoin(tmpdir4(), "agentbox-cp-up-"));
561
693
  const localTar = hostJoin(stage, "payload.tar.gz");
562
694
  try {
563
- await execa3("tar", ["-C", srcParent, "-czf", localTar, srcBasename], {
695
+ await execa4("tar", ["-C", srcParent, "-czf", localTar, srcBasename], {
564
696
  env: { ...process.env, COPYFILE_DISABLE: "1" }
565
697
  });
566
698
  await backend.uploadFile(handle, localTar, REMOTE_UP_TAR);
@@ -586,14 +718,14 @@ async function uploadToCloudBox(backend, handle, hostSrc, boxDst) {
586
718
  throw new Error(`cloud upload extract failed: ${r.stderr || r.stdout}`);
587
719
  }
588
720
  } finally {
589
- await rm4(stage, { recursive: true, force: true });
721
+ await rm5(stage, { recursive: true, force: true });
590
722
  }
591
723
  return { finalPath };
592
724
  }
593
725
  async function pullCloudDirContents(backend, handle, boxSrcDir, hostDstDir) {
594
726
  const dstAbs = hostResolve(hostDstDir);
595
727
  mkdirSync(dstAbs, { recursive: true });
596
- const stage = await mkdtemp3(hostJoin(tmpdir3(), "agentbox-pull-"));
728
+ const stage = await mkdtemp4(hostJoin(tmpdir4(), "agentbox-pull-"));
597
729
  const localTar = hostJoin(stage, "payload.tar.gz");
598
730
  try {
599
731
  const packScript = [
@@ -606,11 +738,11 @@ async function pullCloudDirContents(backend, handle, boxSrcDir, hostDstDir) {
606
738
  throw new Error(`cloud workspace pack failed: ${r.stderr || r.stdout}`);
607
739
  }
608
740
  await backend.downloadFile(handle, REMOTE_DOWN_TAR, localTar);
609
- await execa3("tar", ["-xzf", localTar, "-C", dstAbs]);
741
+ await execa4("tar", ["-xzf", localTar, "-C", dstAbs]);
610
742
  await backend.exec(handle, `rm -f ${quoteShellArg(REMOTE_DOWN_TAR)}`).catch(() => {
611
743
  });
612
744
  } finally {
613
- await rm4(stage, { recursive: true, force: true });
745
+ await rm5(stage, { recursive: true, force: true });
614
746
  }
615
747
  return { finalPath: dstAbs };
616
748
  }
@@ -630,7 +762,7 @@ async function downloadFromCloudBox(backend, handle, boxSrc, hostDst) {
630
762
  }
631
763
  mkdirSync(hostParent, { recursive: true });
632
764
  const finalPath = hostJoin(hostParent, finalName);
633
- const stage = await mkdtemp3(hostJoin(tmpdir3(), "agentbox-cp-down-"));
765
+ const stage = await mkdtemp4(hostJoin(tmpdir4(), "agentbox-cp-down-"));
634
766
  const localTar = hostJoin(stage, "payload.tar.gz");
635
767
  try {
636
768
  const packScript = [
@@ -643,14 +775,14 @@ async function downloadFromCloudBox(backend, handle, boxSrc, hostDst) {
643
775
  throw new Error(`cloud download pack failed: ${r.stderr || r.stdout}`);
644
776
  }
645
777
  await backend.downloadFile(handle, REMOTE_DOWN_TAR, localTar);
646
- await execa3("tar", ["-xzf", localTar, "-C", hostParent]);
778
+ await execa4("tar", ["-xzf", localTar, "-C", hostParent]);
647
779
  if (finalName !== srcBasename) {
648
780
  renameSync(hostJoin(hostParent, srcBasename), finalPath);
649
781
  }
650
782
  await backend.exec(handle, `rm -f ${quoteShellArg(REMOTE_DOWN_TAR)}`).catch(() => {
651
783
  });
652
784
  } finally {
653
- await rm4(stage, { recursive: true, force: true });
785
+ await rm5(stage, { recursive: true, force: true });
654
786
  }
655
787
  return { finalPath };
656
788
  }
@@ -785,16 +917,16 @@ var LARGE_BUNDLE_THRESHOLD_BYTES = 20 * 1024 * 1024;
785
917
  async function seedFromGitClone(args) {
786
918
  const log = args.onLog ?? (() => {
787
919
  });
788
- const stage = await mkdtemp4(join5(tmpdir4(), "agentbox-clone-"));
789
- const cloneDir = join5(stage, "clone");
790
- const tarPath = join5(stage, "workspace.tar.gz");
791
- const untrackedTarPath = join5(stage, "untracked.tar.gz");
920
+ const stage = await mkdtemp5(join6(tmpdir5(), "agentbox-clone-"));
921
+ const cloneDir = join6(stage, "clone");
922
+ const tarPath = join6(stage, "workspace.tar.gz");
923
+ const untrackedTarPath = join6(stage, "untracked.tar.gz");
792
924
  const stashSha = args.useBranch ? null : await safeStashCreate(args.hostRepo);
793
925
  const untrackedSize = args.useBranch ? 0 : await maybeBuildUntrackedTar(args.hostRepo, untrackedTarPath);
794
926
  let stashRefCreated = false;
795
927
  try {
796
928
  if (stashSha) {
797
- const ref = await execa4(
929
+ const ref = await execa5(
798
930
  "git",
799
931
  ["-C", args.hostRepo, "update-ref", STASH_CARRYOVER_REF, stashSha],
800
932
  { reject: false }
@@ -817,8 +949,8 @@ async function seedFromGitClone(args) {
817
949
  log(
818
950
  `clone tar exceeded ${String(LARGE_BUNDLE_THRESHOLD_BYTES / (1024 * 1024))} MB at depth ${String(DEFAULT_BUNDLE_DEPTH)} (${mb} MB), rebuilding at depth ${String(LARGE_BUNDLE_DEPTH)}`
819
951
  );
820
- await rm5(cloneDir, { recursive: true, force: true });
821
- await rm5(tarPath, { force: true });
952
+ await rm6(cloneDir, { recursive: true, force: true });
953
+ await rm6(tarPath, { force: true });
822
954
  await runShallowClone(args.hostRepo, cloneDir, LARGE_BUNDLE_DEPTH, stashRefCreated, cloneBranch);
823
955
  await tarCloneDir(cloneDir, tarPath);
824
956
  }
@@ -869,11 +1001,11 @@ async function seedFromGitClone(args) {
869
1001
  }
870
1002
  } finally {
871
1003
  if (stashRefCreated) {
872
- await execa4("git", ["-C", args.hostRepo, "update-ref", "-d", STASH_CARRYOVER_REF], {
1004
+ await execa5("git", ["-C", args.hostRepo, "update-ref", "-d", STASH_CARRYOVER_REF], {
873
1005
  reject: false
874
1006
  });
875
1007
  }
876
- await rm5(stage, { recursive: true, force: true });
1008
+ await rm6(stage, { recursive: true, force: true });
877
1009
  }
878
1010
  }
879
1011
  async function runShallowClone(hostRepo, cloneDir, depth, includeStashRef, fromBranch) {
@@ -881,7 +1013,7 @@ async function runShallowClone(hostRepo, cloneDir, depth, includeStashRef, fromB
881
1013
  if (depth !== null) cloneArgs.push(`--depth=${String(depth)}`);
882
1014
  if (fromBranch) cloneArgs.push("--branch", fromBranch);
883
1015
  cloneArgs.push(`file://${hostRepo}`, cloneDir);
884
- await execa4("git", cloneArgs);
1016
+ await execa5("git", cloneArgs);
885
1017
  if (includeStashRef) {
886
1018
  const fetchArgs = ["-C", cloneDir, "fetch", "--quiet"];
887
1019
  if (depth !== null) fetchArgs.push(`--depth=${String(depth)}`);
@@ -889,11 +1021,11 @@ async function runShallowClone(hostRepo, cloneDir, depth, includeStashRef, fromB
889
1021
  `file://${hostRepo}`,
890
1022
  `+${STASH_CARRYOVER_REF}:refs/remotes/origin/agentbox-carryover/stash`
891
1023
  );
892
- await execa4("git", fetchArgs, { reject: false });
1024
+ await execa5("git", fetchArgs, { reject: false });
893
1025
  }
894
1026
  }
895
1027
  async function tarCloneDir(cloneDir, outPath) {
896
- await execa4("tar", ["-C", cloneDir, "-czf", outPath, "."], {
1028
+ await execa5("tar", ["-C", cloneDir, "-czf", outPath, "."], {
897
1029
  env: { ...process.env, COPYFILE_DISABLE: "1" }
898
1030
  });
899
1031
  }
@@ -905,19 +1037,19 @@ async function safeFileSize(path) {
905
1037
  }
906
1038
  }
907
1039
  async function safeStashCreate(hostRepo) {
908
- const r = await execa4("git", ["-C", hostRepo, "stash", "create"], { reject: false });
1040
+ const r = await execa5("git", ["-C", hostRepo, "stash", "create"], { reject: false });
909
1041
  if (r.exitCode !== 0) return null;
910
1042
  const sha = r.stdout.trim();
911
1043
  return sha.length > 0 ? sha : null;
912
1044
  }
913
1045
  async function maybeBuildUntrackedTar(hostRepo, outPath) {
914
- const list = await execa4(
1046
+ const list = await execa5(
915
1047
  "git",
916
1048
  ["-C", hostRepo, "ls-files", "--others", "--exclude-standard", "-z"],
917
1049
  { reject: false }
918
1050
  );
919
1051
  if (list.exitCode !== 0 || list.stdout.length === 0) return 0;
920
- const tar = await execa4(
1052
+ const tar = await execa5(
921
1053
  "tar",
922
1054
  ["-C", hostRepo, "--null", "-T", "-", "-czf", outPath],
923
1055
  {
@@ -936,16 +1068,16 @@ async function maybeBuildUntrackedTar(hostRepo, outPath) {
936
1068
  }
937
1069
  }
938
1070
  async function readOriginUrl(hostRepo) {
939
- const r = await execa4("git", ["-C", hostRepo, "remote", "get-url", "origin"], { reject: false });
1071
+ const r = await execa5("git", ["-C", hostRepo, "remote", "get-url", "origin"], { reject: false });
940
1072
  if (r.exitCode !== 0) return null;
941
1073
  const out = (r.stdout ?? "").trim();
942
1074
  return out.length > 0 ? out : null;
943
1075
  }
944
1076
  async function seedFromTar(args) {
945
- const stage = await mkdtemp4(join5(tmpdir4(), "agentbox-tar-"));
946
- const tarPath = join5(stage, "workspace.tar.gz");
1077
+ const stage = await mkdtemp5(join6(tmpdir5(), "agentbox-tar-"));
1078
+ const tarPath = join6(stage, "workspace.tar.gz");
947
1079
  try {
948
- await execa4("tar", ["-C", args.hostDir, "-czf", tarPath, "."]);
1080
+ await execa5("tar", ["-C", args.hostDir, "-czf", tarPath, "."]);
949
1081
  const remoteTar = "/tmp/agentbox-workspace.tar.gz";
950
1082
  await args.backend.uploadFile(args.handle, tarPath, remoteTar);
951
1083
  const SUDO = `if command -v sudo >/dev/null 2>&1; then SUDO='sudo -n'; else SUDO=''; fi`;
@@ -969,7 +1101,7 @@ async function seedFromTar(args) {
969
1101
  throw new Error(`workspace seed (tar) failed: ${r.stderr || r.stdout}`);
970
1102
  }
971
1103
  } finally {
972
- await rm5(stage, { recursive: true, force: true });
1104
+ await rm6(stage, { recursive: true, force: true });
973
1105
  }
974
1106
  }
975
1107
  var CLOUD_WORKSPACE_DIR = "/workspace";
@@ -1220,17 +1352,25 @@ function createCloudProvider(backend, opts = {}) {
1220
1352
  const timeoutMs = typeof timeoutOverride === "number" && timeoutOverride > 0 ? timeoutOverride : void 0;
1221
1353
  const networkPolicyOpt = req.providerOptions?.["networkPolicy"];
1222
1354
  const networkPolicy = typeof networkPolicyOpt === "string" && networkPolicyOpt.trim() !== "" ? networkPolicyOpt.trim() : void 0;
1355
+ const sizeOpt = req.providerOptions?.["size"];
1356
+ const size = typeof sizeOpt === "string" && sizeOpt.trim() !== "" ? sizeOpt.trim() : void 0;
1223
1357
  const relayToken = generateRelayToken();
1224
1358
  const bridgeToken = generateRelayToken();
1225
1359
  try {
1226
1360
  await ensureRelay({ onLog: log });
1227
1361
  } catch (err) {
1228
- log(`relay ensure failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
1362
+ log(
1363
+ `relay ensure failed (continuing): ${err instanceof Error ? err.message : String(err)}`
1364
+ );
1229
1365
  }
1230
1366
  let snapshotName;
1231
1367
  let resolvedCheckpointRef;
1232
1368
  if (req.checkpointRef && req.projectRoot) {
1233
- const found = await resolveCloudCheckpoint(req.projectRoot, backend.name, req.checkpointRef);
1369
+ const found = await resolveCloudCheckpoint(
1370
+ req.projectRoot,
1371
+ backend.name,
1372
+ req.checkpointRef
1373
+ );
1234
1374
  if (found) {
1235
1375
  snapshotName = found.manifest.snapshotName;
1236
1376
  resolvedCheckpointRef = found.name;
@@ -1264,6 +1404,7 @@ function createCloudProvider(backend, opts = {}) {
1264
1404
  image,
1265
1405
  snapshot,
1266
1406
  resources,
1407
+ size,
1267
1408
  timeoutMs,
1268
1409
  exposePorts: exposeServicePorts,
1269
1410
  networkPolicy,
@@ -1317,6 +1458,8 @@ function createCloudProvider(backend, opts = {}) {
1317
1458
  });
1318
1459
  }
1319
1460
  await seedOpencodeModelState(backend, handle, { onLog: log });
1461
+ await seedDynamicConfig(backend, handle, { workspacePath: req.workspacePath, onLog: log });
1462
+ await seedGitIdentity(backend, handle, { hostRepo: req.workspacePath, onLog: log });
1320
1463
  if (req.envFilesToImport && req.envFilesToImport.length > 0) {
1321
1464
  const { copied } = await uploadEnvFiles({
1322
1465
  backend,
@@ -1358,9 +1501,12 @@ function createCloudProvider(backend, opts = {}) {
1358
1501
  log("launching in-box dockerd");
1359
1502
  try {
1360
1503
  const dockerd = await launchCloudDockerdDaemon({ backend, handle, timeoutMs: 6e4 });
1361
- if (!dockerd.up) log(`dockerd did not become ready (continuing): ${dockerd.reason ?? "unknown"}`);
1504
+ if (!dockerd.up)
1505
+ log(`dockerd did not become ready (continuing): ${dockerd.reason ?? "unknown"}`);
1362
1506
  } catch (err) {
1363
- log(`dockerd daemon launch failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
1507
+ log(
1508
+ `dockerd daemon launch failed (continuing): ${err instanceof Error ? err.message : String(err)}`
1509
+ );
1364
1510
  }
1365
1511
  }
1366
1512
  const vncEnabled = req.vnc?.enabled !== false;
@@ -1719,7 +1865,10 @@ function makeCloudCheckpoint(backend) {
1719
1865
  const info = await writeCloudCheckpointManifest(box.projectRoot, backend.name, name, {
1720
1866
  snapshotName,
1721
1867
  sourceBoxId: box.id,
1722
- sourceBoxName: box.name
1868
+ sourceBoxName: box.name,
1869
+ baseProvider: backend.name,
1870
+ baseFingerprint: currentCloudBaseFingerprint(backend.name),
1871
+ cliVersion: readCliStamp().cliVersion
1723
1872
  });
1724
1873
  return { ref: info.name };
1725
1874
  },
@@ -1797,11 +1946,13 @@ export {
1797
1946
  seedAgentVolumesIfFresh,
1798
1947
  agentSpecsForCloud,
1799
1948
  listCloudCheckpoints,
1949
+ listAllCloudCheckpoints,
1800
1950
  resolveCloudCheckpoint,
1801
1951
  writeCloudCheckpointManifest,
1952
+ currentCloudBaseFingerprint,
1802
1953
  removeCloudCheckpointDir,
1803
1954
  probeCloudCheckpoint,
1804
1955
  createCloudProvider,
1805
1956
  renderInnerCommand
1806
1957
  };
1807
- //# sourceMappingURL=chunk-MXXXKJYS.js.map
1958
+ //# sourceMappingURL=chunk-DHJ7OMIP.js.map