Fix SDK typecheck errors and update persist drivers for insertEvent signature

- Fix insertEvent call in client.ts to pass sessionId as first argument
- Update Daytona provider create options to use Partial type (image has default)
- Update StrictUniqueSessionPersistDriver in tests to match new insertEvent signature
- Sync persist packages, openapi spec, and docs with upstream changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nathan Flurry 2026-03-15 13:17:10 -07:00
parent 6a42f06342
commit 441083ea2a
33 changed files with 1051 additions and 2121 deletions

View file

@ -22,36 +22,15 @@ icon: "rocket"
</Tabs>
</Step>
<Step title="Set environment variables">
Each coding agent requires API keys to connect to their respective LLM providers.
```bash
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
```
<AccordionGroup>
<Accordion title="Extracting API keys from current machine">
Use `sandbox-agent credentials extract-env --export` to extract your existing API keys (Anthropic, OpenAI, etc.) from local Claude Code or Codex config files.
</Accordion>
<Accordion title="Testing without API keys">
Use the `mock` agent for SDK and integration testing without provider credentials.
</Accordion>
<Accordion title="Multi-tenant and per-user billing">
For per-tenant token tracking, budget enforcement, or usage-based billing, see [LLM Credentials](/llm-credentials) for gateway options like OpenRouter, LiteLLM, and Portkey.
</Accordion>
</AccordionGroup>
</Step>
<Step title="Start the sandbox">
`SandboxAgent.start()` provisions a sandbox, starts a lightweight [Sandbox Agent server](/architecture) inside it, and connects your SDK client.
`SandboxAgent.start()` provisions a sandbox, starts a lightweight [Sandbox Agent server](/architecture) inside it, and connects your SDK client. Pass your LLM API keys so the agent can reach its provider.
<CodeGroup>
```typescript Local
import { SandboxAgent } from "sandbox-agent";
import { local } from "sandbox-agent/local";
// Runs on your machine. Best for local development and testing.
// Runs on your machine. Inherits process.env automatically.
const sdk = await SandboxAgent.start({
sandbox: local(),
});
@ -62,7 +41,15 @@ icon: "rocket"
import { e2b } from "sandbox-agent/e2b";
const sdk = await SandboxAgent.start({
sandbox: e2b({ create: { envs } }),
sandbox: e2b({
create: {
// Pass whichever keys your agent needs
envs: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
},
},
}),
});
```
@ -71,7 +58,14 @@ icon: "rocket"
import { daytona } from "sandbox-agent/daytona";
const sdk = await SandboxAgent.start({
sandbox: daytona({ create: { envVars } }),
sandbox: daytona({
create: {
envVars: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
},
},
}),
});
```
@ -80,7 +74,15 @@ icon: "rocket"
import { vercel } from "sandbox-agent/vercel";
const sdk = await SandboxAgent.start({
sandbox: vercel({ create: { runtime: "node24", env } }),
sandbox: vercel({
create: {
runtime: "node24",
env: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
},
},
}),
});
```
@ -100,13 +102,16 @@ icon: "rocket"
// Good for testing. Not security-hardened like cloud sandboxes.
const sdk = await SandboxAgent.start({
sandbox: docker({
env: [`ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY}`],
env: [
`ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY}`,
`OPENAI_API_KEY=${process.env.OPENAI_API_KEY}`,
],
}),
});
```
</CodeGroup>
Each provider handles provisioning, server installation, and networking. Install the provider's peer dependency (e.g. `@e2b/code-interpreter`, `dockerode`) in your project. See the [Deploy](/deploy/local) guides for full setup details.
Each provider handles provisioning, server installation, and networking. Install the provider's peer dependency (e.g. `@e2b/code-interpreter`, `dockerode`) in your project. See the [Deploy](/deploy/local) guides for full setup details. For multi-tenant billing, per-user keys, and gateway options, see [LLM Credentials](/llm-credentials).
<AccordionGroup>
<Accordion title="Implementing a custom provider">
@ -212,10 +217,14 @@ icon: "rocket"
```typescript
import { SandboxAgent } from "sandbox-agent";
import { local } from "sandbox-agent/local";
import { e2b } from "sandbox-agent/e2b";
const sdk = await SandboxAgent.start({
sandbox: local(),
sandbox: e2b({
create: {
envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
},
}),
});
try {

View file

@ -23,12 +23,6 @@ The TypeScript SDK is centered on `sandbox-agent` and its `SandboxAgent` class.
</Tab>
</Tabs>
## Optional persistence drivers
```bash
npm install @sandbox-agent/persist-indexeddb@0.3.x @sandbox-agent/persist-sqlite@0.3.x @sandbox-agent/persist-postgres@0.3.x
```
## Optional React components
```bash
@ -68,15 +62,12 @@ const sdk = await SandboxAgent.connect({
controller.abort();
```
With persistence:
With persistence (see [Persisting Sessions](/session-persistence) for driver options):
```ts
import { SandboxAgent } from "sandbox-agent";
import { SQLiteSessionPersistDriver } from "@sandbox-agent/persist-sqlite";
import { SandboxAgent, InMemorySessionPersistDriver } from "sandbox-agent";
const persist = new SQLiteSessionPersistDriver({
filename: "./sessions.db",
});
const persist = new InMemorySessionPersistDriver();
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",

View file

@ -15,9 +15,9 @@ Each driver stores:
## Persistence drivers
### In-memory
### In-memory (built-in)
Best for local dev and ephemeral workloads.
Best for local dev and ephemeral workloads. No extra dependencies required.
```ts
import { InMemorySessionPersistDriver, SandboxAgent } from "sandbox-agent";
@ -33,91 +33,17 @@ const sdk = await SandboxAgent.connect({
});
```
### Rivet
Recommended for sandbox orchestration with actor state.
```bash
npm install @sandbox-agent/persist-rivet@0.3.x
```
```ts
import { actor } from "rivetkit";
import { SandboxAgent } from "sandbox-agent";
import { RivetSessionPersistDriver, type RivetPersistState } from "@sandbox-agent/persist-rivet";
type PersistedState = RivetPersistState & {
sandboxId: string;
baseUrl: string;
};
export default actor({
createState: async () => {
return {
sandboxId: "sbx_123",
baseUrl: "http://127.0.0.1:2468",
} satisfies Partial<PersistedState>;
},
createVars: async (c) => {
const persist = new RivetSessionPersistDriver(c);
const sdk = await SandboxAgent.connect({
baseUrl: c.state.baseUrl,
persist,
});
const session = await sdk.resumeOrCreateSession({ id: "default", agent: "codex" });
const unsubscribe = session.onEvent((event) => {
c.broadcast("session.event", event);
});
return { sdk, session, unsubscribe };
},
actions: {
sendMessage: async (c, message: string) => {
await c.vars.session.prompt([{ type: "text", text: message }]);
},
},
onSleep: async (c) => {
c.vars.unsubscribe?.();
await c.vars.sdk.dispose();
},
});
```
### IndexedDB
Best for browser apps that should survive reloads.
```bash
npm install @sandbox-agent/persist-indexeddb@0.3.x
```
```ts
import { SandboxAgent } from "sandbox-agent";
import { IndexedDbSessionPersistDriver } from "@sandbox-agent/persist-indexeddb";
const persist = new IndexedDbSessionPersistDriver({
databaseName: "sandbox-agent-session-store",
});
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
persist,
});
```
### SQLite
Best for local/server Node apps that need durable storage without a DB server.
```bash
npm install @sandbox-agent/persist-sqlite@0.3.x
npm install better-sqlite3
```
```ts
import { SandboxAgent } from "sandbox-agent";
import { SQLiteSessionPersistDriver } from "@sandbox-agent/persist-sqlite";
import { SQLiteSessionPersistDriver } from "./persist.ts";
const persist = new SQLiteSessionPersistDriver({
filename: "./sandbox-agent.db",
@ -129,17 +55,19 @@ const sdk = await SandboxAgent.connect({
});
```
See the [full SQLite example](https://github.com/nichochar/sandbox-agent/tree/main/examples/persist-sqlite) for the complete driver implementation you can copy into your project.
### Postgres
Use when you already run Postgres and want shared relational storage.
```bash
npm install @sandbox-agent/persist-postgres@0.3.x
npm install pg
```
```ts
import { SandboxAgent } from "sandbox-agent";
import { PostgresSessionPersistDriver } from "@sandbox-agent/persist-postgres";
import { PostgresSessionPersistDriver } from "./persist.ts";
const persist = new PostgresSessionPersistDriver({
connectionString: process.env.DATABASE_URL,
@ -152,6 +80,16 @@ const sdk = await SandboxAgent.connect({
});
```
See the [full Postgres example](https://github.com/nichochar/sandbox-agent/tree/main/examples/persist-postgres) for the complete driver implementation you can copy into your project.
### IndexedDB (browser)
Best for browser apps that should survive reloads. See the [Inspector source](https://github.com/nichochar/sandbox-agent/tree/main/frontend/packages/inspector/src/persist-indexeddb.ts) for a complete IndexedDB driver you can copy into your project.
### Rivet
Recommended for sandbox orchestration with actor state. See [Multiplayer](/multiplayer) for a full Rivet actor example with inline persistence.
### Custom driver
Implement `SessionPersistDriver` for custom backends.