@madarco/agentbox 0.10.1 → 0.11.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/{_cloud-attach-2DGI6FUA.js → _cloud-attach-45ECDTRL.js} +4 -4
  3. package/dist/{chunk-MTVI44DW.js → chunk-ECLLV5JH.js} +6 -3
  4. package/dist/chunk-ECLLV5JH.js.map +1 -0
  5. package/dist/{chunk-M2UWJKFA.js → chunk-MXXXKJYS.js} +5 -5
  6. package/dist/chunk-MXXXKJYS.js.map +1 -0
  7. package/dist/{chunk-I7NOGCL4.js → chunk-PZ2TJF2U.js} +23 -11
  8. package/dist/chunk-PZ2TJF2U.js.map +1 -0
  9. package/dist/{chunk-I24B6AXR.js → chunk-R5XIDQFR.js} +6 -3
  10. package/dist/chunk-R5XIDQFR.js.map +1 -0
  11. package/dist/{chunk-PWUVHPN6.js → chunk-SNTHHWKY.js} +7 -3
  12. package/dist/chunk-SNTHHWKY.js.map +1 -0
  13. package/dist/{chunk-LEV3KICD.js → chunk-ZGVMN54V.js} +6 -3
  14. package/dist/{chunk-LEV3KICD.js.map → chunk-ZGVMN54V.js.map} +1 -1
  15. package/dist/{chunk-CDKVD6UO.js → chunk-ZJXTIH6C.js} +119 -87
  16. package/dist/chunk-ZJXTIH6C.js.map +1 -0
  17. package/dist/{dist-SBCQVFCE.js → dist-ASLPRUQR.js} +3 -3
  18. package/dist/{dist-BD5QJRDC.js → dist-PTJ6CEQY.js} +5 -5
  19. package/dist/{dist-SJHY3HYN.js → dist-RAZP76VX.js} +5 -5
  20. package/dist/{dist-BNI5PQYK.js → dist-WMQDMTWS.js} +5 -5
  21. package/dist/index.js +619 -546
  22. package/dist/index.js.map +1 -1
  23. package/dist/{prepared-state-MQHD3M5F-O5M4NIN4.js → prepared-state-MQHD3M5F-KE4DT3GX.js} +2 -2
  24. package/package.json +4 -4
  25. package/runtime/docker/packages/ctl/dist/bin.cjs +5 -2
  26. package/runtime/hetzner/ctl.cjs +5 -2
  27. package/runtime/relay/bin.cjs +37 -19
  28. package/runtime/vercel/ctl.cjs +5 -2
  29. package/runtime/vercel/scripts/provision.sh +20 -0
  30. package/dist/chunk-CDKVD6UO.js.map +0 -1
  31. package/dist/chunk-I24B6AXR.js.map +0 -1
  32. package/dist/chunk-I7NOGCL4.js.map +0 -1
  33. package/dist/chunk-M2UWJKFA.js.map +0 -1
  34. package/dist/chunk-MTVI44DW.js.map +0 -1
  35. package/dist/chunk-PWUVHPN6.js.map +0 -1
  36. /package/dist/{_cloud-attach-2DGI6FUA.js.map → _cloud-attach-45ECDTRL.js.map} +0 -0
  37. /package/dist/{dist-SBCQVFCE.js.map → dist-ASLPRUQR.js.map} +0 -0
  38. /package/dist/{dist-BD5QJRDC.js.map → dist-PTJ6CEQY.js.map} +0 -0
  39. /package/dist/{dist-SJHY3HYN.js.map → dist-RAZP76VX.js.map} +0 -0
  40. /package/dist/{dist-BNI5PQYK.js.map → dist-WMQDMTWS.js.map} +0 -0
  41. /package/dist/{prepared-state-MQHD3M5F-O5M4NIN4.js.map → prepared-state-MQHD3M5F-KE4DT3GX.js.map} +0 -0
@@ -9,6 +9,7 @@ import {
9
9
  detectGitRepos,
10
10
  ensureImage,
11
11
  findBox,
12
+ hostOpenCommand,
12
13
  imageExists,
13
14
  pickFreshBranch,
14
15
  preparedMatches,
@@ -18,10 +19,9 @@ import {
18
19
  readState,
19
20
  recordBox,
20
21
  removeBoxRecord
21
- } from "./chunk-PWUVHPN6.js";
22
+ } from "./chunk-SNTHHWKY.js";
22
23
 
23
24
  // ../../packages/sandbox-docker/dist/index.js
24
- import { randomBytes as randomBytes3 } from "crypto";
25
25
  import { mkdir as mkdir7, stat as stat6 } from "fs/promises";
26
26
  import { homedir as homedir9 } from "os";
27
27
  import { basename as basename3, join as join10, resolve as resolve3 } from "path";
@@ -1669,13 +1669,71 @@ import { stat as stat32 } from "fs/promises";
1669
1669
  import { homedir as homedir4 } from "os";
1670
1670
  import { join as join5 } from "path";
1671
1671
  import { execa as execa6 } from "execa";
1672
- import { randomBytes as randomBytes2 } from "crypto";
1672
+ import { randomBytes as randomBytes3 } from "crypto";
1673
1673
  import { execa as execa7 } from "execa";
1674
1674
  import { existsSync } from "fs";
1675
1675
  import { readFile as readFile42 } from "fs/promises";
1676
1676
  import { homedir as homedir5 } from "os";
1677
1677
  import { join as join6 } from "path";
1678
1678
  import { execa as execa8 } from "execa";
1679
+
1680
+ // ../../packages/core/dist/index.js
1681
+ import { randomBytes } from "crypto";
1682
+ var claudeCodeLauncher = {
1683
+ kind: "claude-code",
1684
+ // claude treats its first positional argument as the seed user turn in
1685
+ // interactive mode (`claude "<message>"`), so we slot the initial message
1686
+ // ahead of any user-passed flags.
1687
+ buildArgs(initialMessage, userArgs) {
1688
+ if (!initialMessage) return [...userArgs];
1689
+ return [initialMessage, ...userArgs];
1690
+ }
1691
+ };
1692
+ var codexLauncher = {
1693
+ kind: "codex",
1694
+ buildArgs(initialMessage, userArgs) {
1695
+ if (!initialMessage) return [...userArgs];
1696
+ return [initialMessage, ...userArgs];
1697
+ }
1698
+ };
1699
+ var opencodeLauncher = {
1700
+ kind: "opencode",
1701
+ buildArgs(initialMessage, userArgs) {
1702
+ if (!initialMessage) return [...userArgs];
1703
+ return [initialMessage, ...userArgs];
1704
+ }
1705
+ };
1706
+ function resolveAgentLauncher(kind) {
1707
+ if (kind === "claude-code") return claudeCodeLauncher;
1708
+ if (kind === "codex") return codexLauncher;
1709
+ if (kind === "opencode") return opencodeLauncher;
1710
+ throw new Error(`unknown agent kind: ${String(kind)}`);
1711
+ }
1712
+ var BoxNotFoundError = class extends Error {
1713
+ constructor(query) {
1714
+ super(`no agentbox matches "${query}"`);
1715
+ this.query = query;
1716
+ this.name = "BoxNotFoundError";
1717
+ }
1718
+ query;
1719
+ };
1720
+ var AmbiguousBoxError = class extends Error {
1721
+ constructor(query, matches) {
1722
+ const ids = matches.map((m) => m.id).join(", ");
1723
+ super(`"${query}" matches multiple boxes: ${ids}`);
1724
+ this.query = query;
1725
+ this.matches = matches;
1726
+ this.name = "AmbiguousBoxError";
1727
+ }
1728
+ query;
1729
+ matches;
1730
+ };
1731
+ var BOX_ID_PREFIX = "b";
1732
+ function generateBoxId() {
1733
+ return `${BOX_ID_PREFIX}${randomBytes(4).toString("hex")}`;
1734
+ }
1735
+
1736
+ // ../../packages/sandbox-docker/dist/index.js
1679
1737
  import { execa as execa9 } from "execa";
1680
1738
  import { mkdir as mkdir4, readdir as readdir22, rm as rm22, stat as stat4 } from "fs/promises";
1681
1739
  import { homedir as homedir6, platform } from "os";
@@ -1699,7 +1757,7 @@ import { setTimeout as delay2 } from "timers/promises";
1699
1757
  import { fileURLToPath } from "url";
1700
1758
 
1701
1759
  // ../../packages/relay/dist/index.js
1702
- import { createHash as createHash2, randomBytes } from "crypto";
1760
+ import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
1703
1761
  import { execa } from "execa";
1704
1762
  import { spawn as spawn4 } from "child_process";
1705
1763
  import {
@@ -1812,42 +1870,71 @@ async function loadQueue() {
1812
1870
  out.sort((a, b) => a.createdAt < b.createdAt ? -1 : a.createdAt > b.createdAt ? 1 : 0);
1813
1871
  return out;
1814
1872
  }
1873
+ function processAlive(pid) {
1874
+ try {
1875
+ process.kill(pid, 0);
1876
+ return true;
1877
+ } catch {
1878
+ return false;
1879
+ }
1880
+ }
1881
+ function countInFlightCreateJobs(jobs, accountedBoxIds) {
1882
+ let n = 0;
1883
+ for (const j of jobs) {
1884
+ if (j.status !== "running") continue;
1885
+ if (j.boxId && accountedBoxIds.has(j.boxId)) continue;
1886
+ if (typeof j.pid === "number" && !processAlive(j.pid)) continue;
1887
+ n += 1;
1888
+ }
1889
+ return n;
1890
+ }
1815
1891
  var RUNNING_COUNT_CACHE_MS = 3e3;
1816
- var runningCountCache = null;
1892
+ var boxStateCache = null;
1817
1893
  async function defaultCountRunningBoxes() {
1894
+ const { boxCount, stateIds } = await cachedBoxState();
1895
+ let jobs;
1896
+ try {
1897
+ jobs = await loadQueue();
1898
+ } catch {
1899
+ return boxCount;
1900
+ }
1901
+ return boxCount + countInFlightCreateJobs(jobs, stateIds);
1902
+ }
1903
+ async function cachedBoxState() {
1818
1904
  const now = Date.now();
1819
- if (runningCountCache && runningCountCache.expiresAt > now) {
1820
- return runningCountCache.value;
1905
+ if (boxStateCache && boxStateCache.expiresAt > now) {
1906
+ return { boxCount: boxStateCache.boxCount, stateIds: boxStateCache.stateIds };
1821
1907
  }
1822
- const value = await uncachedCountRunningBoxes();
1823
- runningCountCache = { value, expiresAt: now + RUNNING_COUNT_CACHE_MS };
1824
- return value;
1908
+ const fresh = await uncachedBoxStateCount();
1909
+ boxStateCache = { ...fresh, expiresAt: now + RUNNING_COUNT_CACHE_MS };
1910
+ return fresh;
1825
1911
  }
1826
- async function uncachedCountRunningBoxes() {
1912
+ async function uncachedBoxStateCount() {
1827
1913
  let boxes;
1828
1914
  try {
1829
1915
  boxes = (await readState(STATE_FILE)).boxes;
1830
1916
  } catch {
1831
- return 0;
1917
+ return { boxCount: 0, stateIds: /* @__PURE__ */ new Set() };
1832
1918
  }
1833
- if (boxes.length === 0) return 0;
1834
- let count = 0;
1919
+ const stateIds = new Set(boxes.map((b) => b.id));
1920
+ if (boxes.length === 0) return { boxCount: 0, stateIds };
1921
+ let boxCount = 0;
1835
1922
  const dockerBoxes = [];
1836
1923
  for (const b of boxes) {
1837
1924
  const provider = b.provider ?? "docker";
1838
1925
  if (provider === "docker") {
1839
1926
  dockerBoxes.push(b);
1840
1927
  } else {
1841
- count += 1;
1928
+ boxCount += 1;
1842
1929
  }
1843
1930
  }
1844
1931
  if (dockerBoxes.length > 0) {
1845
1932
  const states = await Promise.all(dockerBoxes.map((b) => inspectDockerState(b.container)));
1846
1933
  for (const s of states) {
1847
- if (s === "running") count += 1;
1934
+ if (s === "running") boxCount += 1;
1848
1935
  }
1849
1936
  }
1850
- return count;
1937
+ return { boxCount, stateIds };
1851
1938
  }
1852
1939
  function inspectDockerState(containerName) {
1853
1940
  return new Promise((resolveP) => {
@@ -1887,59 +1974,6 @@ function queueLogPath(id) {
1887
1974
  import { execa as execa15 } from "execa";
1888
1975
  import { readdir as readdir5, rm as rm5, stat as stat7 } from "fs/promises";
1889
1976
  import { join as join12 } from "path";
1890
-
1891
- // ../../packages/core/dist/index.js
1892
- var claudeCodeLauncher = {
1893
- kind: "claude-code",
1894
- // claude treats its first positional argument as the seed user turn in
1895
- // interactive mode (`claude "<message>"`), so we slot the initial message
1896
- // ahead of any user-passed flags.
1897
- buildArgs(initialMessage, userArgs) {
1898
- if (!initialMessage) return [...userArgs];
1899
- return [initialMessage, ...userArgs];
1900
- }
1901
- };
1902
- var codexLauncher = {
1903
- kind: "codex",
1904
- buildArgs(initialMessage, userArgs) {
1905
- if (!initialMessage) return [...userArgs];
1906
- return [initialMessage, ...userArgs];
1907
- }
1908
- };
1909
- var opencodeLauncher = {
1910
- kind: "opencode",
1911
- buildArgs(initialMessage, userArgs) {
1912
- if (!initialMessage) return [...userArgs];
1913
- return [initialMessage, ...userArgs];
1914
- }
1915
- };
1916
- function resolveAgentLauncher(kind) {
1917
- if (kind === "claude-code") return claudeCodeLauncher;
1918
- if (kind === "codex") return codexLauncher;
1919
- if (kind === "opencode") return opencodeLauncher;
1920
- throw new Error(`unknown agent kind: ${String(kind)}`);
1921
- }
1922
- var BoxNotFoundError = class extends Error {
1923
- constructor(query) {
1924
- super(`no agentbox matches "${query}"`);
1925
- this.query = query;
1926
- this.name = "BoxNotFoundError";
1927
- }
1928
- query;
1929
- };
1930
- var AmbiguousBoxError = class extends Error {
1931
- constructor(query, matches) {
1932
- const ids = matches.map((m) => m.id).join(", ");
1933
- super(`"${query}" matches multiple boxes: ${ids}`);
1934
- this.query = query;
1935
- this.matches = matches;
1936
- this.name = "AmbiguousBoxError";
1937
- }
1938
- query;
1939
- matches;
1940
- };
1941
-
1942
- // ../../packages/sandbox-docker/dist/index.js
1943
1977
  import { execa as execa14 } from "execa";
1944
1978
  import { join as join11 } from "path";
1945
1979
  import { homedir as homedir10 } from "os";
@@ -2693,7 +2727,7 @@ async function openInFinder(record, opts) {
2693
2727
  usedFallback = refreshed.usedFallback;
2694
2728
  }
2695
2729
  if (!opts.noOpen) {
2696
- const opened = await execa22("open", [hostPath], { reject: false });
2730
+ const opened = await execa22(hostOpenCommand(), [hostPath], { reject: false });
2697
2731
  if (opened.exitCode !== 0) {
2698
2732
  throw new ExportError(`open ${hostPath} failed`, opened.stdout, opened.stderr);
2699
2733
  }
@@ -4607,7 +4641,7 @@ async function launchVncDaemon(container, timeoutMs = 5e3) {
4607
4641
  }
4608
4642
  var VNC_PASSWORD_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4609
4643
  function generateVncPassword() {
4610
- const bytes = randomBytes2(8);
4644
+ const bytes = randomBytes3(8);
4611
4645
  let out = "";
4612
4646
  for (let i = 0; i < 8; i++) {
4613
4647
  out += VNC_PASSWORD_ALPHABET[bytes[i] % VNC_PASSWORD_ALPHABET.length];
@@ -5459,7 +5493,7 @@ async function ensureRelay(opts = {}) {
5459
5493
  await reclaimRelay(health.pid, log);
5460
5494
  } else {
5461
5495
  const existingPid = await readPidFile();
5462
- if (existingPid !== null && await processAlive(existingPid)) {
5496
+ if (existingPid !== null && await processAlive2(existingPid)) {
5463
5497
  for (let i = 0; i < 10; i++) {
5464
5498
  if (await pingHealthz(300)) return ENDPOINT;
5465
5499
  await delay2(200);
@@ -5488,7 +5522,7 @@ async function reclaimRelay(reportedPid, log) {
5488
5522
  for (const pid of [reportedPid, pidFromFile]) {
5489
5523
  if (typeof pid !== "number" || pid <= 0 || seen.has(pid)) continue;
5490
5524
  seen.add(pid);
5491
- if (!await processAlive(pid)) continue;
5525
+ if (!await processAlive2(pid)) continue;
5492
5526
  log(`stopping crippled relay pid ${String(pid)}`);
5493
5527
  await killPid(pid);
5494
5528
  }
@@ -5507,7 +5541,7 @@ async function killPid(pid) {
5507
5541
  return;
5508
5542
  }
5509
5543
  for (let i = 0; i < 20; i++) {
5510
- if (!await processAlive(pid)) return;
5544
+ if (!await processAlive2(pid)) return;
5511
5545
  await delay2(100);
5512
5546
  }
5513
5547
  try {
@@ -5658,7 +5692,7 @@ async function stopRelay() {
5658
5692
  if (pid === null) {
5659
5693
  return { stopped: false, pid: null };
5660
5694
  }
5661
- if (!await processAlive(pid)) {
5695
+ if (!await processAlive2(pid)) {
5662
5696
  await unlink2(PID_FILE).catch(() => {
5663
5697
  });
5664
5698
  return { stopped: false, pid };
@@ -5668,10 +5702,10 @@ async function stopRelay() {
5668
5702
  } catch {
5669
5703
  }
5670
5704
  for (let i = 0; i < 20; i++) {
5671
- if (!await processAlive(pid)) break;
5705
+ if (!await processAlive2(pid)) break;
5672
5706
  await delay2(100);
5673
5707
  }
5674
- if (await processAlive(pid)) {
5708
+ if (await processAlive2(pid)) {
5675
5709
  try {
5676
5710
  process.kill(pid, "SIGKILL");
5677
5711
  } catch {
@@ -5683,7 +5717,7 @@ async function stopRelay() {
5683
5717
  }
5684
5718
  async function getRelayStatus() {
5685
5719
  const pid = await readPidFile();
5686
- const pidAlive2 = pid !== null && await processAlive(pid);
5720
+ const pidAlive2 = pid !== null && await processAlive2(pid);
5687
5721
  const health = await fetchHealthz(300);
5688
5722
  return {
5689
5723
  running: health !== null,
@@ -5767,7 +5801,7 @@ async function readPidFile() {
5767
5801
  return null;
5768
5802
  }
5769
5803
  }
5770
- async function processAlive(pid) {
5804
+ async function processAlive2(pid) {
5771
5805
  try {
5772
5806
  process.kill(pid, 0);
5773
5807
  return true;
@@ -6087,9 +6121,6 @@ function persistableLimits(lim) {
6087
6121
  if (lim.disk) out.disk = lim.disk;
6088
6122
  return Object.keys(out).length > 0 ? out : void 0;
6089
6123
  }
6090
- function generateBoxId() {
6091
- return randomBytes3(4).toString("hex");
6092
- }
6093
6124
  function sanitizeBasename(workspacePath) {
6094
6125
  const raw = basename3(resolve3(workspacePath));
6095
6126
  return raw.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^[-._]+|[-._]+$/g, "").slice(0, 30).replace(/[-._]+$/, "");
@@ -8228,6 +8259,10 @@ export {
8228
8259
  renderTaskTable,
8229
8260
  renderPortsTable,
8230
8261
  loadCarrySection,
8262
+ resolveAgentLauncher,
8263
+ BoxNotFoundError,
8264
+ AmbiguousBoxError,
8265
+ generateBoxId,
8231
8266
  DEFAULT_RELAY_PORT,
8232
8267
  RELAY_CONTAINER_NAME,
8233
8268
  RELAY_NETWORK_NAME,
@@ -8242,9 +8277,6 @@ export {
8242
8277
  loadQueue,
8243
8278
  defaultCountRunningBoxes,
8244
8279
  queueLogPath,
8245
- resolveAgentLauncher,
8246
- BoxNotFoundError,
8247
- AmbiguousBoxError,
8248
8280
  execInBox,
8249
8281
  removeImage,
8250
8282
  volumeExists,
@@ -8446,4 +8478,4 @@ export {
8446
8478
  browserSessionActive,
8447
8479
  ensureBoxBrowser
8448
8480
  };
8449
- //# sourceMappingURL=chunk-CDKVD6UO.js.map
8481
+ //# sourceMappingURL=chunk-ZJXTIH6C.js.map