export interface E2BDesktopModule { Sandbox: { /** Default `desktop` template (no custom image). The historical, byte-stable call shape. */ create(options: E2BDesktopCreateOptions): Promise; /** * Launch on a CUSTOM E2B desktop template (image) by NAME or ID — the SDK's * `Sandbox.create(template, opts)` overload. Lets a lab run on an adopter-maintained image * with extra runtimes baked in (e.g. node/bun/a local Postgres the stock `desktop` template * lacks), instead of the stock template. The base @e2b/desktop SDK implements this; the * wrapper just exposes it. Threaded from `execution.desktop.template`. */ create(template: string, options: E2BDesktopCreateOptions): Promise; /** * Kill the sandbox specified by exact id. Returns true iff THAT sandbox was found and * killed, false otherwise (the SDK's own doc comment). This boolean is the PRIMARY by-id * cleanup proof: a caller never needs to re-list to confirm reclamation. */ kill?(sandboxId: string, options?: { requestTimeoutMs?: number; }): Promise; /** * Fetch ONE sandbox by its exact id (never account-wide). Throws a SandboxNotFoundError- * shaped error (see isSandboxNotFoundError below) when the id no longer exists; that thrown * error IS the by-id confirmation that a killed sandbox is gone. Optional: older SDKs may * lack it, so callers fall back to kill()'s own boolean rather than ever calling Sandbox.list. */ getInfo?(sandboxId: string, options?: { requestTimeoutMs?: number; }): Promise; /** * ACCOUNT-WIDE enumeration. Kept only for the routes that already avoid it for cleanup * (shared-world/scripted/cua/preflight kill by exact id and never call this); no cleanup * proof in this codebase should call it (see e2b-terminal-lab.ts teardownSandbox and * oss-meta-lab.ts, both of which reclaim and verify by id, never by listing). */ list?(options: E2BSandboxListOptions): E2BSandboxPaginator; }; } export interface E2BSandboxListOptions { metadata?: Record; requestTimeoutMs?: number; } export interface E2BSandboxInfo { id?: string; metadata?: Record; sandboxID?: string; sandboxId?: string; state?: string; } export interface E2BSandboxPaginator { hasNext: boolean; nextItems(options?: { requestTimeoutMs?: number; }): Promise; } /** Sandbox egress policy. Domain filtering works for HTTP on :80 (Host header) and TLS on :443 * (SNI); other ports need IPs. Passed straight through to the E2B SDK's `network` option. */ export interface E2BNetworkOptions { /** Hosts (or CIDRs) the sandbox may reach. Wildcards like `*.example.com` cover subdomains at * any depth; the apex is separate and needs its own entry. */ allowOut?: string[]; /** Denied traffic. `["0.0.0.0/0"]` with a populated allowOut is the deny-all-but shape. */ denyOut?: string[]; /** Static per-host HTTPS header transforms (E2B network rules). Header values override the * outbound request's values. These may contain secrets: never persist or log this object. * This is a structural subset of the installed SDK's SandboxNetworkRules contract. */ rules?: Record; }; }[]>; } export interface E2BDesktopCreateOptions { apiKey: string; dpi?: number; envs?: Record; /** Routing and optional header transforms; absent allowOut/denyOut retains unrestricted egress. */ network?: E2BNetworkOptions; lifecycle?: { onTimeout: "kill" | "pause"; }; metadata?: Record; requestTimeoutMs?: number; resolution?: [number, number]; timeoutMs?: number; } export interface E2BCommandRunOptions { background?: false; cwd?: string; envs?: Record; onStderr?: (data: string) => void | Promise; onStdout?: (data: string) => void | Promise; requestTimeoutMs?: number; timeoutMs?: number; } export interface E2BCommandResult { error?: string; exitCode?: number; stderr?: string; stdout?: string; } export interface E2BDesktopSandbox { sandboxId: string; /** Read the owned allocation's actual resources; available on the current E2B SDK. */ getInfo?(options?: { requestTimeoutMs?: number; signal?: AbortSignal; }): Promise<{ cpuCount?: number; memoryMB?: number; }>; commands: { run(command: string, options?: E2BCommandRunOptions): Promise; }; files: { write(path: string, data: string | ArrayBuffer, options?: { requestTimeoutMs?: number; useOctetStream?: boolean; }): Promise; }; launch(application: string, uri?: string): Promise; /** Open a file or URL with the desktop's default application (present on @e2b/desktop >= 1.x). */ open?(fileOrUrl: string): Promise; /** * Map an in-sandbox port to a reachable host URL — `https://-.e2b.app`, * TOKENLESS (no authKey, unlike `stream.getUrl`). The base `e2b` SDK (v2.27.0) implements this; * the wrapper just exposes it. Used by the CONCURRENT shared-world topology (#164 phase 2) to * expose the ONE subject service plane to N actor sandboxes. Optional: older SDKs may lack it, so * the concurrent backend fails closed when it is absent rather than calling a missing method. */ getHost?(port: number): string; screenshot(format?: "bytes"): Promise; wait(ms: number): Promise; stream: { getAuthKey(): string; getUrl(options?: { authKey?: string; autoConnect?: boolean; resize?: "off" | "scale" | "remote"; viewOnly?: boolean; }): string; start(options?: { requireAuth?: boolean; windowId?: string; }): Promise; }; } export declare function loadE2BDesktopModule(): Promise; export declare const DESKTOP_CREATE_CLEANUP_TIMEOUT_MS = 10000; type DesktopCreateCleanup = "killed" | "already_gone" | "unconfirmed"; /** Startup failed after this call acquired a handle. No credentials/options are included here. */ export declare class E2BDesktopStartupError extends Error { readonly cleanup: DesktopCreateCleanup; constructor(error: unknown, cleanup: DesktopCreateCleanup); } /** * Preserve ownership before the desktop SDK starts Xvfb/XFCE (#581). Its public generic create * constructs `new this(...)` through the base SDK, then awaits desktop startup. Newer SDKs * attempt their own kill before rejecting create; older SDKs leave cleanup to the caller. * Both paths share one bounded cleanup result so an internal kill cannot delay our deadline * or cause a second cleanup request. Successful creation restores normal kill semantics. * Each call gets a separate subclass/closure so concurrent attempts cannot exchange handles. * * This deliberately depends on SDK construction order, not a copied private `_start` method. * The real installed SDK's debug-mode conformance test must pass on dependency updates: the * constructor must run before bootstrap and public create must preserve its subclass type. * Failures before a constructor returns still have no acquired handle and remain unproven. */ export declare function guardDesktopSandboxCreate(module: E2BDesktopModule): E2BDesktopModule; export declare function isMissingE2BDesktopDependency(error: unknown): boolean; /** * Detect a SandboxNotFoundError-shaped error from the real @e2b/desktop SDK, WITHOUT importing * its class (this module stays optional-peer / lazily-loaded, same as everything else here). * The real SDK sets `this.name = "SandboxNotFoundError"` on the class (it extends the * deprecated NotFoundError), so checking `.name` is the stable, import-free detection contract. * The constructor-name fallback covers a bundler/transpile shape where `.name` was not copied * onto the instance. A thrown SandboxNotFoundError from Sandbox.getInfo(id) is the by-id proof * that the exact sandbox humanish created is gone (confirmed reclaimed), never a re-list. */ export declare function isSandboxNotFoundError(error: unknown): boolean; /** * Create an E2B desktop sandbox, optionally on a CUSTOM template (image). The ONE seam every * desktop-creating route calls so the default and custom-template paths are decided in a single * place. * * When `template` is undefined (the default — no `execution.desktop.template` configured), this is * BYTE-STABLE with the historical `Sandbox.create(options)` call: the stock `desktop` template, the * options object passed as the sole argument. When `template` is a non-empty name/id, it selects * the SDK's `Sandbox.create(template, options)` overload so the lab runs on an adopter's image. * The template (when set) is a public-safe label, never a secret. */ export declare function createDesktopSandbox(module: E2BDesktopModule, options: E2BDesktopCreateOptions, template?: string, retry?: TransientRetryHooks): Promise; /** How a caller hears about the one retry; `sleep` is injectable so tests never wait. */ export interface TransientRetryHooks { onRetry?: (reason: string) => void; sleep?: (ms: number) => Promise; } /** Wall-clock pause before the single retry; envd routing settles within a few seconds. */ export declare const TRANSIENT_RETRY_DELAY_MS = 3000; /** * The provider errors worth exactly ONE retry, by the message the SDK throws. Measured * 2026-09-04: six lanes created within 100 s lost five to these three shapes, and a probe of the * same SDK a minute later created a sandbox, wrote 7 MB into it and killed it in 6 s. * * - `12: [unimplemented] HTTP 404` and `[unavailable]`: the sandbox exists but its envd is not * routable yet, so the first request (the desktop SDK's Xvfb start) hits the proxy instead. * - `Cannot read properties of undefined (reading 'envdVersion')` / `Response data is missing`: * the create API answered without a body. * - `Expected to receive information about written file`: a file write the envd accepted without * describing, the same routing gap seen from the upload side. * - transport resets (`fetch failed`, `ECONNRESET`, `socket hang up`, 502/503/504). * * NOT retried: timeouts (the budget is spent), auth (401/403), quota and rate limits (429: a burst * that hit the limit should be spaced, not repeated), and anything that names the request as wrong. */ export declare function isTransientE2BError(error: unknown): boolean; /** * Run `attempt`; on a transient provider error, say so through `onRetry`, wait, and run it once * more. A second failure, or a non-transient first one, propagates as is. The first attempt may * have allocated a sandbox this process never learned the id of (the SDK throws after the API * call); the provider's own `timeoutMs` on that sandbox is what reclaims it, which the caller's * warning should say. */ export declare function withOneRetryOnTransientE2BError(attempt: () => Promise, hooks?: TransientRetryHooks): Promise; export {};