@madarco/agentbox 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-3NU4PS5W.js → chunk-3JKQNOXP.js} +11 -4
- package/dist/chunk-3JKQNOXP.js.map +1 -0
- package/dist/{chunk-3OPLNXQ5.js → chunk-3NCUES35.js} +2 -2
- package/dist/{chunk-3NIZKZPJ.js → chunk-MOC54XL6.js} +1 -1
- package/dist/{chunk-3NIZKZPJ.js.map → chunk-MOC54XL6.js.map} +1 -1
- package/dist/{create-SE6H4B5U-ESNDTXAI.js → create-SE6H4B5U-IWAZHJHV.js} +3 -3
- package/dist/index.js +342 -62
- package/dist/index.js.map +1 -1
- package/dist/{lifecycle-A4QHFADW-4DREGGAE.js → lifecycle-YTMZYKOE-TD5S5FTS.js} +3 -3
- package/package.json +3 -3
- package/runtime/docker/Dockerfile.box +1 -0
- package/runtime/docker/packages/ctl/dist/bin.cjs +24 -3
- package/dist/chunk-3NU4PS5W.js.map +0 -1
- /package/dist/{chunk-3OPLNXQ5.js.map → chunk-3NCUES35.js.map} +0 -0
- /package/dist/{create-SE6H4B5U-ESNDTXAI.js.map → create-SE6H4B5U-IWAZHJHV.js.map} +0 -0
- /package/dist/{lifecycle-A4QHFADW-4DREGGAE.js.map → lifecycle-YTMZYKOE-TD5S5FTS.js.map} +0 -0
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
removeBoxWorktree,
|
|
26
26
|
verifyOverlay,
|
|
27
27
|
vscodeServerVolumeName
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-MOC54XL6.js";
|
|
29
29
|
import {
|
|
30
30
|
findBox,
|
|
31
31
|
readState,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
volumeExists
|
|
57
57
|
} from "./chunk-SOMIKEN2.js";
|
|
58
58
|
|
|
59
|
-
// ../../packages/sandbox-docker/dist/chunk-
|
|
59
|
+
// ../../packages/sandbox-docker/dist/chunk-6GQGGQBQ.js
|
|
60
60
|
import { execa } from "execa";
|
|
61
61
|
import { readdir, rm, stat } from "fs/promises";
|
|
62
62
|
import { join as join2 } from "path";
|
|
@@ -129,7 +129,13 @@ async function listBoxes() {
|
|
|
129
129
|
const state = await inspectContainerStatus(b.container);
|
|
130
130
|
const persisted = await readBoxStatus(b.id);
|
|
131
131
|
const endpoints = await getBoxEndpoints(b, engine, persisted);
|
|
132
|
-
return {
|
|
132
|
+
return {
|
|
133
|
+
...b,
|
|
134
|
+
state,
|
|
135
|
+
endpoints,
|
|
136
|
+
claudeActivity: persisted?.claude.state,
|
|
137
|
+
claudeSessionTitle: persisted?.claude.sessionTitle
|
|
138
|
+
};
|
|
133
139
|
})
|
|
134
140
|
);
|
|
135
141
|
}
|
|
@@ -498,6 +504,7 @@ async function snapshotPresent(path) {
|
|
|
498
504
|
}
|
|
499
505
|
|
|
500
506
|
export {
|
|
507
|
+
getBoxEndpoints,
|
|
501
508
|
listBoxes,
|
|
502
509
|
BoxNotFoundError,
|
|
503
510
|
AmbiguousBoxError,
|
|
@@ -512,4 +519,4 @@ export {
|
|
|
512
519
|
pruneBoxes,
|
|
513
520
|
snapshotPresent
|
|
514
521
|
};
|
|
515
|
-
//# sourceMappingURL=chunk-
|
|
522
|
+
//# sourceMappingURL=chunk-3JKQNOXP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../packages/sandbox-docker/src/lifecycle.ts","../../../packages/sandbox-docker/src/endpoints.ts"],"sourcesContent":["import { execa } from 'execa';\nimport { readdir, rm, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { BoxState } from '@agentbox/core';\nimport type { BoxStatus, ClaudeActivityState } from '@agentbox/ctl';\nimport { claudeSessionInfo, SHARED_CLAUDE_VOLUME, type ClaudeSessionInfo } from './claude.js';\nimport { removeBoxWorktree } from './git-worktree.js';\nimport {\n cursorServerVolumeName,\n SHARED_CURSOR_EXTENSIONS_VOLUME,\n SHARED_VSCODE_EXTENSIONS_VOLUME,\n vscodeServerVolumeName,\n} from './vscode.js';\nimport {\n BOXES_ROOT,\n boxRunDirFor,\n detectEngine,\n getHostPaths,\n openInFinder,\n readBoxStatus,\n type HostPaths,\n type OpenOptions,\n type OpenResult,\n} from './host-export.js';\nimport {\n inspectContainer,\n inspectContainerStatus,\n inspectVolumeMountpoint,\n listAgentboxContainers,\n listAgentboxVolumes,\n pauseContainer,\n publishedHostPort,\n removeContainer,\n removeNetwork,\n removeVolume,\n startContainer,\n stopContainer,\n unpauseContainer,\n volumeExists,\n} from './docker.js';\nimport {\n DEFAULT_LOWER_DIRS,\n mountOverlay,\n verifyOverlay,\n type NestedWorktreeBind,\n type OverlayCheck,\n} from './overlay.js';\nimport { CHECKPOINT_VOLUME_PREFIX } from './checkpoint.js';\nimport { launchCtlDaemon } from './ctl.js';\nimport { launchDockerdDaemon, SHARED_DOCKER_CACHE_VOLUME } from './dockerd.js';\nimport { launchVncDaemon, VNC_CONTAINER_PORT } from './vnc.js';\nimport { WEB_CONTAINER_PORT } from './web.js';\nimport { getBoxEndpoints, type BoxEndpoints } from './endpoints.js';\nimport {\n ensureRelay,\n forgetBoxFromRelay,\n registerBoxWithRelay,\n RELAY_CONTAINER_NAME,\n RELAY_IMAGE_REF,\n RELAY_NETWORK_NAME,\n} from './relay.js';\nimport { SNAPSHOTS_ROOT } from './snapshot.js';\nimport {\n findBox,\n readState,\n recordBox,\n removeBoxRecord,\n type BoxRecord,\n type FindBoxResult,\n} from './state.js';\n\nexport interface ListedBox extends BoxRecord {\n state: BoxState;\n endpoints: BoxEndpoints;\n /** From the persisted status file; undefined for pre-feature/never-pushed boxes. */\n claudeActivity?: ClaudeActivityState;\n /** Sanitized in-box terminal title Claude set; undefined when none. */\n claudeSessionTitle?: string;\n}\n\nexport async function listBoxes(): Promise<ListedBox[]> {\n const { boxes } = await readState();\n const engine = await detectEngine();\n return Promise.all(\n boxes.map(async (b): Promise<ListedBox> => {\n const state = await inspectContainerStatus(b.container);\n const persisted = await readBoxStatus(b.id);\n const endpoints = await getBoxEndpoints(b, engine, persisted);\n return {\n ...b,\n state,\n endpoints,\n claudeActivity: persisted?.claude.state,\n claudeSessionTitle: persisted?.claude.sessionTitle,\n };\n }),\n );\n}\n\nexport class BoxNotFoundError extends Error {\n constructor(public readonly query: string) {\n super(`no agentbox matches \"${query}\"`);\n this.name = 'BoxNotFoundError';\n }\n}\n\nexport class AmbiguousBoxError extends Error {\n constructor(\n public readonly query: string,\n public readonly matches: BoxRecord[],\n ) {\n const ids = matches.map((m) => m.id).join(', ');\n super(`\"${query}\" matches multiple boxes: ${ids}`);\n this.name = 'AmbiguousBoxError';\n }\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function resolveBox(idOrName: string): Promise<BoxRecord> {\n const state = await readState();\n const result: FindBoxResult = findBox(idOrName, state);\n switch (result.kind) {\n case 'ok':\n return result.box;\n case 'none':\n throw new BoxNotFoundError(idOrName);\n case 'ambiguous':\n throw new AmbiguousBoxError(idOrName, result.matches);\n }\n}\n\nexport async function pauseBox(idOrName: string): Promise<BoxRecord> {\n const box = await resolveBox(idOrName);\n await pauseContainer(box.container);\n return box;\n}\n\nexport async function unpauseBox(idOrName: string): Promise<BoxRecord> {\n const box = await resolveBox(idOrName);\n await unpauseContainer(box.container);\n return box;\n}\n\nexport async function stopBox(idOrName: string): Promise<BoxRecord> {\n const box = await resolveBox(idOrName);\n await stopContainer(box.container);\n return box;\n}\n\nexport interface StartedBox {\n record: BoxRecord;\n overlayChecks: OverlayCheck[];\n}\n\nexport async function startBox(idOrName: string): Promise<StartedBox> {\n const box = await resolveBox(idOrName);\n // Bind mounts are baked into the container at create time; if a worktree\n // dir has been deleted out from under us we can't recover by restarting\n // (Docker just fails the start with an opaque mount error). Surface a clear\n // message up front so the user knows to recreate the box or restore the\n // worktree.\n for (const w of box.gitWorktrees ?? []) {\n if (!(await pathExists(w.hostWorktreeDir))) {\n throw new Error(`box worktree missing on host: ${w.hostWorktreeDir} (recreate the box)`);\n }\n if (!(await pathExists(join(w.hostMainRepo, '.git')))) {\n throw new Error(\n `main repo for box worktree missing: ${join(w.hostMainRepo, '.git')} (recreate the box)`,\n );\n }\n }\n // The per-project checkpoint volume is mounted read-only at create time,\n // same baked-in story as worktrees — if it was removed we can't recover by\n // restart, so fail loudly up front. (A removed checkpoint *subdir* instead\n // surfaces as a loud mountOverlay failure, same as a missing worktree dir.)\n if (box.checkpointVolume && !(await volumeExists(box.checkpointVolume))) {\n throw new Error(\n `box checkpoint volume missing: ${box.checkpointVolume} (recreate the box)`,\n );\n }\n await startContainer(box.container);\n const nestedWorktrees: NestedWorktreeBind[] = (box.gitWorktrees ?? [])\n .filter((w) => w.kind === 'nested')\n .map((w) => ({\n containerPath: w.containerPath,\n mountFromPath: `/agentbox-worktrees/${w.relPathFromWorkspace}`,\n }));\n const lowerDirs = box.lowerDirs && box.lowerDirs.length > 0 ? box.lowerDirs : undefined;\n await mountOverlay(box.container, { lowerDirs, nestedWorktrees });\n const overlayChecks = await verifyOverlay(box.container, lowerDirs ?? DEFAULT_LOWER_DIRS);\n if (box.socketPath) {\n // The daemon died with the container; relaunch it. Best-effort, same as\n // create.ts — a missing config or other startup issue shouldn't block\n // resumption of the box itself.\n await launchCtlDaemon(box.container, box.socketPath);\n }\n // dockerd dies with the container too; relaunch it. Records from before\n // DinD landed have no `dockerVolume`, so we skip them — those boxes were\n // created without the in-box dockerd and don't have the launch script\n // baked in either (image rebuild is required to pick it up).\n if (box.dockerVolume) {\n await launchDockerdDaemon(box.container);\n }\n if (box.vncEnabled) {\n // Xvnc + websockify both die with the container. The password is already\n // in the container env (set at `docker run` time and preserved across\n // start/stop), so we don't need to forward it here.\n await launchVncDaemon(box.container);\n // Docker re-allocates an ephemeral host port for `-p 0:6080` on every\n // `start`, so the loopback URL from create time is stale. Re-resolve and\n // persist; the orb.local URL is name-based and unaffected. Best-effort —\n // a failed resolve just leaves the record as-is.\n const freshHostPort = await publishedHostPort(box.container, VNC_CONTAINER_PORT);\n if (freshHostPort && freshHostPort !== box.vncHostPort) {\n box.vncHostPort = freshHostPort;\n await recordBox(box);\n }\n }\n // Same ephemeral-reallocation story for the reserved web port. Gated on\n // webContainerPort so pre-feature boxes (no `-p 0:80` mapping) are skipped.\n if (box.webContainerPort !== undefined) {\n const freshWebPort = await publishedHostPort(\n box.container,\n box.webContainerPort ?? WEB_CONTAINER_PORT,\n );\n if (freshWebPort && freshWebPort !== box.webHostPort) {\n box.webHostPort = freshWebPort;\n await recordBox(box);\n }\n }\n // Relay's in-memory registry may have been lost if the relay restarted\n // between create and now (or this is the first start after a host reboot).\n // Re-ensure + re-register so outbound push from the box keeps working.\n if (box.relayToken) {\n try {\n await ensureRelay();\n await registerBoxWithRelay({\n boxId: box.id,\n token: box.relayToken,\n name: box.name,\n containerName: box.container,\n createdAt: box.createdAt,\n worktrees: box.gitWorktrees,\n });\n } catch {\n // best-effort\n }\n }\n return { record: box, overlayChecks };\n}\n\nexport interface OpenedBox extends OpenResult {\n record: BoxRecord;\n}\n\nexport async function openBoxInFinder(idOrName: string, opts: OpenOptions): Promise<OpenedBox> {\n const box = await resolveBox(idOrName);\n const result = await openInFinder(box, opts);\n return { ...result, record: box };\n}\n\nexport async function getBoxHostPaths(\n idOrName: string,\n): Promise<{ record: BoxRecord; paths: HostPaths }> {\n const box = await resolveBox(idOrName);\n const paths = await getHostPaths(box);\n return { record: box, paths };\n}\n\nexport interface InspectedBox {\n record: BoxRecord;\n state: BoxState;\n upperVolume: { name: string; mountpoint: string | null };\n snapshotSizeBytes: number | null;\n overlayMounted: boolean;\n dockerInspect: unknown;\n /** Null when the container isn't running; otherwise best-effort probe of the tmux 'claude' session. */\n claudeSession: ClaudeSessionInfo | null;\n /** Persisted status snapshot (services/tasks/ports/claude); null when none. */\n persistedStatus: BoxStatus | null;\n /** Host paths for `agentbox open` / `agentbox path`. */\n hostPaths: HostPaths;\n /** Box network surface: domain + VNC + service ports. */\n endpoints: BoxEndpoints;\n}\n\nasync function dirSizeBytes(path: string): Promise<number | null> {\n try {\n const result = await execa('du', ['-sk', path], { reject: false });\n if (result.exitCode !== 0) return null;\n const sizeKb = Number.parseInt((result.stdout ?? '').split(/\\s+/)[0] ?? '', 10);\n if (Number.isNaN(sizeKb)) return null;\n return sizeKb * 1024;\n } catch {\n return null;\n }\n}\n\nexport async function inspectBox(idOrName: string): Promise<InspectedBox> {\n const record = await resolveBox(idOrName);\n const state = await inspectContainerStatus(record.container);\n const upperMountpoint = await inspectVolumeMountpoint(record.upperVolume);\n const snapshotSizeBytes = record.snapshotDir ? await dirSizeBytes(record.snapshotDir) : null;\n const dockerJson = await inspectContainer(record.container);\n\n let overlayMounted = false;\n if (state === 'running' || state === 'paused') {\n const probe = await execa(\n 'docker',\n ['exec', '--user', 'root', record.container, 'mountpoint', '-q', '/workspace'],\n { reject: false },\n );\n overlayMounted = probe.exitCode === 0;\n }\n\n let claudeSession: ClaudeSessionInfo | null = null;\n if (state === 'running') {\n try {\n claudeSession = await claudeSessionInfo(record.container);\n } catch {\n claudeSession = null;\n }\n }\n\n const hostPaths = await getHostPaths(record);\n const engine = await detectEngine();\n const persistedStatus = await readBoxStatus(record.id);\n const endpoints = await getBoxEndpoints(record, engine, persistedStatus);\n\n return {\n record,\n state,\n upperVolume: { name: record.upperVolume, mountpoint: upperMountpoint },\n snapshotSizeBytes,\n overlayMounted,\n dockerInspect: dockerJson,\n claudeSession,\n persistedStatus,\n hostPaths,\n endpoints,\n };\n}\n\nexport interface DestroyOptions {\n keepSnapshot?: boolean;\n}\n\nexport interface DestroyResult {\n record: BoxRecord;\n removedContainer: boolean;\n removedVolumes: string[];\n removedSnapshot: string | null;\n}\n\nexport async function destroyBox(\n idOrName: string,\n opts: DestroyOptions = {},\n): Promise<DestroyResult> {\n const box = await resolveBox(idOrName);\n\n // Each step is best-effort. We collect what actually went away so the CLI\n // can show a truthful summary even if e.g. the container was gone already.\n if (box.relayToken) {\n try {\n await forgetBoxFromRelay(box.id);\n } catch {\n // best-effort — relay may be down or already wiped the entry\n }\n }\n // Remove the git worktrees on the host before nuking the container. The\n // worktree dirs live under the per-box run dir (which is wiped further\n // down), but we also need to deregister them from the main repo's\n // .git/worktrees/ so subsequent `git worktree list` on the host doesn't\n // see stale entries.\n for (const w of box.gitWorktrees ?? []) {\n try {\n await removeBoxWorktree({ hostMainRepo: w.hostMainRepo, worktreeDir: w.hostWorktreeDir });\n } catch {\n // best-effort\n }\n }\n const beforeContainer = await inspectContainerStatus(box.container);\n await removeContainer(box.container);\n const afterContainer = await inspectContainerStatus(box.container);\n const removedContainer = beforeContainer !== 'missing' && afterContainer === 'missing';\n\n const removedVolumes: string[] = [];\n // The dedicated agentbox-nm-<id> volume was removed (node_modules now lives\n // in the per-box overlay upper). Boxes created before that change still have\n // the volume on disk; removeVolume is a no-op for newer boxes that lack it.\n const legacyNodeModulesVolume = `agentbox-nm-${box.id}`;\n for (const v of [box.upperVolume, legacyNodeModulesVolume]) {\n await removeVolume(v);\n removedVolumes.push(v);\n }\n // Per-box claude config volumes are box-private — safe to remove. The shared\n // SHARED_CLAUDE_VOLUME holds user identity (auth, skills, plugins) across\n // every box, so never auto-remove it; users delete it manually if they want.\n if (box.claudeConfigVolume && box.claudeConfigVolume !== SHARED_CLAUDE_VOLUME) {\n await removeVolume(box.claudeConfigVolume);\n removedVolumes.push(box.claudeConfigVolume);\n }\n // Per-box `.vscode-server` and `.cursor-server` volumes. The shared\n // SHARED_*_EXTENSIONS_VOLUMEs are never auto-removed (parallel reasoning to\n // the shared claude volume). Volume names default-derived from `box.id` for\n // boxes created before these fields were recorded.\n const perBoxIdeVolumes = [\n box.vscodeServerVolume ?? vscodeServerVolumeName(box.id),\n box.cursorServerVolume ?? cursorServerVolumeName(box.id),\n ];\n for (const v of perBoxIdeVolumes) {\n await removeVolume(v);\n removedVolumes.push(v);\n }\n // Per-box dockerd data root. Skip when this box used the shared cache —\n // wiping it would also remove image layers other boxes (or future ones)\n // depend on. The shared volume is allowlisted in `pruneBoxes --all` too.\n if (box.dockerVolume && !box.dockerCacheShared) {\n await removeVolume(box.dockerVolume);\n removedVolumes.push(box.dockerVolume);\n }\n\n let removedSnapshot: string | null = null;\n if (box.snapshotDir && !opts.keepSnapshot) {\n try {\n await rm(box.snapshotDir, { recursive: true, force: true });\n removedSnapshot = box.snapshotDir;\n } catch {\n removedSnapshot = null;\n }\n }\n\n // The per-box runtime dir holds the ctl socket plus the workspace/upper\n // export dirs used by `agentbox open`. Wipe the whole thing so destroy\n // leaves no residue under ~/.agentbox/boxes/.\n try {\n await rm(boxRunDirFor(box.id), { recursive: true, force: true });\n } catch {\n // best-effort\n }\n\n await removeBoxRecord(box.id);\n\n return { record: box, removedContainer, removedVolumes, removedSnapshot };\n}\n\nexport interface PruneOptions {\n dryRun?: boolean;\n all?: boolean;\n}\n\nexport interface PruneResult {\n removedRecords: string[];\n removedContainers: string[];\n removedVolumes: string[];\n removedSnapshotDirs: string[];\n removedBoxDirs: string[];\n dryRun: boolean;\n}\n\nasync function listSnapshotDirs(): Promise<string[]> {\n try {\n const entries = await readdir(SNAPSHOTS_ROOT, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => join(SNAPSHOTS_ROOT, e.name));\n } catch {\n return [];\n }\n}\n\nasync function listBoxDirs(): Promise<string[]> {\n try {\n const entries = await readdir(BOXES_ROOT, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => join(BOXES_ROOT, e.name));\n } catch {\n return [];\n }\n}\n\nexport async function pruneBoxes(opts: PruneOptions = {}): Promise<PruneResult> {\n const dryRun = opts.dryRun ?? false;\n const all = opts.all ?? false;\n\n const { boxes } = await readState();\n\n // Step 1: missing-state records.\n const stateChecks = await Promise.all(\n boxes.map(async (b) => ({ box: b, status: await inspectContainerStatus(b.container) })),\n );\n const missingRecords = stateChecks.filter((c) => c.status === 'missing').map((c) => c.box);\n\n // Step 2 (only with --all): orphan docker containers / volumes / snapshot dirs / per-box dirs.\n let orphanContainers: string[] = [];\n let orphanVolumes: string[] = [];\n let orphanSnapshots: string[] = [];\n let orphanBoxDirs: string[] = [];\n\n if (all) {\n const liveContainers = await listAgentboxContainers();\n const liveVolumes = await listAgentboxVolumes();\n const liveSnapshotDirs = await listSnapshotDirs();\n const liveBoxDirs = await listBoxDirs();\n // The state we'd have AFTER step 1 runs: missing-state records gone.\n const survivingBoxes = boxes.filter((b) => !missingRecords.some((m) => m.id === b.id));\n const expectedContainers = new Set<string>([\n ...survivingBoxes.map((b) => b.container),\n // The relay no longer runs as a container (it's a host node process\n // now). Any agentbox-relay container is a leftover from a previous\n // version of agentbox; it will be collected as an orphan below.\n ]);\n const expectedVolumes = new Set<string>([\n // agentbox-nm-<id> reconstructed for back-compat: a surviving box\n // created before the nm volume was removed still mounts it, so it must\n // stay allowlisted. Inert for newer boxes (no such volume exists).\n ...survivingBoxes.flatMap((b) => [b.upperVolume, `agentbox-nm-${b.id}`]),\n ...survivingBoxes\n .map((b) => b.claudeConfigVolume)\n .filter((v): v is string => typeof v === 'string'),\n ...survivingBoxes\n .map((b) => b.vscodeServerVolume)\n .filter((v): v is string => typeof v === 'string'),\n ...survivingBoxes\n .map((b) => b.cursorServerVolume)\n .filter((v): v is string => typeof v === 'string'),\n ...survivingBoxes\n .map((b) => b.dockerVolume)\n .filter((v): v is string => typeof v === 'string'),\n // The shared claude-config volume holds user identity across every box;\n // never reap it via prune even if no surviving box currently references it.\n SHARED_CLAUDE_VOLUME,\n // Shared across boxes: downloaded IDE extensions. Same reasoning.\n SHARED_VSCODE_EXTENSIONS_VOLUME,\n SHARED_CURSOR_EXTENSIONS_VOLUME,\n // Shared in-box docker image cache — opt-in via `box.dockerCacheShared`,\n // never auto-removed (image layers may be reused by future boxes).\n SHARED_DOCKER_CACHE_VOLUME,\n ]);\n const expectedSnapshots = new Set(\n survivingBoxes\n .filter((b): b is BoxRecord & { snapshotDir: string } => b.snapshotDir !== null)\n .map((b) => b.snapshotDir),\n );\n const expectedBoxDirs = new Set(survivingBoxes.map((b) => boxRunDirFor(b.id)));\n orphanContainers = liveContainers.filter((c) => !expectedContainers.has(c));\n // Per-project checkpoint volumes (`agentbox-ckpt-<project-hash>`) are\n // durable project assets — they outlive every box that referenced them\n // (the whole point of a checkpoint). Same reasoning as SHARED_CLAUDE_VOLUME\n // but prefix-scoped since there is one per project.\n orphanVolumes = liveVolumes.filter(\n (v) => !expectedVolumes.has(v) && !v.startsWith(CHECKPOINT_VOLUME_PREFIX),\n );\n orphanSnapshots = liveSnapshotDirs.filter((d) => !expectedSnapshots.has(d));\n orphanBoxDirs = liveBoxDirs.filter((d) => !expectedBoxDirs.has(d));\n }\n\n if (dryRun) {\n return {\n removedRecords: missingRecords.map((b) => b.id),\n removedContainers: orphanContainers,\n removedVolumes: orphanVolumes,\n removedSnapshotDirs: orphanSnapshots,\n removedBoxDirs: orphanBoxDirs,\n dryRun: true,\n };\n }\n\n for (const b of missingRecords) await removeBoxRecord(b.id);\n for (const c of orphanContainers) await removeContainer(c);\n for (const v of orphanVolumes) await removeVolume(v);\n for (const d of orphanSnapshots) {\n try {\n await rm(d, { recursive: true, force: true });\n } catch {\n // best-effort\n }\n }\n for (const d of orphanBoxDirs) {\n try {\n await rm(d, { recursive: true, force: true });\n } catch {\n // best-effort\n }\n }\n\n // Migration sweep: the relay used to be a docker container on a dedicated\n // network with its own image. None of those exist after this version of\n // agentbox; drop any leftovers from previous installs. Idempotent and\n // best-effort — these calls succeed silently if the objects are already\n // gone.\n if (all) {\n try {\n await removeContainer(RELAY_CONTAINER_NAME);\n } catch {\n // best-effort\n }\n try {\n await execa('docker', ['image', 'rm', RELAY_IMAGE_REF], { reject: false });\n } catch {\n // best-effort\n }\n try {\n await removeNetwork(RELAY_NETWORK_NAME);\n } catch {\n // best-effort\n }\n }\n\n return {\n removedRecords: missingRecords.map((b) => b.id),\n removedContainers: orphanContainers,\n removedVolumes: orphanVolumes,\n removedSnapshotDirs: orphanSnapshots,\n removedBoxDirs: orphanBoxDirs,\n dryRun: false,\n };\n}\n\n// Help vitest / unit tests get to the snapshot-root constant without pulling\n// the whole snapshot module surface.\nexport { SNAPSHOTS_ROOT };\n\n// Re-export the file existence helper for inspect output; useful guard for\n// callers that want to know if a snapshot dir was ever created.\nexport async function snapshotPresent(path: string | null): Promise<boolean> {\n if (!path) return false;\n try {\n const s = await stat(path);\n return s.isDirectory();\n } catch {\n return false;\n }\n}\n","import { join } from 'node:path';\nimport { loadConfig } from '@agentbox/ctl';\nimport type { BoxStatus } from '@agentbox/ctl';\nimport type { BoxRecord } from './state.js';\nimport type { DockerEngine } from './host-export.js';\nimport { buildVncUrls, VNC_CONTAINER_PORT } from './vnc.js';\nimport { WEB_CONTAINER_PORT } from './web.js';\n\nexport interface BoxEndpoint {\n kind: 'vnc' | 'service' | 'web';\n /** Service name (kind === 'service'/'web') or 'vnc' (kind === 'vnc'). */\n name: string;\n /** In-container port (6080 for VNC, the `ready_when.port` value for services). */\n containerPort: number;\n /**\n * Host-side URL the user can open. Undefined when the port isn't reachable\n * from the host (service ports on Docker Desktop, since we don't auto-publish\n * them today).\n */\n url?: string;\n /** Whether the URL is reachable from the host on the current engine. */\n reachable: boolean;\n}\n\nexport interface BoxEndpoints {\n /** Bare hostname/IP for the box — `<container>.orb.local` on OrbStack, `127.0.0.1` otherwise. */\n domain: string;\n /** True when domain is the OrbStack auto-DNS (any in-container port works). */\n domainIsOrb: boolean;\n /** Ordered list of endpoints: VNC first (if enabled), then services in agentbox.yaml order. */\n endpoints: BoxEndpoint[];\n}\n\n/**\n * Build the box's user-facing network surface. Pure host-side: no docker exec,\n * no network — safe to call from `agentbox list` in a tight loop.\n *\n * Service ports come from the persisted status snapshot when available\n * (`~/.agentbox/boxes/<id>/status.json`, pushed by the in-box supervisor via\n * the relay). That snapshot resolves `ready_when.port` *inside the box*, so it\n * works even when `agentbox.yaml` lives only in the box and was never pulled to\n * the host. Falls back to parsing the host's `agentbox.yaml` for pre-relay\n * boxes (or ones that never pushed a snapshot).\n *\n * Missing config + no snapshot is non-fatal: the VNC entry (if any) is still\n * returned. Engine drives reachability — OrbStack auto-routes\n * `<container>.orb.local:<port>` for any in-box port; other engines see only\n * what we explicitly publish via `docker run -p`, which today is just VNC.\n */\nexport async function getBoxEndpoints(\n record: BoxRecord,\n engine: DockerEngine,\n persisted?: BoxStatus | null,\n): Promise<BoxEndpoints> {\n const domainIsOrb = engine === 'orbstack';\n const domain = domainIsOrb ? `${record.container}.orb.local` : '127.0.0.1';\n\n const endpoints: BoxEndpoint[] = [];\n\n if (record.vncEnabled && record.vncPassword) {\n const vncUrls = buildVncUrls(record, engine);\n const url = vncUrls.orbUrl ?? vncUrls.loopbackUrl;\n endpoints.push({\n kind: 'vnc',\n name: 'vnc',\n containerPort: VNC_CONTAINER_PORT,\n url,\n reachable: Boolean(url),\n });\n }\n\n // The single `expose:`-flagged service, from the snapshot first (works when\n // agentbox.yaml lives only in the box), else the host yaml.\n let webServiceName: string | null = null;\n const persistedWeb = persisted?.services.find((s) => s.expose);\n if (persistedWeb) {\n webServiceName = persistedWeb.name;\n }\n\n const pushService = (name: string, port: number): void => {\n // The web service is surfaced as the dedicated `web` endpoint below;\n // don't also list it as a generic service.\n if (name === webServiceName) return;\n endpoints.push({\n kind: 'service',\n name,\n containerPort: port,\n // Only OrbStack auto-routes arbitrary in-box ports; on other engines we\n // don't publish service ports, so the URL isn't host-reachable.\n ...(domainIsOrb\n ? { url: `http://${domain}:${String(port)}`, reachable: true }\n : { reachable: false }),\n });\n };\n\n const persistedServices = persisted?.services.filter(\n (s): s is typeof s & { port: number } => typeof s.port === 'number',\n );\n if (persistedServices && persistedServices.length > 0) {\n for (const svc of persistedServices) pushService(svc.name, svc.port);\n } else {\n try {\n const cfg = await loadConfig(join(record.workspacePath, 'agentbox.yaml'));\n if (!webServiceName) {\n webServiceName = cfg.services.find((s) => s.expose)?.name ?? null;\n }\n for (const svc of cfg.services) {\n if (svc.readyWhen?.kind !== 'port') continue;\n pushService(svc.name, svc.readyWhen.port);\n }\n } catch {\n // No persisted snapshot and no host agentbox.yaml — skip service\n // endpoints. The VNC entry, if any, is unaffected.\n }\n }\n\n // Web endpoint: only for boxes that reserved container :80 at create. The\n // URL is the published loopback host port — uniform across engines, NOT\n // gated on OrbStack (requirement: don't rely on orb auto-DNS). No url until\n // both a service declares `expose:` and the host port is resolved; until\n // then it renders as \"reserved\".\n if (record.webContainerPort !== undefined) {\n const hasTarget = webServiceName !== null && record.webHostPort !== undefined;\n endpoints.push({\n kind: 'web',\n name: webServiceName ?? 'web',\n containerPort: record.webContainerPort ?? WEB_CONTAINER_PORT,\n ...(hasTarget\n ? { url: `http://127.0.0.1:${String(record.webHostPort)}`, reachable: true }\n : { reachable: false }),\n });\n }\n\n return { domain, domainIsOrb, endpoints };\n}\n"],"mappings":"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","names":["join","join"]}
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
snapshotPathFor,
|
|
28
28
|
verifyOverlay,
|
|
29
29
|
vscodeServerVolumeName
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MOC54XL6.js";
|
|
31
31
|
import {
|
|
32
32
|
allocateProjectIndex,
|
|
33
33
|
readState,
|
|
@@ -493,4 +493,4 @@ export {
|
|
|
493
493
|
defaultBoxName,
|
|
494
494
|
createBox
|
|
495
495
|
};
|
|
496
|
-
//# sourceMappingURL=chunk-
|
|
496
|
+
//# sourceMappingURL=chunk-3NCUES35.js.map
|