From c9816468d81779666dc7da799e63148ba9b400d5 Mon Sep 17 00:00:00 2001 From: ojowwalker77 Date: Fri, 24 Jul 2026 13:40:34 -0300 Subject: [PATCH 1/2] Live voice, voice-as-orchestrator, P0 fixes, and composer QoL Live voice (experimental, Codex): WebRTC mic + streamed audio playback, realtime transcripts, Thinking Orbs voice states, full-screen voice focus surface. Voice/audio kept out of the durable event log. TeaCode MCP thread controls (threads_list/create/send/read) so voice can orchestrate and spawn separate-context threads across providers. P0 fixes: providers never launch interactive browser auth on startup (Cursor + Grok gated; Codex/OpenCode/Kilo/Pi/Claude audited clean); New Thread exposes the real model picker; Settings controls default thread workspace behavior (new worktree / current branch / pinned base). Composer QoL: per-provider remaining-quota ring in the composer underbar (green->red as it drains, opens the shared usage popover); do-things Cmd-K palette (switch model, switch provider, new thread in a chosen provider). --- apps/server/src/codexAppServerManager.test.ts | 33 ++ apps/server/src/codexAppServerManager.ts | 84 ++++- .../Layers/CheckpointReactor.test.ts | 4 + .../Layers/OrchestrationReactor.test.ts | 1 + .../Layers/ProviderCommandReactor.test.ts | 4 + .../Layers/ProviderCommandReactor.ts | 4 + .../Layers/ProviderRuntimeIngestion.test.ts | 4 + .../Services/ProviderCommandReactor.ts | 8 + .../src/orchestration/workerToolsMcp.test.ts | 53 +++ .../src/orchestration/workerToolsMcp.ts | 260 ++++++++++++++- .../src/provider/Layers/CodexAdapter.test.ts | 115 +++++++ .../src/provider/Layers/CodexAdapter.ts | 137 ++++++++ .../src/provider/Layers/ProviderService.ts | 118 +++++++ .../Layers/ProviderSessionReaper.test.ts | 8 + .../src/provider/Services/ProviderAdapter.ts | 16 + .../src/provider/Services/ProviderService.ts | 18 + .../provider/acp/AcpJsonRpcConnection.test.ts | 61 ++++ .../src/provider/acp/AcpSessionRuntime.ts | 33 +- .../src/provider/acp/CursorAcpSupport.ts | 6 +- .../src/provider/acp/GrokAcpSupport.test.ts | 57 +++- .../server/src/provider/acp/GrokAcpSupport.ts | 22 +- apps/server/src/wsRpc.ts | 17 + apps/web/package.json | 1 + apps/web/src/appSettings.test.ts | 19 ++ apps/web/src/appSettings.ts | 10 + apps/web/src/components/ChatView.tsx | 314 +++++++++++++----- .../components/ProviderUsageMenuControl.tsx | 46 ++- .../src/components/ProviderUsageRing.test.ts | 31 ++ apps/web/src/components/ProviderUsageRing.tsx | 85 +++++ apps/web/src/components/Sidebar.tsx | 55 ++- .../components/SidebarSearchPalette.logic.ts | 9 + .../src/components/SidebarSearchPalette.tsx | 12 +- .../SidebarSearchPaletteCommands.test.ts | 188 +++++++++++ .../SidebarSearchPaletteCommands.ts | 179 ++++++++++ .../src/components/chat/VoiceFocusSurface.tsx | 149 +++++++++ apps/web/src/composerDraftStore.ts | 4 +- apps/web/src/hooks/useCodexVoiceSession.ts | 277 +++++++++++++++ apps/web/src/hooks/useHandleNewThread.ts | 14 +- apps/web/src/lib/icons.tsx | 2 + apps/web/src/lib/realtimeAudio.test.ts | 44 +++ apps/web/src/lib/realtimeAudio.ts | 108 ++++++ apps/web/src/lib/threadBootstrap.test.ts | 45 +++ apps/web/src/lib/threadBootstrap.ts | 23 ++ apps/web/src/lib/voiceFocus.test.ts | 43 +++ apps/web/src/lib/voiceFocus.ts | 32 ++ apps/web/src/routes/_chat.settings.tsx | 68 ++++ apps/web/src/settingsSearchIndex.ts | 12 + apps/web/src/wsNativeApi.test.ts | 23 ++ apps/web/src/wsNativeApi.ts | 35 ++ apps/web/src/wsTransport.ts | 9 + apps/web/vite.config.ts | 5 + bun.lock | 231 ++++++++++++- packages/contracts/src/ipc.ts | 15 +- packages/contracts/src/provider.test.ts | 64 +++- packages/contracts/src/provider.ts | 112 ++++++- packages/contracts/src/rpc.ts | 41 ++- packages/contracts/src/ws.ts | 24 +- 57 files changed, 3271 insertions(+), 121 deletions(-) create mode 100644 apps/web/src/components/ProviderUsageRing.test.ts create mode 100644 apps/web/src/components/ProviderUsageRing.tsx create mode 100644 apps/web/src/components/SidebarSearchPaletteCommands.test.ts create mode 100644 apps/web/src/components/SidebarSearchPaletteCommands.ts create mode 100644 apps/web/src/components/chat/VoiceFocusSurface.tsx create mode 100644 apps/web/src/hooks/useCodexVoiceSession.ts create mode 100644 apps/web/src/lib/realtimeAudio.test.ts create mode 100644 apps/web/src/lib/realtimeAudio.ts create mode 100644 apps/web/src/lib/voiceFocus.test.ts create mode 100644 apps/web/src/lib/voiceFocus.ts diff --git a/apps/server/src/codexAppServerManager.test.ts b/apps/server/src/codexAppServerManager.test.ts index fafb025d7..6d53fba9e 100644 --- a/apps/server/src/codexAppServerManager.test.ts +++ b/apps/server/src/codexAppServerManager.test.ts @@ -628,6 +628,11 @@ describe("isRecoverableThreadResumeError", () => { expect( isRecoverableThreadResumeError(new Error("thread/resume failed: thread not found")), ).toBe(true); + expect( + isRecoverableThreadResumeError( + new Error("thread/resume failed: no rollout found for thread id thread_1"), + ), + ).toBe(true); }); it("ignores non-resume errors", () => { @@ -1775,6 +1780,34 @@ describe("CodexAppServerManager discovery", () => { }); describe("thread checkpoint control", () => { + it("starts WebRTC realtime with feature enablement and the compatible protocol", async () => { + const { manager, context, requireSession, sendRequest } = createThreadControlHarness(); + sendRequest.mockResolvedValue({}); + + await manager.startRealtime({ + threadId: asThreadId("thread_1"), + sdp: "v=0\r\ns=-\r\n", + voice: "cedar", + }); + + expect(requireSession).toHaveBeenCalledWith("thread_1"); + expect(sendRequest).toHaveBeenNthCalledWith(1, context, "experimentalFeature/enablement/set", { + enablement: { + realtime_conversation: true, + }, + }); + expect(sendRequest).toHaveBeenNthCalledWith(2, context, "thread/realtime/start", { + threadId: "thread_1", + outputModality: "audio", + version: "v3", + transport: { + type: "webrtc", + sdp: "v=0\r\ns=-\r\n", + }, + voice: "cedar", + }); + }); + it("lists resumable desktop threads with normalized metadata", async () => { const manager = new CodexAppServerManager(); const context = { discovery: true }; diff --git a/apps/server/src/codexAppServerManager.ts b/apps/server/src/codexAppServerManager.ts index 488fb6a32..8440ba516 100644 --- a/apps/server/src/codexAppServerManager.ts +++ b/apps/server/src/codexAppServerManager.ts @@ -11,6 +11,7 @@ import { ProviderItemId, type ProviderListModelsResult, type ProviderListPluginsResult, + type ProviderListRealtimeVoicesResult, type ProviderMentionReference, type ProviderPluginAppSummary, type ProviderPluginDescriptor, @@ -32,6 +33,7 @@ import { type ProviderEvent, type ProviderSession, type ProviderSessionStartInput, + type ProviderStartRealtimeInput, type ProviderTurnStartResult, RuntimeMode, } from "@t3tools/contracts"; @@ -113,6 +115,7 @@ interface CodexSessionContext { nextRequestId: number; stopping: boolean; discovery?: boolean; + realtimeFeatureEnabled?: boolean; } interface CodexSkillListInput { @@ -188,6 +191,11 @@ export interface CodexAppServerSendTurnInput { readonly effort?: string; } +export type CodexAppServerStartRealtimeInput = Pick< + ProviderStartRealtimeInput, + "threadId" | "sdp" | "voice" +>; + type CodexAppServerReviewTarget = ProviderStartReviewInput["target"]; export interface CodexAppServerStartSessionInput { @@ -257,6 +265,7 @@ const BENIGN_PROCESS_OUTPUT_REGEXES = [/^(?:\^C)?Token usage:/i]; const RECOVERABLE_THREAD_RESUME_ERROR_SNIPPETS = [ "not found", "missing thread", + "no rollout found", "no such thread", "unknown thread", "does not exist", @@ -449,10 +458,14 @@ function spawnCodexAppServer(input: { readonly cwd: string; readonly env: NodeJS.ProcessEnv; }): ChildProcessWithoutNullStreams { - const prepared = prepareWindowsSafeProcess(input.binaryPath, ["app-server"], { - cwd: input.cwd, - env: input.env, - }); + const prepared = prepareWindowsSafeProcess( + input.binaryPath, + ["app-server", "--enable", "realtime_conversation"], + { + cwd: input.cwd, + env: input.env, + }, + ); return spawn(prepared.command, prepared.args, { cwd: input.cwd, env: input.env, @@ -722,6 +735,9 @@ export class CodexAppServerManager extends EventEmitter { + const context = this.requireSession(input.threadId); + const providerThreadId = this.requireProviderThreadId(context); + await this.enableRealtimeConversation(context); + await this.sendRequest(context, "thread/realtime/start", { + threadId: providerThreadId, + outputModality: "audio", + // V2 cannot use WebRTC, while legacy V1 currently routes some accounts + // to the retired quicksilver endpoint. V3 is the supported WebRTC path. + version: "v3", + transport: { + type: "webrtc", + sdp: input.sdp, + }, + ...(input.voice !== undefined ? { voice: input.voice } : {}), + }); + } + + async stopRealtime(threadId: ThreadId): Promise { + const context = this.requireSession(threadId); + await this.sendRequest(context, "thread/realtime/stop", { + threadId: this.requireProviderThreadId(context), + }); + } + + async listRealtimeVoices(threadId: ThreadId): Promise { + const context = this.requireSession(threadId); + await this.enableRealtimeConversation(context); + return this.sendRequest( + context, + "thread/realtime/listVoices", + {}, + ); + } + async steerTurn(input: CodexAppServerSendTurnInput): Promise { const context = this.requireSession(input.threadId); context.collabReceiverTurns.clear(); @@ -1352,6 +1403,7 @@ export class CodexAppServerManager extends EventEmitter { + if (context.realtimeFeatureEnabled) { + return; + } + await this.sendRequest(context, "experimentalFeature/enablement/set", { + enablement: { + realtime_conversation: true, + }, + }); + context.realtimeFeatureEnabled = true; + } + private writeMessage(context: CodexSessionContext, message: unknown): void { const encoded = JSON.stringify(message); if (!context.child.stdin.writable) { diff --git a/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts b/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts index 11da6033c..f48ae27fe 100644 --- a/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts +++ b/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts @@ -103,7 +103,11 @@ function createProviderServiceHarness( getCapabilities: () => Effect.succeed({ sessionModelSwitch: "in-session" }), rollbackConversation, compactThread: () => unsupported(), + startRealtime: () => unsupported(), + stopRealtime: () => unsupported(), + listRealtimeVoices: () => unsupported(), streamEvents: Stream.fromPubSub(runtimeEventPubSub), + streamRealtimeEvents: Stream.empty, }; const emit = (event: LegacyProviderRuntimeEvent): void => { diff --git a/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts b/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts index 1514bef59..b3d195939 100644 --- a/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts +++ b/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts @@ -32,6 +32,7 @@ describe("OrchestrationReactor", () => { ), Layer.provideMerge( Layer.succeed(ProviderCommandReactor, { + ensureSession: (threadId) => Effect.succeed(threadId), start: Effect.sync(() => { started.push("provider-command-reactor"); }), diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts index 5b6b6f63b..a24942ab5 100644 --- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts @@ -326,7 +326,11 @@ describe("ProviderCommandReactor", () => { }), rollbackConversation, compactThread: () => unsupported(), + startRealtime: () => unsupported(), + stopRealtime: () => unsupported(), + listRealtimeVoices: () => unsupported(), streamEvents: Stream.fromPubSub(runtimeEventPubSub), + streamRealtimeEvents: Stream.empty, }; const orchestrationLayer = OrchestrationEngineLive.pipe( diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts index 29bb601bd..8d0f83032 100644 --- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts @@ -2193,6 +2193,9 @@ const make = Effect.gen(function* () { const worker = yield* makeDrainableWorker(processDomainEventSafely); + const ensureSession: ProviderCommandReactorShape["ensureSession"] = (threadId) => + ensureSessionForThread(threadId, new Date().toISOString()); + const start: ProviderCommandReactorShape["start"] = Effect.all([ Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) => { if ( @@ -2221,6 +2224,7 @@ const make = Effect.gen(function* () { ]).pipe(Effect.asVoid); return { + ensureSession, start, drain: worker.drain, } satisfies ProviderCommandReactorShape; diff --git a/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts b/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts index b2400ed20..1dd8c47c8 100644 --- a/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts +++ b/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts @@ -85,7 +85,11 @@ function createProviderServiceHarness() { }), rollbackConversation: () => unsupported(), compactThread: () => unsupported(), + startRealtime: () => unsupported(), + stopRealtime: () => unsupported(), + listRealtimeVoices: () => unsupported(), streamEvents: Stream.fromPubSub(runtimeEventPubSub), + streamRealtimeEvents: Stream.empty, }; const setSession = (session: ProviderSession): void => { diff --git a/apps/server/src/orchestration/Services/ProviderCommandReactor.ts b/apps/server/src/orchestration/Services/ProviderCommandReactor.ts index 8f20571c1..7f926f2b3 100644 --- a/apps/server/src/orchestration/Services/ProviderCommandReactor.ts +++ b/apps/server/src/orchestration/Services/ProviderCommandReactor.ts @@ -6,6 +6,7 @@ * * @module ProviderCommandReactor */ +import type { ThreadId } from "@t3tools/contracts"; import { ServiceMap } from "effect"; import type { Effect, Scope } from "effect"; @@ -13,6 +14,13 @@ import type { Effect, Scope } from "effect"; * ProviderCommandReactorShape - Service API for provider command reactors. */ export interface ProviderCommandReactorShape { + /** + * Establish or recover the canonical provider session for a projected Thread. + * Non-turn provider features must use this instead of inventing a partial + * session startup path. + */ + readonly ensureSession: (threadId: ThreadId) => Effect.Effect; + /** * Start reacting to provider-intent orchestration domain events. * diff --git a/apps/server/src/orchestration/workerToolsMcp.test.ts b/apps/server/src/orchestration/workerToolsMcp.test.ts index 9f792b049..d2ef4ea53 100644 --- a/apps/server/src/orchestration/workerToolsMcp.test.ts +++ b/apps/server/src/orchestration/workerToolsMcp.test.ts @@ -157,6 +157,59 @@ describe("Worker MCP tools", () => { }); expect(snapshot.threads).toHaveLength(2); + const delegated = (await call(threadA, "threads_create", { + title: "Claude implementation", + provider: "claudeAgent", + model: "claude-sonnet-4-5", + prompt: "Implement the isolated change and report the result.", + })) as { + id: string; + provider: string; + parentThreadId: string; + dispatched: boolean; + }; + expect(delegated).toMatchObject({ + provider: "claudeAgent", + parentThreadId: threadA, + dispatched: true, + }); + + const threads = (await call(threadA, "threads_list", {})) as Array<{ + id: string; + provider: string; + }>; + expect(threads).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: delegated.id, provider: "claudeAgent" }), + ]), + ); + + const delegatedRead = (await call(threadA, "threads_read", { + thread_id: delegated.id, + })) as { + messages: Array<{ role: string; text: string }>; + }; + expect(delegatedRead.messages).toEqual([ + expect.objectContaining({ + role: "user", + text: "Implement the isolated change and report the result.", + }), + ]); + + await call(threadA, "threads_send", { + thread_id: delegated.id, + prompt: "Also run the focused tests.", + }); + const delegatedReadAfterSend = (await call(threadA, "threads_read", { + thread_id: delegated.id, + message_limit: 1, + })) as { + messages: Array<{ role: string; text: string }>; + }; + expect(delegatedReadAfterSend.messages).toEqual([ + expect.objectContaining({ role: "user", text: "Also run the focused tests." }), + ]); + await system.runtime.dispose(); }); }); diff --git a/apps/server/src/orchestration/workerToolsMcp.ts b/apps/server/src/orchestration/workerToolsMcp.ts index 7c201d863..485bcdde2 100644 --- a/apps/server/src/orchestration/workerToolsMcp.ts +++ b/apps/server/src/orchestration/workerToolsMcp.ts @@ -5,14 +5,18 @@ import { CommandId, DEFAULT_RUNTIME_MODE, MessageId, + type ModelSelection, ProjectId, + ProviderKind, + type RuntimeMode, TaskId, ThreadId, type OrchestrationShellSnapshot, type ProviderSessionStartInput, type TaskStatus, } from "@t3tools/contracts"; -import { Cause, Effect } from "effect"; +import { getDefaultModel } from "@t3tools/shared/model"; +import { Cause, Effect, Option, Schema } from "effect"; import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"; import type { ServerConfigShape } from "../config.ts"; @@ -37,6 +41,19 @@ const TASK_STATUSES = new Set([ "completed", "cancelled", ]); +const PROVIDER_KINDS = [ + "codex", + "claudeAgent", + "cursor", + "grok", + "kilo", + "opencode", + "pi", +] as const satisfies ReadonlyArray; +const RUNTIME_MODES = [ + "approval-required", + "full-access", +] as const satisfies ReadonlyArray; type JsonRpcRequest = { readonly jsonrpc?: unknown; @@ -52,6 +69,87 @@ type WorkerScope = { }; const toolDefinitions = [ + { + name: "threads_list", + description: + "List active TeaCode Threads owned by this repository Worker. Use this to find a thread before delegating or reading its result.", + inputSchema: { + type: "object", + properties: { + include_archived: { + type: "boolean", + description: "Include archived Threads. Defaults to false.", + }, + }, + additionalProperties: false, + }, + annotations: { readOnlyHint: true }, + }, + { + name: "threads_create", + description: + "Create a separate TeaCode Thread under this Worker, choose its provider/model, and optionally dispatch its first prompt. The child gets an independent provider context and is linked to the calling Thread.", + inputSchema: { + type: "object", + properties: { + title: { type: "string" }, + prompt: { + type: "string", + description: "Optional first request to dispatch immediately.", + }, + provider: { + type: "string", + enum: [...PROVIDER_KINDS], + description: "Defaults to the calling Thread's provider.", + }, + model: { + type: "string", + description: "Defaults to the selected provider's TeaCode default model.", + }, + runtime_mode: { + type: "string", + enum: [...RUNTIME_MODES], + description: "Defaults to the calling Thread's runtime mode.", + }, + }, + required: ["title"], + additionalProperties: false, + }, + }, + { + name: "threads_send", + description: + "Send work to an existing Thread owned by this Worker. The target keeps its own provider and context. Use threads_read afterward to hear back.", + inputSchema: { + type: "object", + properties: { + thread_id: { type: "string" }, + prompt: { type: "string" }, + }, + required: ["thread_id", "prompt"], + additionalProperties: false, + }, + }, + { + name: "threads_read", + description: + "Read the latest transcript and status from a Thread owned by this Worker. Use this after delegation to bring the result back into the orchestrator conversation.", + inputSchema: { + type: "object", + properties: { + thread_id: { type: "string" }, + message_limit: { + type: "number", + minimum: 1, + maximum: 50, + description: "Latest messages to return. Defaults to 12.", + }, + }, + required: ["thread_id"], + additionalProperties: false, + }, + annotations: { readOnlyHint: true }, + }, { name: "tasks_list", description: "List durable Tasks owned by this Thread's repository Worker.", @@ -182,6 +280,27 @@ function optionalString(args: Record, key: string): string | un return value.trim(); } +function optionalInteger( + args: Record, + key: string, + input: { readonly min: number; readonly max: number }, +): number | undefined { + const value = args[key]; + if (value === undefined) return undefined; + if (!Number.isInteger(value) || (value as number) < input.min || (value as number) > input.max) { + throw new Error(`'${key}' must be an integer from ${input.min} to ${input.max}.`); + } + return value as number; +} + +function ownedThread(scope: WorkerScope, rawThreadId: string) { + const thread = scope.snapshot.threads.find((candidate) => candidate.id === rawThreadId); + if (!thread || thread.projectId !== scope.workerId) { + throw new Error(`Thread '${rawThreadId}' is not owned by this Worker.`); + } + return thread; +} + function ownedTask(scope: WorkerScope, rawTaskId: string) { const task = scope.snapshot.tasks.find((candidate) => candidate.id === rawTaskId); if (!task || task.workerId !== scope.workerId) { @@ -241,12 +360,151 @@ export function runWorkerTool(input: { }) { return Effect.gen(function* () { const engine = yield* OrchestrationEngineService; + const snapshotQuery = yield* ProjectionSnapshotQuery; const scope = resolveWorkerScope({ rawThreadId: input.rawThreadId, snapshot: input.snapshot, }); const args = record(input.args ?? {}); + if (input.name === "threads_list") { + const includeArchived = args.include_archived === true; + return scope.snapshot.threads + .filter( + (thread) => + thread.projectId === scope.workerId && (includeArchived || thread.archivedAt === null), + ) + .map((thread) => ({ + id: thread.id, + title: thread.title, + provider: thread.modelSelection.provider, + model: thread.modelSelection.model, + runtimeMode: thread.runtimeMode, + parentThreadId: thread.parentThreadId, + status: thread.session?.status ?? (thread.latestTurn ? "idle" : "not-started"), + latestTurn: thread.latestTurn, + updatedAt: thread.updatedAt, + })); + } + + if (input.name === "threads_create") { + const callingThread = ownedThread(scope, scope.threadId); + const rawProvider = optionalString(args, "provider"); + if (rawProvider !== undefined && !Schema.is(ProviderKind)(rawProvider)) { + throw new Error(`Unknown provider '${rawProvider}'.`); + } + const provider = rawProvider ?? callingThread.modelSelection.provider; + const model = optionalString(args, "model") ?? getDefaultModel(provider); + if (!model) { + throw new Error(`Provider '${provider}' requires an explicit model.`); + } + const rawRuntimeMode = optionalString(args, "runtime_mode"); + if (rawRuntimeMode !== undefined && !RUNTIME_MODES.includes(rawRuntimeMode as RuntimeMode)) { + throw new Error(`Unknown runtime mode '${rawRuntimeMode}'.`); + } + const runtimeMode = (rawRuntimeMode as RuntimeMode | undefined) ?? callingThread.runtimeMode; + const modelSelection = { provider, model } as ModelSelection; + const threadId = ThreadId.makeUnsafe(crypto.randomUUID()); + const now = new Date().toISOString(); + const prompt = optionalString(args, "prompt"); + + yield* engine.dispatch({ + type: "thread.create", + commandId: commandId(), + threadId, + projectId: scope.workerId, + title: requiredString(args, "title"), + modelSelection, + runtimeMode, + // Child contexts share the orchestrator's concrete checkout. This keeps + // delegation immediate and avoids silently creating Git worktrees. + envMode: callingThread.envMode, + branch: callingThread.branch, + worktreePath: callingThread.worktreePath, + parentThreadId: scope.threadId, + createdAt: now, + }); + if (prompt) { + yield* engine.dispatch({ + type: "thread.turn.start", + commandId: commandId(), + threadId, + message: { + messageId: MessageId.makeUnsafe(crypto.randomUUID()), + role: "user", + text: prompt, + attachments: [], + }, + dispatchMode: "queue", + dispatchOrigin: "automation", + runtimeMode, + createdAt: now, + }); + } + return { + id: threadId, + provider, + model, + parentThreadId: scope.threadId, + dispatched: Boolean(prompt), + }; + } + + if (input.name === "threads_send") { + const target = ownedThread(scope, requiredString(args, "thread_id")); + if (target.archivedAt !== null) { + throw new Error(`Thread '${target.id}' is archived.`); + } + const now = new Date().toISOString(); + yield* engine.dispatch({ + type: "thread.turn.start", + commandId: commandId(), + threadId: target.id, + message: { + messageId: MessageId.makeUnsafe(crypto.randomUUID()), + role: "user", + text: requiredString(args, "prompt"), + attachments: [], + }, + dispatchMode: "queue", + dispatchOrigin: "automation", + runtimeMode: target.runtimeMode, + createdAt: now, + }); + return { + id: target.id, + provider: target.modelSelection.provider, + model: target.modelSelection.model, + dispatched: true, + }; + } + + if (input.name === "threads_read") { + const target = ownedThread(scope, requiredString(args, "thread_id")); + const messageLimit = optionalInteger(args, "message_limit", { min: 1, max: 50 }) ?? 12; + const detailOption = yield* snapshotQuery.getThreadDetailById(target.id); + if (Option.isNone(detailOption)) { + throw new Error(`Thread '${target.id}' is no longer available.`); + } + const detail = detailOption.value; + return { + id: detail.id, + title: detail.title, + provider: detail.modelSelection.provider, + model: detail.modelSelection.model, + status: detail.session?.status ?? (detail.latestTurn ? "idle" : "not-started"), + latestTurn: detail.latestTurn, + messages: detail.messages.slice(-messageLimit).map((message) => ({ + id: message.id, + role: message.role, + text: message.text, + createdAt: message.createdAt, + streaming: message.streaming, + })), + updatedAt: detail.updatedAt, + }; + } + if (input.name === "tasks_list") { const includeClosed = args.include_closed === true; return scope.snapshot.tasks diff --git a/apps/server/src/provider/Layers/CodexAdapter.test.ts b/apps/server/src/provider/Layers/CodexAdapter.test.ts index fb301af6a..86703ea2a 100644 --- a/apps/server/src/provider/Layers/CodexAdapter.test.ts +++ b/apps/server/src/provider/Layers/CodexAdapter.test.ts @@ -695,6 +695,41 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { }), ); + it.effect("drops stderr duplicated by typed realtime error notifications", () => + Effect.gen(function* () { + const adapter = yield* CodexAdapter; + const firstEventFiber = yield* Stream.runHead(adapter.streamEvents).pipe(Effect.forkChild); + const createdAt = new Date().toISOString(); + + lifecycleManager.emit("event", { + id: asEventId("evt-realtime-stderr"), + kind: "error", + provider: "codex", + threadId: asThreadId("thread-1"), + createdAt, + method: "process/stderr", + message: + "2026-07-24T15:40:31.951265Z ERROR codex_core::realtime_conversation: realtime stream error event received", + } satisfies ProviderEvent); + lifecycleManager.emit("event", { + id: asEventId("evt-after-realtime-stderr"), + kind: "notification", + provider: "codex", + threadId: asThreadId("thread-1"), + createdAt, + method: "thread/name/updated", + payload: { name: "Still connected" }, + } satisfies ProviderEvent); + + const firstEvent = yield* Fiber.join(firstEventFiber); + assert.equal(firstEvent._tag, "Some"); + if (firstEvent._tag !== "Some") { + return; + } + assert.equal(firstEvent.value.type, "thread.metadata.updated"); + }), + ); + it.effect("preserves request type when mapping serverRequest/resolved", () => Effect.gen(function* () { const adapter = yield* CodexAdapter; @@ -1165,6 +1200,86 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { assert.equal(firstEvent.value.payload.status, "inProgress"); }), ); + + it.effect("routes realtime transcript events through the ephemeral voice stream", () => + Effect.gen(function* () { + const adapter = yield* CodexAdapter; + assert.ok(adapter.streamRealtimeEvents); + const firstEventFiber = yield* Stream.runHead(adapter.streamRealtimeEvents).pipe( + Effect.forkChild, + ); + + lifecycleManager.emit("event", { + id: asEventId("evt-realtime-transcript"), + kind: "notification", + provider: "codex", + threadId: asThreadId("thread-1"), + createdAt: new Date().toISOString(), + method: "thread/realtime/transcript/delta", + payload: { + threadId: "provider-thread-1", + role: "assistant", + delta: "Hello", + }, + } satisfies ProviderEvent); + + const firstEvent = yield* Fiber.join(firstEventFiber); + assert.equal(firstEvent._tag, "Some"); + if (firstEvent._tag !== "Some") return; + assert.deepStrictEqual(firstEvent.value, { + type: "transcript.delta", + threadId: "thread-1", + createdAt: firstEvent.value.createdAt, + role: "assistant", + delta: "Hello", + }); + }), + ); + + it.effect("routes realtime audio through the ephemeral voice stream", () => + Effect.gen(function* () { + const adapter = yield* CodexAdapter; + assert.ok(adapter.streamRealtimeEvents); + const firstEventFiber = yield* Stream.runHead(adapter.streamRealtimeEvents).pipe( + Effect.forkChild, + ); + + lifecycleManager.emit("event", { + id: asEventId("evt-realtime-audio"), + kind: "notification", + provider: "codex", + threadId: asThreadId("thread-1"), + createdAt: new Date().toISOString(), + method: "thread/realtime/outputAudio/delta", + payload: { + threadId: "provider-thread-1", + audio: { + data: "AAABAP//", + sampleRate: 24_000, + numChannels: 1, + samplesPerChannel: 3, + itemId: "item-audio-1", + }, + }, + } satisfies ProviderEvent); + + const firstEvent = yield* Fiber.join(firstEventFiber); + assert.equal(firstEvent._tag, "Some"); + if (firstEvent._tag !== "Some") return; + assert.deepStrictEqual(firstEvent.value, { + type: "audio.delta", + threadId: "thread-1", + createdAt: firstEvent.value.createdAt, + audio: { + data: "AAABAP//", + sampleRate: 24_000, + numChannels: 1, + samplesPerChannel: 3, + itemId: "item-audio-1", + }, + }); + }), + ); }); afterAll(() => { diff --git a/apps/server/src/provider/Layers/CodexAdapter.ts b/apps/server/src/provider/Layers/CodexAdapter.ts index 7091cc3cb..626f487c2 100644 --- a/apps/server/src/provider/Layers/CodexAdapter.ts +++ b/apps/server/src/provider/Layers/CodexAdapter.ts @@ -15,6 +15,8 @@ import { type ProviderListModelsResult, type ProviderListPluginsResult, type ProviderReadPluginResult, + type ProviderRealtimeAudioChunk, + type ProviderRealtimeEvent, type ProviderListSkillsResult, type ProviderRuntimeEvent, type ThreadTokenUsageSnapshot, @@ -151,6 +153,34 @@ function asNumber(value: unknown): number | undefined { return typeof value === "number" && Number.isFinite(value) ? value : undefined; } +function asPositiveInteger(value: unknown): number | undefined { + const number = asNumber(value); + return number !== undefined && Number.isSafeInteger(number) && number > 0 ? number : undefined; +} + +function mapRealtimeAudioChunk(value: unknown): ProviderRealtimeAudioChunk | undefined { + const audio = asObject(value); + const data = asString(audio?.data); + const sampleRate = asPositiveInteger(audio?.sampleRate ?? audio?.sample_rate); + const numChannels = asPositiveInteger( + audio?.numChannels ?? audio?.num_channels ?? audio?.channels, + ); + const samplesPerChannel = asPositiveInteger( + audio?.samplesPerChannel ?? audio?.samples_per_channel, + ); + const itemId = asString(audio?.itemId ?? audio?.item_id); + if (!data || sampleRate === undefined || numChannels === undefined) { + return undefined; + } + return { + data, + sampleRate, + numChannels, + ...(samplesPerChannel !== undefined ? { samplesPerChannel } : {}), + ...(itemId ? { itemId } : {}), + }; +} + // Keep manager-emitted stderr lines visible without escalating them into a fatal thread error. function providerErrorMapsToWarning(event: ProviderEvent): boolean { return ( @@ -162,6 +192,14 @@ function providerErrorMapsToWarning(event: ProviderEvent): boolean { ); } +function isRedundantRealtimeErrorDiagnostic(event: ProviderEvent): boolean { + return ( + event.kind === "error" && + event.method === "process/stderr" && + event.message?.toLowerCase().includes("realtime stream error event received") === true + ); +} + function normalizeCodexTokenUsage(value: unknown): ThreadTokenUsageSnapshot | undefined { const usage = asObject(value); const totalUsage = asObject(usage?.total_token_usage ?? usage?.total); @@ -797,6 +835,12 @@ function mapToRuntimeEvents( } if (event.kind === "error") { + // Core emits this stderr line after the typed thread/realtime/error and + // thread/realtime/closed notifications. Persisting it creates a second, + // less useful warning in the normal transcript after voice fails. + if (isRedundantRealtimeErrorDiagnostic(event)) { + return []; + } if (!event.message) { return []; } @@ -1553,6 +1597,61 @@ function mapToRuntimeEvents( return []; } +function mapToRealtimeEvent(event: ProviderEvent): ProviderRealtimeEvent | undefined { + if (!event.method.startsWith("thread/realtime/")) { + return undefined; + } + const payload = asObject(event.payload); + const base = { + threadId: event.threadId, + createdAt: event.createdAt, + }; + + switch (event.method) { + case "thread/realtime/started": + return { + type: "started", + ...base, + ...(asString(payload?.realtimeSessionId) + ? { realtimeSessionId: asString(payload?.realtimeSessionId) } + : {}), + ...(asString(payload?.version) ? { version: asString(payload?.version) } : {}), + }; + case "thread/realtime/sdp": { + const sdp = asString(payload?.sdp); + return sdp ? { type: "sdp", ...base, sdp } : undefined; + } + case "thread/realtime/transcript/delta": { + const role = asString(payload?.role); + const delta = asString(payload?.delta); + return role && delta !== undefined + ? { type: "transcript.delta", ...base, role, delta } + : undefined; + } + case "thread/realtime/transcript/done": { + const role = asString(payload?.role); + const text = asString(payload?.text); + return role && text !== undefined + ? { type: "transcript.done", ...base, role, text } + : undefined; + } + case "thread/realtime/outputAudio/delta": { + const audio = mapRealtimeAudioChunk(payload?.audio ?? event.payload); + return audio ? { type: "audio.delta", ...base, audio } : undefined; + } + case "thread/realtime/error": { + const message = asString(payload?.message) ?? event.message; + return message ? { type: "error", ...base, message } : undefined; + } + case "thread/realtime/closed": { + const reason = asString(payload?.reason) ?? event.message; + return { type: "closed", ...base, ...(reason ? { reason } : {}) }; + } + default: + return undefined; + } +} + const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; @@ -1866,6 +1965,24 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => catch: (cause) => toRequestError(threadId, "thread/compact/start", cause), }); + const startRealtime: NonNullable = (input) => + Effect.tryPromise({ + try: () => manager.startRealtime(input), + catch: (cause) => toRequestError(input.threadId, "thread/realtime/start", cause), + }); + + const stopRealtime: NonNullable = (threadId) => + Effect.tryPromise({ + try: () => manager.stopRealtime(threadId), + catch: (cause) => toRequestError(threadId, "thread/realtime/stop", cause), + }); + + const listRealtimeVoices: NonNullable = (threadId) => + Effect.tryPromise({ + try: () => manager.listRealtimeVoices(threadId), + catch: (cause) => toRequestError(threadId, "thread/realtime/listVoices", cause), + }); + const listExternalThreads: NonNullable = (input) => Effect.tryPromise({ try: () => manager.listExternalThreads(input.limit), @@ -1989,6 +2106,7 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => }).pipe(Effect.map((result) => result satisfies ProviderListModelsResult)); const runtimeEventQueue = yield* Queue.unbounded(); + const realtimeEventQueue = yield* Queue.unbounded(); yield* Effect.acquireRelease( Effect.gen(function* () { @@ -2003,6 +2121,19 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => const services = yield* Effect.services(); const listener = (event: ProviderEvent) => Effect.gen(function* () { + const realtimeEvent = mapToRealtimeEvent(event); + if (event.method.startsWith("thread/realtime/")) { + if (realtimeEvent) { + if (realtimeEvent.type === "error") { + yield* Effect.logWarning("Codex realtime session error", { + threadId: realtimeEvent.threadId, + message: realtimeEvent.message, + }); + } + yield* Queue.offer(realtimeEventQueue, realtimeEvent); + } + return; + } yield* writeNativeEvent(event); const runtimeEvents = mapToRuntimeEvents(event, event.threadId); if (runtimeEvents.length === 0) { @@ -2025,6 +2156,7 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => manager.off("event", listener); }); yield* Queue.shutdown(runtimeEventQueue); + yield* Queue.shutdown(realtimeEventQueue); }), ); @@ -2040,6 +2172,7 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => supportsRuntimeModelList: true, supportsTurnSteering: true, supportsLiveTurnDiffPatch: true, + supportsRealtimeVoice: true, }, startSession, sendTurn, @@ -2051,6 +2184,9 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => listExternalThreads, rollbackThread, compactThread, + startRealtime, + stopRealtime, + listRealtimeVoices, forkThread, respondToRequest, respondToUserInput, @@ -2064,6 +2200,7 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => readPlugin, listModels, streamEvents: Stream.fromQueue(runtimeEventQueue), + streamRealtimeEvents: Stream.fromQueue(realtimeEventQueue), } satisfies CodexAdapterShape; }); diff --git a/apps/server/src/provider/Layers/ProviderService.ts b/apps/server/src/provider/Layers/ProviderService.ts index 261d923af..7372dbf60 100644 --- a/apps/server/src/provider/Layers/ProviderService.ts +++ b/apps/server/src/provider/Layers/ProviderService.ts @@ -12,6 +12,9 @@ import { ProviderCompactThreadInput, ProviderForkThreadInput, + ProviderListRealtimeVoicesInput, + ProviderStartRealtimeInput, + ProviderStopRealtimeInput, ModelSelection, NonNegativeInt, ThreadId, @@ -25,6 +28,7 @@ import { ProviderStopSessionInput, ProviderStartOptions, type ProviderRuntimeEvent, + type ProviderRealtimeEvent, type ProviderSession, } from "@t3tools/contracts"; import { Cause, Effect, Exit, Layer, Option, PubSub, Schema, SchemaIssue, Stream } from "effect"; @@ -252,6 +256,8 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => const registry = yield* ProviderAdapterRegistry; const directory = yield* ProviderSessionDirectory; const runtimeEventPubSub = yield* PubSub.unbounded(); + const realtimeEventPubSub = yield* PubSub.unbounded(); + const activeRealtimeThreads = new Set(); const runtimeIdleTimers = new Map>(); // Fired idle callbacks outlive their timer map entry, so use generations to // invalidate async stop work when new user work starts in that gap. @@ -290,6 +296,9 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => const scheduleRuntimeIdleStop = (threadId: ThreadId) => { clearRuntimeIdleTimer(threadId); + if (activeRealtimeThreads.has(threadId)) { + return; + } if (runtimeIdleStopMs <= 0) { retireRuntimeIdleGeneration(threadId); return; @@ -354,6 +363,7 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => } return; case "session.exited": + activeRealtimeThreads.delete(event.threadId); clearRuntimeIdleTimer(event.threadId); retireRuntimeIdleGeneration(event.threadId); return; @@ -621,6 +631,22 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => Stream.runForEach(adapter.streamEvents, processRuntimeEvent).pipe(Effect.forkScoped), ).pipe(Effect.asVoid); + yield* Effect.forEach(adapters, (adapter) => + adapter.streamRealtimeEvents + ? Stream.runForEach(adapter.streamRealtimeEvents, (event) => + Effect.sync(() => { + if (event.type === "started") { + activeRealtimeThreads.add(event.threadId); + clearRuntimeIdleTimer(event.threadId); + } else if (event.type === "closed" || event.type === "error") { + activeRealtimeThreads.delete(event.threadId); + scheduleRuntimeIdleStop(event.threadId); + } + }).pipe(Effect.andThen(PubSub.publish(realtimeEventPubSub, event)), Effect.asVoid), + ).pipe(Effect.forkScoped) + : Effect.void, + ).pipe(Effect.asVoid); + const recoverSessionForThread = (input: { readonly binding: ProviderRuntimeBinding; readonly operation: string; @@ -1156,6 +1182,7 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => if (routed.isActive) { yield* routed.adapter.stopSession(routed.threadId); } + activeRealtimeThreads.delete(input.threadId); yield* waitForRuntimeIdleStop(input.threadId); yield* directory.remove(input.threadId); retireRuntimeIdleGeneration(input.threadId); @@ -1196,6 +1223,7 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => if (hasActiveSession) { yield* adapter.stopSession(input.threadId); } + activeRealtimeThreads.delete(input.threadId); if (!isExpectedIdleStopCurrent()) { return; } @@ -1438,6 +1466,89 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => ); }); + const startRealtime: ProviderServiceShape["startRealtime"] = (rawInput) => + Effect.gen(function* () { + const input = yield* decodeInputOrValidationError({ + operation: "ProviderService.startRealtime", + schema: ProviderStartRealtimeInput, + payload: rawInput, + }); + yield* runIdleSensitiveProviderWork( + input.threadId, + Effect.gen(function* () { + const routed = yield* resolveRoutableSession({ + threadId: input.threadId, + operation: "ProviderService.startRealtime", + allowRecovery: true, + }); + if (!routed.adapter.startRealtime) { + return yield* toValidationError( + "ProviderService.startRealtime", + `Live voice is unavailable for provider '${routed.adapter.provider}'.`, + ); + } + activeRealtimeThreads.add(input.threadId); + yield* routed.adapter.startRealtime(input).pipe( + Effect.onError(() => + Effect.sync(() => { + activeRealtimeThreads.delete(input.threadId); + }), + ), + ); + }), + ); + }); + + const stopRealtime: ProviderServiceShape["stopRealtime"] = (rawInput) => + Effect.gen(function* () { + const input = yield* decodeInputOrValidationError({ + operation: "ProviderService.stopRealtime", + schema: ProviderStopRealtimeInput, + payload: rawInput, + }); + const routed = yield* resolveRoutableSession({ + threadId: input.threadId, + operation: "ProviderService.stopRealtime", + allowRecovery: false, + }); + if (!routed.adapter.stopRealtime) { + return yield* toValidationError( + "ProviderService.stopRealtime", + `Live voice is unavailable for provider '${routed.adapter.provider}'.`, + ); + } + yield* routed.adapter.stopRealtime(input.threadId); + activeRealtimeThreads.delete(input.threadId); + scheduleRuntimeIdleStop(input.threadId); + }); + + const listRealtimeVoices: ProviderServiceShape["listRealtimeVoices"] = (rawInput) => + Effect.gen(function* () { + const input = yield* decodeInputOrValidationError({ + operation: "ProviderService.listRealtimeVoices", + schema: ProviderListRealtimeVoicesInput, + payload: rawInput, + }); + return yield* runIdleSensitiveProviderWork( + input.threadId, + Effect.gen(function* () { + const routed = yield* resolveRoutableSession({ + threadId: input.threadId, + operation: "ProviderService.listRealtimeVoices", + allowRecovery: true, + }); + if (!routed.adapter.listRealtimeVoices) { + return yield* toValidationError( + "ProviderService.listRealtimeVoices", + `Live voice is unavailable for provider '${routed.adapter.provider}'.`, + ); + } + return yield* routed.adapter.listRealtimeVoices(input.threadId); + }), + { scheduleIdleStopOnSuccess: true }, + ); + }); + const runStopAll = () => Effect.gen(function* () { const stoppedAt = new Date().toISOString(); @@ -1468,6 +1579,7 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => runtimeIdleTimers.clear(); runtimeIdleGenerations.clear(); runtimeIdleStopsInFlight.clear(); + activeRealtimeThreads.clear(); stopIdleRuntimeSession = null; }).pipe( Effect.andThen(runStopAll()), @@ -1491,12 +1603,18 @@ const makeProviderService = (options?: ProviderServiceLiveOptions) => getCapabilities, rollbackConversation, compactThread, + startRealtime, + stopRealtime, + listRealtimeVoices, // Each access creates a fresh PubSub subscription so that multiple // consumers (ProviderRuntimeIngestion, CheckpointReactor, etc.) each // independently receive all runtime events. get streamEvents(): ProviderServiceShape["streamEvents"] { return Stream.fromPubSub(runtimeEventPubSub); }, + get streamRealtimeEvents(): ProviderServiceShape["streamRealtimeEvents"] { + return Stream.fromPubSub(realtimeEventPubSub); + }, } satisfies ProviderServiceShape; }); diff --git a/apps/server/src/provider/Layers/ProviderSessionReaper.test.ts b/apps/server/src/provider/Layers/ProviderSessionReaper.test.ts index 3e542cd8a..95f5e8170 100644 --- a/apps/server/src/provider/Layers/ProviderSessionReaper.test.ts +++ b/apps/server/src/provider/Layers/ProviderSessionReaper.test.ts @@ -102,7 +102,11 @@ describe("ProviderSessionReaperLive", () => { getCapabilities: () => unsupported(), rollbackConversation: () => unsupported(), compactThread: () => unsupported(), + startRealtime: () => unsupported(), + stopRealtime: () => unsupported(), + listRealtimeVoices: () => unsupported(), streamEvents: Stream.empty, + streamRealtimeEvents: Stream.empty, }; const scope = await Effect.runPromise(Scope.make()); @@ -161,7 +165,11 @@ describe("ProviderSessionReaperLive", () => { getCapabilities: () => unsupported(), rollbackConversation: () => unsupported(), compactThread: () => unsupported(), + startRealtime: () => unsupported(), + stopRealtime: () => unsupported(), + listRealtimeVoices: () => unsupported(), streamEvents: Stream.empty, + streamRealtimeEvents: Stream.empty, }; const scope = await Effect.runPromise(Scope.make()); diff --git a/apps/server/src/provider/Services/ProviderAdapter.ts b/apps/server/src/provider/Services/ProviderAdapter.ts index 4540ed96b..5e81aad38 100644 --- a/apps/server/src/provider/Services/ProviderAdapter.ts +++ b/apps/server/src/provider/Services/ProviderAdapter.ts @@ -22,6 +22,7 @@ import type { ProviderListModelsResult, ProviderListPluginsInput, ProviderListPluginsResult, + ProviderListRealtimeVoicesResult, ProviderReadPluginInput, ProviderReadPluginResult, ProviderListSkillsResult, @@ -29,7 +30,9 @@ import type { ProviderStartReviewInput, ProviderUserInputAnswers, ProviderRuntimeEvent, + ProviderRealtimeEvent, ProviderSendTurnInput, + ProviderStartRealtimeInput, ProviderSteerTurnInput, ProviderSession, ProviderSessionStartInput, @@ -56,6 +59,7 @@ export interface ProviderAdapterCapabilities { readonly supportsTurnSteering?: boolean; /** True when `turn.diff.updated.payload.unifiedDiff` contains a parseable live patch. */ readonly supportsLiveTurnDiffPatch?: boolean; + readonly supportsRealtimeVoice?: boolean; } export interface ProviderThreadTurnSnapshot { @@ -208,6 +212,18 @@ export interface ProviderAdapterShape { */ readonly streamEvents: Stream.Stream; + /** + * Ephemeral realtime voice events. These are intentionally separate from + * canonical runtime events so SDP and transcript deltas are never persisted. + */ + readonly streamRealtimeEvents?: Stream.Stream; + + readonly startRealtime?: (input: ProviderStartRealtimeInput) => Effect.Effect; + readonly stopRealtime?: (threadId: ThreadId) => Effect.Effect; + readonly listRealtimeVoices?: ( + threadId: ThreadId, + ) => Effect.Effect; + /** * Read provider-specific composer capabilities. */ diff --git a/apps/server/src/provider/Services/ProviderService.ts b/apps/server/src/provider/Services/ProviderService.ts index a14d06193..fd5a1228d 100644 --- a/apps/server/src/provider/Services/ProviderService.ts +++ b/apps/server/src/provider/Services/ProviderService.ts @@ -16,11 +16,16 @@ import type { ProviderForkThreadResult, ProviderInterruptTurnInput, ProviderKind, + ProviderListRealtimeVoicesInput, + ProviderListRealtimeVoicesResult, + ProviderRealtimeEvent, ProviderRespondToRequestInput, ProviderRespondToUserInputInput, ProviderRuntimeEvent, ProviderSendTurnInput, ProviderStartReviewInput, + ProviderStartRealtimeInput, + ProviderStopRealtimeInput, ProviderSteerTurnInput, ProviderSession, ProviderSessionStartInput, @@ -150,12 +155,25 @@ export interface ProviderServiceShape { readonly threadId: ThreadId; }) => Effect.Effect; + readonly startRealtime: ( + input: ProviderStartRealtimeInput, + ) => Effect.Effect; + + readonly stopRealtime: ( + input: ProviderStopRealtimeInput, + ) => Effect.Effect; + + readonly listRealtimeVoices: ( + input: ProviderListRealtimeVoicesInput, + ) => Effect.Effect; + /** * Canonical provider runtime event stream. * * Fan-out is owned by ProviderService (not by a standalone event-bus service). */ readonly streamEvents: Stream.Stream; + readonly streamRealtimeEvents: Stream.Stream; } /** diff --git a/apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts b/apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts index 7bdad3916..e063a6e28 100644 --- a/apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts +++ b/apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts @@ -16,6 +16,67 @@ const mockAgentPath = path.join(__dirname, "../../../scripts/acp-mock-agent.ts") const bunExe = "bun"; describe("AcpSessionRuntime", () => { + it.effect("does not authenticate unless the adapter explicitly opts in", () => { + const requestEvents: Array = []; + return Effect.gen(function* () { + const runtime = yield* AcpSessionRuntime; + const started = yield* runtime.start(); + + expect(started.sessionId).toBe("mock-session-1"); + expect(requestEvents.some((event) => event.method === "authenticate")).toBe(false); + expect(requestEvents.some((event) => event.method === "session/new")).toBe(true); + }).pipe( + Effect.provide( + AcpSessionRuntime.layer({ + spawn: { + command: bunExe, + args: [mockAgentPath], + }, + cwd: process.cwd(), + clientInfo: { name: "t3-test", version: "0.0.0" }, + requestLogger: (event) => + Effect.sync(() => { + requestEvents.push(event); + }), + }), + ), + Effect.scoped, + Effect.provide(NodeServices.layer), + ); + }); + + it.effect("authenticates when the adapter explicitly opts in via authMethodId", () => { + const requestEvents: Array = []; + return Effect.gen(function* () { + const runtime = yield* AcpSessionRuntime; + const started = yield* runtime.start(); + + expect(started.sessionId).toBe("mock-session-1"); + expect(requestEvents.some((event) => event.method === "authenticate")).toBe(true); + }).pipe( + Effect.provide( + AcpSessionRuntime.layer({ + spawn: { + command: bunExe, + args: [mockAgentPath], + }, + cwd: process.cwd(), + clientInfo: { name: "t3-test", version: "0.0.0" }, + // Simulates an explicit, user-initiated connect action opting into + // authentication — mirrors what a real adapter's resolveAuthMethodId + // would do once the user asks to connect a provider. + authMethodId: "test", + requestLogger: (event) => + Effect.sync(() => { + requestEvents.push(event); + }), + }), + ), + Effect.scoped, + Effect.provide(NodeServices.layer), + ); + }); + it.effect("merges custom initialize client capabilities into the ACP handshake", () => { const requestEvents: Array = []; return Effect.gen(function* () { diff --git a/apps/server/src/provider/acp/AcpSessionRuntime.ts b/apps/server/src/provider/acp/AcpSessionRuntime.ts index 54757995a..537834147 100644 --- a/apps/server/src/provider/acp/AcpSessionRuntime.ts +++ b/apps/server/src/provider/acp/AcpSessionRuntime.ts @@ -435,25 +435,24 @@ const makeAcpSessionRuntime = ( ? yield* options.resolveAuthMethodId(initializeResult) : options.authMethodId; - if (!authMethodId) { - return yield* new EffectAcpErrors.AcpRequestError({ - code: -32602, - errorMessage: "ACP agent did not provide an authentication method.", - data: { authMethods: initializeResult.authMethods ?? [] }, - }); + // Authentication methods are interactive actions in ACP, not passive + // credential checks. Only invoke one when the adapter explicitly opts in. + // Providers with cached credentials can proceed directly to session setup; + // an unauthenticated provider then fails normally without TeaCode opening a + // login browser behind the user's back. + if (authMethodId) { + const authenticatePayload = { + methodId: authMethodId, + ...(options.authenticateMeta ? { _meta: options.authenticateMeta } : {}), + } satisfies EffectAcpSchema.AuthenticateRequest; + + yield* runLoggedRequest( + "authenticate", + authenticatePayload, + acp.agent.authenticate(authenticatePayload), + ); } - const authenticatePayload = { - methodId: authMethodId, - ...(options.authenticateMeta ? { _meta: options.authenticateMeta } : {}), - } satisfies EffectAcpSchema.AuthenticateRequest; - - yield* runLoggedRequest( - "authenticate", - authenticatePayload, - acp.agent.authenticate(authenticatePayload), - ); - let sessionId: string; let sessionSetupResult: | EffectAcpSchema.LoadSessionResponse diff --git a/apps/server/src/provider/acp/CursorAcpSupport.ts b/apps/server/src/provider/acp/CursorAcpSupport.ts index d32844748..619eabc00 100644 --- a/apps/server/src/provider/acp/CursorAcpSupport.ts +++ b/apps/server/src/provider/acp/CursorAcpSupport.ts @@ -106,8 +106,10 @@ export const makeCursorAcpRuntime = ( AcpSessionRuntime.layer({ ...input, spawn: buildCursorAcpSpawnInput(input.cursorSettings, input.cwd), - authMethodId: "cursor_login", - authenticateMeta: { headless: true }, + // `cursor_login` opens a browser when the CLI has no cached session. + // TeaCode must never trigger that interactive flow during automatic + // model discovery or thread startup. Users authenticate Cursor explicitly + // outside TeaCode; cached credentials are used by session/new directly. clientCapabilities: CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES, }).pipe( Layer.provide( diff --git a/apps/server/src/provider/acp/GrokAcpSupport.test.ts b/apps/server/src/provider/acp/GrokAcpSupport.test.ts index 3bfcc4554..0aa71fde2 100644 --- a/apps/server/src/provider/acp/GrokAcpSupport.test.ts +++ b/apps/server/src/provider/acp/GrokAcpSupport.test.ts @@ -1,11 +1,18 @@ -import { Effect } from "effect"; +import { Effect, Layer } from "effect"; import * as EffectAcpErrors from "effect-acp/errors"; import type * as EffectAcpSchema from "effect-acp/schema"; -import { afterEach, describe, expect, it } from "vitest"; +import { ChildProcessSpawner } from "effect/unstable/process"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { + AcpSessionRuntime, + type AcpSessionRuntimeOptions, + type AcpSessionRuntimeShape, +} from "./AcpSessionRuntime.ts"; import { applyGrokAcpModelSelection, buildGrokAcpSpawnInput, + makeGrokAcpRuntime, resolveGrokAcpAuthMethodId, } from "./GrokAcpSupport.ts"; @@ -33,6 +40,16 @@ describe("buildGrokAcpSpawnInput", () => { }); }); + it("does not restrict the Grok child process environment", () => { + // No `env` override means AcpSessionRuntime spawns Grok with the full + // parent process environment (see the spawn env merge in + // AcpSessionRuntime.ts). That is how an already-present XAI_API_KEY / + // GROK_CODE_XAI_API_KEY reaches the `grok` CLI passively — the same way it + // would if a user ran `grok` directly from a terminal — without TeaCode + // ever needing to call the ACP `authenticate` method. + expect(buildGrokAcpSpawnInput(undefined, "/tmp/project").env).toBeUndefined(); + }); + it("passes model and reasoning effort as Grok agent startup options", () => { expect( buildGrokAcpSpawnInput( @@ -123,6 +140,42 @@ describe("resolveGrokAcpAuthMethodId", () => { }); }); +describe("makeGrokAcpRuntime", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("never wires an auth method into the implicit session-start ACP runtime", async () => { + const fakeShape = {} as AcpSessionRuntimeShape; + let capturedOptions: AcpSessionRuntimeOptions | undefined; + vi.spyOn(AcpSessionRuntime, "layer").mockImplementation((options) => { + capturedOptions = options; + return Layer.succeed(AcpSessionRuntime, fakeShape); + }); + const spawnerThatMustNotBeCalled = { + spawn: () => { + throw new Error("child process spawner must not be invoked in this test"); + }, + } as unknown as ChildProcessSpawner.ChildProcessSpawner["Service"]; + + await Effect.runPromise( + makeGrokAcpRuntime({ + childProcessSpawner: spawnerThatMustNotBeCalled, + grokSettings: null, + cwd: "/tmp/project", + clientInfo: { name: "t3-test", version: "0.0.0" }, + }).pipe(Effect.scoped), + ); + + // Mirrors CursorAcpSupport: TeaCode must never call ACP `authenticate` as + // a side effect of automatic session startup, only when an adapter + // explicitly opts in (see the `authMethodId` gate in AcpSessionRuntime.ts). + expect(capturedOptions?.authMethodId).toBeUndefined(); + expect(capturedOptions?.resolveAuthMethodId).toBeUndefined(); + expect(capturedOptions?.authenticateMeta).toBeUndefined(); + }); +}); + describe("applyGrokAcpModelSelection", () => { it("does not call Grok's unsupported ACP config-option method", async () => { const calls: Array< diff --git a/apps/server/src/provider/acp/GrokAcpSupport.ts b/apps/server/src/provider/acp/GrokAcpSupport.ts index e7460ad61..cebf36d34 100644 --- a/apps/server/src/provider/acp/GrokAcpSupport.ts +++ b/apps/server/src/provider/acp/GrokAcpSupport.ts @@ -87,6 +87,16 @@ function availableAuthMethodIds( return new Set((initializeResult.authMethods ?? []).map((method) => method.id.trim())); } +// Exported for a future explicit, user-initiated "connect Grok" action only. +// `cached_token` is Grok CLI's fallback ACP auth method whenever no API key +// env var is set, and it is picked here purely based on the CLI *advertising* +// it in `initialize` — not on any confirmation that a token is actually cached +// on disk. Nothing in this codebase (and nothing vendored from xAI) proves +// that calling `authenticate({ methodId: "cached_token" })` is a passive +// no-op when no token is cached rather than a fallback interactive/browser +// login. Per the `authMethodId` gate in AcpSessionRuntime.ts, authenticate() +// must only run when an adapter explicitly opts in — do NOT wire this +// function into `makeGrokAcpRuntime`'s implicit session-start path. export const resolveGrokAcpAuthMethodId = ( initializeResult: EffectAcpSchema.InitializeResponse, ): Effect.Effect => @@ -116,8 +126,16 @@ export const makeGrokAcpRuntime = ( AcpSessionRuntime.layer({ ...input, spawn: buildGrokAcpSpawnInput(input.grokSettings, input.cwd), - resolveAuthMethodId: resolveGrokAcpAuthMethodId, - authenticateMeta: { headless: true }, + // Do not resolve/pass an auth method here: TeaCode must never trigger + // an interactive Grok login as a side effect of automatic session + // startup (see resolveGrokAcpAuthMethodId above and the `authMethodId` + // gate in AcpSessionRuntime.ts). A user's XAI_API_KEY / + // GROK_CODE_XAI_API_KEY still works without a browser: the `grok` + // child process inherits the full parent environment (see the spawn + // env merge in AcpSessionRuntime.ts) and reads the key itself, same as + // running `grok` directly from a terminal. A Grok CLI that truly has + // no cached credentials and no env key simply fails session/new with + // a normal error instead of TeaCode opening a login browser. }).pipe( Layer.provide( Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, input.childProcessSpawner), diff --git a/apps/server/src/wsRpc.ts b/apps/server/src/wsRpc.ts index 12610459f..271ee1511 100644 --- a/apps/server/src/wsRpc.ts +++ b/apps/server/src/wsRpc.ts @@ -49,6 +49,7 @@ import { makeImportThreadHandler } from "./orchestration/importThreadRoute"; import { makeListImportableDesktopThreadsHandler } from "./orchestration/listImportableDesktopThreadsRoute"; import { OrchestrationEngineService } from "./orchestration/Services/OrchestrationEngine"; import { ProjectionSnapshotQuery } from "./orchestration/Services/ProjectionSnapshotQuery"; +import { ProviderCommandReactor } from "./orchestration/Services/ProviderCommandReactor"; import { ProviderDiscoveryService } from "./provider/Services/ProviderDiscoveryService"; import { discoverSkillsCatalog, chitauriSkillsDir } from "./provider/skillsCatalog"; import { ProviderAdapterRegistry } from "./provider/Services/ProviderAdapterRegistry"; @@ -385,6 +386,7 @@ export const makeWsRpcLayer = () => const keybindings = yield* Keybindings; const open = yield* Open; const orchestrationEngine = yield* OrchestrationEngineService; + const providerCommandReactor = yield* ProviderCommandReactor; const path = yield* Path.Path; const profileStatsQuery = yield* ProfileStatsQuery; const projectionReadModelQuery = yield* ProjectionSnapshotQuery; @@ -1414,6 +1416,21 @@ export const makeWsRpcLayer = () => ), [WS_METHODS.providerCompactThread]: (input) => rpcEffect(providerService.compactThread(input), "Failed to compact thread"), + [WS_METHODS.providerStartRealtime]: (input) => + rpcEffect( + providerCommandReactor + .ensureSession(input.threadId) + .pipe(Effect.andThen(providerService.startRealtime(input))), + "Failed to start live voice", + ), + [WS_METHODS.providerStopRealtime]: (input) => + rpcEffect(providerService.stopRealtime(input), "Failed to stop live voice"), + [WS_METHODS.providerListRealtimeVoices]: (input) => + rpcEffect(providerService.listRealtimeVoices(input), "Failed to list live voice voices"), + [WS_METHODS.subscribeProviderRealtimeEvents]: () => + providerService.streamRealtimeEvents.pipe( + Stream.mapError((cause) => toWsRpcError(cause, "Live voice stream failed")), + ), [WS_METHODS.providerListCommands]: (input) => rpcEffect(providerDiscoveryService.listCommands(input), "Failed to list commands"), [WS_METHODS.providerListSkills]: (input) => diff --git a/apps/web/package.json b/apps/web/package.json index d163a53f7..667f08e58 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -54,6 +54,7 @@ "remark-math": "^6.0.0", "shadcn": "^4.8.3", "tailwind-merge": "^3.6.0", + "thinking-orbs": "file:/Users/jow/www/thinking-orbs", "tw-animate-css": "^1.4.0", "zustand": "^5.0.11" }, diff --git a/apps/web/src/appSettings.test.ts b/apps/web/src/appSettings.test.ts index c9bde5f8c..f3c91a5de 100644 --- a/apps/web/src/appSettings.test.ts +++ b/apps/web/src/appSettings.test.ts @@ -311,6 +311,25 @@ describe("sidebar sort defaults", () => { }); describe("normalizeStoredAppSettings", () => { + it("defaults new threads to remote-default worktrees", () => { + const decodedSettings = Schema.decodeSync(Schema.fromJsonString(AppSettingsSchema))("{}"); + + expect(decodedSettings.defaultNewThreadWorkspaceMode).toBe("worktree"); + expect(decodedSettings.defaultWorktreeBaseBranch).toBe(""); + }); + + it("preserves configured new-thread workspace defaults", () => { + const decodedSettings = Schema.decodeSync(Schema.fromJsonString(AppSettingsSchema))( + JSON.stringify({ + defaultNewThreadWorkspaceMode: "local", + defaultWorktreeBaseBranch: "release/next", + }), + ); + + expect(decodedSettings.defaultNewThreadWorkspaceMode).toBe("local"); + expect(decodedSettings.defaultWorktreeBaseBranch).toBe("release/next"); + }); + it("defaults native font smoothing by platform", () => { expect(getDefaultNativeFontSmoothing("MacIntel")).toBe(true); expect(getDefaultNativeFontSmoothing("Win32")).toBe(false); diff --git a/apps/web/src/appSettings.ts b/apps/web/src/appSettings.ts index 4ee188621..f501b4944 100644 --- a/apps/web/src/appSettings.ts +++ b/apps/web/src/appSettings.ts @@ -73,6 +73,9 @@ export const DEFAULT_TASK_LIST_DISPLAY_MODE: TaskListDisplayMode = "composer"; export const AppSnapChord = Schema.Literals(["option", "shift", "control", "command"]); export type AppSnapChord = typeof AppSnapChord.Type; export const DEFAULT_APP_SNAP_CHORD: AppSnapChord = "option"; +export const NewThreadWorkspaceMode = Schema.Literals(["worktree", "local"]); +export type NewThreadWorkspaceMode = typeof NewThreadWorkspaceMode.Type; +export const DEFAULT_NEW_THREAD_WORKSPACE_MODE: NewThreadWorkspaceMode = "worktree"; export const ChatHeaderControlIdSchema = Schema.Literals(DEFAULT_CHAT_HEADER_CONTROL_ORDER); @@ -180,6 +183,13 @@ export const AppSettingsSchema = Schema.Struct({ textGenerationModel: Schema.optional(TrimmedNonEmptyString), uiFontFamily: Schema.String.check(Schema.isMaxLength(256)).pipe(withDefaults(() => "")), defaultProvider: ProviderKind.pipe(withDefaults(() => "codex" as const)), + defaultNewThreadWorkspaceMode: NewThreadWorkspaceMode.pipe( + withDefaults(() => DEFAULT_NEW_THREAD_WORKSPACE_MODE), + ), + // Empty means "use the repository's remote default branch". + defaultWorktreeBaseBranch: Schema.String.check(Schema.isMaxLength(256)).pipe( + withDefaults(() => ""), + ), // Local-only UI preference: providers explicitly hidden from the composer picker. // The active/locked provider for a thread is always shown regardless, so users // never get stuck on a thread whose provider they later chose to hide. diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 8539cdb1d..f6e5d7434 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -65,6 +65,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { Debouncer } from "@tanstack/react-pacer"; import { useNavigate } from "@tanstack/react-router"; import { type LegendListRef } from "@legendapp/list/react"; +import { ThinkingOrb } from "thinking-orbs"; import { GIT_WORKING_TREE_DIFF_LIVE_REFETCH_INTERVAL_MS, gitBranchesQueryOptions, @@ -214,6 +215,7 @@ import { useThreadWorkspaceHandoff } from "../hooks/useThreadWorkspaceHandoff"; import { useComposerCommandMenuItems } from "../hooks/useComposerCommandMenuItems"; import { useThreadHandoff } from "../hooks/useThreadHandoff"; import { useTurnDiffSummaries } from "../hooks/useTurnDiffSummaries"; +import { useCodexVoiceSession } from "../hooks/useCodexVoiceSession"; import BranchToolbar from "./BranchToolbar"; import { ThreadWorktreeHandoffDialog } from "./ThreadWorktreeHandoffDialog"; import { @@ -234,8 +236,10 @@ import { XIcon, } from "~/lib/icons"; import { ComposerQueuedHeader } from "./chat/ComposerQueuedHeader"; +import { VoiceFocusSurface } from "./chat/VoiceFocusSurface"; import { ComposerLiveChangesHeader } from "./chat/ComposerLiveChangesHeader"; import { ProviderIcon } from "./ProviderIcon"; +import { ProviderUsageRingControl } from "./ProviderUsageMenuControl"; import { Button } from "./ui/button"; import { IconButton } from "./ui/icon-button"; import { Skeleton } from "./ui/skeleton"; @@ -349,6 +353,7 @@ import { ChatTranscriptPane } from "./chat/ChatTranscriptPane"; import type { MessagesTimelineController } from "./chat/MessagesTimeline"; import { buildTurnDiffSummaryByAssistantMessageId } from "./chat/MessagesTimeline.logic"; import { deriveAgentActivityTimelineState } from "./chat/agentActivity.logic"; +import { resolveVoiceOrbState } from "../lib/voiceFocus"; import { ComposerSlashStatusDialog } from "./chat/ComposerSlashStatusDialog"; import { ExpandedImagePreview } from "./chat/ExpandedImagePreview"; import { @@ -1496,6 +1501,11 @@ export default function ChatView({ : null; const selectedProvider: ProviderKind = lockedProvider ?? selectedProviderByThreadId ?? threadProvider ?? settings.defaultProvider; + // A draft Thread already has its final id. Voice startup promotes it to the + // server before opening realtime, so requiring a prior text turn here would + // make New Thread voice needlessly unavailable. + const voiceThreadId = selectedProvider === "codex" ? activeThreadId : null; + const voiceSession = useCodexVoiceSession(voiceThreadId); const previousSelectedProviderRef = useRef<{ threadId: ThreadId; provider: ProviderKind; @@ -2172,6 +2182,10 @@ export default function ChatView({ const isPreparingWorktree = activeWorktreeSetup !== null; const hasLiveTurn = phase === "running"; const isWorking = hasLiveTurn || isSendBusy || isConnecting || isRevertingCheckpoint; + const voiceOrbState = resolveVoiceOrbState({ + isWorking, + workEntries: agentActivityTimelineState.timelineWorkEntries, + }); const hasStreamingAssistantText = activeThread?.messages.some((message) => message.role === "assistant" && message.streaming) ?? false; @@ -2188,6 +2202,8 @@ export default function ChatView({ activeThreadId === null ? null : `${activeThreadId}:${activeLatestTurn?.turnId ?? "idle"}`; const activeTurnInProgress = activeTurnLayoutLive || keepSettledActiveTurnLayout; const isComposerApprovalState = activePendingApproval !== null; + const canStartVoice = + voiceThreadId !== null && pendingUserInputs.length === 0 && !activePendingApproval; const isComposerEditorDisabled = isConnecting || isComposerApprovalState; const canCollapsePastedTextToDraft = shouldEnableComposerPastedTextCollapse({ isComposerApprovalState, @@ -5499,6 +5515,121 @@ export default function ChatView({ return turnStartSucceeded; }; + const onStartVoice = useCallback(async () => { + const api = readNativeApi(); + if ( + !api || + !activeThread || + !activeProject || + !voiceThreadId || + selectedProvider !== "codex" || + isSendBusy || + isConnecting || + sendInFlightRef.current + ) { + return; + } + + const availability = await resolveProviderSendAvailabilityWithRefresh({ + provider: "codex", + statuses: providerStatuses, + refreshStatuses: () => refreshProviderStatuses({ silent: true }), + }); + if (!availability.usable) { + toastManager.add({ type: "error", title: availability.unavailableReason }); + return; + } + + sendInFlightRef.current = true; + beginLocalDispatch( + envMode === "worktree" && !activeThread.worktreePath + ? { worktreeSetupStepId: "prepare-thread", setupScriptName: null } + : undefined, + ); + + try { + let nextBranch = activeThread.branch; + let nextWorktreePath = activeThread.worktreePath; + + if (isLocalDraftThread) { + await promoteThreadCreate( + { + type: "thread.create", + commandId: newCommandId(), + threadId: voiceThreadId, + projectId: activeProject.id, + title: activeThread.title, + modelSelection: selectedModelSelection, + runtimeMode, + envMode, + branch: nextBranch, + worktreePath: nextWorktreePath, + lastKnownPr: activeThread.lastKnownPr ?? null, + createdAt: activeThread.createdAt, + }, + api, + ); + } + + if (envMode === "worktree" && !nextWorktreePath) { + const result = await api.workspace.provisionThreadWorktree({ + threadId: voiceThreadId, + baseBranch: nextBranch, + newBranch: buildTemporaryWorktreeBranchName(), + }); + nextBranch = result.branch; + nextWorktreePath = result.worktreePath; + setStoreThreadWorkspace(voiceThreadId, { + envMode: result.envMode, + branch: result.branch, + worktreePath: result.worktreePath, + associatedWorktreePath: result.associatedWorktreePath, + associatedWorktreeBranch: result.associatedWorktreeBranch, + associatedWorktreeRef: result.associatedWorktreeRef, + }); + } + + beginLocalDispatch(); + rememberCustomBinaryPathForDispatch({ + threadId: voiceThreadId, + provider: "codex", + providerOptions: providerOptionsForDispatch, + }); + await voiceSession.start(); + } catch (error) { + const description = error instanceof Error ? error.message : "Failed to start live voice."; + setThreadError(voiceThreadId, description); + toastManager.add({ + type: "error", + title: "Live voice unavailable", + description, + }); + } finally { + sendInFlightRef.current = false; + resetLocalDispatch(); + } + }, [ + activeProject, + activeThread, + beginLocalDispatch, + envMode, + isConnecting, + isLocalDraftThread, + isSendBusy, + providerOptionsForDispatch, + providerStatuses, + refreshProviderStatuses, + rememberCustomBinaryPathForDispatch, + resetLocalDispatch, + runtimeMode, + selectedModelSelection, + selectedProvider, + setStoreThreadWorkspace, + setThreadError, + voiceSession, + voiceThreadId, + ]); + const onRespondToApproval = useCallback( async (requestId: ApprovalRequestId, decision: ProviderApprovalDecision) => { const api = readNativeApi(); @@ -7569,6 +7700,7 @@ export default function ChatView({ showEmptyLandingBranchToolbar); const emptyLandingControls = showEmptyLandingControls ? (
+ {composerPickerControls} {isEmptyChatLanding ? ( + {canStartVoice && phase !== "running" && !voiceSession.isActive ? ( + void onStartVoice()} + > + + ) : null} {activePendingProgress ? ( + + + ) : ( + <> + + + + + {status === "ending" ? ( + + ) : ( + + )} + + + )} +
+ + + ); +} diff --git a/apps/web/src/composerDraftStore.ts b/apps/web/src/composerDraftStore.ts index 55703ccbe..498f24f93 100644 --- a/apps/web/src/composerDraftStore.ts +++ b/apps/web/src/composerDraftStore.ts @@ -1037,7 +1037,9 @@ function isGrokReasoningEffort(value: unknown): value is GrokReasoningEffort { return typeof value === "string" && GROK_REASONING_EFFORT_SET.has(value); } -function makeModelSelection( +// Exported so callers outside this store (e.g. the sidebar command palette) can build a +// well-typed `ModelSelection` for a provider/model pair without duplicating this switch. +export function makeModelSelection( provider: ProviderKind, model: string, options?: ProviderModelOptions[ProviderKind], diff --git a/apps/web/src/hooks/useCodexVoiceSession.ts b/apps/web/src/hooks/useCodexVoiceSession.ts new file mode 100644 index 000000000..3d6e61366 --- /dev/null +++ b/apps/web/src/hooks/useCodexVoiceSession.ts @@ -0,0 +1,277 @@ +import type { ProviderRealtimeEvent, ProviderRealtimeVoice, ThreadId } from "@t3tools/contracts"; +import { useCallback, useEffect, useRef, useState } from "react"; + +import { ensureNativeApi } from "../nativeApi"; +import { RealtimePcmPlayer } from "../lib/realtimeAudio"; + +export type CodexVoiceStatus = + | "idle" + | "connecting" + | "listening" + | "speaking" + | "muted" + | "ending" + | "error"; + +interface VoiceTranscript { + readonly user: string; + readonly assistant: string; +} + +function isAssistantRole(role: string): boolean { + const normalized = role.toLowerCase(); + return normalized === "assistant" || normalized === "agent"; +} + +export function useCodexVoiceSession(threadId: ThreadId | null) { + const [status, setStatus] = useState("idle"); + const [error, setError] = useState(null); + const [transcript, setTranscript] = useState({ + user: "", + assistant: "", + }); + + const statusRef = useRef("idle"); + const peerRef = useRef(null); + const dataChannelRef = useRef(null); + const localStreamRef = useRef(null); + const audioContextRef = useRef(null); + const remoteAudioElementRef = useRef(null); + const remoteTrackPlaybackReadyRef = useRef(false); + const pcmPlayerRef = useRef(null); + + const updateStatus = useCallback((next: CodexVoiceStatus) => { + statusRef.current = next; + setStatus(next); + }, []); + + const releaseMedia = useCallback(() => { + dataChannelRef.current?.close(); + dataChannelRef.current = null; + peerRef.current?.close(); + peerRef.current = null; + for (const track of localStreamRef.current?.getTracks() ?? []) { + track.stop(); + } + localStreamRef.current = null; + const remoteAudioElement = remoteAudioElementRef.current; + remoteAudioElementRef.current = null; + remoteTrackPlaybackReadyRef.current = false; + if (remoteAudioElement) { + remoteAudioElement.pause(); + remoteAudioElement.srcObject = null; + remoteAudioElement.remove(); + } + pcmPlayerRef.current?.stop(); + pcmPlayerRef.current = null; + const audioContext = audioContextRef.current; + audioContextRef.current = null; + if (audioContext && audioContext.state !== "closed") { + void audioContext.close(); + } + }, []); + + const finishLocally = useCallback( + (next: "idle" | "error", message?: string) => { + releaseMedia(); + updateStatus(next); + setError(message ?? null); + }, + [releaseMedia, updateStatus], + ); + + useEffect(() => { + if (!threadId) return; + const api = ensureNativeApi(); + const unsubscribe = api.provider.onRealtimeEvent((event: ProviderRealtimeEvent) => { + if (event.threadId !== threadId) return; + switch (event.type) { + case "started": + if (statusRef.current === "connecting") updateStatus("listening"); + return; + case "sdp": + void peerRef.current + ?.setRemoteDescription({ type: "answer", sdp: event.sdp }) + .then(() => updateStatus("listening")) + .catch((cause: unknown) => { + finishLocally( + "error", + cause instanceof Error ? cause.message : "Could not connect live voice audio.", + ); + }); + return; + case "transcript.delta": + if (statusRef.current !== "muted") { + updateStatus(isAssistantRole(event.role) ? "speaking" : "listening"); + } + setTranscript((current) => + isAssistantRole(event.role) + ? { ...current, assistant: `${current.assistant}${event.delta}` } + : { ...current, user: `${current.user}${event.delta}` }, + ); + return; + case "transcript.done": + setTranscript((current) => + isAssistantRole(event.role) + ? { ...current, assistant: event.text } + : { ...current, user: event.text }, + ); + return; + case "audio.delta": + if (!remoteTrackPlaybackReadyRef.current && pcmPlayerRef.current?.enqueue(event.audio)) { + updateStatus("speaking"); + } + return; + case "error": + finishLocally("error", event.message); + return; + case "closed": + // App-server emits `closed` immediately after a realtime error. Keep + // the specific error visible instead of letting the terminal event + // erase it and drop the user back into the normal transcript. + if (statusRef.current === "error") return; + finishLocally("idle"); + return; + } + }); + + return () => { + unsubscribe(); + if (statusRef.current !== "idle") { + void api.provider.stopRealtime({ threadId }).catch(() => undefined); + } + releaseMedia(); + statusRef.current = "idle"; + }; + }, [finishLocally, releaseMedia, threadId, updateStatus]); + + const start = useCallback( + async (voice?: ProviderRealtimeVoice) => { + if (!threadId || (statusRef.current !== "idle" && statusRef.current !== "error")) { + return; + } + if (!navigator.mediaDevices?.getUserMedia || typeof RTCPeerConnection === "undefined") { + finishLocally("error", "Live voice is not supported by this browser."); + return; + } + + updateStatus("connecting"); + setError(null); + setTranscript({ user: "", assistant: "" }); + + try { + const remoteAudioElement = new Audio(); + remoteAudioElement.autoplay = true; + remoteAudioElement.volume = 1; + remoteAudioElement.setAttribute("aria-hidden", "true"); + remoteAudioElement.setAttribute("playsinline", ""); + remoteAudioElement.style.display = "none"; + document.body.append(remoteAudioElement); + remoteAudioElementRef.current = remoteAudioElement; + + const stream = await navigator.mediaDevices.getUserMedia({ + audio: { + echoCancellation: true, + noiseSuppression: true, + autoGainControl: true, + }, + }); + localStreamRef.current = stream; + + const peer = new RTCPeerConnection(); + peerRef.current = peer; + for (const track of stream.getAudioTracks()) { + peer.addTrack(track, stream); + } + dataChannelRef.current = peer.createDataChannel("oai-events"); + + const AudioContextConstructor = + window.AudioContext ?? + ( + window as typeof window & { + webkitAudioContext?: typeof AudioContext; + } + ).webkitAudioContext; + if (!AudioContextConstructor) { + throw new Error("Live voice audio is not supported by this browser."); + } + const audioContext = new AudioContextConstructor(); + audioContextRef.current = audioContext; + await audioContext.resume(); + + pcmPlayerRef.current = new RealtimePcmPlayer(audioContext, audioContext.destination); + + peer.ontrack = (event) => { + const remoteStream = event.streams[0] ?? new MediaStream([event.track]); + remoteAudioElement.srcObject = remoteStream; + void remoteAudioElement + .play() + .then(() => { + remoteTrackPlaybackReadyRef.current = true; + }) + .catch((cause: unknown) => { + finishLocally( + "error", + cause instanceof Error + ? `Could not play live voice audio: ${cause.message}` + : "Could not play live voice audio.", + ); + }); + }; + + peer.onconnectionstatechange = () => { + if (peer.connectionState === "failed" || peer.connectionState === "disconnected") { + finishLocally("error", "The live voice connection was lost."); + } + }; + + const offer = await peer.createOffer(); + await peer.setLocalDescription(offer); + if (!offer.sdp) { + throw new Error("The browser did not create a live voice offer."); + } + await ensureNativeApi().provider.startRealtime({ + threadId, + sdp: offer.sdp, + ...(voice ? { voice } : {}), + }); + } catch (cause) { + finishLocally( + "error", + cause instanceof Error ? cause.message : "Could not start live voice.", + ); + } + }, + [finishLocally, threadId, updateStatus], + ); + + const stop = useCallback(async () => { + if (!threadId || statusRef.current === "idle" || statusRef.current === "ending") return; + updateStatus("ending"); + try { + await ensureNativeApi().provider.stopRealtime({ threadId }); + finishLocally("idle"); + } catch (cause) { + finishLocally("error", cause instanceof Error ? cause.message : "Could not stop live voice."); + } + }, [finishLocally, threadId, updateStatus]); + + const toggleMute = useCallback(() => { + const track = localStreamRef.current?.getAudioTracks()[0]; + if (!track) return; + track.enabled = !track.enabled; + updateStatus(track.enabled ? "listening" : "muted"); + }, [updateStatus]); + + return { + status, + error, + transcript, + isActive: status !== "idle", + isMuted: status === "muted", + start, + stop, + toggleMute, + dismissError: () => finishLocally("idle"), + }; +} diff --git a/apps/web/src/hooks/useHandleNewThread.ts b/apps/web/src/hooks/useHandleNewThread.ts index 1a73b0ff0..104960922 100644 --- a/apps/web/src/hooks/useHandleNewThread.ts +++ b/apps/web/src/hooks/useHandleNewThread.ts @@ -9,6 +9,7 @@ import { useComposerDraftStore, } from "../composerDraftStore"; import { + applyNewThreadWorkspaceDefaults, buildDraftThreadContextPatch, createActiveDraftThreadSnapshot, createActiveThreadSnapshot, @@ -45,6 +46,7 @@ export function useHandleNewThread() { options?: NewThreadOptions, navigation?: NewThreadNavigationOptions, ): Promise => { + const resolvedOptions = applyNewThreadWorkspaceDefaults(options, settings); const navigateToThread = (threadId: ThreadId) => navigation?.navigate ? navigation.navigate(threadId) @@ -181,8 +183,8 @@ export function useHandleNewThread() { ...createFreshDraftThreadSeed({ createdAt, options: { - ...options, - runtimeMode: options?.runtimeMode ?? settings.defaultRuntimeMode, + ...resolvedOptions, + runtimeMode: resolvedOptions.runtimeMode ?? settings.defaultRuntimeMode, }, }), }); @@ -193,7 +195,13 @@ export function useHandleNewThread() { return threadId; })(); }, - [navigate, focusedThreadId, settings.defaultRuntimeMode], + [ + navigate, + focusedThreadId, + settings.defaultNewThreadWorkspaceMode, + settings.defaultRuntimeMode, + settings.defaultWorktreeBaseBranch, + ], ); return { diff --git a/apps/web/src/lib/icons.tsx b/apps/web/src/lib/icons.tsx index 809dd0226..9dca676e1 100644 --- a/apps/web/src/lib/icons.tsx +++ b/apps/web/src/lib/icons.tsx @@ -53,6 +53,7 @@ import { LockClosedIcon as HeroLockClosedIcon, LockOpenIcon as HeroLockOpenIcon, MinusIcon as HeroMinusIcon, + MicrophoneIcon as HeroMicrophoneIcon, MoonIcon as HeroMoonIcon, PaperClipIcon as HeroPaperClipIcon, PlayIcon as HeroPlayIcon, @@ -215,6 +216,7 @@ export const WebSearchIcon: LucideIcon = centralIconWrapper("globe"); export const McpIcon: LucideIcon = (props) => ( ); +export const MicrophoneIcon = heroIcon(HeroMicrophoneIcon); export const PluginIcon: LucideIcon = centralIconWrapper("puzzle"); // Single hammer/build glyph (tool-call rows, codex provider, "build" scripts). // Sourced from the Central set so it matches the other work-row icons (pencil, diff --git a/apps/web/src/lib/realtimeAudio.test.ts b/apps/web/src/lib/realtimeAudio.test.ts new file mode 100644 index 000000000..4659ecc3b --- /dev/null +++ b/apps/web/src/lib/realtimeAudio.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, it } from "vitest"; + +import { decodePcm16AudioChunk } from "./realtimeAudio"; + +function pcm16Base64(samples: ReadonlyArray): string { + const bytes = new Uint8Array(samples.length * Int16Array.BYTES_PER_ELEMENT); + const view = new DataView(bytes.buffer); + for (const [index, sample] of samples.entries()) { + view.setInt16(index * Int16Array.BYTES_PER_ELEMENT, sample, true); + } + return Buffer.from(bytes).toString("base64"); +} + +describe("decodePcm16AudioChunk", () => { + it("decodes interleaved little-endian PCM16 channels", () => { + const decoded = decodePcm16AudioChunk({ + data: pcm16Base64([0, 16_384, -32_768, 32_767]), + sampleRate: 24_000, + numChannels: 2, + samplesPerChannel: 2, + }); + + expect(decoded?.sampleRate).toBe(24_000); + expect(Array.from(decoded?.channels[0] ?? [])).toEqual([0, -1]); + expect(Array.from(decoded?.channels[1] ?? [])).toEqual([0.5, 32_767 / 32_768]); + }); + + it("rejects malformed base64 and empty frames", () => { + expect( + decodePcm16AudioChunk({ + data: "not base64", + sampleRate: 24_000, + numChannels: 1, + }), + ).toBeNull(); + expect( + decodePcm16AudioChunk({ + data: "", + sampleRate: 24_000, + numChannels: 1, + }), + ).toBeNull(); + }); +}); diff --git a/apps/web/src/lib/realtimeAudio.ts b/apps/web/src/lib/realtimeAudio.ts new file mode 100644 index 000000000..aba5f1ede --- /dev/null +++ b/apps/web/src/lib/realtimeAudio.ts @@ -0,0 +1,108 @@ +import type { ProviderRealtimeAudioChunk } from "@t3tools/contracts"; + +export interface DecodedPcm16Audio { + readonly sampleRate: number; + readonly channels: ReadonlyArray>; +} + +const PCM16_SCALE = 32_768; +const INITIAL_PLAYBACK_BUFFER_SECONDS = 0.03; + +export function decodePcm16AudioChunk(audio: ProviderRealtimeAudioChunk): DecodedPcm16Audio | null { + let encoded: string; + try { + encoded = atob(audio.data); + } catch { + return null; + } + + const bytesPerFrame = audio.numChannels * Int16Array.BYTES_PER_ELEMENT; + if (bytesPerFrame <= 0) return null; + const availableFrames = Math.floor(encoded.length / bytesPerFrame); + const frameCount = Math.min(audio.samplesPerChannel ?? availableFrames, availableFrames); + if (frameCount <= 0) return null; + + const bytes = new Uint8Array(encoded.length); + for (let index = 0; index < encoded.length; index += 1) { + bytes[index] = encoded.charCodeAt(index); + } + const samples = new DataView(bytes.buffer); + const channels = Array.from( + { length: audio.numChannels }, + () => new Float32Array(new ArrayBuffer(frameCount * Float32Array.BYTES_PER_ELEMENT)), + ); + + for (let frame = 0; frame < frameCount; frame += 1) { + for (let channel = 0; channel < audio.numChannels; channel += 1) { + const byteOffset = (frame * audio.numChannels + channel) * Int16Array.BYTES_PER_ELEMENT; + channels[channel]![frame] = samples.getInt16(byteOffset, true) / PCM16_SCALE; + } + } + + return { + sampleRate: audio.sampleRate, + channels, + }; +} + +export class RealtimePcmPlayer { + readonly #context: AudioContext; + readonly #destination: AudioNode; + readonly #sources = new Set(); + #nextPlaybackTime = 0; + + constructor(context: AudioContext, destination: AudioNode) { + this.#context = context; + this.#destination = destination; + } + + enqueue(audio: ProviderRealtimeAudioChunk): boolean { + const decoded = decodePcm16AudioChunk(audio); + if (!decoded) return false; + + const frameCount = decoded.channels[0]?.length ?? 0; + if (frameCount === 0) return false; + + const buffer = this.#context.createBuffer( + decoded.channels.length, + frameCount, + decoded.sampleRate, + ); + for (const [channel, samples] of decoded.channels.entries()) { + buffer.copyToChannel(samples, channel); + } + + const source = this.#context.createBufferSource(); + source.buffer = buffer; + source.connect(this.#destination); + source.onended = () => { + source.disconnect(); + this.#sources.delete(source); + }; + this.#sources.add(source); + + const startAt = Math.max( + this.#nextPlaybackTime, + this.#context.currentTime + INITIAL_PLAYBACK_BUFFER_SECONDS, + ); + source.start(startAt); + this.#nextPlaybackTime = startAt + buffer.duration; + if (this.#context.state === "suspended") { + void this.#context.resume(); + } + return true; + } + + stop(): void { + for (const source of this.#sources) { + try { + source.stop(); + } catch { + // The source may already have ended between iteration and stop. + } + source.disconnect(); + } + this.#sources.clear(); + this.#nextPlaybackTime = 0; + } +} diff --git a/apps/web/src/lib/threadBootstrap.test.ts b/apps/web/src/lib/threadBootstrap.test.ts index cd7d5b633..08ea3ce80 100644 --- a/apps/web/src/lib/threadBootstrap.test.ts +++ b/apps/web/src/lib/threadBootstrap.test.ts @@ -2,6 +2,7 @@ import { ProjectId, type ModelSelection, ThreadId } from "@t3tools/contracts"; import { describe, expect, it } from "vitest"; import { type ComposerThreadDraftState, type DraftThreadState } from "../composerDraftStore"; import { + applyNewThreadWorkspaceDefaults, buildDraftThreadContextPatch, createActiveDraftThreadSnapshot, createActiveThreadSnapshot, @@ -255,6 +256,50 @@ describe("threadBootstrap", () => { ).toMatchObject({ envMode: "worktree", branch: null, worktreePath: null }); }); + it("applies a configured worktree base branch to a new thread", () => { + expect( + applyNewThreadWorkspaceDefaults(undefined, { + defaultNewThreadWorkspaceMode: "worktree", + defaultWorktreeBaseBranch: " release/next ", + }), + ).toMatchObject({ + envMode: "worktree", + branch: "release/next", + }); + }); + + it("can default a new thread to the current checkout", () => { + expect( + applyNewThreadWorkspaceDefaults(undefined, { + defaultNewThreadWorkspaceMode: "local", + defaultWorktreeBaseBranch: "main", + }), + ).toMatchObject({ + envMode: "local", + branch: null, + }); + }); + + it("keeps explicit thread workspace choices ahead of app defaults", () => { + expect( + applyNewThreadWorkspaceDefaults( + { + envMode: "worktree", + branch: "feature/explicit", + worktreePath: "/repo/.worktrees/explicit", + }, + { + defaultNewThreadWorkspaceMode: "local", + defaultWorktreeBaseBranch: "main", + }, + ), + ).toMatchObject({ + envMode: "worktree", + branch: "feature/explicit", + worktreePath: "/repo/.worktrees/explicit", + }); + }); + it("keeps an explicit local picker override ahead of the worktree default", () => { expect( createFreshDraftThreadSeed({ diff --git a/apps/web/src/lib/threadBootstrap.ts b/apps/web/src/lib/threadBootstrap.ts index bd4b39fc6..654a1e0b0 100644 --- a/apps/web/src/lib/threadBootstrap.ts +++ b/apps/web/src/lib/threadBootstrap.ts @@ -20,6 +20,7 @@ import { type DraftThreadState, resolvePreferredComposerModelSelection, } from "../composerDraftStore"; +import type { AppSettings, NewThreadWorkspaceMode } from "../appSettings"; import { type Thread } from "../types"; export interface NewThreadOptions { @@ -39,6 +40,28 @@ export interface NewThreadOptions { */ export const DEFAULT_NEW_THREAD_ENV_MODE = "worktree" as const satisfies DraftThreadEnvMode; +export function applyNewThreadWorkspaceDefaults( + options: NewThreadOptions | undefined, + settings: Pick, +): NewThreadOptions { + const hasPinnedWorktree = Boolean(options?.worktreePath); + const envMode: NewThreadWorkspaceMode = + options?.envMode ?? (hasPinnedWorktree ? "worktree" : settings.defaultNewThreadWorkspaceMode); + const defaultBaseBranch = settings.defaultWorktreeBaseBranch.trim(); + const branch = + options?.branch !== undefined + ? options.branch + : envMode === "worktree" && defaultBaseBranch.length > 0 + ? defaultBaseBranch + : null; + + return { + ...options, + envMode, + branch, + }; +} + export interface InheritedThreadContext { branch: string | null; worktreePath: string | null; diff --git a/apps/web/src/lib/voiceFocus.test.ts b/apps/web/src/lib/voiceFocus.test.ts new file mode 100644 index 000000000..b5d8428af --- /dev/null +++ b/apps/web/src/lib/voiceFocus.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "vitest"; + +import { resolveVoiceOrbState } from "./voiceFocus"; + +describe("resolveVoiceOrbState", () => { + it("uses thinking for idle and non-working states", () => { + expect(resolveVoiceOrbState({ isWorking: false, workEntries: [] })).toBe("thinking"); + }); + + it("uses solving while the thread is working", () => { + expect(resolveVoiceOrbState({ isWorking: true, workEntries: [] })).toBe("solving"); + }); + + it("lets an active search override the generic working state", () => { + expect( + resolveVoiceOrbState({ + isWorking: true, + workEntries: [ + { + activityKind: "tool.updated", + label: "Searching", + toolName: "rg", + }, + ], + }), + ).toBe("searching"); + }); + + it("does not keep searching after the search tool completes", () => { + expect( + resolveVoiceOrbState({ + isWorking: true, + workEntries: [ + { + activityKind: "tool.completed", + label: "Searched", + toolName: "rg", + }, + ], + }), + ).toBe("solving"); + }); +}); diff --git a/apps/web/src/lib/voiceFocus.ts b/apps/web/src/lib/voiceFocus.ts new file mode 100644 index 000000000..bf2a378da --- /dev/null +++ b/apps/web/src/lib/voiceFocus.ts @@ -0,0 +1,32 @@ +export type VoiceOrbState = "thinking" | "solving" | "searching"; + +interface VoiceWorkEntry { + readonly activityKind?: string; + readonly label: string; + readonly toolTitle?: string; + readonly toolName?: string; + readonly command?: string; +} + +const ACTIVE_TOOL_ACTIVITY_KINDS = new Set(["tool.started", "tool.updated"]); +const SEARCH_ACTIVITY_PATTERN = /\b(?:search|searching|find|finding|grep|rg)\b/i; + +export function isActiveVoiceSearch(entry: VoiceWorkEntry): boolean { + if (!entry.activityKind || !ACTIVE_TOOL_ACTIVITY_KINDS.has(entry.activityKind)) { + return false; + } + + return SEARCH_ACTIVITY_PATTERN.test( + [entry.toolTitle, entry.label, entry.toolName, entry.command].filter(Boolean).join(" "), + ); +} + +export function resolveVoiceOrbState(input: { + readonly isWorking: boolean; + readonly workEntries: ReadonlyArray; +}): VoiceOrbState { + if (input.workEntries.some(isActiveVoiceSearch)) { + return "searching"; + } + return input.isWorking ? "solving" : "thinking"; +} diff --git a/apps/web/src/routes/_chat.settings.tsx b/apps/web/src/routes/_chat.settings.tsx index 2eced83b6..b11d6ea2b 100644 --- a/apps/web/src/routes/_chat.settings.tsx +++ b/apps/web/src/routes/_chat.settings.tsx @@ -237,6 +237,20 @@ const TASK_LIST_DISPLAY_OPTIONS = [ label: string; }>; +const NEW_THREAD_WORKSPACE_OPTIONS = [ + { + value: "worktree", + label: "New worktree", + }, + { + value: "local", + label: "Current branch", + }, +] as const satisfies ReadonlyArray<{ + value: AppSettings["defaultNewThreadWorkspaceMode"]; + label: string; +}>; + const PROVIDER_SELECT_OPTIONS = [ "codex", "claudeAgent", @@ -1916,6 +1930,60 @@ function SettingsRouteView() { } /> + + updateSettings({ + defaultNewThreadWorkspaceMode: defaults.defaultNewThreadWorkspaceMode, + }) + } + /> + ) : null + } + control={ + updateSettings({ defaultNewThreadWorkspaceMode: value })} + options={NEW_THREAD_WORKSPACE_OPTIONS} + ariaLabel="New thread workspace" + /> + } + /> + + updateSettings({ + defaultWorktreeBaseBranch: defaults.defaultWorktreeBaseBranch, + }) + } + /> + ) : null + } + control={ + updateSettings({ defaultWorktreeBaseBranch: value.trim() })} + placeholder="Remote default" + aria-label="Default worktree base branch" + disabled={settings.defaultNewThreadWorkspaceMode !== "worktree"} + className="w-full sm:w-44" + /> + } + /> diff --git a/apps/web/src/settingsSearchIndex.ts b/apps/web/src/settingsSearchIndex.ts index c52cf23d0..adc20850b 100644 --- a/apps/web/src/settingsSearchIndex.ts +++ b/apps/web/src/settingsSearchIndex.ts @@ -57,6 +57,18 @@ export const SETTINGS_SEARCH_ENTRIES: readonly SettingsSearchEntry[] = [ title: "Default provider", keywords: "Choose the provider used for new chats. agent codex claude", }, + { + id: "general:new-thread-workspace", + section: "general", + title: "New thread workspace", + keywords: "new worktree current branch checkout default thread workspace isolation", + }, + { + id: "general:worktree-base-branch", + section: "general", + title: "Worktree base branch", + keywords: "default branch origin remote main master new worktree base", + }, { id: "general:permissions-mode", section: "permissions", diff --git a/apps/web/src/wsNativeApi.test.ts b/apps/web/src/wsNativeApi.test.ts index 01ddf8000..7bd97b44f 100644 --- a/apps/web/src/wsNativeApi.test.ts +++ b/apps/web/src/wsNativeApi.test.ts @@ -380,6 +380,29 @@ describe("wsNativeApi", () => { }); }); + it("subscribes to ephemeral realtime events only while voice listeners exist", async () => { + const { createWsNativeApi } = await import("./wsNativeApi"); + const api = createWsNativeApi(); + const listener = vi.fn(); + + expect(channelListeners.has(WS_CHANNELS.providerRealtimeEvent)).toBe(false); + const unsubscribe = api.provider.onRealtimeEvent(listener); + expect(channelListeners.has(WS_CHANNELS.providerRealtimeEvent)).toBe(true); + + const event = { + type: "transcript.delta", + threadId: ThreadId.makeUnsafe("thread-voice"), + createdAt: "2026-07-23T00:00:00.000Z", + role: "assistant", + delta: "Hello", + } as const; + emitPush(WS_CHANNELS.providerRealtimeEvent, event); + + expect(listener).toHaveBeenCalledWith(event); + unsubscribe(); + expect(channelListeners.has(WS_CHANNELS.providerRealtimeEvent)).toBe(false); + }); + it("wraps orchestration dispatch commands in the command envelope", async () => { requestMock.mockResolvedValue(undefined); const { createWsNativeApi } = await import("./wsNativeApi"); diff --git a/apps/web/src/wsNativeApi.ts b/apps/web/src/wsNativeApi.ts index eeff74b89..4437f594d 100644 --- a/apps/web/src/wsNativeApi.ts +++ b/apps/web/src/wsNativeApi.ts @@ -20,6 +20,7 @@ import { type OrchestrationShellStreamItem, type OrchestrationThreadStreamItem, type ProjectDevServerEvent, + type ProviderRealtimeEvent, type ServerProviderStatusesUpdatedPayload, type ServerLifecycleStreamEvent, type ServerSettingsUpdatedPayload, @@ -47,6 +48,8 @@ const serverProviderStatusesUpdatedListeners = new Set< const serverMaintenanceUpdatedListeners = new Set<(payload: ServerLifecycleStreamEvent) => void>(); const serverSettingsUpdatedListeners = new Set<(payload: ServerSettingsUpdatedPayload) => void>(); const gitActionProgressListeners = new Set<(payload: GitActionProgressEvent) => void>(); +const providerRealtimeEventListeners = new Set<(payload: ProviderRealtimeEvent) => void>(); +let providerRealtimeEventUnsubscribe: (() => void) | null = null; function omitNullUserInputAnswers( command: Parameters[0], @@ -529,6 +532,32 @@ export function createWsNativeApi(): NativeApi { getComposerCapabilities: (input) => transport.request(WS_METHODS.providerGetComposerCapabilities, input), compactThread: (input) => transport.request(WS_METHODS.providerCompactThread, input), + startRealtime: (input) => transport.request(WS_METHODS.providerStartRealtime, input), + stopRealtime: (input) => transport.request(WS_METHODS.providerStopRealtime, input), + listRealtimeVoices: (input) => + transport.request(WS_METHODS.providerListRealtimeVoices, input), + onRealtimeEvent: (callback) => { + providerRealtimeEventListeners.add(callback); + providerRealtimeEventUnsubscribe ??= transport.subscribe( + WS_CHANNELS.providerRealtimeEvent, + (message) => { + for (const listener of providerRealtimeEventListeners) { + try { + listener(message.data); + } catch { + // Listener errors must not break the shared voice stream. + } + } + }, + ); + return () => { + providerRealtimeEventListeners.delete(callback); + if (providerRealtimeEventListeners.size === 0) { + providerRealtimeEventUnsubscribe?.(); + providerRealtimeEventUnsubscribe = null; + } + }; + }, listCommands: (input) => transport.request(WS_METHODS.providerListCommands, input), listSkills: (input) => transport.request(WS_METHODS.providerListSkills, input), listSkillsCatalog: (input) => transport.request(WS_METHODS.providerListSkillsCatalog, input), @@ -616,6 +645,9 @@ export function resetWsNativeApiForTest(): void { serverMaintenanceUpdatedListeners.clear(); serverSettingsUpdatedListeners.clear(); gitActionProgressListeners.clear(); + providerRealtimeEventUnsubscribe?.(); + providerRealtimeEventUnsubscribe = null; + providerRealtimeEventListeners.clear(); projectDevServerEventListeners.clear(); orchestrationDomainEventUnsubscribe = null; orchestrationDomainEventListeners.clear(); @@ -632,6 +664,9 @@ if (import.meta.hot) { serverProviderStatusesUpdatedListeners.clear(); serverSettingsUpdatedListeners.clear(); gitActionProgressListeners.clear(); + providerRealtimeEventUnsubscribe?.(); + providerRealtimeEventUnsubscribe = null; + providerRealtimeEventListeners.clear(); projectDevServerEventListeners.clear(); orchestrationDomainEventUnsubscribe = null; orchestrationDomainEventListeners.clear(); diff --git a/apps/web/src/wsTransport.ts b/apps/web/src/wsTransport.ts index 53c057a84..f128d8603 100644 --- a/apps/web/src/wsTransport.ts +++ b/apps/web/src/wsTransport.ts @@ -15,6 +15,7 @@ import { type OrchestrationShellStreamItem, type OrchestrationThreadStreamItem, type ProjectDevServerEvent, + type ProviderRealtimeEvent, type ServerConfigStreamEvent, type ServerLifecycleStreamEvent, type ServerProviderStatusesUpdatedPayload, @@ -417,6 +418,13 @@ export class WsTransport { (event: ProjectDevServerEvent) => this.emit(WS_CHANNELS.projectDevServerEvent, event), restartChannel, ); + } else if (channel === WS_CHANNELS.providerRealtimeEvent) { + this.startStream( + "provider.realtime", + client[WS_METHODS.subscribeProviderRealtimeEvents]({}), + (event: ProviderRealtimeEvent) => this.emit(WS_CHANNELS.providerRealtimeEvent, event), + restartChannel, + ); } else if (channel === ORCHESTRATION_WS_CHANNELS.domainEvent) { this.startStream( "orchestration.domain", @@ -442,6 +450,7 @@ export class WsTransport { this.stopStream("server.providers"); else if (channel === WS_CHANNELS.serverSettingsUpdated) this.stopStream("server.settings"); else if (channel === WS_CHANNELS.projectDevServerEvent) this.stopStream("project.devServers"); + else if (channel === WS_CHANNELS.providerRealtimeEvent) this.stopStream("provider.realtime"); else if (channel === ORCHESTRATION_WS_CHANNELS.domainEvent) this.stopStream("orchestration.domain"); } diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 860b6a8eb..c87d6c812 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -139,6 +139,11 @@ export default defineConfig({ }, resolve: { tsconfigPaths: true, + // Local file-linked React packages (for example thinking-orbs) may have + // their own development copy of React next to their source checkout. + // Always render them with TeaCode's React instance so hooks share the + // same dispatcher. + dedupe: ["react", "react-dom"], }, server: { port, diff --git a/bun.lock b/bun.lock index 3e234f0fe..acfd2ff8d 100644 --- a/bun.lock +++ b/bun.lock @@ -14,7 +14,7 @@ }, "apps/desktop": { "name": "@t3tools/desktop", - "version": "0.9.9", + "version": "0.11.0", "dependencies": { "effect": "catalog:", "electron": "40.6.0", @@ -43,7 +43,7 @@ }, "apps/server": { "name": "t3", - "version": "0.9.9", + "version": "0.11.0", "bin": { "t3": "./dist/index.mjs", }, @@ -83,7 +83,7 @@ }, "apps/web": { "name": "@t3tools/web", - "version": "0.9.9", + "version": "0.11.0", "dependencies": { "@base-ui/react": "^1.5.0", "@dnd-kit/core": "^6.3.1", @@ -125,6 +125,7 @@ "remark-math": "^6.0.0", "shadcn": "^4.8.3", "tailwind-merge": "^3.6.0", + "thinking-orbs": "file:/Users/jow/www/thinking-orbs", "tw-animate-css": "^1.4.0", "zustand": "^5.0.11", }, @@ -150,7 +151,7 @@ }, "packages/contracts": { "name": "@t3tools/contracts", - "version": "0.9.9", + "version": "0.11.0", "dependencies": { "effect": "catalog:", }, @@ -382,6 +383,10 @@ "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ=="], + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw=="], + + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q=="], + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-syntax-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw=="], "@babel/preset-typescript": ["@babel/preset-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ=="], @@ -686,6 +691,14 @@ "@mariozechner/clipboard-win32-x64-msvc": ["@mariozechner/clipboard-win32-x64-msvc@0.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA=="], + "@microsoft/api-extractor": ["@microsoft/api-extractor@7.43.0", "", { "dependencies": { "@microsoft/api-extractor-model": "7.28.13", "@microsoft/tsdoc": "0.14.2", "@microsoft/tsdoc-config": "~0.16.1", "@rushstack/node-core-library": "4.0.2", "@rushstack/rig-package": "0.5.2", "@rushstack/terminal": "0.10.0", "@rushstack/ts-command-line": "4.19.1", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", "typescript": "5.4.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w=="], + + "@microsoft/api-extractor-model": ["@microsoft/api-extractor-model@7.28.13", "", { "dependencies": { "@microsoft/tsdoc": "0.14.2", "@microsoft/tsdoc-config": "~0.16.1", "@rushstack/node-core-library": "4.0.2" } }, "sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw=="], + + "@microsoft/tsdoc": ["@microsoft/tsdoc@0.14.2", "", {}, "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug=="], + + "@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.16.2", "", { "dependencies": { "@microsoft/tsdoc": "0.14.2", "ajv": "~6.12.6", "jju": "~1.4.0", "resolve": "~1.19.0" } }, "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw=="], + "@mistralai/mistralai": ["@mistralai/mistralai@2.2.1", "", { "dependencies": { "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" } }, "sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ=="], "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="], @@ -910,6 +923,14 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], + "@rushstack/node-core-library": ["@rushstack/node-core-library@4.0.2", "", { "dependencies": { "fs-extra": "~7.0.1", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.5.4", "z-schema": "~5.0.2" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg=="], + + "@rushstack/rig-package": ["@rushstack/rig-package@0.5.2", "", { "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" } }, "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA=="], + + "@rushstack/terminal": ["@rushstack/terminal@0.10.0", "", { "dependencies": { "@rushstack/node-core-library": "4.0.2", "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw=="], + + "@rushstack/ts-command-line": ["@rushstack/ts-command-line@4.19.1", "", { "dependencies": { "@rushstack/terminal": "0.10.0", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg=="], + "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], "@shikijs/core": ["@shikijs/core@4.0.2", "", { "dependencies": { "@shikijs/primitive": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw=="], @@ -1104,6 +1125,8 @@ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], @@ -1146,6 +1169,8 @@ "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], + "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="], + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], @@ -1202,6 +1227,14 @@ "@vscode/l10n": ["@vscode/l10n@0.0.18", "", {}, "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ=="], + "@vue/compiler-core": ["@vue/compiler-core@3.5.40", "", { "dependencies": { "@babel/parser": "^7.29.7", "@vue/shared": "3.5.40", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ=="], + + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.40", "", { "dependencies": { "@vue/compiler-core": "3.5.40", "@vue/shared": "3.5.40" } }, "sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA=="], + + "@vue/language-core": ["@vue/language-core@1.8.27", "", { "dependencies": { "@volar/language-core": "~1.11.1", "@volar/source-map": "~1.11.1", "@vue/compiler-dom": "^3.3.0", "@vue/shared": "^3.3.0", "computeds": "^0.0.1", "minimatch": "^9.0.3", "muggle-string": "^0.3.1", "path-browserify": "^1.0.1", "vue-template-compiler": "^2.7.14" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA=="], + + "@vue/shared": ["@vue/shared@3.5.40", "", {}, "sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg=="], + "@xterm/addon-clipboard": ["@xterm/addon-clipboard@0.2.0", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-Dl31BCtBhLaUEECUbEiVcCLvLBbaeGYdT7NofB8OJkGTD3MWgBsaLjXvfGAD4tQNHhm6mbKyYkR7XD8kiZsdNg=="], "@xterm/addon-fit": ["@xterm/addon-fit@0.11.0", "", {}, "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g=="], @@ -1378,6 +1411,10 @@ "common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="], + "computeds": ["computeds@0.0.1", "", {}, "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + "content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -1412,6 +1449,8 @@ "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], + "de-indent": ["de-indent@1.0.2", "", {}, "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], @@ -1572,6 +1611,8 @@ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + "fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="], "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], @@ -1712,6 +1753,8 @@ "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], + "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="], "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], @@ -1750,6 +1793,8 @@ "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + "import-lazy": ["import-lazy@4.0.0", "", {}, "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw=="], + "import-without-cache": ["import-without-cache@0.2.5", "", {}, "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -1774,6 +1819,8 @@ "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], @@ -1818,6 +1865,8 @@ "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + "jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="], + "joi": ["joi@18.0.2", "", { "dependencies": { "@hapi/address": "^5.1.1", "@hapi/formula": "^3.0.2", "@hapi/hoek": "^11.0.7", "@hapi/pinpoint": "^2.0.1", "@hapi/tlds": "^1.1.1", "@hapi/topo": "^6.0.2", "@standard-schema/spec": "^1.0.0" } }, "sha512-RuCOQMIt78LWnktPoeBL0GErkNaJPTBGcYuyaBvUOQSpcpcLfWrHPPihYdOGbV5pam9VTWbeoF7TsGiHugcjGA=="], "jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="], @@ -1862,6 +1911,8 @@ "koffi": ["koffi@2.16.2", "", {}, "sha512-owU0MRwv6xkrVqCd+33uw6BaYppkTRXbO/rVdJNI2dvZG0gzyRhYwW25eWtc5pauwK8TGh3AbkFONSezdykfSA=="], + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], + "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="], "lazy-val": ["lazy-val@1.0.5", "", {}, "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q=="], @@ -1902,6 +1953,8 @@ "lodash.escaperegexp": ["lodash.escaperegexp@4.1.2", "", {}, "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="], + "lodash.get": ["lodash.get@4.4.2", "", {}, "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="], + "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], "lodash.isequal": ["lodash.isequal@4.5.0", "", {}, "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="], @@ -1912,6 +1965,8 @@ "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="], "lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], @@ -2182,6 +2237,8 @@ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], @@ -2236,6 +2293,8 @@ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "pure-rand": ["pure-rand@8.1.0", "", {}, "sha512-53B3MB8wetRdD6JZ4W/0gDKaOvKwuXrEmV1auQc0hASWge8rieKV4PCCVNVbJ+i24miiubb4c/B+dg8Ho0ikYw=="], "qs": ["qs@6.15.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg=="], @@ -2262,6 +2321,8 @@ "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], + "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], + "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], @@ -2312,6 +2373,8 @@ "reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="], + "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], + "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -2430,6 +2493,8 @@ "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="], + "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], @@ -2442,6 +2507,8 @@ "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], @@ -2454,6 +2521,8 @@ "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + "svgo": ["svgo@4.0.1", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w=="], "t3": ["t3@workspace:apps/server"], @@ -2608,6 +2677,8 @@ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], @@ -2620,6 +2691,8 @@ "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="], + "validator": ["validator@13.15.35", "", {}, "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw=="], + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], @@ -2630,6 +2703,8 @@ "vite": ["vite@8.0.0", "", { "dependencies": { "@oxc-project/runtime": "0.115.0", "lightningcss": "^1.32.0", "picomatch": "^4.0.3", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.31", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q=="], + "vite-plugin-dts": ["vite-plugin-dts@3.9.1", "", { "dependencies": { "@microsoft/api-extractor": "7.43.0", "@rollup/pluginutils": "^5.1.0", "@vue/language-core": "^1.8.27", "debug": "^4.3.4", "kolorist": "^1.8.0", "magic-string": "^0.30.8", "vue-tsc": "^1.8.27" }, "peerDependencies": { "typescript": "*", "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg=="], + "vitefu": ["vitefu@1.1.2", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw=="], "vitest": ["vitest@4.1.0", "", { "dependencies": { "@vitest/expect": "4.1.0", "@vitest/mocker": "4.1.0", "@vitest/pretty-format": "4.1.0", "@vitest/runner": "4.1.0", "@vitest/snapshot": "4.1.0", "@vitest/spy": "4.1.0", "@vitest/utils": "4.1.0", "es-module-lexer": "^2.0.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": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "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.0", "@vitest/browser-preview": "4.1.0", "@vitest/browser-webdriverio": "4.1.0", "@vitest/ui": "4.1.0", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw=="], @@ -2670,6 +2745,10 @@ "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], + "vue-template-compiler": ["vue-template-compiler@2.7.16", "", { "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ=="], + + "vue-tsc": ["vue-tsc@1.8.27", "", { "dependencies": { "@volar/typescript": "~1.11.1", "@vue/language-core": "1.8.27", "semver": "^7.5.4" }, "peerDependencies": { "typescript": "*" }, "bin": { "vue-tsc": "bin/vue-tsc.js" } }, "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg=="], + "wait-on": ["wait-on@8.0.5", "", { "dependencies": { "axios": "^1.12.1", "joi": "^18.0.1", "lodash": "^4.17.21", "minimist": "^1.2.8", "rxjs": "^7.8.2" }, "bin": { "wait-on": "bin/wait-on" } }, "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag=="], "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], @@ -2720,6 +2799,8 @@ "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="], + "z-schema": ["z-schema@5.0.6", "", { "dependencies": { "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", "validator": "^13.7.0" }, "optionalDependencies": { "commander": "^10.0.0" }, "bin": { "z-schema": "bin/z-schema" } }, "sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg=="], + "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], @@ -2780,6 +2861,10 @@ "@babel/plugin-transform-modules-commonjs/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], + "@babel/plugin-transform-react-jsx-self/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], + + "@babel/plugin-transform-react-jsx-source/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], + "@babel/plugin-transform-typescript/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], "@babel/plugin-transform-typescript/@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA=="], @@ -2828,6 +2913,18 @@ "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + "@microsoft/api-extractor/minimatch": ["minimatch@3.0.8", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q=="], + + "@microsoft/api-extractor/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], + + "@microsoft/api-extractor/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "@microsoft/api-extractor/typescript": ["typescript@5.4.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ=="], + + "@microsoft/tsdoc-config/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "@microsoft/tsdoc-config/resolve": ["resolve@1.19.0", "", { "dependencies": { "is-core-module": "^2.1.0", "path-parse": "^1.0.6" } }, "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg=="], + "@pierre/diffs/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], @@ -2844,6 +2941,14 @@ "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "@rushstack/node-core-library/fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], + + "@rushstack/node-core-library/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], + + "@rushstack/terminal/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "@rushstack/ts-command-line/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], "@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], @@ -2852,6 +2957,8 @@ "@t3tools/scripts/effect": ["effect@../vendor/effect/effect-8881a9b.tgz", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-tZcsKgsLpQ5p1T5/duJHebWAqyG8owTuJdASj/2V+WPMuDlnB+uKvetMMXJsrNOyElUb3lVFeF2Mq00BbCnL9g=="], + "@t3tools/web/thinking-orbs": ["thinking-orbs@file:../../../../www/thinking-orbs", { "devDependencies": { "@tailwindcss/vite": "^4.3.3", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@vitejs/plugin-react": "^4.2.0", "clsx": "^2.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwind-merge": "^3.6.0", "tailwindcss": "^4.3.3", "typescript": "^5.3.0", "vite": "^5.0.0", "vite-plugin-dts": "^3.7.0" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }], + "@tailwindcss/node/lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w=="], @@ -2882,6 +2989,20 @@ "@vitest/browser/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], + "@vue/compiler-core/@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="], + + "@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + + "@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "@vue/language-core/@volar/language-core": ["@volar/language-core@1.11.1", "", { "dependencies": { "@volar/source-map": "1.11.1" } }, "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw=="], + + "@vue/language-core/@volar/source-map": ["@volar/source-map@1.11.1", "", { "dependencies": { "muggle-string": "^0.3.1" } }, "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg=="], + + "@vue/language-core/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "@vue/language-core/muggle-string": ["muggle-string@0.3.1", "", {}, "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg=="], + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "ast-kit/@babel/parser": ["@babel/parser@8.0.0-rc.2", "", { "dependencies": { "@babel/types": "^8.0.0-rc.2" }, "bin": "./bin/babel-parser.js" }, "sha512-29AhEtcq4x8Dp3T72qvUMZHx0OMXCj4Jy/TEReQa+KWLln524Cj1fWb3QFi0l/xSpptQBR6y9RNEXuxpFvwiUQ=="], @@ -2924,6 +3045,8 @@ "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + "is-core-module/hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -2990,6 +3113,8 @@ "vscode-json-languageservice/jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + "vue-tsc/@volar/typescript": ["@volar/typescript@1.11.1", "", { "dependencies": { "@volar/language-core": "1.11.1", "path-browserify": "^1.0.1" } }, "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ=="], + "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="], @@ -2998,6 +3123,8 @@ "yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "z-schema/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + "@babel/generator/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.2", "", {}, "sha512-noLx87RwlBEMrTzncWd/FvTxoJ9+ycHNg0n8yyYydIoDsLZuxknKgWRJUqcrVkNrJ74uGyhWQzQaS3q8xfGAhQ=="], "@babel/helper-annotate-as-pure/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], @@ -3098,6 +3225,12 @@ "@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@microsoft/api-extractor/minimatch/brace-expansion": ["brace-expansion@1.1.16", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw=="], + + "@microsoft/api-extractor/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + + "@microsoft/tsdoc-config/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "@pierre/diffs/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], "@pierre/diffs/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], @@ -3140,8 +3273,30 @@ "@rolldown/plugin-babel/rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.9", "", {}, "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw=="], + "@rushstack/node-core-library/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "@rushstack/node-core-library/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "@rushstack/node-core-library/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + + "@rushstack/ts-command-line/argparse/sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + "@t3tools/scripts/@effect/vitest/effect": ["effect@4.0.0-beta.57", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-rg32VgXnLKaPRs9tbRDaZ5jxmzNY7ojXt85gSHGUTwdlbWH5Ik+OCUY2q14TXliygPGoHwCAvNWS4bQJOqf00g=="], + "@t3tools/web/thinking-orbs/@tailwindcss/vite": ["@tailwindcss/vite@4.3.3", "", { "dependencies": { "@tailwindcss/node": "4.3.3", "@tailwindcss/oxide": "4.3.3", "tailwindcss": "4.3.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw=="], + + "@t3tools/web/thinking-orbs/@types/react": ["@types/react@18.3.31", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw=="], + + "@t3tools/web/thinking-orbs/@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], + + "@t3tools/web/thinking-orbs/@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], + + "@t3tools/web/thinking-orbs/react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], + + "@t3tools/web/thinking-orbs/react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], + + "@t3tools/web/thinking-orbs/tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="], + "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], @@ -3168,6 +3323,10 @@ "@tanstack/router-plugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], + + "@vue/language-core/minimatch/brace-expansion": ["brace-expansion@2.1.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA=="], + "ast-kit/@babel/parser/@babel/types": ["@babel/types@8.0.0-rc.2", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.2", "@babel/helper-validator-identifier": "^8.0.0-rc.2" } }, "sha512-91gAaWRznDwSX4E2tZ1YjBuIfnQVOFDCQ2r0Toby0gu4XEbyF623kXLMA8d4ZbCu+fINcrudkmEcwSUHgDDkNw=="], "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], @@ -3258,6 +3417,8 @@ "vite/rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.9", "", {}, "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw=="], + "vue-tsc/@volar/typescript/@volar/language-core": ["@volar/language-core@1.11.1", "", { "dependencies": { "@volar/source-map": "1.11.1" } }, "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw=="], + "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "@babel/helper-create-class-features-plugin/@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], @@ -3292,10 +3453,26 @@ "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@microsoft/api-extractor/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "@t3tools/scripts/@effect/vitest/effect/toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="], + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node": ["@tailwindcss/node@4.3.3", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.24.1", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.3" } }, "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.3", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.3", "@tailwindcss/oxide-darwin-arm64": "4.3.3", "@tailwindcss/oxide-darwin-x64": "4.3.3", "@tailwindcss/oxide-freebsd-x64": "4.3.3", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", "@tailwindcss/oxide-linux-x64-musl": "4.3.3", "@tailwindcss/oxide-wasm32-wasi": "4.3.3", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA=="], + + "@t3tools/web/thinking-orbs/@vitejs/plugin-react/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], + + "@t3tools/web/thinking-orbs/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], + "@tanstack/router-plugin/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], + + "@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], + + "@vue/language-core/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "ast-kit/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.2", "", {}, "sha512-noLx87RwlBEMrTzncWd/FvTxoJ9+ycHNg0n8yyYydIoDsLZuxknKgWRJUqcrVkNrJ74uGyhWQzQaS3q8xfGAhQ=="], "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -3304,10 +3481,56 @@ "t3/@effect/platform-node/effect/toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="], + "vue-tsc/@volar/typescript/@volar/language-core/@volar/source-map": ["@volar/source-map@1.11.1", "", { "dependencies": { "muggle-string": "^0.3.1" } }, "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg=="], + "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node/enhanced-resolve": ["enhanced-resolve@5.24.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node/jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.3", "", { "os": "android", "cpu": "arm64" }, "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3", "", { "os": "linux", "cpu": "arm" }, "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.3", "", { "dependencies": { "@emnapi/core": "^1.11.1", "@emnapi/runtime": "^1.11.1", "@emnapi/wasi-threads": "^1.2.2", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw=="], + "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "vue-tsc/@volar/typescript/@volar/language-core/@volar/source-map/muggle-string": ["muggle-string@0.3.1", "", {}, "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node/enhanced-resolve/tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], + + "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], } } diff --git a/packages/contracts/src/ipc.ts b/packages/contracts/src/ipc.ts index eafc24be4..b0549e975 100644 --- a/packages/contracts/src/ipc.ts +++ b/packages/contracts/src/ipc.ts @@ -181,7 +181,14 @@ import type { ProviderReadPluginInput, ProviderReadPluginResult, } from "./providerDiscovery"; -import type { ProviderCompactThreadInput } from "./provider"; +import type { + ProviderCompactThreadInput, + ProviderListRealtimeVoicesInput, + ProviderListRealtimeVoicesResult, + ProviderRealtimeEvent, + ProviderStartRealtimeInput, + ProviderStopRealtimeInput, +} from "./provider"; import type { StatsGetProfileStatsInput, StatsGetProfileStatsResult, @@ -504,6 +511,12 @@ export interface NativeApi { input: ProviderGetComposerCapabilitiesInput, ) => Promise; compactThread: (input: ProviderCompactThreadInput) => Promise; + startRealtime: (input: ProviderStartRealtimeInput) => Promise; + stopRealtime: (input: ProviderStopRealtimeInput) => Promise; + listRealtimeVoices: ( + input: ProviderListRealtimeVoicesInput, + ) => Promise; + onRealtimeEvent: (callback: (event: ProviderRealtimeEvent) => void) => () => void; listCommands: (input: ProviderListCommandsInput) => Promise; listSkills: (input: ProviderListSkillsInput) => Promise; listSkillsCatalog: (input: ProviderSkillsCatalogInput) => Promise; diff --git a/packages/contracts/src/provider.test.ts b/packages/contracts/src/provider.test.ts index 91fb60900..d07742645 100644 --- a/packages/contracts/src/provider.test.ts +++ b/packages/contracts/src/provider.test.ts @@ -1,10 +1,17 @@ import { describe, expect, it } from "vitest"; import { Schema } from "effect"; -import { ProviderSendTurnInput, ProviderSessionStartInput } from "./provider"; +import { + ProviderRealtimeEvent, + ProviderSendTurnInput, + ProviderSessionStartInput, + ProviderStartRealtimeInput, +} from "./provider"; const decodeProviderSessionStartInput = Schema.decodeUnknownSync(ProviderSessionStartInput); const decodeProviderSendTurnInput = Schema.decodeUnknownSync(ProviderSendTurnInput); +const decodeProviderStartRealtimeInput = Schema.decodeUnknownSync(ProviderStartRealtimeInput); +const decodeProviderRealtimeEvent = Schema.decodeUnknownSync(ProviderRealtimeEvent); describe("ProviderSessionStartInput", () => { it("accepts codex-compatible payloads", () => { @@ -151,3 +158,58 @@ describe("ProviderSendTurnInput", () => { expect(parsed.modelSelection.options?.effort).toBe("xhigh"); }); }); + +describe("realtime SDP contracts", () => { + const sdp = "v=0\r\no=- 9148632761380695809 2 IN IP4 127.0.0.1\r\ns=-\r\n"; + + it("preserves the browser offer without trimming protocol whitespace", () => { + const parsed = decodeProviderStartRealtimeInput({ + threadId: "thread-1", + sdp, + }); + + expect(parsed.sdp).toBe(sdp); + }); + + it("preserves the provider answer without trimming protocol whitespace", () => { + const parsed = decodeProviderRealtimeEvent({ + type: "sdp", + threadId: "thread-1", + createdAt: "2026-07-23T22:00:00.000Z", + sdp, + }); + + if (parsed.type !== "sdp") { + throw new Error("Expected an SDP realtime event"); + } + expect(parsed.sdp).toBe(sdp); + }); +}); + +describe("realtime audio contracts", () => { + it("preserves app-server PCM audio metadata", () => { + const parsed = decodeProviderRealtimeEvent({ + type: "audio.delta", + threadId: "thread-1", + createdAt: "2026-07-24T12:00:00.000Z", + audio: { + data: "AAABAP//", + sampleRate: 24_000, + numChannels: 1, + samplesPerChannel: 3, + itemId: "item-audio-1", + }, + }); + + if (parsed.type !== "audio.delta") { + throw new Error("Expected an audio realtime event"); + } + expect(parsed.audio).toEqual({ + data: "AAABAP//", + sampleRate: 24_000, + numChannels: 1, + samplesPerChannel: 3, + itemId: "item-audio-1", + }); + }); +}); diff --git a/packages/contracts/src/provider.ts b/packages/contracts/src/provider.ts index c8acc48d7..251c08104 100644 --- a/packages/contracts/src/provider.ts +++ b/packages/contracts/src/provider.ts @@ -1,5 +1,5 @@ import { Schema } from "effect"; -import { TrimmedNonEmptyString } from "./baseSchemas"; +import { PositiveInt, TrimmedNonEmptyString } from "./baseSchemas"; import { ApprovalRequestId, EventId, @@ -136,6 +136,116 @@ export const ProviderCompactThreadInput = Schema.Struct({ }); export type ProviderCompactThreadInput = typeof ProviderCompactThreadInput.Type; +export const ProviderRealtimeVoice = Schema.Literals([ + "alloy", + "arbor", + "ash", + "ballad", + "breeze", + "cedar", + "coral", + "cove", + "echo", + "ember", + "juniper", + "maple", + "marin", + "sage", + "shimmer", + "sol", + "spruce", + "vale", + "verse", +]); +export type ProviderRealtimeVoice = typeof ProviderRealtimeVoice.Type; + +// SDP is opaque protocol data. A valid offer/answer is multiline and normally +// ends in CRLF, so it must never pass through a trimming string schema. +const ProviderRealtimeSdp = Schema.String.check(Schema.isNonEmpty()); + +export const ProviderStartRealtimeInput = Schema.Struct({ + threadId: ThreadId, + sdp: ProviderRealtimeSdp, + voice: Schema.optional(ProviderRealtimeVoice), +}); +export type ProviderStartRealtimeInput = typeof ProviderStartRealtimeInput.Type; + +export const ProviderStopRealtimeInput = Schema.Struct({ + threadId: ThreadId, +}); +export type ProviderStopRealtimeInput = typeof ProviderStopRealtimeInput.Type; + +export const ProviderListRealtimeVoicesInput = Schema.Struct({ + threadId: ThreadId, +}); +export type ProviderListRealtimeVoicesInput = typeof ProviderListRealtimeVoicesInput.Type; + +export const ProviderListRealtimeVoicesResult = Schema.Struct({ + voices: Schema.Struct({ + v1: Schema.Array(ProviderRealtimeVoice), + v2: Schema.Array(ProviderRealtimeVoice), + defaultV1: ProviderRealtimeVoice, + defaultV2: ProviderRealtimeVoice, + }), +}); +export type ProviderListRealtimeVoicesResult = typeof ProviderListRealtimeVoicesResult.Type; + +const ProviderRealtimeEventBase = { + threadId: ThreadId, + createdAt: IsoDateTime, +}; + +export const ProviderRealtimeAudioChunk = Schema.Struct({ + data: TrimmedNonEmptyString, + sampleRate: PositiveInt, + numChannels: PositiveInt, + samplesPerChannel: Schema.optional(PositiveInt), + itemId: Schema.optional(TrimmedNonEmptyString), +}); +export type ProviderRealtimeAudioChunk = typeof ProviderRealtimeAudioChunk.Type; + +export const ProviderRealtimeEvent = Schema.Union([ + Schema.Struct({ + type: Schema.Literal("started"), + ...ProviderRealtimeEventBase, + realtimeSessionId: Schema.optional(TrimmedNonEmptyString), + version: Schema.optional(TrimmedNonEmptyString), + }), + Schema.Struct({ + type: Schema.Literal("sdp"), + ...ProviderRealtimeEventBase, + sdp: ProviderRealtimeSdp, + }), + Schema.Struct({ + type: Schema.Literal("transcript.delta"), + ...ProviderRealtimeEventBase, + role: TrimmedNonEmptyString, + delta: Schema.String, + }), + Schema.Struct({ + type: Schema.Literal("transcript.done"), + ...ProviderRealtimeEventBase, + role: TrimmedNonEmptyString, + text: Schema.String, + }), + Schema.Struct({ + type: Schema.Literal("audio.delta"), + ...ProviderRealtimeEventBase, + audio: ProviderRealtimeAudioChunk, + }), + Schema.Struct({ + type: Schema.Literal("error"), + ...ProviderRealtimeEventBase, + message: TrimmedNonEmptyString, + }), + Schema.Struct({ + type: Schema.Literal("closed"), + ...ProviderRealtimeEventBase, + reason: Schema.optional(TrimmedNonEmptyString), + }), +]); +export type ProviderRealtimeEvent = typeof ProviderRealtimeEvent.Type; + export const ProviderRespondToRequestInput = Schema.Struct({ threadId: ThreadId, requestId: ApprovalRequestId, diff --git a/packages/contracts/src/rpc.ts b/packages/contracts/src/rpc.ts index 8f78dd29d..f21105fa0 100644 --- a/packages/contracts/src/rpc.ts +++ b/packages/contracts/src/rpc.ts @@ -87,7 +87,14 @@ import { OrchestrationShellStreamItem, OrchestrationThreadStreamItem, } from "./orchestration"; -import { ProviderCompactThreadInput } from "./provider"; +import { + ProviderCompactThreadInput, + ProviderListRealtimeVoicesInput, + ProviderListRealtimeVoicesResult, + ProviderRealtimeEvent, + ProviderStartRealtimeInput, + ProviderStopRealtimeInput, +} from "./provider"; import { ResearchListInput, ResearchListResult, @@ -746,6 +753,34 @@ export const WsProviderCompactThreadRpc = Rpc.make(WS_METHODS.providerCompactThr error: WsRpcError, }); +export const WsProviderStartRealtimeRpc = Rpc.make(WS_METHODS.providerStartRealtime, { + payload: ProviderStartRealtimeInput, + success: Schema.Void, + error: WsRpcError, +}); + +export const WsProviderStopRealtimeRpc = Rpc.make(WS_METHODS.providerStopRealtime, { + payload: ProviderStopRealtimeInput, + success: Schema.Void, + error: WsRpcError, +}); + +export const WsProviderListRealtimeVoicesRpc = Rpc.make(WS_METHODS.providerListRealtimeVoices, { + payload: ProviderListRealtimeVoicesInput, + success: ProviderListRealtimeVoicesResult, + error: WsRpcError, +}); + +export const WsSubscribeProviderRealtimeEventsRpc = Rpc.make( + WS_METHODS.subscribeProviderRealtimeEvents, + { + payload: Schema.Struct({}), + success: ProviderRealtimeEvent, + error: WsRpcError, + stream: true, + }, +); + export const WsProviderListCommandsRpc = Rpc.make(WS_METHODS.providerListCommands, { payload: ProviderListCommandsInput, success: ProviderListCommandsResult, @@ -929,6 +964,10 @@ export const WsRpcGroup = RpcGroup.make( WsSubscribeServerSettingsRpc, WsProviderGetComposerCapabilitiesRpc, WsProviderCompactThreadRpc, + WsProviderStartRealtimeRpc, + WsProviderStopRealtimeRpc, + WsProviderListRealtimeVoicesRpc, + WsSubscribeProviderRealtimeEventsRpc, WsProviderListCommandsRpc, WsProviderListSkillsRpc, WsProviderListSkillsCatalogRpc, diff --git a/packages/contracts/src/ws.ts b/packages/contracts/src/ws.ts index 5fa47360c..0e3acab05 100644 --- a/packages/contracts/src/ws.ts +++ b/packages/contracts/src/ws.ts @@ -107,7 +107,13 @@ import { ProviderListSkillsInput, ProviderSkillsCatalogInput, } from "./providerDiscovery"; -import { ProviderCompactThreadInput } from "./provider"; +import { + ProviderCompactThreadInput, + ProviderRealtimeEvent, + ProviderStartRealtimeInput, + ProviderStopRealtimeInput, + ProviderListRealtimeVoicesInput, +} from "./provider"; import { ResearchListInput, ResearchReadInput, ResearchSetArchivedInput } from "./research"; // ── WebSocket RPC Method Names ─────────────────────────────────────── @@ -206,6 +212,10 @@ export const WS_METHODS = { // Provider discovery providerGetComposerCapabilities: "provider.getComposerCapabilities", providerCompactThread: "provider.compactThread", + providerStartRealtime: "provider.startRealtime", + providerStopRealtime: "provider.stopRealtime", + providerListRealtimeVoices: "provider.listRealtimeVoices", + subscribeProviderRealtimeEvents: "provider.subscribeRealtimeEvents", providerListCommands: "provider.listCommands", providerListSkills: "provider.listSkills", providerListSkillsCatalog: "provider.listSkillsCatalog", @@ -230,6 +240,7 @@ export const WS_METHODS = { export const WS_CHANNELS = { automationEvent: "automation.event", + providerRealtimeEvent: "provider.realtimeEvent", gitActionProgress: "git.actionProgress", projectDevServerEvent: "project.devServerEvent", serverWelcome: "server.welcome", @@ -366,6 +377,10 @@ const WebSocketRequestBody = Schema.Union([ // Provider discovery tagRequestBody(WS_METHODS.providerGetComposerCapabilities, ProviderGetComposerCapabilitiesInput), tagRequestBody(WS_METHODS.providerCompactThread, ProviderCompactThreadInput), + tagRequestBody(WS_METHODS.providerStartRealtime, ProviderStartRealtimeInput), + tagRequestBody(WS_METHODS.providerStopRealtime, ProviderStopRealtimeInput), + tagRequestBody(WS_METHODS.providerListRealtimeVoices, ProviderListRealtimeVoicesInput), + tagRequestBody(WS_METHODS.subscribeProviderRealtimeEvents, Schema.Struct({})), tagRequestBody(WS_METHODS.providerListCommands, ProviderListCommandsInput), tagRequestBody(WS_METHODS.providerListSkills, ProviderListSkillsInput), tagRequestBody(WS_METHODS.providerListSkillsCatalog, ProviderSkillsCatalogInput), @@ -423,6 +438,7 @@ export interface WsPushPayloadByChannel { readonly [WS_CHANNELS.serverProviderStatusesUpdated]: typeof ServerProviderStatusesUpdatedPayload.Type; readonly [WS_CHANNELS.serverSettingsUpdated]: typeof ServerSettingsUpdatedPayload.Type; readonly [WS_CHANNELS.automationEvent]: typeof AutomationStreamEvent.Type; + readonly [WS_CHANNELS.providerRealtimeEvent]: typeof ProviderRealtimeEvent.Type; readonly [WS_CHANNELS.gitActionProgress]: typeof GitActionProgressEvent.Type; readonly [WS_CHANNELS.projectDevServerEvent]: typeof ProjectDevServerEvent.Type; readonly [ORCHESTRATION_WS_CHANNELS.domainEvent]: OrchestrationEvent; @@ -465,6 +481,10 @@ export const WsPushAutomationEvent = makeWsPushSchema( WS_CHANNELS.automationEvent, AutomationStreamEvent, ); +export const WsPushProviderRealtimeEvent = makeWsPushSchema( + WS_CHANNELS.providerRealtimeEvent, + ProviderRealtimeEvent, +); export const WsPushGitActionProgress = makeWsPushSchema( WS_CHANNELS.gitActionProgress, GitActionProgressEvent, @@ -494,6 +514,7 @@ export const WsPushChannelSchema = Schema.Literals([ WS_CHANNELS.serverProviderStatusesUpdated, WS_CHANNELS.serverSettingsUpdated, WS_CHANNELS.automationEvent, + WS_CHANNELS.providerRealtimeEvent, WS_CHANNELS.projectDevServerEvent, ORCHESTRATION_WS_CHANNELS.domainEvent, ORCHESTRATION_WS_CHANNELS.shellEvent, @@ -508,6 +529,7 @@ export const WsPush = Schema.Union([ WsPushServerProviderStatusesUpdated, WsPushServerSettingsUpdated, WsPushAutomationEvent, + WsPushProviderRealtimeEvent, WsPushGitActionProgress, WsPushProjectDevServerEvent, WsPushOrchestrationDomainEvent, From 58a7667a583768f107e514b8adf433633f9ba97a Mon Sep 17 00:00:00 2001 From: ojowwalker77 Date: Fri, 24 Jul 2026 13:55:05 -0300 Subject: [PATCH 2/2] Fix portable Thinking Orbs dependency --- apps/web/package.json | 2 +- bun.lock | 274 +++++++----------------------------------- 2 files changed, 43 insertions(+), 233 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 667f08e58..54a78cc0e 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -54,7 +54,7 @@ "remark-math": "^6.0.0", "shadcn": "^4.8.3", "tailwind-merge": "^3.6.0", - "thinking-orbs": "file:/Users/jow/www/thinking-orbs", + "thinking-orbs": "^0.1.1", "tw-animate-css": "^1.4.0", "zustand": "^5.0.11" }, diff --git a/bun.lock b/bun.lock index acfd2ff8d..811814607 100644 --- a/bun.lock +++ b/bun.lock @@ -14,7 +14,7 @@ }, "apps/desktop": { "name": "@t3tools/desktop", - "version": "0.11.0", + "version": "0.12.0", "dependencies": { "effect": "catalog:", "electron": "40.6.0", @@ -43,7 +43,7 @@ }, "apps/server": { "name": "t3", - "version": "0.11.0", + "version": "0.12.0", "bin": { "t3": "./dist/index.mjs", }, @@ -83,7 +83,7 @@ }, "apps/web": { "name": "@t3tools/web", - "version": "0.11.0", + "version": "0.12.0", "dependencies": { "@base-ui/react": "^1.5.0", "@dnd-kit/core": "^6.3.1", @@ -125,7 +125,7 @@ "remark-math": "^6.0.0", "shadcn": "^4.8.3", "tailwind-merge": "^3.6.0", - "thinking-orbs": "file:/Users/jow/www/thinking-orbs", + "thinking-orbs": "^0.1.1", "tw-animate-css": "^1.4.0", "zustand": "^5.0.11", }, @@ -151,7 +151,7 @@ }, "packages/contracts": { "name": "@t3tools/contracts", - "version": "0.11.0", + "version": "0.12.0", "dependencies": { "effect": "catalog:", }, @@ -383,10 +383,6 @@ "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ=="], - "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw=="], - - "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q=="], - "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-syntax-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw=="], "@babel/preset-typescript": ["@babel/preset-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ=="], @@ -691,14 +687,6 @@ "@mariozechner/clipboard-win32-x64-msvc": ["@mariozechner/clipboard-win32-x64-msvc@0.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA=="], - "@microsoft/api-extractor": ["@microsoft/api-extractor@7.43.0", "", { "dependencies": { "@microsoft/api-extractor-model": "7.28.13", "@microsoft/tsdoc": "0.14.2", "@microsoft/tsdoc-config": "~0.16.1", "@rushstack/node-core-library": "4.0.2", "@rushstack/rig-package": "0.5.2", "@rushstack/terminal": "0.10.0", "@rushstack/ts-command-line": "4.19.1", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", "typescript": "5.4.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w=="], - - "@microsoft/api-extractor-model": ["@microsoft/api-extractor-model@7.28.13", "", { "dependencies": { "@microsoft/tsdoc": "0.14.2", "@microsoft/tsdoc-config": "~0.16.1", "@rushstack/node-core-library": "4.0.2" } }, "sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw=="], - - "@microsoft/tsdoc": ["@microsoft/tsdoc@0.14.2", "", {}, "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug=="], - - "@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.16.2", "", { "dependencies": { "@microsoft/tsdoc": "0.14.2", "ajv": "~6.12.6", "jju": "~1.4.0", "resolve": "~1.19.0" } }, "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw=="], - "@mistralai/mistralai": ["@mistralai/mistralai@2.2.1", "", { "dependencies": { "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" } }, "sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ=="], "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="], @@ -923,14 +911,6 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], - "@rushstack/node-core-library": ["@rushstack/node-core-library@4.0.2", "", { "dependencies": { "fs-extra": "~7.0.1", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.5.4", "z-schema": "~5.0.2" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg=="], - - "@rushstack/rig-package": ["@rushstack/rig-package@0.5.2", "", { "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" } }, "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA=="], - - "@rushstack/terminal": ["@rushstack/terminal@0.10.0", "", { "dependencies": { "@rushstack/node-core-library": "4.0.2", "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw=="], - - "@rushstack/ts-command-line": ["@rushstack/ts-command-line@4.19.1", "", { "dependencies": { "@rushstack/terminal": "0.10.0", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg=="], - "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], "@shikijs/core": ["@shikijs/core@4.0.2", "", { "dependencies": { "@shikijs/primitive": "4.0.2", "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw=="], @@ -1053,35 +1033,35 @@ "@t3tools/web": ["@t3tools/web@workspace:apps/web"], - "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], + "@tailwindcss/node": ["@tailwindcss/node@4.3.3", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.24.1", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.3" } }, "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg=="], - "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.3", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.3", "@tailwindcss/oxide-darwin-arm64": "4.3.3", "@tailwindcss/oxide-darwin-x64": "4.3.3", "@tailwindcss/oxide-freebsd-x64": "4.3.3", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", "@tailwindcss/oxide-linux-x64-musl": "4.3.3", "@tailwindcss/oxide-wasm32-wasi": "4.3.3", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA=="], - "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="], + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.3", "", { "os": "android", "cpu": "arm64" }, "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw=="], - "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="], + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw=="], - "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="], + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw=="], - "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="], + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw=="], - "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="], + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3", "", { "os": "linux", "cpu": "arm" }, "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ=="], - "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="], + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w=="], - "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="], + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA=="], - "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="], + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w=="], - "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="], + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img=="], - "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="], + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.3", "", { "dependencies": { "@emnapi/core": "^1.11.1", "@emnapi/runtime": "^1.11.1", "@emnapi/wasi-threads": "^1.2.2", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ=="], - "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="], + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ=="], - "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw=="], - "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="], + "@tailwindcss/vite": ["@tailwindcss/vite@4.3.3", "", { "dependencies": { "@tailwindcss/node": "4.3.3", "@tailwindcss/oxide": "4.3.3", "tailwindcss": "4.3.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw=="], "@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.4.3", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-OZI6QyULw0FI0wjgmeYzCIfbgPsOEzwJtCpa69XrfLMtNXLGnz3d/dIabk7frg0TmHo+Ah49w5I4KC7Tufwsvw=="], @@ -1125,8 +1105,6 @@ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], - "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], @@ -1169,8 +1147,6 @@ "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], - "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="], - "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], @@ -1221,7 +1197,7 @@ "@volar/source-map": ["@volar/source-map@2.4.28", "", {}, "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ=="], - "@volar/typescript": ["@volar/typescript@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw=="], + "@volar/typescript": ["@volar/typescript@1.11.1", "", { "dependencies": { "@volar/language-core": "1.11.1", "path-browserify": "^1.0.1" } }, "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ=="], "@vscode/emmet-helper": ["@vscode/emmet-helper@2.11.0", "", { "dependencies": { "emmet": "^2.4.3", "jsonc-parser": "^2.3.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.15.1", "vscode-uri": "^3.0.8" } }, "sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw=="], @@ -1413,8 +1389,6 @@ "computeds": ["computeds@0.0.1", "", {}, "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q=="], - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - "content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -1543,7 +1517,7 @@ "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], - "enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="], + "enhanced-resolve": ["enhanced-resolve@5.24.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ=="], "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], @@ -1611,8 +1585,6 @@ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - "fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="], "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], @@ -1793,8 +1765,6 @@ "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - "import-lazy": ["import-lazy@4.0.0", "", {}, "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw=="], - "import-without-cache": ["import-without-cache@0.2.5", "", {}, "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -1819,8 +1789,6 @@ "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], - "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], - "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], @@ -1865,8 +1833,6 @@ "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], - "jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="], - "joi": ["joi@18.0.2", "", { "dependencies": { "@hapi/address": "^5.1.1", "@hapi/formula": "^3.0.2", "@hapi/hoek": "^11.0.7", "@hapi/pinpoint": "^2.0.1", "@hapi/tlds": "^1.1.1", "@hapi/topo": "^6.0.2", "@standard-schema/spec": "^1.0.0" } }, "sha512-RuCOQMIt78LWnktPoeBL0GErkNaJPTBGcYuyaBvUOQSpcpcLfWrHPPihYdOGbV5pam9VTWbeoF7TsGiHugcjGA=="], "jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="], @@ -1911,8 +1877,6 @@ "koffi": ["koffi@2.16.2", "", {}, "sha512-owU0MRwv6xkrVqCd+33uw6BaYppkTRXbO/rVdJNI2dvZG0gzyRhYwW25eWtc5pauwK8TGh3AbkFONSezdykfSA=="], - "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], - "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="], "lazy-val": ["lazy-val@1.0.5", "", {}, "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q=="], @@ -1953,8 +1917,6 @@ "lodash.escaperegexp": ["lodash.escaperegexp@4.1.2", "", {}, "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="], - "lodash.get": ["lodash.get@4.4.2", "", {}, "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="], - "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], "lodash.isequal": ["lodash.isequal@4.5.0", "", {}, "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="], @@ -1965,8 +1927,6 @@ "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], - "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="], "lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], @@ -2237,8 +2197,6 @@ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], @@ -2293,8 +2251,6 @@ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "pure-rand": ["pure-rand@8.1.0", "", {}, "sha512-53B3MB8wetRdD6JZ4W/0gDKaOvKwuXrEmV1auQc0hASWge8rieKV4PCCVNVbJ+i24miiubb4c/B+dg8Ho0ikYw=="], "qs": ["qs@6.15.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg=="], @@ -2321,8 +2277,6 @@ "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], - "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], - "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], @@ -2373,8 +2327,6 @@ "reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="], - "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], - "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -2493,8 +2445,6 @@ "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="], - "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], @@ -2507,8 +2457,6 @@ "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - "strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], @@ -2521,8 +2469,6 @@ "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "svgo": ["svgo@4.0.1", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w=="], "t3": ["t3@workspace:apps/server"], @@ -2533,14 +2479,16 @@ "tailwind-merge": ["tailwind-merge@3.6.0", "", {}, "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w=="], - "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], + "tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="], - "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], + "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + "thinking-orbs": ["thinking-orbs@0.1.1", "", { "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-nLvLTGJtk74K13MmP7XiRdzFiQx7UsoZAIyBZNgXyl7Q3h2mdz0r3eKn9LCsuzb3DGOVjwDvMhtnAkIqJJRVQA=="], + "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], @@ -2677,8 +2625,6 @@ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], @@ -2691,8 +2637,6 @@ "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="], - "validator": ["validator@13.15.35", "", {}, "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw=="], - "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], @@ -2703,8 +2647,6 @@ "vite": ["vite@8.0.0", "", { "dependencies": { "@oxc-project/runtime": "0.115.0", "lightningcss": "^1.32.0", "picomatch": "^4.0.3", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.31", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q=="], - "vite-plugin-dts": ["vite-plugin-dts@3.9.1", "", { "dependencies": { "@microsoft/api-extractor": "7.43.0", "@rollup/pluginutils": "^5.1.0", "@vue/language-core": "^1.8.27", "debug": "^4.3.4", "kolorist": "^1.8.0", "magic-string": "^0.30.8", "vue-tsc": "^1.8.27" }, "peerDependencies": { "typescript": "*", "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg=="], - "vitefu": ["vitefu@1.1.2", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw=="], "vitest": ["vitest@4.1.0", "", { "dependencies": { "@vitest/expect": "4.1.0", "@vitest/mocker": "4.1.0", "@vitest/pretty-format": "4.1.0", "@vitest/runner": "4.1.0", "@vitest/snapshot": "4.1.0", "@vitest/spy": "4.1.0", "@vitest/utils": "4.1.0", "es-module-lexer": "^2.0.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": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "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.0", "@vitest/browser-preview": "4.1.0", "@vitest/browser-webdriverio": "4.1.0", "@vitest/ui": "4.1.0", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw=="], @@ -2799,8 +2741,6 @@ "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="], - "z-schema": ["z-schema@5.0.6", "", { "dependencies": { "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", "validator": "^13.7.0" }, "optionalDependencies": { "commander": "^10.0.0" }, "bin": { "z-schema": "bin/z-schema" } }, "sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg=="], - "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], @@ -2861,10 +2801,6 @@ "@babel/plugin-transform-modules-commonjs/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], - "@babel/plugin-transform-react-jsx-self/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], - - "@babel/plugin-transform-react-jsx-source/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], - "@babel/plugin-transform-typescript/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], "@babel/plugin-transform-typescript/@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA=="], @@ -2913,18 +2849,6 @@ "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], - "@microsoft/api-extractor/minimatch": ["minimatch@3.0.8", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q=="], - - "@microsoft/api-extractor/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], - - "@microsoft/api-extractor/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "@microsoft/api-extractor/typescript": ["typescript@5.4.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ=="], - - "@microsoft/tsdoc-config/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "@microsoft/tsdoc-config/resolve": ["resolve@1.19.0", "", { "dependencies": { "is-core-module": "^2.1.0", "path-parse": "^1.0.6" } }, "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg=="], - "@pierre/diffs/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], @@ -2941,14 +2865,6 @@ "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "@rushstack/node-core-library/fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], - - "@rushstack/node-core-library/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], - - "@rushstack/terminal/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "@rushstack/ts-command-line/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], "@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], @@ -2957,19 +2873,17 @@ "@t3tools/scripts/effect": ["effect@../vendor/effect/effect-8881a9b.tgz", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-tZcsKgsLpQ5p1T5/duJHebWAqyG8owTuJdASj/2V+WPMuDlnB+uKvetMMXJsrNOyElUb3lVFeF2Mq00BbCnL9g=="], - "@t3tools/web/thinking-orbs": ["thinking-orbs@file:../../../../www/thinking-orbs", { "devDependencies": { "@tailwindcss/vite": "^4.3.3", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@vitejs/plugin-react": "^4.2.0", "clsx": "^2.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwind-merge": "^3.6.0", "tailwindcss": "^4.3.3", "typescript": "^5.3.0", "vite": "^5.0.0", "vite-plugin-dts": "^3.7.0" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }], - - "@tailwindcss/node/lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], + "@tailwindcss/node/jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], - "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], - "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -2989,6 +2903,12 @@ "@vitest/browser/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], + "@volar/kit/@volar/typescript": ["@volar/typescript@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw=="], + + "@volar/language-server/@volar/typescript": ["@volar/typescript@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw=="], + + "@volar/typescript/@volar/language-core": ["@volar/language-core@1.11.1", "", { "dependencies": { "@volar/source-map": "1.11.1" } }, "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw=="], + "@vue/compiler-core/@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="], "@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], @@ -3045,8 +2965,6 @@ "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - "is-core-module/hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], - "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -3113,8 +3031,6 @@ "vscode-json-languageservice/jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], - "vue-tsc/@volar/typescript": ["@volar/typescript@1.11.1", "", { "dependencies": { "@volar/language-core": "1.11.1", "path-browserify": "^1.0.1" } }, "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ=="], - "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="], @@ -3123,8 +3039,6 @@ "yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - "z-schema/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], - "@babel/generator/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.2", "", {}, "sha512-noLx87RwlBEMrTzncWd/FvTxoJ9+ycHNg0n8yyYydIoDsLZuxknKgWRJUqcrVkNrJ74uGyhWQzQaS3q8xfGAhQ=="], "@babel/helper-annotate-as-pure/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], @@ -3225,12 +3139,6 @@ "@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "@microsoft/api-extractor/minimatch/brace-expansion": ["brace-expansion@1.1.16", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw=="], - - "@microsoft/api-extractor/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - - "@microsoft/tsdoc-config/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "@pierre/diffs/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], "@pierre/diffs/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], @@ -3273,56 +3181,14 @@ "@rolldown/plugin-babel/rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.9", "", {}, "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw=="], - "@rushstack/node-core-library/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], - - "@rushstack/node-core-library/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], - - "@rushstack/node-core-library/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - - "@rushstack/ts-command-line/argparse/sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], - "@t3tools/scripts/@effect/vitest/effect": ["effect@4.0.0-beta.57", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-rg32VgXnLKaPRs9tbRDaZ5jxmzNY7ojXt85gSHGUTwdlbWH5Ik+OCUY2q14TXliygPGoHwCAvNWS4bQJOqf00g=="], - "@t3tools/web/thinking-orbs/@tailwindcss/vite": ["@tailwindcss/vite@4.3.3", "", { "dependencies": { "@tailwindcss/node": "4.3.3", "@tailwindcss/oxide": "4.3.3", "tailwindcss": "4.3.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw=="], - - "@t3tools/web/thinking-orbs/@types/react": ["@types/react@18.3.31", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw=="], - - "@t3tools/web/thinking-orbs/@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], - - "@t3tools/web/thinking-orbs/@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], - - "@t3tools/web/thinking-orbs/react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], - - "@t3tools/web/thinking-orbs/react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], - - "@t3tools/web/thinking-orbs/tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="], - - "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], - - "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], - - "@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], - - "@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], - - "@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], - - "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], - - "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], - - "@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], - - "@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], - - "@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], - - "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], - "@tanstack/router-plugin/chokidar/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "@tanstack/router-plugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "@volar/typescript/@volar/language-core/@volar/source-map": ["@volar/source-map@1.11.1", "", { "dependencies": { "muggle-string": "^0.3.1" } }, "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg=="], + "@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], "@vue/language-core/minimatch/brace-expansion": ["brace-expansion@2.1.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA=="], @@ -3417,8 +3283,6 @@ "vite/rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.9", "", {}, "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw=="], - "vue-tsc/@volar/typescript/@volar/language-core": ["@volar/language-core@1.11.1", "", { "dependencies": { "@volar/source-map": "1.11.1" } }, "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw=="], - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "@babel/helper-create-class-features-plugin/@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], @@ -3453,20 +3317,12 @@ "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@microsoft/api-extractor/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "@t3tools/scripts/@effect/vitest/effect/toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="], - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node": ["@tailwindcss/node@4.3.3", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.24.1", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.3" } }, "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.3", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.3", "@tailwindcss/oxide-darwin-arm64": "4.3.3", "@tailwindcss/oxide-darwin-x64": "4.3.3", "@tailwindcss/oxide-freebsd-x64": "4.3.3", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", "@tailwindcss/oxide-linux-x64-musl": "4.3.3", "@tailwindcss/oxide-wasm32-wasi": "4.3.3", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA=="], - - "@t3tools/web/thinking-orbs/@vitejs/plugin-react/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], - - "@t3tools/web/thinking-orbs/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "@tanstack/router-plugin/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "@volar/typescript/@volar/language-core/@volar/source-map/muggle-string": ["muggle-string@0.3.1", "", {}, "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg=="], + "@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], "@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], @@ -3481,56 +3337,10 @@ "t3/@effect/platform-node/effect/toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="], - "vue-tsc/@volar/typescript/@volar/language-core/@volar/source-map": ["@volar/source-map@1.11.1", "", { "dependencies": { "muggle-string": "^0.3.1" } }, "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg=="], - "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node/enhanced-resolve": ["enhanced-resolve@5.24.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node/jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.3", "", { "os": "android", "cpu": "arm64" }, "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3", "", { "os": "linux", "cpu": "arm" }, "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.3", "", { "dependencies": { "@emnapi/core": "^1.11.1", "@emnapi/runtime": "^1.11.1", "@emnapi/wasi-threads": "^1.2.2", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw=="], - "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "vue-tsc/@volar/typescript/@volar/language-core/@volar/source-map/muggle-string": ["muggle-string@0.3.1", "", {}, "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/node/enhanced-resolve/tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], - - "@t3tools/web/thinking-orbs/@tailwindcss/vite/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], } }