diff --git a/examples/ts-svelte-chat/env.example b/examples/ts-svelte-chat/.env.example similarity index 100% rename from examples/ts-svelte-chat/env.example rename to examples/ts-svelte-chat/.env.example diff --git a/examples/ts-vue-chat/env.example b/examples/ts-vue-chat/.env.example similarity index 100% rename from examples/ts-vue-chat/env.example rename to examples/ts-vue-chat/.env.example diff --git a/examples/ts-vue-chat/package.json b/examples/ts-vue-chat/package.json index d35140bb..dafd3b89 100644 --- a/examples/ts-vue-chat/package.json +++ b/examples/ts-vue-chat/package.json @@ -18,6 +18,8 @@ "@tanstack/ai-openai": "workspace:*", "@tanstack/ai-vue": "workspace:*", "@tanstack/ai-vue-ui": "workspace:*", + "@tanstack/vue-ai-devtools": "workspace:*", + "@tanstack/vue-devtools": "^0.1.2", "marked": "^15.0.6", "vue": "^3.5.25", "vue-router": "^4.5.0", @@ -26,7 +28,7 @@ "devDependencies": { "@tailwindcss/vite": "^4.1.17", "@types/node": "^24.10.1", - "@vitejs/plugin-vue": "^5.2.3", + "@vitejs/plugin-vue": "^6.0.3", "autoprefixer": "^10.4.21", "concurrently": "^9.1.2", "dotenv": "^17.2.3", diff --git a/examples/ts-vue-chat/src/App.vue b/examples/ts-vue-chat/src/App.vue index 0f09c0c1..ba2858b0 100644 --- a/examples/ts-vue-chat/src/App.vue +++ b/examples/ts-vue-chat/src/App.vue @@ -1,10 +1,24 @@ diff --git a/examples/ts-vue-start-chat/.env.example b/examples/ts-vue-start-chat/.env.example new file mode 100644 index 00000000..2b17075b --- /dev/null +++ b/examples/ts-vue-start-chat/.env.example @@ -0,0 +1,11 @@ +# OpenAI +OPENAI_API_KEY=your_openai_api_key_here + +# Anthropic +ANTHROPIC_API_KEY=your_anthropic_api_key_here + +# Gemini +GEMINI_API_KEY=your_gemini_api_key_here + +# Ollama (no API key needed, runs locally) +# Make sure Ollama is running: ollama serve diff --git a/examples/ts-vue-start-chat/.gitignore b/examples/ts-vue-start-chat/.gitignore new file mode 100644 index 00000000..24ebf80e --- /dev/null +++ b/examples/ts-vue-start-chat/.gitignore @@ -0,0 +1,22 @@ +# Dependencies +node_modules + +# Build +dist + +# Logs +*.log + +# Environment +.env +.env.local +.env.*.local + +# IDE +.vscode +.idea +*.swp +*.swo + +# OS +.DS_Store diff --git a/examples/ts-vue-start-chat/CHANGELOG.md b/examples/ts-vue-start-chat/CHANGELOG.md new file mode 100644 index 00000000..9daede3e --- /dev/null +++ b/examples/ts-vue-start-chat/CHANGELOG.md @@ -0,0 +1,15 @@ +# ts-vue-chat + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [[`78f15fe`](https://github.com/TanStack/ai/commit/78f15fea74c7bfd5fcdb0fe106968b110f0b2bc2), [`52c3172`](https://github.com/TanStack/ai/commit/52c317244294a75b0c7f5e6cafc8583fbb6abfb7)]: + - @tanstack/ai-openai@0.0.3 + - @tanstack/ai@0.0.3 + - @tanstack/ai-anthropic@0.0.3 + - @tanstack/ai-client@0.0.3 + - @tanstack/ai-gemini@0.0.3 + - @tanstack/ai-ollama@0.0.3 + - @tanstack/ai-vue@0.0.2 + - @tanstack/ai-vue-ui@0.0.1 diff --git a/examples/ts-vue-start-chat/README.md b/examples/ts-vue-start-chat/README.md new file mode 100644 index 00000000..f90f9f84 --- /dev/null +++ b/examples/ts-vue-start-chat/README.md @@ -0,0 +1,75 @@ +# TanStack AI - Vue Start Chat Example + +A Vue 3 chat application demonstrating the use of `@tanstack/ai-vue` with +file-based routing powered by `@tanstack/vue-start`. + +## Setup + +1. Copy `env.example` to `.env` and add your API keys: + +```bash +cp env.example .env +``` + +2. Install dependencies: + +```bash +pnpm install +``` + +3. Start the development server: + +```bash +pnpm dev +``` + +4. Open [http://localhost:3000](http://localhost:3000) in your browser. + +## Features + +- Real-time streaming chat with multiple AI providers +- Support for OpenAI, Anthropic, Gemini, and Ollama +- Client-side and server-side tools +- Tool approval workflow +- Guitar recommendation demo + +## Project Structure + +``` +src/ +├── routes/ # File-based routes (TanStack Router/Start) +│ ├── __root.tsx +│ ├── index.ts +│ ├── vue-ui.ts +│ ├── api.chat.ts # Server route for chat +│ └── guitars/ +│ ├── index.ts +│ └── $id.ts +├── router.ts # TanStack Vue Router setup +├── routeTree.gen.ts # Generated route tree +├── styles.css # Global styles +├── components/ # UI components +│ ├── Header.vue +│ ├── ChatInput.vue +│ ├── Messages.vue +│ ├── ThinkingPart.vue +│ └── GuitarRecommendation.vue +├── lib/ # Utilities +│ ├── model-selection.ts +│ └── guitar-tools.ts +├── data/ # Example data +│ └── guitars.ts +└── views/ # Page components + ├── ChatView.vue + └── GuitarDetailView.vue +``` + +## Tech Stack + +- Vue 3 with Composition API +- TypeScript +- Vite +- Tailwind CSS +- @tanstack/vue-start +- @tanstack/vue-router +- @tanstack/ai-vue diff --git a/examples/ts-vue-start-chat/package.json b/examples/ts-vue-start-chat/package.json new file mode 100644 index 00000000..d9c2b981 --- /dev/null +++ b/examples/ts-vue-start-chat/package.json @@ -0,0 +1,47 @@ +{ + "name": "ts-vue-start-chat", + "version": "0.0.1", + "private": true, + "type": "module", + "scripts": { + "dev": "vite dev --port 3000", + "build": "vue-tsc -b && vite build", + "preview": "vite preview", + "check": "vue-tsc --noEmit" + }, + "dependencies": { + "@tanstack/ai": "workspace:*", + "@tanstack/ai-anthropic": "workspace:*", + "@tanstack/ai-client": "workspace:*", + "@tanstack/ai-gemini": "workspace:*", + "@tanstack/ai-ollama": "workspace:*", + "@tanstack/ai-openai": "workspace:*", + "@tanstack/ai-vue": "workspace:*", + "@tanstack/ai-vue-ui": "workspace:*", + "@tanstack/vue-ai-devtools": "workspace:*", + "@tanstack/vue-devtools": "^0.1.2", + "@tanstack/vue-router": "^1.141.0", + "@tanstack/vue-router-devtools": "^1.141.0", + "@tanstack/vue-start": "^1.141.0", + "marked": "^15.0.6", + "vue": "^3.5.25", + "zod": "^4.1.13" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.1.17", + "@tanstack/devtools-vite": "^0.3.11", + "@types/node": "^24.10.1", + "@vitejs/plugin-vue": "^6.0.3", + "@vitejs/plugin-vue-jsx": "^5.1.2", + "autoprefixer": "^10.4.21", + "concurrently": "^9.1.2", + "dotenv": "^17.2.3", + "express": "^5.1.0", + "tailwindcss": "^4.1.17", + "tsx": "^4.20.6", + "typescript": "5.9.3", + "vite": "^7.2.4", + "vite-tsconfig-paths": "^5.1.4", + "vue-tsc": "^2.2.10" + } +} diff --git a/examples/ts-vue-start-chat/public/example-guitar-flowers.jpg b/examples/ts-vue-start-chat/public/example-guitar-flowers.jpg new file mode 100644 index 00000000..debe785e Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-flowers.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-guitar-motherboard.jpg b/examples/ts-vue-start-chat/public/example-guitar-motherboard.jpg new file mode 100644 index 00000000..8f1a8d72 Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-motherboard.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-guitar-racing.jpg b/examples/ts-vue-start-chat/public/example-guitar-racing.jpg new file mode 100644 index 00000000..44555574 Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-racing.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-guitar-steamer-trunk.jpg b/examples/ts-vue-start-chat/public/example-guitar-steamer-trunk.jpg new file mode 100644 index 00000000..7b931893 Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-steamer-trunk.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-guitar-superhero.jpg b/examples/ts-vue-start-chat/public/example-guitar-superhero.jpg new file mode 100644 index 00000000..3bbea274 Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-superhero.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-guitar-traveling.jpg b/examples/ts-vue-start-chat/public/example-guitar-traveling.jpg new file mode 100644 index 00000000..285647be Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-traveling.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-guitar-video-games.jpg b/examples/ts-vue-start-chat/public/example-guitar-video-games.jpg new file mode 100644 index 00000000..4987f77e Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-guitar-video-games.jpg differ diff --git a/examples/ts-vue-start-chat/public/example-ukelele-tanstack.jpg b/examples/ts-vue-start-chat/public/example-ukelele-tanstack.jpg new file mode 100644 index 00000000..1e8a5566 Binary files /dev/null and b/examples/ts-vue-start-chat/public/example-ukelele-tanstack.jpg differ diff --git a/examples/ts-vue-start-chat/public/favicon.ico b/examples/ts-vue-start-chat/public/favicon.ico new file mode 100644 index 00000000..a11777cc Binary files /dev/null and b/examples/ts-vue-start-chat/public/favicon.ico differ diff --git a/examples/ts-vue-start-chat/public/logo192.png b/examples/ts-vue-start-chat/public/logo192.png new file mode 100644 index 00000000..fc44b0a3 Binary files /dev/null and b/examples/ts-vue-start-chat/public/logo192.png differ diff --git a/examples/ts-vue-start-chat/public/logo512.png b/examples/ts-vue-start-chat/public/logo512.png new file mode 100644 index 00000000..a4e47a65 Binary files /dev/null and b/examples/ts-vue-start-chat/public/logo512.png differ diff --git a/examples/ts-vue-start-chat/public/manifest.json b/examples/ts-vue-start-chat/public/manifest.json new file mode 100644 index 00000000..078ef501 --- /dev/null +++ b/examples/ts-vue-start-chat/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "TanStack App", + "name": "Create TanStack App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/examples/ts-vue-start-chat/public/robots.txt b/examples/ts-vue-start-chat/public/robots.txt new file mode 100644 index 00000000..e9e57dc4 --- /dev/null +++ b/examples/ts-vue-start-chat/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/examples/ts-vue-start-chat/public/tanstack-circle-logo.png b/examples/ts-vue-start-chat/public/tanstack-circle-logo.png new file mode 100644 index 00000000..9db3e67b Binary files /dev/null and b/examples/ts-vue-start-chat/public/tanstack-circle-logo.png differ diff --git a/examples/ts-vue-start-chat/public/tanstack-word-logo-white.svg b/examples/ts-vue-start-chat/public/tanstack-word-logo-white.svg new file mode 100644 index 00000000..b6ec5086 --- /dev/null +++ b/examples/ts-vue-start-chat/public/tanstack-word-logo-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/ts-vue-start-chat/src/components/ChatInput.vue b/examples/ts-vue-start-chat/src/components/ChatInput.vue new file mode 100644 index 00000000..d41b6b73 --- /dev/null +++ b/examples/ts-vue-start-chat/src/components/ChatInput.vue @@ -0,0 +1,92 @@ + + + diff --git a/examples/ts-vue-start-chat/src/components/ClientOnly.vue b/examples/ts-vue-start-chat/src/components/ClientOnly.vue new file mode 100644 index 00000000..a371d5fa --- /dev/null +++ b/examples/ts-vue-start-chat/src/components/ClientOnly.vue @@ -0,0 +1,13 @@ + + + diff --git a/examples/ts-vue-start-chat/src/components/GuitarRecommendation.vue b/examples/ts-vue-start-chat/src/components/GuitarRecommendation.vue new file mode 100644 index 00000000..21468eba --- /dev/null +++ b/examples/ts-vue-start-chat/src/components/GuitarRecommendation.vue @@ -0,0 +1,54 @@ + + + diff --git a/examples/ts-vue-start-chat/src/components/Header.vue b/examples/ts-vue-start-chat/src/components/Header.vue new file mode 100644 index 00000000..bf51d146 --- /dev/null +++ b/examples/ts-vue-start-chat/src/components/Header.vue @@ -0,0 +1,147 @@ + + + diff --git a/examples/ts-vue-start-chat/src/components/Messages.vue b/examples/ts-vue-start-chat/src/components/Messages.vue new file mode 100644 index 00000000..41a3ba5e --- /dev/null +++ b/examples/ts-vue-start-chat/src/components/Messages.vue @@ -0,0 +1,143 @@ + + + diff --git a/examples/ts-vue-start-chat/src/data/guitars.ts b/examples/ts-vue-start-chat/src/data/guitars.ts new file mode 100644 index 00000000..7765e649 --- /dev/null +++ b/examples/ts-vue-start-chat/src/data/guitars.ts @@ -0,0 +1,93 @@ +export interface Guitar { + id: number + name: string + image: string + description: string + shortDescription: string + price: number +} + +export const guitars: Array = [ + { + id: 1, + name: 'TanStack Ukelele', + image: '/example-ukelele-tanstack.jpg', + description: + "Introducing the TanStack Signature Ukulele—a beautifully handcrafted concert ukulele that combines exceptional sound quality with distinctive style. Featuring a warm, resonant koa-wood body with natural grain patterns, this instrument delivers the rich, mellow tones Hawaii is famous for. The exclusive TanStack palm tree inlay on the soundhole adds a unique touch of island flair, while the matching branded headstock makes this a true collector's piece for developers and musicians alike. Whether you're a beginner looking for a quality starter instrument or an experienced player wanting something special, the TanStack Ukulele brings together craftsmanship, character, and that unmistakable tropical spirit.", + shortDescription: + 'Premium koa-wood ukulele featuring exclusive TanStack branding, perfect for beach vibes and island-inspired melodies.', + price: 299, + }, + { + id: 2, + name: 'Video Game Guitar', + image: '/example-guitar-video-games.jpg', + description: + "The Video Game Guitar is a unique acoustic guitar that features a design inspired by video games. It has a sleek, high-gloss finish and a comfortable playability. The guitar's ergonomic body and fast neck profile ensure comfortable playability for hours on end.", + shortDescription: + 'A unique electric guitar with a video game design, high-gloss finish, and comfortable playability.', + price: 699, + }, + { + id: 3, + name: 'Superhero Guitar', + image: '/example-guitar-superhero.jpg', + description: + "The Superhero Guitar is a bold black electric guitar that stands out with its unique superhero logo design. Its sleek, high-gloss finish and powerful pickups make it perfect for high-energy performances. The guitar's ergonomic body and fast neck profile ensure comfortable playability for hours on end.", + shortDescription: + 'A bold black electric guitar with a unique superhero logo, high-gloss finish, and powerful pickups.', + price: 699, + }, + { + id: 4, + name: 'Motherboard Guitar', + image: '/example-guitar-motherboard.jpg', + description: + "This guitar is a tribute to the motherboard of a computer. It's a unique and stylish instrument that will make you feel like a hacker. The intricate circuit-inspired design features actual LED lights that pulse with your playing intensity, while the neck is inlaid with binary code patterns that glow under stage lights. Each pickup has been custom-wound to produce tones ranging from clean digital precision to glitched-out distortion, perfect for electronic music fusion. The Motherboard Guitar seamlessly bridges the gap between traditional craftsmanship and cutting-edge technology, making it the ultimate instrument for the digital age musician.", + shortDescription: + 'A tech-inspired electric guitar featuring LED lights and binary code inlays that glow under stage lights.', + price: 649, + }, + { + id: 5, + name: 'Racing Guitar', + image: '/example-guitar-racing.jpg', + description: + "Engineered for speed and precision, the Racing Guitar embodies the spirit of motorsport in every curve and contour. Its aerodynamic body, painted in classic racing stripes and high-gloss finish, is crafted from lightweight materials that allow for effortless play during extended performances. The custom low-action setup and streamlined neck profile enable lightning-fast fretwork, while specially designed pickups deliver a high-octane tone that cuts through any mix. Built with performance-grade hardware including racing-inspired control knobs and checkered flag inlays, this guitar isn't just played—it's driven to the limits of musical possibility.", + shortDescription: + 'A lightweight, aerodynamic guitar with racing stripes and a low-action setup designed for speed and precision.', + price: 679, + }, + { + id: 6, + name: 'Steamer Trunk Guitar', + image: '/example-guitar-steamer-trunk.jpg', + description: + 'The Steamer Trunk Guitar is a semi-hollow body instrument that exudes vintage charm and character. Crafted from reclaimed antique luggage wood, it features brass hardware that adds a touch of elegance and durability. The fretboard is adorned with a world map inlay, making it a unique piece that tells a story of travel and adventure.', + shortDescription: + 'A semi-hollow body guitar with brass hardware and a world map inlay, crafted from reclaimed antique luggage wood.', + price: 629, + }, + { + id: 7, + name: "Travelin' Man Guitar", + image: '/example-guitar-traveling.jpg', + description: + "The Travelin' Man Guitar is an acoustic masterpiece adorned with vintage postcards from around the world. Each postcard tells a story of adventure and wanderlust, making this guitar a unique piece of art. Its rich, resonant tones and comfortable playability make it perfect for musicians who love to travel and perform.", + shortDescription: + 'An acoustic guitar with vintage postcards, rich tones, and comfortable playability.', + price: 499, + }, + { + id: 8, + name: 'Flowerly Love Guitar', + image: '/example-guitar-flowers.jpg', + description: + "The Flowerly Love Guitar is an acoustic masterpiece adorned with intricate floral designs on its body. Each flower is hand-painted, adding a touch of nature's beauty to the instrument. Its warm, resonant tones make it perfect for both intimate performances and larger gatherings.", + shortDescription: + 'An acoustic guitar with hand-painted floral designs and warm, resonant tones.', + price: 599, + }, +] + +export default guitars diff --git a/examples/ts-vue-start-chat/src/lib/guitar-tools.ts b/examples/ts-vue-start-chat/src/lib/guitar-tools.ts new file mode 100644 index 00000000..fa3abe72 --- /dev/null +++ b/examples/ts-vue-start-chat/src/lib/guitar-tools.ts @@ -0,0 +1,80 @@ +import { toolDefinition } from '@tanstack/ai' +import { z } from 'zod' + +// Tool definition for getting guitars +export const getGuitarsToolDef = toolDefinition({ + name: 'getGuitars', + description: 'Get all products from the database', + inputSchema: z.object({}), + outputSchema: z.array( + z.object({ + id: z.number(), + name: z.string(), + image: z.string(), + description: z.string(), + shortDescription: z.string(), + price: z.number(), + }), + ), +}) + +// Tool definition for guitar recommendation +export const recommendGuitarToolDef = toolDefinition({ + name: 'recommendGuitar', + description: + 'REQUIRED tool to display a guitar recommendation to the user. This tool MUST be used whenever recommending a guitar - do NOT write recommendations yourself. This displays the guitar in a special appealing format with a buy button.', + inputSchema: z.object({ + id: z + .union([z.string(), z.number()]) + .describe( + 'The ID of the guitar to recommend (from the getGuitars results)', + ), + }), + outputSchema: z.object({ + id: z.number(), + }), +}) + +// Tool definition for personal preference +export const getPersonalGuitarPreferenceToolDef = toolDefinition({ + name: 'getPersonalGuitarPreference', + description: + "Get the user's guitar preference from their local browser storage", + inputSchema: z.object({}), + outputSchema: z.object({ + preference: z.string(), + }), +}) + +// Tool definition for wish list (needs approval) +export const addToWishListToolDef = toolDefinition({ + name: 'addToWishList', + description: "Add a guitar to the user's wish list (requires approval)", + inputSchema: z.object({ + guitarId: z.string(), + }), + outputSchema: z.object({ + success: z.boolean(), + guitarId: z.string(), + totalItems: z.number(), + }), + needsApproval: true, +}) + +// Tool definition for add to cart (server + client) +export const addToCartToolDef = toolDefinition({ + name: 'addToCart', + description: 'Add a guitar to the shopping cart (requires approval)', + inputSchema: z.object({ + guitarId: z.string(), + quantity: z.number(), + }), + outputSchema: z.object({ + success: z.boolean(), + cartId: z.string(), + guitarId: z.string(), + quantity: z.number(), + totalItems: z.number(), + }), + needsApproval: true, +}) diff --git a/examples/ts-vue-start-chat/src/lib/model-selection.ts b/examples/ts-vue-start-chat/src/lib/model-selection.ts new file mode 100644 index 00000000..6b67e813 --- /dev/null +++ b/examples/ts-vue-start-chat/src/lib/model-selection.ts @@ -0,0 +1,113 @@ +export type Provider = 'openai' | 'anthropic' | 'gemini' | 'ollama' + +export interface ModelOption { + provider: Provider + model: string + label: string +} + +export const MODEL_OPTIONS: Array = [ + // OpenAI + { provider: 'openai', model: 'gpt-4o', label: 'OpenAI - GPT-4o' }, + { provider: 'openai', model: 'gpt-4o-mini', label: 'OpenAI - GPT-4o Mini' }, + { provider: 'openai', model: 'gpt-5', label: 'OpenAI - GPT-5' }, + { + provider: 'openai', + model: 'gpt-5.2-2025-12-11', + label: 'OpenAI - GPT-5.2', + }, + + // Anthropic + { + provider: 'anthropic', + model: 'claude-sonnet-4-5-20250929', + label: 'Anthropic - Claude Sonnet 4.5', + }, + { + provider: 'anthropic', + model: 'claude-opus-4-5-20251101', + label: 'Anthropic - Claude Opus 4.5', + }, + { + provider: 'anthropic', + model: 'claude-haiku-4-0-20250514', + label: 'Anthropic - Claude Haiku 4.0', + }, + + // Gemini + { + provider: 'gemini', + model: 'gemini-2.0-flash-exp', + label: 'Gemini - 2.0 Flash', + }, + { + provider: 'gemini', + model: 'gemini-exp-1206', + label: 'Gemini - Exp 1206 (Pro)', + }, + + // Ollama + { + provider: 'ollama', + model: 'mistral:7b', + label: 'Ollama - Mistral 7B', + }, + { + provider: 'ollama', + model: 'mistral', + label: 'Ollama - Mistral', + }, + { + provider: 'ollama', + model: 'gpt-oss:20b', + label: 'Ollama - GPT-OSS 20B', + }, + { + provider: 'ollama', + model: 'granite4:3b', + label: 'Ollama - Granite4 3B', + }, + { + provider: 'ollama', + model: 'smollm', + label: 'Ollama - SmolLM', + }, +] + +const STORAGE_KEY = 'tanstack-ai-model-preference' + +export function getStoredModelPreference(): ModelOption | null { + if (typeof window === 'undefined') return null + + try { + const stored = localStorage.getItem(STORAGE_KEY) + if (!stored) return null + + const parsed = JSON.parse(stored) as { provider: Provider; model: string } + const option = MODEL_OPTIONS.find( + (opt) => opt.provider === parsed.provider && opt.model === parsed.model, + ) + + return option || null + } catch { + return null + } +} + +export function setStoredModelPreference(option: ModelOption): void { + if (typeof window === 'undefined') return + + try { + localStorage.setItem( + STORAGE_KEY, + JSON.stringify({ provider: option.provider, model: option.model }), + ) + } catch { + // Ignore storage errors + } +} + +export function getDefaultModelOption(): ModelOption { + const stored = getStoredModelPreference() + return stored || MODEL_OPTIONS[0] +} diff --git a/examples/ts-vue-start-chat/src/routeTree.gen.ts b/examples/ts-vue-start-chat/src/routeTree.gen.ts new file mode 100644 index 00000000..1402a658 --- /dev/null +++ b/examples/ts-vue-start-chat/src/routeTree.gen.ts @@ -0,0 +1,140 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as VueUiRouteImport } from './routes/vue-ui' +import { Route as IndexRouteImport } from './routes/index' +import { Route as GuitarsIndexRouteImport } from './routes/guitars/index' +import { Route as GuitarsIdRouteImport } from './routes/guitars/$id' +import { Route as ApiChatRouteImport } from './routes/api.chat' + +const VueUiRoute = VueUiRouteImport.update({ + id: '/vue-ui', + path: '/vue-ui', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const GuitarsIndexRoute = GuitarsIndexRouteImport.update({ + id: '/guitars/', + path: '/guitars/', + getParentRoute: () => rootRouteImport, +} as any) +const GuitarsIdRoute = GuitarsIdRouteImport.update({ + id: '/guitars/$id', + path: '/guitars/$id', + getParentRoute: () => rootRouteImport, +} as any) +const ApiChatRoute = ApiChatRouteImport.update({ + id: '/api/chat', + path: '/api/chat', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/vue-ui': typeof VueUiRoute + '/api/chat': typeof ApiChatRoute + '/guitars/$id': typeof GuitarsIdRoute + '/guitars': typeof GuitarsIndexRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/vue-ui': typeof VueUiRoute + '/api/chat': typeof ApiChatRoute + '/guitars/$id': typeof GuitarsIdRoute + '/guitars': typeof GuitarsIndexRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/vue-ui': typeof VueUiRoute + '/api/chat': typeof ApiChatRoute + '/guitars/$id': typeof GuitarsIdRoute + '/guitars/': typeof GuitarsIndexRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/vue-ui' | '/api/chat' | '/guitars/$id' | '/guitars' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/vue-ui' | '/api/chat' | '/guitars/$id' | '/guitars' + id: '__root__' | '/' | '/vue-ui' | '/api/chat' | '/guitars/$id' | '/guitars/' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + VueUiRoute: typeof VueUiRoute + ApiChatRoute: typeof ApiChatRoute + GuitarsIdRoute: typeof GuitarsIdRoute + GuitarsIndexRoute: typeof GuitarsIndexRoute +} + +declare module '@tanstack/vue-router' { + interface FileRoutesByPath { + '/vue-ui': { + id: '/vue-ui' + path: '/vue-ui' + fullPath: '/vue-ui' + preLoaderRoute: typeof VueUiRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/guitars/': { + id: '/guitars/' + path: '/guitars' + fullPath: '/guitars' + preLoaderRoute: typeof GuitarsIndexRouteImport + parentRoute: typeof rootRouteImport + } + '/guitars/$id': { + id: '/guitars/$id' + path: '/guitars/$id' + fullPath: '/guitars/$id' + preLoaderRoute: typeof GuitarsIdRouteImport + parentRoute: typeof rootRouteImport + } + '/api/chat': { + id: '/api/chat' + path: '/api/chat' + fullPath: '/api/chat' + preLoaderRoute: typeof ApiChatRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + VueUiRoute: VueUiRoute, + ApiChatRoute: ApiChatRoute, + GuitarsIdRoute: GuitarsIdRoute, + GuitarsIndexRoute: GuitarsIndexRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +import type { getRouter } from './router.ts' +import type { createStart } from '@tanstack/vue-start' +declare module '@tanstack/vue-start' { + interface Register { + ssr: true + router: Awaited> + } +} diff --git a/examples/ts-vue-start-chat/src/router.ts b/examples/ts-vue-start-chat/src/router.ts new file mode 100644 index 00000000..e6a1bffb --- /dev/null +++ b/examples/ts-vue-start-chat/src/router.ts @@ -0,0 +1,11 @@ +import { createRouter } from '@tanstack/vue-router' +import { routeTree } from './routeTree.gen' + +// Create a new router instance +export function getRouter() { + return createRouter({ + routeTree, + scrollRestoration: true, + defaultPreloadStaleTime: 0, + }) +} diff --git a/examples/ts-vue-start-chat/src/routes/__root.tsx b/examples/ts-vue-start-chat/src/routes/__root.tsx new file mode 100644 index 00000000..4c63b6eb --- /dev/null +++ b/examples/ts-vue-start-chat/src/routes/__root.tsx @@ -0,0 +1,78 @@ +/// +import { + Body, + HeadContent, + Html, + Outlet, + Scripts, + createRootRoute, +} from '@tanstack/vue-router' +import { TanStackRouterDevtoolsPanelInProd } from '@tanstack/vue-router-devtools' +import { AiDevtoolsPanelInProd } from '@tanstack/vue-ai-devtools' + +import { TanStackDevtools } from '@tanstack/vue-devtools' + +import Header from '@/components/Header.vue' +import ClientOnly from '@/components/ClientOnly.vue' +import appCss from '@/styles.css?url' + +export const Route = createRootRoute({ + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + { + title: 'TanStack AI Vue Start Chat', + }, + ], + links: [ + { + rel: 'stylesheet', + href: appCss, + }, + ], + }), + component: RootComponent, +}) + +function RootComponent() { + return ( + + + + + +
+ + + + + + + + ) +} diff --git a/examples/ts-vue-start-chat/src/routes/api.chat.ts b/examples/ts-vue-start-chat/src/routes/api.chat.ts new file mode 100644 index 00000000..254ece5c --- /dev/null +++ b/examples/ts-vue-start-chat/src/routes/api.chat.ts @@ -0,0 +1,130 @@ +import { createFileRoute } from '@tanstack/vue-router' +import { chat, maxIterations, toStreamResponse } from '@tanstack/ai' +import { openai } from '@tanstack/ai-openai' +import { anthropic } from '@tanstack/ai-anthropic' +import { gemini } from '@tanstack/ai-gemini' +import { ollama } from '@tanstack/ai-ollama' +import { guitars } from '@/data/guitars' +import { + addToCartToolDef, + addToWishListToolDef, + getGuitarsToolDef, + getPersonalGuitarPreferenceToolDef, + recommendGuitarToolDef, +} from '@/lib/guitar-tools' + +type Provider = 'openai' | 'anthropic' | 'gemini' | 'ollama' + +const SYSTEM_PROMPT = `You are a helpful assistant for a guitar store. + +CRITICAL INSTRUCTIONS - YOU MUST FOLLOW THIS EXACT WORKFLOW: + +When a user asks for a guitar recommendation: +1. FIRST: Use the getGuitars tool (no parameters needed) +2. SECOND: Use the recommendGuitar tool with the ID of the guitar you want to recommend +3. NEVER write a recommendation directly - ALWAYS use the recommendGuitar tool + +IMPORTANT: +- The recommendGuitar tool will display the guitar in a special, appealing format +- You MUST use recommendGuitar for ANY guitar recommendation +- ONLY recommend guitars from our inventory (use getGuitars first) +- The recommendGuitar tool has a buy button - this is how customers purchase +- Do NOT describe the guitar yourself - let the recommendGuitar tool do it +` + +const getGuitars = getGuitarsToolDef.server(() => guitars) + +const addToCartToolServer = addToCartToolDef.server((args) => ({ + success: true, + cartId: 'CART_' + Date.now(), + guitarId: args.guitarId, + quantity: args.quantity, + totalItems: args.quantity, +})) + +export const Route = createFileRoute('/api/chat')({ + server: { + handlers: { + POST: async ({ request }) => { + // Capture request signal before reading body (it may be aborted after body is consumed) + const requestSignal = request.signal + + if (requestSignal?.aborted) { + return new Response(null, { status: 499 }) + } + + const abortController = new AbortController() + + const { messages, data } = await request.json() + const provider: Provider = data?.provider || 'openai' + const model: string | undefined = data?.model + const conversationId: string | undefined = data?.conversationId + + try { + let adapter + let defaultModel + + switch (provider) { + case 'anthropic': + adapter = anthropic() + defaultModel = 'claude-sonnet-4-5-20250929' + break + case 'gemini': + adapter = gemini() + defaultModel = 'gemini-2.0-flash-exp' + break + case 'ollama': + adapter = ollama() + defaultModel = 'mistral:7b' + break + case 'openai': + default: + adapter = openai() + defaultModel = 'gpt-4o' + break + } + + const selectedModel = model || defaultModel + console.log( + `[API Route] Using provider: ${provider}, model: ${selectedModel}`, + ) + + const stream = chat({ + adapter: adapter as any, + model: selectedModel as any, + tools: [ + getGuitars, + recommendGuitarToolDef, + addToCartToolServer, + addToWishListToolDef, + getPersonalGuitarPreferenceToolDef, + ], + systemPrompts: [SYSTEM_PROMPT], + agentLoopStrategy: maxIterations(20), + messages, + abortController, + conversationId, + }) + + return toStreamResponse(stream, { abortController }) + } catch (error: any) { + console.error('[API Route] Error in chat request:', error) + + if (error.name === 'AbortError' || abortController.signal.aborted) { + return new Response(null, { status: 499 }) + } + + return new Response( + JSON.stringify({ + error: error.message || 'An error occurred', + }), + { + status: 500, + headers: { 'Content-Type': 'application/json' }, + }, + ) + } + }, + }, + }, +}) diff --git a/examples/ts-vue-start-chat/src/routes/guitars/$id.ts b/examples/ts-vue-start-chat/src/routes/guitars/$id.ts new file mode 100644 index 00000000..24e75d13 --- /dev/null +++ b/examples/ts-vue-start-chat/src/routes/guitars/$id.ts @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/vue-router' +import GuitarDetailView from '@/views/GuitarDetailView.vue' + +export const Route = createFileRoute('/guitars/$id')({ + component: GuitarDetailView, +}) diff --git a/examples/ts-vue-start-chat/src/routes/guitars/index.ts b/examples/ts-vue-start-chat/src/routes/guitars/index.ts new file mode 100644 index 00000000..50e25a6d --- /dev/null +++ b/examples/ts-vue-start-chat/src/routes/guitars/index.ts @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/vue-router' +import GuitarsView from '@/views/GuitarsView.vue' + +export const Route = createFileRoute('/guitars/')({ + component: GuitarsView, +}) diff --git a/examples/ts-vue-start-chat/src/routes/index.ts b/examples/ts-vue-start-chat/src/routes/index.ts new file mode 100644 index 00000000..c7dec2b4 --- /dev/null +++ b/examples/ts-vue-start-chat/src/routes/index.ts @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/vue-router' +import ChatView from '@/views/ChatView.vue' + +export const Route = createFileRoute('/')({ + component: ChatView, +}) diff --git a/examples/ts-vue-start-chat/src/routes/vue-ui.ts b/examples/ts-vue-start-chat/src/routes/vue-ui.ts new file mode 100644 index 00000000..bbd1e80b --- /dev/null +++ b/examples/ts-vue-start-chat/src/routes/vue-ui.ts @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/vue-router' +import VueUIView from '@/views/VueUIView.vue' + +export const Route = createFileRoute('/vue-ui')({ + component: VueUIView, +}) diff --git a/examples/ts-vue-start-chat/src/styles.css b/examples/ts-vue-start-chat/src/styles.css new file mode 100644 index 00000000..d49a546b --- /dev/null +++ b/examples/ts-vue-start-chat/src/styles.css @@ -0,0 +1,95 @@ +@import 'tailwindcss'; + +@layer base { + html { + @apply bg-gray-900; + } + + body { + @apply min-h-screen text-white antialiased; + } + + /* Markdown styling */ + .prose { + @apply text-gray-200; + } + + .prose h1, + .prose h2, + .prose h3, + .prose h4 { + @apply text-white font-semibold; + } + + .prose p { + @apply mb-4 last:mb-0; + } + + .prose code { + @apply bg-gray-800 px-1.5 py-0.5 rounded text-orange-400 text-sm; + } + + .prose pre { + @apply bg-gray-800 p-4 rounded-lg overflow-x-auto mb-4; + } + + .prose pre code { + @apply bg-transparent p-0; + } + + .prose ul, + .prose ol { + @apply mb-4 pl-6; + } + + .prose li { + @apply mb-1; + } + + .prose ul li { + @apply list-disc; + } + + .prose ol li { + @apply list-decimal; + } + + .prose a { + @apply text-orange-400 hover:text-orange-300 underline; + } + + .prose blockquote { + @apply border-l-4 border-orange-500 pl-4 italic text-gray-400; + } + + .prose table { + @apply w-full border-collapse mb-4; + } + + .prose th, + .prose td { + @apply border border-gray-700 px-3 py-2 text-left; + } + + .prose th { + @apply bg-gray-800 font-semibold; + } +} + +@layer components { + .btn-primary { + @apply bg-gradient-to-r from-orange-500 to-red-600 text-white px-4 py-2 rounded-lg font-medium hover:opacity-90 transition-opacity; + } + + .btn-secondary { + @apply bg-gray-700 text-white px-4 py-2 rounded-lg font-medium hover:bg-gray-600 transition-colors; + } + + .btn-danger { + @apply bg-red-600 text-white px-4 py-2 rounded-lg font-medium hover:bg-red-700 transition-colors; + } + + .btn-success { + @apply bg-green-600 text-white px-4 py-2 rounded-lg font-medium hover:bg-green-700 transition-colors; + } +} diff --git a/examples/ts-vue-start-chat/src/views/ChatView.vue b/examples/ts-vue-start-chat/src/views/ChatView.vue new file mode 100644 index 00000000..7cdbe9a9 --- /dev/null +++ b/examples/ts-vue-start-chat/src/views/ChatView.vue @@ -0,0 +1,131 @@ + + + diff --git a/examples/ts-vue-start-chat/src/views/GuitarDetailView.vue b/examples/ts-vue-start-chat/src/views/GuitarDetailView.vue new file mode 100644 index 00000000..b82efad6 --- /dev/null +++ b/examples/ts-vue-start-chat/src/views/GuitarDetailView.vue @@ -0,0 +1,68 @@ + + + diff --git a/examples/ts-vue-start-chat/src/views/GuitarsView.vue b/examples/ts-vue-start-chat/src/views/GuitarsView.vue new file mode 100644 index 00000000..fa4fa04e --- /dev/null +++ b/examples/ts-vue-start-chat/src/views/GuitarsView.vue @@ -0,0 +1,40 @@ + + + diff --git a/examples/ts-vue-start-chat/src/views/VueUIView.vue b/examples/ts-vue-start-chat/src/views/VueUIView.vue new file mode 100644 index 00000000..c45bb4b9 --- /dev/null +++ b/examples/ts-vue-start-chat/src/views/VueUIView.vue @@ -0,0 +1,149 @@ + + + diff --git a/examples/ts-vue-start-chat/tsconfig.json b/examples/ts-vue-start-chat/tsconfig.json new file mode 100644 index 00000000..cc025991 --- /dev/null +++ b/examples/ts-vue-start-chat/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "types": ["vite/client"], + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "jsxImportSource": "vue", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + /* Path aliases */ + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/examples/ts-vue-start-chat/vite.config.ts b/examples/ts-vue-start-chat/vite.config.ts new file mode 100644 index 00000000..ff05f80f --- /dev/null +++ b/examples/ts-vue-start-chat/vite.config.ts @@ -0,0 +1,37 @@ +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vite' +import tsConfigPaths from 'vite-tsconfig-paths' +import { tanstackStart } from '@tanstack/vue-start/plugin/vite' +import { devtools } from '@tanstack/devtools-vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import tailwindcss from '@tailwindcss/vite' +export default defineConfig({ + server: { + port: 3000, + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, + plugins: [ + devtools({ + // Vue warns if arbitrary attributes are passed to components that render + // fragments/teleports (like `Html`/`HeadContent`). Ignore those components + // so `data-tsd-source` injection doesn't flood the dev server output. + injectSource: { + ignore: { + components: ['Html', 'HeadContent', 'Body', 'Outlet', 'Scripts'], + }, + }, + }), + tsConfigPaths({ + projects: ['./tsconfig.json'], + }), + tailwindcss(), + tanstackStart(), + vue(), + vueJsx(), + ], +}) diff --git a/packages/typescript/vue-ai-devtools/CHANGELOG.md b/packages/typescript/vue-ai-devtools/CHANGELOG.md new file mode 100644 index 00000000..07347ceb --- /dev/null +++ b/packages/typescript/vue-ai-devtools/CHANGELOG.md @@ -0,0 +1,5 @@ +# @tanstack/vue-ai-devtools + +## 0.0.3 + +- Initial release diff --git a/packages/typescript/vue-ai-devtools/README.md b/packages/typescript/vue-ai-devtools/README.md new file mode 100644 index 00000000..1b250468 --- /dev/null +++ b/packages/typescript/vue-ai-devtools/README.md @@ -0,0 +1,40 @@ +# @tanstack/vue-ai-devtools + +Vue Devtools for TanStack AI. + +## Usage + +```ts +import { aiDevtoolsPlugin } from '@tanstack/vue-ai-devtools' +import { TanStackDevtools } from '@tanstack/vue-devtools' + +const devtoolsPlugins = [aiDevtoolsPlugin()] + +// in .vue file + + +// in jsx + + +``` + +## diff --git a/packages/typescript/vue-ai-devtools/package.json b/packages/typescript/vue-ai-devtools/package.json new file mode 100644 index 00000000..fba7813e --- /dev/null +++ b/packages/typescript/vue-ai-devtools/package.json @@ -0,0 +1,85 @@ +{ + "name": "@tanstack/vue-ai-devtools", + "version": "0.0.3", + "description": "Vue Devtools for TanStack AI.", + "author": "tannerlinsley", + "license": "MIT", + "homepage": "https://tanstack.com/ai", + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/ai.git", + "directory": "packages/typescript/ai" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "scripts": { + "clean": "premove ./build ./dist", + "lint:fix": "eslint ./src --fix", + "test:eslint": "eslint ./src", + "test:lib": "vitest --passWithNoTests", + "test:lib:dev": "pnpm test:lib --watch", + "test:types": "tsc", + "test:build": "publint --strict", + "build": "vite build" + }, + "type": "module", + "types": "./dist/esm/index.d.ts", + "module": "./dist/esm/index.js", + "exports": { + ".": { + "browser": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + } + }, + "node": { + "import": { + "types": "./dist/esm/server.d.ts", + "default": "./dist/esm/server.js" + } + }, + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + } + }, + "./production": { + "browser": { + "import": { + "types": "./dist/esm/production.d.ts", + "default": "./dist/esm/production.js" + } + }, + "node": { + "import": { + "types": "./dist/esm/server.d.ts", + "default": "./dist/esm/server.js" + } + }, + "import": { + "types": "./dist/esm/production.d.ts", + "default": "./dist/esm/production.js" + } + }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "files": [ + "dist", + "src" + ], + "dependencies": { + "@tanstack/ai-devtools-core": "workspace:*" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.3", + "@vitest/coverage-v8": "4.0.14", + "vite": "^7.2.4" + }, + "peerDependencies": { + "vue": ">=3.2.0" + } +} diff --git a/packages/typescript/vue-ai-devtools/src/AiDevtoolsPanel.ts b/packages/typescript/vue-ai-devtools/src/AiDevtoolsPanel.ts new file mode 100644 index 00000000..69702e66 --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/AiDevtoolsPanel.ts @@ -0,0 +1,41 @@ +/// +import { AiDevtoolsCore } from '@tanstack/ai-devtools-core' +import { defineComponent, h } from 'vue' +import { createVuePanel } from './createVuePanel' +import type { DevtoolsPanelProps } from './createVuePanel' +import type { PropType } from 'vue' + +export interface AiDevtoolsVueInit { + /** + * Theme for the devtools UI. + * Defaults to 'dark'. + */ + theme?: DevtoolsPanelProps['theme'] +} + +const [InternalPanel] = createVuePanel( + AiDevtoolsCore as unknown as new ( + _props: AiDevtoolsVueInit, + ) => InstanceType, +) + +// Wrapper to make `devtoolsProps` optional for consumers. +export const AiDevtoolsPanel = defineComponent({ + name: 'AiDevtoolsPanel', + props: { + theme: { + type: String as PropType, + }, + devtoolsProps: { + type: Object as PropType, + default: () => ({}), + }, + }, + setup(props) { + return () => + h(InternalPanel, { + theme: props.theme ?? props.devtoolsProps.theme, + devtoolsProps: props.devtoolsProps, + }) + }, +}) diff --git a/packages/typescript/vue-ai-devtools/src/AiDevtoolsPanelInProd.ts b/packages/typescript/vue-ai-devtools/src/AiDevtoolsPanelInProd.ts new file mode 100644 index 00000000..82f24ee3 --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/AiDevtoolsPanelInProd.ts @@ -0,0 +1,34 @@ +/// +import { AiDevtoolsCore } from '@tanstack/ai-devtools-core/production' +import { defineComponent, h } from 'vue' +import { createVuePanel } from './createVuePanel' +import type { DevtoolsPanelProps } from './createVuePanel' +import type { PropType } from 'vue' +import type { AiDevtoolsVueInit } from './AiDevtoolsPanel' + +const [InternalPanel] = createVuePanel( + AiDevtoolsCore as unknown as new ( + _props: AiDevtoolsVueInit, + ) => InstanceType, +) + +// Wrapper to make `devtoolsProps` optional for consumers. +export const AiDevtoolsPanelInProd = defineComponent({ + name: 'AiDevtoolsPanelInProd', + props: { + theme: { + type: String as PropType, + }, + devtoolsProps: { + type: Object as PropType, + default: () => ({}), + }, + }, + setup(props) { + return () => + h(InternalPanel, { + theme: props.theme ?? props.devtoolsProps.theme, + devtoolsProps: props.devtoolsProps, + }) + }, +}) diff --git a/packages/typescript/vue-ai-devtools/src/createVuePanel.ts b/packages/typescript/vue-ai-devtools/src/createVuePanel.ts new file mode 100644 index 00000000..9dc9fdab --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/createVuePanel.ts @@ -0,0 +1,93 @@ +import { defineComponent, h, onMounted, onUnmounted, ref } from 'vue' +import type { DefineComponent } from 'vue' + +export interface DevtoolsPanelProps { + theme?: 'dark' | 'light' +} + +type Theme = NonNullable + +// Copied from TanStack Devtools Vue helpers (devtools/packages/devtools-utils/src/vue/panel.ts), +// with async mount support. +export function createVuePanel< + TComponentProps extends DevtoolsPanelProps, + TCoreDevtoolsClass extends { + mount: (el: HTMLElement, theme: Theme) => void | Promise + unmount: () => void + }, +>(CoreClass: new (props: TComponentProps) => TCoreDevtoolsClass) { + const props = { + theme: { + type: String as () => DevtoolsPanelProps['theme'], + }, + devtoolsProps: { + type: Object as () => TComponentProps, + }, + } + + const Panel = defineComponent({ + props, + setup(config) { + const devToolRef = ref(null) + // Keep devtools instance non-reactive to avoid proxying, + // since private fields (e.g. #isMounted) break on proxies. + let devtools: TCoreDevtoolsClass | null = null + let didMount = false + let isUnmounted = false + + onMounted(async () => { + const instance = new CoreClass(config.devtoolsProps as TComponentProps) + devtools = instance + + if (devToolRef.value) { + await instance.mount(devToolRef.value, config.theme ?? 'dark') + if (isUnmounted) { + // If we unmounted before mount finished, clean up. + try { + instance.unmount() + } catch { + // ignore + } + } else { + didMount = true + } + } + }) + + onUnmounted(() => { + isUnmounted = true + if (didMount) { + try { + devtools?.unmount() + } catch { + // ignore + } + } + }) + + return () => + h('div', { + style: { height: '100%' }, + ref: devToolRef, + }) + }, + }) + + const NoOpPanel = defineComponent({ + props, + setup() { + return () => null + }, + }) + + return [Panel, NoOpPanel] as unknown as [ + DefineComponent<{ + theme?: DevtoolsPanelProps['theme'] + devtoolsProps: TComponentProps + }>, + DefineComponent<{ + theme?: DevtoolsPanelProps['theme'] + devtoolsProps: TComponentProps + }>, + ] +} diff --git a/packages/typescript/vue-ai-devtools/src/index.ts b/packages/typescript/vue-ai-devtools/src/index.ts new file mode 100644 index 00000000..69f8689a --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/index.ts @@ -0,0 +1,27 @@ +import { defineComponent } from 'vue' +import { AiDevtoolsPanel as DevToolsPanelComponent } from './AiDevtoolsPanel' +import { AiDevtoolsPanelInProd as DevToolsPanelInProdComponent } from './AiDevtoolsPanelInProd' +import * as plugin from './plugin' + +export type { AiDevtoolsVueInit } from './AiDevtoolsPanel' + +const NullComponent = /* #__PURE__ */ defineComponent({ + name: 'NullAiDevtoolsPanel', + setup() { + return () => null + }, +}) + +export const AiDevtoolsPanel = + process.env.NODE_ENV !== 'development' + ? NullComponent + : DevToolsPanelComponent + +export const AiDevtoolsPanelInProd = DevToolsPanelInProdComponent + +export const aiDevtoolsPlugin = + process.env.NODE_ENV !== 'development' + ? plugin.aiDevtoolsNoOpPlugin + : plugin.aiDevtoolsPlugin + +export type { AiDevtoolsVueInit as AiDevtoolsVuePluginInit } from './AiDevtoolsPanel' diff --git a/packages/typescript/vue-ai-devtools/src/plugin.ts b/packages/typescript/vue-ai-devtools/src/plugin.ts new file mode 100644 index 00000000..ec2d9078 --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/plugin.ts @@ -0,0 +1,32 @@ +import { defineComponent } from 'vue' +import { AiDevtoolsPanel } from './AiDevtoolsPanel' +import type { AiDevtoolsVueInit } from './AiDevtoolsPanel' + +const NullComponent = /* #__PURE__ */ defineComponent({ + name: 'NullAiDevtoolsPlugin', + setup() { + return () => null + }, +}) + +/** + * Create a TanStack Devtools Vue plugin for TanStack AI. + * Matches the shape expected by `@tanstack/vue-devtools`. + */ +export function aiDevtoolsPlugin(props: AiDevtoolsVueInit = {}) { + return { + id: 'tanstack-ai', + name: 'TanStack AI', + component: AiDevtoolsPanel, + props, + } +} + +export function aiDevtoolsNoOpPlugin(props: AiDevtoolsVueInit = {}) { + return { + id: 'tanstack-ai', + name: 'TanStack AI', + component: NullComponent, + props, + } +} diff --git a/packages/typescript/vue-ai-devtools/src/production.ts b/packages/typescript/vue-ai-devtools/src/production.ts new file mode 100644 index 00000000..0f23e5dd --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/production.ts @@ -0,0 +1,17 @@ +import { AiDevtoolsPanelInProd } from './AiDevtoolsPanelInProd' +import type { AiDevtoolsVueInit } from './AiDevtoolsPanel' + +export { AiDevtoolsPanelInProd as AiDevtoolsPanel } from './AiDevtoolsPanelInProd' +export type { AiDevtoolsVueInit } from './AiDevtoolsPanel' + +/** + * Production entry: always-on plugin/panel (mirrors `@tanstack/*-ai-devtools/production`). + */ +export function aiDevtoolsPlugin(props: AiDevtoolsVueInit = {}) { + return { + id: 'tanstack-ai', + name: 'TanStack AI', + component: AiDevtoolsPanelInProd, + props, + } +} diff --git a/packages/typescript/vue-ai-devtools/src/server.ts b/packages/typescript/vue-ai-devtools/src/server.ts new file mode 100644 index 00000000..4d47704b --- /dev/null +++ b/packages/typescript/vue-ai-devtools/src/server.ts @@ -0,0 +1,27 @@ +import { defineComponent } from 'vue' + +export interface AiDevtoolsVueInit { + theme?: 'light' | 'dark' +} + +const NullComponent = /* #__PURE__ */ defineComponent({ + name: 'NullAiDevtoolsPanel', + setup() { + return () => null + }, +}) + +// On the server/SSR, devtools are always a no-op. +export const AiDevtoolsPanel = NullComponent +export const AiDevtoolsPanelInProd = NullComponent + +export function aiDevtoolsPlugin(_props: AiDevtoolsVueInit = {}) { + return { + id: 'tanstack-ai', + name: 'TanStack AI', + component: NullComponent, + props: _props, + } +} + +export const aiDevtoolsNoOpPlugin = aiDevtoolsPlugin diff --git a/packages/typescript/vue-ai-devtools/tsconfig.json b/packages/typescript/vue-ai-devtools/tsconfig.json new file mode 100644 index 00000000..b96b7d78 --- /dev/null +++ b/packages/typescript/vue-ai-devtools/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "jsx": "preserve", + "declaration": true, + "declarationMap": true, + "composite": true, + "lib": ["ES2022", "DOM"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/typescript/vue-ai-devtools/vite.config.ts b/packages/typescript/vue-ai-devtools/vite.config.ts new file mode 100644 index 00000000..6dbcbfec --- /dev/null +++ b/packages/typescript/vue-ai-devtools/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/vite-config' +import vue from '@vitejs/plugin-vue' +import packageJson from './package.json' + +const config = defineConfig({ + plugins: [vue()], + test: { + name: packageJson.name, + dir: './', + watch: false, + globals: true, + environment: 'node', + include: ['tests/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + exclude: [ + 'node_modules/', + 'dist/', + 'tests/', + '**/*.test.ts', + '**/*.config.ts', + '**/types.ts', + ], + include: ['src/**/*.ts'], + }, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ + entry: ['./src/index.ts', './src/production.ts', './src/server.ts'], + srcDir: './src', + cjs: false, + }), +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 214dfb20..71ce8de9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -115,10 +115,10 @@ importers: version: 1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/react-router-devtools': specifier: ^1.139.7 - version: 1.139.7(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + version: 1.139.7(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) '@tanstack/react-router-ssr-query': specifier: ^1.139.7 - version: 1.139.7(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.5(react@19.2.0))(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.139.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 1.139.7(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.5(react@19.2.0))(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.141.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/react-start': specifier: ^1.139.8 version: 1.139.8(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) @@ -224,10 +224,10 @@ importers: version: 1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/react-router-devtools': specifier: ^1.139.7 - version: 1.139.7(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + version: 1.139.7(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) '@tanstack/react-router-ssr-query': specifier: ^1.139.7 - version: 1.139.7(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.5(react@19.2.0))(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.139.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 1.139.7(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.5(react@19.2.0))(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.141.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tanstack/react-start': specifier: ^1.139.8 version: 1.139.8(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) @@ -366,10 +366,10 @@ importers: version: 1.139.10(solid-js@1.9.10) '@tanstack/solid-router-devtools': specifier: ^1.139.10 - version: 1.139.10(@tanstack/router-core@1.139.10)(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + version: 1.139.10(@tanstack/router-core@1.141.1)(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) '@tanstack/solid-router-ssr-query': specifier: ^1.139.10 - version: 1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.139.10)(@tanstack/solid-query@5.90.14(solid-js@1.9.10))(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(eslint@9.39.1(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3) + version: 1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.141.1)(@tanstack/solid-query@5.90.14(solid-js@1.9.10))(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(eslint@9.39.1(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3) '@tanstack/solid-start': specifier: ^1.139.10 version: 1.139.10(solid-js@1.9.10)(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) @@ -534,6 +534,12 @@ importers: '@tanstack/ai-vue-ui': specifier: workspace:* version: link:../../packages/typescript/ai-vue-ui + '@tanstack/vue-ai-devtools': + specifier: workspace:* + version: link:../../packages/typescript/vue-ai-devtools + '@tanstack/vue-devtools': + specifier: ^0.1.2 + version: 0.1.2(csstype@3.2.3)(solid-js@1.9.10) marked: specifier: ^15.0.6 version: 15.0.12 @@ -554,8 +560,102 @@ importers: specifier: ^24.10.1 version: 24.10.1 '@vitejs/plugin-vue': - specifier: ^5.2.3 - version: 5.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)) + specifier: ^6.0.3 + version: 6.0.3(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)) + autoprefixer: + specifier: ^10.4.21 + version: 10.4.22(postcss@8.5.6) + concurrently: + specifier: ^9.1.2 + version: 9.2.1 + dotenv: + specifier: ^17.2.3 + version: 17.2.3 + express: + specifier: ^5.1.0 + version: 5.2.1 + tailwindcss: + specifier: ^4.1.17 + version: 4.1.17 + tsx: + specifier: ^4.20.6 + version: 4.20.6 + typescript: + specifier: 5.9.3 + version: 5.9.3 + vite: + specifier: ^7.2.4 + version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vue-tsc: + specifier: ^2.2.10 + version: 2.2.12(typescript@5.9.3) + + examples/ts-vue-start-chat: + dependencies: + '@tanstack/ai': + specifier: workspace:* + version: link:../../packages/typescript/ai + '@tanstack/ai-anthropic': + specifier: workspace:* + version: link:../../packages/typescript/ai-anthropic + '@tanstack/ai-client': + specifier: workspace:* + version: link:../../packages/typescript/ai-client + '@tanstack/ai-gemini': + specifier: workspace:* + version: link:../../packages/typescript/ai-gemini + '@tanstack/ai-ollama': + specifier: workspace:* + version: link:../../packages/typescript/ai-ollama + '@tanstack/ai-openai': + specifier: workspace:* + version: link:../../packages/typescript/ai-openai + '@tanstack/ai-vue': + specifier: workspace:* + version: link:../../packages/typescript/ai-vue + '@tanstack/ai-vue-ui': + specifier: workspace:* + version: link:../../packages/typescript/ai-vue-ui + '@tanstack/vue-ai-devtools': + specifier: workspace:* + version: link:../../packages/typescript/vue-ai-devtools + '@tanstack/vue-devtools': + specifier: ^0.1.2 + version: 0.1.2(csstype@3.2.3)(solid-js@1.9.10) + '@tanstack/vue-router': + specifier: ^1.141.0 + version: 1.141.1(vue@3.5.25(typescript@5.9.3)) + '@tanstack/vue-router-devtools': + specifier: ^1.141.0 + version: 1.141.1(@tanstack/router-core@1.141.1)(@tanstack/vue-router@1.141.1(vue@3.5.25(typescript@5.9.3)))(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(vue@3.5.25(typescript@5.9.3))(yaml@2.8.1) + '@tanstack/vue-start': + specifier: ^1.141.0 + version: 1.141.1(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)) + marked: + specifier: ^15.0.6 + version: 15.0.12 + vue: + specifier: ^3.5.25 + version: 3.5.25(typescript@5.9.3) + zod: + specifier: ^4.1.13 + version: 4.1.13 + devDependencies: + '@tailwindcss/vite': + specifier: ^4.1.17 + version: 4.1.17(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + '@tanstack/devtools-vite': + specifier: ^0.3.11 + version: 0.3.11(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + '@types/node': + specifier: ^24.10.1 + version: 24.10.1 + '@vitejs/plugin-vue': + specifier: ^6.0.3 + version: 6.0.3(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)) + '@vitejs/plugin-vue-jsx': + specifier: ^5.1.2 + version: 5.1.2(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)) autoprefixer: specifier: ^10.4.21 version: 10.4.22(postcss@8.5.6) @@ -580,6 +680,9 @@ importers: vite: specifier: ^7.2.4 version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) vue-tsc: specifier: ^2.2.10 version: 2.2.12(typescript@5.9.3) @@ -1133,6 +1236,25 @@ importers: specifier: ^2.11.10 version: 2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + packages/typescript/vue-ai-devtools: + dependencies: + '@tanstack/ai-devtools-core': + specifier: workspace:* + version: link:../ai-devtools + vue: + specifier: '>=3.2.0' + version: 3.5.25(typescript@5.9.3) + devDependencies: + '@vitejs/plugin-vue': + specifier: ^6.0.3 + version: 6.0.3(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3)) + '@vitest/coverage-v8': + specifier: 4.0.14 + version: 4.0.14(vitest@4.0.14(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + vite: + specifier: ^7.2.4 + version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + packages: '@acemir/cssom@0.9.24': @@ -2603,6 +2725,10 @@ packages: resolution: {integrity: sha512-LefnH9KE9uRDEWifc3QDcooskA8ikfs41bybDTgpYQpyTUspZnaEdUdya9Hry0KYxZ8nos0S3nNbsP79KHqr6Q==} engines: {node: '>=18'} + '@tanstack/devtools-client@0.0.5': + resolution: {integrity: sha512-hsNDE3iu4frt9cC2ppn1mNRnLKo2uc1/1hXAyY9z4UYb+o40M2clFAhiFoo4HngjfGJDV3x18KVVIq7W4Un+zA==} + engines: {node: '>=18'} + '@tanstack/devtools-event-bus@0.3.3': resolution: {integrity: sha512-lWl88uLAz7ZhwNdLH6A3tBOSEuBCrvnY9Fzr5JPdzJRFdM5ZFdyNWz1Bf5l/F3GU57VodrN0KCFi9OA26H5Kpg==} engines: {node: '>=18'} @@ -2651,12 +2777,24 @@ packages: peerDependencies: solid-js: '>=1.9.7' + '@tanstack/devtools@0.9.1': + resolution: {integrity: sha512-fW/1ewT+g0LgJGraS/Irwle3uRgM1VDwfhi/NP3aGHhGyCDAWJI0+Id9FBzjChQ5BuEU5qD5fdegcFqTZShXHw==} + engines: {node: '>=18'} + peerDependencies: + solid-js: '>=1.9.7' + '@tanstack/directive-functions-plugin@1.139.0': resolution: {integrity: sha512-qLGxldnWa0pp/siZEFEYDU+eB/j40bd1V3IuTzP0sFnrYi11Ldx1yVkOruDKUbO1WM0o+OlPhp22Q1h+LMdDMA==} engines: {node: '>=12'} peerDependencies: vite: '>=6.0.0 || >=7.0.0' + '@tanstack/directive-functions-plugin@1.141.0': + resolution: {integrity: sha512-Ca8ylyh2c100Kn9nFUA4Gao95eISBGLbff+4unJ6MF+t+/FR3awIsIC5gBxeEVu+nv6HPaY9ZeD0/Ehh4OsXpQ==} + engines: {node: '>=12'} + peerDependencies: + vite: '>=6.0.0 || >=7.0.0' + '@tanstack/eslint-config@0.3.3': resolution: {integrity: sha512-8VFyAaIFV9onJcfc5yVj5WWl6DmN3W4m+t0Mb+nZrQmqHy+kDndw5O5Xv2BHVWRRPTqnhlJYh6wHWGh0R81ZzQ==} engines: {node: '>=18'} @@ -2665,6 +2803,10 @@ packages: resolution: {integrity: sha512-l6wcxwDBeh/7Dhles23U1O8lp9kNJmAb2yNjekR6olZwCRNAVA8TCXlVCrueELyFlYZqvQkh0ofxnzG62A1Kkg==} engines: {node: '>=12'} + '@tanstack/history@1.141.0': + resolution: {integrity: sha512-LS54XNyxyTs5m/pl1lkwlg7uZM3lvsv2FIIV1rsJgnfwVCnI+n4ZGZ2CcjNT13BPu/3hPP+iHmliBSscJxW5FQ==} + engines: {node: '>=12'} + '@tanstack/nitro-v2-vite-plugin@1.139.0': resolution: {integrity: sha512-TedrzuMjtHA08x47wCaU6KTrrat8gyzn8a4HUswTwjAa0sMpz4vbOOUDDZyYaJpmjKKbTjgTs6iRr4MONneKTQ==} engines: {node: '>=22.12'} @@ -2756,6 +2898,10 @@ packages: resolution: {integrity: sha512-mqgsJi4/B2Jo6PXRUs1AsWA+06nqiqVZe1aXioA3vR6PesNeKUSXWfmIoYF6wOx3osiV0BnwB1JCBrInCOQSWA==} engines: {node: '>=12'} + '@tanstack/router-core@1.141.1': + resolution: {integrity: sha512-fR1GGpp6v3dVKu4KIAjEh+Sd0qGLQd/wvCOVHeopSY6aFidXKCzwrS5cBOBqoPPWTKmn6CdW1a0CzFr5Furdog==} + engines: {node: '>=12'} + '@tanstack/router-devtools-core@1.139.10': resolution: {integrity: sha512-rAUAhTvwivA49dkYR4bRUPRxqShO9dTD1+r3tZsnt23XlpmGtFvxBw8FYY2C9BvqaRLu+2RxACJDaXETVfm3OA==} engines: {node: '>=12'} @@ -2778,6 +2924,17 @@ packages: csstype: optional: true + '@tanstack/router-devtools-core@1.141.1': + resolution: {integrity: sha512-wD9yRvOk6FI+thiNBplhkGutPIPBlXvWu9ttU/obdFY5oXQj9WYgNS+IO9BEe8Pz5rNEu8zE/oLn4RUGIVdtnw==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/router-core': ^1.141.1 + csstype: ^3.0.10 + solid-js: '>=1.9.5' + peerDependenciesMeta: + csstype: + optional: true + '@tanstack/router-generator@1.139.10': resolution: {integrity: sha512-Uo0xmz6w1Ayv1AMyWLsT0ngXmjB8yAKv5khOaci/ZxAZNyvz3t84jqI7XXlG9fwtDRdTF4G/qBmXlPEmPk6Wfg==} engines: {node: '>=12'} @@ -2786,6 +2943,10 @@ packages: resolution: {integrity: sha512-xnmF1poNH/dHtwFxecCcRsaLRIXVnXRZiWYUpvtyaPv4pQYayCrFQCg2ygDbCV0/8H7ctMBJh5MIL7GgPR7+xw==} engines: {node: '>=12'} + '@tanstack/router-generator@1.141.1': + resolution: {integrity: sha512-21RbVAoIDn7s/n/PKMN6U60d5hCeVADrBH/uN6B/poMT4MVYtJXqISVzkc2RAboVRw6eRdYFeF+YlwA3nF6y3Q==} + engines: {node: '>=12'} + '@tanstack/router-plugin@1.139.10': resolution: {integrity: sha512-0c9wzBKuz2U1jO+oAszT6VRaQDWPLfCJuPeXX7MCisM0nV2LVaxdb/y9YaWSKJ7zlQ7pwFkh37KYqcJhPXug/A==} engines: {node: '>=12'} @@ -2828,6 +2989,27 @@ packages: webpack: optional: true + '@tanstack/router-plugin@1.141.1': + resolution: {integrity: sha512-SoNXm8QK8cqX1Q4y1AfLU0tZLOt4mB4wkdpBI/Mi3ZEezF8tIrmaenyJ3987cjT9jedTy3VDBab1wN0g8MoOXg==} + engines: {node: '>=12'} + peerDependencies: + '@rsbuild/core': '>=1.0.2' + '@tanstack/react-router': ^1.141.1 + vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' + vite-plugin-solid: ^2.11.10 + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@tanstack/react-router': + optional: true + vite: + optional: true + vite-plugin-solid: + optional: true + webpack: + optional: true + '@tanstack/router-ssr-query-core@1.139.10': resolution: {integrity: sha512-cTNjPzDOVY8nbSCqgqLcPJ2dpMWrgo5VDFDal5c6xb38rU84mTzocXOX8a/9fjWMn4wzxv5p1S8HPN6RXfKD4w==} engines: {node: '>=12'} @@ -2846,10 +3028,18 @@ packages: resolution: {integrity: sha512-jT7D6NimWqoFSkid4vCno8gvTyfL1+NHpgm3es0B2UNhKKRV3LngOGilm1m6v8Qvk/gy6Fh/tvB+s+hBl6GhOg==} engines: {node: '>=12'} + '@tanstack/router-utils@1.141.0': + resolution: {integrity: sha512-/eFGKCiix1SvjxwgzrmH4pHjMiMxc+GA4nIbgEkG2RdAJqyxLcRhd7RPLG0/LZaJ7d0ad3jrtRqsHLv2152Vbw==} + engines: {node: '>=12'} + '@tanstack/server-functions-plugin@1.139.0': resolution: {integrity: sha512-IpNFiCoy2YU6gY/4lCKIVlFyU67ltlcUMGcdnrevqOgq20AbMyeLbbBVo9tAA3TkHK9F+9Hd7DqGXsup2pmBLg==} engines: {node: '>=12'} + '@tanstack/server-functions-plugin@1.141.0': + resolution: {integrity: sha512-WtqK9f3rGhocjPzmYgfBTF4nt8oLka6EuT0Hc8MheU59bS5WliuKJTU3nvPPNEQUCMFv3J4fFa3vE2b6tC8BUQ==} + engines: {node: '>=12'} + '@tanstack/solid-devtools@0.7.15': resolution: {integrity: sha512-c9QqNwBiWSXTytodgiwu93jkV7VhaktyckbvX8TytqdWxkTSUiqTgbyQ+RjXvG1M3IDTwymXj2YkRhr0krb4Ug==} engines: {node: '>=18'} @@ -2919,6 +3109,10 @@ packages: resolution: {integrity: sha512-omG032CeYUWlwQt6s7VFqhc9dGHKWNJ0C5PoIckL+G/HcV+0/RxYkiKzx/HTTzWt+K+LpsBDFFNnrTUUyTE5sw==} engines: {node: '>=22.12.0'} + '@tanstack/start-client-core@1.141.1': + resolution: {integrity: sha512-Rk/b0ekX7p0ZBKOg9WM5c632YPqu7GlvZSYnAjNi1GDp1/sET6g2Trp+GAjs1s8kakp2pMQ4sZUG/11grCMfJw==} + engines: {node: '>=22.12.0'} + '@tanstack/start-plugin-core@1.139.10': resolution: {integrity: sha512-NzvaBFmODpqLqkN/1iaD7ikF3TDXDvXh4IkhhyVzI4lY5YAxErdQ61wxOnieSxHrFpyz/P/iJI8ipsFO65gj2g==} engines: {node: '>=22.12.0'} @@ -2931,6 +3125,12 @@ packages: peerDependencies: vite: '>=7.0.0' + '@tanstack/start-plugin-core@1.141.1': + resolution: {integrity: sha512-jXfgKeM4XX7aoP7WF/cJZH52N0ewIYRdP028ItXaSwUMcDyBO+PPTNbSEqTu3zbzLsmTOOyuJEpIrVA0/lmbjA==} + engines: {node: '>=22.12.0'} + peerDependencies: + vite: '>=7.0.0' + '@tanstack/start-server-core@1.139.10': resolution: {integrity: sha512-7xMuHFVyqGf++87CrGrhlHE4AO1ltbhf0Cyrj5oe2c0i5c9YYRW95lo+av72IN+xgysyC/yBm8/RyP8UEaTSEA==} engines: {node: '>=22.12.0'} @@ -2939,6 +3139,10 @@ packages: resolution: {integrity: sha512-jKC83uMS2kgCHoqlHmxh9hAK1pN9Wd8l+Lhkibwp9PKKMW4Z1bxy5xCx6sr3TD2yJEOP25SRhYMrtAKmrLmYGA==} engines: {node: '>=22.12.0'} + '@tanstack/start-server-core@1.141.1': + resolution: {integrity: sha512-Qk/lZ/+iGUyNYeAAuj89bLR6GXLD/9BIpAR2CUwlS+xXGL0kQmOFcb1UvccWZ2QwtW+csxJW4NeQOeMuqsfyhA==} + engines: {node: '>=22.12.0'} + '@tanstack/start-storage-context@1.139.10': resolution: {integrity: sha512-nBAH4QAIdVhxfrbiEU8wuIQfozfPPhb989yAhLgntE8lkHhLLAmyHPGt6oWEWbVNZ1eka5QDm2J0d7Z7K7b2Og==} engines: {node: '>=22.12.0'} @@ -2947,6 +3151,10 @@ packages: resolution: {integrity: sha512-l2utb0CXLE+wfj1wlAUPHohiq7n5nOBMl3pflhl3JzCXt+6D9AAogkfrysyxOAvx3KnLh3oG+qwf1KHWIDB9HA==} engines: {node: '>=22.12.0'} + '@tanstack/start-storage-context@1.141.1': + resolution: {integrity: sha512-UPOQd4qsytgmc+pHeeS3oIZQazhyGAmEaCS/IrZI42TzpuVh2ZbLVssKEoDziheNP1dH5KT2lsL1bU9asAw7tA==} + engines: {node: '>=22.12.0'} + '@tanstack/store@0.8.0': resolution: {integrity: sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ==} @@ -2958,10 +3166,63 @@ packages: resolution: {integrity: sha512-9PImF1d1tovTUIpjFVa0W7Fwj/MHif7BaaczgJJfbv3sDt1Gh+oW9W9uCw9M3ndEJynnp5ZD/TTs0RGubH5ssg==} engines: {node: '>=12'} + '@tanstack/virtual-file-routes@1.141.0': + resolution: {integrity: sha512-CJrWtr6L9TVzEImm9S7dQINx+xJcYP/aDkIi6gnaWtIgbZs1pnzsE0yJc2noqXZ+yAOqLx3TBGpBEs9tS0P9/A==} + engines: {node: '>=12'} + '@tanstack/vite-config@0.4.1': resolution: {integrity: sha512-FOl8EF6SAcljanKSm5aBeJaflFcxQAytTbxtNW8HC6D4x+UBW68IC4tBcrlrsI0wXHBmC/Gz4Ovvv8qCtiXSgQ==} engines: {node: '>=18'} + '@tanstack/vue-devtools@0.1.2': + resolution: {integrity: sha512-V/MTs00UyhqoEV+N8MDg0icA7je0ODVFDlYLDhb3yttXmo9a5/H3opqP09lyDA3Kkq//mOPC5xY9jk+6nORYAg==} + engines: {node: '>=18'} + + '@tanstack/vue-router-devtools@1.141.1': + resolution: {integrity: sha512-rILiRa4o46LgtXLLqkrGZ5156BoBqymyuIyC2KD3PsmzO13OdiO2vc3K3tFz1VotceLv8y45+OSILbUZ2XGlEA==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/router-core': ^1.141.1 + '@tanstack/vue-router': ^1.141.1 + vue: ^3.5.13 + peerDependenciesMeta: + '@tanstack/router-core': + optional: true + + '@tanstack/vue-router@1.141.1': + resolution: {integrity: sha512-44JcFYvyiS/KBJBbmZSXAjRgx0SBjf3Zu+NAOL7yj0c3GviRWQc66mudtH4Afc9EM7U3nNxrpTz77LYiIILuSw==} + engines: {node: '>=12'} + peerDependencies: + vue: ^3.3.0 + + '@tanstack/vue-start-client@1.141.1': + resolution: {integrity: sha512-bQXqihO+tGxrNGoddgktXegL/RXIHUHORV+SLfZ1yzMnga1LF667J08CK8OCNPoXQtKn/m8YIaE/O/JWDwBuQw==} + engines: {node: '>=22.12.0'} + peerDependencies: + vue: ^3.3.0 + + '@tanstack/vue-start-server@1.141.1': + resolution: {integrity: sha512-6a9kgYRms63/dChCxpHlPMlFGszhx7V45CaKcF3hX2ysFz5t1OQpvXWpHcaruT45zkzXI2YybSx+ZcYneEpRxQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + vue: ^3.3.0 + + '@tanstack/vue-start@1.141.1': + resolution: {integrity: sha512-99YO2n/f9+Kr/bAggbzlOnDJzMOCWI6LPUOpxFSn70Nu5LcJWlXkxfRBbmgkEPHbo6/9q0TUuNlpmI87Jf+0mg==} + engines: {node: '>=22.12.0'} + peerDependencies: + vite: '>=7.0.0' + vue: ^3.3.0 + + '@tanstack/vue-store@0.8.0': + resolution: {integrity: sha512-YLsinYboBLIjNkxDpAn1ydaMS35dKq3M3a788JRCJi4/stWcN7Swp0pxxJ+p0IwKSY4tBXx7vMz22OYWQ1QsUQ==} + peerDependencies: + '@vue/composition-api': ^1.2.1 + vue: ^2.5.0 || ^3.0.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -3276,12 +3537,12 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitejs/plugin-vue@5.2.4': - resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} - engines: {node: ^18.0.0 || >=20.0.0} + '@vitejs/plugin-vue-jsx@5.1.2': + resolution: {integrity: sha512-3a2BOryRjG/Iih87x87YXz5c8nw27eSlHytvSKYfp8ZIsp5+FgFQoKeA7k2PnqWpjJrv6AoVTMnvmuKUXb771A==} + engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: ^5.0.0 || ^6.0.0 - vue: ^3.2.25 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + vue: ^3.0.0 '@vitejs/plugin-vue@6.0.2': resolution: {integrity: sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==} @@ -3290,6 +3551,13 @@ packages: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 vue: ^3.2.25 + '@vitejs/plugin-vue@6.0.3': + resolution: {integrity: sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + vue: ^3.2.25 + '@vitest/coverage-v8@4.0.14': resolution: {integrity: sha512-EYHLqN/BY6b47qHH7gtMxAg++saoGmsjWmAq9MlXxAz4M0NcHh9iOyKhBZyU4yxZqOd8Xnqp80/5saeitz4Cng==} peerDependencies: @@ -3346,15 +3614,25 @@ packages: '@volar/typescript@2.4.23': resolution: {integrity: sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag==} - '@vue/compiler-core@3.5.24': - resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==} + '@vue/babel-helper-vue-transform-on@2.0.1': + resolution: {integrity: sha512-uZ66EaFbnnZSYqYEyplWvn46GhZ1KuYSThdT68p+am7MgBNbQ3hphTL9L+xSIsWkdktwhPYLwPgVWqo96jDdRA==} + + '@vue/babel-plugin-jsx@2.0.1': + resolution: {integrity: sha512-a8CaLQjD/s4PVdhrLD/zT574ZNPnZBOY+IhdtKWRB4HRZ0I2tXBi5ne7d9eCfaYwp5gU5+4KIyFTV1W1YL9xZA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@2.0.1': + resolution: {integrity: sha512-ybwgIuRGRRBhOU37GImDoWQoz+TlSqap65qVI6iwg/J7FfLTLmMf97TS7xQH9I7Qtr/gp161kYVdhr1ZMraSYQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 '@vue/compiler-core@3.5.25': resolution: {integrity: sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==} - '@vue/compiler-dom@3.5.24': - resolution: {integrity: sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==} - '@vue/compiler-dom@3.5.25': resolution: {integrity: sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==} @@ -3400,9 +3678,6 @@ packages: peerDependencies: vue: 3.5.25 - '@vue/shared@3.5.24': - resolution: {integrity: sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==} - '@vue/shared@3.5.25': resolution: {integrity: sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==} @@ -7018,6 +7293,17 @@ packages: vue-component-type-helpers@2.2.12: resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==} + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue-eslint-parser@10.2.0: resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -8656,6 +8942,10 @@ snapshots: dependencies: '@tanstack/devtools-event-client': 0.3.5 + '@tanstack/devtools-client@0.0.5': + dependencies: + '@tanstack/devtools-event-client': 0.4.0 + '@tanstack/devtools-event-bus@0.3.3': dependencies: ws: 8.18.3 @@ -8720,6 +9010,22 @@ snapshots: - csstype - utf-8-validate + '@tanstack/devtools@0.9.1(csstype@3.2.3)(solid-js@1.9.10)': + dependencies: + '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10) + '@solid-primitives/keyboard': 1.3.3(solid-js@1.9.10) + '@solid-primitives/resize-observer': 2.1.3(solid-js@1.9.10) + '@tanstack/devtools-client': 0.0.5 + '@tanstack/devtools-event-bus': 0.3.3 + '@tanstack/devtools-ui': 0.4.4(csstype@3.2.3)(solid-js@1.9.10) + clsx: 2.1.1 + goober: 2.1.18(csstype@3.2.3) + solid-js: 1.9.10 + transitivePeerDependencies: + - bufferutil + - csstype + - utf-8-validate + '@tanstack/directive-functions-plugin@1.139.0(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/code-frame': 7.27.1 @@ -8734,6 +9040,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@tanstack/directive-functions-plugin@1.141.0(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.28.5 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@tanstack/router-utils': 1.141.0 + babel-dead-code-elimination: 1.0.10 + pathe: 2.0.3 + tiny-invariant: 1.3.3 + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + '@tanstack/eslint-config@0.3.3(@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint/js': 9.39.1 @@ -8752,6 +9072,8 @@ snapshots: '@tanstack/history@1.139.0': {} + '@tanstack/history@1.141.0': {} + '@tanstack/nitro-v2-vite-plugin@1.139.0(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: nitropack: 2.12.9(rolldown@1.0.0-beta.53) @@ -8810,15 +9132,15 @@ snapshots: '@tanstack/query-core': 5.90.5 react: 19.2.0 - '@tanstack/react-router-devtools@1.139.7(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': + '@tanstack/react-router-devtools@1.139.7(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': dependencies: '@tanstack/react-router': 1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@tanstack/router-devtools-core': 1.139.7(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + '@tanstack/router-devtools-core': 1.139.7(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) optionalDependencies: - '@tanstack/router-core': 1.139.10 + '@tanstack/router-core': 1.141.1 transitivePeerDependencies: - '@types/node' - csstype @@ -8834,12 +9156,12 @@ snapshots: - tsx - yaml - '@tanstack/react-router-ssr-query@1.139.7(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.5(react@19.2.0))(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.139.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@tanstack/react-router-ssr-query@1.139.7(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.5(react@19.2.0))(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.141.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@tanstack/query-core': 5.90.11 '@tanstack/react-query': 5.90.5(react@19.2.0) '@tanstack/react-router': 1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@tanstack/router-ssr-query-core': 1.139.7(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.139.10) + '@tanstack/router-ssr-query-core': 1.139.7(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.141.1) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) transitivePeerDependencies: @@ -8925,9 +9247,19 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.139.10(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': + '@tanstack/router-core@1.141.1': dependencies: - '@tanstack/router-core': 1.139.10 + '@tanstack/history': 1.141.0 + '@tanstack/store': 0.8.0 + cookie-es: 2.0.0 + seroval: 1.4.0 + seroval-plugins: 1.4.0(seroval@1.4.0) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/router-devtools-core@1.139.10(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': + dependencies: + '@tanstack/router-core': 1.141.1 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) solid-js: 1.9.10 @@ -8948,9 +9280,9 @@ snapshots: - tsx - yaml - '@tanstack/router-devtools-core@1.139.7(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': + '@tanstack/router-devtools-core@1.139.7(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': dependencies: - '@tanstack/router-core': 1.139.10 + '@tanstack/router-core': 1.141.1 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) solid-js: 1.9.10 @@ -8971,6 +9303,16 @@ snapshots: - tsx - yaml + '@tanstack/router-devtools-core@1.141.1(@tanstack/router-core@1.141.1)(csstype@3.2.3)(solid-js@1.9.10)': + dependencies: + '@tanstack/router-core': 1.141.1 + clsx: 2.1.1 + goober: 2.1.18(csstype@3.2.3) + solid-js: 1.9.10 + tiny-invariant: 1.3.3 + optionalDependencies: + csstype: 3.2.3 + '@tanstack/router-generator@1.139.10': dependencies: '@tanstack/router-core': 1.139.10 @@ -8997,6 +9339,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@tanstack/router-generator@1.141.1': + dependencies: + '@tanstack/router-core': 1.141.1 + '@tanstack/router-utils': 1.141.0 + '@tanstack/virtual-file-routes': 1.141.0 + prettier: 3.7.4 + recast: 0.23.11 + source-map: 0.7.6 + tsx: 4.20.6 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + '@tanstack/router-plugin@1.139.10(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/core': 7.28.5 @@ -9043,15 +9398,37 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-ssr-query-core@1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.139.10)': + '@tanstack/router-plugin@1.141.1(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@tanstack/router-core': 1.141.1 + '@tanstack/router-generator': 1.141.1 + '@tanstack/router-utils': 1.141.0 + '@tanstack/virtual-file-routes': 1.141.0 + babel-dead-code-elimination: 1.0.10 + chokidar: 3.6.0 + unplugin: 2.3.10 + zod: 3.25.76 + optionalDependencies: + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vite-plugin-solid: 2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + transitivePeerDependencies: + - supports-color + + '@tanstack/router-ssr-query-core@1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.141.1)': dependencies: '@tanstack/query-core': 5.90.11 - '@tanstack/router-core': 1.139.10 + '@tanstack/router-core': 1.141.1 - '@tanstack/router-ssr-query-core@1.139.7(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.139.10)': + '@tanstack/router-ssr-query-core@1.139.7(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.141.1)': dependencies: '@tanstack/query-core': 5.90.11 - '@tanstack/router-core': 1.139.10 + '@tanstack/router-core': 1.141.1 '@tanstack/router-utils@1.139.0': dependencies: @@ -9066,6 +9443,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@tanstack/router-utils@1.141.0': + dependencies: + '@babel/core': 7.28.5 + '@babel/generator': 7.28.5 + '@babel/parser': 7.28.5 + '@babel/preset-typescript': 7.28.5(@babel/core@7.28.5) + ansis: 4.2.0 + diff: 8.0.2 + pathe: 2.0.3 + tinyglobby: 0.2.15 + transitivePeerDependencies: + - supports-color + '@tanstack/server-functions-plugin@1.139.0(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/code-frame': 7.27.1 @@ -9082,6 +9472,22 @@ snapshots: - supports-color - vite + '@tanstack/server-functions-plugin@1.141.0(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.28.5 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@tanstack/directive-functions-plugin': 1.141.0(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + babel-dead-code-elimination: 1.0.10 + tiny-invariant: 1.3.3 + transitivePeerDependencies: + - supports-color + - vite + '@tanstack/solid-devtools@0.7.15(csstype@3.2.3)(solid-js@1.9.10)': dependencies: '@tanstack/devtools': 0.8.2(csstype@3.2.3)(solid-js@1.9.10) @@ -9096,14 +9502,14 @@ snapshots: '@tanstack/query-core': 5.90.11 solid-js: 1.9.10 - '@tanstack/solid-router-devtools@1.139.10(@tanstack/router-core@1.139.10)(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': + '@tanstack/solid-router-devtools@1.139.10(@tanstack/router-core@1.141.1)(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)': dependencies: - '@tanstack/router-devtools-core': 1.139.10(@tanstack/router-core@1.139.10)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + '@tanstack/router-devtools-core': 1.139.10(@tanstack/router-core@1.141.1)(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) '@tanstack/solid-router': 1.139.10(solid-js@1.9.10) solid-js: 1.9.10 vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) optionalDependencies: - '@tanstack/router-core': 1.139.10 + '@tanstack/router-core': 1.141.1 transitivePeerDependencies: - '@types/node' - csstype @@ -9118,10 +9524,10 @@ snapshots: - tsx - yaml - '@tanstack/solid-router-ssr-query@1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.139.10)(@tanstack/solid-query@5.90.14(solid-js@1.9.10))(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(eslint@9.39.1(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3)': + '@tanstack/solid-router-ssr-query@1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.141.1)(@tanstack/solid-query@5.90.14(solid-js@1.9.10))(@tanstack/solid-router@1.139.10(solid-js@1.9.10))(eslint@9.39.1(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3)': dependencies: '@tanstack/query-core': 5.90.11 - '@tanstack/router-ssr-query-core': 1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.139.10) + '@tanstack/router-ssr-query-core': 1.139.10(@tanstack/query-core@5.90.11)(@tanstack/router-core@1.141.1) '@tanstack/solid-query': 5.90.14(solid-js@1.9.10) '@tanstack/solid-router': 1.139.10(solid-js@1.9.10) eslint-plugin-solid: 0.14.5(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) @@ -9206,6 +9612,14 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 + '@tanstack/start-client-core@1.141.1': + dependencies: + '@tanstack/router-core': 1.141.1 + '@tanstack/start-storage-context': 1.141.1 + seroval: 1.4.0 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + '@tanstack/start-plugin-core@1.139.10(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@babel/code-frame': 7.26.2 @@ -9270,6 +9684,38 @@ snapshots: - vite-plugin-solid - webpack + '@tanstack/start-plugin-core@1.141.1(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/core': 7.28.5 + '@babel/types': 7.28.5 + '@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(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + '@tanstack/router-utils': 1.141.0 + '@tanstack/server-functions-plugin': 1.141.0(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + '@tanstack/start-client-core': 1.141.1 + '@tanstack/start-server-core': 1.141.1 + babel-dead-code-elimination: 1.0.10 + cheerio: 1.1.2 + exsolve: 1.0.7 + pathe: 2.0.3 + srvx: 0.8.16 + tinyglobby: 0.2.15 + ufo: 1.6.1 + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vitefu: 1.1.1(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + xmlbuilder2: 4.0.1 + zod: 3.25.76 + transitivePeerDependencies: + - '@rsbuild/core' + - '@tanstack/react-router' + - crossws + - supports-color + - vite-plugin-solid + - webpack + '@tanstack/start-server-core@1.139.10': dependencies: '@tanstack/history': 1.139.0 @@ -9294,6 +9740,18 @@ snapshots: transitivePeerDependencies: - crossws + '@tanstack/start-server-core@1.141.1': + dependencies: + '@tanstack/history': 1.141.0 + '@tanstack/router-core': 1.141.1 + '@tanstack/start-client-core': 1.141.1 + '@tanstack/start-storage-context': 1.141.1 + h3-v2: h3@2.0.0-beta.5 + seroval: 1.4.0 + tiny-invariant: 1.3.3 + transitivePeerDependencies: + - crossws + '@tanstack/start-storage-context@1.139.10': dependencies: '@tanstack/router-core': 1.139.10 @@ -9302,6 +9760,10 @@ snapshots: dependencies: '@tanstack/router-core': 1.139.7 + '@tanstack/start-storage-context@1.141.1': + dependencies: + '@tanstack/router-core': 1.141.1 + '@tanstack/store@0.8.0': {} '@tanstack/typedoc-config@0.3.1(typescript@5.9.3)': @@ -9314,6 +9776,8 @@ snapshots: '@tanstack/virtual-file-routes@1.139.0': {} + '@tanstack/virtual-file-routes@1.141.0': {} + '@tanstack/vite-config@0.4.1(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: rollup-plugin-preserve-directives: 0.4.0(rollup@4.53.3) @@ -9327,6 +9791,100 @@ snapshots: - typescript - vite + '@tanstack/vue-devtools@0.1.2(csstype@3.2.3)(solid-js@1.9.10)': + dependencies: + '@tanstack/devtools': 0.9.1(csstype@3.2.3)(solid-js@1.9.10) + transitivePeerDependencies: + - bufferutil + - csstype + - solid-js + - utf-8-validate + + '@tanstack/vue-router-devtools@1.141.1(@tanstack/router-core@1.141.1)(@tanstack/vue-router@1.141.1(vue@3.5.25(typescript@5.9.3)))(@types/node@24.10.1)(csstype@3.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(terser@5.44.0)(tsx@4.20.6)(vue@3.5.25(typescript@5.9.3))(yaml@2.8.1)': + dependencies: + '@tanstack/router-devtools-core': 1.141.1(@tanstack/router-core@1.141.1)(csstype@3.2.3)(solid-js@1.9.10) + '@tanstack/vue-router': 1.141.1(vue@3.5.25(typescript@5.9.3)) + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vue: 3.5.25(typescript@5.9.3) + optionalDependencies: + '@tanstack/router-core': 1.141.1 + transitivePeerDependencies: + - '@types/node' + - csstype + - jiti + - less + - lightningcss + - sass + - sass-embedded + - solid-js + - stylus + - sugarss + - terser + - tsx + - yaml + + '@tanstack/vue-router@1.141.1(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@tanstack/history': 1.141.0 + '@tanstack/router-core': 1.141.1 + '@tanstack/vue-store': 0.8.0(vue@3.5.25(typescript@5.9.3)) + isbot: 5.1.31 + jsesc: 3.1.0 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + vue: 3.5.25(typescript@5.9.3) + transitivePeerDependencies: + - '@vue/composition-api' + + '@tanstack/vue-start-client@1.141.1(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@tanstack/router-core': 1.141.1 + '@tanstack/start-client-core': 1.141.1 + '@tanstack/vue-router': 1.141.1(vue@3.5.25(typescript@5.9.3)) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + vue: 3.5.25(typescript@5.9.3) + transitivePeerDependencies: + - '@vue/composition-api' + + '@tanstack/vue-start-server@1.141.1(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@tanstack/history': 1.141.0 + '@tanstack/router-core': 1.141.1 + '@tanstack/start-client-core': 1.141.1 + '@tanstack/start-server-core': 1.141.1 + '@tanstack/vue-router': 1.141.1(vue@3.5.25(typescript@5.9.3)) + vue: 3.5.25(typescript@5.9.3) + transitivePeerDependencies: + - '@vue/composition-api' + - crossws + + '@tanstack/vue-start@1.141.1(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@tanstack/start-client-core': 1.141.1 + '@tanstack/start-plugin-core': 1.141.1(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + '@tanstack/start-server-core': 1.141.1 + '@tanstack/vue-router': 1.141.1(vue@3.5.25(typescript@5.9.3)) + '@tanstack/vue-start-client': 1.141.1(vue@3.5.25(typescript@5.9.3)) + '@tanstack/vue-start-server': 1.141.1(vue@3.5.25(typescript@5.9.3)) + pathe: 2.0.3 + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vue: 3.5.25(typescript@5.9.3) + transitivePeerDependencies: + - '@rsbuild/core' + - '@tanstack/react-router' + - '@vue/composition-api' + - crossws + - supports-color + - vite-plugin-solid + - webpack + + '@tanstack/vue-store@0.8.0(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@tanstack/store': 0.8.0 + vue: 3.5.25(typescript@5.9.3) + vue-demi: 0.14.10(vue@3.5.25(typescript@5.9.3)) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 @@ -9689,10 +10247,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))': + '@vitejs/plugin-vue-jsx@5.1.2(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))': dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.28.5) + '@rolldown/pluginutils': 1.0.0-beta.53 + '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.28.5) vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) vue: 3.5.25(typescript@5.9.3) + transitivePeerDependencies: + - supports-color '@vitejs/plugin-vue@6.0.2(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))': dependencies: @@ -9700,6 +10265,12 @@ snapshots: vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) vue: 3.5.25(typescript@5.9.3) + '@vitejs/plugin-vue@6.0.3(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-beta.53 + vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vue: 3.5.25(typescript@5.9.3) + '@vitest/coverage-v8@4.0.14(vitest@4.0.14(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -9780,13 +10351,34 @@ snapshots: path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.24': + '@vue/babel-helper-vue-transform-on@2.0.1': {} + + '@vue/babel-plugin-jsx@2.0.1(@babel/core@7.28.5)': dependencies: + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@vue/babel-helper-vue-transform-on': 2.0.1 + '@vue/babel-plugin-resolve-type': 2.0.1(@babel/core@7.28.5) + '@vue/shared': 3.5.25 + optionalDependencies: + '@babel/core': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@2.0.1(@babel/core@7.28.5)': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 '@babel/parser': 7.28.5 - '@vue/shared': 3.5.24 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.1 + '@vue/compiler-sfc': 3.5.25 + transitivePeerDependencies: + - supports-color '@vue/compiler-core@3.5.25': dependencies: @@ -9796,11 +10388,6 @@ snapshots: estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.24': - dependencies: - '@vue/compiler-core': 3.5.24 - '@vue/shared': 3.5.24 - '@vue/compiler-dom@3.5.25': dependencies: '@vue/compiler-core': 3.5.25 @@ -9833,9 +10420,9 @@ snapshots: '@vue/language-core@2.1.6(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.23 - '@vue/compiler-dom': 3.5.24 + '@vue/compiler-dom': 3.5.25 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.24 + '@vue/shared': 3.5.25 computeds: 0.0.1 minimatch: 9.0.5 muggle-string: 0.4.1 @@ -9878,8 +10465,6 @@ snapshots: '@vue/shared': 3.5.25 vue: 3.5.25(typescript@5.9.3) - '@vue/shared@3.5.24': {} - '@vue/shared@3.5.25': {} '@vue/test-utils@2.4.6': @@ -13955,6 +14540,10 @@ snapshots: vue-component-type-helpers@2.2.12: {} + vue-demi@0.14.10(vue@3.5.25(typescript@5.9.3)): + dependencies: + vue: 3.5.25(typescript@5.9.3) + vue-eslint-parser@10.2.0(eslint@9.39.1(jiti@2.6.1)): dependencies: debug: 4.4.3