agentbox-sdk 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # AgentBox
2
2
 
3
+ [Live demo](https://agentbox-demo-175164121374.us-west1.run.app/)
4
+
3
5
  Run coding agents inside sandboxes. One API, any provider.
4
6
 
5
7
  Unlike wrappers that shell out to CLIs in non-interactive mode (e.g. `claude --print`), AgentBox launches each agent as a **server process** inside the sandbox and communicates over WebSocket or HTTP. This preserves the full interactive capabilities of each agent — approval flows, tool-use control, streaming events.
@@ -13,6 +15,8 @@ const sandbox = new Sandbox("local-docker", {
13
15
  env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
14
16
  });
15
17
 
18
+ await sandbox.findOrProvision();
19
+
16
20
  const run = new Agent("claude-code", {
17
21
  sandbox,
18
22
  cwd: "/workspace",
@@ -71,6 +75,11 @@ const sandbox = new Sandbox("local-docker", {
71
75
  env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
72
76
  });
73
77
 
78
+ // Explicitly attach to / create the sandbox before running anything.
79
+ // Subsequent `sandbox.run`, `sandbox.gitClone`, agent runs, etc. all
80
+ // require this to have happened first.
81
+ await sandbox.findOrProvision();
82
+
74
83
  const agent = new Agent("claude-code", {
75
84
  sandbox,
76
85
  cwd: "/workspace",
@@ -118,10 +127,24 @@ Three agent providers are supported. Each wraps a CLI that runs inside the sandb
118
127
 
119
128
  ```ts
120
129
  new Agent("claude-code", { sandbox, cwd: "/workspace", approvalMode: "auto" });
121
- new Agent("opencode", { sandbox, cwd: "/workspace", approvalMode: "auto" });
130
+ new Agent("open-code", { sandbox, cwd: "/workspace", approvalMode: "auto" });
122
131
  new Agent("codex", { sandbox, cwd: "/workspace", approvalMode: "auto" });
123
132
  ```
124
133
 
134
+ ### Reasoning effort
135
+
136
+ Pass an optional `reasoning` level alongside `model` on any run. It maps to each provider's native reasoning control: Codex's `effort` on `turn/start`, Claude Code's `--effort` flag, and OpenCode's `reasoningEffort` agent variant.
137
+
138
+ ```ts
139
+ await agent.run({
140
+ model: "sonnet",
141
+ reasoning: "high", // "low" | "medium" | "high" | "xhigh"
142
+ input: "Refactor this module and explain your reasoning.",
143
+ });
144
+ ```
145
+
146
+ `xhigh` requires a model that supports it (e.g. Claude Opus 4.7+, Codex `gpt-5.4`).
147
+
125
148
  ## Sandboxes
126
149
 
127
150
  Five sandbox providers are supported. Each gives you an isolated environment with the same interface:
@@ -134,7 +157,23 @@ Five sandbox providers are supported. Each gives you an isolated environment wit
134
157
  | `daytona` | Cloud dev environment | `DAYTONA_API_KEY` |
135
158
  | `vercel` | Ephemeral cloud VM | `VERCEL_TOKEN` + `VERCEL_TEAM_ID` + `VERCEL_PROJECT_ID` |
136
159
 
137
- Every sandbox supports: `run()`, `runAsync()`, `gitClone()`, `openPort()`, `getPreviewLink()`, `snapshot()`, `stop()`, `delete()`.
160
+ Every sandbox supports: `findOrProvision()`, `run()`, `runAsync()`, `gitClone()`, `uploadAndRun()`, `openPort()`, `getPreviewLink()`, `snapshot()`, `stop()`, `delete()`.
161
+
162
+ ### Provisioning lifecycle
163
+
164
+ `new Sandbox(...)` only stores configuration — it does **not** create or attach to a real sandbox. Call `findOrProvision()` once when you're ready to start using it, and every subsequent operation (`run`, `gitClone`, `uploadAndRun`, agent runs, …) reuses that sandbox:
165
+
166
+ ```ts
167
+ const sandbox = new Sandbox("modal", {
168
+ /* … */
169
+ });
170
+
171
+ await sandbox.findOrProvision(); // attach to existing tagged sandbox or create a fresh one
172
+ await sandbox.gitClone({ repoUrl: "…" });
173
+ const result = await sandbox.run("pnpm install");
174
+ ```
175
+
176
+ Calling a method that needs a live sandbox before `findOrProvision()` throws a clear error. This makes the (potentially slow) attach / create step explicit and lets you control exactly when it happens.
138
177
 
139
178
  Vercel sandboxes use runtime snapshots instead of pre-built images — call `sandbox.snapshot()` to capture state and pass the returned id via `provider.snapshotId` on the next run.
140
179
 
@@ -232,7 +271,7 @@ const agent = new Agent("claude-code", {
232
271
  Register slash commands the agent can use:
233
272
 
234
273
  ```ts
235
- const agent = new Agent("opencode", {
274
+ const agent = new Agent("open-code", {
236
275
  sandbox,
237
276
  cwd: "/workspace",
238
277
  approvalMode: "auto",
@@ -333,7 +372,7 @@ new Agent("codex", {
333
372
  **OpenCode** — plugin-based hooks:
334
373
 
335
374
  ```ts
336
- new Agent("opencode", {
375
+ new Agent("open-code", {
337
376
  sandbox,
338
377
  cwd: "/workspace",
339
378
  provider: {
@@ -1,10 +1,28 @@
1
1
  import { Sandbox as Sandbox$1 } from 'e2b';
2
2
  import { Sandbox as Sandbox$2 } from '@vercel/sandbox';
3
- import { Daytona, Sandbox as Sandbox$3 } from '@daytonaio/sdk';
4
- import { ModalClient, Sandbox as Sandbox$4 } from 'modal';
3
+ import { Daytona, Sandbox as Sandbox$3, CreateSandboxFromSnapshotParams, CreateSandboxFromImageParams } from '@daytonaio/sdk';
4
+ import { ModalClient, Sandbox as Sandbox$4, SandboxCreateParams } from 'modal';
5
5
  import Docker from 'dockerode';
6
6
  import { SandboxProvider } from './enums.js';
7
7
 
8
+ /**
9
+ * Tiny in-memory tarball builder used by `Sandbox.uploadAndRun`.
10
+ *
11
+ * Builds an uncompressed POSIX USTAR archive entirely in-memory, suitable
12
+ * for piping through a sandbox's stdin to be extracted by `tar -x`. We
13
+ * deliberately don't gzip on the host: setup tarballs are small (a few
14
+ * KB) and the sandbox's `tar` may not always have gzip when the image is
15
+ * stripped down, so plain tar keeps the contract simple.
16
+ */
17
+ interface TarballEntry {
18
+ /** Absolute or relative path the file should be written to in the sandbox. */
19
+ path: string;
20
+ /** File contents. Strings are encoded as UTF-8. */
21
+ content: string | Buffer;
22
+ /** Optional file mode (default `0o644`). Pass `0o755` for executables. */
23
+ mode?: number;
24
+ }
25
+
8
26
  type E2bRaw = {
9
27
  sandbox?: Sandbox$1;
10
28
  };
@@ -107,6 +125,16 @@ interface ModalProviderOptions {
107
125
  unencryptedPorts?: number[];
108
126
  command?: string[];
109
127
  verbose?: boolean;
128
+ /**
129
+ * Escape hatch: extra parameters spread into Modal's
130
+ * `client.sandboxes.create()` call. Lets callers use Modal-specific
131
+ * features that are not surfaced as typed fields here (e.g.
132
+ * `experimentalOptions`, `gpu`, `cloudBucketMounts`, `regions`).
133
+ *
134
+ * Typed fields on `ModalProviderOptions` and `SandboxOptionsBase` take
135
+ * precedence over keys provided via `createParams`.
136
+ */
137
+ createParams?: Partial<SandboxCreateParams>;
110
138
  }
111
139
  interface DaytonaProviderOptions {
112
140
  apiKey?: string;
@@ -118,6 +146,16 @@ interface DaytonaProviderOptions {
118
146
  language?: string;
119
147
  user?: string;
120
148
  public?: boolean;
149
+ /**
150
+ * Escape hatch: extra parameters spread into Daytona's `client.create()`
151
+ * call. Lets callers use Daytona-specific features that are not surfaced
152
+ * as typed fields here (e.g. `volumes`, `networkBlockAll`,
153
+ * `networkAllowList`, `ephemeral`, `autoArchiveInterval`).
154
+ *
155
+ * Typed fields on `DaytonaProviderOptions` and `SandboxOptionsBase` take
156
+ * precedence over keys provided via `createParams`.
157
+ */
158
+ createParams?: Partial<CreateSandboxFromSnapshotParams & CreateSandboxFromImageParams>;
121
159
  }
122
160
  interface VercelGitSource {
123
161
  url: string;
@@ -206,6 +244,20 @@ declare class Sandbox<P extends SandboxProviderName = SandboxProviderName> {
206
244
  get optionsSnapshot(): SandboxOptions<P>;
207
245
  get id(): string | undefined;
208
246
  get raw(): SandboxRaw<P> | undefined;
247
+ /**
248
+ * Whether `findOrProvision()` warm-attached to a pre-existing tagged
249
+ * sandbox (`true`) or created a fresh one (`false`). Useful to skip
250
+ * idempotent setup that the previous run already performed (e.g.
251
+ * `agent.setup()`). Always `false` before `findOrProvision()` resolves.
252
+ */
253
+ get wasFound(): boolean;
254
+ /**
255
+ * Attach to an existing tagged sandbox or create a new one. Must be
256
+ * called before `run`, `runAsync`, `gitClone`, `uploadAndRun`,
257
+ * `getPreviewLink`, etc. Repeated calls are cheap (the result is
258
+ * cached internally).
259
+ */
260
+ findOrProvision(): Promise<this>;
209
261
  openPort(port: number): Promise<this>;
210
262
  setSecret(name: string, value: string): this;
211
263
  setSecrets(values: Record<string, string>): this;
@@ -220,6 +272,7 @@ declare class Sandbox<P extends SandboxProviderName = SandboxProviderName> {
220
272
  get previewHeaders(): Record<string, string>;
221
273
  uploadFile(content: Buffer | string, targetPath: string): Promise<void>;
222
274
  downloadFile(sourcePath: string): Promise<Buffer>;
275
+ uploadAndRun(files: TarballEntry[], command: string, options?: CommandOptions): Promise<CommandResult>;
223
276
  }
224
277
 
225
- export { type AsyncCommandHandle as A, type CommandEvent as C, type DaytonaProviderOptions as D, type E2bProviderOptions as E, type GitCloneOptions as G, type LocalDockerProviderOptions as L, type ModalProviderOptions as M, Sandbox as S, type VercelGitSource as V, type CommandOptions as a, type CommandResult as b, type DaytonaSandboxOptions as c, type E2bSandboxOptions as d, type LocalDockerSandboxOptions as e, type ModalSandboxOptions as f, type SandboxDescriptor as g, type SandboxListOptions as h, type SandboxOptions as i, type SandboxOptionsBase as j, type SandboxOptionsMap as k, type SandboxProviderName as l, type SandboxRaw as m, type SandboxRawMap as n, type SandboxResourceSpec as o, type VercelProviderOptions as p, type VercelSandboxOptions as q };
278
+ export { type AsyncCommandHandle as A, type CommandEvent as C, type DaytonaProviderOptions as D, type E2bProviderOptions as E, type GitCloneOptions as G, type LocalDockerProviderOptions as L, type ModalProviderOptions as M, Sandbox as S, type TarballEntry as T, type VercelGitSource as V, type CommandOptions as a, type CommandResult as b, type DaytonaSandboxOptions as c, type E2bSandboxOptions as d, type LocalDockerSandboxOptions as e, type ModalSandboxOptions as f, type SandboxDescriptor as g, type SandboxListOptions as h, type SandboxOptions as i, type SandboxOptionsBase as j, type SandboxOptionsMap as k, type SandboxProviderName as l, type SandboxRaw as m, type SandboxRawMap as n, type SandboxResourceSpec as o, type VercelProviderOptions as p, type VercelSandboxOptions as q };
@@ -1,7 +1,7 @@
1
- import { m as AgentProviderName, f as AgentOptions, q as AgentRunConfig, p as AgentRun, o as AgentResult, Z as RawAgentEvent } from '../types-Et22oPap.js';
2
- export { a as AgentApprovalMode, b as AgentCommandConfig, c as AgentExecutionRequest, d as AgentLocalMcpConfig, e as AgentMcpConfig, g as AgentOptionsBase, h as AgentOptionsMap, i as AgentPermissionDecision, j as AgentPermissionKind, k as AgentPermissionResponse, l as AgentProviderAdapter, n as AgentRemoteMcpConfig, r as AgentRunSink, s as AgentSkillConfig, t as AgentSubAgentConfig, C as ClaudeCodeAgentOptions, u as ClaudeCodeHookConfig, v as ClaudeCodeHookEvent, w as ClaudeCodeHookHandler, x as ClaudeCodeHookMatcherGroup, y as ClaudeCodeHooksConfig, z as ClaudeCodeProviderOptions, B as CodexAgentOptions, D as CodexCommandHook, E as CodexHookEvent, F as CodexHookMatcherGroup, G as CodexHooksConfig, H as CodexProviderOptions, I as DataContent, J as EmbeddedSkillConfig, K as FilePart, L as ImagePart, S as OpenCodeAgentOptions, T as OpenCodePluginConfig, U as OpenCodePluginEvent, V as OpenCodePluginHookConfig, W as OpenCodeProviderOptions, $ as RepoSkillConfig, a4 as TextPart, a8 as UserContent, a9 as UserContentPart } from '../types-Et22oPap.js';
1
+ import { o as AgentProviderName, h as AgentOptions, v as AgentSetupConfig, t as AgentRunConfig, s as AgentRun, r as AgentResult, a3 as RawAgentEvent, b as AgentAttachRequest, z as AttachedRun } from '../types-B3N-Qo2q.js';
2
+ export { a as AgentApprovalMode, c as AgentCommandConfig, d as AgentCostData, e as AgentExecutionRequest, f as AgentLocalMcpConfig, g as AgentMcpConfig, i as AgentOptionsBase, j as AgentOptionsMap, k as AgentPermissionDecision, l as AgentPermissionKind, m as AgentPermissionResponse, n as AgentProviderAdapter, p as AgentReasoningEffort, q as AgentRemoteMcpConfig, u as AgentRunSink, w as AgentSetupRequest, x as AgentSkillConfig, y as AgentSubAgentConfig, C as ClaudeCodeAgentOptions, B as ClaudeCodeHookConfig, D as ClaudeCodeHookEvent, E as ClaudeCodeHookHandler, F as ClaudeCodeHookMatcherGroup, G as ClaudeCodeHooksConfig, H as ClaudeCodeProviderOptions, I as CodexAgentOptions, J as CodexCommandHook, K as CodexHookEvent, L as CodexHookMatcherGroup, M as CodexHooksConfig, N as CodexProviderOptions, O as DataContent, P as EmbeddedSkillConfig, Q as FilePart, R as ImagePart, Y as OpenCodeAgentOptions, Z as OpenCodePluginConfig, _ as OpenCodePluginEvent, $ as OpenCodePluginHookConfig, a0 as OpenCodeProviderOptions, a5 as RepoSkillConfig, aa as TextPart, ae as UserContent, af as UserContentPart } from '../types-B3N-Qo2q.js';
3
+ import { S as Sandbox } from '../Sandbox-CByFJI8X.js';
3
4
  export { AgentProvider } from '../enums.js';
4
- import '../Sandbox-BQX-sWzs.js';
5
5
  import 'e2b';
6
6
  import '@vercel/sandbox';
7
7
  import '@daytonaio/sdk';
@@ -10,12 +10,61 @@ import 'dockerode';
10
10
 
11
11
  declare class Agent<P extends AgentProviderName = AgentProviderName> {
12
12
  private readonly adapter;
13
- private readonly provider;
13
+ readonly provider: P;
14
14
  private readonly options;
15
+ private setupPromise?;
15
16
  constructor(provider: P, options: AgentOptions<P>);
17
+ /**
18
+ * The sandbox the agent will run inside, if any was passed via
19
+ * `options.sandbox`. Returns `undefined` for host-mode runs (no sandbox).
20
+ */
21
+ get sandbox(): Sandbox | undefined;
22
+ /**
23
+ * Prepare provider-specific runtime state on the configured sandbox
24
+ * (skill artifacts, MCP/hook/sub-agent config, app-server / relay boot, …).
25
+ *
26
+ * `setup()` is REQUIRED before {@link Agent.stream} or {@link Agent.run}
27
+ * for any sandbox-backed run. `stream` and the underlying
28
+ * `adapter.execute` deliberately do not trigger setup themselves so
29
+ * callers can run sandbox-side preparation in parallel with other
30
+ * long-running work (e.g. `git clone`).
31
+ *
32
+ * `execute` does not consume any setup output and does not re-do
33
+ * setup work. It assumes the relay/server boot performed here is
34
+ * already up. Skipping `setup()` against a remote sandbox is a
35
+ * programmer error and surfaces as a connect-retry timeout inside
36
+ * `execute`, not a silent fallback.
37
+ *
38
+ * Idempotent across repeated invocations: subsequent calls return the
39
+ * promise from the first call. The differential setup cache and the
40
+ * relay/server probes also make this cheap on warm sandboxes — the
41
+ * second `setup()` against the same sandbox does ~one round-trip of
42
+ * work.
43
+ */
44
+ setup(config?: AgentSetupConfig): Promise<void>;
16
45
  stream(runConfig: AgentRunConfig): AgentRun;
17
46
  run(runConfig: AgentRunConfig): Promise<AgentResult>;
18
47
  rawEvents(runConfig: AgentRunConfig): AsyncIterable<RawAgentEvent>;
48
+ /**
49
+ * Stateless control plane for an in-flight run.
50
+ *
51
+ * Returns an {@link AttachedRun} whose `abort()` / `sendMessage()` methods
52
+ * dial the in-sandbox provider server directly (codex app-server, opencode
53
+ * HTTP server, claude-code relay control endpoint) — there is no shared
54
+ * in-memory registry or Redis broker. Any process with the right `sandbox`
55
+ * + `runId` (+ optional provider-native `sessionId`) can issue commands
56
+ * against a run started on a different process.
57
+ *
58
+ * The originating process keeps owning the event stream that
59
+ * `agent.stream()` returned; commands attached here cause the in-sandbox
60
+ * server to emit the natural follow-up events (`turn/aborted`, message
61
+ * events, etc.), which the originating process ingests through its
62
+ * existing transport.
63
+ *
64
+ * The handle is short-lived: each method call opens a fresh connection,
65
+ * performs the operation with a timeout, and tears the connection down.
66
+ */
67
+ static attach<P extends AgentProviderName>(request: AgentAttachRequest<P>): Promise<AttachedRun>;
19
68
  }
20
69
 
21
70
  /**
@@ -36,4 +85,4 @@ declare class Agent<P extends AgentProviderName = AgentProviderName> {
36
85
  declare const AGENT_RESERVED_PORTS: Record<AgentProviderName, readonly number[]>;
37
86
  declare function collectAllAgentReservedPorts(): number[];
38
87
 
39
- export { AGENT_RESERVED_PORTS, Agent, AgentOptions, AgentProviderName, AgentResult, AgentRun, AgentRunConfig, collectAllAgentReservedPorts };
88
+ export { AGENT_RESERVED_PORTS, Agent, AgentAttachRequest, AgentOptions, AgentProviderName, AgentResult, AgentRun, AgentRunConfig, AgentSetupConfig, AttachedRun, collectAllAgentReservedPorts };
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  Agent
3
- } from "../chunk-G27423WX.js";
4
- import "../chunk-7FLLQJ6J.js";
3
+ } from "../chunk-4MBB6QHD.js";
4
+ import "../chunk-ZOWBRUQR.js";
5
5
  import {
6
6
  AGENT_RESERVED_PORTS,
7
7
  collectAllAgentReservedPorts
8
- } from "../chunk-O7HCJXKW.js";
8
+ } from "../chunk-INMA52FV.js";
9
9
  import "../chunk-NSJM57Z4.js";
10
10
  import {
11
11
  AgentProvider
12
- } from "../chunk-2NKMDGYH.js";
12
+ } from "../chunk-GOFJNFAD.js";
13
13
  export {
14
14
  AGENT_RESERVED_PORTS,
15
15
  Agent,