import { type SessionMachine } from "./machine.js"; /** The subset of `SandboxAdapter` (`@vendoai/apps`) a session box needs. * Structural so this subpath never widens the package's type surface. * * `snapshot` is deliberately absent now: nothing snapshots a conversation box. */ export interface SandboxAdapterLike { create(spec: { template?: string; env: Record; allowedDomains?: string[]; }): Promise; destroy(snapshotRef: string): Promise; } export interface SandboxMachineLike { id: string; request(req: { method: string; path: string; port?: number; headers?: Record; body?: Uint8Array | string; }): Promise<{ status: number; headers: Record; body: Uint8Array; }>; /** The box's filesystem, as `SandboxMachine.files` defines it: read rejects * for a path the box does not hold, write replaces whole, list is one level * and names only. */ files: { read(path: string): Promise; write(path: string, bytes: Uint8Array | string): Promise; list(dir: string): Promise; }; /** The machine's PUBLIC ingress URL for a port — the browser→box path, which * `request()` (host→box) cannot stand in for. Declared exactly as * `SandboxMachine.url` so a real adapter still satisfies this narrowing. */ url(port?: number): Promise; destroy(): Promise; } /** * Where the host's workspace is mounted ON THE BOX'S DISK. The session door * maps every workspace path the host speaks onto this root (`toDisk`, * `box/turn-routes.mjs`) and opens the in-box session with it as `cwd`. * * Exported because anything a PROMPT sends the in-box agent to has to be spelled * from here: the agent has a shell, so it reads a bare `/user/apps/` as the * filesystem root and writes where `collect` never looks. */ export declare const BOX_WORKSPACE_ROOT = "/workspace"; /** How long a box may sit between messages before it is destroyed. */ export declare const BOX_IDLE_TTL_MS: number; export interface BoxMachineOptions { sandbox: SandboxAdapterLike; threadId: string; env: Record; /** * The outbound-domain allowlist this box boots with, filtered at the * PROVIDER's domain layer. Required, and never optional: the seam reads * `allowedDomains: undefined` as UNRESTRICTED egress (`SandboxAdapter.create` * in `@vendoai/apps`), so a caller that simply forgot would hand a box driven * by user text an unfiltered internet. Unnamed must mean denied for a * network boundary, even now that the box's own TOOLS run unprompted (the * box is the permission; this list is part of what makes that true). An * empty list is the strictest policy expressible here. * * "Strictest expressible" is not "airtight": the provider's filter keys on the * requested server name, so a client that omits SNI is not matched and is let * through (measured; not closable from this side). */ allowedDomains: string[]; /** Provider template; defaults to `VENDO_BOX_TEMPLATE`. */ template?: string; /** Test seam; production uses {@link BOX_IDLE_TTL_MS}. */ idleTtlMs?: number; /** Test seam; production uses {@link MESSAGE_BUDGET_MS}. Same seam the local * rung carries, so neither rung's budget can be exercised only in theory. */ messageBudgetMs?: number; } export declare function boxMachine(options: BoxMachineOptions): Promise; /** * The recorded v0 inference exception (design §9): a boxed harness must reach a * model to think, and that is the ONLY credential in the machine. * * SELECTION LAW, the same one `boxInference()` in the umbrella obeys: the * explicit VENDO_INFERENCE_URL+KEY pair — which is what the box env door sets — * wins; otherwise VENDO_API_KEY funds the box's model through the console's * Anthropic-compatible gateway at `/api/v1`; otherwise the box gets no * inference credential at all. * * A stray ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL selects NOTHING. It used to * outrank both rungs, so a provider key sitting in the deployment's environment * silently decided which account every box billed. Naming an own endpoint is * still fully supported — as the explicit pair, which is config. */ export declare function inferenceEnv(): Record; /** * The reusable inference credential a boxed session holds, for a redactor to * strip from anything the turn streams back to the user (VEGA-INFO-00021). It is * exactly the value that becomes the box's `ANTHROPIC_API_KEY`, read through the * SAME selection law as `inferenceEnv()` so the two can never name a different * secret. Empty when the box gets no credential (a no-key BYO deployment) — then * there is nothing to redact. The 8-char floor keeps a pathological short value * from blanking legitimate output. */ export declare function inferenceSecrets(): readonly string[]; /** * The conversational box's outbound allowlist — the ONE place its network * boundary is assembled. * * Same shape as the served-app machine's (`boxAllowlist` in `@vendoai/apps` * `egress-approval.ts`): the box's OWN skin rides unconditionally, and * everything else is filtered out at the provider's DOMAIN layer. * * Do not rely on that for anything: the filtering is real against ordinary * clients and is BYPASSABLE by * a client that omits SNI (`openssl s_client -noservername` reaches arbitrary * IPs even under an empty list — measured). It is a provider-level gap this * repo cannot close. So this list raises the cost of exfiltration and stops * every ordinary client; it does not make the box unable to reach the network. * * Two skin entries, because a session box needs exactly two things to function: * * 1. the INFERENCE host — the SDK runs the model from inside the box, so a box * that cannot reach it cannot think. Read off the env the box is actually * handed, never guessed, so a managed-inference gateway * (`VENDO_INFERENCE_URL` → `ANTHROPIC_BASE_URL`) is allowed and * `api.anthropic.com` is not. * 2. the DOOR origin — every host tool travels the host's MCP door now * (10-mcp §3b), so this is what replaced "the box holds nothing and reaches * nothing". Per DEPLOYMENT, so it arrives from composition's `toolDoor` * rather than being written down here. * * Nothing else: no npm registry, no telemetry, no update endpoint. The SDK is * baked into the machine image, and the CLI's side traffic is switched off in * `inferenceEnv()`. */ export declare function boxEgress(inference: Record, doorUrl: string | undefined, extra?: readonly string[]): string[]; /** Test + shutdown seam: drop every live box. */ export declare function disposeSessionMachines(): Promise; //# sourceMappingURL=box.d.ts.map