@madarco/agentbox 0.14.0 → 0.16.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 (66) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/dist/{_cloud-attach-GUBB5RH2.js → _cloud-attach-5KJWOASL.js} +4 -4
  3. package/dist/{chunk-RSKG7AFU.js → chunk-3WCEB6RE.js} +2 -2
  4. package/dist/{chunk-XKH7NTT7.js → chunk-DBBUDKKB.js} +248 -5
  5. package/dist/chunk-DBBUDKKB.js.map +1 -0
  6. package/dist/{chunk-TCS5HXJX.js → chunk-GXJNJUEV.js} +1090 -527
  7. package/dist/chunk-GXJNJUEV.js.map +1 -0
  8. package/dist/{chunk-LDMYHWUS.js → chunk-NW2UZQV6.js} +10 -6
  9. package/dist/chunk-NW2UZQV6.js.map +1 -0
  10. package/dist/{chunk-TBSIJVSN.js → chunk-PIK47622.js} +37 -17
  11. package/dist/chunk-PIK47622.js.map +1 -0
  12. package/dist/{chunk-BKU34KYY.js → chunk-QXFNLKJJ.js} +9 -3
  13. package/dist/{chunk-BKU34KYY.js.map → chunk-QXFNLKJJ.js.map} +1 -1
  14. package/dist/{chunk-BYCLD6D6.js → chunk-SB4QTF2T.js} +98 -54
  15. package/dist/chunk-SB4QTF2T.js.map +1 -0
  16. package/dist/{chunk-VATTS2MR.js → chunk-SENASAU4.js} +10 -6
  17. package/dist/{chunk-VATTS2MR.js.map → chunk-SENASAU4.js.map} +1 -1
  18. package/dist/{dist-34RKQ74M.js → dist-4IQFJJQI.js} +5 -5
  19. package/dist/{dist-4DPOL5A7.js → dist-7YB7BMNG.js} +5 -5
  20. package/dist/{dist-3IMQNTTV.js → dist-SL2QSMBE.js} +5 -5
  21. package/dist/{dist-J2IHD5T7.js → dist-VHI5QOSQ.js} +6 -6
  22. package/dist/{dist-57M6ZA7H.js → dist-XC47DSCR.js} +5 -5
  23. package/dist/index.js +1043 -333
  24. package/dist/index.js.map +1 -1
  25. package/dist/{prepared-state-MQHD3M5F-Q27AZU53.js → prepared-state-MQHD3M5F-2LANTRL7.js} +2 -2
  26. package/package.json +6 -5
  27. package/runtime/docker/Dockerfile.box +21 -2
  28. package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +112 -29
  29. package/runtime/docker/packages/ctl/dist/bin.cjs +10353 -8575
  30. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup +5 -2
  31. package/runtime/docker/packages/sandbox-docker/scripts/linear-shim +181 -0
  32. package/runtime/docker/packages/sandbox-docker/scripts/ntn-shim +95 -0
  33. package/runtime/e2b/agentbox-checkpoint-cleanup +5 -2
  34. package/runtime/e2b/agentbox-setup-skill.md +112 -29
  35. package/runtime/e2b/ctl.cjs +10353 -8575
  36. package/runtime/e2b/linear-shim +181 -0
  37. package/runtime/e2b/ntn-shim +95 -0
  38. package/runtime/e2b/scripts/build-template.sh +13 -7
  39. package/runtime/hetzner/agentbox-checkpoint-cleanup +5 -2
  40. package/runtime/hetzner/agentbox-setup-skill.md +112 -29
  41. package/runtime/hetzner/ctl.cjs +10353 -8575
  42. package/runtime/hetzner/linear-shim +181 -0
  43. package/runtime/hetzner/ntn-shim +95 -0
  44. package/runtime/hetzner/scripts/install-box.sh +19 -9
  45. package/runtime/relay/bin.cjs +3707 -2828
  46. package/runtime/vercel/agentbox-checkpoint-cleanup +5 -2
  47. package/runtime/vercel/agentbox-setup-skill.md +112 -29
  48. package/runtime/vercel/ctl.cjs +10353 -8575
  49. package/runtime/vercel/linear-shim +181 -0
  50. package/runtime/vercel/ntn-shim +95 -0
  51. package/runtime/vercel/scripts/provision.sh +13 -7
  52. package/share/agentbox-setup/SKILL.md +112 -29
  53. package/share/host-skills/agentbox-info/SKILL.md +22 -2
  54. package/dist/chunk-BYCLD6D6.js.map +0 -1
  55. package/dist/chunk-LDMYHWUS.js.map +0 -1
  56. package/dist/chunk-TBSIJVSN.js.map +0 -1
  57. package/dist/chunk-TCS5HXJX.js.map +0 -1
  58. package/dist/chunk-XKH7NTT7.js.map +0 -1
  59. /package/dist/{_cloud-attach-GUBB5RH2.js.map → _cloud-attach-5KJWOASL.js.map} +0 -0
  60. /package/dist/{chunk-RSKG7AFU.js.map → chunk-3WCEB6RE.js.map} +0 -0
  61. /package/dist/{dist-34RKQ74M.js.map → dist-4IQFJJQI.js.map} +0 -0
  62. /package/dist/{dist-4DPOL5A7.js.map → dist-7YB7BMNG.js.map} +0 -0
  63. /package/dist/{dist-3IMQNTTV.js.map → dist-SL2QSMBE.js.map} +0 -0
  64. /package/dist/{dist-J2IHD5T7.js.map → dist-VHI5QOSQ.js.map} +0 -0
  65. /package/dist/{dist-57M6ZA7H.js.map → dist-XC47DSCR.js.map} +0 -0
  66. /package/dist/{prepared-state-MQHD3M5F-Q27AZU53.js.map → prepared-state-MQHD3M5F-2LANTRL7.js.map} +0 -0
@@ -1,16 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- UserFacingError
4
- } from "./chunk-TCS5HXJX.js";
5
- import {
3
+ UserFacingError,
6
4
  computeContextSha256,
7
5
  hostOpenCommand,
8
6
  preparedStatePathFor,
9
7
  readPreparedStateRaw,
10
8
  writePreparedStateRaw
11
- } from "./chunk-XKH7NTT7.js";
9
+ } from "./chunk-DBBUDKKB.js";
12
10
 
13
- // ../../packages/sandbox-e2b/dist/chunk-BC7TDU66.js
11
+ // ../../packages/sandbox-e2b/dist/chunk-PBHOR6XE.js
14
12
  import { existsSync, readFileSync } from "fs";
15
13
  import { homedir } from "os";
16
14
  import { resolve } from "path";
@@ -209,6 +207,8 @@ var RUNTIME_ASSETS = [
209
207
  { name: "agentbox-open", remotePath: "/tmp/agentbox-open", remoteMode: 493 },
210
208
  { name: "gh-shim", remotePath: "/tmp/agentbox-gh-shim", remoteMode: 493 },
211
209
  { name: "git-shim", remotePath: "/tmp/agentbox-git-shim", remoteMode: 493 },
210
+ { name: "ntn-shim", remotePath: "/tmp/agentbox-ntn-shim", remoteMode: 493 },
211
+ { name: "linear-shim", remotePath: "/tmp/agentbox-linear-shim", remoteMode: 493 },
212
212
  { name: "custom-system-CLAUDE.md", remotePath: "/tmp/agentbox-custom-CLAUDE.md", remoteMode: 420 },
213
213
  { name: "claude-managed-settings.json", remotePath: "/tmp/agentbox-managed-settings.json", remoteMode: 420 },
214
214
  { name: "agentbox-codex-hooks.json", remotePath: "/tmp/agentbox-codex-hooks.json", remoteMode: 420 },
@@ -225,6 +225,8 @@ function candidatesFor(name, opts = {}) {
225
225
  "agentbox-open": ["packages/sandbox-docker/scripts/agentbox-open"],
226
226
  "gh-shim": ["packages/sandbox-docker/scripts/gh-shim"],
227
227
  "git-shim": ["packages/sandbox-docker/scripts/git-shim"],
228
+ "ntn-shim": ["packages/sandbox-docker/scripts/ntn-shim"],
229
+ "linear-shim": ["packages/sandbox-docker/scripts/linear-shim"],
228
230
  "custom-system-CLAUDE.md": ["packages/sandbox-e2b/scripts/custom-system-CLAUDE.md"],
229
231
  "claude-managed-settings.json": ["packages/sandbox-docker/scripts/claude-managed-settings.json"],
230
232
  "agentbox-codex-hooks.json": ["packages/sandbox-docker/scripts/agentbox-codex-hooks.json"],
@@ -238,6 +240,8 @@ function candidatesFor(name, opts = {}) {
238
240
  "agentbox-open": ["e2b/agentbox-open", "docker/packages/sandbox-docker/scripts/agentbox-open"],
239
241
  "gh-shim": ["e2b/gh-shim", "docker/packages/sandbox-docker/scripts/gh-shim"],
240
242
  "git-shim": ["e2b/git-shim", "docker/packages/sandbox-docker/scripts/git-shim"],
243
+ "ntn-shim": ["e2b/ntn-shim", "docker/packages/sandbox-docker/scripts/ntn-shim"],
244
+ "linear-shim": ["e2b/linear-shim", "docker/packages/sandbox-docker/scripts/linear-shim"],
241
245
  "custom-system-CLAUDE.md": ["e2b/custom-system-CLAUDE.md"],
242
246
  "claude-managed-settings.json": ["e2b/claude-managed-settings.json", "docker/packages/sandbox-docker/scripts/claude-managed-settings.json"],
243
247
  "agentbox-codex-hooks.json": ["e2b/agentbox-codex-hooks.json", "docker/packages/sandbox-docker/scripts/agentbox-codex-hooks.json"],
@@ -343,4 +347,4 @@ export {
343
347
  currentE2bBaseFingerprintLive,
344
348
  ensureE2bBaseTemplate
345
349
  };
346
- //# sourceMappingURL=chunk-LDMYHWUS.js.map
350
+ //# sourceMappingURL=chunk-NW2UZQV6.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: 'ntn-shim', remotePath: '/tmp/agentbox-ntn-shim', remoteMode: 0o755 },\n { name: 'linear-shim', remotePath: '/tmp/agentbox-linear-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 'ntn-shim': ['packages/sandbox-docker/scripts/ntn-shim'],\n 'linear-shim': ['packages/sandbox-docker/scripts/linear-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 'ntn-shim': ['e2b/ntn-shim', 'docker/packages/sandbox-docker/scripts/ntn-shim'],\n 'linear-shim': ['e2b/linear-shim', 'docker/packages/sandbox-docker/scripts/linear-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"]}
@@ -20,12 +20,12 @@ import {
20
20
  extractCodexCredentials,
21
21
  extractOpencodeCredentials,
22
22
  forgetBoxFromRelay,
23
- generateBoxId,
24
23
  generateRelayToken,
25
24
  generateVncPassword,
26
25
  hashProjectPath,
27
26
  hostClaudeBackupExpired,
28
27
  isRealAgentCredential,
28
+ loadEffectiveConfig,
29
29
  portlessAlias,
30
30
  portlessGetUrl,
31
31
  portlessUnalias,
@@ -42,17 +42,19 @@ import {
42
42
  stageOpencodeStateForUpload,
43
43
  stageOpencodeStaticForUpload,
44
44
  syncClaudeCredentials
45
- } from "./chunk-TCS5HXJX.js";
45
+ } from "./chunk-GXJNJUEV.js";
46
46
  import {
47
47
  DEFAULT_BOX_IMAGE,
48
48
  allocateProjectIndex,
49
49
  detectGitRepos,
50
+ generateBoxId,
50
51
  readCliStamp,
51
52
  readPreparedStateRaw,
52
53
  readState,
53
54
  recordBox,
54
- removeBoxRecord
55
- } from "./chunk-XKH7NTT7.js";
55
+ removeBoxRecord,
56
+ renderCarryEntries
57
+ } from "./chunk-DBBUDKKB.js";
56
58
 
57
59
  // ../../packages/sandbox-cloud/dist/index.js
58
60
  import { basename as basename2 } from "path";
@@ -686,7 +688,8 @@ async function uploadOneEntry(args) {
686
688
  const isDir = entry.kind === "dir";
687
689
  const parentDir = isDir ? boxDest : dirnameUnix(boxDest);
688
690
  const localTar = join4(args.stageDir, `carry-${String(args.index)}.tar`);
689
- const tarArgs = isDir ? ["-C", entry.absSrc, "-cf", localTar, "."] : ["-C", dirnameUnix(entry.absSrc), "-cf", localTar, basenameUnix(entry.absSrc)];
691
+ const excludeArgs = isDir ? (entry.exclude ?? []).map((p) => `--exclude=${p}`) : [];
692
+ const tarArgs = isDir ? ["-C", entry.absSrc, "-cf", localTar, ...excludeArgs, "."] : ["-C", dirnameUnix(entry.absSrc), "-cf", localTar, basenameUnix(entry.absSrc)];
690
693
  const packed = await execa3("tar", tarArgs, { reject: false });
691
694
  if (packed.exitCode !== 0) {
692
695
  throw new Error(`tar pack failed: ${String(packed.stderr).slice(0, 300)}`);
@@ -770,7 +773,7 @@ function isPlainObject(v) {
770
773
  }
771
774
  var REMOTE_UP_TAR = "/tmp/agentbox-cp-up.tar.gz";
772
775
  var REMOTE_DOWN_TAR = "/tmp/agentbox-cp-down.tar.gz";
773
- async function uploadToCloudBox(backend, handle, hostSrc, boxDst) {
776
+ async function uploadToCloudBox(backend, handle, hostSrc, boxDst, exclude) {
774
777
  const srcAbs = hostResolve(hostSrc);
775
778
  if (!existsSync(srcAbs)) throw new Error(`source not found: ${hostSrc}`);
776
779
  const srcBasename = hostBasename(srcAbs);
@@ -788,7 +791,8 @@ async function uploadToCloudBox(backend, handle, hostSrc, boxDst) {
788
791
  const stage = await mkdtemp4(hostJoin(tmpdir4(), "agentbox-cp-up-"));
789
792
  const localTar = hostJoin(stage, "payload.tar.gz");
790
793
  try {
791
- await execa4("tar", ["-C", srcParent, "-czf", localTar, srcBasename], {
794
+ const excludeArgs = (exclude ?? []).map((p) => `--exclude=${p}`);
795
+ await execa4("tar", ["-C", srcParent, "-czf", localTar, ...excludeArgs, srcBasename], {
792
796
  env: { ...process.env, COPYFILE_DISABLE: "1" }
793
797
  });
794
798
  await backend.uploadFile(handle, localTar, REMOTE_UP_TAR);
@@ -842,7 +846,7 @@ async function pullCloudDirContents(backend, handle, boxSrcDir, hostDstDir) {
842
846
  }
843
847
  return { finalPath: dstAbs };
844
848
  }
845
- async function downloadFromCloudBox(backend, handle, boxSrc, hostDst) {
849
+ async function downloadFromCloudBox(backend, handle, boxSrc, hostDst, exclude) {
846
850
  const srcBasename = posix.basename(boxSrc);
847
851
  const srcParent = posix.dirname(boxSrc);
848
852
  const dstAbs = hostResolve(hostDst);
@@ -861,10 +865,11 @@ async function downloadFromCloudBox(backend, handle, boxSrc, hostDst) {
861
865
  const stage = await mkdtemp4(hostJoin(tmpdir4(), "agentbox-cp-down-"));
862
866
  const localTar = hostJoin(stage, "payload.tar.gz");
863
867
  try {
868
+ const excludeArgs = (exclude ?? []).map((p) => `--exclude=${quoteShellArg(p)}`).join(" ");
864
869
  const packScript = [
865
870
  `set -euo pipefail`,
866
871
  `cd ${quoteShellArg(srcParent)}`,
867
- `tar -czf ${quoteShellArg(REMOTE_DOWN_TAR)} ${quoteShellArg(srcBasename)}`
872
+ `tar -czf ${quoteShellArg(REMOTE_DOWN_TAR)} ${excludeArgs} ${quoteShellArg(srcBasename)}`
868
873
  ].join("\n");
869
874
  const r = await backend.exec(handle, bashScript(packScript));
870
875
  if (r.exitCode !== 0) {
@@ -1428,7 +1433,8 @@ function createCloudProvider(backend, opts = {}) {
1428
1433
  previewToken: relayPreview.token,
1429
1434
  bridgeToken: box.cloud.bridgeToken,
1430
1435
  createdAt: box.createdAt,
1431
- projectIndex: box.projectIndex
1436
+ projectIndex: box.projectIndex,
1437
+ autoApproveHostActions: box.autoApproveHostActions
1432
1438
  });
1433
1439
  } catch {
1434
1440
  }
@@ -1576,10 +1582,21 @@ function createCloudProvider(backend, opts = {}) {
1576
1582
  let carrySummary;
1577
1583
  if (req.carry && req.carry.length > 0) {
1578
1584
  log(`carry: copying ${String(req.carry.length)} host path(s) into the box`);
1585
+ const entries = await renderCarryEntries(
1586
+ req.carry,
1587
+ {
1588
+ name,
1589
+ id,
1590
+ kind: "cloud",
1591
+ hostWorkspace: req.workspacePath,
1592
+ projectRoot: req.projectRoot
1593
+ },
1594
+ log
1595
+ );
1579
1596
  const result = await uploadCarryPaths({
1580
1597
  backend,
1581
1598
  handle,
1582
- entries: req.carry,
1599
+ entries,
1583
1600
  onLog: log
1584
1601
  });
1585
1602
  log(`carry: copied ${String(result.copied)}/${String(req.carry.length)} entry/entries`);
@@ -1686,6 +1703,7 @@ function createCloudProvider(backend, opts = {}) {
1686
1703
  }
1687
1704
  const state = await readState();
1688
1705
  const projectIndex = req.projectRoot ? allocateProjectIndex(state, req.projectRoot) : void 0;
1706
+ const autoApproveHostActions = (await loadEffectiveConfig(req.projectRoot ?? req.workspacePath)).effective.box.autoApproveHostActions;
1689
1707
  if (relayPreview) {
1690
1708
  try {
1691
1709
  await registerBoxWithRelay({
@@ -1698,7 +1716,8 @@ function createCloudProvider(backend, opts = {}) {
1698
1716
  previewUrl: relayPreview.url,
1699
1717
  previewToken: relayPreview.token,
1700
1718
  bridgeToken,
1701
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
1719
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1720
+ autoApproveHostActions
1702
1721
  });
1703
1722
  } catch (err) {
1704
1723
  log(
@@ -1724,6 +1743,7 @@ function createCloudProvider(backend, opts = {}) {
1724
1743
  relayToken,
1725
1744
  withPlaywright: req.withPlaywright,
1726
1745
  withEnv: req.withEnv,
1746
+ autoApproveHostActions: autoApproveHostActions ? true : void 0,
1727
1747
  carry: carrySummary,
1728
1748
  portlessAlias: portlessAliasName,
1729
1749
  portlessUrl: portlessUrlResolved,
@@ -1874,11 +1894,11 @@ function createCloudProvider(backend, opts = {}) {
1874
1894
  } : void 0;
1875
1895
  return { argv: fullArgv, cleanup };
1876
1896
  },
1877
- async uploadPath(box, hostSrc, boxDst) {
1878
- return uploadToCloudBox(backend, handleFor(box), hostSrc, boxDst);
1897
+ async uploadPath(box, hostSrc, boxDst, exclude) {
1898
+ return uploadToCloudBox(backend, handleFor(box), hostSrc, boxDst, exclude);
1879
1899
  },
1880
- async downloadPath(box, boxSrc, hostDst) {
1881
- return downloadFromCloudBox(backend, handleFor(box), boxSrc, hostDst);
1900
+ async downloadPath(box, boxSrc, hostDst, exclude) {
1901
+ return downloadFromCloudBox(backend, handleFor(box), boxSrc, hostDst, exclude);
1882
1902
  },
1883
1903
  async downloadDirContents(box, boxSrc, hostDst) {
1884
1904
  return pullCloudDirContents(backend, handleFor(box), boxSrc, hostDst);
@@ -2057,4 +2077,4 @@ export {
2057
2077
  createCloudProvider,
2058
2078
  renderInnerCommand
2059
2079
  };
2060
- //# sourceMappingURL=chunk-TBSIJVSN.js.map
2080
+ //# sourceMappingURL=chunk-PIK47622.js.map