@madarco/agentbox 0.9.0 → 0.10.1
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/CHANGELOG.md +102 -0
- package/README.md +161 -0
- package/dist/{_cloud-attach-ZXBCNWJX.js → _cloud-attach-2DGI6FUA.js} +4 -4
- package/dist/{chunk-NCJP5MTN.js → chunk-CDKVD6UO.js} +239 -61
- package/dist/chunk-CDKVD6UO.js.map +1 -0
- package/dist/{chunk-GU5LW4B5.js → chunk-I7NOGCL4.js} +374 -62
- package/dist/chunk-I7NOGCL4.js.map +1 -0
- package/dist/{chunk-BXQMIEHC.js → chunk-M2UWJKFA.js} +255 -163
- package/dist/chunk-M2UWJKFA.js.map +1 -0
- package/dist/{chunk-KL36BRN4.js → chunk-PWUVHPN6.js} +66 -17
- package/dist/{chunk-KL36BRN4.js.map → chunk-PWUVHPN6.js.map} +1 -1
- package/dist/{dist-CX5CGVEB.js → dist-BD5QJRDC.js} +4 -4
- package/dist/{dist-GDHP34ZK.js → dist-BNI5PQYK.js} +16 -4
- package/dist/dist-BNI5PQYK.js.map +1 -0
- package/dist/{dist-32EZBYG4.js → dist-SBCQVFCE.js} +23 -3
- package/dist/{dist-XML54CNB.js → dist-SJHY3HYN.js} +31 -6
- package/dist/dist-SJHY3HYN.js.map +1 -0
- package/dist/index.js +1787 -528
- package/dist/index.js.map +1 -1
- package/dist/{prepared-state-CL4CWXQA-H5THETIM.js → prepared-state-MQHD3M5F-O5M4NIN4.js} +2 -2
- package/package.json +10 -8
- package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +10 -9
- package/runtime/docker/packages/ctl/dist/bin.cjs +38 -3
- package/runtime/hetzner/agentbox-setup-skill.md +10 -9
- package/runtime/hetzner/ctl.cjs +38 -3
- package/runtime/relay/bin.cjs +41 -3
- package/runtime/vercel/agentbox-setup-skill.md +10 -9
- package/runtime/vercel/ctl.cjs +38 -3
- package/runtime/vercel/custom-system-CLAUDE.md +1 -4
- package/runtime/vercel/scripts/provision.sh +40 -0
- package/share/agentbox-setup/SKILL.md +10 -9
- package/dist/chunk-BXQMIEHC.js.map +0 -1
- package/dist/chunk-GU5LW4B5.js.map +0 -1
- package/dist/chunk-NCJP5MTN.js.map +0 -1
- package/dist/dist-GDHP34ZK.js.map +0 -1
- package/dist/dist-XML54CNB.js.map +0 -1
- /package/dist/{_cloud-attach-ZXBCNWJX.js.map → _cloud-attach-2DGI6FUA.js.map} +0 -0
- /package/dist/{dist-CX5CGVEB.js.map → dist-BD5QJRDC.js.map} +0 -0
- /package/dist/{dist-32EZBYG4.js.map → dist-SBCQVFCE.js.map} +0 -0
- /package/dist/{prepared-state-CL4CWXQA-H5THETIM.js.map → prepared-state-MQHD3M5F-O5M4NIN4.js.map} +0 -0
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
STATE_DIR,
|
|
6
6
|
STATE_FILE,
|
|
7
7
|
allocateProjectIndex,
|
|
8
|
-
buildImage,
|
|
9
8
|
computeDockerContextFingerprint,
|
|
10
9
|
detectGitRepos,
|
|
11
10
|
ensureImage,
|
|
@@ -13,19 +12,19 @@ import {
|
|
|
13
12
|
imageExists,
|
|
14
13
|
pickFreshBranch,
|
|
15
14
|
preparedMatches,
|
|
15
|
+
pullOrBuild,
|
|
16
16
|
readCliStamp,
|
|
17
17
|
readPreparedDockerState,
|
|
18
18
|
readState,
|
|
19
19
|
recordBox,
|
|
20
|
-
removeBoxRecord
|
|
21
|
-
|
|
22
|
-
} from "./chunk-KL36BRN4.js";
|
|
20
|
+
removeBoxRecord
|
|
21
|
+
} from "./chunk-PWUVHPN6.js";
|
|
23
22
|
|
|
24
23
|
// ../../packages/sandbox-docker/dist/index.js
|
|
25
24
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
26
25
|
import { mkdir as mkdir7, stat as stat6 } from "fs/promises";
|
|
27
26
|
import { homedir as homedir9 } from "os";
|
|
28
|
-
import { basename as
|
|
27
|
+
import { basename as basename3, join as join10, resolve as resolve3 } from "path";
|
|
29
28
|
import { execa as execa13 } from "execa";
|
|
30
29
|
|
|
31
30
|
// ../../packages/ctl/dist/index.js
|
|
@@ -744,6 +743,9 @@ var BUILT_IN_DEFAULTS = {
|
|
|
744
743
|
isolateCodexConfig: false,
|
|
745
744
|
isolateOpencodeConfig: false,
|
|
746
745
|
image: "agentbox/box:dev",
|
|
746
|
+
// Mirrors BOX_IMAGE_REGISTRY in @agentbox/sandbox-docker. Empty disables the
|
|
747
|
+
// registry pull (always build the docker base image locally).
|
|
748
|
+
imageRegistry: "ghcr.io/madarco/agentbox/box",
|
|
747
749
|
dockerCacheShared: false,
|
|
748
750
|
memory: 0,
|
|
749
751
|
cpus: 0,
|
|
@@ -758,10 +760,12 @@ var BUILT_IN_DEFAULTS = {
|
|
|
758
760
|
maxLayers: 3
|
|
759
761
|
},
|
|
760
762
|
claude: {
|
|
761
|
-
sessionName: "claude"
|
|
763
|
+
sessionName: "claude",
|
|
764
|
+
dangerouslySkipPermissions: true
|
|
762
765
|
},
|
|
763
766
|
codex: {
|
|
764
|
-
sessionName: "codex"
|
|
767
|
+
sessionName: "codex",
|
|
768
|
+
dangerouslySkipPermissions: true
|
|
765
769
|
},
|
|
766
770
|
opencode: {
|
|
767
771
|
sessionName: "opencode"
|
|
@@ -898,6 +902,12 @@ var KEY_REGISTRY = [
|
|
|
898
902
|
description: "Box image ref (advanced).",
|
|
899
903
|
advanced: true
|
|
900
904
|
},
|
|
905
|
+
{
|
|
906
|
+
key: "box.imageRegistry",
|
|
907
|
+
type: "string",
|
|
908
|
+
description: "Registry repo to pull the prebuilt docker base image from before building locally. Empty = always build. Docker only (advanced).",
|
|
909
|
+
advanced: true
|
|
910
|
+
},
|
|
901
911
|
{
|
|
902
912
|
key: "box.dockerCacheShared",
|
|
903
913
|
type: "bool",
|
|
@@ -949,11 +959,21 @@ var KEY_REGISTRY = [
|
|
|
949
959
|
type: "string",
|
|
950
960
|
description: "tmux session name for `agentbox claude`."
|
|
951
961
|
},
|
|
962
|
+
{
|
|
963
|
+
key: "claude.dangerouslySkipPermissions",
|
|
964
|
+
type: "bool",
|
|
965
|
+
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."
|
|
966
|
+
},
|
|
952
967
|
{
|
|
953
968
|
key: "codex.sessionName",
|
|
954
969
|
type: "string",
|
|
955
970
|
description: "tmux session name for `agentbox codex`."
|
|
956
971
|
},
|
|
972
|
+
{
|
|
973
|
+
key: "codex.dangerouslySkipPermissions",
|
|
974
|
+
type: "bool",
|
|
975
|
+
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."
|
|
976
|
+
},
|
|
957
977
|
{
|
|
958
978
|
key: "opencode.sessionName",
|
|
959
979
|
type: "string",
|
|
@@ -1637,7 +1657,7 @@ async function touchProjectMeta(absPath) {
|
|
|
1637
1657
|
|
|
1638
1658
|
// ../../packages/sandbox-docker/dist/index.js
|
|
1639
1659
|
import { chmod, mkdir as mkdir32, readFile as readFile32 } from "fs/promises";
|
|
1640
|
-
import { join as join32 } from "path";
|
|
1660
|
+
import { basename as basename2, join as join32 } from "path";
|
|
1641
1661
|
import { execa as execa4 } from "execa";
|
|
1642
1662
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
1643
1663
|
import { stat as stat22 } from "fs/promises";
|
|
@@ -1662,7 +1682,7 @@ import { homedir as homedir6, platform } from "os";
|
|
|
1662
1682
|
import { join as join7, resolve as resolve2 } from "path";
|
|
1663
1683
|
import { mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile5, readdir as readdir32, rm as rm3, writeFile as writeFile22 } from "fs/promises";
|
|
1664
1684
|
import { homedir as homedir7, tmpdir as tmpdir2 } from "os";
|
|
1665
|
-
import { basename as
|
|
1685
|
+
import { basename as basename22, join as join8 } from "path";
|
|
1666
1686
|
import { execa as execa10 } from "execa";
|
|
1667
1687
|
import { stat as stat5 } from "fs/promises";
|
|
1668
1688
|
import { execa as execa11 } from "execa";
|
|
@@ -1670,10 +1690,11 @@ import { execa as execa12 } from "execa";
|
|
|
1670
1690
|
import { spawn } from "child_process";
|
|
1671
1691
|
import { randomBytes as randomBytes22 } from "crypto";
|
|
1672
1692
|
import { existsSync as existsSync2, openSync } from "fs";
|
|
1673
|
-
import { mkdir as mkdir6, readFile as readFile6, unlink as unlink2, writeFile as writeFile32 } from "fs/promises";
|
|
1693
|
+
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
1694
|
import { request as httpRequest } from "http";
|
|
1695
|
+
import { createRequire } from "module";
|
|
1675
1696
|
import { homedir as homedir8 } from "os";
|
|
1676
|
-
import { dirname as dirname3, join as join9, resolve as resolve22 } from "path";
|
|
1697
|
+
import { dirname as dirname3, join as join9, resolve as resolve22, sep } from "path";
|
|
1677
1698
|
import { setTimeout as delay2 } from "timers/promises";
|
|
1678
1699
|
import { fileURLToPath } from "url";
|
|
1679
1700
|
|
|
@@ -1864,7 +1885,7 @@ function queueLogPath(id) {
|
|
|
1864
1885
|
|
|
1865
1886
|
// ../../packages/sandbox-docker/dist/index.js
|
|
1866
1887
|
import { execa as execa15 } from "execa";
|
|
1867
|
-
import { readdir as
|
|
1888
|
+
import { readdir as readdir5, rm as rm5, stat as stat7 } from "fs/promises";
|
|
1868
1889
|
import { join as join12 } from "path";
|
|
1869
1890
|
|
|
1870
1891
|
// ../../packages/core/dist/index.js
|
|
@@ -1925,11 +1946,11 @@ import { homedir as homedir10 } from "os";
|
|
|
1925
1946
|
import { join as join13 } from "path";
|
|
1926
1947
|
import { execa as execa16 } from "execa";
|
|
1927
1948
|
import { existsSync as existsSync3, mkdirSync, renameSync, statSync } from "fs";
|
|
1928
|
-
import { basename as
|
|
1949
|
+
import { basename as basename4, dirname as dirname22, posix, resolve as resolve4 } from "path";
|
|
1929
1950
|
import { execa as execa17 } from "execa";
|
|
1930
|
-
import { copyFile, mkdtemp as mkdtemp3, readdir as
|
|
1951
|
+
import { copyFile, mkdtemp as mkdtemp3, readdir as readdir6, readFile as readFile7, rm as rm6, stat as stat8, writeFile as writeFile4 } from "fs/promises";
|
|
1931
1952
|
import { homedir as homedir11, tmpdir as tmpdir3 } from "os";
|
|
1932
|
-
import { basename as
|
|
1953
|
+
import { basename as basename5, join as join14, relative as relative2 } from "path";
|
|
1933
1954
|
import { execa as execa18 } from "execa";
|
|
1934
1955
|
function isHostPathHookCommand(command, hostHome) {
|
|
1935
1956
|
if (typeof command !== "string" || command.length === 0) return false;
|
|
@@ -2728,13 +2749,13 @@ async function copyOneEntry(container, entry) {
|
|
|
2728
2749
|
throw new Error(`mkdir -p ${parentDir} failed: ${String(mkdir8.stderr).slice(0, 300)}`);
|
|
2729
2750
|
}
|
|
2730
2751
|
if (entry.kind === "file") {
|
|
2731
|
-
const
|
|
2752
|
+
const cp2 = await execa22(
|
|
2732
2753
|
"docker",
|
|
2733
2754
|
["cp", entry.absSrc, `${container}:${boxDest}`],
|
|
2734
2755
|
{ reject: false }
|
|
2735
2756
|
);
|
|
2736
|
-
if (
|
|
2737
|
-
throw new Error(`docker cp failed: ${String(
|
|
2757
|
+
if (cp2.exitCode !== 0) {
|
|
2758
|
+
throw new Error(`docker cp failed: ${String(cp2.stderr).slice(0, 300)}`);
|
|
2738
2759
|
}
|
|
2739
2760
|
} else {
|
|
2740
2761
|
const packed = await execa22(
|
|
@@ -3744,6 +3765,54 @@ function isRealAgentCredential(agent, text) {
|
|
|
3744
3765
|
}
|
|
3745
3766
|
return Object.keys(parsed).length > 0;
|
|
3746
3767
|
}
|
|
3768
|
+
async function hostClaudeBackupExpired(path = CREDENTIALS_BACKUP_FILE, now = Date.now()) {
|
|
3769
|
+
try {
|
|
3770
|
+
const parsed = JSON.parse(await readFile32(path, "utf8"));
|
|
3771
|
+
const exp = parsed?.claudeAiOauth?.expiresAt;
|
|
3772
|
+
return typeof exp === "number" && Number.isFinite(exp) && exp < now;
|
|
3773
|
+
} catch {
|
|
3774
|
+
return false;
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
function parseExtractResult(stdout) {
|
|
3778
|
+
return { copied: /\bCOPIED=yes\b/.test(stdout) };
|
|
3779
|
+
}
|
|
3780
|
+
async function extractVolumeAuthToBackup(opts) {
|
|
3781
|
+
try {
|
|
3782
|
+
await mkdir32(STATE_DIR, { recursive: true });
|
|
3783
|
+
const script = 'COPIED=no; if [ -s /dst/auth.json ]; then cp -a /dst/auth.json "/host-state/$DEST" && COPIED=yes; fi; echo "COPIED=$COPIED"';
|
|
3784
|
+
const { stdout } = await execa4("docker", [
|
|
3785
|
+
"run",
|
|
3786
|
+
"--rm",
|
|
3787
|
+
"--user",
|
|
3788
|
+
"0",
|
|
3789
|
+
"-v",
|
|
3790
|
+
`${opts.volume}:/dst`,
|
|
3791
|
+
"-v",
|
|
3792
|
+
`${STATE_DIR}:/host-state`,
|
|
3793
|
+
"-e",
|
|
3794
|
+
// Pass the destination filename via env so the path isn't interpolated
|
|
3795
|
+
// into the script string (keeps the docker arg list static + injection-safe).
|
|
3796
|
+
`DEST=${basename2(opts.backupFile)}`,
|
|
3797
|
+
opts.image,
|
|
3798
|
+
"sh",
|
|
3799
|
+
"-c",
|
|
3800
|
+
script
|
|
3801
|
+
]);
|
|
3802
|
+
const result = parseExtractResult(stdout);
|
|
3803
|
+
if (result.copied) await chmod(opts.backupFile, 384).catch(() => {
|
|
3804
|
+
});
|
|
3805
|
+
return result;
|
|
3806
|
+
} catch {
|
|
3807
|
+
return { copied: false };
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
function extractCodexCredentials(volume, image) {
|
|
3811
|
+
return extractVolumeAuthToBackup({ volume, image, backupFile: CODEX_CREDENTIALS_BACKUP_FILE });
|
|
3812
|
+
}
|
|
3813
|
+
function extractOpencodeCredentials(volume, image) {
|
|
3814
|
+
return extractVolumeAuthToBackup({ volume, image, backupFile: OPENCODE_CREDENTIALS_BACKUP_FILE });
|
|
3815
|
+
}
|
|
3747
3816
|
async function hostBackupHasCredentials(path = CREDENTIALS_BACKUP_FILE) {
|
|
3748
3817
|
try {
|
|
3749
3818
|
const parsed = JSON.parse(await readFile32(path, "utf8"));
|
|
@@ -4998,7 +5067,7 @@ async function createSnapshot(opts) {
|
|
|
4998
5067
|
var CHECKPOINTS_ROOT = join8(homedir7(), ".agentbox", "checkpoints");
|
|
4999
5068
|
var CHECKPOINT_IMAGE_PREFIX = "agentbox-ckpt-";
|
|
5000
5069
|
function checkpointImageTag(projectRoot, name) {
|
|
5001
|
-
const mnemonic = sanitizeMnemonic(
|
|
5070
|
+
const mnemonic = sanitizeMnemonic(basename22(projectRoot));
|
|
5002
5071
|
return `${CHECKPOINT_IMAGE_PREFIX}${hashProjectPath(projectRoot)}_${mnemonic}:${name}`;
|
|
5003
5072
|
}
|
|
5004
5073
|
function projectCheckpointsDir(projectRoot) {
|
|
@@ -5348,6 +5417,7 @@ async function ensureHomeOwnedByVscode(container) {
|
|
|
5348
5417
|
var STATE_DIR22 = join9(homedir8(), ".agentbox");
|
|
5349
5418
|
var PID_FILE = join9(STATE_DIR22, "relay.pid");
|
|
5350
5419
|
var LOG_FILE = join9(STATE_DIR22, "relay.log");
|
|
5420
|
+
var RELAY_HOME_DIR = join9(STATE_DIR22, "relay");
|
|
5351
5421
|
var PORT = DEFAULT_RELAY_PORT;
|
|
5352
5422
|
var ENDPOINT = {
|
|
5353
5423
|
// host.docker.internal is the Docker Desktop / OrbStack-supplied alias for
|
|
@@ -5358,6 +5428,13 @@ var ENDPOINT = {
|
|
|
5358
5428
|
hostUrl: `http://127.0.0.1:${String(PORT)}`,
|
|
5359
5429
|
port: PORT
|
|
5360
5430
|
};
|
|
5431
|
+
function shouldReclaimForVersion(health, currentVersion) {
|
|
5432
|
+
if (health.cliEntry === false) return true;
|
|
5433
|
+
if (typeof health.version === "string" && health.version.length > 0 && typeof currentVersion === "string" && currentVersion.length > 0 && health.version !== currentVersion) {
|
|
5434
|
+
return true;
|
|
5435
|
+
}
|
|
5436
|
+
return false;
|
|
5437
|
+
}
|
|
5361
5438
|
async function ensureRelay(opts = {}) {
|
|
5362
5439
|
const log = opts.onLog ?? (() => {
|
|
5363
5440
|
});
|
|
@@ -5366,12 +5443,19 @@ async function ensureRelay(opts = {}) {
|
|
|
5366
5443
|
await removeContainer(RELAY_CONTAINER_NAME);
|
|
5367
5444
|
log(`removed legacy relay container ${RELAY_CONTAINER_NAME}`);
|
|
5368
5445
|
}
|
|
5446
|
+
const currentVersion = process.env.AGENTBOX_CLI_VERSION;
|
|
5369
5447
|
const health = await fetchHealthz(500);
|
|
5370
5448
|
if (health !== null) {
|
|
5371
|
-
if (health
|
|
5449
|
+
if (!shouldReclaimForVersion(health, currentVersion)) {
|
|
5372
5450
|
return ENDPOINT;
|
|
5373
5451
|
}
|
|
5374
|
-
|
|
5452
|
+
if (health.cliEntry === false) {
|
|
5453
|
+
log("relay is alive but lacks AGENTBOX_CLI_ENTRY (cp/download/checkpoint would fail) \u2014 reclaiming");
|
|
5454
|
+
} else {
|
|
5455
|
+
log(
|
|
5456
|
+
`relay was spawned by agentbox ${health.version ?? "?"} but this CLI is ${currentVersion ?? "?"} \u2014 reclaiming to keep the relay version-consistent`
|
|
5457
|
+
);
|
|
5458
|
+
}
|
|
5375
5459
|
await reclaimRelay(health.pid, log);
|
|
5376
5460
|
} else {
|
|
5377
5461
|
const existingPid = await readPidFile();
|
|
@@ -5388,8 +5472,9 @@ async function ensureRelay(opts = {}) {
|
|
|
5388
5472
|
});
|
|
5389
5473
|
}
|
|
5390
5474
|
}
|
|
5391
|
-
const
|
|
5392
|
-
const
|
|
5475
|
+
const staged = await stageRelayHome(currentVersion ?? "", log).catch(() => null);
|
|
5476
|
+
const relayBin = staged?.relayBin ?? resolveRelayBin();
|
|
5477
|
+
const cliEntry = staged?.cliEntry ?? resolveCliEntry();
|
|
5393
5478
|
if (cliEntry === null) {
|
|
5394
5479
|
throw new Error(
|
|
5395
5480
|
"cannot start the host relay: agentbox CLI entry not found (is the build complete / dist present?). Set AGENTBOX_CLI_ENTRY to override."
|
|
@@ -5411,7 +5496,7 @@ async function reclaimRelay(reportedPid, log) {
|
|
|
5411
5496
|
});
|
|
5412
5497
|
if (await pingHealthz(300)) {
|
|
5413
5498
|
throw new Error(
|
|
5414
|
-
`a relay
|
|
5499
|
+
`a relay is still listening on :${String(PORT)} and could not be stopped (reported pid ${String(reportedPid ?? "unknown")}); kill it manually and retry`
|
|
5415
5500
|
);
|
|
5416
5501
|
}
|
|
5417
5502
|
}
|
|
@@ -5494,6 +5579,80 @@ function resolveCliEntry() {
|
|
|
5494
5579
|
}
|
|
5495
5580
|
return null;
|
|
5496
5581
|
}
|
|
5582
|
+
async function stageRelayHome(version, log) {
|
|
5583
|
+
if (!version || version === "0.0.0-dev") return null;
|
|
5584
|
+
if (process.env.AGENTBOX_RELAY_BIN || process.env.AGENTBOX_CLI_ENTRY) return null;
|
|
5585
|
+
const cliRoot = findCliRoot(dirname3(fileURLToPath(import.meta.url)));
|
|
5586
|
+
if (cliRoot === null) return null;
|
|
5587
|
+
const homeDir = join9(RELAY_HOME_DIR, version);
|
|
5588
|
+
const stagedEntry = join9(homeDir, "dist", "index.js");
|
|
5589
|
+
const stagedBin = join9(homeDir, "runtime", "relay", "bin.cjs");
|
|
5590
|
+
if (existsSync2(stagedEntry) && existsSync2(stagedBin)) {
|
|
5591
|
+
return { relayBin: stagedBin, cliEntry: stagedEntry };
|
|
5592
|
+
}
|
|
5593
|
+
const nodeModules = resolveDepRoot(join9(cliRoot, "dist", "index.js"));
|
|
5594
|
+
if (nodeModules === null) return null;
|
|
5595
|
+
const tmpDir = `${homeDir}.tmp-${String(process.pid)}`;
|
|
5596
|
+
try {
|
|
5597
|
+
await mkdir6(RELAY_HOME_DIR, { recursive: true });
|
|
5598
|
+
await rm4(tmpDir, { recursive: true, force: true });
|
|
5599
|
+
await mkdir6(tmpDir, { recursive: true });
|
|
5600
|
+
for (const sub of ["dist", "runtime", "share"]) {
|
|
5601
|
+
const src = join9(cliRoot, sub);
|
|
5602
|
+
if (existsSync2(src)) await cp(src, join9(tmpDir, sub), { recursive: true });
|
|
5603
|
+
}
|
|
5604
|
+
await cp(nodeModules, join9(tmpDir, "node_modules"), { recursive: true, dereference: true });
|
|
5605
|
+
await rm4(homeDir, { recursive: true, force: true });
|
|
5606
|
+
await rename3(tmpDir, homeDir);
|
|
5607
|
+
} catch (err) {
|
|
5608
|
+
await rm4(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
5609
|
+
});
|
|
5610
|
+
if (existsSync2(stagedEntry) && existsSync2(stagedBin)) {
|
|
5611
|
+
return { relayBin: stagedBin, cliEntry: stagedEntry };
|
|
5612
|
+
}
|
|
5613
|
+
log(`relay home staging failed (${err instanceof Error ? err.message : String(err)}); using bundle paths`);
|
|
5614
|
+
return null;
|
|
5615
|
+
}
|
|
5616
|
+
log(`staged relay home for ${version} at ${homeDir}`);
|
|
5617
|
+
await gcOldRelayHomes(version).catch(() => {
|
|
5618
|
+
});
|
|
5619
|
+
return { relayBin: stagedBin, cliEntry: stagedEntry };
|
|
5620
|
+
}
|
|
5621
|
+
function findCliRoot(moduleDir) {
|
|
5622
|
+
for (const root of [resolve22(moduleDir, ".."), resolve22(moduleDir, "..", "..")]) {
|
|
5623
|
+
if (existsSync2(join9(root, "dist", "index.js")) && existsSync2(join9(root, "runtime", "relay", "bin.cjs"))) {
|
|
5624
|
+
return root;
|
|
5625
|
+
}
|
|
5626
|
+
}
|
|
5627
|
+
return null;
|
|
5628
|
+
}
|
|
5629
|
+
function resolveDepRoot(fromFile) {
|
|
5630
|
+
try {
|
|
5631
|
+
const req = createRequire(fromFile);
|
|
5632
|
+
const main = req.resolve("commander");
|
|
5633
|
+
if (main.includes(`${sep}.pnpm${sep}`)) return null;
|
|
5634
|
+
const marker = `${sep}node_modules${sep}`;
|
|
5635
|
+
const idx = main.lastIndexOf(marker);
|
|
5636
|
+
if (idx === -1) return null;
|
|
5637
|
+
const nm = main.slice(0, idx + marker.length - 1);
|
|
5638
|
+
return existsSync2(join9(nm, "commander")) ? nm : null;
|
|
5639
|
+
} catch {
|
|
5640
|
+
return null;
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5643
|
+
async function gcOldRelayHomes(keepVersion) {
|
|
5644
|
+
let entries;
|
|
5645
|
+
try {
|
|
5646
|
+
entries = await readdir4(RELAY_HOME_DIR);
|
|
5647
|
+
} catch {
|
|
5648
|
+
return;
|
|
5649
|
+
}
|
|
5650
|
+
for (const name of entries) {
|
|
5651
|
+
if (name === keepVersion) continue;
|
|
5652
|
+
await rm4(join9(RELAY_HOME_DIR, name), { recursive: true, force: true }).catch(() => {
|
|
5653
|
+
});
|
|
5654
|
+
}
|
|
5655
|
+
}
|
|
5497
5656
|
async function stopRelay() {
|
|
5498
5657
|
const pid = await readPidFile();
|
|
5499
5658
|
if (pid === null) {
|
|
@@ -5532,7 +5691,7 @@ async function getRelayStatus() {
|
|
|
5532
5691
|
pidAlive: pidAlive2,
|
|
5533
5692
|
port: PORT,
|
|
5534
5693
|
endpoint: ENDPOINT,
|
|
5535
|
-
health: health === null ? null : { boxes: health.boxes, events: health.events },
|
|
5694
|
+
health: health === null ? null : { boxes: health.boxes, events: health.events, version: health.version, commit: health.commit },
|
|
5536
5695
|
pidFile: PID_FILE,
|
|
5537
5696
|
logFile: LOG_FILE
|
|
5538
5697
|
};
|
|
@@ -5577,7 +5736,9 @@ function fetchHealthz(timeoutMs) {
|
|
|
5577
5736
|
boxes: parsed.boxes,
|
|
5578
5737
|
events: parsed.events,
|
|
5579
5738
|
pid: typeof parsed.pid === "number" ? parsed.pid : void 0,
|
|
5580
|
-
cliEntry: typeof parsed.cliEntry === "boolean" ? parsed.cliEntry : void 0
|
|
5739
|
+
cliEntry: typeof parsed.cliEntry === "boolean" ? parsed.cliEntry : void 0,
|
|
5740
|
+
version: typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : void 0,
|
|
5741
|
+
commit: typeof parsed.commit === "string" && parsed.commit.length > 0 ? parsed.commit : void 0
|
|
5581
5742
|
});
|
|
5582
5743
|
} else {
|
|
5583
5744
|
resolveP(null);
|
|
@@ -5930,7 +6091,7 @@ function generateBoxId() {
|
|
|
5930
6091
|
return randomBytes3(4).toString("hex");
|
|
5931
6092
|
}
|
|
5932
6093
|
function sanitizeBasename(workspacePath) {
|
|
5933
|
-
const raw =
|
|
6094
|
+
const raw = basename3(resolve3(workspacePath));
|
|
5934
6095
|
return raw.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^[-._]+|[-._]+$/g, "").slice(0, 30).replace(/[-._]+$/, "");
|
|
5935
6096
|
}
|
|
5936
6097
|
function defaultBoxName(workspacePath, id) {
|
|
@@ -6021,7 +6182,9 @@ async function createBox(opts) {
|
|
|
6021
6182
|
const imageRef = checkpointImage ?? opts.image ?? DEFAULT_BOX_IMAGE;
|
|
6022
6183
|
const ensureRef = checkpointImage ? opts.image ?? DEFAULT_BOX_IMAGE : imageRef;
|
|
6023
6184
|
const { built } = await ensureImage(ensureRef, {
|
|
6024
|
-
onProgress: (line) => log(`[image] ${line}`)
|
|
6185
|
+
onProgress: (line) => log(`[image] ${line}`),
|
|
6186
|
+
allowPull: opts.allowPull,
|
|
6187
|
+
registry: opts.imageRegistry
|
|
6025
6188
|
});
|
|
6026
6189
|
log(built ? `built image ${ensureRef}` : `using cached image ${imageRef}`);
|
|
6027
6190
|
let relayUp = false;
|
|
@@ -6771,10 +6934,11 @@ async function listBoxes() {
|
|
|
6771
6934
|
};
|
|
6772
6935
|
return {
|
|
6773
6936
|
...b,
|
|
6774
|
-
state: "running",
|
|
6937
|
+
state: b.cloud?.lastState ?? "running",
|
|
6775
6938
|
endpoints: endpoints2,
|
|
6776
6939
|
claudeActivity: persisted2?.claude.state,
|
|
6777
6940
|
claudeSessionTitle: persisted2?.claude.sessionTitle,
|
|
6941
|
+
claudeQuestion: persisted2?.claude.state === "question" ? persisted2.claude.question : void 0,
|
|
6778
6942
|
codexActivity: persisted2?.codex?.state,
|
|
6779
6943
|
codexSessionTitle: persisted2?.codex?.sessionTitle,
|
|
6780
6944
|
opencodeSessionTitle: persisted2?.opencode?.sessionTitle,
|
|
@@ -6795,6 +6959,7 @@ async function listBoxes() {
|
|
|
6795
6959
|
endpoints,
|
|
6796
6960
|
claudeActivity: persisted?.claude.state,
|
|
6797
6961
|
claudeSessionTitle: persisted?.claude.sessionTitle,
|
|
6962
|
+
claudeQuestion: persisted?.claude.state === "question" ? persisted.claude.question : void 0,
|
|
6798
6963
|
codexActivity: persisted?.codex?.state,
|
|
6799
6964
|
codexSessionTitle: persisted?.codex?.sessionTitle,
|
|
6800
6965
|
opencodeSessionTitle: persisted?.opencode?.sessionTitle,
|
|
@@ -7065,14 +7230,14 @@ async function destroyBox(idOrName, opts = {}) {
|
|
|
7065
7230
|
let removedSnapshot = null;
|
|
7066
7231
|
if (box.snapshotDir && !opts.keepSnapshot) {
|
|
7067
7232
|
try {
|
|
7068
|
-
await
|
|
7233
|
+
await rm5(box.snapshotDir, { recursive: true, force: true });
|
|
7069
7234
|
removedSnapshot = box.snapshotDir;
|
|
7070
7235
|
} catch {
|
|
7071
7236
|
removedSnapshot = null;
|
|
7072
7237
|
}
|
|
7073
7238
|
}
|
|
7074
7239
|
try {
|
|
7075
|
-
await
|
|
7240
|
+
await rm5(boxRunDirFor(box), { recursive: true, force: true });
|
|
7076
7241
|
} catch {
|
|
7077
7242
|
}
|
|
7078
7243
|
await removeBoxRecord(box.id);
|
|
@@ -7080,7 +7245,7 @@ async function destroyBox(idOrName, opts = {}) {
|
|
|
7080
7245
|
}
|
|
7081
7246
|
async function listSnapshotDirs() {
|
|
7082
7247
|
try {
|
|
7083
|
-
const entries = await
|
|
7248
|
+
const entries = await readdir5(SNAPSHOTS_ROOT, { withFileTypes: true });
|
|
7084
7249
|
return entries.filter((e) => e.isDirectory()).map((e) => join12(SNAPSHOTS_ROOT, e.name));
|
|
7085
7250
|
} catch {
|
|
7086
7251
|
return [];
|
|
@@ -7088,7 +7253,7 @@ async function listSnapshotDirs() {
|
|
|
7088
7253
|
}
|
|
7089
7254
|
async function listBoxDirs() {
|
|
7090
7255
|
try {
|
|
7091
|
-
const entries = await
|
|
7256
|
+
const entries = await readdir5(BOXES_ROOT, { withFileTypes: true });
|
|
7092
7257
|
return entries.filter((e) => e.isDirectory()).map((e) => join12(BOXES_ROOT, e.name));
|
|
7093
7258
|
} catch {
|
|
7094
7259
|
return [];
|
|
@@ -7184,13 +7349,13 @@ async function pruneBoxes(opts = {}) {
|
|
|
7184
7349
|
for (const v of orphanVolumes) await removeVolume(v);
|
|
7185
7350
|
for (const d of orphanSnapshots) {
|
|
7186
7351
|
try {
|
|
7187
|
-
await
|
|
7352
|
+
await rm5(d, { recursive: true, force: true });
|
|
7188
7353
|
} catch {
|
|
7189
7354
|
}
|
|
7190
7355
|
}
|
|
7191
7356
|
for (const d of orphanBoxDirs) {
|
|
7192
7357
|
try {
|
|
7193
|
-
await
|
|
7358
|
+
await rm5(d, { recursive: true, force: true });
|
|
7194
7359
|
} catch {
|
|
7195
7360
|
}
|
|
7196
7361
|
}
|
|
@@ -7455,7 +7620,7 @@ function asText(s) {
|
|
|
7455
7620
|
async function uploadToBox(box, hostSrc, boxDst) {
|
|
7456
7621
|
const srcAbs = resolve4(hostSrc);
|
|
7457
7622
|
if (!existsSync3(srcAbs)) throw new Error(`source not found: ${hostSrc}`);
|
|
7458
|
-
const srcBasename =
|
|
7623
|
+
const srcBasename = basename4(srcAbs);
|
|
7459
7624
|
const srcParent = dirname22(srcAbs);
|
|
7460
7625
|
let boxParent;
|
|
7461
7626
|
let finalName;
|
|
@@ -7539,7 +7704,7 @@ async function downloadFromBox(box, boxSrc, hostDst) {
|
|
|
7539
7704
|
finalName = srcBasename;
|
|
7540
7705
|
} else {
|
|
7541
7706
|
hostParent = dirname22(dstAbs);
|
|
7542
|
-
finalName =
|
|
7707
|
+
finalName = basename4(dstAbs);
|
|
7543
7708
|
}
|
|
7544
7709
|
mkdirSync(hostParent, { recursive: true });
|
|
7545
7710
|
const finalPath = posix.join(hostParent, finalName);
|
|
@@ -7575,6 +7740,8 @@ var dockerProvider = {
|
|
|
7575
7740
|
fromBranch: req.fromBranch,
|
|
7576
7741
|
useBranch: req.useBranch,
|
|
7577
7742
|
image: req.image,
|
|
7743
|
+
allowPull: req.allowPull,
|
|
7744
|
+
imageRegistry: req.imageRegistry,
|
|
7578
7745
|
onLog: req.onLog,
|
|
7579
7746
|
claudeConfig: po.claudeConfig,
|
|
7580
7747
|
claudeEnv: po.claudeEnv,
|
|
@@ -7681,15 +7848,19 @@ var dockerProvider = {
|
|
|
7681
7848
|
return {};
|
|
7682
7849
|
}
|
|
7683
7850
|
}
|
|
7684
|
-
|
|
7685
|
-
|
|
7851
|
+
const { source } = await pullOrBuild(ref, fingerprint, {
|
|
7852
|
+
onProgress: opts.onLog,
|
|
7853
|
+
allowPull: opts.force ? false : opts.allowPull,
|
|
7854
|
+
registry: opts.registry
|
|
7855
|
+
});
|
|
7686
7856
|
if (fingerprint) {
|
|
7687
|
-
writePreparedDockerState({ imageRef: ref, contextSha256: fingerprint.contextSha256 });
|
|
7688
7857
|
opts.onLog?.(
|
|
7689
|
-
`docker image ${ref}
|
|
7858
|
+
`docker image ${ref} ${source}; recorded fingerprint ${fingerprint.contextSha256.slice(0, 12)}`
|
|
7690
7859
|
);
|
|
7691
7860
|
} else {
|
|
7692
|
-
opts.onLog?.(
|
|
7861
|
+
opts.onLog?.(
|
|
7862
|
+
`docker image ${ref} ${source} (fingerprint unavailable, prepared state not written)`
|
|
7863
|
+
);
|
|
7693
7864
|
}
|
|
7694
7865
|
return {};
|
|
7695
7866
|
}
|
|
@@ -7708,7 +7879,7 @@ async function findBrokenSymlinks2(root) {
|
|
|
7708
7879
|
async function walk(dir) {
|
|
7709
7880
|
let entries;
|
|
7710
7881
|
try {
|
|
7711
|
-
entries = await
|
|
7882
|
+
entries = await readdir6(dir, { withFileTypes: true });
|
|
7712
7883
|
} catch {
|
|
7713
7884
|
return;
|
|
7714
7885
|
}
|
|
@@ -7736,7 +7907,7 @@ function emptyResult(warnings = []) {
|
|
|
7736
7907
|
}, warnings };
|
|
7737
7908
|
}
|
|
7738
7909
|
async function tarballFromDir(stageDir, agent) {
|
|
7739
|
-
const tarballPath = join14(tmpdir3(), `agentbox-${agent}-${
|
|
7910
|
+
const tarballPath = join14(tmpdir3(), `agentbox-${agent}-${basename5(stageDir)}.tar.gz`);
|
|
7740
7911
|
await execa18("tar", ["-czf", tarballPath, "-C", stageDir, "."], {
|
|
7741
7912
|
env: { ...process.env, COPYFILE_DISABLE: "1" }
|
|
7742
7913
|
});
|
|
@@ -7745,7 +7916,7 @@ async function tarballFromDir(stageDir, agent) {
|
|
|
7745
7916
|
function makeCleanup(paths) {
|
|
7746
7917
|
return async () => {
|
|
7747
7918
|
for (const p of paths) {
|
|
7748
|
-
await
|
|
7919
|
+
await rm6(p, { recursive: true, force: true });
|
|
7749
7920
|
}
|
|
7750
7921
|
};
|
|
7751
7922
|
}
|
|
@@ -7761,8 +7932,8 @@ async function stageSingleFileTarball(agent, sourcePath, tarballEntryName) {
|
|
|
7761
7932
|
warnings: []
|
|
7762
7933
|
};
|
|
7763
7934
|
} catch (err) {
|
|
7764
|
-
await
|
|
7765
|
-
if (tarballPath) await
|
|
7935
|
+
await rm6(stageDir, { recursive: true, force: true });
|
|
7936
|
+
if (tarballPath) await rm6(tarballPath, { force: true });
|
|
7766
7937
|
throw err;
|
|
7767
7938
|
}
|
|
7768
7939
|
}
|
|
@@ -7845,7 +8016,7 @@ async function stageClaudeStaticForUpload(opts = {}) {
|
|
|
7845
8016
|
const pluginsDir = join14(stageDir, "plugins");
|
|
7846
8017
|
if (await pathExists7(pluginsDir)) {
|
|
7847
8018
|
try {
|
|
7848
|
-
const entries = await
|
|
8019
|
+
const entries = await readdir6(pluginsDir, { withFileTypes: true });
|
|
7849
8020
|
for (const ent of entries) {
|
|
7850
8021
|
if (!ent.isFile() || !ent.name.endsWith(".json")) continue;
|
|
7851
8022
|
const file = join14(pluginsDir, ent.name);
|
|
@@ -7863,8 +8034,8 @@ async function stageClaudeStaticForUpload(opts = {}) {
|
|
|
7863
8034
|
warnings: []
|
|
7864
8035
|
};
|
|
7865
8036
|
} catch (err) {
|
|
7866
|
-
await
|
|
7867
|
-
if (tarballPath) await
|
|
8037
|
+
await rm6(stageDir, { recursive: true, force: true });
|
|
8038
|
+
if (tarballPath) await rm6(tarballPath, { force: true });
|
|
7868
8039
|
throw err;
|
|
7869
8040
|
}
|
|
7870
8041
|
}
|
|
@@ -7924,16 +8095,17 @@ async function stageCodexStaticForUpload(opts = {}) {
|
|
|
7924
8095
|
warnings: []
|
|
7925
8096
|
};
|
|
7926
8097
|
} catch (err) {
|
|
7927
|
-
await
|
|
7928
|
-
if (tarballPath) await
|
|
8098
|
+
await rm6(stageDir, { recursive: true, force: true });
|
|
8099
|
+
if (tarballPath) await rm6(tarballPath, { force: true });
|
|
7929
8100
|
throw err;
|
|
7930
8101
|
}
|
|
7931
8102
|
}
|
|
7932
8103
|
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
8104
|
const hostHome = opts.hostHome ?? homedir11();
|
|
8105
|
+
const cloudBackup = join14(hostHome, ".agentbox", "codex-credentials.json");
|
|
8106
|
+
if (await pathExists7(cloudBackup)) {
|
|
8107
|
+
return stageSingleFileTarball("codex-creds", cloudBackup, "auth.json");
|
|
8108
|
+
}
|
|
7937
8109
|
const hostAuth = join14(hostHome, ".codex", "auth.json");
|
|
7938
8110
|
if (!await pathExists7(hostAuth)) return emptyResult([CODEX_KEYCHAIN_WARNING]);
|
|
7939
8111
|
return stageSingleFileTarball("codex-creds", hostAuth, "auth.json");
|
|
@@ -7991,16 +8163,17 @@ async function stageOpencodeStaticForUpload(opts = {}) {
|
|
|
7991
8163
|
warnings: []
|
|
7992
8164
|
};
|
|
7993
8165
|
} catch (err) {
|
|
7994
|
-
await
|
|
7995
|
-
if (tarballPath) await
|
|
8166
|
+
await rm6(stageDir, { recursive: true, force: true });
|
|
8167
|
+
if (tarballPath) await rm6(tarballPath, { force: true });
|
|
7996
8168
|
throw err;
|
|
7997
8169
|
}
|
|
7998
8170
|
}
|
|
7999
8171
|
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
8172
|
const hostHome = opts.hostHome ?? homedir11();
|
|
8173
|
+
const cloudBackup = join14(hostHome, ".agentbox", "opencode-credentials.json");
|
|
8174
|
+
if (await pathExists7(cloudBackup)) {
|
|
8175
|
+
return stageSingleFileTarball("opencode-creds", cloudBackup, "auth.json");
|
|
8176
|
+
}
|
|
8004
8177
|
const hostAuth = join14(hostHome, ".local", "share", "opencode", "auth.json");
|
|
8005
8178
|
if (!await pathExists7(hostAuth)) return emptyResult();
|
|
8006
8179
|
return stageSingleFileTarball("opencode-creds", hostAuth, "auth.json");
|
|
@@ -8123,6 +8296,11 @@ export {
|
|
|
8123
8296
|
CODEX_CREDENTIALS_BACKUP_FILE,
|
|
8124
8297
|
OPENCODE_CREDENTIALS_BACKUP_FILE,
|
|
8125
8298
|
isRealAgentCredential,
|
|
8299
|
+
hostClaudeBackupExpired,
|
|
8300
|
+
parseExtractResult,
|
|
8301
|
+
extractVolumeAuthToBackup,
|
|
8302
|
+
extractCodexCredentials,
|
|
8303
|
+
extractOpencodeCredentials,
|
|
8126
8304
|
hostBackupHasCredentials,
|
|
8127
8305
|
parseSyncResult,
|
|
8128
8306
|
syncClaudeCredentials,
|
|
@@ -8268,4 +8446,4 @@ export {
|
|
|
8268
8446
|
browserSessionActive,
|
|
8269
8447
|
ensureBoxBrowser
|
|
8270
8448
|
};
|
|
8271
|
-
//# sourceMappingURL=chunk-
|
|
8449
|
+
//# sourceMappingURL=chunk-CDKVD6UO.js.map
|