@agentproto/sandbox-instabox 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api.ts","../src/provider.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Tiny typed InstaBox API client (https://instabox.sh, API\n * https://api.instabox.sh) over injectable `fetch`. Shapes measured on a real\n * account on 2026-10-18:\n *\n * - auth: `X-API-Key: ibk_...` (NEVER logged and never echoed in an error).\n * - every lifecycle verb (`POST /v1/machines`, suspend/resume/stop/start,\n * ports, DELETE) returns 202 `{id:\"op_...\", machineId, state:\"queued\"}` and\n * is awaited via `GET /v1/operations/{id}?wait=25s` long-polling.\n * - errors: `{\"error\":{\"code\",\"message\",\"requestId\",\"retryable\",\"operationId\"}}`.\n * - a publish-port request is idempotent (201 first, 200 if already\n * published) and both creates get an idempotency header, but `exec` is NOT\n * retried on transport errors.\n */\n\n/** Machine states reported by `GET /v1/machines/{id}` right now. */\nexport type InstaboxMachineState = \"running\" | \"suspended\" | \"stopped\"\n\n/** The action a machine takes when its `timeoutSeconds` lifetime elapses. */\nexport type InstaboxOnTimeout = \"pause\" | \"kill\"\n\nexport interface InstaboxMachine {\n /** Canonical id, `m_...` (a GET still accepts the machine NAME for direct\n * lookups, but `files`, `wake` and `ports` need the canonical id). */\n id: string\n state: InstaboxMachineState | string\n desiredState?: string\n name?: string\n runtime?: { ready?: boolean }\n /** ISO timestamp of the current lifetime deadline (null when not Running). */\n timeoutAt?: string | null\n onTimeout?: InstaboxOnTimeout\n autoSuspendAfterSeconds?: number\n metadata?: Record<string, string>\n /** Pending operation id, or null when the answer is already final. */\n operationId?: string | null\n}\n\nexport type InstaboxOperationState =\n | \"queued\"\n | \"running\"\n | \"succeeded\"\n | \"failed\"\n | string\n\nexport interface InstaboxOperation {\n /** Operation id, `op_...`. */\n id: string\n machineId?: string\n state: InstaboxOperationState\n error?: unknown\n machine?: InstaboxMachine\n}\n\nexport interface InstaboxCreateMachineInput {\n name: string\n /** Template id. Default `universal` (Debian 13, git, gh, Node 22, Python,\n * Go, Rust, Docker; one fixed 4 vCPU / 8 GB / 20 GB shape). */\n templateId?: string\n /** Boot from a snapshot instead of a template. Wins over `templateId`. */\n snapshotId?: string\n timeoutSeconds: number\n onTimeout: InstaboxOnTimeout\n /** 0 is requested to disable auto-suspend; the live API ignores it (window\n * stays 1800s). 120..86400 arms it. */\n autoSuspendAfterSeconds: number\n metadata: Record<string, string>\n /** ALWAYS false: a vault would write the caller's secrets into a box that\n * runs agent code. */\n vault: false\n guestUser?: string\n desiredState?: string\n}\n\nexport interface InstaboxExecInput {\n cmd: string\n cwd?: string\n envs?: Record<string, string>\n /** Feeds the command's stdin. Max 1 MiB. */\n stdin?: string\n /** 1..600, default 60 (seconds). */\n timeoutSeconds?: number\n}\n\nexport interface InstaboxExecResult {\n stdout: string\n stderr: string\n exitCode: number\n /** True when the exec hit its `timeoutSeconds` (the API still answers 200\n * with exitCode 124). */\n timedOut: boolean\n /** True when output was clipped by the API's 1 MiB stdout/stderr cap. */\n truncated: boolean\n}\n\nexport interface InstaboxPort {\n id: string\n port: number\n /** `https://{port}-{machineIdWithoutM_}.instabox.tech`: stable per\n * (machine, port), PUBLIC with no InstaBox-side authentication. */\n url: string\n expiresAt?: string | null\n}\n\nexport interface InstaboxUsage {\n limits?: { maxMachines?: number }\n [k: string]: unknown\n}\n\n/** A typed failure from the InstaBox API. The API key is never part of\n * `message` (transport errors and JSON error bodies carry no credential). */\nexport class InstaboxApiError extends Error {\n readonly status: number | null\n readonly code: string\n readonly requestId?: string\n readonly retryable?: boolean\n readonly operationId?: string\n\n constructor(\n message: string,\n info: {\n status: number | null\n code: string\n requestId?: string\n retryable?: boolean\n operationId?: string\n },\n ) {\n super(message)\n this.name = \"InstaboxApiError\"\n this.status = info.status\n this.code = info.code\n this.requestId = info.requestId\n this.retryable = info.retryable\n this.operationId = info.operationId\n }\n}\n\nexport interface InstaboxClientOpts {\n /** API key (`ibk_...`). Sent only as the `X-API-Key` request header. */\n apiKey: string\n /** Default `https://api.instabox.sh`. */\n apiUrl?: string\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch\n /** Delay between a failed transport attempt and the retry, ms (backoff\n * branches on it). */\n retryDelayMs?: (attempt: number) => Promise<void>\n}\n\nconst DEFAULT_API_URL = \"https://api.instabox.sh\"\n/** Per-request fetch timeout for control-plane calls (operations long-poll on\n * the server at `wait=25s`, so this must exceed that). */\nconst REQUEST_TIMEOUT_MS = 30_000\n/** Long-poll window sent to the operations endpoint. */\nconst OPERATION_WAIT = \"25s\"\n/** Max HTTP wait the client lets itself spend on ONE exec call: the exec can\n * take up to 600s inside the box. A transport error is mapped, not retried\n * (a retry could double-run a mutating command). */\nconst EXEC_HTTP_TIMEOUT_MS = 620_000\n/** Overall cap on waiting for ONE operation to settle. */\nconst OPERATION_TIMEOUT_MS = 300_000\n/** Base delay for transport-error backoff on the operation poll. */\nconst OPERATION_RETRY_BASE_DELAY_MS = 500\n/** Max attempts of the create-retry loop under transport errors. */\nconst CREATE_RETRY_ATTEMPTS = 5\n\ninterface InstaboxErrorBody {\n error?: {\n code?: unknown\n message?: unknown\n requestId?: unknown\n retryable?: unknown\n operationId?: unknown\n }\n [k: string]: unknown\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined\n}\n\n/** True by rules measured in the official CLI: HTTP 402/403/429, or a code or\n * message mentioning \"quota\" or \"limit\", means this ACCOUNT is out of room\n * (the limit is 5 machines, suspended and stopped ones included). */\nexport function isInstaboxQuotaFailure(\n status: number | null,\n code: string,\n message: string,\n): boolean {\n if (status === 402 || status === 403 || status === 429) return true\n return /quota|limit/i.test(code) || /quota|limit/i.test(message)\n}\n\n/**\n * Typed InstaBox client. Transport errors on ONE-SHOT local calls are mapped\n * to an `InstaboxApiError` with `code: \"transport_error\"`; only the\n * operation-waiter retries (with backoff). `exec` is never auto-retried: a\n * retry could run a mutating command twice.\n */\nexport class InstaboxClient {\n private readonly apiKey: string\n private readonly apiUrl: string\n private readonly fetchImpl: typeof fetch\n private readonly retryDelayMs: (attempt: number) => Promise<void>\n\n constructor(opts: InstaboxClientOpts) {\n this.apiKey = opts.apiKey\n this.apiUrl = (opts.apiUrl ?? DEFAULT_API_URL).replace(/\\/$/, \"\")\n this.fetchImpl = opts.fetchImpl ?? globalThis.fetch\n this.retryDelayMs =\n opts.retryDelayMs ??\n (attempt => new Promise(resolve => setTimeout(resolve, OPERATION_RETRY_BASE_DELAY_MS * attempt)))\n }\n\n private async request<T>(\n method: string,\n path: string,\n init: {\n body?: unknown\n idempotency?: string\n serviceTimeoutMs?: number\n } = {},\n ): Promise<T> {\n let res: Response\n try {\n res = await this.fetchImpl(`${this.apiUrl}${path}`, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n ...(init.idempotency ? { \"Idempotency-Key\": init.idempotency } : {}),\n },\n ...(init.body !== undefined ? { body: JSON.stringify(init.body) } : {}),\n signal: AbortSignal.timeout(init.serviceTimeoutMs ?? REQUEST_TIMEOUT_MS),\n })\n } catch (err) {\n throw new InstaboxApiError(`instabox: transport failure calling ${method} ${path}`, {\n status: null,\n code: \"transport_error\",\n retryable: true,\n })\n }\n if (!res.ok) {\n const text = await res.text().catch(() => \"\")\n const body: InstaboxErrorBody = safeParse(text)\n const code = asString(body.error?.code) ?? \"http_error\"\n const message = asString(body.error?.message) ?? `${method} ${path} failed with HTTP ${res.status}`\n throw new InstaboxApiError(`instabox: ${message}`, {\n status: res.status,\n code,\n requestId: asString(body.error?.requestId),\n retryable: body.error?.retryable === true || res.status === 429 || res.status >= 500,\n operationId: asString(body.error?.operationId),\n })\n }\n const raw = (await res.json()) as T\n return raw\n }\n\n /** POST /v1/machines. Retried on TRANSPORT errors only (idempotency key is\n * fixed per instance call, so a retry after a lost response cannot mint a\n * duplicate machine). Applied to the network-safe envelope, then the 202\n * body is returned. */\n async createMachine(input: InstaboxCreateMachineInput, idempotencyKey: string): Promise<InstaboxOperation> {\n return requestWithTransportRetry(\n () => this.request<InstaboxOperation>(\"POST\", \"/v1/machines\", { body: input, idempotency: idempotencyKey }),\n CREATE_RETRY_ATTEMPTS,\n )\n }\n\n /** GET /v1/operations/{id}?wait=25s, with an overall timeout and retryable\n * transport-error backoff. */\n async waitForOperation(operationId: string, timeoutMs = OPERATION_TIMEOUT_MS): Promise<InstaboxOperation> {\n const deadline = Date.now() + timeoutMs\n for (let attempt = 1; ; attempt++) {\n let op: InstaboxOperation | null = null\n let transportError = false\n try {\n op = await this.request<InstaboxOperation>(\n \"GET\",\n `/v1/operations/${encodeURIComponent(operationId)}?wait=${OPERATION_WAIT}`,\n )\n } catch (err) {\n if (!isTransportError(err)) throw err\n transportError = true\n }\n if (op !== null) {\n if (op.state === \"succeeded\") return op\n if (op.state === \"failed\") {\n throw new InstaboxApiError(describeOperationError(op), {\n status: null,\n code: \"operation_failed\",\n operationId,\n })\n }\n }\n if (Date.now() >= deadline) {\n throw new InstaboxApiError(\n `instabox: operation ${operationId} did not settle within ${timeoutMs}ms.`,\n { status: null, code: \"operation_timeout\", operationId },\n )\n }\n if (transportError) await this.retryDelayMs(attempt)\n }\n }\n\n /** GET /v1/machines/{id} (accepts id or name; ports/wake/files need `id`). */\n getMachine(idOrName: string): Promise<InstaboxMachine> {\n return this.request<InstaboxMachine>(\"GET\", `/v1/machines/${encodeURIComponent(idOrName)}`)\n }\n\n /** GET /v1/machines?metadata=k:v&...&limit=N. */\n async listMachines(metadata: Record<string, string>, limit?: number): Promise<InstaboxMachine[]> {\n const qs = new URLSearchParams()\n for (const [k, v] of Object.entries(metadata)) qs.append(\"metadata\", `${k}:${v}`)\n if (limit !== undefined) qs.set(\"limit\", String(limit))\n const suffix = qs.size > 0 ? `?${qs.toString()}` : \"\"\n const raw: unknown = await this.request<unknown>(\"GET\", `/v1/machines${suffix}`)\n if (Array.isArray(raw)) return raw as InstaboxMachine[]\n const wrapped = raw as { machines?: unknown }\n if (Array.isArray(wrapped.machines)) return wrapped.machines as InstaboxMachine[]\n return []\n }\n\n /** GET /v1/usage (limits.maxMachines). */\n readUsage(): Promise<InstaboxUsage> {\n return this.request<InstaboxUsage>(\"GET\", \"/v1/usage\")\n }\n\n /** PATCH /v1/machines/{id}. Answers 200 with the updated MACHINE (measured\n * live: `operationId` is null, there is no operation to wait on), so the\n * machine's own `id` must never be handed to `waitForOperation`. A pending\n * `operationId` is still awaited if the API ever returns one. */\n async patchMachine(\n id: string,\n patch: { timeoutSeconds?: number; onTimeout?: InstaboxOnTimeout } | { autoSuspendAfterSeconds: number },\n idempotencyKey?: string,\n ): Promise<InstaboxMachine> {\n const machine = await this.request<InstaboxMachine>(\"PATCH\", `/v1/machines/${encodeURIComponent(id)}`, {\n body: patch,\n idempotency: idempotencyKey ?? crypto.randomUUID(),\n })\n if (typeof machine.operationId === \"string\" && machine.operationId.length > 0) {\n await this.waitForOperation(machine.operationId)\n }\n return machine\n }\n\n /** DELETE /v1/machines/{id}. The API rejects a DELETE without an\n * `Idempotency-Key` (HTTP 400), so one is always sent. */\n deleteMachine(id: string): Promise<InstaboxOperation> {\n return this.request<InstaboxOperation>(\"DELETE\", `/v1/machines/${encodeURIComponent(id)}`, {\n idempotency: crypto.randomUUID(),\n })\n }\n\n /** POST /v1/machines/{id}/ports {port}. 201 first, 200 if already published\n * (both answer the same body). */\n async publishPort(id: string, port: number): Promise<InstaboxPort> {\n return await this.request<InstaboxPort>(\"POST\", `/v1/machines/${encodeURIComponent(id)}/ports`, {\n body: { port },\n idempotency: crypto.randomUUID(),\n })\n }\n\n /** DELETE /v1/machines/{id}/ports/{port}. */\n deletePort(id: string, port: number): Promise<void> {\n return this.request<void>(\"DELETE\", `/v1/machines/${encodeURIComponent(id)}/ports/${port}`)\n }\n\n /** POST /v1/machines/{id}/{verb} for suspend|resume|stop|start. */\n machineAction(id: string, verb: \"suspend\" | \"resume\" | \"stop\" | \"start\"): Promise<InstaboxOperation> {\n return this.request<InstaboxOperation>(\n \"POST\",\n `/v1/machines/${encodeURIComponent(id)}/${verb}`,\n { idempotency: crypto.randomUUID() },\n )\n }\n\n /** POST /v1/machines/{id}/wake: 200 DIRECT (no operation to wait on). */\n wake(id: string): Promise<unknown> {\n return this.request<unknown>(\n \"POST\",\n `/v1/machines/${encodeURIComponent(id)}/wake`,\n { idempotency: crypto.randomUUID() },\n )\n }\n\n /** POST /v1/machines/{id}/exec. NEVER retried and NEVER idempotent: a\n * retry could double-run a mutating command. */\n exec(id: string, input: InstaboxExecInput): Promise<InstaboxExecResult> {\n return this.request<InstaboxExecResult>(\n \"POST\",\n `/v1/machines/${encodeURIComponent(id)}/exec`,\n { body: input, serviceTimeoutMs: EXEC_HTTP_TIMEOUT_MS },\n )\n }\n}\n\nfunction describeOperationError(op: InstaboxOperation): string {\n const detail = op.error\n if (typeof detail === \"string\" && detail.length > 0) return `instabox: operation ${op.id} failed: ${detail}`\n if (detail !== null && typeof detail === \"object\") {\n const code = asString((detail as Record<string, unknown>).code)\n const message = asString((detail as Record<string, unknown>).message)\n return `instabox: operation ${op.id} failed${code ? ` (${code})` : \"\"}${message ? `: ${message}` : \"\"}`\n }\n return `instabox: operation ${op.id} failed.`\n}\n\nfunction safeParse(text: string): InstaboxErrorBody {\n try {\n const parsed: unknown = JSON.parse(text)\n if (parsed !== null && typeof parsed === \"object\") return parsed as InstaboxErrorBody\n } catch {\n // not JSON — fall through to an empty body\n }\n return {}\n}\n\n/** Transport errors (never an HTTP status answer) and 5xx. */\nexport function isTransientInstaboxError(err: unknown): boolean {\n if (!(err instanceof InstaboxApiError)) {\n // Unknown non-API errors (fetch rejections already wrapped above) are not\n // retried by generic call sites.\n return false\n }\n return err.code === \"transport_error\" || (err.status !== null && err.status >= 500)\n}\n\nfunction isTransportError(err: unknown): boolean {\n return err instanceof InstaboxApiError && err.code === \"transport_error\"\n}\n\nasync function requestWithTransportRetry<T>(fn: () => Promise<T>, attempts: number): Promise<T> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await fn()\n } catch (err) {\n if (attempt >= attempts || !isTransportError(err)) throw err\n await new Promise(resolve => setTimeout(resolve, OPERATION_RETRY_BASE_DELAY_MS * attempt))\n }\n }\n}\n\n\n","/**\n * InstaBox `SandboxProvider` (https://instabox.sh, API\n * https://api.instabox.sh) for @agentproto/sandbox — boots an InstaBox VM,\n * publishes the agentproto daemon behind the account's public edge, and hands\n * its `/mcp` endpoint to `createSandboxAgentSessionHost` the same way\n * `@agentproto/sandbox-box` (ascii.dev Box) does.\n *\n * Shape notes measured live on 2026-10-18 (see `api.ts` for the API itself):\n *\n * - Synchronous `exec` API (`POST /machines/{id}/exec`): a non-zero exit is a\n * normal 200 RESULT (not an error); a command that runs past its\n * `timeoutSeconds` answers with `exitCode: 124, timedOut: true`; each\n * stream is capped at 1 MiB (`truncated: true`). There is NO upload route\n * (PUT/POST on `/files` 404), so `writeFile`/`readFile` go through `exec`:\n * write = `mkdir -p` + base64 on STDIN to `base64 -d > file` in chunks of at\n * most 700 KB; read = `dd` slice + `base64 -w0` in chunks small enough that\n * each stdout stays under the API's 1 MiB capture cap.\n * - A published port's edge (`https://{port}-{machineIdWithoutM_}.instabox.tech`,\n * stable per machine+port) is PUBLIC with NO InstaBox-side authentication,\n * so the daemon MUST be started with an auth token: the unit's ExecStart\n * carries `--auth-token`, whose value is ONLY substituted by systemd from\n * the EnvironmentFile (`AGENTPROTO_AUTH_TOKEN`), so the token never lands in\n * an exec command's argv; secrets ride the heredoc body (exec stdin) into a\n * root-owned 0600 EnvironmentFile.\n * - Backgrounded in-VM processes MUST redirect their stdio: a bare `cmd &`\n * keeps the synchronous exec open until its timeout. The provider never\n * backgrounds anything itself: the daemon runs as a systemd unit\n * (`Restart=always`), which survives `kill -9`, suspend/resume and\n * auto-suspend (proven live).\n * - A MANUALLY suspended machine does NOT wake on its own: its public URL\n * 503s, its exec and `wake` answer 409. This provider therefore NEVER sends\n * the suspend verb and deliberately does NOT implement `pause()` (omitting\n * it lets callers fall back to `stop()`, which deletes the box). Instead it\n * requests `autoSuspendAfterSeconds` 0 by default (configurable), but the\n * live API ignores 0 (the window stays 1800s) and a PATCH of it is a no-op:\n * do not rely on it. Auto-suspended machines DO wake on a public request,\n * on `wake` and on `exec`, and `connect` revives a manually suspended one\n * through `resume` (proven live: process memory survives).\n */\n\nimport { randomBytes } from \"node:crypto\"\nimport type {\n BootedSandbox,\n SandboxBootOpts,\n SandboxExecOpts,\n SandboxExecResult,\n SandboxProbeResult,\n SandboxProvider,\n SandboxSpec,\n} from \"@agentproto/sandbox\"\nimport { SandboxBoxGoneError, SandboxQuotaError, scrubCommandFromMessage } from \"@agentproto/sandbox\"\nimport {\n InstaboxApiError,\n InstaboxClient,\n isInstaboxQuotaFailure,\n type InstaboxExecResult as InstaboxExecResultApi,\n type InstaboxMachine,\n} from \"./api.js\"\n\n/** `serve.ts`'s default port (`DEFAULT_MCP_URL` in `@agentproto/harness`). */\nconst DEFAULT_PORT = 18790\n/** InstaBox's Debian 13 image boots with user home under /data (`HOME` is\n * `/data/home`; `/data` itself is root-owned, so the daemon workspace is\n * written under HOME). */\nconst DEFAULT_WORKSPACE = \"/data/home\"\n/** Default template: `universal` (Debian 13, git, gh, Node 22, Python, Go,\n * Rust, Docker, Claude Code, Codex; one fixed 4 vCPU / 8 GB / 20 GB shape,\n * passwordless sudo). */\nconst DEFAULT_TEMPLATE = \"universal\"\n/**\n * Default box lifetime, seconds. InstaBox restarts the countdown from NOW on\n * every PATCH `timeoutSeconds` (`extendTimeout`), the same re-arm contract as\n * e2b's `setTimeout` (see `@agentproto/sandbox-e2b`'s DEFAULT_SANDBOX_TIMEOUT_MS\n * for why a 1h default is survivable only with re-arms).\n */\nconst DEFAULT_TIMEOUT_SECONDS = 3600\n/** Clamp range for machine `timeoutSeconds` (create and extend re-arms). */\nconst MIN_TIMEOUT_SECONDS = 60\nconst MAX_TIMEOUT_SECONDS = 86400\n/** Default auto-suspend request: 0 means \"disabled\", which the live API\n * ignores (the window stays 1800s); kept so an account that honours it does. */\nconst DEFAULT_AUTO_SUSPEND_AFTER_SECONDS = 0\nconst HEALTH_PROBE_TIMEOUT_MS = 5_000\n/** Pre-install probe window (the daemon can only be there by luck; keep the\n * \"already up?\" check short so a fresh boot does not stall on it). */\nconst ALREADY_UP_PROBE_TIMEOUT_MS = 2_000\nconst POLL_INTERVAL_MS = 500\n/** Overall wait for a fresh/starting machine to reach `runtime.ready`. */\nconst READY_TIMEOUT_MS = 120_000\n/** Overall wait for the freshly-started daemon to answer /health. The\n * InstaBox edge 502s a connection with no bytes for 20s, so the probe\n * cadence stays well under that. */\nconst DAEMON_READY_TIMEOUT_MS = 60_000\n/** Per-command exec clamp range (seconds), measured API contract 1..600. */\nconst EXEC_MAX_TIMEOUT_SECONDS = 600\n/** Default per-call exec timeout when the caller gives none: the API's own\n * 60s default is the same mid-work-kill trap e2b's 5-minute box default\n * was (a busy `pnpm test` legitimately runs past a minute). */\nconst EXEC_DEFAULT_TIMEOUT_SECONDS = 600\n/** Default exec timeout (seconds) for the boot `npm i -g @agentproto/cli`. */\nconst DEFAULT_UPDATE_CLI_TIMEOUT_SECONDS = 600\n/** Chunk size for file transfer through exec: 700 KB stays under the API's\n * 1 MiB stdin and stdout caps after base64 inflation (700 KB -> ~933 KB). */\nconst FILE_CHUNK_BYTES = 700 * 1024\n/** B64 chars of one max chunk (4/3 rounding up to a multiple of 4, so every\n * slice boundary decodes AND a shorter answer means EOF was reached). */\nconst FILE_CHUNK_B64_CHARS = Math.ceil(FILE_CHUNK_BYTES / 3) * 4\n/** Length (bytes) of the generated daemon bearer token. */\nconst AUTH_TOKEN_BYTES = 32\nconst PROVIDER_SLUG = \"instabox\"\n\nconst ENV_FILE_DIR = \"/etc/agentproto\"\nexport const ENV_FILE_PATH = `${ENV_FILE_DIR}/agentproto.env`\nexport const SYSTEMD_UNIT_PATH = \"/etc/systemd/system/agentproto.service\"\n/** Unit name of the systemd service wrapping the daemon. */\nexport const DAEMON_UNIT_NAME = \"agentproto\"\n/** Env var the EnvironmentFile sets for the unit's `--auth-token` value. */\nexport const AUTH_TOKEN_ENV_VAR = \"AGENTPROTO_AUTH_TOKEN\"\n/** Machine metadata stamp: which machines this provider owns (`agentproto: \"1\"`). */\nexport const AGENTPROTO_METADATA_KEY = \"agentproto\"\nconst AGENTPROTO_METADATA_VALUE = \"1\"\n\n/** Suffix that MANDATORY redirection takes on any in-box background\n * invocation (a background `cmd &` without it keeps the synchronous exec\n * open until its timeout). Exported so tests can assert every provider-built\n * command that backgrounds something carries it. */\nexport const BACKGROUND_REDIRECT = \">/dev/null 2>&1 </dev/null\"\n\nexport interface InstaboxSandboxSpecConfig {\n /** InstaBox API key (`ibk_...`). Falls back to `INSTABOX_API_KEY` in the\n * host process env. Sent only as the `X-API-Key` header (never logged,\n * never part of an error message). */\n apiKey?: string\n /** Default `https://api.instabox.sh`. */\n apiUrl?: string\n /** Template id. Default `universal`. (A `snapshotId` would win on the API,\n * but this provider always boots from a template.) */\n template?: string\n /** Machine lifetime in seconds, re-armed from now on every extend.\n * Default 3600, clamp 60..86400. */\n timeoutSeconds?: number\n /** This provider only ever sends `kill`: `pause` would leave a manually\n * suspended box stranded (it does not wake on its own). */\n onTimeout?: \"kill\"\n /** 0 disables auto-suspend (default); 120..86400 arms it. */\n autoSuspendAfterSeconds?: number\n /** Port the agentproto daemon listens on inside the box. Default 18790. */\n port?: number\n /** `--workspace` passed to `agentproto serve`. Default `/data/home`. */\n workspace?: string\n /** CLI version pinned on boot, instead of a floating `@latest`.\n * Produces `@agentproto/cli@<version>`. */\n cliVersion?: string\n /** Run `npm i -g @agentproto/cli@...` before installing the systemd unit.\n * Default true. Skipped when the health probe finds the daemon already up. */\n updateCliOnBoot?: boolean\n /** Extra npm package specs installed globally ALONGSIDE the CLI update\n * (one `npm i -g`). Ignored when `updateCliOnBoot` is false or the daemon\n * was already up. */\n installPackages?: string[]\n /** Timeout (seconds, exec-clamped 1..600) for the `npm i -g` update. */\n updateCliTimeoutSeconds?: number\n /** How long to wait for the machine itself to reach `runtime.ready`. */\n readyTimeoutMs?: number\n /** How long to wait for the daemon to become healthy after starting it. */\n daemonReadyTimeoutMs?: number\n /** Extra machine metadata written at create time (merged with the\n * provider's own `agentproto: \"1\"` stamp). */\n metadata?: Record<string, string>\n /** Extra shell commands host-executed after the boot update, before the\n * daemon starts. Runs on EVERY boot/connect; entries must be idempotent. */\n setupCommands?: string[]\n}\n\ninterface ResolvedConfig {\n apiKey: string\n apiUrl: string\n template: string\n timeoutSeconds: number\n autoSuspendAfterSeconds: number\n port: number\n workspace: string\n cliVersion: string\n updateCliOnBoot: boolean\n installPackages: string[]\n updateCliTimeoutSeconds: number\n readyTimeoutMs: number\n daemonReadyTimeoutMs: number\n metadata: Record<string, string>\n setupCommands: string[]\n}\n\nfunction readConfig(rawConfig: unknown): ResolvedConfig {\n const raw = (rawConfig ?? {}) as Record<string, unknown>\n const num = (field: unknown, fallback: number, min: number, max: number): number => {\n if (typeof field !== \"number\" || !Number.isFinite(field)) return fallback\n return Math.min(max, Math.max(min, Math.floor(field)))\n }\n const str = (field: unknown): string | undefined =>\n typeof field === \"string\" && field.length > 0 ? field : undefined\n const metadata =\n typeof raw.metadata === \"object\" && raw.metadata !== null\n ? Object.fromEntries(\n Object.entries(raw.metadata as Record<string, unknown>).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n ),\n )\n : {}\n return {\n apiKey: str(raw.apiKey) ?? process.env.INSTABOX_API_KEY ?? \"\",\n apiUrl: str(raw.apiUrl) ?? \"https://api.instabox.sh\",\n template: str(raw.template) ?? DEFAULT_TEMPLATE,\n timeoutSeconds: num(raw.timeoutSeconds, DEFAULT_TIMEOUT_SECONDS, MIN_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS),\n autoSuspendAfterSeconds:\n typeof raw.autoSuspendAfterSeconds === \"number\" && Number.isFinite(raw.autoSuspendAfterSeconds)\n ? Math.min(86400, Math.max(0, Math.floor(raw.autoSuspendAfterSeconds)))\n : DEFAULT_AUTO_SUSPEND_AFTER_SECONDS,\n port: num(raw.port, DEFAULT_PORT, 1, 65_535),\n workspace: str(raw.workspace) ?? DEFAULT_WORKSPACE,\n cliVersion: str(raw.cliVersion) ?? \"latest\",\n updateCliOnBoot: typeof raw.updateCliOnBoot === \"boolean\" ? raw.updateCliOnBoot : true,\n installPackages: Array.isArray(raw.installPackages)\n ? raw.installPackages.filter((p): p is string => typeof p === \"string\" && p.length > 0)\n : [],\n updateCliTimeoutSeconds: num(\n raw.updateCliTimeoutSeconds,\n DEFAULT_UPDATE_CLI_TIMEOUT_SECONDS,\n 1,\n EXEC_MAX_TIMEOUT_SECONDS,\n ),\n readyTimeoutMs: num(raw.readyTimeoutMs, READY_TIMEOUT_MS, 1_000, 600_000),\n daemonReadyTimeoutMs: num(raw.daemonReadyTimeoutMs, DAEMON_READY_TIMEOUT_MS, 1_000, 600_000),\n metadata,\n setupCommands: Array.isArray(raw.setupCommands)\n ? raw.setupCommands.filter((c): c is string => typeof c === \"string\" && c.length > 0)\n : [],\n }\n}\n\n/** The EnvironmentFile body: resolved secrets from `opts.env` PLUS the token\n * gating the public edge. Never rendered into a command line. */\nexport function environmentFileContents(env: Record<string, string>, authToken: string): string {\n const lines = [\n ...Object.entries(env).map(([key, value]) => `${key}=${value}`),\n `${AUTH_TOKEN_ENV_VAR}=${authToken}`,\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n\n/**\n * One shell command that writes the daemon's EnvironmentFile (root, 0600)\n * and its systemd unit, BOTH through heredocs. No secret is ever part of an\n * argv token: the env content sits inside the heredoc body (which the exec\n * API turns into `sudo tee`'s stdin), and the unit's ExecStart references the\n * token as `${AGENTPROTO_AUTH_TOKEN}`, substituted by systemd from the\n * EnvironmentFile. Heredoc terminators must sit on their own lines (the same\n * live-tested lesson as `@agentproto/sandbox-box`'s writeSystemdUnitCommand:\n * chaining \" && \" after a heredoc lands the next command INSIDE it and the\n * unit write silently no-ops at exit 0).\n */\nexport function writeDaemonUnitCommand(\n port: number,\n workspace: string,\n env: Record<string, string>,\n authToken: string,\n): { command: string; envFileContents: string; unitContents: string } {\n const envFileContents = environmentFileContents(env, authToken)\n const unit = [\n \"[Unit]\",\n \"Description=agentproto daemon\",\n \"After=network.target\",\n \"\",\n \"[Service]\",\n `EnvironmentFile=-${ENV_FILE_PATH}`,\n `ExecStart=agentproto serve --port ${port} --bind 0.0.0.0 --workspace \"${workspace}\" ` +\n `--auth-token \\${${AUTH_TOKEN_ENV_VAR}}`,\n \"Restart=always\",\n \"User=user\",\n \"\",\n \"[Install]\",\n \"WantedBy=multi-user.target\",\n ].join(\"\\n\")\n const command = [\n \"set -e\",\n `sudo mkdir -p ${ENV_FILE_DIR}`,\n `sudo tee ${ENV_FILE_PATH} > /dev/null <<'AGENTPROTO_ENV'\\n${envFileContents}AGENTPROTO_ENV`,\n `sudo chmod 600 ${ENV_FILE_PATH}`,\n `sudo tee ${SYSTEMD_UNIT_PATH} > /dev/null <<'AGENTPROTO_UNIT'\\n${unit}\\nAGENTPROTO_UNIT`,\n ].join(\"\\n\")\n return { command, envFileContents, unitContents: unit }\n}\n\n/** The global install command line (exported for tests: only package spec\n * names, never a secret). The box user is the unprivileged `user` and the\n * npm prefix is the root-owned /usr/local (measured live: a bare `npm i -g`\n * dies with EACCES), so it runs through `sudo`, keeping the caller's PATH\n * because `sudo`'s secure_path may not list node's directory. */\nexport function buildCliInstallCommand(cliVersion: string, extras: string[]): string {\n const extraText = extras.map(extra => ` '${extra.replace(/'/g, \"\")}'`).join(\"\")\n return `sudo env \"PATH=$PATH\" npm i -g \"@agentproto/cli@${cliVersion}\"${extraText}`\n}\n\n/**\n * Quota gate, run BEFORE creating anything: the account limit is 5 machines\n * and suspended/stopped ones count against it, so a pre-check (`GET /v1/usage`\n * + `GET /v1/machines`) catches the common case early and throws a typed\n * `SandboxQuotaError` a caller can fall back to another provider on. The\n * calls are best-effort: a usage API that does not answer must not break a\n * boot that the create call could still grant.\n */\nexport async function assertQuotaAvailable(client: InstaboxClient): Promise<void> {\n const [usage, machines] = await Promise.all([\n client.readUsage().catch(() => undefined),\n client.listMachines({}, 200).catch(() => undefined),\n ])\n const max = usage?.limits?.maxMachines\n if (typeof max === \"number\" && machines !== undefined && machines.length >= max) {\n throw new SandboxQuotaError(\n PROVIDER_SLUG,\n `instabox: account limit is ${max} machines and ${machines.length} already exist ` +\n \"(suspended and stopped machines count); stop one before booting another.\",\n )\n }\n}\n\n/** Re-map a create/lifecycle failure that is quota-shaped (HTTP 402/403/429,\n * or a code/message containing \"quota\" or \"limit\"; the string exists in the\n * official CLI but was never received live) to `SandboxQuotaError`, so a\n * caller falls back to a different provider instead of surfacing the noise. */\nexport function normalizeQuotaError(err: unknown): unknown {\n if (err instanceof InstaboxApiError && isInstaboxQuotaFailure(err.status, err.code, err.message)) {\n return new SandboxQuotaError(\n PROVIDER_SLUG,\n `instabox: account limit reached (HTTP ${err.status ?? \"?\"}, code \"${err.code}\"): ` +\n \"fall back to a different sandbox provider.\",\n err,\n )\n }\n return err\n}\n\nfunction bootMetadata(config: ResolvedConfig, spec: SandboxSpec): Record<string, string> {\n const sessionId = (spec as SandboxSpec & { id?: unknown }).id\n const metadata: Record<string, string> = { ...config.metadata }\n metadata[AGENTPROTO_METADATA_KEY] = AGENTPROTO_METADATA_VALUE\n if (typeof sessionId === \"string\" && sessionId.length > 0) {\n metadata.session = sessionId\n }\n return metadata\n}\n\n/** Poll the machine until `runtime.ready` (or the deadline). */\nasync function waitMachineReady(\n client: InstaboxClient,\n machineId: string,\n timeoutMs: number,\n): Promise<InstaboxMachine> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const machine = await client.getMachine(machineId)\n if (machine.runtime?.ready === true) return machine\n if (Date.now() >= deadline) {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} did not reach runtime.ready ` +\n `within ${timeoutMs}ms.`,\n )\n }\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS))\n }\n}\n\n/** Poll `<url>/health` until it answers OK, or false once the deadline\n * elapses. */\nasync function probeHealth(url: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(HEALTH_PROBE_TIMEOUT_MS) })\n if (res.ok) return true\n } catch {\n // not up yet (the InstaBox edge answers 502 while nothing listens)\n }\n if (Date.now() >= deadline) return false\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS))\n }\n}\n\ninterface PendingProvision {\n client: InstaboxClient\n machineId: string\n config: ResolvedConfig\n env: Record<string, string>\n authToken: string\n}\n\n/**\n * Shared tail of `boot` and `connect`: publish the daemon port, then probe\n * the daemon through the PUBLIC edge (/health unauthenticated; /mcp itself is\n * bearer-gated by `--auth-token`). Only when the probe stays red: update the\n * CLI, write the EnvironmentFile (0600) and the systemd unit (secrets in the\n * heredoc, token via env substitution), run the setup hooks, enable the unit,\n * and re-probe through the edge. `deleteOnFailure` (the FRESH boot path)\n * reaps the machine when the daemon never comes up, so a failed boot never\n * leaks a running, session-less box; connect leaves the machine alone.\n */\nasync function provisionAndProbe(\n state: PendingProvision,\n deleteOnFailure: boolean,\n): Promise<{ url: string; mcpUrl: string }> {\n const { client, machineId, config } = state\n const published = await client.publishPort(machineId, config.port)\n const publicUrl = published.url\n const healthUrl = `${publicUrl}/health`\n\n const alreadyUp = await probeHealth(healthUrl, ALREADY_UP_PROBE_TIMEOUT_MS)\n if (!alreadyUp) {\n if (config.updateCliOnBoot) {\n await execChecked(client, machineId, \"CLI install\", {\n cmd: buildCliInstallCommand(\n config.cliVersion,\n config.installPackages.map(extra => extra.replace(/'/g, \"\")),\n ),\n timeoutSeconds: config.updateCliTimeoutSeconds,\n })\n }\n await execChecked(client, machineId, \"workspace setup\", {\n cmd: `mkdir -p '${config.workspace}' && sudo mkdir -p ${ENV_FILE_DIR}`,\n })\n // stderr is NOT quoted here: the command carries the secrets heredoc.\n await execChecked(\n client,\n machineId,\n \"daemon unit install\",\n { cmd: writeDaemonUnitCommand(config.port, config.workspace, state.env, state.authToken).command },\n { quoteStderr: false },\n )\n for (const command of config.setupCommands) {\n await execChecked(client, machineId, \"setup command\", {\n cmd: command,\n timeoutSeconds: EXEC_MAX_TIMEOUT_SECONDS,\n })\n }\n await execChecked(client, machineId, \"daemon enable\", {\n cmd: `sudo systemctl daemon-reload && sudo systemctl enable --now ${DAEMON_UNIT_NAME} ${BACKGROUND_REDIRECT}`,\n })\n const ready = await probeHealth(healthUrl, config.daemonReadyTimeoutMs)\n if (!ready) {\n if (deleteOnFailure) await client.deleteMachine(machineId).catch(() => undefined)\n throw new Error(\n `@agentproto/sandbox-instabox: agentproto daemon did not become healthy at ${healthUrl} ` +\n `within ${config.daemonReadyTimeoutMs}ms (machine ${machineId}).`,\n )\n }\n }\n return { url: publicUrl, mcpUrl: `${publicUrl}/mcp` }\n}\n\n/** Run one exec for provisioning; a non-zero exit is a RESULT, a transport\n * failure throws with its message scrubbed (so the error never carries the\n * command body, let alone a secret). */\nasync function execScrubbed(\n client: InstaboxClient,\n machineId: string,\n input: { cmd: string; stdin?: string; timeoutSeconds?: number },\n): Promise<InstaboxExecResultApi> {\n try {\n return await client.exec(machineId, input)\n } catch (err) {\n if (err instanceof Error) {\n const scrubbed = scrubCommandFromMessage(err.message, input.cmd)\n if (scrubbed !== err.message) {\n const wrapped = new Error(scrubbed)\n wrapped.name = err.name\n throw wrapped\n }\n }\n throw err\n }\n}\n\n/** `execScrubbed` that also refuses a non-zero exit: a failed install must\n * surface as itself instead of as a daemon that \"never became healthy\" 60s\n * later. Only the exit code and the head of stderr are reported, never the\n * command (it can carry the env file heredoc). */\nasync function execChecked(\n client: InstaboxClient,\n machineId: string,\n what: string,\n input: { cmd: string; stdin?: string; timeoutSeconds?: number },\n opts: { quoteStderr?: boolean } = {},\n): Promise<InstaboxExecResultApi> {\n const result = await execScrubbed(client, machineId, input)\n if (result.exitCode !== 0) {\n const detail =\n opts.quoteStderr === false ? \"\" : scrubCommandFromMessage(result.stderr.trim(), input.cmd).slice(0, 300)\n throw new Error(\n `@agentproto/sandbox-instabox: ${what} failed on machine ${machineId} ` +\n `(exit ${result.exitCode}${result.timedOut ? \", timed out\" : \"\"}${detail ? `: ${detail}` : \"\"}).`,\n )\n }\n return result\n}\n\nfunction newInstanceName(): string {\n return `agentproto-${randomBytes(5).toString(\"hex\")}`\n}\n\nfunction newAuthToken(): string {\n return randomBytes(AUTH_TOKEN_BYTES).toString(\"hex\")\n}\n\nfunction machineIdOf(machine: InstaboxMachine): string {\n if (typeof machine.id !== \"string\" || machine.id.length === 0) {\n throw new Error(\"instabox: machine response carries no id\")\n }\n return machine.id\n}\n\n/** Clamp for machine `timeoutSeconds` (create and extend re-arms). */\nfunction clampTimeoutSeconds(seconds: number): number {\n return Math.min(MAX_TIMEOUT_SECONDS, Math.max(MIN_TIMEOUT_SECONDS, Math.floor(seconds)))\n}\n\n/** InstaBox execs clamp 1..600 seconds; an absent bound maps to the max (not\n * the API's own 60s default, see module docs). */\nfunction clampExecTimeoutSeconds(timeoutMs: number | undefined): number {\n const seconds = Math.floor((timeoutMs ?? EXEC_DEFAULT_TIMEOUT_SECONDS * 1000) / 1000)\n return Math.min(EXEC_MAX_TIMEOUT_SECONDS, Math.max(1, seconds))\n}\n\n/** Wrap a healthy machine into the `BootedSandbox` shape common to `boot` and\n * `connect`. Deliberately NO `pause()`: a manually suspended InstaBox machine\n * does not wake on its own, so callers must fall back to `stop()` (delete). */\nfunction toBootedSandbox(\n client: InstaboxClient,\n machineId: string,\n mcpUrl: string,\n authToken: string,\n config: ResolvedConfig,\n ports: Record<number, string>,\n): BootedSandbox {\n return {\n mcpUrl,\n sandboxId: machineId,\n ...(Object.keys(ports).length > 0 ? { ports } : {}),\n // The public edge is UNGATED at InstaBox: the daemon's own bearer (minted\n // here at unit install time and substituted from the 0600 EnvironmentFile)\n // is the only thing gating /mcp, so it is ALWAYS surfaced.\n token: authToken,\n authHeaders: { Authorization: `Bearer ${authToken}` },\n async stop(): Promise<void> {\n try {\n const op = await client.deleteMachine(machineId)\n await client.waitForOperation(op.id)\n } catch (err) {\n if (err instanceof InstaboxApiError && err.status === 404) return\n await client.deleteMachine(machineId).catch(() => undefined)\n throw err\n }\n },\n async exec(opts: SandboxExecOpts): Promise<SandboxExecResult> {\n const startedAt = Date.now()\n const result = await client.exec(machineId, {\n cmd: opts.command,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.env !== undefined ? { envs: opts.env } : {}),\n // InstaBox clamps exec 1..600s. An omitted bound maps to the max,\n // NOT the API's own 60s default (mid-work-kill trap, module docs).\n timeoutSeconds: clampExecTimeoutSeconds(opts.timeoutMs),\n })\n return {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n durationMs: Date.now() - startedAt,\n ...(result.truncated ? { truncated: result.truncated } : {}),\n }\n },\n async readFile(path: string): Promise<Uint8Array> {\n const chunks: Uint8Array[] = []\n for (let index = 0; ; index++) {\n // `dd ibs=<chunk> skip=<index> count=1` slices the file, `base64 -w0`\n // inlines it under the 1 MiB stdout cap (700 KB -> ~933 KB of b64).\n // A pipeline exits with base64's status, so `test -r` guards it: an\n // unreadable file must fail, not read back as empty.\n const result = await client.exec(machineId, {\n cmd: `test -r '${path}' && dd if='${path}' ibs=${FILE_CHUNK_BYTES} skip=${index} count=1 2>/dev/null | base64 -w0`,\n timeoutSeconds: EXEC_MAX_TIMEOUT_SECONDS,\n })\n const encoded = result.stdout.trim()\n if (index === 0 && result.exitCode !== 0 && encoded === \"\") {\n throw new Error(\n `instabox readFile: cannot read \"${path}\" (exit ${result.exitCode}, ` +\n `stderr: ${result.stderr.trim() || \"(none)\"})`,\n )\n }\n if (encoded.length === 0) break\n chunks.push(new Uint8Array(Buffer.from(encoded, \"base64\")))\n if (encoded.length < FILE_CHUNK_B64_CHARS) break\n }\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0)\n const out = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n },\n async writeFile(path: string, data: Uint8Array): Promise<void> {\n // Base64 the whole payload once, then stream `dd`-independent slices of\n // that b64 through exec STDIN (never an argv token). Slicing on\n // `FILE_CHUNK_B64_CHARS` (a multiple of 4) keeps every middle chunk\n // cleanly decodable; the trailing chunk keeps the base64 padding.\n const encoded = Buffer.from(data).toString(\"base64\")\n const directory = path.slice(0, Math.max(path.lastIndexOf(\"/\"), 0)) || \"/\"\n for (let offset = 0, index = 0; index === 0 || offset < encoded.length; offset += FILE_CHUNK_B64_CHARS, index++) {\n const slice = encoded.slice(offset, offset + FILE_CHUNK_B64_CHARS)\n await client.exec(machineId, {\n cmd:\n index === 0\n ? `mkdir -p '${directory}' && base64 -d > '${path}'`\n : `base64 -d >> '${path}'`,\n stdin: slice,\n timeoutSeconds: EXEC_MAX_TIMEOUT_SECONDS,\n })\n }\n },\n async expose(port: number): Promise<{ url: string }> {\n const published = await client.publishPort(machineId, port)\n return { url: published.url }\n },\n async extendTimeout(ms: number): Promise<void> {\n // PATCH timeoutSeconds restarts the countdown FROM NOW (the API's own\n // semantics), so `ms` simply maps to a clamped second count.\n const seconds = clampTimeoutSeconds(ms / 1000)\n await client.patchMachine(machineId, { timeoutSeconds: seconds })\n },\n lifetimeMs: config.timeoutSeconds * 1000,\n }\n}\n\n/**\n * Bring a machine back to running, STATE-AWARE (module docs): `running` is a\n * no-op; `suspended` first tries `wake` (the AUTO-suspend path: 200 direct)\n * then `resume` for a manually-suspended box; anything else (`stopped`) goes\n * through `start`. A verb the API refuses surfaces a clear error instead of a\n * silent wrong-state reconnect.\n */\nasync function reviveMachine(client: InstaboxClient, machineId: string, state: string): Promise<void> {\n if (state === \"running\") return\n if (state === \"suspended\") {\n try {\n await client.wake(machineId)\n return\n } catch (err) {\n // Only a CONFLICT means \"manually suspended, wake refuses\" (the API\n // answers 409 machine_not_running). Any other failure — a transport\n // error, a 5xx — must surface as itself rather than be misreported as\n // \"wake and resume both refused\".\n const conflict =\n err instanceof InstaboxApiError &&\n (err.status === 409 || err.code === \"machine_not_running\")\n if (!conflict) throw err\n }\n const resume = await client.machineAction(machineId, \"resume\").catch(err => {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} is suspended and refused both ` +\n `wake and resume (${err instanceof Error ? err.message : String(err)}).`,\n )\n })\n await client.waitForOperation(resume.id)\n return\n }\n const start = await client.machineAction(machineId, \"start\").catch(err => {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} is \"${state}\" and refused start ` +\n `(${err instanceof Error ? err.message : String(err)}).`,\n )\n })\n await client.waitForOperation(start.id)\n}\n\n/**\n * Re-derive the daemon bearer from the 0600 EnvironmentFile the boot that\n * installed this daemon wrote: connect never rewrites the env file while the\n * daemon is running, so the token it returns MUST match what is installed.\n */\nasync function readExistingAuthToken(client: InstaboxClient, machineId: string): Promise<string> {\n // Read ONLY the token line: `cat`-ing the whole EnvironmentFile would pull\n // every box secret (OPENROUTER_API_KEY, …) back into this host process for\n // no reason. `grep` keeps the sensitive values in the box.\n const result = await client.exec(machineId, {\n cmd: `sudo grep '^${AUTH_TOKEN_ENV_VAR}=' ${ENV_FILE_PATH} 2>/dev/null || true`,\n timeoutSeconds: 60,\n })\n const line = result.stdout\n .split(\"\\n\")\n .map(entry => entry.trim())\n .find(entry => entry.startsWith(`${AUTH_TOKEN_ENV_VAR}=`))\n const value = line?.slice(`${AUTH_TOKEN_ENV_VAR}=`.length)\n if (typeof value !== \"string\" || value.length === 0) {\n throw new Error(`instabox: ${AUTH_TOKEN_ENV_VAR} missing from the daemon env file`)\n }\n return value\n}\n\nfunction resolveExtraPorts(spec: SandboxSpec): number[] {\n const extras = (spec as SandboxSpec & { extraPorts?: unknown }).extraPorts\n if (!Array.isArray(extras)) return []\n return extras.filter((port): port is number => typeof port === \"number\" && Number.isInteger(port))\n}\n\n/**\n * `createInstaboxSandboxProvider(config)` — an AIP-36 `SandboxProvider`\n * factory. `config` seeds every boot/connect's spec.config (a per-spec value\n * wins per field). The bare `instaboxSandboxProvider` export (what the\n * registry wraps) seeds nothing: credentials come from spec.config or the\n * `INSTABOX_API_KEY` env var.\n */\nexport function createInstaboxSandboxProvider(baseConfig: InstaboxSandboxSpecConfig = {}): SandboxProvider {\n function resolveConfig(spec: SandboxSpec): ResolvedConfig {\n const raw = (spec.config ?? {}) as Record<string, unknown>\n const merged: Record<string, unknown> = { ...baseConfig, ...raw }\n if (baseConfig.metadata !== undefined && raw.metadata !== undefined) {\n merged.metadata = {\n ...baseConfig.metadata,\n ...(typeof raw.metadata === \"object\" && raw.metadata !== null\n ? (raw.metadata as Record<string, string>)\n : {}),\n }\n }\n return readConfig(merged)\n }\n\n function assertApiKey(config: ResolvedConfig): void {\n if (config.apiKey === \"\") {\n throw new Error(\n \"@agentproto/sandbox-instabox: no InstaBox API key — set spec.config.apiKey \" +\n \"or the INSTABOX_API_KEY environment variable.\",\n )\n }\n }\n\n return {\n async boot(spec: SandboxSpec, opts: SandboxBootOpts): Promise<BootedSandbox> {\n const config = resolveConfig(spec)\n assertApiKey(config)\n const client = new InstaboxClient({ apiKey: config.apiKey, apiUrl: config.apiUrl })\n const authToken = newAuthToken()\n await assertQuotaAvailable(client)\n const created = await client\n .createMachine(\n {\n name: newInstanceName(),\n templateId: config.template,\n timeoutSeconds: config.timeoutSeconds,\n onTimeout: \"kill\",\n autoSuspendAfterSeconds: config.autoSuspendAfterSeconds,\n metadata: bootMetadata(config, spec),\n // ALWAYS sent and ALWAYS false: a vault would write the caller's\n // secrets into a box that runs agent code.\n vault: false,\n },\n crypto.randomUUID(),\n )\n .catch(err => {\n throw normalizeQuotaError(err)\n })\n try {\n await client.waitForOperation(created.id)\n const machineId = created.machineId ?? created.machine?.id\n if (machineId === undefined) {\n throw new Error(\n `@agentproto/sandbox-instabox: create operation ${created.id} settled with no machine id.`,\n )\n }\n await waitMachineReady(client, machineId, config.readyTimeoutMs)\n const extraPorts = resolveExtraPorts(spec)\n const provisioned = await provisionAndProbe(\n { client, machineId, config, env: opts.env, authToken },\n true,\n )\n const ports: Record<number, string> = {}\n for (const port of extraPorts) {\n ports[port] = (await client.publishPort(machineId, port)).url\n }\n return toBootedSandbox(client, machineId, provisioned.mcpUrl, authToken, config, ports)\n } catch (err) {\n // Every failure past the create must reclaim the machine, so a failed\n // create operation or a long provisioning failure never leaves a\n // running, session-less box behind.\n const machineId = created.machineId ?? created.machine?.id\n if (machineId !== undefined) await client.deleteMachine(machineId).catch(() => undefined)\n throw normalizeQuotaError(err)\n }\n },\n\n /** Reconnect to an existing box, state-aware (see `reviveMachine`).\n * State mapping: `running` = ok, auto-`suspended` = `wake`, manually\n * `suspended` or `stopped` = `resume`/`start` as the API allows, else a\n * clear error. A deleted machine surfaces as `SandboxBoxGoneError`. */\n async connect(sandboxId: string, spec: SandboxSpec, opts: SandboxBootOpts): Promise<BootedSandbox> {\n const config = resolveConfig(spec)\n assertApiKey(config)\n const client = new InstaboxClient({ apiKey: config.apiKey, apiUrl: config.apiUrl })\n let machine: InstaboxMachine\n try {\n machine = await client.getMachine(sandboxId)\n } catch (err) {\n if (err instanceof InstaboxApiError && err.status === 404) {\n throw new SandboxBoxGoneError(sandboxId, err)\n }\n throw err\n }\n const machineId = machineIdOf(machine)\n await reviveMachine(client, machineId, machine.state)\n await waitMachineReady(client, machineId, config.readyTimeoutMs)\n if (machine.state !== \"running\" && (await client.getMachine(machineId)).state !== \"running\") {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} did not reach \"running\" — cannot reconnect.`,\n )\n }\n let authToken: string\n try {\n authToken = await readExistingAuthToken(client, machineId)\n } catch (err) {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} is running but its daemon token ` +\n `could not be read from ${ENV_FILE_PATH} (${err instanceof Error ? err.message : String(err)}) ` +\n \"— reconnect needs the token the boot that installed the daemon issued.\",\n )\n }\n // Re-arm the SAME runway a fresh boot gets (InstaBox restarts the life\n // countdown from now), like e2b's connect `setTimeout` re-arm.\n await client.patchMachine(machineId, { timeoutSeconds: clampTimeoutSeconds(config.timeoutSeconds) })\n const provisioned = await provisionAndProbe(\n { client, machineId, config, env: opts.env, authToken },\n false,\n )\n const ports: Record<number, string> = {}\n for (const port of resolveExtraPorts(spec)) {\n ports[port] = (await client.publishPort(machineId, port)).url\n }\n return toBootedSandbox(client, machineId, provisioned.mcpUrl, authToken, config, ports)\n },\n\n /** Provider control-plane liveness: 404 means gone; any other answer (or\n * thrown error) stays verbatim so callers read \"check failed\", never\n * \"box died\". */\n async probe(sandboxId: string): Promise<SandboxProbeResult> {\n // probe() has no spec to carry a key: fall back to the factory config,\n // then the env var, and be loud when there is nothing to authenticate.\n const providerApiKey = baseConfig.apiKey ?? process.env.INSTABOX_API_KEY\n if (providerApiKey === undefined || providerApiKey === \"\") {\n throw new Error(\n \"@agentproto/sandbox-instabox: no InstaBox API key for probe — construct the \" +\n \"provider with createInstaboxSandboxProvider({ apiKey }) or set INSTABOX_API_KEY.\",\n )\n }\n const client = new InstaboxClient({ apiKey: providerApiKey, apiUrl: baseConfig.apiUrl })\n try {\n const machine = await client.getMachine(sandboxId)\n return { alive: true, ...(machine.state !== undefined ? { state: String(machine.state) } : {}) }\n } catch (err) {\n if (err instanceof InstaboxApiError && err.status === 404) return { alive: false }\n throw err\n }\n },\n }\n}\n\n/** Bare provider instance the catalog/registry wraps. */\nexport const instaboxSandboxProvider: SandboxProvider = createInstaboxSandboxProvider()\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/api.ts","../src/provider.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Tiny typed InstaBox API client (https://instabox.sh, API\n * https://api.instabox.sh) over injectable `fetch`. Shapes measured on a real\n * account on 2026-10-18:\n *\n * - auth: `X-API-Key: ibk_...` (NEVER logged and never echoed in an error).\n * - every lifecycle verb (`POST /v1/machines`, suspend/resume/stop/start,\n * ports, DELETE) returns 202 `{id:\"op_...\", machineId, state:\"queued\"}` and\n * is awaited via `GET /v1/operations/{id}?wait=25s` long-polling.\n * - errors: `{\"error\":{\"code\",\"message\",\"requestId\",\"retryable\",\"operationId\"}}`.\n * - a publish-port request is idempotent (201 first, 200 if already\n * published) and both creates get an idempotency header, but `exec` is NOT\n * retried on transport errors.\n */\n\n/** Machine states reported by `GET /v1/machines/{id}` right now. */\nexport type InstaboxMachineState = \"running\" | \"suspended\" | \"stopped\"\n\n/** The action a machine takes when its `timeoutSeconds` lifetime elapses. */\nexport type InstaboxOnTimeout = \"pause\" | \"kill\"\n\nexport interface InstaboxMachine {\n /** Canonical id, `m_...` (a GET still accepts the machine NAME for direct\n * lookups, but `files`, `wake` and `ports` need the canonical id). */\n id: string\n state: InstaboxMachineState | string\n desiredState?: string\n name?: string\n runtime?: { ready?: boolean }\n /** ISO timestamp of the current lifetime deadline (null when not Running). */\n timeoutAt?: string | null\n onTimeout?: InstaboxOnTimeout\n autoSuspendAfterSeconds?: number\n metadata?: Record<string, string>\n /** Pending operation id, or null when the answer is already final. */\n operationId?: string | null\n}\n\nexport type InstaboxOperationState =\n | \"queued\"\n | \"running\"\n | \"succeeded\"\n | \"failed\"\n | string\n\nexport interface InstaboxOperation {\n /** Operation id, `op_...`. */\n id: string\n machineId?: string\n state: InstaboxOperationState\n error?: unknown\n machine?: InstaboxMachine\n}\n\nexport interface InstaboxCreateMachineInput {\n name: string\n /** Template id. Default `universal` (Debian 13, git, gh, Node 22, Python,\n * Go, Rust, Docker; one fixed 4 vCPU / 8 GB / 20 GB shape). */\n templateId?: string\n /** Boot from a snapshot instead of a template. Wins over `templateId`. */\n snapshotId?: string\n timeoutSeconds: number\n onTimeout: InstaboxOnTimeout\n /** 0 is requested to disable auto-suspend; the live API ignores it (window\n * stays 1800s). 120..86400 arms it. */\n autoSuspendAfterSeconds: number\n metadata: Record<string, string>\n /** ALWAYS false: a vault would write the caller's secrets into a box that\n * runs agent code. */\n vault: false\n guestUser?: string\n desiredState?: string\n}\n\nexport interface InstaboxExecInput {\n cmd: string\n cwd?: string\n envs?: Record<string, string>\n /** Feeds the command's stdin. Max 1 MiB. */\n stdin?: string\n /** 1..600, default 60 (seconds). */\n timeoutSeconds?: number\n}\n\nexport interface InstaboxExecResult {\n stdout: string\n stderr: string\n exitCode: number\n /** True when the exec hit its `timeoutSeconds` (the API still answers 200\n * with exitCode 124). */\n timedOut: boolean\n /** True when output was clipped by the API's 1 MiB stdout/stderr cap. */\n truncated: boolean\n}\n\nexport interface InstaboxPort {\n id: string\n port: number\n /** `https://{port}-{machineIdWithoutM_}.instabox.tech`: stable per\n * (machine, port), PUBLIC with no InstaBox-side authentication. */\n url: string\n expiresAt?: string | null\n}\n\nexport interface InstaboxUsage {\n limits?: { maxMachines?: number }\n [k: string]: unknown\n}\n\n/** A typed failure from the InstaBox API. The API key is never part of\n * `message` (transport errors and JSON error bodies carry no credential). */\nexport class InstaboxApiError extends Error {\n readonly status: number | null\n readonly code: string\n readonly requestId?: string\n readonly retryable?: boolean\n readonly operationId?: string\n\n constructor(\n message: string,\n info: {\n status: number | null\n code: string\n requestId?: string\n retryable?: boolean\n operationId?: string\n },\n ) {\n super(message)\n this.name = \"InstaboxApiError\"\n this.status = info.status\n this.code = info.code\n this.requestId = info.requestId\n this.retryable = info.retryable\n this.operationId = info.operationId\n }\n}\n\nexport interface InstaboxClientOpts {\n /** API key (`ibk_...`). Sent only as the `X-API-Key` request header. */\n apiKey: string\n /** Default `https://api.instabox.sh`. */\n apiUrl?: string\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch\n /** Delay between a failed transport attempt and the retry, ms (backoff\n * branches on it). */\n retryDelayMs?: (attempt: number) => Promise<void>\n}\n\nconst DEFAULT_API_URL = \"https://api.instabox.sh\"\n/** Per-request fetch timeout for control-plane calls (operations long-poll on\n * the server at `wait=25s`, so this must exceed that). */\nconst REQUEST_TIMEOUT_MS = 30_000\n/** Long-poll window sent to the operations endpoint. */\nconst OPERATION_WAIT = \"25s\"\n/** Max HTTP wait the client lets itself spend on ONE exec call: the exec can\n * take up to 600s inside the box. A transport error is mapped, not retried\n * (a retry could double-run a mutating command). */\nconst EXEC_HTTP_TIMEOUT_MS = 620_000\n/** Overall cap on waiting for ONE operation to settle. */\nconst OPERATION_TIMEOUT_MS = 300_000\n/** Base delay for transport-error backoff on the operation poll. */\nconst OPERATION_RETRY_BASE_DELAY_MS = 500\n/** Max attempts of the create-retry loop under transport errors. */\nconst CREATE_RETRY_ATTEMPTS = 5\n\ninterface InstaboxErrorBody {\n error?: {\n code?: unknown\n message?: unknown\n requestId?: unknown\n retryable?: unknown\n operationId?: unknown\n }\n [k: string]: unknown\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined\n}\n\n/** True by rules measured in the official CLI: HTTP 402/403/429, or a code or\n * message mentioning \"quota\" or \"limit\", means this ACCOUNT is out of room\n * (the limit is 5 machines, suspended and stopped ones included). */\nexport function isInstaboxQuotaFailure(\n status: number | null,\n code: string,\n message: string,\n): boolean {\n if (status === 402 || status === 403 || status === 429) return true\n return /quota|limit/i.test(code) || /quota|limit/i.test(message)\n}\n\n/**\n * Typed InstaBox client. Transport errors on ONE-SHOT local calls are mapped\n * to an `InstaboxApiError` with `code: \"transport_error\"`; only the\n * operation-waiter retries (with backoff). `exec` is never auto-retried: a\n * retry could run a mutating command twice.\n */\nexport class InstaboxClient {\n private readonly apiKey: string\n private readonly apiUrl: string\n private readonly fetchImpl: typeof fetch\n private readonly retryDelayMs: (attempt: number) => Promise<void>\n\n constructor(opts: InstaboxClientOpts) {\n this.apiKey = opts.apiKey\n this.apiUrl = (opts.apiUrl ?? DEFAULT_API_URL).replace(/\\/$/, \"\")\n this.fetchImpl = opts.fetchImpl ?? globalThis.fetch\n this.retryDelayMs =\n opts.retryDelayMs ??\n (attempt => new Promise(resolve => setTimeout(resolve, OPERATION_RETRY_BASE_DELAY_MS * attempt)))\n }\n\n private async request<T>(\n method: string,\n path: string,\n init: {\n body?: unknown\n idempotency?: string\n serviceTimeoutMs?: number\n } = {},\n ): Promise<T> {\n let res: Response\n try {\n res = await this.fetchImpl(`${this.apiUrl}${path}`, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n ...(init.idempotency ? { \"Idempotency-Key\": init.idempotency } : {}),\n },\n ...(init.body !== undefined ? { body: JSON.stringify(init.body) } : {}),\n signal: AbortSignal.timeout(init.serviceTimeoutMs ?? REQUEST_TIMEOUT_MS),\n })\n } catch (err) {\n throw new InstaboxApiError(`instabox: transport failure calling ${method} ${path}`, {\n status: null,\n code: \"transport_error\",\n retryable: true,\n })\n }\n if (!res.ok) {\n const text = await res.text().catch(() => \"\")\n const body: InstaboxErrorBody = safeParse(text)\n const code = asString(body.error?.code) ?? \"http_error\"\n const message = asString(body.error?.message) ?? `${method} ${path} failed with HTTP ${res.status}`\n throw new InstaboxApiError(`instabox: ${message}`, {\n status: res.status,\n code,\n requestId: asString(body.error?.requestId),\n retryable: body.error?.retryable === true || res.status === 429 || res.status >= 500,\n operationId: asString(body.error?.operationId),\n })\n }\n const raw = (await res.json()) as T\n return raw\n }\n\n /** POST /v1/machines. Retried on TRANSPORT errors only (idempotency key is\n * fixed per instance call, so a retry after a lost response cannot mint a\n * duplicate machine). Applied to the network-safe envelope, then the 202\n * body is returned. */\n async createMachine(input: InstaboxCreateMachineInput, idempotencyKey: string): Promise<InstaboxOperation> {\n return requestWithTransportRetry(\n () => this.request<InstaboxOperation>(\"POST\", \"/v1/machines\", { body: input, idempotency: idempotencyKey }),\n CREATE_RETRY_ATTEMPTS,\n )\n }\n\n /** GET /v1/operations/{id}?wait=25s, with an overall timeout and retryable\n * transport-error backoff. */\n async waitForOperation(operationId: string, timeoutMs = OPERATION_TIMEOUT_MS): Promise<InstaboxOperation> {\n const deadline = Date.now() + timeoutMs\n for (let attempt = 1; ; attempt++) {\n let op: InstaboxOperation | null = null\n let transportError = false\n try {\n op = await this.request<InstaboxOperation>(\n \"GET\",\n `/v1/operations/${encodeURIComponent(operationId)}?wait=${OPERATION_WAIT}`,\n )\n } catch (err) {\n if (!isTransportError(err)) throw err\n transportError = true\n }\n if (op !== null) {\n if (op.state === \"succeeded\") return op\n if (op.state === \"failed\") {\n throw new InstaboxApiError(describeOperationError(op), {\n status: null,\n code: \"operation_failed\",\n operationId,\n })\n }\n }\n if (Date.now() >= deadline) {\n throw new InstaboxApiError(\n `instabox: operation ${operationId} did not settle within ${timeoutMs}ms.`,\n { status: null, code: \"operation_timeout\", operationId },\n )\n }\n if (transportError) await this.retryDelayMs(attempt)\n }\n }\n\n /** GET /v1/machines/{id} (accepts id or name; ports/wake/files need `id`). */\n getMachine(idOrName: string): Promise<InstaboxMachine> {\n return this.request<InstaboxMachine>(\"GET\", `/v1/machines/${encodeURIComponent(idOrName)}`)\n }\n\n /** GET /v1/machines?metadata=k:v&...&limit=N. */\n async listMachines(metadata: Record<string, string>, limit?: number): Promise<InstaboxMachine[]> {\n const qs = new URLSearchParams()\n for (const [k, v] of Object.entries(metadata)) qs.append(\"metadata\", `${k}:${v}`)\n if (limit !== undefined) qs.set(\"limit\", String(limit))\n const suffix = qs.size > 0 ? `?${qs.toString()}` : \"\"\n const raw: unknown = await this.request<unknown>(\"GET\", `/v1/machines${suffix}`)\n if (Array.isArray(raw)) return raw as InstaboxMachine[]\n const wrapped = raw as { machines?: unknown }\n if (Array.isArray(wrapped.machines)) return wrapped.machines as InstaboxMachine[]\n return []\n }\n\n /** GET /v1/usage (limits.maxMachines). */\n readUsage(): Promise<InstaboxUsage> {\n return this.request<InstaboxUsage>(\"GET\", \"/v1/usage\")\n }\n\n /** PATCH /v1/machines/{id}. Answers 200 with the updated MACHINE (measured\n * live: `operationId` is null, there is no operation to wait on), so the\n * machine's own `id` must never be handed to `waitForOperation`. A pending\n * `operationId` is still awaited if the API ever returns one. */\n async patchMachine(\n id: string,\n patch: { timeoutSeconds?: number; onTimeout?: InstaboxOnTimeout } | { autoSuspendAfterSeconds: number },\n idempotencyKey?: string,\n ): Promise<InstaboxMachine> {\n const machine = await this.request<InstaboxMachine>(\"PATCH\", `/v1/machines/${encodeURIComponent(id)}`, {\n body: patch,\n idempotency: idempotencyKey ?? crypto.randomUUID(),\n })\n if (typeof machine.operationId === \"string\" && machine.operationId.length > 0) {\n await this.waitForOperation(machine.operationId)\n }\n return machine\n }\n\n /** DELETE /v1/machines/{id}. The API rejects a DELETE without an\n * `Idempotency-Key` (HTTP 400), so one is always sent. */\n deleteMachine(id: string): Promise<InstaboxOperation> {\n return this.request<InstaboxOperation>(\"DELETE\", `/v1/machines/${encodeURIComponent(id)}`, {\n idempotency: crypto.randomUUID(),\n })\n }\n\n /** POST /v1/machines/{id}/ports {port}. 201 first, 200 if already published\n * (both answer the same body). */\n async publishPort(id: string, port: number): Promise<InstaboxPort> {\n return await this.request<InstaboxPort>(\"POST\", `/v1/machines/${encodeURIComponent(id)}/ports`, {\n body: { port },\n idempotency: crypto.randomUUID(),\n })\n }\n\n /** DELETE /v1/machines/{id}/ports/{port}. */\n deletePort(id: string, port: number): Promise<void> {\n return this.request<void>(\"DELETE\", `/v1/machines/${encodeURIComponent(id)}/ports/${port}`)\n }\n\n /** POST /v1/machines/{id}/{verb} for suspend|resume|stop|start. */\n machineAction(id: string, verb: \"suspend\" | \"resume\" | \"stop\" | \"start\"): Promise<InstaboxOperation> {\n return this.request<InstaboxOperation>(\n \"POST\",\n `/v1/machines/${encodeURIComponent(id)}/${verb}`,\n { idempotency: crypto.randomUUID() },\n )\n }\n\n /** POST /v1/machines/{id}/wake: 200 DIRECT (no operation to wait on). */\n wake(id: string): Promise<unknown> {\n return this.request<unknown>(\n \"POST\",\n `/v1/machines/${encodeURIComponent(id)}/wake`,\n { idempotency: crypto.randomUUID() },\n )\n }\n\n /** POST /v1/machines/{id}/exec. NEVER retried and NEVER idempotent: a\n * retry could double-run a mutating command. */\n exec(id: string, input: InstaboxExecInput): Promise<InstaboxExecResult> {\n return this.request<InstaboxExecResult>(\n \"POST\",\n `/v1/machines/${encodeURIComponent(id)}/exec`,\n { body: input, serviceTimeoutMs: EXEC_HTTP_TIMEOUT_MS },\n )\n }\n}\n\nfunction describeOperationError(op: InstaboxOperation): string {\n const detail = op.error\n if (typeof detail === \"string\" && detail.length > 0) return `instabox: operation ${op.id} failed: ${detail}`\n if (detail !== null && typeof detail === \"object\") {\n const code = asString((detail as Record<string, unknown>).code)\n const message = asString((detail as Record<string, unknown>).message)\n return `instabox: operation ${op.id} failed${code ? ` (${code})` : \"\"}${message ? `: ${message}` : \"\"}`\n }\n return `instabox: operation ${op.id} failed.`\n}\n\nfunction safeParse(text: string): InstaboxErrorBody {\n try {\n const parsed: unknown = JSON.parse(text)\n if (parsed !== null && typeof parsed === \"object\") return parsed as InstaboxErrorBody\n } catch {\n // not JSON — fall through to an empty body\n }\n return {}\n}\n\n/** Transport errors (never an HTTP status answer) and 5xx. */\nexport function isTransientInstaboxError(err: unknown): boolean {\n if (!(err instanceof InstaboxApiError)) {\n // Unknown non-API errors (fetch rejections already wrapped above) are not\n // retried by generic call sites.\n return false\n }\n return err.code === \"transport_error\" || (err.status !== null && err.status >= 500)\n}\n\nfunction isTransportError(err: unknown): boolean {\n return err instanceof InstaboxApiError && err.code === \"transport_error\"\n}\n\nasync function requestWithTransportRetry<T>(fn: () => Promise<T>, attempts: number): Promise<T> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await fn()\n } catch (err) {\n if (attempt >= attempts || !isTransportError(err)) throw err\n await new Promise(resolve => setTimeout(resolve, OPERATION_RETRY_BASE_DELAY_MS * attempt))\n }\n }\n}\n\n\n","/**\n * InstaBox `SandboxProvider` (https://instabox.sh, API\n * https://api.instabox.sh) for @agentproto/sandbox — boots an InstaBox VM,\n * publishes the agentproto daemon behind the account's public edge, and hands\n * its `/mcp` endpoint to `createSandboxAgentSessionHost` the same way\n * `@agentproto/sandbox-box` (ascii.dev Box) does.\n *\n * Shape notes measured live on 2026-10-18 (see `api.ts` for the API itself):\n *\n * - Synchronous `exec` API (`POST /machines/{id}/exec`): a non-zero exit is a\n * normal 200 RESULT (not an error); a command that runs past its\n * `timeoutSeconds` answers with `exitCode: 124, timedOut: true`; each\n * stream is capped at 1 MiB (`truncated: true`). There is NO upload route\n * (PUT/POST on `/files` 404), so `writeFile`/`readFile` go through `exec`:\n * write = `mkdir -p` + base64 on STDIN to `base64 -d > file` in chunks of at\n * most 700 KB; read = `dd` slice + `base64 -w0` in chunks small enough that\n * each stdout stays under the API's 1 MiB capture cap.\n * - A published port's edge (`https://{port}-{machineIdWithoutM_}.instabox.tech`,\n * stable per machine+port) is PUBLIC with NO InstaBox-side authentication,\n * so the daemon MUST be started with an auth token: the unit's ExecStart\n * carries `--auth-token`, whose value is ONLY substituted by systemd from\n * the EnvironmentFile (`AGENTPROTO_AUTH_TOKEN`), so the token never lands in\n * an exec command's argv; secrets ride the heredoc body (exec stdin) into a\n * root-owned 0600 EnvironmentFile.\n * - Backgrounded in-VM processes MUST redirect their stdio: a bare `cmd &`\n * keeps the synchronous exec open until its timeout. The provider never\n * backgrounds anything itself: the daemon runs as a systemd unit\n * (`Restart=always`), which survives `kill -9`, suspend/resume and\n * auto-suspend (proven live).\n * - A MANUALLY suspended machine does NOT wake on its own: its public URL\n * 503s, its exec and `wake` answer 409. This provider therefore NEVER sends\n * the suspend verb and deliberately does NOT implement `pause()` (omitting\n * it lets callers fall back to `stop()`, which deletes the box). Instead it\n * requests `autoSuspendAfterSeconds` 0 by default (configurable), but the\n * live API ignores 0 (the window stays 1800s) and a PATCH of it is a no-op:\n * do not rely on it. Auto-suspended machines DO wake on a public request,\n * on `wake` and on `exec`, and `connect` revives a manually suspended one\n * through `resume` (proven live: process memory survives).\n */\n\nimport { randomBytes } from \"node:crypto\"\nimport type {\n BootedSandbox,\n SandboxBootOpts,\n SandboxExecOpts,\n SandboxExecResult,\n SandboxProbeResult,\n SandboxProvider,\n SandboxSpec,\n} from \"@agentproto/sandbox\"\nimport { SandboxBoxGoneError, SandboxQuotaError, scrubCommandFromMessage } from \"@agentproto/sandbox\"\nimport {\n InstaboxApiError,\n InstaboxClient,\n isInstaboxQuotaFailure,\n type InstaboxExecResult as InstaboxExecResultApi,\n type InstaboxMachine,\n} from \"./api.js\"\n\n/** `serve.ts`'s default port (`DEFAULT_MCP_URL` in `@agentproto/session-presets`). */\nconst DEFAULT_PORT = 18790\n/** InstaBox's Debian 13 image boots with user home under /data (`HOME` is\n * `/data/home`; `/data` itself is root-owned, so the daemon workspace is\n * written under HOME). */\nconst DEFAULT_WORKSPACE = \"/data/home\"\n/** Default template: `universal` (Debian 13, git, gh, Node 22, Python, Go,\n * Rust, Docker, Claude Code, Codex; one fixed 4 vCPU / 8 GB / 20 GB shape,\n * passwordless sudo). */\nconst DEFAULT_TEMPLATE = \"universal\"\n/**\n * Default box lifetime, seconds. InstaBox restarts the countdown from NOW on\n * every PATCH `timeoutSeconds` (`extendTimeout`), the same re-arm contract as\n * e2b's `setTimeout` (see `@agentproto/sandbox-e2b`'s DEFAULT_SANDBOX_TIMEOUT_MS\n * for why a 1h default is survivable only with re-arms).\n */\nconst DEFAULT_TIMEOUT_SECONDS = 3600\n/** Clamp range for machine `timeoutSeconds` (create and extend re-arms). */\nconst MIN_TIMEOUT_SECONDS = 60\nconst MAX_TIMEOUT_SECONDS = 86400\n/** Default auto-suspend request: 0 means \"disabled\", which the live API\n * ignores (the window stays 1800s); kept so an account that honours it does. */\nconst DEFAULT_AUTO_SUSPEND_AFTER_SECONDS = 0\nconst HEALTH_PROBE_TIMEOUT_MS = 5_000\n/** Pre-install probe window (the daemon can only be there by luck; keep the\n * \"already up?\" check short so a fresh boot does not stall on it). */\nconst ALREADY_UP_PROBE_TIMEOUT_MS = 2_000\nconst POLL_INTERVAL_MS = 500\n/** Overall wait for a fresh/starting machine to reach `runtime.ready`. */\nconst READY_TIMEOUT_MS = 120_000\n/** Overall wait for the freshly-started daemon to answer /health. The\n * InstaBox edge 502s a connection with no bytes for 20s, so the probe\n * cadence stays well under that. */\nconst DAEMON_READY_TIMEOUT_MS = 60_000\n/** Per-command exec clamp range (seconds), measured API contract 1..600. */\nconst EXEC_MAX_TIMEOUT_SECONDS = 600\n/** Default per-call exec timeout when the caller gives none: the API's own\n * 60s default is the same mid-work-kill trap e2b's 5-minute box default\n * was (a busy `pnpm test` legitimately runs past a minute). */\nconst EXEC_DEFAULT_TIMEOUT_SECONDS = 600\n/** Default exec timeout (seconds) for the boot `npm i -g @agentproto/cli`. */\nconst DEFAULT_UPDATE_CLI_TIMEOUT_SECONDS = 600\n/** Chunk size for file transfer through exec: 700 KB stays under the API's\n * 1 MiB stdin and stdout caps after base64 inflation (700 KB -> ~933 KB). */\nconst FILE_CHUNK_BYTES = 700 * 1024\n/** B64 chars of one max chunk (4/3 rounding up to a multiple of 4, so every\n * slice boundary decodes AND a shorter answer means EOF was reached). */\nconst FILE_CHUNK_B64_CHARS = Math.ceil(FILE_CHUNK_BYTES / 3) * 4\n/** Length (bytes) of the generated daemon bearer token. */\nconst AUTH_TOKEN_BYTES = 32\nconst PROVIDER_SLUG = \"instabox\"\n\nconst ENV_FILE_DIR = \"/etc/agentproto\"\nexport const ENV_FILE_PATH = `${ENV_FILE_DIR}/agentproto.env`\nexport const SYSTEMD_UNIT_PATH = \"/etc/systemd/system/agentproto.service\"\n/** Unit name of the systemd service wrapping the daemon. */\nexport const DAEMON_UNIT_NAME = \"agentproto\"\n/** Env var the EnvironmentFile sets for the unit's `--auth-token` value. */\nexport const AUTH_TOKEN_ENV_VAR = \"AGENTPROTO_AUTH_TOKEN\"\n/** Machine metadata stamp: which machines this provider owns (`agentproto: \"1\"`). */\nexport const AGENTPROTO_METADATA_KEY = \"agentproto\"\nconst AGENTPROTO_METADATA_VALUE = \"1\"\n\n/** Suffix that MANDATORY redirection takes on any in-box background\n * invocation (a background `cmd &` without it keeps the synchronous exec\n * open until its timeout). Exported so tests can assert every provider-built\n * command that backgrounds something carries it. */\nexport const BACKGROUND_REDIRECT = \">/dev/null 2>&1 </dev/null\"\n\nexport interface InstaboxSandboxSpecConfig {\n /** InstaBox API key (`ibk_...`). Falls back to `INSTABOX_API_KEY` in the\n * host process env. Sent only as the `X-API-Key` header (never logged,\n * never part of an error message). */\n apiKey?: string\n /** Default `https://api.instabox.sh`. */\n apiUrl?: string\n /** Template id. Default `universal`. (A `snapshotId` would win on the API,\n * but this provider always boots from a template.) */\n template?: string\n /** Machine lifetime in seconds, re-armed from now on every extend.\n * Default 3600, clamp 60..86400. */\n timeoutSeconds?: number\n /** This provider only ever sends `kill`: `pause` would leave a manually\n * suspended box stranded (it does not wake on its own). */\n onTimeout?: \"kill\"\n /** 0 disables auto-suspend (default); 120..86400 arms it. */\n autoSuspendAfterSeconds?: number\n /** Port the agentproto daemon listens on inside the box. Default 18790. */\n port?: number\n /** `--workspace` passed to `agentproto serve`. Default `/data/home`. */\n workspace?: string\n /** CLI version pinned on boot, instead of a floating `@latest`.\n * Produces `@agentproto/cli@<version>`. */\n cliVersion?: string\n /** Run `npm i -g @agentproto/cli@...` before installing the systemd unit.\n * Default true. Skipped when the health probe finds the daemon already up. */\n updateCliOnBoot?: boolean\n /** Extra npm package specs installed globally ALONGSIDE the CLI update\n * (one `npm i -g`). Ignored when `updateCliOnBoot` is false or the daemon\n * was already up. */\n installPackages?: string[]\n /** Timeout (seconds, exec-clamped 1..600) for the `npm i -g` update. */\n updateCliTimeoutSeconds?: number\n /** How long to wait for the machine itself to reach `runtime.ready`. */\n readyTimeoutMs?: number\n /** How long to wait for the daemon to become healthy after starting it. */\n daemonReadyTimeoutMs?: number\n /** Extra machine metadata written at create time (merged with the\n * provider's own `agentproto: \"1\"` stamp). */\n metadata?: Record<string, string>\n /** Extra shell commands host-executed after the boot update, before the\n * daemon starts. Runs on EVERY boot/connect; entries must be idempotent. */\n setupCommands?: string[]\n}\n\ninterface ResolvedConfig {\n apiKey: string\n apiUrl: string\n template: string\n timeoutSeconds: number\n autoSuspendAfterSeconds: number\n port: number\n workspace: string\n cliVersion: string\n updateCliOnBoot: boolean\n installPackages: string[]\n updateCliTimeoutSeconds: number\n readyTimeoutMs: number\n daemonReadyTimeoutMs: number\n metadata: Record<string, string>\n setupCommands: string[]\n}\n\nfunction readConfig(rawConfig: unknown): ResolvedConfig {\n const raw = (rawConfig ?? {}) as Record<string, unknown>\n const num = (field: unknown, fallback: number, min: number, max: number): number => {\n if (typeof field !== \"number\" || !Number.isFinite(field)) return fallback\n return Math.min(max, Math.max(min, Math.floor(field)))\n }\n const str = (field: unknown): string | undefined =>\n typeof field === \"string\" && field.length > 0 ? field : undefined\n const metadata =\n typeof raw.metadata === \"object\" && raw.metadata !== null\n ? Object.fromEntries(\n Object.entries(raw.metadata as Record<string, unknown>).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n ),\n )\n : {}\n return {\n apiKey: str(raw.apiKey) ?? process.env.INSTABOX_API_KEY ?? \"\",\n apiUrl: str(raw.apiUrl) ?? \"https://api.instabox.sh\",\n template: str(raw.template) ?? DEFAULT_TEMPLATE,\n timeoutSeconds: num(raw.timeoutSeconds, DEFAULT_TIMEOUT_SECONDS, MIN_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS),\n autoSuspendAfterSeconds:\n typeof raw.autoSuspendAfterSeconds === \"number\" && Number.isFinite(raw.autoSuspendAfterSeconds)\n ? Math.min(86400, Math.max(0, Math.floor(raw.autoSuspendAfterSeconds)))\n : DEFAULT_AUTO_SUSPEND_AFTER_SECONDS,\n port: num(raw.port, DEFAULT_PORT, 1, 65_535),\n workspace: str(raw.workspace) ?? DEFAULT_WORKSPACE,\n cliVersion: str(raw.cliVersion) ?? \"latest\",\n updateCliOnBoot: typeof raw.updateCliOnBoot === \"boolean\" ? raw.updateCliOnBoot : true,\n installPackages: Array.isArray(raw.installPackages)\n ? raw.installPackages.filter((p): p is string => typeof p === \"string\" && p.length > 0)\n : [],\n updateCliTimeoutSeconds: num(\n raw.updateCliTimeoutSeconds,\n DEFAULT_UPDATE_CLI_TIMEOUT_SECONDS,\n 1,\n EXEC_MAX_TIMEOUT_SECONDS,\n ),\n readyTimeoutMs: num(raw.readyTimeoutMs, READY_TIMEOUT_MS, 1_000, 600_000),\n daemonReadyTimeoutMs: num(raw.daemonReadyTimeoutMs, DAEMON_READY_TIMEOUT_MS, 1_000, 600_000),\n metadata,\n setupCommands: Array.isArray(raw.setupCommands)\n ? raw.setupCommands.filter((c): c is string => typeof c === \"string\" && c.length > 0)\n : [],\n }\n}\n\n/** The EnvironmentFile body: resolved secrets from `opts.env` PLUS the token\n * gating the public edge. Never rendered into a command line. */\nexport function environmentFileContents(env: Record<string, string>, authToken: string): string {\n const lines = [\n ...Object.entries(env).map(([key, value]) => `${key}=${value}`),\n `${AUTH_TOKEN_ENV_VAR}=${authToken}`,\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n\n/**\n * One shell command that writes the daemon's EnvironmentFile (root, 0600)\n * and its systemd unit, BOTH through heredocs. No secret is ever part of an\n * argv token: the env content sits inside the heredoc body (which the exec\n * API turns into `sudo tee`'s stdin), and the unit's ExecStart references the\n * token as `${AGENTPROTO_AUTH_TOKEN}`, substituted by systemd from the\n * EnvironmentFile. Heredoc terminators must sit on their own lines (the same\n * live-tested lesson as `@agentproto/sandbox-box`'s writeSystemdUnitCommand:\n * chaining \" && \" after a heredoc lands the next command INSIDE it and the\n * unit write silently no-ops at exit 0).\n */\nexport function writeDaemonUnitCommand(\n port: number,\n workspace: string,\n env: Record<string, string>,\n authToken: string,\n): { command: string; envFileContents: string; unitContents: string } {\n const envFileContents = environmentFileContents(env, authToken)\n const unit = [\n \"[Unit]\",\n \"Description=agentproto daemon\",\n \"After=network.target\",\n \"\",\n \"[Service]\",\n `EnvironmentFile=-${ENV_FILE_PATH}`,\n `ExecStart=agentproto serve --port ${port} --bind 0.0.0.0 --workspace \"${workspace}\" ` +\n `--auth-token \\${${AUTH_TOKEN_ENV_VAR}}`,\n \"Restart=always\",\n \"User=user\",\n \"\",\n \"[Install]\",\n \"WantedBy=multi-user.target\",\n ].join(\"\\n\")\n const command = [\n \"set -e\",\n `sudo mkdir -p ${ENV_FILE_DIR}`,\n `sudo tee ${ENV_FILE_PATH} > /dev/null <<'AGENTPROTO_ENV'\\n${envFileContents}AGENTPROTO_ENV`,\n `sudo chmod 600 ${ENV_FILE_PATH}`,\n `sudo tee ${SYSTEMD_UNIT_PATH} > /dev/null <<'AGENTPROTO_UNIT'\\n${unit}\\nAGENTPROTO_UNIT`,\n ].join(\"\\n\")\n return { command, envFileContents, unitContents: unit }\n}\n\n/** The global install command line (exported for tests: only package spec\n * names, never a secret). The box user is the unprivileged `user` and the\n * npm prefix is the root-owned /usr/local (measured live: a bare `npm i -g`\n * dies with EACCES), so it runs through `sudo`, keeping the caller's PATH\n * because `sudo`'s secure_path may not list node's directory. */\nexport function buildCliInstallCommand(cliVersion: string, extras: string[]): string {\n const extraText = extras.map(extra => ` '${extra.replace(/'/g, \"\")}'`).join(\"\")\n return `sudo env \"PATH=$PATH\" npm i -g \"@agentproto/cli@${cliVersion}\"${extraText}`\n}\n\n/**\n * Quota gate, run BEFORE creating anything: the account limit is 5 machines\n * and suspended/stopped ones count against it, so a pre-check (`GET /v1/usage`\n * + `GET /v1/machines`) catches the common case early and throws a typed\n * `SandboxQuotaError` a caller can fall back to another provider on. The\n * calls are best-effort: a usage API that does not answer must not break a\n * boot that the create call could still grant.\n */\nexport async function assertQuotaAvailable(client: InstaboxClient): Promise<void> {\n const [usage, machines] = await Promise.all([\n client.readUsage().catch(() => undefined),\n client.listMachines({}, 200).catch(() => undefined),\n ])\n const max = usage?.limits?.maxMachines\n if (typeof max === \"number\" && machines !== undefined && machines.length >= max) {\n throw new SandboxQuotaError(\n PROVIDER_SLUG,\n `instabox: account limit is ${max} machines and ${machines.length} already exist ` +\n \"(suspended and stopped machines count); stop one before booting another.\",\n )\n }\n}\n\n/** Re-map a create/lifecycle failure that is quota-shaped (HTTP 402/403/429,\n * or a code/message containing \"quota\" or \"limit\"; the string exists in the\n * official CLI but was never received live) to `SandboxQuotaError`, so a\n * caller falls back to a different provider instead of surfacing the noise. */\nexport function normalizeQuotaError(err: unknown): unknown {\n if (err instanceof InstaboxApiError && isInstaboxQuotaFailure(err.status, err.code, err.message)) {\n return new SandboxQuotaError(\n PROVIDER_SLUG,\n `instabox: account limit reached (HTTP ${err.status ?? \"?\"}, code \"${err.code}\"): ` +\n \"fall back to a different sandbox provider.\",\n err,\n )\n }\n return err\n}\n\nfunction bootMetadata(config: ResolvedConfig, spec: SandboxSpec): Record<string, string> {\n const sessionId = (spec as SandboxSpec & { id?: unknown }).id\n const metadata: Record<string, string> = { ...config.metadata }\n metadata[AGENTPROTO_METADATA_KEY] = AGENTPROTO_METADATA_VALUE\n if (typeof sessionId === \"string\" && sessionId.length > 0) {\n metadata.session = sessionId\n }\n return metadata\n}\n\n/** Poll the machine until `runtime.ready` (or the deadline). */\nasync function waitMachineReady(\n client: InstaboxClient,\n machineId: string,\n timeoutMs: number,\n): Promise<InstaboxMachine> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const machine = await client.getMachine(machineId)\n if (machine.runtime?.ready === true) return machine\n if (Date.now() >= deadline) {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} did not reach runtime.ready ` +\n `within ${timeoutMs}ms.`,\n )\n }\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS))\n }\n}\n\n/** Poll `<url>/health` until it answers OK, or false once the deadline\n * elapses. */\nasync function probeHealth(url: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(HEALTH_PROBE_TIMEOUT_MS) })\n if (res.ok) return true\n } catch {\n // not up yet (the InstaBox edge answers 502 while nothing listens)\n }\n if (Date.now() >= deadline) return false\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS))\n }\n}\n\ninterface PendingProvision {\n client: InstaboxClient\n machineId: string\n config: ResolvedConfig\n env: Record<string, string>\n authToken: string\n}\n\n/**\n * Shared tail of `boot` and `connect`: publish the daemon port, then probe\n * the daemon through the PUBLIC edge (/health unauthenticated; /mcp itself is\n * bearer-gated by `--auth-token`). Only when the probe stays red: update the\n * CLI, write the EnvironmentFile (0600) and the systemd unit (secrets in the\n * heredoc, token via env substitution), run the setup hooks, enable the unit,\n * and re-probe through the edge. `deleteOnFailure` (the FRESH boot path)\n * reaps the machine when the daemon never comes up, so a failed boot never\n * leaks a running, session-less box; connect leaves the machine alone.\n */\nasync function provisionAndProbe(\n state: PendingProvision,\n deleteOnFailure: boolean,\n): Promise<{ url: string; mcpUrl: string }> {\n const { client, machineId, config } = state\n const published = await client.publishPort(machineId, config.port)\n const publicUrl = published.url\n const healthUrl = `${publicUrl}/health`\n\n const alreadyUp = await probeHealth(healthUrl, ALREADY_UP_PROBE_TIMEOUT_MS)\n if (!alreadyUp) {\n if (config.updateCliOnBoot) {\n await execChecked(client, machineId, \"CLI install\", {\n cmd: buildCliInstallCommand(\n config.cliVersion,\n config.installPackages.map(extra => extra.replace(/'/g, \"\")),\n ),\n timeoutSeconds: config.updateCliTimeoutSeconds,\n })\n }\n await execChecked(client, machineId, \"workspace setup\", {\n cmd: `mkdir -p '${config.workspace}' && sudo mkdir -p ${ENV_FILE_DIR}`,\n })\n // stderr is NOT quoted here: the command carries the secrets heredoc.\n await execChecked(\n client,\n machineId,\n \"daemon unit install\",\n { cmd: writeDaemonUnitCommand(config.port, config.workspace, state.env, state.authToken).command },\n { quoteStderr: false },\n )\n for (const command of config.setupCommands) {\n await execChecked(client, machineId, \"setup command\", {\n cmd: command,\n timeoutSeconds: EXEC_MAX_TIMEOUT_SECONDS,\n })\n }\n await execChecked(client, machineId, \"daemon enable\", {\n cmd: `sudo systemctl daemon-reload && sudo systemctl enable --now ${DAEMON_UNIT_NAME} ${BACKGROUND_REDIRECT}`,\n })\n const ready = await probeHealth(healthUrl, config.daemonReadyTimeoutMs)\n if (!ready) {\n if (deleteOnFailure) await client.deleteMachine(machineId).catch(() => undefined)\n throw new Error(\n `@agentproto/sandbox-instabox: agentproto daemon did not become healthy at ${healthUrl} ` +\n `within ${config.daemonReadyTimeoutMs}ms (machine ${machineId}).`,\n )\n }\n }\n return { url: publicUrl, mcpUrl: `${publicUrl}/mcp` }\n}\n\n/** Run one exec for provisioning; a non-zero exit is a RESULT, a transport\n * failure throws with its message scrubbed (so the error never carries the\n * command body, let alone a secret). */\nasync function execScrubbed(\n client: InstaboxClient,\n machineId: string,\n input: { cmd: string; stdin?: string; timeoutSeconds?: number },\n): Promise<InstaboxExecResultApi> {\n try {\n return await client.exec(machineId, input)\n } catch (err) {\n if (err instanceof Error) {\n const scrubbed = scrubCommandFromMessage(err.message, input.cmd)\n if (scrubbed !== err.message) {\n const wrapped = new Error(scrubbed)\n wrapped.name = err.name\n throw wrapped\n }\n }\n throw err\n }\n}\n\n/** `execScrubbed` that also refuses a non-zero exit: a failed install must\n * surface as itself instead of as a daemon that \"never became healthy\" 60s\n * later. Only the exit code and the head of stderr are reported, never the\n * command (it can carry the env file heredoc). */\nasync function execChecked(\n client: InstaboxClient,\n machineId: string,\n what: string,\n input: { cmd: string; stdin?: string; timeoutSeconds?: number },\n opts: { quoteStderr?: boolean } = {},\n): Promise<InstaboxExecResultApi> {\n const result = await execScrubbed(client, machineId, input)\n if (result.exitCode !== 0) {\n const detail =\n opts.quoteStderr === false ? \"\" : scrubCommandFromMessage(result.stderr.trim(), input.cmd).slice(0, 300)\n throw new Error(\n `@agentproto/sandbox-instabox: ${what} failed on machine ${machineId} ` +\n `(exit ${result.exitCode}${result.timedOut ? \", timed out\" : \"\"}${detail ? `: ${detail}` : \"\"}).`,\n )\n }\n return result\n}\n\nfunction newInstanceName(): string {\n return `agentproto-${randomBytes(5).toString(\"hex\")}`\n}\n\nfunction newAuthToken(): string {\n return randomBytes(AUTH_TOKEN_BYTES).toString(\"hex\")\n}\n\nfunction machineIdOf(machine: InstaboxMachine): string {\n if (typeof machine.id !== \"string\" || machine.id.length === 0) {\n throw new Error(\"instabox: machine response carries no id\")\n }\n return machine.id\n}\n\n/** Clamp for machine `timeoutSeconds` (create and extend re-arms). */\nfunction clampTimeoutSeconds(seconds: number): number {\n return Math.min(MAX_TIMEOUT_SECONDS, Math.max(MIN_TIMEOUT_SECONDS, Math.floor(seconds)))\n}\n\n/** InstaBox execs clamp 1..600 seconds; an absent bound maps to the max (not\n * the API's own 60s default, see module docs). */\nfunction clampExecTimeoutSeconds(timeoutMs: number | undefined): number {\n const seconds = Math.floor((timeoutMs ?? EXEC_DEFAULT_TIMEOUT_SECONDS * 1000) / 1000)\n return Math.min(EXEC_MAX_TIMEOUT_SECONDS, Math.max(1, seconds))\n}\n\n/** Wrap a healthy machine into the `BootedSandbox` shape common to `boot` and\n * `connect`. Deliberately NO `pause()`: a manually suspended InstaBox machine\n * does not wake on its own, so callers must fall back to `stop()` (delete). */\nfunction toBootedSandbox(\n client: InstaboxClient,\n machineId: string,\n mcpUrl: string,\n authToken: string,\n config: ResolvedConfig,\n ports: Record<number, string>,\n): BootedSandbox {\n return {\n mcpUrl,\n sandboxId: machineId,\n ...(Object.keys(ports).length > 0 ? { ports } : {}),\n // The public edge is UNGATED at InstaBox: the daemon's own bearer (minted\n // here at unit install time and substituted from the 0600 EnvironmentFile)\n // is the only thing gating /mcp, so it is ALWAYS surfaced.\n token: authToken,\n authHeaders: { Authorization: `Bearer ${authToken}` },\n async stop(): Promise<void> {\n try {\n const op = await client.deleteMachine(machineId)\n await client.waitForOperation(op.id)\n } catch (err) {\n if (err instanceof InstaboxApiError && err.status === 404) return\n await client.deleteMachine(machineId).catch(() => undefined)\n throw err\n }\n },\n async exec(opts: SandboxExecOpts): Promise<SandboxExecResult> {\n const startedAt = Date.now()\n const result = await client.exec(machineId, {\n cmd: opts.command,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...(opts.env !== undefined ? { envs: opts.env } : {}),\n // InstaBox clamps exec 1..600s. An omitted bound maps to the max,\n // NOT the API's own 60s default (mid-work-kill trap, module docs).\n timeoutSeconds: clampExecTimeoutSeconds(opts.timeoutMs),\n })\n return {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n durationMs: Date.now() - startedAt,\n ...(result.truncated ? { truncated: result.truncated } : {}),\n }\n },\n async readFile(path: string): Promise<Uint8Array> {\n const chunks: Uint8Array[] = []\n for (let index = 0; ; index++) {\n // `dd ibs=<chunk> skip=<index> count=1` slices the file, `base64 -w0`\n // inlines it under the 1 MiB stdout cap (700 KB -> ~933 KB of b64).\n // A pipeline exits with base64's status, so `test -r` guards it: an\n // unreadable file must fail, not read back as empty.\n const result = await client.exec(machineId, {\n cmd: `test -r '${path}' && dd if='${path}' ibs=${FILE_CHUNK_BYTES} skip=${index} count=1 2>/dev/null | base64 -w0`,\n timeoutSeconds: EXEC_MAX_TIMEOUT_SECONDS,\n })\n const encoded = result.stdout.trim()\n if (index === 0 && result.exitCode !== 0 && encoded === \"\") {\n throw new Error(\n `instabox readFile: cannot read \"${path}\" (exit ${result.exitCode}, ` +\n `stderr: ${result.stderr.trim() || \"(none)\"})`,\n )\n }\n if (encoded.length === 0) break\n chunks.push(new Uint8Array(Buffer.from(encoded, \"base64\")))\n if (encoded.length < FILE_CHUNK_B64_CHARS) break\n }\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0)\n const out = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n },\n async writeFile(path: string, data: Uint8Array): Promise<void> {\n // Base64 the whole payload once, then stream `dd`-independent slices of\n // that b64 through exec STDIN (never an argv token). Slicing on\n // `FILE_CHUNK_B64_CHARS` (a multiple of 4) keeps every middle chunk\n // cleanly decodable; the trailing chunk keeps the base64 padding.\n const encoded = Buffer.from(data).toString(\"base64\")\n const directory = path.slice(0, Math.max(path.lastIndexOf(\"/\"), 0)) || \"/\"\n for (let offset = 0, index = 0; index === 0 || offset < encoded.length; offset += FILE_CHUNK_B64_CHARS, index++) {\n const slice = encoded.slice(offset, offset + FILE_CHUNK_B64_CHARS)\n await client.exec(machineId, {\n cmd:\n index === 0\n ? `mkdir -p '${directory}' && base64 -d > '${path}'`\n : `base64 -d >> '${path}'`,\n stdin: slice,\n timeoutSeconds: EXEC_MAX_TIMEOUT_SECONDS,\n })\n }\n },\n async expose(port: number): Promise<{ url: string }> {\n const published = await client.publishPort(machineId, port)\n return { url: published.url }\n },\n async extendTimeout(ms: number): Promise<void> {\n // PATCH timeoutSeconds restarts the countdown FROM NOW (the API's own\n // semantics), so `ms` simply maps to a clamped second count.\n const seconds = clampTimeoutSeconds(ms / 1000)\n await client.patchMachine(machineId, { timeoutSeconds: seconds })\n },\n lifetimeMs: config.timeoutSeconds * 1000,\n }\n}\n\n/**\n * Bring a machine back to running, STATE-AWARE (module docs): `running` is a\n * no-op; `suspended` first tries `wake` (the AUTO-suspend path: 200 direct)\n * then `resume` for a manually-suspended box; anything else (`stopped`) goes\n * through `start`. A verb the API refuses surfaces a clear error instead of a\n * silent wrong-state reconnect.\n */\nasync function reviveMachine(client: InstaboxClient, machineId: string, state: string): Promise<void> {\n if (state === \"running\") return\n if (state === \"suspended\") {\n try {\n await client.wake(machineId)\n return\n } catch (err) {\n // Only a CONFLICT means \"manually suspended, wake refuses\" (the API\n // answers 409 machine_not_running). Any other failure — a transport\n // error, a 5xx — must surface as itself rather than be misreported as\n // \"wake and resume both refused\".\n const conflict =\n err instanceof InstaboxApiError &&\n (err.status === 409 || err.code === \"machine_not_running\")\n if (!conflict) throw err\n }\n const resume = await client.machineAction(machineId, \"resume\").catch(err => {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} is suspended and refused both ` +\n `wake and resume (${err instanceof Error ? err.message : String(err)}).`,\n )\n })\n await client.waitForOperation(resume.id)\n return\n }\n const start = await client.machineAction(machineId, \"start\").catch(err => {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} is \"${state}\" and refused start ` +\n `(${err instanceof Error ? err.message : String(err)}).`,\n )\n })\n await client.waitForOperation(start.id)\n}\n\n/**\n * Re-derive the daemon bearer from the 0600 EnvironmentFile the boot that\n * installed this daemon wrote: connect never rewrites the env file while the\n * daemon is running, so the token it returns MUST match what is installed.\n */\nasync function readExistingAuthToken(client: InstaboxClient, machineId: string): Promise<string> {\n // Read ONLY the token line: `cat`-ing the whole EnvironmentFile would pull\n // every box secret (OPENROUTER_API_KEY, …) back into this host process for\n // no reason. `grep` keeps the sensitive values in the box.\n const result = await client.exec(machineId, {\n cmd: `sudo grep '^${AUTH_TOKEN_ENV_VAR}=' ${ENV_FILE_PATH} 2>/dev/null || true`,\n timeoutSeconds: 60,\n })\n const line = result.stdout\n .split(\"\\n\")\n .map(entry => entry.trim())\n .find(entry => entry.startsWith(`${AUTH_TOKEN_ENV_VAR}=`))\n const value = line?.slice(`${AUTH_TOKEN_ENV_VAR}=`.length)\n if (typeof value !== \"string\" || value.length === 0) {\n throw new Error(`instabox: ${AUTH_TOKEN_ENV_VAR} missing from the daemon env file`)\n }\n return value\n}\n\nfunction resolveExtraPorts(spec: SandboxSpec): number[] {\n const extras = (spec as SandboxSpec & { extraPorts?: unknown }).extraPorts\n if (!Array.isArray(extras)) return []\n return extras.filter((port): port is number => typeof port === \"number\" && Number.isInteger(port))\n}\n\n/**\n * `createInstaboxSandboxProvider(config)` — an AIP-36 `SandboxProvider`\n * factory. `config` seeds every boot/connect's spec.config (a per-spec value\n * wins per field). The bare `instaboxSandboxProvider` export (what the\n * registry wraps) seeds nothing: credentials come from spec.config or the\n * `INSTABOX_API_KEY` env var.\n */\nexport function createInstaboxSandboxProvider(baseConfig: InstaboxSandboxSpecConfig = {}): SandboxProvider {\n function resolveConfig(spec: SandboxSpec): ResolvedConfig {\n const raw = (spec.config ?? {}) as Record<string, unknown>\n const merged: Record<string, unknown> = { ...baseConfig, ...raw }\n if (baseConfig.metadata !== undefined && raw.metadata !== undefined) {\n merged.metadata = {\n ...baseConfig.metadata,\n ...(typeof raw.metadata === \"object\" && raw.metadata !== null\n ? (raw.metadata as Record<string, string>)\n : {}),\n }\n }\n return readConfig(merged)\n }\n\n function assertApiKey(config: ResolvedConfig): void {\n if (config.apiKey === \"\") {\n throw new Error(\n \"@agentproto/sandbox-instabox: no InstaBox API key — set spec.config.apiKey \" +\n \"or the INSTABOX_API_KEY environment variable.\",\n )\n }\n }\n\n return {\n async boot(spec: SandboxSpec, opts: SandboxBootOpts): Promise<BootedSandbox> {\n const config = resolveConfig(spec)\n assertApiKey(config)\n const client = new InstaboxClient({ apiKey: config.apiKey, apiUrl: config.apiUrl })\n const authToken = newAuthToken()\n await assertQuotaAvailable(client)\n const created = await client\n .createMachine(\n {\n name: newInstanceName(),\n templateId: config.template,\n timeoutSeconds: config.timeoutSeconds,\n onTimeout: \"kill\",\n autoSuspendAfterSeconds: config.autoSuspendAfterSeconds,\n metadata: bootMetadata(config, spec),\n // ALWAYS sent and ALWAYS false: a vault would write the caller's\n // secrets into a box that runs agent code.\n vault: false,\n },\n crypto.randomUUID(),\n )\n .catch(err => {\n throw normalizeQuotaError(err)\n })\n try {\n await client.waitForOperation(created.id)\n const machineId = created.machineId ?? created.machine?.id\n if (machineId === undefined) {\n throw new Error(\n `@agentproto/sandbox-instabox: create operation ${created.id} settled with no machine id.`,\n )\n }\n await waitMachineReady(client, machineId, config.readyTimeoutMs)\n const extraPorts = resolveExtraPorts(spec)\n const provisioned = await provisionAndProbe(\n { client, machineId, config, env: opts.env, authToken },\n true,\n )\n const ports: Record<number, string> = {}\n for (const port of extraPorts) {\n ports[port] = (await client.publishPort(machineId, port)).url\n }\n return toBootedSandbox(client, machineId, provisioned.mcpUrl, authToken, config, ports)\n } catch (err) {\n // Every failure past the create must reclaim the machine, so a failed\n // create operation or a long provisioning failure never leaves a\n // running, session-less box behind.\n const machineId = created.machineId ?? created.machine?.id\n if (machineId !== undefined) await client.deleteMachine(machineId).catch(() => undefined)\n throw normalizeQuotaError(err)\n }\n },\n\n /** Reconnect to an existing box, state-aware (see `reviveMachine`).\n * State mapping: `running` = ok, auto-`suspended` = `wake`, manually\n * `suspended` or `stopped` = `resume`/`start` as the API allows, else a\n * clear error. A deleted machine surfaces as `SandboxBoxGoneError`. */\n async connect(sandboxId: string, spec: SandboxSpec, opts: SandboxBootOpts): Promise<BootedSandbox> {\n const config = resolveConfig(spec)\n assertApiKey(config)\n const client = new InstaboxClient({ apiKey: config.apiKey, apiUrl: config.apiUrl })\n let machine: InstaboxMachine\n try {\n machine = await client.getMachine(sandboxId)\n } catch (err) {\n if (err instanceof InstaboxApiError && err.status === 404) {\n throw new SandboxBoxGoneError(sandboxId, err)\n }\n throw err\n }\n const machineId = machineIdOf(machine)\n await reviveMachine(client, machineId, machine.state)\n await waitMachineReady(client, machineId, config.readyTimeoutMs)\n if (machine.state !== \"running\" && (await client.getMachine(machineId)).state !== \"running\") {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} did not reach \"running\" — cannot reconnect.`,\n )\n }\n let authToken: string\n try {\n authToken = await readExistingAuthToken(client, machineId)\n } catch (err) {\n throw new Error(\n `@agentproto/sandbox-instabox: machine ${machineId} is running but its daemon token ` +\n `could not be read from ${ENV_FILE_PATH} (${err instanceof Error ? err.message : String(err)}) ` +\n \"— reconnect needs the token the boot that installed the daemon issued.\",\n )\n }\n // Re-arm the SAME runway a fresh boot gets (InstaBox restarts the life\n // countdown from now), like e2b's connect `setTimeout` re-arm.\n await client.patchMachine(machineId, { timeoutSeconds: clampTimeoutSeconds(config.timeoutSeconds) })\n const provisioned = await provisionAndProbe(\n { client, machineId, config, env: opts.env, authToken },\n false,\n )\n const ports: Record<number, string> = {}\n for (const port of resolveExtraPorts(spec)) {\n ports[port] = (await client.publishPort(machineId, port)).url\n }\n return toBootedSandbox(client, machineId, provisioned.mcpUrl, authToken, config, ports)\n },\n\n /** Provider control-plane liveness: 404 means gone; any other answer (or\n * thrown error) stays verbatim so callers read \"check failed\", never\n * \"box died\". */\n async probe(sandboxId: string): Promise<SandboxProbeResult> {\n // probe() has no spec to carry a key: fall back to the factory config,\n // then the env var, and be loud when there is nothing to authenticate.\n const providerApiKey = baseConfig.apiKey ?? process.env.INSTABOX_API_KEY\n if (providerApiKey === undefined || providerApiKey === \"\") {\n throw new Error(\n \"@agentproto/sandbox-instabox: no InstaBox API key for probe — construct the \" +\n \"provider with createInstaboxSandboxProvider({ apiKey }) or set INSTABOX_API_KEY.\",\n )\n }\n const client = new InstaboxClient({ apiKey: providerApiKey, apiUrl: baseConfig.apiUrl })\n try {\n const machine = await client.getMachine(sandboxId)\n return { alive: true, ...(machine.state !== undefined ? { state: String(machine.state) } : {}) }\n } catch (err) {\n if (err instanceof InstaboxApiError && err.status === 404) return { alive: false }\n throw err\n }\n },\n }\n}\n\n/** Bare provider instance the catalog/registry wraps. */\nexport const instaboxSandboxProvider: SandboxProvider = createInstaboxSandboxProvider()\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentproto/sandbox-instabox",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "@agentproto/sandbox-instabox — InstaBox `SandboxProvider` for @agentproto/sandbox. Boots an InstaBox VM, installs an always-on systemd unit for the agentproto daemon, publishes the daemon port as the account's public edge URL, and exposes its MCP endpoint so any AgentSessionHost consumer (worktreeAgentWorkflow, worktree-agent CLI) can run a coding-agent step inside the sandbox.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentproto",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@agentproto/sandbox": "0.
|
|
44
|
+
"@agentproto/sandbox": "0.14.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^25.9.5",
|