diff --git a/.changeset/huge-lizards-admire.md b/.changeset/huge-lizards-admire.md new file mode 100644 index 000000000..cc17b39d0 --- /dev/null +++ b/.changeset/huge-lizards-admire.md @@ -0,0 +1,5 @@ +--- +'@tanstack/ai-gemini': minor +--- + +Added Gemini Realtime Adapter diff --git a/examples/ts-react-chat/.env.example b/examples/ts-react-chat/.env.example index 2bdb43f49..178fc6d97 100644 --- a/examples/ts-react-chat/.env.example +++ b/examples/ts-react-chat/.env.example @@ -2,6 +2,10 @@ # Get yours at: https://platform.openai.com/api-keys OPENAI_API_KEY=sk-... +# Gemini API Key +# Get yours at: https://aistudio.google.com/api-keys +GEMINI_API_KEY=... + # ElevenLabs API Key (for realtime voice) # Get yours at: https://elevenlabs.io/app/settings/api-keys ELEVENLABS_API_KEY=xi-... diff --git a/examples/ts-react-chat/src/lib/use-realtime.ts b/examples/ts-react-chat/src/lib/use-realtime.ts index 848c702ca..41a17798c 100644 --- a/examples/ts-react-chat/src/lib/use-realtime.ts +++ b/examples/ts-react-chat/src/lib/use-realtime.ts @@ -1,17 +1,20 @@ -import { createServerFn } from '@tanstack/react-start' import { realtimeToken } from '@tanstack/ai' -import { useRealtimeChat } from '@tanstack/ai-react' -import { openaiRealtime, openaiRealtimeToken } from '@tanstack/ai-openai' import { elevenlabsRealtime, elevenlabsRealtimeToken, } from '@tanstack/ai-elevenlabs' +import { geminiRealtime, geminiRealtimeToken } from '@tanstack/ai-gemini' +import { openaiRealtime, openaiRealtimeToken } from '@tanstack/ai-openai' +import { useRealtimeChat } from '@tanstack/ai-react' +import { createServerFn } from '@tanstack/react-start' +import type { OpenAIRealtimeVoice } from "@tanstack/ai-openai" +import type { GeminiRealtimeVoice } from "@tanstack/ai-gemini" import { realtimeClientTools } from '@/lib/realtime-tools' -type Provider = 'openai' | 'elevenlabs' +type Provider = 'openai' | 'elevenlabs' | 'gemini' const getRealtimeTokenFn = createServerFn({ method: 'POST' }) - .inputValidator((data: { provider: Provider; agentId?: string }) => { + .inputValidator((data: { provider?: Provider; agentId?: string }) => { if (!data.provider) throw new Error('Provider is required') return data }) @@ -24,6 +27,12 @@ const getRealtimeTokenFn = createServerFn({ method: 'POST' }) }) } + if (data.provider === 'gemini') { + return realtimeToken({ + adapter: geminiRealtimeToken(), + }) + } + if (data.provider === 'elevenlabs') { const agentId = data.agentId || process.env.ELEVENLABS_AGENT_ID if (!agentId) { @@ -46,6 +55,7 @@ export function useRealtime({ temperature, maxOutputTokens, semanticEagerness, + voice }: { provider: Provider agentId: string @@ -53,9 +63,14 @@ export function useRealtime({ temperature?: number maxOutputTokens?: number | 'inf' semanticEagerness?: 'low' | 'medium' | 'high' + voice?: OpenAIRealtimeVoice | GeminiRealtimeVoice }) { const adapter = - provider === 'openai' ? openaiRealtime() : elevenlabsRealtime() + provider === 'openai' + ? openaiRealtime() + : provider === 'gemini' + ? geminiRealtime() + : elevenlabsRealtime() return useRealtimeChat({ getToken: () => @@ -78,7 +93,7 @@ Keep your responses concise and conversational since this is a voice interface. When using tools, briefly explain what you're doing and then share the results naturally. If the user sends an image, describe what you see and answer any questions about it. Be friendly and engaging!`, - voice: 'alloy', + voice: voice || provider === 'gemini' ? 'Puck' : 'alloy', tools: realtimeClientTools, outputModalities, temperature, diff --git a/examples/ts-react-chat/src/routes/realtime.tsx b/examples/ts-react-chat/src/routes/realtime.tsx index 3225249e2..1d2e4a527 100644 --- a/examples/ts-react-chat/src/routes/realtime.tsx +++ b/examples/ts-react-chat/src/routes/realtime.tsx @@ -13,10 +13,11 @@ import { import { AudioSparkline } from '@/components/AudioSparkline' import { useRealtime } from '@/lib/use-realtime' -type Provider = 'openai' | 'elevenlabs' +type Provider = 'openai' | 'elevenlabs' | 'gemini' type OutputMode = 'audio+text' | 'text-only' | 'audio-only' const PROVIDER_OPTIONS: Array<{ value: Provider; label: string }> = [ + { value: 'gemini', label: 'Google Gemini' }, { value: 'openai', label: 'OpenAI Realtime' }, { value: 'elevenlabs', label: 'ElevenLabs' }, ] @@ -43,7 +44,7 @@ function outputModeToModalities( } function RealtimePage() { - const [provider, setProvider] = useState('openai') + const [provider, setProvider] = useState('gemini') const [agentId, setAgentId] = useState('') const [textInput, setTextInput] = useState('') const [outputMode, setOutputMode] = useState('audio+text') @@ -275,7 +276,7 @@ function RealtimePage() { {/* Tools indicator */} - {provider === 'openai' && ( + {(provider === 'openai' || provider === 'gemini') && (
diff --git a/packages/typescript/ai-client/src/realtime-client.ts b/packages/typescript/ai-client/src/realtime-client.ts index 2683294c0..82ed354e4 100644 --- a/packages/typescript/ai-client/src/realtime-client.ts +++ b/packages/typescript/ai-client/src/realtime-client.ts @@ -4,6 +4,7 @@ import type { AudioVisualization, RealtimeMessage, RealtimeMode, + RealtimeSessionConfig, RealtimeStatus, RealtimeToken, } from '@tanstack/ai' @@ -100,6 +101,7 @@ export class RealtimeClient { this.clientTools.size > 0 ? Array.from(this.clientTools.values()) : undefined + this.connection = await this.options.adapter.connect( this.token, toolsList, @@ -281,6 +283,35 @@ export class RealtimeClient { return this.connection?.getAudioVisualization() ?? null } + /** + * Update the session configuration. + * This applies changes to the active connection and persists them for future reconnections. + */ + updateSession(config: Partial): void { + // Update local options so future connections use the updated config + const sessionKeys: Array = [ + 'instructions', + 'voice', + 'vadMode', + 'tools', + 'outputModalities', + 'temperature', + 'maxOutputTokens', + 'semanticEagerness', + 'modelOptions', + ] + + for (const key of sessionKeys) { + if (key in config) { + (this.options as any)[key] = (config as any)[key] + } + } + + if (this.connection) { + this.applySessionConfig() + } + } + // ============================================================================ // State Subscription // ============================================================================ @@ -352,6 +383,7 @@ export class RealtimeClient { try { this.token = await this.options.getToken() this.scheduleTokenRefresh() + this.connection?.updateToken?.(this.token) // Note: Some providers may require reconnection with new token // This is handled by the adapter implementation } catch (error) { @@ -472,6 +504,18 @@ export class RealtimeClient { this.options.onError?.(error) }), ) + + this.unsubscribers.push( + this.connection.on('go_away', ({ timeLeft }) => { + this.options.onGoAway?.(timeLeft) + }), + ) + + this.unsubscribers.push( + this.connection.on('usage', (usage) => { + this.options.onUsage?.(usage) + }), + ) } private applySessionConfig(): void { @@ -500,12 +544,12 @@ export class RealtimeClient { const toolsConfig = tools ? Array.from(this.clientTools.values()).map((t) => ({ - name: t.name, - description: t.description, - inputSchema: t.inputSchema - ? convertSchemaToJsonSchema(t.inputSchema) - : undefined, - })) + name: t.name, + description: t.description, + inputSchema: t.inputSchema + ? convertSchemaToJsonSchema(t.inputSchema) + : undefined, + })) : undefined this.connection.updateSession({ diff --git a/packages/typescript/ai-client/src/realtime-types.ts b/packages/typescript/ai-client/src/realtime-types.ts index bffd6df34..c81f662de 100644 --- a/packages/typescript/ai-client/src/realtime-types.ts +++ b/packages/typescript/ai-client/src/realtime-types.ts @@ -8,6 +8,7 @@ import type { RealtimeSessionConfig, RealtimeStatus, RealtimeToken, + UsageInfo, } from '@tanstack/ai' // ============================================================================ @@ -25,7 +26,7 @@ export interface RealtimeAdapter { /** * Create a connection using the provided token * @param token - The ephemeral token from the server - * @param clientTools - Optional client-side tools to register with the provider + * @param config - Initial session configuration (voice, instructions, etc.) * @returns A connection instance */ connect: ( @@ -64,6 +65,8 @@ export interface RealtimeConnection { // Session management /** Update session configuration */ updateSession: (config: Partial) => void + /** Update token */ + updateToken?: (token: RealtimeToken) => void /** Interrupt the current response */ interrupt: () => void @@ -148,6 +151,11 @@ export interface RealtimeClientOptions { */ semanticEagerness?: 'low' | 'medium' | 'high' + /** + * Provider-specific options + */ + modelOptions?: Record + // Callbacks onStatusChange?: (status: RealtimeStatus) => void onModeChange?: (mode: RealtimeMode) => void @@ -156,6 +164,8 @@ export interface RealtimeClientOptions { onConnect?: () => void onDisconnect?: () => void onInterrupted?: () => void + onUsage?: (usage: UsageInfo) => void + onGoAway?: (timeLeft?: string) => void } // ============================================================================ diff --git a/packages/typescript/ai-elevenlabs/src/realtime/adapter.ts b/packages/typescript/ai-elevenlabs/src/realtime/adapter.ts index 33bc5344e..157a4623a 100644 --- a/packages/typescript/ai-elevenlabs/src/realtime/adapter.ts +++ b/packages/typescript/ai-elevenlabs/src/realtime/adapter.ts @@ -1,9 +1,8 @@ import { Conversation } from '@11labs/client' +import { createRealtimeEventEmitter } from '@tanstack/ai' import type { AnyClientTool, AudioVisualization, - RealtimeEvent, - RealtimeEventHandler, RealtimeMessage, RealtimeMode, RealtimeSessionConfig, @@ -42,7 +41,7 @@ export function elevenlabsRealtime( token: RealtimeToken, clientToolDefs?: ReadonlyArray, ): Promise { - return createElevenLabsConnection(token, options, clientToolDefs) + return createElevenLabsConnection(token, clientToolDefs) }, } } @@ -52,10 +51,9 @@ export function elevenlabsRealtime( */ async function createElevenLabsConnection( token: RealtimeToken, - _options: ElevenLabsRealtimeOptions, clientToolDefs?: ReadonlyArray, ): Promise { - const eventHandlers = new Map>>() + const { emit, on: realtimeEventEmitterOn } = createRealtimeEventEmitter() let conversation: Awaited< ReturnType > | null = null @@ -65,19 +63,6 @@ async function createElevenLabsConnection( const emptyFrequencyData = new Uint8Array(128) const emptyTimeDomainData = new Uint8Array(128).fill(128) - // Helper to emit events - function emit( - event: TEvent, - payload: Parameters>[0], - ) { - const handlers = eventHandlers.get(event) - if (handlers) { - for (const handler of handlers) { - handler(payload) - } - } - } - function generateMessageId(): string { return `el-msg-${Date.now()}-${++messageIdCounter}` } @@ -223,19 +208,7 @@ async function createElevenLabsConnection( emit('interrupted', {}) }, - on( - event: TEvent, - handler: RealtimeEventHandler, - ): () => void { - if (!eventHandlers.has(event)) { - eventHandlers.set(event, new Set()) - } - eventHandlers.get(event)!.add(handler) - - return () => { - eventHandlers.get(event)?.delete(handler) - } - }, + on: realtimeEventEmitterOn, getAudioVisualization(): AudioVisualization { return { diff --git a/packages/typescript/ai-elevenlabs/src/realtime/token.ts b/packages/typescript/ai-elevenlabs/src/realtime/token.ts index 030d0c9a9..14e975da7 100644 --- a/packages/typescript/ai-elevenlabs/src/realtime/token.ts +++ b/packages/typescript/ai-elevenlabs/src/realtime/token.ts @@ -91,7 +91,7 @@ export function elevenlabsRealtimeToken( config: { voice: overrides?.voiceId, instructions: overrides?.systemPrompt, - providerOptions: { + modelOptions: { agentId, firstMessage: overrides?.firstMessage, language: overrides?.language, diff --git a/packages/typescript/ai-gemini/package.json b/packages/typescript/ai-gemini/package.json index 11656a9c1..6f2a128d5 100644 --- a/packages/typescript/ai-gemini/package.json +++ b/packages/typescript/ai-gemini/package.json @@ -39,15 +39,17 @@ "tanstack", "adapter" ], - "dependencies": { - "@google/genai": "^1.43.0" - }, "peerDependencies": { - "@tanstack/ai": "workspace:^" + "@tanstack/ai": "workspace:^", + "@tanstack/ai-client": "workspace:^" }, "devDependencies": { "@tanstack/ai": "workspace:*", + "@tanstack/ai-client": "workspace:*", "@vitest/coverage-v8": "4.0.14", - "vite": "^7.2.7" + "vite": "^7.3.1" + }, + "dependencies": { + "@google/genai": "^1.50.1" } } diff --git a/packages/typescript/ai-gemini/src/index.ts b/packages/typescript/ai-gemini/src/index.ts index 05c46547a..92f9a0975 100644 --- a/packages/typescript/ai-gemini/src/index.ts +++ b/packages/typescript/ai-gemini/src/index.ts @@ -82,3 +82,16 @@ export type { GeminiDocumentMetadata, GeminiMessageMetadataByModality, } from './message-types' + +// ============================================================================ +// Realtime (Voice) Adapters +// ============================================================================ + +export { geminiRealtime, geminiRealtimeToken } from './realtime/index' + +export type { + GeminiRealtimeModel, + GeminiRealtimeOptions, + GeminiRealtimeTokenOptions, + GeminiRealtimeVoice, +} from './realtime/index' \ No newline at end of file diff --git a/packages/typescript/ai-gemini/src/realtime/adapter.ts b/packages/typescript/ai-gemini/src/realtime/adapter.ts new file mode 100644 index 000000000..5572e3e34 --- /dev/null +++ b/packages/typescript/ai-gemini/src/realtime/adapter.ts @@ -0,0 +1,294 @@ +import { + createRealtimeEventEmitter, +} from "@tanstack/ai" +import { AudioPlayer, AudioStreamer, base64ToArrayBuffer } from './utils' +import { GeminiLiveClient } from './client' +import type { LiveResponse } from './client' +import type { + AudioVisualization, + RealtimeMessage, + RealtimeMode, + RealtimeToken, +} from '@tanstack/ai' +import type { AnyClientTool, RealtimeAdapter, RealtimeConnection } from '@tanstack/ai-client' +import type { GeminiRealtimeModel, GeminiRealtimeOptions } from './types' + +/** + * Creates a Gemini realtime adapter for client-side use. + * + * @param options - Optional configuration + * @returns A RealtimeAdapter for use with RealtimeClient + * + * @example + * ```typescript + * import { RealtimeClient } from '@tanstack/ai-client' + * import { geminiRealtime } from '@tanstack/ai-gemini' + * + * const client = new RealtimeClient({ + * getToken: () => fetch('/api/realtime-token').then(r => r.json()), + * adapter: geminiRealtime(), + * onGoAway: () => client.updateSession({ ... }) // Resume session with new config (available only for Gemini Live adapter) + * }) + * + * ``` + */ +export function geminiRealtime( + options: GeminiRealtimeOptions = {}, +): RealtimeAdapter { + return { + provider: 'gemini', + + connect( + token: RealtimeToken, + clientTools?: ReadonlyArray, + ): Promise { + return createWebSocketConnection(token, options.model, clientTools) + }, + } +} + +/** + * Creates a WebSocket connection to Gemini's realtime API + */ +async function createWebSocketConnection( + token: RealtimeToken, + model: GeminiRealtimeModel = 'gemini-3.1-flash-live-preview', + tools?: ReadonlyArray, +): Promise { + + const { emit, on: realtimeEventEmitterOn } = createRealtimeEventEmitter() + + // Current state + let currentMode: RealtimeMode = 'idle' + let currentMessageId: string | null = null + let messageIdCounter = 0 + + function generateMessageId(): string { + return `gemini-msg-${Date.now()}-${++messageIdCounter}` + } + + const client = new GeminiLiveClient(token.token, model, tools) + + let message: RealtimeMessage = { + id: '', + role: 'assistant', + timestamp: 0, + parts: [] + } + + let pendingAssistantResponse = '' + + client.onClose = () => { + emit('status_change', { status: 'idle' }) + emit('mode_change', { mode: 'idle' }) + } + + client.onError = (error) => { + emit('error', { error }) + emit('status_change', { status: 'error' }) + emit('mode_change', { mode: 'idle' }) + } + + client.onReceiveResponse = (response: LiveResponse) => { + switch (response.type) { + case 'text': + message.parts.push({ + type: 'text', + content: response.data, + }) + break; + case 'audio': + message.parts.push({ + type: 'audio', + transcript: response.data.transcript, + audioData: base64ToArrayBuffer(response.data.audioData) + }) + if (currentMode !== 'speaking') { + currentMode = 'speaking' + emit('mode_change', { mode: 'speaking' }) + } + audioPlayer.play(response.data.audioData) + break; + case 'go_away': + emit("go_away", { timeLeft: response.data.timeLeft }) + break; + case 'usage_metadata': + emit("usage", { + completionTokens: response.data.responseTokenCount ?? 0, + promptTokens: response.data.promptTokenCount ?? 0, + totalTokens: response.data.totalTokenCount ?? 0, + }) + break; + case 'input_transcription': + if (response.data.finished && currentMode !== 'thinking') { + currentMode = 'thinking' + emit('mode_change', { mode: 'thinking' }) + } + emit('transcript', { + isFinal: true, + transcript: response.data.text, + role: 'user', + }) + break; + case 'output_transcription': + pendingAssistantResponse += response.data.text + emit('transcript', { + isFinal: response.data.finished, + transcript: pendingAssistantResponse, + role: 'assistant', + }) + break; + case 'interrupted': + audioPlayer.interrupt() + currentMode = 'listening' + emit('mode_change', { mode: 'listening' }) + emit('interrupted', { messageId: currentMessageId ?? undefined }) + break; + case 'tool_call': + for (const tool of response.data.functionCalls || []) { + if (tool.id && tool.name) { + emit('tool_call', { + toolCallId: tool.id, + input: tool.args, + toolName: tool.name + }) + } + } + break; + case 'turn_complete': + currentMessageId = generateMessageId() + message.id = currentMessageId + message.timestamp = Date.now() + message.parts.push({ + type: "text", + content: pendingAssistantResponse + }) + emit('message_complete', { message }) + + pendingAssistantResponse = '' + message = { + id: '', + role: 'assistant', + timestamp: 0, + parts: [] + } + currentMode = 'listening' + emit('mode_change', { mode: 'listening' }) + break; + case 'setup_complete': + emit('status_change', { status: 'connected' }) + break; + case 'error': + emit('error', { + error: new Error(response.data) + }) + break; + } + } + + await client.connect() + + const audioStreamer = new AudioStreamer(client) + const audioPlayer = new AudioPlayer() + await audioPlayer.init() + await audioStreamer.start() + + const connection: RealtimeConnection = { + async disconnect() { + audioStreamer.stop() + audioPlayer.destroy() + client.disconnect() + currentMode = 'idle' + emit('status_change', { status: 'idle' }) + }, + + async startAudioCapture() { + // Audio capture is established during connection setup + audioStreamer.startAudioCapture() + currentMode = 'listening' + emit('mode_change', { mode: 'listening' }) + }, + + stopAudioCapture() { + audioStreamer.stopAudioCapture() + currentMode = 'idle' + emit('mode_change', { mode: 'idle' }) + }, + + sendText(text: string) { + client.sendTextMessage(text) + currentMode = 'thinking' + emit('mode_change', { mode: 'thinking' }) + }, + + sendImage(imageData: string, mimeType: string) { + client.sendImageMessage(imageData, mimeType) + currentMode = 'thinking' + emit('mode_change', { mode: 'thinking' }) + }, + + sendToolResult(callId: string, result: string) { + client.sendToolResponse([{ + id: callId, + response: { + result + } + }]) + }, + + updateSession(config) { + client.updateSession(config) + emit('status_change', { status: 'reconnecting' }) + }, + + updateToken(token) { + client.updateToken(token) + emit('status_change', { status: 'reconnecting' }) + }, + + interrupt() { + audioPlayer.interrupt() + currentMode = 'listening' + emit('mode_change', { mode: 'listening' }) + emit('interrupted', { messageId: currentMessageId ?? undefined }) + }, + on: realtimeEventEmitterOn, + getAudioVisualization(): AudioVisualization { + return { + get inputLevel() { + return audioStreamer.inputLevel + }, + + get outputLevel() { + return audioPlayer.outputLevel + }, + + getInputFrequencyData() { + return audioStreamer.inputFrequencyData + }, + + getOutputFrequencyData() { + return audioPlayer.outputFrequencyData + }, + + getInputTimeDomainData() { + return audioStreamer.inputTimeDomainData + }, + + getOutputTimeDomainData() { + return audioPlayer.outputTimeDomainData + }, + + get inputSampleRate() { + return audioStreamer.inputSampleRate + }, + + get outputSampleRate() { + return audioPlayer.outputSampleRate + }, + } + }, + } + + return connection; +} diff --git a/packages/typescript/ai-gemini/src/realtime/client.ts b/packages/typescript/ai-gemini/src/realtime/client.ts new file mode 100644 index 000000000..be8653a5a --- /dev/null +++ b/packages/typescript/ai-gemini/src/realtime/client.ts @@ -0,0 +1,480 @@ +import { convertSchemaToJsonSchema } from "@tanstack/ai"; +import { ActivityHandling, EndSensitivity, Modality, StartSensitivity, TurnCoverage } from "@google/genai"; +import type { ContextWindowCompressionConfig, FunctionDeclaration, FunctionResponse, LiveClientMessage, LiveServerGoAway, LiveServerMessage, LiveServerSessionResumptionUpdate, LiveServerToolCall, ThinkingConfig, UsageMetadata } from "@google/genai"; +import type { AnyClientTool, RealtimeSessionConfig, RealtimeToken } from "@tanstack/ai"; +import type { GeminiRealtimeModel, GeminiRealtimeVoice } from "./types"; + +interface LiveResponsePayloads { + text: string + thought: string + audio: { audioData: string, transcript: string } + setup_complete: string + interrupted: string + turn_complete: string + tool_call: LiveServerToolCall + session_resumption_update: LiveServerSessionResumptionUpdate + go_away: LiveServerGoAway + usage_metadata: UsageMetadata + error: string + input_transcription: { text: string, finished: boolean } + output_transcription: { text: string, finished: boolean } +} + +export type MultimodalLiveResponseType = keyof LiveResponsePayloads + +export type LiveResponse = { + [K in MultimodalLiveResponseType]: { + type: K, + data: LiveResponsePayloads[K], + endOfTurn: boolean, + } +}[MultimodalLiveResponseType] + +/** + * Parses response messages from the Gemini Live API + */ +/** + * Parses ALL response types from a single server message. + * The server can now bundle multiple fields (e.g. audio + transcription) + * in the same message. Returns an array of response objects. + */ +function parseResponseMessages(data: LiveServerMessage) { + const responses: Array = []; + const serverContent = data.serverContent; + const parts = serverContent?.modelTurn?.parts; + + try { + // Setup complete (exclusive β€” no other fields expected) + if (data.setupComplete) { + console.log("🏁 SETUP COMPLETE response", data); + responses.push({ type: "setup_complete", data: "", endOfTurn: false }); + return responses; + } + + // Tool call (exclusive) + if (data.toolCall) { + console.log("🎯 πŸ› οΈ TOOL CALL response", data.toolCall); + responses.push({ type: "tool_call", data: data.toolCall, endOfTurn: false }); + return responses; + } + + if (data.sessionResumptionUpdate) { + responses.push({ type: "session_resumption_update", data: data.sessionResumptionUpdate, endOfTurn: false }) + } + + if (data.goAway) { + responses.push({ type: "go_away", data: data.goAway, endOfTurn: false }) + } + + if (data.usageMetadata) { + responses.push({ type: "usage_metadata", data: data.usageMetadata, endOfTurn: false }) + } + + // Audio data from model turn parts + if (parts?.length) { + for (const part of parts) { + if (part.inlineData?.data) { + responses.push({ + type: "audio", + data: { + audioData: part.inlineData.data, + // The transcription is independent to the model turn which means it doesn’t imply any ordering between transcription and model turn. + transcript: "", + }, + endOfTurn: false + }); + } else if (part.text) { + if (part.thought) { + console.log("πŸ’¬ THOUGHT response", part.text); + responses.push({ type: "thought", data: part.text, endOfTurn: false }); + } else { + console.log("πŸ’¬ TEXT response", part.text); + responses.push({ type: "text", data: part.text, endOfTurn: false }); + } + } + } + } + + // Transcriptions β€” checked independently, NOT in else-if with audio + if (serverContent?.inputTranscription) { + responses.push({ + type: "input_transcription", + data: { + text: serverContent.inputTranscription.text || "", + finished: serverContent.inputTranscription.finished || false, + }, + endOfTurn: false, + }); + } + + if (serverContent?.outputTranscription) { + responses.push({ + type: "output_transcription", + data: { + text: serverContent.outputTranscription.text || "", + finished: serverContent.outputTranscription.finished || false, + }, + endOfTurn: false, + }); + } + + // Interrupted + if (serverContent?.interrupted) { + console.log("πŸ—£οΈ INTERRUPTED response"); + responses.push({ type: "interrupted", data: "", endOfTurn: false }); + } + + // Turn complete + if (serverContent?.turnComplete) { + console.log("🏁 TURN COMPLETE response"); + responses.push({ type: "turn_complete", data: "", endOfTurn: true }); + } + } catch (err) { + console.log("⚠️ Error parsing response data: ", err, data); + } + + return responses; +} + +export class GeminiLiveClient { + + private token: string | null = null + private model: GeminiRealtimeModel | null = null + + private responseModalities: Array = [Modality.AUDIO]; + private systemInstructions = ""; + private googleGrounding = false; + private voiceName: GeminiRealtimeVoice = "Puck"; + private temperature = 1.0; + private inputAudioTranscription = false; + private outputAudioTranscription = false; + private contextWindowCompression: ContextWindowCompressionConfig | undefined; + private proactiveAudio = false; + private enableAffectiveDialog = false; + private thinkingConfig: ThinkingConfig | undefined + private speechLanguageCode: string | undefined + + private maxOutputTokens: number | undefined; + private functions: Array = []; + private functionsMap = new Map(); + + private automaticActivityDetection = { + disabled: false, + silence_duration_ms: 2000, + prefix_padding_ms: 500, + end_of_speech_sensitivity: EndSensitivity.END_SENSITIVITY_UNSPECIFIED, + start_of_speech_sensitivity: StartSensitivity.START_SENSITIVITY_UNSPECIFIED, + }; + + private activityHandling = ActivityHandling.ACTIVITY_HANDLING_UNSPECIFIED; + + private webSocket: WebSocket | null = null + private lastResumptionUpdate: LiveServerSessionResumptionUpdate | null = null + private setupComplete = false + private connected = false + + public onReceiveResponse: (response: LiveResponse) => void = () => { } + public onOpen: () => void = () => { } + public onClose: () => void = () => { } + public onError: (error: Error) => void = () => { } + + constructor(token: string, model: GeminiRealtimeModel, tools?: ReadonlyArray ) { + this.token = token + this.model = model + + if (tools) { + tools.forEach(tool => { + this.functions.push(tool) + this.functionsMap.set(tool.name, tool) + }) + } + } + + get isConnected() { + return this.connected + } + + get isSetupCompelete() { + return this.setupComplete + } + + /** + * Connection management + */ + connect() { + const promise = new Promise((resolve, reject) => { + this.webSocket = new WebSocket(`wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContentConstrained?access_token=${this.token}`) + + this.webSocket.onclose = (event) => { + console.log('realtime websocket close:', event) + this.connected = false + this.setupComplete = false; + this.onClose() + reject(new Error("Closed before connecting")) + } + + this.webSocket.onerror = (event) => { + console.error('realtime websocket error:', event) + this.connected = false + this.setupComplete = false; + const error = new Error('Connection error') + this.onError(error) + reject(error) + } + + this.webSocket.onopen = (event) => { + console.log('realtime websocket open:', event) + this.connected = true + this.onOpen() + resolve(this.webSocket) + } + + this.webSocket.onmessage = this.onReceiveMessage.bind(this) + }) + + return promise + } + + disconnect() { + if (this.webSocket) { + this.webSocket.close(); + this.connected = false; + this.setupComplete = false; + } + } + + /** + * Session management + */ + getFunctionDefinitions(): Array { + return this.functions.map(f => ({ + name: f.name, + description: f.description, + parametersJsonSchema: convertSchemaToJsonSchema(f.inputSchema), + outputJsonSchema: convertSchemaToJsonSchema(f.outputSchema), + })) + } + + sendInitialSetupMessage(resume = false) { + const tools = this.getFunctionDefinitions() + + const sessionSetupMessage: LiveClientMessage = { + setup: { + model: `models/${this.model}`, + generationConfig: { + responseModalities: this.responseModalities, + temperature: this.temperature, + speechConfig: { + languageCode: this.speechLanguageCode, + voiceConfig: { + prebuiltVoiceConfig: { + voiceName: this.voiceName + } + } + }, + enableAffectiveDialog: this.enableAffectiveDialog, + maxOutputTokens: this.maxOutputTokens, + thinkingConfig: this.thinkingConfig + }, + sessionResumption: { + transparent: true, + handle: resume ? this.lastResumptionUpdate?.newHandle : undefined + }, + contextWindowCompression: this.contextWindowCompression, + proactivity: { + proactiveAudio: this.proactiveAudio + }, + systemInstruction: { parts: [{ text: this.systemInstructions }] }, + tools: [{ functionDeclarations: tools }], + realtimeInputConfig: { + automaticActivityDetection: { + disabled: this.automaticActivityDetection.disabled, + silenceDurationMs: this.automaticActivityDetection.silence_duration_ms, + prefixPaddingMs: this.automaticActivityDetection.prefix_padding_ms, + endOfSpeechSensitivity: this.automaticActivityDetection.end_of_speech_sensitivity, + startOfSpeechSensitivity: this.automaticActivityDetection.start_of_speech_sensitivity, + }, + activityHandling: this.activityHandling, + turnCoverage: TurnCoverage.TURN_INCLUDES_ONLY_ACTIVITY, + }, + } + } + + if (this.inputAudioTranscription) { + sessionSetupMessage.setup!.inputAudioTranscription = {} + } + + if (this.outputAudioTranscription) { + sessionSetupMessage.setup!.outputAudioTranscription = {} + } + + if (this.googleGrounding) { + // Currently can't have both Google Search with custom tools. + console.warn( + "Google Grounding enabled, removing custom function calls if any." + ); + sessionSetupMessage.setup!.tools = [{ googleSearch: {} }]; + } + + console.log("FINAL SETUP JSON:", JSON.stringify(sessionSetupMessage, null, 2)); + this.sendMessage(sessionSetupMessage) + } + + async restartSession(resume = false) { + console.log("RESTARTING SESSION") + this.disconnect() + await this.connect() + this.sendInitialSetupMessage(resume) + } + + updateToken(token: RealtimeToken) { + console.log("UPDATING TOKEN") + this.token = token.token + + if (token.config.model && this.model != token.config.model) { + this.model = token.config.model as GeminiRealtimeModel + this.restartSession() // Restart session completely with new model + } else { + this.restartSession(true) + } + } + + async updateSession(config: Partial) { + // model can only be set during initial setup + if (config.model && !this.setupComplete) { + this.model = config.model as GeminiRealtimeModel + } + + if (config.instructions) { + this.systemInstructions = config.instructions + } + + if (config.tools) { + this.functions = config.tools as Array + this.functionsMap.clear() + config.tools.forEach(tool => { + this.functionsMap.set(tool.name, tool as any) + }) + } + + if (config.maxOutputTokens) { + this.maxOutputTokens = typeof config.maxOutputTokens === 'number' ? config.maxOutputTokens : undefined + } + + if (config.temperature) { + this.temperature = config.temperature + } + + if (config.voice) { + this.voiceName = config.voice as GeminiRealtimeVoice + } + + if (config.modelOptions?.googleGrounding) { + this.googleGrounding = config.modelOptions.googleGrounding + } + + if (config.modelOptions?.proactivity) { + this.proactiveAudio = config.modelOptions.proactivity + } + + if (config.modelOptions?.enableAffectiveDialog) { + this.enableAffectiveDialog = config.modelOptions.enableAffectiveDialog + } + + if (config.modelOptions?.contextWindowCompression) { + this.contextWindowCompression = config.modelOptions.contextWindowCompression + } + + if (config.modelOptions?.thinkingConfig) { + this.thinkingConfig = config.modelOptions.thinkingConfig + } + + if (config.modelOptions?.languageCode) { + this.speechLanguageCode = config.modelOptions.languageCode + } + + const includeTranscription = config.outputModalities?.includes("text") || false + this.inputAudioTranscription = includeTranscription + this.outputAudioTranscription = includeTranscription + + if (!this.setupComplete) { + this.sendInitialSetupMessage() + } else { + return this.restartSession(true) + } + } + + /** + * Message transmission & receiving + */ + sendMessage(message: LiveClientMessage) { + if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) { + // TODO: add message buffering + this.webSocket.send(JSON.stringify(message)); + } + } + + async onReceiveMessage(messageEvent: MessageEvent) { + let jsonData; + if (messageEvent.data instanceof Blob) { + jsonData = await messageEvent.data.text(); + } else if (messageEvent.data instanceof ArrayBuffer) { + jsonData = new TextDecoder().decode(messageEvent.data); + } else { + jsonData = messageEvent.data; + } + + try { + const messageData = JSON.parse(jsonData); + // Parse all response types from this message (audio + transcription can coexist) + const responses = parseResponseMessages(messageData); + for (const response of responses) { + if (response.type === "session_resumption_update" && response.data.resumable) { + this.lastResumptionUpdate = response.data; + } + if (response.type === "setup_complete") { + this.setupComplete = true + } + this.onReceiveResponse(response); + } + } catch (err) { + console.error("Error parsing JSON message:", err, jsonData); + } + } + + sendRealtimeInputMessage(data: string, mimeType: string) { + const blob = { mimeType, data }; + + if (mimeType.startsWith("audio/")) { + this.sendMessage({ realtimeInput: { audio: blob } }) + } else if (mimeType.startsWith("image/") || mimeType.startsWith("video/")) { + this.sendMessage({ realtimeInput: { video: blob } }) + } + } + + sendAudioMessage(base64PCM: string) { + this.sendRealtimeInputMessage(base64PCM, "audio/pcm") + } + + sendImageMessage(base64: string, mimeType = 'image/jpeg') { + this.sendRealtimeInputMessage(base64, mimeType) + } + + sendTextMessage(text: string) { + const message: LiveClientMessage = { + realtimeInput: { + text + } + } + this.sendMessage(message) + } + + sendToolResponse(functionResponses: Array) { + const message: LiveClientMessage = { + toolResponse: { + functionResponses + } + } + this.sendMessage(message) + } +} \ No newline at end of file diff --git a/packages/typescript/ai-gemini/src/realtime/index.ts b/packages/typescript/ai-gemini/src/realtime/index.ts new file mode 100644 index 000000000..1291c083c --- /dev/null +++ b/packages/typescript/ai-gemini/src/realtime/index.ts @@ -0,0 +1,13 @@ +// Token adapter for server-side use +export { geminiRealtimeToken } from './token' + +// Client adapter for browser use +export { geminiRealtime } from './adapter' + +// Types +export type { + GeminiRealtimeModel, + GeminiRealtimeVoice, + GeminiRealtimeTokenOptions, + GeminiRealtimeOptions, +} from './types' diff --git a/packages/typescript/ai-gemini/src/realtime/token.ts b/packages/typescript/ai-gemini/src/realtime/token.ts new file mode 100644 index 000000000..ab5a49ca8 --- /dev/null +++ b/packages/typescript/ai-gemini/src/realtime/token.ts @@ -0,0 +1,69 @@ +import { GoogleGenAI } from '@google/genai' +import { getGeminiApiKeyFromEnv } from '../utils' +import type { RealtimeToken, RealtimeTokenAdapter } from '@tanstack/ai' +import type { GeminiRealtimeTokenOptions } from './types' + +/** + * Creates a Google Gemini realtime token adapter. + * + * This adapter generates ephemeral tokens for client-side WebSocket connections. + * + * @param options - Configuration options for the realtime session + * @returns A RealtimeTokenAdapter for use with realtimeToken() + * + * @example + * ```typescript + * import { realtimeToken } from '@tanstack/ai' + * import { geminiRealtimeToken } from '@tanstack/ai-gemini' + * + * const token = await realtimeToken({ + * adapter: geminiRealtimeToken({ + * // Optional: constraint model config by token + * liveConnectConstraints: { + * model: 'gemini-live-2.5-flash-native-audio', + * }, + * }), + * }) + * ``` + */ +export function geminiRealtimeToken( + options: GeminiRealtimeTokenOptions = {}, +): RealtimeTokenAdapter { + const apiKey = getGeminiApiKeyFromEnv() + + const client = new GoogleGenAI({ + apiKey, + }) + + // Defaults to 30 minutes + const expireTime = options.expiresAt ?? Date.now() + 30 * 60 * 1000 + + return { + provider: 'gemini', + async generateToken(): Promise { + const token = await client.authTokens.create({ + config: { + uses: options.uses ?? 1, + expireTime: new Date(expireTime).toISOString(), + liveConnectConstraints: options.liveConnectConstraints, + httpOptions: { + apiVersion: 'v1alpha', + }, + }, + }) + + if (!token.name) { + throw new Error('Gemini realtime token creation failed') + } + + return { + provider: 'gemini', + token: token.name, + expiresAt: expireTime, + config: { + model: options.liveConnectConstraints?.model, + }, + } + }, + } +} diff --git a/packages/typescript/ai-gemini/src/realtime/types.ts b/packages/typescript/ai-gemini/src/realtime/types.ts new file mode 100644 index 000000000..4911b1d00 --- /dev/null +++ b/packages/typescript/ai-gemini/src/realtime/types.ts @@ -0,0 +1,81 @@ +import type { ContextWindowCompressionConfig, LiveConnectConstraints, ProactivityConfig, ThinkingConfig } from "@google/genai"; + +/** + * Gemini realtime voice options + */ +export type GeminiRealtimeVoice = + | "Achernar" + | "Achird" + | "Algenib" + | "Algieba" + | "Alnilam" + | "Aoede" + | "Autonoe" + | "Callirrhoe" + | "Charon" + | "Despina" + | "Enceladus" + | "Erinome" + | "Fenrir" + | "Gacrux" + | "Iapetus" + | "Kore" + | "Laomedeia" + | "Leda" + | "Orus" + | "Pulcherrima" + | "Puck" + | "Rasalgethi" + | "Sadachbia" + | "Sadaltager" + | "Schedar" + | "Sulafat" + | "Umbriel" + | "Vindemiatrix" + | "Zephyr" + | "Zubenelgenubi"; + +/** + * Gemini realtime model options + */ +export type GeminiRealtimeModel = + | 'gemini-3.1-flash-live-preview' + | 'gemini-2.5-flash-native-audio-preview-12-2025' + +/** + * Options for the Gemini realtime client adapter + */ +export interface GeminiRealtimeOptions { + /** Connection mode (default: 'websocket' in browser) */ + connectionMode?: 'websocket' + model?: GeminiRealtimeModel +} + +export interface StrictLiveConnectionConstraints extends Omit { + model?: GeminiRealtimeModel +} + +/** + * Options for the Gemini realtime token adapter + */ +export interface GeminiRealtimeTokenOptions { + expiresAt?: number + uses?: number + /** + * Config for LiveConnectConstraints for Auth Token creation. + * + * NOTE: Adding liveConnectConstraints will cause the API to ignore any config passed later to WebSocket. + */ + liveConnectConstraints?: StrictLiveConnectionConstraints +} + +/** + * Gemini Realtime provider options + */ +export interface GeminiRealtimeProviderOptions { + languageCode?: string + contextWindowCompression?: ContextWindowCompressionConfig + proactivity?: ProactivityConfig + enableAffectiveDialog?: boolean, + thinkingConfig?: ThinkingConfig +} \ No newline at end of file diff --git a/packages/typescript/ai-gemini/src/realtime/utils.ts b/packages/typescript/ai-gemini/src/realtime/utils.ts new file mode 100644 index 000000000..a2824e49a --- /dev/null +++ b/packages/typescript/ai-gemini/src/realtime/utils.ts @@ -0,0 +1,450 @@ +import type { GeminiLiveClient } from "./client" + +/** + * Audio Worklet Processor for capturing and processing audio + */ +const captureWorkletCode = ` +class AudioCaptureProcessor extends AudioWorkletProcessor { + constructor() { + super(); + this.bufferSize = 512; // 32ms at 16kHz β€” per Gemini best practices (20-40ms chunks) + this.buffer = new Float32Array(this.bufferSize); + this.bufferIndex = 0; + } + + process(inputs, outputs, parameters) { + const input = inputs[0]; + + if (input && input.length > 0) { + const inputChannel = input[0]; + + // Buffer the incoming audio + for (let i = 0; i < inputChannel.length; i++) { + this.buffer[this.bufferIndex++] = inputChannel[i]; + + // When buffer is full, send it to main thread + if (this.bufferIndex >= this.bufferSize) { + // Send the buffered audio to the main thread + this.port.postMessage({ + type: "audio", + data: this.buffer.slice(), + }); + + // Reset buffer + this.bufferIndex = 0; + } + } + } + + // Return true to keep the processor alive + return true; + } +} + +// Register the processor +registerProcessor("audio-capture-processor", AudioCaptureProcessor);` + +/** + * Audio Playback Worklet Processor for playing PCM audio. + * Uses an offset tracker instead of slice() to avoid allocations + * on the real-time audio thread. + */ +const playbackWorkletCode = ` +class PCMProcessor extends AudioWorkletProcessor { + constructor() { + super(); + this.audioQueue = []; + this.currentOffset = 0; // Track position in current buffer (avoids slice()) + + this.port.onmessage = (event) => { + if (event.data === "interrupt") { + // Clear the queue on interrupt + this.audioQueue = []; + this.currentOffset = 0; + } else if (event.data instanceof Float32Array) { + // Add audio data to the queue + this.audioQueue.push(event.data); + } + }; + } + + process(inputs, outputs, parameters) { + const output = outputs[0]; + if (output.length === 0) return true; + + const channel = output[0]; + let outputIndex = 0; + + // Fill the output buffer from the queue + while (outputIndex < channel.length && this.audioQueue.length > 0) { + const currentBuffer = this.audioQueue[0]; + + if (!currentBuffer || currentBuffer.length === 0) { + this.audioQueue.shift(); + this.currentOffset = 0; + continue; + } + + const remainingOutput = channel.length - outputIndex; + const remainingBuffer = currentBuffer.length - this.currentOffset; + const copyLength = Math.min(remainingOutput, remainingBuffer); + + // Copy audio data to output using offset (no slice allocation) + for (let i = 0; i < copyLength; i++) { + channel[outputIndex++] = currentBuffer[this.currentOffset++]; + } + + // If we've consumed the entire buffer, move to the next one + if (this.currentOffset >= currentBuffer.length) { + this.audioQueue.shift(); + this.currentOffset = 0; + } + } + + // Fill remaining output with silence + while (outputIndex < channel.length) { + channel[outputIndex++] = 0; + } + + return true; + } +} + +registerProcessor("pcm-processor", PCMProcessor);` + +function calculateLevel(analyser: AnalyserNode): number { + const data = new Uint8Array(analyser.fftSize) + analyser.getByteTimeDomainData(data) + + // Find peak deviation from center (128 is silence) + // This is more responsive than RMS for voice level meters + let maxDeviation = 0 + for (const sample of data) { + const deviation = Math.abs(sample - 128) + if (deviation > maxDeviation) { + maxDeviation = deviation + } + } + + // Normalize to 0-1 range (max deviation is 128) + // Scale by 1.5x so that ~66% amplitude reads as full scale + // This provides good visual feedback without pegging too early + const normalized = maxDeviation / 128 + return Math.min(1, normalized * 1.5) +} + +export function base64ToArrayBuffer(base64: string): ArrayBuffer { + const binary = atob(base64) + const bytes = Uint8Array.from(binary, char => char.charCodeAt(0)) + return bytes.buffer +} + +// Empty arrays for when visualization isn't available +// frequencyBinCount = fftSize / 2 = 1024 +const emptyFrequencyData = new Uint8Array(1024) +const emptyTimeDomainData = new Uint8Array(2048).fill(128) // 128 is silence + +export class AudioStreamer { + private audioContext: AudioContext | null = null + private audioWorklet: AudioWorkletNode | null = null + private mediaStream: MediaStream | null = null + private analyser: AnalyserNode | null = null + private isStreaming = false + private sampleRate = 16000 + private client: GeminiLiveClient | null = null + + constructor(client: GeminiLiveClient) { + this.client = client + } + + get inputLevel() { + if (!this.analyser) return 0 + return calculateLevel(this.analyser) + } + + get inputFrequencyData() { + if (!this.analyser) return emptyFrequencyData + const data = new Uint8Array(this.analyser.frequencyBinCount) + this.analyser.getByteFrequencyData(data) + return data + } + + get inputTimeDomainData() { + if (!this.analyser) return emptyTimeDomainData + const data = new Uint8Array(this.analyser.fftSize) + this.analyser.getByteTimeDomainData(data) + return data + } + + get inputSampleRate() { + return this.sampleRate + } + + async start() { + try { + const audioConstraints: MediaTrackConstraints = { + sampleRate: this.sampleRate, + echoCancellation: true, + noiseSuppression: true, + autoGainControl: true, + } + + // Get microphone access + this.mediaStream = await navigator.mediaDevices.getUserMedia({ + audio: audioConstraints + }) + + // Check if native AGC is active + const track = this.mediaStream.getAudioTracks()[0]; + const settings = track?.getSettings(); + + if (settings?.autoGainControl) { + console.warn("Native AGC not supported.") + } + + // Create audio context + this.audioContext = new AudioContext({ + sampleRate: this.sampleRate + }) + + if (this.audioContext.state === 'suspended') { + await this.audioContext.resume().catch(() => { }) + } + + const workletBlob = new Blob([captureWorkletCode], { type: 'application/javascript' }) + const workletUrl = URL.createObjectURL(workletBlob) + + // Load the audio worklet module + await this.audioContext.audioWorklet.addModule(workletUrl) + + // Create the audio worklet node + this.audioWorklet = new AudioWorkletNode( + this.audioContext, + "audio-capture-processor" + ) + + // Set up message handling from the worklet + this.audioWorklet.port.onmessage = (event) => { + if (!this.isStreaming) return; + + if (event.data.type === "audio") { + const inputData = event.data.data; + const pcmData = this.convertToPCM16(inputData); + const base64Audio = this.arrayBufferToBase64(pcmData); + + // Send to Gemini only if after setup complete + if (this.client?.isSetupCompelete) { + this.client.sendAudioMessage(base64Audio); + } + } + }; + + // Create analyser for volume detection + this.analyser = this.audioContext.createAnalyser(); + this.analyser.fftSize = 2048 // Larger size for more accurate level detection + this.analyser.smoothingTimeConstant = 0.3 + + // Connect the audio graph + const source = this.audioContext.createMediaStreamSource( + this.mediaStream + ); + source.connect(this.analyser); + this.analyser.connect(this.audioWorklet); + + // Start streaming + this.isStreaming = true + console.log("Audio streaming started"); + } catch (error) { + console.error("Failed to start audio streaming:", error); + throw error; + } + } + + stop() { + this.isStreaming = false; + + if (this.audioWorklet) { + this.audioWorklet.disconnect(); + this.audioWorklet.port.close(); + this.audioWorklet = null; + } + + if (this.audioContext) { + this.audioContext.close(); + this.audioContext = null; + } + + if (this.mediaStream) { + this.mediaStream.getTracks().forEach((track) => track.stop()); + this.mediaStream = null; + } + + console.log("Audio streaming stopped"); + } + + startAudioCapture() { + if (this.mediaStream) { + for (const track of this.mediaStream.getAudioTracks()) { + track.enabled = true + } + } + this.isStreaming = true + } + + stopAudioCapture() { + if (this.mediaStream) { + // Disable tracks rather than stopping them to allow re-enabling + for (const track of this.mediaStream.getAudioTracks()) { + track.enabled = false + } + } + this.isStreaming = false + } + + private convertToPCM16(float32Array: Float32Array): ArrayBuffer { + const int16Array = new Int16Array(float32Array.length); + for (let i = 0; i < float32Array.length; i++) { + const sample = Math.max(-1, Math.min(1, float32Array[i]!)); + int16Array[i] = sample * 0x7fff; + } + return int16Array.buffer; + } + + private arrayBufferToBase64(buffer: ArrayBuffer): string { + const bytes = new Uint8Array(buffer) + const binary = String.fromCharCode(...bytes) + return btoa(binary) + } +} + +export class AudioPlayer { + private audioContext: AudioContext | null = null + private workletNode: AudioWorkletNode | null = null + private gainNode: GainNode | null = null + private analyser: AnalyserNode | null = null + private isInitialized = false + private volume = 1.0 + private sampleRate = 24000 + + get outputLevel() { + if (!this.analyser) return 0 + return calculateLevel(this.analyser) + } + + get outputFrequencyData() { + if (!this.analyser) return emptyFrequencyData + const data = new Uint8Array(this.analyser.frequencyBinCount) + this.analyser.getByteFrequencyData(data) + return data + } + + get outputTimeDomainData() { + if (!this.analyser) return emptyTimeDomainData + const data = new Uint8Array(this.analyser.fftSize) + this.analyser.getByteTimeDomainData(data) + return data + } + + get outputSampleRate() { + return this.sampleRate + } + + async init() { + if (this.isInitialized) return; + + try { + // Create audio context at 24kHz to match Gemini + this.audioContext = new AudioContext({ + sampleRate: this.sampleRate, + }); + + const workletBlob = new Blob([playbackWorkletCode], { type: 'application/javascript' }) + const workletUrl = URL.createObjectURL(workletBlob) + + // Load the audio worklet module + await this.audioContext.audioWorklet.addModule(workletUrl) + + // Create worklet node + this.workletNode = new AudioWorkletNode( + this.audioContext, + "pcm-processor" + ) + + // Create gain node for volume control + this.gainNode = this.audioContext.createGain(); + this.gainNode.gain.value = this.volume; + + // Create analyser for volume detection + this.analyser = this.audioContext.createAnalyser() + this.analyser.fftSize = 2048 // Larger size for more accurate level detection + this.analyser.smoothingTimeConstant = 0.3 + + // Connect nodes + this.workletNode.connect(this.gainNode); + this.gainNode.connect(this.analyser); + this.analyser.connect(this.audioContext.destination); + + this.isInitialized = true; + console.log("Audio player initialized"); + } catch (error) { + console.error("Failed to initialize audio player:", error); + throw error; + } + } + + async play(base64Audio: string) { + if (!this.isInitialized) { + await this.init(); + } + + try { + // Resume audio context if suspended + if (this.audioContext?.state === "suspended") { + await this.audioContext.resume(); + } + + // Efficient base64 β†’ binary decode + const binaryString = atob(base64Audio); + const len = binaryString.length; + const bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + + // Convert PCM16 LE to Float32 + const inputArray = new Int16Array(bytes.buffer); + const float32Data = new Float32Array(inputArray.length); + for (let i = 0; i < inputArray.length; i++) { + float32Data[i] = inputArray[i]! / 32768; + } + + // Send to worklet for playback + this.workletNode?.port.postMessage(float32Data); + } catch (error) { + console.error("Error playing audio chunk:", error); + throw error; + } + } + + /* Interrupt playback */ + interrupt() { + if (this.workletNode) { + this.workletNode.port.postMessage("interrupt"); + } + } + + setVolume(volume: number) { + this.volume = Math.max(0, Math.min(1, volume)); + if (this.gainNode) { + this.gainNode.gain.value = this.volume; + } + } + + destroy() { + if (this.audioContext) { + this.audioContext.close(); + this.audioContext = null; + } + this.isInitialized = false; + } +} \ No newline at end of file diff --git a/packages/typescript/ai-openai/src/realtime/adapter.ts b/packages/typescript/ai-openai/src/realtime/adapter.ts index 35187a5d2..7924f1e18 100644 --- a/packages/typescript/ai-openai/src/realtime/adapter.ts +++ b/packages/typescript/ai-openai/src/realtime/adapter.ts @@ -1,13 +1,12 @@ +import { createRealtimeEventEmitter } from '@tanstack/ai' import type { AnyClientTool, AudioVisualization, - RealtimeEvent, - RealtimeEventHandler, RealtimeMessage, RealtimeMode, RealtimeSessionConfig, RealtimeStatus, - RealtimeToken, + RealtimeToken } from '@tanstack/ai' import type { RealtimeAdapter, RealtimeConnection } from '@tanstack/ai-client' import type { OpenAIRealtimeOptions } from './types' @@ -60,7 +59,7 @@ async function createWebRTCConnection( token: RealtimeToken, ): Promise { const model = token.config.model ?? 'gpt-4o-realtime-preview' - const eventHandlers = new Map>>() + const { emit, on: realtimeEventEmitterOn } = createRealtimeEventEmitter() // WebRTC peer connection const pc = new RTCPeerConnection() @@ -88,19 +87,6 @@ async function createWebRTCConnection( const emptyFrequencyData = new Uint8Array(1024) const emptyTimeDomainData = new Uint8Array(2048).fill(128) // 128 is silence - // Helper to emit events (defined early so it can be used during setup) - function emit( - event: TEvent, - payload: Parameters>[0], - ) { - const handlers = eventHandlers.get(event) - if (handlers) { - for (const handler of handlers) { - handler(payload) - } - } - } - // Set up data channel for bidirectional communication dataChannel = pc.createDataChannel('oai-events') @@ -489,9 +475,9 @@ async function createWebRTCConnection( const imageContent = isUrl ? { type: 'input_image', image_url: imageData } : { - type: 'input_image', - image_url: `data:${mimeType};base64,${imageData}`, - } + type: 'input_image', + image_url: `data:${mimeType};base64,${imageData}`, + } sendEvent({ type: 'conversation.item.create', @@ -587,19 +573,7 @@ async function createWebRTCConnection( emit('interrupted', { messageId: currentMessageId ?? undefined }) }, - on( - event: TEvent, - handler: RealtimeEventHandler, - ): () => void { - if (!eventHandlers.has(event)) { - eventHandlers.set(event, new Set()) - } - eventHandlers.get(event)!.add(handler) - - return () => { - eventHandlers.get(event)?.delete(handler) - } - }, + on: realtimeEventEmitterOn, getAudioVisualization(): AudioVisualization { // Helper to calculate audio level from time domain data diff --git a/packages/typescript/ai-react/src/realtime-types.ts b/packages/typescript/ai-react/src/realtime-types.ts index bad512d29..e58150237 100644 --- a/packages/typescript/ai-react/src/realtime-types.ts +++ b/packages/typescript/ai-react/src/realtime-types.ts @@ -2,8 +2,10 @@ import type { AnyClientTool, RealtimeMessage, RealtimeMode, + RealtimeSessionConfig, RealtimeStatus, RealtimeToken, + UsageInfo, } from '@tanstack/ai' import type { RealtimeAdapter } from '@tanstack/ai-client' @@ -79,6 +81,9 @@ export interface UseRealtimeChatOptions { onMessage?: (message: RealtimeMessage) => void onModeChange?: (mode: RealtimeMode) => void onInterrupted?: () => void + onUsage?: (usage: UsageInfo) => void + onGoAway?: (timeLeft?: string) => void + onStatusChange?: (status: RealtimeStatus) => void } /** @@ -135,9 +140,6 @@ export interface UseRealtimeChatReturn { /** Get time domain data for output waveform */ getOutputTimeDomainData: () => Uint8Array - // VAD control - /** Current VAD mode */ - vadMode: 'server' | 'semantic' | 'manual' - /** Change VAD mode at runtime */ - setVADMode: (mode: 'server' | 'semantic' | 'manual') => void + // Session control + updateSession: (config: RealtimeSessionConfig) => void } diff --git a/packages/typescript/ai-react/src/use-realtime-chat.ts b/packages/typescript/ai-react/src/use-realtime-chat.ts index 63272821f..6f2dabf89 100644 --- a/packages/typescript/ai-react/src/use-realtime-chat.ts +++ b/packages/typescript/ai-react/src/use-realtime-chat.ts @@ -3,6 +3,7 @@ import { RealtimeClient } from '@tanstack/ai-client' import type { RealtimeMessage, RealtimeMode, + RealtimeSessionConfig, RealtimeStatus, } from '@tanstack/ai' import type { @@ -70,9 +71,6 @@ export function useRealtimeChat( const [error, setError] = useState(null) const [inputLevel, setInputLevel] = useState(0) const [outputLevel, setOutputLevel] = useState(0) - const [vadMode, setVADModeState] = useState<'server' | 'semantic' | 'manual'>( - options.vadMode ?? 'server', - ) // Refs const clientRef = useRef(null) @@ -107,6 +105,12 @@ export function useRealtimeChat( setMessages((prev) => [...prev, message]) optionsRef.current.onMessage?.(message) }, + onUsage(usage) { + optionsRef.current.onUsage?.(usage) + }, + onGoAway(timeLeft) { + optionsRef.current.onGoAway?.(timeLeft) + }, onError: (err) => { setError(err) optionsRef.current.onError?.(err) @@ -229,13 +233,10 @@ export function useRealtimeChat( ) }, []) - // VAD mode control - const setVADMode = useCallback( - (newMode: 'server' | 'semantic' | 'manual') => { - setVADModeState(newMode) - // TODO: Update session config if connected - }, - [], + const updateSession = useCallback( + (config: RealtimeSessionConfig) => { + clientRef.current?.updateSession(config) + }, [] ) return { @@ -270,8 +271,7 @@ export function useRealtimeChat( getInputTimeDomainData, getOutputTimeDomainData, - // VAD control - vadMode, - setVADMode, + // Session control + updateSession, } } diff --git a/packages/typescript/ai/src/index.ts b/packages/typescript/ai/src/index.ts index 0d1f7aeef..5b0b861dd 100644 --- a/packages/typescript/ai/src/index.ts +++ b/packages/typescript/ai/src/index.ts @@ -94,7 +94,7 @@ export * from './types' export { detectImageMimeType } from './utils' // Realtime -export { realtimeToken } from './realtime/index' +export { realtimeToken, createRealtimeEventEmitter } from './realtime/index' export type { RealtimeToken, RealtimeTokenAdapter, diff --git a/packages/typescript/ai/src/realtime/event-emitter.ts b/packages/typescript/ai/src/realtime/event-emitter.ts new file mode 100644 index 000000000..922cfb1e3 --- /dev/null +++ b/packages/typescript/ai/src/realtime/event-emitter.ts @@ -0,0 +1,32 @@ +import type { RealtimeEvent, RealtimeEventHandler } from "./types"; + +export function createRealtimeEventEmitter() { + const eventHandlers = new Map>>() + + return { + emit( + event: TEvent, + payload: Parameters>[0], + ) { + const handlers = eventHandlers.get(event) + if (handlers) { + for (const handler of handlers) { + handler(payload) + } + } + }, + on( + event: TEvent, + handler: RealtimeEventHandler, + ): () => void { + if (!eventHandlers.has(event)) { + eventHandlers.set(event, new Set()) + } + eventHandlers.get(event)!.add(handler) + + return () => { + eventHandlers.get(event)!.delete(handler) + } + } + } +} \ No newline at end of file diff --git a/packages/typescript/ai/src/realtime/index.ts b/packages/typescript/ai/src/realtime/index.ts index 74c450c1d..ea5ab41d1 100644 --- a/packages/typescript/ai/src/realtime/index.ts +++ b/packages/typescript/ai/src/realtime/index.ts @@ -1,5 +1,7 @@ import type { RealtimeToken, RealtimeTokenOptions } from './types' +export { createRealtimeEventEmitter } from './event-emitter' + // Re-export all types export * from './types' diff --git a/packages/typescript/ai/src/realtime/types.ts b/packages/typescript/ai/src/realtime/types.ts index daaf6f57c..0cffbdc89 100644 --- a/packages/typescript/ai/src/realtime/types.ts +++ b/packages/typescript/ai/src/realtime/types.ts @@ -2,6 +2,8 @@ // Token Types // ============================================================================ +import type { UsageInfo } from "../activities/chat/middleware" + /** * Voice activity detection configuration */ @@ -22,6 +24,7 @@ export interface RealtimeToolConfig { name: string description: string inputSchema?: Record + outputSchema?: Record } /** @@ -49,7 +52,7 @@ export interface RealtimeSessionConfig { /** Eagerness level for semantic VAD ('low', 'medium', 'high') */ semanticEagerness?: 'low' | 'medium' | 'high' /** Provider-specific options */ - providerOptions?: Record + modelOptions?: Record } /** @@ -244,6 +247,8 @@ export type RealtimeEvent = | 'message_complete' | 'interrupted' | 'error' + | 'go_away' // Event that signals that the current connection will soon be terminated + | 'usage' /** * Event payloads for realtime events @@ -261,6 +266,8 @@ export interface RealtimeEventPayloads { message_complete: { message: RealtimeMessage } interrupted: { messageId?: string } error: { error: Error } + go_away: { timeLeft?: string } + usage: UsageInfo } /** diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37caa9ab7..36d7f76c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,7 +33,7 @@ importers: version: 0.3.1(typescript@5.9.3) '@tanstack/vite-config': specifier: 0.4.1 - version: 0.4.1(@types/node@24.10.3)(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 0.4.1(@types/node@24.10.3)(rollup@4.60.2)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@types/node': specifier: ^24.10.1 version: 24.10.3 @@ -84,7 +84,7 @@ importers: version: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitest: specifier: ^4.0.14 - version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) examples/php-slim: devDependencies: @@ -178,7 +178,7 @@ importers: version: 5.1.2(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) typescript: specifier: 5.9.3 version: 5.9.3 @@ -187,7 +187,7 @@ importers: version: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitest: specifier: ^4.0.14 - version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -323,7 +323,7 @@ importers: version: 5.1.2(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) typescript: specifier: 5.9.3 version: 5.9.3 @@ -332,7 +332,7 @@ importers: version: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitest: specifier: ^4.0.14 - version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -365,7 +365,7 @@ importers: version: 0.561.0(react@19.2.3) nitro: specifier: 3.0.1-alpha.2 - version: 3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.0.0-beta.53)(rollup@4.57.1)(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.0.0-beta.53)(rollup@4.60.2)(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) react: specifier: ^19.2.3 version: 19.2.3 @@ -450,7 +450,7 @@ importers: version: 1.141.1(@tanstack/router-core@1.159.4)(@tanstack/solid-router@1.141.1(solid-js@1.9.10))(csstype@3.2.3)(solid-js@1.9.10) '@tanstack/solid-router-ssr-query': specifier: ^1.139.10 - version: 1.141.1(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.159.4)(@tanstack/solid-query@5.90.15(solid-js@1.9.10))(@tanstack/solid-router@1.141.1(solid-js@1.9.10))(eslint@9.39.2(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3) + version: 1.141.1(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.159.4)(@tanstack/solid-query@5.90.15(solid-js@1.9.10))(@tanstack/solid-router@1.141.1(solid-js@1.9.10))(eslint@9.39.4(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3) '@tanstack/solid-start': specifier: ^1.139.10 version: 1.141.1(@tanstack/react-router@1.159.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.4(srvx@0.11.2))(solid-js@1.9.10)(vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -499,7 +499,7 @@ importers: version: 24.10.3 jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) typescript: specifier: 5.9.3 version: 5.9.3 @@ -511,7 +511,7 @@ importers: version: 2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) vitest: specifier: ^4.0.14 - version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) web-vitals: specifier: ^5.1.0 version: 5.1.0 @@ -575,7 +575,7 @@ importers: version: 5.45.10 svelte-check: specifier: ^4.2.0 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.10)(typescript@5.9.3) + version: 4.3.4(picomatch@4.0.4)(svelte@5.45.10)(typescript@5.9.3) tailwindcss: specifier: ^4.1.18 version: 4.1.18 @@ -639,7 +639,7 @@ importers: version: 6.0.3(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) autoprefixer: specifier: ^10.4.21 - version: 10.4.22(postcss@8.5.6) + version: 10.4.22(postcss@8.5.10) concurrently: specifier: ^9.1.2 version: 9.2.1 @@ -673,7 +673,7 @@ importers: devDependencies: vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai: dependencies: @@ -689,7 +689,7 @@ importers: version: 1.1.0 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) zod: specifier: ^4.2.0 version: 4.2.1 @@ -705,7 +705,7 @@ importers: version: link:../ai '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) zod: specifier: ^4.2.0 version: 4.2.1 @@ -721,10 +721,10 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) zod: specifier: ^4.2.0 version: 4.2.1 @@ -752,22 +752,22 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) tsup: specifier: ^8.5.1 - version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.0.1))(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.5.0))(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) tsup-preset-solid: specifier: ^2.2.0 - version: 2.2.0(esbuild@0.27.3)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.0.1))(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)) + version: 2.2.0(esbuild@0.27.3)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.5.0))(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-plugin-solid: specifier: ^2.11.10 - version: 2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) packages/typescript/ai-elevenlabs: dependencies: @@ -783,7 +783,7 @@ importers: version: link:../ai-client '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) packages/typescript/ai-event-client: dependencies: @@ -796,7 +796,7 @@ importers: version: link:../ai '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) packages/typescript/ai-fal: dependencies: @@ -809,26 +809,29 @@ importers: version: link:../ai '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-gemini: dependencies: '@google/genai': - specifier: ^1.43.0 - version: 1.43.0 + specifier: ^1.50.1 + version: 1.50.1 devDependencies: '@tanstack/ai': specifier: workspace:* version: link:../ai + '@tanstack/ai-client': + specifier: workspace:* + version: link:../ai-client '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: - specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + specifier: ^7.3.1 + version: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-grok: dependencies: @@ -837,17 +840,17 @@ importers: version: link:../ai openai: specifier: ^6.9.1 - version: 6.10.0(ws@8.18.3)(zod@4.2.1) + version: 6.10.0(ws@8.20.0)(zod@4.2.1) zod: specifier: ^4.0.0 version: 4.2.1 devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-groq: dependencies: @@ -863,10 +866,10 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-ollama: dependencies: @@ -879,16 +882,16 @@ importers: version: link:../ai '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-openai: dependencies: openai: specifier: ^6.9.1 - version: 6.10.0(ws@8.18.3)(zod@4.2.1) + version: 6.10.0(ws@8.20.0)(zod@4.2.1) devDependencies: '@tanstack/ai': specifier: workspace:* @@ -898,10 +901,10 @@ importers: version: link:../ai-client '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) zod: specifier: ^4.2.0 version: 4.2.1 @@ -917,10 +920,10 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-preact: dependencies: @@ -936,16 +939,16 @@ importers: version: 3.2.4(preact@10.28.2) '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) preact: specifier: ^10.26.9 version: 10.28.2 vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-react: dependencies: @@ -964,16 +967,16 @@ importers: version: 19.2.7 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) react: specifier: ^19.2.3 version: 19.2.3 vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-react-ui: dependencies: @@ -1004,7 +1007,7 @@ importers: version: 19.2.7 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) react: specifier: ^19.2.3 version: 19.2.3 @@ -1013,7 +1016,7 @@ importers: version: 19.2.3(react@19.2.3) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-solid: dependencies: @@ -1032,10 +1035,10 @@ importers: version: 24.10.3 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) solid-js: specifier: ^1.9.10 version: 1.9.10 @@ -1047,7 +1050,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.14 - version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-solid-ui: dependencies: @@ -1075,13 +1078,13 @@ importers: version: link:../ai-solid '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) solid-js: specifier: ^1.9.10 version: 1.9.10 vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/ai-svelte: dependencies: @@ -1103,16 +1106,16 @@ importers: version: 24.10.3 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) svelte: specifier: ^5.20.0 version: 5.45.10 svelte-check: specifier: ^4.2.0 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.10)(typescript@5.9.3) + version: 4.3.4(picomatch@4.0.4)(svelte@5.45.10)(typescript@5.9.3) typescript: specifier: 5.9.3 version: 5.9.3 @@ -1134,13 +1137,13 @@ importers: version: 24.10.3 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vue/test-utils': specifier: ^2.4.6 version: 2.4.6 jsdom: specifier: ^27.2.0 - version: 27.3.0(postcss@8.5.6) + version: 27.3.0(postcss@8.5.10) tsdown: specifier: ^0.17.0-beta.6 version: 0.17.3(oxc-resolver@11.15.0)(publint@0.3.16)(typescript@5.9.3) @@ -1149,7 +1152,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.14 - version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vue: specifier: ^3.5.25 version: 3.5.25(typescript@5.9.3) @@ -1177,13 +1180,13 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: ^6.0.2 - version: 6.0.3(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) + version: 6.0.3(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3)) '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vue: specifier: ^3.5.25 version: 3.5.25(typescript@5.9.3) @@ -1205,10 +1208,10 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/react-ai-devtools: dependencies: @@ -1224,13 +1227,13 @@ importers: version: 19.2.7 '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) react: specifier: ^19.2.3 version: 19.2.3 vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages/typescript/smoke-tests: {} @@ -1278,7 +1281,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.14 - version: 4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) zod: specifier: ^4.2.0 version: 4.2.1 @@ -1364,16 +1367,16 @@ importers: devDependencies: '@vitest/coverage-v8': specifier: 4.0.14 - version: 4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.14(vitest@4.1.5) solid-js: specifier: ^1.9.10 version: 1.9.10 vite: specifier: ^7.2.7 - version: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-plugin-solid: specifier: ^2.11.10 - version: 2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) testing/panel: dependencies: @@ -1619,6 +1622,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-syntax-jsx@7.27.1': resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} engines: {node: '>=6.9.0'} @@ -1821,12 +1829,6 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.27.3': resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} @@ -1845,12 +1847,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} @@ -1869,12 +1865,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} @@ -1893,12 +1883,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} @@ -1917,12 +1901,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} @@ -1941,12 +1919,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} @@ -1965,12 +1937,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} @@ -1989,12 +1955,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} @@ -2013,12 +1973,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} @@ -2037,12 +1991,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} @@ -2061,12 +2009,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} @@ -2085,12 +2027,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} @@ -2109,12 +2045,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} @@ -2133,12 +2063,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} @@ -2157,12 +2081,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} @@ -2181,12 +2099,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} @@ -2205,12 +2117,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} @@ -2223,12 +2129,6 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} @@ -2247,12 +2147,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} @@ -2265,12 +2159,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} @@ -2289,12 +2177,6 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} @@ -2307,12 +2189,6 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} @@ -2331,12 +2207,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} @@ -2355,12 +2225,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} @@ -2379,12 +2243,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} @@ -2403,12 +2261,6 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -2435,6 +2287,10 @@ packages: resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.4.2': resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2447,12 +2303,16 @@ packages: resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.39.1': resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': @@ -2474,8 +2334,8 @@ packages: '@gerrit0/mini-shiki@3.19.0': resolution: {integrity: sha512-ZSlWfLvr8Nl0T4iA3FF/8VH8HivYF82xQts2DY0tJxZd4wtXJ8AA0nmdW9lmO4hlrh3f9xNwEPtOgqETPqKwDA==} - '@google/genai@1.43.0': - resolution: {integrity: sha512-hklCsJNdMlDM1IwcCVcGQFBg2izY0+t5BIGbRsxi2UnKi6AGKL7pqJqmBDNRbw0bYCs4y3NA7TB+fkKfP/Nrdw==} + '@google/genai@1.50.1': + resolution: {integrity: sha512-YbkX7H9+1Pt8wOt7DDREy8XSoiL6fRDzZQRyaVBarFf8MR3zHGqVdvM4cLbDXqPhxqvegZShgfxb8kw9C7YhAQ==} engines: {node: '>=20.0.0'} peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 @@ -2487,10 +2347,22 @@ packages: resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + '@humanfs/node@0.16.7': resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -3389,6 +3261,11 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.60.2': + resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm64@4.53.3': resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} cpu: [arm64] @@ -3399,6 +3276,11 @@ packages: cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.60.2': + resolution: {integrity: sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==} + cpu: [arm64] + os: [android] + '@rollup/rollup-darwin-arm64@4.53.3': resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} cpu: [arm64] @@ -3409,6 +3291,11 @@ packages: cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.60.2': + resolution: {integrity: sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.53.3': resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} cpu: [x64] @@ -3419,6 +3306,11 @@ packages: cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.60.2': + resolution: {integrity: sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-freebsd-arm64@4.53.3': resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} cpu: [arm64] @@ -3429,6 +3321,11 @@ packages: cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.60.2': + resolution: {integrity: sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.53.3': resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} cpu: [x64] @@ -3439,6 +3336,11 @@ packages: cpu: [x64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.60.2': + resolution: {integrity: sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} cpu: [arm] @@ -3449,6 +3351,11 @@ packages: cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + resolution: {integrity: sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.53.3': resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} cpu: [arm] @@ -3459,6 +3366,11 @@ packages: cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.60.2': + resolution: {integrity: sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.53.3': resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} cpu: [arm64] @@ -3469,6 +3381,11 @@ packages: cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.60.2': + resolution: {integrity: sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.53.3': resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} cpu: [arm64] @@ -3479,6 +3396,11 @@ packages: cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.60.2': + resolution: {integrity: sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-loong64-gnu@4.53.3': resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} cpu: [loong64] @@ -3489,11 +3411,21 @@ packages: cpu: [loong64] os: [linux] + '@rollup/rollup-linux-loong64-gnu@4.60.2': + resolution: {integrity: sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==} + cpu: [loong64] + os: [linux] + '@rollup/rollup-linux-loong64-musl@4.57.1': resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} cpu: [loong64] os: [linux] + '@rollup/rollup-linux-loong64-musl@4.60.2': + resolution: {integrity: sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==} + cpu: [loong64] + os: [linux] + '@rollup/rollup-linux-ppc64-gnu@4.53.3': resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} cpu: [ppc64] @@ -3504,11 +3436,21 @@ packages: cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-ppc64-gnu@4.60.2': + resolution: {integrity: sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-ppc64-musl@4.57.1': resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-ppc64-musl@4.60.2': + resolution: {integrity: sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.53.3': resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} cpu: [riscv64] @@ -3519,6 +3461,11 @@ packages: cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.60.2': + resolution: {integrity: sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.53.3': resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} cpu: [riscv64] @@ -3529,6 +3476,11 @@ packages: cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.60.2': + resolution: {integrity: sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.53.3': resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} cpu: [s390x] @@ -3539,6 +3491,11 @@ packages: cpu: [s390x] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.60.2': + resolution: {integrity: sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.53.3': resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} cpu: [x64] @@ -3549,6 +3506,11 @@ packages: cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.60.2': + resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.53.3': resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} cpu: [x64] @@ -3559,11 +3521,21 @@ packages: cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.60.2': + resolution: {integrity: sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==} + cpu: [x64] + os: [linux] + '@rollup/rollup-openbsd-x64@4.57.1': resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} cpu: [x64] os: [openbsd] + '@rollup/rollup-openbsd-x64@4.60.2': + resolution: {integrity: sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==} + cpu: [x64] + os: [openbsd] + '@rollup/rollup-openharmony-arm64@4.53.3': resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} cpu: [arm64] @@ -3574,6 +3546,11 @@ packages: cpu: [arm64] os: [openharmony] + '@rollup/rollup-openharmony-arm64@4.60.2': + resolution: {integrity: sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==} + cpu: [arm64] + os: [openharmony] + '@rollup/rollup-win32-arm64-msvc@4.53.3': resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} cpu: [arm64] @@ -3584,6 +3561,11 @@ packages: cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.60.2': + resolution: {integrity: sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.53.3': resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} cpu: [ia32] @@ -3594,6 +3576,11 @@ packages: cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.60.2': + resolution: {integrity: sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-x64-gnu@4.53.3': resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} cpu: [x64] @@ -3604,6 +3591,11 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-gnu@4.60.2': + resolution: {integrity: sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==} + cpu: [x64] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.53.3': resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} cpu: [x64] @@ -3614,6 +3606,11 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.60.2': + resolution: {integrity: sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==} + cpu: [x64] + os: [win32] + '@rushstack/node-core-library@5.7.0': resolution: {integrity: sha512-Ff9Cz/YlWu9ce4dmqNBZpA45AEya04XaBFIjV7xTVeEf+y/kTjEasmozqFELXlNG4ROdevss75JrrZ5WgufDkQ==} peerDependencies: @@ -4556,8 +4553,8 @@ packages: '@types/node@24.10.3': resolution: {integrity: sha512-gqkrWUsS8hcm0r44yn7/xZeV1ERva/nLgrLxFRUGb7aoNMIJfZJ3AC261zDQuOAKC7MiXai1WCpYc48jAHoShQ==} - '@types/node@25.0.1': - resolution: {integrity: sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==} + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -4790,6 +4787,9 @@ packages: '@vitest/expect@4.0.18': resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} + '@vitest/mocker@4.0.15': resolution: {integrity: sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==} peerDependencies: @@ -4812,6 +4812,17 @@ packages: vite: optional: true + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@4.0.14': resolution: {integrity: sha512-SOYPgujB6TITcJxgd3wmsLl+wZv+fy3av2PpiPpsWPZ6J1ySUYfScfpIt2Yv56ShJXR2MOA6q2KjKHN4EpdyRQ==} @@ -4821,24 +4832,36 @@ packages: '@vitest/pretty-format@4.0.18': resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} + '@vitest/runner@4.0.15': resolution: {integrity: sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==} '@vitest/runner@4.0.18': resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} + '@vitest/snapshot@4.0.15': resolution: {integrity: sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==} '@vitest/snapshot@4.0.18': resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} + '@vitest/spy@4.0.15': resolution: {integrity: sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==} '@vitest/spy@4.0.18': resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} + '@vitest/utils@4.0.14': resolution: {integrity: sha512-hLqXZKAWNg8pI+SQXyXxWCTOpA3MvsqcbVeNgSi8x/CSN2wi26dSzn1wrOhmCmFjEvN9p8/kLFRHa6PI8jHazw==} @@ -4848,6 +4871,9 @@ packages: '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} + '@volar/language-core@2.4.15': resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} @@ -4985,6 +5011,9 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} @@ -5076,8 +5105,8 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} - ast-v8-to-istanbul@0.3.11: - resolution: {integrity: sha512-Qya9fkoofMjCBNVdWINMjB5KZvkYfaO9/anwkWnjxibpWUxo5iHl2sOdP7/uAqaRuUYuoo8rDwnbaaKVFxoUvw==} + ast-v8-to-istanbul@0.3.12: + resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==} async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} @@ -5192,6 +5221,9 @@ packages: brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + brace-expansion@1.1.14: + resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} + brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} @@ -5455,6 +5487,9 @@ packages: cookie-es@2.0.0: resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==} + cookie-es@2.0.1: + resolution: {integrity: sha512-aVf4A4hI2w70LnF7GG+7xDQUkliwiXWXFvTjkip4+b64ygDQ2sJPRSKFDHbxn8o0xu9QzPkMuuiWIXyFSE2slA==} + cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -5795,6 +5830,9 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -5819,11 +5857,6 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} - engines: {node: '>=18'} - hasBin: true - esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} engines: {node: '>=18'} @@ -5926,8 +5959,8 @@ packages: jiti: optional: true - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -6184,8 +6217,8 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - gaxios@7.1.3: - resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} + gaxios@7.1.4: + resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} engines: {node: '>=18'} gcp-metadata@8.1.2: @@ -6271,8 +6304,8 @@ packages: peerDependencies: csstype: ^3.0.10 - google-auth-library@10.5.0: - resolution: {integrity: sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==} + google-auth-library@10.6.2: + resolution: {integrity: sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==} engines: {node: '>=18'} google-logging-utils@1.1.3: @@ -6289,10 +6322,6 @@ packages: groq-sdk@0.37.0: resolution: {integrity: sha512-lT72pcT8b/X5XrzdKf+rWVzUGW1OQSKESmL8fFN5cTbsf02gq6oFam4SVeNtzELt9cYE2Pt3pdGgSImuTbHFDg==} - gtoken@8.0.0: - resolution: {integrity: sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==} - engines: {node: '>=18'} - gzip-size@7.0.0: resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7311,6 +7340,9 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} @@ -7725,6 +7757,10 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -7774,6 +7810,10 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.5.10: + resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -7837,8 +7877,8 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - protobufjs@7.5.4: - resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + protobufjs@7.5.5: + resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} engines: {node: '>=12.0.0'} proxy-addr@2.0.7: @@ -8030,10 +8070,6 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@5.0.10: - resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} - hasBin: true - robot3@0.4.1: resolution: {integrity: sha512-hzjy826lrxzx8eRgv80idkf8ua1JAepRc9Efdtj03N3KNJuznQCPlyCJ7gnUmDFwZCLQjxy567mQVKmdv2BsXQ==} @@ -8089,6 +8125,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.60.2: + resolution: {integrity: sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + rou3@0.7.12: resolution: {integrity: sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg==} @@ -8400,6 +8441,9 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -8568,14 +8612,26 @@ packages: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} + tinyexec@1.1.1: + resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + engines: {node: '>=18'} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + tinyrainbow@3.0.3: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + tldts-core@7.0.19: resolution: {integrity: sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==} @@ -8802,6 +8858,9 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + undici@7.16.0: resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} engines: {node: '>=20.18.1'} @@ -9307,6 +9366,47 @@ packages: jsdom: optional: true + vitest@4.1.5: + resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 + '@vitest/coverage-istanbul': 4.1.5 + '@vitest/coverage-v8': 4.1.5 + '@vitest/ui': 4.1.5 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} @@ -9458,6 +9558,18 @@ packages: utf-8-validate: optional: true + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -9704,6 +9816,10 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 @@ -9974,9 +10090,9 @@ snapshots: dependencies: '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.0.14(postcss@8.5.6)': + '@csstools/css-syntax-patches-for-csstree@1.0.14(postcss@8.5.10)': dependencies: - postcss: 8.5.6 + postcss: 8.5.10 '@csstools/css-tokenizer@3.0.4': {} @@ -10006,9 +10122,6 @@ snapshots: '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/aix-ppc64@0.27.2': - optional: true - '@esbuild/aix-ppc64@0.27.3': optional: true @@ -10018,9 +10131,6 @@ snapshots: '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm64@0.27.2': - optional: true - '@esbuild/android-arm64@0.27.3': optional: true @@ -10030,9 +10140,6 @@ snapshots: '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-arm@0.27.2': - optional: true - '@esbuild/android-arm@0.27.3': optional: true @@ -10042,9 +10149,6 @@ snapshots: '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/android-x64@0.27.2': - optional: true - '@esbuild/android-x64@0.27.3': optional: true @@ -10054,9 +10158,6 @@ snapshots: '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.27.2': - optional: true - '@esbuild/darwin-arm64@0.27.3': optional: true @@ -10066,9 +10167,6 @@ snapshots: '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/darwin-x64@0.27.2': - optional: true - '@esbuild/darwin-x64@0.27.3': optional: true @@ -10078,9 +10176,6 @@ snapshots: '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.27.2': - optional: true - '@esbuild/freebsd-arm64@0.27.3': optional: true @@ -10090,9 +10185,6 @@ snapshots: '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.27.2': - optional: true - '@esbuild/freebsd-x64@0.27.3': optional: true @@ -10102,9 +10194,6 @@ snapshots: '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm64@0.27.2': - optional: true - '@esbuild/linux-arm64@0.27.3': optional: true @@ -10114,9 +10203,6 @@ snapshots: '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-arm@0.27.2': - optional: true - '@esbuild/linux-arm@0.27.3': optional: true @@ -10126,9 +10212,6 @@ snapshots: '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-ia32@0.27.2': - optional: true - '@esbuild/linux-ia32@0.27.3': optional: true @@ -10138,9 +10221,6 @@ snapshots: '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-loong64@0.27.2': - optional: true - '@esbuild/linux-loong64@0.27.3': optional: true @@ -10150,9 +10230,6 @@ snapshots: '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-mips64el@0.27.2': - optional: true - '@esbuild/linux-mips64el@0.27.3': optional: true @@ -10162,9 +10239,6 @@ snapshots: '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-ppc64@0.27.2': - optional: true - '@esbuild/linux-ppc64@0.27.3': optional: true @@ -10174,9 +10248,6 @@ snapshots: '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.27.2': - optional: true - '@esbuild/linux-riscv64@0.27.3': optional: true @@ -10186,9 +10257,6 @@ snapshots: '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-s390x@0.27.2': - optional: true - '@esbuild/linux-s390x@0.27.3': optional: true @@ -10198,18 +10266,12 @@ snapshots: '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.27.2': - optional: true - '@esbuild/linux-x64@0.27.3': optional: true '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.27.2': - optional: true - '@esbuild/netbsd-arm64@0.27.3': optional: true @@ -10219,18 +10281,12 @@ snapshots: '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.27.2': - optional: true - '@esbuild/netbsd-x64@0.27.3': optional: true '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.27.2': - optional: true - '@esbuild/openbsd-arm64@0.27.3': optional: true @@ -10240,18 +10296,12 @@ snapshots: '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.27.2': - optional: true - '@esbuild/openbsd-x64@0.27.3': optional: true '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.27.2': - optional: true - '@esbuild/openharmony-arm64@0.27.3': optional: true @@ -10261,9 +10311,6 @@ snapshots: '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/sunos-x64@0.27.2': - optional: true - '@esbuild/sunos-x64@0.27.3': optional: true @@ -10273,9 +10320,6 @@ snapshots: '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-arm64@0.27.2': - optional: true - '@esbuild/win32-arm64@0.27.3': optional: true @@ -10285,9 +10329,6 @@ snapshots: '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-ia32@0.27.2': - optional: true - '@esbuild/win32-ia32@0.27.3': optional: true @@ -10297,9 +10338,6 @@ snapshots: '@esbuild/win32-x64@0.25.12': optional: true - '@esbuild/win32-x64@0.27.2': - optional: true - '@esbuild/win32-x64@0.27.3': optional: true @@ -10308,14 +10346,14 @@ snapshots: eslint: 9.39.1(jiti@2.6.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.4(jiti@2.6.1))': dependencies: - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': dependencies: - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -10328,6 +10366,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + '@eslint/config-helpers@0.4.2': dependencies: '@eslint/core': 0.17.0 @@ -10350,9 +10396,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + '@eslint/js@9.39.1': {} - '@eslint/js@9.39.2': {} + '@eslint/js@9.39.4': {} '@eslint/object-schema@2.1.7': {} @@ -10377,12 +10437,12 @@ snapshots: '@shikijs/types': 3.20.0 '@shikijs/vscode-textmate': 10.0.2 - '@google/genai@1.43.0': + '@google/genai@1.50.1': dependencies: - google-auth-library: 10.5.0 + google-auth-library: 10.6.2 p-retry: 4.6.2 - protobufjs: 7.5.4 - ws: 8.18.3 + protobufjs: 7.5.5 + ws: 8.20.0 transitivePeerDependencies: - bufferutil - supports-color @@ -10390,11 +10450,23 @@ snapshots: '@humanfs/core@0.19.1': {} + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + '@humanfs/node@0.16.7': dependencies: '@humanfs/core': 0.19.1 '@humanwhocodes/retry': 0.4.3 + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.4.3': {} @@ -10504,11 +10576,11 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor-model@7.29.6(@types/node@25.0.1)': + '@microsoft/api-extractor-model@7.29.6(@types/node@25.5.0)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.7.0(@types/node@25.0.1) + '@rushstack/node-core-library': 5.7.0(@types/node@25.5.0) transitivePeerDependencies: - '@types/node' optional: true @@ -10531,15 +10603,15 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.47.7(@types/node@25.0.1)': + '@microsoft/api-extractor@7.47.7(@types/node@25.5.0)': dependencies: - '@microsoft/api-extractor-model': 7.29.6(@types/node@25.0.1) + '@microsoft/api-extractor-model': 7.29.6(@types/node@25.5.0) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.7.0(@types/node@25.0.1) + '@rushstack/node-core-library': 5.7.0(@types/node@25.5.0) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.14.0(@types/node@25.0.1) - '@rushstack/ts-command-line': 4.22.6(@types/node@25.0.1) + '@rushstack/terminal': 0.14.0(@types/node@25.5.0) + '@rushstack/ts-command-line': 4.22.6(@types/node@25.5.0) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.11 @@ -11106,147 +11178,230 @@ snapshots: optionalDependencies: rollup: 4.57.1 + '@rollup/pluginutils@5.3.0(rollup@4.60.2)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.60.2 + '@rollup/rollup-android-arm-eabi@4.53.3': optional: true '@rollup/rollup-android-arm-eabi@4.57.1': optional: true + '@rollup/rollup-android-arm-eabi@4.60.2': + optional: true + '@rollup/rollup-android-arm64@4.53.3': optional: true '@rollup/rollup-android-arm64@4.57.1': optional: true + '@rollup/rollup-android-arm64@4.60.2': + optional: true + '@rollup/rollup-darwin-arm64@4.53.3': optional: true '@rollup/rollup-darwin-arm64@4.57.1': optional: true + '@rollup/rollup-darwin-arm64@4.60.2': + optional: true + '@rollup/rollup-darwin-x64@4.53.3': optional: true '@rollup/rollup-darwin-x64@4.57.1': optional: true + '@rollup/rollup-darwin-x64@4.60.2': + optional: true + '@rollup/rollup-freebsd-arm64@4.53.3': optional: true '@rollup/rollup-freebsd-arm64@4.57.1': optional: true + '@rollup/rollup-freebsd-arm64@4.60.2': + optional: true + '@rollup/rollup-freebsd-x64@4.53.3': optional: true '@rollup/rollup-freebsd-x64@4.57.1': optional: true + '@rollup/rollup-freebsd-x64@4.60.2': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': optional: true '@rollup/rollup-linux-arm-gnueabihf@4.57.1': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.53.3': optional: true '@rollup/rollup-linux-arm-musleabihf@4.57.1': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.60.2': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.53.3': optional: true '@rollup/rollup-linux-arm64-gnu@4.57.1': optional: true + '@rollup/rollup-linux-arm64-gnu@4.60.2': + optional: true + '@rollup/rollup-linux-arm64-musl@4.53.3': optional: true '@rollup/rollup-linux-arm64-musl@4.57.1': optional: true + '@rollup/rollup-linux-arm64-musl@4.60.2': + optional: true + '@rollup/rollup-linux-loong64-gnu@4.53.3': optional: true '@rollup/rollup-linux-loong64-gnu@4.57.1': optional: true + '@rollup/rollup-linux-loong64-gnu@4.60.2': + optional: true + '@rollup/rollup-linux-loong64-musl@4.57.1': optional: true + '@rollup/rollup-linux-loong64-musl@4.60.2': + optional: true + '@rollup/rollup-linux-ppc64-gnu@4.53.3': optional: true '@rollup/rollup-linux-ppc64-gnu@4.57.1': optional: true + '@rollup/rollup-linux-ppc64-gnu@4.60.2': + optional: true + '@rollup/rollup-linux-ppc64-musl@4.57.1': optional: true + '@rollup/rollup-linux-ppc64-musl@4.60.2': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.53.3': optional: true '@rollup/rollup-linux-riscv64-gnu@4.57.1': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.60.2': + optional: true + '@rollup/rollup-linux-riscv64-musl@4.53.3': optional: true '@rollup/rollup-linux-riscv64-musl@4.57.1': optional: true + '@rollup/rollup-linux-riscv64-musl@4.60.2': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.53.3': optional: true '@rollup/rollup-linux-s390x-gnu@4.57.1': optional: true + '@rollup/rollup-linux-s390x-gnu@4.60.2': + optional: true + '@rollup/rollup-linux-x64-gnu@4.53.3': optional: true '@rollup/rollup-linux-x64-gnu@4.57.1': optional: true + '@rollup/rollup-linux-x64-gnu@4.60.2': + optional: true + '@rollup/rollup-linux-x64-musl@4.53.3': optional: true '@rollup/rollup-linux-x64-musl@4.57.1': optional: true + '@rollup/rollup-linux-x64-musl@4.60.2': + optional: true + '@rollup/rollup-openbsd-x64@4.57.1': optional: true + '@rollup/rollup-openbsd-x64@4.60.2': + optional: true + '@rollup/rollup-openharmony-arm64@4.53.3': optional: true '@rollup/rollup-openharmony-arm64@4.57.1': optional: true + '@rollup/rollup-openharmony-arm64@4.60.2': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.53.3': optional: true '@rollup/rollup-win32-arm64-msvc@4.57.1': optional: true + '@rollup/rollup-win32-arm64-msvc@4.60.2': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.53.3': optional: true '@rollup/rollup-win32-ia32-msvc@4.57.1': optional: true + '@rollup/rollup-win32-ia32-msvc@4.60.2': + optional: true + '@rollup/rollup-win32-x64-gnu@4.53.3': optional: true '@rollup/rollup-win32-x64-gnu@4.57.1': optional: true + '@rollup/rollup-win32-x64-gnu@4.60.2': + optional: true + '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true '@rollup/rollup-win32-x64-msvc@4.57.1': optional: true + '@rollup/rollup-win32-x64-msvc@4.60.2': + optional: true + '@rushstack/node-core-library@5.7.0(@types/node@24.10.3)': dependencies: ajv: 8.13.0 @@ -11260,7 +11415,7 @@ snapshots: optionalDependencies: '@types/node': 24.10.3 - '@rushstack/node-core-library@5.7.0(@types/node@25.0.1)': + '@rushstack/node-core-library@5.7.0(@types/node@25.5.0)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -11271,7 +11426,7 @@ snapshots: resolve: 1.22.11 semver: 7.5.4 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.5.0 optional: true '@rushstack/rig-package@0.5.3': @@ -11286,12 +11441,12 @@ snapshots: optionalDependencies: '@types/node': 24.10.3 - '@rushstack/terminal@0.14.0(@types/node@25.0.1)': + '@rushstack/terminal@0.14.0(@types/node@25.5.0)': dependencies: - '@rushstack/node-core-library': 5.7.0(@types/node@25.0.1) + '@rushstack/node-core-library': 5.7.0(@types/node@25.5.0) supports-color: 8.1.1 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.5.0 optional: true '@rushstack/ts-command-line@4.22.6(@types/node@24.10.3)': @@ -11303,9 +11458,9 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@rushstack/ts-command-line@4.22.6(@types/node@25.0.1)': + '@rushstack/ts-command-line@4.22.6(@types/node@25.5.0)': dependencies: - '@rushstack/terminal': 0.14.0(@types/node@25.0.1) + '@rushstack/terminal': 0.14.0(@types/node@25.5.0) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -11616,14 +11771,14 @@ snapshots: '@tanstack/devtools-event-bus@0.3.3': dependencies: - ws: 8.18.3 + ws: 8.20.0 transitivePeerDependencies: - bufferutil - utf-8-validate '@tanstack/devtools-event-bus@0.4.1': dependencies: - ws: 8.18.3 + ws: 8.20.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -12358,13 +12513,13 @@ snapshots: transitivePeerDependencies: - csstype - '@tanstack/solid-router-ssr-query@1.141.1(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.159.4)(@tanstack/solid-query@5.90.15(solid-js@1.9.10))(@tanstack/solid-router@1.141.1(solid-js@1.9.10))(eslint@9.39.2(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3)': + '@tanstack/solid-router-ssr-query@1.141.1(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.159.4)(@tanstack/solid-query@5.90.15(solid-js@1.9.10))(@tanstack/solid-router@1.141.1(solid-js@1.9.10))(eslint@9.39.4(jiti@2.6.1))(solid-js@1.9.10)(typescript@5.9.3)': dependencies: '@tanstack/query-core': 5.90.12 '@tanstack/router-ssr-query-core': 1.141.1(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.159.4) '@tanstack/solid-query': 5.90.15(solid-js@1.9.10) '@tanstack/solid-router': 1.141.1(solid-js@1.9.10) - eslint-plugin-solid: 0.14.5(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint-plugin-solid: 0.14.5(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) solid-js: 1.9.10 transitivePeerDependencies: - '@tanstack/router-core' @@ -12907,10 +13062,10 @@ snapshots: '@tanstack/virtual-file-routes@1.154.7': {} - '@tanstack/vite-config@0.4.1(@types/node@24.10.3)(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tanstack/vite-config@0.4.1(@types/node@24.10.3)(rollup@4.60.2)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - rollup-plugin-preserve-directives: 0.4.0(rollup@4.57.1) - vite-plugin-dts: 4.2.3(@types/node@24.10.3)(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + rollup-plugin-preserve-directives: 0.4.0(rollup@4.60.2) + vite-plugin-dts: 4.2.3(@types/node@24.10.3)(rollup@4.60.2)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) vite-plugin-externalize-deps: 0.10.0(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) vite-tsconfig-paths: 5.1.4(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: @@ -13051,9 +13206,9 @@ snapshots: dependencies: undici-types: 7.16.0 - '@types/node@25.0.1': + '@types/node@25.5.0': dependencies: - undici-types: 7.16.0 + undici-types: 7.18.2 optional: true '@types/react-dom@19.2.3(@types/react@19.2.7)': @@ -13164,13 +13319,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.49.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.4(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.49.0 '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -13341,34 +13496,17 @@ snapshots: vite: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vue: 3.5.25(typescript@5.9.3) - '@vitejs/plugin-vue@6.0.3(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.3(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.53 - vite: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vue: 3.5.25(typescript@5.9.3) - '@vitest/coverage-v8@4.0.14(vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': - dependencies: - '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.0.14 - ast-v8-to-istanbul: 0.3.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 - istanbul-reports: 3.2.0 - magicast: 0.5.2 - obug: 2.1.1 - std-env: 3.10.0 - tinyrainbow: 3.0.3 - vitest: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - transitivePeerDependencies: - - supports-color - - '@vitest/coverage-v8@4.0.14(vitest@4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.14(vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.14 - ast-v8-to-istanbul: 0.3.11 + ast-v8-to-istanbul: 0.3.12 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -13376,16 +13514,16 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 std-env: 3.10.0 - tinyrainbow: 3.0.3 - vitest: 4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + tinyrainbow: 3.1.0 + vitest: 4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@4.0.14(vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.14(vitest@4.1.5)': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.14 - ast-v8-to-istanbul: 0.3.11 + ast-v8-to-istanbul: 0.3.12 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -13393,8 +13531,8 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 std-env: 3.10.0 - tinyrainbow: 3.0.3 - vitest: 4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + tinyrainbow: 3.1.0 + vitest: 4.1.5(@types/node@25.5.0)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.10))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - supports-color @@ -13416,13 +13554,22 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.15(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/expect@4.1.5': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.0.15(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.15 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: @@ -13432,17 +13579,17 @@ snapshots: optionalDependencies: vite: 7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@4.1.5(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@vitest/spy': 4.0.18 + '@vitest/spy': 4.1.5 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@4.0.14': dependencies: - tinyrainbow: 3.0.3 + tinyrainbow: 3.1.0 '@vitest/pretty-format@4.0.15': dependencies: @@ -13452,6 +13599,10 @@ snapshots: dependencies: tinyrainbow: 3.0.3 + '@vitest/pretty-format@4.1.5': + dependencies: + tinyrainbow: 3.1.0 + '@vitest/runner@4.0.15': dependencies: '@vitest/utils': 4.0.15 @@ -13462,6 +13613,11 @@ snapshots: '@vitest/utils': 4.0.18 pathe: 2.0.3 + '@vitest/runner@4.1.5': + dependencies: + '@vitest/utils': 4.1.5 + pathe: 2.0.3 + '@vitest/snapshot@4.0.15': dependencies: '@vitest/pretty-format': 4.0.15 @@ -13474,14 +13630,23 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 + '@vitest/snapshot@4.1.5': + dependencies: + '@vitest/pretty-format': 4.1.5 + '@vitest/utils': 4.1.5 + magic-string: 0.30.21 + pathe: 2.0.3 + '@vitest/spy@4.0.15': {} '@vitest/spy@4.0.18': {} + '@vitest/spy@4.1.5': {} + '@vitest/utils@4.0.14': dependencies: '@vitest/pretty-format': 4.0.14 - tinyrainbow: 3.0.3 + tinyrainbow: 3.1.0 '@vitest/utils@4.0.15': dependencies: @@ -13493,6 +13658,12 @@ snapshots: '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 + '@vitest/utils@4.1.5': + dependencies: + '@vitest/pretty-format': 4.1.5 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + '@volar/language-core@2.4.15': dependencies: '@volar/source-map': 2.4.15 @@ -13662,6 +13833,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + ajv@8.12.0: dependencies: fast-deep-equal: 3.1.3 @@ -13762,7 +13940,7 @@ snapshots: dependencies: tslib: 2.8.1 - ast-v8-to-istanbul@0.3.11: + ast-v8-to-istanbul@0.3.12: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -13774,14 +13952,14 @@ snapshots: asynckit@0.4.0: {} - autoprefixer@10.4.22(postcss@8.5.6): + autoprefixer@10.4.22(postcss@8.5.10): dependencies: browserslist: 4.28.1 caniuse-lite: 1.0.30001760 fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 - postcss: 8.5.6 + postcss: 8.5.10 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -13900,6 +14078,11 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 + brace-expansion@1.1.14: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -14168,6 +14351,8 @@ snapshots: cookie-es@2.0.0: {} + cookie-es@2.0.1: {} + cookie-signature@1.2.2: {} cookie@0.6.0: {} @@ -14219,10 +14404,10 @@ snapshots: css-what@6.2.2: {} - cssstyle@5.3.4(postcss@8.5.6): + cssstyle@5.3.4(postcss@8.5.10): dependencies: '@asamuzakjp/css-color': 4.1.0 - '@csstools/css-syntax-patches-for-csstree': 1.0.14(postcss@8.5.6) + '@csstools/css-syntax-patches-for-csstree': 1.0.14(postcss@8.5.10) css-tree: 3.1.0 transitivePeerDependencies: - postcss @@ -14460,6 +14645,8 @@ snapshots: es-module-lexer@1.7.0: {} + es-module-lexer@2.1.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -14536,35 +14723,6 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 - esbuild@0.27.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 - esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -14655,10 +14813,10 @@ snapshots: transitivePeerDependencies: - typescript - eslint-plugin-solid@0.14.5(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + eslint-plugin-solid@0.14.5(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + '@typescript-eslint/utils': 8.49.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) estraverse: 5.3.0 is-html: 2.0.0 kebab-case: 1.0.2 @@ -14724,21 +14882,21 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.39.2(jiti@2.6.1): + eslint@9.39.4(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 + '@eslint/config-array': 0.21.2 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 + '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 - ajv: 6.12.6 + ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 @@ -14757,7 +14915,7 @@ snapshots: is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -14900,6 +15058,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + fetch-blob@3.2.0: dependencies: node-domexception: 1.0.0 @@ -15027,18 +15189,17 @@ snapshots: functions-have-names@1.2.3: {} - gaxios@7.1.3: + gaxios@7.1.4: dependencies: extend: 3.0.2 https-proxy-agent: 7.0.6 node-fetch: 3.3.2 - rimraf: 5.0.10 transitivePeerDependencies: - supports-color gcp-metadata@8.1.2: dependencies: - gaxios: 7.1.3 + gaxios: 7.1.4 google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -15145,14 +15306,13 @@ snapshots: dependencies: csstype: 3.2.3 - google-auth-library@10.5.0: + google-auth-library@10.6.2: dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.3 + gaxios: 7.1.4 gcp-metadata: 8.1.2 google-logging-utils: 1.1.3 - gtoken: 8.0.0 jws: 4.0.1 transitivePeerDependencies: - supports-color @@ -15175,13 +15335,6 @@ snapshots: transitivePeerDependencies: - encoding - gtoken@8.0.0: - dependencies: - gaxios: 7.1.3 - jws: 4.0.1 - transitivePeerDependencies: - - supports-color - gzip-size@7.0.0: dependencies: duplexer: 0.1.2 @@ -15213,7 +15366,7 @@ snapshots: h3@2.0.0-beta.5(crossws@0.4.4(srvx@0.11.2)): dependencies: - cookie-es: 2.0.0 + cookie-es: 2.0.1 fetchdts: 0.1.7 rou3: 0.7.12 srvx: 0.8.16 @@ -15738,11 +15891,11 @@ snapshots: dependencies: argparse: 2.0.1 - jsdom@27.3.0(postcss@8.5.6): + jsdom@27.3.0(postcss@8.5.10): dependencies: '@acemir/cssom': 0.9.29 '@asamuzakjp/dom-selector': 6.7.6 - cssstyle: 5.3.4(postcss@8.5.6) + cssstyle: 5.3.4(postcss@8.5.10) data-urls: 6.0.0 decimal.js: 10.6.0 html-encoding-sniffer: 4.0.0 @@ -15758,7 +15911,7 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 15.1.0 - ws: 8.18.3 + ws: 8.20.0 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil @@ -16029,7 +16182,7 @@ snapshots: magicast@0.5.2: dependencies: - '@babel/parser': 7.29.0 + '@babel/parser': 7.29.2 '@babel/types': 7.29.0 source-map-js: 1.2.1 @@ -16462,6 +16615,10 @@ snapshots: dependencies: brace-expansion: 1.1.12 + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.14 + minimatch@5.1.6: dependencies: brace-expansion: 2.0.2 @@ -16519,7 +16676,7 @@ snapshots: nf3@0.3.10: {} - nitro@3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.0.0-beta.53)(rollup@4.57.1)(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + nitro@3.0.1-alpha.2(chokidar@5.0.0)(ioredis@5.9.2)(lru-cache@11.2.4)(rolldown@1.0.0-beta.53)(rollup@4.60.2)(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: consola: 3.4.2 crossws: 0.4.4(srvx@0.10.1) @@ -16537,7 +16694,7 @@ snapshots: unstorage: 2.0.0-alpha.5(chokidar@5.0.0)(db0@0.3.4)(ioredis@5.9.2)(lru-cache@11.2.4)(ofetch@2.0.0-alpha.3) optionalDependencies: rolldown: 1.0.0-beta.53 - rollup: 4.57.1 + rollup: 4.60.2 vite: 7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@azure/app-configuration' @@ -16941,9 +17098,9 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 - openai@6.10.0(ws@8.18.3)(zod@4.2.1): + openai@6.10.0(ws@8.20.0)(zod@4.2.1): optionalDependencies: - ws: 8.18.3 + ws: 8.20.0 zod: 4.2.1 optionator@0.9.4: @@ -17149,6 +17306,8 @@ snapshots: picomatch@4.0.3: {} + picomatch@4.0.4: {} + pify@4.0.1: {} pirates@4.0.7: {} @@ -17175,17 +17334,23 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(yaml@2.8.2): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 2.6.1 - postcss: 8.5.6 + postcss: 8.5.10 tsx: 4.21.0 yaml: 2.8.2 postcss-value-parser@4.2.0: {} + postcss@8.5.10: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -17233,7 +17398,7 @@ snapshots: proto-list@1.2.4: {} - protobufjs@7.5.4: + protobufjs@7.5.5: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -17477,10 +17642,6 @@ snapshots: reusify@1.1.0: {} - rimraf@5.0.10: - dependencies: - glob: 10.5.0 - robot3@0.4.1: {} rolldown-plugin-dts@0.18.3(oxc-resolver@11.15.0)(rolldown@1.0.0-beta.53)(typescript@5.9.3): @@ -17519,11 +17680,11 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53 - rollup-plugin-preserve-directives@0.4.0(rollup@4.57.1): + rollup-plugin-preserve-directives@0.4.0(rollup@4.60.2): dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@rollup/pluginutils': 5.3.0(rollup@4.60.2) magic-string: 0.30.21 - rollup: 4.57.1 + rollup: 4.60.2 rollup-plugin-visualizer@6.0.5(rolldown@1.0.0-beta.53)(rollup@4.57.1): dependencies: @@ -17594,6 +17755,37 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.57.1 fsevents: 2.3.3 + rollup@4.60.2: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.2 + '@rollup/rollup-android-arm64': 4.60.2 + '@rollup/rollup-darwin-arm64': 4.60.2 + '@rollup/rollup-darwin-x64': 4.60.2 + '@rollup/rollup-freebsd-arm64': 4.60.2 + '@rollup/rollup-freebsd-x64': 4.60.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.2 + '@rollup/rollup-linux-arm-musleabihf': 4.60.2 + '@rollup/rollup-linux-arm64-gnu': 4.60.2 + '@rollup/rollup-linux-arm64-musl': 4.60.2 + '@rollup/rollup-linux-loong64-gnu': 4.60.2 + '@rollup/rollup-linux-loong64-musl': 4.60.2 + '@rollup/rollup-linux-ppc64-gnu': 4.60.2 + '@rollup/rollup-linux-ppc64-musl': 4.60.2 + '@rollup/rollup-linux-riscv64-gnu': 4.60.2 + '@rollup/rollup-linux-riscv64-musl': 4.60.2 + '@rollup/rollup-linux-s390x-gnu': 4.60.2 + '@rollup/rollup-linux-x64-gnu': 4.60.2 + '@rollup/rollup-linux-x64-musl': 4.60.2 + '@rollup/rollup-openbsd-x64': 4.60.2 + '@rollup/rollup-openharmony-arm64': 4.60.2 + '@rollup/rollup-win32-arm64-msvc': 4.60.2 + '@rollup/rollup-win32-ia32-msvc': 4.60.2 + '@rollup/rollup-win32-x64-gnu': 4.60.2 + '@rollup/rollup-win32-x64-msvc': 4.60.2 + fsevents: 2.3.3 + rou3@0.7.12: {} router@2.2.0: @@ -17918,6 +18110,8 @@ snapshots: std-env@3.10.0: {} + std-env@4.1.0: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -18013,11 +18207,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.45.10)(typescript@5.9.3): + svelte-check@4.3.4(picomatch@4.0.4)(svelte@5.45.10)(typescript@5.9.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 - fdir: 6.5.0(picomatch@4.0.3) + fdir: 6.5.0(picomatch@4.0.4) picocolors: 1.1.1 sade: 1.8.1 svelte: 5.45.10 @@ -18118,13 +18312,22 @@ snapshots: tinyexec@1.0.2: {} + tinyexec@1.1.1: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + tinyrainbow@3.0.3: {} + tinyrainbow@3.1.0: {} + tldts-core@7.0.19: {} tldts@7.0.19: @@ -18211,16 +18414,16 @@ snapshots: tslib@2.8.1: {} - tsup-preset-solid@2.2.0(esbuild@0.27.3)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.0.1))(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)): + tsup-preset-solid@2.2.0(esbuild@0.27.3)(solid-js@1.9.10)(tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.5.0))(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)): dependencies: esbuild-plugin-solid: 0.5.0(esbuild@0.27.3)(solid-js@1.9.10) - tsup: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.0.1))(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + tsup: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.5.0))(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) transitivePeerDependencies: - esbuild - solid-js - supports-color - tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.0.1))(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2): + tsup@8.5.1(@microsoft/api-extractor@7.47.7(@types/node@25.5.0))(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.27.3) cac: 6.7.14 @@ -18231,7 +18434,7 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(yaml@2.8.2) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.10)(tsx@4.21.0)(yaml@2.8.2) resolve-from: 5.0.0 rollup: 4.57.1 source-map: 0.7.6 @@ -18240,8 +18443,8 @@ snapshots: tinyglobby: 0.2.15 tree-kill: 1.2.2 optionalDependencies: - '@microsoft/api-extractor': 7.47.7(@types/node@25.0.1) - postcss: 8.5.6 + '@microsoft/api-extractor': 7.47.7(@types/node@25.5.0) + postcss: 8.5.10 typescript: 5.9.3 transitivePeerDependencies: - jiti @@ -18251,7 +18454,7 @@ snapshots: tsx@4.21.0: dependencies: - esbuild: 0.27.2 + esbuild: 0.27.3 get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 @@ -18346,6 +18549,9 @@ snapshots: undici-types@7.16.0: {} + undici-types@7.18.2: + optional: true + undici@7.16.0: {} undici@7.21.0: {} @@ -18681,10 +18887,10 @@ snapshots: - xml2js - yaml - vite-plugin-dts@4.2.3(@types/node@24.10.3)(rollup@4.57.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + vite-plugin-dts@4.2.3(@types/node@24.10.3)(rollup@4.60.2)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@microsoft/api-extractor': 7.47.7(@types/node@24.10.3) - '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@rollup/pluginutils': 5.3.0(rollup@4.60.2) '@volar/typescript': 2.4.27 '@vue/language-core': 2.1.6(typescript@5.9.3) compare-versions: 6.1.1 @@ -18717,7 +18923,7 @@ snapshots: transitivePeerDependencies: - supports-color - vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + vite-plugin-solid@2.11.10(solid-js@1.9.10)(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@babel/core': 7.28.5 '@types/babel__core': 7.20.5 @@ -18725,8 +18931,8 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.10 solid-refresh: 0.6.3(solid-js@1.9.10) - vite: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vitefu: 1.1.1(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + vite: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitefu: 1.1.1(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - supports-color @@ -18800,7 +19006,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -18809,7 +19015,7 @@ snapshots: rollup: 4.53.3 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.5.0 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 @@ -18834,7 +19040,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vite@7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) @@ -18843,7 +19049,7 @@ snapshots: rollup: 4.57.1 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.5.0 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 @@ -18855,18 +19061,18 @@ snapshots: optionalDependencies: vite: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vitefu@1.1.1(vite@7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + vitefu@1.1.1(vite@7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): optionalDependencies: - vite: 7.2.7(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.2.7(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitefu@1.1.1(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): optionalDependencies: vite: 7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.0.15(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.15 - '@vitest/mocker': 4.0.15(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 4.0.15(vite@7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.15 '@vitest/runner': 4.0.15 '@vitest/snapshot': 4.0.15 @@ -18883,12 +19089,12 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.2.7(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.10.3 happy-dom: 20.0.11 - jsdom: 27.3.0(postcss@8.5.6) + jsdom: 27.3.0(postcss@8.5.10) transitivePeerDependencies: - jiti - less @@ -18902,7 +19108,7 @@ snapshots: - tsx - yaml - vitest@4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.0.18(@types/node@24.10.3)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.10))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@24.10.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) @@ -18927,7 +19133,7 @@ snapshots: optionalDependencies: '@types/node': 24.10.3 happy-dom: 20.0.11 - jsdom: 27.3.0(postcss@8.5.6) + jsdom: 27.3.0(postcss@8.5.10) transitivePeerDependencies: - jiti - less @@ -18941,44 +19147,35 @@ snapshots: - tsx - yaml - vitest@4.0.18(@types/node@25.0.1)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.1.5(@types/node@25.5.0)(@vitest/coverage-v8@4.0.14)(happy-dom@20.0.11)(jsdom@27.3.0(postcss@8.5.10))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: - '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@vitest/pretty-format': 4.0.18 - '@vitest/runner': 4.0.18 - '@vitest/snapshot': 4.0.18 - '@vitest/spy': 4.0.18 - '@vitest/utils': 4.0.18 - es-module-lexer: 1.7.0 + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 obug: 2.1.1 pathe: 2.0.3 - picomatch: 4.0.3 - std-env: 3.10.0 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + tinyexec: 1.1.1 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.5.0 + '@vitest/coverage-v8': 4.0.14(vitest@4.1.5) happy-dom: 20.0.11 - jsdom: 27.3.0(postcss@8.5.6) + jsdom: 27.3.0(postcss@8.5.10) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml vscode-uri@3.1.0: {} @@ -19125,6 +19322,8 @@ snapshots: ws@8.18.3: {} + ws@8.20.0: {} + xml-name-validator@5.0.0: {} xmlbuilder2@3.1.1: