import * as eve_sandbox_provider from 'eve/sandbox/provider'; import { BoxConfig, NetworkPolicy } from '@upstash/box'; import { SandboxSession, SandboxNetworkPolicy } from 'eve/sandbox'; /** * The session type of an Upstash Box sandbox: eve's {@link SandboxSession} plus `setNetworkPolicy`. * eve ≥0.66 made network policy provider-specific (it left the common session), so this provider * declares it; `ctx.getSandbox(environment)` returns this type. */ type UpstashSandboxSession = SandboxSession & { /** Replace the box's egress policy (deny-all by default). */ setNetworkPolicy(policy: SandboxNetworkPolicy): Promise; }; /** Options for `environment.open(...)` — applied once, when eve starts the session's box. */ interface UpstashSandboxOpenOptions { /** Network policy for the session's box. Defaults to deny-all. */ readonly networkPolicy?: SandboxNetworkPolicy; } /** * Options for `UpstashSandbox.environment(...)` — the **Upstash Box** `BoxConfig` as-is (`runtime`, * `size`, `apiKey`/`baseUrl`, `keepAlive`, `initCommand`, `env`, `git`, `skills`, `mcpServers`, * `attachHeaders`, `timeout`, …), plus two AgentKit fields: `prepare` and `baseSnapshot`. * * Omitted from `BoxConfig`: `networkPolicy` (egress is deny-all at creation and opened per session — * see {@link UpstashSandboxOpenOptions}) and `name` (box names are unique per account, and every * session gets its own box; the provider names them `eve--`). * * Eve hashes these options into the environment's configuration, so changing any of them (including * the source of `prepare`) starts a new environment generation for new sessions. Prefer * `UPSTASH_BOX_API_KEY` over an inline `apiKey` so rotating the key doesn't do that. */ type UpstashSandboxEnvironmentOptions = Omit & { /** * Setup every session's box inherits — installing packages, cloning a repo, warming caches. Runs * once per environment generation inside a temporary box (after workspace seeds and skills are * written); the result is captured as a Box snapshot. The box starts deny-all: call * `sandbox.setNetworkPolicy("allow-all")` (or an allow-list) first if the setup needs egress. * Sessions do **not** inherit the policy you set here. */ prepare?: (sandbox: UpstashSandboxSession) => Promise | void; /** * A **base Box snapshot** to build on instead of a bare `Box.create` — for heavy, slow-changing * setup (browser binaries, a toolchain) you bake and manage yourself, out of band. `prepare` layers * on top of it; with nothing to prepare, sessions restore from it directly. * * A snapshot id, or a resolver (sync or async) — e.g. looking the id up in your own store. * `undefined` means no base. The resolver runs when eve prepares the environment and, when there * is nothing to prepare, again whenever a session starts. */ baseSnapshot?: string | (() => string | undefined | Promise); }; /** * Bridge an Eve-rooted path to its Box location: Eve assumes `/workspace`, Box uses `/workspace/home`. * Relative paths anchor under the box root; `/workspace[/…]` is remapped; already-Box-rooted and other * absolute paths (`/tmp`, `/etc`) pass through untouched. */ declare function toBoxPath(path: string): string; /** * Remap `/workspace` → `/workspace/home` inside a raw command string. Eve's built-in glob/grep tools * run commands like `find /workspace …` with the literal Eve root (they don't go through `resolvePath`), * so the box would search the wrong (off-limits) directory. * * Only rewrites `/workspace` when it **starts a path token**: the lookbehind skips it when preceded by a * word char, `.`, or `/` — i.e. inside a URL (`https://host/workspace/x`) or a relative path * (`./workspace`) — and the lookahead leaves `/workspace/home…` (already box-rooted) and words like * `/workspaces` alone. This still can't reach `/workspace` paths baked **inside files** the model writes * (only the command text is rewritten); the model normally avoids that because tool output shows it the * real `/workspace/home` paths. */ declare function rewriteWorkspacePaths(command: string): string; /** * Map Eve's (Vercel-shaped) network policy onto Box's. Box's policy is a plain domain/CIDR allow-list, * so it can't honor Eve's per-domain firewall rules: `transform` (inject headers at the firewall to * broker credentials so secrets never enter the box), `forwardURL` or `match`. Silently dropping those * would send the request unauthenticated, or push the model to embed the secret inside the box, so we * **throw** rather than quietly downgrade a security control. (Plain allow-lists and empty rule arrays * map fine.) * * For credential brokering on Box, set `attachHeaders` in the environment options instead: * `UpstashSandbox.environment({ attachHeaders: { "api.example.com": { Authorization: "Bearer ..." } } })`. */ declare function toBoxNetworkPolicy(policy: SandboxNetworkPolicy): NetworkPolicy; /** * The Upstash Box sandbox provider for Eve. Call `UpstashSandbox.environment(options)`, export the * result from your sandbox file as `environment`, and return `environment.open()` from * `defineSandbox()`. */ declare const UpstashSandbox: eve_sandbox_provider.SandboxProvider; export { UpstashSandbox, type UpstashSandboxEnvironmentOptions, type UpstashSandboxOpenOptions, type UpstashSandboxSession, rewriteWorkspacePaths, toBoxNetworkPolicy, toBoxPath };