From a7aa3cffaef310dd489aa5288f863bbd96caa171 Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Fri, 12 Jun 2026 01:56:37 +0800 Subject: [PATCH 1/2] feat(ai-isolate): add native QuickJS Code Mode isolate driver for Bun Adds @tanstack/ai-isolate-quickjs-bun, a Code Mode IsolateDriver that runs QuickJS natively on the Bun runtime via bun:ffi (through quickjs-bun) instead of WebAssembly. It is a drop-in replacement for @tanstack/ai-isolate-quickjs on Bun servers. - Per-context native QuickJS runtime with its own memory/stack/timeout limits; contexts execute independently (the WASM driver serializes all executions through one asyncified module). - Same JSON tool-call protocol, console prefixes, and normalized MemoryLimit/StackOverflowError/DisposedError contract as the other drivers, plus a normalized TimeoutError for deadline expiry. - maxToolCalls (default 1000) and conosle log caps to bound stack and memory growth from untrusted snadbox code. - Requires Bun >= 1.3.14; throws an error on Node.js. Unit tests mirror the WASM/Node suites and run under `bun test`; the Node-side rejection test runs in normal CI. Docs, the ai-code-mode README + skill, and the code-mode example have been updated. --- .changeset/quickjs-bun-isolate-driver.md | 29 + docs/code-mode/code-mode-isolates.md | 107 ++- docs/code-mode/code-mode.md | 10 +- docs/comparison/vercel-ai-sdk.md | 7 +- docs/config.json | 9 +- examples/ts-code-mode-web/package.json | 1 + .../src/components/ToolSidebar.tsx | 8 +- .../src/lib/create-isolate-driver.ts | 8 +- examples/ts-code-mode-web/vite.config.ts | 3 +- knip.json | 3 + packages/ai-code-mode/README.md | 18 +- .../ai-code-mode/skills/ai-code-mode/SKILL.md | 31 +- packages/ai-isolate-quickjs-bun/README.md | 90 +++ .../benchmarks/compare-with-wasm.ts | 305 ++++++++ packages/ai-isolate-quickjs-bun/package.json | 64 ++ .../src/error-normalizer.ts | 102 +++ packages/ai-isolate-quickjs-bun/src/index.ts | 13 + .../src/isolate-context.ts | 598 ++++++++++++++ .../src/isolate-driver.ts | 169 ++++ .../tests/escape-attempts.test.ts | 145 ++++ .../tests/isolate-driver.test.ts | 739 ++++++++++++++++++ packages/ai-isolate-quickjs-bun/tsconfig.json | 11 + .../ai-isolate-quickjs-bun/vite.config.ts | 36 + pnpm-lock.yaml | 636 +++++++++------ 24 files changed, 2828 insertions(+), 314 deletions(-) create mode 100644 .changeset/quickjs-bun-isolate-driver.md create mode 100644 packages/ai-isolate-quickjs-bun/README.md create mode 100644 packages/ai-isolate-quickjs-bun/benchmarks/compare-with-wasm.ts create mode 100644 packages/ai-isolate-quickjs-bun/package.json create mode 100644 packages/ai-isolate-quickjs-bun/src/error-normalizer.ts create mode 100644 packages/ai-isolate-quickjs-bun/src/index.ts create mode 100644 packages/ai-isolate-quickjs-bun/src/isolate-context.ts create mode 100644 packages/ai-isolate-quickjs-bun/src/isolate-driver.ts create mode 100644 packages/ai-isolate-quickjs-bun/tests/escape-attempts.test.ts create mode 100644 packages/ai-isolate-quickjs-bun/tests/isolate-driver.test.ts create mode 100644 packages/ai-isolate-quickjs-bun/tsconfig.json create mode 100644 packages/ai-isolate-quickjs-bun/vite.config.ts diff --git a/.changeset/quickjs-bun-isolate-driver.md b/.changeset/quickjs-bun-isolate-driver.md new file mode 100644 index 000000000..1affd320d --- /dev/null +++ b/.changeset/quickjs-bun-isolate-driver.md @@ -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. diff --git a/docs/code-mode/code-mode-isolates.md b/docs/code-mode/code-mode-isolates.md index 81c447fcd..f48e09039 100644 --- a/docs/code-mode/code-mode-isolates.md +++ b/docs/code-mode/code-mode-isolates.md @@ -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 | + --- @@ -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 @@ -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 + +```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. --- @@ -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 @@ -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 { @@ -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 + diff --git a/docs/code-mode/code-mode.md b/docs/code-mode/code-mode.md index 5cad9fa1d..5e237733b 100644 --- a/docs/code-mode/code-mode.md +++ b/docs/code-mode/code-mode.md @@ -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 @@ -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 ``` @@ -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). @@ -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 @@ -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 diff --git a/docs/comparison/vercel-ai-sdk.md b/docs/comparison/vercel-ai-sdk.md index 3a0be59c4..0fc8ce844 100644 --- a/docs/comparison/vercel-ai-sdk.md +++ b/docs/comparison/vercel-ai-sdk.md @@ -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) | @@ -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). diff --git a/docs/config.json b/docs/config.json index 3a18eb12e..bbe5aa3d3 100644 --- a/docs/config.json +++ b/docs/config.json @@ -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" } ] }, @@ -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", @@ -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" } ] }, diff --git a/examples/ts-code-mode-web/package.json b/examples/ts-code-mode-web/package.json index 0f74ed7b6..f2fd025cb 100644 --- a/examples/ts-code-mode-web/package.json +++ b/examples/ts-code-mode-web/package.json @@ -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:*", diff --git a/examples/ts-code-mode-web/src/components/ToolSidebar.tsx b/examples/ts-code-mode-web/src/components/ToolSidebar.tsx index 30d9f3ebe..eb5157545 100644 --- a/examples/ts-code-mode-web/src/components/ToolSidebar.tsx +++ b/examples/ts-code-mode-web/src/components/ToolSidebar.tsx @@ -15,7 +15,7 @@ export interface LLMTool { } // Isolate VM options -export type IsolateVM = 'node' | 'quickjs' | 'cloudflare' +export type IsolateVM = 'node' | 'quickjs' | 'quickjs-bun' | 'cloudflare' export interface IsolateVMOption { id: IsolateVM @@ -103,6 +103,12 @@ export const DEFAULT_ISOLATE_VM_OPTIONS: Array = [ description: 'Lightweight JavaScript engine', available: true, }, + { + id: 'quickjs-bun', + name: 'QuickJS Bun', + description: 'Native QuickJS engine (requires running the server with Bun)', + available: true, + }, { id: 'cloudflare', name: 'Cloudflare Workers', diff --git a/examples/ts-code-mode-web/src/lib/create-isolate-driver.ts b/examples/ts-code-mode-web/src/lib/create-isolate-driver.ts index fa6b33ef5..b3b4263bc 100644 --- a/examples/ts-code-mode-web/src/lib/create-isolate-driver.ts +++ b/examples/ts-code-mode-web/src/lib/create-isolate-driver.ts @@ -1,6 +1,6 @@ import type { IsolateDriver } from '@tanstack/ai-code-mode' -export type IsolateVM = 'node' | 'quickjs' | 'cloudflare' +export type IsolateVM = 'node' | 'quickjs' | 'quickjs-bun' | 'cloudflare' const driverCache = new Map() @@ -19,6 +19,12 @@ export async function createIsolateDriver( driver = createQuickJSIsolateDriver() break } + case 'quickjs-bun': { + const { createQuickJSBunIsolateDriver } = + await import('@tanstack/ai-isolate-quickjs-bun') + driver = createQuickJSBunIsolateDriver() + break + } case 'cloudflare': { const { createCloudflareIsolateDriver } = await import('@tanstack/ai-isolate-cloudflare') diff --git a/examples/ts-code-mode-web/vite.config.ts b/examples/ts-code-mode-web/vite.config.ts index c60f52d0f..8a84f68e9 100644 --- a/examples/ts-code-mode-web/vite.config.ts +++ b/examples/ts-code-mode-web/vite.config.ts @@ -28,6 +28,7 @@ const config = defineConfig({ '@jitl/quickjs-wasmfile-release-sync', '@jitl/quickjs-wasmfile-debug-asyncify', '@jitl/quickjs-wasmfile-debug-sync', + 'quickjs-bun', 'esbuild', // Google/Gemini related CJS packages 'google-auth-library', @@ -45,7 +46,7 @@ const config = defineConfig({ ], }, optimizeDeps: { - exclude: ['isolated-vm', 'quickjs-emscripten'], + exclude: ['isolated-vm', 'quickjs-emscripten', 'quickjs-bun'], }, }) diff --git a/knip.json b/knip.json index a5e8a03e1..42cb6cc33 100644 --- a/knip.json +++ b/knip.json @@ -39,6 +39,9 @@ "packages/ai-client": { "ignoreDependencies": ["@standard-schema/spec"] }, + "packages/ai-isolate-quickjs-bun": { + "entry": ["src/index.ts", "benchmarks/*.ts"] + }, "packages/ai-react-ui": { "ignoreDependencies": ["react-dom"] }, diff --git a/packages/ai-code-mode/README.md b/packages/ai-code-mode/README.md index b21e92fe6..23e7efd7e 100644 --- a/packages/ai-code-mode/README.md +++ b/packages/ai-code-mode/README.md @@ -21,6 +21,9 @@ pnpm add @tanstack/ai-isolate-node # QuickJS WASM (browser-compatible, no native deps) pnpm add @tanstack/ai-isolate-quickjs +# Bun servers (native QuickJS via bun:ffi) +bun add @tanstack/ai-isolate-quickjs-bun + # Cloudflare Workers (edge execution) pnpm add @tanstack/ai-isolate-cloudflare ``` @@ -82,10 +85,10 @@ Creates both the `execute_typescript` tool and its matching system prompt. This **Config:** -- `driver` — An `IsolateDriver` (Node, QuickJS, or Cloudflare) +- `driver` — An `IsolateDriver` (Node, QuickJS, QuickJS Bun, or Cloudflare) - `tools` — Array of `ServerTool` or `ToolDefinition` instances. Exposed as `external_*` functions in the sandbox - `timeout` — Execution timeout in ms (default: 30000) -- `memoryLimit` — Memory limit in MB (default: 128, supported by Node and QuickJS drivers) +- `memoryLimit` — Memory limit in MB (default: 128, supported by the Node, QuickJS, and QuickJS Bun drivers) - `getSkillBindings` — Optional async function returning dynamic bindings ### `createCodeModeTool(config)` / `createCodeModeSystemPrompt(config)` @@ -102,11 +105,12 @@ These utilities are used internally and exported for custom pipelines: ## Driver Selection Guide -| Driver | Best For | Native Deps | Browser | Memory Limit | -| --------------------------------- | -------------------------------------------- | ------------------- | ------- | ------------ | -| `@tanstack/ai-isolate-node` | Server-side Node.js apps | Yes (`isolated-vm`) | No | Yes | -| `@tanstack/ai-isolate-quickjs` | Browser, edge, or no-native-dep environments | No (WASM) | Yes | Yes | -| `@tanstack/ai-isolate-cloudflare` | Cloudflare Workers deployments | No | N/A | N/A | +| Driver | Best For | Native Deps | Browser | Memory Limit | +| ---------------------------------- | -------------------------------------------- | ------------------- | ------- | ------------ | +| `@tanstack/ai-isolate-node` | Server-side Node.js apps | Yes (`isolated-vm`) | No | Yes | +| `@tanstack/ai-isolate-quickjs` | Browser, edge, or no-native-dep environments | No (WASM) | Yes | Yes | +| `@tanstack/ai-isolate-quickjs-bun` | Bun servers (native QuickJS via `bun:ffi`) | No | No | Yes | +| `@tanstack/ai-isolate-cloudflare` | Cloudflare Workers deployments | No | N/A | N/A | ## Custom Events diff --git a/packages/ai-code-mode/skills/ai-code-mode/SKILL.md b/packages/ai-code-mode/skills/ai-code-mode/SKILL.md index c769d5a94..7d82beec3 100644 --- a/packages/ai-code-mode/skills/ai-code-mode/SKILL.md +++ b/packages/ai-code-mode/skills/ai-code-mode/SKILL.md @@ -3,7 +3,8 @@ name: ai-code-mode description: > LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, - createQuickJSIsolateDriver, createCloudflareIsolateDriver), + createQuickJSIsolateDriver, createQuickJSBunIsolateDriver, + createCloudflareIsolateDriver), codeModeWithSkills() for persistent skill libraries, trust strategies, skill storage (FileSystem, LocalStorage, InMemory, Mongo), client-side execution progress via code_mode:* custom events in useChat. @@ -89,7 +90,7 @@ const stream = chat({ ### 1. Choosing an Isolate Driver -Three drivers implement the `IsolateDriver` interface. All are interchangeable. +Four drivers implement the `IsolateDriver` interface. All are interchangeable. **Node.js** (`createNodeIsolateDriver`) -- Full V8 with JIT. Fastest option. Requires `isolated-vm` native C++ addon. @@ -115,6 +116,18 @@ const driver = createQuickJSIsolateDriver({ }) ``` +**QuickJS Bun** (`createQuickJSBunIsolateDriver`) -- Native QuickJS on the Bun runtime via `bun:ffi`. Requires Bun >= 1.3.14 (throws a descriptive error on Node.js). No native deps or build step. Each context gets a dedicated QuickJS runtime with its own memory limit, stack size, and interrupt-based timeout. Recommended QuickJS option on Bun, where the WASM driver's asyncify bridge is unreliable for async host tool calls. + +```typescript +import { createQuickJSBunIsolateDriver } from '@tanstack/ai-isolate-quickjs-bun' + +const driver = createQuickJSBunIsolateDriver({ + memoryLimit: 128, // MB, default 128 + timeout: 30_000, // ms, default 30000 + maxStackSize: 524288, // bytes, default 512 KiB +}) +``` + **Cloudflare** (`createCloudflareIsolateDriver`) -- Edge execution via a deployed Cloudflare Worker. Requires a `workerUrl` pointing to your deployed worker. Network latency on each tool call. ```typescript @@ -128,11 +141,12 @@ const driver = createCloudflareIsolateDriver({ }) ``` -| Driver | Best for | Native deps | Browser support | Performance | -| ---------- | --------------------------- | --------------- | --------------- | -------------------- | -| Node | Server-side Node.js | Yes (C++ addon) | No | Fast (V8 JIT) | -| QuickJS | Browsers, edge, portability | None (WASM) | Yes | Slower (interpreted) | -| Cloudflare | Edge deployments | None | N/A | Fast (V8 on edge) | +| Driver | Best for | Native deps | Browser support | Performance | +| ----------- | --------------------------- | --------------- | --------------- | --------------------- | +| Node | Server-side Node.js | Yes (C++ addon) | No | Fast (V8 JIT) | +| QuickJS | Browsers, edge, portability | None (WASM) | Yes | Slower (interpreted) | +| QuickJS Bun | Bun servers | None | No | Fast (native QuickJS) | +| Cloudflare | Edge deployments | None | N/A | Fast (V8 on edge) | ### 2. Adding Persistent Skills with codeModeWithSkills() @@ -416,10 +430,11 @@ Source: ai-isolate-node source (probeIsolatedVm implementation) ### MEDIUM: Expecting identical behavior across isolate drivers -The three drivers have different capabilities. Same code may work in Node but fail elsewhere. +The four drivers have different capabilities. Same code may work in Node but fail elsewhere. - **Node**: Full V8 support, JIT compilation, configurable memory limit - **QuickJS**: Interpreted, limited stdlib (no File I/O), configurable stack size, asyncified execution (serialized through global queue) +- **QuickJS Bun**: Bun runtime only (throws on Node.js), native QuickJS via `bun:ffi`, dedicated runtime per context with per-context memory/stack limits and normalized `MemoryLimitError`/`StackOverflowError`/`TimeoutError` - **Cloudflare**: Network latency per tool call round-trip, `maxToolRounds` limit (default 10), requires deployed worker with `UNSAFE_EVAL` or `eval` unsafe binding Test generated code against your target driver. If you need portability, target QuickJS's subset. diff --git a/packages/ai-isolate-quickjs-bun/README.md b/packages/ai-isolate-quickjs-bun/README.md new file mode 100644 index 000000000..3eb177f4d --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/README.md @@ -0,0 +1,90 @@ +# @tanstack/ai-isolate-quickjs-bun + +Native QuickJS driver for TanStack AI Code Mode on the [Bun](https://bun.sh) runtime. Runs the same QuickJS engine as `@tanstack/ai-isolate-quickjs`, but natively through [`bun:ffi`](https://bun.sh/docs/api/ffi) instead of WebAssembly — substantially faster context creation and execution, with the same sandboxing guarantees. + +## Requirements + +- Bun `>= 1.3.14` — the driver throws a descriptive error when used on Node.js (use `@tanstack/ai-isolate-node` or `@tanstack/ai-isolate-quickjs` there). +- macOS or Linux on `x86_64`/`aarch64` work out of the box ([`quickjs-bun`](https://github.com/superpowerdotcom/quickjs-bun) compiles the vendored QuickJS sources on the fly with Bun's embedded TinyCC — no build tools needed). On Windows, point the `QUICKJS_BUN_NATIVE_LIBRARY` environment variable at a prebuilt QuickJS dynamic library. + +## Installation + +```bash +bun add @tanstack/ai-isolate-quickjs-bun +``` + +## Usage + +```typescript +import { createQuickJSBunIsolateDriver } from '@tanstack/ai-isolate-quickjs-bun' +import { createCodeModeTool } from '@tanstack/ai-code-mode' + +const driver = createQuickJSBunIsolateDriver({ + timeout: 30000, // execution timeout in ms (default: 30000) + memoryLimit: 128, // memory limit in MB (default: 128) + maxStackSize: 512 * 1024, // max stack size in bytes (default: 512 KiB) + maxToolCalls: 1000, // max host tool calls per execution (default: 1000) +}) + +const executeTypescript = createCodeModeTool({ + driver, + tools: [myTool], +}) +``` + +## Config Options + +- `timeout` — Default execution timeout in milliseconds (default: 30000) +- `memoryLimit` — Default QuickJS runtime memory limit in MB (default: 128) +- `maxStackSize` — Default QuickJS runtime max stack size in bytes (default: 524288) +- `maxToolCalls` — Maximum host tool calls per execution (default: 1000). Bounds output and memory growth from untrusted sandbox code; exceeding it throws a catchable error inside the sandbox. + +Console output is captured and returned to the model; it is bounded to 10,000 entries / ~1 MB per execution, after which a `[log output truncated]` marker is appended and further output dropped. + +## Tradeoffs vs QuickJS WASM Driver + +| | QuickJS Bun (`bun:ffi`) | QuickJS (WASM) | +| ------------ | ------------------------------ | -------------------------- | +| Runtime | Bun only | Node, browser, edge | +| Native deps | None (TinyCC compiles QuickJS) | None | +| Performance | Fast (native QuickJS) | Slower (WASM + asyncify) | +| Memory limit | Per-context runtime | Configurable | +| Concurrency | Independent contexts | Serialized (one WASM VM) | +| Best for | Bun servers | Browser, edge, portability | + +Each context gets a dedicated native QuickJS runtime, so executions on different contexts run independently — the WASM driver has to serialize all executions through one asyncified WASM module. + +## How It Works + +Uses [QuickJS](https://bellard.org/quickjs/) bound natively through [`quickjs-bun`](https://github.com/superpowerdotcom/quickjs-bun) (`bun:ffi`). The QuickJS library is compiled once per process (~100ms); each execution then creates a fresh QuickJS runtime + context (~1-2ms) with its own memory and stack limits, and tools injected as global async functions that bridge back to the host. Async tool calls resolve through QuickJS promises driven by the host event loop. + +## Runtime Limits and Errors + +- Every context enforces its own memory and stack limits via QuickJS `JS_SetMemoryLimit` / `JS_SetMaxStackSize`; timeouts use `JS_SetInterruptHandler` and also bound async tool waits. +- Exceeding limits produces normalized errors such as `MemoryLimitError`, `StackOverflowError`, or `TimeoutError`. +- Fatal limit conditions dispose the underlying VM; create a fresh context before running more code after disposal. + +## Benchmarks + +`benchmarks/compare-with-wasm.ts` compares this driver against `@tanstack/ai-isolate-quickjs` (WASM) through the public `IsolateDriver` interface: + +```bash +bun benchmarks/compare-with-wasm.ts +``` + +Representative numbers (Apple M-series, darwin/arm64; Bun 1.3.14 for this driver, Node 22 for the WASM driver): + +| Scenario (fresh context per run) | QuickJS Bun | QuickJS WASM (Node) | +| -------------------------------- | ----------: | ------------------: | +| Cold start (first context + run) | ~150 ms | ~24 ms | +| `return 1 + 1` | 0.63 ms | 13.5 ms (median) | +| 3 sequential tool calls | 0.77 ms | see note ¹ | +| 8 sequential tool calls | 0.85 ms | see note ¹ | +| compute (recursive `fib(20)`) | 4.5 ms | see note ¹ | +| `return 1 + 1` (reused context) | 0.04 ms | — | + +¹ In our benchmark runs, the WASM driver's asyncified host tool calls repeatedly crashed the shared WASM module (`memory access out of bounds`) and hung subsequent executions, on both Node 22 and Bun 1.3.14 — e.g. deterministically after running executions with 1, 2, 3, then 4 sequential awaited tool calls in one process. Sync-only workloads were unaffected. + +## License + +MIT diff --git a/packages/ai-isolate-quickjs-bun/benchmarks/compare-with-wasm.ts b/packages/ai-isolate-quickjs-bun/benchmarks/compare-with-wasm.ts new file mode 100644 index 000000000..7fe07a9af --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/benchmarks/compare-with-wasm.ts @@ -0,0 +1,305 @@ +/** + * Benchmark: quickjs-bun (native, bun:ffi) vs quickjs-emscripten (WASM). + * + * Both drivers are exercised through the public IsolateDriver interface so + * the numbers include each driver's marshalling/bridging overhead. + * + * Run under Bun (benchmarks both drivers): + * + * bun benchmarks/compare-with-wasm.ts + * + * Run under Node (benchmarks the WASM driver only) + * + * pnpm exec tsx benchmarks/compare-with-wasm.ts + */ +import * as os from 'node:os' +import process from 'node:process' +import { createQuickJSIsolateDriver } from '@tanstack/ai-isolate-quickjs' +import { createQuickJSBunIsolateDriver } from '../src/index' +import type { IsolateDriver, ToolBinding } from '@tanstack/ai-code-mode' + +const FRESH_CONTEXT_ITERATIONS = 30 +const WARM_CONTEXT_ITERATIONS = 100 +const WARMUP_ITERATIONS = 3 + +interface Stats { + mean: number + p50: number + p95: number +} + +interface ScenarioResult { + name: string + stats: Stats + perSecond: number +} + +function summarize(samplesMs: Array): Stats { + const sorted = [...samplesMs].sort((a, b) => a - b) + const at = (q: number) => + sorted[Math.min(sorted.length - 1, Math.floor(q * sorted.length))] ?? 0 + const mean = sorted.reduce((sum, v) => sum + v, 0) / sorted.length + return { mean, p50: at(0.5), p95: at(0.95) } +} + +function echoBinding(): ToolBinding { + return { + name: 'echo', + description: 'echo tool', + inputSchema: { type: 'object', properties: {} }, + execute: (args: unknown) => Promise.resolve(args), + } +} + +async function runOnce( + driver: IsolateDriver, + code: string, + bindings: Record = {}, +): Promise { + const context = await driver.createContext({ bindings, timeout: 30000 }) + try { + const result = await context.execute(code) + if (!result.success) { + throw new Error( + `benchmark execution failed: ${result.error?.name}: ${result.error?.message}`, + ) + } + } finally { + await context.dispose() + } +} + +/** + * quickjs-emscripten's asyncify bridge is known to break under Bun (host + * tool calls crash with "Out of bounds memory access" and never settle), so + * every scenario is raced against a guard. A scenario that hangs poisons + * the WASM driver's global execution queue, so the remaining scenarios are + * skipped once that happens. + */ +async function withGuard( + fn: () => Promise, + guardMs: number, +): Promise<{ ok: true; value: T } | { ok: false; reason: string }> { + let timer: ReturnType | undefined + const guard = new Promise<{ ok: false; reason: string }>((resolve) => { + timer = setTimeout( + () => resolve({ ok: false, reason: `hung (> ${guardMs}ms)` }), + guardMs, + ) + }) + try { + return await Promise.race([ + fn().then((value) => ({ ok: true as const, value })), + guard, + ]) + } catch (error) { + return { + ok: false, + reason: error instanceof Error ? error.message : String(error), + } + } finally { + clearTimeout(timer) + } +} + +async function measure( + iterations: number, + fn: () => Promise, +): Promise<{ stats: Stats; perSecond: number }> { + for (let i = 0; i < WARMUP_ITERATIONS; i++) await fn() + const samples: Array = [] + const startedAt = performance.now() + for (let i = 0; i < iterations; i++) { + const start = performance.now() + await fn() + samples.push(performance.now() - start) + } + const totalSeconds = (performance.now() - startedAt) / 1000 + return { stats: summarize(samples), perSecond: iterations / totalSeconds } +} + +const SCENARIOS: Array<{ + name: string + code: string + bindings?: Record +}> = [ + { + name: 'trivial (`return 1 + 1`)', + code: 'return 1 + 1', + }, + { + // The WASM driver can complete at most 3 sequential asyncified host + // calls per execution (see the 8-call scenario below), so this is the + // largest like-for-like tool-call comparison. + name: '3 sequential tool calls', + code: ` + let out = [] + for (let i = 0; i < 3; i++) { + out.push(await echo({ i })) + } + return out.length + `, + bindings: { echo: echoBinding() }, + }, + { + // quickjs-emscripten's asyncify bridge crashes ("memory access out of + // bounds") and hangs at >= 4 sequential awaited host calls in one + // execution — on both Node and Bun. Kept to document the limit; the + // native driver has no such cap. + name: '8 sequential tool calls', + code: ` + let out = [] + for (let i = 0; i < 8; i++) { + out.push(await echo({ i })) + } + return out.length + `, + bindings: { echo: echoBinding() }, + }, + { + name: 'compute (fib(20), recursive)', + code: ` + function fib(n) { return n < 2 ? n : fib(n - 1) + fib(n - 2) } + return fib(20) + `, + }, + { + name: 'json (build + roundtrip 5k rows)', + code: ` + const rows = [] + for (let i = 0; i < 5000; i++) { + rows.push({ id: i, name: 'row-' + i, score: i * 1.5 }) + } + return JSON.parse(JSON.stringify(rows)).length + `, + }, +] + +async function benchmarkDriver( + label: string, + driver: IsolateDriver, +): Promise { + console.log(`\n## ${label}`) + + // Cold start: first context creation pays one-time engine initialization + // (TinyCC compile for quickjs-bun, WASM instantiation for emscripten). + const coldStart = performance.now() + const cold = await withGuard(() => runOnce(driver, 'return 1'), 30000) + if (!cold.ok) { + console.log(`\ncold start FAILED: ${cold.reason} — skipping driver\n`) + return + } + const coldMs = performance.now() - coldStart + console.log( + `\ncold start (first context + execute): ${coldMs.toFixed(1)}ms\n`, + ) + + const results: Array = [] + let poisoned = false + + for (const scenario of SCENARIOS) { + const name = `${scenario.name} — fresh context per run` + if (poisoned) { + results.push({ name, failed: 'skipped (driver hung earlier)' }) + continue + } + const fresh = await withGuard( + () => + measure(FRESH_CONTEXT_ITERATIONS, () => + runOnce(driver, scenario.code, scenario.bindings), + ), + 120000, + ) + if (fresh.ok) { + results.push({ + name, + stats: fresh.value.stats, + perSecond: fresh.value.perSecond, + }) + } else { + results.push({ name, failed: fresh.reason }) + if (fresh.reason.startsWith('hung')) poisoned = true + } + } + + // Warm-context variant for the trivial case isolates per-execute overhead + // from context creation cost. + if (!poisoned) { + const warm = await withGuard(async () => { + const context = await driver.createContext({ + bindings: {}, + timeout: 30000, + }) + try { + return await measure(WARM_CONTEXT_ITERATIONS, async () => { + const result = await context.execute('return 1 + 1') + if (!result.success) throw new Error('warm execution failed') + }) + } finally { + await context.dispose() + } + }, 120000) + const name = 'trivial (`return 1 + 1`) — reused context' + if (warm.ok) { + results.push({ + name, + stats: warm.value.stats, + perSecond: warm.value.perSecond, + }) + } else { + results.push({ name, failed: warm.reason }) + } + } + + console.log('| Scenario | mean | p50 | p95 | ops/s |') + console.log('| --- | ---: | ---: | ---: | ---: |') + for (const result of results) { + if ('failed' in result) { + console.log(`| ${result.name} | — | — | — | FAILED: ${result.failed} |`) + continue + } + console.log( + `| ${result.name} | ${result.stats.mean.toFixed(2)}ms | ${result.stats.p50.toFixed(2)}ms | ${result.stats.p95.toFixed(2)}ms | ${result.perSecond.toFixed(0)} |`, + ) + } +} + +async function main(): Promise { + // A hung asyncify call surfaces as a late unhandled rejection / + // uncaught WASM RuntimeError; keep the benchmark alive so the table + // still prints. + process.on('unhandledRejection', (reason) => { + console.error( + `[unhandled rejection] ${reason instanceof Error ? reason.message : String(reason)}`, + ) + }) + process.on('uncaughtException', (error) => { + console.error(`[uncaught exception] ${error.message}`) + }) + + const isBun = typeof Bun !== 'undefined' + const runtime = isBun ? `Bun ${Bun.version}` : `Node ${process.version}` + console.log( + `isolate driver benchmark — ${runtime}, ${process.platform}/${process.arch}, ${os.cpus().length} CPUs`, + ) + console.log( + `iterations: fresh-context=${FRESH_CONTEXT_ITERATIONS}, warm-context=${WARM_CONTEXT_ITERATIONS}, warmup=${WARMUP_ITERATIONS}`, + ) + + if (isBun) { + await benchmarkDriver( + '@tanstack/ai-isolate-quickjs-bun (native QuickJS via bun:ffi)', + createQuickJSBunIsolateDriver(), + ) + } + + await benchmarkDriver( + '@tanstack/ai-isolate-quickjs (QuickJS WASM via quickjs-emscripten)', + createQuickJSIsolateDriver(), + ) +} + +await main() +// Force exit: a poisoned WASM execution queue can otherwise keep stuck +// handles alive after the benchmark completes. +process.exit(0) diff --git a/packages/ai-isolate-quickjs-bun/package.json b/packages/ai-isolate-quickjs-bun/package.json new file mode 100644 index 000000000..9acb141ed --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/package.json @@ -0,0 +1,64 @@ +{ + "name": "@tanstack/ai-isolate-quickjs-bun", + "version": "0.0.0", + "description": "Native QuickJS sandbox driver for TanStack AI Code Mode TypeScript execution on Bun via bun:ffi.", + "author": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/ai.git", + "directory": "packages/ai-isolate-quickjs-bun" + }, + "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, + "files": [ + "dist", + "src" + ], + "engines": { + "bun": ">=1.3.14" + }, + "scripts": { + "build": "vite build", + "clean": "premove ./build ./dist", + "lint:fix": "eslint ./src --fix", + "test:build": "publint --strict", + "test:bun": "bun test ./tests", + "test:eslint": "eslint ./src", + "test:lib": "vitest --passWithNoTests", + "test:lib:dev": "pnpm test:lib --watch", + "test:types": "tsc" + }, + "keywords": [ + "ai", + "ai-sdk", + "typescript", + "tanstack", + "code-mode", + "quickjs", + "bun", + "ffi", + "isolate", + "sandbox", + "code-execution" + ], + "dependencies": { + "quickjs-bun": "0.1.2" + }, + "peerDependencies": { + "@tanstack/ai-code-mode": "workspace:*" + }, + "devDependencies": { + "@tanstack/ai-isolate-quickjs": "workspace:*", + "@types/bun": "^1.3.14", + "@vitest/coverage-v8": "4.0.14" + } +} diff --git a/packages/ai-isolate-quickjs-bun/src/error-normalizer.ts b/packages/ai-isolate-quickjs-bun/src/error-normalizer.ts new file mode 100644 index 000000000..3fafac9e5 --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/src/error-normalizer.ts @@ -0,0 +1,102 @@ +import type { NormalizedError } from '@tanstack/ai-code-mode' + +const MEMORY_LIMIT_ERROR = 'MemoryLimitError' +const STACK_OVERFLOW_ERROR = 'StackOverflowError' +const TIMEOUT_ERROR = 'TimeoutError' + +/** + * Whether this normalized error indicates the QuickJS VM should not be reused + * (memory or stack limit exceeded). + */ +export function isFatalQuickJSLimitError(error: NormalizedError): boolean { + return ( + error.name === MEMORY_LIMIT_ERROR || error.name === STACK_OVERFLOW_ERROR + ) +} + +/** + * Normalized error for code that exhausted the QuickJS heap so thoroughly + * that QuickJS could not even allocate an Error object — it throws a bare + * `null` exception value in that situation. + */ +export function memoryLimitError(stack?: string): NormalizedError { + return { + name: MEMORY_LIMIT_ERROR, + message: 'Code execution exceeded memory limit', + ...(stack !== undefined && { stack }), + } +} + +/** + * Normalize various error types into a consistent format + */ +export function normalizeError(error: unknown): NormalizedError { + if (error instanceof Error) { + const msg = error.message + const lower = msg.toLowerCase() + + if ( + lower.includes('out of memory') || + lower.includes('memory alloc') || + (error.name === 'InternalError' && lower.includes('memory')) + ) { + return { + name: MEMORY_LIMIT_ERROR, + message: 'Code execution exceeded memory limit', + stack: error.stack, + } + } + + if (lower.includes('stack overflow')) { + return { + name: STACK_OVERFLOW_ERROR, + message: 'Code execution exceeded stack size limit', + stack: error.stack, + } + } + + // quickjs-bun reports deadline expiry as a TimeoutError ("QuickJS + // execution timed out"); a raw QuickJS interrupt surfaces as + // `InternalError: interrupted`. + if ( + error.name === TIMEOUT_ERROR || + (error.name === 'InternalError' && msg === 'interrupted') + ) { + return { + name: TIMEOUT_ERROR, + message: + error.name === TIMEOUT_ERROR ? msg : 'Code execution timed out', + stack: error.stack, + } + } + + return { + name: error.name, + message: error.message, + stack: error.stack, + } + } + + if (typeof error === 'string') { + return { + name: 'Error', + message: error, + } + } + + if (typeof error === 'object' && error !== null) { + const errObj = error as Record + return { + name: String(errObj.name || 'Error'), + message: String(errObj.message || 'Unknown error'), + ...(errObj['stack'] !== undefined && { + stack: String(errObj['stack']), + }), + } + } + + return { + name: 'UnknownError', + message: String(error), + } +} diff --git a/packages/ai-isolate-quickjs-bun/src/index.ts b/packages/ai-isolate-quickjs-bun/src/index.ts new file mode 100644 index 000000000..70b05e228 --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/src/index.ts @@ -0,0 +1,13 @@ +export { + createQuickJSBunIsolateDriver, + type QuickJSBunIsolateDriverConfig, +} from './isolate-driver' + +// Re-export types from ai-code-mode for convenience +export type { + IsolateDriver, + IsolateConfig, + IsolateContext, + ExecutionResult, + NormalizedError, +} from '@tanstack/ai-code-mode' diff --git a/packages/ai-isolate-quickjs-bun/src/isolate-context.ts b/packages/ai-isolate-quickjs-bun/src/isolate-context.ts new file mode 100644 index 000000000..3cff3feb6 --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/src/isolate-context.ts @@ -0,0 +1,598 @@ +import { wrapCode } from '@tanstack/ai-code-mode' +import { + isFatalQuickJSLimitError, + memoryLimitError, + normalizeError, +} from './error-normalizer' +import type { + ExecutionResult, + IsolateContext, + NormalizedError, + ToolBinding, +} from '@tanstack/ai-code-mode' +import type * as QuickJSBun from 'quickjs-bun' +import type { Deferred, JSContext, JSRuntime, JSValue } from 'quickjs-bun' + +/** + * The `quickjs-bun` module namespace. The module is imported dynamically by + * the driver (it only loads under the Bun runtime), so the classes and enums + * it exports are threaded through here instead of being imported statically. + */ +export type QuickJSBunModule = typeof QuickJSBun + +/** + * An in-flight host tool call. The sandbox holds a QuickJS promise that is + * resolved from the host once the binding's `execute` settles; `settled` + * lets the execution loop wait for host work without polling. + */ +interface HostTask { + deferred: Deferred + settle: () => void + settled: Promise +} + +/** + * Result envelope passed across the sandbox boundary as a JSON string. + */ +interface ToolResultEnvelope { + success: boolean + value?: unknown + error?: string +} + +/** + * Caps on captured console output. Logs are held on the host and flow back + * to the model, so an unbounded `while (true) console.log(...)` loop in + * untrusted code could grow host memory without ever tripping the sandbox + * heap limit (the sandbox only holds one string at a time). Once either cap + * is reached a single truncation marker is appended and further output is + * dropped for the rest of the execution. + */ +const MAX_LOG_ENTRIES = 10_000 +const MAX_LOG_BYTES = 1_000_000 + +/** Default ceiling on host tool-call invocations per execution. */ +export const DEFAULT_MAX_TOOL_CALLS = 1000 + +/** Placeholder used when a console argument cannot be coerced to a string. */ +const UNPRINTABLE_LOG_VALUE = '[unprintable]' + +/** + * Rebuild a throwable carrying a normalized error's name/message/stack so it + * round-trips through `normalizeError` (which preserves the name, keeping + * fatal-limit classification intact). + */ +function normalizedErrorToThrowable(error: NormalizedError): Error { + const throwable = new Error(error.message) + throwable.name = error.name + if (error.stack !== undefined) throwable.stack = error.stack + return throwable +} + +/** + * Generic wrapper factory evaluated once per context. Tool functions are + * created by calling it with the host implementation and installed on the + * global object with `setGlobal`, so binding names are never interpolated + * into evaluated source code. + */ +const TOOL_WRAPPER_FACTORY = `(function (impl) { + return async function (input) { + const resultJson = await impl(JSON.stringify(input ?? {})); + const result = JSON.parse(resultJson); + if (!result.success) { + throw new Error(result.error); + } + return result.value; + }; +})` + +/** + * IsolateContext implementation backed by a dedicated native QuickJS + * runtime + context pair (via `quickjs-bun`). + */ +export class QuickJSBunIsolateContext implements IsolateContext { + private readonly quickjs: QuickJSBunModule + private readonly runtime: JSRuntime + private readonly vm: JSContext + private readonly timeout: number + private readonly maxToolCalls: number + private readonly logs: Array = [] + private logBytes = 0 + private logTruncated = false + private readonly tasks = new Set() + private toolCallsUsed = 0 + private disposed = false + /** + * A VM-level failure raised while settling a host tool call (e.g. the + * sandbox heap was exhausted when allocating the result string). It is + * surfaced through the execution loop rather than left to escape the + * floating settle callback as an unhandled rejection. + */ + private hostSettleError: NormalizedError | undefined + /** + * Serializes executions on this context. A context only ever runs one + * program at a time; QuickJS contexts are single-threaded and the + * execution loop drives the runtime's job queue. + */ + private execQueue: Promise = Promise.resolve() + + constructor(options: { + quickjs: QuickJSBunModule + runtime: JSRuntime + vm: JSContext + timeout: number + maxToolCalls: number + bindings: Record + }) { + this.quickjs = options.quickjs + this.runtime = options.runtime + this.vm = options.vm + this.timeout = options.timeout + this.maxToolCalls = options.maxToolCalls + this.installConsole() + this.installBindings(options.bindings) + } + + async execute(code: string): Promise> { + if (this.disposed) { + return this.disposedResult() + } + + // Serialize through the per-context queue so a second execute (or a + // concurrent dispose) never interleaves with an in-flight run. + let release!: () => void + const myTurn = new Promise((resolve) => { + release = resolve + }) + const waitForPrev = this.execQueue + this.execQueue = myTurn + + await waitForPrev + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- dispose() may run while awaiting the queue + if (this.disposed) { + release() + return this.disposedResult() + } + + this.logs.length = 0 + this.logBytes = 0 + this.logTruncated = false + this.toolCallsUsed = 0 + this.hostSettleError = undefined + + try { + const value = await this.runToCompletion(wrapCode(code)) + return { + success: true, + value: value as T, + logs: [...this.logs], + } + } catch (error) { + return this.fail(error) + } finally { + // Abandon host tool calls that are still in flight (e.g. after a + // timeout) so a late completion cannot touch the VM. + this.abortTasks() + release() + } + } + + async dispose(): Promise { + if (this.disposed) return + + // Wait for any in-flight execution to finish before freeing the + // runtime; the execution loop touches native handles throughout. + await this.execQueue + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- a fatal limit error may dispose the VM while awaiting the queue + if (this.disposed) return + this.disposed = true + this.abortTasks() + this.runtime.dispose() + } + + /** + * Evaluate the wrapped program and drive the QuickJS job queue (and any + * in-flight host tool calls) until the program's promise settles or the + * deadline passes. Returns the parsed result value. + */ + private async runToCompletion(wrappedCode: string): Promise { + const { QuickJSPromiseState, JSException } = this.quickjs + const deadline = performance.now() + this.timeout + + // The synchronous portion of the program is bounded by the QuickJS + // interrupt handler; async continuations are bounded by the deadline + // checks in the loop below. + const resultHandle = this.vm.evalCode(wrappedCode, { + filename: '', + timeoutMs: this.timeout, + }) + + let settledHandle: JSValue + try { + if (resultHandle.promiseState === QuickJSPromiseState.NOT_PROMISE) { + // wrapCode always produces an async IIFE, but stay defensive. + settledHandle = resultHandle.dup() + } else { + for (;;) { + const state = resultHandle.promiseState + if (state === QuickJSPromiseState.FULFILLED) { + settledHandle = resultHandle.promiseResult() + break + } + if (state === QuickJSPromiseState.REJECTED) { + throw new JSException(resultHandle.promiseResult()) + } + + // A host tool call failed to settle the sandbox promise because + // the VM itself errored (e.g. OOM allocating the result string). + // Surface it here so fail() can classify it and release the VM if + // it was fatal, rather than letting it escape as an unhandled + // rejection from the floating settle callback. + if (this.hostSettleError !== undefined) { + throw normalizedErrorToThrowable(this.hostSettleError) + } + + const remainingMs = deadline - performance.now() + if (remainingMs <= 0) { + throw this.timeoutError() + } + + // Run one queued microtask (promise reaction) if there is one... + if (this.runtime.executePendingJob(Math.max(1, remainingMs))) { + continue + } + + // ...otherwise the program is waiting on host work. A settle + // failure raised while draining the last task is caught by the + // hostSettleError check at the top of the next iteration before we + // ever reach this branch. + if (this.tasks.size === 0) { + throw new Error( + 'Code execution is pending on a promise that no host work will ever resolve', + ) + } + await this.waitForAnyTask(remainingMs) + } + } + } finally { + resultHandle.dispose() + } + + try { + const dumped = this.vm.dump(settledHandle) + + // The wrapper returns JSON.stringify(userResult) — parse it back. + // A bare string that isn't valid JSON is returned as-is, and code + // that returned nothing yields undefined. + if (typeof dumped === 'string') { + try { + return JSON.parse(dumped) + } catch { + return dumped + } + } + return dumped + } finally { + settledHandle.dispose() + } + } + + /** Wait until any in-flight host tool call settles, or `timeoutMs` passes. */ + private async waitForAnyTask(timeoutMs: number): Promise { + const settled = Array.from(this.tasks, (task) => task.settled) + let timer: ReturnType | undefined + try { + await Promise.race([ + Promise.race(settled), + new Promise((resolve) => { + // Resolve (not reject): the execution loop re-checks the deadline. + timer = setTimeout(resolve, Math.max(1, timeoutMs)) + }), + ]) + } finally { + clearTimeout(timer) + } + } + + private installConsole(): void { + const { vm } = this + const methods: Array<[name: string, prefix: string]> = [ + ['log', ''], + ['error', 'ERROR'], + ['warn', 'WARN'], + ['info', 'INFO'], + ] + + const consoleObj = vm.newObject() + try { + for (const [method, prefix] of methods) { + const fn = vm.newFunction((...args) => { + const parts = args.map((arg) => this.stringifyConsoleArg(arg)) + const msg = prefix ? `${prefix}: ${parts.join(' ')}` : parts.join(' ') + this.pushLog(msg) + }) + try { + consoleObj.setProp(method, fn) + } finally { + fn.dispose() + } + } + vm.setGlobal('console', consoleObj) + } finally { + consoleObj.dispose() + } + } + + /** + * Coerce a console argument to a string. quickjs-bun's `JSValue.toString()` + * asserts the value is already a string and throws for numbers, objects, + * booleans, etc.; `coerceToString()` performs a real `ToString` (matching + * the WASM driver's `getString`). A coercion that throws (e.g. a symbol or + * a `toString` that throws) degrades to a placeholder rather than aborting + * the whole execution. + */ + private stringifyConsoleArg(arg: JSValue): string { + const { JSException } = this.quickjs + try { + const coerced = arg.coerceToString() + try { + return coerced.toString() + } finally { + coerced.dispose() + } + } catch (error) { + if (error instanceof JSException) error.dispose() + return UNPRINTABLE_LOG_VALUE + } + } + + /** Append a captured log line, enforcing the entry-count and byte caps. */ + private pushLog(msg: string): void { + if (this.logTruncated) return + if ( + this.logs.length >= MAX_LOG_ENTRIES || + this.logBytes + msg.length > MAX_LOG_BYTES + ) { + this.logTruncated = true + this.logs.push('[log output truncated]') + return + } + this.logs.push(msg) + this.logBytes += msg.length + } + + private installBindings(bindings: Record): void { + const { vm } = this + const entries = Object.entries(bindings) + if (entries.length === 0) return + + const factory = vm.evalCode(TOOL_WRAPPER_FACTORY, { + filename: '', + }) + try { + for (const [name, binding] of entries) { + const impl = vm.newFunction((argsHandle) => + this.runBinding(binding, argsHandle), + ) + try { + const wrapped = vm.callFunction(factory, vm.undefined, impl) + try { + vm.setGlobal(name, wrapped) + } finally { + wrapped.dispose() + } + } finally { + impl.dispose() + } + } + } finally { + factory.dispose() + } + } + + /** + * Host side of a tool call. Invoked synchronously from inside the VM; + * returns a QuickJS promise immediately and settles it from the host + * once `binding.execute` finishes. Never rejects the promise for tool + * errors — failures travel in the JSON envelope so the sandbox wrapper + * can rethrow them as regular errors. + */ + private runBinding( + binding: ToolBinding, + argsHandle: JSValue | undefined, + ): JSValue { + const { vm } = this + + // Bound the number of host tool calls per execution. Untrusted sandbox + // code can otherwise fan out (e.g. `Promise.all` over a huge array) into + // unbounded concurrent host work — the deadline only bounds wall-clock, + // not the burst. Throwing here surfaces as a catchable error at the call + // site inside the sandbox. + if (this.toolCallsUsed >= this.maxToolCalls) { + throw new Error( + `Exceeded the maximum of ${this.maxToolCalls} tool calls per execution`, + ) + } + this.toolCallsUsed++ + + const deferred = vm.newPromise() + const promise = deferred.promise.dup() + + let settle: () => void = () => undefined + const settledPromise = new Promise((resolve) => { + settle = resolve + }) + const task: HostTask = { deferred, settle, settled: settledPromise } + this.tasks.add(task) + + const settleWith = (envelope: ToolResultEnvelope): void => { + // The task may have been abandoned by a timeout or dispose — never + // touch the VM in that case. + if (this.disposed || !this.tasks.has(task)) return + this.tasks.delete(task) + try { + let json: string + try { + json = JSON.stringify(envelope) + } catch (error) { + json = JSON.stringify({ + success: false, + error: `Tool result is not JSON-serializable: ${ + error instanceof Error ? error.message : String(error) + }`, + }) + } + const handle = vm.newString(json) + try { + deferred.resolve(handle) + } finally { + handle.dispose() + } + } catch (error) { + // Allocating the result string or resolving the promise can fail if + // the sandbox heap is exhausted. Record it so the execution loop can + // classify it (and release the VM if fatal) instead of letting it + // escape the floating async callback as an unhandled rejection. + this.hostSettleError ??= this.toNormalizedError(error) + } finally { + deferred.dispose() + task.settle() + } + } + + // The wrapper always passes a JSON string, but degrade gracefully if + // the handle dumps to something else. + let argsJson = '{}' + try { + const dumped = vm.dump(argsHandle ?? vm.undefined) + if (typeof dumped === 'string') { + argsJson = dumped + } + } catch (error) { + // Fall through with empty args (JSON.parse below cannot fail on '{}'). + // dump() rethrows VM failures as a JSException whose owned value must + // be released. + if (error instanceof this.quickjs.JSException) error.dispose() + } + + void (async () => { + let envelope: ToolResultEnvelope + try { + const args: unknown = JSON.parse(argsJson) + const value = await binding.execute(args) + envelope = { success: true, value } + } catch (error) { + envelope = { + success: false, + error: error instanceof Error ? error.message : String(error), + } + } + settleWith(envelope) + })() + + return promise + } + + /** Abandon all in-flight host tool calls and release their VM handles. */ + private abortTasks(): void { + for (const task of this.tasks) { + task.deferred.dispose() + task.settle() + } + this.tasks.clear() + } + + private fail(error: unknown): ExecutionResult { + const normalized = this.toNormalizedError(error) + if (isFatalQuickJSLimitError(normalized)) { + this.releaseVmAfterFatalLimit() + } + return { + success: false, + error: normalized, + logs: [...this.logs], + } + } + + private toNormalizedError(error: unknown): NormalizedError { + const { JSException } = this.quickjs + if (error instanceof JSException) { + try { + const value = error.value + // QuickJS throws a bare `null` exception value when the heap is too + // exhausted to allocate an Error object. (A literal `throw null` in + // sandbox code is indistinguishable and is treated the same way.) + if (value.type === 'null') { + return memoryLimitError(error.stack) + } + // A thrown plain object/array surfaces through quickjs-bun's + // JSException as the generic "QuickJS object was thrown"; recover its + // `message` (and `name`) so the model still gets useful feedback for + // self-correction — parity with the WASM driver. + if (value.type === 'object' || value.type === 'array') { + const message = this.readValueProp(value, 'message') + if (message !== undefined) { + return { + name: this.readValueProp(value, 'name') ?? error.name, + message, + ...(error.stack !== undefined && { stack: error.stack }), + } + } + } + return normalizeError(error) + } finally { + error.dispose() + } + } + return normalizeError(error) + } + + /** + * Read a string property from a thrown QuickJS value, tolerating throwing + * getters (the value is attacker-controlled). Returns undefined on any + * failure and releases the owned exception in that case. + */ + private readValueProp(value: JSValue, name: string): string | undefined { + try { + return value.errorProperty(name) + } catch (error) { + if (error instanceof this.quickjs.JSException) error.dispose() + return undefined + } + } + + /** + * After a memory/stack limit error the QuickJS runtime may be left in an + * unusable state — release it eagerly so the host process reclaims the + * native memory. Matches the QuickJS WASM driver's behavior. + */ + private releaseVmAfterFatalLimit(): void { + if (this.disposed) return + this.disposed = true + this.abortTasks() + try { + this.runtime.dispose() + } catch { + // ignore if the runtime is already torn down + } + } + + private timeoutError(): Error { + const error = new Error(`Code execution timed out after ${this.timeout}ms`) + error.name = 'TimeoutError' + return error + } + + private disposedResult(): ExecutionResult { + return { + success: false, + error: { + name: 'DisposedError', + message: 'Context has been disposed', + }, + logs: [], + } + } +} diff --git a/packages/ai-isolate-quickjs-bun/src/isolate-driver.ts b/packages/ai-isolate-quickjs-bun/src/isolate-driver.ts new file mode 100644 index 000000000..f368b48df --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/src/isolate-driver.ts @@ -0,0 +1,169 @@ +import { + DEFAULT_MAX_TOOL_CALLS, + QuickJSBunIsolateContext, +} from './isolate-context' +import type { + IsolateConfig, + IsolateContext, + IsolateDriver, +} from '@tanstack/ai-code-mode' +import type { QuickJS } from 'quickjs-bun' +import type { QuickJSBunModule } from './isolate-context' + +/** Default execution timeout in ms (matches the other isolate drivers). */ +const DEFAULT_TIMEOUT_MS = 30000 + +/** Default memory limit in MB (matches the other isolate drivers). */ +const DEFAULT_MEMORY_LIMIT_MB = 128 + +/** Default max stack size in bytes (matches the QuickJS WASM driver). */ +const DEFAULT_MAX_STACK_SIZE_BYTES = 512 * 1024 + +/** + * quickjs-bun's exports map only declares a `bun` condition, so build- and + * test-time resolvers running on Node.js cannot resolve it. The non-literal + * specifier keeps the import out of Vite's static analysis; it only ever + * executes under the Bun runtime. + */ +const QUICKJS_BUN_SPECIFIER = 'quickjs-bun' + +function importQuickJSBun(): Promise { + return import(/* @vite-ignore */ QUICKJS_BUN_SPECIFIER) +} + +/** + * The QuickJS library is loaded once per process: `quickjs-bun` compiles the + * vendored QuickJS C sources with Bun's embedded TinyCC on first use + * (~100ms), after which creating a runtime + context costs ~1-2ms. + */ +let libraryPromise: Promise | undefined + +async function loadQuickJSLibrary(): Promise { + libraryPromise ??= importQuickJSBun().then((mod) => new mod.QuickJS()) + try { + return await libraryPromise + } catch (error) { + // Don't cache failures (e.g. a missing prebuilt library path on + // Windows) so a corrected environment can retry. + libraryPromise = undefined + throw error + } +} + +/** + * Configuration for the QuickJS Bun isolate driver + */ +export interface QuickJSBunIsolateDriverConfig { + /** + * Default execution timeout in ms (default: 30000) + */ + timeout?: number + + /** + * Default memory limit in MB (default: 128). + * Applied via QuickJS `JS_SetMemoryLimit` on the per-context runtime. + */ + memoryLimit?: number + + /** + * Default max stack size in bytes (default: 512 KiB). + * Applied via QuickJS `JS_SetMaxStackSize` on the per-context runtime. + */ + maxStackSize?: number + + /** + * Maximum number of host tool calls a single execution may make (default: + * 1000). Bounds output and memory growth from untrusted sandbox code (e.g. a + * `Promise.all` over a huge array); exceeding it throws a catchable error + * inside the sandbox. The execution timeout still bounds wall-clock time. + */ + maxToolCalls?: number +} + +/** + * Create a QuickJS isolate driver for the Bun runtime + * + * This driver runs QuickJS natively through `bun:ffi` (via `quickjs-bun`) + * instead of WebAssembly. Each context gets its own QuickJS runtime with + * dedicated memory and stack limits, so sandboxes are fully isolated from + * each other and from the host. It requires Bun >= 1.3.14 — on Node.js use + * `@tanstack/ai-isolate-node` or `@tanstack/ai-isolate-quickjs` instead. + * + * Tools are injected as async functions that bridge back to the host. + * + * @example + * ```typescript + * import { createQuickJSBunIsolateDriver } from '@tanstack/ai-isolate-quickjs-bun' + * + * const driver = createQuickJSBunIsolateDriver({ + * timeout: 30000, + * }) + * + * const context = await driver.createContext({ + * bindings: { + * readFile: { + * name: 'readFile', + * description: 'Read a file', + * inputSchema: { type: 'object', properties: { path: { type: 'string' } } }, + * execute: async ({ path }) => fs.readFile(path, 'utf-8'), + * }, + * }, + * }) + * + * const result = await context.execute(` + * const content = await readFile({ path: './data.json' }) + * return JSON.parse(content) + * `) + * ``` + */ +export function createQuickJSBunIsolateDriver( + config: QuickJSBunIsolateDriverConfig = {}, +): IsolateDriver { + const defaultTimeout = config.timeout ?? DEFAULT_TIMEOUT_MS + const defaultMemoryLimit = config.memoryLimit ?? DEFAULT_MEMORY_LIMIT_MB + const defaultMaxStackSize = + config.maxStackSize ?? DEFAULT_MAX_STACK_SIZE_BYTES + const maxToolCalls = config.maxToolCalls ?? DEFAULT_MAX_TOOL_CALLS + + return { + async createContext(isolateConfig: IsolateConfig): Promise { + if (typeof Bun === 'undefined') { + throw new Error( + '@tanstack/ai-isolate-quickjs-bun requires the Bun runtime (https://bun.sh). ' + + 'On Node.js, use @tanstack/ai-isolate-node or @tanstack/ai-isolate-quickjs instead.', + ) + } + + const timeout = Math.max(1, isolateConfig.timeout ?? defaultTimeout) + const memoryLimitMb = isolateConfig.memoryLimit ?? defaultMemoryLimit + const maxStackSizeBytes = defaultMaxStackSize + + const quickjs = await importQuickJSBun() + const library = await loadQuickJSLibrary() + + // A dedicated runtime per context gives every sandbox its own heap + // and stack limits, mirroring `setMemoryLimit`/`setMaxStackSize` in + // the QuickJS WASM driver. + const runtime = new quickjs.JSRuntime({ + library, + memoryBytes: memoryLimitMb * 1024 * 1024, + stackBytes: maxStackSizeBytes, + }) + + try { + const vm = runtime.createContext({ timeoutMs: timeout }) + return new QuickJSBunIsolateContext({ + quickjs, + runtime, + vm, + timeout, + maxToolCalls, + bindings: isolateConfig.bindings, + }) + } catch (error) { + runtime.dispose() + throw error + } + }, + } +} diff --git a/packages/ai-isolate-quickjs-bun/tests/escape-attempts.test.ts b/packages/ai-isolate-quickjs-bun/tests/escape-attempts.test.ts new file mode 100644 index 000000000..1b2b03343 --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/tests/escape-attempts.test.ts @@ -0,0 +1,145 @@ +import { describe, expect, it } from 'vitest' +import { createQuickJSBunIsolateDriver } from '../src/isolate-driver' + +async function runInIsolate( + code: string, + opts?: { timeout?: number }, +): Promise<{ + success: boolean + value: unknown + error?: { name: string; message: string } +}> { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: {}, + ...(opts?.timeout !== undefined && { timeout: opts.timeout }), + }) + try { + const res = await context.execute(code) + return { + success: res.success, + value: res.value, + ...(res.error !== undefined && { error: res.error }), + } + } finally { + await context.dispose() + } +} + +// quickjs-bun is built on bun:ffi, so this suite only runs under Bun. +// Run locally with: bun test ./tests +describe.skipIf(typeof Bun === 'undefined')( + 'QuickJS Bun isolate — sandbox escape attempts', + () => { + it('does not expose `process`', async () => { + const res = await runInIsolate('return typeof process') + expect(res.success).toBe(true) + expect(res.value).toBe('undefined') + }) + + it('does not expose `require`', async () => { + const res = await runInIsolate('return typeof require') + expect(res.success).toBe(true) + expect(res.value).toBe('undefined') + }) + + it('does not expose `fetch`', async () => { + const res = await runInIsolate('return typeof fetch') + expect(res.success).toBe(true) + expect(res.value).toBe('undefined') + }) + + it('does not expose `Bun`', async () => { + const res = await runInIsolate('return typeof Bun') + expect(res.success).toBe(true) + expect(res.value).toBe('undefined') + }) + + it('does not expose timers or the host event loop', async () => { + const res = await runInIsolate( + 'return [typeof setTimeout, typeof setInterval, typeof queueMicrotask].join(",")', + ) + expect(res.success).toBe(true) + expect(res.value).toBe('undefined,undefined,undefined') + }) + + it('does not include the QuickJS std and os modules', async () => { + const res = await runInIsolate(` + try { + const std = await import('std') + return 'loaded' + } catch (e) { + return 'blocked' + } + `) + expect(res.success).toBe(true) + expect(res.value).toBe('blocked') + }) + + it('does not leak Object.prototype pollution to the host', async () => { + await runInIsolate(` + Object.prototype.__qjsLeak = 'leaked' + return 1 + `) + expect( + (Object.prototype as { __qjsLeak?: unknown }).__qjsLeak, + ).toBeUndefined() + }) + + it('does not leak Object.prototype pollution between separate contexts', async () => { + const driver = createQuickJSBunIsolateDriver() + const ctxA = await driver.createContext({ bindings: {} }) + const ctxB = await driver.createContext({ bindings: {} }) + try { + await ctxA.execute(`Object.prototype.__qjsCtxProbe = 'a'; return 1;`) + const res = await ctxB.execute(`return ({}).__qjsCtxProbe`) + expect(res.success).toBe(true) + expect(res.value).toBeUndefined() + } finally { + await ctxA.dispose() + await ctxB.dispose() + } + }) + + it('terminates a synchronous CPU-spin loop via timeout (does not hang)', async () => { + const start = Date.now() + const res = await runInIsolate('while (true) {}', { timeout: 200 }) + const elapsed = Date.now() - start + expect(res.success).toBe(false) + expect(elapsed).toBeLessThan(5000) + }) + + it('rejects Function-constructor escape attempts', async () => { + const res = await runInIsolate(` + try { + const C = (function(){}).constructor + return typeof C('return process')() + } catch (e) { + return 'blocked: ' + e.message + } + `) + expect(res.success).toBe(true) + // Either undefined (Function runs in isolate where process doesn't exist) + // or a blocked message. The sandbox must not return a real process object. + expect( + res.value === 'undefined' || + (typeof res.value === 'string' && res.value.startsWith('blocked:')), + ).toBe(true) + }) + + it('treats global mutations within a context as scoped to that context only', async () => { + const driver = createQuickJSBunIsolateDriver() + const ctxA = await driver.createContext({ bindings: {} }) + const ctxB = await driver.createContext({ bindings: {} }) + try { + await ctxA.execute(`globalThis.__ctxMarker = 'A'; return 1;`) + const res = await ctxB.execute(`return typeof globalThis.__ctxMarker`) + expect(res.success).toBe(true) + expect(res.value).toBe('undefined') + } finally { + await ctxA.dispose() + await ctxB.dispose() + } + }) + }, +) diff --git a/packages/ai-isolate-quickjs-bun/tests/isolate-driver.test.ts b/packages/ai-isolate-quickjs-bun/tests/isolate-driver.test.ts new file mode 100644 index 000000000..20988bf29 --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/tests/isolate-driver.test.ts @@ -0,0 +1,739 @@ +import { describe, expect, it } from 'vitest' +import { createQuickJSBunIsolateDriver } from '../src/isolate-driver' +import type { ToolBinding } from '@tanstack/ai-code-mode' + +function makeBinding( + name: string, + execute: (args: unknown) => Promise, +): ToolBinding { + return { + name, + description: `${name} tool`, + inputSchema: { type: 'object', properties: {} }, + execute, + } +} + +// The driver only runs under Bun (quickjs-bun is built on bun:ffi). Under +// Node the suite is skipped, mirroring how ai-isolate-node skips when the +// isolated-vm addon is unavailable. Run locally with: bun test ./tests +describe.skipIf(typeof Bun === 'undefined')( + 'createQuickJSBunIsolateDriver', + () => { + describe('createContext', () => { + it('returns a context with execute and dispose', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + expect(context).toBeDefined() + expect(typeof context.execute).toBe('function') + expect(typeof context.dispose).toBe('function') + + const result = await context.execute('return 42') + expect(result.success).toBe(true) + expect(result.value).toBe(42) + await context.dispose() + }) + }) + + describe('execute - basic execution', () => { + it('evaluates arithmetic and returns value', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute('return 3 + 4') + + expect(result.success).toBe(true) + expect(result.value).toBe(7) + await context.dispose() + }) + + it('evaluates string operations', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute('return "hello" + " " + "world"') + + expect(result.success).toBe(true) + expect(result.value).toBe('hello world') + await context.dispose() + }) + + it('evaluates async code and returns value', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + const x = await Promise.resolve(10); + return x + 2; + `) + + expect(result.success).toBe(true) + expect(result.value).toBe(12) + await context.dispose() + }) + + it('returns object and array values', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute('return { a: 1, b: [2, 3] }') + + expect(result.success).toBe(true) + expect(result.value).toEqual({ a: 1, b: [2, 3] }) + await context.dispose() + }) + + it('returns undefined when code returns nothing', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute('const x = 1;') + + expect(result.success).toBe(true) + expect(result.value).toBeUndefined() + await context.dispose() + }) + }) + + describe('execute - tool bindings', () => { + it('injects tool and executes tool call', async () => { + const add = makeBinding('add', async (args: unknown) => { + const { a, b } = args as { a: number; b: number } + return a + b + }) + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { add }, + }) + + const result = await context.execute(` + const sum = await add({ a: 2, b: 3 }); + return sum; + `) + + expect(result.success).toBe(true) + expect(result.value).toBe(5) + await context.dispose() + }) + + it('supports multiple tools in one execution', async () => { + const getA = makeBinding('getA', async () => 'A') + const getB = makeBinding('getB', async () => 'B') + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { getA, getB }, + }) + + const result = await context.execute(` + return (await getA({})) + (await getB({})); + `) + + expect(result.success).toBe(true) + expect(result.value).toBe('AB') + await context.dispose() + }) + + it('supports concurrent tool calls via Promise.all', async () => { + const double = makeBinding('double', async (args: unknown) => { + const { n } = args as { n: number } + await new Promise((resolve) => setTimeout(resolve, 10)) + return n * 2 + }) + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { double }, + }) + + const result = await context.execute(` + const [a, b, c] = await Promise.all([ + double({ n: 1 }), + double({ n: 2 }), + double({ n: 3 }), + ]); + return a + b + c; + `) + + expect(result.success).toBe(true) + expect(result.value).toBe(12) + await context.dispose() + }) + + it('passes empty input when a tool is called without arguments', async () => { + let received: unknown = 'unset' + const probe = makeBinding('probe', async (args: unknown) => { + received = args + return 'ok' + }) + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { probe }, + }) + + const result = await context.execute('return await probe()') + + expect(result.success).toBe(true) + expect(result.value).toBe('ok') + expect(received).toEqual({}) + await context.dispose() + }) + + it('returns undefined for tools that resolve with undefined', async () => { + const noop = makeBinding('noop', async () => undefined) + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { noop }, + }) + + const result = await context.execute('return typeof (await noop({}))') + + expect(result.success).toBe(true) + expect(result.value).toBe('undefined') + await context.dispose() + }) + + it('surfaces tool execution errors', async () => { + const failTool = makeBinding('failTool', async () => { + throw new Error('Tool failed') + }) + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { failTool }, + }) + + const result = await context.execute('return await failTool({})') + + expect(result.success).toBe(false) + expect(result.error?.message).toContain('Tool failed') + await context.dispose() + }) + + it('lets sandbox code catch tool errors', async () => { + const failTool = makeBinding('failTool', async () => { + throw new Error('Tool failed') + }) + + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ + bindings: { failTool }, + }) + + const result = await context.execute(` + try { + await failTool({}); + return 'no error'; + } catch (e) { + return 'caught: ' + e.message; + } + `) + + expect(result.success).toBe(true) + expect(result.value).toBe('caught: Tool failed') + await context.dispose() + }) + }) + + describe('execute - timeout', () => { + it('returns timeout error when code runs too long', async () => { + const driver = createQuickJSBunIsolateDriver({ timeout: 50 }) + const context = await driver.createContext({ + bindings: {}, + timeout: 50, + }) + + // Busy loop that should trigger interrupt handler + const result = await context.execute(` + const start = Date.now(); + while (Date.now() - start < 500) { + // spin + } + return 1; + `) + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('TimeoutError') + await context.dispose() + }) + + it('returns timeout error when a tool call outlives the deadline', async () => { + const slow = makeBinding('slow', async () => { + await new Promise((resolve) => setTimeout(resolve, 500)) + return 'too late' + }) + + const driver = createQuickJSBunIsolateDriver({ timeout: 50 }) + const context = await driver.createContext({ + bindings: { slow }, + timeout: 50, + }) + + const start = Date.now() + const result = await context.execute('return await slow({})') + const elapsed = Date.now() - start + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('TimeoutError') + expect(elapsed).toBeLessThan(5000) + await context.dispose() + }) + + it('fails fast for promises no host work will resolve', async () => { + const driver = createQuickJSBunIsolateDriver({ timeout: 5000 }) + const context = await driver.createContext({ bindings: {} }) + + const start = Date.now() + const result = await context.execute( + 'return await new Promise(() => {})', + ) + const elapsed = Date.now() - start + + expect(result.success).toBe(false) + expect(result.error?.message).toContain('no host work') + // Should not wait for the full 5s timeout + expect(elapsed).toBeLessThan(1000) + await context.dispose() + }) + }) + + describe('execute - error handling', () => { + it('returns error for syntax errors', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute('syntax error!!!') + + expect(result.success).toBe(false) + expect(result.error?.message).toBeDefined() + await context.dispose() + }) + + it('returns error for runtime errors', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute('throw new Error("oops")') + + expect(result.success).toBe(false) + expect(result.error?.message).toContain('oops') + await context.dispose() + }) + + it('includes captured logs in failure results', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + console.log("before failure"); + throw new Error("oops"); + `) + + expect(result.success).toBe(false) + expect(result.logs).toContain('before failure') + await context.dispose() + }) + }) + + describe('execute - console capture', () => { + it('captures console.log in logs', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + console.log("hello"); + console.log("world"); + return 1; + `) + + expect(result.success).toBe(true) + expect(result.logs).toContain('hello') + expect(result.logs).toContain('world') + await context.dispose() + }) + + it('captures console.error with ERROR prefix', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + console.error("fail"); + return 1; + `) + + expect(result.success).toBe(true) + expect(result.logs?.some((l) => l.includes('fail'))).toBe(true) + expect(result.logs).toContain('ERROR: fail') + await context.dispose() + }) + + it('captures console.warn and console.info with prefixes', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + console.warn("careful"); + console.info("fyi"); + return 1; + `) + + expect(result.success).toBe(true) + expect(result.logs).toContain('WARN: careful') + expect(result.logs).toContain('INFO: fyi') + await context.dispose() + }) + }) + + describe('dispose', () => { + it('execute returns DisposedError after dispose', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + await context.dispose() + + const result = await context.execute('return 1') + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('DisposedError') + expect(result.error?.message).toContain('disposed') + }) + + it('dispose is idempotent', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + await context.dispose() + await expect(context.dispose()).resolves.toBeUndefined() + }) + }) + + describe('memory isolation', () => { + it('contexts do not share state', async () => { + const driver = createQuickJSBunIsolateDriver() + const ctx1 = await driver.createContext({ bindings: {} }) + const ctx2 = await driver.createContext({ bindings: {} }) + + await ctx1.execute('globalThis.__secret = 100; return 1') + const result2 = await ctx2.execute('return typeof globalThis.__secret') + + expect(result2.success).toBe(true) + expect(result2.value).toBe('undefined') + + await ctx1.dispose() + await ctx2.dispose() + }) + }) + + describe('memoryLimit config', () => { + it('accepts memoryLimit via createContext and runs successfully', async () => { + const driver = createQuickJSBunIsolateDriver({ memoryLimit: 64 }) + const context = await driver.createContext({ + bindings: {}, + memoryLimit: 64, + }) + + const result = await context.execute('return 1 + 1') + + expect(result.success).toBe(true) + expect(result.value).toBe(2) + await context.dispose() + }) + + it('returns MemoryLimitError when allocation exceeds limit (does not crash)', async () => { + const driver = createQuickJSBunIsolateDriver({ memoryLimit: 1 }) + const context = await driver.createContext({ + bindings: {}, + memoryLimit: 1, + }) + + const result = await context.execute( + `return "x".repeat(8 * 1024 * 1024);`, + ) + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('MemoryLimitError') + expect(result.error?.message).toContain('memory limit') + }) + + it('returns MemoryLimitError when the heap is fully exhausted', async () => { + const driver = createQuickJSBunIsolateDriver({ memoryLimit: 1 }) + const context = await driver.createContext({ + bindings: {}, + memoryLimit: 1, + }) + + const result = await context.execute(` + const items = []; + while (true) items.push(new Array(1000).fill('x').join('')); + `) + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('MemoryLimitError') + expect(result.error?.message).toContain('memory limit') + }) + + it('dispose is safe after memory limit error', async () => { + const driver = createQuickJSBunIsolateDriver({ memoryLimit: 1 }) + const context = await driver.createContext({ + bindings: {}, + memoryLimit: 1, + }) + + await context.execute(`return "x".repeat(8 * 1024 * 1024);`) + + await expect(context.dispose()).resolves.toBeUndefined() + }) + }) + + describe('maxStackSize config', () => { + it('returns StackOverflowError for deep recursion when stack is small', async () => { + const driver = createQuickJSBunIsolateDriver({ + maxStackSize: 32 * 1024, + timeout: 30000, + }) + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + function f(n) { + if (n <= 0) return 0; + return 1 + f(n - 1); + } + return f(200000); + `) + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('StackOverflowError') + expect(result.error?.message).toContain('stack') + await context.dispose() + }) + }) + + describe('execute after fatal memory limit', () => { + it('returns DisposedError on subsequent execute after OOM', async () => { + const driver = createQuickJSBunIsolateDriver({ memoryLimit: 1 }) + const context = await driver.createContext({ + bindings: {}, + memoryLimit: 1, + }) + + const first = await context.execute( + `return "x".repeat(8 * 1024 * 1024);`, + ) + expect(first.success).toBe(false) + expect(first.error?.name).toBe('MemoryLimitError') + + const second = await context.execute('return 42') + expect(second.success).toBe(false) + expect(second.error?.name).toBe('DisposedError') + expect(second.error?.message).toContain('disposed') + }) + }) + + describe('execution serialization', () => { + it('serializes concurrent executes on the same context', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const [first, second] = await Promise.all([ + context.execute( + 'globalThis.__order = (globalThis.__order ?? "") + "a"; return globalThis.__order', + ), + context.execute( + 'globalThis.__order = (globalThis.__order ?? "") + "b"; return globalThis.__order', + ), + ]) + + expect(first.success).toBe(true) + expect(second.success).toBe(true) + expect(first.value).toBe('a') + expect(second.value).toBe('ab') + await context.dispose() + }) + }) + + describe('console capture - non-string arguments', () => { + it('coerces numbers, booleans, objects, and mixed args', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + console.log(42); + console.log(true); + console.log({ a: 1 }); + console.log('count:', 3); + console.log(null, undefined); + return 'done'; + `) + + expect(result.success).toBe(true) + expect(result.value).toBe('done') + expect(result.logs).toContain('42') + expect(result.logs).toContain('true') + expect(result.logs).toContain('[object Object]') + expect(result.logs).toContain('count: 3') + expect(result.logs).toContain('null undefined') + await context.dispose() + }) + + it('does not let a throwing toString abort the execution', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + const evil = { toString() { throw new Error('nope') } }; + console.log(evil); + return 'survived'; + `) + + expect(result.success).toBe(true) + expect(result.value).toBe('survived') + expect(result.logs).toContain('[unprintable]') + await context.dispose() + }) + }) + + describe('console capture - log buffer cap', () => { + it('truncates runaway log output instead of growing unbounded', async () => { + const driver = createQuickJSBunIsolateDriver({ timeout: 10000 }) + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(` + for (let i = 0; i < 100000; i++) console.log('x'.repeat(1000)); + return 'done'; + `) + + expect(result.success).toBe(true) + expect(result.logs).toContain('[log output truncated]') + // Cap is 1,000,000 bytes; allow generous slack for the marker. + const totalBytes = (result.logs ?? []).reduce( + (sum, line) => sum + line.length, + 0, + ) + expect(totalBytes).toBeLessThan(1_100_000) + await context.dispose() + }) + }) + + describe('maxToolCalls config', () => { + it('throws inside the sandbox once the tool-call budget is exhausted', async () => { + const ping = makeBinding('ping', async () => 'pong') + const driver = createQuickJSBunIsolateDriver({ maxToolCalls: 3 }) + const context = await driver.createContext({ bindings: { ping } }) + + const result = await context.execute(` + let calls = 0; + try { + for (let i = 0; i < 100; i++) { await ping({}); calls++; } + } catch (e) { + return { calls, error: e.message }; + } + return { calls, error: null }; + `) + + expect(result.success).toBe(true) + const value = result.value as { calls: number; error: string | null } + expect(value.calls).toBe(3) + expect(value.error).toContain('maximum of 3 tool calls') + await context.dispose() + }) + }) + + describe('tool result exceeding the memory limit', () => { + it('fails with a normalized error and no unhandled rejection', async () => { + const onRejection = (reason: unknown) => { + throw reason instanceof Error ? reason : new Error(String(reason)) + } + process.on('unhandledRejection', onRejection) + try { + const huge = makeBinding('huge', async () => + 'y'.repeat(16 * 1024 * 1024), + ) + const driver = createQuickJSBunIsolateDriver({ memoryLimit: 2 }) + const context = await driver.createContext({ + bindings: { huge }, + memoryLimit: 2, + }) + + const result = await context.execute('return await huge({})') + + expect(result.success).toBe(false) + expect(result.error?.name).toBe('MemoryLimitError') + + // The VM was released as fatal; the next execute is DisposedError. + const next = await context.execute('return 1') + expect(next.error?.name).toBe('DisposedError') + + // Give any stray rejection a tick to surface before we detach. + await new Promise((resolve) => setTimeout(resolve, 50)) + } finally { + process.off('unhandledRejection', onRejection) + } + }) + }) + + describe('error normalization - thrown values', () => { + it('preserves the message of a thrown plain object', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute( + `throw { name: 'CustomError', message: 'custom obj' }`, + ) + + expect(result.success).toBe(false) + expect(result.error?.message).toBe('custom obj') + expect(result.error?.name).toBe('CustomError') + await context.dispose() + }) + + it('preserves a thrown string', async () => { + const driver = createQuickJSBunIsolateDriver() + const context = await driver.createContext({ bindings: {} }) + + const result = await context.execute(`throw 'bare string'`) + + expect(result.success).toBe(false) + expect(result.error?.message).toBe('bare string') + await context.dispose() + }) + }) + + describe('context reuse after non-fatal timeout', () => { + it('remains usable after a timed-out execution', async () => { + const driver = createQuickJSBunIsolateDriver({ timeout: 50 }) + const context = await driver.createContext({ + bindings: {}, + timeout: 50, + }) + + const timedOut = await context.execute('while (true) {}') + expect(timedOut.success).toBe(false) + expect(timedOut.error?.name).toBe('TimeoutError') + + const ok = await context.execute('return 7') + expect(ok.success).toBe(true) + expect(ok.value).toBe(7) + await context.dispose() + }) + }) + }, +) + +// This part of the contract is observable on Node.js (where bun:ffi is +// unavailable), so it runs in regular CI. +describe.skipIf(typeof Bun !== 'undefined')( + 'createQuickJSBunIsolateDriver on Node.js', + () => { + it('rejects createContext with a descriptive runtime error', async () => { + const driver = createQuickJSBunIsolateDriver() + + await expect(driver.createContext({ bindings: {} })).rejects.toThrow( + /requires the Bun runtime/, + ) + }) + }, +) diff --git a/packages/ai-isolate-quickjs-bun/tsconfig.json b/packages/ai-isolate-quickjs-bun/tsconfig.json new file mode 100644 index 000000000..3948f968d --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + // quickjs-bun ships TypeScript sources that use import attributes + // (`with { type: "file" }`), which require a newer module target. + "module": "ESNext", + "outDir": "dist" + }, + "include": ["src", "tests", "benchmarks"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/ai-isolate-quickjs-bun/vite.config.ts b/packages/ai-isolate-quickjs-bun/vite.config.ts new file mode 100644 index 000000000..77bcc2e60 --- /dev/null +++ b/packages/ai-isolate-quickjs-bun/vite.config.ts @@ -0,0 +1,36 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/vite-config' +import packageJson from './package.json' + +const config = defineConfig({ + test: { + name: packageJson.name, + dir: './', + watch: false, + globals: true, + environment: 'node', + include: ['tests/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + exclude: [ + 'node_modules/', + 'dist/', + 'tests/', + '**/*.test.ts', + '**/*.config.ts', + '**/types.ts', + ], + include: ['src/**/*.ts'], + }, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ + entry: ['./src/index.ts'], + srcDir: './src', + cjs: false, + }), +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aee0c7730..fb80ad14f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -146,10 +146,10 @@ importers: devDependencies: '@analogjs/vite-plugin-angular': specifier: ^1.10.0 - version: 1.22.5(@angular/build@21.2.15(73b2d729d40f30686a7c435867c88436)) + version: 1.22.5(@angular/build@21.2.15(dc2c5e0af87e42451164817325dee7e3)) '@angular/build': specifier: ^21.2.0 - version: 21.2.15(73b2d729d40f30686a7c435867c88436) + version: 21.2.15(dc2c5e0af87e42451164817325dee7e3) '@tailwindcss/vite': specifier: ^4.1.18 version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -201,6 +201,9 @@ importers: '@tanstack/ai-isolate-quickjs': specifier: workspace:* version: link:../../packages/ai-isolate-quickjs + '@tanstack/ai-isolate-quickjs-bun': + specifier: workspace:* + version: link:../../packages/ai-isolate-quickjs-bun '@tanstack/ai-ollama': specifier: workspace:* version: link:../../packages/ai-ollama @@ -212,13 +215,13 @@ importers: version: link:../../packages/ai-react '@tanstack/nitro-v2-vite-plugin': specifier: ^1.154.7 - version: 1.154.7(rolldown@1.0.0-rc.17)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.154.7(rolldown@1.1.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/react-router': specifier: ^1.158.4 version: 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': specifier: ^1.159.0 - version: 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/router-plugin': specifier: ^1.158.4 version: 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -327,7 +330,7 @@ importers: version: 1.159.5(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.159.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': specifier: ^1.159.0 - version: 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/router-plugin': specifier: ^1.158.4 version: 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -439,7 +442,7 @@ importers: version: link:../../packages/ai-react-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.154.7 - version: 1.154.7(rolldown@1.0.0-rc.17)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.154.7(rolldown@1.1.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/react-devtools': specifier: ^0.9.10 version: 0.9.10(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10) @@ -454,7 +457,7 @@ importers: version: 1.159.5(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.159.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': specifier: ^1.159.0 - version: 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/react-store': specifier: ^0.8.0 version: 0.8.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -569,7 +572,7 @@ importers: version: 0.561.0(react@19.2.3) nitro: specifier: 3.0.1-alpha.2 - version: 3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.0.0-rc.17)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.1.1)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) react: specifier: ^19.2.3 version: 19.2.3 @@ -688,7 +691,7 @@ importers: version: 1.159.5(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.159.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': specifier: ^1.159.0 - version: 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/router-plugin': specifier: ^1.158.4 version: 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -706,7 +709,7 @@ importers: version: 0.561.0(react@19.2.3) nitro: specifier: latest - version: 3.0.260429-beta(chokidar@5.0.0)(dotenv@17.2.3)(giget@2.0.0)(jiti@2.6.1)(miniflare@4.20260609.0)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 3.0.260610-beta(chokidar@5.0.0)(dotenv@17.2.3)(giget@2.0.0)(jiti@2.6.1)(miniflare@4.20260609.0)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(wrangler@4.88.0) radix-ui: specifier: ^1.4.3 version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -806,7 +809,7 @@ importers: version: link:../../packages/ai-solid-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.154.7 - version: 1.154.7(rolldown@1.0.0-rc.17)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.154.7(rolldown@1.1.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/router-plugin': specifier: ^1.158.4 version: 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -827,7 +830,7 @@ importers: version: 1.141.1(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.159.4)(@tanstack/solid-query@5.90.15(solid-js@1.9.10))(@tanstack/solid-router@1.141.1(solid-js@1.9.10))(eslint@9.39.4(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3) '@tanstack/solid-start': specifier: ^1.139.10 - version: 1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.5(srvx@0.11.15))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.6(srvx@0.11.16))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/solid-store': specifier: ^0.8.0 version: 0.8.0(solid-js@1.9.10) @@ -1088,10 +1091,10 @@ importers: devDependencies: '@analogjs/vite-plugin-angular': specifier: ^1.10.0 - version: 1.22.5(@angular/build@21.2.15(b4e3cce66654bd2e0d0fab951dffc04a)) + version: 1.22.5(@angular/build@21.2.15(04a6deee5a19f5aede5908c321226b68)) '@angular/build': specifier: ^21.2.0 - version: 21.2.15(b4e3cce66654bd2e0d0fab951dffc04a) + version: 21.2.15(04a6deee5a19f5aede5908c321226b68) '@angular/common': specifier: ^21.2.0 version: 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) @@ -1477,6 +1480,25 @@ importers: specifier: 4.0.14 version: 4.0.14(vitest@4.0.14(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.15))(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + packages/ai-isolate-quickjs-bun: + dependencies: + '@tanstack/ai-code-mode': + specifier: workspace:* + version: link:../ai-code-mode + quickjs-bun: + specifier: 0.1.2 + version: 0.1.2 + devDependencies: + '@tanstack/ai-isolate-quickjs': + specifier: workspace:* + version: link:../ai-isolate-quickjs + '@types/bun': + specifier: ^1.3.14 + version: 1.3.14 + '@vitest/coverage-v8': + specifier: 4.0.14 + version: 4.0.14(vitest@4.0.14(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.15))(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + packages/ai-mcp: dependencies: '@modelcontextprotocol/sdk': @@ -2010,7 +2032,7 @@ importers: version: 0.4.1 '@tanstack/nitro-v2-vite-plugin': specifier: ^1.154.7 - version: 1.154.7(rolldown@1.0.0-rc.17)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.154.7(rolldown@1.1.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/react-ai-devtools': specifier: workspace:* version: link:../../packages/react-ai-devtools @@ -2019,7 +2041,7 @@ importers: version: 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': specifier: ^1.159.0 - version: 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) arktype: specifier: ^2.1.28 version: 2.2.0 @@ -2122,16 +2144,16 @@ importers: version: link:../../packages/ai-react-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.154.7 - version: 1.154.7(rolldown@1.0.0-rc.17)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.154.7(rolldown@1.1.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/react-router': specifier: ^1.158.4 version: 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': specifier: ^1.159.0 - version: 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/start': specifier: ^1.120.20 - version: 1.120.20(@types/node@24.10.3)(crossws@0.4.5(srvx@0.11.15))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2) + version: 1.120.20(@types/node@24.10.3)(crossws@0.4.6(srvx@0.11.16))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2) highlight.js: specifier: ^11.11.1 version: 11.11.1 @@ -2358,6 +2380,7 @@ packages: '@angular/platform-browser-dynamic@21.2.17': resolution: {integrity: sha512-r/BU/T8bOTghP3fIXhzYf5wcMcAmhWnAFv3p4asCCPXomaktoas70wYcMaDH+pK1LAFBxLwzBWHm36MpFlTMFg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + deprecated: '@angular/platform-browser-dynamic is deprecated. Use `@angular/platform-browser` instead.' peerDependencies: '@angular/common': 21.2.17 '@angular/compiler': 21.2.17 @@ -3161,12 +3184,18 @@ packages: '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@emnapi/core@1.11.0': + resolution: {integrity: sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==} + '@emnapi/core@1.7.1': resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emnapi/runtime@1.11.0': + resolution: {integrity: sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==} + '@emnapi/runtime@1.7.1': resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} @@ -3176,6 +3205,9 @@ packages: '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@esbuild/aix-ppc64@0.20.2': resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} engines: {node: '>=12'} @@ -4756,6 +4788,12 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -5000,8 +5038,8 @@ packages: '@oxc-project/types@0.113.0': resolution: {integrity: sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==} - '@oxc-project/types@0.127.0': - resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} + '@oxc-project/types@0.135.0': + resolution: {integrity: sha512-wR+xRdFkUBMvcAjBJ2q2kcZM6d+DKu2NgoOyxZgYwZdLhmiv6+rnO8PZ/P68kMiZtIKm+pW7zyEJ4kSOs0vo+Q==} '@oxc-resolver/binding-android-arm-eabi@11.15.0': resolution: {integrity: sha512-Q+lWuFfq7whNelNJIP1dhXaVz4zO9Tu77GcQHyxDWh3MaCoO2Bisphgzmsh4ZoUe2zIchQh6OvQL99GlWHg9Tw==} @@ -6166,14 +6204,14 @@ packages: cpu: [arm64] os: [android] - '@rolldown/binding-android-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} + '@rolldown/binding-android-arm64@1.0.0-rc.4': + resolution: {integrity: sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-android-arm64@1.0.0-rc.4': - resolution: {integrity: sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==} + '@rolldown/binding-android-arm64@1.1.1': + resolution: {integrity: sha512-BLf9Wak/gfwVb7NQTQW4wBgL3oAfPy7ArEkhwV543OVw/uY6B47z5xYsqPSZ9PDOorvURPinws6ThaFuNgGLgA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] @@ -6184,14 +6222,14 @@ packages: cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} + '@rolldown/binding-darwin-arm64@1.0.0-rc.4': + resolution: {integrity: sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.0-rc.4': - resolution: {integrity: sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==} + '@rolldown/binding-darwin-arm64@1.1.1': + resolution: {integrity: sha512-rRZRPy/Ynb+Mxu0O6tfPldHeDgAn0sRij+IOUy6sFdUlv3hArGW/DloE3GfAxtqpOJuRNgF74Nr5gM4xBeU2jQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] @@ -6202,14 +6240,14 @@ packages: cpu: [x64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.17': - resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} + '@rolldown/binding-darwin-x64@1.0.0-rc.4': + resolution: {integrity: sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.4': - resolution: {integrity: sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==} + '@rolldown/binding-darwin-x64@1.1.1': + resolution: {integrity: sha512-/MtefPxhKPyWWFM8L45OWiEqRf+eSU2Qv9ZAyTaoZOoGcoPKxbbhjTJO2/U2IThv0uDZ4NWHc3/oTsR6IEOtww==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] @@ -6220,14 +6258,14 @@ packages: cpu: [x64] os: [freebsd] - '@rolldown/binding-freebsd-x64@1.0.0-rc.17': - resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} + '@rolldown/binding-freebsd-x64@1.0.0-rc.4': + resolution: {integrity: sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-freebsd-x64@1.0.0-rc.4': - resolution: {integrity: sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==} + '@rolldown/binding-freebsd-x64@1.1.1': + resolution: {integrity: sha512-202K+cpIi1kx/Zn7AtxBi4LTXSY67Aszb2K9rNsuW7FeBeh0nqoNmYLOSZidV0p88VPBzMmTZcHAdPNo3kRYzQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] @@ -6238,14 +6276,14 @@ packages: cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': - resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': + resolution: {integrity: sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': - resolution: {integrity: sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.1': + resolution: {integrity: sha512-wl9NfeXNUwrXtUc063tddmZFUI6qiNs1CNOwni0OL4vC7MqVSYugra3ZgtDmtVy8e0DluJTENmzIv2BwqLzT4Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -6257,15 +6295,15 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': + resolution: {integrity: sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': - resolution: {integrity: sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==} + '@rolldown/binding-linux-arm64-gnu@1.1.1': + resolution: {integrity: sha512-at2EO4o7D/PJLC4Xik16bU4CcjQE2tSv1LfqMA0TRYQYQihRm3gZeDB8xaX28A9SFedibcAk5DeMCKt4REKG0A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -6278,29 +6316,29 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': - resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': + resolution: {integrity: sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': - resolution: {integrity: sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==} + '@rolldown/binding-linux-arm64-musl@1.1.1': + resolution: {integrity: sha512-5PUjZx366h9tkJTPJF5eibxOlK3sGoeRiBJLLjjEB5/kLDuhr6qB3LkhqLz1smXNgsX+pBhnbcJBrPE30HznAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} + '@rolldown/binding-linux-ppc64-gnu@1.1.1': + resolution: {integrity: sha512-1WK84XPeio3tjP1sM/TMXiC0G1i1iq1qGZ71KfNQjEFLU1kwD+Cv5T8nGySg/JUFwLbaScu6ve9DmeXlmqpkFA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} + '@rolldown/binding-linux-s390x-gnu@1.1.1': + resolution: {integrity: sha512-1nS1X5z1uMJ369RU25hTpKCFvUwXZp12dIzlzk4S+UxCTcSVGsAE6tzkOSufv/7jnmAtK0ZlrsJxh2fGmsnVSw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] @@ -6313,15 +6351,15 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': + resolution: {integrity: sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': - resolution: {integrity: sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==} + '@rolldown/binding-linux-x64-gnu@1.1.1': + resolution: {integrity: sha512-NwX/wspnq4vYyMFsqbYvzums3ki/Tk8FZbMzMAovPDp3OfLeYKby/D+9osokadXuYEV3OvpeHlwnr/bG8QMixA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -6334,15 +6372,15 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': - resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} + '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': + resolution: {integrity: sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': - resolution: {integrity: sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==} + '@rolldown/binding-linux-x64-musl@1.1.1': + resolution: {integrity: sha512-+n46LhDrJFQM+229y4oXtVpj1G50U/+XuHMlpnisFTEXhrg9f/YIjp/HymX+PVJjBEr7XHRs3CFLelV464pqwA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -6354,14 +6392,14 @@ packages: cpu: [arm64] os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} + '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': + resolution: {integrity: sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': - resolution: {integrity: sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==} + '@rolldown/binding-openharmony-arm64@1.1.1': + resolution: {integrity: sha512-qGwEu47zOWYo7LdRHhCWTNhzwGtxXpdY6CERs8QEOqC0PXGGics/e3vHnyEUKt8xK6YkbZXFUCeklrpB6js8ag==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] @@ -6371,30 +6409,30 @@ packages: engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': - resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.4': resolution: {integrity: sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==} engines: {node: '>=14.0.0'} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.1.1': + resolution: {integrity: sha512-qczfgEH8u0wHGGOXtA7UMAybNKuQjjEXairyQaw4WzjiMztfbgatG1h4OKays/smhtwbWltpKCRGtVhU6h40Sg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': resolution: {integrity: sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': - resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': + resolution: {integrity: sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': - resolution: {integrity: sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==} + '@rolldown/binding-win32-arm64-msvc@1.1.1': + resolution: {integrity: sha512-4psXSh63mSbwJF+mB8/9yfUUEzBiHYcUjxa32EO9ZwKy0Ypwjcg4F10D8SvVXgd+isy2UUUjF9HJJnDu1T/4Gg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] @@ -6405,14 +6443,14 @@ packages: cpu: [x64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': - resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.4': + resolution: {integrity: sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.4': - resolution: {integrity: sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==} + '@rolldown/binding-win32-x64-msvc@1.1.1': + resolution: {integrity: sha512-MUvC/HLXVjzkQkWiExdVTEEWf0py+GfWm8WKSZsekG3ih6a21iy0BHPF07X3JIf3ifoklZXTIaHTLPBgH1C3dw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -6426,12 +6464,12 @@ packages: '@rolldown/pluginutils@1.0.0-beta.53': resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} - '@rolldown/pluginutils@1.0.0-rc.17': - resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} - '@rolldown/pluginutils@1.0.0-rc.4': resolution: {integrity: sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==} + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@rollup/plugin-alias@5.1.1': resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} engines: {node: '>=14.0.0'} @@ -7717,6 +7755,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -7744,6 +7785,9 @@ packages: '@types/braces@3.0.5': resolution: {integrity: sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==} + '@types/bun@1.3.14': + resolution: {integrity: sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw==} + '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -8751,6 +8795,9 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bun-types@1.3.14: + resolution: {integrity: sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ==} + bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -9168,6 +9215,14 @@ packages: srvx: optional: true + crossws@0.4.6: + resolution: {integrity: sha512-/Wxe9Z007EbJ496j88nToZEvyPZ8PY/wjZJ18Agh/GCA9cYHyLbxtrpdFlFzAw3TV20F0SUYGl0g6PzChbwUrg==} + peerDependencies: + srvx: '>=0.11.5' + peerDependenciesMeta: + srvx: + optional: true + css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} @@ -9551,17 +9606,23 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - env-runner@0.1.7: - resolution: {integrity: sha512-i7h96jxETJYhXy5grgHNJ9xNzCzWIn9Ck/VkkYgOlE4gOqknsLX3CmlVb5LmwNex8sOoLFVZLz+TIw/+b5rktA==} + env-runner@0.1.14: + resolution: {integrity: sha512-qdk5mmgFsd+zPg3r1bkZ+IbvpfUfypyDvNhMGypSMRpz7kOa/kI6SpW8fgyukuEM4Lo24M65r+1Ne0DtT7vFBA==} hasBin: true peerDependencies: - '@netlify/runtime': ^4 - miniflare: ^4.20260317.3 + '@netlify/runtime': ^4.1.23 + '@vercel/queue': ^0.2.0 + miniflare: ^4.20260515.0 + wrangler: ^4.0.0 peerDependenciesMeta: '@netlify/runtime': optional: true + '@vercel/queue': + optional: true miniflare: optional: true + wrangler: + optional: true environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} @@ -10326,8 +10387,8 @@ packages: crossws: optional: true - h3@2.0.1-rc.20: - resolution: {integrity: sha512-28ljodXuUp0fZovdiSRq4G9OgrxCztrJe5VdYzXAB7ueRvI7pIUqLU14Xi3XqdYJ/khXjfpUOOD2EQa6CmBgsg==} + h3@2.0.1-rc.22: + resolution: {integrity: sha512-Esv0DMIuPkCTSWCA0vO73vcTqwzH1wjSrAO1TXNu/K3up1sZHa9EKMapbmxCDYBeymC3fVTk4qxp7ogQWQ+KgA==} engines: {node: '>=20.11.1'} hasBin: true peerDependencies: @@ -10487,8 +10548,8 @@ packages: httpxy@0.1.7: resolution: {integrity: sha512-pXNx8gnANKAndgga5ahefxc++tJvNL87CXoRwxn1cJE2ZkWEojF3tNfQIEhZX/vfpt+wzeAzpUI4qkediX1MLQ==} - httpxy@0.5.1: - resolution: {integrity: sha512-JPhqYiixe1A1I+MXDewWDZqeudBGU8Q9jCHYN8ML+779RQzLjTi78HBvWz4jMxUD6h2/vUL12g4q/mFM0OUw1A==} + httpxy@0.5.3: + resolution: {integrity: sha512-SMS9V6Sn7VWaS11lYhoAr0ceoaiolTWf4jYdJn0NJhCdKMu9R2H9Fh0LBDWBHQF6HRLI1PmaePYsjanSpE5PEw==} human-id@4.1.3: resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} @@ -11780,8 +11841,8 @@ packages: nf3@0.3.10: resolution: {integrity: sha512-UlqmHkZiHGgSkRj17yrOXEsSu5ECvtlJ3Xm1W5WsWrTKgu9m7OjrMZh9H/ME2LcWrTlMD0/vmmNVpyBG4yRdGg==} - nf3@0.3.16: - resolution: {integrity: sha512-Gs0xRPpUm2nDkqbi40NJ9g7qDIcjcJzgExiydnq6LAyqhI2jfno8wG3NKTL+IiJsx799UHOb1CnSd4Wg4SG4Pw==} + nf3@0.3.17: + resolution: {integrity: sha512-N9zEWySuJFw+gR0lhS5863YsvNeudOdqRyFvNb+jMXbeTJOdrjDqkCpDginIZfUm0LzT1t1nCRiDeqQm/8kirQ==} ng-packagr@21.2.5: resolution: {integrity: sha512-WGF4DK6nOE3xKPj8miC3lw6I66n1wdBhnMl25zMExqFmzRk9jABwFj3eycellTiH4t4x+yHnuxS/im9DLTa9cg==} @@ -11815,16 +11876,16 @@ packages: xml2js: optional: true - nitro@3.0.260429-beta: - resolution: {integrity: sha512-KweLVCUN5X9v9g+4yxAyRcz3FcOlnjmt9FyrAIWDxJETJmNT7I0JV0clgsONjo2nI0U5gwedXYA3RaNtF5XWzg==} + nitro@3.0.260610-beta: + resolution: {integrity: sha512-KPb4L5yaF/Rx/xoGMpgHRJvZhbhGiqbRKOwwPLCH9jKTKTsEUHLjnJas85AeCzaswqa8Wi52eQBtRsODC4PS0Q==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@vercel/queue': ^0.1.6 + '@vercel/queue': ^0.3.0 dotenv: '*' giget: '*' - jiti: ^2.6.1 - rollup: ^4.60.2 + jiti: ^2.7.0 + rollup: ^4.61.1 vite: ^7 || ^8 xml2js: ^0.6.2 zephyr-agent: ^0.2.0 @@ -11997,8 +12058,8 @@ packages: obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - ocache@0.1.4: - resolution: {integrity: sha512-e7geNdWjxSnvsSgvLuPvgKgu7ubM10ZmTPOgpr7mz2BXYtvjMKTiLhjFi/gWU8chkuP6hNkZBsa9LzOusyaqkQ==} + ocache@0.1.5: + resolution: {integrity: sha512-kNNnkkVQup/QDvmTz8Q84wc2ntiyoVHDxa6eHWKt5qdGAmFRBIxy83rxgCYEjW0x06UJ9E3P6VgM2yY4rOBH4w==} ofetch@1.5.1: resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} @@ -12504,6 +12565,10 @@ packages: queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} + quickjs-bun@0.1.2: + resolution: {integrity: sha512-mmbG4UwB+FqckVGJXttx4vAg92X/mjcp5e42UZXWrIe80m48x6/Vs3SW3UFTHzRzGFHuzCPnChCKB+W7AK8OSA==} + engines: {bun: '>=1.3.14'} + quickjs-emscripten-core@0.31.0: resolution: {integrity: sha512-oQz8p0SiKDBc1TC7ZBK2fr0GoSHZKA0jZIeXxsnCyCs4y32FStzCW4d1h6E1sE0uHDMbGITbk2zhNaytaoJwXQ==} @@ -12842,13 +12907,13 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rolldown@1.0.0-rc.17: - resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} + rolldown@1.0.0-rc.4: + resolution: {integrity: sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rolldown@1.0.0-rc.4: - resolution: {integrity: sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==} + rolldown@1.1.1: + resolution: {integrity: sha512-IN750c0p+s3jqJIsFLRZrQazmbAB1kkQDTtQjSt/gbS2ywLhlv4R5Shazer0FZKmuo/BsO3/w2UoYnUjuOZqHg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -13242,6 +13307,11 @@ packages: engines: {node: '>=20.16.0'} hasBin: true + srvx@0.11.16: + resolution: {integrity: sha512-bp07zRuycfTY43IjAvvTFnmnJi8ikW0VFiHwOhhYcVW/L4xQ1XY4PAd4Nuum1rsA17C39zL7x+CDhrn5AL32Rw==} + engines: {node: '>=20.16.0'} + hasBin: true + srvx@0.11.2: resolution: {integrity: sha512-u6NbjE84IJwm1XUnJ53WqylLTQ3BdWRw03lcjBNNeMBD+EFjkl0Cnw1RVaGSqRAo38pOHOPXJH30M6cuTINUxw==} engines: {node: '>=20.16.0'} @@ -14869,19 +14939,19 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@analogjs/vite-plugin-angular@1.22.5(@angular/build@21.2.15(73b2d729d40f30686a7c435867c88436))': + '@analogjs/vite-plugin-angular@1.22.5(@angular/build@21.2.15(04a6deee5a19f5aede5908c321226b68))': dependencies: ts-morph: 21.0.1 vfile: 6.0.3 optionalDependencies: - '@angular/build': 21.2.15(73b2d729d40f30686a7c435867c88436) + '@angular/build': 21.2.15(04a6deee5a19f5aede5908c321226b68) - '@analogjs/vite-plugin-angular@1.22.5(@angular/build@21.2.15(b4e3cce66654bd2e0d0fab951dffc04a))': + '@analogjs/vite-plugin-angular@1.22.5(@angular/build@21.2.15(dc2c5e0af87e42451164817325dee7e3))': dependencies: ts-morph: 21.0.1 vfile: 6.0.3 optionalDependencies: - '@angular/build': 21.2.15(b4e3cce66654bd2e0d0fab951dffc04a) + '@angular/build': 21.2.15(dc2c5e0af87e42451164817325dee7e3) '@angular-devkit/architect@0.2102.15(chokidar@5.0.0)': dependencies: @@ -14901,7 +14971,7 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular/build@21.2.15(73b2d729d40f30686a7c435867c88436)': + '@angular/build@21.2.15(04a6deee5a19f5aede5908c321226b68)': dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.2102.15(chokidar@5.0.0) @@ -14924,7 +14994,7 @@ snapshots: parse5-html-rewriting-stream: 8.0.0 picomatch: 4.0.4 piscina: 5.1.4 - rolldown: 1.0.0-rc.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + rolldown: 1.0.0-rc.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) sass: 1.97.3 semver: 7.7.4 source-map-support: 0.5.21 @@ -14942,7 +15012,7 @@ snapshots: ng-packagr: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) postcss: 8.5.15 tailwindcss: 4.1.18 - vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.15))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.15))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -14958,7 +15028,7 @@ snapshots: - tsx - yaml - '@angular/build@21.2.15(b4e3cce66654bd2e0d0fab951dffc04a)': + '@angular/build@21.2.15(dc2c5e0af87e42451164817325dee7e3)': dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.2102.15(chokidar@5.0.0) @@ -14981,7 +15051,7 @@ snapshots: parse5-html-rewriting-stream: 8.0.0 picomatch: 4.0.4 piscina: 5.1.4 - rolldown: 1.0.0-rc.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + rolldown: 1.0.0-rc.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) sass: 1.97.3 semver: 7.7.4 source-map-support: 0.5.21 @@ -14999,7 +15069,7 @@ snapshots: ng-packagr: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) postcss: 8.5.15 tailwindcss: 4.1.18 - vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.15))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.15))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -16240,6 +16310,12 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.11.0': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/core@1.7.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -16250,6 +16326,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.7.1': dependencies: tslib: 2.8.1 @@ -16263,6 +16344,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.20.2': optional: true @@ -17615,13 +17701,20 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 + '@emnapi/core': 1.11.0 + '@emnapi/runtime': 1.11.0 '@tybys/wasm-util': 0.10.1 optional: true + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)': + dependencies: + '@emnapi/core': 1.11.0 + '@emnapi/runtime': 1.11.0 + '@tybys/wasm-util': 0.10.2 + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -17774,7 +17867,7 @@ snapshots: '@oxc-project/types@0.113.0': {} - '@oxc-project/types@0.127.0': {} + '@oxc-project/types@0.135.0': {} '@oxc-resolver/binding-android-arm-eabi@11.15.0': optional: true @@ -18870,97 +18963,97 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0-beta.53': optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.17': + '@rolldown/binding-android-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.4': + '@rolldown/binding-android-arm64@1.1.1': optional: true '@rolldown/binding-darwin-arm64@1.0.0-beta.53': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + '@rolldown/binding-darwin-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.4': + '@rolldown/binding-darwin-arm64@1.1.1': optional: true '@rolldown/binding-darwin-x64@1.0.0-beta.53': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.17': + '@rolldown/binding-darwin-x64@1.0.0-rc.4': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.4': + '@rolldown/binding-darwin-x64@1.1.1': optional: true '@rolldown/binding-freebsd-x64@1.0.0-beta.53': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + '@rolldown/binding-freebsd-x64@1.0.0-rc.4': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.4': + '@rolldown/binding-freebsd-x64@1.1.1': optional: true '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': + '@rolldown/binding-linux-arm-gnueabihf@1.1.1': optional: true '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': + '@rolldown/binding-linux-arm64-gnu@1.1.1': optional: true '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': + '@rolldown/binding-linux-arm64-musl@1.1.1': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-ppc64-gnu@1.1.1': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-s390x-gnu@1.1.1': optional: true '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': + '@rolldown/binding-linux-x64-gnu@1.1.1': optional: true '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': + '@rolldown/binding-linux-x64-musl@1.1.1': optional: true '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': + '@rolldown/binding-openharmony-arm64@1.1.1': optional: true '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': @@ -18968,49 +19061,49 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.0 optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - optional: true - - '@rolldown/binding-wasm32-wasi@1.0.0-rc.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)': dependencies: - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': + '@rolldown/binding-wasm32-wasi@1.1.1': + dependencies: + '@emnapi/core': 1.11.0 + '@emnapi/runtime': 1.11.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': + '@rolldown/binding-win32-arm64-msvc@1.1.1': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': optional: true '@rolldown/binding-win32-x64-msvc@1.0.0-rc.4': optional: true + '@rolldown/binding-win32-x64-msvc@1.1.1': + optional: true + '@rolldown/pluginutils@1.0.0-beta.27': {} '@rolldown/pluginutils@1.0.0-beta.40': {} '@rolldown/pluginutils@1.0.0-beta.53': {} - '@rolldown/pluginutils@1.0.0-rc.17': {} - '@rolldown/pluginutils@1.0.0-rc.4': {} + '@rolldown/pluginutils@1.0.1': {} + '@rollup/plugin-alias@5.1.1(rollup@4.60.1)': optionalDependencies: rollup: 4.60.1 @@ -19799,9 +19892,9 @@ snapshots: '@tanstack/history@1.154.14': {} - '@tanstack/nitro-v2-vite-plugin@1.154.7(rolldown@1.0.0-rc.17)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/nitro-v2-vite-plugin@1.154.7(rolldown@1.1.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - nitropack: 2.13.1(rolldown@1.0.0-rc.17) + nitropack: 2.13.1(rolldown@1.1.1) pathe: 2.0.3 vite: 7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: @@ -19936,9 +20029,9 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/react-start-plugin@1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@vitejs/plugin-react@4.7.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rolldown@1.0.0-rc.17)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/react-start-plugin@1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@vitejs/plugin-react@4.7.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rolldown@1.1.1)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@tanstack/start-plugin-core': 1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(rolldown@1.0.0-rc.17)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@tanstack/start-plugin-core': 1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(rolldown@1.1.1)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitejs/plugin-react': 4.7.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) pathe: 2.0.3 vite: 7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) @@ -19978,11 +20071,11 @@ snapshots: - webpack - xml2js - '@tanstack/react-start-router-manifest@1.120.19(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)': + '@tanstack/react-start-router-manifest@1.120.19(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)': dependencies: '@tanstack/router-core': 1.157.16 tiny-invariant: 1.3.3 - vinxi: 0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vinxi: 0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -20028,13 +20121,13 @@ snapshots: - xml2js - yaml - '@tanstack/react-start-server@1.141.1(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-start-server@1.141.1(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/history': 1.141.0 '@tanstack/react-router': 1.141.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/router-core': 1.141.1 '@tanstack/start-client-core': 1.141.1 - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: @@ -20052,13 +20145,13 @@ snapshots: transitivePeerDependencies: - crossws - '@tanstack/react-start-server@1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-start-server@1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/history': 1.154.14 '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/router-core': 1.159.4 '@tanstack/start-client-core': 1.159.4 - '@tanstack/start-server-core': 1.159.4(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.16)) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: @@ -20084,15 +20177,15 @@ snapshots: - vite-plugin-solid - webpack - '@tanstack/react-start@1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/react-start@1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start-client': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/react-start-server': 1.159.5(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/react-start-server': 1.159.5(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/router-utils': 1.158.0 '@tanstack/start-client-core': 1.159.4 - '@tanstack/start-plugin-core': 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.5(srvx@0.11.15))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@tanstack/start-server-core': 1.159.4(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-plugin-core': 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.6(srvx@0.11.16))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.16)) pathe: 2.0.3 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) @@ -20417,26 +20510,26 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/solid-start-server@1.141.1(crossws@0.4.5(srvx@0.11.15))(solid-js@1.9.10)': + '@tanstack/solid-start-server@1.141.1(crossws@0.4.6(srvx@0.11.16))(solid-js@1.9.10)': dependencies: '@solidjs/meta': 0.29.4(solid-js@1.9.10) '@tanstack/history': 1.141.0 '@tanstack/router-core': 1.141.1 '@tanstack/solid-router': 1.141.1(solid-js@1.9.10) '@tanstack/start-client-core': 1.141.1 - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) solid-js: 1.9.10 transitivePeerDependencies: - crossws - '@tanstack/solid-start@1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.5(srvx@0.11.15))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/solid-start@1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.6(srvx@0.11.16))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@tanstack/solid-router': 1.141.1(solid-js@1.9.10) '@tanstack/solid-start-client': 1.141.1(solid-js@1.9.10) - '@tanstack/solid-start-server': 1.141.1(crossws@0.4.5(srvx@0.11.15))(solid-js@1.9.10) + '@tanstack/solid-start-server': 1.141.1(crossws@0.4.6(srvx@0.11.16))(solid-js@1.9.10) '@tanstack/start-client-core': 1.141.1 - '@tanstack/start-plugin-core': 1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.5(srvx@0.11.15))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-plugin-core': 1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.6(srvx@0.11.16))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) pathe: 2.0.3 solid-js: 1.9.10 vite: 7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) @@ -20453,11 +20546,11 @@ snapshots: '@tanstack/store': 0.8.0 solid-js: 1.9.10 - '@tanstack/start-api-routes@1.120.19(@types/node@24.10.3)(crossws@0.4.5(srvx@0.11.15))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)': + '@tanstack/start-api-routes@1.120.19(@types/node@24.10.3)(crossws@0.4.6(srvx@0.11.16))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)': dependencies: '@tanstack/router-core': 1.157.16 - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) - vinxi: 0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) + vinxi: 0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -20529,21 +20622,21 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/start-config@1.120.20(@types/node@24.10.3)(crossws@0.4.5(srvx@0.11.15))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)': + '@tanstack/start-config@1.120.20(@types/node@24.10.3)(crossws@0.4.6(srvx@0.11.16))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)': dependencies: '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/react-start-plugin': 1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@vitejs/plugin-react@4.7.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rolldown@1.0.0-rc.17)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@tanstack/react-start-plugin': 1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@vitejs/plugin-react@4.7.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rolldown@1.1.1)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/router-generator': 1.141.1 '@tanstack/router-plugin': 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/server-functions-plugin': 1.141.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@tanstack/start-server-functions-handler': 1.120.19(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-functions-handler': 1.120.19(crossws@0.4.6(srvx@0.11.16)) '@vitejs/plugin-react': 4.7.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) import-meta-resolve: 4.2.0 - nitropack: 2.12.9(rolldown@1.0.0-rc.17) + nitropack: 2.12.9(rolldown@1.1.1) ofetch: 1.5.1 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - vinxi: 0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vinxi: 0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite: 7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) zod: 3.25.76 transitivePeerDependencies: @@ -20597,7 +20690,7 @@ snapshots: '@tanstack/start-fn-stubs@1.154.7': {} - '@tanstack/start-plugin-core@1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(rolldown@1.0.0-rc.17)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/start-plugin-core@1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(rolldown@1.1.1)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/code-frame': 7.26.2 '@babel/core': 7.29.0 @@ -20613,7 +20706,7 @@ snapshots: babel-dead-code-elimination: 1.0.10 cheerio: 1.1.2 h3: 1.13.0 - nitropack: 2.12.9(rolldown@1.0.0-rc.17) + nitropack: 2.12.9(rolldown@1.1.1) pathe: 2.0.3 ufo: 1.6.1 vite: 7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) @@ -20655,7 +20748,7 @@ snapshots: - webpack - xml2js - '@tanstack/start-plugin-core@1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.5(srvx@0.11.15))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/start-plugin-core@1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.6(srvx@0.11.16))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/code-frame': 7.26.2 '@babel/core': 7.29.0 @@ -20667,7 +20760,7 @@ snapshots: '@tanstack/router-utils': 1.141.0 '@tanstack/server-functions-plugin': 1.141.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/start-client-core': 1.141.1 - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) babel-dead-code-elimination: 1.0.10 cheerio: 1.1.2 exsolve: 1.0.8 @@ -20717,7 +20810,7 @@ snapshots: - vite-plugin-solid - webpack - '@tanstack/start-plugin-core@1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.5(srvx@0.11.15))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/start-plugin-core@1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.6(srvx@0.11.16))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.29.0 @@ -20728,7 +20821,7 @@ snapshots: '@tanstack/router-plugin': 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/router-utils': 1.158.0 '@tanstack/start-client-core': 1.159.4 - '@tanstack/start-server-core': 1.159.4(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.16)) cheerio: 1.1.2 exsolve: 1.0.8 pathe: 2.0.3 @@ -20759,13 +20852,13 @@ snapshots: tiny-warning: 1.0.3 unctx: 2.4.1 - '@tanstack/start-server-core@1.141.1(crossws@0.4.5(srvx@0.11.15))': + '@tanstack/start-server-core@1.141.1(crossws@0.4.6(srvx@0.11.16))': dependencies: '@tanstack/history': 1.141.0 '@tanstack/router-core': 1.141.1 '@tanstack/start-client-core': 1.141.1 '@tanstack/start-storage-context': 1.141.1 - h3-v2: h3@2.0.0-beta.5(crossws@0.4.5(srvx@0.11.15)) + h3-v2: h3@2.0.0-beta.5(crossws@0.4.6(srvx@0.11.16)) seroval: 1.4.0 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -20783,13 +20876,13 @@ snapshots: transitivePeerDependencies: - crossws - '@tanstack/start-server-core@1.159.4(crossws@0.4.5(srvx@0.11.15))': + '@tanstack/start-server-core@1.159.4(crossws@0.4.6(srvx@0.11.16))': dependencies: '@tanstack/history': 1.154.14 '@tanstack/router-core': 1.159.4 '@tanstack/start-client-core': 1.159.4 '@tanstack/start-storage-context': 1.159.4 - h3-v2: h3@2.0.1-rc.14(crossws@0.4.5(srvx@0.11.15)) + h3-v2: h3@2.0.1-rc.14(crossws@0.4.6(srvx@0.11.16)) seroval: 1.5.0 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -20808,11 +20901,11 @@ snapshots: '@tanstack/router-core': 1.131.50 '@tanstack/start-client-core': 1.131.50 - '@tanstack/start-server-functions-handler@1.120.19(crossws@0.4.5(srvx@0.11.15))': + '@tanstack/start-server-functions-handler@1.120.19(crossws@0.4.6(srvx@0.11.16))': dependencies: '@tanstack/router-core': 1.157.16 '@tanstack/start-client-core': 1.141.1 - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) tiny-invariant: 1.3.3 transitivePeerDependencies: - crossws @@ -20825,11 +20918,11 @@ snapshots: - supports-color - vite - '@tanstack/start-server-functions-ssr@1.120.19(crossws@0.4.5(srvx@0.11.15))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/start-server-functions-ssr@1.120.19(crossws@0.4.6(srvx@0.11.16))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@tanstack/server-functions-plugin': 1.141.0(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tanstack/start-client-core': 1.141.1 - '@tanstack/start-server-core': 1.141.1(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.16)) '@tanstack/start-server-functions-fetcher': 1.131.50 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -20849,17 +20942,17 @@ snapshots: dependencies: '@tanstack/router-core': 1.159.4 - '@tanstack/start@1.120.20(@types/node@24.10.3)(crossws@0.4.5(srvx@0.11.15))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)': + '@tanstack/start@1.120.20(@types/node@24.10.3)(crossws@0.4.6(srvx@0.11.16))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2)': dependencies: '@tanstack/react-start-client': 1.141.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/react-start-router-manifest': 1.120.19(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@tanstack/react-start-server': 1.141.1(crossws@0.4.5(srvx@0.11.15))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/start-api-routes': 1.120.19(@types/node@24.10.3)(crossws@0.4.5(srvx@0.11.15))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@tanstack/start-config': 1.120.20(@types/node@24.10.3)(crossws@0.4.5(srvx@0.11.15))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2) + '@tanstack/react-start-router-manifest': 1.120.19(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + '@tanstack/react-start-server': 1.141.1(crossws@0.4.6(srvx@0.11.16))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/start-api-routes': 1.120.19(@types/node@24.10.3)(crossws@0.4.6(srvx@0.11.16))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + '@tanstack/start-config': 1.120.20(@types/node@24.10.3)(crossws@0.4.6(srvx@0.11.16))(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(yaml@2.8.2) '@tanstack/start-server-functions-client': 1.131.50(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@tanstack/start-server-functions-handler': 1.120.19(crossws@0.4.5(srvx@0.11.15)) + '@tanstack/start-server-functions-handler': 1.120.19(crossws@0.4.6(srvx@0.11.16)) '@tanstack/start-server-functions-server': 1.131.2(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@tanstack/start-server-functions-ssr': 1.120.19(crossws@0.4.5(srvx@0.11.15))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@tanstack/start-server-functions-ssr': 1.120.19(crossws@0.4.6(srvx@0.11.16))(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -20999,6 +21092,11 @@ snapshots: tslib: 2.8.1 optional: true + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 @@ -21032,6 +21130,10 @@ snapshots: '@types/braces@3.0.5': {} + '@types/bun@1.3.14': + dependencies: + bun-types: 1.3.14 + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -22314,6 +22416,10 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + bun-types@1.3.14: + dependencies: + '@types/node': 24.10.3 + bundle-require@5.1.0(esbuild@0.27.3): dependencies: esbuild: 0.27.3 @@ -22724,9 +22830,13 @@ snapshots: optionalDependencies: srvx: 0.10.1 - crossws@0.4.5(srvx@0.11.15): + crossws@0.4.5(srvx@0.11.16): optionalDependencies: - srvx: 0.11.15 + srvx: 0.11.16 + + crossws@0.4.6(srvx@0.11.16): + optionalDependencies: + srvx: 0.11.16 css-select@5.2.2: dependencies: @@ -23049,14 +23159,15 @@ snapshots: env-paths@2.2.1: {} - env-runner@0.1.7(miniflare@4.20260609.0): + env-runner@0.1.14(miniflare@4.20260609.0)(wrangler@4.88.0): dependencies: - crossws: 0.4.5(srvx@0.11.15) + crossws: 0.4.5(srvx@0.11.16) exsolve: 1.0.8 - httpxy: 0.5.1 - srvx: 0.11.15 + httpxy: 0.5.3 + srvx: 0.11.16 optionalDependencies: miniflare: 4.20260609.0 + wrangler: 4.88.0(@cloudflare/workers-types@4.20260317.1) environment@1.1.0: {} @@ -24079,14 +24190,14 @@ snapshots: ufo: 1.6.3 uncrypto: 0.1.3 - h3@2.0.0-beta.5(crossws@0.4.5(srvx@0.11.15)): + h3@2.0.0-beta.5(crossws@0.4.6(srvx@0.11.16)): dependencies: cookie-es: 2.0.1 fetchdts: 0.1.7 rou3: 0.7.12 srvx: 0.8.16 optionalDependencies: - crossws: 0.4.5(srvx@0.11.15) + crossws: 0.4.6(srvx@0.11.16) h3@2.0.1-rc.14(crossws@0.4.4(srvx@0.10.1)): dependencies: @@ -24095,19 +24206,19 @@ snapshots: optionalDependencies: crossws: 0.4.4(srvx@0.10.1) - h3@2.0.1-rc.14(crossws@0.4.5(srvx@0.11.15)): + h3@2.0.1-rc.14(crossws@0.4.6(srvx@0.11.16)): dependencies: rou3: 0.7.12 srvx: 0.11.15 optionalDependencies: - crossws: 0.4.5(srvx@0.11.15) + crossws: 0.4.6(srvx@0.11.16) - h3@2.0.1-rc.20(crossws@0.4.5(srvx@0.11.15)): + h3@2.0.1-rc.22(crossws@0.4.6(srvx@0.11.16)): dependencies: rou3: 0.8.1 srvx: 0.11.15 optionalDependencies: - crossws: 0.4.5(srvx@0.11.15) + crossws: 0.4.6(srvx@0.11.16) happy-dom@20.0.11: dependencies: @@ -24320,7 +24431,7 @@ snapshots: httpxy@0.1.7: {} - httpxy@0.5.1: {} + httpxy@0.5.3: {} human-id@4.1.3: {} @@ -25926,7 +26037,7 @@ snapshots: nf3@0.3.10: {} - nf3@0.3.16: {} + nf3@0.3.17: {} ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3): dependencies: @@ -25958,7 +26069,7 @@ snapshots: rollup: 4.60.1 tailwindcss: 4.1.18 - nitro@3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.0.0-rc.17)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + nitro@3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.1.1)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: consola: 3.4.2 crossws: 0.4.4(srvx@0.10.1) @@ -25975,7 +26086,7 @@ snapshots: unenv: 2.0.0-rc.24 unstorage: 2.0.0-alpha.5(chokidar@5.0.0)(db0@0.3.4)(ioredis@5.9.2)(lru-cache@11.2.4)(ofetch@2.0.0-alpha.3) optionalDependencies: - rolldown: 1.0.0-rc.17 + rolldown: 1.1.1 rollup: 4.60.1 vite: 7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: @@ -26007,20 +26118,20 @@ snapshots: - sqlite3 - uploadthing - nitro@3.0.260429-beta(chokidar@5.0.0)(dotenv@17.2.3)(giget@2.0.0)(jiti@2.6.1)(miniflare@4.20260609.0)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + nitro@3.0.260610-beta(chokidar@5.0.0)(dotenv@17.2.3)(giget@2.0.0)(jiti@2.6.1)(miniflare@4.20260609.0)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(wrangler@4.88.0): dependencies: consola: 3.4.2 - crossws: 0.4.5(srvx@0.11.15) + crossws: 0.4.6(srvx@0.11.16) db0: 0.3.4 - env-runner: 0.1.7(miniflare@4.20260609.0) - h3: 2.0.1-rc.20(crossws@0.4.5(srvx@0.11.15)) + env-runner: 0.1.14(miniflare@4.20260609.0)(wrangler@4.88.0) + h3: 2.0.1-rc.22(crossws@0.4.6(srvx@0.11.16)) hookable: 6.1.1 - nf3: 0.3.16 - ocache: 0.1.4 + nf3: 0.3.17 + ocache: 0.1.5 ofetch: 2.0.0-alpha.3 ohash: 2.0.11 - rolldown: 1.0.0-rc.17 - srvx: 0.11.15 + rolldown: 1.1.1 + srvx: 0.11.16 unenv: 2.0.0-rc.24 unstorage: 2.0.0-alpha.7(chokidar@5.0.0)(db0@0.3.4)(ofetch@2.0.0-alpha.3) optionalDependencies: @@ -26059,8 +26170,9 @@ snapshots: - mysql2 - sqlite3 - uploadthing + - wrangler - nitropack@2.12.9(rolldown@1.0.0-rc.17): + nitropack@2.12.9(rolldown@1.1.1): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 '@rollup/plugin-alias': 5.1.1(rollup@4.60.1) @@ -26113,7 +26225,7 @@ snapshots: pretty-bytes: 7.1.0 radix3: 1.1.2 rollup: 4.60.1 - rollup-plugin-visualizer: 6.0.5(rolldown@1.0.0-rc.17)(rollup@4.60.1) + rollup-plugin-visualizer: 6.0.5(rolldown@1.1.1)(rollup@4.60.1) scule: 1.3.0 semver: 7.7.4 serve-placeholder: 2.0.2 @@ -26162,7 +26274,7 @@ snapshots: - supports-color - uploadthing - nitropack@2.13.1(rolldown@1.0.0-rc.17): + nitropack@2.13.1(rolldown@1.1.1): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 '@rollup/plugin-alias': 6.0.0(rollup@4.57.1) @@ -26215,7 +26327,7 @@ snapshots: pretty-bytes: 7.1.0 radix3: 1.1.2 rollup: 4.57.1 - rollup-plugin-visualizer: 6.0.5(rolldown@1.0.0-rc.17)(rollup@4.57.1) + rollup-plugin-visualizer: 6.0.5(rolldown@1.1.1)(rollup@4.57.1) scule: 1.3.0 semver: 7.7.4 serve-placeholder: 2.0.2 @@ -26418,7 +26530,7 @@ snapshots: obug@2.1.1: {} - ocache@0.1.4: + ocache@0.1.5: dependencies: ohash: 2.0.11 @@ -27016,6 +27128,8 @@ snapshots: dependencies: inherits: 2.0.4 + quickjs-bun@0.1.2: {} + quickjs-emscripten-core@0.31.0: dependencies: '@jitl/quickjs-ffi-types': 0.31.0 @@ -27509,28 +27623,7 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53 - rolldown@1.0.0-rc.17: - dependencies: - '@oxc-project/types': 0.127.0 - '@rolldown/pluginutils': 1.0.0-rc.17 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.17 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 - '@rolldown/binding-darwin-x64': 1.0.0-rc.17 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 - - rolldown@1.0.0-rc.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0): + rolldown@1.0.0-rc.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0): dependencies: '@oxc-project/types': 0.113.0 '@rolldown/pluginutils': 1.0.0-rc.4 @@ -27545,13 +27638,34 @@ snapshots: '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.4 '@rolldown/binding-linux-x64-musl': 1.0.0-rc.4 '@rolldown/binding-openharmony-arm64': 1.0.0-rc.4 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.4(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.4 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.4 transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' + rolldown@1.1.1: + dependencies: + '@oxc-project/types': 0.135.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.1 + '@rolldown/binding-darwin-arm64': 1.1.1 + '@rolldown/binding-darwin-x64': 1.1.1 + '@rolldown/binding-freebsd-x64': 1.1.1 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.1 + '@rolldown/binding-linux-arm64-gnu': 1.1.1 + '@rolldown/binding-linux-arm64-musl': 1.1.1 + '@rolldown/binding-linux-ppc64-gnu': 1.1.1 + '@rolldown/binding-linux-s390x-gnu': 1.1.1 + '@rolldown/binding-linux-x64-gnu': 1.1.1 + '@rolldown/binding-linux-x64-musl': 1.1.1 + '@rolldown/binding-openharmony-arm64': 1.1.1 + '@rolldown/binding-wasm32-wasi': 1.1.1 + '@rolldown/binding-win32-arm64-msvc': 1.1.1 + '@rolldown/binding-win32-x64-msvc': 1.1.1 + rollup-plugin-dts@6.4.1(rollup@4.60.1)(typescript@5.9.3): dependencies: '@jridgewell/remapping': 2.3.5 @@ -27569,24 +27683,24 @@ snapshots: magic-string: 0.30.21 rollup: 4.60.1 - rollup-plugin-visualizer@6.0.5(rolldown@1.0.0-rc.17)(rollup@4.57.1): + rollup-plugin-visualizer@6.0.5(rolldown@1.1.1)(rollup@4.57.1): dependencies: open: 8.4.2 picomatch: 4.0.4 source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: - rolldown: 1.0.0-rc.17 + rolldown: 1.1.1 rollup: 4.57.1 - rollup-plugin-visualizer@6.0.5(rolldown@1.0.0-rc.17)(rollup@4.60.1): + rollup-plugin-visualizer@6.0.5(rolldown@1.1.1)(rollup@4.60.1): dependencies: open: 8.4.2 picomatch: 4.0.4 source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: - rolldown: 1.0.0-rc.17 + rolldown: 1.1.1 rollup: 4.60.1 rollup@4.57.1: @@ -28059,6 +28173,8 @@ snapshots: srvx@0.11.15: {} + srvx@0.11.16: {} + srvx@0.11.2: {} srvx@0.8.16: {} @@ -28916,7 +29032,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vinxi@0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.0.0-rc.17)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vinxi@0.5.3(@types/node@24.10.3)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(less@4.6.6)(lightningcss@1.30.2)(rolldown@1.1.1)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.29.0) @@ -28938,7 +29054,7 @@ snapshots: hookable: 5.5.3 http-proxy: 1.18.1 micromatch: 4.0.8 - nitropack: 2.12.9(rolldown@1.0.0-rc.17) + nitropack: 2.12.9(rolldown@1.1.1) node-fetch-native: 1.6.7 path-to-regexp: 6.3.0 pathe: 1.1.2 From ab738517ad829dd731f2167cf6ad8fb9bb6f9dad Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki <63115601+lithdew@users.noreply.github.com> Date: Fri, 12 Jun 2026 02:49:53 +0800 Subject: [PATCH 2/2] fix: docs/code-mode/code-mode-isolates.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- docs/code-mode/code-mode-isolates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/code-mode/code-mode-isolates.md b/docs/code-mode/code-mode-isolates.md index f48e09039..9a9fbe304 100644 --- a/docs/code-mode/code-mode-isolates.md +++ b/docs/code-mode/code-mode-isolates.md @@ -114,7 +114,7 @@ QuickJS WASM uses an asyncified execution model — the WASM module can pause wh ## 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. +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