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
29 changes: 29 additions & 0 deletions .changeset/quickjs-bun-isolate-driver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
'@tanstack/ai-isolate-quickjs-bun': minor
'@tanstack/ai-code-mode': patch
---

Add `@tanstack/ai-isolate-quickjs-bun`, a Code Mode isolate driver that runs QuickJS natively on the Bun runtime through `bun:ffi` (via [`quickjs-bun`](https://github.com/superpowerdotcom/quickjs-bun)).

It implements the same `IsolateDriver` contract as the existing drivers and is a drop-in replacement for `@tanstack/ai-isolate-quickjs` on Bun servers:

```typescript
import { createQuickJSBunIsolateDriver } from '@tanstack/ai-isolate-quickjs-bun'
import { createCodeModeTool } from '@tanstack/ai-code-mode'

const executeTypescript = createCodeModeTool({
driver: createQuickJSBunIsolateDriver(),
tools: [myTool],
})
```

Compared to the WASM driver:

- Native QuickJS through `bun:ffi` — no WebAssembly or asyncify overhead, and no native build step (the QuickJS sources are compiled once per process by Bun's embedded TinyCC).
- Each context gets a dedicated QuickJS runtime with its own memory and stack limits, so executions on different contexts are not serialized through a shared VM.
- Same normalized `MemoryLimitError` / `StackOverflowError` / `DisposedError` contract, console capture prefixes, and JSON tool-call protocol as the other drivers, plus a normalized `TimeoutError` for deadline expiry (the WASM driver surfaces timeouts as `InternalError: interrupted`).
- A configurable `maxToolCalls` limit (default 1000) bounds output and memory growth from untrusted sandbox code.

The driver requires Bun `>= 1.3.14` and throws an error when used on Node.js.

The `@tanstack/ai-code-mode` README and bundled skill are updated to document the new driver.
107 changes: 80 additions & 27 deletions docs/code-mode/code-mode-isolates.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,35 @@
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, QuickJS Bun (bun:ffi), and Cloudflare Workers — and choose the right runtime for your deployment."
keywords:
- tanstack ai
- code mode
- isolate driver
- isolated-vm
- quickjs
- quickjs-bun
- bun
- bun:ffi
- cloudflare workers
- sandbox
- secure execution
---

Isolate drivers provide the secure sandbox runtimes that [Code Mode](./code-mode.md) uses to execute generated TypeScript. All drivers implement the same `IsolateDriver` interface, so you can swap them without changing any other code.

## 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) | QuickJS Bun (`bun:ffi`) | Cloudflare Workers |
| -------------------- | ------------------------ | --------------------------- | ------------------------ | ------------------------------ |
| **Best for** | Server-side Node.js apps | Browsers, edge, portability | Bun servers | Edge deployments on Cloudflare |
| **Performance** | Fast (V8 JIT) | Slower (interpreted) | Fast (native QuickJS) | Fast (V8 on Cloudflare edge) |
| **Native deps** | Yes (C++ addon) | None | None (TinyCC on the fly) | None |
| **Browser support** | No | Yes | No (Bun only) | N/A |
| **Memory limit** | Configurable | Configurable | Configurable | N/A |
| **Stack size limit** | N/A | Configurable | Configurable | N/A |
| **Setup** | `pnpm add` | `pnpm add` | `bun add` | Deploy a Worker first |


---

Expand Down Expand Up @@ -55,10 +59,12 @@ const driver = createNodeIsolateDriver({

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `memoryLimit` | `number` | `128` | Maximum heap size for the V8 isolate, in megabytes. Execution is terminated if this limit is exceeded. |
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |

| Option | Type | Default | Description |
| ------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| `memoryLimit` | `number` | `128` | Maximum heap size for the V8 isolate, in megabytes. Execution is terminated if this limit is exceeded. |
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |


### How it works

Expand Down Expand Up @@ -90,17 +96,61 @@ const driver = createQuickJSIsolateDriver({

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `memoryLimit` | `number` | `128` | Maximum heap memory for the QuickJS VM, in megabytes. |
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |

| Option | Type | Default | Description |
| -------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `memoryLimit` | `number` | `128` | Maximum heap memory for the QuickJS VM, in megabytes. |
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |
| `maxStackSize` | `number` | `524288` | Maximum call stack size in bytes (default: 512 KiB). Increase for deeply recursive code; decrease to catch runaway recursion sooner. |


### How it works

QuickJS WASM uses an asyncified execution model — the WASM module can pause while awaiting host async functions (your tools). Executions are serialized through a global queue to prevent concurrent WASM calls, which the asyncify model does not support. Fatal errors (memory exhaustion, stack overflow) are detected, the VM is disposed, and a structured error is returned. Console output is captured and returned with the result.

> **Performance note:** QuickJS interprets JavaScript rather than JIT-compiling it, so compute-heavy scripts run slower than with the Node driver. For typical LLM-generated scripts that are mostly waiting on `external_*` tool calls, this difference is not significant.
> **Performance note:** QuickJS interprets JavaScript rather than JIT-compiling it, so compute-heavy scripts run slower than with the Node driver. For typical LLM-generated scripts that are mostly waiting on `external_`* tool calls, this difference is not significant.

---

## QuickJS Bun Driver (`@tanstack/ai-isolate-quickjs-bun`)

Runs [QuickJS](https://bellard.org/quickjs/) natively on the [Bun](https://bun.sh/) runtime through `bun:ffi`, via the [`quickjs-bun`](https://github.com/superpowerdotcom/quickjs-bun) package. There are no native dependencies and no build step — the vendored QuickJS C sources are compiled on the fly with Bun's embedded TinyCC, once per process. This makes it the fastest sandboxed option for Code Mode on Bun.

### Installation

Comment thread
lithdew marked this conversation as resolved.
```bash
bun add @tanstack/ai-isolate-quickjs-bun
```

Requires Bun 1.3.14 or later. On Windows, provide a prebuilt QuickJS dynamic library via the `QUICKJS_BUN_NATIVE_LIBRARY` environment variable.

### Usage

```typescript
import { createQuickJSBunIsolateDriver } from '@tanstack/ai-isolate-quickjs-bun'

const driver = createQuickJSBunIsolateDriver({
memoryLimit: 128, // MB
timeout: 30_000, // ms
maxStackSize: 524288, // bytes (512 KiB)
})
```

### Options


| Option | Type | Default | Description |
| -------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `memoryLimit` | `number` | `128` | Maximum heap memory for the QuickJS runtime, in megabytes. |
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |
| `maxStackSize` | `number` | `524288` | Maximum call stack size in bytes (default: 512 KiB). Increase for deeply recursive code; decrease to catch runaway recursion sooner. |


### How it works

Each context gets a dedicated native QuickJS runtime with its own memory limit, stack size, and interrupt-based timeout, so contexts execute independently — unlike the WASM driver, which serializes all executions through one shared asyncified WASM module. Fatal errors (memory exhaustion, stack overflow) are detected, the VM is disposed, and a structured error is returned; create a fresh context afterwards. Console output is captured and returned with the result.

> **Bun only:** This driver requires Bun 1.3.14 or later and throws a descriptive error when creating a context on Node.js — use the Node or QuickJS WASM driver there. On Bun, prefer this driver over the WASM one: it runs QuickJS natively, and quickjs-emscripten's asyncify bridge is unreliable for async host tool calls under Bun.

---

Expand Down Expand Up @@ -129,12 +179,14 @@ const driver = createCloudflareIsolateDriver({

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `workerUrl` | `string` | — | **Required.** Full URL of the deployed Cloudflare Worker. |
| `authorization` | `string` | — | Optional value sent as the `Authorization` header on every request. Use this to prevent unauthorized access to your Worker. |
| `timeout` | `number` | `30000` | Maximum wall-clock time for the entire execution (including all tool round-trips), in milliseconds. |
| `maxToolRounds` | `number` | `10` | Maximum number of tool-call/result cycles per execution. Prevents infinite loops when generated code calls tools in a loop. |

| Option | Type | Default | Description |
| --------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `workerUrl` | `string` | — | **Required.** Full URL of the deployed Cloudflare Worker. |
| `authorization` | `string` | — | Optional value sent as the `Authorization` header on every request. Use this to prevent unauthorized access to your Worker. |
| `timeout` | `number` | `30000` | Maximum wall-clock time for the entire execution (including all tool round-trips), in milliseconds. |
| `maxToolRounds` | `number` | `10` | Maximum number of tool-call/result cycles per execution. Prevents infinite loops when generated code calls tools in a loop. |


### Deploying the Worker

Expand Down Expand Up @@ -184,7 +236,7 @@ Each round-trip adds network latency, so the `maxToolRounds` limit both prevents

## The `IsolateDriver` Interface

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

```typescript
interface IsolateDriver {
Expand Down Expand Up @@ -217,3 +269,4 @@ You can implement this interface to build a custom driver — for example, a Doc
- [Code Mode](./code-mode) — Core setup, API reference, and getting started guide
- [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

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, 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.

## Getting Started

Expand All @@ -54,6 +54,9 @@ pnpm add @tanstack/ai-isolate-node
# QuickJS WASM — no native deps, works in browsers and edge runtimes
pnpm add @tanstack/ai-isolate-quickjs

# QuickJS Bun — native QuickJS via bun:ffi, fastest option on Bun
bun add @tanstack/ai-isolate-quickjs-bun

# Cloudflare Workers — run on the edge
pnpm add @tanstack/ai-isolate-cloudflare
```
Expand Down Expand Up @@ -207,6 +210,7 @@ interface IsolateDriver {
|---------|-----------------|-------------|
| `@tanstack/ai-isolate-node` | `createNodeIsolateDriver()` | Node.js |
| `@tanstack/ai-isolate-quickjs` | `createQuickJSIsolateDriver()` | Node.js, browser, edge |
| `@tanstack/ai-isolate-quickjs-bun` | `createQuickJSBunIsolateDriver()` | Bun |
| `@tanstack/ai-isolate-cloudflare` | `createCloudflareIsolateDriver()` | Cloudflare Workers |

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), **QuickJS Bun** for Bun servers (native QuickJS via `bun:ffi`), and the **Cloudflare driver** when you deploy to Cloudflare Workers.

## 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, QuickJS Bun, and Cloudflare sandbox runtimes
7 changes: 4 additions & 3 deletions docs/comparison/vercel-ai-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Versions referenced below: TanStack AI as of this writing; Vercel AI SDK `ai@6.x
| Transcription | Stable API with word timestamps and diarization (OpenAI, Grok, ElevenLabs, fal.ai) | `transcribe()` (experimental) |
| Audio / Music Generation | `generateAudio()` for music & sound effects (Gemini, ElevenLabs, fal.ai) | - |
| Summarization | Dedicated `summarize()` with streaming and style options | - |
| Code Execution | Node.js, Cloudflare Workers, QuickJS sandboxes you run yourself | Provider-hosted code-execution tools (Anthropic, xAI, OpenAI) |
| Code Execution | Node.js, Cloudflare Workers, QuickJS (WASM + Bun-native) sandboxes you run yourself | Provider-hosted code-execution tools (Anthropic, xAI, OpenAI) |
| Code Mode Skills | LLM-writable persistent skill library | - |
| Realtime Voice | OpenAI, Grok, and ElevenLabs with VAD modes and tool support | - |
| DevTools | Isomorphic in-app panel via TanStack DevTools (all frameworks, media previews) | `devToolsMiddleware` + local inspector (server-side, dev-only) |
Expand Down Expand Up @@ -380,13 +380,14 @@ This isn't just philosophical - it means no accidental dependencies on platform-

### Code Execution Sandboxes

TanStack AI provides three isolate drivers for safe code execution in AI workflows:
TanStack AI provides four isolate drivers for safe code execution in AI workflows:

- **`@tanstack/ai-isolate-node`** - Node.js sandbox via `isolated-vm`
- **`@tanstack/ai-isolate-cloudflare`** - Cloudflare Workers sandbox
- **`@tanstack/ai-isolate-quickjs`** - QuickJS lightweight sandbox
- **`@tanstack/ai-isolate-quickjs-bun`** - Native QuickJS sandbox for Bun via `bun:ffi`

All three implement the same `IsolateDriver` interface, so you can swap execution environments without changing application code. This powers TanStack AI's code mode - where the LLM writes and executes code as part of the agent loop. A companion `@tanstack/ai-code-mode-skills` package lets you give code mode a persistent, reusable library of runtime skills. Skills are LLM-writable: the model can save working TypeScript snippets, list and reuse them across sessions, with trust strategies controlling what gets promoted to a first-class tool. The closest AI SDK analogues - Anthropic's provider-hosted code execution and developer-uploaded skills, or pre-authored file skills loaded into a sandbox - are provider-specific and static; none give the model a persistent, provider-agnostic skill library it builds itself.
All four implement the same `IsolateDriver` interface, so you can swap execution environments without changing application code. This powers TanStack AI's code mode - where the LLM writes and executes code as part of the agent loop. A companion `@tanstack/ai-code-mode-skills` package lets you give code mode a persistent, reusable library of runtime skills. Skills are LLM-writable: the model can save working TypeScript snippets, list and reuse them across sessions, with trust strategies controlling what gets promoted to a first-class tool. The closest AI SDK analogues - Anthropic's provider-hosted code execution and developer-uploaded skills, or pre-authored file skills loaded into a sandbox - are provider-specific and static; none give the model a persistent, provider-agnostic skill library it builds itself.

Vercel AI SDK does not provide built-in code execution sandboxes (though some providers expose their own server-side code execution as provider-executed tools).

Expand Down
9 changes: 6 additions & 3 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
{
"label": "TanStack AI vs Vercel AI SDK",
"to": "comparison/vercel-ai-sdk",
"addedAt": "2026-04-15"
"addedAt": "2026-04-15",
"updatedAt": "2026-06-11"
}
]
},
Expand Down Expand Up @@ -202,7 +203,8 @@
{
"label": "Code Mode",
"to": "code-mode/code-mode",
"addedAt": "2026-04-15"
"addedAt": "2026-04-15",
"updatedAt": "2026-06-11"
},
{
"label": "Showing Code Mode in the UI",
Expand All @@ -217,7 +219,8 @@
{
"label": "Code Mode Isolate Drivers",
"to": "code-mode/code-mode-isolates",
"addedAt": "2026-04-15"
"addedAt": "2026-04-15",
"updatedAt": "2026-06-11"
}
]
},
Expand Down
1 change: 1 addition & 0 deletions examples/ts-code-mode-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@tanstack/ai-isolate-cloudflare": "workspace:*",
"@tanstack/ai-isolate-node": "workspace:*",
"@tanstack/ai-isolate-quickjs": "workspace:*",
"@tanstack/ai-isolate-quickjs-bun": "workspace:*",
"@tanstack/ai-ollama": "workspace:*",
"@tanstack/ai-openai": "workspace:*",
"@tanstack/ai-react": "workspace:*",
Expand Down
Loading