Skip to content

Commit 54abae0

Browse files
jherrclaudeautofix-ci[bot]AlemTuzlak
authored
Code mode (#362)
* Pull in code-mode changes from ai-code-mode Adds code-mode packages (ai-code-mode, ai-code-mode-skills, ai-isolate-*), example app, tool registry, and devtools code-mode tab. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * more refinements * Simpler example * Fewer examples * Working skills example * Home page really coming together * Home page done * More realistic tools * Finished home page * Reworking the demo * final fixups * last few fixups * ci: apply automated fixes * fix: replace md-to-pdf with puppeteer+marked to fix provenance check md-to-pdf depends on marked@4 which lacks npm provenance, failing the CI provenance check. Use puppeteer (already a dep) + marked@15 directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: apply automated fixes * add changeset for code mode packages and revert ai-devtools changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add database tools demo route with in-memory DB Add a new demo route for database code tools using an in-memory database with three tables: customers (10 rows), products (10 rows), and purchases (25 rows). Includes two simple tools - queryTable for filtering/sorting/ selecting data and getSchemaInfo for introspection. Supports both Code Mode (execute_typescript) and regular tool-calling modes. https://claude.ai/code/session_012K7mAaWtcw5ZCGPcs88zmm * database demo * database demo * feat: add gold-standard judging, export, layout fixes, and nav rename for database demo - Add Opus-powered judge API that compares responses against gold-standard results using structured output - Add JSON export button for message arrays - Fix three-column layout so sidebars don't get pushed off screen - Remove duplicate "Try These" from left sidebar - Expose getSchemaInfo as both a code-mode and direct LLM tool - Rename nav item to "Database Demo" and move to second position Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: apply automated fixes * simplifying * simplifying * adding skills * refactoring * dashboard demo start * merging main * small tweaks * More execute prompt work * Model evals * Model evals * chore: sync lockfile with models-eval dotenv ^17.2.3 Align pnpm-lock.yaml with @tanstack/ai-code-mode-models-eval so frozen pnpm install in CI matches the manifest after sherif alignment. Made-with: Cursor * ci: apply automated fixes * ci: bump autofix-ci/action to v1.3.3 and opt into Node 24 - Pin autofix-ci/action to 7a166d75 (v1.3.3) for API reliability - Set FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 for JS action runtime deprecation Made-with: Cursor * feat(ts-code-mode-web): realtime dashboard + execute_prompt API - Replace tile orchestrator dashboard with text-mode OpenAI Realtime + execute_prompt tool - Add /api/execute-prompt (shoe catalog via executePrompt) and /api/realtime-token - Harden client tool args and OpenAI Realtime function_call id (call_id/item_id) - RealtimeClient: always send tool result for unknown tools - Remove legacy dashboard components and lib/dashboard Made-with: Cursor * Working * Merged main * Docs update * ci: apply automated fixes * final fixes * ci: apply automated fixes * ci: fix formatting and lint in ai-isolate-node Apply Prettier formatting fixes and remove unnecessary optional chain on non-nullish value flagged by ESLint. Made-with: Cursor * chore: update changeset with missing packages Add ai-event-client, ai-ollama, ai-openai, ai-client, and ai-devtools to the changeset to cover all source changes on this branch. Made-with: Cursor * fix: correct ai-devtools package name in changeset The package is @tanstack/ai-devtools-core, not @tanstack/ai-devtools. Made-with: Cursor --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Alem Tuzlak <t.zlak@hotmail.com>
1 parent b709c3d commit 54abae0

File tree

240 files changed

+38897
-93
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

240 files changed

+38897
-93
lines changed

.changeset/code-mode-packages.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@tanstack/ai': minor
3+
'@tanstack/ai-code-mode': minor
4+
'@tanstack/ai-code-mode-skills': minor
5+
'@tanstack/ai-isolate-cloudflare': minor
6+
'@tanstack/ai-isolate-node': minor
7+
'@tanstack/ai-isolate-quickjs': minor
8+
'@tanstack/ai-event-client': minor
9+
'@tanstack/ai-ollama': patch
10+
'@tanstack/ai-openai': patch
11+
'@tanstack/ai-client': patch
12+
'@tanstack/ai-devtools-core': patch
13+
---
14+
15+
Add code mode and isolate packages for secure AI code execution
16+
17+
Also includes fixes for Ollama tool call argument streaming and usage
18+
reporting, OpenAI realtime adapter handling of missing call_id/item_id,
19+
realtime client guards for missing toolCallId, and new DevtoolsChatMiddleware
20+
type export from ai-event-client.

.github/workflows/autofix.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ jobs:
1616
autofix:
1717
name: autofix
1818
runs-on: ubuntu-latest
19+
env:
20+
# Run JS actions (e.g. autofix-ci/action, still `node20` runtime) on Node 24 per
21+
# https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
22+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
1923
steps:
2024
- name: Checkout
2125
uses: actions/checkout@v6.0.2
@@ -24,6 +28,7 @@ jobs:
2428
- name: Fix formatting
2529
run: pnpm format
2630
- name: Apply fixes
27-
uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27
31+
# v1.3.3 — API endpoint reliability (see https://github.com/autofix-ci/action/releases/tag/v1.3.3)
32+
uses: autofix-ci/action@7a166d7532b277f34e16238930461bf77f9d7ed8
2833
with:
2934
commit-message: 'ci: apply automated fixes'

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,16 @@ test-traces
5858
playwright-report
5959
test-results
6060

61+
solo.yml
62+
.structured-output-skills
63+
6164
STATUS_*.md
6265

66+
# models-eval run artifacts (full candidate/gold text per model)
67+
packages/typescript/ai-code-mode/models-eval/log/
68+
69+
.skills
6370
# Only .claude.settings.json should be committed
6471
.claude/settings.local.json
65-
.claude/worktrees/*
72+
.claude/worktrees/*
73+
solo.yml

docs/guides/code-mode-isolates.md

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
---
2+
title: Code Mode Isolate Drivers
3+
id: code-mode-isolates
4+
order: 21
5+
---
6+
7+
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.
8+
9+
## Choosing a Driver
10+
11+
| | Node (`isolated-vm`) | QuickJS (WASM) | Cloudflare Workers |
12+
|---|---|---|---|
13+
| **Best for** | Server-side Node.js apps | Browsers, edge, portability | Edge deployments on Cloudflare |
14+
| **Performance** | Fast (V8 JIT) | Slower (interpreted) | Fast (V8 on Cloudflare edge) |
15+
| **Native deps** | Yes (C++ addon) | None | None |
16+
| **Browser support** | No | Yes | N/A |
17+
| **Memory limit** | Configurable | Configurable | N/A |
18+
| **Stack size limit** | N/A | Configurable | N/A |
19+
| **Setup** | `pnpm add` | `pnpm add` | Deploy a Worker first |
20+
21+
---
22+
23+
## Node.js Driver (`@tanstack/ai-isolate-node`)
24+
25+
Uses V8 isolates via the [`isolated-vm`](https://github.com/laverdet/isolated-vm) native addon. This is the fastest option for server-side Node.js applications because generated code runs in the same V8 engine as the host, under JIT compilation, with no serialization overhead beyond tool call boundaries.
26+
27+
### Installation
28+
29+
```bash
30+
pnpm add @tanstack/ai-isolate-node
31+
```
32+
33+
`isolated-vm` is a native C++ addon and must be compiled for your platform. It requires Node.js 18 or later.
34+
35+
### Usage
36+
37+
```typescript
38+
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
39+
40+
const driver = createNodeIsolateDriver({
41+
memoryLimit: 128, // MB
42+
timeout: 30_000, // ms
43+
})
44+
```
45+
46+
### Options
47+
48+
| Option | Type | Default | Description |
49+
|--------|------|---------|-------------|
50+
| `memoryLimit` | `number` | `128` | Maximum heap size for the V8 isolate, in megabytes. Execution is terminated if this limit is exceeded. |
51+
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |
52+
53+
### How it works
54+
55+
Each `execute_typescript` call creates a fresh V8 isolate. Your tools are bridged into the isolate as async reference functions — when generated code calls `external_myTool(...)`, the call crosses the isolate boundary back into the host Node.js process, executes your tool implementation, and returns the result. Console output (`log`, `error`, `warn`, `info`) is captured and returned in the execution result. The isolate is destroyed after each call.
56+
57+
---
58+
59+
## QuickJS Driver (`@tanstack/ai-isolate-quickjs`)
60+
61+
Uses [QuickJS](https://bellard.org/quickjs/) compiled to WebAssembly via Emscripten. Because the sandbox is a WASM module, it has no native dependencies and runs anywhere JavaScript runs: Node.js, browsers, Deno, Bun, and Cloudflare Workers (without deploying a separate Worker).
62+
63+
### Installation
64+
65+
```bash
66+
pnpm add @tanstack/ai-isolate-quickjs
67+
```
68+
69+
### Usage
70+
71+
```typescript
72+
import { createQuickJSIsolateDriver } from '@tanstack/ai-isolate-quickjs'
73+
74+
const driver = createQuickJSIsolateDriver({
75+
memoryLimit: 128, // MB
76+
timeout: 30_000, // ms
77+
maxStackSize: 524288, // bytes (512 KiB)
78+
})
79+
```
80+
81+
### Options
82+
83+
| Option | Type | Default | Description |
84+
|--------|------|---------|-------------|
85+
| `memoryLimit` | `number` | `128` | Maximum heap memory for the QuickJS VM, in megabytes. |
86+
| `timeout` | `number` | `30000` | Maximum wall-clock time per execution, in milliseconds. |
87+
| `maxStackSize` | `number` | `524288` | Maximum call stack size in bytes (default: 512 KiB). Increase for deeply recursive code; decrease to catch runaway recursion sooner. |
88+
89+
### How it works
90+
91+
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.
92+
93+
> **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.
94+
95+
---
96+
97+
## Cloudflare Workers Driver (`@tanstack/ai-isolate-cloudflare`)
98+
99+
Runs generated code inside a [Cloudflare Worker](https://workers.cloudflare.com/) at the edge. Your application server sends code and tool schemas to the Worker via HTTP; the Worker executes the code and calls back when it needs a tool result. This keeps your tool implementations on your server while sandboxed execution happens on Cloudflare's global network.
100+
101+
### Installation
102+
103+
```bash
104+
pnpm add @tanstack/ai-isolate-cloudflare
105+
```
106+
107+
### Usage
108+
109+
```typescript
110+
import { createCloudflareIsolateDriver } from '@tanstack/ai-isolate-cloudflare'
111+
112+
const driver = createCloudflareIsolateDriver({
113+
workerUrl: 'https://my-code-mode-worker.my-account.workers.dev',
114+
authorization: process.env.CODE_MODE_WORKER_SECRET,
115+
timeout: 30_000,
116+
maxToolRounds: 10,
117+
})
118+
```
119+
120+
### Options
121+
122+
| Option | Type | Default | Description |
123+
|--------|------|---------|-------------|
124+
| `workerUrl` | `string` || **Required.** Full URL of the deployed Cloudflare Worker. |
125+
| `authorization` | `string` || Optional value sent as the `Authorization` header on every request. Use this to prevent unauthorized access to your Worker. |
126+
| `timeout` | `number` | `30000` | Maximum wall-clock time for the entire execution (including all tool round-trips), in milliseconds. |
127+
| `maxToolRounds` | `number` | `10` | Maximum number of tool-call/result cycles per execution. Prevents infinite loops when generated code calls tools in a loop. |
128+
129+
### Deploying the Worker
130+
131+
The package exports a ready-made Worker handler at `@tanstack/ai-isolate-cloudflare/worker`. Create a `wrangler.toml` and a worker entry file:
132+
133+
```toml
134+
# wrangler.toml
135+
name = "code-mode-worker"
136+
main = "src/worker.ts"
137+
compatibility_date = "2024-01-01"
138+
139+
[unsafe]
140+
bindings = [{ name = "eval", type = "eval" }]
141+
```
142+
143+
```typescript
144+
// src/worker.ts
145+
export { default } from '@tanstack/ai-isolate-cloudflare/worker'
146+
```
147+
148+
Deploy:
149+
150+
```bash
151+
wrangler deploy
152+
```
153+
154+
### How it works
155+
156+
The driver implements a request/response loop for tool execution:
157+
158+
```
159+
Driver (your server) Worker (Cloudflare edge)
160+
───────────────────── ─────────────────────────
161+
Send: code + tool schemas ──────▶ Execute code
162+
◀────── Return: needs tool X with args Y
163+
Execute tool X locally
164+
Send: tool result ──────▶ Resume execution
165+
◀────── Return: final result / needs tool Z
166+
...repeat until done...
167+
```
168+
169+
Each round-trip adds network latency, so the `maxToolRounds` limit both prevents runaway scripts and caps the maximum number of cross-continent hops. Console output from all rounds is aggregated and returned in the final result.
170+
171+
> **Security:** The Worker requires `UNSAFE_EVAL` (local dev) or the `eval` unsafe binding (production) to execute arbitrary code. Restrict access using the `authorization` option or Cloudflare Access policies.
172+
173+
---
174+
175+
## The `IsolateDriver` Interface
176+
177+
All three drivers satisfy this interface, exported from `@tanstack/ai-code-mode`:
178+
179+
```typescript
180+
interface IsolateDriver {
181+
createContext(config: IsolateConfig): Promise<IsolateContext>
182+
}
183+
184+
interface IsolateConfig {
185+
bindings: Record<string, ToolBinding>
186+
timeout?: number
187+
memoryLimit?: number
188+
}
189+
190+
interface IsolateContext {
191+
execute(code: string): Promise<ExecutionResult>
192+
dispose(): Promise<void>
193+
}
194+
195+
interface ExecutionResult<T = unknown> {
196+
success: boolean
197+
value?: T
198+
logs: Array<string>
199+
error?: NormalizedError
200+
}
201+
```
202+
203+
You can implement this interface to build a custom driver — for example, a Docker-based sandbox or a Deno subprocess.

0 commit comments

Comments
 (0)