From 420dd13ddeac70f93767d7b3b49fb35714aa84e1 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Fri, 14 Aug 2026 18:42:12 +0200 Subject: [PATCH 01/23] feat: honor outputSchema on dedicated harness adapters Harness adapters honor chat({ outputSchema }) on the same turn. Claude Code and Codex pass a native schema flag. OpenCode and Grok Build parse JSON from the last assistant text. The engine reads structured-output.complete so harness prose is not parsed as JSON. Add a repo-report page in ts-react-chat and a Harness Agents guide. --- .changeset/harness-output-schema.md | 11 + docs/adapters/acp-compatible.md | 2 + docs/adapters/claude-code.md | 29 +- docs/adapters/codex.md | 29 +- docs/adapters/grok-build.md | 31 +++ docs/adapters/opencode.md | 29 +- docs/chat/structured-outputs.md | 1 + docs/config.json | 30 ++- docs/sandbox/harnesses.md | 4 + docs/sandbox/overview.md | 6 +- docs/structured-outputs/harnesses.md | 199 ++++++++++++++ docs/structured-outputs/one-shot.md | 2 +- docs/structured-outputs/overview.md | 7 +- docs/structured-outputs/streaming.md | 2 +- docs/structured-outputs/with-tools.md | 2 + .../ts-react-chat/src/components/Header.tsx | 13 + .../ts-react-chat/src/repo-report-options.ts | 51 ++++ .../src/repo-report-prompt.test.ts | 12 + .../ts-react-chat/src/repo-report-schema.ts | 16 ++ examples/ts-react-chat/src/routeTree.gen.ts | 62 ++++- .../src/routes/api.sandbox-repo-report.ts | 122 +++++++++ examples/ts-react-chat/src/routes/index.tsx | 7 + .../src/routes/sandboxes.repo-report.tsx | 206 ++++++++++++++ packages/ai-claude-code/src/adapters/text.ts | 26 +- .../ai-claude-code/src/stream/translate.ts | 28 ++ .../ai-claude-code/tests/text-adapter.test.ts | 53 ++++ .../ai-claude-code/tests/translate.test.ts | 75 +++++- packages/ai-codex/src/adapters/text.ts | 27 +- packages/ai-codex/src/stream/translate.ts | 106 ++++++-- packages/ai-codex/tests/text-adapter.test.ts | 52 ++++ packages/ai-codex/tests/translate.test.ts | 72 +++++ packages/ai-grok-build/src/adapters/text.ts | 92 ++++++- .../ai-grok-build/src/stream/translate.ts | 41 +++ .../ai-grok-build/tests/translate.test.ts | 45 +++- packages/ai-opencode/src/adapters/text.ts | 65 ++++- .../ai-opencode/tests/text-adapter.test.ts | 6 + .../ai-core/structured-outputs/SKILL.md | 71 ++++- packages/ai/src/activities/chat/adapter.ts | 14 + packages/ai/src/activities/chat/index.ts | 129 ++++++--- packages/ai/src/adapter-internals.ts | 8 + packages/ai/src/types.ts | 11 +- .../src/utilities/structured-output-events.ts | 44 +++ .../src/utilities/structured-output-text.ts | 21 ++ ...t-combined-event-structured-output.test.ts | 252 ++++++++++++++++++ .../ai/tests/structured-output-text.test.ts | 33 +++ packages/ai/tests/test-utils.ts | 7 + 46 files changed, 2047 insertions(+), 104 deletions(-) create mode 100644 .changeset/harness-output-schema.md create mode 100644 docs/structured-outputs/harnesses.md create mode 100644 examples/ts-react-chat/src/repo-report-options.ts create mode 100644 examples/ts-react-chat/src/repo-report-prompt.test.ts create mode 100644 examples/ts-react-chat/src/repo-report-schema.ts create mode 100644 examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts create mode 100644 examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx create mode 100644 packages/ai/src/utilities/structured-output-events.ts create mode 100644 packages/ai/src/utilities/structured-output-text.ts create mode 100644 packages/ai/tests/chat-combined-event-structured-output.test.ts create mode 100644 packages/ai/tests/structured-output-text.test.ts diff --git a/.changeset/harness-output-schema.md b/.changeset/harness-output-schema.md new file mode 100644 index 0000000000..3e98a72526 --- /dev/null +++ b/.changeset/harness-output-schema.md @@ -0,0 +1,11 @@ +--- +'@tanstack/ai': minor +'@tanstack/ai-claude-code': minor +'@tanstack/ai-codex': minor +'@tanstack/ai-opencode': minor +'@tanstack/ai-grok-build': minor +--- + +Harness adapters honor `chat({ outputSchema })` on the same turn. + +Claude Code and Codex pass a native schema flag. OpenCode and Grok Build parse JSON from the final assistant text. The engine reads a `structured-output.complete` event so harness prose is not parsed as JSON. diff --git a/docs/adapters/acp-compatible.md b/docs/adapters/acp-compatible.md index 54c03fd4e5..a309ebacb3 100644 --- a/docs/adapters/acp-compatible.md +++ b/docs/adapters/acp-compatible.md @@ -16,6 +16,8 @@ Coding-agent CLIs that speak the [Agent Client Protocol](https://agentclientprot It is the harness equivalent of the [OpenAI-Compatible adapter](./openai-compatible). Use it when your agent speaks ACP but has no `@tanstack/ai-*` package. If a dedicated harness adapter exists ([Grok Build](./grok-build), and others), prefer it — those carry curated per-model metadata and vendor-specific behavior. +`acpCompatible` does not accept `outputSchema`. If you need a typed object from a coding agent, use a dedicated harness adapter. See [Harness Agents](../structured-outputs/harnesses). + ## Installation `acpCompatible` ships in `@tanstack/ai-acp`. You drive it inside a sandbox, so install the sandbox package and a provider too: diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index 01bfaeb300..a486ee9a6f 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -170,7 +170,34 @@ const stream = chat({ ## Structured Output -`structuredOutput()` uses the harness's native JSON-schema output format in a one-shot run (single turn, no tools). It works for finalization after a chat, but a plain provider adapter (e.g. `@tanstack/ai-anthropic`) is the better choice when structured extraction is the primary job — it's faster and doesn't spawn a subprocess. +Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema is sent with `--json-schema`. Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. + +```ts +import { chat } from "@tanstack/ai" +import { claudeCodeText } from "@tanstack/ai-claude-code" +import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +const report = await chat({ + adapter: claudeCodeText("claude-opus-4-8"), + messages: [{ role: "user", content: "Review this repo." }], + outputSchema: Report, + middleware: [withSandbox(defineSandbox({ /* provider */ }))], +}) + +report.summary +``` + +On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. + +If you only need to extract JSON from a prompt and do not need a sandbox, use `@tanstack/ai-anthropic`. That path is faster. + +Full walkthrough, including the client: [Harness Agents](../structured-outputs/harnesses). ## Limitations diff --git a/docs/adapters/codex.md b/docs/adapters/codex.md index eb000dd053..64607d9488 100644 --- a/docs/adapters/codex.md +++ b/docs/adapters/codex.md @@ -170,7 +170,34 @@ const stream = chat({ ## Structured Output -`structuredOutput()` uses Codex's native `outputSchema` support in a fresh, read-only, one-shot thread whose final message is a JSON string conforming to your schema. It works for finalization after a chat, but a plain provider adapter (e.g. `@tanstack/ai-openai`) is the better choice when structured extraction is the primary job — it's faster and doesn't spawn a subprocess. +Pass `outputSchema` on `chat()`. Codex runs one harness turn and constrains the last message with `--output-schema`. Tool activity still streams. The object arrives as `structured-output.complete`. + +```ts +import { chat } from "@tanstack/ai" +import { codexText } from "@tanstack/ai-codex" +import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +const report = await chat({ + adapter: codexText("gpt-5.3-codex"), + messages: [{ role: "user", content: "Review this repo." }], + outputSchema: Report, + middleware: [withSandbox(defineSandbox({ /* provider */ }))], +}) + +report.summary +``` + +On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. + +If you only need to extract JSON from a prompt and do not need a sandbox, use `@tanstack/ai-openai`. That path is faster. + +Full walkthrough, including the client: [Harness Agents](../structured-outputs/harnesses). ## Limitations diff --git a/docs/adapters/grok-build.md b/docs/adapters/grok-build.md index 7d1e6600cc..2fa25cd1df 100644 --- a/docs/adapters/grok-build.md +++ b/docs/adapters/grok-build.md @@ -185,6 +185,37 @@ On the `'streaming-json'` path with auto-approve, the adapter adds `--always-approve --no-plan --no-auto-update`. Those flags keep Plan Mode and the CLI update check from blocking a headless run. +## Structured Output + +Pass `outputSchema` on `chat()`. Grok Build has no native schema flag. The adapter adds the JSON Schema to the prompt (ACP and `streaming-json`) and parses the last assistant text. Tool activity still streams. The object arrives as `structured-output.complete`. + +```ts +import { chat } from "@tanstack/ai" +import { grokBuildText } from "@tanstack/ai-grok-build" +import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +const report = await chat({ + adapter: grokBuildText("grok-build"), + messages: [{ role: "user", content: "Review this repo." }], + outputSchema: Report, + middleware: [withSandbox(defineSandbox({ /* provider */ }))], +}) + +report.summary +``` + +This path parses JSON from the last assistant message. If extract-only is the job, use `@tanstack/ai-grok`. + +On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. + +Full walkthrough, including the client: [Harness Agents](../structured-outputs/harnesses). + ## Limitations - **Requires a sandbox.** Always run it under `withSandbox(...)`; see the diff --git a/docs/adapters/opencode.md b/docs/adapters/opencode.md index 23ccbb453c..48790e2a0a 100644 --- a/docs/adapters/opencode.md +++ b/docs/adapters/opencode.md @@ -175,7 +175,34 @@ const stream = chat({ ## Structured Output -`structuredOutput()` is best-effort: OpenCode's prompt API has no native JSON-schema channel, so the schema is embedded as a prompt instruction in a fresh, one-shot session and the final text is parsed (markdown fences are stripped when present). It works for finalization after a chat, but a plain provider adapter (e.g. `@tanstack/ai-openai`) is the better choice when structured extraction is the primary job — it's faster, deterministic, and doesn't spawn a harness. +Pass `outputSchema` on `chat()`. OpenCode has no native schema flag. The adapter adds the JSON Schema to the prompt and parses the last assistant text (markdown fences are stripped). Tool activity still streams. The object arrives as `structured-output.complete`. + +```ts +import { chat } from "@tanstack/ai" +import { opencodeText } from "@tanstack/ai-opencode" +import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +const report = await chat({ + adapter: opencodeText("anthropic/claude-opus-4-5"), + messages: [{ role: "user", content: "Review this repo." }], + outputSchema: Report, + middleware: [withSandbox(defineSandbox({ /* provider */ }))], +}) + +report.summary +``` + +This path parses JSON from the last assistant message. If extract-only is the job, use a model adapter such as `@tanstack/ai-openai`. + +On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. + +Full walkthrough, including the client: [Harness Agents](../structured-outputs/harnesses). ## Limitations diff --git a/docs/chat/structured-outputs.md b/docs/chat/structured-outputs.md index 425dc56abe..4793bed491 100644 --- a/docs/chat/structured-outputs.md +++ b/docs/chat/structured-outputs.md @@ -17,5 +17,6 @@ The structured-outputs guide has moved to its own top-level section, split by wh - **[Streaming UIs](../structured-outputs/streaming)** — `useChat({ outputSchema })` with `partial` and `final` populating a UI field by field. - **[Multi-Turn Chat](../structured-outputs/multi-turn)** — every assistant turn carries its own typed `StructuredOutputPart`, history stays renderable, and `messages[i].parts.find(p => p.type === "structured-output").data` is typed by your schema. - **[With Tools](../structured-outputs/with-tools)** — combining `outputSchema` with the agent loop, including pause/resume for server-tool approvals and client-tool invocations. +- **[Harness Agents](../structured-outputs/harnesses)** — a coding agent in a sandbox inspects files, then returns a typed object. > **Note:** This URL is kept for backward compatibility. New content lives under `/structured-outputs/*` — update existing bookmarks when you can. diff --git a/docs/config.json b/docs/config.json index e1a5aa44b6..7c8240ec7c 100644 --- a/docs/config.json +++ b/docs/config.json @@ -335,17 +335,19 @@ "label": "Overview", "to": "structured-outputs/overview", "addedAt": "2026-05-19", - "updatedAt": "2026-06-10" + "updatedAt": "2026-08-14" }, { "label": "One-Shot Extraction", "to": "structured-outputs/one-shot", - "addedAt": "2026-05-19" + "addedAt": "2026-05-19", + "updatedAt": "2026-08-14" }, { "label": "Streaming UIs", "to": "structured-outputs/streaming", - "addedAt": "2026-05-19" + "addedAt": "2026-05-19", + "updatedAt": "2026-08-14" }, { "label": "Multi-Turn Chat", @@ -356,7 +358,12 @@ "label": "With Tools", "to": "structured-outputs/with-tools", "addedAt": "2026-05-19", - "updatedAt": "2026-07-08" + "updatedAt": "2026-08-14" + }, + { + "label": "Harness Agents", + "to": "structured-outputs/harnesses", + "addedAt": "2026-08-14" } ] }, @@ -509,7 +516,7 @@ "label": "Overview", "to": "sandbox/overview", "addedAt": "2026-06-16", - "updatedAt": "2026-08-12" + "updatedAt": "2026-08-14" }, { "label": "Quick Start", @@ -527,7 +534,7 @@ "label": "Harnesses", "to": "sandbox/harnesses", "addedAt": "2026-06-30", - "updatedAt": "2026-08-04" + "updatedAt": "2026-08-14" }, { "label": "Workspace", @@ -864,30 +871,31 @@ "label": "Claude Code", "to": "adapters/claude-code", "addedAt": "2026-06-12", - "updatedAt": "2026-06-30" + "updatedAt": "2026-08-14" }, { "label": "Codex", "to": "adapters/codex", "addedAt": "2026-06-12", - "updatedAt": "2026-08-12" + "updatedAt": "2026-08-14" }, { "label": "OpenCode", "to": "adapters/opencode", "addedAt": "2026-06-12", - "updatedAt": "2026-06-30" + "updatedAt": "2026-08-14" }, { "label": "Grok Build", "to": "adapters/grok-build", "addedAt": "2026-06-29", - "updatedAt": "2026-08-12" + "updatedAt": "2026-08-14" }, { "label": "ACP-Compatible", "to": "adapters/acp-compatible", - "addedAt": "2026-06-30" + "addedAt": "2026-06-30", + "updatedAt": "2026-08-14" }, { "label": "Amazon Bedrock", diff --git a/docs/sandbox/harnesses.md b/docs/sandbox/harnesses.md index 21da0c4b4a..8e9f290700 100644 --- a/docs/sandbox/harnesses.md +++ b/docs/sandbox/harnesses.md @@ -39,6 +39,10 @@ const stream = chat({ }) ``` +## Typed report from a harness + +If you want a typed object after the agent inspects the repo, pass `outputSchema` on the same `chat()` call. See [Harness Agents](../structured-outputs/harnesses). + ## Harness output can go to a journal `grokBuildText`, `claudeCodeText`, and `codexText` can stop holding the agent's diff --git a/docs/sandbox/overview.md b/docs/sandbox/overview.md index 79259a6b84..76bdcdcb6e 100644 --- a/docs/sandbox/overview.md +++ b/docs/sandbox/overview.md @@ -127,7 +127,7 @@ build an adapter. ## Try it -Two runnable demos: +Three runnable demos: - [`examples/sandbox-web`](https://github.com/TanStack/ai/tree/main/examples/sandbox-web): a "build me an app" agent on Docker with durable runs wired. It scaffolds an app, @@ -135,3 +135,7 @@ Two runnable demos: and a closed tab, and Stop is a real cancel. - [`examples/sandbox-cloudflare`](https://github.com/TanStack/ai/tree/main/examples/sandbox-cloudflare): the same idea at the edge, with the harness picked per run from the UI. +- [`examples/ts-react-chat`](https://github.com/TanStack/ai/tree/main/examples/ts-react-chat) + at `/sandboxes/repo-report`: clone `TanStack/ai`, pick Claude Code, Grok Build, + or Codex, and read a typed report from `useChat().final`. See + [Harness Agents](../structured-outputs/harnesses). diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md new file mode 100644 index 0000000000..a675addf03 --- /dev/null +++ b/docs/structured-outputs/harnesses.md @@ -0,0 +1,199 @@ +--- +title: Harness Structured Output +id: structured-outputs-harnesses +order: 6 +description: "Ask a coding agent in a sandbox to inspect a repo, then read a typed object from chat({ outputSchema }). Works with Claude Code, Codex, OpenCode, and Grok Build." +keywords: + - tanstack ai + - structured outputs + - harness + - claude code + - codex + - opencode + - grok build + - outputSchema + - sandbox +--- + +You asked a coding agent to inspect a repository. The agent streams tool calls and prose. You need a typed object you can store or render, not a wall of text to parse. + +Pass `outputSchema` on the same `chat()` call. The harness runs its native tools. Then you get a validated object from `await chat()` or from `useChat().final`. + +This page is for dedicated harness adapters: + +- [Claude Code](../adapters/claude-code) +- [Codex](../adapters/codex) +- [OpenCode](../adapters/opencode) +- [Grok Build](../adapters/grok-build) + +If you only extract JSON from a prompt and you do not need a sandbox, use [One-Shot Extraction](./one-shot) with an HTTP adapter. + +## Define the schema + +```typescript +import { z } from "zod"; + +export const ReportSchema = z.object({ + name: z.string(), + oneLiner: z.string(), + audience: z.string(), + mainPackages: z.array( + z.object({ + name: z.string(), + role: z.string(), + }), + ), + howToRun: z.string(), +}); +``` + +The return type follows from the schema. You do not need a cast. + +## Server: sandbox plus outputSchema + +The harness needs a sandbox. Pass `withSandbox(...)`. If the client reads the stream, pass `stream: true`. Without `stream: true`, `chat()` returns a `Promise`, not SSE. + +```typescript +import { chat, toServerSentEventsResponse } from "@tanstack/ai"; +import { claudeCodeText } from "@tanstack/ai-claude-code"; +import { + defineSandbox, + defineWorkspace, + githubRepo, + withSandbox, +} from "@tanstack/ai-sandbox"; +import { dockerSandbox } from "@tanstack/ai-sandbox-docker"; +import { ReportSchema } from "./report-schema"; + +const sandbox = defineSandbox({ + id: "repo-report", + provider: dockerSandbox({ image: "node:22" }), + workspace: defineWorkspace({ + source: githubRepo({ repo: "TanStack/ai" }), + }), +}); + +export async function POST(request: Request) { + const body: unknown = await request.json(); + const messages = + typeof body === "object" && + body !== null && + "messages" in body && + Array.isArray(body.messages) + ? body.messages + : []; + + const stream = chat({ + adapter: claudeCodeText("claude-opus-4-8"), + messages, + outputSchema: ReportSchema, + stream: true, + middleware: [withSandbox(sandbox)], + }); + + return toServerSentEventsResponse(stream); +} +``` + +Swap the adapter to change the agent: + +- `codexText("gpt-5.3-codex")` +- `opencodeText("anthropic/claude-opus-4-5")` +- `grokBuildText("grok-build")` + +The typed object arrives as a `structured-output.complete` event. Tool activity streams first. + +## Client: read `final` + +Pass the same schema to `useChat`. Read the object from `final`. + +```tsx +import { useChat, fetchServerSentEvents } from "@tanstack/ai-react"; +import { ReportSchema } from "./report-schema"; + +function RepoReport() { + const { sendMessage, isLoading, final } = useChat({ + connection: fetchServerSentEvents("/api/repo-report"), + outputSchema: ReportSchema, + }); + + return ( + <> + + {isLoading &&

The agent is inspecting the repo.

} + {final && ( + <> +

{final.name}

+

{final.oneLiner}

+

{final.audience}

+ + )} + + ); +} +``` + +`final` is typed as the schema. It stays `null` until `structured-output.complete` arrives. + +`partial` stays empty on harness adapters. The object is not streamed field by field. Render tool calls from `messages` while you wait. See [Streaming UIs](./streaming) for the `partial` / `final` shape. + +## How each harness applies the schema + +| Adapter | How the schema is applied | +|---|---| +| Claude Code | Native `--json-schema` flag on the same turn | +| Codex | Native `--output-schema` flag on the same turn | +| OpenCode | Schema is added to the prompt. The adapter parses the last assistant text. | +| Grok Build | Schema is added to the prompt. The adapter parses the last assistant text. | + +OpenCode and Grok Build parse JSON from the last assistant message. That parse fails if the message is not JSON. If the job is extract-only and you do not need a sandbox, use `@tanstack/ai-openai` or `@tanstack/ai-grok`. + +The generic ACP adapter (`acpCompatible`) does not accept `outputSchema`. Use a dedicated harness adapter. + +## Approval gates and client tools + +Harness adapters run tools inside the sandbox. They do not pause for a browser round-trip. + +- A tool without a server `execute()` fails fast. +- A tool with `needsApproval` fails fast. + +If you need approval gates or client tools, use [With Tools](./with-tools) with an HTTP adapter. + +## Script without a UI + +If you do not stream to a browser, omit `stream: true`. The promise resolves with the typed object. + +```typescript +import { chat } from "@tanstack/ai"; +import { claudeCodeText } from "@tanstack/ai-claude-code"; +import { withSandbox } from "@tanstack/ai-sandbox"; +import { ReportSchema } from "./report-schema"; +import { sandbox } from "./sandbox"; + +const report = await chat({ + adapter: claudeCodeText("claude-opus-4-8"), + messages: [{ role: "user", content: "What is this repository about?" }], + outputSchema: ReportSchema, + middleware: [withSandbox(sandbox)], +}); + +report.name; +report.oneLiner; +``` + +## Try it + +The React chat example includes a repo-report page. + +1. Open [`examples/ts-react-chat`](https://github.com/TanStack/ai/tree/main/examples/ts-react-chat). +2. Set the harness API key in `.env`. +3. Open `/sandboxes/repo-report`. +4. Pick Claude Code, Grok Build, or Codex. +5. Run the report. The page reads the typed object from `useChat().final`. + +The page clones `TanStack/ai` into a sandbox, asks the agent to inspect it, and shows the validated report. diff --git a/docs/structured-outputs/one-shot.md b/docs/structured-outputs/one-shot.md index 183181b88f..2e43cb4684 100644 --- a/docs/structured-outputs/one-shot.md +++ b/docs/structured-outputs/one-shot.md @@ -17,7 +17,7 @@ You have unstructured input — a paragraph of text, a freeform user prompt, the By the end of this guide you'll have a working `chat({ outputSchema })` call returning a fully-typed result, know how to describe fields so the model fills them correctly, and have a pattern for handling validation errors. -> **Note:** If you want to stream the result field-by-field into a UI, you want [Streaming UIs](./streaming) instead. If you want users to iterate on the object across multiple turns, you want [Multi-Turn Chat](./multi-turn). This page is for the single-extraction case. +> **Note:** If you want to stream the result field-by-field into a UI, you want [Streaming UIs](./streaming) instead. If you want users to iterate on the object across multiple turns, you want [Multi-Turn Chat](./multi-turn). If the model must inspect files in a sandbox first, you want [Harness Agents](./harnesses). This page is for the single-extraction case. ## Basic Usage diff --git a/docs/structured-outputs/overview.md b/docs/structured-outputs/overview.md index 18edaac6e5..e9cb3fc4e4 100644 --- a/docs/structured-outputs/overview.md +++ b/docs/structured-outputs/overview.md @@ -57,8 +57,10 @@ Every adapter handles structured output through its provider's native API: | Google Gemini | `responseSchema` | | Ollama | JSON mode with schema | | OpenRouter / Grok / Groq | `response_format` with `json_schema` | +| Claude Code / Codex | Native schema flag on the same harness turn (`--json-schema` / `--output-schema`) | +| OpenCode / Grok Build | Same-turn prompt-and-parse | -The provider-specific details are handled for you — the same `chat({ outputSchema })` call works across all of them. +The provider-specific details are handled for you. The same `chat({ outputSchema })` call works across all of them. For a coding agent in a sandbox, see [Harness Agents](./harnesses). ### Anthropic schema complexity limits @@ -75,7 +77,7 @@ Anthropic's exact limits change over time and aren't all published, so we delibe ## Which page do I read? -Pick the journey that matches what you're building. The four guides under "Structured Outputs" cover non-overlapping use cases — read the one that fits, not all of them. +Pick the journey that matches what you're building. The guides under Structured Outputs cover separate use cases. Read the one that fits. | You want to… | Read | |---|---| @@ -83,6 +85,7 @@ Pick the journey that matches what you're building. The four guides under "Struc | Build a UI that fills in field-by-field as the model streams (progressive form, live card, typewriter preview) | [Streaming UIs](./streaming) | | Let users iterate on a structured object across multiple turns — each turn produces a new typed object and history stays renderable | [Multi-Turn Chat](./multi-turn) | | Combine structured output with tool calls (agent loop that runs tools first, then returns a typed object) | [With Tools](./with-tools) | +| Ask a coding agent in a sandbox to inspect files, then return a typed object | [Harness Agents](./harnesses) | The streaming and multi-turn paths both build on `useChat({ outputSchema })`. The "with tools" path layers on top of either. Pick the one that describes your shipping shape — start there, follow the cross-links when you need a piece of another story. diff --git a/docs/structured-outputs/streaming.md b/docs/structured-outputs/streaming.md index cd37c21c7a..54ad8a132c 100644 --- a/docs/structured-outputs/streaming.md +++ b/docs/structured-outputs/streaming.md @@ -93,7 +93,7 @@ What the hook does for you: - **`partial`** is `DeepPartial>` — every property optional, every nested array element optional. Updated from `TEXT_MESSAGE_CONTENT` deltas via the runtime's partial-JSON parser. The hook derives it from the latest assistant message's `structured-output` part (see [Multi-Turn Chat](./multi-turn) for why that distinction matters), so it reads `{}` between `sendMessage()` and the first chunk without any extra reset state. - **`final`** is `z.infer | null` — the validated terminal payload from the `structured-output.complete` event. `null` until the run completes successfully. - **`outputSchema`** is used purely for client-side TypeScript inference. Validation still runs on the server against the schema you pass to `chat({ outputSchema })` on the server route — the client doesn't re-validate. -- The same shape works for **non-streaming adapters too**. If an adapter (Anthropic, Gemini, Ollama) returns a single `structured-output.complete` event with no incremental deltas, `partial` stays `{}` and `final` populates when the event arrives. Same consumer code. +- The same shape works for **non-streaming adapters too**. If an adapter (Anthropic, Gemini, Ollama) returns a single `structured-output.complete` event with no incremental deltas, `partial` stays `{}` and `final` populates when the event arrives. Same consumer code. Harness adapters work this way too: tool activity streams first, then `final` snaps. See [Harness Agents](./harnesses). `outputSchema` is optional: omit it and `useChat` returns its standard shape without `partial` / `final`. diff --git a/docs/structured-outputs/with-tools.md b/docs/structured-outputs/with-tools.md index 69e43d7be4..4a11c5e47e 100644 --- a/docs/structured-outputs/with-tools.md +++ b/docs/structured-outputs/with-tools.md @@ -56,6 +56,8 @@ recommendation.reason; // string The agent decides when to call `get_product_price`, executes the tool, integrates the result into its reasoning, and only then produces the final structured response. You see the validated object; the tool calls happen behind the scenes. +> **Note:** Coding agents in a sandbox (Claude Code, Codex, OpenCode, Grok Build) run native tools and the schema on the same turn. They do not pause for TanStack tool approval or client tools. See [Harness Agents](./harnesses). + ## Streaming: lifecycle events before the structured payload Pass `stream: true` and the wire format changes — the client now sees tool-call events as they happen, _then_ the structured-output stream emits its terminal event. The lifecycle ordering is: diff --git a/examples/ts-react-chat/src/components/Header.tsx b/examples/ts-react-chat/src/components/Header.tsx index 9b4d744f98..159f8593ce 100644 --- a/examples/ts-react-chat/src/components/Header.tsx +++ b/examples/ts-react-chat/src/components/Header.tsx @@ -204,6 +204,19 @@ export default function Header() { Structured Output + setIsOpen(false)} + className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-1" + activeProps={{ + className: + 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-1', + }} + > + + Repo report + + setIsOpen(false)} diff --git a/examples/ts-react-chat/src/repo-report-options.ts b/examples/ts-react-chat/src/repo-report-options.ts new file mode 100644 index 0000000000..9694ceadab --- /dev/null +++ b/examples/ts-react-chat/src/repo-report-options.ts @@ -0,0 +1,51 @@ +/** + * Client-safe picker types for /sandboxes/repo-report. + * Do not import harness packages here. + */ + +export type ReportHarness = 'claude-code' | 'codex' | 'grok' +export type ReportProvider = 'docker' | 'local' +export type ReportAgent = 'explainer' | 'package-map' | 'first-hour' + +export const REPORT_HARNESSES: Record = { + 'claude-code': { label: 'Claude Code' }, + grok: { label: 'Grok Build' }, + codex: { label: 'Codex' }, +} + +export const REPORT_PROVIDERS: Record = { + docker: { label: 'Docker' }, + local: { label: 'Local process' }, +} + +export const REPORT_AGENTS: Record< + ReportAgent, + { label: string; hint: string } +> = { + explainer: { + label: 'Explainer', + hint: 'What this repo is, and who it is for', + }, + 'package-map': { + label: 'Package map', + hint: 'Main packages and what each one does', + }, + 'first-hour': { + label: 'First hour', + hint: 'Clone, install, and run the first command', + }, +} + +export function isReportHarness(value: unknown): value is ReportHarness { + return typeof value === 'string' && value in REPORT_HARNESSES +} + +export function isReportProvider(value: unknown): value is ReportProvider { + return typeof value === 'string' && value in REPORT_PROVIDERS +} + +export function isReportAgent(value: unknown): value is ReportAgent { + return typeof value === 'string' && value in REPORT_AGENTS +} + +export const REPORT_REPO = 'TanStack/ai' diff --git a/examples/ts-react-chat/src/repo-report-prompt.test.ts b/examples/ts-react-chat/src/repo-report-prompt.test.ts new file mode 100644 index 0000000000..5eedc39fe2 --- /dev/null +++ b/examples/ts-react-chat/src/repo-report-prompt.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest' +import { buildRepoReportPrompt } from './routes/api.sandbox-repo-report' +import { REPORT_REPO } from './repo-report-options' + +describe('buildRepoReportPrompt', () => { + it('names the repo and the explainer focus', () => { + const prompt = buildRepoReportPrompt('explainer') + expect(prompt).toContain(REPORT_REPO) + expect(prompt).toContain('Do not change files.') + expect(prompt).toContain('What this repo is') + }) +}) diff --git a/examples/ts-react-chat/src/repo-report-schema.ts b/examples/ts-react-chat/src/repo-report-schema.ts new file mode 100644 index 0000000000..510ba8aece --- /dev/null +++ b/examples/ts-react-chat/src/repo-report-schema.ts @@ -0,0 +1,16 @@ +import { z } from 'zod' + +export const RepoReportSchema = z.object({ + name: z.string(), + oneLiner: z.string(), + audience: z.string(), + mainPackages: z.array( + z.object({ + name: z.string(), + role: z.string(), + }), + ), + howToRun: z.string(), +}) + +export type RepoReport = z.infer diff --git a/examples/ts-react-chat/src/routeTree.gen.ts b/examples/ts-react-chat/src/routeTree.gen.ts index 7dfa0251b7..d752600492 100644 --- a/examples/ts-react-chat/src/routeTree.gen.ts +++ b/examples/ts-react-chat/src/routeTree.gen.ts @@ -27,6 +27,7 @@ import { Route as ImageGenRouteImport } from './routes/image-gen' import { Route as GenerationHooksRouteImport } from './routes/generation-hooks' import { Route as CapabilityDemoRouteImport } from './routes/capability-demo' import { Route as IndexRouteImport } from './routes/index' +import { Route as SandboxesRepoReportRouteImport } from './routes/sandboxes.repo-report' import { Route as GenerationsVideoRouteImport } from './routes/generations.video' import { Route as GenerationsTranscriptionRouteImport } from './routes/generations.transcription' import { Route as GenerationsSummarizeRouteImport } from './routes/generations.summarize' @@ -44,6 +45,7 @@ import { Route as ApiStructuredOutputRouteImport } from './routes/api.structured import { Route as ApiStructuredChatRouteImport } from './routes/api.structured-chat' import { Route as ApiSandboxTriageDurableRouteImport } from './routes/api.sandbox-triage-durable' import { Route as ApiSandboxTriageRouteImport } from './routes/api.sandbox-triage' +import { Route as ApiSandboxRepoReportRouteImport } from './routes/api.sandbox-repo-report' import { Route as ApiResumableRouteImport } from './routes/api.resumable' import { Route as ApiPersistentChatRouteImport } from './routes/api.persistent-chat' import { Route as ApiMcpStatusRouteImport } from './routes/api.mcp-status' @@ -157,6 +159,11 @@ const IndexRoute = IndexRouteImport.update({ path: '/', getParentRoute: () => rootRouteImport, } as any) +const SandboxesRepoReportRoute = SandboxesRepoReportRouteImport.update({ + id: '/repo-report', + path: '/repo-report', + getParentRoute: () => SandboxesRoute, +} as any) const GenerationsVideoRoute = GenerationsVideoRouteImport.update({ id: '/generations/video', path: '/generations/video', @@ -246,6 +253,11 @@ const ApiSandboxTriageRoute = ApiSandboxTriageRouteImport.update({ path: '/api/sandbox-triage', getParentRoute: () => rootRouteImport, } as any) +const ApiSandboxRepoReportRoute = ApiSandboxRepoReportRouteImport.update({ + id: '/api/sandbox-repo-report', + path: '/api/sandbox-repo-report', + getParentRoute: () => rootRouteImport, +} as any) const ApiResumableRoute = ApiResumableRouteImport.update({ id: '/api/resumable', path: '/api/resumable', @@ -372,7 +384,7 @@ export interface FileRoutesByFullPath { '/queueing': typeof QueueingRoute '/realtime': typeof RealtimeRoute '/resumable': typeof ResumableRoute - '/sandboxes': typeof SandboxesRoute + '/sandboxes': typeof SandboxesRouteWithChildren '/sandboxes-durable': typeof SandboxesDurableRoute '/server-fn-chat': typeof ServerFnChatRoute '/threads': typeof ThreadsRoute @@ -392,6 +404,7 @@ export interface FileRoutesByFullPath { '/api/mcp-status': typeof ApiMcpStatusRoute '/api/persistent-chat': typeof ApiPersistentChatRoute '/api/resumable': typeof ApiResumableRoute + '/api/sandbox-repo-report': typeof ApiSandboxRepoReportRoute '/api/sandbox-triage': typeof ApiSandboxTriageRoute '/api/sandbox-triage-durable': typeof ApiSandboxTriageDurableRoute '/api/structured-chat': typeof ApiStructuredChatRoute @@ -409,6 +422,7 @@ export interface FileRoutesByFullPath { '/generations/summarize': typeof GenerationsSummarizeRoute '/generations/transcription': typeof GenerationsTranscriptionRoute '/generations/video': typeof GenerationsVideoRoute + '/sandboxes/repo-report': typeof SandboxesRepoReportRoute '/api/generate/audio': typeof ApiGenerateAudioRoute '/api/generate/image': typeof ApiGenerateImageRouteWithChildren '/api/generate/speech': typeof ApiGenerateSpeechRoute @@ -431,7 +445,7 @@ export interface FileRoutesByTo { '/queueing': typeof QueueingRoute '/realtime': typeof RealtimeRoute '/resumable': typeof ResumableRoute - '/sandboxes': typeof SandboxesRoute + '/sandboxes': typeof SandboxesRouteWithChildren '/sandboxes-durable': typeof SandboxesDurableRoute '/server-fn-chat': typeof ServerFnChatRoute '/threads': typeof ThreadsRoute @@ -451,6 +465,7 @@ export interface FileRoutesByTo { '/api/mcp-status': typeof ApiMcpStatusRoute '/api/persistent-chat': typeof ApiPersistentChatRoute '/api/resumable': typeof ApiResumableRoute + '/api/sandbox-repo-report': typeof ApiSandboxRepoReportRoute '/api/sandbox-triage': typeof ApiSandboxTriageRoute '/api/sandbox-triage-durable': typeof ApiSandboxTriageDurableRoute '/api/structured-chat': typeof ApiStructuredChatRoute @@ -468,6 +483,7 @@ export interface FileRoutesByTo { '/generations/summarize': typeof GenerationsSummarizeRoute '/generations/transcription': typeof GenerationsTranscriptionRoute '/generations/video': typeof GenerationsVideoRoute + '/sandboxes/repo-report': typeof SandboxesRepoReportRoute '/api/generate/audio': typeof ApiGenerateAudioRoute '/api/generate/image': typeof ApiGenerateImageRouteWithChildren '/api/generate/speech': typeof ApiGenerateSpeechRoute @@ -491,7 +507,7 @@ export interface FileRoutesById { '/queueing': typeof QueueingRoute '/realtime': typeof RealtimeRoute '/resumable': typeof ResumableRoute - '/sandboxes': typeof SandboxesRoute + '/sandboxes': typeof SandboxesRouteWithChildren '/sandboxes-durable': typeof SandboxesDurableRoute '/server-fn-chat': typeof ServerFnChatRoute '/threads': typeof ThreadsRoute @@ -511,6 +527,7 @@ export interface FileRoutesById { '/api/mcp-status': typeof ApiMcpStatusRoute '/api/persistent-chat': typeof ApiPersistentChatRoute '/api/resumable': typeof ApiResumableRoute + '/api/sandbox-repo-report': typeof ApiSandboxRepoReportRoute '/api/sandbox-triage': typeof ApiSandboxTriageRoute '/api/sandbox-triage-durable': typeof ApiSandboxTriageDurableRoute '/api/structured-chat': typeof ApiStructuredChatRoute @@ -528,6 +545,7 @@ export interface FileRoutesById { '/generations/summarize': typeof GenerationsSummarizeRoute '/generations/transcription': typeof GenerationsTranscriptionRoute '/generations/video': typeof GenerationsVideoRoute + '/sandboxes/repo-report': typeof SandboxesRepoReportRoute '/api/generate/audio': typeof ApiGenerateAudioRoute '/api/generate/image': typeof ApiGenerateImageRouteWithChildren '/api/generate/speech': typeof ApiGenerateSpeechRoute @@ -572,6 +590,7 @@ export interface FileRouteTypes { | '/api/mcp-status' | '/api/persistent-chat' | '/api/resumable' + | '/api/sandbox-repo-report' | '/api/sandbox-triage' | '/api/sandbox-triage-durable' | '/api/structured-chat' @@ -589,6 +608,7 @@ export interface FileRouteTypes { | '/generations/summarize' | '/generations/transcription' | '/generations/video' + | '/sandboxes/repo-report' | '/api/generate/audio' | '/api/generate/image' | '/api/generate/speech' @@ -631,6 +651,7 @@ export interface FileRouteTypes { | '/api/mcp-status' | '/api/persistent-chat' | '/api/resumable' + | '/api/sandbox-repo-report' | '/api/sandbox-triage' | '/api/sandbox-triage-durable' | '/api/structured-chat' @@ -648,6 +669,7 @@ export interface FileRouteTypes { | '/generations/summarize' | '/generations/transcription' | '/generations/video' + | '/sandboxes/repo-report' | '/api/generate/audio' | '/api/generate/image' | '/api/generate/speech' @@ -690,6 +712,7 @@ export interface FileRouteTypes { | '/api/mcp-status' | '/api/persistent-chat' | '/api/resumable' + | '/api/sandbox-repo-report' | '/api/sandbox-triage' | '/api/sandbox-triage-durable' | '/api/structured-chat' @@ -707,6 +730,7 @@ export interface FileRouteTypes { | '/generations/summarize' | '/generations/transcription' | '/generations/video' + | '/sandboxes/repo-report' | '/api/generate/audio' | '/api/generate/image' | '/api/generate/speech' @@ -730,7 +754,7 @@ export interface RootRouteChildren { QueueingRoute: typeof QueueingRoute RealtimeRoute: typeof RealtimeRoute ResumableRoute: typeof ResumableRoute - SandboxesRoute: typeof SandboxesRoute + SandboxesRoute: typeof SandboxesRouteWithChildren SandboxesDurableRoute: typeof SandboxesDurableRoute ServerFnChatRoute: typeof ServerFnChatRoute ThreadsRoute: typeof ThreadsRoute @@ -750,6 +774,7 @@ export interface RootRouteChildren { ApiMcpStatusRoute: typeof ApiMcpStatusRoute ApiPersistentChatRoute: typeof ApiPersistentChatRoute ApiResumableRoute: typeof ApiResumableRoute + ApiSandboxRepoReportRoute: typeof ApiSandboxRepoReportRoute ApiSandboxTriageRoute: typeof ApiSandboxTriageRoute ApiSandboxTriageDurableRoute: typeof ApiSandboxTriageDurableRoute ApiStructuredChatRoute: typeof ApiStructuredChatRoute @@ -903,6 +928,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexRouteImport parentRoute: typeof rootRouteImport } + '/sandboxes/repo-report': { + id: '/sandboxes/repo-report' + path: '/repo-report' + fullPath: '/sandboxes/repo-report' + preLoaderRoute: typeof SandboxesRepoReportRouteImport + parentRoute: typeof SandboxesRoute + } '/generations/video': { id: '/generations/video' path: '/generations/video' @@ -1022,6 +1054,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ApiSandboxTriageRouteImport parentRoute: typeof rootRouteImport } + '/api/sandbox-repo-report': { + id: '/api/sandbox-repo-report' + path: '/api/sandbox-repo-report' + fullPath: '/api/sandbox-repo-report' + preLoaderRoute: typeof ApiSandboxRepoReportRouteImport + parentRoute: typeof rootRouteImport + } '/api/resumable': { id: '/api/resumable' path: '/api/resumable' @@ -1179,6 +1218,18 @@ declare module '@tanstack/react-router' { } } +interface SandboxesRouteChildren { + SandboxesRepoReportRoute: typeof SandboxesRepoReportRoute +} + +const SandboxesRouteChildren: SandboxesRouteChildren = { + SandboxesRepoReportRoute: SandboxesRepoReportRoute, +} + +const SandboxesRouteWithChildren = SandboxesRoute._addFileChildren( + SandboxesRouteChildren, +) + interface ApiGenerateImageRouteChildren { ApiGenerateImageArtifactRoute: typeof ApiGenerateImageArtifactRoute } @@ -1204,7 +1255,7 @@ const rootRouteChildren: RootRouteChildren = { QueueingRoute: QueueingRoute, RealtimeRoute: RealtimeRoute, ResumableRoute: ResumableRoute, - SandboxesRoute: SandboxesRoute, + SandboxesRoute: SandboxesRouteWithChildren, SandboxesDurableRoute: SandboxesDurableRoute, ServerFnChatRoute: ServerFnChatRoute, ThreadsRoute: ThreadsRoute, @@ -1224,6 +1275,7 @@ const rootRouteChildren: RootRouteChildren = { ApiMcpStatusRoute: ApiMcpStatusRoute, ApiPersistentChatRoute: ApiPersistentChatRoute, ApiResumableRoute: ApiResumableRoute, + ApiSandboxRepoReportRoute: ApiSandboxRepoReportRoute, ApiSandboxTriageRoute: ApiSandboxTriageRoute, ApiSandboxTriageDurableRoute: ApiSandboxTriageDurableRoute, ApiStructuredChatRoute: ApiStructuredChatRoute, diff --git a/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts b/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts new file mode 100644 index 0000000000..8c146bb20e --- /dev/null +++ b/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts @@ -0,0 +1,122 @@ +import { createFileRoute } from '@tanstack/react-router' +import { + isReportAgent, + isReportHarness, + isReportProvider, + REPORT_AGENTS, + REPORT_REPO, +} from '../repo-report-options' +import { RepoReportSchema } from '../repo-report-schema' +import type { ReportAgent } from '../repo-report-options' + +interface ReportBody { + harness: unknown + provider: unknown + agent: unknown + threadId: unknown +} + +function json(status: number, error: string): Response { + return new Response(JSON.stringify({ error }), { + status, + headers: { 'content-type': 'application/json' }, + }) +} + +export function buildRepoReportPrompt(agent: ReportAgent): string { + const focus = REPORT_AGENTS[agent].hint + return [ + `The ${REPORT_REPO} repository is checked out in the working directory.`, + 'Read README, package.json, and packages/* enough to answer.', + 'Do not change files.', + `Focus: ${focus}.`, + 'Return only the structured report.', + ].join('\n') +} + +export async function repoReportPost(request: Request): Promise { + if (request.signal.aborted) return new Response(null, { status: 499 }) + + const [{ chat, toServerSentEventsStream }, { withSandbox }, triage] = + await Promise.all([ + import('@tanstack/ai'), + import('@tanstack/ai-sandbox'), + import('../sandbox-triage'), + ]) + const { buildHarnessAdapter, buildSandbox, isProvider, missingEnv } = triage + + let data: ReportBody + try { + const body = (await request.json()) as { + data?: ReportBody + forwardedProps?: ReportBody + } + const layer = body.data ?? body.forwardedProps + if (layer == null || typeof layer !== 'object') { + throw new Error('body.data (or forwardedProps) is required') + } + data = layer + } catch (error) { + return json(400, error instanceof Error ? error.message : 'invalid body') + } + + if (!isReportHarness(data.harness) || !isProvider(data.provider)) { + return json(400, 'Unknown harness or provider.') + } + if (!isReportProvider(data.provider)) { + return json(400, 'This page only supports docker or local.') + } + if (!isReportAgent(data.agent)) { + return json(400, 'Unknown agent.') + } + + const threadId = + typeof data.threadId === 'string' && data.threadId !== '' + ? data.threadId + : crypto.randomUUID() + const missing = missingEnv(data.harness, data.provider) + if (missing.length > 0) { + return json( + 500, + `Missing required env: ${missing.join(', ')}. Set it and restart the dev server.`, + ) + } + + const abortController = new AbortController() + request.signal.addEventListener('abort', () => abortController.abort()) + + try { + const sandbox = buildSandbox({ + harness: data.harness, + provider: data.provider, + repo: REPORT_REPO, + threadId, + }) + const stream = chat({ + threadId, + adapter: buildHarnessAdapter(data.harness, data.provider), + messages: [{ role: 'user', content: buildRepoReportPrompt(data.agent) }], + outputSchema: RepoReportSchema, + stream: true, + middleware: [withSandbox(sandbox)], + abortController, + }) + return new Response(toServerSentEventsStream(stream, abortController), { + headers: { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + }, + }) + } catch (error) { + return json(500, error instanceof Error ? error.message : 'report failed') + } +} + +export const Route = createFileRoute('/api/sandbox-repo-report')({ + server: { + handlers: { + POST: ({ request }) => repoReportPost(request), + }, + }, +}) diff --git a/examples/ts-react-chat/src/routes/index.tsx b/examples/ts-react-chat/src/routes/index.tsx index be30c2f919..c7accdc509 100644 --- a/examples/ts-react-chat/src/routes/index.tsx +++ b/examples/ts-react-chat/src/routes/index.tsx @@ -223,6 +223,13 @@ function Messages({ Sandboxes + + + Repo report + diff --git a/examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx b/examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx new file mode 100644 index 0000000000..3884522173 --- /dev/null +++ b/examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx @@ -0,0 +1,206 @@ +import { useState } from 'react' +import { createFileRoute } from '@tanstack/react-router' +import { BookOpen, Play, Square } from 'lucide-react' +import { fetchServerSentEvents, useChat } from '@tanstack/ai-react' +import { + isReportAgent, + isReportHarness, + isReportProvider, + REPORT_AGENTS, + REPORT_HARNESSES, + REPORT_PROVIDERS, + REPORT_REPO, +} from '../repo-report-options' +import { RepoReportSchema } from '../repo-report-schema' +import type { + ReportAgent, + ReportHarness, + ReportProvider, +} from '../repo-report-options' + +export const Route = createFileRoute('/sandboxes/repo-report')({ + component: RepoReportPage, +}) + +function RepoReportPage() { + const [threadId] = useState(() => crypto.randomUUID()) + const [harness, setHarness] = useState('claude-code') + const [provider, setProvider] = useState('docker') + const [agent, setAgent] = useState('explainer') + + const chat = useChat({ + threadId, + outputSchema: RepoReportSchema, + connection: fetchServerSentEvents('/api/sandbox-repo-report'), + forwardedProps: { harness, provider, agent, threadId }, + }) + + const canRun = !chat.isLoading + + function run() { + if (!canRun) return + chat.clear() + void chat.sendMessage(`Report on ${REPORT_REPO}`) + } + + const report = chat.final + + return ( +
+
+ +
+

Repo report

+

+ Clone {REPORT_REPO}, pick a harness, and grab a typed report from{' '} + outputSchema. +

+
+
+ +
+ + + + + {REPORT_AGENTS[agent].hint} + + {chat.isLoading ? ( + + ) : ( + + )} +
+ +
+
+ {chat.error ? ( +

{chat.error.message}

+ ) : null} + + {chat.messages.map((message) => ( +
+ {message.parts.map((part, index) => { + if (part.type === 'text' && part.content) { + return ( +

+ {part.content} +

+ ) + } + if (part.type === 'tool-call') { + return ( +

+ tool {part.name} +

+ ) + } + return null + })} +
+ ))} + + {report ? ( +
+

{report.name}

+

{report.oneLiner}

+

+ Audience: + {report.audience} +

+
    + {report.mainPackages.map((pkg) => ( +
  • + + {pkg.name} + + {': '} + {pkg.role} +
  • + ))} +
+

{report.howToRun}

+
+ ) : null} + + {!chat.isLoading && chat.messages.length === 0 ? ( +

+ Pick Claude Code, Grok Build, or Codex, pick an agent, then Run. + The sandbox clones {REPORT_REPO} and the typed report lands here. +

+ ) : null} +
+
+
+ ) +} diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 0725b46f67..2fd3625080 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -154,12 +154,21 @@ export class ClaudeCodeTextAdapter< } /** Build the `claude` command line (prompt goes via stdin, not argv). */ + supportsCombinedToolsAndSchema(): boolean { + return true + } + + combinedStructuredOutputSource(): 'event' { + return 'event' + } + private buildCommand( options: TextOptions, resume: string | undefined, policyFlags: ClaudePolicyFlags, mcpConfigPath: string | undefined, permissionPromptTool: string | undefined, + jsonSchemaPath: string | undefined, ): string { const config = this.adapterConfig const modelOptions = options.modelOptions @@ -218,6 +227,9 @@ export class ClaudeCodeTextAdapter< } if (mcpConfigPath !== undefined) args.push('--mcp-config', q(mcpConfigPath)) + if (jsonSchemaPath !== undefined) { + args.push('--json-schema', q(jsonSchemaPath)) + } if (permissionPromptTool !== undefined) { args.push('--permission-prompt-tool', q(permissionPromptTool)) } @@ -421,6 +433,14 @@ export class ClaudeCodeTextAdapter< tempFiles.push(mcpConfigPath) mcpConfigArg = mcpConfigFile } + let jsonSchemaArg: string | undefined + if (options.outputSchema) { + const schemaFile = `.tanstack-output-schema-${runIdSegment}.json` + const schemaPath = `${cwd}/${schemaFile}` + await sandbox.fs.write(schemaPath, JSON.stringify(options.outputSchema)) + tempFiles.push(schemaPath) + jsonSchemaArg = schemaFile + } const command = this.buildCommand( options, resume, @@ -429,6 +449,7 @@ export class ClaudeCodeTextAdapter< bridge && permission ? `mcp__${bridge.name}__${permission.toolName}` : undefined, + jsonSchemaArg, ) // Deliver the prompt. The default feeds it over stdin (keeps it out of @@ -509,6 +530,7 @@ export class ClaudeCodeTextAdapter< // which mixes in `Date.now()` / `Math.random()`). See // `createRunScopedIdGen` in `@tanstack/ai-sandbox`. genId: createRunScopedIdGen(runId), + ...(options.outputSchema ? { expectStructuredOutput: true } : {}), onSdkMessage: (message) => logger.provider(`provider=claude-code type=${message.type}`, { chunk: message, @@ -585,8 +607,8 @@ export class ClaudeCodeTextAdapter< ): Promise> { return Promise.reject( new Error( - 'Structured output is not yet supported by the in-sandbox Claude Code adapter. ' + - 'Use a model adapter (e.g. anthropic) for structured output, or omit outputSchema.', + 'This harness honors outputSchema on chat() in the same turn. ' + + 'Pass outputSchema to chat(), or use a model adapter for a one-shot extract.', ), ) } diff --git a/packages/ai-claude-code/src/stream/translate.ts b/packages/ai-claude-code/src/stream/translate.ts index 67271d63c7..d4313f0c98 100644 --- a/packages/ai-claude-code/src/stream/translate.ts +++ b/packages/ai-claude-code/src/stream/translate.ts @@ -1,4 +1,8 @@ import { EventType, buildBaseUsage } from '@tanstack/ai' +import { + structuredOutputCompleteChunk, + structuredOutputStartChunk, +} from '@tanstack/ai/adapter-internals' import type { StreamChunk, TokenUsage } from '@tanstack/ai' import type { AgentSdkMessage, @@ -34,6 +38,8 @@ export interface TranslateContext { onSessionId?: (sessionId: string) => void /** Called for each raw SDK message, for logging. */ onSdkMessage?: (message: AgentSdkMessage) => void + /** Emit structured-output events from `result.structured_output`. */ + expectStructuredOutput?: boolean } /** @@ -320,6 +326,28 @@ export async function* translateSdkStream( yield* synthesizeUnresolvedResults() const usage = buildUsage(message.usage, message.total_cost_usd) + if ( + ctx.expectStructuredOutput === true && + message.structured_output !== undefined + ) { + const object = message.structured_output + const raw = JSON.stringify(object) + const messageId = genId() + yield structuredOutputStartChunk({ + messageId, + model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId, + model, + threadId, + runId, + object, + raw, + }) + } if (message.subtype === 'success') { yield { type: EventType.RUN_FINISHED, diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index fe468ccc43..404cce480f 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -161,4 +161,57 @@ describe('claude-code in-sandbox adapter', () => { expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) await sbx.destroy() }) + + it('passes --json-schema and emits structured-output.complete', async () => { + const fake = [ + `import { writeFileSync } from 'node:fs'`, + `writeFileSync('argv.txt', process.argv.slice(2).join(' '))`, + `let input = ''`, + `process.stdin.on('data', (d) => { input += d })`, + `process.stdin.on('end', () => {`, + ` const w = (o) => process.stdout.write(JSON.stringify(o) + '\\n')`, + ` w({ type: 'system', subtype: 'init', session_id: 'sess-so', model: 'haiku', tools: [] })`, + ` w({ type: 'assistant', message: { id: 'msg-1', content: [{ type: 'text', text: 'looking' }] }, parent_tool_use_id: null })`, + ` w({ type: 'result', subtype: 'success', result: 'done', structured_output: { summary: 'ok' }, usage: { input_tokens: 1, output_tokens: 1 } })`, + `})`, + ].join('\n') + + const sbx = await provider.create({}) + await sbx.fs.write('/workspace/fake-claude.mjs', fake) + + const adapter = claudeCodeText('haiku', { + claudeExecutable: 'node fake-claude.mjs', + streamPartials: false, + emitDiff: false, + }) + + const chunks = await collect( + adapter.chatStream({ + model: 'haiku', + messages: [{ role: 'user', content: 'summarize' }], + logger: noopLogger, + capabilities: capabilityContextWith(sbx), + outputSchema: { + type: 'object', + properties: { summary: { type: 'string' } }, + required: ['summary'], + }, + }), + ) + + const argv = await sbx.fs.read('/workspace/argv.txt') + expect(argv).toContain('--json-schema') + + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual( + expect.objectContaining({ object: { summary: 'ok' } }), + ) + } + + await sbx.destroy() + }) }) diff --git a/packages/ai-claude-code/tests/translate.test.ts b/packages/ai-claude-code/tests/translate.test.ts index 607d2c4573..ed85706254 100644 --- a/packages/ai-claude-code/tests/translate.test.ts +++ b/packages/ai-claude-code/tests/translate.test.ts @@ -23,12 +23,12 @@ async function* fromArray( async function collect( messages: Array, + context: ReturnType & { + expectStructuredOutput?: boolean + } = makeContext(), ): Promise> { const chunks: Array = [] - for await (const chunk of translateSdkStream( - fromArray(messages), - makeContext(), - )) { + for await (const chunk of translateSdkStream(fromArray(messages), context)) { chunks.push(chunk) } return chunks @@ -482,4 +482,71 @@ describe('translateSdkStream', () => { 'RUN_FINISHED', ]) }) + + it('emits structured-output events from result.structured_output when expected', async () => { + const resultWithObject: AgentSdkMessage = { + type: 'result', + subtype: 'success', + result: 'done', + usage, + structured_output: { summary: 'ok' }, + } + const chunks = await collect( + [init, assistantText('Looking around.'), resultWithObject], + { ...makeContext(), expectStructuredOutput: true }, + ) + const start = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.start', + ) + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(start).toBeDefined() + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual( + expect.objectContaining({ + object: { summary: 'ok' }, + raw: JSON.stringify({ summary: 'ok' }), + }), + ) + } + expect(chunks.some((c) => c.type === 'TEXT_MESSAGE_CONTENT')).toBe(true) + expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) + }) + + it('does not emit structured-output events when the flag is off', async () => { + const resultWithObject: AgentSdkMessage = { + type: 'result', + subtype: 'success', + result: 'done', + usage, + structured_output: { summary: 'ok' }, + } + const chunks = await collect([ + init, + assistantText('Looking around.'), + resultWithObject, + ]) + expect( + chunks.some( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ), + ).toBe(false) + }) + + it('maps error_max_structured_output_retries to RUN_ERROR', async () => { + const failed: AgentSdkMessage = { + type: 'result', + subtype: 'error_max_structured_output_retries', + errors: ['schema retries exhausted'], + usage, + } + const chunks = await collect([init, failed]) + const err = chunks.find((c) => c.type === 'RUN_ERROR') + expect(err).toBeDefined() + if (err?.type === 'RUN_ERROR') { + expect(err.message).toContain('schema retries exhausted') + } + }) }) diff --git a/packages/ai-codex/src/adapters/text.ts b/packages/ai-codex/src/adapters/text.ts index 85583df937..fc8c3367b8 100644 --- a/packages/ai-codex/src/adapters/text.ts +++ b/packages/ai-codex/src/adapters/text.ts @@ -140,12 +140,21 @@ export class CodexTextAdapter< } /** Mirror @openai/codex-sdk's `codex exec --experimental-json` invocation. */ + supportsCombinedToolsAndSchema(): boolean { + return true + } + + combinedStructuredOutputSource(): 'event' { + return 'event' + } + private buildCommand( options: TextOptions, resume: string | undefined, bridge: HostToolBridge | undefined, policyFlags: CodexPolicyFlags, provider: string, + outputSchemaPath: string | undefined, ): string { const config = this.adapterConfig const modelOptions = options.modelOptions @@ -214,6 +223,10 @@ export class CodexTextAdapter< args.push('--config', q(`${key}=${value}`)) } + if (outputSchemaPath !== undefined) { + args.push('--output-schema', q(outputSchemaPath)) + } + // Resume an existing thread (mirrors the SDK's `resume `). if (resume !== undefined) args.push('resume', q(resume)) @@ -304,12 +317,21 @@ export class CodexTextAdapter< const policy = options.capabilities ? getSandboxPolicy(options.capabilities, { optional: true }) : undefined + let outputSchemaArg: string | undefined + if (options.outputSchema) { + const schemaFile = `.tanstack-output-schema-${encodeRunId(runId)}.json` + const schemaPath = `${cwd}/${schemaFile}` + await sandbox.fs.write(schemaPath, JSON.stringify(options.outputSchema)) + tempFiles.push(schemaPath) + outputSchemaArg = schemaFile + } const command = this.buildCommand( options, resume, bridge, mapPolicyToCodexFlags(policy), sandbox.provider, + outputSchemaArg, ) logger.request( @@ -409,6 +431,7 @@ export class CodexTextAdapter< parentRunId: options.parentRunId, }), genId, + ...(options.outputSchema ? { expectStructuredOutput: true } : {}), onThreadEvent: (event) => logger.provider(`provider=codex type=${event.type}`, { chunk: event, @@ -458,8 +481,8 @@ export class CodexTextAdapter< ): Promise> { return Promise.reject( new Error( - 'Structured output is not yet supported by the in-sandbox Codex adapter. ' + - 'Use a model adapter for structured output, or omit outputSchema.', + 'This harness honors outputSchema on chat() in the same turn. ' + + 'Pass outputSchema to chat(), or use a model adapter for a one-shot extract.', ), ) } diff --git a/packages/ai-codex/src/stream/translate.ts b/packages/ai-codex/src/stream/translate.ts index 082e26ba3e..ca3244405b 100644 --- a/packages/ai-codex/src/stream/translate.ts +++ b/packages/ai-codex/src/stream/translate.ts @@ -1,4 +1,8 @@ import { EventType, buildBaseUsage } from '@tanstack/ai' +import { + structuredOutputCompleteChunk, + structuredOutputStartChunk, +} from '@tanstack/ai/adapter-internals' import type { StreamChunk, TokenUsage } from '@tanstack/ai' import type { CodexThreadEvent, CodexThreadItem, CodexUsage } from './sdk-types' @@ -18,6 +22,8 @@ export interface TranslateContext { onSessionId?: (sessionId: string) => void /** Called for each raw SDK thread event, for logging. */ onThreadEvent?: (event: CodexThreadEvent) => void + /** Treat the last agent_message as schema JSON. */ + expectStructuredOutput?: boolean } /** @@ -237,30 +243,86 @@ export async function* translateThreadEvents( unresolvedToolCalls.add(item.id) } + const pendingAgentMessages: Array<{ id: string; text: string }> = [] + + function* emitAgentText(item: { + id: string + text: string + }): Generator { + yield { + type: EventType.TEXT_MESSAGE_START, + messageId: item.id, + model, + timestamp: now(), + role: 'assistant', + } + yield { + type: EventType.TEXT_MESSAGE_CONTENT, + messageId: item.id, + model, + timestamp: now(), + delta: item.text, + content: item.text, + } + yield { + type: EventType.TEXT_MESSAGE_END, + messageId: item.id, + model, + timestamp: now(), + } + } + + function* flushAgentMessages( + lastIsStructured: boolean, + ): Generator { + for (let index = 0; index < pendingAgentMessages.length; index++) { + const item = pendingAgentMessages[index] + if (item === undefined) continue + const isLast = index === pendingAgentMessages.length - 1 + if (lastIsStructured && isLast) { + try { + const object: unknown = JSON.parse(item.text) + yield structuredOutputStartChunk({ + messageId: item.id, + model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId: item.id, + model, + threadId, + runId, + object, + raw: item.text, + }) + } catch (error: unknown) { + const message = + error instanceof Error + ? error.message + : 'Invalid structured output JSON' + yield { + type: EventType.RUN_ERROR, + model, + timestamp: now(), + message, + error: { message }, + } + } + } else { + yield* emitAgentText(item) + } + } + pendingAgentMessages.length = 0 + } + function* handleItemCompleted(item: CodexThreadItem): Generator { if (item.type === 'agent_message') { - const messageId = item.id - yield { - type: EventType.TEXT_MESSAGE_START, - messageId, - model, - timestamp: now(), - role: 'assistant', - } - yield { - type: EventType.TEXT_MESSAGE_CONTENT, - messageId, - model, - timestamp: now(), - delta: item.text, - content: item.text, - } - yield { - type: EventType.TEXT_MESSAGE_END, - messageId, - model, - timestamp: now(), + if (ctx.expectStructuredOutput === true) { + pendingAgentMessages.push({ id: item.id, text: item.text }) + return } + yield* emitAgentText(item) } else if (item.type === 'reasoning') { const reasoningId = item.id yield { @@ -341,6 +403,7 @@ export async function* translateThreadEvents( } else if (event.type === 'item.completed') { yield* handleItemCompleted(event.item) } else if (event.type === 'turn.completed') { + yield* flushAgentMessages(ctx.expectStructuredOutput === true) yield* synthesizeUnresolvedResults() const usage = buildUsage(event.usage) yield { @@ -353,6 +416,7 @@ export async function* translateThreadEvents( ...(usage !== undefined && { usage }), } } else if (event.type === 'turn.failed' || event.type === 'error') { + yield* flushAgentMessages(false) yield* synthesizeUnresolvedResults() const message = event.type === 'turn.failed' diff --git a/packages/ai-codex/tests/text-adapter.test.ts b/packages/ai-codex/tests/text-adapter.test.ts index 57b84b3d70..681635c370 100644 --- a/packages/ai-codex/tests/text-adapter.test.ts +++ b/packages/ai-codex/tests/text-adapter.test.ts @@ -201,4 +201,56 @@ describe('codex in-sandbox adapter', () => { const err = chunks.find((c) => c.type === 'RUN_ERROR') expect((err as { message?: string }).message).toMatch(/requires a sandbox/i) }) + + it('passes --output-schema and emits structured-output.complete', async () => { + const fake = [ + `import { writeFileSync } from 'node:fs'`, + `writeFileSync('codex-argv.txt', process.argv.join(' '))`, + `let input = ''`, + `process.stdin.on('data', (d) => { input += d })`, + `process.stdin.on('end', () => {`, + ` const w = (o) => process.stdout.write(JSON.stringify(o) + '\\n')`, + ` w({ type: 'thread.started', thread_id: 'th-so' })`, + ` w({ type: 'turn.started' })`, + ` w({ type: 'item.completed', item: { id: 'i1', type: 'agent_message', text: '{"ok":true}' } })`, + ` w({ type: 'turn.completed', usage: { input_tokens: 1, output_tokens: 1 } })`, + `})`, + ].join('\n') + + const sbx = await provider.create({}) + await sbx.fs.write('/workspace/fake-codex.mjs', fake) + + const adapter = codexText('gpt-5.5-codex', { + codexExecutable: 'node fake-codex.mjs', + }) + + const chunks = await collect( + adapter.chatStream({ + model: 'gpt-5.5-codex', + messages: [{ role: 'user', content: 'summarize' }], + logger: noopLogger, + capabilities: capabilityContextWith(sbx), + outputSchema: { + type: 'object', + properties: { ok: { type: 'boolean' } }, + required: ['ok'], + }, + }), + ) + + const argv = await sbx.fs.read('/workspace/codex-argv.txt') + expect(argv).toContain('--output-schema') + + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual( + expect.objectContaining({ object: { ok: true } }), + ) + } + + await sbx.destroy() + }) }) diff --git a/packages/ai-codex/tests/translate.test.ts b/packages/ai-codex/tests/translate.test.ts index b76e1d48fc..9b20810a32 100644 --- a/packages/ai-codex/tests/translate.test.ts +++ b/packages/ai-codex/tests/translate.test.ts @@ -451,4 +451,76 @@ describe('translateThreadEvents', () => { 'RUN_FINISHED', ]) }) + + it('emits structured-output events from the last agent_message when expected', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: '{"ok":true}' }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + expect( + chunks.some( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.start', + ), + ).toBe(true) + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual( + expect.objectContaining({ object: { ok: true }, raw: '{"ok":true}' }), + ) + } + expect(chunks.some((c) => c.type === 'TEXT_MESSAGE_CONTENT')).toBe(false) + }) + + it('keeps earlier agent_message text when only the last item is structured', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: 'working' }, + }, + { + type: 'item.completed', + item: { id: 'item-2', type: 'agent_message', text: '{"ok":true}' }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + const text = chunks + .filter((c) => c.type === 'TEXT_MESSAGE_CONTENT') + .map((c) => ('delta' in c ? c.delta : '')) + .join('') + expect(text).toBe('working') + expect( + chunks.some( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ), + ).toBe(true) + }) + + it('emits RUN_ERROR when the last agent_message is not JSON', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: 'not json' }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(true) + }) }) diff --git a/packages/ai-grok-build/src/adapters/text.ts b/packages/ai-grok-build/src/adapters/text.ts index f8658aebe3..d05178744d 100644 --- a/packages/ai-grok-build/src/adapters/text.ts +++ b/packages/ai-grok-build/src/adapters/text.ts @@ -1,5 +1,11 @@ import { EventType, normalizeSystemPrompts } from '@tanstack/ai' -import { toRunErrorRawEvent } from '@tanstack/ai/adapter-internals' +import { + appendOutputSchemaInstruction, + parseJsonFromAssistantText, + structuredOutputCompleteChunk, + structuredOutputStartChunk, + toRunErrorRawEvent, +} from '@tanstack/ai/adapter-internals' import { BaseTextAdapter } from '@tanstack/ai/adapters' import { AsyncQueue, @@ -197,6 +203,14 @@ export class GrokBuildTextAdapter< return `${exe} ${args.join(' ')}` } + supportsCombinedToolsAndSchema(): boolean { + return true + } + + combinedStructuredOutputSource(): 'event' { + return 'event' + } + private protocol( options: TextOptions, ): GrokBuildProtocol { @@ -407,12 +421,18 @@ export class GrokBuildTextAdapter< const systemPrompts = normalizeSystemPrompts(options.systemPrompts) .map((p) => p.content) .filter((c) => c.trim() !== '') - const promptText = this.applySystemPrompts( + let promptText = this.applySystemPrompts( systemPrompts, session.resumed || sessionId === undefined ? resumePrompt : buildPrompt(options.messages, undefined).prompt, ) + if (options.outputSchema) { + promptText = appendOutputSchemaInstruction( + promptText, + options.outputSchema, + ) + } session .prompt(promptText) @@ -426,7 +446,8 @@ export class GrokBuildTextAdapter< }) .catch((error: unknown) => queue.fail(error)) - yield* mergeChunkStreams( + let lastAssistantText = '' + for await (const chunk of mergeChunkStreams( translateAcpStream(queue, { model: this.model, runId, @@ -446,7 +467,20 @@ export class GrokBuildTextAdapter< }), }), channel.stream, - ) + )) { + if (chunk.type === EventType.TEXT_MESSAGE_CONTENT) { + lastAssistantText += chunk.delta + } + yield chunk + } + + if (options.outputSchema) { + yield* this.emitParsedStructuredOutput( + lastAssistantText, + threadId, + runId, + ) + } if (this.adapterConfig.emitDiff !== false) { yield* this.emitDiffChunks(sandbox, cwd, threadId, runId) @@ -487,6 +521,43 @@ export class GrokBuildTextAdapter< return `${systemPrompts.join('\n\n')}\n\n${prompt}` } + private *emitParsedStructuredOutput( + raw: string, + threadId: string, + runId: string, + ): Generator { + try { + const object = parseJsonFromAssistantText(raw) + const messageId = this.generateId() + yield structuredOutputStartChunk({ + messageId, + model: this.model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId, + model: this.model, + threadId, + runId, + object, + raw, + }) + } catch (error: unknown) { + const message = + error instanceof Error + ? error.message + : 'Failed to parse structured output' + yield { + type: EventType.RUN_ERROR, + model: this.model, + timestamp: Date.now(), + message, + error: { message }, + } + } + } + private async *emitDiffChunks( sandbox: SandboxHandle, cwd: string, @@ -579,10 +650,16 @@ export class GrokBuildTextAdapter< const systemPrompts = normalizeSystemPrompts(options.systemPrompts) .map((p) => p.content) .filter((c) => c.trim() !== '') - const fullPrompt = + let fullPrompt = systemPrompts.length > 0 ? `${systemPrompts.join('\n\n')}\n\n${prompt}` : prompt + if (options.outputSchema) { + fullPrompt = appendOutputSchemaInstruction( + fullPrompt, + options.outputSchema, + ) + } const exe = await resolveGrokExecutable( sandbox, @@ -664,6 +741,7 @@ export class GrokBuildTextAdapter< parentRunId: options.parentRunId, }), genId, + ...(options.outputSchema ? { expectStructuredOutput: true } : {}), onThreadEvent: (event) => logger.provider(`provider=grok-build type=${event.type}`, { chunk: event, @@ -715,8 +793,8 @@ export class GrokBuildTextAdapter< ): Promise> { return Promise.reject( new Error( - 'Structured output is not yet supported by the in-sandbox Grok Build adapter. ' + - 'Use a model adapter (e.g. grok) for structured output, or omit outputSchema.', + 'This harness honors outputSchema on chat() in the same turn. ' + + 'Pass outputSchema to chat(), or use a model adapter for a one-shot extract.', ), ) } diff --git a/packages/ai-grok-build/src/stream/translate.ts b/packages/ai-grok-build/src/stream/translate.ts index b54116fa4e..885565287e 100644 --- a/packages/ai-grok-build/src/stream/translate.ts +++ b/packages/ai-grok-build/src/stream/translate.ts @@ -1,4 +1,9 @@ import { EventType, buildBaseUsage } from '@tanstack/ai' +import { + parseJsonFromAssistantText, + structuredOutputCompleteChunk, + structuredOutputStartChunk, +} from '@tanstack/ai/adapter-internals' import { GrokThoughtRouter } from './thought-router' import type { StreamChunk, TokenUsage } from '@tanstack/ai' import type { @@ -23,6 +28,8 @@ export interface TranslateContext { onSessionId?: (sessionId: string) => void /** Called for each raw harness event, for logging. */ onThreadEvent?: (event: GrokBuildStreamEvent) => void + /** Parse accumulated assistant text as schema JSON at run end. */ + expectStructuredOutput?: boolean } /** @@ -153,6 +160,7 @@ export async function* translateThreadEvents( let assistantMessageId: string | null = null let reasoningMessageId: string | null = null let thoughtRouter: GrokThoughtRouter | null = null + let assistantText = '' const unresolvedToolCalls = new Set() const openedToolItems = new Set() @@ -255,12 +263,45 @@ export async function* translateThreadEvents( model, timestamp: now(), } + assistantText += event.data break } case 'end': { yield* getThoughtRouter().finalize() yield* closeReasoning() yield* closeAssistant() + if (ctx.expectStructuredOutput === true) { + try { + const object = parseJsonFromAssistantText(assistantText) + const messageId = genId() + yield structuredOutputStartChunk({ + messageId, + model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId, + model, + threadId, + runId, + object, + raw: assistantText, + }) + } catch (error: unknown) { + const message = + error instanceof Error + ? error.message + : 'Failed to parse structured output' + yield { + type: EventType.RUN_ERROR, + model, + timestamp: now(), + message, + error: { message }, + } + } + } if (event.sessionId) { onSessionId?.(event.sessionId) yield { diff --git a/packages/ai-grok-build/tests/translate.test.ts b/packages/ai-grok-build/tests/translate.test.ts index 5bb4619a7b..04dd0b614c 100644 --- a/packages/ai-grok-build/tests/translate.test.ts +++ b/packages/ai-grok-build/tests/translate.test.ts @@ -5,16 +5,19 @@ import type { StreamChunk } from '@tanstack/ai' async function collect( events: Array, + expectStructuredOutput = false, ): Promise> { async function* source() { for (const event of events) yield event } + let n = 0 const out: Array = [] for await (const chunk of translateThreadEvents(source(), { model: 'grok-build', runId: 'run-1', threadId: 'thread-1', - genId: () => 'gen-id', + genId: () => `gen-${++n}`, + ...(expectStructuredOutput ? { expectStructuredOutput: true } : {}), })) { out.push(chunk) } @@ -57,6 +60,46 @@ describe('translateThreadEvents (native grok streaming-json)', () => { ).toBe(true) }) + it('emits structured-output events from accumulated text when expected', async () => { + const chunks = await collect( + [ + { type: 'text', data: '{"ok":true}' }, + { + type: 'end', + stopReason: 'EndTurn', + sessionId: 'sess-so', + requestId: 'req-1', + }, + ], + true, + ) + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual( + expect.objectContaining({ object: { ok: true } }), + ) + } + }) + + it('emits RUN_ERROR when expected structured text is not JSON', async () => { + const chunks = await collect( + [ + { type: 'text', data: 'not json' }, + { + type: 'end', + stopReason: 'EndTurn', + sessionId: 'sess-so', + requestId: 'req-1', + }, + ], + true, + ) + expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(true) + }) + it('surfaces native error events as RUN_ERROR', async () => { const chunks = await collect([{ type: 'error', message: 'bad model' }]) expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(true) diff --git a/packages/ai-opencode/src/adapters/text.ts b/packages/ai-opencode/src/adapters/text.ts index de3650103c..fd9837a3c1 100644 --- a/packages/ai-opencode/src/adapters/text.ts +++ b/packages/ai-opencode/src/adapters/text.ts @@ -1,5 +1,11 @@ import { EventType, normalizeSystemPrompts } from '@tanstack/ai' -import { toRunErrorRawEvent } from '@tanstack/ai/adapter-internals' +import { + appendOutputSchemaInstruction, + parseJsonFromAssistantText, + structuredOutputCompleteChunk, + structuredOutputStartChunk, + toRunErrorRawEvent, +} from '@tanstack/ai/adapter-internals' import { BaseTextAdapter } from '@tanstack/ai/adapters' import { DurableAttachNotSupportedError, @@ -110,6 +116,14 @@ export class OpencodeTextAdapter< return getSandbox(ctx) } + supportsCombinedToolsAndSchema(): boolean { + return true + } + + combinedStructuredOutputSource(): 'event' { + return 'event' + } + private applySystemPrompts( options: TextOptions, prompt: string, @@ -321,16 +335,24 @@ export class OpencodeTextAdapter< queue.push({ kind: 'session', sessionId: session.sessionId }) - const promptText = this.applySystemPrompts( + let promptText = this.applySystemPrompts( options, session.resumed || sessionId === undefined ? resumePrompt : buildPrompt(options.messages, undefined).prompt, ) + if (options.outputSchema) { + promptText = appendOutputSchemaInstruction( + promptText, + options.outputSchema, + ) + } + let lastAssistantText = '' session .prompt(promptText) - .then(({ message }) => { + .then(({ message, text }) => { + lastAssistantText = text queue.push({ kind: 'done', message }) queue.end() }) @@ -354,6 +376,39 @@ export class OpencodeTextAdapter< channel.stream, ) + if (options.outputSchema) { + try { + const object = parseJsonFromAssistantText(lastAssistantText) + const messageId = this.generateId() + yield structuredOutputStartChunk({ + messageId, + model: this.model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId, + model: this.model, + threadId, + runId, + object, + raw: lastAssistantText, + }) + } catch (error: unknown) { + const message = + error instanceof Error + ? error.message + : 'Failed to parse structured output' + yield { + type: EventType.RUN_ERROR, + model: this.model, + timestamp: Date.now(), + message, + error: { message }, + } + } + } + // Surface pending approval requests (ask-policy actions awaiting a client // decision); the client approves and re-runs to continue. for (const event of approvalRequests) yield event @@ -392,8 +447,8 @@ export class OpencodeTextAdapter< ): Promise> { return Promise.reject( new Error( - 'Structured output is not yet supported by the in-sandbox OpenCode adapter. ' + - 'Use a model adapter for structured output, or omit outputSchema.', + 'This harness honors outputSchema on chat() in the same turn. ' + + 'Pass outputSchema to chat(), or use a model adapter for a one-shot extract.', ), ) } diff --git a/packages/ai-opencode/tests/text-adapter.test.ts b/packages/ai-opencode/tests/text-adapter.test.ts index 0ab5f0fce6..00d9a0a172 100644 --- a/packages/ai-opencode/tests/text-adapter.test.ts +++ b/packages/ai-opencode/tests/text-adapter.test.ts @@ -94,6 +94,12 @@ describe('startOpencodeServerInSandbox', () => { }) describe('opencode adapter', () => { + it('opts into combined event-source structured output', () => { + const adapter = opencodeText('anthropic/claude-sonnet-4-5') + expect(adapter.supportsCombinedToolsAndSchema()).toBe(true) + expect(adapter.combinedStructuredOutputSource()).toBe('event') + }) + it('requires a sandbox capability', async () => { const adapter = opencodeText('anthropic/claude-sonnet-4-5') const result = await collect( diff --git a/packages/ai/skills/ai-core/structured-outputs/SKILL.md b/packages/ai/skills/ai-core/structured-outputs/SKILL.md index 6126921fcc..a8616061ca 100644 --- a/packages/ai/skills/ai-core/structured-outputs/SKILL.md +++ b/packages/ai/skills/ai-core/structured-outputs/SKILL.md @@ -20,6 +20,7 @@ sources: - 'TanStack/ai:docs/structured-outputs/streaming.md' - 'TanStack/ai:docs/structured-outputs/multi-turn.md' - 'TanStack/ai:docs/structured-outputs/with-tools.md' + - 'TanStack/ai:docs/structured-outputs/harnesses.md' --- # Structured Outputs @@ -48,7 +49,7 @@ person.age // number When `outputSchema` is provided, `chat()` returns `Promise>` instead of `AsyncIterable`. The result is fully typed. -Adding `stream: true` switches the return to `StructuredOutputStream>` — incremental JSON deltas plus a terminal validated object. See **Pattern 3** below for direct iteration, **Pattern 4** for the `useChat` shape on the client, and **Pattern 5** for multi-turn structured chats. +Adding `stream: true` switches the return to `StructuredOutputStream>` — incremental JSON deltas plus a terminal validated object. See **Pattern 3** below for direct iteration, **Pattern 4** for the `useChat` shape on the client, **Pattern 5** for multi-turn structured chats, and **Pattern 6** for harness adapters. ## Decision: which pattern fits @@ -59,6 +60,7 @@ Adding `stream: true` switches the return to `StructuredOutputStream }` so the model sees its own prior structured response. Streaming / errored parts are dropped from the round-trip. +### Pattern 6: Harness adapters (Claude Code, Codex, OpenCode, Grok Build) + +Dedicated harness adapters honor `chat({ outputSchema })` on the same turn. Native harness tools still run. Read the object from `await chat()` or from `useChat().final`. Do not parse assistant prose. + +A UI endpoint must pass `stream: true`. Without it, `chat()` returns a `Promise`, not SSE. + +```typescript +import { chat, toServerSentEventsResponse } from '@tanstack/ai' +import { claudeCodeText } from '@tanstack/ai-claude-code' +import { withSandbox } from '@tanstack/ai-sandbox' +import { z } from 'zod' +import { sandbox } from './sandbox' + +const ReportSchema = z.object({ + name: z.string(), + oneLiner: z.string(), +}) + +export async function POST(request: Request) { + const body: unknown = await request.json() + const messages = + typeof body === 'object' && + body !== null && + 'messages' in body && + Array.isArray(body.messages) + ? body.messages + : [] + + const stream = chat({ + adapter: claudeCodeText('claude-opus-4-8'), + messages, + outputSchema: ReportSchema, + stream: true, + middleware: [withSandbox(sandbox)], + }) + return toServerSentEventsResponse(stream) +} +``` + +```tsx +import { useChat, fetchServerSentEvents } from '@tanstack/ai-react' +import { z } from 'zod' + +const ReportSchema = z.object({ + name: z.string(), + oneLiner: z.string(), +}) + +const { final } = useChat({ + connection: fetchServerSentEvents('/api/repo-report'), + outputSchema: ReportSchema, +}) + +final?.name +``` + +- Claude Code: `--json-schema`. Codex: `--output-schema`. OpenCode and Grok Build: prompt-and-parse. +- `partial` stays empty until `structured-output.complete`. +- Client tools and `needsApproval` fail fast. The harness cannot pause for a browser round-trip. +- `acpCompatible` does not accept `outputSchema`. +- See [docs/structured-outputs/harnesses.md](https://github.com/TanStack/ai/blob/main/docs/structured-outputs/harnesses.md). + ## Common Mistakes ### HIGH: Filtering `TextPart`s out of `useChat` renderers when using `outputSchema` @@ -509,4 +577,5 @@ provider call, stripping system prompts), use the dedicated - See also: **ai-core/chat-experience/SKILL.md** — Base `useChat` surface; the structured-output additions documented here layer on top. - See also: **ai-core/adapter-configuration/SKILL.md** — Adapter handles structured-output strategy transparently. - See also: **ai-core/tool-calling/SKILL.md** — Combine `tools` with `outputSchema` for an agent loop that runs tools first and returns a typed object. Tool-approval and client-tool flows compose with structured runs without extra wiring; see [docs/structured-outputs/with-tools.md](https://github.com/TanStack/ai/blob/main/docs/structured-outputs/with-tools.md). +- See also: [docs/structured-outputs/harnesses.md](https://github.com/TanStack/ai/blob/main/docs/structured-outputs/harnesses.md) — dedicated harness adapters and `useChat().final`. - See also: **ai-core/middleware/SKILL.md** — `onStructuredOutputConfig` hook and the `structuredOutput` phase for observing/transforming the final structured-output call. diff --git a/packages/ai/src/activities/chat/adapter.ts b/packages/ai/src/activities/chat/adapter.ts index cb3bcae6df..d461afb669 100644 --- a/packages/ai/src/activities/chat/adapter.ts +++ b/packages/ai/src/activities/chat/adapter.ts @@ -159,6 +159,20 @@ export interface TextAdapter< supportsCombinedToolsAndSchema?: ( modelOptions?: TProviderOptions | undefined, ) => boolean + + /** + * Where native-combined structured output is taken from. + * + * - `'text'` (default when omitted): the agent loop's accumulated + * assistant text is schema JSON. The engine parses it after the loop. + * HTTP adapters use this. + * - `'event'`: the adapter emits `structured-output.complete` during + * `chatStream`. The engine must not parse accumulated prose. Harness + * adapters use this. + */ + combinedStructuredOutputSource?: ( + modelOptions?: TProviderOptions | undefined, + ) => 'text' | 'event' } /** diff --git a/packages/ai/src/activities/chat/index.ts b/packages/ai/src/activities/chat/index.ts index 15fb215ba0..1a25d55675 100644 --- a/packages/ai/src/activities/chat/index.ts +++ b/packages/ai/src/activities/chat/index.ts @@ -655,11 +655,12 @@ interface TextEngineConfig< * - nativeCombined: when true, the adapter declared * `supportsCombinedToolsAndSchema()` and the engine wires `jsonSchema` * into the regular `chatStream` call instead of running a separate - * finalization round-trip. The agent loop's final-turn text is the - * schema-constrained JSON; the engine parses it from accumulated - * content. The `'structuredOutput'` middleware phase does NOT fire on - * this path — middleware sees the run through `beforeModel` / - * `modelStream` as usual. + * finalization round-trip. The `'structuredOutput'` middleware phase + * does NOT fire on this path — middleware sees the run through + * `beforeModel` / `modelStream` as usual. + * - source: how to take the combined object. `'text'` (default) parses + * accumulated assistant text. `'event'` reads an adapter-emitted + * `structured-output.complete` and does not parse prose. */ finalStructuredOutput?: { jsonSchema: JSONSchema @@ -667,6 +668,7 @@ interface TextEngineConfig< normalize?: (data: unknown) => unknown validate?: (data: unknown) => unknown nativeCombined?: boolean + source?: 'text' | 'event' } } @@ -801,12 +803,14 @@ class TextEngine< code?: string cause?: unknown } | null = null + private combinedCompleteEmitted = false private readonly finalStructuredOutput?: { jsonSchema: JSONSchema yieldChunks: boolean normalize?: (data: unknown) => unknown validate?: (data: unknown) => unknown nativeCombined?: boolean + source?: 'text' | 'event' } constructor( @@ -1110,7 +1114,8 @@ class TextEngine< this.finalStructuredOutput && this.toolPhase !== 'wait' && !this.isCancelled() && - !this.finalizationError + !this.finalizationError && + !this.earlyTermination ) { if (this.finalStructuredOutput.nativeCombined === true) { yield* this.harvestCombinedStructuredOutput() @@ -1374,9 +1379,46 @@ class TextEngine< // text starting — intermediate tool-call iterations don't need it, // and emitting at run-start would wrap tool-call commentary into a // structured-output part too. + if ( + chunk.type === EventType.CUSTOM && + chunk.name === 'structured-output.start' + ) { + this.combinedStartEmitted = true + const startValue = chunk.value + if ( + startValue && + typeof startValue === 'object' && + 'messageId' in startValue && + typeof startValue.messageId === 'string' + ) { + this.combinedStructuredMessageId = startValue.messageId + } + } + + let outboundChunk: StreamChunk = chunk + if ( + this.finalStructuredOutput?.source === 'event' && + chunk.type === EventType.CUSTOM && + chunk.name === 'structured-output.complete' + ) { + const parsed = readStructuredOutputCompleteValue(chunk.value) + if (parsed) { + const object = this.finalStructuredOutput.normalize + ? this.finalStructuredOutput.normalize(parsed.object) + : parsed.object + this.structuredOutputResult = { data: object, rawText: parsed.raw } + this.combinedCompleteEmitted = true + const value = chunk.value + if (object !== parsed.object && value && typeof value === 'object') { + outboundChunk = { ...chunk, value: { ...value, object } } + } + } + } + if ( this.finalStructuredOutput?.nativeCombined === true && this.finalStructuredOutput.yieldChunks && + this.finalStructuredOutput.source !== 'event' && !this.combinedStartEmitted && chunk.type === EventType.TEXT_MESSAGE_START ) { @@ -1408,7 +1450,7 @@ class TextEngine< // Pipe chunk through middleware (devtools middleware observes; strip-to-spec cleans) const outputChunks = await this.middlewareRunner.runOnChunk( this.middlewareCtx, - chunk, + outboundChunk, ) // When a streaming structured-output finalization step will run after // the agent loop, suppress the agent-loop's RUN_STARTED/RUN_FINISHED @@ -3139,35 +3181,46 @@ class TextEngine< } const yieldChunks = this.finalStructuredOutput.yieldChunks - const rawText = this.accumulatedContent + const source = this.finalStructuredOutput.source ?? 'text' - // Empty final-turn text means the agent loop terminated without the - // model emitting any assistant content (e.g. early termination after - // tool calls). Mirror the fallback path's "missing structured result" - // error rather than silently returning undefined. - if (rawText.length === 0) { - this.finalizationError = { - message: 'missing structured result', - code: 'structured-output-missing-result', + if (source === 'event') { + if (!this.structuredOutputResult) { + this.finalizationError = { + message: 'missing structured result', + code: 'structured-output-missing-result', + } } } else { - try { - const parsed: unknown = JSON.parse(rawText) - // Normalize (un-widen) before storing so the synthesized - // structured-output.complete chunk and the Promise result both - // carry the cleaned payload. JSON.parse preserves provider nulls, so - // this is where native-combined output gets its widening undone. - const data = this.finalStructuredOutput.normalize - ? this.finalStructuredOutput.normalize(parsed) - : parsed - this.structuredOutputResult = { data, rawText } - } catch (err: unknown) { - const detail = - rawText.slice(0, 200) + (rawText.length > 200 ? '...' : '') + const rawText = this.accumulatedContent + + // Empty final-turn text means the agent loop terminated without the + // model emitting any assistant content (e.g. early termination after + // tool calls). Mirror the fallback path's "missing structured result" + // error rather than silently returning undefined. + if (rawText.length === 0) { this.finalizationError = { - message: `Failed to parse structured output as JSON. Content: ${detail}`, - code: 'structured-output-parse-failed', - cause: err, + message: 'missing structured result', + code: 'structured-output-missing-result', + } + } else { + try { + const parsed: unknown = JSON.parse(rawText) + // Normalize (un-widen) before storing so the synthesized + // structured-output.complete chunk and the Promise result both + // carry the cleaned payload. JSON.parse preserves provider nulls, so + // this is where native-combined output gets its widening undone. + const data = this.finalStructuredOutput.normalize + ? this.finalStructuredOutput.normalize(parsed) + : parsed + this.structuredOutputResult = { data, rawText } + } catch (err: unknown) { + const detail = + rawText.slice(0, 200) + (rawText.length > 200 ? '...' : '') + this.finalizationError = { + message: `Failed to parse structured output as JSON. Content: ${detail}`, + code: 'structured-output-parse-failed', + cause: err, + } } } } @@ -3237,7 +3290,11 @@ class TextEngine< // complete event yields AFTER the loop ends, by which point // `getActiveAssistantMessageId()` returns null and would otherwise drop // the event silently). - if (this.structuredOutputResult && !this.finalizationError) { + if ( + this.structuredOutputResult && + !this.finalizationError && + !this.combinedCompleteEmitted + ) { const completeChunk: StreamChunk = { type: EventType.CUSTOM, name: 'structured-output.complete', @@ -3890,6 +3947,8 @@ async function runAgenticStructuredOutput< // agent loop's accumulated final-turn text. const nativeCombined = adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true + const source = + adapter.combinedStructuredOutputSource?.(options.modelOptions) ?? 'text' const mcpManager = MCPManager.from(mcp) const mcpTools = await mcpManager.discover() @@ -3913,6 +3972,7 @@ async function runAgenticStructuredOutput< normalize, ...(validate ? { validate } : {}), ...(nativeCombined ? { nativeCombined: true } : {}), + source, }, }, logger, @@ -4205,6 +4265,8 @@ async function* runStreamingStructuredOutputImpl< // does not fire. const nativeCombined = adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true + const source = + adapter.combinedStructuredOutputSource?.(options.modelOptions) ?? 'text' const mcpManager = MCPManager.from(mcp) const mcpTools = await mcpManager.discover() @@ -4229,6 +4291,7 @@ async function* runStreamingStructuredOutputImpl< yieldChunks: true, normalize, ...(nativeCombined ? { nativeCombined: true } : {}), + source, }, }, logger, diff --git a/packages/ai/src/adapter-internals.ts b/packages/ai/src/adapter-internals.ts index b0c2612bb6..ddcb6724f2 100644 --- a/packages/ai/src/adapter-internals.ts +++ b/packages/ai/src/adapter-internals.ts @@ -25,3 +25,11 @@ export { PendingTurnCapability, providePendingTurn, } from './activities/chat/middleware/pending-turn' +export { + appendOutputSchemaInstruction, + parseJsonFromAssistantText, +} from './utilities/structured-output-text' +export { + structuredOutputCompleteChunk, + structuredOutputStartChunk, +} from './utilities/structured-output-events' diff --git a/packages/ai/src/types.ts b/packages/ai/src/types.ts index e80d02175a..5ed75a547f 100644 --- a/packages/ai/src/types.ts +++ b/packages/ai/src/types.ts @@ -958,10 +958,13 @@ export interface TextOptions< * `supportsCombinedToolsAndSchema(modelOptions) === true`. The adapter * should then wire the schema into the upstream request (e.g. * `response_format: { type: 'json_schema', ... }`, `text.format`, - * `output_format`) alongside any `tools`. The model's natural final - * turn carries the schema-constrained JSON text and the engine - * harvests it from the agent loop without a separate finalization - * round-trip. + * `output_format`, `--json-schema`) alongside any `tools`. + * + * How the engine then takes the object depends on + * `combinedStructuredOutputSource()`: + * - `'text'` (default): the final-turn assistant text is the JSON. + * - `'event'`: the adapter emits `structured-output.complete` during + * `chatStream`. Accumulated prose is not parsed. * * Adapters that did NOT declare the capability never see this field * populated — the engine instead invokes `structuredOutput` / diff --git a/packages/ai/src/utilities/structured-output-events.ts b/packages/ai/src/utilities/structured-output-events.ts new file mode 100644 index 0000000000..6f7daa64ac --- /dev/null +++ b/packages/ai/src/utilities/structured-output-events.ts @@ -0,0 +1,44 @@ +import { EventType } from '../types' +import type { StreamChunk } from '../types' + +export function structuredOutputStartChunk(args: { + messageId: string + model: string + threadId: string + runId: string + timestamp?: number +}): StreamChunk { + return { + type: EventType.CUSTOM, + name: 'structured-output.start', + value: { messageId: args.messageId }, + model: args.model, + timestamp: args.timestamp ?? Date.now(), + threadId: args.threadId, + runId: args.runId, + } +} + +export function structuredOutputCompleteChunk(args: { + messageId: string + model: string + threadId: string + runId: string + object: unknown + raw: string + timestamp?: number +}): StreamChunk { + return { + type: EventType.CUSTOM, + name: 'structured-output.complete', + value: { + object: args.object, + raw: args.raw, + messageId: args.messageId, + }, + model: args.model, + timestamp: args.timestamp ?? Date.now(), + threadId: args.threadId, + runId: args.runId, + } +} diff --git a/packages/ai/src/utilities/structured-output-text.ts b/packages/ai/src/utilities/structured-output-text.ts new file mode 100644 index 0000000000..4d96e51363 --- /dev/null +++ b/packages/ai/src/utilities/structured-output-text.ts @@ -0,0 +1,21 @@ +/** + * Parse JSON from a model/harness assistant string. + * Strips a wrapping markdown fence when the whole payload is fenced. + */ +export function parseJsonFromAssistantText(raw: string): unknown { + const trimmed = raw.trim() + const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/) + const payload = (fenced?.[1] ?? trimmed).trim() + return JSON.parse(payload) +} + +export function appendOutputSchemaInstruction( + prompt: string, + schema: unknown, +): string { + return `${prompt} + +Respond with a single JSON object that matches this JSON Schema. Do not wrap the object in markdown unless you must. + +${JSON.stringify(schema)}` +} diff --git a/packages/ai/tests/chat-combined-event-structured-output.test.ts b/packages/ai/tests/chat-combined-event-structured-output.test.ts new file mode 100644 index 0000000000..f98e06c862 --- /dev/null +++ b/packages/ai/tests/chat-combined-event-structured-output.test.ts @@ -0,0 +1,252 @@ +/** + * Native combined mode with `combinedStructuredOutputSource() === 'event'`. + * + * Harness adapters emit `structured-output.complete` during chatStream. + * The engine must harvest that event and must not JSON.parse assistant prose. + */ +import { describe, expect, it } from 'vitest' +import { z } from 'zod' +import { chat } from '../src/activities/chat/index' +import { EventType } from '../src/types' +import { collectChunks, createMockAdapter } from './test-utils' +import type { StreamChunk } from '../src/types' + +const PersonSchema = z.object({ + name: z.string(), + age: z.number(), +}) +type Person = z.infer + +const validPerson: Person = { name: 'Jane Roe', age: 31 } + +function isNamedCustom(chunk: StreamChunk, name: string): boolean { + return chunk.type === EventType.CUSTOM && chunk.name === name +} + +function eventSourcedTurn(args: { + prose: string + complete?: Person + runError?: string +}): Array { + const ts = 1 + const chunks: Array = [ + { + type: EventType.RUN_STARTED, + runId: 'run-1', + threadId: 'thread-1', + timestamp: ts, + }, + { + type: EventType.TEXT_MESSAGE_START, + messageId: 'msg-1', + role: 'assistant', + timestamp: ts, + }, + { + type: EventType.TEXT_MESSAGE_CONTENT, + messageId: 'msg-1', + delta: args.prose, + timestamp: ts, + }, + { + type: EventType.TEXT_MESSAGE_END, + messageId: 'msg-1', + timestamp: ts, + }, + ] + if (args.complete) { + const raw = JSON.stringify(args.complete) + chunks.push( + { + type: EventType.CUSTOM, + name: 'structured-output.start', + value: { messageId: 'msg-so' }, + timestamp: ts, + }, + { + type: EventType.CUSTOM, + name: 'structured-output.complete', + value: { object: args.complete, raw, messageId: 'msg-so' }, + timestamp: ts, + }, + ) + } + if (args.runError) { + chunks.push({ + type: EventType.RUN_ERROR, + runId: 'run-1', + threadId: 'thread-1', + timestamp: ts, + message: args.runError, + error: { message: args.runError }, + }) + } else { + chunks.push({ + type: EventType.RUN_FINISHED, + runId: 'run-1', + threadId: 'thread-1', + finishReason: 'stop', + timestamp: ts, + }) + } + return chunks +} + +describe('chat({ outputSchema }) — combined event source', () => { + it('forwards outputSchema to chatStream and skips the finalization adapter call', async () => { + let structuredCalled = false + let structuredStreamCalled = false + + const { adapter, calls } = createMockAdapter({ + iterations: [ + eventSourcedTurn({ prose: 'looking around', complete: validPerson }), + ], + structuredOutput: async () => { + structuredCalled = true + return { data: {}, rawText: '{}' } + }, + structuredOutputStream: () => { + structuredStreamCalled = true + return (async function* () {})() + }, + supportsCombinedToolsAndSchema: true, + combinedStructuredOutputSource: 'event', + }) + + await collectChunks( + chat({ + adapter, + messages: [{ role: 'user', content: 'extract' }], + outputSchema: PersonSchema, + stream: true, + }), + ) + + expect(calls.length).toBe(1) + expect(calls[0]?.outputSchema).toBeDefined() + expect(structuredCalled).toBe(false) + expect(structuredStreamCalled).toBe(false) + }) + + it('returns the adapter complete object on the Promise path', async () => { + const { adapter } = createMockAdapter({ + iterations: [ + eventSourcedTurn({ + prose: 'I will look around.', + complete: validPerson, + }), + ], + supportsCombinedToolsAndSchema: true, + combinedStructuredOutputSource: 'event', + }) + + const person = await chat({ + adapter, + messages: [{ role: 'user', content: 'extract' }], + outputSchema: PersonSchema, + }) + + expect(person).toEqual(validPerson) + }) + + it('does not synthesize start before prose text on the stream path', async () => { + const { adapter } = createMockAdapter({ + iterations: [ + eventSourcedTurn({ + prose: 'I will look around.', + complete: validPerson, + }), + ], + supportsCombinedToolsAndSchema: true, + combinedStructuredOutputSource: 'event', + }) + + const chunks = await collectChunks( + chat({ + adapter, + messages: [{ role: 'user', content: 'extract' }], + outputSchema: PersonSchema, + stream: true, + }), + ) + + const startIdx = chunks.findIndex((c) => + isNamedCustom(c, 'structured-output.start'), + ) + const textStartIdx = chunks.findIndex( + (c) => c.type === EventType.TEXT_MESSAGE_START, + ) + const completeIdx = chunks.findIndex((c) => + isNamedCustom(c, 'structured-output.complete'), + ) + + expect(textStartIdx).toBeGreaterThanOrEqual(0) + expect(startIdx).toBeGreaterThan(textStartIdx) + expect(completeIdx).toBeGreaterThan(startIdx) + + const completes = chunks.filter((c) => + isNamedCustom(c, 'structured-output.complete'), + ) + expect(completes).toHaveLength(1) + const complete = completes[0] + expect(complete?.type).toBe(EventType.CUSTOM) + if (complete?.type === EventType.CUSTOM) { + expect(complete.value).toEqual( + expect.objectContaining({ object: validPerson }), + ) + } + }) + + it('errors with missing-result when no complete event arrives', async () => { + const { adapter } = createMockAdapter({ + iterations: [eventSourcedTurn({ prose: 'I will look around.' })], + supportsCombinedToolsAndSchema: true, + combinedStructuredOutputSource: 'event', + }) + + const chunks = await collectChunks( + chat({ + adapter, + messages: [{ role: 'user', content: 'extract' }], + outputSchema: PersonSchema, + stream: true, + }), + ) + + const runError = chunks.find((c) => c.type === EventType.RUN_ERROR) + expect(runError?.type).toBe(EventType.RUN_ERROR) + if (runError?.type === EventType.RUN_ERROR) { + expect(runError.code).toBe('structured-output-missing-result') + } + }) + + it('does not harvest a second error after an adapter RUN_ERROR', async () => { + const { adapter } = createMockAdapter({ + iterations: [ + eventSourcedTurn({ + prose: 'I will look around.', + runError: 'harness failed', + }), + ], + supportsCombinedToolsAndSchema: true, + combinedStructuredOutputSource: 'event', + }) + + const chunks = await collectChunks( + chat({ + adapter, + messages: [{ role: 'user', content: 'extract' }], + outputSchema: PersonSchema, + stream: true, + }), + ) + + const errors = chunks.filter((c) => c.type === EventType.RUN_ERROR) + expect(errors).toHaveLength(1) + if (errors[0]?.type === EventType.RUN_ERROR) { + expect(errors[0].message).toBe('harness failed') + expect(errors[0].code).not.toBe('structured-output-missing-result') + expect(errors[0].code).not.toBe('structured-output-parse-failed') + } + }) +}) diff --git a/packages/ai/tests/structured-output-text.test.ts b/packages/ai/tests/structured-output-text.test.ts new file mode 100644 index 0000000000..c028489f8c --- /dev/null +++ b/packages/ai/tests/structured-output-text.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from 'vitest' +import { + appendOutputSchemaInstruction, + parseJsonFromAssistantText, +} from '../src/utilities/structured-output-text' + +describe('parseJsonFromAssistantText', () => { + it('parses a bare object', () => { + expect(parseJsonFromAssistantText('{"a":1}')).toEqual({ a: 1 }) + }) + + it('strips a json fence', () => { + expect(parseJsonFromAssistantText('```json\n{"a":1}\n```')).toEqual({ + a: 1, + }) + }) + + it('strips a bare fence', () => { + expect(parseJsonFromAssistantText('```\n{"a":1}\n```')).toEqual({ a: 1 }) + }) + + it('throws on prose', () => { + expect(() => parseJsonFromAssistantText('not json')).toThrow() + }) + + it('appends the schema instruction', () => { + const next = appendOutputSchemaInstruction('Look around.', { + type: 'object', + }) + expect(next).toContain('Look around.') + expect(next).toContain('"type":"object"') + }) +}) diff --git a/packages/ai/tests/test-utils.ts b/packages/ai/tests/test-utils.ts index 2c6b713037..ffd0c28036 100644 --- a/packages/ai/tests/test-utils.ts +++ b/packages/ai/tests/test-utils.ts @@ -162,6 +162,9 @@ export function createMockAdapter(options: { * The engine then forwards `outputSchema` into `chatStream` and skips * the separate finalization round-trip. */ supportsCombinedToolsAndSchema?: boolean + /** When `'event'`, the engine harvests `structured-output.complete` + * from `chatStream` instead of parsing accumulated assistant text. */ + combinedStructuredOutputSource?: 'text' | 'event' }) { const calls: Array> = [] let callIndex = 0 @@ -213,6 +216,10 @@ export function createMockAdapter(options: { adapter.supportsCombinedToolsAndSchema = () => true } + if (options.combinedStructuredOutputSource === 'event') { + adapter.combinedStructuredOutputSource = () => 'event' + } + return { adapter, calls } } From 9b7898048cefdee2d5faab194cea477c22cf1798 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Fri, 14 Aug 2026 19:18:03 +0200 Subject: [PATCH 02/23] fix(docs): give adapter outputSchema snippets a real sandbox Kiira type-checks doc fences. defineSandbox requires id and provider. --- docs/adapters/claude-code.md | 8 +++++++- docs/adapters/codex.md | 8 +++++++- docs/adapters/grok-build.md | 8 +++++++- docs/adapters/opencode.md | 8 +++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index a486ee9a6f..c6bd77fd51 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -176,6 +176,7 @@ Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its nat import { chat } from "@tanstack/ai" import { claudeCodeText } from "@tanstack/ai-claude-code" import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { dockerSandbox } from "@tanstack/ai-sandbox-docker" import { z } from "zod" const Report = z.object({ @@ -183,11 +184,16 @@ const Report = z.object({ filesChanged: z.array(z.string()), }) +const sandbox = defineSandbox({ + id: "repo-report", + provider: dockerSandbox({ image: "node:22" }), +}) + const report = await chat({ adapter: claudeCodeText("claude-opus-4-8"), messages: [{ role: "user", content: "Review this repo." }], outputSchema: Report, - middleware: [withSandbox(defineSandbox({ /* provider */ }))], + middleware: [withSandbox(sandbox)], }) report.summary diff --git a/docs/adapters/codex.md b/docs/adapters/codex.md index 64607d9488..da15db97eb 100644 --- a/docs/adapters/codex.md +++ b/docs/adapters/codex.md @@ -176,6 +176,7 @@ Pass `outputSchema` on `chat()`. Codex runs one harness turn and constrains the import { chat } from "@tanstack/ai" import { codexText } from "@tanstack/ai-codex" import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { dockerSandbox } from "@tanstack/ai-sandbox-docker" import { z } from "zod" const Report = z.object({ @@ -183,11 +184,16 @@ const Report = z.object({ filesChanged: z.array(z.string()), }) +const sandbox = defineSandbox({ + id: "repo-report", + provider: dockerSandbox({ image: "node:22" }), +}) + const report = await chat({ adapter: codexText("gpt-5.3-codex"), messages: [{ role: "user", content: "Review this repo." }], outputSchema: Report, - middleware: [withSandbox(defineSandbox({ /* provider */ }))], + middleware: [withSandbox(sandbox)], }) report.summary diff --git a/docs/adapters/grok-build.md b/docs/adapters/grok-build.md index 2fa25cd1df..fbbae01fff 100644 --- a/docs/adapters/grok-build.md +++ b/docs/adapters/grok-build.md @@ -193,6 +193,7 @@ Pass `outputSchema` on `chat()`. Grok Build has no native schema flag. The adapt import { chat } from "@tanstack/ai" import { grokBuildText } from "@tanstack/ai-grok-build" import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { dockerSandbox } from "@tanstack/ai-sandbox-docker" import { z } from "zod" const Report = z.object({ @@ -200,11 +201,16 @@ const Report = z.object({ filesChanged: z.array(z.string()), }) +const sandbox = defineSandbox({ + id: "repo-report", + provider: dockerSandbox({ image: "node:22" }), +}) + const report = await chat({ adapter: grokBuildText("grok-build"), messages: [{ role: "user", content: "Review this repo." }], outputSchema: Report, - middleware: [withSandbox(defineSandbox({ /* provider */ }))], + middleware: [withSandbox(sandbox)], }) report.summary diff --git a/docs/adapters/opencode.md b/docs/adapters/opencode.md index 48790e2a0a..f4744d7a60 100644 --- a/docs/adapters/opencode.md +++ b/docs/adapters/opencode.md @@ -181,6 +181,7 @@ Pass `outputSchema` on `chat()`. OpenCode has no native schema flag. The adapter import { chat } from "@tanstack/ai" import { opencodeText } from "@tanstack/ai-opencode" import { defineSandbox, withSandbox } from "@tanstack/ai-sandbox" +import { dockerSandbox } from "@tanstack/ai-sandbox-docker" import { z } from "zod" const Report = z.object({ @@ -188,11 +189,16 @@ const Report = z.object({ filesChanged: z.array(z.string()), }) +const sandbox = defineSandbox({ + id: "repo-report", + provider: dockerSandbox({ image: "node:22" }), +}) + const report = await chat({ adapter: opencodeText("anthropic/claude-opus-4-5"), messages: [{ role: "user", content: "Review this repo." }], outputSchema: Report, - middleware: [withSandbox(defineSandbox({ /* provider */ }))], + middleware: [withSandbox(sandbox)], }) report.summary From 1a909c16840482921da6c6965c3e05f1281ca686 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 14:55:54 +0200 Subject: [PATCH 03/23] fix(example): render repo report on its own route /sandboxes/repo-report was a child of the triage page. The parent has no Outlet, so the URL showed issue triage. Move the page to /repo-report. --- docs/sandbox/overview.md | 2 +- docs/structured-outputs/harnesses.md | 2 +- .../ts-react-chat/src/components/Header.tsx | 2 +- .../ts-react-chat/src/repo-report-options.ts | 2 +- examples/ts-react-chat/src/routeTree.gen.ts | 62 ++++++++----------- examples/ts-react-chat/src/routes/index.tsx | 2 +- ...dboxes.repo-report.tsx => repo-report.tsx} | 2 +- 7 files changed, 32 insertions(+), 42 deletions(-) rename examples/ts-react-chat/src/routes/{sandboxes.repo-report.tsx => repo-report.tsx} (99%) diff --git a/docs/sandbox/overview.md b/docs/sandbox/overview.md index 76bdcdcb6e..1c52969520 100644 --- a/docs/sandbox/overview.md +++ b/docs/sandbox/overview.md @@ -136,6 +136,6 @@ Three runnable demos: - [`examples/sandbox-cloudflare`](https://github.com/TanStack/ai/tree/main/examples/sandbox-cloudflare): the same idea at the edge, with the harness picked per run from the UI. - [`examples/ts-react-chat`](https://github.com/TanStack/ai/tree/main/examples/ts-react-chat) - at `/sandboxes/repo-report`: clone `TanStack/ai`, pick Claude Code, Grok Build, + at `/repo-report`: clone `TanStack/ai`, pick Claude Code, Grok Build, or Codex, and read a typed report from `useChat().final`. See [Harness Agents](../structured-outputs/harnesses). diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index a675addf03..b57d241637 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -192,7 +192,7 @@ The React chat example includes a repo-report page. 1. Open [`examples/ts-react-chat`](https://github.com/TanStack/ai/tree/main/examples/ts-react-chat). 2. Set the harness API key in `.env`. -3. Open `/sandboxes/repo-report`. +3. Open `/repo-report`. 4. Pick Claude Code, Grok Build, or Codex. 5. Run the report. The page reads the typed object from `useChat().final`. diff --git a/examples/ts-react-chat/src/components/Header.tsx b/examples/ts-react-chat/src/components/Header.tsx index 159f8593ce..8660905a3c 100644 --- a/examples/ts-react-chat/src/components/Header.tsx +++ b/examples/ts-react-chat/src/components/Header.tsx @@ -205,7 +205,7 @@ export default function Header() { setIsOpen(false)} className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-1" activeProps={{ diff --git a/examples/ts-react-chat/src/repo-report-options.ts b/examples/ts-react-chat/src/repo-report-options.ts index 9694ceadab..aba8f93da7 100644 --- a/examples/ts-react-chat/src/repo-report-options.ts +++ b/examples/ts-react-chat/src/repo-report-options.ts @@ -1,5 +1,5 @@ /** - * Client-safe picker types for /sandboxes/repo-report. + * Client-safe picker types for /repo-report. * Do not import harness packages here. */ diff --git a/examples/ts-react-chat/src/routeTree.gen.ts b/examples/ts-react-chat/src/routeTree.gen.ts index d752600492..e42124b47d 100644 --- a/examples/ts-react-chat/src/routeTree.gen.ts +++ b/examples/ts-react-chat/src/routeTree.gen.ts @@ -15,6 +15,7 @@ import { Route as ServerFnChatRouteImport } from './routes/server-fn-chat' import { Route as SandboxesDurableRouteImport } from './routes/sandboxes-durable' import { Route as SandboxesRouteImport } from './routes/sandboxes' import { Route as ResumableRouteImport } from './routes/resumable' +import { Route as RepoReportRouteImport } from './routes/repo-report' import { Route as RealtimeRouteImport } from './routes/realtime' import { Route as QueueingRouteImport } from './routes/queueing' import { Route as PersistentChatRouteImport } from './routes/persistent-chat' @@ -27,7 +28,6 @@ import { Route as ImageGenRouteImport } from './routes/image-gen' import { Route as GenerationHooksRouteImport } from './routes/generation-hooks' import { Route as CapabilityDemoRouteImport } from './routes/capability-demo' import { Route as IndexRouteImport } from './routes/index' -import { Route as SandboxesRepoReportRouteImport } from './routes/sandboxes.repo-report' import { Route as GenerationsVideoRouteImport } from './routes/generations.video' import { Route as GenerationsTranscriptionRouteImport } from './routes/generations.transcription' import { Route as GenerationsSummarizeRouteImport } from './routes/generations.summarize' @@ -99,6 +99,11 @@ const ResumableRoute = ResumableRouteImport.update({ path: '/resumable', getParentRoute: () => rootRouteImport, } as any) +const RepoReportRoute = RepoReportRouteImport.update({ + id: '/repo-report', + path: '/repo-report', + getParentRoute: () => rootRouteImport, +} as any) const RealtimeRoute = RealtimeRouteImport.update({ id: '/realtime', path: '/realtime', @@ -159,11 +164,6 @@ const IndexRoute = IndexRouteImport.update({ path: '/', getParentRoute: () => rootRouteImport, } as any) -const SandboxesRepoReportRoute = SandboxesRepoReportRouteImport.update({ - id: '/repo-report', - path: '/repo-report', - getParentRoute: () => SandboxesRoute, -} as any) const GenerationsVideoRoute = GenerationsVideoRouteImport.update({ id: '/generations/video', path: '/generations/video', @@ -383,8 +383,9 @@ export interface FileRoutesByFullPath { '/persistent-chat': typeof PersistentChatRoute '/queueing': typeof QueueingRoute '/realtime': typeof RealtimeRoute + '/repo-report': typeof RepoReportRoute '/resumable': typeof ResumableRoute - '/sandboxes': typeof SandboxesRouteWithChildren + '/sandboxes': typeof SandboxesRoute '/sandboxes-durable': typeof SandboxesDurableRoute '/server-fn-chat': typeof ServerFnChatRoute '/threads': typeof ThreadsRoute @@ -422,7 +423,6 @@ export interface FileRoutesByFullPath { '/generations/summarize': typeof GenerationsSummarizeRoute '/generations/transcription': typeof GenerationsTranscriptionRoute '/generations/video': typeof GenerationsVideoRoute - '/sandboxes/repo-report': typeof SandboxesRepoReportRoute '/api/generate/audio': typeof ApiGenerateAudioRoute '/api/generate/image': typeof ApiGenerateImageRouteWithChildren '/api/generate/speech': typeof ApiGenerateSpeechRoute @@ -444,8 +444,9 @@ export interface FileRoutesByTo { '/persistent-chat': typeof PersistentChatRoute '/queueing': typeof QueueingRoute '/realtime': typeof RealtimeRoute + '/repo-report': typeof RepoReportRoute '/resumable': typeof ResumableRoute - '/sandboxes': typeof SandboxesRouteWithChildren + '/sandboxes': typeof SandboxesRoute '/sandboxes-durable': typeof SandboxesDurableRoute '/server-fn-chat': typeof ServerFnChatRoute '/threads': typeof ThreadsRoute @@ -483,7 +484,6 @@ export interface FileRoutesByTo { '/generations/summarize': typeof GenerationsSummarizeRoute '/generations/transcription': typeof GenerationsTranscriptionRoute '/generations/video': typeof GenerationsVideoRoute - '/sandboxes/repo-report': typeof SandboxesRepoReportRoute '/api/generate/audio': typeof ApiGenerateAudioRoute '/api/generate/image': typeof ApiGenerateImageRouteWithChildren '/api/generate/speech': typeof ApiGenerateSpeechRoute @@ -506,8 +506,9 @@ export interface FileRoutesById { '/persistent-chat': typeof PersistentChatRoute '/queueing': typeof QueueingRoute '/realtime': typeof RealtimeRoute + '/repo-report': typeof RepoReportRoute '/resumable': typeof ResumableRoute - '/sandboxes': typeof SandboxesRouteWithChildren + '/sandboxes': typeof SandboxesRoute '/sandboxes-durable': typeof SandboxesDurableRoute '/server-fn-chat': typeof ServerFnChatRoute '/threads': typeof ThreadsRoute @@ -545,7 +546,6 @@ export interface FileRoutesById { '/generations/summarize': typeof GenerationsSummarizeRoute '/generations/transcription': typeof GenerationsTranscriptionRoute '/generations/video': typeof GenerationsVideoRoute - '/sandboxes/repo-report': typeof SandboxesRepoReportRoute '/api/generate/audio': typeof ApiGenerateAudioRoute '/api/generate/image': typeof ApiGenerateImageRouteWithChildren '/api/generate/speech': typeof ApiGenerateSpeechRoute @@ -569,6 +569,7 @@ export interface FileRouteTypes { | '/persistent-chat' | '/queueing' | '/realtime' + | '/repo-report' | '/resumable' | '/sandboxes' | '/sandboxes-durable' @@ -608,7 +609,6 @@ export interface FileRouteTypes { | '/generations/summarize' | '/generations/transcription' | '/generations/video' - | '/sandboxes/repo-report' | '/api/generate/audio' | '/api/generate/image' | '/api/generate/speech' @@ -630,6 +630,7 @@ export interface FileRouteTypes { | '/persistent-chat' | '/queueing' | '/realtime' + | '/repo-report' | '/resumable' | '/sandboxes' | '/sandboxes-durable' @@ -669,7 +670,6 @@ export interface FileRouteTypes { | '/generations/summarize' | '/generations/transcription' | '/generations/video' - | '/sandboxes/repo-report' | '/api/generate/audio' | '/api/generate/image' | '/api/generate/speech' @@ -691,6 +691,7 @@ export interface FileRouteTypes { | '/persistent-chat' | '/queueing' | '/realtime' + | '/repo-report' | '/resumable' | '/sandboxes' | '/sandboxes-durable' @@ -730,7 +731,6 @@ export interface FileRouteTypes { | '/generations/summarize' | '/generations/transcription' | '/generations/video' - | '/sandboxes/repo-report' | '/api/generate/audio' | '/api/generate/image' | '/api/generate/speech' @@ -753,8 +753,9 @@ export interface RootRouteChildren { PersistentChatRoute: typeof PersistentChatRoute QueueingRoute: typeof QueueingRoute RealtimeRoute: typeof RealtimeRoute + RepoReportRoute: typeof RepoReportRoute ResumableRoute: typeof ResumableRoute - SandboxesRoute: typeof SandboxesRouteWithChildren + SandboxesRoute: typeof SandboxesRoute SandboxesDurableRoute: typeof SandboxesDurableRoute ServerFnChatRoute: typeof ServerFnChatRoute ThreadsRoute: typeof ThreadsRoute @@ -844,6 +845,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ResumableRouteImport parentRoute: typeof rootRouteImport } + '/repo-report': { + id: '/repo-report' + path: '/repo-report' + fullPath: '/repo-report' + preLoaderRoute: typeof RepoReportRouteImport + parentRoute: typeof rootRouteImport + } '/realtime': { id: '/realtime' path: '/realtime' @@ -928,13 +936,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexRouteImport parentRoute: typeof rootRouteImport } - '/sandboxes/repo-report': { - id: '/sandboxes/repo-report' - path: '/repo-report' - fullPath: '/sandboxes/repo-report' - preLoaderRoute: typeof SandboxesRepoReportRouteImport - parentRoute: typeof SandboxesRoute - } '/generations/video': { id: '/generations/video' path: '/generations/video' @@ -1218,18 +1219,6 @@ declare module '@tanstack/react-router' { } } -interface SandboxesRouteChildren { - SandboxesRepoReportRoute: typeof SandboxesRepoReportRoute -} - -const SandboxesRouteChildren: SandboxesRouteChildren = { - SandboxesRepoReportRoute: SandboxesRepoReportRoute, -} - -const SandboxesRouteWithChildren = SandboxesRoute._addFileChildren( - SandboxesRouteChildren, -) - interface ApiGenerateImageRouteChildren { ApiGenerateImageArtifactRoute: typeof ApiGenerateImageArtifactRoute } @@ -1254,8 +1243,9 @@ const rootRouteChildren: RootRouteChildren = { PersistentChatRoute: PersistentChatRoute, QueueingRoute: QueueingRoute, RealtimeRoute: RealtimeRoute, + RepoReportRoute: RepoReportRoute, ResumableRoute: ResumableRoute, - SandboxesRoute: SandboxesRouteWithChildren, + SandboxesRoute: SandboxesRoute, SandboxesDurableRoute: SandboxesDurableRoute, ServerFnChatRoute: ServerFnChatRoute, ThreadsRoute: ThreadsRoute, diff --git a/examples/ts-react-chat/src/routes/index.tsx b/examples/ts-react-chat/src/routes/index.tsx index c7accdc509..fac7e8aa3d 100644 --- a/examples/ts-react-chat/src/routes/index.tsx +++ b/examples/ts-react-chat/src/routes/index.tsx @@ -224,7 +224,7 @@ function Messages({ Sandboxes diff --git a/examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx similarity index 99% rename from examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx rename to examples/ts-react-chat/src/routes/repo-report.tsx index 3884522173..54b2b1c385 100644 --- a/examples/ts-react-chat/src/routes/sandboxes.repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -18,7 +18,7 @@ import type { ReportProvider, } from '../repo-report-options' -export const Route = createFileRoute('/sandboxes/repo-report')({ +export const Route = createFileRoute('/repo-report')({ component: RepoReportPage, }) From 17bd21ef17515c3e7d475ac93adf94a75219fdbe Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 15:02:04 +0200 Subject: [PATCH 04/23] fix: parse harness JSON after prose and render the report card Grok writes tool notes then the object. Parsing the whole assistant text failed on I'll. Take the last JSON object. The repo-report page hides the raw JSON and fills the card as the object streams. Claude Code sets CLAUDE_CODE_SANDBOXED so a cloned repo is not blocked as untrusted. --- .../ts-react-chat/src/routes/repo-report.tsx | 95 ++++++++++++++----- examples/ts-react-chat/src/sandbox-triage.ts | 6 +- .../src/utilities/structured-output-text.ts | 53 ++++++++++- .../ai/tests/structured-output-text.test.ts | 12 +++ 4 files changed, 137 insertions(+), 29 deletions(-) diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index 54b2b1c385..3d4714ea7b 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -1,6 +1,7 @@ import { useState } from 'react' import { createFileRoute } from '@tanstack/react-router' import { BookOpen, Play, Square } from 'lucide-react' +import { parsePartialJSON } from '@tanstack/ai' import { fetchServerSentEvents, useChat } from '@tanstack/ai-react' import { isReportAgent, @@ -12,16 +13,79 @@ import { REPORT_REPO, } from '../repo-report-options' import { RepoReportSchema } from '../repo-report-schema' +import type { RepoReport } from '../repo-report-schema' import type { ReportAgent, ReportHarness, ReportProvider, } from '../repo-report-options' +import type { UIMessage } from '@tanstack/ai-react' export const Route = createFileRoute('/repo-report')({ component: RepoReportPage, }) +function assistantText(messages: Array): string { + return messages + .filter((message) => message.role === 'assistant') + .flatMap((message) => message.parts) + .flatMap((part) => + part.type === 'text' && typeof part.content === 'string' + ? [part.content] + : [], + ) + .join('\n') +} + +function liveReportFromMessages( + messages: Array, +): Partial | undefined { + const text = assistantText(messages) + const start = text.lastIndexOf('{') + if (start < 0) return undefined + const parsed: unknown = parsePartialJSON(text.slice(start)) + if (parsed === null || parsed === undefined || typeof parsed !== 'object') { + return undefined + } + return parsed as Partial +} + +function proseWithoutJson(content: string): string | null { + const start = content.indexOf('{') + if (start < 0) return content + const before = content.slice(0, start).trim() + return before === '' ? null : before +} + +function ReportCard({ + report, +}: { + report: Partial +}) { + return ( +
+

{report.name ?? '…'}

+

{report.oneLiner ?? '…'}

+

+ Audience: + {report.audience ?? '…'} +

+
    + {(report.mainPackages ?? []).map((pkg, index) => ( +
  • + {pkg.name ?? '…'} + {': '} + {pkg.role ?? '…'} +
  • + ))} +
+ {report.howToRun ? ( +

{report.howToRun}

+ ) : null} +
+ ) +} + function RepoReportPage() { const [threadId] = useState(() => crypto.randomUUID()) const [harness, setHarness] = useState('claude-code') @@ -43,7 +107,7 @@ function RepoReportPage() { void chat.sendMessage(`Report on ${REPORT_REPO}`) } - const report = chat.final + const report = chat.final ?? liveReportFromMessages(chat.messages) return (
@@ -134,7 +198,7 @@ function RepoReportPage() {
- {chat.error ? ( + {chat.error && !report ? (

{chat.error.message}

) : null} @@ -149,9 +213,11 @@ function RepoReportPage() { > {message.parts.map((part, index) => { if (part.type === 'text' && part.content) { + const prose = proseWithoutJson(part.content) + if (prose === null) return null return (

- {part.content} + {prose}

) } @@ -170,28 +236,7 @@ function RepoReportPage() {
))} - {report ? ( -
-

{report.name}

-

{report.oneLiner}

-

- Audience: - {report.audience} -

-
    - {report.mainPackages.map((pkg) => ( -
  • - - {pkg.name} - - {': '} - {pkg.role} -
  • - ))} -
-

{report.howToRun}

-
- ) : null} + {report ? : null} {!chat.isLoading && chat.messages.length === 0 ? (

diff --git a/examples/ts-react-chat/src/sandbox-triage.ts b/examples/ts-react-chat/src/sandbox-triage.ts index 5bf1259ab1..7bea441901 100644 --- a/examples/ts-react-chat/src/sandbox-triage.ts +++ b/examples/ts-react-chat/src/sandbox-triage.ts @@ -111,7 +111,11 @@ function npmGlobalCli(spec: string, verify: string): string { export const HARNESSES: Record = { 'claude-code': { label: 'Claude Code', - makeAdapter: () => claudeCodeText('sonnet'), + makeAdapter: () => + claudeCodeText('sonnet', { + permissionMode: 'bypassPermissions', + env: { CLAUDE_CODE_SANDBOXED: '1' }, + }), installCommand: npmGlobalCli( '@anthropic-ai/claude-code', 'claude --version', diff --git a/packages/ai/src/utilities/structured-output-text.ts b/packages/ai/src/utilities/structured-output-text.ts index 4d96e51363..5019e018f7 100644 --- a/packages/ai/src/utilities/structured-output-text.ts +++ b/packages/ai/src/utilities/structured-output-text.ts @@ -1,12 +1,59 @@ /** * Parse JSON from a model/harness assistant string. * Strips a wrapping markdown fence when the whole payload is fenced. + * If the model wrote prose first, take the last JSON object or array. */ export function parseJsonFromAssistantText(raw: string): unknown { const trimmed = raw.trim() - const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/) - const payload = (fenced?.[1] ?? trimmed).trim() - return JSON.parse(payload) + if (trimmed === '') { + throw new SyntaxError('Assistant text is empty') + } + + const candidates: Array = [] + const wholeFence = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/) + if (wholeFence?.[1]) candidates.push(wholeFence[1].trim()) + candidates.push(trimmed) + const lastFence = [...trimmed.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/g)].at( + -1, + ) + if (lastFence?.[1]) candidates.push(lastFence[1].trim()) + const extracted = extractLastJsonSlice(trimmed) + if (extracted !== undefined) candidates.push(extracted) + + let lastError: unknown + for (const candidate of candidates) { + try { + return JSON.parse(candidate) + } catch (error) { + lastError = error + } + } + throw lastError instanceof Error + ? lastError + : new SyntaxError('No JSON object found in assistant text') +} + +function extractLastJsonSlice(text: string): string | undefined { + let end = -1 + for (let i = text.length - 1; i >= 0; i--) { + if (text[i] === '}' || text[i] === ']') { + end = i + break + } + } + if (end < 0) return undefined + for (let start = end; start >= 0; start--) { + const opener = text[start] + if (opener !== '{' && opener !== '[') continue + const slice = text.slice(start, end + 1) + try { + JSON.parse(slice) + return slice + } catch { + // Try an earlier opener. Nested braces often fail until the real start. + } + } + return undefined } export function appendOutputSchemaInstruction( diff --git a/packages/ai/tests/structured-output-text.test.ts b/packages/ai/tests/structured-output-text.test.ts index c028489f8c..46ec5df893 100644 --- a/packages/ai/tests/structured-output-text.test.ts +++ b/packages/ai/tests/structured-output-text.test.ts @@ -23,6 +23,18 @@ describe('parseJsonFromAssistantText', () => { expect(() => parseJsonFromAssistantText('not json')).toThrow() }) + it('takes the last object after assistant prose', () => { + expect( + parseJsonFromAssistantText('I\'ll read the README.\n{"a":1}'), + ).toEqual({ a: 1 }) + }) + + it('takes the last fenced object after prose', () => { + expect( + parseJsonFromAssistantText('Looking around.\n```json\n{"a":2}\n```'), + ).toEqual({ a: 2 }) + }) + it('appends the schema instruction', () => { const next = appendOutputSchemaInstruction('Look around.', { type: 'object', From 1103b2bb4b41671d5aa7ff257851415069d6ccb8 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 15:19:05 +0200 Subject: [PATCH 05/23] fix: pass Claude --json-schema inline and stop guessing the report card --json-schema expects JSON, not a .json filename. Mark the local sandbox cwd trusted so cloned .claude/settings.json is used. Render the card from structured-output parts or a text part that starts with the root object. Show thinking, tools, and text while the run is still going. --- docs/adapters/claude-code.md | 2 +- .../ts-react-chat/src/routes/repo-report.tsx | 172 ++++++++++++------ packages/ai-claude-code/src/adapters/text.ts | 23 ++- packages/ai-claude-code/src/adapters/trust.ts | 57 ++++++ .../ai-claude-code/tests/text-adapter.test.ts | 2 + packages/ai-claude-code/tests/trust.test.ts | 24 +++ 6 files changed, 216 insertions(+), 64 deletions(-) create mode 100644 packages/ai-claude-code/src/adapters/trust.ts create mode 100644 packages/ai-claude-code/tests/trust.test.ts diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index c6bd77fd51..eeea051e20 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -170,7 +170,7 @@ const stream = chat({ ## Structured Output -Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema is sent with `--json-schema`. Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. +Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` (inline, not a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. ```ts import { chat } from "@tanstack/ai" diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index 3d4714ea7b..88c6efeca1 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -25,60 +25,83 @@ export const Route = createFileRoute('/repo-report')({ component: RepoReportPage, }) -function assistantText(messages: Array): string { - return messages - .filter((message) => message.role === 'assistant') - .flatMap((message) => message.parts) - .flatMap((part) => - part.type === 'text' && typeof part.content === 'string' - ? [part.content] - : [], - ) - .join('\n') +function looksLikeReport(value: unknown): value is Partial { + if (value === null || typeof value !== 'object' || Array.isArray(value)) { + return false + } + const record = value as Record + return ( + 'name' in record || + 'oneLiner' in record || + 'audience' in record || + 'mainPackages' in record || + 'howToRun' in record + ) } -function liveReportFromMessages( +function reportFromMessages( messages: Array, ): Partial | undefined { - const text = assistantText(messages) - const start = text.lastIndexOf('{') - if (start < 0) return undefined - const parsed: unknown = parsePartialJSON(text.slice(start)) - if (parsed === null || parsed === undefined || typeof parsed !== 'object') { - return undefined + for (const message of [...messages].reverse()) { + for (const part of [...message.parts].reverse()) { + if (part.type === 'structured-output') { + if (part.data !== undefined && looksLikeReport(part.data)) { + return part.data + } + if (part.partial !== undefined && looksLikeReport(part.partial)) { + return part.partial + } + } + } } - return parsed as Partial + for (const message of [...messages].reverse()) { + for (const part of [...message.parts].reverse()) { + if (part.type !== 'text' || typeof part.content !== 'string') continue + const trimmed = part.content.trim() + if (!trimmed.startsWith('{')) continue + const parsed: unknown = parsePartialJSON(trimmed) + if (looksLikeReport(parsed)) return parsed + } + } + return undefined } -function proseWithoutJson(content: string): string | null { - const start = content.indexOf('{') - if (start < 0) return content - const before = content.slice(0, start).trim() - return before === '' ? null : before +function isCompleteReportJson(content: string): boolean { + const trimmed = content.trim() + if (!trimmed.startsWith('{')) return false + try { + return looksLikeReport(JSON.parse(trimmed)) + } catch { + return false + } } -function ReportCard({ - report, -}: { - report: Partial -}) { +function ReportCard({ report }: { report: Partial }) { + const packages = report.mainPackages ?? [] return (

-

{report.name ?? '…'}

-

{report.oneLiner ?? '…'}

-

- Audience: - {report.audience ?? '…'} -

-
    - {(report.mainPackages ?? []).map((pkg, index) => ( -
  • - {pkg.name ?? '…'} - {': '} - {pkg.role ?? '…'} -
  • - ))} -
+ {report.name ? ( +

{report.name}

+ ) : null} + {report.oneLiner ?

{report.oneLiner}

: null} + {report.audience ? ( +

+ Audience: + {report.audience} +

+ ) : null} + {packages.length > 0 ? ( +
    + {packages.map((pkg, index) => ( +
  • + + {pkg.name ?? '…'} + + {pkg.role ? `: ${pkg.role}` : ''} +
  • + ))} +
+ ) : null} {report.howToRun ? (

{report.howToRun}

) : null} @@ -107,7 +130,19 @@ function RepoReportPage() { void chat.sendMessage(`Report on ${REPORT_REPO}`) } - const report = chat.final ?? liveReportFromMessages(chat.messages) + const report = chat.final ?? reportFromMessages(chat.messages) + const last = chat.messages.at(-1) + const waiting = + chat.isLoading && + (last === undefined || + last.role === 'user' || + last.parts.every( + (part) => + part.type !== 'text' && + part.type !== 'tool-call' && + part.type !== 'thinking' && + part.type !== 'structured-output', + )) return (
@@ -198,8 +233,18 @@ function RepoReportPage() {
- {chat.error && !report ? ( -

{chat.error.message}

+ {chat.error ? ( +

+ {chat.error.message} +

+ ) : null} + + {waiting ? ( +

+ Starting the sandbox and the agent. Tool calls and text show up + here as they arrive. Codex can take a few minutes before the first + line. +

) : null} {chat.messages.map((message) => ( @@ -207,17 +252,26 @@ function RepoReportPage() { key={message.id} className={ message.role === 'assistant' - ? 'rounded-lg bg-orange-500/5 p-4' + ? 'rounded-lg bg-orange-500/5 p-4 space-y-2' : 'text-gray-400 text-sm' } > {message.parts.map((part, index) => { + if (part.type === 'thinking' && part.content) { + return ( +

+ {part.content} +

+ ) + } if (part.type === 'text' && part.content) { - const prose = proseWithoutJson(part.content) - if (prose === null) return null + if (report && isCompleteReportJson(part.content)) return null return (

- {prose} + {part.content}

) } @@ -228,15 +282,31 @@ function RepoReportPage() { className="font-mono text-xs text-orange-200/80" > tool {part.name} + {part.state ? ` (${part.state})` : ''}

) } + if (part.type === 'structured-output') { + const data = part.data ?? part.partial + if (!looksLikeReport(data)) return null + return ( + + ) + } return null })}
))} - {report ? : null} + {report && + !chat.messages.some((message) => + message.parts.some((part) => part.type === 'structured-output'), + ) ? ( + + ) : null} {!chat.isLoading && chat.messages.length === 0 ? (

diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 2fd3625080..6a762db90c 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -20,12 +20,14 @@ import { resolveApproval, resolveDurableRunId, resolveDurableThreadId, + resolveHarnessCwd, spawnNdjson, } from '@tanstack/ai-sandbox' import { buildPrompt } from '../messages/prompt' import { translateSdkStream } from '../stream/translate' import { mapPolicyToClaudeFlags } from './policy-map' import { projectClaudeWorkspace } from './projection' +import { acceptClaudeTrustDialog } from './trust' import type { ClaudePolicyFlags } from './policy-map' import type { BridgeEventChannel, @@ -168,7 +170,7 @@ export class ClaudeCodeTextAdapter< policyFlags: ClaudePolicyFlags, mcpConfigPath: string | undefined, permissionPromptTool: string | undefined, - jsonSchemaPath: string | undefined, + jsonSchemaJson: string | undefined, ): string { const config = this.adapterConfig const modelOptions = options.modelOptions @@ -227,8 +229,8 @@ export class ClaudeCodeTextAdapter< } if (mcpConfigPath !== undefined) args.push('--mcp-config', q(mcpConfigPath)) - if (jsonSchemaPath !== undefined) { - args.push('--json-schema', q(jsonSchemaPath)) + if (jsonSchemaJson !== undefined) { + args.push('--json-schema', q(jsonSchemaJson)) } if (permissionPromptTool !== undefined) { args.push('--permission-prompt-tool', q(permissionPromptTool)) @@ -320,6 +322,7 @@ export class ClaudeCodeTextAdapter< const sandbox = this.sandboxFrom(options) cleanupSandbox = sandbox const cwd = this.workdir(options) + await acceptClaudeTrustDialog(resolveHarnessCwd(sandbox, cwd)) // Durability comes from `withSandbox(sandbox, { runs, durability })`, read // back off the capability bus. Absent it, everything below resolves to // exactly today's behavior (no journal option, no alignment, and a @@ -433,14 +436,10 @@ export class ClaudeCodeTextAdapter< tempFiles.push(mcpConfigPath) mcpConfigArg = mcpConfigFile } - let jsonSchemaArg: string | undefined - if (options.outputSchema) { - const schemaFile = `.tanstack-output-schema-${runIdSegment}.json` - const schemaPath = `${cwd}/${schemaFile}` - await sandbox.fs.write(schemaPath, JSON.stringify(options.outputSchema)) - tempFiles.push(schemaPath) - jsonSchemaArg = schemaFile - } + const jsonSchemaJson = + options.outputSchema !== undefined + ? JSON.stringify(options.outputSchema) + : undefined const command = this.buildCommand( options, resume, @@ -449,7 +448,7 @@ export class ClaudeCodeTextAdapter< bridge && permission ? `mcp__${bridge.name}__${permission.toolName}` : undefined, - jsonSchemaArg, + jsonSchemaJson, ) // Deliver the prompt. The default feeds it over stdin (keeps it out of diff --git a/packages/ai-claude-code/src/adapters/trust.ts b/packages/ai-claude-code/src/adapters/trust.ts new file mode 100644 index 0000000000..f688e90685 --- /dev/null +++ b/packages/ai-claude-code/src/adapters/trust.ts @@ -0,0 +1,57 @@ +import * as fs from 'node:fs/promises' +import * as os from 'node:os' +import * as path from 'node:path' + +/** Claude stores project keys with forward slashes, even on Windows. */ +export function claudeProjectKey(cwd: string): string { + return path.resolve(cwd).replace(/\\/g, '/') +} + +export function withTrustDialogAccepted( + config: Record, + cwd: string, +): Record { + const key = claudeProjectKey(cwd) + const projectsRaw = config.projects + const projects = + projectsRaw !== null && + typeof projectsRaw === 'object' && + !Array.isArray(projectsRaw) + ? { ...(projectsRaw as Record) } + : {} + const existingRaw = projects[key] + const existing = + existingRaw !== null && + typeof existingRaw === 'object' && + !Array.isArray(existingRaw) + ? { ...(existingRaw as Record) } + : {} + projects[key] = { ...existing, hasTrustDialogAccepted: true } + return { ...config, projects } +} + +/** + * Mark a host cwd as trusted in `~/.claude.json` so headless `-p` can use + * the repo's `.claude/settings.json`. Skip virtual sandbox roots. + */ +export async function acceptClaudeTrustDialog(cwd: string): Promise { + if (cwd === '' || cwd === '/workspace' || cwd.startsWith('/workspace/')) { + return + } + const file = path.join(os.homedir(), '.claude.json') + let current: Record = {} + try { + const raw = await fs.readFile(file, 'utf8') + const parsed: unknown = JSON.parse(raw) + if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) { + current = parsed as Record + } + } catch (error) { + if ((error as NodeJS.ErrnoException).code !== 'ENOENT') return + } + await fs.writeFile( + file, + `${JSON.stringify(withTrustDialogAccepted(current, cwd), null, 2)}\n`, + 'utf8', + ) +} diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index 404cce480f..d5f7b7feb6 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -201,6 +201,8 @@ describe('claude-code in-sandbox adapter', () => { const argv = await sbx.fs.read('/workspace/argv.txt') expect(argv).toContain('--json-schema') + expect(argv).toContain('"type":"object"') + expect(argv).toContain('"summary"') const complete = chunks.find( (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', diff --git a/packages/ai-claude-code/tests/trust.test.ts b/packages/ai-claude-code/tests/trust.test.ts new file mode 100644 index 0000000000..c13250895e --- /dev/null +++ b/packages/ai-claude-code/tests/trust.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from 'vitest' +import { claudeProjectKey, withTrustDialogAccepted } from '../src/adapters/trust' + +describe('withTrustDialogAccepted', () => { + it('sets hasTrustDialogAccepted on the resolved cwd', () => { + const next = withTrustDialogAccepted({}, 'C:\\tmp\\repo') + const key = claudeProjectKey('C:\\tmp\\repo') + expect(key.includes('\\')).toBe(false) + const projects = next.projects as Record + expect(projects[key]?.hasTrustDialogAccepted).toBe(true) + }) + + it('keeps other project entries', () => { + const next = withTrustDialogAccepted( + { projects: { '/other': { hasTrustDialogAccepted: false } } }, + '/tmp/repo', + ) + const projects = next.projects as Record + expect(projects['/other']?.hasTrustDialogAccepted).toBe(false) + expect(projects[claudeProjectKey('/tmp/repo')]?.hasTrustDialogAccepted).toBe( + true, + ) + }) +}) From 7f0c3ed15152932e4ae027669e085e2f74947a3f Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 15:29:59 +0200 Subject: [PATCH 06/23] fix(ai-claude-code): expand --json-schema from a file and skip project settings The CLI parses --json-schema as JSON. A .json filename dies on the leading dot. Pass the schema through the shell with cat. Add --bare so a cloned repo's .claude/settings.json does not require a trust dialog. --- packages/ai-claude-code/src/adapters/text.ts | 29 +++++++++++++------ .../ai-claude-code/tests/text-adapter.test.ts | 1 + 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 6a762db90c..2c2e07438f 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -170,7 +170,7 @@ export class ClaudeCodeTextAdapter< policyFlags: ClaudePolicyFlags, mcpConfigPath: string | undefined, permissionPromptTool: string | undefined, - jsonSchemaJson: string | undefined, + jsonSchemaFile: string | undefined, ): string { const config = this.adapterConfig const modelOptions = options.modelOptions @@ -178,6 +178,7 @@ export class ClaudeCodeTextAdapter< const args: Array = [ '-p', + '--bare', '--output-format', 'stream-json', '--verbose', @@ -229,8 +230,11 @@ export class ClaudeCodeTextAdapter< } if (mcpConfigPath !== undefined) args.push('--mcp-config', q(mcpConfigPath)) - if (jsonSchemaJson !== undefined) { - args.push('--json-schema', q(jsonSchemaJson)) + if (jsonSchemaFile !== undefined) { + // The CLI parses this flag as JSON. A filename like + // `.tanstack-output-schema-….json` becomes `Unexpected token '.'`. + // Expand the file in the POSIX shell so git-bash does not mangle quotes. + args.push('--json-schema', `"$(cat ${q(jsonSchemaFile)})"`) } if (permissionPromptTool !== undefined) { args.push('--permission-prompt-tool', q(permissionPromptTool)) @@ -436,10 +440,13 @@ export class ClaudeCodeTextAdapter< tempFiles.push(mcpConfigPath) mcpConfigArg = mcpConfigFile } - const jsonSchemaJson = - options.outputSchema !== undefined - ? JSON.stringify(options.outputSchema) - : undefined + let jsonSchemaFile: string | undefined + if (options.outputSchema !== undefined) { + jsonSchemaFile = `tanstack-output-schema-${runIdSegment}.json` + const schemaPath = `${cwd}/${jsonSchemaFile}` + await sandbox.fs.write(schemaPath, JSON.stringify(options.outputSchema)) + tempFiles.push(schemaPath) + } const command = this.buildCommand( options, resume, @@ -448,7 +455,7 @@ export class ClaudeCodeTextAdapter< bridge && permission ? `mcp__${bridge.name}__${permission.toolName}` : undefined, - jsonSchemaJson, + jsonSchemaFile, ) // Deliver the prompt. The default feeds it over stdin (keeps it out of @@ -480,7 +487,11 @@ export class ClaudeCodeTextAdapter< // documented escape hatch for skip-permissions in an isolated // environment — merged over the sandbox env (a caller-provided value // wins). Safe to set unconditionally; it is a no-op for stricter modes. - env: { IS_SANDBOX: '1', ...this.adapterConfig.env }, + env: { + IS_SANDBOX: '1', + CLAUDE_CODE_SANDBOXED: '1', + ...this.adapterConfig.env, + }, ...(options.abortController?.signal ? { signal: options.abortController.signal } : options.request?.signal diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index d5f7b7feb6..ea17fce66e 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -200,6 +200,7 @@ describe('claude-code in-sandbox adapter', () => { ) const argv = await sbx.fs.read('/workspace/argv.txt') + expect(argv).toContain('--bare') expect(argv).toContain('--json-schema') expect(argv).toContain('"type":"object"') expect(argv).toContain('"summary"') From 1a87e8b19b527fa669880407bcada62dce8481cf Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 15:35:54 +0200 Subject: [PATCH 07/23] fix(ai-claude-code): spawn Claude with real argv for --json-schema -p was eating --bare as the prompt, so project settings still loaded. Pass --bare before -p. Feed --json-schema through a Node runner so the shell never sees a .json filename or broken quotes. --- .../src/adapters/claude-run-source.ts | 36 +++++++++++++ packages/ai-claude-code/src/adapters/text.ts | 51 ++++++++++--------- 2 files changed, 63 insertions(+), 24 deletions(-) create mode 100644 packages/ai-claude-code/src/adapters/claude-run-source.ts diff --git a/packages/ai-claude-code/src/adapters/claude-run-source.ts b/packages/ai-claude-code/src/adapters/claude-run-source.ts new file mode 100644 index 0000000000..e8a7275754 --- /dev/null +++ b/packages/ai-claude-code/src/adapters/claude-run-source.ts @@ -0,0 +1,36 @@ +/** Written into the sandbox and run with `node` so --json-schema is a real argv value. */ +export const CLAUDE_RUNNER_SOURCE = `import { spawn } from 'node:child_process' +import { readFileSync } from 'node:fs' + +const argv = JSON.parse(process.argv[2]) +const schemaFile = process.argv[3] +if (schemaFile) { + const schema = readFileSync(schemaFile, 'utf8') + for (let i = 0; i < argv.length; i++) { + if (argv[i] === '__TANSTACK_SCHEMA__') argv[i] = schema + } +} + +const [cmd, ...args] = argv +if (!cmd) { + console.error('tanstack-claude-run: missing command') + process.exit(1) +} + +const child = spawn(cmd, args, { + stdio: ['pipe', 'pipe', 'pipe'], + env: process.env, + windowsHide: true, +}) +process.stdin.pipe(child.stdin) +child.stdout.pipe(process.stdout) +child.stderr.pipe(process.stderr) +child.on('error', (error) => { + console.error(error) + process.exit(1) +}) +child.on('exit', (code, signal) => { + if (signal) process.exit(1) + process.exit(code ?? 1) +}) +` diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 2c2e07438f..7e2f388a19 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -27,6 +27,7 @@ import { buildPrompt } from '../messages/prompt' import { translateSdkStream } from '../stream/translate' import { mapPolicyToClaudeFlags } from './policy-map' import { projectClaudeWorkspace } from './projection' +import { CLAUDE_RUNNER_SOURCE } from './claude-run-source' import { acceptClaudeTrustDialog } from './trust' import type { ClaudePolicyFlags } from './policy-map' import type { @@ -164,57 +165,60 @@ export class ClaudeCodeTextAdapter< return 'event' } - private buildCommand( + private buildArgv( options: TextOptions, resume: string | undefined, policyFlags: ClaudePolicyFlags, mcpConfigPath: string | undefined, permissionPromptTool: string | undefined, - jsonSchemaFile: string | undefined, - ): string { + hasJsonSchema: boolean, + ): Array { const config = this.adapterConfig const modelOptions = options.modelOptions - const exe = config.claudeExecutable ?? 'claude' + const exeParts = (config.claudeExecutable ?? 'claude').split(' ') + // --bare before -p. `-p` can take the next token as the prompt, so + // `claude -p --bare` treats --bare as the prompt and still loads the + // cloned repo's .claude/settings.json (trust dialog). const args: Array = [ - '-p', + ...exeParts, '--bare', + '-p', '--output-format', 'stream-json', '--verbose', '--model', - q(this.model), + this.model, ] if (config.streamPartials !== false) args.push('--include-partial-messages') - if (resume !== undefined) args.push('--resume', q(resume)) + if (resume !== undefined) args.push('--resume', resume) - // Precedence: per-call modelOptions > adapter config > policy > sandbox default. const permissionMode = modelOptions?.permissionMode ?? config.permissionMode ?? policyFlags.permissionMode ?? 'bypassPermissions' - args.push('--permission-mode', q(permissionMode)) + args.push('--permission-mode', permissionMode) const maxTurns = modelOptions?.maxTurns ?? config.maxTurns if (maxTurns !== undefined) args.push('--max-turns', String(maxTurns)) - for (const dir of config.addDirs ?? []) args.push('--add-dir', q(dir)) + for (const dir of config.addDirs ?? []) args.push('--add-dir', dir) const allowedTools = [ ...(modelOptions?.allowedTools ?? config.allowedTools ?? []), ...policyFlags.allowedTools, ] if (allowedTools.length > 0) { - args.push('--allowedTools', q([...new Set(allowedTools)].join(','))) + args.push('--allowedTools', [...new Set(allowedTools)].join(',')) } const disallowedTools = [ ...(modelOptions?.disallowedTools ?? config.disallowedTools ?? []), ...policyFlags.disallowedTools, ] if (disallowedTools.length > 0) { - args.push('--disallowedTools', q([...new Set(disallowedTools)].join(','))) + args.push('--disallowedTools', [...new Set(disallowedTools)].join(',')) } const systemPrompts = normalizeSystemPrompts(options.systemPrompts) @@ -226,21 +230,16 @@ export class ClaudeCodeTextAdapter< config.systemPromptMode === 'replace' ? '--system-prompt' : '--append-system-prompt' - args.push(flag, q(joined)) + args.push(flag, joined) } - if (mcpConfigPath !== undefined) args.push('--mcp-config', q(mcpConfigPath)) - if (jsonSchemaFile !== undefined) { - // The CLI parses this flag as JSON. A filename like - // `.tanstack-output-schema-….json` becomes `Unexpected token '.'`. - // Expand the file in the POSIX shell so git-bash does not mangle quotes. - args.push('--json-schema', `"$(cat ${q(jsonSchemaFile)})"`) - } + if (mcpConfigPath !== undefined) args.push('--mcp-config', mcpConfigPath) + if (hasJsonSchema) args.push('--json-schema', '__TANSTACK_SCHEMA__') if (permissionPromptTool !== undefined) { - args.push('--permission-prompt-tool', q(permissionPromptTool)) + args.push('--permission-prompt-tool', permissionPromptTool) } - return `${exe} ${args.join(' ')}` + return args } /** @@ -447,7 +446,10 @@ export class ClaudeCodeTextAdapter< await sandbox.fs.write(schemaPath, JSON.stringify(options.outputSchema)) tempFiles.push(schemaPath) } - const command = this.buildCommand( + const runnerFile = `tanstack-claude-run-${runIdSegment}.mjs` + await sandbox.fs.write(`${cwd}/${runnerFile}`, CLAUDE_RUNNER_SOURCE) + tempFiles.push(`${cwd}/${runnerFile}`) + const argv = this.buildArgv( options, resume, mapPolicyToClaudeFlags(policy), @@ -455,8 +457,9 @@ export class ClaudeCodeTextAdapter< bridge && permission ? `mcp__${bridge.name}__${permission.toolName}` : undefined, - jsonSchemaFile, + jsonSchemaFile !== undefined, ) + const command = `node ${q(runnerFile)} ${q(JSON.stringify(argv))} ${q(jsonSchemaFile ?? '')}` // Deliver the prompt. The default feeds it over stdin (keeps it out of // argv). Providers without a writable host→process stdin (e.g. Cloudflare) From 25a80650ebc255ed4a4b0de974c3666e5fec81ae Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 17:52:25 +0200 Subject: [PATCH 08/23] fix(ai-claude-code): stop sending --json-schema through the shell Claude's CLI only accepts inline JSON for --json-schema. Passing a filename (or letting git-bash retokenize JSON) failed with Unexpected token '.'. The runner now reads argv and the schema from files, then spawn()s claude so the JSON is one real argument. A cloned repo that ships .claude/settings.json no longer needs a trust dialog. Those files are renamed for the run so headless -p can start. --- docs/adapters/claude-code.md | 4 +- docs/config.json | 5 +- docs/structured-outputs/harnesses.md | 4 +- .../src/adapters/claude-run-source.ts | 42 +++++++++++++--- .../src/adapters/project-settings.ts | 25 ++++++++++ packages/ai-claude-code/src/adapters/text.ts | 21 ++++++-- packages/ai-claude-code/tests/attach.test.ts | 22 +++++--- .../tests/project-settings.test.ts | 47 +++++++++++++++++ .../ai-claude-code/tests/text-adapter.test.ts | 50 +++++++++++++++++++ 9 files changed, 199 insertions(+), 21 deletions(-) create mode 100644 packages/ai-claude-code/src/adapters/project-settings.ts create mode 100644 packages/ai-claude-code/tests/project-settings.test.ts diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index eeea051e20..6df1abb561 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -170,7 +170,9 @@ const stream = chat({ ## Structured Output -Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` (inline, not a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. +Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` as inline JSON (the CLI rejects a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. + +If the cloned repo has `.claude/settings.json`, the adapter turns those settings off for the run. Headless `-p` then does not need a trust dialog for that workspace. ```ts import { chat } from "@tanstack/ai" diff --git a/docs/config.json b/docs/config.json index 7c8240ec7c..19783c47d5 100644 --- a/docs/config.json +++ b/docs/config.json @@ -363,7 +363,8 @@ { "label": "Harness Agents", "to": "structured-outputs/harnesses", - "addedAt": "2026-08-14" + "addedAt": "2026-08-14", + "updatedAt": "2026-08-17" } ] }, @@ -871,7 +872,7 @@ "label": "Claude Code", "to": "adapters/claude-code", "addedAt": "2026-06-12", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-17" }, { "label": "Codex", diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index b57d241637..fa4f208ccd 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -146,7 +146,7 @@ function RepoReport() { | Adapter | How the schema is applied | |---|---| -| Claude Code | Native `--json-schema` flag on the same turn | +| Claude Code | Native `--json-schema` flag on the same turn. The value is inline JSON, not a file path. | | Codex | Native `--output-schema` flag on the same turn | | OpenCode | Schema is added to the prompt. The adapter parses the last assistant text. | | Grok Build | Schema is added to the prompt. The adapter parses the last assistant text. | @@ -197,3 +197,5 @@ The React chat example includes a repo-report page. 5. Run the report. The page reads the typed object from `useChat().final`. The page clones `TanStack/ai` into a sandbox, asks the agent to inspect it, and shows the validated report. + +Claude Code does not need you to accept a trust dialog for that clone. The adapter turns off `.claude/settings.json` for the run so headless `-p` can start. diff --git a/packages/ai-claude-code/src/adapters/claude-run-source.ts b/packages/ai-claude-code/src/adapters/claude-run-source.ts index e8a7275754..b12670db40 100644 --- a/packages/ai-claude-code/src/adapters/claude-run-source.ts +++ b/packages/ai-claude-code/src/adapters/claude-run-source.ts @@ -1,27 +1,57 @@ -/** Written into the sandbox and run with `node` so --json-schema is a real argv value. */ +/** Placeholder swapped for the schema JSON after the runner reads the files. */ +export const CLAUDE_JSON_SCHEMA_PLACEHOLDER = '__TANSTACK_SCHEMA__' + +/** + * Written into the sandbox and run with `node`. + * + * The shell only sees two filenames. The runner reads the argv array and the + * schema JSON from those files, then spawn()s claude so `--json-schema` is a + * real argv value (the CLI rejects a file path). + * + * On Windows, `claude` is often a `.cmd` shim. `spawn(cmd, args)` without a + * shell cannot find that shim, so we go through `sh` with `"$0"` / `"$@"` + * (git-bash is already on PATH in the local-process sandbox). + */ export const CLAUDE_RUNNER_SOURCE = `import { spawn } from 'node:child_process' import { readFileSync } from 'node:fs' -const argv = JSON.parse(process.argv[2]) +const argvFile = process.argv[2] +if (!argvFile) { + console.error('tanstack-claude-run: missing argv file') + process.exit(1) +} + +const argv = JSON.parse(readFileSync(argvFile, 'utf8')) +if (!Array.isArray(argv)) { + console.error('tanstack-claude-run: argv file must be a JSON array') + process.exit(1) +} + const schemaFile = process.argv[3] if (schemaFile) { const schema = readFileSync(schemaFile, 'utf8') for (let i = 0; i < argv.length; i++) { - if (argv[i] === '__TANSTACK_SCHEMA__') argv[i] = schema + if (argv[i] === ${JSON.stringify(CLAUDE_JSON_SCHEMA_PLACEHOLDER)}) argv[i] = schema } } const [cmd, ...args] = argv -if (!cmd) { +if (typeof cmd !== 'string' || cmd === '') { console.error('tanstack-claude-run: missing command') process.exit(1) } -const child = spawn(cmd, args, { +const opts = { stdio: ['pipe', 'pipe', 'pipe'], env: process.env, windowsHide: true, -}) +} + +const child = + process.platform === 'win32' + ? spawn('sh', ['-c', 'exec "$0" "$@"', cmd, ...args], opts) + : spawn(cmd, args, opts) + process.stdin.pipe(child.stdin) child.stdout.pipe(process.stdout) child.stderr.pipe(process.stderr) diff --git a/packages/ai-claude-code/src/adapters/project-settings.ts b/packages/ai-claude-code/src/adapters/project-settings.ts new file mode 100644 index 0000000000..a8a454bd52 --- /dev/null +++ b/packages/ai-claude-code/src/adapters/project-settings.ts @@ -0,0 +1,25 @@ +import type { SandboxFs } from '@tanstack/ai-sandbox' + +const SETTING_FILES = ['settings.json', 'settings.local.json'] as const +const DISABLED_SUFFIX = '.tanstack-disabled' + +/** + * Move project Claude settings aside so headless `-p` does not refuse the + * workspace. A cloned repo (for example TanStack/ai) often ships + * `.claude/settings.json` with `permissions.allow`. Claude then prints a + * trust warning and ignores those rules unless the host has accepted the + * trust dialog for that cwd. + */ +export async function disableClaudeProjectSettings( + fs: Pick, + cwd: string, +): Promise> { + const disabled: Array = [] + for (const name of SETTING_FILES) { + const from = `${cwd}/.claude/${name}` + if (!(await fs.exists(from))) continue + await fs.rename(from, `${from}${DISABLED_SUFFIX}`) + disabled.push(from) + } + return disabled +} diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 7e2f388a19..a87ed57816 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -27,7 +27,11 @@ import { buildPrompt } from '../messages/prompt' import { translateSdkStream } from '../stream/translate' import { mapPolicyToClaudeFlags } from './policy-map' import { projectClaudeWorkspace } from './projection' -import { CLAUDE_RUNNER_SOURCE } from './claude-run-source' +import { + CLAUDE_JSON_SCHEMA_PLACEHOLDER, + CLAUDE_RUNNER_SOURCE, +} from './claude-run-source' +import { disableClaudeProjectSettings } from './project-settings' import { acceptClaudeTrustDialog } from './trust' import type { ClaudePolicyFlags } from './policy-map' import type { @@ -234,7 +238,9 @@ export class ClaudeCodeTextAdapter< } if (mcpConfigPath !== undefined) args.push('--mcp-config', mcpConfigPath) - if (hasJsonSchema) args.push('--json-schema', '__TANSTACK_SCHEMA__') + if (hasJsonSchema) { + args.push('--json-schema', CLAUDE_JSON_SCHEMA_PLACEHOLDER) + } if (permissionPromptTool !== undefined) { args.push('--permission-prompt-tool', permissionPromptTool) } @@ -326,6 +332,7 @@ export class ClaudeCodeTextAdapter< cleanupSandbox = sandbox const cwd = this.workdir(options) await acceptClaudeTrustDialog(resolveHarnessCwd(sandbox, cwd)) + await disableClaudeProjectSettings(sandbox.fs, cwd) // Durability comes from `withSandbox(sandbox, { runs, durability })`, read // back off the capability bus. Absent it, everything below resolves to // exactly today's behavior (no journal option, no alignment, and a @@ -459,7 +466,15 @@ export class ClaudeCodeTextAdapter< : undefined, jsonSchemaFile !== undefined, ) - const command = `node ${q(runnerFile)} ${q(JSON.stringify(argv))} ${q(jsonSchemaFile ?? '')}` + // Filenames only on the shell line. JSON (schema, system prompt, MCP + // config path) lives in the argv file so git-bash cannot retokenize it. + const argvFile = `tanstack-claude-argv-${runIdSegment}.json` + await sandbox.fs.write(`${cwd}/${argvFile}`, JSON.stringify(argv)) + tempFiles.push(`${cwd}/${argvFile}`) + const command = + jsonSchemaFile === undefined + ? `node ${q(runnerFile)} ${q(argvFile)}` + : `node ${q(runnerFile)} ${q(argvFile)} ${q(jsonSchemaFile)}` // Deliver the prompt. The default feeds it over stdin (keeps it out of // argv). Providers without a writable host→process stdin (e.g. Cloudflare) diff --git a/packages/ai-claude-code/tests/attach.test.ts b/packages/ai-claude-code/tests/attach.test.ts index ba6d0ff4e1..784430f798 100644 --- a/packages/ai-claude-code/tests/attach.test.ts +++ b/packages/ai-claude-code/tests/attach.test.ts @@ -50,8 +50,8 @@ afterAll(async () => { // Same stand-in as `text-adapter.test.ts`: ignores its flags, reads the // prompt from stdin, then emits stream-json (system/init → assistant text → -// result). Its filename ("fake-claude") is asserted to be ABSENT from the -// spawned commands on the attach path, proving the agent was never started. +// result). The runner filename is asserted to be ABSENT from the spawned +// commands on the attach path, proving the agent was never started. const FAKE_CLAUDE = [ `let input = ''`, `process.stdin.on('data', (d) => { input += d })`, @@ -152,10 +152,12 @@ describe('claude-code durable-run wiring (attach path)', () => { ) expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) - // The agent still ran directly (unjournaled): its own command shows up, + // The agent still ran directly (unjournaled): the argv runner shows up, // but no command anywhere references a journal path for this runId. expect( - recorder.spawned.some((command) => command.includes('fake-claude.mjs')), + recorder.spawned.some((command) => + command.includes('tanstack-claude-run-'), + ), ).toBe(true) const paths = journalPaths(runId) expect( @@ -192,9 +194,11 @@ describe('claude-code durable-run wiring (attach path)', () => { expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) - // The agent was actually started (`startJournaledAgent` spawns it). + // The agent was actually started (`startJournaledAgent` spawns the runner). expect( - recorder.spawned.some((command) => command.includes('fake-claude.mjs')), + recorder.spawned.some((command) => + command.includes('tanstack-claude-run-'), + ), ).toBe(true) // ...and its output was journaled under a path derived from THIS runId. @@ -273,10 +277,12 @@ describe('claude-code durable-run wiring (attach path)', () => { expect(text).toContain('resumed') expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) - // No command ever referenced the agent executable: the agent was never + // No command ever referenced the argv runner: the agent was never // started on the attach path. expect( - recorder.spawned.some((command) => command.includes('fake-claude.mjs')), + recorder.spawned.some((command) => + command.includes('tanstack-claude-run-'), + ), ).toBe(false) // A read command against this run's journal DID happen. diff --git a/packages/ai-claude-code/tests/project-settings.test.ts b/packages/ai-claude-code/tests/project-settings.test.ts new file mode 100644 index 0000000000..71fa43091b --- /dev/null +++ b/packages/ai-claude-code/tests/project-settings.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from 'vitest' +import { disableClaudeProjectSettings } from '../src/adapters/project-settings' + +function memoryFs(initial: Record) { + const files = { ...initial } + return { + files, + exists: (path: string) => Promise.resolve(path in files), + rename: (from: string, to: string) => { + if (!(from in files)) { + return Promise.reject(new Error(`missing ${from}`)) + } + files[to] = files[from] ?? '' + delete files[from] + return Promise.resolve() + }, + } +} + +describe('disableClaudeProjectSettings', () => { + it('renames settings.json and settings.local.json', async () => { + const fs = memoryFs({ + '/workspace/.claude/settings.json': '{"permissions":{"allow":["Bash"]}}', + '/workspace/.claude/settings.local.json': '{}', + }) + + const disabled = await disableClaudeProjectSettings(fs, '/workspace') + + expect(disabled).toEqual([ + '/workspace/.claude/settings.json', + '/workspace/.claude/settings.local.json', + ]) + expect(fs.files['/workspace/.claude/settings.json']).toBeUndefined() + expect(fs.files['/workspace/.claude/settings.json.tanstack-disabled']).toBe( + '{"permissions":{"allow":["Bash"]}}', + ) + expect( + fs.files['/workspace/.claude/settings.local.json.tanstack-disabled'], + ).toBe('{}') + }) + + it('no-ops when the project has no Claude settings', async () => { + const fs = memoryFs({}) + const disabled = await disableClaudeProjectSettings(fs, '/workspace') + expect(disabled).toEqual([]) + }) +}) diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index ea17fce66e..6fa138653a 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -204,6 +204,8 @@ describe('claude-code in-sandbox adapter', () => { expect(argv).toContain('--json-schema') expect(argv).toContain('"type":"object"') expect(argv).toContain('"summary"') + expect(argv).not.toContain('tanstack-output-schema') + expect(argv).not.toMatch(/--json-schema\s+\./) const complete = chunks.find( (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', @@ -217,4 +219,52 @@ describe('claude-code in-sandbox adapter', () => { await sbx.destroy() }) + + it('moves .claude/settings.json aside so headless -p does not need trust', async () => { + const fake = [ + `import { existsSync, writeFileSync } from 'node:fs'`, + `writeFileSync(`, + ` 'settings-probe.txt',`, + ` existsSync('.claude/settings.json') ? 'present' : 'absent',`, + `)`, + `let input = ''`, + `process.stdin.on('data', (d) => { input += d })`, + `process.stdin.on('end', () => {`, + ` const w = (o) => process.stdout.write(JSON.stringify(o) + '\\n')`, + ` w({ type: 'system', subtype: 'init', session_id: 'sess-trust', model: 'haiku', tools: [] })`, + ` w({ type: 'assistant', message: { id: 'msg-1', content: [{ type: 'text', text: 'ok' }] }, parent_tool_use_id: null })`, + ` w({ type: 'result', subtype: 'success', result: 'ok', usage: { input_tokens: 1, output_tokens: 1 } })`, + `})`, + ].join('\n') + + const sbx = await provider.create({}) + await sbx.fs.write('/workspace/fake-claude.mjs', fake) + await sbx.fs.write( + '/workspace/.claude/settings.json', + JSON.stringify({ permissions: { allow: ['Bash'] } }), + ) + + const adapter = claudeCodeText('haiku', { + claudeExecutable: 'node fake-claude.mjs', + streamPartials: false, + emitDiff: false, + }) + + const chunks = await collect( + adapter.chatStream({ + model: 'haiku', + messages: [{ role: 'user', content: 'hi' }], + logger: noopLogger, + capabilities: capabilityContextWith(sbx), + }), + ) + + expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(false) + expect(await sbx.fs.read('/workspace/settings-probe.txt')).toBe('absent') + expect( + await sbx.fs.exists('/workspace/.claude/settings.json.tanstack-disabled'), + ).toBe(true) + + await sbx.destroy() + }) }) From 3320f4b8a01d7455dde2b8a1f092dc441b59051e Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 17:54:53 +0200 Subject: [PATCH 09/23] fix(ai-claude-code): skip project settings with --setting-sources Renaming .claude/settings.json dirtied a reused sandbox and could fail on Windows when the disabled file already existed. Pass --setting-sources user instead so headless -p ignores project settings without touching the repo. --- docs/adapters/claude-code.md | 2 +- docs/structured-outputs/harnesses.md | 2 +- .../src/adapters/project-settings.ts | 25 ---------- packages/ai-claude-code/src/adapters/text.ts | 12 +++-- .../tests/project-settings.test.ts | 47 ----------------- .../ai-claude-code/tests/text-adapter.test.ts | 50 +------------------ 6 files changed, 11 insertions(+), 127 deletions(-) delete mode 100644 packages/ai-claude-code/src/adapters/project-settings.ts delete mode 100644 packages/ai-claude-code/tests/project-settings.test.ts diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index 6df1abb561..26be00fa26 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -172,7 +172,7 @@ const stream = chat({ Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` as inline JSON (the CLI rejects a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. -If the cloned repo has `.claude/settings.json`, the adapter turns those settings off for the run. Headless `-p` then does not need a trust dialog for that workspace. +The adapter loads only user settings (`--setting-sources user`). A cloned repo's `.claude/settings.json` does not block headless `-p`. ```ts import { chat } from "@tanstack/ai" diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index fa4f208ccd..6de1d6a1b8 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -198,4 +198,4 @@ The React chat example includes a repo-report page. The page clones `TanStack/ai` into a sandbox, asks the agent to inspect it, and shows the validated report. -Claude Code does not need you to accept a trust dialog for that clone. The adapter turns off `.claude/settings.json` for the run so headless `-p` can start. +Claude Code does not need you to accept a trust dialog for that clone. The adapter loads only user settings, so the clone's `.claude/settings.json` does not block headless `-p`. diff --git a/packages/ai-claude-code/src/adapters/project-settings.ts b/packages/ai-claude-code/src/adapters/project-settings.ts deleted file mode 100644 index a8a454bd52..0000000000 --- a/packages/ai-claude-code/src/adapters/project-settings.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { SandboxFs } from '@tanstack/ai-sandbox' - -const SETTING_FILES = ['settings.json', 'settings.local.json'] as const -const DISABLED_SUFFIX = '.tanstack-disabled' - -/** - * Move project Claude settings aside so headless `-p` does not refuse the - * workspace. A cloned repo (for example TanStack/ai) often ships - * `.claude/settings.json` with `permissions.allow`. Claude then prints a - * trust warning and ignores those rules unless the host has accepted the - * trust dialog for that cwd. - */ -export async function disableClaudeProjectSettings( - fs: Pick, - cwd: string, -): Promise> { - const disabled: Array = [] - for (const name of SETTING_FILES) { - const from = `${cwd}/.claude/${name}` - if (!(await fs.exists(from))) continue - await fs.rename(from, `${from}${DISABLED_SUFFIX}`) - disabled.push(from) - } - return disabled -} diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index a87ed57816..7a4f1d3b77 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -31,7 +31,6 @@ import { CLAUDE_JSON_SCHEMA_PLACEHOLDER, CLAUDE_RUNNER_SOURCE, } from './claude-run-source' -import { disableClaudeProjectSettings } from './project-settings' import { acceptClaudeTrustDialog } from './trust' import type { ClaudePolicyFlags } from './policy-map' import type { @@ -181,12 +180,16 @@ export class ClaudeCodeTextAdapter< const modelOptions = options.modelOptions const exeParts = (config.claudeExecutable ?? 'claude').split(' ') - // --bare before -p. `-p` can take the next token as the prompt, so - // `claude -p --bare` treats --bare as the prompt and still loads the - // cloned repo's .claude/settings.json (trust dialog). + // Flags that skip project settings must come before `-p`. `-p` can take + // the next token as the prompt, so `claude -p --bare` treats --bare as + // the prompt and still loads `.claude/settings.json`. + // `--setting-sources user` skips project/local settings, so a cloned + // repo's allow-list does not trigger the trust dialog. const args: Array = [ ...exeParts, '--bare', + '--setting-sources', + 'user', '-p', '--output-format', 'stream-json', @@ -332,7 +335,6 @@ export class ClaudeCodeTextAdapter< cleanupSandbox = sandbox const cwd = this.workdir(options) await acceptClaudeTrustDialog(resolveHarnessCwd(sandbox, cwd)) - await disableClaudeProjectSettings(sandbox.fs, cwd) // Durability comes from `withSandbox(sandbox, { runs, durability })`, read // back off the capability bus. Absent it, everything below resolves to // exactly today's behavior (no journal option, no alignment, and a diff --git a/packages/ai-claude-code/tests/project-settings.test.ts b/packages/ai-claude-code/tests/project-settings.test.ts deleted file mode 100644 index 71fa43091b..0000000000 --- a/packages/ai-claude-code/tests/project-settings.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { disableClaudeProjectSettings } from '../src/adapters/project-settings' - -function memoryFs(initial: Record) { - const files = { ...initial } - return { - files, - exists: (path: string) => Promise.resolve(path in files), - rename: (from: string, to: string) => { - if (!(from in files)) { - return Promise.reject(new Error(`missing ${from}`)) - } - files[to] = files[from] ?? '' - delete files[from] - return Promise.resolve() - }, - } -} - -describe('disableClaudeProjectSettings', () => { - it('renames settings.json and settings.local.json', async () => { - const fs = memoryFs({ - '/workspace/.claude/settings.json': '{"permissions":{"allow":["Bash"]}}', - '/workspace/.claude/settings.local.json': '{}', - }) - - const disabled = await disableClaudeProjectSettings(fs, '/workspace') - - expect(disabled).toEqual([ - '/workspace/.claude/settings.json', - '/workspace/.claude/settings.local.json', - ]) - expect(fs.files['/workspace/.claude/settings.json']).toBeUndefined() - expect(fs.files['/workspace/.claude/settings.json.tanstack-disabled']).toBe( - '{"permissions":{"allow":["Bash"]}}', - ) - expect( - fs.files['/workspace/.claude/settings.local.json.tanstack-disabled'], - ).toBe('{}') - }) - - it('no-ops when the project has no Claude settings', async () => { - const fs = memoryFs({}) - const disabled = await disableClaudeProjectSettings(fs, '/workspace') - expect(disabled).toEqual([]) - }) -}) diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index 6fa138653a..5992fb3c9d 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -201,6 +201,8 @@ describe('claude-code in-sandbox adapter', () => { const argv = await sbx.fs.read('/workspace/argv.txt') expect(argv).toContain('--bare') + expect(argv).toContain('--setting-sources') + expect(argv).toContain('user') expect(argv).toContain('--json-schema') expect(argv).toContain('"type":"object"') expect(argv).toContain('"summary"') @@ -219,52 +221,4 @@ describe('claude-code in-sandbox adapter', () => { await sbx.destroy() }) - - it('moves .claude/settings.json aside so headless -p does not need trust', async () => { - const fake = [ - `import { existsSync, writeFileSync } from 'node:fs'`, - `writeFileSync(`, - ` 'settings-probe.txt',`, - ` existsSync('.claude/settings.json') ? 'present' : 'absent',`, - `)`, - `let input = ''`, - `process.stdin.on('data', (d) => { input += d })`, - `process.stdin.on('end', () => {`, - ` const w = (o) => process.stdout.write(JSON.stringify(o) + '\\n')`, - ` w({ type: 'system', subtype: 'init', session_id: 'sess-trust', model: 'haiku', tools: [] })`, - ` w({ type: 'assistant', message: { id: 'msg-1', content: [{ type: 'text', text: 'ok' }] }, parent_tool_use_id: null })`, - ` w({ type: 'result', subtype: 'success', result: 'ok', usage: { input_tokens: 1, output_tokens: 1 } })`, - `})`, - ].join('\n') - - const sbx = await provider.create({}) - await sbx.fs.write('/workspace/fake-claude.mjs', fake) - await sbx.fs.write( - '/workspace/.claude/settings.json', - JSON.stringify({ permissions: { allow: ['Bash'] } }), - ) - - const adapter = claudeCodeText('haiku', { - claudeExecutable: 'node fake-claude.mjs', - streamPartials: false, - emitDiff: false, - }) - - const chunks = await collect( - adapter.chatStream({ - model: 'haiku', - messages: [{ role: 'user', content: 'hi' }], - logger: noopLogger, - capabilities: capabilityContextWith(sbx), - }), - ) - - expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(false) - expect(await sbx.fs.read('/workspace/settings-probe.txt')).toBe('absent') - expect( - await sbx.fs.exists('/workspace/.claude/settings.json.tanstack-disabled'), - ).toBe(true) - - await sbx.destroy() - }) }) From d4595b99c394f17ce4e90fd81e639ed40195e300 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 18:47:41 +0200 Subject: [PATCH 10/23] fix(ai-claude-code): pass host Anthropic auth into the sandbox Claude printed "Not logged in" after spawn started working. Docker exec replaces the container env, so ANTHROPIC_API_KEY set at create time can vanish. Copy the host API key into the spawn env, keep PATH/HOME on Docker exec, and set HOME from USERPROFILE on Windows local-process so `claude login` still finds ~/.claude.json. --- docs/adapters/claude-code.md | 2 + .../ts-react-chat/src/routes/repo-report.tsx | 2 +- examples/ts-react-chat/src/sandbox-triage.ts | 24 +++++------ packages/ai-claude-code/src/adapters/text.ts | 23 +++++++++++ .../ai-claude-code/tests/text-adapter.test.ts | 41 +++++++++++++++++++ packages/ai-sandbox-docker/src/handle.ts | 12 ++++-- 6 files changed, 88 insertions(+), 16 deletions(-) diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index 26be00fa26..1f151dc06d 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -174,6 +174,8 @@ Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its nat The adapter loads only user settings (`--setting-sources user`). A cloned repo's `.claude/settings.json` does not block headless `-p`. +Headless Claude needs an `ANTHROPIC_API_KEY` in the process env, or a host `claude login` when you use the local-process sandbox. The adapter copies the host API key into the sandbox process. A Docker container has no host login. + ```ts import { chat } from "@tanstack/ai" import { claudeCodeText } from "@tanstack/ai-claude-code" diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index 88c6efeca1..5b7db501ad 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -112,7 +112,7 @@ function ReportCard({ report }: { report: Partial }) { function RepoReportPage() { const [threadId] = useState(() => crypto.randomUUID()) const [harness, setHarness] = useState('claude-code') - const [provider, setProvider] = useState('docker') + const [provider, setProvider] = useState('local') const [agent, setAgent] = useState('explainer') const chat = useChat({ diff --git a/examples/ts-react-chat/src/sandbox-triage.ts b/examples/ts-react-chat/src/sandbox-triage.ts index 7bea441901..2e7230cf9a 100644 --- a/examples/ts-react-chat/src/sandbox-triage.ts +++ b/examples/ts-react-chat/src/sandbox-triage.ts @@ -401,20 +401,20 @@ export function buildSandbox(opts: { ? localProcessSandbox({ scrubEnv: ['ANTHROPIC_API_KEY'] }) : PROVIDERS[opts.provider].make(ports) - // Inject auth secrets only for sandboxed providers — local-process inherits the - // host's own env (API key, or a `claude login`/`codex login`), so nothing to inject. + // Inject harness auth whenever it is set. Local-process also inherits the + // host env, but Docker `exec` replaces the container env, so the key must + // be on the handle too. Subscription mode still scrubs ANTHROPIC_API_KEY + // after merge so `claude login` can win. const secretEnv: Record = {} - if (opts.provider !== 'local') { - // Harness auth: a custom mapping (e.g. codex → CODEX_API_KEY) if provided, - // otherwise inject whichever of its requiredEnv vars are set. - if (harness.sandboxSecrets) { - Object.assign(secretEnv, harness.sandboxSecrets()) - } else { - for (const key of harness.requiredEnv) { - const value = process.env[key] - if (value) secretEnv[key] = value - } + if (harness.sandboxSecrets) { + Object.assign(secretEnv, harness.sandboxSecrets()) + } else { + for (const key of harness.requiredEnv) { + const value = process.env[key] + if (value) secretEnv[key] = value } + } + if (opts.provider !== 'local') { // Provider auth (e.g. DAYTONA_API_KEY) — used host-side, harmless in-sandbox. for (const key of PROVIDERS[opts.provider].requiredEnv) { const value = process.env[key] diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 7a4f1d3b77..a5668f57e9 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -104,6 +104,27 @@ function q(value: string): string { return `'${value.replace(/'/g, `'\\''`)}'` } +/** Copy host Anthropic auth into the sandbox process. Docker `exec` Env replaces the container env, so a key set only at create time can vanish. */ +function hostClaudeAuthEnv(): Record { + const env: Record = {} + const apiKey = process.env.ANTHROPIC_API_KEY + if (apiKey) env.ANTHROPIC_API_KEY = apiKey + const authToken = process.env.ANTHROPIC_AUTH_TOKEN + if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken + return env +} + +/** + * Windows Node often has USERPROFILE but no HOME. Claude then cannot find + * `~/.claude.json` (the `claude login` file) and prints "Not logged in". + */ +function localProcessHomeEnv(provider: string): Record { + if (provider !== 'local-process') return {} + if (process.env.HOME) return {} + const home = process.env.USERPROFILE + return home ? { HOME: home } : {} +} + /** Format a host tool-bridge as claude's `--mcp-config` JSON. */ function bridgeToMcpConfig(bridge: HostToolBridge): string { return JSON.stringify({ @@ -510,6 +531,8 @@ export class ClaudeCodeTextAdapter< env: { IS_SANDBOX: '1', CLAUDE_CODE_SANDBOXED: '1', + ...hostClaudeAuthEnv(), + ...localProcessHomeEnv(sandbox.provider), ...this.adapterConfig.env, }, ...(options.abortController?.signal diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index 5992fb3c9d..cc03f270f8 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -221,4 +221,45 @@ describe('claude-code in-sandbox adapter', () => { await sbx.destroy() }) + + it('copies ANTHROPIC_API_KEY from the host process into the CLI env', async () => { + const fake = [ + `import { writeFileSync } from 'node:fs'`, + `writeFileSync('auth-probe.txt', process.env.ANTHROPIC_API_KEY ? 'set' : 'missing')`, + `let input = ''`, + `process.stdin.on('data', (d) => { input += d })`, + `process.stdin.on('end', () => {`, + ` const w = (o) => process.stdout.write(JSON.stringify(o) + '\\n')`, + ` w({ type: 'system', subtype: 'init', session_id: 'sess-auth', model: 'haiku', tools: [] })`, + ` w({ type: 'assistant', message: { id: 'msg-1', content: [{ type: 'text', text: 'ok' }] }, parent_tool_use_id: null })`, + ` w({ type: 'result', subtype: 'success', result: 'ok', usage: { input_tokens: 1, output_tokens: 1 } })`, + `})`, + ].join('\n') + + const previous = process.env.ANTHROPIC_API_KEY + process.env.ANTHROPIC_API_KEY = 'sk-test-not-a-real-key' + const sbx = await provider.create({}) + try { + await sbx.fs.write('/workspace/fake-claude.mjs', fake) + const adapter = claudeCodeText('haiku', { + claudeExecutable: 'node fake-claude.mjs', + streamPartials: false, + emitDiff: false, + }) + const chunks = await collect( + adapter.chatStream({ + model: 'haiku', + messages: [{ role: 'user', content: 'hi' }], + logger: noopLogger, + capabilities: capabilityContextWith(sbx), + }), + ) + expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(false) + expect(await sbx.fs.read('/workspace/auth-probe.txt')).toBe('set') + } finally { + if (previous === undefined) delete process.env.ANTHROPIC_API_KEY + else process.env.ANTHROPIC_API_KEY = previous + await sbx.destroy() + } + }) }) diff --git a/packages/ai-sandbox-docker/src/handle.ts b/packages/ai-sandbox-docker/src/handle.ts index 3eb5392540..b35f18852d 100644 --- a/packages/ai-sandbox-docker/src/handle.ts +++ b/packages/ai-sandbox-docker/src/handle.ts @@ -430,9 +430,15 @@ export class DockerHandle implements SandboxHandle { } private envArray(extra?: Record): Array { - return Object.entries({ ...this.envVars, ...extra }).map( - ([k, v]) => `${k}=${v}`, - ) + // Docker `exec` Env replaces the container env. Keep a PATH and HOME so + // CLIs still resolve and `~/.claude` has a home when secrets are the only + // other vars. + return Object.entries({ + PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + HOME: '/root', + ...this.envVars, + ...extra, + }).map(([k, v]) => `${k}=${v}`) } /** From e533f7c76a162ec5ef462ff85124d1748a741c4a Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 18:54:26 +0200 Subject: [PATCH 11/23] fix(ai-claude-code): do not use --bare (it ignores claude login) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--bare` skips stored OAuth credentials. Headless `-p` then prints "Not logged in · Please run /login" even when the host is logged in (claude-code#51047). Keep `--setting-sources user` so project settings do not block the run. On local-process, do not force ANTHROPIC_API_KEY over the host login. --- docs/adapters/claude-code.md | 4 ++-- docs/structured-outputs/harnesses.md | 2 +- .../src/routes/api.sandbox-repo-report.ts | 4 ++++ packages/ai-claude-code/src/adapters/text.ts | 21 ++++++++++--------- .../ai-claude-code/tests/text-adapter.test.ts | 2 +- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index 1f151dc06d..75e8f0edb3 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -172,9 +172,9 @@ const stream = chat({ Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` as inline JSON (the CLI rejects a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. -The adapter loads only user settings (`--setting-sources user`). A cloned repo's `.claude/settings.json` does not block headless `-p`. +The adapter loads only user settings (`--setting-sources user`). A cloned repo's `.claude/settings.json` does not block headless `-p`. The adapter does not pass `--bare`, because that flag ignores a host `claude login`. -Headless Claude needs an `ANTHROPIC_API_KEY` in the process env, or a host `claude login` when you use the local-process sandbox. The adapter copies the host API key into the sandbox process. A Docker container has no host login. +On local-process, Claude uses your host `claude login`. On Docker, pass `ANTHROPIC_API_KEY` in the process env. A container has no host login. ```ts import { chat } from "@tanstack/ai" diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index 6de1d6a1b8..26ee22326b 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -198,4 +198,4 @@ The React chat example includes a repo-report page. The page clones `TanStack/ai` into a sandbox, asks the agent to inspect it, and shows the validated report. -Claude Code does not need you to accept a trust dialog for that clone. The adapter loads only user settings, so the clone's `.claude/settings.json` does not block headless `-p`. +Claude Code does not need you to accept a trust dialog for that clone. The adapter loads only user settings, so the clone's `.claude/settings.json` does not block headless `-p`. On local-process, Claude uses your host `claude login`. diff --git a/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts b/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts index 8c146bb20e..0b9758e6b3 100644 --- a/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts +++ b/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts @@ -91,6 +91,10 @@ export async function repoReportPost(request: Request): Promise { provider: data.provider, repo: REPORT_REPO, threadId, + // Local Claude Code uses the host `claude login`. An API key in `.env` + // would override that login in `-p` mode. + useSubscription: + data.provider === 'local' && data.harness === 'claude-code', }) const stream = chat({ threadId, diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index a5668f57e9..5e1a52dbef 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -20,7 +20,6 @@ import { resolveApproval, resolveDurableRunId, resolveDurableThreadId, - resolveHarnessCwd, spawnNdjson, } from '@tanstack/ai-sandbox' import { buildPrompt } from '../messages/prompt' @@ -31,7 +30,7 @@ import { CLAUDE_JSON_SCHEMA_PLACEHOLDER, CLAUDE_RUNNER_SOURCE, } from './claude-run-source' -import { acceptClaudeTrustDialog } from './trust' + import type { ClaudePolicyFlags } from './policy-map' import type { BridgeEventChannel, @@ -201,14 +200,12 @@ export class ClaudeCodeTextAdapter< const modelOptions = options.modelOptions const exeParts = (config.claudeExecutable ?? 'claude').split(' ') - // Flags that skip project settings must come before `-p`. `-p` can take - // the next token as the prompt, so `claude -p --bare` treats --bare as - // the prompt and still loads `.claude/settings.json`. - // `--setting-sources user` skips project/local settings, so a cloned - // repo's allow-list does not trigger the trust dialog. + // `--setting-sources user` before `-p`. Do not pass `--bare`: that flag + // skips stored `claude login` credentials and prints + // "Not logged in · Please run /login" (claude-code#51047). + // `-p` can take the next token as the prompt, so these flags stay first. const args: Array = [ ...exeParts, - '--bare', '--setting-sources', 'user', '-p', @@ -355,7 +352,7 @@ export class ClaudeCodeTextAdapter< const sandbox = this.sandboxFrom(options) cleanupSandbox = sandbox const cwd = this.workdir(options) - await acceptClaudeTrustDialog(resolveHarnessCwd(sandbox, cwd)) + // Durability comes from `withSandbox(sandbox, { runs, durability })`, read // back off the capability bus. Absent it, everything below resolves to // exactly today's behavior (no journal option, no alignment, and a @@ -531,7 +528,11 @@ export class ClaudeCodeTextAdapter< env: { IS_SANDBOX: '1', CLAUDE_CODE_SANDBOXED: '1', - ...hostClaudeAuthEnv(), + // Docker has no host `claude login`. Local-process must not force + // ANTHROPIC_API_KEY: `-p` would use the key instead of the login. + ...(sandbox.provider === 'local-process' + ? {} + : hostClaudeAuthEnv()), ...localProcessHomeEnv(sandbox.provider), ...this.adapterConfig.env, }, diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index cc03f270f8..3e2d659042 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -200,7 +200,7 @@ describe('claude-code in-sandbox adapter', () => { ) const argv = await sbx.fs.read('/workspace/argv.txt') - expect(argv).toContain('--bare') + expect(argv).not.toContain('--bare') expect(argv).toContain('--setting-sources') expect(argv).toContain('user') expect(argv).toContain('--json-schema') From f7dff32d69b6cf0b400a78082aa257673c56a9a1 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 19:01:56 +0200 Subject: [PATCH 12/23] fix(ai-claude-code): harvest StructuredOutput tool into chat.final Claude Code --json-schema forces a fake StructuredOutput tool. The UI showed "tool StructuredOutput (complete)" and never got structured-output.complete, so the report card stayed empty. Capture that tool input and emit the same complete event as result.structured_output. --- docs/adapters/claude-code.md | 2 +- .../ai-claude-code/src/stream/translate.ts | 66 +++++++++++++------ .../ai-claude-code/tests/translate.test.ts | 66 +++++++++++++++++++ 3 files changed, 112 insertions(+), 22 deletions(-) diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index 75e8f0edb3..367ba61246 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -170,7 +170,7 @@ const stream = chat({ ## Structured Output -Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` as inline JSON (the CLI rejects a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`. +Pass `outputSchema` on `chat()`. Claude Code runs one harness turn, uses its native tools, and returns a typed object. The schema JSON is passed to `--json-schema` as inline JSON (the CLI rejects a file path). Tool activity and prose stream as usual. The object arrives as `structured-output.complete`, including when Claude delivers it through its built-in `StructuredOutput` tool. The adapter loads only user settings (`--setting-sources user`). A cloned repo's `.claude/settings.json` does not block headless `-p`. The adapter does not pass `--bare`, because that flag ignores a host `claude login`. diff --git a/packages/ai-claude-code/src/stream/translate.ts b/packages/ai-claude-code/src/stream/translate.ts index d4313f0c98..393d033af4 100644 --- a/packages/ai-claude-code/src/stream/translate.ts +++ b/packages/ai-claude-code/src/stream/translate.ts @@ -22,6 +22,13 @@ export const BRIDGED_MCP_SERVER_NAME = 'tanstack' const BRIDGED_MCP_PREFIX = `mcp__${BRIDGED_MCP_SERVER_NAME}__` +/** + * Claude Code `--json-schema` injects a fake tool named StructuredOutput. + * The model "calls" it with the schema JSON. The result message may omit + * `structured_output`; harvest the tool input in that case. + */ +export const SYNTHETIC_STRUCTURED_OUTPUT_TOOL = 'StructuredOutput' + /** Claude Code-specific usage details attached to RUN_FINISHED usage. */ export type ClaudeCodeProviderUsageDetails = { /** Total cost of the harness run in USD, as reported by Claude Code. */ @@ -115,6 +122,8 @@ export async function* translateSdkStream( let runStarted = false /** Tool calls started but with no result yet. */ const unresolvedToolCalls = new Set() + const syntheticOutputToolIds = new Set() + let capturedStructuredOutput: unknown /** Anthropic message ids whose text/thinking already streamed via partials. */ const streamedMessageIds = new Set() @@ -185,12 +194,39 @@ export async function* translateSdkStream( partialReasoningId = null } + function* emitStructuredOutput(object: unknown): Generator { + const raw = JSON.stringify(object) + const messageId = genId() + yield structuredOutputStartChunk({ + messageId, + model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId, + model, + threadId, + runId, + object, + raw, + }) + } + function* emitToolUse(block: { id: string name: string input: unknown }): Generator { const toolCallName = stripMcpPrefix(block.name) + if ( + ctx.expectStructuredOutput === true && + toolCallName === SYNTHETIC_STRUCTURED_OUTPUT_TOOL + ) { + capturedStructuredOutput = block.input + syntheticOutputToolIds.add(block.id) + return + } const args = JSON.stringify(block.input ?? {}) yield { type: EventType.TOOL_CALL_START, @@ -307,6 +343,10 @@ export async function* translateSdkStream( content?: SdkToolResultContent is_error?: boolean } + if (syntheticOutputToolIds.has(toolResult.tool_use_id)) { + syntheticOutputToolIds.delete(toolResult.tool_use_id) + continue + } unresolvedToolCalls.delete(toolResult.tool_use_id) yield { type: EventType.TOOL_CALL_RESULT, @@ -326,27 +366,11 @@ export async function* translateSdkStream( yield* synthesizeUnresolvedResults() const usage = buildUsage(message.usage, message.total_cost_usd) - if ( - ctx.expectStructuredOutput === true && - message.structured_output !== undefined - ) { - const object = message.structured_output - const raw = JSON.stringify(object) - const messageId = genId() - yield structuredOutputStartChunk({ - messageId, - model, - threadId, - runId, - }) - yield structuredOutputCompleteChunk({ - messageId, - model, - threadId, - runId, - object, - raw, - }) + if (ctx.expectStructuredOutput === true) { + const object = message.structured_output ?? capturedStructuredOutput + if (object !== undefined) { + yield* emitStructuredOutput(object) + } } if (message.subtype === 'success') { yield { diff --git a/packages/ai-claude-code/tests/translate.test.ts b/packages/ai-claude-code/tests/translate.test.ts index ed85706254..643edf5685 100644 --- a/packages/ai-claude-code/tests/translate.test.ts +++ b/packages/ai-claude-code/tests/translate.test.ts @@ -515,6 +515,72 @@ describe('translateSdkStream', () => { expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) }) + it('harvests StructuredOutput tool input when result.structured_output is missing', async () => { + const report = { + name: 'TanStack AI', + oneLiner: 'Type-safe AI SDK', + } + const chunks = await collect( + [ + init, + assistantText('I have enough to compile the report.'), + { + type: 'assistant', + message: { + id: 'msg-so', + content: [ + { + type: 'tool_use', + id: 'toolu_so', + name: 'StructuredOutput', + input: report, + }, + ], + }, + parent_tool_use_id: null, + }, + { + type: 'user', + message: { + role: 'user', + content: [ + { + type: 'tool_result', + tool_use_id: 'toolu_so', + content: 'ok', + }, + ], + }, + parent_tool_use_id: null, + }, + resultSuccess, + ], + { ...makeContext(), expectStructuredOutput: true }, + ) + + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual( + expect.objectContaining({ + object: report, + raw: JSON.stringify(report), + }), + ) + } + expect( + chunks.some( + (c) => + c.type === 'TOOL_CALL_START' && + 'toolCallName' in c && + c.toolCallName === 'StructuredOutput', + ), + ).toBe(false) + expect(chunks.some((c) => c.type === 'TOOL_CALL_RESULT')).toBe(false) + }) + it('does not emit structured-output events when the flag is off', async () => { const resultWithObject: AgentSdkMessage = { type: 'result', From e9b62aedb8ea7002530037c6683dc165675f40a7 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 19:19:10 +0200 Subject: [PATCH 13/23] fix(ai-claude-code): harvest streamed StructuredOutput JSON Claude streams StructuredOutput as input_json_delta, then may send an empty tool_use snapshot. That empty input wiped the captured object, so the report card never appeared. Keep the last useful object, parse streamed JSON, and fall back to JSON in the assistant text. --- packages/ai-claude-code/src/adapters/text.ts | 12 +- .../ai-claude-code/src/stream/sdk-types.ts | 14 ++- .../ai-claude-code/src/stream/translate.ts | 84 ++++++++++++- .../ai-claude-code/tests/translate.test.ts | 118 ++++++++++++++++++ 4 files changed, 221 insertions(+), 7 deletions(-) diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 5e1a52dbef..81deaf3bfb 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -1,5 +1,8 @@ import { EventType, normalizeSystemPrompts } from '@tanstack/ai' -import { toRunErrorRawEvent } from '@tanstack/ai/adapter-internals' +import { + appendOutputSchemaInstruction, + toRunErrorRawEvent, +} from '@tanstack/ai/adapter-internals' import { BaseTextAdapter } from '@tanstack/ai/adapters' import { SandboxCapability, @@ -435,10 +438,15 @@ export class ClaudeCodeTextAdapter< }) } - const { prompt, resume } = buildPrompt( + const built = buildPrompt( options.messages, options.modelOptions?.sessionId, ) + const resume = built.resume + const prompt = + options.outputSchema !== undefined + ? appendOutputSchemaInstruction(built.prompt, options.outputSchema) + : built.prompt // Both files below name themselves after `runId`, and durability makes // `runId` CALLER-chosen. Raw, a `/` in it would silently turn each basename // into a nested path (writing outside the intended directory, or failing on diff --git a/packages/ai-claude-code/src/stream/sdk-types.ts b/packages/ai-claude-code/src/stream/sdk-types.ts index a4b40be743..ab1ffcfc5c 100644 --- a/packages/ai-claude-code/src/stream/sdk-types.ts +++ b/packages/ai-claude-code/src/stream/sdk-types.ts @@ -60,12 +60,22 @@ export type SdkRawStreamEvent = | { type: 'content_block_start' index: number - content_block: { type: string } + content_block: { + type: string + id?: string + name?: string + input?: unknown + } } | { type: 'content_block_delta' index: number - delta: { type: string; text?: string; thinking?: string } + delta: { + type: string + text?: string + thinking?: string + partial_json?: string + } } | { type: 'content_block_stop'; index: number } | { type: 'message_delta' } diff --git a/packages/ai-claude-code/src/stream/translate.ts b/packages/ai-claude-code/src/stream/translate.ts index 393d033af4..60b2ef866e 100644 --- a/packages/ai-claude-code/src/stream/translate.ts +++ b/packages/ai-claude-code/src/stream/translate.ts @@ -1,5 +1,6 @@ import { EventType, buildBaseUsage } from '@tanstack/ai' import { + parseJsonFromAssistantText, structuredOutputCompleteChunk, structuredOutputStartChunk, } from '@tanstack/ai/adapter-internals' @@ -60,6 +61,22 @@ export function stripMcpPrefix(name: string): string { : name } +function isUsefulStructuredObject(value: unknown): boolean { + return ( + value !== null && + typeof value === 'object' && + !Array.isArray(value) && + Object.keys(value).length > 0 + ) +} + +function rememberStructuredOutput( + current: unknown, + next: unknown, +): unknown { + return isUsefulStructuredObject(next) ? next : current +} + function stringifyToolResultContent( content: SdkToolResultContent | undefined, ): string { @@ -124,6 +141,9 @@ export async function* translateSdkStream( const unresolvedToolCalls = new Set() const syntheticOutputToolIds = new Set() let capturedStructuredOutput: unknown + let assistantTextForHarvest = '' + let partialStructuredJson = '' + let partialIsStructuredOutput = false /** Anthropic message ids whose text/thinking already streamed via partials. */ const streamedMessageIds = new Set() @@ -223,7 +243,10 @@ export async function* translateSdkStream( ctx.expectStructuredOutput === true && toolCallName === SYNTHETIC_STRUCTURED_OUTPUT_TOOL ) { - capturedStructuredOutput = block.input + capturedStructuredOutput = rememberStructuredOutput( + capturedStructuredOutput, + block.input, + ) syntheticOutputToolIds.add(block.id) return } @@ -268,6 +291,7 @@ export async function* translateSdkStream( if (alreadyStreamed) continue const messageId = message.message.id ?? genId() const text = (block as { text: string }).text + if (!alreadyStreamed) assistantTextForHarvest += text yield { type: EventType.TEXT_MESSAGE_START, messageId, @@ -367,8 +391,25 @@ export async function* translateSdkStream( const usage = buildUsage(message.usage, message.total_cost_usd) if (ctx.expectStructuredOutput === true) { - const object = message.structured_output ?? capturedStructuredOutput - if (object !== undefined) { + const fromResult = isUsefulStructuredObject(message.structured_output) + ? message.structured_output + : undefined + const fromTool = isUsefulStructuredObject(capturedStructuredOutput) + ? capturedStructuredOutput + : undefined + let fromText: unknown + if (fromResult === undefined && fromTool === undefined) { + const raw = assistantTextForHarvest || message.result || '' + if (raw.trim() !== '') { + try { + fromText = parseJsonFromAssistantText(raw) + } catch { + fromText = undefined + } + } + } + const object = fromResult ?? fromTool ?? fromText + if (isUsefulStructuredObject(object)) { yield* emitStructuredOutput(object) } } @@ -417,6 +458,24 @@ export async function* translateSdkStream( streamedMessageIds.add(partialMessageId) } else if (event.type === 'content_block_start') { partialBlockType = event.content_block.type + const startedBlock = event.content_block + partialIsStructuredOutput = + ctx.expectStructuredOutput === true && + startedBlock.type === 'tool_use' && + 'name' in startedBlock && + startedBlock.name === SYNTHETIC_STRUCTURED_OUTPUT_TOOL + if (partialIsStructuredOutput) { + partialStructuredJson = '' + if ('id' in startedBlock && typeof startedBlock.id === 'string') { + syntheticOutputToolIds.add(startedBlock.id) + } + if ('input' in startedBlock) { + capturedStructuredOutput = rememberStructuredOutput( + capturedStructuredOutput, + startedBlock.input, + ) + } + } if (partialBlockType === 'text') { partialTextMessageId = partialMessageId ?? genId() partialTextContent = '' @@ -454,6 +513,7 @@ export async function* translateSdkStream( typeof event.delta.text === 'string' ) { partialTextContent += event.delta.text + assistantTextForHarvest += event.delta.text yield { type: EventType.TEXT_MESSAGE_CONTENT, messageId: partialTextMessageId, @@ -462,6 +522,12 @@ export async function* translateSdkStream( delta: event.delta.text, content: partialTextContent, } + } else if ( + event.delta.type === 'input_json_delta' && + partialIsStructuredOutput && + typeof event.delta.partial_json === 'string' + ) { + partialStructuredJson += event.delta.partial_json } else if ( event.delta.type === 'thinking_delta' && partialReasoningId && @@ -476,12 +542,24 @@ export async function* translateSdkStream( } } } else if (event.type === 'content_block_stop') { + if (partialIsStructuredOutput && partialStructuredJson !== '') { + try { + capturedStructuredOutput = rememberStructuredOutput( + capturedStructuredOutput, + JSON.parse(partialStructuredJson), + ) + } catch { + // Incomplete JSON; the complete assistant tool_use may still arrive. + } + } if (partialBlockType === 'text') { yield* closePartialText() } else if (partialBlockType === 'thinking') { yield* closePartialReasoning() } partialBlockType = null + partialIsStructuredOutput = false + partialStructuredJson = '' } } diff --git a/packages/ai-claude-code/tests/translate.test.ts b/packages/ai-claude-code/tests/translate.test.ts index 643edf5685..4f4a759034 100644 --- a/packages/ai-claude-code/tests/translate.test.ts +++ b/packages/ai-claude-code/tests/translate.test.ts @@ -581,6 +581,124 @@ describe('translateSdkStream', () => { expect(chunks.some((c) => c.type === 'TOOL_CALL_RESULT')).toBe(false) }) + it('does not let an empty StructuredOutput tool wipe a captured object', async () => { + const report = { name: 'TanStack AI', oneLiner: 'SDK' } + const chunks = await collect( + [ + init, + { + type: 'assistant', + message: { + id: 'msg-so-1', + content: [ + { + type: 'tool_use', + id: 'toolu_so_full', + name: 'StructuredOutput', + input: report, + }, + ], + }, + parent_tool_use_id: null, + }, + { + type: 'assistant', + message: { + id: 'msg-so-2', + content: [ + { + type: 'tool_use', + id: 'toolu_so_empty', + name: 'StructuredOutput', + input: {}, + }, + ], + }, + parent_tool_use_id: null, + }, + resultSuccess, + ], + { ...makeContext(), expectStructuredOutput: true }, + ) + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete?.type === 'CUSTOM' && complete.value).toEqual( + expect.objectContaining({ object: report }), + ) + }) + + it('harvests StructuredOutput from streamed input_json_delta', async () => { + const report = { name: 'TanStack AI', oneLiner: 'SDK' } + const chunks = await collect( + [ + init, + { + type: 'stream_event', + event: { type: 'message_start', message: { id: 'msg-p' } }, + parent_tool_use_id: null, + }, + { + type: 'stream_event', + event: { + type: 'content_block_start', + index: 0, + content_block: { + type: 'tool_use', + id: 'toolu_stream', + name: 'StructuredOutput', + input: {}, + }, + }, + parent_tool_use_id: null, + }, + { + type: 'stream_event', + event: { + type: 'content_block_delta', + index: 0, + delta: { + type: 'input_json_delta', + partial_json: JSON.stringify(report), + }, + }, + parent_tool_use_id: null, + }, + { + type: 'stream_event', + event: { type: 'content_block_stop', index: 0 }, + parent_tool_use_id: null, + }, + resultSuccess, + ], + { ...makeContext(), expectStructuredOutput: true }, + ) + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete?.type === 'CUSTOM' && complete.value).toEqual( + expect.objectContaining({ object: report }), + ) + }) + + it('parses JSON from assistant text when the StructuredOutput tool is missing', async () => { + const report = { name: 'TanStack AI', oneLiner: 'SDK' } + const chunks = await collect( + [ + init, + assistantText(JSON.stringify(report)), + resultSuccess, + ], + { ...makeContext(), expectStructuredOutput: true }, + ) + const complete = chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) + expect(complete?.type === 'CUSTOM' && complete.value).toEqual( + expect.objectContaining({ object: report }), + ) + }) + it('does not emit structured-output events when the flag is off', async () => { const resultWithObject: AgentSdkMessage = { type: 'result', From b90c885197a667b53d5785d1c021f8acf9f14c92 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 19:39:46 +0200 Subject: [PATCH 14/23] fix(ai): attach late structured-output.complete to the open assistant Harness adapters emit structured-output.start/complete with a fresh messageId after tool calls and prose. The client kept the existing assistant active, then looked up the new id and dropped the object. useChat().final stayed empty and the report card never rendered. Resolve start/complete against the open assistant message instead. --- .../src/activities/chat/stream/processor.ts | 9 ++-- packages/ai/tests/stream-processor.test.ts | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/ai/src/activities/chat/stream/processor.ts b/packages/ai/src/activities/chat/stream/processor.ts index 1994a5b37c..aa67f808b0 100644 --- a/packages/ai/src/activities/chat/stream/processor.ts +++ b/packages/ai/src/activities/chat/stream/processor.ts @@ -1854,9 +1854,10 @@ export class StreamProcessor { if (chunk.name === 'structured-output.start' && chunk.value) { const v = chunk.value as { messageId?: string } - const targetId = v.messageId ?? messageId + const { messageId: targetId } = this.ensureAssistantMessage( + v.messageId ?? messageId ?? undefined, + ) if (targetId) { - this.ensureAssistantMessage(targetId) this.structuredMessageIds.add(targetId) this.structuredOutputUpdateBatches.delete(targetId) this.events.onStructuredOutputChange?.({ @@ -1876,7 +1877,9 @@ export class StreamProcessor { reasoning?: string messageId?: string } - const targetId = v.messageId ?? messageId + const { messageId: targetId } = this.ensureAssistantMessage( + v.messageId ?? messageId ?? undefined, + ) if (targetId) { this.flushStructuredOutputUpdate(targetId) this.messages = completeStructuredOutputPart( diff --git a/packages/ai/tests/stream-processor.test.ts b/packages/ai/tests/stream-processor.test.ts index 72b825771a..714ea4afc9 100644 --- a/packages/ai/tests/stream-processor.test.ts +++ b/packages/ai/tests/stream-processor.test.ts @@ -4428,6 +4428,51 @@ describe('StreamProcessor', () => { expect((sop as any).raw).toBe('{"name":"Alice"}') }) + it('attaches a late structured-output.complete to the open assistant when the event uses a new messageId', () => { + const processor = new StreamProcessor() + const report = { + name: 'TanStack AI', + oneLiner: 'Type-safe AI SDK', + } + + processor.processChunk(ev.runStarted()) + processor.processChunk(ev.toolStart('toolu_1', 'Read')) + processor.processChunk(ev.toolEnd('toolu_1', 'Read')) + processor.processChunk(ev.textStart('msg-1')) + processor.processChunk( + ev.textContent('I have enough to produce the report.', 'msg-1'), + ) + processor.processChunk(ev.textEnd('msg-1')) + processor.processChunk( + chunk(EventType.CUSTOM, { + name: 'structured-output.start', + value: { messageId: 'so-fresh-id' }, + }), + ) + processor.processChunk( + chunk(EventType.CUSTOM, { + name: 'structured-output.complete', + value: { + object: report, + raw: JSON.stringify(report), + messageId: 'so-fresh-id', + }, + }), + ) + processor.processChunk(ev.runFinished('stop')) + + const assistants = processor + .getMessages() + .filter((m) => m.role === 'assistant') + expect(assistants).toHaveLength(1) + const sop = assistants[0]!.parts.find( + (p) => p.type === 'structured-output', + ) + expect(sop).toBeDefined() + expect((sop as { status: string }).status).toBe('complete') + expect((sop as { data: unknown }).data).toEqual(report) + }) + it('progressively populates partial as JSON deltas arrive', () => { const processor = new StreamProcessor() From 46fc9b8e048f0d1aa886d47e0a9374f629e5ae2d Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 17 Aug 2026 20:21:18 +0200 Subject: [PATCH 15/23] fix: address review comments and sync lockfile with main Parse JSON even when later prose has a brace. Validate report card fields. Label the example pickers. Add client useChat snippets. Drop the unused ~/.claude.json writer. Set IS_SANDBOX only on isolated sandboxes. Refresh the lockfile after merging main. --- .gitignore | 1 + docs/adapters/claude-code.md | 23 +- docs/adapters/codex.md | 23 +- docs/adapters/grok-build.md | 23 +- docs/adapters/opencode.md | 23 +- docs/config.json | 8 +- docs/structured-outputs/harnesses.md | 16 +- docs/structured-outputs/streaming.md | 2 +- .../src/repo-report-schema.test.ts | 32 + .../ts-react-chat/src/repo-report-schema.ts | 30 + .../ts-react-chat/src/routes/repo-report.tsx | 134 +- examples/ts-react-chat/src/sandbox-triage.ts | 5 +- knip.json | 1 + packages/ai-claude-code/src/adapters/text.ts | 24 +- packages/ai-claude-code/src/adapters/trust.ts | 57 - .../ai-claude-code/src/stream/translate.ts | 5 +- .../ai-claude-code/tests/text-adapter.test.ts | 8 +- .../ai-claude-code/tests/translate.test.ts | 6 +- packages/ai-claude-code/tests/trust.test.ts | 24 - packages/ai-codex/src/adapters/text.ts | 2 +- .../src/utilities/structured-output-text.ts | 35 +- .../ai/tests/structured-output-text.test.ts | 6 + pnpm-lock.yaml | 2397 +++++++++-------- 23 files changed, 1538 insertions(+), 1347 deletions(-) create mode 100644 examples/ts-react-chat/src/repo-report-schema.test.ts delete mode 100644 packages/ai-claude-code/src/adapters/trust.ts delete mode 100644 packages/ai-claude-code/tests/trust.test.ts diff --git a/.gitignore b/.gitignore index a1b0907740..a65d10233d 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,7 @@ docs/superpowers # Only .claude.settings.json should be committed .claude/settings.local.json .claude/worktrees/* +/worktrees/ .claude/scheduled_tasks.lock solo.yml diff --git a/docs/adapters/claude-code.md b/docs/adapters/claude-code.md index 367ba61246..57590e1fe7 100644 --- a/docs/adapters/claude-code.md +++ b/docs/adapters/claude-code.md @@ -203,7 +203,28 @@ const report = await chat({ report.summary ``` -On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. +On the client, pass the same schema to `useChat` and read `final`. `partial` stays empty until the end. + +```tsx +import { fetchServerSentEvents, useChat } from "@tanstack/ai-react" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +function ReportView() { + const { final, isLoading } = useChat({ + connection: fetchServerSentEvents("/api/repo-report"), + outputSchema: Report, + }) + + if (isLoading) return

The agent is inspecting the repo.

+ if (!final) return null + return

{final.summary}

+} +``` If you only need to extract JSON from a prompt and do not need a sandbox, use `@tanstack/ai-anthropic`. That path is faster. diff --git a/docs/adapters/codex.md b/docs/adapters/codex.md index da15db97eb..ed1ef8e63c 100644 --- a/docs/adapters/codex.md +++ b/docs/adapters/codex.md @@ -199,7 +199,28 @@ const report = await chat({ report.summary ``` -On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. +On the client, pass the same schema to `useChat` and read `final`. `partial` stays empty until the end. + +```tsx +import { fetchServerSentEvents, useChat } from "@tanstack/ai-react" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +function ReportView() { + const { final, isLoading } = useChat({ + connection: fetchServerSentEvents("/api/repo-report"), + outputSchema: Report, + }) + + if (isLoading) return

The agent is inspecting the repo.

+ if (!final) return null + return

{final.summary}

+} +``` If you only need to extract JSON from a prompt and do not need a sandbox, use `@tanstack/ai-openai`. That path is faster. diff --git a/docs/adapters/grok-build.md b/docs/adapters/grok-build.md index fbbae01fff..faf826d3f1 100644 --- a/docs/adapters/grok-build.md +++ b/docs/adapters/grok-build.md @@ -218,7 +218,28 @@ report.summary This path parses JSON from the last assistant message. If extract-only is the job, use `@tanstack/ai-grok`. -On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. +On the client, pass the same schema to `useChat` and read `final`. `partial` stays empty until the end. + +```tsx +import { fetchServerSentEvents, useChat } from "@tanstack/ai-react" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +function ReportView() { + const { final, isLoading } = useChat({ + connection: fetchServerSentEvents("/api/repo-report"), + outputSchema: Report, + }) + + if (isLoading) return

The agent is inspecting the repo.

+ if (!final) return null + return

{final.summary}

+} +``` Full walkthrough, including the client: [Harness Agents](../structured-outputs/harnesses). diff --git a/docs/adapters/opencode.md b/docs/adapters/opencode.md index f4744d7a60..a6915d752e 100644 --- a/docs/adapters/opencode.md +++ b/docs/adapters/opencode.md @@ -206,7 +206,28 @@ report.summary This path parses JSON from the last assistant message. If extract-only is the job, use a model adapter such as `@tanstack/ai-openai`. -On the client, `useChat({ outputSchema }).final` works the same as HTTP adapters. `partial` stays empty until the end. +On the client, pass the same schema to `useChat` and read `final`. `partial` stays empty until the end. + +```tsx +import { fetchServerSentEvents, useChat } from "@tanstack/ai-react" +import { z } from "zod" + +const Report = z.object({ + summary: z.string(), + filesChanged: z.array(z.string()), +}) + +function ReportView() { + const { final, isLoading } = useChat({ + connection: fetchServerSentEvents("/api/repo-report"), + outputSchema: Report, + }) + + if (isLoading) return

The agent is inspecting the repo.

+ if (!final) return null + return

{final.summary}

+} +``` Full walkthrough, including the client: [Harness Agents](../structured-outputs/harnesses). diff --git a/docs/config.json b/docs/config.json index 1692739558..740aa5b482 100644 --- a/docs/config.json +++ b/docs/config.json @@ -348,7 +348,7 @@ "label": "Streaming UIs", "to": "structured-outputs/streaming", "addedAt": "2026-05-19", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-17" }, { "label": "Multi-Turn Chat", @@ -879,19 +879,19 @@ "label": "Codex", "to": "adapters/codex", "addedAt": "2026-06-12", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-17" }, { "label": "OpenCode", "to": "adapters/opencode", "addedAt": "2026-06-12", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-17" }, { "label": "Grok Build", "to": "adapters/grok-build", "addedAt": "2026-06-29", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-17" }, { "label": "ACP-Compatible", diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index 26ee22326b..8c8e6f7e65 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -30,7 +30,7 @@ If you only extract JSON from a prompt and you do not need a sandbox, use [One-S ## Define the schema -```typescript +```typescript group=harness-output import { z } from "zod"; export const ReportSchema = z.object({ @@ -53,7 +53,7 @@ The return type follows from the schema. You do not need a cast. The harness needs a sandbox. Pass `withSandbox(...)`. If the client reads the stream, pass `stream: true`. Without `stream: true`, `chat()` returns a `Promise`, not SSE. -```typescript +```typescript group=harness-output import { chat, toServerSentEventsResponse } from "@tanstack/ai"; import { claudeCodeText } from "@tanstack/ai-claude-code"; import { @@ -63,7 +63,6 @@ import { withSandbox, } from "@tanstack/ai-sandbox"; import { dockerSandbox } from "@tanstack/ai-sandbox-docker"; -import { ReportSchema } from "./report-schema"; const sandbox = defineSandbox({ id: "repo-report", @@ -107,9 +106,8 @@ The typed object arrives as a `structured-output.complete` event. Tool activity Pass the same schema to `useChat`. Read the object from `final`. -```tsx +```tsx group=harness-output import { useChat, fetchServerSentEvents } from "@tanstack/ai-react"; -import { ReportSchema } from "./report-schema"; function RepoReport() { const { sendMessage, isLoading, final } = useChat({ @@ -168,13 +166,7 @@ If you need approval gates or client tools, use [With Tools](./with-tools) with If you do not stream to a browser, omit `stream: true`. The promise resolves with the typed object. -```typescript -import { chat } from "@tanstack/ai"; -import { claudeCodeText } from "@tanstack/ai-claude-code"; -import { withSandbox } from "@tanstack/ai-sandbox"; -import { ReportSchema } from "./report-schema"; -import { sandbox } from "./sandbox"; - +```typescript group=harness-output const report = await chat({ adapter: claudeCodeText("claude-opus-4-8"), messages: [{ role: "user", content: "What is this repository about?" }], diff --git a/docs/structured-outputs/streaming.md b/docs/structured-outputs/streaming.md index 54ad8a132c..d562caab5b 100644 --- a/docs/structured-outputs/streaming.md +++ b/docs/structured-outputs/streaming.md @@ -93,7 +93,7 @@ What the hook does for you: - **`partial`** is `DeepPartial>` — every property optional, every nested array element optional. Updated from `TEXT_MESSAGE_CONTENT` deltas via the runtime's partial-JSON parser. The hook derives it from the latest assistant message's `structured-output` part (see [Multi-Turn Chat](./multi-turn) for why that distinction matters), so it reads `{}` between `sendMessage()` and the first chunk without any extra reset state. - **`final`** is `z.infer | null` — the validated terminal payload from the `structured-output.complete` event. `null` until the run completes successfully. - **`outputSchema`** is used purely for client-side TypeScript inference. Validation still runs on the server against the schema you pass to `chat({ outputSchema })` on the server route — the client doesn't re-validate. -- The same shape works for **non-streaming adapters too**. If an adapter (Anthropic, Gemini, Ollama) returns a single `structured-output.complete` event with no incremental deltas, `partial` stays `{}` and `final` populates when the event arrives. Same consumer code. Harness adapters work this way too: tool activity streams first, then `final` snaps. See [Harness Agents](./harnesses). +- The same shape works for **non-streaming adapters too**. If an adapter (Anthropic, Gemini, Ollama) returns a single `structured-output.complete` event with no incremental deltas, `partial` stays `{}` and `final` populates when the event arrives. Same consumer code. Claude Code and Codex emit `structured-output.complete` from the harness event. OpenCode and Grok Build parse the last assistant text at the end. In both cases `partial` stays empty until `final` is set. See [Harness Agents](./harnesses). `outputSchema` is optional: omit it and `useChat` returns its standard shape without `partial` / `final`. diff --git a/examples/ts-react-chat/src/repo-report-schema.test.ts b/examples/ts-react-chat/src/repo-report-schema.test.ts new file mode 100644 index 0000000000..5156ef7641 --- /dev/null +++ b/examples/ts-react-chat/src/repo-report-schema.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from 'vitest' +import { looksLikeReport } from './repo-report-schema' + +describe('looksLikeReport', () => { + it('accepts a complete report', () => { + expect( + looksLikeReport({ + name: 'TanStack AI', + oneLiner: 'A type-safe AI SDK.', + audience: 'TypeScript developers', + mainPackages: [{ name: '@tanstack/ai', role: 'core' }], + howToRun: 'pnpm install', + }), + ).toBe(true) + }) + + it('accepts a partial report while fields stream in', () => { + expect(looksLikeReport({ name: 'TanStack AI' })).toBe(true) + }) + + it('rejects a string in mainPackages', () => { + expect(looksLikeReport({ mainPackages: 'invalid' })).toBe(false) + }) + + it('rejects a non-string name', () => { + expect(looksLikeReport({ name: {} })).toBe(false) + }) + + it('rejects an empty object', () => { + expect(looksLikeReport({})).toBe(false) + }) +}) diff --git a/examples/ts-react-chat/src/repo-report-schema.ts b/examples/ts-react-chat/src/repo-report-schema.ts index 510ba8aece..9d54157da0 100644 --- a/examples/ts-react-chat/src/repo-report-schema.ts +++ b/examples/ts-react-chat/src/repo-report-schema.ts @@ -14,3 +14,33 @@ export const RepoReportSchema = z.object({ }) export type RepoReport = z.infer + +const RepoReportCardSchema = z + .object({ + name: z.string().optional(), + oneLiner: z.string().optional(), + audience: z.string().optional(), + howToRun: z.string().optional(), + mainPackages: z + .array( + z.object({ + name: z.string().optional(), + role: z.string().optional(), + }), + ) + .optional(), + }) + .refine( + (value) => + value.name !== undefined || + value.oneLiner !== undefined || + value.audience !== undefined || + value.howToRun !== undefined || + value.mainPackages !== undefined, + ) + +export type RepoReportCard = z.infer + +export function looksLikeReport(value: unknown): value is RepoReportCard { + return RepoReportCardSchema.safeParse(value).success +} diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index 5b7db501ad..cfa57591c5 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -12,8 +12,8 @@ import { REPORT_PROVIDERS, REPORT_REPO, } from '../repo-report-options' -import { RepoReportSchema } from '../repo-report-schema' -import type { RepoReport } from '../repo-report-schema' +import { looksLikeReport, RepoReportSchema } from '../repo-report-schema' +import type { RepoReportCard } from '../repo-report-schema' import type { ReportAgent, ReportHarness, @@ -25,23 +25,9 @@ export const Route = createFileRoute('/repo-report')({ component: RepoReportPage, }) -function looksLikeReport(value: unknown): value is Partial { - if (value === null || typeof value !== 'object' || Array.isArray(value)) { - return false - } - const record = value as Record - return ( - 'name' in record || - 'oneLiner' in record || - 'audience' in record || - 'mainPackages' in record || - 'howToRun' in record - ) -} - function reportFromMessages( messages: Array, -): Partial | undefined { +): RepoReportCard | undefined { for (const message of [...messages].reverse()) { for (const part of [...message.parts].reverse()) { if (part.type === 'structured-output') { @@ -76,7 +62,7 @@ function isCompleteReportJson(content: string): boolean { } } -function ReportCard({ report }: { report: Partial }) { +function ReportCard({ report }: { report: RepoReportCard }) { const packages = report.mainPackages ?? [] return (
@@ -158,54 +144,63 @@ function RepoReportPage() {
- - - + + + {REPORT_AGENTS[agent].hint} @@ -289,12 +284,7 @@ function RepoReportPage() { if (part.type === 'structured-output') { const data = part.data ?? part.partial if (!looksLikeReport(data)) return null - return ( - - ) + return } return null })} diff --git a/examples/ts-react-chat/src/sandbox-triage.ts b/examples/ts-react-chat/src/sandbox-triage.ts index 2e7230cf9a..8ab0e09272 100644 --- a/examples/ts-react-chat/src/sandbox-triage.ts +++ b/examples/ts-react-chat/src/sandbox-triage.ts @@ -111,10 +111,13 @@ function npmGlobalCli(spec: string, verify: string): string { export const HARNESSES: Record = { 'claude-code': { label: 'Claude Code', + // Headless `-p` cannot answer permission prompts. Isolated sandboxes and + // this trusted local demo both need bypassPermissions, same as Codex + // `danger-full-access`. Do not set CLAUDE_CODE_SANDBOXED here: that marker + // is only for a real isolation boundary, which the adapter sets itself. makeAdapter: () => claudeCodeText('sonnet', { permissionMode: 'bypassPermissions', - env: { CLAUDE_CODE_SANDBOXED: '1' }, }), installCommand: npmGlobalCli( '@anthropic-ai/claude-code', diff --git a/knip.json b/knip.json index 98ba9561f6..e6abef78b5 100644 --- a/knip.json +++ b/knip.json @@ -17,6 +17,7 @@ "**/*.test-d.ts", "packages/ai-code-mode-snippets/test-cli/**", ".claude/worktrees/**", + "worktrees/**", "packages/ai-openai/live-tests/**", "packages/ai-openai/src/**/*.test.ts", "packages/ai-openai/src/audio/audio-provider-options.ts", diff --git a/packages/ai-claude-code/src/adapters/text.ts b/packages/ai-claude-code/src/adapters/text.ts index 81deaf3bfb..efae39dc5a 100644 --- a/packages/ai-claude-code/src/adapters/text.ts +++ b/packages/ai-claude-code/src/adapters/text.ts @@ -182,7 +182,6 @@ export class ClaudeCodeTextAdapter< ) } - /** Build the `claude` command line (prompt goes via stdin, not argv). */ supportsCombinedToolsAndSchema(): boolean { return true } @@ -191,6 +190,7 @@ export class ClaudeCodeTextAdapter< return 'event' } + /** Build the `claude` command line (prompt goes via stdin, not argv). */ private buildArgv( options: TextOptions, resume: string | undefined, @@ -527,20 +527,20 @@ export class ClaudeCodeTextAdapter< const rawEvents = spawnNdjson(sandbox, runCommand, { cwd, ...(stdinInput !== undefined ? { input: stdinInput } : {}), - // claude maps `bypassPermissions` to `--dangerously-skip-permissions`, - // which it refuses to run as root. Sandbox containers routinely run as - // root (Docker / Cloudflare), so set `IS_SANDBOX=1` — claude's - // documented escape hatch for skip-permissions in an isolated - // environment — merged over the sandbox env (a caller-provided value - // wins). Safe to set unconditionally; it is a no-op for stricter modes. + // Isolated sandboxes often run as root. Claude refuses + // `--dangerously-skip-permissions` as root unless IS_SANDBOX=1. + // CLAUDE_CODE_SANDBOXED marks a real isolation boundary. Do not set + // either on local-process: that provider runs on the host. env: { - IS_SANDBOX: '1', - CLAUDE_CODE_SANDBOXED: '1', - // Docker has no host `claude login`. Local-process must not force - // ANTHROPIC_API_KEY: `-p` would use the key instead of the login. ...(sandbox.provider === 'local-process' ? {} - : hostClaudeAuthEnv()), + : { + IS_SANDBOX: '1', + CLAUDE_CODE_SANDBOXED: '1', + }), + // Docker has no host `claude login`. Local-process must not force + // ANTHROPIC_API_KEY: `-p` would use the key instead of the login. + ...(sandbox.provider === 'local-process' ? {} : hostClaudeAuthEnv()), ...localProcessHomeEnv(sandbox.provider), ...this.adapterConfig.env, }, diff --git a/packages/ai-claude-code/src/adapters/trust.ts b/packages/ai-claude-code/src/adapters/trust.ts deleted file mode 100644 index f688e90685..0000000000 --- a/packages/ai-claude-code/src/adapters/trust.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as fs from 'node:fs/promises' -import * as os from 'node:os' -import * as path from 'node:path' - -/** Claude stores project keys with forward slashes, even on Windows. */ -export function claudeProjectKey(cwd: string): string { - return path.resolve(cwd).replace(/\\/g, '/') -} - -export function withTrustDialogAccepted( - config: Record, - cwd: string, -): Record { - const key = claudeProjectKey(cwd) - const projectsRaw = config.projects - const projects = - projectsRaw !== null && - typeof projectsRaw === 'object' && - !Array.isArray(projectsRaw) - ? { ...(projectsRaw as Record) } - : {} - const existingRaw = projects[key] - const existing = - existingRaw !== null && - typeof existingRaw === 'object' && - !Array.isArray(existingRaw) - ? { ...(existingRaw as Record) } - : {} - projects[key] = { ...existing, hasTrustDialogAccepted: true } - return { ...config, projects } -} - -/** - * Mark a host cwd as trusted in `~/.claude.json` so headless `-p` can use - * the repo's `.claude/settings.json`. Skip virtual sandbox roots. - */ -export async function acceptClaudeTrustDialog(cwd: string): Promise { - if (cwd === '' || cwd === '/workspace' || cwd.startsWith('/workspace/')) { - return - } - const file = path.join(os.homedir(), '.claude.json') - let current: Record = {} - try { - const raw = await fs.readFile(file, 'utf8') - const parsed: unknown = JSON.parse(raw) - if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) { - current = parsed as Record - } - } catch (error) { - if ((error as NodeJS.ErrnoException).code !== 'ENOENT') return - } - await fs.writeFile( - file, - `${JSON.stringify(withTrustDialogAccepted(current, cwd), null, 2)}\n`, - 'utf8', - ) -} diff --git a/packages/ai-claude-code/src/stream/translate.ts b/packages/ai-claude-code/src/stream/translate.ts index 60b2ef866e..072cc90a82 100644 --- a/packages/ai-claude-code/src/stream/translate.ts +++ b/packages/ai-claude-code/src/stream/translate.ts @@ -70,10 +70,7 @@ function isUsefulStructuredObject(value: unknown): boolean { ) } -function rememberStructuredOutput( - current: unknown, - next: unknown, -): unknown { +function rememberStructuredOutput(current: unknown, next: unknown): unknown { return isUsefulStructuredObject(next) ? next : current } diff --git a/packages/ai-claude-code/tests/text-adapter.test.ts b/packages/ai-claude-code/tests/text-adapter.test.ts index 3e2d659042..a7b300bdec 100644 --- a/packages/ai-claude-code/tests/text-adapter.test.ts +++ b/packages/ai-claude-code/tests/text-adapter.test.ts @@ -34,8 +34,7 @@ const FAKE_CLAUDE = [ `process.stdin.on('end', () => {`, ` const w = (o) => process.stdout.write(JSON.stringify(o) + '\\n')`, ` w({ type: 'system', subtype: 'init', session_id: 'sess-abc', model: 'haiku', tools: [] })`, - // Echo IS_SANDBOX so the test can assert the adapter sets it (claude refuses - // bypassPermissions as root without it). + // Echo IS_SANDBOX so the test can assert local-process does not set it. ` w({ type: 'assistant', message: { id: 'msg-1', content: [{ type: 'text', text: 'pong IS_SANDBOX=' + process.env.IS_SANDBOX }] }, parent_tool_use_id: null })`, ` w({ type: 'result', subtype: 'success', result: 'pong', usage: { input_tokens: 1, output_tokens: 1 } })`, `})`, @@ -107,9 +106,8 @@ describe('claude-code in-sandbox adapter', () => { .map((c) => (c as { delta?: string }).delta ?? '') .join('') expect(text).toContain('pong') - // The adapter must set IS_SANDBOX=1 in the CLI env (claude refuses - // `--dangerously-skip-permissions`/bypassPermissions as root otherwise). - expect(text).toContain('IS_SANDBOX=1') + // Isolated sandboxes set IS_SANDBOX=1. local-process must not. + expect(text).toContain('IS_SANDBOX=undefined') expect(chunks.some((c) => c.type === 'RUN_FINISHED')).toBe(true) diff --git a/packages/ai-claude-code/tests/translate.test.ts b/packages/ai-claude-code/tests/translate.test.ts index 4f4a759034..5c6fe1a761 100644 --- a/packages/ai-claude-code/tests/translate.test.ts +++ b/packages/ai-claude-code/tests/translate.test.ts @@ -684,11 +684,7 @@ describe('translateSdkStream', () => { it('parses JSON from assistant text when the StructuredOutput tool is missing', async () => { const report = { name: 'TanStack AI', oneLiner: 'SDK' } const chunks = await collect( - [ - init, - assistantText(JSON.stringify(report)), - resultSuccess, - ], + [init, assistantText(JSON.stringify(report)), resultSuccess], { ...makeContext(), expectStructuredOutput: true }, ) const complete = chunks.find( diff --git a/packages/ai-claude-code/tests/trust.test.ts b/packages/ai-claude-code/tests/trust.test.ts deleted file mode 100644 index c13250895e..0000000000 --- a/packages/ai-claude-code/tests/trust.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { claudeProjectKey, withTrustDialogAccepted } from '../src/adapters/trust' - -describe('withTrustDialogAccepted', () => { - it('sets hasTrustDialogAccepted on the resolved cwd', () => { - const next = withTrustDialogAccepted({}, 'C:\\tmp\\repo') - const key = claudeProjectKey('C:\\tmp\\repo') - expect(key.includes('\\')).toBe(false) - const projects = next.projects as Record - expect(projects[key]?.hasTrustDialogAccepted).toBe(true) - }) - - it('keeps other project entries', () => { - const next = withTrustDialogAccepted( - { projects: { '/other': { hasTrustDialogAccepted: false } } }, - '/tmp/repo', - ) - const projects = next.projects as Record - expect(projects['/other']?.hasTrustDialogAccepted).toBe(false) - expect(projects[claudeProjectKey('/tmp/repo')]?.hasTrustDialogAccepted).toBe( - true, - ) - }) -}) diff --git a/packages/ai-codex/src/adapters/text.ts b/packages/ai-codex/src/adapters/text.ts index fc8c3367b8..0f97604968 100644 --- a/packages/ai-codex/src/adapters/text.ts +++ b/packages/ai-codex/src/adapters/text.ts @@ -139,7 +139,6 @@ export class CodexTextAdapter< ) } - /** Mirror @openai/codex-sdk's `codex exec --experimental-json` invocation. */ supportsCombinedToolsAndSchema(): boolean { return true } @@ -148,6 +147,7 @@ export class CodexTextAdapter< return 'event' } + /** Mirror @openai/codex-sdk's `codex exec --experimental-json` invocation. */ private buildCommand( options: TextOptions, resume: string | undefined, diff --git a/packages/ai/src/utilities/structured-output-text.ts b/packages/ai/src/utilities/structured-output-text.ts index 5019e018f7..ba3d98ca86 100644 --- a/packages/ai/src/utilities/structured-output-text.ts +++ b/packages/ai/src/utilities/structured-output-text.ts @@ -13,9 +13,9 @@ export function parseJsonFromAssistantText(raw: string): unknown { const wholeFence = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/) if (wholeFence?.[1]) candidates.push(wholeFence[1].trim()) candidates.push(trimmed) - const lastFence = [...trimmed.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/g)].at( - -1, - ) + const lastFence = [ + ...trimmed.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/g), + ].at(-1) if (lastFence?.[1]) candidates.push(lastFence[1].trim()) const extracted = extractLastJsonSlice(trimmed) if (extracted !== undefined) candidates.push(extracted) @@ -34,23 +34,18 @@ export function parseJsonFromAssistantText(raw: string): unknown { } function extractLastJsonSlice(text: string): string | undefined { - let end = -1 - for (let i = text.length - 1; i >= 0; i--) { - if (text[i] === '}' || text[i] === ']') { - end = i - break - } - } - if (end < 0) return undefined - for (let start = end; start >= 0; start--) { - const opener = text[start] - if (opener !== '{' && opener !== '[') continue - const slice = text.slice(start, end + 1) - try { - JSON.parse(slice) - return slice - } catch { - // Try an earlier opener. Nested braces often fail until the real start. + for (let end = text.length - 1; end >= 0; end--) { + if (text[end] !== '}' && text[end] !== ']') continue + for (let start = end; start >= 0; start--) { + const opener = text[start] + if (opener !== '{' && opener !== '[') continue + const slice = text.slice(start, end + 1) + try { + JSON.parse(slice) + return slice + } catch { + // Try an earlier opener, then an earlier closer. + } } } return undefined diff --git a/packages/ai/tests/structured-output-text.test.ts b/packages/ai/tests/structured-output-text.test.ts index 46ec5df893..d87d562ffd 100644 --- a/packages/ai/tests/structured-output-text.test.ts +++ b/packages/ai/tests/structured-output-text.test.ts @@ -35,6 +35,12 @@ describe('parseJsonFromAssistantText', () => { ).toEqual({ a: 2 }) }) + it('ignores a brace in prose after a valid object', () => { + expect(parseJsonFromAssistantText('{"a":1}\nTool note: }')).toEqual({ + a: 1, + }) + }) + it('appends the schema instruction', () => { const next = appendOutputSchemaInstruction('Look around.', { type: 'object', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 03a987c888..d5b156d4ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,7 +36,7 @@ importers: version: 0.3.4 '@tanstack/vite-config': specifier: 0.6.0 - version: 0.6.0(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.6.0(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -47,8 +47,8 @@ importers: specifier: ^4.3.0 version: 4.3.0(@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@7.0.2))(eslint@9.39.4(jiti@2.7.0))(typescript@7.0.2))(eslint@9.39.4(jiti@2.7.0)) happy-dom: - specifier: ^20.0.10 - version: 20.0.11 + specifier: ^20.11.2 + version: 20.11.2 kiira: specifier: 0.6.0 version: 0.6.0 @@ -59,8 +59,8 @@ importers: specifier: ^4.0.3 version: 4.0.3 nx: - specifier: 23.1.0 - version: 23.1.0 + specifier: 23.1.1 + version: 23.1.1 oxfmt: specifier: ^0.59.0 version: 0.59.0(svelte@5.45.10) @@ -83,20 +83,20 @@ importers: specifier: ^1.9.0 version: 1.9.0 tinyglobby: - specifier: ^0.2.15 - version: 0.2.15 + specifier: ^0.2.17 + version: 0.2.17 tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.12 + version: 4.23.12 typescript: specifier: 7.0.2 version: 7.0.2 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) codemods: devDependencies: @@ -117,7 +117,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) examples/ag-ui: dependencies: @@ -139,7 +139,7 @@ importers: devDependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/react': specifier: ^19.2.7 version: 19.2.7 @@ -147,8 +147,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(supports-color@7.2.0)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) concurrently: specifier: ^9.1.2 version: 9.2.1 @@ -162,8 +162,8 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/sandbox-cloudflare: dependencies: @@ -199,7 +199,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.6(srvx@0.11.17))(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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) lucide-react: specifier: ^0.561.0 version: 0.561.0(react@19.2.3) @@ -230,13 +230,13 @@ importers: devDependencies: '@cloudflare/vite-plugin': specifier: ^1.42.1 - version: 1.42.1(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(workerd@1.20260617.1)(wrangler@4.103.0) + version: 1.42.1(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(workerd@1.20260617.1)(wrangler@4.103.0) '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(supports-color@7.2.0)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -247,8 +247,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) tailwindcss: specifier: ^4.1.18 version: 4.1.18 @@ -256,8 +256,8 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) wrangler: specifier: ^4.103.0 version: 4.103.0(@cloudflare/workers-types@4.20260317.1) @@ -287,7 +287,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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) lucide-react: specifier: ^0.561.0 version: 0.561.0(react@19.2.3) @@ -318,10 +318,10 @@ importers: devDependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -332,14 +332,14 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) dotenv: specifier: ^17.2.3 version: 17.2.3 nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0) tailwindcss: specifier: ^4.1.18 version: 4.1.18 @@ -347,26 +347,26 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/ts-angular-chat: dependencies: '@angular/common': - specifier: ^21.2.19 - version: 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + specifier: ^21.2.20 + version: 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^21.2.19 - version: 21.2.19 + specifier: ^21.2.20 + version: 21.2.20 '@angular/core': - specifier: ^21.2.19 - version: 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) + specifier: ^21.2.20 + version: 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) '@angular/forms': - specifier: ^21.2.19 - version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + specifier: ^21.2.20 + version: 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@angular/platform-browser': - specifier: ^21.2.19 - version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)) + specifier: ^21.2.20 + version: 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -391,13 +391,13 @@ importers: devDependencies: '@analogjs/vite-plugin-angular': specifier: ^2.6.2 - version: 2.6.3(@angular/build@21.2.20(6306034858a4461af901a78c987641b8))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.6.3(a8e4d9beea01c48751a3f4ef1beb3aea) '@angular/build': - specifier: ^21.2.20 - version: 21.2.20(6306034858a4461af901a78c987641b8) + specifier: ^21.2.21 + version: 21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.19)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0) '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -408,8 +408,8 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/ts-code-mode-web: dependencies: @@ -430,7 +430,7 @@ importers: version: 1.1.12(@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) '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -475,10 +475,10 @@ 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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/store': specifier: ^0.8.0 version: 0.8.0 @@ -499,7 +499,7 @@ importers: version: 15.0.12 nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0) puppeteer: specifier: ^24.34.0 version: 24.39.1(supports-color@7.2.0)(typescript@5.9.3) @@ -545,7 +545,7 @@ importers: devDependencies: '@tanstack/devtools-vite': specifier: ^0.5.3 - version: 0.5.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.5.3(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -556,20 +556,20 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/ts-group-chat: dependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -587,16 +587,16 @@ importers: version: 1.159.5(@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)(csstype@3.2.3)(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.6(srvx@0.11.17))(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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(supports-color@7.2.0)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) capnweb: specifier: ^0.10.0 version: 0.10.0 nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0) react: specifier: ^19.2.3 version: 19.2.3 @@ -608,20 +608,20 @@ importers: version: 4.1.18 vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(supports-color@7.2.0)(typescript@5.9.3)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.4(supports-color@7.2.0)(typescript@5.9.3)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) ws: specifier: ^8.18.3 version: 8.18.3 devDependencies: '@tanstack/devtools-vite': specifier: ^0.5.3 - version: 0.5.3(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.5.3(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@testing-library/dom': specifier: ^10.4.1 version: 10.4.1 '@testing-library/react': - specifier: ^16.3.0 - version: 16.3.0(@testing-library/dom@10.4.1)(@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) + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@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) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -635,20 +635,20 @@ importers: specifier: ^8.18.1 version: 8.18.1 '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -672,7 +672,7 @@ importers: version: 1.7.0 '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -771,13 +771,13 @@ 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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/react-store': specifier: ^0.8.0 version: 0.8.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/store': specifier: ^0.8.0 version: 0.8.0 @@ -792,7 +792,7 @@ importers: version: 0.561.0(react@19.2.3) nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0) react: specifier: ^19.2.3 version: 19.2.3 @@ -823,7 +823,7 @@ importers: devDependencies: '@tanstack/devtools-vite': specifier: ^0.5.3 - version: 0.5.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.5.3(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/react-ai-devtools': specifier: workspace:* version: link:../../packages/react-ai-devtools @@ -831,8 +831,8 @@ importers: specifier: ^10.4.1 version: 10.4.1 '@testing-library/react': - specifier: ^16.3.0 - version: 16.3.0(@testing-library/dom@10.4.1)(@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) + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@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) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -843,23 +843,23 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) concurrently: specifier: ^9.1.2 version: 9.2.1 jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -868,7 +868,7 @@ importers: dependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -895,16 +895,16 @@ 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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) lucide-react: specifier: ^0.561.0 version: 0.561.0(react@19.2.3) nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0) react: specifier: ^19.2.3 version: 19.2.3 @@ -925,14 +925,14 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/ts-react-native-chat: dependencies: @@ -974,8 +974,8 @@ importers: specifier: ^19.2.7 version: 19.2.7 tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.12 + version: 4.23.12 typescript: specifier: 5.9.3 version: 5.9.3 @@ -984,7 +984,7 @@ importers: dependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -999,16 +999,16 @@ 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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) lucide-react: specifier: ^0.561.0 version: 0.561.0(react@19.2.3) nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.4.2)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@3.3.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.4.2)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@3.3.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0) react: specifier: ^19.2.3 version: 19.2.3 @@ -1029,14 +1029,14 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/ts-react-search: dependencies: @@ -1045,7 +1045,7 @@ importers: version: 1.2.4(@types/react@19.2.7)(react@19.2.3) '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -1078,10 +1078,10 @@ 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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/zod-adapter': specifier: ^1.140.1 version: 1.166.9(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(zod@4.3.6) @@ -1096,7 +1096,7 @@ importers: version: 0.561.0(react@19.2.3) nitro: specifier: 3.0.260610-beta - version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0) + version: 3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.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) @@ -1124,13 +1124,13 @@ importers: devDependencies: '@tanstack/devtools-vite': specifier: ^0.5.3 - version: 0.5.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.5.3(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@testing-library/dom': specifier: ^10.4.1 version: 10.4.1 '@testing-library/react': - specifier: ^16.3.0 - version: 16.3.0(@testing-library/dom@10.4.1)(@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) + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@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) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -1141,20 +1141,20 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -1163,7 +1163,7 @@ importers: dependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -1193,10 +1193,10 @@ importers: version: link:../../packages/ai-solid-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.155.0 - version: 1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/solid-ai-devtools': specifier: workspace:* version: link:../../packages/solid-ai-devtools @@ -1214,7 +1214,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.7.0))(solid-js@1.9.10)(supports-color@7.2.0)(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.6(srvx@0.11.17))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + 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.17))(solid-js@1.9.10)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/solid-store': specifier: ^0.8.0 version: 0.8.0(solid-js@1.9.10) @@ -1248,7 +1248,7 @@ importers: version: 0.4.1 '@tanstack/devtools-vite': specifier: ^0.5.3 - version: 0.5.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 0.5.3(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@testing-library/dom': specifier: ^10.4.1 version: 10.4.1 @@ -1256,20 +1256,20 @@ importers: specifier: ^24.10.1 version: 24.10.3 jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vite-plugin-solid: - specifier: ^2.11.10 - version: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^2.11.14 + version: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -1315,16 +1315,16 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^3.3.1 - version: 3.3.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 3.3.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))) '@sveltejs/kit': specifier: ^2.15.10 - version: 2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -1344,8 +1344,8 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) examples/ts-vue-chat: dependencies: @@ -1388,16 +1388,16 @@ importers: devDependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/node': specifier: ^24.10.1 version: 24.10.3 '@vitejs/plugin-vue': - specifier: ^6.0.2 - version: 6.0.3(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3)) + specifier: ^6.0.8 + version: 6.0.8(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3)) autoprefixer: specifier: ^10.4.21 - version: 10.4.22(postcss@8.5.19) + version: 10.4.22(postcss@8.5.26) concurrently: specifier: ^9.1.2 version: 9.2.1 @@ -1411,14 +1411,14 @@ importers: specifier: ^4.1.18 version: 4.1.18 tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.12 + version: 4.23.12 typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vue-tsc: specifier: ^2.2.10 version: 2.2.12(typescript@5.9.3) @@ -1430,8 +1430,8 @@ importers: version: link:../../packages/ai-client devDependencies: vite: - specifier: ^7.3.3 - version: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^7.3.6 + version: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai: dependencies: @@ -1455,8 +1455,8 @@ importers: specifier: ^1.9.0 version: 1.9.1 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) arktype: specifier: ^2.1.28 version: 2.2.0 @@ -1480,8 +1480,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox-local-process '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-angular: dependencies: @@ -1494,25 +1494,25 @@ importers: devDependencies: '@analogjs/vite-plugin-angular': specifier: ^2.6.2 - version: 2.6.3(@angular/build@21.2.20(7176eabe523c375be6c990a7b771f135))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 2.6.3(@angular/build@21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.26)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@angular/build': - specifier: ^21.2.20 - version: 21.2.20(7176eabe523c375be6c990a7b771f135) + specifier: ^21.2.21 + version: 21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.26)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0) '@angular/common': - specifier: ^21.2.19 - version: 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + specifier: ^21.2.20 + version: 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/compiler': - specifier: ^21.2.19 - version: 21.2.19 + specifier: ^21.2.20 + version: 21.2.20 '@angular/core': - specifier: ^21.2.19 - version: 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) + specifier: ^21.2.20 + version: 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) '@angular/platform-browser': - specifier: ^21.2.19 - version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)) + specifier: ^21.2.20 + version: 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)) '@angular/platform-browser-dynamic': - specifier: ^21.2.19 - version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))) + specifier: ^21.2.20 + version: 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))) '@tanstack/ai': specifier: workspace:* version: link:../ai @@ -1520,17 +1520,17 @@ importers: specifier: ^24.10.1 version: 24.10.3 jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) ng-packagr: specifier: ^21.2.0 - version: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) + version: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) typescript: specifier: 5.9.3 version: 5.9.3 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) zod: specifier: ^4.2.0 version: 4.3.6 @@ -1551,8 +1551,8 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) zod: specifier: ^4.2.0 version: 4.2.1 @@ -1588,11 +1588,11 @@ importers: version: 4.3.6 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-byteplus: dependencies: @@ -1613,11 +1613,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-claude-code: devDependencies: @@ -1631,8 +1631,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox-local-process '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-client: dependencies: @@ -1650,11 +1650,11 @@ importers: specifier: ^1.1.0 version: 1.1.0 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.2.1 @@ -1669,8 +1669,8 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) zod: specifier: ^4.2.0 version: 4.3.6 @@ -1697,8 +1697,8 @@ importers: specifier: workspace:* version: link:../ai-openai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) commander: specifier: ^13.1.0 version: 13.1.0 @@ -1706,8 +1706,8 @@ importers: specifier: ^17.2.3 version: 17.4.2 tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.12 + version: 4.23.12 zod: specifier: ^4.2.0 version: 4.3.6 @@ -1749,8 +1749,8 @@ importers: version: 4.3.6 devDependencies: tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.12 + version: 4.23.12 packages/ai-codex: devDependencies: @@ -1764,8 +1764,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox-local-process '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-cohere: dependencies: @@ -1777,11 +1777,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-devtools: dependencies: @@ -1805,23 +1805,23 @@ importers: version: 1.9.10 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) tsup: specifier: ^8.5.1 - version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.19)(supports-color@7.2.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) + version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.26)(supports-color@7.2.0)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0) tsup-preset-solid: specifier: ^2.2.0 - version: 2.2.0(esbuild@0.28.1)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.19)(supports-color@7.2.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0)) + version: 2.2.0(esbuild@0.28.1)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.26)(supports-color@7.2.0)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0)) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vite-plugin-solid: - specifier: ^2.11.10 - version: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^2.11.14 + version: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) packages/ai-durable-stream: devDependencies: @@ -1832,8 +1832,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-elevenlabs: dependencies: @@ -1851,8 +1851,8 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-event-client: dependencies: @@ -1861,8 +1861,8 @@ importers: version: 0.4.1 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-fal: dependencies: @@ -1877,11 +1877,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-gemini: dependencies: @@ -1899,11 +1899,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.3.6 @@ -1927,11 +1927,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-grok-build: dependencies: @@ -1949,8 +1949,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox-local-process '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-groq: dependencies: @@ -1971,11 +1971,11 @@ importers: version: 4.3.6 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-isolate-cloudflare: dependencies: @@ -1987,8 +1987,8 @@ importers: specifier: ^4.20260317.1 version: 4.20260317.1 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) wrangler: specifier: ^4.103.0 version: 4.103.0(@cloudflare/workers-types@4.20260317.1) @@ -2002,8 +2002,8 @@ importers: specifier: workspace:* version: link:../ai-code-mode '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-isolate-node: dependencies: @@ -2015,8 +2015,8 @@ importers: version: 6.1.2 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-isolate-quickjs: dependencies: @@ -2028,8 +2028,8 @@ importers: version: 0.31.0 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-isolate-quickjs-bun: dependencies: @@ -2047,8 +2047,8 @@ importers: specifier: ^1.3.14 version: 1.3.14 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-mcp: dependencies: @@ -2060,8 +2060,8 @@ importers: version: link:../ai devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) jiti: specifier: ^2.4.2 version: 2.6.1 @@ -2070,10 +2070,10 @@ importers: version: 15.0.4 tsup: specifier: ^8.5.1 - version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.6.1)(postcss@8.5.19)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) + version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.6.1)(postcss@8.5.26)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.6.1)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.6.1)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.3.6 @@ -2097,8 +2097,8 @@ importers: specifier: ^0.6.1 version: 0.6.2 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) ioredis-mock: specifier: ^8.9.0 version: 8.13.1(@types/ioredis-mock@8.2.7(ioredis@5.9.2))(ioredis@5.9.2) @@ -2119,11 +2119,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-ollama: dependencies: @@ -2138,11 +2138,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-openai: dependencies: @@ -2160,11 +2160,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.3.6 @@ -2182,8 +2182,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-openrouter: dependencies: @@ -2198,11 +2198,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.3.6 @@ -2214,11 +2214,11 @@ importers: version: link:../ai devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.3.6 @@ -2233,11 +2233,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) packages/ai-preact: dependencies: @@ -2255,17 +2255,17 @@ importers: specifier: ^3.2.4 version: 3.2.4(preact@10.28.2) '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) preact: specifier: ^10.26.9 version: 10.28.2 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-react: dependencies: @@ -2283,23 +2283,23 @@ importers: specifier: workspace:* version: link:../ai '@testing-library/react': - specifier: ^16.3.0 - version: 16.3.0(@testing-library/dom@10.4.1)(@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) + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@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) '@types/react': specifier: ^19.2.7 version: 19.2.7 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) react: specifier: ^19.2.3 version: 19.2.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-react-ui: dependencies: @@ -2329,8 +2329,8 @@ importers: specifier: ^19.2.7 version: 19.2.7 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) react: specifier: ^19.2.3 version: 19.2.3 @@ -2338,8 +2338,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(react@19.2.3) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-sandbox: dependencies: @@ -2354,11 +2354,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) packages/ai-sandbox-cloudflare: dependencies: @@ -2382,8 +2382,8 @@ importers: specifier: ^24.10.1 version: 24.10.3 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) zod: specifier: ^4.2.0 version: 4.3.6 @@ -2398,8 +2398,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-sandbox-docker: dependencies: @@ -2414,8 +2414,8 @@ importers: specifier: ^3.3.31 version: 3.3.47 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-sandbox-local-process: devDependencies: @@ -2426,8 +2426,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-sandbox-sprites: devDependencies: @@ -2435,8 +2435,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-sandbox-vercel: dependencies: @@ -2448,8 +2448,8 @@ importers: specifier: workspace:* version: link:../ai-sandbox '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) packages/ai-solid: dependencies: @@ -2470,11 +2470,11 @@ importers: specifier: ^24.10.1 version: 24.10.3 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) solid-js: specifier: ^1.9.10 version: 1.9.10 @@ -2486,7 +2486,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) packages/ai-solid-ui: dependencies: @@ -2513,20 +2513,20 @@ importers: specifier: workspace:* version: link:../ai-solid '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) happy-dom: - specifier: ^20.0.10 - version: 20.0.11 + specifier: ^20.11.2 + version: 20.11.2 solid-js: specifier: ^1.9.10 version: 1.9.10 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vite-plugin-solid: - specifier: ^2.11.10 - version: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^2.11.14 + version: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) packages/ai-svelte: dependencies: @@ -2542,7 +2542,7 @@ importers: version: 2.5.7(svelte@5.45.10) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 5.1.1(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../ai @@ -2550,11 +2550,11 @@ importers: specifier: ^24.10.1 version: 24.10.3 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) svelte: specifier: ^5.20.0 version: 5.45.10 @@ -2565,8 +2565,8 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-utils: devDependencies: @@ -2574,11 +2574,11 @@ importers: specifier: ^24.10.1 version: 24.10.3 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-vercel-gateway: dependencies: @@ -2599,11 +2599,11 @@ importers: version: 4.3.6 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/ai-vue: dependencies: @@ -2621,14 +2621,14 @@ importers: specifier: ^24.10.1 version: 24.10.3 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) '@vue/test-utils': specifier: ^2.4.6 version: 2.4.6 jsdom: - specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.19) + specifier: ^27.4.0 + version: 27.4.0(postcss@8.5.26) tsdown: specifier: ^0.17.0-beta.6 version: 0.17.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(oxc-resolver@11.21.3)(publint@0.3.16)(typescript@5.9.3) @@ -2637,7 +2637,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.1.10 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) vue: specifier: ^3.5.25 version: 3.5.25(typescript@5.9.3) @@ -2661,14 +2661,14 @@ importers: version: 4.0.1 devDependencies: '@vitejs/plugin-vue': - specifier: ^6.0.2 - version: 6.0.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3)) + specifier: ^6.0.8 + version: 6.0.8(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3)) '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vue: specifier: ^3.5.25 version: 3.5.25(typescript@5.9.3) @@ -2689,11 +2689,11 @@ importers: specifier: workspace:* version: link:../ai '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: specifier: ^4.2.0 version: 4.3.6 @@ -2711,11 +2711,11 @@ importers: version: 10.28.1 devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/react-ai-devtools: dependencies: @@ -2730,14 +2730,14 @@ importers: specifier: ^19.2.7 version: 19.2.7 '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) react: specifier: ^19.2.3 version: 19.2.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) packages/solid-ai-devtools: dependencies: @@ -2749,23 +2749,23 @@ importers: version: 0.4.0(@types/react@19.2.7)(preact@10.28.2)(react@19.2.3)(solid-js@1.9.10)(vue@3.5.25(typescript@7.0.2)) devDependencies: '@vitest/coverage-v8': - specifier: 4.0.14 - version: 4.0.14(supports-color@7.2.0)(vitest@4.1.10) + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) solid-js: specifier: ^1.9.10 version: 1.9.10 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vite-plugin-solid: - specifier: ^2.11.10 - version: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^2.11.14 + version: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) testing/e2e: dependencies: '@copilotkit/aimock': specifier: ^1.34.0 - version: 1.34.0(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))) + version: 1.34.0(vitest@4.1.10) '@modelcontextprotocol/sdk': specifier: ^1.29.0 version: 1.29.0(zod@4.3.6) @@ -2777,7 +2777,7 @@ importers: version: 1.9.1 '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -2846,7 +2846,7 @@ importers: version: 0.4.1 '@tanstack/nitro-v2-vite-plugin': specifier: ^1.155.0 - version: 1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/react-ai-devtools': specifier: workspace:* version: link:../../packages/react-ai-devtools @@ -2855,7 +2855,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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) arktype: specifier: ^2.1.28 version: 2.2.0 @@ -2903,8 +2903,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) miniflare: specifier: ^4.20260609.0 version: 4.20260609.0 @@ -2912,14 +2912,14 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) testing/panel: dependencies: '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai @@ -2958,7 +2958,7 @@ importers: version: link:../../packages/ai-react-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.155.0 - version: 1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/react-ai-devtools': specifier: workspace:* version: link:../../packages/react-ai-devtools @@ -2970,10 +2970,10 @@ 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.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + version: 1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start': specifier: ^1.120.20 - version: 1.120.20(525aa2ef7692c9b3e6ea9eb659ae95d8) + version: 1.120.20(340eefabdbae5b0c948fd6f8943277d1) highlight.js: specifier: ^11.11.1 version: 11.11.1 @@ -3021,8 +3021,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) dotenv: specifier: ^17.2.3 version: 17.2.3 @@ -3030,8 +3030,8 @@ importers: specifier: 5.9.3 version: 5.9.3 vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + specifier: ^8.2.1 + version: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) testing/react-native-smoke: dependencies: @@ -3061,8 +3061,8 @@ importers: specifier: ^0.25.12 version: 0.25.12 tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.23.12 + version: 4.23.12 typescript: specifier: 5.9.3 version: 5.9.3 @@ -3103,13 +3103,13 @@ packages: vite: optional: true - '@angular-devkit/architect@0.2102.20': - resolution: {integrity: sha512-s7wPFCMrt9mWMr+NWs4T8849snnOE4DcmLb9Set7KtbhV6Z8E7ZASs/wqPOS3KPxLjxTqM6CnkwKhc3Th6DniA==} + '@angular-devkit/architect@0.2102.21': + resolution: {integrity: sha512-WqITVviALevNpCQoI50e3YY9qNOQT+gqTow/4FhWsxlAJFMb5uyilFpVz2hGYWPgosF3OAKmT1h9r+Jm9S6SUQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular-devkit/core@21.2.20': - resolution: {integrity: sha512-QViRAYFj3jcElWND79hM6y4vTSYhMlJSOjy9nby9JsQaPgetkf039jI2u9Lp+PduE6lysewzf85d1UGsm3eI0A==} + '@angular-devkit/core@21.2.21': + resolution: {integrity: sha512-xOr6mZ00M6hgM/xltAVkPVc/Yd1a/Wa0CGecV64JTITaVaSH8p8+wXe62Xavdr3pcc9cLKKUUB4mAup4k7Kkyw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^5.0.0 @@ -3117,8 +3117,8 @@ packages: chokidar: optional: true - '@angular/build@21.2.20': - resolution: {integrity: sha512-Dl9AX8e3mQpAl4RkmvoNnYRoRSpqMLQBqJYf/quupGLxMpQ55mOBhnGfzmoBLyETFhMUd329tvGtOcicPW/hdA==} + '@angular/build@21.2.21': + resolution: {integrity: sha512-Z88uTaPte8uEYW+Sn5BUz7YoGAbi1dcoz8X1eaJi30bT7qtZ5Bph0vELMBu2VCtp9JFgZhsLn+uy8F6iIPiOUQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: '@angular/compiler': ^21.0.0 @@ -3128,7 +3128,7 @@ packages: '@angular/platform-browser': ^21.0.0 '@angular/platform-server': ^21.0.0 '@angular/service-worker': ^21.0.0 - '@angular/ssr': ^21.2.20 + '@angular/ssr': ^21.2.21 karma: ^6.4.0 less: ^4.2.0 ng-packagr: ^21.0.0 @@ -3163,11 +3163,11 @@ packages: vitest: optional: true - '@angular/common@21.2.19': - resolution: {integrity: sha512-Rvo/VXI0kUmfQT7+OeAjv526OJlf/WrLnJq1Tz84Jkyv9bs9SOMTCT6m4+boo8gxVNdrcxvGU3Q0o2jZzKceSg==} + '@angular/common@21.2.20': + resolution: {integrity: sha512-TzUVfa4Asq/np3eStFX3Q6W+dPG7JDNtkj4XwTvRnSL0CN8pPe+wPHSo76awHFzYWcucxpZTmk2GUemeqxa4Yw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/core': 21.2.19 + '@angular/core': 21.2.20 rxjs: ^6.5.3 || ^7.4.0 '@angular/compiler-cli@21.2.17': @@ -3181,15 +3181,15 @@ packages: typescript: optional: true - '@angular/compiler@21.2.19': - resolution: {integrity: sha512-vuF5i1t14ftJiHXVVLgDYLWkT99QuajphcUHy1VZaMX3FiqSGXRV62g+R2RMxL0OJ5C1ai8xTHKPx9n1lQFyFg==} + '@angular/compiler@21.2.20': + resolution: {integrity: sha512-7UY4x+YOvDCUpiiVM1wEU9gIiME54vF9n+84FdaSL/6MxgHknkaB/R8iwNrfXwsHThzy4NKv+25UvlJrz9P7mg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@angular/core@21.2.19': - resolution: {integrity: sha512-PVoXD1kBexOJLkFzKx2zBY/0oZJXGru0eGn2hu0q5n3vkZlYsR1yRolfGenK1gZE48Qibiw/ttg/X/pAIPEZGg==} + '@angular/core@21.2.20': + resolution: {integrity: sha512-4yp6EKd1VJHUOiKmd3+s9UUXtBGsdO/IKewABuPXZ+UdrXPQSRMhgnMt49yqgz29XS7jSHyq6nZgt0CXOVEDZg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/compiler': 21.2.19 + '@angular/compiler': 21.2.20 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 || ~0.16.0 peerDependenciesMeta: @@ -3198,32 +3198,32 @@ packages: zone.js: optional: true - '@angular/forms@21.2.19': - resolution: {integrity: sha512-tEw8cz2UU6VSB+ReJN86k87nRdLRXGi+8SZhoRl2dFu2iReIO3S6kJAVTH7Y9kdrokqTPhWG+KNEzWgqhdjXOg==} + '@angular/forms@21.2.20': + resolution: {integrity: sha512-OP1/UtMGBfJEVGs85ns1jSYVyyezQRQYPG1ReUDzGPGRt62+JQkLdtHYu6RKwkXzW+LF2mt8cpIb4YfhxnnYrA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.19 - '@angular/core': 21.2.19 - '@angular/platform-browser': 21.2.19 + '@angular/common': 21.2.20 + '@angular/core': 21.2.20 + '@angular/platform-browser': 21.2.20 rxjs: ^6.5.3 || ^7.4.0 - '@angular/platform-browser-dynamic@21.2.19': - resolution: {integrity: sha512-Ns+0D4S8A6Bypxgeba0QSDdIIVosOUfSfxDxiC0oN/VrgMBiLAbOROTnoNfOaFRgkV2gUzPNPFdHD2Ciflq+bQ==} + '@angular/platform-browser-dynamic@21.2.20': + resolution: {integrity: sha512-n3+eLj0F/hjf+cgLaNWsBcqZcaeGoh5TCMe+VXUnh6XRwbwXorxP91ypfMT/rj0QnroY6NoZcvvPlx1ezsIVrw==} 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.19 - '@angular/compiler': 21.2.19 - '@angular/core': 21.2.19 - '@angular/platform-browser': 21.2.19 + '@angular/common': 21.2.20 + '@angular/compiler': 21.2.20 + '@angular/core': 21.2.20 + '@angular/platform-browser': 21.2.20 - '@angular/platform-browser@21.2.19': - resolution: {integrity: sha512-YMguYVhdkV8tr9MvbN+VpMjbdmsYq6g12M9WPvAYM51BkL2iREbWeoXDGmfCw9G0it6+0pMdgrSPFFUFuOqpAQ==} + '@angular/platform-browser@21.2.20': + resolution: {integrity: sha512-KtIrkSol2Q5qx6Poj53fLN6x3FYTPXCJ3Qi4KzlPbK0EFoiltaYCh3C2hmBze9QNdA8TM719THGvIDpCznl8PQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 21.2.19 - '@angular/common': 21.2.19 - '@angular/core': 21.2.19 + '@angular/animations': 21.2.20 + '@angular/common': 21.2.20 + '@angular/core': 21.2.20 peerDependenciesMeta: '@angular/animations': optional: true @@ -3884,10 +3884,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} - engines: {node: '>=6.9.0'} - '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} @@ -4866,6 +4862,15 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@expo/cli@56.1.12': resolution: {integrity: sha512-Ya/13E1yDx1oAuPw5MDmqzIGyzwSs7KSr1EjgSObOF0VO0GD9jqJjvjOiwurjScLUfxcGZQgq23UzMlBVHwdvA==} hasBin: true @@ -5732,57 +5737,57 @@ packages: '@nothing-but/utils@0.17.0': resolution: {integrity: sha512-TuCHcHLOqDL0SnaAxACfuRHBNRgNJcNn9X0GiH5H3YSDBVquCr3qEIG3FOQAuMyZCbu9w8nk2CHhOsn7IvhIwQ==} - '@nx/nx-darwin-arm64@23.1.0': - resolution: {integrity: sha512-wIFH5p0AXLxbYUHgYEH/zpWpPTQ9LpqESo/GcOPXkSBtUkSAZcqXZ6jmFzTPqGAeP4PBcVZIetO0TXmSSyEO7Q==} + '@nx/nx-darwin-arm64@23.1.1': + resolution: {integrity: sha512-Rq/RXLX5uIvJQfb6kuUgEirquT5ARaAgQyNaMZVnOPAL5wuxaDvQag8WX/WUCIgbUKZuGkclJwM7Vlnvtn3bdg==} cpu: [arm64] os: [darwin] - '@nx/nx-darwin-x64@23.1.0': - resolution: {integrity: sha512-D7fEW3+agyb0cWGi8qgN/0irHUwcO8nsuYOrRJjphtWE6J76EORW5sMY93/YFfnLeFVhBMBNVrE6aj2Y4wYCbA==} + '@nx/nx-darwin-x64@23.1.1': + resolution: {integrity: sha512-doWaPLPd6yUas3FhQJqMAScupCsToeTedK4RRWm700VhHoVdBTN4ejIBRBfoiT/SPAwY6EOHb8uFDJhGo7geMg==} cpu: [x64] os: [darwin] - '@nx/nx-freebsd-x64@23.1.0': - resolution: {integrity: sha512-yZoZyc9t3ViaA9WWDe5F7IlJ+58Hqdn6gqoO9UG2FH3Io1mj+KpF3jhUoj3S1m18D28MN2oItS762QIt6otO3g==} + '@nx/nx-freebsd-x64@23.1.1': + resolution: {integrity: sha512-9rDZKBPGuX8mid11RimJ2ENqDYZpPZhrqTlI9q/VnqcPLq0Bw/8AhqCKhBVlfNqJjbi4OsRQYDK7UkqIlcfThg==} cpu: [x64] os: [freebsd] - '@nx/nx-linux-arm-gnueabihf@23.1.0': - resolution: {integrity: sha512-D6QhBsLRUmwCc1jSjmY5MkyKOSWuQXQmu5K3BH6d1/uoX2HEZ68XgNyMkSwMA0g6jBKHIAguGkujiaCiXBEPeA==} + '@nx/nx-linux-arm-gnueabihf@23.1.1': + resolution: {integrity: sha512-NDR5X2HiD6WU3JEaDJmOLteIGIFqjrjkzoFWrQke2Y1oCRYu+UyFdPeaMVUyAs5OyUx4U+SD+eBQPTCNbWmazA==} cpu: [arm] os: [linux] - '@nx/nx-linux-arm64-gnu@23.1.0': - resolution: {integrity: sha512-Q61stbUFVBw9TprlVLkRQmk+fuMXPlyTlvGExJ1y8KYymDTFsjs8LFk7zTnRvFpI9LVMRuhyD3osaLy2TxPU7Q==} + '@nx/nx-linux-arm64-gnu@23.1.1': + resolution: {integrity: sha512-tWDHJII8+aHweTzHelf5dGM6qGNmHbAPhCc3jrtrM0uE+UD/wt2Dpq7H3086Iyia9M9jGM9sYpuD/6W6WAFAMA==} cpu: [arm64] os: [linux] libc: [glibc] - '@nx/nx-linux-arm64-musl@23.1.0': - resolution: {integrity: sha512-Lm5PC4yuBHw4gr37vcAX3kvS75prqL1VpbQkPHs4Z2Us1ri29ALxgdrEFgF6fbCXxl4w3sWmcbKGvrcMdpuvIQ==} + '@nx/nx-linux-arm64-musl@23.1.1': + resolution: {integrity: sha512-t7iVMZ7Cj3LmPcfaYt9KOkojpuC5XRmtZ/0G+NBMA2GuRhCVbzpOgUCob0nQMV2TrTwn5oAWJeDc4xLni+oteg==} cpu: [arm64] os: [linux] libc: [musl] - '@nx/nx-linux-x64-gnu@23.1.0': - resolution: {integrity: sha512-v1ELSkVskidK6A+mm/Ynm8TWIb5UdzGWMcD7CTgmvjTzKfXIO0QY1ToDTqvoBwnetcehWR5gnhQlhQgOSH8XFA==} + '@nx/nx-linux-x64-gnu@23.1.1': + resolution: {integrity: sha512-stuCayctOt/4AFvxKYgGTPluUc0HW7DcyTz9yeTMl/zj0+FENEr8RCTjInD0Q5qVGzYphma6SssVSh432w5agw==} cpu: [x64] os: [linux] libc: [glibc] - '@nx/nx-linux-x64-musl@23.1.0': - resolution: {integrity: sha512-pD/Axn0usK2/RV2bSrLX7h59YpOXGiaYHmlZynVVS+CqkKbyFzxnrvvLmRdOdMxsfM6oDXom4lCcJMg+wUYcpw==} + '@nx/nx-linux-x64-musl@23.1.1': + resolution: {integrity: sha512-cZSUqGV+iHda39W91BNKSysSu6OFfR6M4ViQBcMtbwq3ce19gDr2f23MqGZEQZtaD/eSQ9UNEhx09nhrdYxWDg==} cpu: [x64] os: [linux] libc: [musl] - '@nx/nx-win32-arm64-msvc@23.1.0': - resolution: {integrity: sha512-lhnRaXPGUwqw/dqBnWl/6d6r8mRQXuZS7qnnTd+U5O1R7YPb2494BQyE7aSVEFLHcX9nXywMGxo5+OUCH84xQA==} + '@nx/nx-win32-arm64-msvc@23.1.1': + resolution: {integrity: sha512-iDlYbFHgTYV5lg1ypEt+LAj86o/uyy6vR0ha5pcUs4FqXzQgy14lOeyRod/EZs9Er3DIyJlEi/rpEvaP99/Hag==} cpu: [arm64] os: [win32] - '@nx/nx-win32-x64-msvc@23.1.0': - resolution: {integrity: sha512-fJaNYwNk4RiUnyEDTc0bMu69dmUzgM7iGinoqFenwYEtwaXPWREBRWL6lgRDyR3CFsJw3Wi0uc+33cfreTbhVw==} + '@nx/nx-win32-x64-msvc@23.1.1': + resolution: {integrity: sha512-UD21AHWJ2PEA+PuANPCt+lj3kYpAzYNq+bm4VCbrt3KZd7zDPas0ns85UIhfrhsNiSmYzjWz2/JDk2S3cA6lGw==} cpu: [x64] os: [win32] @@ -6288,6 +6293,9 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.144.0': + resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==} + '@oxc-resolver/binding-android-arm-eabi@11.21.3': resolution: {integrity: sha512-eNU11A2WNizh04v3uyaJCootrHIaS0B9aHYXvAvVnPNk4xYSjMUjHnhQ6dewPN2MRYDskV85d1N0Aw0WNWhcyg==} cpu: [arm] @@ -7691,6 +7699,12 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.2.4': + resolution: {integrity: sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.0-beta.53': resolution: {integrity: sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7709,6 +7723,12 @@ packages: cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.2.4': + resolution: {integrity: sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-beta.53': resolution: {integrity: sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7727,6 +7747,12 @@ packages: cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.2.4': + resolution: {integrity: sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0-beta.53': resolution: {integrity: sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7745,6 +7771,12 @@ packages: cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.2.4': + resolution: {integrity: sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': resolution: {integrity: sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7763,6 +7795,12 @@ packages: cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.2.4': + resolution: {integrity: sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': resolution: {integrity: sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7784,6 +7822,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.2.4': + resolution: {integrity: sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': resolution: {integrity: sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7805,6 +7850,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.2.4': + resolution: {integrity: sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.1.5': resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7812,6 +7864,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.2.4': + resolution: {integrity: sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.1.5': resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7819,6 +7878,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.2.4': + resolution: {integrity: sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': resolution: {integrity: sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7840,6 +7906,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.2.4': + resolution: {integrity: sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': resolution: {integrity: sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7861,6 +7934,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-x64-musl@1.2.4': + resolution: {integrity: sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': resolution: {integrity: sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7879,6 +7959,12 @@ packages: cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.2.4': + resolution: {integrity: sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': resolution: {integrity: sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==} engines: {node: '>=14.0.0'} @@ -7912,6 +7998,12 @@ packages: cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.2.4': + resolution: {integrity: sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': resolution: {integrity: sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7930,6 +8022,12 @@ packages: cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.2.4': + resolution: {integrity: sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} @@ -7939,6 +8037,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.53': resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + '@rolldown/pluginutils@1.0.0-rc.4': resolution: {integrity: sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==} @@ -9213,8 +9314,8 @@ packages: peerDependencies: preact: '>=10 || ^10.0.0-alpha.0 || ^10.0.0-beta.0' - '@testing-library/react@16.3.0': - resolution: {integrity: sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==} + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} engines: {node: '>=18'} peerDependencies: '@testing-library/dom': ^10.0.0 @@ -9398,9 +9499,6 @@ packages: '@types/node@18.19.130': resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - '@types/node@20.19.26': - resolution: {integrity: sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg==} - '@types/node@24.10.3': resolution: {integrity: sha512-gqkrWUsS8hcm0r44yn7/xZeV1ERva/nLgrLxFRUGb7aoNMIJfZJ3AC261zDQuOAKC7MiXai1WCpYc48jAHoShQ==} @@ -9732,24 +9830,24 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitejs/plugin-react@5.1.2': - resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} + '@vitejs/plugin-react@5.2.0': + resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - '@vitejs/plugin-vue@6.0.3': - resolution: {integrity: sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==} + '@vitejs/plugin-vue@6.0.8': + resolution: {integrity: sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vue: ^3.2.25 - '@vitest/coverage-v8@4.0.14': - resolution: {integrity: sha512-EYHLqN/BY6b47qHH7gtMxAg++saoGmsjWmAq9MlXxAz4M0NcHh9iOyKhBZyU4yxZqOd8Xnqp80/5saeitz4Cng==} + '@vitest/coverage-v8@4.1.10': + resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} peerDependencies: - '@vitest/browser': 4.0.14 - vitest: 4.0.14 + '@vitest/browser': 4.1.10 + vitest: 4.1.10 peerDependenciesMeta: '@vitest/browser': optional: true @@ -9768,9 +9866,6 @@ packages: vite: optional: true - '@vitest/pretty-format@4.0.14': - resolution: {integrity: sha512-SOYPgujB6TITcJxgd3wmsLl+wZv+fy3av2PpiPpsWPZ6J1ySUYfScfpIt2Yv56ShJXR2MOA6q2KjKHN4EpdyRQ==} - '@vitest/pretty-format@4.1.10': resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} @@ -9783,9 +9878,6 @@ packages: '@vitest/spy@4.1.10': resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - '@vitest/utils@4.0.14': - resolution: {integrity: sha512-hLqXZKAWNg8pI+SQXyXxWCTOpA3MvsqcbVeNgSi8x/CSN2wi26dSzn1wrOhmCmFjEvN9p8/kLFRHa6PI8jHazw==} - '@vitest/utils@4.1.10': resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} @@ -10068,8 +10160,8 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} - ast-v8-to-istanbul@0.3.11: - resolution: {integrity: sha512-Qya9fkoofMjCBNVdWINMjB5KZvkYfaO9/anwkWnjxibpWUxo5iHl2sOdP7/uAqaRuUYuoo8rDwnbaaKVFxoUvw==} + ast-v8-to-istanbul@1.0.5: + resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==} async-retry@1.3.3: resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} @@ -10101,9 +10193,6 @@ packages: aws4fetch@1.0.20: resolution: {integrity: sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==} - axios@1.16.1: - resolution: {integrity: sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==} - axios@1.18.1: resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} @@ -10324,6 +10413,10 @@ packages: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.8: + resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==} + engines: {node: 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -10349,6 +10442,10 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-image-size@0.6.4: + resolution: {integrity: sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==} + engines: {node: '>=4.0'} + buffer@5.6.0: resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} @@ -10365,6 +10462,10 @@ packages: bun-types@1.3.14: resolution: {integrity: sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ==} + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -10985,6 +11086,14 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -10996,6 +11105,10 @@ packages: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -11314,6 +11427,10 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -11840,10 +11957,6 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} - form-data@4.0.6: resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} @@ -12099,8 +12212,8 @@ packages: crossws: optional: true - happy-dom@20.0.11: - resolution: {integrity: sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==} + happy-dom@20.11.2: + resolution: {integrity: sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw==} engines: {node: '>=20.0.0'} has-bigints@1.1.0: @@ -12126,10 +12239,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} @@ -12205,9 +12314,9 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} - html-encoding-sniffer@4.0.0: - resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} - engines: {node: '>=18'} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} @@ -12618,10 +12727,6 @@ packages: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@5.0.6: - resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} - engines: {node: '>=10'} - istanbul-reports@3.2.0: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} @@ -12716,8 +12821,8 @@ packages: '@babel/preset-env': optional: true - jsdom@27.3.0: - resolution: {integrity: sha512-GtldT42B8+jefDUC4yUKAvsaOrH7PDHmZxZXNgF2xMmymjUbRYJvpAybZAKEmXDGTM0mCsz8duOa4vTm5AY2Kg==} + jsdom@27.4.0: + resolution: {integrity: sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: canvas: ^3.0.0 @@ -12856,8 +12961,8 @@ packages: cpu: [arm64] os: [android] - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] @@ -12868,8 +12973,8 @@ packages: cpu: [arm64] os: [darwin] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] @@ -12880,8 +12985,8 @@ packages: cpu: [x64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] @@ -12892,8 +12997,8 @@ packages: cpu: [x64] os: [freebsd] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] @@ -12904,8 +13009,8 @@ packages: cpu: [arm] os: [linux] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] @@ -12917,8 +13022,8 @@ packages: os: [linux] libc: [glibc] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] @@ -12931,8 +13036,8 @@ packages: os: [linux] libc: [musl] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] @@ -12945,8 +13050,8 @@ packages: os: [linux] libc: [glibc] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] @@ -12959,8 +13064,8 @@ packages: os: [linux] libc: [musl] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] @@ -12972,8 +13077,8 @@ packages: cpu: [arm64] os: [win32] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] @@ -12984,8 +13089,8 @@ packages: cpu: [x64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] @@ -12994,8 +13099,8 @@ packages: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} lilconfig@3.1.3: @@ -13620,6 +13725,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} @@ -13795,8 +13905,8 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} - nx@23.1.0: - resolution: {integrity: sha512-Z4hzIdRF6naDDpOTOazrJODmbU5D7slq94FR5q/dySW+evGxiOSFLO981VqDVvtNEvHPnEDh/C1wvFseWyvSrQ==} + nx@23.1.1: + resolution: {integrity: sha512-oDdW2JgVllgfyyN6OqlRzeABw0QrlXdxyl9rtOUMMXQzlkpYA1RTs8jinJCe6QSo7aEn0dZ+Ar7dd09hMudBsg==} hasBin: true peerDependencies: '@swc-node/register': ^1.11.1 @@ -13888,6 +13998,10 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} + open@7.4.2: resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} engines: {node: '>=8'} @@ -14239,6 +14353,10 @@ packages: resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.26: + resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} + engines: {node: ^10 || ^12 || >=14} + postgres@3.4.7: resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} engines: {node: '>=12'} @@ -14790,6 +14908,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.2.4: + resolution: {integrity: sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup-plugin-dts@6.4.1: resolution: {integrity: sha512-l//F3Zf7ID5GoOfLfD8kroBjQKEKpy1qfhtAdnpibFZMffPaylrg1CoDC2vGkPeTeyxUe4bVFCln2EFuL7IGGg==} engines: {node: '>=20'} @@ -14830,6 +14953,10 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -15477,10 +15604,6 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinyglobby@0.2.16: - resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} - engines: {node: '>=12.0.0'} - tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -15644,6 +15767,11 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tsx@4.23.12: + resolution: {integrity: sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==} + engines: {node: '>=18.0.0'} + hasBin: true + tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -15755,9 +15883,6 @@ packages: undici-types@5.28.4: resolution: {integrity: sha512-3OeMF5Lyowe8VW0skf5qaIE7Or3yS9LS7fvMUI0gg4YxpIBVg0L8BxCmROw2CcYhSkpR68Epz7CGc8MPj94Uww==} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -15769,6 +15894,10 @@ packages: resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} engines: {node: '>=20.18.1'} + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} + engines: {node: '>=20.18.1'} + unenv@1.10.0: resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==} @@ -16137,12 +16266,12 @@ packages: peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - vite-plugin-solid@2.11.10: - resolution: {integrity: sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw==} + vite-plugin-solid@2.11.14: + resolution: {integrity: sha512-7ZVBt8rpoyqmlwin2kRIUveaHoF6/kulY7gsnD+qFh4nS29V4OPAnw+ojoAspXIjObiL9o1xh9a/nTuYHm02Rw==} peerDependencies: - '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.0.0 || ^7.0.0 solid-js: ^1.7.2 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 peerDependenciesMeta: '@testing-library/jest-dom': optional: true @@ -16200,46 +16329,6 @@ packages: yaml: optional: true - vite@7.3.3: - resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - vite@7.3.6: resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -16280,13 +16369,13 @@ packages: yaml: optional: true - vite@8.1.4: - resolution: {integrity: sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==} + vite@8.2.1: + resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.3.0 + '@vitejs/devtools': ^0.4.0 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -16765,8 +16854,8 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@analogjs/vite-plugin-angular@2.6.3(@angular/build@21.2.20(6306034858a4461af901a78c987641b8))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': - dependencies: + ? '@analogjs/vite-plugin-angular@2.6.3(@angular/build@21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.26)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))' + : dependencies: magic-string: 0.30.21 obug: 2.1.1 oxc-parser: 0.121.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) @@ -16774,13 +16863,13 @@ snapshots: ts-morph: 21.0.1 typescript: 5.9.3 optionalDependencies: - '@angular/build': 21.2.20(6306034858a4461af901a78c987641b8) - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + '@angular/build': 21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.26)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' - '@analogjs/vite-plugin-angular@2.6.3(@angular/build@21.2.20(7176eabe523c375be6c990a7b771f135))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@analogjs/vite-plugin-angular@2.6.3(a8e4d9beea01c48751a3f4ef1beb3aea)': dependencies: magic-string: 0.30.21 obug: 2.1.1 @@ -16789,20 +16878,20 @@ snapshots: ts-morph: 21.0.1 typescript: 5.9.3 optionalDependencies: - '@angular/build': 21.2.20(7176eabe523c375be6c990a7b771f135) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + '@angular/build': 21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.19)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' - '@angular-devkit/architect@0.2102.20(chokidar@5.0.0)': + '@angular-devkit/architect@0.2102.21(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.20(chokidar@5.0.0) + '@angular-devkit/core': 21.2.21(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular-devkit/core@21.2.20(chokidar@5.0.0)': + '@angular-devkit/core@21.2.21(chokidar@5.0.0)': dependencies: ajv: 8.18.0 ajv-formats: 3.0.1(ajv@8.18.0) @@ -16813,17 +16902,17 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular/build@21.2.20(6306034858a4461af901a78c987641b8)': + '@angular/build@21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.19)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2102.20(chokidar@5.0.0) - '@angular/compiler': 21.2.19 - '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3) + '@angular-devkit/architect': 0.2102.21(chokidar@5.0.0) + '@angular/compiler': 21.2.20 + '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3) '@babel/core': 7.29.7 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 '@inquirer/confirm': 5.1.21(@types/node@24.10.3) - '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) beasties: 0.4.1 browserslist: 4.28.1 esbuild: 0.28.1 @@ -16843,18 +16932,18 @@ snapshots: tinyglobby: 0.2.15 tslib: 2.8.1 typescript: 5.9.3 - undici: 7.28.0 - vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + undici: 7.29.0 + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) watchpack: 2.5.1 optionalDependencies: - '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)) less: 4.6.6 lmdb: 3.5.1 - ng-packagr: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) + ng-packagr: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) postcss: 8.5.19 tailwindcss: 4.1.18 - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.19))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -16870,17 +16959,17 @@ snapshots: - tsx - yaml - '@angular/build@21.2.20(7176eabe523c375be6c990a7b771f135)': + '@angular/build@21.2.21(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.10.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3))(postcss@8.5.26)(tailwindcss@4.1.18)(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.12)(typescript@5.9.3)(vitest@4.1.10)(yaml@2.9.0)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2102.20(chokidar@5.0.0) - '@angular/compiler': 21.2.19 - '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3) + '@angular-devkit/architect': 0.2102.21(chokidar@5.0.0) + '@angular/compiler': 21.2.20 + '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3) '@babel/core': 7.29.7 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 '@inquirer/confirm': 5.1.21(@types/node@24.10.3) - '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) beasties: 0.4.1 browserslist: 4.28.1 esbuild: 0.28.1 @@ -16900,18 +16989,18 @@ snapshots: tinyglobby: 0.2.15 tslib: 2.8.1 typescript: 5.9.3 - undici: 7.28.0 - vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + undici: 7.29.0 + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) watchpack: 2.5.1 optionalDependencies: - '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)) less: 4.6.6 lmdb: 3.5.1 - ng-packagr: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) - postcss: 8.5.19 + ng-packagr: 21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3) + postcss: 8.5.26 tailwindcss: 4.1.18 - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -16927,16 +17016,16 @@ snapshots: - tsx - yaml - '@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + '@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3)': + '@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3)': dependencies: - '@angular/compiler': 21.2.19 - '@babel/core': 7.29.0 + '@angular/compiler': 21.2.20 + '@babel/core': 7.29.0(supports-color@7.2.0) '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 5.0.0 convert-source-map: 1.9.0 @@ -16949,39 +17038,39 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/compiler@21.2.19': + '@angular/compiler@21.2.20': dependencies: tslib: 2.8.1 - '@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)': + '@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 21.2.19 + '@angular/compiler': 21.2.20 zone.js: 0.15.1 - '@angular/forms@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/forms@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)) '@standard-schema/spec': 1.1.0 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/platform-browser-dynamic@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)))': + '@angular/platform-browser-dynamic@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)))': dependencies: - '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/compiler': 21.2.19 - '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/compiler': 21.2.20 + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1)) tslib: 2.8.1 - '@angular/platform-browser@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))': + '@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))': dependencies: - '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 '@anthropic-ai/sdk@0.97.1(zod@4.2.1)': @@ -17433,32 +17522,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.0) - '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@7.2.0) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/core@7.29.0(supports-color@7.2.0)': dependencies: '@babel/code-frame': 7.29.7 '@babel/generator': 7.29.7 '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.0(supports-color@7.2.0)) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.0) '@babel/helpers': 7.29.7 '@babel/parser': 7.29.7 '@babel/template': 7.29.7 @@ -17582,7 +17651,7 @@ snapshots: '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 @@ -17663,7 +17732,7 @@ snapshots: '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5(supports-color@7.2.0))': dependencies: '@babel/core': 7.28.5(supports-color@7.2.0) - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.7 transitivePeerDependencies: @@ -17672,7 +17741,7 @@ snapshots: '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.7 transitivePeerDependencies: @@ -17680,8 +17749,8 @@ snapshots: '@babel/helper-module-transforms@7.28.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.27.1 + '@babel/core': 7.29.0(supports-color@7.2.0) + '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.7 transitivePeerDependencies: @@ -17690,15 +17759,6 @@ snapshots: '@babel/helper-module-transforms@7.28.3(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.0(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.7 @@ -17707,7 +17767,7 @@ snapshots: '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.7 @@ -17775,7 +17835,7 @@ snapshots: '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 '@babel/traverse': 7.29.7 @@ -17897,7 +17957,7 @@ snapshots: '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.29.7)': @@ -17907,7 +17967,7 @@ snapshots: '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': @@ -17932,7 +17992,7 @@ snapshots: '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.29.7)': @@ -18047,7 +18107,7 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-module-transforms': 7.28.3(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: @@ -18151,24 +18211,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0(supports-color@7.2.0))': - dependencies: - '@babel/core': 7.29.0(supports-color@7.2.0) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0(supports-color@7.2.0))': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0(supports-color@7.2.0) + '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7)': @@ -18213,7 +18263,7 @@ snapshots: '@babel/plugin-transform-typescript@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.29.7 @@ -18259,7 +18309,7 @@ snapshots: '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.29.0) @@ -18288,8 +18338,6 @@ snapshots: pirates: 4.0.7 source-map-support: 0.5.21 - '@babel/runtime@7.28.4': {} - '@babel/runtime@7.29.2': {} '@babel/template@7.27.2': @@ -18375,7 +18423,7 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.7.4 + semver: 7.8.4 '@changesets/assemble-release-plan@6.0.9(patch_hash=1bc53c741da20baad9cdeb674c599225dcf9fe6aa7b0de16ff87e63f12a97b24)': dependencies: @@ -18384,7 +18432,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 - semver: 7.7.4 + semver: 7.8.4 '@changesets/changelog-git@0.2.1': dependencies: @@ -18449,7 +18497,7 @@ snapshots: '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 picocolors: 1.1.1 - semver: 7.7.4 + semver: 7.8.4 '@changesets/get-github-info@0.8.0': dependencies: @@ -18540,12 +18588,12 @@ snapshots: optionalDependencies: workerd: 1.20260617.1 - '@cloudflare/vite-plugin@1.42.1(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(workerd@1.20260617.1)(wrangler@4.103.0)': + '@cloudflare/vite-plugin@1.42.1(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(workerd@1.20260617.1)(wrangler@4.103.0)': dependencies: '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260617.1) miniflare: 4.20260617.1 unenv: 2.0.0-rc.24 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) wrangler: 4.103.0(@cloudflare/workers-types@4.20260317.1) ws: 8.21.0 transitivePeerDependencies: @@ -18585,9 +18633,9 @@ snapshots: '@cloudflare/workers-types@4.20260317.1': {} - '@copilotkit/aimock@1.34.0(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))': + '@copilotkit/aimock@1.34.0(vitest@4.1.10)': optionalDependencies: - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@crazydos/vue-markdown@1.1.4(vue@3.5.25(typescript@5.9.3))': dependencies: @@ -18626,6 +18674,11 @@ snapshots: '@csstools/css-syntax-patches-for-csstree@1.0.14(postcss@8.5.19)': dependencies: postcss: 8.5.19 + optional: true + + '@csstools/css-syntax-patches-for-csstree@1.0.14(postcss@8.5.26)': + dependencies: + postcss: 8.5.26 '@csstools/css-tokenizer@3.0.4': {} @@ -18633,7 +18686,7 @@ snapshots: '@daytona/api-client@0.191.0': dependencies: - axios: 1.18.1 + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: - debug - supports-color @@ -18653,7 +18706,7 @@ snapshots: '@opentelemetry/sdk-node': 0.217.0(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-base': 2.8.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.41.1 - axios: 1.18.1 + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) busboy: 1.6.0 dotenv: 17.4.2 expand-tilde: 2.0.2 @@ -18670,7 +18723,7 @@ snapshots: '@daytona/toolbox-api-client@0.191.0': dependencies: - axios: 1.18.1 + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: - debug - supports-color @@ -19100,6 +19153,8 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@exodus/bytes@1.15.1': {} + '@expo/cli@56.1.12(@expo/dom-webview@56.0.5)(expo-constants@56.0.16(expo@56.0.5)(react-native@0.85.3(@babel/core@7.29.7)(@types/react@19.2.7)(react@19.2.3)(supports-color@7.2.0)))(expo-font@56.0.5(expo@56.0.5)(react-native@0.85.3(@babel/core@7.29.7)(@types/react@19.2.7)(react@19.2.3)(supports-color@7.2.0))(react@19.2.3))(expo@56.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.85.3(@babel/core@7.29.7)(@types/react@19.2.7)(react@19.2.3)(supports-color@7.2.0))(react@19.2.3)(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@expo/code-signing-certificates': 0.0.6 @@ -19404,7 +19459,7 @@ snapshots: '@expo/metro-config@56.0.13(expo@56.0.5)(typescript@5.9.3)': dependencies: '@babel/code-frame': 7.29.0 - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/generator': 7.29.1 '@expo/config': 56.0.9(typescript@5.9.3) '@expo/env': 2.3.0 @@ -19505,8 +19560,8 @@ snapshots: '@expo/require-utils@56.1.3(typescript@5.9.3)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/core': 7.29.0 - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.29.7) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -19904,7 +19959,7 @@ snapshots: '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.2 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -20239,34 +20294,34 @@ snapshots: '@nothing-but/utils@0.17.0': {} - '@nx/nx-darwin-arm64@23.1.0': + '@nx/nx-darwin-arm64@23.1.1': optional: true - '@nx/nx-darwin-x64@23.1.0': + '@nx/nx-darwin-x64@23.1.1': optional: true - '@nx/nx-freebsd-x64@23.1.0': + '@nx/nx-freebsd-x64@23.1.1': optional: true - '@nx/nx-linux-arm-gnueabihf@23.1.0': + '@nx/nx-linux-arm-gnueabihf@23.1.1': optional: true - '@nx/nx-linux-arm64-gnu@23.1.0': + '@nx/nx-linux-arm64-gnu@23.1.1': optional: true - '@nx/nx-linux-arm64-musl@23.1.0': + '@nx/nx-linux-arm64-musl@23.1.1': optional: true - '@nx/nx-linux-x64-gnu@23.1.0': + '@nx/nx-linux-x64-gnu@23.1.1': optional: true - '@nx/nx-linux-x64-musl@23.1.0': + '@nx/nx-linux-x64-musl@23.1.1': optional: true - '@nx/nx-win32-arm64-msvc@23.1.0': + '@nx/nx-win32-arm64-msvc@23.1.1': optional: true - '@nx/nx-win32-x64-msvc@23.1.0': + '@nx/nx-win32-x64-msvc@23.1.1': optional: true '@one-ini/wasm@0.1.1': {} @@ -20718,6 +20773,8 @@ snapshots: '@oxc-project/types@0.139.0': {} + '@oxc-project/types@0.144.0': {} + '@oxc-resolver/binding-android-arm-eabi@11.21.3': optional: true @@ -22028,6 +22085,9 @@ snapshots: '@rolldown/binding-android-arm64@1.1.5': optional: true + '@rolldown/binding-android-arm64@1.2.4': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-beta.53': optional: true @@ -22037,6 +22097,9 @@ snapshots: '@rolldown/binding-darwin-arm64@1.1.5': optional: true + '@rolldown/binding-darwin-arm64@1.2.4': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-beta.53': optional: true @@ -22046,6 +22109,9 @@ snapshots: '@rolldown/binding-darwin-x64@1.1.5': optional: true + '@rolldown/binding-darwin-x64@1.2.4': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-beta.53': optional: true @@ -22055,6 +22121,9 @@ snapshots: '@rolldown/binding-freebsd-x64@1.1.5': optional: true + '@rolldown/binding-freebsd-x64@1.2.4': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': optional: true @@ -22064,6 +22133,9 @@ snapshots: '@rolldown/binding-linux-arm-gnueabihf@1.1.5': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.2.4': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': optional: true @@ -22073,6 +22145,9 @@ snapshots: '@rolldown/binding-linux-arm64-gnu@1.1.5': optional: true + '@rolldown/binding-linux-arm64-gnu@1.2.4': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': optional: true @@ -22082,12 +22157,21 @@ snapshots: '@rolldown/binding-linux-arm64-musl@1.1.5': optional: true + '@rolldown/binding-linux-arm64-musl@1.2.4': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.1.5': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.2.4': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.1.5': optional: true + '@rolldown/binding-linux-s390x-gnu@1.2.4': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': optional: true @@ -22097,6 +22181,9 @@ snapshots: '@rolldown/binding-linux-x64-gnu@1.1.5': optional: true + '@rolldown/binding-linux-x64-gnu@1.2.4': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': optional: true @@ -22106,6 +22193,9 @@ snapshots: '@rolldown/binding-linux-x64-musl@1.1.5': optional: true + '@rolldown/binding-linux-x64-musl@1.2.4': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': optional: true @@ -22115,6 +22205,9 @@ snapshots: '@rolldown/binding-openharmony-arm64@1.1.5': optional: true + '@rolldown/binding-openharmony-arm64@1.2.4': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-beta.53(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) @@ -22147,6 +22240,9 @@ snapshots: '@rolldown/binding-win32-arm64-msvc@1.1.5': optional: true + '@rolldown/binding-win32-arm64-msvc@1.2.4': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': optional: true @@ -22156,12 +22252,17 @@ snapshots: '@rolldown/binding-win32-x64-msvc@1.1.5': optional: true + '@rolldown/binding-win32-x64-msvc@1.2.4': + 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.3': {} + '@rolldown/pluginutils@1.0.0-rc.4': {} '@rolldown/pluginutils@1.0.1': {} @@ -22627,16 +22728,16 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))': + '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))': dependencies: - '@sveltejs/kit': 2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/kit': 2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) import-meta-resolve: 4.2.0 - '@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 @@ -22649,7 +22750,7 @@ snapshots: set-cookie-parser: 2.7.2 sirv: 3.0.2 svelte: 5.45.10 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) optionalDependencies: '@opentelemetry/api': 1.9.1 @@ -22663,47 +22764,47 @@ snapshots: svelte2tsx: 0.7.45(@typescript/typescript6@6.0.2)(svelte@5.45.10) typescript: '@typescript/typescript6@6.0.2' - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) debug: 4.4.3(supports-color@7.2.0) svelte: 5.45.10 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) debug: 4.4.3(supports-color@7.2.0) svelte: 5.45.10 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(supports-color@7.2.0)(svelte@5.45.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) debug: 4.4.3(supports-color@7.2.0) deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 svelte: 5.45.10 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(svelte@5.45.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(svelte@5.45.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) debug: 4.4.3(supports-color@7.2.0) deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 svelte: 5.45.10 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color @@ -22770,26 +22871,26 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tailwindcss/vite@4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - '@tailwindcss/vite@4.1.18(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tailwindcss/vite@4.1.18(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - '@tailwindcss/vite@4.1.18(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tailwindcss/vite@4.1.18(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) '@tanstack/db-ivm@0.1.18(typescript@5.9.3)': dependencies: @@ -22870,7 +22971,7 @@ snapshots: solid-js: 1.9.10 vue: 3.5.25(typescript@7.0.2) - '@tanstack/devtools-vite@0.5.3(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/devtools-vite@0.5.3(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/core': 7.28.5 '@babel/generator': 7.28.5 @@ -22882,13 +22983,13 @@ snapshots: chalk: 5.6.2 launch-editor: 2.12.0 picomatch: 4.0.3 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@tanstack/devtools-vite@0.5.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/devtools-vite@0.5.3(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/core': 7.28.5 '@babel/generator': 7.28.5 @@ -22900,7 +23001,7 @@ snapshots: chalk: 5.6.2 launch-editor: 2.12.0 picomatch: 4.0.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - bufferutil - supports-color @@ -22938,30 +23039,30 @@ snapshots: - csstype - utf-8-validate - '@tanstack/directive-functions-plugin@1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/directive-functions-plugin@1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.27.1 - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 '@tanstack/router-utils': 1.131.2 babel-dead-code-elimination: 1.0.12 tiny-invariant: 1.3.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@tanstack/directive-functions-plugin@1.141.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/directive-functions-plugin@1.141.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.27.1 - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 '@tanstack/router-utils': 1.141.0 babel-dead-code-elimination: 1.0.12 pathe: 2.0.3 tiny-invariant: 1.3.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -22971,11 +23072,11 @@ snapshots: '@tanstack/history@1.154.14': {} - '@tanstack/nitro-v2-vite-plugin@1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/nitro-v2-vite-plugin@1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5) + nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4) pathe: 2.0.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -23007,11 +23108,11 @@ snapshots: - uploadthing - xml2js - '@tanstack/nitro-v2-vite-plugin@1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/nitro-v2-vite-plugin@1.155.0(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5) pathe: 2.0.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -23144,12 +23245,12 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/react-start-plugin@1.131.50(ca145db0ed4fe17ae9305fb3c3f34b9c)': + '@tanstack/react-start-plugin@1.131.50(e7a157c953e155a2765d901b34df38b3)': dependencies: - '@tanstack/start-plugin-core': 1.131.50(1b6c6d12f54334d0121e3887f2ab8ba8) - '@vitejs/plugin-react': 4.7.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/start-plugin-core': 1.131.50(1a1cdd8b9c2c533357f243540b1932ef) + '@vitejs/plugin-react': 4.7.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) pathe: 2.0.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: 3.25.76 transitivePeerDependencies: - '@azure/app-configuration' @@ -23186,11 +23287,11 @@ snapshots: - webpack - xml2js - '@tanstack/react-start-router-manifest@1.120.19(91b39b40f4efbadaf93b05367f1ce328)': + '@tanstack/react-start-router-manifest@1.120.19(e2865e417d15aa2efdac89fcc0288f0b)': dependencies: '@tanstack/router-core': 1.159.4 tiny-invariant: 1.3.3 - vinxi: 0.5.3(91b39b40f4efbadaf93b05367f1ce328) + vinxi: 0.5.3(e2865e417d15aa2efdac89fcc0288f0b) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -23260,19 +23361,19 @@ snapshots: transitivePeerDependencies: - crossws - '@tanstack/react-start@1.159.5(crossws@0.4.6(srvx@0.11.17))(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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/react-start@1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': 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.6(srvx@0.11.17))(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.6(srvx@0.11.17))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@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.17))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.17)) pathe: 2.0.3 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@rsbuild/core' - crossws @@ -23280,19 +23381,19 @@ snapshots: - vite-plugin-solid - webpack - '@tanstack/react-start@1.159.5(crossws@0.4.6(srvx@0.11.17))(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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/react-start@1.159.5(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': 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.6(srvx@0.11.17))(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.6(srvx@0.11.17))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@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.17))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.17)) pathe: 2.0.3 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@rsbuild/core' - crossws @@ -23395,11 +23496,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.131.50(@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/router-plugin@1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.7) '@babel/template': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 @@ -23413,16 +23514,16 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-solid: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vite-plugin-solid: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.141.1(@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/router-plugin@1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.7) '@babel/template': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 @@ -23436,14 +23537,14 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-solid: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vite-plugin-solid: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@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))(supports-color@7.2.0)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) '@babel/template': 7.29.7 @@ -23458,14 +23559,14 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-solid: 2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vite-plugin-solid: 2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) '@babel/template': 7.29.7 @@ -23480,8 +23581,8 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-solid: 2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vite-plugin-solid: 2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color @@ -23497,10 +23598,10 @@ snapshots: '@tanstack/router-utils@1.131.2': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 - '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.7) ansis: 4.2.0 diff: 8.0.2 transitivePeerDependencies: @@ -23508,10 +23609,10 @@ snapshots: '@tanstack/router-utils@1.141.0': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 - '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.7) ansis: 4.2.0 diff: 8.0.2 pathe: 2.0.3 @@ -23521,7 +23622,7 @@ snapshots: '@tanstack/router-utils@1.158.0': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 '@babel/types': 7.29.7 @@ -23533,32 +23634,32 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/server-functions-plugin@1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/server-functions-plugin@1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.27.1 - '@babel/core': 7.29.0 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.7) '@babel/template': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 - '@tanstack/directive-functions-plugin': 1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/directive-functions-plugin': 1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) babel-dead-code-elimination: 1.0.10 tiny-invariant: 1.3.3 transitivePeerDependencies: - supports-color - vite - '@tanstack/server-functions-plugin@1.141.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/server-functions-plugin@1.141.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.27.1 - '@babel/core': 7.29.0 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.7) '@babel/template': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 - '@tanstack/directive-functions-plugin': 1.141.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/directive-functions-plugin': 1.141.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) babel-dead-code-elimination: 1.0.10 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -23637,17 +23738,17 @@ snapshots: 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.6(srvx@0.11.17))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@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.17))(solid-js@1.9.10)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': 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.6(srvx@0.11.17))(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.6(srvx@0.11.17))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@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.17))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.17)) pathe: 2.0.3 solid-js: 1.9.10 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -23661,11 +23762,11 @@ snapshots: '@tanstack/store': 0.8.0 solid-js: 1.9.10 - '@tanstack/start-api-routes@1.120.19(abae81bc69f4a97f0a6e0125a81866f1)': + '@tanstack/start-api-routes@1.120.19(91e012b4b7f2d471a11b1e1ea02d5103)': dependencies: '@tanstack/router-core': 1.159.4 '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.17)) - vinxi: 0.5.3(91b39b40f4efbadaf93b05367f1ce328) + vinxi: 0.5.3(e2865e417d15aa2efdac89fcc0288f0b) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -23737,22 +23838,22 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/start-config@1.120.20(525aa2ef7692c9b3e6ea9eb659ae95d8)': + '@tanstack/start-config@1.120.20(340eefabdbae5b0c948fd6f8943277d1)': 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(ca145db0ed4fe17ae9305fb3c3f34b9c) + '@tanstack/react-start-plugin': 1.131.50(e7a157c953e155a2765d901b34df38b3) '@tanstack/router-generator': 1.159.4 - '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) - '@tanstack/server-functions-plugin': 1.141.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.141.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-functions-handler': 1.120.19(crossws@0.4.6(srvx@0.11.17)) - '@vitejs/plugin-react': 4.7.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitejs/plugin-react': 4.7.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) import-meta-resolve: 4.2.0 - nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5) + nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4) ofetch: 1.5.1 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - vinxi: 0.5.3(91b39b40f4efbadaf93b05367f1ce328) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vinxi: 0.5.3(e2865e417d15aa2efdac89fcc0288f0b) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: 3.25.76 transitivePeerDependencies: - '@azure/app-configuration' @@ -23805,27 +23906,27 @@ snapshots: '@tanstack/start-fn-stubs@1.154.7': {} - '@tanstack/start-plugin-core@1.131.50(1b6c6d12f54334d0121e3887f2ab8ba8)': + '@tanstack/start-plugin-core@1.131.50(1a1cdd8b9c2c533357f243540b1932ef)': dependencies: '@babel/code-frame': 7.26.2 - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/types': 7.29.7 '@tanstack/router-core': 1.131.50 '@tanstack/router-generator': 1.131.50 - '@tanstack/router-plugin': 1.131.50(@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.131.50(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/router-utils': 1.131.2 - '@tanstack/server-functions-plugin': 1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-core': 1.131.50 '@types/babel__code-frame': 7.0.6 '@types/babel__core': 7.20.5 babel-dead-code-elimination: 1.0.12 cheerio: 1.1.2 h3: 1.13.0 - nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5) + nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4) pathe: 2.0.3 ufo: 1.6.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) xmlbuilder2: 3.1.1 zod: 3.25.76 transitivePeerDependencies: @@ -23863,17 +23964,17 @@ 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.6(srvx@0.11.17))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@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.17))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.26.2 - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/types': 7.29.0 '@rolldown/pluginutils': 1.0.0-beta.40 '@tanstack/router-core': 1.141.1 '@tanstack/router-generator': 1.141.1 - '@tanstack/router-plugin': 1.141.1(@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/router-utils': 1.141.0 - '@tanstack/server-functions-plugin': 1.141.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.141.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-client-core': 1.141.1 '@tanstack/start-server-core': 1.141.1(crossws@0.4.6(srvx@0.11.17)) babel-dead-code-elimination: 1.0.10 @@ -23883,8 +23984,8 @@ snapshots: srvx: 0.8.16 tinyglobby: 0.2.17 ufo: 1.6.1 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) xmlbuilder2: 4.0.3 zod: 3.25.76 transitivePeerDependencies: @@ -23895,15 +23996,15 @@ 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.6(srvx@0.11.17))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@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.17))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.27.1 - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/types': 7.29.7 '@rolldown/pluginutils': 1.0.0-beta.40 '@tanstack/router-core': 1.159.4 '@tanstack/router-generator': 1.159.4 - '@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.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@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))(supports-color@7.2.0)(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/router-utils': 1.158.0 '@tanstack/start-client-core': 1.159.4 '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.17)) @@ -23913,8 +24014,8 @@ snapshots: srvx: 0.11.17 tinyglobby: 0.2.17 ufo: 1.6.3 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) xmlbuilder2: 4.0.3 zod: 3.25.76 transitivePeerDependencies: @@ -23925,15 +24026,15 @@ 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.6(srvx@0.11.17))(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@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.17))(vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@babel/code-frame': 7.27.1 - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/types': 7.29.7 '@rolldown/pluginutils': 1.0.0-beta.40 '@tanstack/router-core': 1.159.4 '@tanstack/router-generator': 1.159.4 - '@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@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@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.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/router-utils': 1.158.0 '@tanstack/start-client-core': 1.159.4 '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.17)) @@ -23943,8 +24044,8 @@ snapshots: srvx: 0.11.17 tinyglobby: 0.2.17 ufo: 1.6.3 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) xmlbuilder2: 4.0.3 zod: 3.25.76 transitivePeerDependencies: @@ -23991,9 +24092,9 @@ snapshots: transitivePeerDependencies: - crossws - '@tanstack/start-server-functions-client@1.131.50(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/start-server-functions-client@1.131.50(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@tanstack/server-functions-plugin': 1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-functions-fetcher': 1.131.50 transitivePeerDependencies: - supports-color @@ -24013,17 +24114,17 @@ snapshots: transitivePeerDependencies: - crossws - '@tanstack/start-server-functions-server@1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/start-server-functions-server@1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@tanstack/server-functions-plugin': 1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) tiny-invariant: 1.3.3 transitivePeerDependencies: - supports-color - vite - '@tanstack/start-server-functions-ssr@1.120.19(crossws@0.4.6(srvx@0.11.17))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/start-server-functions-ssr@1.120.19(crossws@0.4.6(srvx@0.11.17))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@tanstack/server-functions-plugin': 1.141.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/server-functions-plugin': 1.141.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-client-core': 1.159.4 '@tanstack/start-server-core': 1.159.4(crossws@0.4.6(srvx@0.11.17)) '@tanstack/start-server-functions-fetcher': 1.131.50 @@ -24045,17 +24146,17 @@ snapshots: dependencies: '@tanstack/router-core': 1.159.4 - '@tanstack/start@1.120.20(525aa2ef7692c9b3e6ea9eb659ae95d8)': + '@tanstack/start@1.120.20(340eefabdbae5b0c948fd6f8943277d1)': 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(91b39b40f4efbadaf93b05367f1ce328) + '@tanstack/react-start-router-manifest': 1.120.19(e2865e417d15aa2efdac89fcc0288f0b) '@tanstack/react-start-server': 1.141.1(crossws@0.4.6(srvx@0.11.17))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/start-api-routes': 1.120.19(abae81bc69f4a97f0a6e0125a81866f1) - '@tanstack/start-config': 1.120.20(525aa2ef7692c9b3e6ea9eb659ae95d8) - '@tanstack/start-server-functions-client': 1.131.50(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/start-api-routes': 1.120.19(91e012b4b7f2d471a11b1e1ea02d5103) + '@tanstack/start-config': 1.120.20(340eefabdbae5b0c948fd6f8943277d1) + '@tanstack/start-server-functions-client': 1.131.50(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@tanstack/start-server-functions-handler': 1.120.19(crossws@0.4.6(srvx@0.11.17)) - '@tanstack/start-server-functions-server': 1.131.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) - '@tanstack/start-server-functions-ssr': 1.120.19(crossws@0.4.6(srvx@0.11.17))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@tanstack/start-server-functions-server': 1.131.2(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) + '@tanstack/start-server-functions-ssr': 1.120.19(crossws@0.4.6(srvx@0.11.17))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -24125,12 +24226,12 @@ snapshots: '@tanstack/virtual-file-routes@1.154.7': {} - '@tanstack/vite-config@0.6.0(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@tanstack/vite-config@0.6.0(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vite-plugin-dts: 5.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) - vite-plugin-externalize-deps: 0.10.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) - vite-tsconfig-paths: 6.1.1(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vite-plugin-dts: 5.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) + vite-plugin-externalize-deps: 0.10.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) + vite-tsconfig-paths: 6.1.1(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - '@microsoft/api-extractor' - '@rspack/core' @@ -24174,9 +24275,9 @@ snapshots: '@testing-library/dom': 8.20.1 preact: 10.28.2 - '@testing-library/react@16.3.0(@testing-library/dom@10.4.1)(@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)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@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)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.2 '@testing-library/dom': 10.4.1 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) @@ -24378,10 +24479,6 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@20.19.26': - dependencies: - undici-types: 6.21.0 - '@types/node@24.10.3': dependencies: undici-types: 7.16.0 @@ -24786,86 +24883,71 @@ snapshots: internmap: 2.0.3 optional: true - '@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - '@vitejs/plugin-react@4.7.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitejs/plugin-react@4.7.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.7) '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - transitivePeerDependencies: - - supports-color - - '@vitejs/plugin-react@5.1.2(supports-color@7.2.0)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': - dependencies: - '@babel/core': 7.29.0(supports-color@7.2.0) - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0(supports-color@7.2.0)) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0(supports-color@7.2.0)) - '@rolldown/pluginutils': 1.0.0-beta.53 - '@types/babel__core': 7.20.5 - react-refresh: 0.18.0 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@5.1.2(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitejs/plugin-react@5.2.0(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-beta.53 + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@5.1.2(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitejs/plugin-react@5.2.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-beta.53 + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@6.0.3(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.8(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3))': dependencies: - '@rolldown/pluginutils': 1.0.0-beta.53 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + '@rolldown/pluginutils': 1.0.1 + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vue: 3.5.25(typescript@5.9.3) - '@vitejs/plugin-vue@6.0.3(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.8(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(vue@3.5.25(typescript@5.9.3))': dependencies: - '@rolldown/pluginutils': 1.0.0-beta.53 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + '@rolldown/pluginutils': 1.0.1 + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) vue: 3.5.25(typescript@5.9.3) - '@vitest/coverage-v8@4.0.14(supports-color@7.2.0)(vitest@4.1.10)': + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.0.14 - ast-v8-to-istanbul: 0.3.11 + '@vitest/utils': 4.1.10 + ast-v8-to-istanbul: 1.0.5 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6(supports-color@7.2.0) istanbul-reports: 3.2.0 magicast: 0.5.2 obug: 2.1.1 - std-env: 3.10.0 + std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) - transitivePeerDependencies: - - supports-color + vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@vitest/expect@4.1.10': dependencies: @@ -24876,34 +24958,30 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.10(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - '@vitest/mocker@4.1.10(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) optional: true - '@vitest/mocker@4.1.10(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - - '@vitest/pretty-format@4.0.14': - dependencies: - tinyrainbow: 3.1.0 + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -24923,11 +25001,6 @@ snapshots: '@vitest/spy@4.1.10': {} - '@vitest/utils@4.0.14': - dependencies: - '@vitest/pretty-format': 4.0.14 - tinyrainbow: 3.1.0 - '@vitest/utils@4.1.10': dependencies: '@vitest/pretty-format': 4.1.10 @@ -25273,7 +25346,7 @@ snapshots: dependencies: tslib: 2.8.1 - ast-v8-to-istanbul@0.3.11: + ast-v8-to-istanbul@1.0.5: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -25289,14 +25362,14 @@ snapshots: asynckit@0.4.0: {} - autoprefixer@10.4.22(postcss@8.5.19): + autoprefixer@10.4.22(postcss@8.5.26): dependencies: browserslist: 4.28.1 caniuse-lite: 1.0.30001760 fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 - postcss: 8.5.19 + postcss: 8.5.26 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -25308,17 +25381,7 @@ snapshots: aws4fetch@1.0.20: {} - axios@1.16.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0): - dependencies: - follow-redirects: 1.16.0(debug@4.4.3(supports-color@7.2.0)) - form-data: 4.0.5 - https-proxy-agent: 5.0.1(supports-color@7.2.0) - proxy-from-env: 2.1.0 - transitivePeerDependencies: - - debug - - supports-color - - axios@1.18.1: + axios@1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0): dependencies: follow-redirects: 1.16.0(debug@4.4.3(supports-color@7.2.0)) form-data: 4.0.6 @@ -25334,7 +25397,7 @@ snapshots: babel-dead-code-elimination@1.0.10: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/parser': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 @@ -25343,7 +25406,7 @@ snapshots: babel-dead-code-elimination@1.0.12: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/parser': 7.29.7 '@babel/traverse': 7.29.7 '@babel/types': 7.29.7 @@ -25352,7 +25415,7 @@ snapshots: babel-plugin-jsx-dom-expressions@0.40.3(@babel/core@7.29.0): dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-module-imports': 7.18.6 '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) '@babel/types': 7.29.7 @@ -25514,7 +25577,7 @@ snapshots: babel-preset-solid@1.9.10(@babel/core@7.29.0)(solid-js@1.9.10): dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) babel-plugin-jsx-dom-expressions: 0.40.3(@babel/core@7.29.0) optionalDependencies: solid-js: 1.9.10 @@ -25685,6 +25748,10 @@ snapshots: dependencies: balanced-match: 4.0.4 + brace-expansion@5.0.8: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -25709,6 +25776,10 @@ snapshots: buffer-from@1.1.2: {} + buffer-image-size@0.6.4: + dependencies: + '@types/node': 24.10.3 + buffer@5.6.0: dependencies: base64-js: 1.5.1 @@ -25731,6 +25802,10 @@ snapshots: dependencies: '@types/node': 24.10.3 + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + bundle-require@5.1.0(esbuild@0.27.7): dependencies: esbuild: 0.27.7 @@ -26190,6 +26265,15 @@ snapshots: css-tree: 3.1.0 transitivePeerDependencies: - postcss + optional: true + + cssstyle@5.3.4(postcss@8.5.26): + dependencies: + '@asamuzakjp/css-color': 4.1.0 + '@csstools/css-syntax-patches-for-csstree': 1.0.14(postcss@8.5.26) + css-tree: 3.1.0 + transitivePeerDependencies: + - postcss csstype@3.2.3: {} @@ -26347,6 +26431,13 @@ snapshots: deepmerge@4.3.1: {} + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + defaults@1.0.4: dependencies: clone: 1.0.4 @@ -26359,6 +26450,8 @@ snapshots: define-lazy-prop@2.0.0: {} + define-lazy-prop@3.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -26588,6 +26681,8 @@ snapshots: entities@6.0.1: {} + entities@7.0.1: {} + env-paths@2.2.1: {} env-paths@3.0.0: @@ -26649,11 +26744,11 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 esbuild-plugin-solid@0.5.0(esbuild@0.28.1)(solid-js@1.9.10): dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) babel-preset-solid: 1.9.10(@babel/core@7.29.0)(solid-js@1.9.10) esbuild: 0.28.1 @@ -27235,10 +27330,6 @@ snapshots: dependencies: pend: 1.2.0 - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 @@ -27371,14 +27462,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - form-data@4.0.6: dependencies: asynckit: 0.4.0 @@ -27480,7 +27563,7 @@ snapshots: get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-nonce@1.0.1: {} @@ -27665,11 +27748,18 @@ snapshots: optionalDependencies: crossws: 0.4.6(srvx@0.11.17) - happy-dom@20.0.11: + happy-dom@20.11.2: dependencies: - '@types/node': 20.19.26 + '@types/node': 24.10.3 '@types/whatwg-mimetype': 3.0.2 + '@types/ws': 8.18.1 + buffer-image-size: 0.6.4 + entities: 7.0.1 whatwg-mimetype: 3.0.0 + ws: 8.21.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate has-bigints@1.1.0: {} @@ -27687,10 +27777,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -27817,9 +27903,11 @@ snapshots: dependencies: lru-cache: 10.4.3 - html-encoding-sniffer@4.0.0: + html-encoding-sniffer@6.0.0: dependencies: - whatwg-encoding: 3.1.1 + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' html-entities@2.3.3: {} @@ -28110,7 +28198,7 @@ snapshots: call-bound: 1.0.4 gopd: 1.2.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 is-set@2.0.3: {} @@ -28188,7 +28276,7 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/parser': 7.29.7 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 @@ -28202,14 +28290,6 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@5.0.6(supports-color@7.2.0): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - debug: 4.4.3(supports-color@7.2.0) - istanbul-lib-coverage: 3.2.2 - transitivePeerDependencies: - - supports-color - istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 @@ -28320,14 +28400,15 @@ snapshots: transitivePeerDependencies: - supports-color - jsdom@27.3.0(postcss@8.5.19): + jsdom@27.4.0(postcss@8.5.19): dependencies: '@acemir/cssom': 0.9.29 '@asamuzakjp/dom-selector': 6.7.6 + '@exodus/bytes': 1.15.1 cssstyle: 5.3.4(postcss@8.5.19) data-urls: 6.0.0 decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 + html-encoding-sniffer: 6.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 @@ -28337,12 +28418,42 @@ snapshots: tough-cookie: 6.0.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.0 - whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 15.1.0 ws: 8.21.0 xml-name-validator: 5.0.0 transitivePeerDependencies: + - '@noble/hashes' + - bufferutil + - postcss + - supports-color + - utf-8-validate + optional: true + + jsdom@27.4.0(postcss@8.5.26): + dependencies: + '@acemir/cssom': 0.9.29 + '@asamuzakjp/dom-selector': 6.7.6 + '@exodus/bytes': 1.15.1 + cssstyle: 5.3.4(postcss@8.5.26) + data-urls: 6.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 8.0.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.0 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.21.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' - bufferutil - postcss - supports-color @@ -28373,7 +28484,7 @@ snapshots: lodash: 4.17.21 minimist: 1.2.8 prettier: 3.7.4 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 json-schema-traverse@0.4.1: {} @@ -28492,67 +28603,67 @@ snapshots: lightningcss-android-arm64@1.30.2: optional: true - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true lightningcss-darwin-arm64@1.30.2: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true lightningcss-darwin-x64@1.30.2: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true lightningcss-freebsd-x64@1.30.2: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true lightningcss-linux-arm-gnueabihf@1.30.2: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true lightningcss-linux-arm64-gnu@1.30.2: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true lightningcss-linux-arm64-musl@1.30.2: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true lightningcss-linux-x64-gnu@1.30.2: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true lightningcss-linux-x64-musl@1.30.2: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true lightningcss-win32-arm64-msvc@1.30.2: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true lightningcss-win32-x64-msvc@1.30.2: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true lightningcss@1.30.2: @@ -28571,21 +28682,21 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2 - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 lilconfig@3.1.3: {} @@ -28997,7 +29108,7 @@ snapshots: metro-babel-transformer@0.84.4: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 flow-enums-runtime: 0.0.6 hermes-parser: 0.35.0 metro-cache-key: 0.84.4 @@ -29094,7 +29205,7 @@ snapshots: metro-transform-plugins@0.84.4: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/generator': 7.29.7 '@babel/template': 7.29.7 '@babel/traverse': 7.29.7 @@ -29105,7 +29216,7 @@ snapshots: metro-transform-worker@0.84.4: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 '@babel/types': 7.29.7 @@ -29126,7 +29237,7 @@ snapshots: metro@0.84.4: dependencies: '@babel/code-frame': 7.29.7 - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 '@babel/template': 7.29.7 @@ -29557,6 +29668,8 @@ snapshots: nanoid@3.3.12: {} + nanoid@3.3.18: {} + napi-build-utils@2.0.0: optional: true @@ -29580,10 +29693,10 @@ snapshots: nf3@0.3.17: {} - ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3): + ng-packagr@21.2.5(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3))(tailwindcss@4.1.18)(tslib@2.8.1)(typescript@5.9.3): dependencies: '@ampproject/remapping': 2.3.0 - '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.19)(typescript@5.9.3) + '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.20)(typescript@5.9.3) '@rollup/plugin-json': 6.1.0(rollup@4.60.1) '@rollup/wasm-node': 4.62.0 ajv: 8.20.0 @@ -29610,7 +29723,7 @@ snapshots: rollup: 4.60.1 tailwindcss: 4.1.18 - nitro@3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0): + nitro@3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0): dependencies: consola: 3.4.2 crossws: 0.4.6(srvx@0.11.17) @@ -29631,7 +29744,7 @@ snapshots: giget: 2.0.0 jiti: 2.7.0 rollup: 4.60.1 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -29664,7 +29777,7 @@ snapshots: - uploadthing - wrangler - nitro@3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0): + nitro@3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.2.3)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@2.0.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0): dependencies: consola: 3.4.2 crossws: 0.4.6(srvx@0.11.17) @@ -29685,7 +29798,7 @@ snapshots: giget: 2.0.0 jiti: 2.7.0 rollup: 4.60.1 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -29718,7 +29831,7 @@ snapshots: - uploadthing - wrangler - nitro@3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.4.2)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@3.3.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0))(wrangler@4.103.0): + nitro@3.0.260610-beta(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(chokidar@5.0.0)(dotenv@17.4.2)(drizzle-orm@0.45.2(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(giget@3.3.0)(jiti@2.7.0)(miniflare@4.20260617.1)(mysql2@3.15.3)(rollup@4.60.1)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0))(wrangler@4.103.0): dependencies: consola: 3.4.2 crossws: 0.4.6(srvx@0.11.17) @@ -29739,7 +29852,7 @@ snapshots: giget: 3.3.0 jiti: 2.7.0 rollup: 4.60.1 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -29772,7 +29885,7 @@ snapshots: - uploadthing - wrangler - nitropack@2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5): + nitropack@2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 '@rollup/plugin-alias': 6.0.0(rollup@4.60.1) @@ -29825,7 +29938,7 @@ snapshots: pretty-bytes: 7.1.0 radix3: 1.1.2 rollup: 4.60.1 - rollup-plugin-visualizer: 6.0.5(rolldown@1.1.5)(rollup@4.60.1) + rollup-plugin-visualizer: 6.0.5(rolldown@1.2.4)(rollup@4.60.1) scule: 1.3.0 semver: 7.8.4 serve-placeholder: 2.0.2 @@ -30048,7 +30161,7 @@ snapshots: nullthrows@1.1.1: {} - nx@23.1.0: + nx@23.1.1: dependencies: '@emnapi/core': 1.4.5 '@emnapi/runtime': 1.4.5 @@ -30064,12 +30177,13 @@ snapshots: ansi-styles: 4.3.0 argparse: 2.0.1 asynckit: 0.4.0 - axios: 1.16.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) + axios: 1.18.1(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0) balanced-match: 4.0.3 base64-js: 1.5.1 bl: 4.1.0 - brace-expansion: 5.0.6 + brace-expansion: 5.0.8 buffer: 5.7.1 + bundle-name: 4.1.0 call-bind-apply-helpers: 1.0.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -30080,8 +30194,10 @@ snapshots: color-name: 1.1.4 combined-stream: 1.0.8 debug: 4.4.3(supports-color@7.2.0) + default-browser: 5.2.1 + default-browser-id: 5.0.0 defaults: 1.0.4 - define-lazy-prop: 2.0.0 + define-lazy-prop: 3.0.0 delayed-stream: 1.0.0 dotenv: 16.4.7 dotenv-expand: 12.0.3 @@ -30114,11 +30230,12 @@ snapshots: ieee754: 1.2.1 ignore: 7.0.5 inherits: 2.0.4 - is-docker: 2.2.1 + is-docker: 3.0.0 is-fullwidth-code-point: 3.0.0 + is-inside-container: 1.0.0 is-interactive: 1.0.0 is-unicode-supported: 0.1.0 - is-wsl: 2.2.0 + is-wsl: 3.1.0 isexe: 2.0.0 json5: 2.2.3 jsonc-parser: 3.3.1 @@ -30134,7 +30251,7 @@ snapshots: npm-run-path: 4.0.1 once: 1.4.0 onetime: 5.1.2 - open: 8.4.2 + open: 10.1.0 ora: 5.4.1 path-key: 3.1.1 picocolors: 1.1.1 @@ -30143,6 +30260,7 @@ snapshots: require-directory: 2.1.1 resolve.exports: 2.0.3 restore-cursor: 3.1.0 + run-applescript: 7.0.0 safe-buffer: 5.2.1 semver: 7.8.4 signal-exit: 3.0.7 @@ -30166,16 +30284,16 @@ snapshots: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 23.1.0 - '@nx/nx-darwin-x64': 23.1.0 - '@nx/nx-freebsd-x64': 23.1.0 - '@nx/nx-linux-arm-gnueabihf': 23.1.0 - '@nx/nx-linux-arm64-gnu': 23.1.0 - '@nx/nx-linux-arm64-musl': 23.1.0 - '@nx/nx-linux-x64-gnu': 23.1.0 - '@nx/nx-linux-x64-musl': 23.1.0 - '@nx/nx-win32-arm64-msvc': 23.1.0 - '@nx/nx-win32-x64-msvc': 23.1.0 + '@nx/nx-darwin-arm64': 23.1.1 + '@nx/nx-darwin-x64': 23.1.1 + '@nx/nx-freebsd-x64': 23.1.1 + '@nx/nx-linux-arm-gnueabihf': 23.1.1 + '@nx/nx-linux-arm64-gnu': 23.1.1 + '@nx/nx-linux-arm64-musl': 23.1.1 + '@nx/nx-linux-x64-gnu': 23.1.1 + '@nx/nx-linux-x64-musl': 23.1.1 + '@nx/nx-win32-arm64-msvc': 23.1.1 + '@nx/nx-win32-x64-msvc': 23.1.1 nypm@0.6.2: dependencies: @@ -30261,6 +30379,13 @@ snapshots: dependencies: mimic-function: 5.0.1 + open@10.1.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + open@7.4.2: dependencies: is-docker: 2.2.1 @@ -30675,22 +30800,22 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.19)(tsx@4.21.0)(yaml@2.9.0): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.26)(tsx@4.23.12)(yaml@2.9.0): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 2.6.1 - postcss: 8.5.19 - tsx: 4.21.0 + postcss: 8.5.26 + tsx: 4.23.12 yaml: 2.9.0 - postcss-load-config@6.0.1(jiti@2.7.0)(postcss@8.5.19)(tsx@4.21.0)(yaml@2.9.0): + postcss-load-config@6.0.1(jiti@2.7.0)(postcss@8.5.26)(tsx@4.23.12)(yaml@2.9.0): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 2.7.0 - postcss: 8.5.19 - tsx: 4.21.0 + postcss: 8.5.26 + tsx: 4.23.12 yaml: 2.9.0 postcss-media-query-parser@0.2.3: {} @@ -30707,6 +30832,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.26: + dependencies: + nanoid: 3.3.18 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postgres@3.4.7: optional: true @@ -31115,7 +31246,7 @@ snapshots: scheduler: 0.27.0 semver: 7.7.4 stacktrace-parser: 0.1.11 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 whatwg-fetch: 3.6.20 ws: 7.5.11 yargs: 17.7.2 @@ -31160,7 +31291,7 @@ snapshots: scheduler: 0.27.0 semver: 7.7.4 stacktrace-parser: 0.1.11 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 whatwg-fetch: 3.6.20 ws: 7.5.11 yargs: 17.7.2 @@ -31558,6 +31689,26 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.1.5 '@rolldown/binding-win32-x64-msvc': 1.1.5 + rolldown@1.2.4: + dependencies: + '@oxc-project/types': 0.144.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.2.4 + '@rolldown/binding-darwin-arm64': 1.2.4 + '@rolldown/binding-darwin-x64': 1.2.4 + '@rolldown/binding-freebsd-x64': 1.2.4 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.4 + '@rolldown/binding-linux-arm64-gnu': 1.2.4 + '@rolldown/binding-linux-arm64-musl': 1.2.4 + '@rolldown/binding-linux-ppc64-gnu': 1.2.4 + '@rolldown/binding-linux-s390x-gnu': 1.2.4 + '@rolldown/binding-linux-x64-gnu': 1.2.4 + '@rolldown/binding-linux-x64-musl': 1.2.4 + '@rolldown/binding-openharmony-arm64': 1.2.4 + '@rolldown/binding-win32-arm64-msvc': 1.2.4 + '@rolldown/binding-win32-x64-msvc': 1.2.4 + rollup-plugin-dts@6.4.1(rollup@4.60.1)(typescript@5.9.3): dependencies: '@jridgewell/remapping': 2.3.5 @@ -31579,6 +31730,16 @@ snapshots: rolldown: 1.1.5 rollup: 4.60.1 + rollup-plugin-visualizer@6.0.5(rolldown@1.2.4)(rollup@4.60.1): + dependencies: + open: 8.4.2 + picomatch: 4.0.5 + source-map: 0.7.6 + yargs: 17.7.2 + optionalDependencies: + rolldown: 1.2.4 + rollup: 4.60.1 + rollup@4.57.1: dependencies: '@types/estree': 1.0.8 @@ -31655,6 +31816,8 @@ snapshots: transitivePeerDependencies: - supports-color + run-applescript@7.0.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -32222,7 +32385,7 @@ snapshots: lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ts-interface-checker: 0.1.13 supports-color@10.2.2: {} @@ -32390,11 +32553,6 @@ snapshots: tinyexec@1.1.1: {} tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.5) picomatch: 4.0.5 @@ -32493,7 +32651,7 @@ snapshots: rolldown-plugin-dts: 0.18.3(oxc-resolver@11.21.3)(rolldown@1.0.0-beta.53(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1))(typescript@5.9.3) semver: 7.7.3 tinyexec: 1.0.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 tree-kill: 1.2.2 unconfig-core: 7.4.2 unrun: 0.2.19(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) @@ -32511,16 +32669,16 @@ snapshots: tslib@2.8.1: {} - tsup-preset-solid@2.2.0(esbuild@0.28.1)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.19)(supports-color@7.2.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0)): + tsup-preset-solid@2.2.0(esbuild@0.28.1)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.26)(supports-color@7.2.0)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0)): dependencies: esbuild-plugin-solid: 0.5.0(esbuild@0.28.1)(solid-js@1.9.10) - tsup: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.19)(supports-color@7.2.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) + tsup: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.26)(supports-color@7.2.0)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0) transitivePeerDependencies: - esbuild - solid-js - supports-color - tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.6.1)(postcss@8.5.19)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0): + tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.6.1)(postcss@8.5.26)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0): dependencies: bundle-require: 5.1.0(esbuild@0.27.7) cac: 6.7.14 @@ -32531,17 +32689,17 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.19)(tsx@4.21.0)(yaml@2.9.0) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.26)(tsx@4.23.12)(yaml@2.9.0) resolve-from: 5.0.0 rollup: 4.57.1 source-map: 0.7.6 sucrase: 3.35.1 tinyexec: 0.3.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 tree-kill: 1.2.2 optionalDependencies: '@microsoft/api-extractor': 7.47.7(@types/node@24.10.3) - postcss: 8.5.19 + postcss: 8.5.26 typescript: 5.9.3 transitivePeerDependencies: - jiti @@ -32549,7 +32707,7 @@ snapshots: - tsx - yaml - tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.19)(supports-color@7.2.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0): + tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(jiti@2.7.0)(postcss@8.5.26)(supports-color@7.2.0)(tsx@4.23.12)(typescript@5.9.3)(yaml@2.9.0): dependencies: bundle-require: 5.1.0(esbuild@0.27.7) cac: 6.7.14 @@ -32560,17 +32718,17 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@2.7.0)(postcss@8.5.19)(tsx@4.21.0)(yaml@2.9.0) + postcss-load-config: 6.0.1(jiti@2.7.0)(postcss@8.5.26)(tsx@4.23.12)(yaml@2.9.0) resolve-from: 5.0.0 rollup: 4.57.1 source-map: 0.7.6 sucrase: 3.35.1 tinyexec: 0.3.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 tree-kill: 1.2.2 optionalDependencies: '@microsoft/api-extractor': 7.47.7(@types/node@24.10.3) - postcss: 8.5.19 + postcss: 8.5.26 typescript: 5.9.3 transitivePeerDependencies: - jiti @@ -32585,6 +32743,12 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tsx@4.23.12: + dependencies: + esbuild: 0.28.1 + optionalDependencies: + fsevents: 2.3.3 + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 @@ -32703,14 +32867,14 @@ snapshots: undici-types@5.28.4: {} - undici-types@6.21.0: {} - undici-types@7.16.0: {} undici@7.24.8: {} undici@7.28.0: {} + undici@7.29.0: {} + unenv@1.10.0: dependencies: consola: 3.4.2 @@ -32810,7 +32974,7 @@ snapshots: unpipe@1.0.0: {} - unplugin-dts@1.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + unplugin-dts@1.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: '@rollup/pluginutils': 5.3.0(rollup@4.60.1) '@volar/typescript': 2.4.27 @@ -32826,7 +32990,7 @@ snapshots: esbuild: 0.28.1 rolldown: 1.1.5 rollup: 4.60.1 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -32989,11 +33153,11 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vinxi@0.5.3(91b39b40f4efbadaf93b05367f1ce328): + vinxi@0.5.3(e2865e417d15aa2efdac89fcc0288f0b): dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.29.7) '@types/micromatch': 4.0.10 '@vinxi/listhen': 1.5.6 boxen: 7.1.1 @@ -33011,7 +33175,7 @@ snapshots: hookable: 5.5.3 http-proxy: 1.18.1 micromatch: 4.0.8 - nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.1.5) + nitropack: 2.13.1(@electric-sql/pglite@0.4.3)(aws4fetch@1.0.20)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3)(rolldown@1.2.4) node-fetch-native: 1.6.7 path-to-regexp: 6.3.0 pathe: 1.1.2 @@ -33023,7 +33187,7 @@ snapshots: unctx: 2.4.1 unenv: 1.10.0 unstorage: 1.17.4(aws4fetch@1.0.20)(db0@0.3.4(@electric-sql/pglite@0.4.3)(better-sqlite3@12.11.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260317.1)(@electric-sql/pglite@0.4.3)(@opentelemetry/api@1.9.1)(@prisma/client@7.9.0(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.11.1)(bun-types@1.3.14)(mysql2@3.15.3)(postgres@3.4.7)(prisma@7.9.0(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(better-sqlite3@12.11.1)(magicast@0.5.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)))(mysql2@3.15.3))(ioredis@5.9.2) - vite: 6.4.2(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 6.4.2(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) zod: 3.25.76 transitivePeerDependencies: - '@azure/app-configuration' @@ -33070,13 +33234,13 @@ snapshots: - xml2js - yaml - vite-plugin-dts@5.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-dts@5.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: - unplugin-dts: 1.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + unplugin-dts: 1.0.3(@microsoft/api-extractor@7.47.7(@types/node@24.10.3))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.60.1)(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) optionalDependencies: '@microsoft/api-extractor': 7.47.7(@types/node@24.10.3) rollup: 4.60.1 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - '@rspack/core' - '@vue/language-core' @@ -33086,11 +33250,11 @@ snapshots: - typescript - webpack - vite-plugin-externalize-deps@0.10.0(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-externalize-deps@0.10.0(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: '@babel/core': 7.29.7 '@types/babel__core': 7.20.5 @@ -33098,13 +33262,13 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.10 solid-refresh: 0.6.3(solid-js@1.9.10) - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color optional: true - vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-plugin-solid@2.11.14(solid-js@1.9.10)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: '@babel/core': 7.29.7 '@types/babel__core': 7.20.5 @@ -33112,33 +33276,33 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.10 solid-refresh: 0.6.3(solid-js@1.9.10) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) - vitefu: 1.1.1(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) + vitefu: 1.1.1(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - vite-tsconfig-paths@5.1.4(supports-color@7.2.0)(typescript@5.9.3)(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-tsconfig-paths@5.1.4(supports-color@7.2.0)(typescript@5.9.3)(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: debug: 4.4.3(supports-color@7.2.0) globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) optionalDependencies: - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - typescript - vite-tsconfig-paths@6.1.1(supports-color@7.2.0)(typescript@7.0.2)(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vite-tsconfig-paths@6.1.1(supports-color@7.2.0)(typescript@7.0.2)(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: debug: 4.4.3(supports-color@7.2.0) globrex: 0.1.2 tsconfck: 3.1.6(typescript@7.0.2) - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) transitivePeerDependencies: - supports-color - typescript - vite@6.4.2(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0): + vite@6.4.2(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.5) @@ -33151,15 +33315,15 @@ snapshots: fsevents: 2.3.3 jiti: 2.7.0 less: 4.6.6 - lightningcss: 1.32.0 + lightningcss: 1.33.0 sass: 1.101.0 terser: 5.44.1 - tsx: 4.21.0 + tsx: 4.23.12 yaml: 2.9.0 - vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0): + vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0): dependencies: - esbuild: 0.27.7 + esbuild: 0.28.1 fdir: 6.5.0(picomatch@4.0.5) picomatch: 4.0.5 postcss: 8.5.19 @@ -33170,32 +33334,13 @@ snapshots: fsevents: 2.3.3 jiti: 2.7.0 less: 4.6.6 - lightningcss: 1.32.0 + lightningcss: 1.33.0 sass: 1.101.0 terser: 5.44.1 - tsx: 4.21.0 + tsx: 4.23.12 yaml: 2.9.0 - vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0): - dependencies: - esbuild: 0.27.7 - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 - postcss: 8.5.19 - rollup: 4.60.1 - tinyglobby: 0.2.17 - optionalDependencies: - '@types/node': 24.10.3 - fsevents: 2.3.3 - jiti: 2.7.0 - less: 4.6.6 - lightningcss: 1.32.0 - sass: 1.97.3 - terser: 5.44.1 - tsx: 4.21.0 - yaml: 2.9.0 - - vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0): + vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0): dependencies: esbuild: 0.28.1 fdir: 6.5.0(picomatch@4.0.5) @@ -33208,18 +33353,18 @@ snapshots: fsevents: 2.3.3 jiti: 2.7.0 less: 4.6.6 - lightningcss: 1.32.0 + lightningcss: 1.33.0 sass: 1.97.3 terser: 5.44.1 - tsx: 4.21.0 + tsx: 4.23.12 yaml: 2.9.0 - vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.6.1)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0): + vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.6.1)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 + lightningcss: 1.33.0 picomatch: 4.0.5 - postcss: 8.5.19 - rolldown: 1.1.5 + postcss: 8.5.26 + rolldown: 1.2.4 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 24.10.3 @@ -33229,15 +33374,15 @@ snapshots: less: 4.6.6 sass: 1.101.0 terser: 5.44.1 - tsx: 4.21.0 + tsx: 4.23.12 yaml: 2.9.0 - vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0): + vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 + lightningcss: 1.33.0 picomatch: 4.0.5 - postcss: 8.5.19 - rolldown: 1.1.5 + postcss: 8.5.26 + rolldown: 1.2.4 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 24.10.3 @@ -33247,21 +33392,21 @@ snapshots: less: 4.6.6 sass: 1.101.0 terser: 5.44.1 - tsx: 4.21.0 + tsx: 4.23.12 yaml: 2.9.0 - vitefu@1.1.1(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vitefu@1.1.1(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): optionalDependencies: - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - vitefu@1.1.1(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vitefu@1.1.1(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): optionalDependencies: - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.19))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -33278,21 +33423,22 @@ snapshots: tinyexec: 1.1.1 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.1.4(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.10.3 - '@vitest/coverage-v8': 4.0.14(supports-color@7.2.0)(vitest@4.1.10) - happy-dom: 20.0.11 - jsdom: 27.3.0(postcss@8.5.19) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) + happy-dom: 20.11.2 + jsdom: 27.4.0(postcss@8.5.19) transitivePeerDependencies: - msw + optional: true - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -33309,20 +33455,21 @@ snapshots: tinyexec: 1.1.1 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 7.3.6(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.33.0)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.10.3 - happy-dom: 20.0.11 - jsdom: 27.3.0(postcss@8.5.19) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) + happy-dom: 20.11.2 + jsdom: 27.4.0(postcss@8.5.26) transitivePeerDependencies: - msw - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.19))(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)): + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.10.3)(@vitest/coverage-v8@4.1.10)(happy-dom@20.11.2)(jsdom@27.4.0(postcss@8.5.26))(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -33339,16 +33486,16 @@ snapshots: tinyexec: 1.1.1 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 7.3.3(@types/node@24.10.3)(jiti@2.7.0)(less@4.6.6)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.9.0) + vite: 8.2.1(@types/node@24.10.3)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass@1.101.0)(terser@5.44.1)(tsx@4.23.12)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.10.3 - happy-dom: 20.0.11 - jsdom: 27.3.0(postcss@8.5.19) + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) + happy-dom: 20.11.2 + jsdom: 27.4.0(postcss@8.5.26) transitivePeerDependencies: - msw - optional: true vlq@1.0.1: {} From 968b823100619b40bb611685c1cafc41c7ccae91 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 18 Aug 2026 12:59:56 +0200 Subject: [PATCH 16/23] feat(ai-acp): honor outputSchema and add ACP repo-report example acpCompatible now parses the last assistant text as structured output, same as OpenCode and Grok Build. The React example picker includes ACP compatible (Grok). Docs show how to read messages[].parts, not only useChat().final. --- .changeset/harness-output-schema.md | 3 +- docs/adapters/acp-compatible.md | 73 +++++++++++++- docs/config.json | 10 +- docs/sandbox/harnesses.md | 2 +- docs/structured-outputs/harnesses.md | 65 +++++++++---- docs/structured-outputs/overview.md | 2 +- docs/structured-outputs/streaming.md | 45 ++++++--- examples/ts-react-chat/package.json | 1 + .../ts-react-chat/src/repo-report-options.ts | 3 +- .../ts-react-chat/src/routes/repo-report.tsx | 7 +- .../src/sandbox-triage-options.ts | 3 +- .../ts-react-chat/src/sandbox-triage.test.ts | 3 +- examples/ts-react-chat/src/sandbox-triage.ts | 21 ++++ packages/ai-acp/src/adapters/compatible.ts | 95 +++++++++++++++++-- packages/ai-acp/tests/compatible.test.ts | 87 ++++++++++++++++- .../ai-core/structured-outputs/SKILL.md | 11 ++- pnpm-lock.yaml | 9 +- 17 files changed, 377 insertions(+), 63 deletions(-) diff --git a/.changeset/harness-output-schema.md b/.changeset/harness-output-schema.md index 3e98a72526..a4a5bbb703 100644 --- a/.changeset/harness-output-schema.md +++ b/.changeset/harness-output-schema.md @@ -4,8 +4,9 @@ '@tanstack/ai-codex': minor '@tanstack/ai-opencode': minor '@tanstack/ai-grok-build': minor +'@tanstack/ai-acp': minor --- Harness adapters honor `chat({ outputSchema })` on the same turn. -Claude Code and Codex pass a native schema flag. OpenCode and Grok Build parse JSON from the final assistant text. The engine reads a `structured-output.complete` event so harness prose is not parsed as JSON. +Claude Code and Codex pass a native schema flag. OpenCode, Grok Build, and `acpCompatible` parse JSON from the final assistant text. The engine reads a `structured-output.complete` event so harness prose is not parsed as JSON. diff --git a/docs/adapters/acp-compatible.md b/docs/adapters/acp-compatible.md index a309ebacb3..b5f213566a 100644 --- a/docs/adapters/acp-compatible.md +++ b/docs/adapters/acp-compatible.md @@ -16,7 +16,7 @@ Coding-agent CLIs that speak the [Agent Client Protocol](https://agentclientprot It is the harness equivalent of the [OpenAI-Compatible adapter](./openai-compatible). Use it when your agent speaks ACP but has no `@tanstack/ai-*` package. If a dedicated harness adapter exists ([Grok Build](./grok-build), and others), prefer it — those carry curated per-model metadata and vendor-specific behavior. -`acpCompatible` does not accept `outputSchema`. If you need a typed object from a coding agent, use a dedicated harness adapter. See [Harness Agents](../structured-outputs/harnesses). +Pass `outputSchema` on the same `chat()` call. `acpCompatible` adds the schema to the prompt and parses the last assistant text. Native harness tools still run on that turn. Read the typed object from `await chat()`, from `useChat().final`, or from the assistant `structured-output` part. See [Harness Agents](../structured-outputs/harnesses). ## Installation @@ -91,6 +91,77 @@ const stream = chat({ }) ``` +## Typed output + +Pass `outputSchema` on the same `chat()` call. The agent runs its native tools. Then the adapter parses the last assistant text as JSON. + +```ts +import { chat, toServerSentEventsResponse } from '@tanstack/ai' +import { acpCompatibleText } from '@tanstack/ai-acp' +import { withSandbox } from '@tanstack/ai-sandbox' +import { z } from 'zod' +import { sandbox } from './sandbox' +import { messages } from './chat-context' + +const ReportSchema = z.object({ + name: z.string(), + oneLiner: z.string(), +}) + +export async function POST() { + const stream = chat({ + adapter: acpCompatibleText('pi-fast', { + name: 'pi', + command: ({ model }) => `pi --acp -m ${model}`, + }), + messages, + outputSchema: ReportSchema, + stream: true, + middleware: [withSandbox(sandbox)], + }) + return toServerSentEventsResponse(stream) +} +``` + +On the client, walk `messages[].parts` for tool calls and reasoning. Read the typed object from the `structured-output` part or from `useChat().final`. + +```tsx +import { useChat, fetchServerSentEvents } from '@tanstack/ai-react' +import { z } from 'zod' + +const ReportSchema = z.object({ + name: z.string(), + oneLiner: z.string(), +}) + +function Report() { + const { messages, final } = useChat({ + connection: fetchServerSentEvents('/api/report'), + outputSchema: ReportSchema, + }) + + return ( + <> + {messages.map((message) => + message.parts.map((part, index) => { + if (part.type === 'tool-call') { + return

{part.name}

+ } + if (part.type === 'structured-output') { + const report = part.data ?? part.partial + return report?.name ?

{report.name}

: null + } + return null + }), + )} + {final ?

{final.oneLiner}

: null} + + ) +} +``` + +See [Harness Agents](../structured-outputs/harnesses) for the full part list and the repo-report example. + ## Typed models & options Like `openaiCompatible`, you can declare the harness's **models** and its diff --git a/docs/config.json b/docs/config.json index 2848060b5a..7e9287d2a1 100644 --- a/docs/config.json +++ b/docs/config.json @@ -336,7 +336,7 @@ "label": "Overview", "to": "structured-outputs/overview", "addedAt": "2026-05-19", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-18" }, { "label": "One-Shot Extraction", @@ -348,7 +348,7 @@ "label": "Streaming UIs", "to": "structured-outputs/streaming", "addedAt": "2026-05-19", - "updatedAt": "2026-08-17" + "updatedAt": "2026-08-18" }, { "label": "Multi-Turn Chat", @@ -365,7 +365,7 @@ "label": "Harness Agents", "to": "structured-outputs/harnesses", "addedAt": "2026-08-14", - "updatedAt": "2026-08-17" + "updatedAt": "2026-08-18" } ] }, @@ -536,7 +536,7 @@ "label": "Harnesses", "to": "sandbox/harnesses", "addedAt": "2026-06-30", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-18" }, { "label": "Workspace", @@ -897,7 +897,7 @@ "label": "ACP-Compatible", "to": "adapters/acp-compatible", "addedAt": "2026-06-30", - "updatedAt": "2026-08-14" + "updatedAt": "2026-08-18" }, { "label": "Amazon Bedrock", diff --git a/docs/sandbox/harnesses.md b/docs/sandbox/harnesses.md index 8e9f290700..cd922304d8 100644 --- a/docs/sandbox/harnesses.md +++ b/docs/sandbox/harnesses.md @@ -41,7 +41,7 @@ const stream = chat({ ## Typed report from a harness -If you want a typed object after the agent inspects the repo, pass `outputSchema` on the same `chat()` call. See [Harness Agents](../structured-outputs/harnesses). +If you want a typed object after the agent inspects the repo, pass `outputSchema` on the same `chat()` call. Dedicated adapters and `acpCompatible` honor it. See [Harness Agents](../structured-outputs/harnesses). ## Harness output can go to a journal diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index 8c8e6f7e65..f5913d27c5 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -2,7 +2,7 @@ title: Harness Structured Output id: structured-outputs-harnesses order: 6 -description: "Ask a coding agent in a sandbox to inspect a repo, then read a typed object from chat({ outputSchema }). Works with Claude Code, Codex, OpenCode, and Grok Build." +description: "Ask a coding agent in a sandbox to inspect a repo, then read a typed object from chat({ outputSchema }). Works with Claude Code, Codex, OpenCode, Grok Build, and acpCompatible." keywords: - tanstack ai - structured outputs @@ -19,12 +19,13 @@ You asked a coding agent to inspect a repository. The agent streams tool calls a Pass `outputSchema` on the same `chat()` call. The harness runs its native tools. Then you get a validated object from `await chat()` or from `useChat().final`. -This page is for dedicated harness adapters: +This page is for sandbox harness adapters: - [Claude Code](../adapters/claude-code) - [Codex](../adapters/codex) - [OpenCode](../adapters/opencode) - [Grok Build](../adapters/grok-build) +- [ACP-Compatible](../adapters/acp-compatible) (`acpCompatible`) If you only extract JSON from a prompt and you do not need a sandbox, use [One-Shot Extraction](./one-shot) with an HTTP adapter. @@ -98,19 +99,20 @@ Swap the adapter to change the agent: - `codexText("gpt-5.3-codex")` - `opencodeText("anthropic/claude-opus-4-5")` -- `grokBuildText("grok-build")` +- `grokBuildText("composer-2.5")` +- `acpCompatibleText(...)` for any ACP CLI. See [ACP-Compatible](../adapters/acp-compatible). The typed object arrives as a `structured-output.complete` event. Tool activity streams first. -## Client: read `final` +## Client: read `parts` and `final` -Pass the same schema to `useChat`. Read the object from `final`. +The assistant message holds the live run. Walk `messages[].parts` for tool calls, reasoning, and the typed object. `useChat().final` is a shortcut for the latest `structured-output` part. ```tsx group=harness-output import { useChat, fetchServerSentEvents } from "@tanstack/ai-react"; function RepoReport() { - const { sendMessage, isLoading, final } = useChat({ + const { messages, sendMessage, isLoading, final } = useChat({ connection: fetchServerSentEvents("/api/repo-report"), outputSchema: ReportSchema, }); @@ -123,20 +125,44 @@ function RepoReport() { > Run report - {isLoading &&

The agent is inspecting the repo.

} - {final && ( - <> -

{final.name}

-

{final.oneLiner}

-

{final.audience}

- - )} + {messages.map((message) => ( +
+ {message.parts.map((part, index) => { + if (part.type === "thinking") { + return

{part.content}

; + } + if (part.type === "tool-call") { + return ( +

+ {part.name} ({part.state}) +

+ ); + } + if (part.type === "text") { + return

{part.content}

; + } + if (part.type === "structured-output") { + const report = part.data ?? part.partial; + return report?.name ?

{report.name}

: null; + } + return null; + })} +
+ ))} + {final ?

{final.oneLiner}

: null} ); } ``` -`final` is typed as the schema. It stays `null` until `structured-output.complete` arrives. +Each part type: + +- `thinking`: harness reasoning, when the agent emits it +- `tool-call`: native harness tools such as `Read` or `Bash` +- `text`: prose the agent writes before the JSON +- `structured-output`: the schema object. `part.data` is the validated value. `part.partial` is a progressive parse when the adapter streams JSON text. `part.raw` is the source string. + +`final` is typed as the schema. It stays `null` until `structured-output.complete` arrives. It always matches the latest assistant turn. Older turns stay on their own `structured-output` parts. `partial` stays empty on harness adapters. The object is not streamed field by field. Render tool calls from `messages` while you wait. See [Streaming UIs](./streaming) for the `partial` / `final` shape. @@ -148,10 +174,9 @@ function RepoReport() { | Codex | Native `--output-schema` flag on the same turn | | OpenCode | Schema is added to the prompt. The adapter parses the last assistant text. | | Grok Build | Schema is added to the prompt. The adapter parses the last assistant text. | +| ACP compatible | Schema is added to the prompt. The adapter parses the last assistant text. | -OpenCode and Grok Build parse JSON from the last assistant message. That parse fails if the message is not JSON. If the job is extract-only and you do not need a sandbox, use `@tanstack/ai-openai` or `@tanstack/ai-grok`. - -The generic ACP adapter (`acpCompatible`) does not accept `outputSchema`. Use a dedicated harness adapter. +OpenCode, Grok Build, and `acpCompatible` parse JSON from the last assistant message. That parse fails if the message is not JSON. If the job is extract-only and you do not need a sandbox, use `@tanstack/ai-openai` or `@tanstack/ai-grok`. ## Approval gates and client tools @@ -185,8 +210,8 @@ The React chat example includes a repo-report page. 1. Open [`examples/ts-react-chat`](https://github.com/TanStack/ai/tree/main/examples/ts-react-chat). 2. Set the harness API key in `.env`. 3. Open `/repo-report`. -4. Pick Claude Code, Grok Build, or Codex. -5. Run the report. The page reads the typed object from `useChat().final`. +4. Pick Claude Code, Grok Build, ACP compatible, or Codex. +5. Run the report. The page renders tool calls and reasoning from `messages[].parts`. It reads the typed object from the `structured-output` part and from `useChat().final`. The page clones `TanStack/ai` into a sandbox, asks the agent to inspect it, and shows the validated report. diff --git a/docs/structured-outputs/overview.md b/docs/structured-outputs/overview.md index e9cb3fc4e4..79d1ad1c3f 100644 --- a/docs/structured-outputs/overview.md +++ b/docs/structured-outputs/overview.md @@ -58,7 +58,7 @@ Every adapter handles structured output through its provider's native API: | Ollama | JSON mode with schema | | OpenRouter / Grok / Groq | `response_format` with `json_schema` | | Claude Code / Codex | Native schema flag on the same harness turn (`--json-schema` / `--output-schema`) | -| OpenCode / Grok Build | Same-turn prompt-and-parse | +| OpenCode / Grok Build / ACP compatible | Same-turn prompt-and-parse | The provider-specific details are handled for you. The same `chat({ outputSchema })` call works across all of them. For a coding agent in a sandbox, see [Harness Agents](./harnesses). diff --git a/docs/structured-outputs/streaming.md b/docs/structured-outputs/streaming.md index d562caab5b..01c3f5bb77 100644 --- a/docs/structured-outputs/streaming.md +++ b/docs/structured-outputs/streaming.md @@ -93,7 +93,7 @@ What the hook does for you: - **`partial`** is `DeepPartial>` — every property optional, every nested array element optional. Updated from `TEXT_MESSAGE_CONTENT` deltas via the runtime's partial-JSON parser. The hook derives it from the latest assistant message's `structured-output` part (see [Multi-Turn Chat](./multi-turn) for why that distinction matters), so it reads `{}` between `sendMessage()` and the first chunk without any extra reset state. - **`final`** is `z.infer | null` — the validated terminal payload from the `structured-output.complete` event. `null` until the run completes successfully. - **`outputSchema`** is used purely for client-side TypeScript inference. Validation still runs on the server against the schema you pass to `chat({ outputSchema })` on the server route — the client doesn't re-validate. -- The same shape works for **non-streaming adapters too**. If an adapter (Anthropic, Gemini, Ollama) returns a single `structured-output.complete` event with no incremental deltas, `partial` stays `{}` and `final` populates when the event arrives. Same consumer code. Claude Code and Codex emit `structured-output.complete` from the harness event. OpenCode and Grok Build parse the last assistant text at the end. In both cases `partial` stays empty until `final` is set. See [Harness Agents](./harnesses). +- The same shape works for **non-streaming adapters too**. If an adapter (Anthropic, Gemini, Ollama) returns a single `structured-output.complete` event with no incremental deltas, `partial` stays `{}` and `final` populates when the event arrives. Same consumer code. Claude Code and Codex emit `structured-output.complete` from the harness event. OpenCode, Grok Build, and `acpCompatible` parse the last assistant text at the end. In both cases `partial` stays empty until `final` is set. See [Harness Agents](./harnesses). `outputSchema` is optional: omit it and `useChat` returns its standard shape without `partial` / `final`. @@ -109,26 +109,45 @@ What the hook does for you: | `TEXT_MESSAGE_CONTENT` (with `outputSchema` set) | `StructuredOutputPart` on the assistant message — the JSON deltas accumulate into `part.raw` and the progressive parse populates `part.partial` | | `TEXT_MESSAGE_CONTENT` (no `outputSchema`) | `TextPart` on the assistant message | -So render reasoning and tool calls the same way you'd render them in a normal chat UI: +So render reasoning, tool calls, and the typed object from `messages[].parts`. `final` and `partial` are shortcuts for the latest `structured-output` part only. ```tsx ignore -const last = messages.at(-1); - return ( <> - {last?.parts.map((part, i) => { - if (part.type === "thinking") return ; - if (part.type === "tool-call") return ; - // The structured-output part is rendered separately via the - // `partial` / `final` sugar below — no need to walk it here. - return null; - })} - - + {messages.map((message) => ( +
+ {message.parts.map((part, i) => { + if (part.type === "thinking") { + return ; + } + if (part.type === "tool-call") { + return ; + } + if (part.type === "text") { + return

{part.content}

; + } + if (part.type === "structured-output") { + return ( + + ); + } + return null; + })} +
+ ))} ); ``` +The `structured-output` part fields: + +- `data`: the validated object after `structured-output.complete` +- `partial`: a progressive parse of `raw` while JSON streams +- `raw`: the source JSON string +- `status`: `streaming`, `complete`, or `error` + +`final` equals `data` on the latest assistant turn. Walk `parts` when you need history, tool calls, or reasoning. + > **Migration note:** Earlier versions of TanStack AI routed structured JSON deltas through a `TextPart` and required you to filter that part out of your renderer. That hack is gone — `TEXT_MESSAGE_CONTENT` on a structured-output run now routes into a dedicated `StructuredOutputPart` (with `raw`, `partial`, `data`, `status`, optional `errorMessage`). If your render loop still has an explicit `if (part.type === "text") return null;` line specifically for hiding structured JSON, you can remove it. > **Going lower-level?** `useChat` still exposes `onChunk` if you want to observe individual chunks alongside the managed `partial` / `final` state (e.g. to drive a custom progress UI). Internal partial/final tracking runs first, then your `onChunk` callback fires with the same chunk — the two paths compose. diff --git a/examples/ts-react-chat/package.json b/examples/ts-react-chat/package.json index 673d79dc7e..d7bb5d2cb6 100644 --- a/examples/ts-react-chat/package.json +++ b/examples/ts-react-chat/package.json @@ -19,6 +19,7 @@ "@ngrok/ngrok": "^1.7.0", "@tailwindcss/vite": "^4.1.18", "@tanstack/ai": "workspace:*", + "@tanstack/ai-acp": "workspace:*", "@tanstack/ai-anthropic": "workspace:*", "@tanstack/ai-bedrock": "workspace:*", "@tanstack/ai-byteplus": "workspace:*", diff --git a/examples/ts-react-chat/src/repo-report-options.ts b/examples/ts-react-chat/src/repo-report-options.ts index aba8f93da7..454febe7ce 100644 --- a/examples/ts-react-chat/src/repo-report-options.ts +++ b/examples/ts-react-chat/src/repo-report-options.ts @@ -3,13 +3,14 @@ * Do not import harness packages here. */ -export type ReportHarness = 'claude-code' | 'codex' | 'grok' +export type ReportHarness = 'claude-code' | 'codex' | 'grok' | 'acp' export type ReportProvider = 'docker' | 'local' export type ReportAgent = 'explainer' | 'package-map' | 'first-hour' export const REPORT_HARNESSES: Record = { 'claude-code': { label: 'Claude Code' }, grok: { label: 'Grok Build' }, + acp: { label: 'ACP compatible (Grok)' }, codex: { label: 'Codex' }, } diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index cfa57591c5..52236d5cbd 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -137,7 +137,9 @@ function RepoReportPage() {

Repo report

- Clone {REPORT_REPO}, pick a harness, and grab a typed report from{' '} + Clone {REPORT_REPO}, pick a harness (including ACP compatible), and + grab a typed report from{' '} + messages[].parts and{' '} outputSchema.

@@ -300,7 +302,8 @@ function RepoReportPage() { {!chat.isLoading && chat.messages.length === 0 ? (

- Pick Claude Code, Grok Build, or Codex, pick an agent, then Run. + Pick Claude Code, Grok Build, ACP compatible, or Codex, pick an + agent, then Run. The sandbox clones {REPORT_REPO} and the typed report lands here.

) : null} diff --git a/examples/ts-react-chat/src/sandbox-triage-options.ts b/examples/ts-react-chat/src/sandbox-triage-options.ts index b75905eab0..bf2cb0bcad 100644 --- a/examples/ts-react-chat/src/sandbox-triage-options.ts +++ b/examples/ts-react-chat/src/sandbox-triage-options.ts @@ -9,7 +9,7 @@ */ // Pure string-literal types — re-exported by sandbox-triage.ts (single source of truth here). -export type HarnessName = 'claude-code' | 'codex' | 'opencode' | 'grok' +export type HarnessName = 'claude-code' | 'codex' | 'opencode' | 'grok' | 'acp' export type ProviderName = 'docker' | 'local' | 'vercel' | 'daytona' export type GrokBuildModel = 'grok-build-0.1' | 'composer-2.5' export type GrokBuildProtocol = 'acp' | 'streaming-json' @@ -37,6 +37,7 @@ export interface PickerSpec { export const HARNESSES: Record = { grok: { label: 'Grok Build' }, + acp: { label: 'ACP compatible (Grok)' }, 'claude-code': { label: 'Claude Code' }, codex: { label: 'Codex' }, opencode: { label: 'OpenCode' }, diff --git a/examples/ts-react-chat/src/sandbox-triage.test.ts b/examples/ts-react-chat/src/sandbox-triage.test.ts index e820c73a9a..7c088f84dc 100644 --- a/examples/ts-react-chat/src/sandbox-triage.test.ts +++ b/examples/ts-react-chat/src/sandbox-triage.test.ts @@ -50,8 +50,9 @@ describe('parseVerdict', () => { }) describe('registries', () => { - it('has 4 harnesses and 4 providers with labels + required env arrays', () => { + it('has 5 harnesses and 4 providers with labels + required env arrays', () => { expect(Object.keys(HARNESSES).sort()).toEqual([ + 'acp', 'claude-code', 'codex', 'grok', diff --git a/examples/ts-react-chat/src/sandbox-triage.ts b/examples/ts-react-chat/src/sandbox-triage.ts index 8ab0e09272..fb1a9f2bf7 100644 --- a/examples/ts-react-chat/src/sandbox-triage.ts +++ b/examples/ts-react-chat/src/sandbox-triage.ts @@ -1,3 +1,4 @@ +import { acpCompatibleText } from '@tanstack/ai-acp' import { claudeCodeText } from '@tanstack/ai-claude-code' import { codexText } from '@tanstack/ai-codex' import { @@ -180,6 +181,26 @@ export const HARNESSES: Record = { }, exposePort: 2419, }, + acp: { + label: 'ACP compatible (Grok)', + makeAdapter: () => + acpCompatibleText('composer-2.5', { + name: 'acp', + command: ({ model }) => + `grok agent -m '${model}' --always-approve stdio`, + permissionMode: 'bypassPermissions', + }), + installCommand: GROK_CLI_INSTALL_COMMAND, + requiredEnv: ['XAI_API_KEY'], + envCheck: () => + process.env.XAI_API_KEY || process.env.GROK_API_KEY + ? [] + : ['XAI_API_KEY (or GROK_API_KEY)'], + sandboxSecrets: (): Record => { + const key = process.env.XAI_API_KEY ?? process.env.GROK_API_KEY + return key ? { XAI_API_KEY: key } : {} + }, + }, } export interface GrokHarnessOptions { diff --git a/packages/ai-acp/src/adapters/compatible.ts b/packages/ai-acp/src/adapters/compatible.ts index 1cf84721b1..0b92fe7ec1 100644 --- a/packages/ai-acp/src/adapters/compatible.ts +++ b/packages/ai-acp/src/adapters/compatible.ts @@ -1,5 +1,11 @@ import { EventType, normalizeSystemPrompts } from '@tanstack/ai' -import { toRunErrorRawEvent } from '@tanstack/ai/adapter-internals' +import { + appendOutputSchemaInstruction, + parseJsonFromAssistantText, + structuredOutputCompleteChunk, + structuredOutputStartChunk, + toRunErrorRawEvent, +} from '@tanstack/ai/adapter-internals' import { BaseTextAdapter } from '@tanstack/ai/adapters' import { DurableAttachNotSupportedError, @@ -247,6 +253,14 @@ export class AcpCompatibleTextAdapter< this.name = config.name } + supportsCombinedToolsAndSchema(): boolean { + return true + } + + combinedStructuredOutputSource(): 'event' { + return 'event' + } + private sandboxFrom( options: TextOptions>, ): SandboxHandle { @@ -510,12 +524,18 @@ export class AcpCompatibleTextAdapter< const systemPrompts = normalizeSystemPrompts(options.systemPrompts) .map((p) => p.content) .filter((c) => c.trim() !== '') - const promptText = this.applySystemPrompts( + let promptText = this.applySystemPrompts( systemPrompts, session.resumed || sessionId === undefined ? resumePrompt : this.buildPrompt(options.messages, undefined).prompt, ) + if (options.outputSchema) { + promptText = appendOutputSchemaInstruction( + promptText, + options.outputSchema, + ) + } session .prompt(promptText) @@ -529,7 +549,9 @@ export class AcpCompatibleTextAdapter< }) .catch((error: unknown) => queue.fail(error)) - yield* mergeChunkStreams( + const wantsStructured = options.outputSchema !== undefined + let lastAssistantText = '' + for await (const chunk of mergeChunkStreams( translateAcpStream(queue, { model: this.model, runId, @@ -557,7 +579,27 @@ export class AcpCompatibleTextAdapter< }), }), channel.stream, - ) + )) { + if (wantsStructured) { + if (chunk.type === EventType.TEXT_MESSAGE_START) { + lastAssistantText = '' + } else if ( + chunk.type === EventType.TEXT_MESSAGE_CONTENT && + typeof chunk.delta === 'string' + ) { + lastAssistantText += chunk.delta + } + } + yield chunk + } + + if (options.outputSchema) { + yield* this.emitParsedStructuredOutput( + lastAssistantText, + threadId, + runId, + ) + } // Surface any pending approval requests (interactive ask-policy actions // awaiting a client decision); the client approves and re-runs to continue. @@ -641,13 +683,54 @@ export class AcpCompatibleTextAdapter< } } + private *emitParsedStructuredOutput( + raw: string, + threadId: string, + runId: string, + ): Generator { + try { + const object = parseJsonFromAssistantText(raw) + const messageId = this.generateId() + yield structuredOutputStartChunk({ + messageId, + model: this.model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId, + model: this.model, + threadId, + runId, + object, + raw, + }) + } catch (error: unknown) { + const parserMessage = + error instanceof Error + ? error.message + : 'Failed to parse structured output' + const preview = raw.trim().slice(0, 200) + const message = + preview === '' ? parserMessage : `${parserMessage} Content: ${preview}` + yield { + type: EventType.RUN_ERROR, + model: this.model, + timestamp: Date.now(), + message, + code: 'structured-output-parse-failed', + error: { message, code: 'structured-output-parse-failed' }, + } + } + } + structuredOutput( _options: StructuredOutputOptions>, ): Promise> { return Promise.reject( new Error( - `Structured output is not supported by the in-sandbox "${this.name}" ACP harness adapter. ` + - 'Use a model adapter for structured output, or omit outputSchema.', + 'This harness honors outputSchema on chat() in the same turn. ' + + 'Pass outputSchema to chat(), or use a model adapter for a one-shot extract.', ), ) } diff --git a/packages/ai-acp/tests/compatible.test.ts b/packages/ai-acp/tests/compatible.test.ts index bb08954608..92c28db360 100644 --- a/packages/ai-acp/tests/compatible.test.ts +++ b/packages/ai-acp/tests/compatible.test.ts @@ -27,7 +27,10 @@ const SDK_URL = pathToFileURL(require.resolve('@agentclientprotocol/sdk')).href * params it received, and reports the given protocol version (defaults to the * SDK's `PROTOCOL_VERSION`). */ -function fakeAcpAgent(protocolVersionExpr = 'PROTOCOL_VERSION'): string { +function fakeAcpAgent( + protocolVersionExpr = 'PROTOCOL_VERSION', + reply = 'pong', +): string { return ` import { AgentSideConnection, ndJsonStream, PROTOCOL_VERSION } from ${JSON.stringify(SDK_URL)} import { Readable, Writable } from 'node:stream' @@ -54,7 +57,7 @@ new AgentSideConnection((conn) => ({ writeFileSync('acp-prompt.txt', JSON.stringify(params)) await conn.sessionUpdate({ sessionId: params.sessionId, - update: { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text: 'pong' } }, + update: { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text: ${JSON.stringify(reply)} } }, }) return { stopReason: 'end_turn' } }, @@ -156,6 +159,15 @@ describe('acpCompatible config validation', () => { /needs either a "command" or an "openTransport"/, ) }) + + it('opts into combined event-source structured output', () => { + const adapter = acpCompatibleText('pi-fast', { + name: 'pi', + command: () => 'node fake-acp-agent.mjs', + }) + expect(adapter.supportsCombinedToolsAndSchema()).toBe(true) + expect(adapter.combinedStructuredOutputSource()).toBe('event') + }) }) describe('acpCompatible in-sandbox adapter (stdio)', () => { @@ -364,4 +376,75 @@ describe('acpCompatible in-sandbox adapter (stdio)', () => { await sbx.destroy() }) + + it('parses the last assistant text as structured output', async () => { + const sbx = await provider.create({}) + await sbx.fs.write( + '/workspace/fake-acp-agent.mjs', + fakeAcpAgent('PROTOCOL_VERSION', '{"ok":true}'), + ) + + const chunks = await collect( + acpCompatibleText('pi-fast', { + name: 'pi', + command: () => 'node fake-acp-agent.mjs', + }).chatStream({ + model: 'pi-fast', + messages: [{ role: 'user', content: 'report' }], + outputSchema: { + type: 'object', + properties: { ok: { type: 'boolean' } }, + required: ['ok'], + }, + logger: noopLogger, + capabilities: capabilityContextWith(sbx), + }), + ) + + const complete = chunks.find( + (chunk) => + chunk.type === 'CUSTOM' && + (chunk as { name?: string }).name === 'structured-output.complete', + ) as { value?: { object?: unknown } } | undefined + expect(complete?.value?.object).toEqual({ ok: true }) + + const prompt = JSON.parse( + await sbx.fs.read('/workspace/acp-prompt.txt'), + ) as { prompt?: Array<{ text?: string }> } + const promptText = prompt.prompt?.map((part) => part.text ?? '').join('') + expect(promptText).toMatch(/JSON object/i) + + await sbx.destroy() + }) + + it('emits a parse error when the last assistant text is not JSON', async () => { + const sbx = await provider.create({}) + await sbx.fs.write('/workspace/fake-acp-agent.mjs', FAKE_ACP_AGENT) + + const chunks = await collect( + acpCompatibleText('pi-fast', { + name: 'pi', + command: () => 'node fake-acp-agent.mjs', + }).chatStream({ + model: 'pi-fast', + messages: [{ role: 'user', content: 'report' }], + outputSchema: { + type: 'object', + properties: { ok: { type: 'boolean' } }, + required: ['ok'], + }, + logger: noopLogger, + capabilities: capabilityContextWith(sbx), + }), + ) + + const error = chunks.find((chunk) => chunk.type === 'RUN_ERROR') as { + code?: string + message?: string + } + expect(error?.code).toBe('structured-output-parse-failed') + expect(error?.message).toMatch(/pong/) + + await sbx.destroy() + }) }) diff --git a/packages/ai/skills/ai-core/structured-outputs/SKILL.md b/packages/ai/skills/ai-core/structured-outputs/SKILL.md index a8616061ca..c14833caaf 100644 --- a/packages/ai/skills/ai-core/structured-outputs/SKILL.md +++ b/packages/ai/skills/ai-core/structured-outputs/SKILL.md @@ -194,7 +194,8 @@ The terminal event is a `CUSTOM` chunk: `{ type: 'CUSTOM', name: 'structured-out | `@tanstack/ai-claude-code` | Combined + event source — `--json-schema` on the same harness turn. Read `useChat().final`. See Pattern 6. | | `@tanstack/ai-codex` | Combined + event source — `--output-schema` on the same harness turn. Read `useChat().final`. See Pattern 6. | | `@tanstack/ai-opencode` | Combined + event source — prompt-and-parse. Read `useChat().final`. See Pattern 6. | -| `@tanstack/ai-grok-build` | Combined + event source — prompt-and-parse (ACP and streaming-json). Read `useChat().final`. See Pattern 6. | +| `@tanstack/ai-grok-build` | Combined + event source — prompt-and-parse (ACP and streaming-json). Read `useChat().final` or the `structured-output` part. See Pattern 6. | +| `@tanstack/ai-acp` (`acpCompatible`) | Combined + event source — prompt-and-parse. Read `useChat().final` or the `structured-output` part. See Pattern 6. | | All other adapters (ollama, older Claude, Gemini 2.x, Grok 2/3) | Fallback: runs non-streaming `structuredOutput`, emits one `structured-output.complete` event | **Native combined mode vs fallback** is signaled by the adapter's @@ -347,9 +348,9 @@ Key behaviors: - **`partial` / `final` are derived.** The hook-level `partial` and `final` are NOT singleton state — they're derived from the latest assistant message's part (the one after the most recent user message). Between `sendMessage()` and the first chunk, `partial` reads `{}` and `final` reads `null` because no new assistant turn exists yet. - **Round-trip preserves history.** When the client sends turn N+1, each prior assistant turn's `structured-output` part is serialized back as `{ role: 'assistant', content: }` so the model sees its own prior structured response. Streaming / errored parts are dropped from the round-trip. -### Pattern 6: Harness adapters (Claude Code, Codex, OpenCode, Grok Build) +### Pattern 6: Harness adapters (Claude Code, Codex, OpenCode, Grok Build, ACP) -Dedicated harness adapters honor `chat({ outputSchema })` on the same turn. Native harness tools still run. Read the object from `await chat()` or from `useChat().final`. Do not parse assistant prose. +Dedicated harness adapters honor `chat({ outputSchema })` on the same turn. Native harness tools still run. Read the object from `await chat()`, from `useChat().final`, or from the assistant `structured-output` part on `messages[].parts`. Do not parse assistant prose. A UI endpoint must pass `stream: true`. Without it, `chat()` returns a `Promise`, not SSE. @@ -403,10 +404,10 @@ const { final } = useChat({ final?.name ``` -- Claude Code: `--json-schema`. Codex: `--output-schema`. OpenCode and Grok Build: prompt-and-parse. +- Claude Code: `--json-schema`. Codex: `--output-schema`. OpenCode, Grok Build, and `acpCompatible`: prompt-and-parse. - `partial` stays empty until `structured-output.complete`. - Client tools and `needsApproval` fail fast. The harness cannot pause for a browser round-trip. -- `acpCompatible` does not accept `outputSchema`. +- Render live work from `messages[].parts` (`thinking`, `tool-call`, `text`, `structured-output`). `final` is only the latest turn. - See [docs/structured-outputs/harnesses.md](https://github.com/TanStack/ai/blob/main/docs/structured-outputs/harnesses.md). ## Common Mistakes diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d5b156d4ef..92ff2c6bfe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -676,6 +676,9 @@ importers: '@tanstack/ai': specifier: workspace:* version: link:../../packages/ai + '@tanstack/ai-acp': + specifier: workspace:* + version: link:../../packages/ai-acp '@tanstack/ai-anthropic': specifier: workspace:* version: link:../../packages/ai-anthropic @@ -17527,7 +17530,7 @@ snapshots: '@babel/code-frame': 7.29.7 '@babel/generator': 7.29.7 '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.0) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.0(supports-color@7.2.0)) '@babel/helpers': 7.29.7 '@babel/parser': 7.29.7 '@babel/template': 7.29.7 @@ -17765,7 +17768,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.0)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.0(supports-color@7.2.0))': dependencies: '@babel/core': 7.29.0(supports-color@7.2.0) '@babel/helper-module-imports': 7.29.7 @@ -29712,7 +29715,7 @@ snapshots: less: 4.6.6 ora: 9.4.0 piscina: 5.2.0 - postcss: 8.5.19 + postcss: 8.5.26 rollup-plugin-dts: 6.4.1(rollup@4.60.1)(typescript@5.9.3) rxjs: 7.8.2 sass: 1.101.0 From 94d6cf98471435bd8e33b2adcccf5ee5e230dd4e Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 11:01:48 +0000 Subject: [PATCH 17/23] ci: apply automated fixes --- examples/ts-react-chat/src/routes/repo-report.tsx | 4 ++-- packages/ai/skills/ai-core/structured-outputs/SKILL.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index 52236d5cbd..097a688b9c 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -303,8 +303,8 @@ function RepoReportPage() { {!chat.isLoading && chat.messages.length === 0 ? (

Pick Claude Code, Grok Build, ACP compatible, or Codex, pick an - agent, then Run. - The sandbox clones {REPORT_REPO} and the typed report lands here. + agent, then Run. The sandbox clones {REPORT_REPO} and the typed + report lands here.

) : null}
diff --git a/packages/ai/skills/ai-core/structured-outputs/SKILL.md b/packages/ai/skills/ai-core/structured-outputs/SKILL.md index c14833caaf..a041a261a7 100644 --- a/packages/ai/skills/ai-core/structured-outputs/SKILL.md +++ b/packages/ai/skills/ai-core/structured-outputs/SKILL.md @@ -194,7 +194,7 @@ The terminal event is a `CUSTOM` chunk: `{ type: 'CUSTOM', name: 'structured-out | `@tanstack/ai-claude-code` | Combined + event source — `--json-schema` on the same harness turn. Read `useChat().final`. See Pattern 6. | | `@tanstack/ai-codex` | Combined + event source — `--output-schema` on the same harness turn. Read `useChat().final`. See Pattern 6. | | `@tanstack/ai-opencode` | Combined + event source — prompt-and-parse. Read `useChat().final`. See Pattern 6. | -| `@tanstack/ai-grok-build` | Combined + event source — prompt-and-parse (ACP and streaming-json). Read `useChat().final` or the `structured-output` part. See Pattern 6. | +| `@tanstack/ai-grok-build` | Combined + event source — prompt-and-parse (ACP and streaming-json). Read `useChat().final` or the `structured-output` part. See Pattern 6. | | `@tanstack/ai-acp` (`acpCompatible`) | Combined + event source — prompt-and-parse. Read `useChat().final` or the `structured-output` part. See Pattern 6. | | All other adapters (ollama, older Claude, Gemini 2.x, Grok 2/3) | Fallback: runs non-streaming `structuredOutput`, emits one `structured-output.complete` event | From 5384cec1e26327bd8e6c26db11158f297e8bdccd Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 18 Aug 2026 13:17:27 +0200 Subject: [PATCH 18/23] fix: emit harness structured output before RUN_FINISHED Hold RUN_FINISHED on ACP, Grok Build ACP, and OpenCode so the typed object lands on the same assistant turn. Reset Grok ACP text on each TEXT_MESSAGE_START. Preserve adapter RUN_ERROR on await chat({ outputSchema }). --- packages/ai-acp/src/adapters/compatible.ts | 13 +++++++++- packages/ai-acp/tests/compatible.test.ts | 12 +++++++-- packages/ai-grok-build/src/adapters/text.ts | 25 ++++++++++++++++--- packages/ai-opencode/src/adapters/text.ts | 22 +++++++++++++--- packages/ai/src/activities/chat/index.ts | 16 +++++++++++- ...t-combined-event-structured-output.test.ts | 21 ++++++++++++++++ 6 files changed, 99 insertions(+), 10 deletions(-) diff --git a/packages/ai-acp/src/adapters/compatible.ts b/packages/ai-acp/src/adapters/compatible.ts index 0b92fe7ec1..17dacb5870 100644 --- a/packages/ai-acp/src/adapters/compatible.ts +++ b/packages/ai-acp/src/adapters/compatible.ts @@ -551,6 +551,8 @@ export class AcpCompatibleTextAdapter< const wantsStructured = options.outputSchema !== undefined let lastAssistantText = '' + let lastTextMessageId: string | undefined + let heldFinished: StreamChunk | undefined for await (const chunk of mergeChunkStreams( translateAcpStream(queue, { model: this.model, @@ -580,9 +582,16 @@ export class AcpCompatibleTextAdapter< }), channel.stream, )) { + if (wantsStructured && chunk.type === EventType.RUN_FINISHED) { + heldFinished = chunk + continue + } if (wantsStructured) { if (chunk.type === EventType.TEXT_MESSAGE_START) { lastAssistantText = '' + if (typeof chunk.messageId === 'string' && chunk.messageId !== '') { + lastTextMessageId = chunk.messageId + } } else if ( chunk.type === EventType.TEXT_MESSAGE_CONTENT && typeof chunk.delta === 'string' @@ -598,8 +607,10 @@ export class AcpCompatibleTextAdapter< lastAssistantText, threadId, runId, + lastTextMessageId, ) } + if (heldFinished) yield heldFinished // Surface any pending approval requests (interactive ask-policy actions // awaiting a client decision); the client approves and re-runs to continue. @@ -687,10 +698,10 @@ export class AcpCompatibleTextAdapter< raw: string, threadId: string, runId: string, + messageId = this.generateId(), ): Generator { try { const object = parseJsonFromAssistantText(raw) - const messageId = this.generateId() yield structuredOutputStartChunk({ messageId, model: this.model, diff --git a/packages/ai-acp/tests/compatible.test.ts b/packages/ai-acp/tests/compatible.test.ts index 92c28db360..fe93f19824 100644 --- a/packages/ai-acp/tests/compatible.test.ts +++ b/packages/ai-acp/tests/compatible.test.ts @@ -401,12 +401,20 @@ describe('acpCompatible in-sandbox adapter (stdio)', () => { }), ) - const complete = chunks.find( + const completeIndex = chunks.findIndex( (chunk) => chunk.type === 'CUSTOM' && (chunk as { name?: string }).name === 'structured-output.complete', - ) as { value?: { object?: unknown } } | undefined + ) + const finishedIndex = chunks.findIndex( + (chunk) => chunk.type === 'RUN_FINISHED', + ) + const complete = chunks[completeIndex] as + | { value?: { object?: unknown } } + | undefined expect(complete?.value?.object).toEqual({ ok: true }) + expect(completeIndex).toBeGreaterThan(-1) + expect(finishedIndex).toBeGreaterThan(completeIndex) const prompt = JSON.parse( await sbx.fs.read('/workspace/acp-prompt.txt'), diff --git a/packages/ai-grok-build/src/adapters/text.ts b/packages/ai-grok-build/src/adapters/text.ts index d05178744d..c54367dac9 100644 --- a/packages/ai-grok-build/src/adapters/text.ts +++ b/packages/ai-grok-build/src/adapters/text.ts @@ -446,7 +446,10 @@ export class GrokBuildTextAdapter< }) .catch((error: unknown) => queue.fail(error)) + const wantsStructured = options.outputSchema !== undefined let lastAssistantText = '' + let lastTextMessageId: string | undefined + let heldFinished: StreamChunk | undefined for await (const chunk of mergeChunkStreams( translateAcpStream(queue, { model: this.model, @@ -468,8 +471,22 @@ export class GrokBuildTextAdapter< }), channel.stream, )) { - if (chunk.type === EventType.TEXT_MESSAGE_CONTENT) { - lastAssistantText += chunk.delta + if (wantsStructured && chunk.type === EventType.RUN_FINISHED) { + heldFinished = chunk + continue + } + if (wantsStructured) { + if (chunk.type === EventType.TEXT_MESSAGE_START) { + lastAssistantText = '' + if (typeof chunk.messageId === 'string' && chunk.messageId !== '') { + lastTextMessageId = chunk.messageId + } + } else if ( + chunk.type === EventType.TEXT_MESSAGE_CONTENT && + typeof chunk.delta === 'string' + ) { + lastAssistantText += chunk.delta + } } yield chunk } @@ -479,8 +496,10 @@ export class GrokBuildTextAdapter< lastAssistantText, threadId, runId, + lastTextMessageId, ) } + if (heldFinished) yield heldFinished if (this.adapterConfig.emitDiff !== false) { yield* this.emitDiffChunks(sandbox, cwd, threadId, runId) @@ -525,10 +544,10 @@ export class GrokBuildTextAdapter< raw: string, threadId: string, runId: string, + messageId = this.generateId(), ): Generator { try { const object = parseJsonFromAssistantText(raw) - const messageId = this.generateId() yield structuredOutputStartChunk({ messageId, model: this.model, diff --git a/packages/ai-opencode/src/adapters/text.ts b/packages/ai-opencode/src/adapters/text.ts index fd9837a3c1..1ee74d4c66 100644 --- a/packages/ai-opencode/src/adapters/text.ts +++ b/packages/ai-opencode/src/adapters/text.ts @@ -358,7 +358,9 @@ export class OpencodeTextAdapter< }) .catch((error: unknown) => queue.fail(error)) - yield* mergeChunkStreams( + let heldFinished: StreamChunk | undefined + let lastTextMessageId: string | undefined + for await (const chunk of mergeChunkStreams( translateOpencodeStream(queue, { model: this.model, runId, @@ -374,12 +376,25 @@ export class OpencodeTextAdapter< }), }), channel.stream, - ) + )) { + if (options.outputSchema && chunk.type === EventType.RUN_FINISHED) { + heldFinished = chunk + continue + } + if ( + chunk.type === EventType.TEXT_MESSAGE_START && + typeof chunk.messageId === 'string' && + chunk.messageId !== '' + ) { + lastTextMessageId = chunk.messageId + } + yield chunk + } if (options.outputSchema) { try { const object = parseJsonFromAssistantText(lastAssistantText) - const messageId = this.generateId() + const messageId = lastTextMessageId ?? this.generateId() yield structuredOutputStartChunk({ messageId, model: this.model, @@ -408,6 +423,7 @@ export class OpencodeTextAdapter< } } } + if (heldFinished) yield heldFinished // Surface pending approval requests (ask-policy actions awaiting a client // decision); the client approves and re-runs to continue. diff --git a/packages/ai/src/activities/chat/index.ts b/packages/ai/src/activities/chat/index.ts index 6727ac20bf..8c7da926c6 100644 --- a/packages/ai/src/activities/chat/index.ts +++ b/packages/ai/src/activities/chat/index.ts @@ -1596,9 +1596,23 @@ class TextEngine< } private handleRunErrorEvent( - _chunk: Extract, + chunk: Extract, ): void { this.earlyTermination = true + if (this.finalStructuredOutput && this.finalizationError === null) { + const message = + chunk.message || + chunk.error?.message || + 'Run failed before structured output completed' + this.finalizationError = { + message, + ...(chunk.code !== undefined + ? { code: chunk.code } + : chunk.error?.code !== undefined + ? { code: chunk.error.code } + : {}), + } + } } private finalizeCurrentThinkingStep(): void { diff --git a/packages/ai/tests/chat-combined-event-structured-output.test.ts b/packages/ai/tests/chat-combined-event-structured-output.test.ts index f98e06c862..f33e0e0d1e 100644 --- a/packages/ai/tests/chat-combined-event-structured-output.test.ts +++ b/packages/ai/tests/chat-combined-event-structured-output.test.ts @@ -249,4 +249,25 @@ describe('chat({ outputSchema }) — combined event source', () => { expect(errors[0].code).not.toBe('structured-output-parse-failed') } }) + + it('throws the adapter RUN_ERROR on the Promise path', async () => { + const { adapter } = createMockAdapter({ + iterations: [ + eventSourcedTurn({ + prose: 'I will look around.', + runError: 'harness failed', + }), + ], + supportsCombinedToolsAndSchema: true, + combinedStructuredOutputSource: 'event', + }) + + await expect( + chat({ + adapter, + messages: [{ role: 'user', content: 'extract' }], + outputSchema: PersonSchema, + }), + ).rejects.toThrow('harness failed') + }) }) From dc92df3706d9da68ec9b5b55c025323327b6f6d9 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 18 Aug 2026 13:40:32 +0200 Subject: [PATCH 19/23] fix(ai-codex): stream intermediate prose and parse last schema JSON Hold only the last agent_message when outputSchema is set. Flush non-JSON prose when the next message, tool, or reasoning item starts. Parse the last held message with parseJsonFromAssistantText so fenced JSON works. Parse failures use code structured-output-parse-failed. --- docs/adapters/codex.md | 2 +- docs/config.json | 2 +- docs/structured-outputs/harnesses.md | 2 +- packages/ai-codex/src/stream/translate.ts | 120 +++++++----- packages/ai-codex/tests/translate.test.ts | 211 ++++++++++++++++++++-- 5 files changed, 274 insertions(+), 63 deletions(-) diff --git a/docs/adapters/codex.md b/docs/adapters/codex.md index ed1ef8e63c..a39a32b4e4 100644 --- a/docs/adapters/codex.md +++ b/docs/adapters/codex.md @@ -170,7 +170,7 @@ const stream = chat({ ## Structured Output -Pass `outputSchema` on `chat()`. Codex runs one harness turn and constrains the last message with `--output-schema`. Tool activity still streams. The object arrives as `structured-output.complete`. +Pass `outputSchema` on `chat()`. Codex runs one harness turn and constrains the last message with `--output-schema`. Tool activity and earlier assistant text still stream. The last message is parsed as the schema object and arrives as `structured-output.complete`. ```ts import { chat } from "@tanstack/ai" diff --git a/docs/config.json b/docs/config.json index 7e9287d2a1..81a71a0ad7 100644 --- a/docs/config.json +++ b/docs/config.json @@ -879,7 +879,7 @@ "label": "Codex", "to": "adapters/codex", "addedAt": "2026-06-12", - "updatedAt": "2026-08-17" + "updatedAt": "2026-08-18" }, { "label": "OpenCode", diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index f5913d27c5..14e7dca6b4 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -171,7 +171,7 @@ Each part type: | Adapter | How the schema is applied | |---|---| | Claude Code | Native `--json-schema` flag on the same turn. The value is inline JSON, not a file path. | -| Codex | Native `--output-schema` flag on the same turn | +| Codex | Native `--output-schema` flag on the same turn. Earlier assistant text streams. The last message is the schema object. | | OpenCode | Schema is added to the prompt. The adapter parses the last assistant text. | | Grok Build | Schema is added to the prompt. The adapter parses the last assistant text. | | ACP compatible | Schema is added to the prompt. The adapter parses the last assistant text. | diff --git a/packages/ai-codex/src/stream/translate.ts b/packages/ai-codex/src/stream/translate.ts index ca3244405b..ab2419f3b0 100644 --- a/packages/ai-codex/src/stream/translate.ts +++ b/packages/ai-codex/src/stream/translate.ts @@ -1,5 +1,6 @@ import { EventType, buildBaseUsage } from '@tanstack/ai' import { + parseJsonFromAssistantText, structuredOutputCompleteChunk, structuredOutputStartChunk, } from '@tanstack/ai/adapter-internals' @@ -162,7 +163,11 @@ function buildUsage(usage: CodexUsage | undefined): TokenUsage | undefined { * * Codex reports assistant text and reasoning only as completed items (no * token-level deltas), so each `agent_message` / `reasoning` item becomes a - * single START/CONTENT/END burst. + * single START/CONTENT/END burst. When `expectStructuredOutput` is set, earlier + * `agent_message` items stream as text as soon as the next message starts, or + * as soon as a tool or reasoning item starts if that text is not JSON. JSON + * stays held through later tools so a last schema message is not dropped. The + * last held message is parsed as the schema object on `turn.completed`. * * Invariant: every TOOL_CALL_START is eventually paired with a * TOOL_CALL_RESULT (synthesized as `{"status":"interrupted"}` when the run @@ -243,7 +248,7 @@ export async function* translateThreadEvents( unresolvedToolCalls.add(item.id) } - const pendingAgentMessages: Array<{ id: string; text: string }> = [] + let pendingStructuredMessage: { id: string; text: string } | undefined function* emitAgentText(item: { id: string @@ -272,58 +277,71 @@ export async function* translateThreadEvents( } } - function* flushAgentMessages( - lastIsStructured: boolean, - ): Generator { - for (let index = 0; index < pendingAgentMessages.length; index++) { - const item = pendingAgentMessages[index] - if (item === undefined) continue - const isLast = index === pendingAgentMessages.length - 1 - if (lastIsStructured && isLast) { - try { - const object: unknown = JSON.parse(item.text) - yield structuredOutputStartChunk({ - messageId: item.id, - model, - threadId, - runId, - }) - yield structuredOutputCompleteChunk({ - messageId: item.id, - model, - threadId, - runId, - object, - raw: item.text, - }) - } catch (error: unknown) { - const message = - error instanceof Error - ? error.message - : 'Invalid structured output JSON' - yield { - type: EventType.RUN_ERROR, - model, - timestamp: now(), - message, - error: { message }, - } - } - } else { - yield* emitAgentText(item) + function* flushPendingAsText(): Generator { + if (pendingStructuredMessage === undefined) return + const item = pendingStructuredMessage + pendingStructuredMessage = undefined + yield* emitAgentText(item) + } + + function* flushPendingIfNotStructured(): Generator { + if (pendingStructuredMessage === undefined) return + try { + parseJsonFromAssistantText(pendingStructuredMessage.text) + } catch { + yield* flushPendingAsText() + } + } + + function* emitStructuredFromPending(): Generator { + if (pendingStructuredMessage === undefined) return + const item = pendingStructuredMessage + pendingStructuredMessage = undefined + try { + const object = parseJsonFromAssistantText(item.text) + yield structuredOutputStartChunk({ + messageId: item.id, + model, + threadId, + runId, + }) + yield structuredOutputCompleteChunk({ + messageId: item.id, + model, + threadId, + runId, + object, + raw: item.text, + }) + } catch (error: unknown) { + const parserMessage = + error instanceof Error + ? error.message + : 'Invalid structured output JSON' + const preview = item.text.trim().slice(0, 200) + const message = + preview === '' ? parserMessage : `${parserMessage} Content: ${preview}` + yield { + type: EventType.RUN_ERROR, + model, + timestamp: now(), + message, + code: 'structured-output-parse-failed', + error: { message, code: 'structured-output-parse-failed' }, } } - pendingAgentMessages.length = 0 } function* handleItemCompleted(item: CodexThreadItem): Generator { if (item.type === 'agent_message') { if (ctx.expectStructuredOutput === true) { - pendingAgentMessages.push({ id: item.id, text: item.text }) + yield* flushPendingAsText() + pendingStructuredMessage = { id: item.id, text: item.text } return } yield* emitAgentText(item) } else if (item.type === 'reasoning') { + yield* flushPendingIfNotStructured() const reasoningId = item.id yield { type: EventType.REASONING_START, @@ -358,6 +376,7 @@ export async function* translateThreadEvents( timestamp: now(), } } else if (isToolItem(item)) { + yield* flushPendingIfNotStructured() yield* openToolCall(item) unresolvedToolCalls.delete(item.id) const { content, isError } = toolResultForItem(item) @@ -398,12 +417,17 @@ export async function* translateThreadEvents( if (event.type === 'item.started') { if (isToolItem(event.item)) { + yield* flushPendingIfNotStructured() yield* openToolCall(event.item) } } else if (event.type === 'item.completed') { yield* handleItemCompleted(event.item) } else if (event.type === 'turn.completed') { - yield* flushAgentMessages(ctx.expectStructuredOutput === true) + if (ctx.expectStructuredOutput === true) { + yield* emitStructuredFromPending() + } else { + yield* flushPendingAsText() + } yield* synthesizeUnresolvedResults() const usage = buildUsage(event.usage) yield { @@ -416,7 +440,7 @@ export async function* translateThreadEvents( ...(usage !== undefined && { usage }), } } else if (event.type === 'turn.failed' || event.type === 'error') { - yield* flushAgentMessages(false) + yield* flushPendingAsText() yield* synthesizeUnresolvedResults() const message = event.type === 'turn.failed' @@ -434,11 +458,17 @@ export async function* translateThreadEvents( // long-running items resolve via item.completed, and intermediate // updates (e.g. streaming command output) are intentionally dropped. } + if (ctx.expectStructuredOutput === true) { + yield* emitStructuredFromPending() + } else { + yield* flushPendingAsText() + } } catch (error) { // The run is dying (abort or SDK failure). Pair any started tool calls // with a synthetic result first so the next request's pending-tool-call // scan doesn't try to execute them, then let the adapter surface the // error as RUN_ERROR. + yield* flushPendingAsText() yield* synthesizeUnresolvedResults() throw error } diff --git a/packages/ai-codex/tests/translate.test.ts b/packages/ai-codex/tests/translate.test.ts index 9b20810a32..cf50e76641 100644 --- a/packages/ai-codex/tests/translate.test.ts +++ b/packages/ai-codex/tests/translate.test.ts @@ -36,6 +36,30 @@ async function collect( return chunks } +function structuredComplete(chunks: Array) { + return chunks.find( + (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', + ) +} + +function textDeltas(chunks: Array): string { + return chunks + .filter((c) => c.type === 'TEXT_MESSAGE_CONTENT') + .map((c) => ('delta' in c ? c.delta : '')) + .join('') +} + +function expectStructuredObject( + chunks: Array, + object: Record, +) { + const complete = structuredComplete(chunks) + expect(complete).toBeDefined() + if (complete?.type === 'CUSTOM') { + expect(complete.value).toEqual(expect.objectContaining({ object })) + } +} + const started: CodexThreadEvent = { type: 'thread.started', thread_id: 'sess-1', @@ -469,16 +493,14 @@ describe('translateThreadEvents', () => { (c) => c.type === 'CUSTOM' && c.name === 'structured-output.start', ), ).toBe(true) - const complete = chunks.find( - (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', - ) + const complete = structuredComplete(chunks) expect(complete).toBeDefined() if (complete?.type === 'CUSTOM') { expect(complete.value).toEqual( expect.objectContaining({ object: { ok: true }, raw: '{"ok":true}' }), ) } - expect(chunks.some((c) => c.type === 'TEXT_MESSAGE_CONTENT')).toBe(false) + expect(textDeltas(chunks)).toBe('') }) it('keeps earlier agent_message text when only the last item is structured', async () => { @@ -497,16 +519,8 @@ describe('translateThreadEvents', () => { ], makeCtx({ expectStructuredOutput: true }), ) - const text = chunks - .filter((c) => c.type === 'TEXT_MESSAGE_CONTENT') - .map((c) => ('delta' in c ? c.delta : '')) - .join('') - expect(text).toBe('working') - expect( - chunks.some( - (c) => c.type === 'CUSTOM' && c.name === 'structured-output.complete', - ), - ).toBe(true) + expect(textDeltas(chunks)).toBe('working') + expectStructuredObject(chunks, { ok: true }) }) it('emits RUN_ERROR when the last agent_message is not JSON', async () => { @@ -521,6 +535,173 @@ describe('translateThreadEvents', () => { ], makeCtx({ expectStructuredOutput: true }), ) - expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(true) + expect(chunks.find((c) => c.type === 'RUN_ERROR')).toMatchObject({ + type: 'RUN_ERROR', + code: 'structured-output-parse-failed', + message: expect.stringMatching(/not json/), + }) + }) + + it('parses fenced JSON from the last agent_message', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { + id: 'item-1', + type: 'agent_message', + text: '```json\n{"ok":true}\n```', + }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + expectStructuredObject(chunks, { ok: true }) + expect(chunks.some((c) => c.type === 'RUN_ERROR')).toBe(false) + }) + + it('emits earlier agent_message text before the last structured item arrives', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: 'working' }, + }, + { + type: 'item.started', + item: { + id: 'cmd-1', + type: 'command_execution', + command: 'ls', + status: 'in_progress', + }, + }, + { + type: 'item.completed', + item: { + id: 'cmd-1', + type: 'command_execution', + command: 'ls', + aggregated_output: 'ok', + status: 'completed', + }, + }, + { + type: 'item.completed', + item: { id: 'item-2', type: 'agent_message', text: '{"ok":true}' }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + const types = chunks.map((c) => + c.type === 'CUSTOM' ? `CUSTOM:${c.name}` : c.type, + ) + const workingIdx = chunks.findIndex( + (c) => c.type === 'TEXT_MESSAGE_CONTENT' && c.delta === 'working', + ) + const toolStartIdx = types.indexOf('TOOL_CALL_START') + const completeIdx = types.indexOf('CUSTOM:structured-output.complete') + const finishedIdx = types.indexOf('RUN_FINISHED') + expect(workingIdx).toBeGreaterThan(-1) + expect(toolStartIdx).toBeGreaterThan(workingIdx) + expect(completeIdx).toBeGreaterThan(toolStartIdx) + expect(completeIdx).toBeLessThan(finishedIdx) + }) + + it('keeps a JSON agent_message as structured output when a started tool completes after it', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.started', + item: { + id: 'cmd-1', + type: 'command_execution', + command: 'ls', + status: 'in_progress', + }, + }, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: '{"ok":true}' }, + }, + { + type: 'item.completed', + item: { + id: 'cmd-1', + type: 'command_execution', + command: 'ls', + aggregated_output: 'ok', + status: 'completed', + }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + expect(textDeltas(chunks)).toBe('') + expectStructuredObject(chunks, { ok: true }) + const types = chunks.map((c) => + c.type === 'CUSTOM' ? `CUSTOM:${c.name}` : c.type, + ) + expect(types.indexOf('TOOL_CALL_START')).toBeLessThan( + types.indexOf('CUSTOM:structured-output.complete'), + ) + expect(types.indexOf('TOOL_CALL_RESULT')).toBeLessThan( + types.indexOf('CUSTOM:structured-output.complete'), + ) + }) + + it('keeps a JSON agent_message as structured output when tools follow it', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: '{"ok":true}' }, + }, + { + type: 'item.started', + item: { + id: 'cmd-1', + type: 'command_execution', + command: 'ls', + status: 'in_progress', + }, + }, + { + type: 'item.completed', + item: { + id: 'cmd-1', + type: 'command_execution', + command: 'ls', + aggregated_output: 'ok', + status: 'completed', + }, + }, + completedTurn, + ], + makeCtx({ expectStructuredOutput: true }), + ) + expect(textDeltas(chunks)).toBe('') + expectStructuredObject(chunks, { ok: true }) + }) + + it('does not drop the last agent_message when the stream ends without turn.completed', async () => { + const chunks = await collect( + [ + started, + { + type: 'item.completed', + item: { id: 'item-1', type: 'agent_message', text: '{"ok":true}' }, + }, + ], + makeCtx({ expectStructuredOutput: true }), + ) + expectStructuredObject(chunks, { ok: true }) }) }) From b516a4b6a690c009a59697ead04d804bc9e047dc Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 18 Aug 2026 14:45:53 +0200 Subject: [PATCH 20/23] fix: make harness auth a setting and stream Codex text Auth is now authMode host or api-key on the adapter. It is not inferred from the sandbox. Host login skips ACP authenticate and scrubs API keys so grok login can win. API key mode is for CI and runners. Codex now emits agent_message deltas from item.updated instead of holding all text until turn.completed. --- docs/adapters/codex.md | 2 +- docs/adapters/grok-build.md | 20 ++- docs/config.json | 2 +- docs/sandbox/harnesses.md | 6 +- docs/structured-outputs/harnesses.md | 2 +- .../ts-react-chat/src/repo-report-options.ts | 10 ++ .../src/routes/api.sandbox-repo-report.ts | 12 +- .../ts-react-chat/src/routes/repo-report.tsx | 25 +++- .../ts-react-chat/src/sandbox-triage.test.ts | 9 ++ examples/ts-react-chat/src/sandbox-triage.ts | 88 ++++++++++---- packages/ai-acp/src/adapters/compatible.ts | 20 ++- packages/ai-claude-code/src/adapters/text.ts | 16 ++- .../ai-claude-code/src/provider-options.ts | 5 + packages/ai-codex/src/adapters/text.ts | 7 ++ packages/ai-codex/src/index.ts | 1 + packages/ai-codex/src/provider-options.ts | 5 + packages/ai-codex/src/stream/translate.ts | 115 ++++++++---------- packages/ai-codex/tests/translate.test.ts | 33 ++++- packages/ai-grok-build/src/adapters/text.ts | 33 +++-- packages/ai-grok-build/src/auth.ts | 42 ++++++- packages/ai-grok-build/src/index.ts | 6 + .../ai-grok-build/src/provider-options.ts | 9 +- packages/ai-grok-build/tests/acp.test.ts | 43 ++++++- .../tests/durability-protocol-warning.test.ts | 3 +- 24 files changed, 377 insertions(+), 137 deletions(-) diff --git a/docs/adapters/codex.md b/docs/adapters/codex.md index a39a32b4e4..30fed02eb6 100644 --- a/docs/adapters/codex.md +++ b/docs/adapters/codex.md @@ -170,7 +170,7 @@ const stream = chat({ ## Structured Output -Pass `outputSchema` on `chat()`. Codex runs one harness turn and constrains the last message with `--output-schema`. Tool activity and earlier assistant text still stream. The last message is parsed as the schema object and arrives as `structured-output.complete`. +Pass `outputSchema` on `chat()`. Codex runs one harness turn and constrains the last message with `--output-schema`. Tool activity and assistant text stream as Codex writes them. The last message is also parsed as the schema object and arrives as `structured-output.complete`. ```ts import { chat } from "@tanstack/ai" diff --git a/docs/adapters/grok-build.md b/docs/adapters/grok-build.md index faf826d3f1..c02d76c601 100644 --- a/docs/adapters/grok-build.md +++ b/docs/adapters/grok-build.md @@ -38,13 +38,23 @@ You also need a sandbox provider (e.g. `@tanstack/ai-sandbox-docker`) and the ## Authentication -Grok Build resolves credentials the same way the `grok` CLI does: +Pick the mode. Do not infer it from the sandbox. A local-process run can be +your laptop (`grok login`) or a GitHub runner that only has `XAI_API_KEY`. -- the `XAI_API_KEY` environment variable (headless / sandbox — inject it as a - workspace secret), or -- an existing grok.com browser login on the machine (local dev). +```ts +// Machine already has `grok login` +grokBuildText('composer-2.5', { authMode: 'host' }) + +// CI / runner: inject the key and authenticate with it +grokBuildText('composer-2.5', { authMode: 'api-key' }) +``` + +- `'host'`: skip ACP `authenticate`. The CLI uses the host login. Do not + inject `XAI_API_KEY` into that process, or the CLI may prefer a bad key. +- `'api-key'`: call ACP `authenticate` with `xai.api_key`. Inject + `XAI_API_KEY` as a workspace secret. -The two auth modes expose the model under slightly different ids; the adapter +The two auth modes expose the model under slightly different ids. The adapter maps the short alias for you (see [Models](#models)). ## Basic Usage diff --git a/docs/config.json b/docs/config.json index 81a71a0ad7..a26b044ad0 100644 --- a/docs/config.json +++ b/docs/config.json @@ -891,7 +891,7 @@ "label": "Grok Build", "to": "adapters/grok-build", "addedAt": "2026-06-29", - "updatedAt": "2026-08-17" + "updatedAt": "2026-08-18" }, { "label": "ACP-Compatible", diff --git a/docs/sandbox/harnesses.md b/docs/sandbox/harnesses.md index cd922304d8..2bf3f4fdf2 100644 --- a/docs/sandbox/harnesses.md +++ b/docs/sandbox/harnesses.md @@ -20,9 +20,9 @@ to `chat({ adapter })` and run it under any provider. | Harness | Package | Adapter | Auth env | | --- | --- | --- | --- | -| [Grok Build](../adapters/grok-build) | `@tanstack/ai-grok-build` | `grokBuildText` | `XAI_API_KEY` (or grok.com login on local-process) | -| [Claude Code](../adapters/claude-code) | `@tanstack/ai-claude-code` | `claudeCodeText` | `ANTHROPIC_API_KEY` (or `claude login`) | -| [Codex](../adapters/codex) | `@tanstack/ai-codex` | `codexText` | `CODEX_API_KEY` (or `OPENAI_API_KEY`) | +| [Grok Build](../adapters/grok-build) | `@tanstack/ai-grok-build` | `grokBuildText` | `authMode: 'host'` (`grok login`) or `authMode: 'api-key'` (`XAI_API_KEY`) | +| [Claude Code](../adapters/claude-code) | `@tanstack/ai-claude-code` | `claudeCodeText` | `authMode: 'host'` (`claude login`) or `authMode: 'api-key'` (`ANTHROPIC_API_KEY`) | +| [Codex](../adapters/codex) | `@tanstack/ai-codex` | `codexText` | `authMode: 'host'` (`codex login`) or `authMode: 'api-key'` (`CODEX_API_KEY`) | | [OpenCode](../adapters/opencode) | `@tanstack/ai-opencode` | `opencodeText` | `OPENAI_API_KEY` (model-dependent) | ```ts diff --git a/docs/structured-outputs/harnesses.md b/docs/structured-outputs/harnesses.md index 14e7dca6b4..dda8f9e996 100644 --- a/docs/structured-outputs/harnesses.md +++ b/docs/structured-outputs/harnesses.md @@ -171,7 +171,7 @@ Each part type: | Adapter | How the schema is applied | |---|---| | Claude Code | Native `--json-schema` flag on the same turn. The value is inline JSON, not a file path. | -| Codex | Native `--output-schema` flag on the same turn. Earlier assistant text streams. The last message is the schema object. | +| Codex | Native `--output-schema` flag on the same turn. Assistant text streams as Codex writes it. The last message is also the schema object. | | OpenCode | Schema is added to the prompt. The adapter parses the last assistant text. | | Grok Build | Schema is added to the prompt. The adapter parses the last assistant text. | | ACP compatible | Schema is added to the prompt. The adapter parses the last assistant text. | diff --git a/examples/ts-react-chat/src/repo-report-options.ts b/examples/ts-react-chat/src/repo-report-options.ts index 454febe7ce..68dafc5214 100644 --- a/examples/ts-react-chat/src/repo-report-options.ts +++ b/examples/ts-react-chat/src/repo-report-options.ts @@ -5,6 +5,7 @@ export type ReportHarness = 'claude-code' | 'codex' | 'grok' | 'acp' export type ReportProvider = 'docker' | 'local' +export type ReportAuthMode = 'host' | 'api-key' export type ReportAgent = 'explainer' | 'package-map' | 'first-hour' export const REPORT_HARNESSES: Record = { @@ -19,6 +20,11 @@ export const REPORT_PROVIDERS: Record = { local: { label: 'Local process' }, } +export const REPORT_AUTH_MODES: Record = { + host: { label: 'Host login' }, + 'api-key': { label: 'API key' }, +} + export const REPORT_AGENTS: Record< ReportAgent, { label: string; hint: string } @@ -49,4 +55,8 @@ export function isReportAgent(value: unknown): value is ReportAgent { return typeof value === 'string' && value in REPORT_AGENTS } +export function isReportAuthMode(value: unknown): value is ReportAuthMode { + return typeof value === 'string' && value in REPORT_AUTH_MODES +} + export const REPORT_REPO = 'TanStack/ai' diff --git a/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts b/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts index 0b9758e6b3..7d73b3549b 100644 --- a/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts +++ b/examples/ts-react-chat/src/routes/api.sandbox-repo-report.ts @@ -1,6 +1,7 @@ import { createFileRoute } from '@tanstack/react-router' import { isReportAgent, + isReportAuthMode, isReportHarness, isReportProvider, REPORT_AGENTS, @@ -12,6 +13,7 @@ import type { ReportAgent } from '../repo-report-options' interface ReportBody { harness: unknown provider: unknown + authMode: unknown agent: unknown threadId: unknown } @@ -69,12 +71,13 @@ export async function repoReportPost(request: Request): Promise { if (!isReportAgent(data.agent)) { return json(400, 'Unknown agent.') } + const authMode = isReportAuthMode(data.authMode) ? data.authMode : 'host' const threadId = typeof data.threadId === 'string' && data.threadId !== '' ? data.threadId : crypto.randomUUID() - const missing = missingEnv(data.harness, data.provider) + const missing = missingEnv(data.harness, data.provider, authMode) if (missing.length > 0) { return json( 500, @@ -91,14 +94,11 @@ export async function repoReportPost(request: Request): Promise { provider: data.provider, repo: REPORT_REPO, threadId, - // Local Claude Code uses the host `claude login`. An API key in `.env` - // would override that login in `-p` mode. - useSubscription: - data.provider === 'local' && data.harness === 'claude-code', + authMode, }) const stream = chat({ threadId, - adapter: buildHarnessAdapter(data.harness, data.provider), + adapter: buildHarnessAdapter(data.harness, data.provider, { authMode }), messages: [{ role: 'user', content: buildRepoReportPrompt(data.agent) }], outputSchema: RepoReportSchema, stream: true, diff --git a/examples/ts-react-chat/src/routes/repo-report.tsx b/examples/ts-react-chat/src/routes/repo-report.tsx index 097a688b9c..a32a5cae80 100644 --- a/examples/ts-react-chat/src/routes/repo-report.tsx +++ b/examples/ts-react-chat/src/routes/repo-report.tsx @@ -5,9 +5,11 @@ import { parsePartialJSON } from '@tanstack/ai' import { fetchServerSentEvents, useChat } from '@tanstack/ai-react' import { isReportAgent, + isReportAuthMode, isReportHarness, isReportProvider, REPORT_AGENTS, + REPORT_AUTH_MODES, REPORT_HARNESSES, REPORT_PROVIDERS, REPORT_REPO, @@ -16,6 +18,7 @@ import { looksLikeReport, RepoReportSchema } from '../repo-report-schema' import type { RepoReportCard } from '../repo-report-schema' import type { ReportAgent, + ReportAuthMode, ReportHarness, ReportProvider, } from '../repo-report-options' @@ -99,13 +102,14 @@ function RepoReportPage() { const [threadId] = useState(() => crypto.randomUUID()) const [harness, setHarness] = useState('claude-code') const [provider, setProvider] = useState('local') + const [authMode, setAuthMode] = useState('host') const [agent, setAgent] = useState('explainer') const chat = useChat({ threadId, outputSchema: RepoReportSchema, connection: fetchServerSentEvents('/api/sandbox-repo-report'), - forwardedProps: { harness, provider, agent, threadId }, + forwardedProps: { harness, provider, authMode, agent, threadId }, }) const canRun = !chat.isLoading @@ -184,6 +188,25 @@ function RepoReportPage() { ))} +