@madarco/agentbox 0.6.0 → 0.8.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 (75) hide show
  1. package/dist/_cloud-attach-T727ZPRV.js +13 -0
  2. package/dist/chunk-67N47KUS.js +1640 -0
  3. package/dist/chunk-67N47KUS.js.map +1 -0
  4. package/dist/chunk-6OZDFNBF.js +8114 -0
  5. package/dist/chunk-6OZDFNBF.js.map +1 -0
  6. package/dist/chunk-BGK32PZE.js +455 -0
  7. package/dist/chunk-BGK32PZE.js.map +1 -0
  8. package/dist/chunk-FODMEHD3.js +1200 -0
  9. package/dist/chunk-FODMEHD3.js.map +1 -0
  10. package/dist/chunk-G3H2L3O2.js +288 -0
  11. package/dist/chunk-G3H2L3O2.js.map +1 -0
  12. package/dist/chunk-I24B6AXR.js +600 -0
  13. package/dist/chunk-I24B6AXR.js.map +1 -0
  14. package/dist/chunk-LEV3KICD.js +738 -0
  15. package/dist/chunk-LEV3KICD.js.map +1 -0
  16. package/dist/cloud-poller-SUNA6ZQC-2RG5WPRN.js +10 -0
  17. package/dist/dist-L4LCG5SJ.js +293 -0
  18. package/dist/dist-L4LCG5SJ.js.map +1 -0
  19. package/dist/dist-LOZBWMBF.js +447 -0
  20. package/dist/dist-ZODPD2I6.js +1407 -0
  21. package/dist/dist-ZODPD2I6.js.map +1 -0
  22. package/dist/index.js +7281 -2134
  23. package/dist/index.js.map +1 -1
  24. package/dist/prepared-state-CL4CWXQA-ME4HSKDE.js +18 -0
  25. package/package.json +8 -3
  26. package/runtime/daytona/custom-system-CLAUDE.md +39 -0
  27. package/runtime/docker/Dockerfile.box +120 -14
  28. package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +15 -8
  29. package/runtime/docker/packages/ctl/dist/bin.cjs +11310 -816
  30. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-codex-hooks.json +68 -0
  31. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-open +9 -9
  32. package/runtime/docker/packages/sandbox-docker/scripts/claude-managed-settings.json +62 -1
  33. package/runtime/docker/packages/sandbox-docker/scripts/custom-system-CLAUDE.md +15 -4
  34. package/runtime/docker/packages/sandbox-docker/scripts/gh-shim +263 -0
  35. package/runtime/docker/packages/sandbox-docker/scripts/git-shim +131 -0
  36. package/runtime/docker/packages/sandbox-docker/scripts/opencode-agentbox-plugin.js +76 -0
  37. package/runtime/hetzner/agentbox-checkpoint-cleanup +52 -0
  38. package/runtime/hetzner/agentbox-codex-hooks.json +68 -0
  39. package/runtime/hetzner/agentbox-dockerd-start +132 -0
  40. package/runtime/hetzner/agentbox-open +28 -0
  41. package/runtime/hetzner/agentbox-setup-skill.md +196 -0
  42. package/runtime/hetzner/agentbox-vnc-start +77 -0
  43. package/runtime/hetzner/claude-managed-settings.json +115 -0
  44. package/runtime/hetzner/ctl.cjs +23397 -0
  45. package/runtime/hetzner/custom-system-CLAUDE.md +39 -0
  46. package/runtime/hetzner/gh-shim +263 -0
  47. package/runtime/hetzner/git-shim +131 -0
  48. package/runtime/hetzner/opencode-agentbox-plugin.js +76 -0
  49. package/runtime/hetzner/scripts/install-box.sh +374 -0
  50. package/runtime/relay/bin.cjs +10017 -817
  51. package/share/agentbox-setup/SKILL.md +15 -8
  52. package/share/host-skills/agentbox/SKILL.md +29 -0
  53. package/share/host-skills/agentbox-info/SKILL.md +211 -0
  54. package/share/host-skills/codex/agentbox.md +35 -0
  55. package/share/host-skills/opencode/agentbox.md +26 -0
  56. package/dist/chunk-BBZMA2K6.js +0 -238
  57. package/dist/chunk-BBZMA2K6.js.map +0 -1
  58. package/dist/chunk-HHMWQNLF.js +0 -1709
  59. package/dist/chunk-HHMWQNLF.js.map +0 -1
  60. package/dist/chunk-HPZMD5DE.js +0 -106
  61. package/dist/chunk-HPZMD5DE.js.map +0 -1
  62. package/dist/chunk-HTTKML3C.js +0 -2655
  63. package/dist/chunk-HTTKML3C.js.map +0 -1
  64. package/dist/chunk-KJNZP6I3.js +0 -586
  65. package/dist/chunk-KJNZP6I3.js.map +0 -1
  66. package/dist/chunk-M7I247BK.js +0 -525
  67. package/dist/chunk-M7I247BK.js.map +0 -1
  68. package/dist/create-6PWXI6HO-OWAMHBAK.js +0 -15
  69. package/dist/lifecycle-EMXR46DI-DUVBXNTV.js +0 -38
  70. package/dist/state-KD7M46ZP-KHFTHFUS.js +0 -26
  71. package/dist/stats-SZXOJE3D-N7OODCHW.js +0 -19
  72. /package/dist/{create-6PWXI6HO-OWAMHBAK.js.map → _cloud-attach-T727ZPRV.js.map} +0 -0
  73. /package/dist/{lifecycle-EMXR46DI-DUVBXNTV.js.map → cloud-poller-SUNA6ZQC-2RG5WPRN.js.map} +0 -0
  74. /package/dist/{state-KD7M46ZP-KHFTHFUS.js.map → dist-LOZBWMBF.js.map} +0 -0
  75. /package/dist/{stats-SZXOJE3D-N7OODCHW.js.map → prepared-state-CL4CWXQA-ME4HSKDE.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../packages/sandbox-daytona/src/dockerfile-context.ts","../../../packages/sandbox-daytona/src/env-loader.ts","../../../packages/sandbox-daytona/src/backend.ts","../../../packages/sandbox-daytona/src/retry.ts","../../../packages/sandbox-daytona/src/credentials.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Locate `Dockerfile.box` + its build context so Daytona can `Image.fromDockerfile`\n * the same image the Docker provider builds locally. The Dockerfile COPYs from\n * the monorepo (packages/ctl/dist/bin.cjs, apps/cli/share/..., scripts/), so\n * the context dir must contain that tree.\n *\n * Mirrors `@agentbox/sandbox-docker`'s `resolveDockerBuild`, intentionally\n * inlined: sandbox-daytona must not depend on sandbox-docker (cross-provider\n * dep would defeat the point of `@agentbox/sandbox-cloud`).\n *\n * Resolution order:\n * 0. AGENTBOX_DOCKER_CONTEXT env override.\n * 1. Staged context shipped with the bundled `agent-box` package (sibling\n * of dist/, uniform in dev + installed).\n * 2. Legacy monorepo layout: Dockerfile.box at sandbox-docker's package\n * root, context = monorepo root.\n */\nexport interface DockerfileContext {\n dockerfile: string;\n context: string;\n}\n\nexport function resolveDockerfileContext(): DockerfileContext | null {\n const override = process.env.AGENTBOX_DOCKER_CONTEXT;\n if (override && existsSync(resolve(override, 'Dockerfile.box'))) {\n return { dockerfile: resolve(override, 'Dockerfile.box'), context: override };\n }\n const here = dirname(fileURLToPath(import.meta.url));\n const staged = resolve(here, '..', 'runtime', 'docker');\n if (existsSync(resolve(staged, 'Dockerfile.box'))) {\n return { dockerfile: resolve(staged, 'Dockerfile.box'), context: staged };\n }\n // Legacy monorepo: this module is at packages/sandbox-daytona/dist; the\n // Dockerfile lives at packages/sandbox-docker/Dockerfile.box; the build\n // context is the monorepo root.\n const monorepoRoot = resolve(here, '..', '..', '..');\n const dockerfile = resolve(monorepoRoot, 'packages', 'sandbox-docker', 'Dockerfile.box');\n if (existsSync(dockerfile)) {\n return { dockerfile, context: monorepoRoot };\n }\n return null;\n}\n\n/**\n * Locate the daytona-specific `custom-system-CLAUDE.md` that overlays the\n * docker-shaped one baked into `Dockerfile.box`. Daytona boxes have no host\n * `.git/` bind-mount, so the in-box hint needs daytona-specific git wording\n * (use `agentbox-ctl git` for any host-touching op). Same two-tier lookup\n * shape as `resolveDockerfileContext()`: staged CLI runtime first, monorepo\n * source as the dev fallback.\n */\nexport function resolveDaytonaCustomClaudeMd(): string | null {\n const here = dirname(fileURLToPath(import.meta.url));\n const staged = resolve(here, '..', 'runtime', 'daytona', 'custom-system-CLAUDE.md');\n if (existsSync(staged)) return staged;\n const monorepoRoot = resolve(here, '..', '..', '..');\n const dev = resolve(\n monorepoRoot,\n 'packages',\n 'sandbox-daytona',\n 'scripts',\n 'custom-system-CLAUDE.md',\n );\n if (existsSync(dev)) return dev;\n return null;\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { resolve } from 'node:path';\n\n/**\n * Daytona env auto-loader. The SDK reads `DAYTONA_API_KEY` /\n * `DAYTONA_JWT_TOKEN` + `DAYTONA_ORGANIZATION_ID` from `process.env`. We pull\n * those keys in from `~/.agentbox/secrets.env` so the SDK Just Works after\n * the user runs `agentbox daytona login` once.\n *\n * Lookup order (first wins; process.env is never overwritten):\n * 1. `process.env` (already set in the shell).\n * 2. `~/.agentbox/secrets.env` — written by `agentbox daytona login`.\n *\n * Project-level `.env` / `.env.local` are intentionally NOT consulted: those\n * files belong to the app code being developed, and a `DAYTONA_API_KEY`\n * there is typically meant for in-box code execution, not for the host CLI\n * to harvest and provision sandboxes with.\n *\n * Only Daytona-prefixed keys are imported; the rest of the file is left\n * alone. The loader is idempotent and side-effect-free after the first call.\n */\nconst DAYTONA_KEYS = [\n 'DAYTONA_API_KEY',\n 'DAYTONA_JWT_TOKEN',\n 'DAYTONA_ORGANIZATION_ID',\n 'DAYTONA_API_URL',\n 'DAYTONA_TARGET',\n] as const;\n\nlet loaded = false;\n\nexport function ensureDaytonaEnvLoaded(): void {\n if (loaded) return;\n loaded = true;\n importDaytonaFromFile(resolve(homedir(), '.agentbox', 'secrets.env'));\n}\n\nfunction importDaytonaFromFile(path: string): void {\n if (!existsSync(path)) return;\n let body: string;\n try {\n body = readFileSync(path, 'utf8');\n } catch {\n return;\n }\n const parsed = parseEnvFile(body);\n for (const key of DAYTONA_KEYS) {\n if (process.env[key] !== undefined) continue;\n const value = parsed[key];\n if (typeof value === 'string') {\n process.env[key] = value;\n }\n }\n}\n\n/**\n * Minimal `.env` parser: handles `KEY=value`, `KEY=\"value with spaces\"`,\n * `KEY='value with $special chars'`, `export KEY=value`, blank lines, and\n * `#` comments. Doesn't do variable interpolation — that's surprising to\n * users coming from full dotenv, but secrets typically don't reference each\n * other and we'd rather be predictable.\n */\nexport function parseEnvFile(body: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const rawLine of body.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line.length === 0 || line.startsWith('#')) continue;\n const stripped = line.startsWith('export ') ? line.slice('export '.length) : line;\n const eq = stripped.indexOf('=');\n if (eq <= 0) continue;\n const key = stripped.slice(0, eq).trim();\n let value = stripped.slice(eq + 1).trim();\n // Strip surrounding quotes (single or double).\n if (\n value.length >= 2 &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n","/**\n * Daytona `CloudBackend` — maps the provider-neutral cloud primitives onto\n * `@daytonaio/sdk`. Lazy SDK client + lazy sandbox handle resolution so\n * importing this module costs nothing until a daytona-tagged box does something.\n */\n\nimport { Daytona, DaytonaNotFoundError, Image, SandboxState, type Sandbox } from '@daytonaio/sdk';\nimport type { CloudSandboxSummary } from '@agentbox/core';\nimport type {\n CloudBackend,\n CloudExecOptions,\n CloudExecResult,\n CloudFileEntry,\n CloudHandle,\n CloudPreviewUrl,\n CloudProvisionRequest,\n CloudState,\n CloudVolumeMount,\n} from '@agentbox/core';\nimport { resolveDockerfileContext } from './dockerfile-context.js';\nimport { ensureDaytonaEnvLoaded } from './env-loader.js';\nimport { withDaytonaRetry } from './retry.js';\n\n/**\n * Thin shorthand for `withDaytonaRetry` with our defaults. Most methods are\n * idempotent and use `retryOnAmbiguous: true`; the few that aren't override.\n */\nfunction retry<T>(\n method: string,\n fn: () => Promise<T>,\n opts: {\n attemptTimeoutMs?: number;\n retryOnAmbiguous?: boolean;\n /** When true, single-shot — no backoff list, no retries. */\n noRetry?: boolean;\n } = {},\n): Promise<T> {\n return withDaytonaRetry(\n {\n method,\n retryOnAmbiguous: opts.retryOnAmbiguous ?? true,\n attemptTimeoutMs: opts.attemptTimeoutMs,\n backoffMs: opts.noRetry === true ? [] : undefined,\n },\n fn,\n );\n}\n\n/**\n * Sentinel image ref the cloud-provider hands to us when the user didn't pass\n * `--image`. We translate it to `Image.fromDockerfile(...)` so Daytona builds\n * the same box image the Docker provider builds locally.\n */\nexport const DEFAULT_BOX_IMAGE_REF = 'agentbox/box:dev';\n\nlet client: Daytona | null = null;\nexport function getClient(): Daytona {\n if (!client) {\n // Pull DAYTONA_* keys from `.env.local` / `.env` / `~/.agentbox/secrets.env`\n // into process.env first — the SDK reads from process.env and most users\n // keep secrets in a project file rather than their shell rc.\n ensureDaytonaEnvLoaded();\n try {\n // Daytona() reads DAYTONA_API_KEY / DAYTONA_JWT_TOKEN + DAYTONA_ORGANIZATION_ID\n // from env.\n client = new Daytona();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // The interactive prompt in `agentbox daytona login` handles first-run\n // setup; this error path is for non-TTY callers (CI, scripts) where the\n // prompt was skipped.\n throw new Error(\n `Daytona credentials not configured: ${msg}\\n` +\n `Run \\`agentbox daytona login\\` interactively, or set DAYTONA_API_KEY in the environment.`,\n );\n }\n }\n return client;\n}\n\nasync function getSandbox(id: string): Promise<Sandbox> {\n return getClient().get(id);\n}\n\nasync function maybeGetSandbox(id: string): Promise<Sandbox | null> {\n try {\n return await getClient().get(id);\n } catch {\n return null;\n }\n}\n\n/**\n * Map Daytona's `SandboxState` (16 fine-grained values incl. transitional ones)\n * onto our 4-value `CloudState`. Transitional states ('starting', 'creating')\n * are reported as 'running' so callers don't ping-pong; 'archived' maps to\n * 'paused' (our pause is Daytona's archive).\n */\nfunction mapState(s: SandboxState | string | undefined): CloudState {\n switch (s) {\n case SandboxState.STARTED:\n return 'running';\n case SandboxState.STARTING:\n case SandboxState.CREATING:\n case SandboxState.RESTORING:\n case SandboxState.BUILDING_SNAPSHOT:\n case SandboxState.PULLING_SNAPSHOT:\n case SandboxState.PENDING_BUILD:\n case SandboxState.STOPPING:\n return 'running';\n case SandboxState.STOPPED:\n return 'stopped';\n case SandboxState.ARCHIVED:\n case SandboxState.ARCHIVING:\n return 'paused';\n case SandboxState.DESTROYED:\n case SandboxState.DESTROYING:\n case SandboxState.ERROR:\n case SandboxState.BUILD_FAILED:\n case SandboxState.UNKNOWN:\n default:\n return 'missing';\n }\n}\n\n/**\n * Translate our provider-neutral `CloudVolumeMount` into the SDK shape Daytona\n * expects. The SDK's `VolumeMount` carries `volumeId` + `mountPath` (+ optional\n * `subpath` for S3-prefix mounts); a 1:1 mapping with our type.\n */\nfunction toDaytonaVolumeMount(v: CloudVolumeMount): {\n volumeId: string;\n mountPath: string;\n subpath?: string;\n} {\n return {\n volumeId: v.volumeId,\n mountPath: v.mountPath,\n ...(v.subpath ? { subpath: v.subpath } : {}),\n };\n}\n\n/** Translate the request's image ref into something Daytona's `create` accepts. */\nfunction resolveImage(ref: string): string | Image {\n if (ref !== DEFAULT_BOX_IMAGE_REF) return ref;\n const ctx = resolveDockerfileContext();\n if (!ctx) {\n throw new Error(\n \"could not locate the AgentBox Dockerfile.box build context for the Daytona snapshot. \" +\n \"Set AGENTBOX_DOCKER_CONTEXT to a directory containing Dockerfile.box, or pass --image <ref> with a Daytona-compatible image.\",\n );\n }\n // Image.fromDockerfile bundles the directory the Dockerfile lives in and\n // ships it to Daytona to build a snapshot. The Dockerfile.box COPYs from\n // the monorepo tree; the staged `runtime/docker` context already mirrors\n // that tree, so the build resolves COPY paths correctly.\n return Image.fromDockerfile(ctx.dockerfile);\n}\n\nexport const daytonaBackend: CloudBackend = {\n name: 'daytona',\n\n async provision(req: CloudProvisionRequest): Promise<CloudHandle> {\n // No-retry: provision is non-idempotent — a 504 after the request reaches\n // the origin could create a duplicate billable sandbox we can't reference\n // for cleanup. The wrapper still bounds wall-clock at 900s (matching the\n // existing inline SDK timeout) so a wedged connection fails cleanly.\n return retry(\n 'provision',\n async () => {\n // Two SDK overloads:\n // - `CreateSandboxFromSnapshotParams` takes `snapshot:` and no\n // `onSnapshotCreateLogs` (the snapshot already exists, nothing to build).\n // - `CreateSandboxFromImageParams` takes `image:` and accepts\n // `onSnapshotCreateLogs` for streaming the Dockerfile build.\n // TypeScript can't infer the right overload from a union literal, so\n // split the call.\n const baseParams = {\n ...(req.resources ? { resources: req.resources } : {}),\n envVars: req.env,\n ...(req.volumes && req.volumes.length > 0\n ? { volumes: req.volumes.map(toDaytonaVolumeMount) }\n : {}),\n labels: { 'agentbox.name': req.name },\n };\n const client = getClient();\n // The first-time Dockerfile.box snapshot build is ~41 layers and pulls\n // Chromium — comfortably 5+ minutes wall time. Daytona's default ready\n // timeout is too short for that; override with 15 min so a cold build\n // doesn't fail mid-snapshot. Cached snapshots and snapshot-based\n // creates come up in seconds.\n // Resolve `req.image` against Daytona's snapshot registry first when\n // it's set to a non-default value: `agentbox prepare --provider\n // daytona` registers a named snapshot and writes `box.image:\n // <name>` into project config; subsequent creates should boot from\n // that snapshot, not try to pull `<name>:latest` from Docker Hub.\n // Default ref (agentbox/box:dev) skips the lookup and goes through\n // resolveImage (Image.fromDockerfile). Explicit `req.snapshot` always\n // wins (cloud checkpoint path).\n let snapshotName = req.snapshot;\n if (!snapshotName && req.image && req.image !== DEFAULT_BOX_IMAGE_REF) {\n try {\n const snap = await client.snapshot.get(req.image);\n if (snap && snap.name) snapshotName = snap.name;\n } catch {\n // Not a known snapshot — fall through and treat as a Docker image ref.\n }\n }\n // Daytona rejects `resources` on the snapshot path — the snapshot's\n // own params encode them. Strip resources only for the snapshot\n // branch; the image branch keeps them.\n const snapshotParams: Record<string, unknown> = { ...baseParams };\n delete snapshotParams.resources;\n const sandbox = snapshotName\n ? await client.create({ snapshot: snapshotName, ...snapshotParams }, { timeout: 900 })\n : await client.create(\n { image: resolveImage(req.image), ...baseParams },\n {\n timeout: 900,\n ...(req.onLog ? { onSnapshotCreateLogs: req.onLog } : {}),\n },\n );\n return { sandboxId: sandbox.id };\n },\n { retryOnAmbiguous: false, attemptTimeoutMs: 900_000 },\n );\n },\n\n async ensureVolume(name: string): Promise<{ volumeId: string }> {\n // Daytona's `volume.get(name, create=true)` returns the existing volume or\n // initiates creation on first call. Critically, a freshly-created volume\n // comes back in `creating`/`pending_create` state — passing such a volume\n // into `Daytona.create({ volumes: […] })` is rejected with\n // \"Volume is not in a ready state. Current state: creating\". So poll\n // `volume.get` until the state lands on `ready` (or a terminal failure).\n //\n // Volumes are org-scoped on Daytona — every sandbox in the same Daytona\n // organization sees the same id, which is what we want for sharing agent\n // credentials across all of a user's boxes.\n //\n // Each individual `volume.get` call is retry-wrapped so a transient edge\n // hiccup mid-poll doesn't fail the whole ensure.\n const client = getClient();\n let vol = await retry('volume.get(create)', () => client.volume.get(name, true));\n // Volumes typically transition from creating → ready within a few seconds.\n // Allow up to 60s in case of slow control-plane operations.\n const deadline = Date.now() + 60_000;\n while (vol.state !== 'ready') {\n if (vol.state === 'error' || vol.state === 'deleted' || vol.state === 'deleting') {\n throw new Error(\n `Daytona volume '${name}' is in unrecoverable state '${vol.state}'. ` +\n `Delete it from the Daytona dashboard and retry.`,\n );\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `Daytona volume '${name}' did not become ready within 60s (state: ${vol.state}). ` +\n `Try again — the Daytona control plane may be slow.`,\n );\n }\n await new Promise((r) => setTimeout(r, 1000));\n vol = await retry('volume.get(poll)', () => client.volume.get(name));\n }\n return { volumeId: vol.id };\n },\n\n async get(sandboxId: string): Promise<CloudHandle | null> {\n return retry('get', async () => {\n const sb = await maybeGetSandbox(sandboxId);\n return sb ? { sandboxId: sb.id } : null;\n });\n },\n\n async list(): Promise<CloudSandboxSummary[]> {\n return retry('list', async () => {\n const client = getClient();\n // `client.list()` returns `PaginatedSandboxes { items: Sandbox[] }`\n // (page 1 by default). For prune we don't need multi-page traversal\n // yet — sandboxes per org are bounded; if that changes, loop on page.\n const page = await client.list();\n const items = Array.isArray(page) ? page : (page.items ?? []);\n return items.map((sb): CloudSandboxSummary => {\n const summary: CloudSandboxSummary = { sandboxId: sb.id };\n const raw = sb as unknown as {\n name?: string;\n labels?: Record<string, string>;\n state?: string;\n createdAt?: string;\n };\n const friendly = raw.labels?.['agentbox.name'] ?? raw.name;\n if (friendly) summary.name = friendly;\n if (raw.createdAt) summary.createdAt = raw.createdAt;\n if (typeof raw.state === 'string') summary.state = mapState(raw.state);\n return summary;\n });\n });\n },\n\n async start(h: CloudHandle): Promise<void> {\n return retry(\n 'start',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.start();\n },\n { attemptTimeoutMs: 60_000 },\n );\n },\n\n async stop(h: CloudHandle): Promise<void> {\n return retry(\n 'stop',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.stop();\n },\n { attemptTimeoutMs: 60_000 },\n );\n },\n\n async pause(h: CloudHandle): Promise<void> {\n // Our pause == cold storage (Daytona archive). The tradeoff is documented\n // in CloudBackend's interface comment.\n return retry(\n 'pause',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.archive();\n },\n { attemptTimeoutMs: 60_000 },\n );\n },\n\n async resume(h: CloudHandle): Promise<void> {\n return retry(\n 'resume',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.start();\n },\n { attemptTimeoutMs: 60_000 },\n );\n },\n\n async destroy(h: CloudHandle): Promise<void> {\n return retry(\n 'destroy',\n async () => {\n const sb = await maybeGetSandbox(h.sandboxId);\n if (!sb) return; // already gone — destroy is idempotent\n // Daytona's `delete()` on a running sandbox is queued, not synchronous —\n // observed in practice: `delete()` returns ok, the sandbox stays in\n // 'started' for tens of seconds, then eventually disappears. Stopping\n // first makes the delete synchronous so callers (and the dashboard) see\n // it gone immediately. Swallow stop errors — if the sandbox is already\n // stopped/archived, delete still works.\n try {\n await sb.stop(60);\n } catch {\n /* best-effort */\n }\n try {\n await sb.delete(60);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // Already deleted between stop and delete — fine.\n if (!/not found/i.test(msg)) throw err;\n }\n },\n { attemptTimeoutMs: 120_000 },\n );\n },\n\n async state(h: CloudHandle): Promise<CloudState> {\n return retry('state', async () => {\n const sb = await maybeGetSandbox(h.sandboxId);\n if (!sb) return 'missing';\n return mapState(sb.state);\n });\n },\n\n async exec(\n h: CloudHandle,\n cmd: string,\n opts?: CloudExecOptions,\n ): Promise<CloudExecResult> {\n return retry(\n 'exec',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n // Daytona's ExecuteResponse returns combined output in `result` with no\n // separate stderr stream. Surface it as stdout and leave stderr empty —\n // callers that need split streams must redirect inside `cmd` itself.\n const r = await sb.process.executeCommand(cmd, opts?.cwd, opts?.env);\n return { exitCode: r.exitCode, stdout: r.result, stderr: '' };\n },\n { attemptTimeoutMs: opts?.attemptTimeoutMs ?? 120_000, noRetry: opts?.noRetry },\n );\n },\n\n async uploadFile(h: CloudHandle, localPath: string, remotePath: string): Promise<void> {\n return retry(\n 'uploadFile',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.fs.uploadFile(localPath, remotePath);\n },\n { attemptTimeoutMs: 300_000 },\n );\n },\n\n async downloadFile(h: CloudHandle, remotePath: string, localPath: string): Promise<void> {\n return retry(\n 'downloadFile',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.fs.downloadFile(remotePath, localPath);\n },\n { attemptTimeoutMs: 300_000 },\n );\n },\n\n async listFiles(h: CloudHandle, remoteDir: string): Promise<CloudFileEntry[]> {\n return retry('listFiles', async () => {\n const sb = await getSandbox(h.sandboxId);\n const files = await sb.fs.listFiles(remoteDir);\n return files.map((f) => ({\n name: f.name,\n isDir: Boolean((f as { isDir?: boolean }).isDir),\n }));\n });\n },\n\n async previewUrl(h: CloudHandle, port: number): Promise<CloudPreviewUrl> {\n return retry('previewUrl', async () => {\n const sb = await getSandbox(h.sandboxId);\n const p = await sb.getPreviewLink(port);\n // The host CloudBoxPoller attaches `token` as `x-daytona-preview-token`\n // for every /bridge call. Browser-bound URLs use `signedPreviewUrl` below\n // instead (the two token kinds are not interchangeable on Daytona).\n return { url: p.url, token: p.token };\n });\n },\n\n async signedPreviewUrl(\n h: CloudHandle,\n port: number,\n expiresInSeconds: number,\n ): Promise<CloudPreviewUrl> {\n return retry('signedPreviewUrl', async () => {\n const sb = await getSandbox(h.sandboxId);\n const s = await sb.getSignedPreviewUrl(port, expiresInSeconds);\n return { url: s.url, token: s.token };\n });\n },\n\n async attachArgv(h: CloudHandle): Promise<string[]> {\n return retry('attachArgv', async () => {\n const sb = await getSandbox(h.sandboxId);\n // 60 min default expiry matches the SDK default; an interactive session\n // longer than that is rare. `sandbox-cloud`'s buildAttach appends\n // `-t '<inner cmd>'` for the per-session tmux attach.\n const ssh = await sb.createSshAccess(60);\n return [\n 'ssh',\n // First-connect to a never-seen host fingerprint should be silent in a\n // PTY — the user already authenticated via Daytona's API.\n '-o', 'StrictHostKeyChecking=accept-new',\n // Daytona's SSH gateway terminates per-token; no key file, no port.\n `${ssh.token}@ssh.app.daytona.io`,\n ];\n });\n },\n\n async revokeAttachToken(h: CloudHandle, argv: string[]): Promise<void> {\n // argv[3] = `${token}@ssh.app.daytona.io`; pull the token off the front.\n const userhost = argv[argv.length - 1] ?? '';\n const atIdx = userhost.indexOf('@');\n if (atIdx <= 0) return;\n const token = userhost.slice(0, atIdx);\n if (token.length === 0) return;\n try {\n await retry('revokeAttachToken', async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb.revokeSshAccess(token);\n });\n } catch {\n // Best-effort — tokens auto-expire after 60 min anyway.\n }\n },\n\n async createSnapshot(h: CloudHandle, snapshotName: string): Promise<void> {\n // Daytona's `_experimental_createSnapshot` puts the sandbox into the\n // `snapshotting` state, captures its filesystem, then returns. The\n // resulting snapshot is org-scoped and visible via the Daytona dashboard\n // and `client.snapshot.list()`. We give it a generous timeout (15min,\n // matching `provision`) because a large `/workspace` plus warmed agent\n // volumes can take a while to snapshot.\n //\n // No retry on ambiguous failures: a 504 mid-snapshot could leave a\n // half-built named snapshot in Daytona that a retry would collide on.\n // Matches `provision`'s policy.\n return retry(\n 'createSnapshot',\n async () => {\n const sb = await getSandbox(h.sandboxId);\n await sb._experimental_createSnapshot(snapshotName);\n },\n { attemptTimeoutMs: 900_000, retryOnAmbiguous: false },\n );\n },\n\n async deleteSnapshot(snapshotName: string): Promise<void> {\n return retry('deleteSnapshot', async () => {\n try {\n const client = getClient();\n const snapshot = await client.snapshot.get(snapshotName);\n await client.snapshot.delete(snapshot);\n } catch (err) {\n // Idempotent: a snapshot that's already gone is success from the\n // caller's perspective (mirrors `destroy()`'s \"not found\" handling).\n if (err instanceof DaytonaNotFoundError) return;\n const msg = err instanceof Error ? err.message : String(err);\n if (/not found/i.test(msg)) return;\n throw err;\n }\n });\n },\n};\n","/**\n * Bounded retry wrapper for `daytonaBackend` SDK calls. Daytona's CloudFront\n * edge intermittently 504s on `executeCommand` and other API calls (backlog\n * item 6.1) — without bounded retries an edge hiccup propagates as an\n * unbounded wedge in the calling code. This helper classifies transient\n * failures vs. permanent ones using the SDK's typed error classes, bounds\n * each attempt with a timeout, and caps the total wall-clock cost.\n *\n * Non-idempotent ops (`provision`) pass `retryOnAmbiguous: false` so a 504\n * after the request reached the origin doesn't create a duplicate sandbox.\n */\n\nimport {\n DaytonaAuthenticationError,\n DaytonaAuthorizationError,\n DaytonaConflictError,\n DaytonaConnectionError,\n DaytonaError,\n DaytonaNotFoundError,\n DaytonaRateLimitError,\n DaytonaTimeoutError,\n DaytonaValidationError,\n} from '@daytonaio/sdk';\n\nexport interface WithRetryOptions {\n /** Method name, used in retry log lines. */\n method: string;\n /** Per-attempt timeout (ms). Default 30_000. */\n attemptTimeoutMs?: number;\n /** Backoff before attempts 2, 3, … (ms). Default [1000, 2000, 4000]. */\n backoffMs?: readonly number[];\n /**\n * Whether to retry on errors where we can't be sure the server applied\n * the request — connection failures, per-attempt timeouts, and 5xx\n * responses (since 504 from CloudFront can mean \"origin still processing\").\n * Set false for non-idempotent operations (e.g. `provision`) where a\n * retry could create a duplicate.\n */\n retryOnAmbiguous: boolean;\n /** Override the default `process.stderr` retry sink (used by tests). */\n onRetry?: (line: string) => void;\n}\n\nconst DEFAULT_BACKOFF: readonly number[] = [1000, 2000, 4000];\nconst DEFAULT_ATTEMPT_TIMEOUT_MS = 30_000;\n\n/** Internal sentinel used by the per-attempt timeout race. */\nclass AttemptTimeoutError extends Error {\n constructor(method: string, ms: number) {\n super(`daytona ${method}: per-attempt timeout after ${String(ms)}ms`);\n this.name = 'AttemptTimeoutError';\n }\n}\n\nexport function isAttemptTimeout(err: unknown): err is AttemptTimeoutError {\n return err instanceof AttemptTimeoutError;\n}\n\n/**\n * Classify an error as retriable or not. `allowAmbiguous` gates the cases\n * where the server may or may not have applied the request — the caller\n * decides based on idempotency.\n */\nexport function isRetriable(err: unknown, allowAmbiguous: boolean): boolean {\n // Rate-limit responses always carry an intent from the server: back off.\n if (err instanceof DaytonaRateLimitError) return true;\n\n // Permanent client-side failures: never retry — the next call will get\n // the same answer and we'd just be wasting wall-clock.\n if (\n err instanceof DaytonaNotFoundError ||\n err instanceof DaytonaAuthenticationError ||\n err instanceof DaytonaAuthorizationError ||\n err instanceof DaytonaValidationError ||\n err instanceof DaytonaConflictError\n ) {\n return false;\n }\n\n // Connection / per-attempt timeout: the request may not have reached\n // the server. Gated by allowAmbiguous so non-idempotent callers can opt\n // out of double-execute risk.\n if (\n err instanceof DaytonaConnectionError ||\n err instanceof DaytonaTimeoutError ||\n err instanceof AttemptTimeoutError\n ) {\n return allowAmbiguous;\n }\n\n // Base DaytonaError: branch on statusCode. 5xx is ambiguous; 4xx we\n // didn't catch above is a permanent failure we hadn't seen before.\n if (err instanceof DaytonaError) {\n const status = err.statusCode;\n if (typeof status === 'number' && status >= 500 && status <= 599) {\n return allowAmbiguous;\n }\n return false;\n }\n\n // Axios-style fallback for raw errors that leak through without an SDK\n // wrapper. Match the same shape the SDK uses internally.\n if (err && typeof err === 'object') {\n const code = (err as { code?: unknown }).code;\n if (\n code === 'ECONNRESET' ||\n code === 'ETIMEDOUT' ||\n code === 'ECONNABORTED' ||\n code === 'EAI_AGAIN' ||\n code === 'ECONNREFUSED' ||\n code === 'ENOTFOUND'\n ) {\n return allowAmbiguous;\n }\n const status =\n (err as { response?: { status?: unknown } }).response?.status ??\n (err as { status?: unknown }).status ??\n (err as { statusCode?: unknown }).statusCode;\n if (typeof status === 'number' && status >= 500 && status <= 599) {\n return allowAmbiguous;\n }\n }\n\n return false;\n}\n\n/**\n * Run `fn`, retrying on transient failures with capped exponential backoff.\n * Each attempt is bounded by `attemptTimeoutMs` via Promise.race; total\n * wall-clock = sum(backoffMs) + maxAttempts * attemptTimeoutMs.\n */\nexport async function withDaytonaRetry<T>(\n opts: WithRetryOptions,\n fn: () => Promise<T>,\n): Promise<T> {\n const backoff = opts.backoffMs ?? DEFAULT_BACKOFF;\n const maxAttempts = backoff.length + 1;\n const timeoutMs = opts.attemptTimeoutMs ?? DEFAULT_ATTEMPT_TIMEOUT_MS;\n const log = opts.onRetry ?? defaultRetryLog;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await raceTimeout(fn(), timeoutMs, opts.method);\n } catch (err) {\n const last = attempt === maxAttempts;\n if (last || !isRetriable(err, opts.retryOnAmbiguous)) throw err;\n const delay = backoff[attempt - 1] ?? backoff[backoff.length - 1] ?? 4000;\n log(\n `daytona ${opts.method}: attempt ${String(attempt)} failed (${errorSummary(err)}); retrying in ${String(delay)}ms`,\n );\n await sleep(delay);\n }\n }\n // Unreachable: the loop above either returns or throws.\n throw new Error(`withDaytonaRetry: exhausted attempts for ${opts.method}`);\n}\n\nfunction defaultRetryLog(line: string): void {\n // Prefix so log scrapers + users can distinguish retry chatter from real\n // CLI output. `\\n` before is intentional — many CLI surfaces use clack\n // spinners on stdout, and stderr lines without a leading newline can\n // collide with a redraw.\n process.stderr.write(`\\n[daytona-retry] ${line}\\n`);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function raceTimeout<T>(p: Promise<T>, ms: number, method: string): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n p,\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => reject(new AttemptTimeoutError(method, ms)), ms);\n }),\n ]);\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n\nfunction errorSummary(err: unknown): string {\n if (err instanceof DaytonaError) {\n const status = err.statusCode;\n const cls = err.constructor.name;\n return `${cls}${typeof status === 'number' ? ` ${String(status)}` : ''}: ${truncate(err.message)}`;\n }\n if (err instanceof Error) {\n const code = (err as { code?: unknown }).code;\n return code !== undefined ? `${err.name}(${String(code)}): ${truncate(err.message)}` : `${err.name}: ${truncate(err.message)}`;\n }\n return truncate(String(err));\n}\n\nfunction truncate(s: string, max = 160): string {\n return s.length > max ? `${s.slice(0, max)}…` : s;\n}\n","import { spawnSync } from 'node:child_process';\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, resolve } from 'node:path';\nimport { confirm, isCancel, intro, log, note, outro, password, spinner, text } from '@clack/prompts';\nimport { ensureDaytonaEnvLoaded } from './env-loader.js';\n\nconst DASHBOARD_KEYS_URL = 'https://app.daytona.io/dashboard/keys';\n\n/**\n * Keys we manage in `~/.agentbox/secrets.env`. When the user reconfigures we\n * strip any prior values for these keys before appending the new ones so the\n * file never accumulates duplicates.\n */\nconst MANAGED_KEYS = ['DAYTONA_API_KEY', 'DAYTONA_JWT_TOKEN', 'DAYTONA_ORGANIZATION_ID'] as const;\ntype ManagedKey = (typeof MANAGED_KEYS)[number];\n\nexport interface EnsureDaytonaCredentialsOptions {\n /** Re-prompt even when valid credentials are already present (used by `agentbox daytona login`). */\n force?: boolean;\n}\n\n/**\n * First-run interactive setup for Daytona credentials. Walks the user through\n * opening the dashboard, pasting an API key (or JWT + organization ID), and\n * persists the result to `~/.agentbox/secrets.env` — which the env-loader\n * already picks up for every cloud command.\n *\n * No-op when credentials are already configured (env var or our secrets\n * file). Silent no-op when stdin isn't a TTY so scripted/CI callers get the\n * \"credentials not configured\" error from the SDK instead of a hung prompt.\n */\nexport async function ensureDaytonaCredentials(\n opts: EnsureDaytonaCredentialsOptions = {},\n): Promise<void> {\n ensureDaytonaEnvLoaded();\n\n if (!opts.force && hasUsableCredentials()) return;\n if (!process.stdin.isTTY) return;\n\n intro('Daytona setup');\n note(\n `AgentBox needs a Daytona API key to provision cloud boxes.\\n` +\n `Generate one at ${DASHBOARD_KEYS_URL}`,\n 'API key required',\n );\n\n const open = await confirm({\n message: `Open ${DASHBOARD_KEYS_URL} in your browser?`,\n initialValue: true,\n });\n if (isCancel(open)) {\n log.warn('Daytona setup cancelled — re-run `agentbox daytona login` when ready.');\n return;\n }\n if (open) openDashboard();\n\n // One retry on auth failure (typos are the common case). Beyond that we bail\n // and surface the validation error; the user can re-run `agentbox daytona login`.\n for (let attempt = 0; attempt < 2; attempt++) {\n const creds = await promptForCredentials();\n if (creds === null) return;\n\n const result = await validateCredentials(creds);\n if (result.ok) {\n persistCredentials(creds);\n log.success(`Daytona credentials saved to ${secretsPath()}`);\n outro('Setup complete.');\n return;\n }\n if (result.kind === 'auth' && attempt === 0) {\n log.error(`That key was rejected by Daytona: ${result.message}`);\n log.info('Try again, or press Ctrl-C to cancel.');\n continue;\n }\n if (result.kind === 'network') {\n log.warn(`Could not reach Daytona to validate (${result.message}) — saving anyway.`);\n persistCredentials(creds);\n log.success(`Daytona credentials saved to ${secretsPath()}`);\n outro('Setup complete (unvalidated).');\n return;\n }\n throw new Error(`Daytona credentials rejected: ${result.message}`);\n }\n}\n\nfunction hasUsableCredentials(): boolean {\n if (process.env.DAYTONA_API_KEY) return true;\n if (process.env.DAYTONA_JWT_TOKEN && process.env.DAYTONA_ORGANIZATION_ID) return true;\n return false;\n}\n\ninterface Credentials {\n apiKey?: string;\n jwtToken?: string;\n organizationId?: string;\n}\n\nasync function promptForCredentials(): Promise<Credentials | null> {\n const key = await password({\n message: 'Paste your Daytona API key (or JWT token)',\n validate(v) {\n if (!v || v.trim().length === 0) return 'Cannot be empty';\n return undefined;\n },\n });\n if (isCancel(key)) {\n log.warn('Daytona setup cancelled.');\n return null;\n }\n const trimmed = key.trim();\n\n // JWTs start with `eyJ` (base64-encoded `{\"`). API keys don't, and don't need\n // an org ID — the SDK derives it from the key. Only ask for org ID for JWTs.\n if (trimmed.startsWith('eyJ')) {\n const org = await text({\n message: 'Paste your Daytona organization ID',\n placeholder: 'org_...',\n validate(v) {\n if (!v || v.trim().length === 0) return 'Cannot be empty';\n return undefined;\n },\n });\n if (isCancel(org)) {\n log.warn('Daytona setup cancelled.');\n return null;\n }\n return { jwtToken: trimmed, organizationId: org.trim() };\n }\n\n return { apiKey: trimmed };\n}\n\ntype ValidationResult =\n | { ok: true }\n | { ok: false; kind: 'auth'; message: string }\n | { ok: false; kind: 'network'; message: string };\n\nasync function validateCredentials(creds: Credentials): Promise<ValidationResult> {\n const s = spinner();\n s.start('Validating credentials with Daytona');\n\n // Snapshot existing env so we can restore on failure — never poison\n // process.env with a bad key.\n const snapshot = snapshotManagedEnv();\n applyToEnv(creds);\n\n try {\n // Dynamic import so the SDK only loads when we actually need it (keeps the\n // Docker hot path lean, same reason as the provider registry).\n const { Daytona } = await import('@daytonaio/sdk');\n const client = new Daytona();\n await client.list();\n s.stop('Daytona credentials accepted');\n return { ok: true };\n } catch (err) {\n restoreManagedEnv(snapshot);\n const message = err instanceof Error ? err.message : String(err);\n s.stop('Daytona credentials check failed');\n if (/401|403|unauthor|forbidden|invalid/i.test(message)) {\n return { ok: false, kind: 'auth', message };\n }\n return { ok: false, kind: 'network', message };\n }\n}\n\nfunction snapshotManagedEnv(): Record<ManagedKey, string | undefined> {\n const out = {} as Record<ManagedKey, string | undefined>;\n for (const k of MANAGED_KEYS) out[k] = process.env[k];\n return out;\n}\n\nfunction restoreManagedEnv(snap: Record<ManagedKey, string | undefined>): void {\n for (const k of MANAGED_KEYS) {\n if (snap[k] === undefined) delete process.env[k];\n else process.env[k] = snap[k];\n }\n}\n\nfunction applyToEnv(creds: Credentials): void {\n // Wipe the other auth method so the SDK doesn't get confused by stale env\n // (e.g. an old JWT lingering from a previous shell export).\n for (const k of MANAGED_KEYS) delete process.env[k];\n if (creds.apiKey) process.env.DAYTONA_API_KEY = creds.apiKey;\n if (creds.jwtToken) process.env.DAYTONA_JWT_TOKEN = creds.jwtToken;\n if (creds.organizationId) process.env.DAYTONA_ORGANIZATION_ID = creds.organizationId;\n}\n\nfunction persistCredentials(creds: Credentials): void {\n applyToEnv(creds);\n const path = secretsPath();\n mkdirSync(dirname(path), { recursive: true });\n\n // Read existing file, strip any managed keys, append fresh values. Keeps\n // unrelated DAYTONA_API_URL / DAYTONA_TARGET (or anything else the user\n // dropped here) untouched.\n let existing = '';\n if (existsSync(path)) {\n try {\n existing = readFileSync(path, 'utf8');\n } catch {\n existing = '';\n }\n }\n\n const kept = existing\n .split(/\\r?\\n/)\n .filter((line) => {\n const stripped = line.startsWith('export ') ? line.slice('export '.length) : line;\n const eq = stripped.indexOf('=');\n if (eq <= 0) return true;\n const key = stripped.slice(0, eq).trim();\n return !(MANAGED_KEYS as readonly string[]).includes(key);\n })\n .join('\\n')\n .replace(/\\s+$/u, '');\n\n const lines: string[] = [];\n if (creds.apiKey) lines.push(`DAYTONA_API_KEY=${creds.apiKey}`);\n if (creds.jwtToken) lines.push(`DAYTONA_JWT_TOKEN=${creds.jwtToken}`);\n if (creds.organizationId) lines.push(`DAYTONA_ORGANIZATION_ID=${creds.organizationId}`);\n\n const body = (kept ? `${kept}\\n` : '') + lines.join('\\n') + '\\n';\n\n // Atomic write — rename(2) is atomic on the same filesystem, so partially\n // written secrets can't be left behind on a crash.\n const tmp = `${path}.tmp`;\n writeFileSync(tmp, body, { mode: 0o600 });\n try {\n chmodSync(tmp, 0o600);\n } catch {\n // chmod best-effort; writeFileSync mode already covers most filesystems.\n }\n renameSync(tmp, path);\n try {\n chmodSync(path, 0o600);\n } catch {\n // ignore — already attempted above\n }\n}\n\nfunction openDashboard(): void {\n try {\n const r = spawnSync('open', [DASHBOARD_KEYS_URL], { stdio: 'ignore' });\n if (r.status !== 0) {\n log.warn(`Could not auto-open the browser — visit ${DASHBOARD_KEYS_URL} manually.`);\n }\n } catch {\n log.warn(`Could not auto-open the browser — visit ${DASHBOARD_KEYS_URL} manually.`);\n }\n}\n\nexport function secretsPath(): string {\n return resolve(homedir(), '.agentbox', 'secrets.env');\n}\n\n/** What's currently configured. Used by `daytona login --status`. */\nexport interface DaytonaCredStatus {\n apiKey?: string;\n jwtToken?: string;\n organizationId?: string;\n source: 'env' | 'secrets.env' | 'none';\n}\n\nexport function readDaytonaCredStatus(): DaytonaCredStatus {\n // Snapshot what the shell already had before the loader runs so we can\n // distinguish env-from-shell from env-loaded-from-secrets.env.\n const shellHadKey = !!process.env.DAYTONA_API_KEY || !!process.env.DAYTONA_JWT_TOKEN;\n ensureDaytonaEnvLoaded();\n const apiKey = process.env.DAYTONA_API_KEY;\n const jwtToken = process.env.DAYTONA_JWT_TOKEN;\n const organizationId = process.env.DAYTONA_ORGANIZATION_ID;\n if (!apiKey && !jwtToken) return { source: 'none' };\n return {\n apiKey,\n jwtToken,\n organizationId,\n source: shellHadKey ? 'env' : 'secrets.env',\n };\n}\n\nexport function maskKey(value: string): string {\n if (value.length <= 8) return '*'.repeat(value.length);\n return `${value.slice(0, 4)}…${'*'.repeat(8)}${value.slice(-4)}`;\n}\n"],"mappings":"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","names":["existsSync","resolve","DaytonaNotFoundError","readFileSync","homedir","dirname","log","client","Daytona"]}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ CloudBoxPoller,
4
+ CloudBoxPollers
5
+ } from "./chunk-G3H2L3O2.js";
6
+ export {
7
+ CloudBoxPoller,
8
+ CloudBoxPollers
9
+ };
10
+ //# sourceMappingURL=cloud-poller-SUNA6ZQC-2RG5WPRN.js.map
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DEFAULT_BOX_IMAGE_REF,
4
+ daytonaBackend,
5
+ ensureDaytonaCredentials,
6
+ ensureDaytonaEnvLoaded,
7
+ getClient,
8
+ resolveDaytonaCustomClaudeMd,
9
+ resolveDockerfileContext
10
+ } from "./chunk-LEV3KICD.js";
11
+ import {
12
+ createCloudProvider
13
+ } from "./chunk-67N47KUS.js";
14
+ import {
15
+ stageClaudeStaticForUpload,
16
+ stageCodexStaticForUpload,
17
+ stageOpencodeStaticForUpload
18
+ } from "./chunk-6OZDFNBF.js";
19
+ import {
20
+ DOCKER_CONTEXT_FILE_MAP,
21
+ computeContextSha256,
22
+ readCliStamp,
23
+ readPreparedStateRaw,
24
+ resolveContextFilesFrom,
25
+ writePreparedStateRaw
26
+ } from "./chunk-BGK32PZE.js";
27
+ import "./chunk-G3H2L3O2.js";
28
+
29
+ // ../../packages/sandbox-daytona/dist/index.js
30
+ import { Image } from "@daytonaio/sdk";
31
+ import { existsSync } from "fs";
32
+ import { dirname, resolve } from "path";
33
+ import { fileURLToPath } from "url";
34
+ var SCHEMA = 1;
35
+ function resolveDaytonaContextFiles() {
36
+ const ctx = resolveDockerfileContext();
37
+ if (!ctx) return null;
38
+ const here = dirname(fileURLToPath(import.meta.url));
39
+ const packageRoot = resolve(here, "..");
40
+ const monorepoRoot = resolve(here, "..", "..", "..");
41
+ const dockerPackageRoot = resolve(monorepoRoot, "packages", "sandbox-docker");
42
+ const docker = resolveContextFilesFrom(DOCKER_CONTEXT_FILE_MAP, {
43
+ contextDir: ctx.context,
44
+ devRoot: existsSync(dockerPackageRoot) ? dockerPackageRoot : packageRoot
45
+ });
46
+ if (!docker) return null;
47
+ const overlay = resolveDaytonaCustomClaudeMd();
48
+ if (!overlay) return null;
49
+ return [
50
+ ...docker,
51
+ // Daytona-specific overlay: separate logical name so a docker/daytona
52
+ // CLAUDE.md drift produces different fingerprints (the daytona snapshot
53
+ // contains both files in distinct locations).
54
+ { rel: "daytona/custom-system-CLAUDE.md", abs: overlay }
55
+ ];
56
+ }
57
+ async function computeDaytonaContextFingerprint() {
58
+ const files = resolveDaytonaContextFiles();
59
+ if (!files) return null;
60
+ return { contextSha256: await computeContextSha256(files), files };
61
+ }
62
+ function readPreparedDaytonaState() {
63
+ const raw = readPreparedStateRaw("daytona");
64
+ if (raw === null || typeof raw !== "object") return null;
65
+ const parsed = raw;
66
+ if (parsed.schema !== SCHEMA) return null;
67
+ return { schema: SCHEMA, base: parsed.base };
68
+ }
69
+ function writePreparedDaytonaState(opts) {
70
+ const stamp = readCliStamp();
71
+ const state = {
72
+ schema: SCHEMA,
73
+ base: {
74
+ imageRef: opts.snapshotName,
75
+ contextSha256: opts.contextSha256,
76
+ cliVersion: stamp.cliVersion,
77
+ cliCommit: stamp.cliCommit,
78
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
79
+ }
80
+ };
81
+ writePreparedStateRaw("daytona", state);
82
+ }
83
+ function preparedMatches(state, current) {
84
+ return state?.base?.contextSha256 === current;
85
+ }
86
+ function defaultSnapshotName(fingerprint) {
87
+ if (fingerprint) return `agentbox-base-${fingerprint.slice(0, 12)}`;
88
+ return `agentbox-base-${Math.floor(Date.now() / 1e3).toString()}`;
89
+ }
90
+ async function stageAllAgentStatic(opts) {
91
+ const [claudeStaged, codexStaged, opencodeStaged] = await Promise.all([
92
+ stageClaudeStaticForUpload({ hostWorkspace: opts.hostWorkspace }),
93
+ stageCodexStaticForUpload(),
94
+ stageOpencodeStaticForUpload()
95
+ ]);
96
+ return [
97
+ {
98
+ kind: "claude",
99
+ remoteTar: "/tmp/agentbox-seed-claude.tar.gz",
100
+ extractDir: "/home/vscode/.claude",
101
+ staged: claudeStaged
102
+ },
103
+ {
104
+ kind: "codex",
105
+ remoteTar: "/tmp/agentbox-seed-codex.tar.gz",
106
+ extractDir: "/home/vscode/.codex",
107
+ staged: codexStaged
108
+ },
109
+ {
110
+ kind: "opencode",
111
+ remoteTar: "/tmp/agentbox-seed-opencode.tar.gz",
112
+ extractDir: "/home/vscode/.local/share/opencode",
113
+ staged: opencodeStaged
114
+ }
115
+ ];
116
+ }
117
+ async function prepareDaytona(opts) {
118
+ ensureDaytonaEnvLoaded();
119
+ const log = opts.onLog ?? (() => {
120
+ });
121
+ const fingerprint = await computeDaytonaContextFingerprint();
122
+ const snapshotName = opts.name ?? defaultSnapshotName(fingerprint?.contextSha256 ?? null);
123
+ const prepared = readPreparedDaytonaState();
124
+ if (!opts.force && fingerprint && preparedMatches(prepared, fingerprint.contextSha256)) {
125
+ try {
126
+ const existing = await getClient().snapshot.get(
127
+ prepared?.base?.imageRef ?? snapshotName
128
+ );
129
+ if (existing?.name) {
130
+ log(
131
+ `daytona snapshot '${existing.name}' up to date (fingerprint ${fingerprint.contextSha256.slice(0, 12)}) \u2014 skipping rebuild (pass --force to override)`
132
+ );
133
+ return { snapshotName: existing.name };
134
+ }
135
+ log(
136
+ `recorded snapshot '${prepared?.base?.imageRef ?? snapshotName}' not found on Daytona; rebuilding`
137
+ );
138
+ } catch {
139
+ log(
140
+ `recorded snapshot lookup failed; rebuilding (pass --force to silence)`
141
+ );
142
+ }
143
+ } else if (!opts.force && fingerprint && prepared?.base?.contextSha256) {
144
+ log(
145
+ `daytona build context changed (was ${prepared.base.contextSha256.slice(0, 12)}, now ${fingerprint.contextSha256.slice(0, 12)}); rebuilding snapshot`
146
+ );
147
+ }
148
+ const ctx = resolveDockerfileContext();
149
+ if (!ctx) {
150
+ throw new Error(
151
+ "could not locate AgentBox Dockerfile.box build context for the Daytona snapshot. Set AGENTBOX_DOCKER_CONTEXT to the directory containing Dockerfile.box."
152
+ );
153
+ }
154
+ const daytonaClaudeMd = resolveDaytonaCustomClaudeMd();
155
+ if (!daytonaClaudeMd) {
156
+ throw new Error(
157
+ "could not locate packages/sandbox-daytona/scripts/custom-system-CLAUDE.md (or its staged runtime/daytona/ copy). Ensure `pnpm -w build` ran so the CLI staging populated runtime/daytona/."
158
+ );
159
+ }
160
+ const stages = await stageAllAgentStatic({ hostWorkspace: opts.hostWorkspace });
161
+ for (const s of stages) {
162
+ for (const w of s.staged.warnings) log(w);
163
+ }
164
+ try {
165
+ let image = Image.fromDockerfile(ctx.dockerfile);
166
+ image = image.addLocalFile(daytonaClaudeMd, "/tmp/agentbox-custom-CLAUDE.md");
167
+ const extractCmds = [
168
+ "install -m 0644 /tmp/agentbox-custom-CLAUDE.md /etc/claude-code/CLAUDE.md",
169
+ "rm -f /tmp/agentbox-custom-CLAUDE.md"
170
+ ];
171
+ const usable = stages.filter((s) => s.staged.tarballPath !== null);
172
+ for (const s of usable) {
173
+ image = image.addLocalFile(s.staged.tarballPath, s.remoteTar);
174
+ extractCmds.push(`mkdir -p ${s.extractDir}`);
175
+ extractCmds.push(`tar -xzf ${s.remoteTar} -C ${s.extractDir}`);
176
+ }
177
+ if (usable.length > 0) {
178
+ extractCmds.push(
179
+ "chown -R vscode:vscode /home/vscode/.claude /home/vscode/.codex /home/vscode/.local"
180
+ );
181
+ extractCmds.push("rm -f /tmp/agentbox-seed-*.tar.gz");
182
+ }
183
+ image = image.dockerfileCommands(["USER root"]).runCommands(...extractCmds).dockerfileCommands(["USER vscode"]);
184
+ const client = getClient();
185
+ log(`creating Daytona snapshot '${snapshotName}'\u2026`);
186
+ const snapshot = await client.snapshot.create(
187
+ { name: snapshotName, image },
188
+ {
189
+ onLogs: (chunk) => log(String(chunk).split("\n").filter(Boolean).join(" "))
190
+ }
191
+ );
192
+ log(`snapshot '${snapshot.name}' is ${snapshot.state ?? "created"}`);
193
+ if (fingerprint) {
194
+ writePreparedDaytonaState({
195
+ snapshotName: snapshot.name ?? snapshotName,
196
+ contextSha256: fingerprint.contextSha256
197
+ });
198
+ log(
199
+ `recorded daytona-prepared.json (fingerprint ${fingerprint.contextSha256.slice(0, 12)})`
200
+ );
201
+ }
202
+ return { snapshotName: snapshot.name ?? snapshotName };
203
+ } finally {
204
+ await Promise.all(stages.map((s) => s.staged.cleanup()));
205
+ }
206
+ }
207
+ function isAgentboxName(name) {
208
+ return typeof name === "string" && name.toLowerCase().startsWith("agentbox");
209
+ }
210
+ async function getDaytonaStatus() {
211
+ try {
212
+ ensureDaytonaEnvLoaded();
213
+ } catch (err) {
214
+ return {
215
+ configured: false,
216
+ snapshots: [],
217
+ volumes: [],
218
+ reason: err instanceof Error ? err.message : String(err)
219
+ };
220
+ }
221
+ let client;
222
+ try {
223
+ client = getClient();
224
+ } catch (err) {
225
+ return {
226
+ configured: false,
227
+ snapshots: [],
228
+ volumes: [],
229
+ reason: err instanceof Error ? err.message.split("\n")[0] : String(err)
230
+ };
231
+ }
232
+ const snapshots = [];
233
+ const volumes = [];
234
+ let reason;
235
+ try {
236
+ const list = await client.snapshot.list();
237
+ const items = list.items ?? (Array.isArray(list) ? list : []);
238
+ for (const s of items) {
239
+ const dto = s;
240
+ if (!isAgentboxName(dto.name)) continue;
241
+ snapshots.push({
242
+ name: dto.name,
243
+ state: typeof dto.state === "string" ? dto.state : void 0,
244
+ sizeGb: typeof dto.size === "number" ? dto.size : void 0,
245
+ createdAt: typeof dto.createdAt === "string" ? dto.createdAt : void 0,
246
+ errorReason: typeof dto.errorReason === "string" ? dto.errorReason : void 0
247
+ });
248
+ }
249
+ } catch (err) {
250
+ reason = `snapshot list failed: ${err instanceof Error ? err.message.split("\n")[0] : String(err)}`;
251
+ }
252
+ try {
253
+ const list = await client.volume.list();
254
+ const items = Array.isArray(list) ? list : list.items ?? [];
255
+ for (const v of items) {
256
+ const dto = v;
257
+ if (!isAgentboxName(dto.name)) continue;
258
+ volumes.push({
259
+ name: dto.name,
260
+ id: typeof dto.id === "string" ? dto.id : "",
261
+ state: typeof dto.state === "string" ? dto.state : void 0,
262
+ createdAt: typeof dto.createdAt === "string" ? dto.createdAt : void 0,
263
+ lastUsedAt: typeof dto.lastUsedAt === "string" ? dto.lastUsedAt : void 0
264
+ });
265
+ }
266
+ } catch (err) {
267
+ const msg = `volume list failed: ${err instanceof Error ? err.message.split("\n")[0] : String(err)}`;
268
+ reason = reason ? `${reason}; ${msg}` : msg;
269
+ }
270
+ return {
271
+ configured: true,
272
+ snapshots: snapshots.sort((a, b) => (b.createdAt ?? "").localeCompare(a.createdAt ?? "")),
273
+ volumes: volumes.sort((a, b) => a.name.localeCompare(b.name)),
274
+ reason
275
+ };
276
+ }
277
+ var cloudProvider = createCloudProvider(daytonaBackend, {
278
+ defaultResources: { cpu: 2, memory: 4, disk: 8 }
279
+ });
280
+ var daytonaProvider = {
281
+ ...cloudProvider,
282
+ prepare: prepareDaytona
283
+ };
284
+ export {
285
+ DEFAULT_BOX_IMAGE_REF,
286
+ daytonaBackend,
287
+ daytonaProvider,
288
+ ensureDaytonaCredentials,
289
+ ensureDaytonaEnvLoaded,
290
+ getDaytonaStatus,
291
+ resolveDockerfileContext
292
+ };
293
+ //# sourceMappingURL=dist-L4LCG5SJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../packages/sandbox-daytona/src/index.ts","../../../packages/sandbox-daytona/src/prepare.ts","../../../packages/sandbox-daytona/src/prepared-state.ts","../../../packages/sandbox-daytona/src/status.ts"],"sourcesContent":["/**\n * The Daytona Cloud sandbox provider. A thin `CloudBackend` over\n * `@daytonaio/sdk`, composed via `@agentbox/sandbox-cloud`'s `createCloudProvider`\n * for everything provider-agnostic (workspace seeding, ctl launch, state).\n */\n\nimport type { Provider } from '@agentbox/core';\nimport { createCloudProvider } from '@agentbox/sandbox-cloud';\nimport { daytonaBackend, DEFAULT_BOX_IMAGE_REF } from './backend.js';\nimport { prepareDaytona } from './prepare.js';\n\nconst cloudProvider = createCloudProvider(daytonaBackend, {\n defaultResources: { cpu: 2, memory: 4, disk: 8 },\n});\n\nexport const daytonaProvider: Provider = {\n ...cloudProvider,\n prepare: prepareDaytona,\n};\n\nexport { daytonaBackend, DEFAULT_BOX_IMAGE_REF };\nexport { resolveDockerfileContext, type DockerfileContext } from './dockerfile-context.js';\nexport { ensureDaytonaEnvLoaded } from './env-loader.js';\n// Called by the CLI provider registry to gate first-run interactive setup.\n// Plain async function — no commander surface — so adding it here doesn't\n// pull commander/clack into consumers' type graphs. The full CLI command\n// lives at the `./cli` subpath export.\nexport { ensureDaytonaCredentials } from './credentials.js';\nexport type { EnsureDaytonaCredentialsOptions } from './credentials.js';\nexport {\n getDaytonaStatus,\n type DaytonaStatus,\n type DaytonaSnapshotSummary,\n type DaytonaVolumeSummary,\n} from './status.js';\n","/**\n * Daytona-side implementation of the `Provider.prepare` hook (`agentbox\n * prepare --provider daytona`). One-time, user-triggered:\n *\n * 1. Stage filtered tarballs of the host's `~/.claude`, `~/.codex`, and\n * `~/.local/share/opencode` static config (no auth tokens — those go on\n * the per-org `agentbox-credentials` volume at create time).\n * 2. Build a layered Daytona `Image`: start from `Dockerfile.box`, then\n * `.addLocalFile()` each staged tarball + `.runCommands()` to extract\n * them into the right paths inside the image.\n * 3. Call `daytona.snapshot.create({ name, image }, { onLogs })` — Daytona\n * runs the build server-side, registers the result as an org-scoped\n * named snapshot, and returns when it's `active`.\n *\n * Replaces the old `agentbox daytona publish-snapshot` flow that\n * provisioned a sandbox + ran an in-sandbox bake + called the broken\n * `_experimental_createSnapshot`. The new path never provisions a sandbox.\n *\n * Source of truth for the public API:\n * https://www.daytona.io/docs/en/snapshots/\n */\n\nimport { Image } from '@daytonaio/sdk';\nimport type { PrepareOptions, PrepareResult } from '@agentbox/core';\nimport {\n stageClaudeStaticForUpload,\n stageCodexStaticForUpload,\n stageOpencodeStaticForUpload,\n type StageResult,\n} from '@agentbox/sandbox-cloud';\nimport { getClient } from './backend.js';\nimport { resolveDaytonaCustomClaudeMd, resolveDockerfileContext } from './dockerfile-context.js';\nimport { ensureDaytonaEnvLoaded } from './env-loader.js';\nimport {\n computeDaytonaContextFingerprint,\n preparedMatches,\n readPreparedDaytonaState,\n writePreparedDaytonaState,\n} from './prepared-state.js';\n\n/**\n * Default snapshot name. Keyed on the first 12 chars of the build-context\n * fingerprint so identical content produces the same snapshot name across\n * machines / CLI runs (idempotent): if the named snapshot already exists\n * on Daytona, prepare can short-circuit without uploading the build\n * context again. Falls back to a timestamp when fingerprinting fails\n * (partial dev rebuild).\n */\nfunction defaultSnapshotName(fingerprint: string | null): string {\n if (fingerprint) return `agentbox-base-${fingerprint.slice(0, 12)}`;\n return `agentbox-base-${Math.floor(Date.now() / 1000).toString()}`;\n}\n\ninterface AgentStage {\n kind: 'claude' | 'codex' | 'opencode';\n /** Path inside the image build that the tarball is uploaded to. */\n remoteTar: string;\n /** Path the image build extracts the tarball into. */\n extractDir: string;\n staged: StageResult;\n}\n\n/**\n * Stage the three agents' static tarballs in parallel. Each `StageResult`'s\n * `cleanup()` must be called by the caller, after the image build picks the\n * file up.\n */\nasync function stageAllAgentStatic(opts: { hostWorkspace?: string }): Promise<AgentStage[]> {\n const [claudeStaged, codexStaged, opencodeStaged] = await Promise.all([\n stageClaudeStaticForUpload({ hostWorkspace: opts.hostWorkspace }),\n stageCodexStaticForUpload(),\n stageOpencodeStaticForUpload(),\n ]);\n return [\n {\n kind: 'claude',\n remoteTar: '/tmp/agentbox-seed-claude.tar.gz',\n extractDir: '/home/vscode/.claude',\n staged: claudeStaged,\n },\n {\n kind: 'codex',\n remoteTar: '/tmp/agentbox-seed-codex.tar.gz',\n extractDir: '/home/vscode/.codex',\n staged: codexStaged,\n },\n {\n kind: 'opencode',\n remoteTar: '/tmp/agentbox-seed-opencode.tar.gz',\n extractDir: '/home/vscode/.local/share/opencode',\n staged: opencodeStaged,\n },\n ];\n}\n\n/**\n * Run `agentbox prepare --provider daytona`. Returns `{ snapshotName }` on\n * success so the CLI can pin it into the project config.\n */\nexport async function prepareDaytona(opts: PrepareOptions): Promise<PrepareResult> {\n ensureDaytonaEnvLoaded();\n const log = opts.onLog ?? (() => {});\n\n // Fingerprint the build context first so we can (a) name the snapshot\n // deterministically and (b) detect cache hits against the recorded\n // prepared state. Computed before staging so an early `null` (partial\n // dev rebuild) doesn't waste a tar staging cycle.\n const fingerprint = await computeDaytonaContextFingerprint();\n const snapshotName =\n opts.name ?? defaultSnapshotName(fingerprint?.contextSha256 ?? null);\n\n const prepared = readPreparedDaytonaState();\n if (\n !opts.force &&\n fingerprint &&\n preparedMatches(prepared, fingerprint.contextSha256)\n ) {\n // Confirm the snapshot still exists on Daytona before short-circuiting.\n // A \"yes locally, no on the server\" mismatch must rebuild.\n try {\n const existing = await getClient().snapshot.get(\n prepared?.base?.imageRef ?? snapshotName,\n );\n if (existing?.name) {\n log(\n `daytona snapshot '${existing.name}' up to date ` +\n `(fingerprint ${fingerprint.contextSha256.slice(0, 12)}) — skipping rebuild ` +\n `(pass --force to override)`,\n );\n return { snapshotName: existing.name };\n }\n log(\n `recorded snapshot '${prepared?.base?.imageRef ?? snapshotName}' not found on Daytona; rebuilding`,\n );\n } catch {\n log(\n `recorded snapshot lookup failed; rebuilding (pass --force to silence)`,\n );\n }\n } else if (!opts.force && fingerprint && prepared?.base?.contextSha256) {\n log(\n `daytona build context changed (was ${prepared.base.contextSha256.slice(0, 12)}, ` +\n `now ${fingerprint.contextSha256.slice(0, 12)}); rebuilding snapshot`,\n );\n }\n\n const ctx = resolveDockerfileContext();\n if (!ctx) {\n throw new Error(\n 'could not locate AgentBox Dockerfile.box build context for the Daytona snapshot. ' +\n 'Set AGENTBOX_DOCKER_CONTEXT to the directory containing Dockerfile.box.',\n );\n }\n\n const daytonaClaudeMd = resolveDaytonaCustomClaudeMd();\n if (!daytonaClaudeMd) {\n throw new Error(\n 'could not locate packages/sandbox-daytona/scripts/custom-system-CLAUDE.md ' +\n '(or its staged runtime/daytona/ copy). Ensure `pnpm -w build` ran so the ' +\n 'CLI staging populated runtime/daytona/.',\n );\n }\n\n const stages = await stageAllAgentStatic({ hostWorkspace: opts.hostWorkspace });\n // Surface staging warnings (codex Keychain landmine, etc.) before the\n // longer build kicks off.\n for (const s of stages) {\n for (const w of s.staged.warnings) log(w);\n }\n\n try {\n let image: Image = Image.fromDockerfile(ctx.dockerfile);\n\n // Overlay the daytona-specific /etc/claude-code/CLAUDE.md on top of the\n // docker-shaped one baked by Dockerfile.box. Daytona boxes have no host\n // .git/ bind-mount, so the in-box hint needs daytona-specific git wording.\n image = image.addLocalFile(daytonaClaudeMd, '/tmp/agentbox-custom-CLAUDE.md');\n const extractCmds: string[] = [\n 'install -m 0644 /tmp/agentbox-custom-CLAUDE.md /etc/claude-code/CLAUDE.md',\n 'rm -f /tmp/agentbox-custom-CLAUDE.md',\n ];\n\n // For each agent whose stage produced a tarball, add the file to the\n // image build context and append a single tar-extract + chown.\n const usable = stages.filter((s) => s.staged.tarballPath !== null);\n for (const s of usable) {\n image = image.addLocalFile(s.staged.tarballPath as string, s.remoteTar);\n extractCmds.push(`mkdir -p ${s.extractDir}`);\n extractCmds.push(`tar -xzf ${s.remoteTar} -C ${s.extractDir}`);\n }\n if (usable.length > 0) {\n // One final pass: own the extracted trees as the box user, then drop the\n // staging tarballs (no point shipping them twice in the image layer).\n extractCmds.push(\n 'chown -R vscode:vscode /home/vscode/.claude /home/vscode/.codex /home/vscode/.local',\n );\n extractCmds.push('rm -f /tmp/agentbox-seed-*.tar.gz');\n }\n // Dockerfile.box ends with `USER vscode`. Switch to root for the\n // install/tar/chown/rm pass — COPYed files are root-owned in /tmp (sticky\n // bit), chown -R on /home/vscode/.* only works as root, and\n // /etc/claude-code is root-owned. Switch back to vscode so the image\n // keeps its default-user invariant.\n image = image\n .dockerfileCommands(['USER root'])\n .runCommands(...extractCmds)\n .dockerfileCommands(['USER vscode']);\n\n const client = getClient();\n log(`creating Daytona snapshot '${snapshotName}'…`);\n const snapshot = await client.snapshot.create(\n { name: snapshotName, image },\n {\n onLogs: (chunk: string) => log(String(chunk).split('\\n').filter(Boolean).join(' ')),\n },\n );\n log(`snapshot '${snapshot.name}' is ${snapshot.state ?? 'created'}`);\n if (fingerprint) {\n writePreparedDaytonaState({\n snapshotName: snapshot.name ?? snapshotName,\n contextSha256: fingerprint.contextSha256,\n });\n log(\n `recorded daytona-prepared.json (fingerprint ${fingerprint.contextSha256.slice(0, 12)})`,\n );\n }\n return { snapshotName: snapshot.name ?? snapshotName };\n } finally {\n await Promise.all(stages.map((s) => s.staged.cleanup()));\n }\n}\n","/**\n * Daytona provider's `~/.agentbox/daytona-prepared.json` reader/writer +\n * build-context fingerprinting for the org-scoped base snapshot.\n *\n * The daytona prepare bakes the docker `Dockerfile.box` plus a daytona-\n * specific `custom-system-CLAUDE.md` overlay. The fingerprint covers both\n * — same canonical file map as the docker provider for the dockerfile\n * inputs, plus one extra entry for the daytona overlay.\n */\n\nimport { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n computeContextSha256,\n DOCKER_CONTEXT_FILE_MAP,\n readCliStamp,\n readPreparedStateRaw,\n resolveContextFilesFrom,\n writePreparedStateRaw,\n type ContextFile,\n type PreparedBaseSnapshot,\n} from '@agentbox/sandbox-core';\nimport { resolveDaytonaCustomClaudeMd, resolveDockerfileContext } from './dockerfile-context.js';\n\nconst SCHEMA = 1 as const;\n\nexport type PreparedDaytonaState = PreparedBaseSnapshot<string, never>;\n\n/**\n * Resolve every file that influences the daytona base snapshot: the docker\n * build context (shared map from sandbox-core) plus the daytona-specific\n * CLAUDE.md overlay added by `Image.addLocalFile` in `prepare.ts`.\n *\n * Returns `null` if any file is missing — callers degrade to \"always\n * rebuild\" rather than stamp a misleading fingerprint.\n */\nexport function resolveDaytonaContextFiles(): ContextFile[] | null {\n const ctx = resolveDockerfileContext();\n if (!ctx) return null;\n // sandbox-daytona's package root = parent of src/ or parent of dist/.\n // Mirrors the `resolve(here, '..', '..', '..')` walk in dockerfile-context.ts.\n const here = dirname(fileURLToPath(import.meta.url));\n const packageRoot = resolve(here, '..');\n const monorepoRoot = resolve(here, '..', '..', '..');\n // Docker's dev fallback is anchored at sandbox-docker's root, not\n // sandbox-daytona's, so we pass the monorepo root and prefix the dev\n // paths to walk into packages/sandbox-docker/.\n //\n // Simpler: just point devRoot at sandbox-docker's package root when it\n // exists (legacy monorepo layout).\n const dockerPackageRoot = resolve(monorepoRoot, 'packages', 'sandbox-docker');\n const docker = resolveContextFilesFrom(DOCKER_CONTEXT_FILE_MAP, {\n contextDir: ctx.context,\n devRoot: existsSync(dockerPackageRoot) ? dockerPackageRoot : packageRoot,\n });\n if (!docker) return null;\n const overlay = resolveDaytonaCustomClaudeMd();\n if (!overlay) return null;\n return [\n ...docker,\n // Daytona-specific overlay: separate logical name so a docker/daytona\n // CLAUDE.md drift produces different fingerprints (the daytona snapshot\n // contains both files in distinct locations).\n { rel: 'daytona/custom-system-CLAUDE.md', abs: overlay },\n ];\n}\n\nexport interface DaytonaFingerprint {\n contextSha256: string;\n files: ContextFile[];\n}\n\nexport async function computeDaytonaContextFingerprint(): Promise<DaytonaFingerprint | null> {\n const files = resolveDaytonaContextFiles();\n if (!files) return null;\n return { contextSha256: await computeContextSha256(files), files };\n}\n\nexport function readPreparedDaytonaState(): PreparedDaytonaState | null {\n const raw = readPreparedStateRaw('daytona');\n if (raw === null || typeof raw !== 'object') return null;\n const parsed = raw as Partial<PreparedDaytonaState>;\n if (parsed.schema !== SCHEMA) return null;\n return { schema: SCHEMA, base: parsed.base };\n}\n\nexport function writePreparedDaytonaState(opts: {\n snapshotName: string;\n contextSha256: string;\n}): void {\n const stamp = readCliStamp();\n const state: PreparedDaytonaState = {\n schema: SCHEMA,\n base: {\n imageRef: opts.snapshotName,\n contextSha256: opts.contextSha256,\n cliVersion: stamp.cliVersion,\n cliCommit: stamp.cliCommit,\n createdAt: new Date().toISOString(),\n },\n };\n writePreparedStateRaw('daytona', state);\n}\n\nexport function preparedMatches(\n state: PreparedDaytonaState | null,\n current: string,\n): boolean {\n return state?.base?.contextSha256 === current;\n}\n","/**\n * Read-only status helpers for `agentbox prepare` (no-args mode). Surfaces\n * the user-facing inventory of agentbox-owned base images / snapshots /\n * volumes on the configured Daytona org so the user can see at a glance\n * what's already prepared and what isn't.\n *\n * Daytona-side state lives in two places:\n * - **Snapshots** — built by `agentbox prepare --provider daytona`. Listed\n * filtered to `agentbox*` so we don't surface unrelated org snapshots.\n * - **Volumes** — the per-org `agentbox-credentials` volume created lazily\n * by `ensureAgentVolumesForCloud` on first `agentbox create --provider\n * daytona`.\n *\n * All calls swallow auth/network errors and return an empty section — the\n * status command must work for users who don't have Daytona configured.\n */\n\nimport { ensureDaytonaEnvLoaded } from './env-loader.js';\nimport { getClient } from './backend.js';\n\nexport interface DaytonaSnapshotSummary {\n name: string;\n state?: string;\n /** Snapshot size in GB, as reported by Daytona (may be undefined for non-`active` states). */\n sizeGb?: number;\n createdAt?: string;\n errorReason?: string;\n}\n\nexport interface DaytonaVolumeSummary {\n name: string;\n id: string;\n state?: string;\n createdAt?: string;\n lastUsedAt?: string;\n}\n\nexport interface DaytonaStatus {\n /** True when Daytona credentials are present + the SDK could connect. */\n configured: boolean;\n /** Snapshots whose name starts with `agentbox` (case-insensitive). */\n snapshots: DaytonaSnapshotSummary[];\n /** Volumes whose name starts with `agentbox` (case-insensitive). */\n volumes: DaytonaVolumeSummary[];\n /** Non-fatal explanation when `configured` is false. */\n reason?: string;\n}\n\nfunction isAgentboxName(name: unknown): boolean {\n return typeof name === 'string' && name.toLowerCase().startsWith('agentbox');\n}\n\n/**\n * Collect a read-only summary of agentbox-owned snapshots + volumes on the\n * Daytona org. Never throws — failure paths return `configured: false` with\n * a one-line reason.\n */\nexport async function getDaytonaStatus(): Promise<DaytonaStatus> {\n try {\n ensureDaytonaEnvLoaded();\n } catch (err) {\n return {\n configured: false,\n snapshots: [],\n volumes: [],\n reason: err instanceof Error ? err.message : String(err),\n };\n }\n\n let client;\n try {\n client = getClient();\n } catch (err) {\n return {\n configured: false,\n snapshots: [],\n volumes: [],\n reason: err instanceof Error ? err.message.split('\\n')[0] : String(err),\n };\n }\n\n const snapshots: DaytonaSnapshotSummary[] = [];\n const volumes: DaytonaVolumeSummary[] = [];\n let reason: string | undefined;\n\n try {\n const list = await client.snapshot.list();\n const items = (list as { items?: unknown[] }).items ?? (Array.isArray(list) ? list : []);\n for (const s of items) {\n const dto = s as { name?: unknown; state?: unknown; size?: unknown; createdAt?: unknown; errorReason?: unknown };\n if (!isAgentboxName(dto.name)) continue;\n snapshots.push({\n name: dto.name as string,\n state: typeof dto.state === 'string' ? dto.state : undefined,\n sizeGb: typeof dto.size === 'number' ? dto.size : undefined,\n createdAt: typeof dto.createdAt === 'string' ? dto.createdAt : undefined,\n errorReason: typeof dto.errorReason === 'string' ? dto.errorReason : undefined,\n });\n }\n } catch (err) {\n reason = `snapshot list failed: ${err instanceof Error ? err.message.split('\\n')[0] : String(err)}`;\n }\n\n try {\n const list = await client.volume.list();\n const items: unknown[] = Array.isArray(list)\n ? list\n : ((list as { items?: unknown[] }).items ?? []);\n for (const v of items) {\n const dto = v as { name?: unknown; id?: unknown; state?: unknown; createdAt?: unknown; lastUsedAt?: unknown };\n if (!isAgentboxName(dto.name)) continue;\n volumes.push({\n name: dto.name as string,\n id: typeof dto.id === 'string' ? dto.id : '',\n state: typeof dto.state === 'string' ? dto.state : undefined,\n createdAt: typeof dto.createdAt === 'string' ? dto.createdAt : undefined,\n lastUsedAt: typeof dto.lastUsedAt === 'string' ? dto.lastUsedAt : undefined,\n });\n }\n } catch (err) {\n const msg = `volume list failed: ${err instanceof Error ? err.message.split('\\n')[0] : String(err)}`;\n reason = reason ? `${reason}; ${msg}` : msg;\n }\n\n return {\n configured: true,\n snapshots: snapshots.sort((a, b) => (b.createdAt ?? '').localeCompare(a.createdAt ?? '')),\n volumes: volumes.sort((a, b) => a.name.localeCompare(b.name)),\n reason,\n };\n}\n"],"mappings":"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","names":[]}