@madarco/agentbox 0.11.3 → 0.12.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/CHANGELOG.md +59 -0
- package/dist/{_cloud-attach-XWCVLO5V.js → _cloud-attach-XKO4SHR3.js} +3 -3
- package/dist/{chunk-ZGVMN54V.js → chunk-2LF5YILI.js} +21 -3
- package/dist/chunk-2LF5YILI.js.map +1 -0
- package/dist/{chunk-MXXXKJYS.js → chunk-DHJ7OMIP.js} +234 -83
- package/dist/chunk-DHJ7OMIP.js.map +1 -0
- package/dist/{chunk-GYJ62GFL.js → chunk-HFV6THYG.js} +6 -6
- package/dist/{chunk-ZJXTIH6C.js → chunk-IZXPJPPV.js} +1347 -852
- package/dist/chunk-IZXPJPPV.js.map +1 -0
- package/dist/{dist-RAZP76VX.js → dist-24PY2ZMO.js} +3 -3
- package/dist/{dist-PTJ6CEQY.js → dist-47LVLYUV.js} +4 -4
- package/dist/{dist-ASLPRUQR.js → dist-RZZSSUNB.js} +28 -2
- package/dist/{dist-WMQDMTWS.js → dist-SWUOU34W.js} +8 -5
- package/dist/dist-SWUOU34W.js.map +1 -0
- package/dist/index.js +1324 -736
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/runtime/docker/packages/ctl/dist/bin.cjs +335 -4
- package/runtime/docker/packages/sandbox-docker/scripts/gh-shim +86 -5
- package/runtime/hetzner/ctl.cjs +335 -4
- package/runtime/hetzner/gh-shim +86 -5
- package/runtime/relay/bin.cjs +285 -2
- package/runtime/vercel/ctl.cjs +335 -4
- package/runtime/vercel/gh-shim +86 -5
- package/share/host-skills/agentbox/SKILL.md +16 -5
- package/share/host-skills/agentbox-info/SKILL.md +3 -1
- package/dist/chunk-MXXXKJYS.js.map +0 -1
- package/dist/chunk-ZGVMN54V.js.map +0 -1
- package/dist/chunk-ZJXTIH6C.js.map +0 -1
- package/dist/dist-WMQDMTWS.js.map +0 -1
- /package/dist/{_cloud-attach-XWCVLO5V.js.map → _cloud-attach-XKO4SHR3.js.map} +0 -0
- /package/dist/{chunk-GYJ62GFL.js.map → chunk-HFV6THYG.js.map} +0 -0
- /package/dist/{dist-RAZP76VX.js.map → dist-24PY2ZMO.js.map} +0 -0
- /package/dist/{dist-PTJ6CEQY.js.map → dist-47LVLYUV.js.map} +0 -0
- /package/dist/{dist-ASLPRUQR.js.map → dist-RZZSSUNB.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,65 @@ Entries are generated from the commit history with `/release-notes` and then
|
|
|
9
9
|
hand-reviewed — they describe what changed for someone using the `agentbox`
|
|
10
10
|
CLI, not the raw commits.
|
|
11
11
|
|
|
12
|
+
## [0.12.0] - 2026-06-01
|
|
13
|
+
|
|
14
|
+
### Breaking
|
|
15
|
+
|
|
16
|
+
- `agentbox fork` replaced the opt-in `--carry-yes` flag with an opt-out
|
|
17
|
+
`--carry <mode>`. Fork now copies the declared `carry:` files into the box
|
|
18
|
+
by default; pass `--carry skip` to opt out. Scripts passing `--carry-yes`
|
|
19
|
+
to `fork` must drop it.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- On agent-session start (`claude` / `codex` / `opencode`, including `-i`) and
|
|
24
|
+
on create-from-checkpoint, the box now resyncs with the host workspace:
|
|
25
|
+
it merges the host's current branch and overlays uncommitted + untracked
|
|
26
|
+
changes (box wins conflicts, skipped paths surfaced to the agent). Gated by
|
|
27
|
+
`box.resyncOnStart` (default on) / `--no-resync`. Docker only for now.
|
|
28
|
+
- `agentbox checkpoints -g` / `--global` lists checkpoints across every
|
|
29
|
+
project, grouped and labeled by project root (mirrors `agentbox list -g`).
|
|
30
|
+
- Expanded the relay `gh` proxy: `gh pr diff` / `gh pr checks`,
|
|
31
|
+
`gh run list` / `view` / `rerun`, allowlisted read-only `gh api` (GET), and
|
|
32
|
+
posting PR review comments via `gh api` POST without a prompt.
|
|
33
|
+
- `agentbox fork --plan <path>` carries a Claude Code plan into the box and
|
|
34
|
+
launches `claude` in plan mode, resuming from the plan.
|
|
35
|
+
- `agentbox create --size` plus `box.size` config with per-provider overrides
|
|
36
|
+
(`box.sizeDaytona` / `box.sizeHetzner`, etc.). Hetzner reads it as a
|
|
37
|
+
`server_type`; Daytona parses `cpu-memory-disk` GB.
|
|
38
|
+
- Per-provider `box.image` keys (`box.imageDocker` / `box.imageDaytona` /
|
|
39
|
+
`box.imageHetzner` / `box.imageVercel`) so a `prepare` on one provider no
|
|
40
|
+
longer overwrites another's base image.
|
|
41
|
+
- Boxes are now seeded with your `~/.claude/workflows/` and the project's
|
|
42
|
+
`memory/` at create, refreshed incrementally per-box rather than baked into
|
|
43
|
+
the snapshot. Works on docker, daytona, hetzner, and vercel.
|
|
44
|
+
- `-i` queued background runs now honor the `carry:` block (previously dropped).
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- `agentbox install` (and `pnpm register`) now symlink the host skills when run
|
|
49
|
+
from a source checkout, so edits to the bundled skills are picked up live; an
|
|
50
|
+
installed package still copies.
|
|
51
|
+
- Folded the orphan `git`, `vercel`, and `doctor` commands into the Advanced
|
|
52
|
+
group in `agentbox --help`.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- The setup wizard no longer silently boots from a stale default checkpoint. A
|
|
57
|
+
default snapshot captured against a since-rebuilt base (or a dead
|
|
58
|
+
image/snapshot) is now detected: interactive runs re-prompt (recreate vs use
|
|
59
|
+
anyway), and `-y`/non-interactive runs discard it and provision from the
|
|
60
|
+
current base. Explicit `--snapshot` is still honored as-is.
|
|
61
|
+
- Cloud boxes (vercel / hetzner / daytona) now get a git committer identity at
|
|
62
|
+
create, mirroring the host repo's, so the agent's commits and
|
|
63
|
+
`agentbox git pull` merge commits no longer fail with "Committer identity
|
|
64
|
+
unknown".
|
|
65
|
+
- `agentbox prepare` now always migrates a stale generic `box.image` left by an
|
|
66
|
+
older version, not just when it writes a new snapshot.
|
|
67
|
+
- A host skill symlinked outside the box-mounted trees (common in dev checkouts)
|
|
68
|
+
no longer aborts the whole `~/.claude` sync.
|
|
69
|
+
- A single corrupt project config no longer aborts `agentbox checkpoints -g`.
|
|
70
|
+
|
|
12
71
|
## [0.11.3] - 2026-05-31
|
|
13
72
|
|
|
14
73
|
### Changed
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
buildCloudAttachInnerCommand,
|
|
4
4
|
cloudAgentAttach,
|
|
5
5
|
cloudAgentStartDetached
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-HFV6THYG.js";
|
|
7
|
+
import "./chunk-IZXPJPPV.js";
|
|
8
8
|
import "./chunk-SNTHHWKY.js";
|
|
9
9
|
import "./chunk-G3H2L3O2.js";
|
|
10
10
|
export {
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
cloudAgentAttach,
|
|
13
13
|
cloudAgentStartDetached
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=_cloud-attach-
|
|
15
|
+
//# sourceMappingURL=_cloud-attach-XKO4SHR3.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
hostOpenCommand
|
|
4
4
|
} from "./chunk-SNTHHWKY.js";
|
|
5
5
|
|
|
6
|
-
// ../../packages/sandbox-daytona/dist/chunk-
|
|
6
|
+
// ../../packages/sandbox-daytona/dist/chunk-MLQU4RFU.js
|
|
7
7
|
import { existsSync } from "fs";
|
|
8
8
|
import { dirname, resolve } from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
@@ -285,14 +285,32 @@ function resolveImage(ref) {
|
|
|
285
285
|
}
|
|
286
286
|
return Image.fromDockerfile(ctx.dockerfile);
|
|
287
287
|
}
|
|
288
|
+
function parseDaytonaSize(spec) {
|
|
289
|
+
if (!spec) return void 0;
|
|
290
|
+
const parts = spec.trim().split("-");
|
|
291
|
+
if (parts.length !== 3) return void 0;
|
|
292
|
+
const nums = parts.map((p) => Number(p));
|
|
293
|
+
if (nums.some((n) => !Number.isInteger(n) || n <= 0)) return void 0;
|
|
294
|
+
return { cpu: nums[0], memory: nums[1], disk: nums[2] };
|
|
295
|
+
}
|
|
288
296
|
var daytonaBackend = {
|
|
289
297
|
name: "daytona",
|
|
290
298
|
async provision(req) {
|
|
291
299
|
return retry(
|
|
292
300
|
"provision",
|
|
293
301
|
async () => {
|
|
302
|
+
let sizeResources;
|
|
303
|
+
if (req.size && req.size.length > 0) {
|
|
304
|
+
sizeResources = parseDaytonaSize(req.size);
|
|
305
|
+
if (!sizeResources) {
|
|
306
|
+
req.onLog?.(
|
|
307
|
+
`daytona: ignoring invalid size '${req.size}' (expected 'cpu-memory-disk' GB, e.g. '4-8-20')`
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const resources = sizeResources ?? req.resources;
|
|
294
312
|
const baseParams = {
|
|
295
|
-
...
|
|
313
|
+
...resources ? { resources } : {},
|
|
296
314
|
envVars: req.env,
|
|
297
315
|
...req.volumes && req.volumes.length > 0 ? { volumes: req.volumes.map(toDaytonaVolumeMount) } : {},
|
|
298
316
|
labels: { "agentbox.name": req.name }
|
|
@@ -738,4 +756,4 @@ export {
|
|
|
738
756
|
readDaytonaCredStatus,
|
|
739
757
|
maskKey
|
|
740
758
|
};
|
|
741
|
-
//# sourceMappingURL=chunk-
|
|
759
|
+
//# sourceMappingURL=chunk-2LF5YILI.js.map
|
|
@@ -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\n/**\n * Parse a `cpu-memory-disk` GB size spec (e.g. `4-8-20`) into Daytona's\n * `resources` shape. Returns `undefined` on any malformed input — three\n * positive integer slots are required.\n */\nexport function parseDaytonaSize(\n spec: string | undefined,\n): { cpu: number; memory: number; disk: number } | undefined {\n if (!spec) return undefined;\n const parts = spec.trim().split('-');\n if (parts.length !== 3) return undefined;\n const nums = parts.map((p) => Number(p));\n if (nums.some((n) => !Number.isInteger(n) || n <= 0)) return undefined;\n return { cpu: nums[0]!, memory: nums[1]!, disk: nums[2]! };\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 // A `--size` / `box.sizeDaytona` like `4-8-20` overrides the default\n // resources. Note: Daytona rejects `resources` on the snapshot path\n // (stripped below), so this only takes effect when creating from an\n // image — snapshot-resume keeps the snapshot's baked-in resources.\n let sizeResources: { cpu: number; memory: number; disk: number } | undefined;\n if (req.size && req.size.length > 0) {\n sizeResources = parseDaytonaSize(req.size);\n if (!sizeResources) {\n req.onLog?.(\n `daytona: ignoring invalid size '${req.size}' (expected 'cpu-memory-disk' GB, e.g. '4-8-20')`,\n );\n }\n }\n const resources = sizeResources ?? req.resources;\n const baseParams = {\n ...(resources ? { 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 { hostOpenCommand } from '@agentbox/sandbox-core';\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(hostOpenCommand(), [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":";;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;ACF9B,SAAS,cAAAA,aAAY,oBAAoB;AACzC,SAAS,eAAe;AACxB,SAAS,WAAAC,gBAAe;ACIxB,SAAS,SAAS,wBAAAC,uBAAsB,OAAO,oBAAkC;ACMjF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;OACK;ACtBP,SAAS,iBAAiB;AAE1B;EACE;EACA,cAAAC;EACA;EACA,gBAAAC;EACA;EACA;OACK;AACP,SAAS,WAAAC,gBAAe;AACxB,SAAS,WAAAC,UAAS,WAAAC,gBAAe;AACjC,SAAS,SAAS,UAAU,OAAO,KAAK,MAAM,OAAO,UAAU,SAAS,YAAY;AJc7E,SAAS,2BAAqD;AACnE,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,YAAY,WAAW,QAAQ,UAAU,gBAAgB,CAAC,GAAG;AAC/D,WAAO,EAAE,YAAY,QAAQ,UAAU,gBAAgB,GAAG,SAAS,SAAS;EAC9E;AACA,QAAM,OAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AACnD,QAAM,SAAS,QAAQ,MAAM,MAAM,WAAW,QAAQ;AACtD,MAAI,WAAW,QAAQ,QAAQ,gBAAgB,CAAC,GAAG;AACjD,WAAO,EAAE,YAAY,QAAQ,QAAQ,gBAAgB,GAAG,SAAS,OAAO;EAC1E;AAIA,QAAM,eAAe,QAAQ,MAAM,MAAM,MAAM,IAAI;AACnD,QAAM,aAAa,QAAQ,cAAc,YAAY,kBAAkB,gBAAgB;AACvF,MAAI,WAAW,UAAU,GAAG;AAC1B,WAAO,EAAE,YAAY,SAAS,aAAa;EAC7C;AACA,SAAO;AACT;AAUO,SAAS,+BAA8C;AAC5D,QAAM,OAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AACnD,QAAM,SAAS,QAAQ,MAAM,MAAM,WAAW,WAAW,yBAAyB;AAClF,MAAI,WAAW,MAAM,EAAG,QAAO;AAC/B,QAAM,eAAe,QAAQ,MAAM,MAAM,MAAM,IAAI;AACnD,QAAM,MAAM;IACV;IACA;IACA;IACA;IACA;EACF;AACA,MAAI,WAAW,GAAG,EAAG,QAAO;AAC5B,SAAO;AACT;AC/CA,IAAM,eAAe;EACnB;EACA;EACA;EACA;EACA;AACF;AAEA,IAAI,SAAS;AAEN,SAAS,yBAA+B;AAC7C,MAAI,OAAQ;AACZ,WAAS;AACT,wBAAsBA,SAAQ,QAAQ,GAAG,aAAa,aAAa,CAAC;AACtE;AAEA,SAAS,sBAAsB,MAAoB;AACjD,MAAI,CAACJ,YAAW,IAAI,EAAG;AACvB,MAAI;AACJ,MAAI;AACF,WAAO,aAAa,MAAM,MAAM;EAClC,QAAQ;AACN;EACF;AACA,QAAM,SAAS,aAAa,IAAI;AAChC,aAAW,OAAO,cAAc;AAC9B,QAAI,QAAQ,IAAI,GAAG,MAAM,OAAW;AACpC,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,IAAI,GAAG,IAAI;IACrB;EACF;AACF;AASO,SAAS,aAAa,MAAsC;AACjE,QAAM,MAA8B,CAAC;AACrC,aAAW,WAAW,KAAK,MAAM,OAAO,GAAG;AACzC,UAAM,OAAO,QAAQ,KAAK;AAC1B,QAAI,KAAK,WAAW,KAAK,KAAK,WAAW,GAAG,EAAG;AAC/C,UAAM,WAAW,KAAK,WAAW,SAAS,IAAI,KAAK,MAAM,UAAU,MAAM,IAAI;AAC7E,UAAM,KAAK,SAAS,QAAQ,GAAG;AAC/B,QAAI,MAAM,EAAG;AACb,UAAM,MAAM,SAAS,MAAM,GAAG,EAAE,EAAE,KAAK;AACvC,QAAI,QAAQ,SAAS,MAAM,KAAK,CAAC,EAAE,KAAK;AAExC,QACE,MAAM,UAAU,MACd,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC1C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,IAC9C;AACA,cAAQ,MAAM,MAAM,GAAG,EAAE;IAC3B;AACA,QAAI,GAAG,IAAI;EACb;AACA,SAAO;AACT;AEzCA,IAAM,kBAAqC,CAAC,KAAM,KAAM,GAAI;AAC5D,IAAM,6BAA6B;AAGnC,IAAM,sBAAN,cAAkC,MAAM;EACtC,YAAY,QAAgB,IAAY;AACtC,UAAM,WAAW,MAAM,+BAA+B,OAAO,EAAE,CAAC,IAAI;AACpE,SAAK,OAAO;EACd;AACF;AAWO,SAAS,YAAY,KAAc,gBAAkC;AAE1E,MAAI,eAAe,sBAAuB,QAAO;AAIjD,MACE,eAAe,wBACf,eAAe,8BACf,eAAe,6BACf,eAAe,0BACf,eAAe,sBACf;AACA,WAAO;EACT;AAKA,MACE,eAAe,0BACf,eAAe,uBACf,eAAe,qBACf;AACA,WAAO;EACT;AAIA,MAAI,eAAe,cAAc;AAC/B,UAAM,SAAS,IAAI;AACnB,QAAI,OAAO,WAAW,YAAY,UAAU,OAAO,UAAU,KAAK;AAChE,aAAO;IACT;AACA,WAAO;EACT;AAIA,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,OAAQ,IAA2B;AACzC,QACE,SAAS,gBACT,SAAS,eACT,SAAS,kBACT,SAAS,eACT,SAAS,kBACT,SAAS,aACT;AACA,aAAO;IACT;AACA,UAAM,SACH,IAA4C,UAAU,UACtD,IAA6B,UAC7B,IAAiC;AACpC,QAAI,OAAO,WAAW,YAAY,UAAU,OAAO,UAAU,KAAK;AAChE,aAAO;IACT;EACF;AAEA,SAAO;AACT;AAOA,eAAsB,iBACpB,MACA,IACY;AACZ,QAAM,UAAU,KAAK,aAAa;AAClC,QAAM,cAAc,QAAQ,SAAS;AACrC,QAAM,YAAY,KAAK,oBAAoB;AAC3C,QAAMK,OAAM,KAAK,WAAW;AAE5B,WAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,QAAI;AACF,aAAO,MAAM,YAAY,GAAG,GAAG,WAAW,KAAK,MAAM;IACvD,SAAS,KAAK;AACZ,YAAM,OAAO,YAAY;AACzB,UAAI,QAAQ,CAAC,YAAY,KAAK,KAAK,gBAAgB,EAAG,OAAM;AAC5D,YAAM,QAAQ,QAAQ,UAAU,CAAC,KAAK,QAAQ,QAAQ,SAAS,CAAC,KAAK;AACrEA;QACE,WAAW,KAAK,MAAM,aAAa,OAAO,OAAO,CAAC,YAAY,aAAa,GAAG,CAAC,kBAAkB,OAAO,KAAK,CAAC;MAChH;AACA,YAAM,MAAM,KAAK;IACnB;EACF;AAEA,QAAM,IAAI,MAAM,4CAA4C,KAAK,MAAM,EAAE;AAC3E;AAEA,SAAS,gBAAgB,MAAoB;AAK3C,UAAQ,OAAO,MAAM;kBAAqB,IAAI;CAAI;AACpD;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAACD,aAAY,WAAWA,UAAS,EAAE,CAAC;AACzD;AAEA,eAAe,YAAe,GAAe,IAAY,QAA4B;AACnF,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK;MACxB;MACA,IAAI,QAAe,CAAC,UAAU,WAAW;AACvC,gBAAQ,WAAW,MAAM,OAAO,IAAI,oBAAoB,QAAQ,EAAE,CAAC,GAAG,EAAE;MAC1E,CAAC;IACH,CAAC;EACH,UAAA;AACE,QAAI,UAAU,OAAW,cAAa,KAAK;EAC7C;AACF;AAEA,SAAS,aAAa,KAAsB;AAC1C,MAAI,eAAe,cAAc;AAC/B,UAAM,SAAS,IAAI;AACnB,UAAM,MAAM,IAAI,YAAY;AAC5B,WAAO,GAAG,GAAG,GAAG,OAAO,WAAW,WAAW,IAAI,OAAO,MAAM,CAAC,KAAK,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC;EAClG;AACA,MAAI,eAAe,OAAO;AACxB,UAAM,OAAQ,IAA2B;AACzC,WAAO,SAAS,SAAY,GAAG,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,SAAS,IAAI,OAAO,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC;EAC9H;AACA,SAAO,SAAS,OAAO,GAAG,CAAC;AAC7B;AAEA,SAAS,SAAS,GAAW,MAAM,KAAa;AAC9C,SAAO,EAAE,SAAS,MAAM,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,WAAM;AAClD;AD3KA,SAAS,MACP,QACA,IACA,OAKI,CAAC,GACO;AACZ,SAAO;IACL;MACE;MACA,kBAAkB,KAAK,oBAAoB;MAC3C,kBAAkB,KAAK;MACvB,WAAW,KAAK,YAAY,OAAO,CAAC,IAAI;IAC1C;IACA;EACF;AACF;AAOO,IAAM,wBAAwB;AAErC,IAAI,SAAyB;AACtB,SAAS,YAAqB;AACnC,MAAI,CAAC,QAAQ;AAIX,2BAAuB;AACvB,QAAI;AAGF,eAAS,IAAI,QAAQ;IACvB,SAAS,KAAK;AACZ,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAI3D,YAAM,IAAI;QACR,uCAAuC,GAAG;;MAE5C;IACF;EACF;AACA,SAAO;AACT;AAEA,eAAe,WAAW,IAA8B;AACtD,SAAO,UAAU,EAAE,IAAI,EAAE;AAC3B;AAEA,eAAe,gBAAgB,IAAqC;AAClE,MAAI;AACF,WAAO,MAAM,UAAU,EAAE,IAAI,EAAE;EACjC,QAAQ;AACN,WAAO;EACT;AACF;AAQA,SAAS,SAAS,GAAkD;AAClE,UAAQ,GAAG;IACT,KAAK,aAAa;AAChB,aAAO;IACT,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;AAChB,aAAO;IACT,KAAK,aAAa;AAChB,aAAO;IACT,KAAK,aAAa;IAClB,KAAK,aAAa;AAChB,aAAO;IACT,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB,KAAK,aAAa;IAClB;AACE,aAAO;EACX;AACF;AAOA,SAAS,qBAAqB,GAI5B;AACA,SAAO;IACL,UAAU,EAAE;IACZ,WAAW,EAAE;IACb,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;EAC5C;AACF;AAGA,SAAS,aAAa,KAA6B;AACjD,MAAI,QAAQ,sBAAuB,QAAO;AAC1C,QAAM,MAAM,yBAAyB;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;MACR;IAEF;EACF;AAKA,SAAO,MAAM,eAAe,IAAI,UAAU;AAC5C;AAOO,SAAS,iBACd,MAC2D;AAC3D,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,GAAG;AACnC,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,OAAO,MAAM,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AACvC,MAAI,KAAK,KAAK,CAAC,MAAM,CAAC,OAAO,UAAU,CAAC,KAAK,KAAK,CAAC,EAAG,QAAO;AAC7D,SAAO,EAAE,KAAK,KAAK,CAAC,GAAI,QAAQ,KAAK,CAAC,GAAI,MAAM,KAAK,CAAC,EAAG;AAC3D;AAEO,IAAM,iBAA+B;EAC1C,MAAM;EAEN,MAAM,UAAU,KAAkD;AAKhE,WAAO;MACL;MACA,YAAY;AAYV,YAAI;AACJ,YAAI,IAAI,QAAQ,IAAI,KAAK,SAAS,GAAG;AACnC,0BAAgB,iBAAiB,IAAI,IAAI;AACzC,cAAI,CAAC,eAAe;AAClB,gBAAI;cACF,mCAAmC,IAAI,IAAI;YAC7C;UACF;QACF;AACA,cAAM,YAAY,iBAAiB,IAAI;AACvC,cAAM,aAAa;UACjB,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;UACjC,SAAS,IAAI;UACb,GAAI,IAAI,WAAW,IAAI,QAAQ,SAAS,IACpC,EAAE,SAAS,IAAI,QAAQ,IAAI,oBAAoB,EAAE,IACjD,CAAC;UACL,QAAQ,EAAE,iBAAiB,IAAI,KAAK;QACtC;AACA,cAAME,UAAS,UAAU;AAczB,YAAI,eAAe,IAAI;AACvB,YAAI,CAAC,gBAAgB,IAAI,SAAS,IAAI,UAAU,uBAAuB;AACrE,cAAI;AACF,kBAAM,OAAO,MAAMA,QAAO,SAAS,IAAI,IAAI,KAAK;AAChD,gBAAI,QAAQ,KAAK,KAAM,gBAAe,KAAK;UAC7C,QAAQ;UAER;QACF;AAIA,cAAM,iBAA0C,EAAE,GAAG,WAAW;AAChE,eAAO,eAAe;AACtB,cAAM,UAAU,eACZ,MAAMA,QAAO,OAAO,EAAE,UAAU,cAAc,GAAG,eAAe,GAAG,EAAE,SAAS,IAAI,CAAC,IACnF,MAAMA,QAAO;UACX,EAAE,OAAO,aAAa,IAAI,KAAK,GAAG,GAAG,WAAW;UAChD;YACE,SAAS;YACT,GAAI,IAAI,QAAQ,EAAE,sBAAsB,IAAI,MAAM,IAAI,CAAC;UACzD;QACF;AACJ,eAAO,EAAE,WAAW,QAAQ,GAAG;MACjC;MACA,EAAE,kBAAkB,OAAO,kBAAkB,IAAQ;IACvD;EACF;EAEA,MAAM,aAAa,MAA6C;AAc9D,UAAMA,UAAS,UAAU;AACzB,QAAI,MAAM,MAAM,MAAM,sBAAsB,MAAMA,QAAO,OAAO,IAAI,MAAM,IAAI,CAAC;AAG/E,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,WAAO,IAAI,UAAU,SAAS;AAC5B,UAAI,IAAI,UAAU,WAAW,IAAI,UAAU,aAAa,IAAI,UAAU,YAAY;AAChF,cAAM,IAAI;UACR,mBAAmB,IAAI,gCAAgC,IAAI,KAAK;QAElE;MACF;AACA,UAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,cAAM,IAAI;UACR,mBAAmB,IAAI,6CAA6C,IAAI,KAAK;QAE/E;MACF;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAI,CAAC;AAC5C,YAAM,MAAM,MAAM,oBAAoB,MAAMA,QAAO,OAAO,IAAI,IAAI,CAAC;IACrE;AACA,WAAO,EAAE,UAAU,IAAI,GAAG;EAC5B;EAEA,MAAM,IAAI,WAAgD;AACxD,WAAO,MAAM,OAAO,YAAY;AAC9B,YAAM,KAAK,MAAM,gBAAgB,SAAS;AAC1C,aAAO,KAAK,EAAE,WAAW,GAAG,GAAG,IAAI;IACrC,CAAC;EACH;EAEA,MAAM,OAAuC;AAC3C,WAAO,MAAM,QAAQ,YAAY;AAC/B,YAAMA,UAAS,UAAU;AAIzB,YAAM,OAAO,MAAMA,QAAO,KAAK;AAC/B,YAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,OAAQ,KAAK,SAAS,CAAC;AAC3D,aAAO,MAAM,IAAI,CAAC,OAA4B;AAC5C,cAAM,UAA+B,EAAE,WAAW,GAAG,GAAG;AACxD,cAAM,MAAM;AAMZ,cAAM,WAAW,IAAI,SAAS,eAAe,KAAK,IAAI;AACtD,YAAI,SAAU,SAAQ,OAAO;AAC7B,YAAI,IAAI,UAAW,SAAQ,YAAY,IAAI;AAC3C,YAAI,OAAO,IAAI,UAAU,SAAU,SAAQ,QAAQ,SAAS,IAAI,KAAK;AACrE,eAAO;MACT,CAAC;IACH,CAAC;EACH;EAEA,MAAM,MAAM,GAA+B;AACzC,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,MAAM;MACjB;MACA,EAAE,kBAAkB,IAAO;IAC7B;EACF;EAEA,MAAM,KAAK,GAA+B;AACxC,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,KAAK;MAChB;MACA,EAAE,kBAAkB,IAAO;IAC7B;EACF;EAEA,MAAM,MAAM,GAA+B;AAGzC,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,QAAQ;MACnB;MACA,EAAE,kBAAkB,IAAO;IAC7B;EACF;EAEA,MAAM,OAAO,GAA+B;AAC1C,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,MAAM;MACjB;MACA,EAAE,kBAAkB,IAAO;IAC7B;EACF;EAEA,MAAM,QAAQ,GAA+B;AAC3C,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,gBAAgB,EAAE,SAAS;AAC5C,YAAI,CAAC,GAAI;AAOT,YAAI;AACF,gBAAM,GAAG,KAAK,EAAE;QAClB,QAAQ;QAER;AACA,YAAI;AACF,gBAAM,GAAG,OAAO,EAAE;QACpB,SAAS,KAAK;AACZ,gBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE3D,cAAI,CAAC,aAAa,KAAK,GAAG,EAAG,OAAM;QACrC;MACF;MACA,EAAE,kBAAkB,KAAQ;IAC9B;EACF;EAEA,MAAM,MAAM,GAAqC;AAC/C,WAAO,MAAM,SAAS,YAAY;AAChC,YAAM,KAAK,MAAM,gBAAgB,EAAE,SAAS;AAC5C,UAAI,CAAC,GAAI,QAAO;AAChB,aAAO,SAAS,GAAG,KAAK;IAC1B,CAAC;EACH;EAEA,MAAM,KACJ,GACA,KACA,MAC0B;AAC1B,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AAIvC,cAAM,IAAI,MAAM,GAAG,QAAQ,eAAe,KAAK,MAAM,KAAK,MAAM,GAAG;AACnE,eAAO,EAAE,UAAU,EAAE,UAAU,QAAQ,EAAE,QAAQ,QAAQ,GAAG;MAC9D;MACA,EAAE,kBAAkB,MAAM,oBAAoB,MAAS,SAAS,MAAM,QAAQ;IAChF;EACF;EAEA,MAAM,WAAW,GAAgB,WAAmB,YAAmC;AACrF,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,GAAG,WAAW,WAAW,UAAU;MAC9C;MACA,EAAE,kBAAkB,IAAQ;IAC9B;EACF;EAEA,MAAM,aAAa,GAAgB,YAAoB,WAAkC;AACvF,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,GAAG,aAAa,YAAY,SAAS;MAChD;MACA,EAAE,kBAAkB,IAAQ;IAC9B;EACF;EAEA,MAAM,UAAU,GAAgB,WAA8C;AAC5E,WAAO,MAAM,aAAa,YAAY;AACpC,YAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,YAAM,QAAQ,MAAM,GAAG,GAAG,UAAU,SAAS;AAC7C,aAAO,MAAM,IAAI,CAAC,OAAO;QACvB,MAAM,EAAE;QACR,OAAO,QAAS,EAA0B,KAAK;MACjD,EAAE;IACJ,CAAC;EACH;EAEA,MAAM,WAAW,GAAgB,MAAwC;AACvE,WAAO,MAAM,cAAc,YAAY;AACrC,YAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,YAAM,IAAI,MAAM,GAAG,eAAe,IAAI;AAItC,aAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM;IACtC,CAAC;EACH;EAEA,MAAM,iBACJ,GACA,MACA,kBAC0B;AAC1B,WAAO,MAAM,oBAAoB,YAAY;AAC3C,YAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,YAAM,IAAI,MAAM,GAAG,oBAAoB,MAAM,gBAAgB;AAC7D,aAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM;IACtC,CAAC;EACH;EAEA,MAAM,WAAW,GAAmC;AAClD,WAAO,MAAM,cAAc,YAAY;AACrC,YAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AAIvC,YAAM,MAAM,MAAM,GAAG,gBAAgB,EAAE;AACvC,aAAO;QACL;;;QAGA;QAAM;;QAEN,GAAG,IAAI,KAAK;MACd;IACF,CAAC;EACH;EAEA,MAAM,kBAAkB,GAAgB,MAA+B;AAErE,UAAM,WAAW,KAAK,KAAK,SAAS,CAAC,KAAK;AAC1C,UAAM,QAAQ,SAAS,QAAQ,GAAG;AAClC,QAAI,SAAS,EAAG;AAChB,UAAM,QAAQ,SAAS,MAAM,GAAG,KAAK;AACrC,QAAI,MAAM,WAAW,EAAG;AACxB,QAAI;AACF,YAAM,MAAM,qBAAqB,YAAY;AAC3C,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,gBAAgB,KAAK;MAChC,CAAC;IACH,QAAQ;IAER;EACF;EAEA,MAAM,eAAe,GAAgB,cAAqC;AAWxE,WAAO;MACL;MACA,YAAY;AACV,cAAM,KAAK,MAAM,WAAW,EAAE,SAAS;AACvC,cAAM,GAAG,6BAA6B,YAAY;MACpD;MACA,EAAE,kBAAkB,KAAS,kBAAkB,MAAM;IACvD;EACF;EAEA,MAAM,eAAe,cAAqC;AACxD,WAAO,MAAM,kBAAkB,YAAY;AACzC,UAAI;AACF,cAAMA,UAAS,UAAU;AACzB,cAAM,WAAW,MAAMA,QAAO,SAAS,IAAI,YAAY;AACvD,cAAMA,QAAO,SAAS,OAAO,QAAQ;MACvC,SAAS,KAAK;AAGZ,YAAI,eAAeC,sBAAsB;AACzC,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAI,aAAa,KAAK,GAAG,EAAG;AAC5B,cAAM;MACR;IACF,CAAC;EACH;AACF;AE/hBA,IAAM,qBAAqB;AAO3B,IAAM,eAAe,CAAC,mBAAmB,qBAAqB,yBAAyB;AAkBvF,eAAsB,yBACpB,OAAwC,CAAC,GAC1B;AACf,yBAAuB;AAEvB,MAAI,CAAC,KAAK,SAAS,qBAAqB,EAAG;AAC3C,MAAI,CAAC,QAAQ,MAAM,MAAO;AAE1B,QAAM,eAAe;AACrB;IACE;kBACqB,kBAAkB;IACvC;EACF;AAEA,QAAM,OAAO,MAAM,QAAQ;IACzB,SAAS,QAAQ,kBAAkB;IACnC,cAAc;EAChB,CAAC;AACD,MAAI,SAAS,IAAI,GAAG;AAClB,QAAI,KAAK,4EAAuE;AAChF;EACF;AACA,MAAI,KAAM,eAAc;AAIxB,WAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,UAAM,QAAQ,MAAM,qBAAqB;AACzC,QAAI,UAAU,KAAM;AAEpB,UAAM,SAAS,MAAM,oBAAoB,KAAK;AAC9C,QAAI,OAAO,IAAI;AACb,yBAAmB,KAAK;AACxB,UAAI,QAAQ,gCAAgC,YAAY,CAAC,EAAE;AAC3D,YAAM,iBAAiB;AACvB;IACF;AACA,QAAI,OAAO,SAAS,UAAU,YAAY,GAAG;AAC3C,UAAI,MAAM,qCAAqC,OAAO,OAAO,EAAE;AAC/D,UAAI,KAAK,uCAAuC;AAChD;IACF;AACA,QAAI,OAAO,SAAS,WAAW;AAC7B,UAAI,KAAK,wCAAwC,OAAO,OAAO,yBAAoB;AACnF,yBAAmB,KAAK;AACxB,UAAI,QAAQ,gCAAgC,YAAY,CAAC,EAAE;AAC3D,YAAM,+BAA+B;AACrC;IACF;AACA,UAAM,IAAI,MAAM,iCAAiC,OAAO,OAAO,EAAE;EACnE;AACF;AAEA,SAAS,uBAAgC;AACvC,MAAI,QAAQ,IAAI,gBAAiB,QAAO;AACxC,MAAI,QAAQ,IAAI,qBAAqB,QAAQ,IAAI,wBAAyB,QAAO;AACjF,SAAO;AACT;AAQA,eAAe,uBAAoD;AACjE,QAAM,MAAM,MAAM,SAAS;IACzB,SAAS;IACT,SAAS,GAAG;AACV,UAAI,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAG,QAAO;AACxC,aAAO;IACT;EACF,CAAC;AACD,MAAI,SAAS,GAAG,GAAG;AACjB,QAAI,KAAK,0BAA0B;AACnC,WAAO;EACT;AACA,QAAM,UAAU,IAAI,KAAK;AAIzB,MAAI,QAAQ,WAAW,KAAK,GAAG;AAC7B,UAAM,MAAM,MAAM,KAAK;MACrB,SAAS;MACT,aAAa;MACb,SAAS,GAAG;AACV,YAAI,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAG,QAAO;AACxC,eAAO;MACT;IACF,CAAC;AACD,QAAI,SAAS,GAAG,GAAG;AACjB,UAAI,KAAK,0BAA0B;AACnC,aAAO;IACT;AACA,WAAO,EAAE,UAAU,SAAS,gBAAgB,IAAI,KAAK,EAAE;EACzD;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AAOA,eAAe,oBAAoB,OAA+C;AAChF,QAAM,IAAI,QAAQ;AAClB,IAAE,MAAM,qCAAqC;AAI7C,QAAM,WAAW,mBAAmB;AACpC,aAAW,KAAK;AAEhB,MAAI;AAGF,UAAM,EAAE,SAAAC,SAAQ,IAAI,MAAM,OAAO,gBAAgB;AACjD,UAAMF,UAAS,IAAIE,SAAQ;AAC3B,UAAMF,QAAO,KAAK;AAClB,MAAE,KAAK,8BAA8B;AACrC,WAAO,EAAE,IAAI,KAAK;EACpB,SAAS,KAAK;AACZ,sBAAkB,QAAQ;AAC1B,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,MAAE,KAAK,kCAAkC;AACzC,QAAI,sCAAsC,KAAK,OAAO,GAAG;AACvD,aAAO,EAAE,IAAI,OAAO,MAAM,QAAQ,QAAQ;IAC5C;AACA,WAAO,EAAE,IAAI,OAAO,MAAM,WAAW,QAAQ;EAC/C;AACF;AAEA,SAAS,qBAA6D;AACpE,QAAM,MAAM,CAAC;AACb,aAAW,KAAK,aAAc,KAAI,CAAC,IAAI,QAAQ,IAAI,CAAC;AACpD,SAAO;AACT;AAEA,SAAS,kBAAkB,MAAoD;AAC7E,aAAW,KAAK,cAAc;AAC5B,QAAI,KAAK,CAAC,MAAM,OAAW,QAAO,QAAQ,IAAI,CAAC;QAC1C,SAAQ,IAAI,CAAC,IAAI,KAAK,CAAC;EAC9B;AACF;AAEA,SAAS,WAAW,OAA0B;AAG5C,aAAW,KAAK,aAAc,QAAO,QAAQ,IAAI,CAAC;AAClD,MAAI,MAAM,OAAQ,SAAQ,IAAI,kBAAkB,MAAM;AACtD,MAAI,MAAM,SAAU,SAAQ,IAAI,oBAAoB,MAAM;AAC1D,MAAI,MAAM,eAAgB,SAAQ,IAAI,0BAA0B,MAAM;AACxE;AAEA,SAAS,mBAAmB,OAA0B;AACpD,aAAW,KAAK;AAChB,QAAM,OAAO,YAAY;AACzB,YAAUH,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAK5C,MAAI,WAAW;AACf,MAAIH,YAAW,IAAI,GAAG;AACpB,QAAI;AACF,iBAAWC,cAAa,MAAM,MAAM;IACtC,QAAQ;AACN,iBAAW;IACb;EACF;AAEA,QAAM,OAAO,SACV,MAAM,OAAO,EACb,OAAO,CAAC,SAAS;AAChB,UAAM,WAAW,KAAK,WAAW,SAAS,IAAI,KAAK,MAAM,UAAU,MAAM,IAAI;AAC7E,UAAM,KAAK,SAAS,QAAQ,GAAG;AAC/B,QAAI,MAAM,EAAG,QAAO;AACpB,UAAM,MAAM,SAAS,MAAM,GAAG,EAAE,EAAE,KAAK;AACvC,WAAO,CAAE,aAAmC,SAAS,GAAG;EAC1D,CAAC,EACA,KAAK,IAAI,EACT,QAAQ,SAAS,EAAE;AAEtB,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,OAAQ,OAAM,KAAK,mBAAmB,MAAM,MAAM,EAAE;AAC9D,MAAI,MAAM,SAAU,OAAM,KAAK,qBAAqB,MAAM,QAAQ,EAAE;AACpE,MAAI,MAAM,eAAgB,OAAM,KAAK,2BAA2B,MAAM,cAAc,EAAE;AAEtF,QAAM,QAAQ,OAAO,GAAG,IAAI;IAAO,MAAM,MAAM,KAAK,IAAI,IAAI;AAI5D,QAAM,MAAM,GAAG,IAAI;AACnB,gBAAc,KAAK,MAAM,EAAE,MAAM,IAAM,CAAC;AACxC,MAAI;AACF,cAAU,KAAK,GAAK;EACtB,QAAQ;EAER;AACA,aAAW,KAAK,IAAI;AACpB,MAAI;AACF,cAAU,MAAM,GAAK;EACvB,QAAQ;EAER;AACF;AAEA,SAAS,gBAAsB;AAC7B,MAAI;AACF,UAAM,IAAI,UAAU,gBAAgB,GAAG,CAAC,kBAAkB,GAAG,EAAE,OAAO,SAAS,CAAC;AAChF,QAAI,EAAE,WAAW,GAAG;AAClB,UAAI,KAAK,gDAA2C,kBAAkB,YAAY;IACpF;EACF,QAAQ;AACN,QAAI,KAAK,gDAA2C,kBAAkB,YAAY;EACpF;AACF;AAEO,SAAS,cAAsB;AACpC,SAAOG,SAAQF,SAAQ,GAAG,aAAa,aAAa;AACtD;AAUO,SAAS,wBAA2C;AAGzD,QAAM,cAAc,CAAC,CAAC,QAAQ,IAAI,mBAAmB,CAAC,CAAC,QAAQ,IAAI;AACnE,yBAAuB;AACvB,QAAM,SAAS,QAAQ,IAAI;AAC3B,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,iBAAiB,QAAQ,IAAI;AACnC,MAAI,CAAC,UAAU,CAAC,SAAU,QAAO,EAAE,QAAQ,OAAO;AAClD,SAAO;IACL;IACA;IACA;IACA,QAAQ,cAAc,QAAQ;EAChC;AACF;AAEO,SAAS,QAAQ,OAAuB;AAC7C,MAAI,MAAM,UAAU,EAAG,QAAO,IAAI,OAAO,MAAM,MAAM;AACrD,SAAO,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,SAAI,IAAI,OAAO,CAAC,CAAC,GAAG,MAAM,MAAM,EAAE,CAAC;AAChE;","names":["existsSync","resolve","DaytonaNotFoundError","existsSync","readFileSync","homedir","dirname","resolve","log","client","DaytonaNotFoundError","Daytona"]}
|