Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/daytona-isolate-driver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/ai-isolate-daytona': minor
---

Add the Daytona sandbox isolate driver for Code Mode.
82 changes: 71 additions & 11 deletions docs/code-mode/code-mode-isolates.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
title: Code Mode Isolate Drivers
id: code-mode-isolates
order: 4
description: "Compare Code Mode sandbox drivers — Node isolated-vm, QuickJS WASM, and Cloudflare Workers — and choose the right runtime for your deployment."
description: "Compare Code Mode sandbox drivers — Node isolated-vm, QuickJS WASM, Cloudflare Workers, and Daytona sandboxes — and choose the right runtime for your deployment."
keywords:
- tanstack ai
- code mode
- isolate driver
- isolated-vm
- quickjs
- cloudflare workers
- daytona
- sandbox
- secure execution
---
Expand All @@ -18,15 +19,15 @@ Isolate drivers provide the secure sandbox runtimes that [Code Mode](./code-mode

## Choosing a Driver

| | Node (`isolated-vm`) | QuickJS (WASM) | Cloudflare Workers |
|---|---|---|---|
| **Best for** | Server-side Node.js apps | Browsers, edge, portability | Edge deployments on Cloudflare |
| **Performance** | Fast (V8 JIT) | Slower (interpreted) | Fast (V8 on Cloudflare edge) |
| **Native deps** | Yes (C++ addon) | None | None |
| **Browser support** | No | Yes | N/A |
| **Memory limit** | Configurable | Configurable | N/A |
| **Stack size limit** | N/A | Configurable | N/A |
| **Setup** | `pnpm add` | `pnpm add` | Deploy a Worker first |
| | Node (`isolated-vm`) | QuickJS (WASM) | Cloudflare Workers | Daytona |
|---|---|---|---|---|
| **Best for** | Server-side Node.js apps | Browsers, edge, portability | Edge deployments on Cloudflare | Full remote Linux sandboxes |
| **Performance** | Fast (V8 JIT) | Slower (interpreted) | Fast (V8 on Cloudflare edge) | Fast (native runtime; remote call) |
| **Native deps** | Yes (C++ addon) | None | None | None |
| **Browser support** | No | Yes | N/A | Yes |
| **Memory limit** | Configurable | Configurable | N/A | Configurable |
| **Stack size limit** | N/A | Configurable | N/A | N/A |
| **Setup** | `pnpm add` | `pnpm add` | Deploy a Worker first | Create or pass a Daytona sandbox |

---

Expand Down Expand Up @@ -182,9 +183,68 @@ Each round-trip adds network latency, so the `maxToolRounds` limit both prevents

---

## Daytona Driver (`@tanstack/ai-isolate-daytona`)

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.

### Installation

```bash
pnpm add @tanstack/ai-isolate-daytona
```

If your application creates sandboxes with the official Daytona SDK, also install it:

```bash
pnpm add @daytona/sdk
```

### Usage

```typescript
import { Daytona } from '@daytona/sdk'
import { createDaytonaIsolateDriver } from '@tanstack/ai-isolate-daytona'

const daytona = new Daytona()
const sandbox = await daytona.create({ language: 'typescript' })

const driver = createDaytonaIsolateDriver({
sandbox,
timeout: 30_000,
maxToolRounds: 10,
})
```

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `sandbox` | `DaytonaSandboxLike` | — | **Required.** A caller-owned Daytona sandbox-like object with `process.codeRun(code, params?, timeout?)`. |
| `timeout` | `number` | `30000` | Maximum wall-clock time for the entire execution, including replay rounds, in milliseconds. |
| `maxToolRounds` | `number` | `10` | Maximum number of sandbox <-> host tool callback rounds. Prevents infinite loops when generated code repeatedly asks for tools. |

### How it works

The driver uses the same host-owned tool replay shape as the Cloudflare driver without Cloudflare's parent Worker / Dynamic Worker split:

```text
Driver (your server) Daytona sandbox
───────────────────── ───────────────
Send: wrapped code ──────▶ Execute with process.codeRun
◀────── Return: need_tools with tool requests
Execute tools locally
Replay with toolResults ──────▶ Continue execution
◀────── Return: final result / more tool requests
...repeat until done...
```

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.

---

## The `IsolateDriver` Interface

All three drivers satisfy this interface, exported from `@tanstack/ai-code-mode`:
All provided drivers satisfy this interface, exported from `@tanstack/ai-code-mode`:

```typescript
interface IsolateDriver {
Expand Down
10 changes: 7 additions & 3 deletions docs/code-mode/code-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Tools you pass to Code Mode are converted to typed function stubs that appear in

### Secure sandboxing

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

## Getting Started

Expand All @@ -56,6 +56,9 @@ pnpm add @tanstack/ai-isolate-quickjs

# Cloudflare Workers — run on the edge
pnpm add @tanstack/ai-isolate-cloudflare

# Daytona sandboxes — run in a remote Daytona sandbox
pnpm add @tanstack/ai-isolate-daytona @daytona/sdk
```

### 2. Define tools
Expand Down Expand Up @@ -208,6 +211,7 @@ interface IsolateDriver {
| `@tanstack/ai-isolate-node` | `createNodeIsolateDriver()` | Node.js |
| `@tanstack/ai-isolate-quickjs` | `createQuickJSIsolateDriver()` | Node.js, browser, edge |
| `@tanstack/ai-isolate-cloudflare` | `createCloudflareIsolateDriver()` | Cloudflare Workers |
| `@tanstack/ai-isolate-daytona` | `createDaytonaIsolateDriver()` | Daytona sandboxes |

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

Expand All @@ -223,7 +227,7 @@ These utilities are used internally and are exported for custom pipelines:

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

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

## Custom Events

Expand Down Expand Up @@ -289,4 +293,4 @@ pnpm eval -- --no-judge # skip Anthropic-based judging

- [Showing Code Mode in the UI](./client-integration) — Display execution progress in your React app
- [Code Mode with Skills](./code-mode-with-skills) — Add persistent, reusable skill libraries
- [Isolate Drivers](./code-mode-isolates) — Compare Node, QuickJS, and Cloudflare sandbox runtimes
- [Isolate Drivers](./code-mode-isolates) — Compare Node, QuickJS, Cloudflare, and Daytona sandbox runtimes
91 changes: 91 additions & 0 deletions packages/ai-isolate-daytona/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# @tanstack/ai-isolate-daytona

Daytona sandbox driver for TanStack AI Code Mode.

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.

## Installation

```bash
pnpm add @tanstack/ai-isolate-daytona @tanstack/ai-code-mode
```

If you use the official Daytona SDK to create sandboxes, install it in your app too:

```bash
pnpm add @daytona/sdk
```

## Usage

```typescript
import { Daytona } from '@daytona/sdk'
import { createCodeMode } from '@tanstack/ai-code-mode'
import { createDaytonaIsolateDriver } from '@tanstack/ai-isolate-daytona'

const daytona = new Daytona()
const sandbox = await daytona.create({ language: 'typescript' })

const driver = createDaytonaIsolateDriver({
sandbox,
timeout: 30_000,
maxToolRounds: 10,
})

const { tool, systemPrompt } = createCodeMode({
driver,
tools: [myServerTool],
})
```

The driver accepts a structural sandbox object with `sandbox.process.codeRun(...)`; it does not require `@daytona/sdk` as a package dependency.

## API

### `createDaytonaIsolateDriver(config)`

Creates an isolate driver that delegates Code Mode execution to a Daytona sandbox.

- `sandbox` (required): caller-owned object with `process.codeRun(code, params?, timeout?)`
- `timeout` (optional): total execution timeout across replay rounds, in milliseconds (default: `30000`)
- `maxToolRounds` (optional): maximum `need_tools` replay rounds per execution (default: `10`)

## Requirements

- Use a sandbox language/runtime that can execute the JavaScript emitted by Code Mode.
- Tool inputs and outputs must be JSON-serializable.
- 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.

## How It Works

```text
Host process Daytona sandbox
------------ ---------------
createCodeMode + tools
wrap generated code ---------> run with process.codeRun
execute host tools <--------- need_tools requests
replay with toolResults ---------> continue execution
final result/logs <--------- done or error envelope
```

The host process talks directly to a Daytona sandbox through `process.codeRun`, while tool execution stays host-owned.

## Validation

Run the package checks once the implementation files are present:

```bash
pnpm --filter @tanstack/ai-isolate-daytona test:lib
pnpm --filter @tanstack/ai-isolate-daytona test:types
pnpm --filter @tanstack/ai-isolate-daytona test:eslint
pnpm --filter @tanstack/ai-isolate-daytona build
pnpm --filter @tanstack/ai-isolate-daytona test:build
```

Live Daytona validation should be gated on explicit credentials and sandbox setup in the implementation tests or a local smoke script.

```bash
DAYTONA_LIVE_TEST=1 DAYTONA_API_KEY=... pnpm --filter @tanstack/ai-isolate-daytona test:live
```

The live suite is skipped unless `DAYTONA_LIVE_TEST=1` and `DAYTONA_API_KEY` are both present.
59 changes: 59 additions & 0 deletions packages/ai-isolate-daytona/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "@tanstack/ai-isolate-daytona",
"version": "0.0.1",
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/ai.git",
"directory": "packages/ai-isolate-daytona"
},
"type": "module",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"exports": {
".": {
"types": "./dist/esm/index.d.ts",
"import": "./dist/esm/index.js"
}
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "vite build",
"clean": "premove ./build ./dist",
"lint:fix": "eslint ./src --fix",
"test:build": "publint --strict",
"test:eslint": "eslint ./src",
"test:live": "vitest --run tests/live.test.ts",
"test:lib": "vitest --passWithNoTests",
"test:lib:dev": "pnpm test:lib --watch",
"test:types": "tsc"
},
"keywords": [
"ai",
"ai-sdk",
"typescript",
"tanstack",
"code-mode",
"daytona",
"sandbox",
"isolate",
"code-execution"
],
"peerDependencies": {
"@tanstack/ai-code-mode": "workspace:*"
},
"devDependencies": {
"@daytona/sdk": "^0.180.0",
"@tanstack/ai-code-mode": "workspace:*",
"@vitest/coverage-v8": "4.0.14"
}
}
Comment on lines +1 to +59
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add packageManager to pin pnpm version.

This manifest does not declare the required package manager pin, which can lead to inconsistent lockfile/tooling behavior across contributors.

Suggested fix
 {
   "name": "`@tanstack/ai-isolate-daytona`",
   "version": "0.0.1",
+  "packageManager": "pnpm@10.17.0",
   "description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",

As per coding guidelines "**/package.json: Use pnpm@10.17.0 as the package manager for this repository".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
"name": "@tanstack/ai-isolate-daytona",
"version": "0.0.1",
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/ai.git",
"directory": "packages/typescript/ai-isolate-daytona"
},
"type": "module",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"exports": {
".": {
"types": "./dist/esm/index.d.ts",
"import": "./dist/esm/index.js"
}
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "vite build",
"clean": "premove ./build ./dist",
"lint:fix": "eslint ./src --fix",
"test:build": "publint --strict",
"test:eslint": "eslint ./src",
"test:live": "vitest --run tests/live.test.ts",
"test:lib": "vitest --passWithNoTests",
"test:lib:dev": "pnpm test:lib --watch",
"test:types": "tsc"
},
"keywords": [
"ai",
"ai-sdk",
"typescript",
"tanstack",
"code-mode",
"daytona",
"sandbox",
"isolate",
"code-execution"
],
"peerDependencies": {
"@tanstack/ai-code-mode": "workspace:*"
},
"devDependencies": {
"@daytona/sdk": "^0.180.0",
"@tanstack/ai-code-mode": "workspace:*",
"@vitest/coverage-v8": "4.0.14"
}
}
{
"name": "`@tanstack/ai-isolate-daytona`",
"version": "0.0.1",
"packageManager": "pnpm@10.17.0",
"description": "Daytona sandbox driver for TanStack AI Code Mode TypeScript execution.",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/ai.git",
"directory": "packages/typescript/ai-isolate-daytona"
},
"type": "module",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"exports": {
".": {
"types": "./dist/esm/index.d.ts",
"import": "./dist/esm/index.js"
}
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "vite build",
"clean": "premove ./build ./dist",
"lint:fix": "eslint ./src --fix",
"test:build": "publint --strict",
"test:eslint": "eslint ./src",
"test:live": "vitest --run tests/live.test.ts",
"test:lib": "vitest --passWithNoTests",
"test:lib:dev": "pnpm test:lib --watch",
"test:types": "tsc"
},
"keywords": [
"ai",
"ai-sdk",
"typescript",
"tanstack",
"code-mode",
"daytona",
"sandbox",
"isolate",
"code-execution"
],
"peerDependencies": {
"`@tanstack/ai-code-mode`": "workspace:*"
},
"devDependencies": {
"`@daytona/sdk`": "^0.180.0",
"`@tanstack/ai-code-mode`": "workspace:*",
"`@vitest/coverage-v8`": "4.0.14"
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/typescript/ai-isolate-daytona/package.json` around lines 1 - 59, Add
the required packageManager field to this package.json to pin pnpm to the repo
standard: add "packageManager": "pnpm@10.17.0" at the top-level of the JSON
(near other root keys such as "name" and "version") so the manifest explicitly
declares pnpm@10.17.0 for consistent lockfile/tooling behavior.

36 changes: 36 additions & 0 deletions packages/ai-isolate-daytona/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @tanstack/ai-isolate-daytona
*
* Daytona sandbox driver for TanStack AI Code Mode.
* Execute LLM-generated code inside a caller-provided Daytona sandbox.
*
* @example
* ```typescript
* import { createDaytonaIsolateDriver } from '@tanstack/ai-isolate-daytona'
*
* const driver = createDaytonaIsolateDriver({ sandbox })
* ```
*
* @packageDocumentation
*/

export {
createDaytonaIsolateDriver,
type DaytonaIsolateDriverConfig,
} from './isolate-driver'

export type {
DaytonaCodeRunArtifacts,
DaytonaCodeRunParams,
DaytonaCodeRunResponse,
DaytonaProcessLike,
DaytonaSandboxLike,
} from './types'

export type {
ExecutionResult,
IsolateConfig,
IsolateContext,
IsolateDriver,
NormalizedError,
} from '@tanstack/ai-code-mode'
Loading