@madarco/agentbox 0.12.0 → 0.14.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 (74) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +21 -7
  3. package/dist/{_cloud-attach-XKO4SHR3.js → _cloud-attach-GUBB5RH2.js} +4 -4
  4. package/dist/{chunk-R5XIDQFR.js → chunk-BKU34KYY.js} +170 -6
  5. package/dist/chunk-BKU34KYY.js.map +1 -0
  6. package/dist/{chunk-HFV6THYG.js → chunk-BYCLD6D6.js} +308 -36
  7. package/dist/chunk-BYCLD6D6.js.map +1 -0
  8. package/dist/chunk-LDMYHWUS.js +346 -0
  9. package/dist/chunk-LDMYHWUS.js.map +1 -0
  10. package/dist/{chunk-2LF5YILI.js → chunk-RSKG7AFU.js} +80 -6
  11. package/dist/chunk-RSKG7AFU.js.map +1 -0
  12. package/dist/{chunk-DHJ7OMIP.js → chunk-TBSIJVSN.js} +149 -47
  13. package/dist/chunk-TBSIJVSN.js.map +1 -0
  14. package/dist/{chunk-IZXPJPPV.js → chunk-TCS5HXJX.js} +389 -176
  15. package/dist/chunk-TCS5HXJX.js.map +1 -0
  16. package/dist/{chunk-ECLLV5JH.js → chunk-VATTS2MR.js} +156 -5
  17. package/dist/chunk-VATTS2MR.js.map +1 -0
  18. package/dist/{chunk-SNTHHWKY.js → chunk-XKH7NTT7.js} +80 -22
  19. package/dist/chunk-XKH7NTT7.js.map +1 -0
  20. package/dist/dist-34RKQ74M.js +662 -0
  21. package/dist/dist-34RKQ74M.js.map +1 -0
  22. package/dist/{dist-47LVLYUV.js → dist-3IMQNTTV.js} +14 -69
  23. package/dist/dist-3IMQNTTV.js.map +1 -0
  24. package/dist/{dist-RZZSSUNB.js → dist-4DPOL5A7.js} +5 -3
  25. package/dist/{dist-24PY2ZMO.js → dist-57M6ZA7H.js} +25 -177
  26. package/dist/dist-57M6ZA7H.js.map +1 -0
  27. package/dist/{dist-SWUOU34W.js → dist-J2IHD5T7.js} +37 -226
  28. package/dist/dist-J2IHD5T7.js.map +1 -0
  29. package/dist/index.js +1524 -921
  30. package/dist/index.js.map +1 -1
  31. package/dist/{prepared-state-MQHD3M5F-KE4DT3GX.js → prepared-state-MQHD3M5F-Q27AZU53.js} +2 -2
  32. package/package.json +9 -7
  33. package/runtime/docker/Dockerfile.box +21 -26
  34. package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +37 -1
  35. package/runtime/docker/packages/ctl/dist/bin.cjs +46 -17
  36. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-vnc-start +17 -6
  37. package/runtime/docker/packages/sandbox-docker/scripts/chromium-resolver +57 -0
  38. package/runtime/docker/packages/sandbox-docker/scripts/claude-managed-settings.json +2 -1
  39. package/runtime/e2b/agentbox-checkpoint-cleanup +52 -0
  40. package/runtime/e2b/agentbox-codex-hooks.json +68 -0
  41. package/runtime/e2b/agentbox-open +28 -0
  42. package/runtime/e2b/agentbox-setup-skill.md +233 -0
  43. package/runtime/e2b/agentbox-vnc-start +102 -0
  44. package/runtime/e2b/attach-helper.cjs +167 -0
  45. package/runtime/e2b/claude-managed-settings.json +116 -0
  46. package/runtime/e2b/ctl.cjs +23864 -0
  47. package/runtime/e2b/custom-system-CLAUDE.md +46 -0
  48. package/runtime/e2b/gh-shim +344 -0
  49. package/runtime/e2b/git-shim +131 -0
  50. package/runtime/e2b/scripts/build-template.sh +295 -0
  51. package/runtime/hetzner/agentbox-setup-skill.md +37 -1
  52. package/runtime/hetzner/agentbox-vnc-start +17 -6
  53. package/runtime/hetzner/claude-managed-settings.json +2 -1
  54. package/runtime/hetzner/ctl.cjs +46 -17
  55. package/runtime/relay/bin.cjs +305 -230
  56. package/runtime/vercel/agentbox-setup-skill.md +37 -1
  57. package/runtime/vercel/agentbox-vnc-start +17 -6
  58. package/runtime/vercel/claude-managed-settings.json +2 -1
  59. package/runtime/vercel/ctl.cjs +46 -17
  60. package/share/agentbox-setup/SKILL.md +37 -1
  61. package/share/host-skills/agentbox-info/SKILL.md +26 -34
  62. package/dist/chunk-2LF5YILI.js.map +0 -1
  63. package/dist/chunk-DHJ7OMIP.js.map +0 -1
  64. package/dist/chunk-ECLLV5JH.js.map +0 -1
  65. package/dist/chunk-HFV6THYG.js.map +0 -1
  66. package/dist/chunk-IZXPJPPV.js.map +0 -1
  67. package/dist/chunk-R5XIDQFR.js.map +0 -1
  68. package/dist/chunk-SNTHHWKY.js.map +0 -1
  69. package/dist/dist-24PY2ZMO.js.map +0 -1
  70. package/dist/dist-47LVLYUV.js.map +0 -1
  71. package/dist/dist-SWUOU34W.js.map +0 -1
  72. /package/dist/{_cloud-attach-XKO4SHR3.js.map → _cloud-attach-GUBB5RH2.js.map} +0 -0
  73. /package/dist/{dist-RZZSSUNB.js.map → dist-4DPOL5A7.js.map} +0 -0
  74. /package/dist/{prepared-state-MQHD3M5F-KE4DT3GX.js.map → prepared-state-MQHD3M5F-Q27AZU53.js.map} +0 -0
@@ -0,0 +1,346 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ UserFacingError
4
+ } from "./chunk-TCS5HXJX.js";
5
+ import {
6
+ computeContextSha256,
7
+ hostOpenCommand,
8
+ preparedStatePathFor,
9
+ readPreparedStateRaw,
10
+ writePreparedStateRaw
11
+ } from "./chunk-XKH7NTT7.js";
12
+
13
+ // ../../packages/sandbox-e2b/dist/chunk-BC7TDU66.js
14
+ import { existsSync, readFileSync } from "fs";
15
+ import { homedir } from "os";
16
+ import { resolve } from "path";
17
+ import { Sandbox, Template } from "e2b";
18
+ import {
19
+ chmodSync,
20
+ existsSync as existsSync2,
21
+ mkdirSync,
22
+ readFileSync as readFileSync2,
23
+ renameSync,
24
+ writeFileSync
25
+ } from "fs";
26
+ import { homedir as homedir2 } from "os";
27
+ import { dirname, resolve as resolve2 } from "path";
28
+ import {
29
+ confirm,
30
+ intro,
31
+ isCancel,
32
+ log,
33
+ note,
34
+ outro,
35
+ password
36
+ } from "@clack/prompts";
37
+ import { existsSync as existsSync3 } from "fs";
38
+ import { dirname as dirname2, resolve as resolve3 } from "path";
39
+ import { fileURLToPath } from "url";
40
+ var E2B_KEYS = ["E2B_API_KEY", "E2B_DOMAIN"];
41
+ var loaded = false;
42
+ function ensureE2bEnvLoaded() {
43
+ if (loaded) return;
44
+ loaded = true;
45
+ importE2bFromFile(resolve(homedir(), ".agentbox", "secrets.env"), E2B_KEYS);
46
+ }
47
+ function reloadE2bEnv() {
48
+ loaded = false;
49
+ ensureE2bEnvLoaded();
50
+ }
51
+ function importE2bFromFile(path, keys) {
52
+ if (!existsSync(path)) return;
53
+ let body;
54
+ try {
55
+ body = readFileSync(path, "utf8");
56
+ } catch {
57
+ return;
58
+ }
59
+ const parsed = parseEnvFile(body);
60
+ for (const key of keys) {
61
+ if (process.env[key] !== void 0) continue;
62
+ const value = parsed[key];
63
+ if (typeof value === "string") {
64
+ process.env[key] = value;
65
+ }
66
+ }
67
+ }
68
+ function parseEnvFile(body) {
69
+ const out = {};
70
+ for (const rawLine of body.split(/\r?\n/)) {
71
+ const line = rawLine.trim();
72
+ if (line.length === 0 || line.startsWith("#")) continue;
73
+ const stripped = line.startsWith("export ") ? line.slice("export ".length) : line;
74
+ const eq = stripped.indexOf("=");
75
+ if (eq <= 0) continue;
76
+ const key = stripped.slice(0, eq).trim();
77
+ let value = stripped.slice(eq + 1).trim();
78
+ if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
79
+ value = value.slice(1, -1);
80
+ }
81
+ out[key] = value;
82
+ }
83
+ return out;
84
+ }
85
+ function resolveApiKey() {
86
+ ensureE2bEnvLoaded();
87
+ const k = process.env.E2B_API_KEY;
88
+ if (!k) {
89
+ throw new Error(
90
+ "E2B credentials not configured.\nRun `agentbox e2b login` to paste your API key (from https://e2b.dev/dashboard?tab=keys), or set E2B_API_KEY in the environment / ~/.agentbox/secrets.env."
91
+ );
92
+ }
93
+ return k;
94
+ }
95
+ function hasUsableCredentials() {
96
+ ensureE2bEnvLoaded();
97
+ return Boolean(process.env.E2B_API_KEY);
98
+ }
99
+ var DASHBOARD_KEYS_URL = "https://e2b.dev/dashboard?tab=keys";
100
+ var MANAGED_KEYS = ["E2B_API_KEY"];
101
+ async function ensureE2bCredentials(opts = {}) {
102
+ ensureE2bEnvLoaded();
103
+ if (!opts.force && hasUsableCredentials()) return;
104
+ if (!process.stdin.isTTY) return;
105
+ intro("E2B setup");
106
+ note(
107
+ `AgentBox needs an E2B API key to provision sandboxes.
108
+ Get one from ${DASHBOARD_KEYS_URL} (free tier available), then paste it below.
109
+ The key is stored in \`~/.agentbox/secrets.env\` (mode 0600) \u2014 no .env.local harvesting.`,
110
+ "Credentials required"
111
+ );
112
+ const openIt = await confirm({
113
+ message: `Open ${DASHBOARD_KEYS_URL} to create a key?`,
114
+ initialValue: true
115
+ });
116
+ if (isCancel(openIt)) {
117
+ log.warn("E2B setup cancelled.");
118
+ return;
119
+ }
120
+ if (openIt) openDashboard();
121
+ const key = await password({
122
+ message: "Paste your E2B API key",
123
+ validate: (v) => v && v.trim().length > 0 ? void 0 : "Cannot be empty"
124
+ });
125
+ if (isCancel(key)) {
126
+ log.warn("E2B setup cancelled.");
127
+ return;
128
+ }
129
+ persistCredentials({ apiKey: key.trim() });
130
+ reloadE2bEnv();
131
+ log.success(`E2B credentials saved to ${secretsPath()}`);
132
+ outro("Setup complete.");
133
+ }
134
+ function persistCredentials(creds) {
135
+ writeManaged({ E2B_API_KEY: creds.apiKey });
136
+ }
137
+ function writeManaged(record) {
138
+ for (const k of MANAGED_KEYS) delete process.env[k];
139
+ for (const [k, v] of Object.entries(record)) process.env[k] = v;
140
+ const path = secretsPath();
141
+ mkdirSync(dirname(path), { recursive: true });
142
+ let existing = "";
143
+ if (existsSync2(path)) {
144
+ try {
145
+ existing = readFileSync2(path, "utf8");
146
+ } catch {
147
+ existing = "";
148
+ }
149
+ }
150
+ const kept = existing.split(/\r?\n/).filter((line) => {
151
+ const stripped = line.startsWith("export ") ? line.slice("export ".length) : line;
152
+ const eq = stripped.indexOf("=");
153
+ if (eq <= 0) return true;
154
+ const key = stripped.slice(0, eq).trim();
155
+ return !MANAGED_KEYS.includes(key);
156
+ }).join("\n").replace(/\s+$/u, "");
157
+ const lines = Object.entries(record).map(([k, v]) => `${k}=${v}`);
158
+ const body = (kept ? `${kept}
159
+ ` : "") + lines.join("\n") + "\n";
160
+ const tmp = `${path}.tmp`;
161
+ writeFileSync(tmp, body, { mode: 384 });
162
+ try {
163
+ chmodSync(tmp, 384);
164
+ } catch {
165
+ }
166
+ renameSync(tmp, path);
167
+ try {
168
+ chmodSync(path, 384);
169
+ } catch {
170
+ }
171
+ }
172
+ function openDashboard() {
173
+ import("child_process").then(({ spawnSync }) => {
174
+ const r = spawnSync(hostOpenCommand(), [DASHBOARD_KEYS_URL], { stdio: "ignore" });
175
+ if (r.status !== 0) {
176
+ log.warn(`Could not auto-open the browser \u2014 visit ${DASHBOARD_KEYS_URL} manually.`);
177
+ }
178
+ }).catch(() => {
179
+ log.warn(`Could not auto-open the browser \u2014 visit ${DASHBOARD_KEYS_URL} manually.`);
180
+ });
181
+ }
182
+ function secretsPath() {
183
+ return resolve2(homedir2(), ".agentbox", "secrets.env");
184
+ }
185
+ function readE2bCredStatus() {
186
+ const shellHad = process.env.E2B_API_KEY !== void 0;
187
+ ensureE2bEnvLoaded();
188
+ const key = process.env.E2B_API_KEY;
189
+ if (!key) return { auth: "none", source: "none" };
190
+ return { auth: "key", token: key, source: shellHad ? "env" : "secrets.env" };
191
+ }
192
+ function maskKey(value) {
193
+ if (value.length <= 8) return "*".repeat(value.length);
194
+ return `${value.slice(0, 4)}\u2026${"*".repeat(8)}${value.slice(-4)}`;
195
+ }
196
+ var SELF = dirname2(fileURLToPath(import.meta.url));
197
+ function findStagedCliRuntimeRoot() {
198
+ const candidates = [resolve3(SELF, "..", "runtime"), resolve3(SELF, "..", "..", "runtime")];
199
+ for (const c of candidates) {
200
+ if (existsSync3(resolve3(c, "e2b", "scripts", "build-template.sh"))) return c;
201
+ }
202
+ return void 0;
203
+ }
204
+ var RUNTIME_ASSETS = [
205
+ { name: "build-template.sh", remotePath: "/tmp/agentbox-build-template.sh", remoteMode: 493 },
206
+ { name: "agentbox-ctl", remotePath: "/tmp/agentbox-ctl", remoteMode: 493 },
207
+ { name: "agentbox-vnc-start", remotePath: "/tmp/agentbox-vnc-start", remoteMode: 493 },
208
+ { name: "agentbox-checkpoint-cleanup", remotePath: "/tmp/agentbox-checkpoint-cleanup", remoteMode: 493 },
209
+ { name: "agentbox-open", remotePath: "/tmp/agentbox-open", remoteMode: 493 },
210
+ { name: "gh-shim", remotePath: "/tmp/agentbox-gh-shim", remoteMode: 493 },
211
+ { name: "git-shim", remotePath: "/tmp/agentbox-git-shim", remoteMode: 493 },
212
+ { name: "custom-system-CLAUDE.md", remotePath: "/tmp/agentbox-custom-CLAUDE.md", remoteMode: 420 },
213
+ { name: "claude-managed-settings.json", remotePath: "/tmp/agentbox-managed-settings.json", remoteMode: 420 },
214
+ { name: "agentbox-codex-hooks.json", remotePath: "/tmp/agentbox-codex-hooks.json", remoteMode: 420 },
215
+ { name: "agentbox-setup-skill.md", remotePath: "/tmp/agentbox-setup-skill.md", remoteMode: 420 }
216
+ ];
217
+ function candidatesFor(name, opts = {}) {
218
+ const cliRoot = opts.cliRuntimeRoot;
219
+ const monorepo = opts.repoRoot ?? guessRepoRoot();
220
+ const monorepoRelative = {
221
+ "build-template.sh": ["packages/sandbox-e2b/scripts/build-template.sh"],
222
+ "agentbox-ctl": ["packages/ctl/dist/bin.cjs"],
223
+ "agentbox-vnc-start": ["packages/sandbox-docker/scripts/agentbox-vnc-start"],
224
+ "agentbox-checkpoint-cleanup": ["packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup"],
225
+ "agentbox-open": ["packages/sandbox-docker/scripts/agentbox-open"],
226
+ "gh-shim": ["packages/sandbox-docker/scripts/gh-shim"],
227
+ "git-shim": ["packages/sandbox-docker/scripts/git-shim"],
228
+ "custom-system-CLAUDE.md": ["packages/sandbox-e2b/scripts/custom-system-CLAUDE.md"],
229
+ "claude-managed-settings.json": ["packages/sandbox-docker/scripts/claude-managed-settings.json"],
230
+ "agentbox-codex-hooks.json": ["packages/sandbox-docker/scripts/agentbox-codex-hooks.json"],
231
+ "agentbox-setup-skill.md": ["apps/cli/share/agentbox-setup/SKILL.md"]
232
+ };
233
+ const cliRelative = {
234
+ "build-template.sh": ["e2b/scripts/build-template.sh"],
235
+ "agentbox-ctl": ["e2b/ctl.cjs"],
236
+ "agentbox-vnc-start": ["e2b/agentbox-vnc-start", "docker/packages/sandbox-docker/scripts/agentbox-vnc-start"],
237
+ "agentbox-checkpoint-cleanup": ["e2b/agentbox-checkpoint-cleanup", "docker/packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup"],
238
+ "agentbox-open": ["e2b/agentbox-open", "docker/packages/sandbox-docker/scripts/agentbox-open"],
239
+ "gh-shim": ["e2b/gh-shim", "docker/packages/sandbox-docker/scripts/gh-shim"],
240
+ "git-shim": ["e2b/git-shim", "docker/packages/sandbox-docker/scripts/git-shim"],
241
+ "custom-system-CLAUDE.md": ["e2b/custom-system-CLAUDE.md"],
242
+ "claude-managed-settings.json": ["e2b/claude-managed-settings.json", "docker/packages/sandbox-docker/scripts/claude-managed-settings.json"],
243
+ "agentbox-codex-hooks.json": ["e2b/agentbox-codex-hooks.json", "docker/packages/sandbox-docker/scripts/agentbox-codex-hooks.json"],
244
+ "agentbox-setup-skill.md": ["e2b/agentbox-setup-skill.md", "docker/apps/cli/share/agentbox-setup/SKILL.md"]
245
+ };
246
+ const out = [];
247
+ if (cliRoot) {
248
+ for (const rel of cliRelative[name] ?? []) out.push(resolve3(cliRoot, rel));
249
+ }
250
+ for (const rel of monorepoRelative[name] ?? []) out.push(resolve3(monorepo, rel));
251
+ return out;
252
+ }
253
+ function resolveRuntimeAssets(opts = {}) {
254
+ const out = [];
255
+ const missing = [];
256
+ for (const asset of RUNTIME_ASSETS) {
257
+ const cands = candidatesFor(asset.name, opts);
258
+ const hit = cands.find((p) => existsSync3(p));
259
+ if (!hit) {
260
+ missing.push({ name: asset.name, tried: cands });
261
+ continue;
262
+ }
263
+ out.push({ ...asset, localPath: hit });
264
+ }
265
+ if (missing.length > 0) {
266
+ const lines = missing.flatMap((m) => [` - ${m.name}: tried`, ...m.tried.map((p) => ` ${p}`)]);
267
+ throw new Error(
268
+ `e2b: could not resolve runtime assets needed to bake the base template:
269
+ ` + lines.join("\n") + `
270
+
271
+ If running from the monorepo, ensure \`pnpm -w build\` has run so packages/ctl/dist/bin.cjs exists.`
272
+ );
273
+ }
274
+ return out;
275
+ }
276
+ function guessRepoRoot() {
277
+ let cur = SELF;
278
+ for (let i = 0; i < 8; i++) {
279
+ if (existsSync3(resolve3(cur, "pnpm-workspace.yaml"))) return cur;
280
+ const parent = dirname2(cur);
281
+ if (parent === cur) break;
282
+ cur = parent;
283
+ }
284
+ return SELF;
285
+ }
286
+ var SCHEMA = 1;
287
+ function preparedStatePath() {
288
+ return preparedStatePathFor("e2b");
289
+ }
290
+ function readPreparedState() {
291
+ const raw = readPreparedStateRaw("e2b");
292
+ if (raw === null || typeof raw !== "object") return { schema: SCHEMA };
293
+ const parsed = raw;
294
+ if (parsed.schema !== SCHEMA) {
295
+ return { schema: SCHEMA };
296
+ }
297
+ return { schema: SCHEMA, base: parsed.base };
298
+ }
299
+ function writePreparedState(state) {
300
+ writePreparedStateRaw("e2b", state);
301
+ }
302
+ function updatePreparedState(mutate) {
303
+ const s = readPreparedState();
304
+ mutate(s);
305
+ writePreparedState(s);
306
+ }
307
+ async function currentE2bBaseFingerprintLive() {
308
+ try {
309
+ const assets = resolveRuntimeAssets({ cliRuntimeRoot: findStagedCliRuntimeRoot() });
310
+ return await computeContextSha256(
311
+ assets.map((a) => ({ rel: a.name, abs: a.localPath }))
312
+ );
313
+ } catch {
314
+ return void 0;
315
+ }
316
+ }
317
+ function ensureE2bBaseTemplate() {
318
+ const state = readPreparedState();
319
+ if (state.base !== void 0) return;
320
+ throw new UserFacingError(
321
+ "no E2B base template found.\nRun `agentbox prepare --provider e2b` first \u2014 it bakes a custom template with the agentbox runtime (agentbox-ctl, vscode user, claude/codex/opencode, tmux) so per-box `create` boots ready in seconds."
322
+ );
323
+ }
324
+
325
+ export {
326
+ ensureE2bEnvLoaded,
327
+ reloadE2bEnv,
328
+ Sandbox,
329
+ Template,
330
+ resolveApiKey,
331
+ ensureE2bCredentials,
332
+ secretsPath,
333
+ readE2bCredStatus,
334
+ maskKey,
335
+ findStagedCliRuntimeRoot,
336
+ RUNTIME_ASSETS,
337
+ candidatesFor,
338
+ resolveRuntimeAssets,
339
+ preparedStatePath,
340
+ readPreparedState,
341
+ writePreparedState,
342
+ updatePreparedState,
343
+ currentE2bBaseFingerprintLive,
344
+ ensureE2bBaseTemplate
345
+ };
346
+ //# sourceMappingURL=chunk-LDMYHWUS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../packages/sandbox-e2b/src/env-loader.ts","../../../packages/sandbox-e2b/src/sdk.ts","../../../packages/sandbox-e2b/src/credentials.ts","../../../packages/sandbox-e2b/src/runtime-assets.ts","../../../packages/sandbox-e2b/src/prepared-state.ts"],"sourcesContent":["/**\n * E2B env auto-loader. The `e2b` SDK reads `E2B_API_KEY` (and optionally\n * `E2B_DOMAIN` for non-default deployments) from `process.env`. We seed those\n * from `~/.agentbox/secrets.env` (written by `agentbox e2b login`) so the SDK\n * Just Works after a one-time login — same pattern as the daytona / hetzner /\n * vercel env-loaders.\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 e2b login`.\n *\n * Project-level `.env` / `.env.local` are intentionally NOT consulted: those\n * files belong to the app code being developed. Put host credentials in\n * `~/.agentbox/secrets.env` (or the shell env).\n *\n * Only E2B-prefixed keys are imported; the rest of the file is left alone.\n * Idempotent and side-effect-free after the first call.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { resolve } from 'node:path';\n\nconst E2B_KEYS = ['E2B_API_KEY', 'E2B_DOMAIN'] as const;\n\nlet loaded = false;\n\nexport function ensureE2bEnvLoaded(): void {\n if (loaded) return;\n loaded = true;\n importE2bFromFile(resolve(homedir(), '.agentbox', 'secrets.env'), E2B_KEYS);\n}\n\n/**\n * Force a re-read of `~/.agentbox/secrets.env`. Used by the interactive\n * `agentbox e2b login` flow after it persists the API key, so the same process\n * can pick it up without a restart.\n */\nexport function reloadE2bEnv(): void {\n loaded = false;\n ensureE2bEnvLoaded();\n}\n\nfunction importE2bFromFile(path: string, keys: readonly 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 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\"`, `KEY='value'`,\n * `export KEY=value`, blank lines, and `#` comments. No variable interpolation\n * — predictable over feature-complete (matches the daytona / vercel loaders).\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 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 * Thin wrapper around the `e2b` SDK. Resolves the API key once and re-exports\n * the SDK surface the rest of the package uses from a single place (so tests\n * can mock `./sdk.js` instead of the package).\n *\n * E2B only ships one auth mode for first-party use: a single API key. The SDK\n * already reads `process.env.E2B_API_KEY` on each call, but we still expose\n * `resolveApiKey()` so callers can fail loud with an actionable error before\n * the SDK throws a generic \"401 unauthorized\" deep inside an op.\n */\n\nimport { Sandbox, Template } from 'e2b';\nimport { ensureE2bEnvLoaded } from './env-loader.js';\n\nexport { Sandbox, Template };\nexport type { SandboxOpts, SandboxInfo, SandboxState, SandboxListOpts, LogEntry, BuildInfo } from 'e2b';\n\n/**\n * Return the configured E2B API key. Throws an actionable error when nothing\n * is configured. Idempotent — env-loader caches itself after first call.\n */\nexport function resolveApiKey(): string {\n ensureE2bEnvLoaded();\n const k = process.env.E2B_API_KEY;\n if (!k) {\n throw new Error(\n 'E2B credentials not configured.\\n' +\n 'Run `agentbox e2b login` to paste your API key (from https://e2b.dev/dashboard?tab=keys), ' +\n 'or set E2B_API_KEY in the environment / ~/.agentbox/secrets.env.',\n );\n }\n return k;\n}\n\n/** True when an API key is configured. Used by the credential gate. */\nexport function hasUsableCredentials(): boolean {\n ensureE2bEnvLoaded();\n return Boolean(process.env.E2B_API_KEY);\n}\n","/**\n * Interactive E2B credential setup. Single mode — paste an API key from\n * https://e2b.dev/dashboard?tab=keys — much simpler than vercel's three-mode\n * flow. Persists to `~/.agentbox/secrets.env` (the canonical store, matching\n * daytona / hetzner / vercel).\n *\n * Non-interactive callers (no TTY): silent no-op, so scripted/CI runs surface\n * the SDK's own \"not configured\" error instead of hanging on a prompt.\n */\n\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 { hostOpenCommand } from '@agentbox/sandbox-core';\nimport {\n confirm,\n intro,\n isCancel,\n log,\n note,\n outro,\n password,\n} from '@clack/prompts';\nimport { ensureE2bEnvLoaded, reloadE2bEnv } from './env-loader.js';\nimport { hasUsableCredentials } from './sdk.js';\n\nconst DASHBOARD_KEYS_URL = 'https://e2b.dev/dashboard?tab=keys';\n\n/**\n * Keys we manage in `~/.agentbox/secrets.env`. On reconfigure we strip prior\n * values for these before appending so the file never accumulates duplicates.\n */\nconst MANAGED_KEYS = ['E2B_API_KEY'] as const;\n\nexport interface EnsureE2bCredentialsOptions {\n /** Re-prompt even when valid credentials are already present (`agentbox e2b login`). */\n force?: boolean;\n}\n\nexport async function ensureE2bCredentials(\n opts: EnsureE2bCredentialsOptions = {},\n): Promise<void> {\n ensureE2bEnvLoaded();\n\n if (!opts.force && hasUsableCredentials()) return;\n if (!process.stdin.isTTY) return;\n\n intro('E2B setup');\n note(\n `AgentBox needs an E2B API key to provision sandboxes.\\n` +\n `Get one from ${DASHBOARD_KEYS_URL} (free tier available), then paste it below.\\n` +\n `The key is stored in \\`~/.agentbox/secrets.env\\` (mode 0600) — no .env.local harvesting.`,\n 'Credentials required',\n );\n\n const openIt = await confirm({\n message: `Open ${DASHBOARD_KEYS_URL} to create a key?`,\n initialValue: true,\n });\n if (isCancel(openIt)) {\n log.warn('E2B setup cancelled.');\n return;\n }\n if (openIt) openDashboard();\n\n const key = await password({\n message: 'Paste your E2B API key',\n validate: (v) => (v && v.trim().length > 0 ? undefined : 'Cannot be empty'),\n });\n if (isCancel(key)) {\n log.warn('E2B setup cancelled.');\n return;\n }\n\n persistCredentials({ apiKey: key.trim() });\n reloadE2bEnv();\n log.success(`E2B credentials saved to ${secretsPath()}`);\n outro('Setup complete.');\n}\n\nfunction persistCredentials(creds: { apiKey: string }): void {\n writeManaged({ E2B_API_KEY: creds.apiKey });\n}\n\n/**\n * Atomically rewrite the managed E2B keys in `~/.agentbox/secrets.env`:\n * strip every prior value for a `MANAGED_KEYS` entry, then append exactly the\n * keys in `record` (mode 0600, temp-file + rename). Also mirrors the record\n * into `process.env` so the current run uses the new values immediately.\n */\nfunction writeManaged(record: Record<string, string>): void {\n for (const k of MANAGED_KEYS) delete process.env[k];\n for (const [k, v] of Object.entries(record)) process.env[k] = v;\n\n const path = secretsPath();\n mkdirSync(dirname(path), { recursive: true });\n\n let existing = '';\n if (existsSync(path)) {\n try {\n existing = readFileSync(path, 'utf8');\n } catch {\n existing = '';\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 = Object.entries(record).map(([k, v]) => `${k}=${v}`);\n const body = (kept ? `${kept}\\n` : '') + lines.join('\\n') + '\\n';\n\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 import('node:child_process')\n .then(({ spawnSync }) => {\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 })\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\nexport interface E2bCredStatus {\n auth: 'key' | 'none';\n token?: string;\n source: 'env' | 'secrets.env' | 'none';\n}\n\nexport function readE2bCredStatus(): E2bCredStatus {\n const shellHad = process.env.E2B_API_KEY !== undefined;\n ensureE2bEnvLoaded();\n const key = process.env.E2B_API_KEY;\n if (!key) return { auth: 'none', source: 'none' };\n return { auth: 'key', token: key, source: shellHad ? 'env' : 'secrets.env' };\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","/**\n * Resolver for the runtime payload baked into the E2B base template during\n * `prepareE2b()`. Same idea as the vercel resolver: a flat list of files to\n * `template.copy` into the build context, each resolved from either the\n * staged CLI runtime tree or the monorepo source tree.\n *\n * Lookup order per file:\n * 1. The CLI's staged runtime tree: `<cliRoot>/e2b/...`.\n * 2. The monorepo source tree (dev fallback) under `packages/`.\n *\n * Any missing file throws a clear error naming the paths tried. Note: no\n * dockerd helper — E2B microVMs can't run nested containers.\n */\n\nimport { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst SELF = dirname(fileURLToPath(import.meta.url));\n\nexport function findStagedCliRuntimeRoot(): string | undefined {\n const candidates = [resolve(SELF, '..', 'runtime'), resolve(SELF, '..', '..', 'runtime')];\n for (const c of candidates) {\n if (existsSync(resolve(c, 'e2b', 'scripts', 'build-template.sh'))) return c;\n }\n return undefined;\n}\n\nexport interface RuntimeAsset {\n /** Logical name (used in error messages + log lines). */\n name: string;\n /** Absolute path inside the template's build filesystem (Template.copy target). */\n remotePath: string;\n /** File mode to apply after upload. */\n remoteMode: number;\n}\n\n/**\n * Where each asset lands inside the sandbox during template build. build-template.sh\n * reads them from these fixed paths. The agent/runtime helpers go straight to\n * /usr/local/bin via the script; baked config files to /tmp for the script to\n * `install` into place.\n */\nexport const RUNTIME_ASSETS: readonly RuntimeAsset[] = [\n { name: 'build-template.sh', remotePath: '/tmp/agentbox-build-template.sh', remoteMode: 0o755 },\n { name: 'agentbox-ctl', remotePath: '/tmp/agentbox-ctl', remoteMode: 0o755 },\n { name: 'agentbox-vnc-start', remotePath: '/tmp/agentbox-vnc-start', remoteMode: 0o755 },\n { name: 'agentbox-checkpoint-cleanup', remotePath: '/tmp/agentbox-checkpoint-cleanup', remoteMode: 0o755 },\n { name: 'agentbox-open', remotePath: '/tmp/agentbox-open', remoteMode: 0o755 },\n { name: 'gh-shim', remotePath: '/tmp/agentbox-gh-shim', remoteMode: 0o755 },\n { name: 'git-shim', remotePath: '/tmp/agentbox-git-shim', remoteMode: 0o755 },\n { name: 'custom-system-CLAUDE.md', remotePath: '/tmp/agentbox-custom-CLAUDE.md', remoteMode: 0o644 },\n { name: 'claude-managed-settings.json', remotePath: '/tmp/agentbox-managed-settings.json', remoteMode: 0o644 },\n { name: 'agentbox-codex-hooks.json', remotePath: '/tmp/agentbox-codex-hooks.json', remoteMode: 0o644 },\n { name: 'agentbox-setup-skill.md', remotePath: '/tmp/agentbox-setup-skill.md', remoteMode: 0o644 },\n] as const;\n\nexport interface ResolvedAsset extends RuntimeAsset {\n localPath: string;\n}\n\nexport function candidatesFor(\n name: string,\n opts: { cliRuntimeRoot?: string; repoRoot?: string } = {},\n): string[] {\n const cliRoot = opts.cliRuntimeRoot;\n const monorepo = opts.repoRoot ?? guessRepoRoot();\n\n const monorepoRelative: Record<string, string[]> = {\n 'build-template.sh': ['packages/sandbox-e2b/scripts/build-template.sh'],\n 'agentbox-ctl': ['packages/ctl/dist/bin.cjs'],\n 'agentbox-vnc-start': ['packages/sandbox-docker/scripts/agentbox-vnc-start'],\n 'agentbox-checkpoint-cleanup': ['packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup'],\n 'agentbox-open': ['packages/sandbox-docker/scripts/agentbox-open'],\n 'gh-shim': ['packages/sandbox-docker/scripts/gh-shim'],\n 'git-shim': ['packages/sandbox-docker/scripts/git-shim'],\n 'custom-system-CLAUDE.md': ['packages/sandbox-e2b/scripts/custom-system-CLAUDE.md'],\n 'claude-managed-settings.json': ['packages/sandbox-docker/scripts/claude-managed-settings.json'],\n 'agentbox-codex-hooks.json': ['packages/sandbox-docker/scripts/agentbox-codex-hooks.json'],\n 'agentbox-setup-skill.md': ['apps/cli/share/agentbox-setup/SKILL.md'],\n };\n\n const cliRelative: Record<string, string[]> = {\n 'build-template.sh': ['e2b/scripts/build-template.sh'],\n 'agentbox-ctl': ['e2b/ctl.cjs'],\n 'agentbox-vnc-start': ['e2b/agentbox-vnc-start', 'docker/packages/sandbox-docker/scripts/agentbox-vnc-start'],\n 'agentbox-checkpoint-cleanup': ['e2b/agentbox-checkpoint-cleanup', 'docker/packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup'],\n 'agentbox-open': ['e2b/agentbox-open', 'docker/packages/sandbox-docker/scripts/agentbox-open'],\n 'gh-shim': ['e2b/gh-shim', 'docker/packages/sandbox-docker/scripts/gh-shim'],\n 'git-shim': ['e2b/git-shim', 'docker/packages/sandbox-docker/scripts/git-shim'],\n 'custom-system-CLAUDE.md': ['e2b/custom-system-CLAUDE.md'],\n 'claude-managed-settings.json': ['e2b/claude-managed-settings.json', 'docker/packages/sandbox-docker/scripts/claude-managed-settings.json'],\n 'agentbox-codex-hooks.json': ['e2b/agentbox-codex-hooks.json', 'docker/packages/sandbox-docker/scripts/agentbox-codex-hooks.json'],\n 'agentbox-setup-skill.md': ['e2b/agentbox-setup-skill.md', 'docker/apps/cli/share/agentbox-setup/SKILL.md'],\n };\n\n const out: string[] = [];\n if (cliRoot) {\n for (const rel of cliRelative[name] ?? []) out.push(resolve(cliRoot, rel));\n }\n for (const rel of monorepoRelative[name] ?? []) out.push(resolve(monorepo, rel));\n return out;\n}\n\nexport function resolveRuntimeAssets(\n opts: { cliRuntimeRoot?: string; repoRoot?: string } = {},\n): ResolvedAsset[] {\n const out: ResolvedAsset[] = [];\n const missing: Array<{ name: string; tried: string[] }> = [];\n for (const asset of RUNTIME_ASSETS) {\n const cands = candidatesFor(asset.name, opts);\n const hit = cands.find((p) => existsSync(p));\n if (!hit) {\n missing.push({ name: asset.name, tried: cands });\n continue;\n }\n out.push({ ...asset, localPath: hit });\n }\n if (missing.length > 0) {\n const lines = missing.flatMap((m) => [` - ${m.name}: tried`, ...m.tried.map((p) => ` ${p}`)]);\n throw new Error(\n `e2b: could not resolve runtime assets needed to bake the base template:\\n` +\n lines.join('\\n') +\n `\\n\\nIf running from the monorepo, ensure \\`pnpm -w build\\` has run so packages/ctl/dist/bin.cjs exists.`,\n );\n }\n return out;\n}\n\nfunction guessRepoRoot(): string {\n let cur = SELF;\n for (let i = 0; i < 8; i++) {\n if (existsSync(resolve(cur, 'pnpm-workspace.yaml'))) return cur;\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n return SELF;\n}\n","/**\n * Persisted record of what `agentbox prepare --provider e2b` has built.\n * Lives at `~/.agentbox/e2b-prepared.json` so the auto-prepare gate\n * (`ensureE2bBaseTemplate()`) and `backend.provision` can resolve the base\n * template every box boots from.\n *\n * Single tier for now — the shared base template (Debian + agentbox-ctl +\n * agents). Templates on E2B are id+tag-addressed reusable resources, so unlike\n * Vercel snapshots we don't worry about per-box snapshot eviction; one template\n * is reused for every create.\n *\n * Schema versioned so future shape changes can migrate; only `schema: 1` is\n * accepted today.\n */\n\nimport { computeContextSha256, readPreparedStateRaw, writePreparedStateRaw, preparedStatePathFor } from '@agentbox/sandbox-core';\nimport { UserFacingError } from '@agentbox/core';\nimport { findStagedCliRuntimeRoot, resolveRuntimeAssets } from './runtime-assets.js';\n\nconst SCHEMA = 1 as const;\n\nexport interface PreparedE2bBase {\n /** Opaque E2B template id (e.g. `tmpl_xxxx` or `name:tag`). Sandbox.create({ template }) boots from this. */\n templateId: string;\n /** Human-friendly template name passed to Template.build (e.g. `agentbox-base:latest`). */\n templateName?: string;\n /** Deterministic SHA-256 of the build context (build script + assets). */\n contextSha256?: string;\n /** CLI version that produced this template (informational). */\n cliVersion?: string;\n /** Git short SHA of the CLI build (informational). */\n cliCommit?: string;\n /** ISO timestamp of bake completion. */\n createdAt: string;\n}\n\nexport interface PreparedE2bState {\n schema: typeof SCHEMA;\n /** The shared base template. Absent until first `agentbox prepare`. */\n base?: PreparedE2bBase;\n}\n\nexport function preparedStatePath(): string {\n return preparedStatePathFor('e2b');\n}\n\nexport function readPreparedState(): PreparedE2bState {\n const raw = readPreparedStateRaw('e2b');\n if (raw === null || typeof raw !== 'object') return { schema: SCHEMA };\n const parsed = raw as Partial<PreparedE2bState>;\n if (parsed.schema !== SCHEMA) {\n // Unknown/missing schema: refuse to read — the next prepare overwrites it.\n return { schema: SCHEMA };\n }\n return { schema: SCHEMA, base: parsed.base };\n}\n\nexport function writePreparedState(state: PreparedE2bState): void {\n writePreparedStateRaw('e2b', state);\n}\n\n/** Update one field of the state without forcing callers to read/merge/write. */\nexport function updatePreparedState(mutate: (s: PreparedE2bState) => void): void {\n const s = readPreparedState();\n mutate(s);\n writePreparedState(s);\n}\n\n/**\n * Compute the CURRENT build-context fingerprint for the e2b base template\n * (the SHA over every file `prepare` would copy into the Template build).\n * Side-effect-free — never builds. Returns `undefined` when the runtime\n * assets can't be resolved (dev tree without `pnpm -w build`) so the CLI\n * can degrade to \"can't tell, don't nag\" rather than flag a false stale.\n *\n * Used by `evaluateBaseFreshness` to compare against the stored value in\n * `e2b-prepared.json.base.contextSha256`. Must produce a byte-identical\n * hash to the one `prepare` writes — both go through the same\n * `resolveRuntimeAssets` + `computeContextSha256` chain.\n */\nexport async function currentE2bBaseFingerprintLive(): Promise<string | undefined> {\n try {\n const assets = resolveRuntimeAssets({ cliRuntimeRoot: findStagedCliRuntimeRoot() });\n return await computeContextSha256(\n assets.map((a) => ({ rel: a.name, abs: a.localPath })),\n );\n } catch {\n return undefined;\n }\n}\n\n/**\n * First-use gate. If no base template is recorded, throw an actionable error\n * pointing at `agentbox prepare --provider e2b`. Called by `backend.provision`\n * (so `create` / `claude` trip it but `prepare` itself does not — same shape\n * as the hetzner/vercel gates).\n */\nexport function ensureE2bBaseTemplate(): void {\n const state = readPreparedState();\n if (state.base !== undefined) return;\n throw new UserFacingError(\n 'no E2B base template found.\\n' +\n 'Run `agentbox prepare --provider e2b` first — it bakes a custom template ' +\n 'with the agentbox runtime (agentbox-ctl, vscode user, claude/codex/opencode, tmux) ' +\n 'so per-box `create` boots ready in seconds.',\n );\n}\n"],"mappings":"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","names":["existsSync","readFileSync","homedir","resolve","existsSync","dirname","resolve","existsSync","readFileSync","resolve","homedir","dirname"]}
@@ -1,9 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- hostOpenCommand
4
- } from "./chunk-SNTHHWKY.js";
3
+ DOCKER_CONTEXT_FILE_MAP,
4
+ computeContextSha256,
5
+ hostOpenCommand,
6
+ readCliStamp,
7
+ readPreparedStateRaw,
8
+ resolveContextFilesFrom,
9
+ writePreparedStateRaw
10
+ } from "./chunk-XKH7NTT7.js";
5
11
 
6
- // ../../packages/sandbox-daytona/dist/chunk-MLQU4RFU.js
12
+ // ../../packages/sandbox-daytona/dist/chunk-35HJOOGT.js
7
13
  import { existsSync } from "fs";
8
14
  import { dirname, resolve } from "path";
9
15
  import { fileURLToPath } from "url";
@@ -34,6 +40,9 @@ import {
34
40
  import { homedir as homedir2 } from "os";
35
41
  import { dirname as dirname2, resolve as resolve3 } from "path";
36
42
  import { confirm, isCancel, intro, log, note, outro, password, spinner, text } from "@clack/prompts";
43
+ import { existsSync as existsSync4 } from "fs";
44
+ import { dirname as dirname3, resolve as resolve4 } from "path";
45
+ import { fileURLToPath as fileURLToPath2 } from "url";
37
46
  function resolveDockerfileContext() {
38
47
  const override = process.env.AGENTBOX_DOCKER_CONTEXT;
39
48
  if (override && existsSync(resolve(override, "Dockerfile.box"))) {
@@ -174,7 +183,7 @@ function defaultRetryLog(line) {
174
183
  `);
175
184
  }
176
185
  function sleep(ms) {
177
- return new Promise((resolve4) => setTimeout(resolve4, ms));
186
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
178
187
  }
179
188
  async function raceTimeout(p, ms, method) {
180
189
  let timer;
@@ -743,6 +752,66 @@ function maskKey(value) {
743
752
  if (value.length <= 8) return "*".repeat(value.length);
744
753
  return `${value.slice(0, 4)}\u2026${"*".repeat(8)}${value.slice(-4)}`;
745
754
  }
755
+ var SCHEMA = 1;
756
+ function resolveDaytonaContextFiles() {
757
+ const ctx = resolveDockerfileContext();
758
+ if (!ctx) return null;
759
+ const here = dirname3(fileURLToPath2(import.meta.url));
760
+ const packageRoot = resolve4(here, "..");
761
+ const monorepoRoot = resolve4(here, "..", "..", "..");
762
+ const dockerPackageRoot = resolve4(monorepoRoot, "packages", "sandbox-docker");
763
+ const docker = resolveContextFilesFrom(DOCKER_CONTEXT_FILE_MAP, {
764
+ contextDir: ctx.context,
765
+ devRoot: existsSync4(dockerPackageRoot) ? dockerPackageRoot : packageRoot
766
+ });
767
+ if (!docker) return null;
768
+ const overlay = resolveDaytonaCustomClaudeMd();
769
+ if (!overlay) return null;
770
+ return [
771
+ ...docker,
772
+ // Daytona-specific overlay: separate logical name so a docker/daytona
773
+ // CLAUDE.md drift produces different fingerprints (the daytona snapshot
774
+ // contains both files in distinct locations).
775
+ { rel: "daytona/custom-system-CLAUDE.md", abs: overlay }
776
+ ];
777
+ }
778
+ async function computeDaytonaContextFingerprint() {
779
+ const files = resolveDaytonaContextFiles();
780
+ if (!files) return null;
781
+ return { contextSha256: await computeContextSha256(files), files };
782
+ }
783
+ async function currentDaytonaBaseFingerprintLive() {
784
+ try {
785
+ const fp = await computeDaytonaContextFingerprint();
786
+ return fp?.contextSha256;
787
+ } catch {
788
+ return void 0;
789
+ }
790
+ }
791
+ function readPreparedDaytonaState() {
792
+ const raw = readPreparedStateRaw("daytona");
793
+ if (raw === null || typeof raw !== "object") return null;
794
+ const parsed = raw;
795
+ if (parsed.schema !== SCHEMA) return null;
796
+ return { schema: SCHEMA, base: parsed.base };
797
+ }
798
+ function writePreparedDaytonaState(opts) {
799
+ const stamp = readCliStamp();
800
+ const state = {
801
+ schema: SCHEMA,
802
+ base: {
803
+ imageRef: opts.snapshotName,
804
+ contextSha256: opts.contextSha256,
805
+ cliVersion: stamp.cliVersion,
806
+ cliCommit: stamp.cliCommit,
807
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
808
+ }
809
+ };
810
+ writePreparedStateRaw("daytona", state);
811
+ }
812
+ function preparedMatches(state, current) {
813
+ return state?.base?.contextSha256 === current;
814
+ }
746
815
 
747
816
  export {
748
817
  resolveDockerfileContext,
@@ -754,6 +823,11 @@ export {
754
823
  ensureDaytonaCredentials,
755
824
  secretsPath,
756
825
  readDaytonaCredStatus,
757
- maskKey
826
+ maskKey,
827
+ computeDaytonaContextFingerprint,
828
+ currentDaytonaBaseFingerprintLive,
829
+ readPreparedDaytonaState,
830
+ writePreparedDaytonaState,
831
+ preparedMatches
758
832
  };
759
- //# sourceMappingURL=chunk-2LF5YILI.js.map
833
+ //# sourceMappingURL=chunk-RSKG7AFU.js.map