Skip to content

Commit 8a159db

Browse files
mu-hashmijherrclaudeAlemTuzlak
authored
feat: add Daytona Code Mode isolate driver (#645)
* feat: add Daytona Code Mode isolate driver * fix: clear Daytona timeout timers * docs: clarify Daytona isolate driver positioning * chore(ai-isolate-daytona): use oxlint to match repo lint convention The package shipped eslint lint scripts (lint:fix/test:eslint) while the rest of the monorepo standardized on oxlint. This left the package's source outside the CI lint gate (nx affected --target=test:oxlint skipped it) and tripped knip with an unlisted 'eslint' binary. Align with sibling drivers (oxlint src --type-aware). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-isolate-daytona): align @daytona/sdk to ^0.191.0 to satisfy sherif Merging main brought in @tanstack/ai-sandbox-daytona, which depends on @daytona/sdk@^0.191.0. This package still pinned ^0.180.0, so sherif's multiple-dependency-versions rule failed the Test job (single-version policy across the workspace). Bump the devDependency to ^0.191.0 to match. It stays a devDependency: this driver is bring-your-own-SDK (the caller passes a Daytona sandbox via the `DaytonaSandboxLike` structural type and the driver never imports @daytona/sdk at runtime), so the SDK is only needed for dev/type-checking. Build, types, oxlint, and the unit suite all pass against 0.191.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Jack Herrington <jherr@pobox.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Alem Tuzlak <t.zlak@hotmail.com>
1 parent 3ba9c8b commit 8a159db

15 files changed

Lines changed: 3053 additions & 16 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/ai-isolate-daytona': minor
3+
---
4+
5+
Add the Daytona sandbox isolate driver for Code Mode.

docs/code-mode/code-mode-isolates.md

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Code Mode Isolate Drivers
33
id: code-mode-isolates
44
order: 4
5-
description: "Compare Code Mode sandbox drivers — Node isolated-vm, QuickJS WASM, QuickJS Bun (bun:ffi), and Cloudflare Workers — and choose the right runtime for your deployment."
5+
description: "Compare Code Mode sandbox drivers — Node isolated-vm, QuickJS WASM, QuickJS Bun (bun:ffi), Cloudflare Workers, and Daytona sandboxes — and choose the right runtime for your deployment."
66
keywords:
77
- tanstack ai
88
- code mode
@@ -13,6 +13,7 @@ keywords:
1313
- bun
1414
- bun:ffi
1515
- cloudflare workers
16+
- daytona
1617
- sandbox
1718
- secure execution
1819
---
@@ -22,15 +23,15 @@ Isolate drivers provide the secure sandbox runtimes that [Code Mode](./code-mode
2223
## Choosing a Driver
2324

2425

25-
| | Node (`isolated-vm`) | QuickJS (WASM) | QuickJS Bun (`bun:ffi`) | Cloudflare Workers |
26-
| -------------------- | ------------------------ | --------------------------- | ------------------------ | ------------------------------ |
27-
| **Best for** | Server-side Node.js apps | Browsers, edge, portability | Bun servers | Edge deployments on Cloudflare |
28-
| **Performance** | Fast (V8 JIT) | Slower (interpreted) | Fast (native QuickJS) | Fast (V8 on Cloudflare edge) |
29-
| **Native deps** | Yes (C++ addon) | None | None (TinyCC on the fly) | None |
30-
| **Browser support** | No | Yes | No (Bun only) | N/A |
31-
| **Memory limit** | Configurable | Configurable | Configurable | N/A |
32-
| **Stack size limit** | N/A | Configurable | Configurable | N/A |
33-
| **Setup** | `pnpm add` | `pnpm add` | `bun add` | Deploy a Worker first |
26+
| | Node (`isolated-vm`) | QuickJS (WASM) | QuickJS Bun (`bun:ffi`) | Cloudflare Workers | Daytona |
27+
| -------------------- | ------------------------ | --------------------------- | ------------------------ | ------------------------------ | ---------------------------------- |
28+
| **Best for** | Server-side Node.js apps | Browsers, edge, portability | Bun servers | Edge deployments on Cloudflare | Full remote Linux sandboxes |
29+
| **Performance** | Fast (V8 JIT) | Slower (interpreted) | Fast (native QuickJS) | Fast (V8 on Cloudflare edge) | Fast (native runtime; remote call) |
30+
| **Native deps** | Yes (C++ addon) | None | None (TinyCC on the fly) | None | None |
31+
| **Browser support** | No | Yes | No (Bun only) | N/A | Yes |
32+
| **Memory limit** | Configurable | Configurable | Configurable | N/A | Configurable |
33+
| **Stack size limit** | N/A | Configurable | Configurable | N/A | N/A |
34+
| **Setup** | `pnpm add` | `pnpm add` | `bun add` | Deploy a Worker first | Create or pass a Daytona sandbox |
3435

3536

3637
---
@@ -236,9 +237,68 @@ Each round-trip adds network latency, so the `maxToolRounds` limit both prevents
236237
237238
---
238239

240+
## Daytona Driver (`@tanstack/ai-isolate-daytona`)
241+
242+
Runs generated code inside a Daytona sandbox through `sandbox.process.codeRun`. Your application process still owns TanStack tool implementations; the Daytona sandbox only receives wrapped generated code plus replayed tool results.
243+
244+
### Installation
245+
246+
```bash
247+
pnpm add @tanstack/ai-isolate-daytona
248+
```
249+
250+
If your application creates sandboxes with the official Daytona SDK, also install it:
251+
252+
```bash
253+
pnpm add @daytona/sdk
254+
```
255+
256+
### Usage
257+
258+
```typescript
259+
import { Daytona } from '@daytona/sdk'
260+
import { createDaytonaIsolateDriver } from '@tanstack/ai-isolate-daytona'
261+
262+
const daytona = new Daytona()
263+
const sandbox = await daytona.create({ language: 'typescript' })
264+
265+
const driver = createDaytonaIsolateDriver({
266+
sandbox,
267+
timeout: 30_000,
268+
maxToolRounds: 10,
269+
})
270+
```
271+
272+
### Options
273+
274+
| Option | Type | Default | Description |
275+
|--------|------|---------|-------------|
276+
| `sandbox` | `DaytonaSandboxLike` || **Required.** A caller-owned Daytona sandbox-like object with `process.codeRun(code, params?, timeout?)`. |
277+
| `timeout` | `number` | `30000` | Maximum wall-clock time for the entire execution, including replay rounds, in milliseconds. |
278+
| `maxToolRounds` | `number` | `10` | Maximum number of sandbox <-> host tool callback rounds. Prevents infinite loops when generated code repeatedly asks for tools. |
279+
280+
### How it works
281+
282+
The driver uses the same host-owned tool replay shape as the Cloudflare driver without Cloudflare's parent Worker / Dynamic Worker split:
283+
284+
```text
285+
Driver (your server) Daytona sandbox
286+
───────────────────── ───────────────
287+
Send: wrapped code ──────▶ Execute with process.codeRun
288+
◀────── Return: need_tools with tool requests
289+
Execute tools locally
290+
Replay with toolResults ──────▶ Continue execution
291+
◀────── Return: final result / more tool requests
292+
...repeat until done...
293+
```
294+
295+
Use this driver when you want Code Mode execution in a full Daytona sandbox instead of an in-process isolate, QuickJS WASM runtime, or Cloudflare Worker. The sandbox should use a language/runtime capable of executing the JavaScript emitted by Code Mode, and your application remains responsible for sandbox lifecycle, filesystem, network, cleanup, and secret policy. Creating a Code Mode context does not create or delete a Daytona sandbox.
296+
297+
---
298+
239299
## The `IsolateDriver` Interface
240300

241-
All four drivers satisfy this interface, exported from `@tanstack/ai-code-mode`:
301+
All provided drivers satisfy this interface, exported from `@tanstack/ai-code-mode`:
242302

243303
```typescript
244304
import type { ToolBinding, NormalizedError } from "@tanstack/ai-code-mode";

docs/code-mode/code-mode.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Tools you pass to Code Mode are converted to typed function stubs that appear in
3535

3636
### Secure sandboxing
3737

38-
Generated code runs in an isolated environment (V8 isolate, QuickJS WASM, native QuickJS on Bun, or Cloudflare Worker) with no access to the host file system, network, or process. The sandbox has configurable timeouts and memory limits.
38+
Generated code runs in an isolated environment (V8 isolate, QuickJS WASM, native QuickJS on Bun, Cloudflare Worker, or Daytona sandbox) with no access to the host file system, network, or process. The sandbox has configurable timeouts and memory limits.
3939

4040
## Getting Started
4141

@@ -59,6 +59,9 @@ bun add @tanstack/ai-isolate-quickjs-bun
5959

6060
# Cloudflare Workers — run on the edge
6161
pnpm add @tanstack/ai-isolate-cloudflare
62+
63+
# Daytona sandboxes — run in a remote Daytona sandbox
64+
pnpm add @tanstack/ai-isolate-daytona @daytona/sdk
6265
```
6366

6467
### 2. Define tools
@@ -215,6 +218,7 @@ interface IsolateDriver {
215218
| `@tanstack/ai-isolate-quickjs` | `createQuickJSIsolateDriver()` | Node.js, browser, edge |
216219
| `@tanstack/ai-isolate-quickjs-bun` | `createQuickJSBunIsolateDriver()` | Bun |
217220
| `@tanstack/ai-isolate-cloudflare` | `createCloudflareIsolateDriver()` | Cloudflare Workers |
221+
| `@tanstack/ai-isolate-daytona` | `createDaytonaIsolateDriver()` | Daytona sandboxes |
218222

219223
For full configuration options for each driver, see [Isolate Drivers](./code-mode-isolates.md).
220224

@@ -230,7 +234,7 @@ These utilities are used internally and are exported for custom pipelines:
230234

231235
For a full comparison of drivers with all configuration options, see [Isolate Drivers](./code-mode-isolates.md).
232236

233-
In brief: use the **Node driver** for server-side Node.js (fastest, V8 JIT), **QuickJS** for browsers or portable edge deployments (no native deps), **QuickJS Bun** for Bun servers (native QuickJS via `bun:ffi`), and the **Cloudflare driver** when you deploy to Cloudflare Workers.
237+
In brief: use the **Node driver** for server-side Node.js (fastest, V8 JIT), **QuickJS** for browsers or portable edge deployments (no native deps), **QuickJS Bun** for Bun servers (native QuickJS via `bun:ffi`), the **Cloudflare driver** when you deploy to Cloudflare Workers, and the **Daytona driver** when you want execution inside a full remote Linux sandbox.
234238

235239
## Custom Events
236240

@@ -296,4 +300,4 @@ pnpm eval -- --no-judge # skip Anthropic-based judging
296300

297301
- [Showing Code Mode in the UI](./client-integration) — Display execution progress in your React app
298302
- [Code Mode with Skills](./code-mode-with-skills) — Add persistent, reusable skill libraries
299-
- [Isolate Drivers](./code-mode-isolates) — Compare Node, QuickJS, QuickJS Bun, and Cloudflare sandbox runtimes
303+
- [Isolate Drivers](./code-mode-isolates) — Compare Node, QuickJS, QuickJS Bun, Cloudflare, and Daytona sandbox runtimes
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# @tanstack/ai-isolate-daytona
2+
3+
Daytona sandbox driver for TanStack AI Code Mode.
4+
5+
This package runs generated JavaScript or TypeScript in a caller-provided Daytona sandbox and keeps TanStack tool implementations in your host process. When generated code calls an `external_*` tool, the sandbox returns a `need_tools` payload, the host executes the matching `ToolBinding.execute` callbacks, and the driver replays the code with accumulated tool results until it completes.
6+
7+
## Installation
8+
9+
```bash
10+
pnpm add @tanstack/ai-isolate-daytona @tanstack/ai-code-mode
11+
```
12+
13+
If you use the official Daytona SDK to create sandboxes, install it in your app too:
14+
15+
```bash
16+
pnpm add @daytona/sdk
17+
```
18+
19+
## Usage
20+
21+
```typescript
22+
import { Daytona } from '@daytona/sdk'
23+
import { createCodeMode } from '@tanstack/ai-code-mode'
24+
import { createDaytonaIsolateDriver } from '@tanstack/ai-isolate-daytona'
25+
26+
const daytona = new Daytona()
27+
const sandbox = await daytona.create({ language: 'typescript' })
28+
29+
const driver = createDaytonaIsolateDriver({
30+
sandbox,
31+
timeout: 30_000,
32+
maxToolRounds: 10,
33+
})
34+
35+
const { tool, systemPrompt } = createCodeMode({
36+
driver,
37+
tools: [myServerTool],
38+
})
39+
```
40+
41+
The driver accepts a structural sandbox object with `sandbox.process.codeRun(...)`; it does not require `@daytona/sdk` as a package dependency.
42+
43+
## API
44+
45+
### `createDaytonaIsolateDriver(config)`
46+
47+
Creates an isolate driver that delegates Code Mode execution to a Daytona sandbox.
48+
49+
- `sandbox` (required): caller-owned object with `process.codeRun(code, params?, timeout?)`
50+
- `timeout` (optional): total execution timeout across replay rounds, in milliseconds (default: `30000`)
51+
- `maxToolRounds` (optional): maximum `need_tools` replay rounds per execution (default: `10`)
52+
53+
## Requirements
54+
55+
- Use a sandbox language/runtime that can execute the JavaScript emitted by Code Mode.
56+
- Tool inputs and outputs must be JSON-serializable.
57+
- Sandbox lifecycle, network access, filesystem contents, secrets, and cleanup are owned by your application. Creating a Code Mode context does not create or delete a Daytona sandbox.
58+
59+
## How It Works
60+
61+
```text
62+
Host process Daytona sandbox
63+
------------ ---------------
64+
createCodeMode + tools
65+
wrap generated code ---------> run with process.codeRun
66+
execute host tools <--------- need_tools requests
67+
replay with toolResults ---------> continue execution
68+
final result/logs <--------- done or error envelope
69+
```
70+
71+
The host process talks directly to a Daytona sandbox through `process.codeRun`, while tool execution stays host-owned.
72+
73+
## Validation
74+
75+
Run the package checks once the implementation files are present:
76+
77+
```bash
78+
pnpm --filter @tanstack/ai-isolate-daytona test:lib
79+
pnpm --filter @tanstack/ai-isolate-daytona test:types
80+
pnpm --filter @tanstack/ai-isolate-daytona test:eslint
81+
pnpm --filter @tanstack/ai-isolate-daytona build
82+
pnpm --filter @tanstack/ai-isolate-daytona test:build
83+
```
84+
85+
Live Daytona validation should be gated on explicit credentials and sandbox setup in the implementation tests or a local smoke script.
86+
87+
```bash
88+
DAYTONA_LIVE_TEST=1 DAYTONA_API_KEY=... pnpm --filter @tanstack/ai-isolate-daytona test:live
89+
```
90+
91+
The live suite is skipped unless `DAYTONA_LIVE_TEST=1` and `DAYTONA_API_KEY` are both present.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"name": "@tanstack/ai-isolate-daytona",
3+
"version": "0.0.1",
4+
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
5+
"author": "",
6+
"license": "MIT",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/TanStack/ai.git",
10+
"directory": "packages/ai-isolate-daytona"
11+
},
12+
"type": "module",
13+
"module": "./dist/esm/index.js",
14+
"types": "./dist/esm/index.d.ts",
15+
"exports": {
16+
".": {
17+
"types": "./dist/esm/index.d.ts",
18+
"import": "./dist/esm/index.js"
19+
}
20+
},
21+
"sideEffects": false,
22+
"engines": {
23+
"node": ">=18"
24+
},
25+
"files": [
26+
"dist",
27+
"src"
28+
],
29+
"scripts": {
30+
"build": "vite build",
31+
"clean": "premove ./build ./dist",
32+
"lint:fix": "oxlint src --type-aware --fix",
33+
"test:build": "publint --strict",
34+
"test:oxlint": "oxlint src --type-aware",
35+
"test:live": "vitest --run tests/live.test.ts",
36+
"test:lib": "vitest --passWithNoTests",
37+
"test:lib:dev": "pnpm test:lib --watch",
38+
"test:types": "tsc"
39+
},
40+
"keywords": [
41+
"ai",
42+
"ai-sdk",
43+
"typescript",
44+
"tanstack",
45+
"code-mode",
46+
"daytona",
47+
"sandbox",
48+
"isolate",
49+
"code-execution"
50+
],
51+
"peerDependencies": {
52+
"@tanstack/ai-code-mode": "workspace:*"
53+
},
54+
"devDependencies": {
55+
"@daytona/sdk": "^0.191.0",
56+
"@tanstack/ai-code-mode": "workspace:*",
57+
"@vitest/coverage-v8": "4.0.14"
58+
}
59+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @tanstack/ai-isolate-daytona
3+
*
4+
* Daytona sandbox driver for TanStack AI Code Mode.
5+
* Execute LLM-generated code inside a caller-provided Daytona sandbox.
6+
*
7+
* @example
8+
* ```typescript
9+
* import { createDaytonaIsolateDriver } from '@tanstack/ai-isolate-daytona'
10+
*
11+
* const driver = createDaytonaIsolateDriver({ sandbox })
12+
* ```
13+
*
14+
* @packageDocumentation
15+
*/
16+
17+
export {
18+
createDaytonaIsolateDriver,
19+
type DaytonaIsolateDriverConfig,
20+
} from './isolate-driver'
21+
22+
export type {
23+
DaytonaCodeRunArtifacts,
24+
DaytonaCodeRunParams,
25+
DaytonaCodeRunResponse,
26+
DaytonaProcessLike,
27+
DaytonaSandboxLike,
28+
} from './types'
29+
30+
export type {
31+
ExecutionResult,
32+
IsolateConfig,
33+
IsolateContext,
34+
IsolateDriver,
35+
NormalizedError,
36+
} from '@tanstack/ai-code-mode'

0 commit comments

Comments
 (0)