@madarco/agentbox 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/README.md +161 -0
  3. package/dist/{_cloud-attach-ZXBCNWJX.js → _cloud-attach-O6NYTLES.js} +3 -3
  4. package/dist/{chunk-BXQMIEHC.js → chunk-2GPORKYF.js} +254 -162
  5. package/dist/chunk-2GPORKYF.js.map +1 -0
  6. package/dist/{chunk-NCJP5MTN.js → chunk-7UIAO7PC.js} +213 -51
  7. package/dist/chunk-7UIAO7PC.js.map +1 -0
  8. package/dist/{chunk-GU5LW4B5.js → chunk-R4O5WPHW.js} +374 -62
  9. package/dist/chunk-R4O5WPHW.js.map +1 -0
  10. package/dist/{dist-GDHP34ZK.js → dist-5FQGYRW5.js} +15 -3
  11. package/dist/dist-5FQGYRW5.js.map +1 -0
  12. package/dist/{dist-32EZBYG4.js → dist-BQNX7RQE.js} +12 -2
  13. package/dist/{dist-XML54CNB.js → dist-PZW3GWWU.js} +30 -5
  14. package/dist/dist-PZW3GWWU.js.map +1 -0
  15. package/dist/{dist-CX5CGVEB.js → dist-TMHSUVTP.js} +3 -3
  16. package/dist/index.js +1773 -526
  17. package/dist/index.js.map +1 -1
  18. package/package.json +9 -7
  19. package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +9 -8
  20. package/runtime/docker/packages/ctl/dist/bin.cjs +32 -3
  21. package/runtime/hetzner/agentbox-setup-skill.md +9 -8
  22. package/runtime/hetzner/ctl.cjs +32 -3
  23. package/runtime/relay/bin.cjs +32 -3
  24. package/runtime/vercel/agentbox-setup-skill.md +9 -8
  25. package/runtime/vercel/ctl.cjs +32 -3
  26. package/runtime/vercel/custom-system-CLAUDE.md +1 -4
  27. package/runtime/vercel/scripts/provision.sh +40 -0
  28. package/share/agentbox-setup/SKILL.md +9 -8
  29. package/dist/chunk-BXQMIEHC.js.map +0 -1
  30. package/dist/chunk-GU5LW4B5.js.map +0 -1
  31. package/dist/chunk-NCJP5MTN.js.map +0 -1
  32. package/dist/dist-GDHP34ZK.js.map +0 -1
  33. package/dist/dist-XML54CNB.js.map +0 -1
  34. /package/dist/{_cloud-attach-ZXBCNWJX.js.map → _cloud-attach-O6NYTLES.js.map} +0 -0
  35. /package/dist/{dist-32EZBYG4.js.map → dist-BQNX7RQE.js.map} +0 -0
  36. /package/dist/{dist-CX5CGVEB.js.map → dist-TMHSUVTP.js.map} +0 -0
@@ -25,7 +25,7 @@ import {
25
25
  import { randomBytes as randomBytes3 } from "crypto";
26
26
  import { mkdir as mkdir7, stat as stat6 } from "fs/promises";
27
27
  import { homedir as homedir9 } from "os";
28
- import { basename as basename2, join as join10, resolve as resolve3 } from "path";
28
+ import { basename as basename3, join as join10, resolve as resolve3 } from "path";
29
29
  import { execa as execa13 } from "execa";
30
30
 
31
31
  // ../../packages/ctl/dist/index.js
@@ -758,10 +758,12 @@ var BUILT_IN_DEFAULTS = {
758
758
  maxLayers: 3
759
759
  },
760
760
  claude: {
761
- sessionName: "claude"
761
+ sessionName: "claude",
762
+ dangerouslySkipPermissions: true
762
763
  },
763
764
  codex: {
764
- sessionName: "codex"
765
+ sessionName: "codex",
766
+ dangerouslySkipPermissions: true
765
767
  },
766
768
  opencode: {
767
769
  sessionName: "opencode"
@@ -949,11 +951,21 @@ var KEY_REGISTRY = [
949
951
  type: "string",
950
952
  description: "tmux session name for `agentbox claude`."
951
953
  },
954
+ {
955
+ key: "claude.dangerouslySkipPermissions",
956
+ type: "bool",
957
+ description: "Launch claude in new boxes with --dangerously-skip-permissions (auto-accept tool use). Safe because boxes are isolated; on by default. Override per-box with --no-dangerously-skip-permissions."
958
+ },
952
959
  {
953
960
  key: "codex.sessionName",
954
961
  type: "string",
955
962
  description: "tmux session name for `agentbox codex`."
956
963
  },
964
+ {
965
+ key: "codex.dangerouslySkipPermissions",
966
+ type: "bool",
967
+ description: "Launch codex in new boxes with --dangerously-bypass-approvals-and-sandbox (never prompt for approval). Safe because boxes are isolated; on by default. Override per-box with --no-dangerously-skip-permissions."
968
+ },
957
969
  {
958
970
  key: "opencode.sessionName",
959
971
  type: "string",
@@ -1637,7 +1649,7 @@ async function touchProjectMeta(absPath) {
1637
1649
 
1638
1650
  // ../../packages/sandbox-docker/dist/index.js
1639
1651
  import { chmod, mkdir as mkdir32, readFile as readFile32 } from "fs/promises";
1640
- import { join as join32 } from "path";
1652
+ import { basename as basename2, join as join32 } from "path";
1641
1653
  import { execa as execa4 } from "execa";
1642
1654
  import { spawnSync as spawnSync2 } from "child_process";
1643
1655
  import { stat as stat22 } from "fs/promises";
@@ -1662,7 +1674,7 @@ import { homedir as homedir6, platform } from "os";
1662
1674
  import { join as join7, resolve as resolve2 } from "path";
1663
1675
  import { mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile5, readdir as readdir32, rm as rm3, writeFile as writeFile22 } from "fs/promises";
1664
1676
  import { homedir as homedir7, tmpdir as tmpdir2 } from "os";
1665
- import { basename as basename3, join as join8 } from "path";
1677
+ import { basename as basename22, join as join8 } from "path";
1666
1678
  import { execa as execa10 } from "execa";
1667
1679
  import { stat as stat5 } from "fs/promises";
1668
1680
  import { execa as execa11 } from "execa";
@@ -1670,10 +1682,11 @@ import { execa as execa12 } from "execa";
1670
1682
  import { spawn } from "child_process";
1671
1683
  import { randomBytes as randomBytes22 } from "crypto";
1672
1684
  import { existsSync as existsSync2, openSync } from "fs";
1673
- import { mkdir as mkdir6, readFile as readFile6, unlink as unlink2, writeFile as writeFile32 } from "fs/promises";
1685
+ import { cp, mkdir as mkdir6, readFile as readFile6, readdir as readdir4, rename as rename3, rm as rm4, unlink as unlink2, writeFile as writeFile32 } from "fs/promises";
1674
1686
  import { request as httpRequest } from "http";
1687
+ import { createRequire } from "module";
1675
1688
  import { homedir as homedir8 } from "os";
1676
- import { dirname as dirname3, join as join9, resolve as resolve22 } from "path";
1689
+ import { dirname as dirname3, join as join9, resolve as resolve22, sep } from "path";
1677
1690
  import { setTimeout as delay2 } from "timers/promises";
1678
1691
  import { fileURLToPath } from "url";
1679
1692
 
@@ -1864,7 +1877,7 @@ function queueLogPath(id) {
1864
1877
 
1865
1878
  // ../../packages/sandbox-docker/dist/index.js
1866
1879
  import { execa as execa15 } from "execa";
1867
- import { readdir as readdir4, rm as rm4, stat as stat7 } from "fs/promises";
1880
+ import { readdir as readdir5, rm as rm5, stat as stat7 } from "fs/promises";
1868
1881
  import { join as join12 } from "path";
1869
1882
 
1870
1883
  // ../../packages/core/dist/index.js
@@ -1925,11 +1938,11 @@ import { homedir as homedir10 } from "os";
1925
1938
  import { join as join13 } from "path";
1926
1939
  import { execa as execa16 } from "execa";
1927
1940
  import { existsSync as existsSync3, mkdirSync, renameSync, statSync } from "fs";
1928
- import { basename as basename32, dirname as dirname22, posix, resolve as resolve4 } from "path";
1941
+ import { basename as basename4, dirname as dirname22, posix, resolve as resolve4 } from "path";
1929
1942
  import { execa as execa17 } from "execa";
1930
- import { copyFile, mkdtemp as mkdtemp3, readdir as readdir5, readFile as readFile7, rm as rm5, stat as stat8, writeFile as writeFile4 } from "fs/promises";
1943
+ import { copyFile, mkdtemp as mkdtemp3, readdir as readdir6, readFile as readFile7, rm as rm6, stat as stat8, writeFile as writeFile4 } from "fs/promises";
1931
1944
  import { homedir as homedir11, tmpdir as tmpdir3 } from "os";
1932
- import { basename as basename4, join as join14, relative as relative2 } from "path";
1945
+ import { basename as basename5, join as join14, relative as relative2 } from "path";
1933
1946
  import { execa as execa18 } from "execa";
1934
1947
  function isHostPathHookCommand(command, hostHome) {
1935
1948
  if (typeof command !== "string" || command.length === 0) return false;
@@ -2728,13 +2741,13 @@ async function copyOneEntry(container, entry) {
2728
2741
  throw new Error(`mkdir -p ${parentDir} failed: ${String(mkdir8.stderr).slice(0, 300)}`);
2729
2742
  }
2730
2743
  if (entry.kind === "file") {
2731
- const cp = await execa22(
2744
+ const cp2 = await execa22(
2732
2745
  "docker",
2733
2746
  ["cp", entry.absSrc, `${container}:${boxDest}`],
2734
2747
  { reject: false }
2735
2748
  );
2736
- if (cp.exitCode !== 0) {
2737
- throw new Error(`docker cp failed: ${String(cp.stderr).slice(0, 300)}`);
2749
+ if (cp2.exitCode !== 0) {
2750
+ throw new Error(`docker cp failed: ${String(cp2.stderr).slice(0, 300)}`);
2738
2751
  }
2739
2752
  } else {
2740
2753
  const packed = await execa22(
@@ -3744,6 +3757,54 @@ function isRealAgentCredential(agent, text) {
3744
3757
  }
3745
3758
  return Object.keys(parsed).length > 0;
3746
3759
  }
3760
+ async function hostClaudeBackupExpired(path = CREDENTIALS_BACKUP_FILE, now = Date.now()) {
3761
+ try {
3762
+ const parsed = JSON.parse(await readFile32(path, "utf8"));
3763
+ const exp = parsed?.claudeAiOauth?.expiresAt;
3764
+ return typeof exp === "number" && Number.isFinite(exp) && exp < now;
3765
+ } catch {
3766
+ return false;
3767
+ }
3768
+ }
3769
+ function parseExtractResult(stdout) {
3770
+ return { copied: /\bCOPIED=yes\b/.test(stdout) };
3771
+ }
3772
+ async function extractVolumeAuthToBackup(opts) {
3773
+ try {
3774
+ await mkdir32(STATE_DIR, { recursive: true });
3775
+ const script = 'COPIED=no; if [ -s /dst/auth.json ]; then cp -a /dst/auth.json "/host-state/$DEST" && COPIED=yes; fi; echo "COPIED=$COPIED"';
3776
+ const { stdout } = await execa4("docker", [
3777
+ "run",
3778
+ "--rm",
3779
+ "--user",
3780
+ "0",
3781
+ "-v",
3782
+ `${opts.volume}:/dst`,
3783
+ "-v",
3784
+ `${STATE_DIR}:/host-state`,
3785
+ "-e",
3786
+ // Pass the destination filename via env so the path isn't interpolated
3787
+ // into the script string (keeps the docker arg list static + injection-safe).
3788
+ `DEST=${basename2(opts.backupFile)}`,
3789
+ opts.image,
3790
+ "sh",
3791
+ "-c",
3792
+ script
3793
+ ]);
3794
+ const result = parseExtractResult(stdout);
3795
+ if (result.copied) await chmod(opts.backupFile, 384).catch(() => {
3796
+ });
3797
+ return result;
3798
+ } catch {
3799
+ return { copied: false };
3800
+ }
3801
+ }
3802
+ function extractCodexCredentials(volume, image) {
3803
+ return extractVolumeAuthToBackup({ volume, image, backupFile: CODEX_CREDENTIALS_BACKUP_FILE });
3804
+ }
3805
+ function extractOpencodeCredentials(volume, image) {
3806
+ return extractVolumeAuthToBackup({ volume, image, backupFile: OPENCODE_CREDENTIALS_BACKUP_FILE });
3807
+ }
3747
3808
  async function hostBackupHasCredentials(path = CREDENTIALS_BACKUP_FILE) {
3748
3809
  try {
3749
3810
  const parsed = JSON.parse(await readFile32(path, "utf8"));
@@ -4998,7 +5059,7 @@ async function createSnapshot(opts) {
4998
5059
  var CHECKPOINTS_ROOT = join8(homedir7(), ".agentbox", "checkpoints");
4999
5060
  var CHECKPOINT_IMAGE_PREFIX = "agentbox-ckpt-";
5000
5061
  function checkpointImageTag(projectRoot, name) {
5001
- const mnemonic = sanitizeMnemonic(basename3(projectRoot));
5062
+ const mnemonic = sanitizeMnemonic(basename22(projectRoot));
5002
5063
  return `${CHECKPOINT_IMAGE_PREFIX}${hashProjectPath(projectRoot)}_${mnemonic}:${name}`;
5003
5064
  }
5004
5065
  function projectCheckpointsDir(projectRoot) {
@@ -5348,6 +5409,7 @@ async function ensureHomeOwnedByVscode(container) {
5348
5409
  var STATE_DIR22 = join9(homedir8(), ".agentbox");
5349
5410
  var PID_FILE = join9(STATE_DIR22, "relay.pid");
5350
5411
  var LOG_FILE = join9(STATE_DIR22, "relay.log");
5412
+ var RELAY_HOME_DIR = join9(STATE_DIR22, "relay");
5351
5413
  var PORT = DEFAULT_RELAY_PORT;
5352
5414
  var ENDPOINT = {
5353
5415
  // host.docker.internal is the Docker Desktop / OrbStack-supplied alias for
@@ -5358,6 +5420,13 @@ var ENDPOINT = {
5358
5420
  hostUrl: `http://127.0.0.1:${String(PORT)}`,
5359
5421
  port: PORT
5360
5422
  };
5423
+ function shouldReclaimForVersion(health, currentVersion) {
5424
+ if (health.cliEntry === false) return true;
5425
+ if (typeof health.version === "string" && health.version.length > 0 && typeof currentVersion === "string" && currentVersion.length > 0 && health.version !== currentVersion) {
5426
+ return true;
5427
+ }
5428
+ return false;
5429
+ }
5361
5430
  async function ensureRelay(opts = {}) {
5362
5431
  const log = opts.onLog ?? (() => {
5363
5432
  });
@@ -5366,12 +5435,19 @@ async function ensureRelay(opts = {}) {
5366
5435
  await removeContainer(RELAY_CONTAINER_NAME);
5367
5436
  log(`removed legacy relay container ${RELAY_CONTAINER_NAME}`);
5368
5437
  }
5438
+ const currentVersion = process.env.AGENTBOX_CLI_VERSION;
5369
5439
  const health = await fetchHealthz(500);
5370
5440
  if (health !== null) {
5371
- if (health.cliEntry !== false) {
5441
+ if (!shouldReclaimForVersion(health, currentVersion)) {
5372
5442
  return ENDPOINT;
5373
5443
  }
5374
- log("relay is alive but lacks AGENTBOX_CLI_ENTRY (cp/download/checkpoint would fail) \u2014 reclaiming");
5444
+ if (health.cliEntry === false) {
5445
+ log("relay is alive but lacks AGENTBOX_CLI_ENTRY (cp/download/checkpoint would fail) \u2014 reclaiming");
5446
+ } else {
5447
+ log(
5448
+ `relay was spawned by agentbox ${health.version ?? "?"} but this CLI is ${currentVersion ?? "?"} \u2014 reclaiming to keep the relay version-consistent`
5449
+ );
5450
+ }
5375
5451
  await reclaimRelay(health.pid, log);
5376
5452
  } else {
5377
5453
  const existingPid = await readPidFile();
@@ -5388,8 +5464,9 @@ async function ensureRelay(opts = {}) {
5388
5464
  });
5389
5465
  }
5390
5466
  }
5391
- const relayBin = resolveRelayBin();
5392
- const cliEntry = resolveCliEntry();
5467
+ const staged = await stageRelayHome(currentVersion ?? "", log).catch(() => null);
5468
+ const relayBin = staged?.relayBin ?? resolveRelayBin();
5469
+ const cliEntry = staged?.cliEntry ?? resolveCliEntry();
5393
5470
  if (cliEntry === null) {
5394
5471
  throw new Error(
5395
5472
  "cannot start the host relay: agentbox CLI entry not found (is the build complete / dist present?). Set AGENTBOX_CLI_ENTRY to override."
@@ -5411,7 +5488,7 @@ async function reclaimRelay(reportedPid, log) {
5411
5488
  });
5412
5489
  if (await pingHealthz(300)) {
5413
5490
  throw new Error(
5414
- `a relay without AGENTBOX_CLI_ENTRY is still listening on :${String(PORT)} and could not be stopped (reported pid ${String(reportedPid ?? "unknown")}); kill it manually and retry`
5491
+ `a relay is still listening on :${String(PORT)} and could not be stopped (reported pid ${String(reportedPid ?? "unknown")}); kill it manually and retry`
5415
5492
  );
5416
5493
  }
5417
5494
  }
@@ -5494,6 +5571,80 @@ function resolveCliEntry() {
5494
5571
  }
5495
5572
  return null;
5496
5573
  }
5574
+ async function stageRelayHome(version, log) {
5575
+ if (!version || version === "0.0.0-dev") return null;
5576
+ if (process.env.AGENTBOX_RELAY_BIN || process.env.AGENTBOX_CLI_ENTRY) return null;
5577
+ const cliRoot = findCliRoot(dirname3(fileURLToPath(import.meta.url)));
5578
+ if (cliRoot === null) return null;
5579
+ const homeDir = join9(RELAY_HOME_DIR, version);
5580
+ const stagedEntry = join9(homeDir, "dist", "index.js");
5581
+ const stagedBin = join9(homeDir, "runtime", "relay", "bin.cjs");
5582
+ if (existsSync2(stagedEntry) && existsSync2(stagedBin)) {
5583
+ return { relayBin: stagedBin, cliEntry: stagedEntry };
5584
+ }
5585
+ const nodeModules = resolveDepRoot(join9(cliRoot, "dist", "index.js"));
5586
+ if (nodeModules === null) return null;
5587
+ const tmpDir = `${homeDir}.tmp-${String(process.pid)}`;
5588
+ try {
5589
+ await mkdir6(RELAY_HOME_DIR, { recursive: true });
5590
+ await rm4(tmpDir, { recursive: true, force: true });
5591
+ await mkdir6(tmpDir, { recursive: true });
5592
+ for (const sub of ["dist", "runtime", "share"]) {
5593
+ const src = join9(cliRoot, sub);
5594
+ if (existsSync2(src)) await cp(src, join9(tmpDir, sub), { recursive: true });
5595
+ }
5596
+ await cp(nodeModules, join9(tmpDir, "node_modules"), { recursive: true, dereference: true });
5597
+ await rm4(homeDir, { recursive: true, force: true });
5598
+ await rename3(tmpDir, homeDir);
5599
+ } catch (err) {
5600
+ await rm4(tmpDir, { recursive: true, force: true }).catch(() => {
5601
+ });
5602
+ if (existsSync2(stagedEntry) && existsSync2(stagedBin)) {
5603
+ return { relayBin: stagedBin, cliEntry: stagedEntry };
5604
+ }
5605
+ log(`relay home staging failed (${err instanceof Error ? err.message : String(err)}); using bundle paths`);
5606
+ return null;
5607
+ }
5608
+ log(`staged relay home for ${version} at ${homeDir}`);
5609
+ await gcOldRelayHomes(version).catch(() => {
5610
+ });
5611
+ return { relayBin: stagedBin, cliEntry: stagedEntry };
5612
+ }
5613
+ function findCliRoot(moduleDir) {
5614
+ for (const root of [resolve22(moduleDir, ".."), resolve22(moduleDir, "..", "..")]) {
5615
+ if (existsSync2(join9(root, "dist", "index.js")) && existsSync2(join9(root, "runtime", "relay", "bin.cjs"))) {
5616
+ return root;
5617
+ }
5618
+ }
5619
+ return null;
5620
+ }
5621
+ function resolveDepRoot(fromFile) {
5622
+ try {
5623
+ const req = createRequire(fromFile);
5624
+ const main = req.resolve("commander");
5625
+ if (main.includes(`${sep}.pnpm${sep}`)) return null;
5626
+ const marker = `${sep}node_modules${sep}`;
5627
+ const idx = main.lastIndexOf(marker);
5628
+ if (idx === -1) return null;
5629
+ const nm = main.slice(0, idx + marker.length - 1);
5630
+ return existsSync2(join9(nm, "commander")) ? nm : null;
5631
+ } catch {
5632
+ return null;
5633
+ }
5634
+ }
5635
+ async function gcOldRelayHomes(keepVersion) {
5636
+ let entries;
5637
+ try {
5638
+ entries = await readdir4(RELAY_HOME_DIR);
5639
+ } catch {
5640
+ return;
5641
+ }
5642
+ for (const name of entries) {
5643
+ if (name === keepVersion) continue;
5644
+ await rm4(join9(RELAY_HOME_DIR, name), { recursive: true, force: true }).catch(() => {
5645
+ });
5646
+ }
5647
+ }
5497
5648
  async function stopRelay() {
5498
5649
  const pid = await readPidFile();
5499
5650
  if (pid === null) {
@@ -5532,7 +5683,7 @@ async function getRelayStatus() {
5532
5683
  pidAlive: pidAlive2,
5533
5684
  port: PORT,
5534
5685
  endpoint: ENDPOINT,
5535
- health: health === null ? null : { boxes: health.boxes, events: health.events },
5686
+ health: health === null ? null : { boxes: health.boxes, events: health.events, version: health.version, commit: health.commit },
5536
5687
  pidFile: PID_FILE,
5537
5688
  logFile: LOG_FILE
5538
5689
  };
@@ -5577,7 +5728,9 @@ function fetchHealthz(timeoutMs) {
5577
5728
  boxes: parsed.boxes,
5578
5729
  events: parsed.events,
5579
5730
  pid: typeof parsed.pid === "number" ? parsed.pid : void 0,
5580
- cliEntry: typeof parsed.cliEntry === "boolean" ? parsed.cliEntry : void 0
5731
+ cliEntry: typeof parsed.cliEntry === "boolean" ? parsed.cliEntry : void 0,
5732
+ version: typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : void 0,
5733
+ commit: typeof parsed.commit === "string" && parsed.commit.length > 0 ? parsed.commit : void 0
5581
5734
  });
5582
5735
  } else {
5583
5736
  resolveP(null);
@@ -5930,7 +6083,7 @@ function generateBoxId() {
5930
6083
  return randomBytes3(4).toString("hex");
5931
6084
  }
5932
6085
  function sanitizeBasename(workspacePath) {
5933
- const raw = basename2(resolve3(workspacePath));
6086
+ const raw = basename3(resolve3(workspacePath));
5934
6087
  return raw.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^[-._]+|[-._]+$/g, "").slice(0, 30).replace(/[-._]+$/, "");
5935
6088
  }
5936
6089
  function defaultBoxName(workspacePath, id) {
@@ -6771,10 +6924,11 @@ async function listBoxes() {
6771
6924
  };
6772
6925
  return {
6773
6926
  ...b,
6774
- state: "running",
6927
+ state: b.cloud?.lastState ?? "running",
6775
6928
  endpoints: endpoints2,
6776
6929
  claudeActivity: persisted2?.claude.state,
6777
6930
  claudeSessionTitle: persisted2?.claude.sessionTitle,
6931
+ claudeQuestion: persisted2?.claude.state === "question" ? persisted2.claude.question : void 0,
6778
6932
  codexActivity: persisted2?.codex?.state,
6779
6933
  codexSessionTitle: persisted2?.codex?.sessionTitle,
6780
6934
  opencodeSessionTitle: persisted2?.opencode?.sessionTitle,
@@ -6795,6 +6949,7 @@ async function listBoxes() {
6795
6949
  endpoints,
6796
6950
  claudeActivity: persisted?.claude.state,
6797
6951
  claudeSessionTitle: persisted?.claude.sessionTitle,
6952
+ claudeQuestion: persisted?.claude.state === "question" ? persisted.claude.question : void 0,
6798
6953
  codexActivity: persisted?.codex?.state,
6799
6954
  codexSessionTitle: persisted?.codex?.sessionTitle,
6800
6955
  opencodeSessionTitle: persisted?.opencode?.sessionTitle,
@@ -7065,14 +7220,14 @@ async function destroyBox(idOrName, opts = {}) {
7065
7220
  let removedSnapshot = null;
7066
7221
  if (box.snapshotDir && !opts.keepSnapshot) {
7067
7222
  try {
7068
- await rm4(box.snapshotDir, { recursive: true, force: true });
7223
+ await rm5(box.snapshotDir, { recursive: true, force: true });
7069
7224
  removedSnapshot = box.snapshotDir;
7070
7225
  } catch {
7071
7226
  removedSnapshot = null;
7072
7227
  }
7073
7228
  }
7074
7229
  try {
7075
- await rm4(boxRunDirFor(box), { recursive: true, force: true });
7230
+ await rm5(boxRunDirFor(box), { recursive: true, force: true });
7076
7231
  } catch {
7077
7232
  }
7078
7233
  await removeBoxRecord(box.id);
@@ -7080,7 +7235,7 @@ async function destroyBox(idOrName, opts = {}) {
7080
7235
  }
7081
7236
  async function listSnapshotDirs() {
7082
7237
  try {
7083
- const entries = await readdir4(SNAPSHOTS_ROOT, { withFileTypes: true });
7238
+ const entries = await readdir5(SNAPSHOTS_ROOT, { withFileTypes: true });
7084
7239
  return entries.filter((e) => e.isDirectory()).map((e) => join12(SNAPSHOTS_ROOT, e.name));
7085
7240
  } catch {
7086
7241
  return [];
@@ -7088,7 +7243,7 @@ async function listSnapshotDirs() {
7088
7243
  }
7089
7244
  async function listBoxDirs() {
7090
7245
  try {
7091
- const entries = await readdir4(BOXES_ROOT, { withFileTypes: true });
7246
+ const entries = await readdir5(BOXES_ROOT, { withFileTypes: true });
7092
7247
  return entries.filter((e) => e.isDirectory()).map((e) => join12(BOXES_ROOT, e.name));
7093
7248
  } catch {
7094
7249
  return [];
@@ -7184,13 +7339,13 @@ async function pruneBoxes(opts = {}) {
7184
7339
  for (const v of orphanVolumes) await removeVolume(v);
7185
7340
  for (const d of orphanSnapshots) {
7186
7341
  try {
7187
- await rm4(d, { recursive: true, force: true });
7342
+ await rm5(d, { recursive: true, force: true });
7188
7343
  } catch {
7189
7344
  }
7190
7345
  }
7191
7346
  for (const d of orphanBoxDirs) {
7192
7347
  try {
7193
- await rm4(d, { recursive: true, force: true });
7348
+ await rm5(d, { recursive: true, force: true });
7194
7349
  } catch {
7195
7350
  }
7196
7351
  }
@@ -7455,7 +7610,7 @@ function asText(s) {
7455
7610
  async function uploadToBox(box, hostSrc, boxDst) {
7456
7611
  const srcAbs = resolve4(hostSrc);
7457
7612
  if (!existsSync3(srcAbs)) throw new Error(`source not found: ${hostSrc}`);
7458
- const srcBasename = basename32(srcAbs);
7613
+ const srcBasename = basename4(srcAbs);
7459
7614
  const srcParent = dirname22(srcAbs);
7460
7615
  let boxParent;
7461
7616
  let finalName;
@@ -7539,7 +7694,7 @@ async function downloadFromBox(box, boxSrc, hostDst) {
7539
7694
  finalName = srcBasename;
7540
7695
  } else {
7541
7696
  hostParent = dirname22(dstAbs);
7542
- finalName = basename32(dstAbs);
7697
+ finalName = basename4(dstAbs);
7543
7698
  }
7544
7699
  mkdirSync(hostParent, { recursive: true });
7545
7700
  const finalPath = posix.join(hostParent, finalName);
@@ -7708,7 +7863,7 @@ async function findBrokenSymlinks2(root) {
7708
7863
  async function walk(dir) {
7709
7864
  let entries;
7710
7865
  try {
7711
- entries = await readdir5(dir, { withFileTypes: true });
7866
+ entries = await readdir6(dir, { withFileTypes: true });
7712
7867
  } catch {
7713
7868
  return;
7714
7869
  }
@@ -7736,7 +7891,7 @@ function emptyResult(warnings = []) {
7736
7891
  }, warnings };
7737
7892
  }
7738
7893
  async function tarballFromDir(stageDir, agent) {
7739
- const tarballPath = join14(tmpdir3(), `agentbox-${agent}-${basename4(stageDir)}.tar.gz`);
7894
+ const tarballPath = join14(tmpdir3(), `agentbox-${agent}-${basename5(stageDir)}.tar.gz`);
7740
7895
  await execa18("tar", ["-czf", tarballPath, "-C", stageDir, "."], {
7741
7896
  env: { ...process.env, COPYFILE_DISABLE: "1" }
7742
7897
  });
@@ -7745,7 +7900,7 @@ async function tarballFromDir(stageDir, agent) {
7745
7900
  function makeCleanup(paths) {
7746
7901
  return async () => {
7747
7902
  for (const p of paths) {
7748
- await rm5(p, { recursive: true, force: true });
7903
+ await rm6(p, { recursive: true, force: true });
7749
7904
  }
7750
7905
  };
7751
7906
  }
@@ -7761,8 +7916,8 @@ async function stageSingleFileTarball(agent, sourcePath, tarballEntryName) {
7761
7916
  warnings: []
7762
7917
  };
7763
7918
  } catch (err) {
7764
- await rm5(stageDir, { recursive: true, force: true });
7765
- if (tarballPath) await rm5(tarballPath, { force: true });
7919
+ await rm6(stageDir, { recursive: true, force: true });
7920
+ if (tarballPath) await rm6(tarballPath, { force: true });
7766
7921
  throw err;
7767
7922
  }
7768
7923
  }
@@ -7845,7 +8000,7 @@ async function stageClaudeStaticForUpload(opts = {}) {
7845
8000
  const pluginsDir = join14(stageDir, "plugins");
7846
8001
  if (await pathExists7(pluginsDir)) {
7847
8002
  try {
7848
- const entries = await readdir5(pluginsDir, { withFileTypes: true });
8003
+ const entries = await readdir6(pluginsDir, { withFileTypes: true });
7849
8004
  for (const ent of entries) {
7850
8005
  if (!ent.isFile() || !ent.name.endsWith(".json")) continue;
7851
8006
  const file = join14(pluginsDir, ent.name);
@@ -7863,8 +8018,8 @@ async function stageClaudeStaticForUpload(opts = {}) {
7863
8018
  warnings: []
7864
8019
  };
7865
8020
  } catch (err) {
7866
- await rm5(stageDir, { recursive: true, force: true });
7867
- if (tarballPath) await rm5(tarballPath, { force: true });
8021
+ await rm6(stageDir, { recursive: true, force: true });
8022
+ if (tarballPath) await rm6(tarballPath, { force: true });
7868
8023
  throw err;
7869
8024
  }
7870
8025
  }
@@ -7924,16 +8079,17 @@ async function stageCodexStaticForUpload(opts = {}) {
7924
8079
  warnings: []
7925
8080
  };
7926
8081
  } catch (err) {
7927
- await rm5(stageDir, { recursive: true, force: true });
7928
- if (tarballPath) await rm5(tarballPath, { force: true });
8082
+ await rm6(stageDir, { recursive: true, force: true });
8083
+ if (tarballPath) await rm6(tarballPath, { force: true });
7929
8084
  throw err;
7930
8085
  }
7931
8086
  }
7932
8087
  async function stageCodexCredentialsForUpload(opts = {}) {
7933
- if (await pathExists7(CODEX_CREDENTIALS_BACKUP_FILE)) {
7934
- return stageSingleFileTarball("codex-creds", CODEX_CREDENTIALS_BACKUP_FILE, "auth.json");
7935
- }
7936
8088
  const hostHome = opts.hostHome ?? homedir11();
8089
+ const cloudBackup = join14(hostHome, ".agentbox", "codex-credentials.json");
8090
+ if (await pathExists7(cloudBackup)) {
8091
+ return stageSingleFileTarball("codex-creds", cloudBackup, "auth.json");
8092
+ }
7937
8093
  const hostAuth = join14(hostHome, ".codex", "auth.json");
7938
8094
  if (!await pathExists7(hostAuth)) return emptyResult([CODEX_KEYCHAIN_WARNING]);
7939
8095
  return stageSingleFileTarball("codex-creds", hostAuth, "auth.json");
@@ -7991,16 +8147,17 @@ async function stageOpencodeStaticForUpload(opts = {}) {
7991
8147
  warnings: []
7992
8148
  };
7993
8149
  } catch (err) {
7994
- await rm5(stageDir, { recursive: true, force: true });
7995
- if (tarballPath) await rm5(tarballPath, { force: true });
8150
+ await rm6(stageDir, { recursive: true, force: true });
8151
+ if (tarballPath) await rm6(tarballPath, { force: true });
7996
8152
  throw err;
7997
8153
  }
7998
8154
  }
7999
8155
  async function stageOpencodeCredentialsForUpload(opts = {}) {
8000
- if (await pathExists7(OPENCODE_CREDENTIALS_BACKUP_FILE)) {
8001
- return stageSingleFileTarball("opencode-creds", OPENCODE_CREDENTIALS_BACKUP_FILE, "auth.json");
8002
- }
8003
8156
  const hostHome = opts.hostHome ?? homedir11();
8157
+ const cloudBackup = join14(hostHome, ".agentbox", "opencode-credentials.json");
8158
+ if (await pathExists7(cloudBackup)) {
8159
+ return stageSingleFileTarball("opencode-creds", cloudBackup, "auth.json");
8160
+ }
8004
8161
  const hostAuth = join14(hostHome, ".local", "share", "opencode", "auth.json");
8005
8162
  if (!await pathExists7(hostAuth)) return emptyResult();
8006
8163
  return stageSingleFileTarball("opencode-creds", hostAuth, "auth.json");
@@ -8123,6 +8280,11 @@ export {
8123
8280
  CODEX_CREDENTIALS_BACKUP_FILE,
8124
8281
  OPENCODE_CREDENTIALS_BACKUP_FILE,
8125
8282
  isRealAgentCredential,
8283
+ hostClaudeBackupExpired,
8284
+ parseExtractResult,
8285
+ extractVolumeAuthToBackup,
8286
+ extractCodexCredentials,
8287
+ extractOpencodeCredentials,
8126
8288
  hostBackupHasCredentials,
8127
8289
  parseSyncResult,
8128
8290
  syncClaudeCredentials,
@@ -8268,4 +8430,4 @@ export {
8268
8430
  browserSessionActive,
8269
8431
  ensureBoxBrowser
8270
8432
  };
8271
- //# sourceMappingURL=chunk-NCJP5MTN.js.map
8433
+ //# sourceMappingURL=chunk-7UIAO7PC.js.map