diff --git a/examples/README.md b/examples/README.md index a69801d31..d8bc29b6e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -100,6 +100,7 @@ Create a multi-agent research workflow where different AI agents collaborate to - [OpenRouter](./with-openrouter) — Use OpenRouter through VoltAgent's built-in `openrouter/` routing. - [Chroma](./with-chroma) — RAG with Chroma vectors showing automatic vs tool‑driven retrieval patterns. - [Client‑side Tools](./with-client-side-tools) — Next.js UI triggers typed client‑side tools safely, VoltAgent on the server. +- [OpenUI](./with-openui) — Retrieve grounded facts from one PDF with VoltAgent and stream them as themed charts, forms, and follow-up actions with OpenUI. - [Cloudflare Workers](./with-cloudflare-workers) — Deploy your agent on Workers using the Hono server adapter. - [Composio (MCP)](./with-composio-mcp) — Call Composio actions through MCP tools inside your workflows. - [Custom Endpoints](./with-custom-endpoints) — Add bespoke REST endpoints alongside agent/workflow routes. diff --git a/examples/with-openui/.env.example b/examples/with-openui/.env.example new file mode 100644 index 000000000..b0814539b --- /dev/null +++ b/examples/with-openui/.env.example @@ -0,0 +1,3 @@ +OPENAI_API_KEY=your-openai-api-key +VOLTAGENT_MODEL=openai/gpt-4o-mini +VOLTAGENT_EMBEDDING_MODEL=text-embedding-3-small diff --git a/examples/with-openui/.gitignore b/examples/with-openui/.gitignore new file mode 100644 index 000000000..5b770e5d4 --- /dev/null +++ b/examples/with-openui/.gitignore @@ -0,0 +1,9 @@ +/node_modules +/.next +/out +/coverage +/openui/generated +/.env* +!/.env.example +*.tsbuildinfo +next-env.d.ts diff --git a/examples/with-openui/README.md b/examples/with-openui/README.md new file mode 100644 index 000000000..284699f12 --- /dev/null +++ b/examples/with-openui/README.md @@ -0,0 +1,144 @@ +# VoltAgent + OpenUI PDF RAG + +This example connects [VoltAgent](https://voltagent.dev/) to +[OpenUI](https://openui.com/) in a grounded, streaming RAG chat. VoltAgent +extracts and chunks one bundled PDF, embeds the chunks in memory, retrieves the +most relevant pages for every turn, and supplies that context to the model. +OpenUI turns the grounded answer into interactive charts, forms, and follow-up +actions. + +The bundled [2025 Housing Supply Report](./data/nyc-2025-housing-supply-report.pdf) +from the [New York City Rent Guidelines Board](https://rentguidelinesboard.cityofnewyork.us/research/) +is the only runtime source of housing facts. It is an official annual government +report covering calendar-year 2024. The starter prompts contain no hidden chart +values, and there is no fallback mock dataset. The bundled file was downloaded +from the Board's [official PDF](https://rentguidelinesboard.cityofnewyork.us/wp-content/uploads/2025/05/2025-HSR.pdf). + +## Supported versions + +The example is tested from this repository lockfile with VoltAgent +`@voltagent/core` 2.9.x, `@voltagent/rag` 1.0.x, `pdf-parse` 2.4.x, and OpenUI +`@openuidev/react-ui` 0.13.x, `@openuidev/react-lang` 0.2.x, and +`@openuidev/react-headless` 0.9.x. + +## Run it + +From the repository root: + +```bash +pnpm install +cp examples/with-openui/.env.example examples/with-openui/.env +# Add your OPENAI_API_KEY to examples/with-openui/.env +pnpm --filter voltagent-example-with-openui dev +``` + +Open [http://localhost:3000](http://localhost:3000). `VOLTAGENT_MODEL` defaults +to `openai/gpt-4o-mini`, and `VOLTAGENT_EMBEDDING_MODEL` defaults to +`text-embedding-3-small`. Both accept bare OpenAI model IDs; the chat setting +also accepts an `openai/` prefix. + +The API key, PDF parsing, embeddings, and retrieval all stay server-side. Do +not expose the key with a `NEXT_PUBLIC_` prefix. + +## Architecture + +```text +data/nyc-2025-housing-supply-report.pdf + -> pdf-parse page extraction (once, lazily) + -> @voltagent/rag RecursiveChunker + -> OpenAI embeddings cached in memory + +AgentInterface user/action + -> POST /api/chat with the full thread and threadId + -> HttpOnly anonymous visitor cookie + server-derived conversation ID + -> VoltAgent Agent.streamText() + -> NycHousingPdfRetriever vector search + -> retrieved page context injected by VoltAgent + -> model emits source-grounded OpenUI Lang + -> OpenAI-compatible SSE + -> OpenUI adapter -> parser -> AgentInterface renderer +``` + +`voltagent/pdf-retriever.ts` extends VoltAgent's `BaseRetriever`. Its index is +created on the first request and reused for the life of the server process. It +ranks chunks semantically, then expands the best matches back to their complete +PDF pages so multi-column tables and map labels remain intact. VoltAgent injects +those pages, the report title, and exact page numbers into the agent's prompt as +relevant context. No vector database is required for this small, +single-document demo. Matches below the `0.30` cosine-similarity cutoff are +discarded; retrieval failures produce an explicit source-unavailable context so +the agent refuses to answer from memory. + +`openui/library.ts` exports the same `openuiChatLibrary` used by the renderer. +The OpenUI CLI generates `openui/generated/system-prompt.txt` from that file, +and the VoltAgent agent reads the generated prompt on the server. Regenerate it +after changing the library: + +```bash +pnpm --filter voltagent-example-with-openui generate:prompt +``` + +The `AgentInterface` keeps its built-in `ThemeProvider` enabled and applies a +visible VoltAgent-green dark theme. Its built-in `ContinueConversation` action +adapter sends a `FollowUpItem` label or `@ToAssistant` form action back through +the same `/api/chat` route. Form state is serialized into the user message +context, so VoltAgent receives the values the user actually edited. + +## Replace the datasource + +To use a different source of truth: + +1. Replace `data/nyc-2025-housing-supply-report.pdf` with your PDF. +2. Update the report filename, title, publisher, source URL, and domain-specific agent rules. +3. Restart the server so the lazy in-memory index is rebuilt. + +For a larger or frequently changing document collection, move chunk embeddings +to a persistent vector store and invalidate the index when documents change. +The demo isolates in-memory conversations with a server-generated anonymous ID +stored in an HttpOnly cookie and hashes that identity with the client thread ID +before calling VoltAgent. In production, replace the anonymous identity with an +authenticated server identity, validate conversation ownership, add rate +limiting to `/api/chat`, configure durable conversation memory, and treat +uploaded PDF text as untrusted input. + +## Acceptance prompts + +Chart: + +> Using only the official 2025 Housing Supply Report PDF, show 2024 residential +> building permits for all five New York City boroughs as a labeled bar chart. +> Cite the source page and end with two relevant follow-up suggestions. + +The chart should show Bronx `3,125`, Brooklyn `6,588`, Manhattan `2,347`, Queens +`3,240`, and Staten Island `326` dwelling units, citing PDF page 6. Those values +must come from retrieval, not the prompt. + +Click either rendered follow-up. Its exact label should appear as one new user +turn and produce one new VoltAgent request in the same conversation. + +Analysis: + +> Using only the official source report, explain the most important 2024 housing +> supply and vacancy signals, including where borough trends diverged. Cite +> source pages and end with two next questions. + +Form: + +> Create a validated housing analysis form with required focus area and audience +> fields plus notes. Add a primary Analyze button that sends the completed +> values to you. + +Leave required fields empty to see validation. Then submit focus area +`Vacancy rates`, audience `City planners`, and notes +`Compare borough differences`. The next rendered answer should acknowledge the +focus area and audience, then use only facts retrieved from the PDF. + +## Checks + +```bash +pnpm --filter voltagent-example-with-openui generate:prompt +pnpm --filter voltagent-example-with-openui typecheck +pnpm --filter voltagent-example-with-openui lint +pnpm --filter voltagent-example-with-openui test +pnpm --filter voltagent-example-with-openui build +``` diff --git a/examples/with-openui/app/api/chat/route.ts b/examples/with-openui/app/api/chat/route.ts new file mode 100644 index 000000000..8508cb7cc --- /dev/null +++ b/examples/with-openui/app/api/chat/route.ts @@ -0,0 +1,84 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { InvalidChatRequestError, parseChatRequestBody } from "@/lib/chat-request"; +import { deriveConversationId, resolveAnonymousSession } from "@/lib/chat-session"; +import { createOpenUIAgent } from "@/voltagent/agent"; +import { safeStringify } from "@voltagent/internal/utils"; + +export const runtime = "nodejs"; + +const openUISystemPrompt = readFileSync( + join(process.cwd(), "openui/generated/system-prompt.txt"), + "utf8", +); +const agent = createOpenUIAgent(openUISystemPrompt); + +function completionChunk(id: string, content: string) { + return `data: ${safeStringify({ + id, + object: "chat.completion.chunk", + choices: [{ index: 0, delta: { content }, finish_reason: null }], + })}\n\n`; +} + +function stopChunk(id: string) { + return `data: ${safeStringify({ + id, + object: "chat.completion.chunk", + choices: [{ index: 0, delta: {}, finish_reason: "stop" }], + })}\n\n`; +} + +export async function POST(request: Request) { + try { + const { messages, threadId = "openui-demo" } = await parseChatRequestBody(request); + const anonymousSession = resolveAnonymousSession(request.headers.get("cookie")); + const result = await agent.streamText(messages, { + userId: anonymousSession.userId, + conversationId: deriveConversationId(anonymousSession.userId, threadId), + abortSignal: request.signal, + }); + + const encoder = new TextEncoder(); + const responseId = `voltagent-${crypto.randomUUID()}`; + + const stream = new ReadableStream({ + async start(controller) { + try { + for await (const text of result.textStream) { + controller.enqueue(encoder.encode(completionChunk(responseId, text))); + } + + controller.enqueue(encoder.encode(stopChunk(responseId))); + controller.enqueue(encoder.encode("data: [DONE]\n\n")); + controller.close(); + } catch (error) { + if (request.signal.aborted) { + return; + } + + console.error("[voltagent-openui] stream failed", error); + controller.error(error); + } + }, + }); + + const headers = new Headers({ + "Cache-Control": "no-cache, no-transform", + Connection: "keep-alive", + "Content-Type": "text/event-stream", + }); + if (anonymousSession.setCookie) headers.append("Set-Cookie", anonymousSession.setCookie); + + return new Response(stream, { + headers, + }); + } catch (error) { + if (error instanceof InvalidChatRequestError) { + return Response.json({ error: "Invalid chat request" }, { status: 400 }); + } + + console.error("[voltagent-openui] route failed", error); + return Response.json({ error: "Unable to start the VoltAgent stream" }, { status: 500 }); + } +} diff --git a/examples/with-openui/app/globals.css b/examples/with-openui/app/globals.css new file mode 100644 index 000000000..21e769516 --- /dev/null +++ b/examples/with-openui/app/globals.css @@ -0,0 +1,16 @@ +@import "tailwindcss"; +@import "@openuidev/react-ui/styles/index.css"; + +:root { + color-scheme: dark; +} + +html, +body { + height: 100%; + margin: 0; +} + +body { + background: oklch(0.15 0.015 162); +} diff --git a/examples/with-openui/app/layout.tsx b/examples/with-openui/app/layout.tsx new file mode 100644 index 000000000..35769484a --- /dev/null +++ b/examples/with-openui/app/layout.tsx @@ -0,0 +1,15 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "VoltAgent + OpenUI", + description: "Interactive generative UI streamed by VoltAgent and rendered with OpenUI", +}; + +export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { + return ( + + {children} + + ); +} diff --git a/examples/with-openui/app/page.tsx b/examples/with-openui/app/page.tsx new file mode 100644 index 000000000..e153e1d76 --- /dev/null +++ b/examples/with-openui/app/page.tsx @@ -0,0 +1,60 @@ +"use client"; + +import { + AgentInterface, + createTheme, + fetchLLM, + openAIAdapter, + openAIMessageFormat, +} from "@openuidev/react-ui"; +import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib"; +import { useMemo } from "react"; + +const voltAgentTheme = createTheme({ + background: "oklch(0.15 0.015 162 / 1)", + foreground: "oklch(0.2 0.018 162 / 1)", + interactiveAccentDefault: "oklch(0.76 0.18 157 / 1)", + interactiveAccentHover: "oklch(0.82 0.17 157 / 1)", + textBrand: "oklch(0.82 0.17 157 / 1)", +}); + +export default function Home() { + const llm = useMemo( + () => + fetchLLM({ + url: "/api/chat", + streamAdapter: openAIAdapter(), + messageFormat: openAIMessageFormat, + }), + [], + ); + + return ( +
+ +
+ ); +} diff --git a/examples/with-openui/data/nyc-2025-housing-supply-report.pdf b/examples/with-openui/data/nyc-2025-housing-supply-report.pdf new file mode 100644 index 000000000..39237f4c3 Binary files /dev/null and b/examples/with-openui/data/nyc-2025-housing-supply-report.pdf differ diff --git a/examples/with-openui/lib/chat-request.test.ts b/examples/with-openui/lib/chat-request.test.ts new file mode 100644 index 000000000..917aa47e5 --- /dev/null +++ b/examples/with-openui/lib/chat-request.test.ts @@ -0,0 +1,76 @@ +import { describe, expect, it } from "vitest"; +import { + InvalidChatRequestError, + MAX_CHAT_REQUEST_BYTES, + parseChatRequest, + parseChatRequestBody, +} from "./chat-request"; + +describe("parseChatRequest", () => { + it("preserves a follow-up action as the next VoltAgent user turn", () => { + const content = + 'Compare borough permit trends["User clicked: Compare borough permit trends"]'; + + const result = parseChatRequest({ + threadId: "acceptance-thread", + messages: [{ role: "user", content }], + }); + + expect(result.messages[0]?.content).toBe(content); + }); + + it("preserves distinctive form values in the action context", () => { + const content = + 'Analyze the submitted housing focus for the specified audience using exact PDF facts and page citations["User clicked: Analyze the submitted housing focus for the specified audience using exact PDF facts and page citations",{"housingAnalysis":{"focusArea":"Vacancy rates","audience":"City planners","notes":"Compare borough differences"}}]'; + + const result = parseChatRequest({ + threadId: "acceptance-thread", + messages: [{ role: "user", content }], + }); + + expect(result.messages[0]?.content).toContain("Vacancy rates"); + expect(result.messages[0]?.content).toContain("Compare borough differences"); + }); + + it("rejects malformed JSON as an invalid chat request", async () => { + const request = new Request("http://localhost/api/chat", { + method: "POST", + body: "{", + headers: { "Content-Type": "application/json" }, + }); + + await expect(parseChatRequestBody(request)).rejects.toBeInstanceOf(InvalidChatRequestError); + }); + + it("rejects a declared oversized body before reading it", async () => { + const request = new Request("http://localhost/api/chat", { + method: "POST", + body: "{}", + headers: { "Content-Length": String(MAX_CHAT_REQUEST_BYTES + 1) }, + }); + + await expect(parseChatRequestBody(request)).rejects.toBeInstanceOf(InvalidChatRequestError); + expect(request.bodyUsed).toBe(false); + }); + + it("stops reading a chunked body when it exceeds the byte limit", async () => { + const chunk = new Uint8Array(256 * 1024); + let streamWasCanceled = false; + const body = new ReadableStream({ + pull(controller) { + controller.enqueue(chunk); + }, + cancel() { + streamWasCanceled = true; + }, + }); + const request = new Request("http://localhost/api/chat", { + method: "POST", + body, + duplex: "half", + } as RequestInit & { duplex: "half" }); + + await expect(parseChatRequestBody(request)).rejects.toBeInstanceOf(InvalidChatRequestError); + expect(streamWasCanceled).toBe(true); + }); +}); diff --git a/examples/with-openui/lib/chat-request.ts b/examples/with-openui/lib/chat-request.ts new file mode 100644 index 000000000..29b318888 --- /dev/null +++ b/examples/with-openui/lib/chat-request.ts @@ -0,0 +1,79 @@ +import { z } from "zod"; + +export const MAX_CHAT_REQUEST_BYTES = 1024 * 1024; + +const chatMessageSchema = z.object({ + role: z.enum(["user", "assistant"]), + content: z.string().max(100_000), +}); + +const chatRequestSchema = z.object({ + threadId: z.string().min(1).max(128).optional(), + messages: z.array(chatMessageSchema).min(1).max(50), +}); + +export type ChatMessage = z.infer; + +export class InvalidChatRequestError extends Error { + override name = "InvalidChatRequestError"; +} + +export function parseChatRequest(input: unknown) { + return chatRequestSchema.parse(input); +} + +async function readRequestBody(request: Request) { + const declaredLength = Number(request.headers.get("content-length")); + if (Number.isFinite(declaredLength) && declaredLength > MAX_CHAT_REQUEST_BYTES) { + throw new InvalidChatRequestError("Request body exceeds the size limit"); + } + + const reader = request.body?.getReader(); + if (!reader) return ""; + + const chunks: Uint8Array[] = []; + let totalBytes = 0; + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + totalBytes += value.byteLength; + if (totalBytes > MAX_CHAT_REQUEST_BYTES) { + await reader.cancel().catch(() => undefined); + throw new InvalidChatRequestError("Request body exceeds the size limit"); + } + + chunks.push(value); + } + + const body = new Uint8Array(totalBytes); + let offset = 0; + for (const chunk of chunks) { + body.set(chunk, offset); + offset += chunk.byteLength; + } + + return new TextDecoder().decode(body); +} + +export async function parseChatRequestBody(request: Request) { + let input: unknown; + + try { + input = JSON.parse(await readRequestBody(request)); + } catch (error) { + if (error instanceof InvalidChatRequestError) throw error; + throw new InvalidChatRequestError("Request body must be valid JSON"); + } + + try { + return parseChatRequest(input); + } catch (error) { + if (error instanceof z.ZodError) { + throw new InvalidChatRequestError("Request body does not match the chat schema"); + } + + throw error; + } +} diff --git a/examples/with-openui/lib/chat-session.test.ts b/examples/with-openui/lib/chat-session.test.ts new file mode 100644 index 000000000..ce25cbe01 --- /dev/null +++ b/examples/with-openui/lib/chat-session.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from "vitest"; +import { anonymousUserCookie, deriveConversationId, resolveAnonymousSession } from "./chat-session"; + +const generatedId = "123e4567-e89b-42d3-a456-426614174000"; +const existingId = "d9428888-122b-4bf0-a331-2c6f1a6a2182"; + +describe("anonymous chat sessions", () => { + it("issues an HttpOnly cookie for a new anonymous visitor", () => { + const session = resolveAnonymousSession(null, () => generatedId); + + expect(session.userId).toBe(`anonymous:${generatedId}`); + expect(session.setCookie).toContain(`${anonymousUserCookie}=${generatedId}`); + expect(session.setCookie).toContain("HttpOnly"); + expect(session.setCookie).toContain("SameSite=Lax"); + }); + + it("reuses only a valid server-issued anonymous identifier", () => { + const existing = resolveAnonymousSession( + `theme=dark; ${anonymousUserCookie}=${existingId}`, + () => generatedId, + ); + const invalid = resolveAnonymousSession( + `${anonymousUserCookie}=predictable`, + () => generatedId, + ); + + expect(existing).toEqual({ userId: `anonymous:${existingId}`, setCookie: undefined }); + expect(invalid.userId).toBe(`anonymous:${generatedId}`); + expect(invalid.setCookie).toContain(`${anonymousUserCookie}=${generatedId}`); + }); + + it("derives separate conversation IDs for each visitor and client thread", () => { + const first = deriveConversationId(`anonymous:${existingId}`, "thread-a"); + + expect(first).toBe(deriveConversationId(`anonymous:${existingId}`, "thread-a")); + expect(first).not.toBe(deriveConversationId(`anonymous:${generatedId}`, "thread-a")); + expect(first).not.toBe(deriveConversationId(`anonymous:${existingId}`, "thread-b")); + expect(first).not.toContain("thread-a"); + }); +}); diff --git a/examples/with-openui/lib/chat-session.ts b/examples/with-openui/lib/chat-session.ts new file mode 100644 index 000000000..281ec26a2 --- /dev/null +++ b/examples/with-openui/lib/chat-session.ts @@ -0,0 +1,47 @@ +import { createHash, randomUUID } from "node:crypto"; + +export const anonymousUserCookie = "voltagent-openui-user"; + +const anonymousIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + +function readAnonymousId(cookieHeader: string | null) { + if (!cookieHeader) return undefined; + + for (const cookie of cookieHeader.split(";")) { + const separator = cookie.indexOf("="); + if (separator === -1) continue; + + const name = cookie.slice(0, separator).trim(); + const value = cookie.slice(separator + 1).trim(); + if (name === anonymousUserCookie && anonymousIdPattern.test(value)) return value; + } + + return undefined; +} + +export function resolveAnonymousSession( + cookieHeader: string | null, + generateId: () => string = randomUUID, +) { + const existingId = readAnonymousId(cookieHeader); + const anonymousId = existingId ?? generateId(); + + return { + userId: `anonymous:${anonymousId}`, + setCookie: existingId + ? undefined + : `${anonymousUserCookie}=${anonymousId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=31536000${ + process.env.NODE_ENV === "production" ? "; Secure" : "" + }`, + }; +} + +export function deriveConversationId(userId: string, clientThreadId: string) { + const digest = createHash("sha256") + .update(userId) + .update("\0") + .update(clientThreadId) + .digest("hex"); + + return `openui:${digest}`; +} diff --git a/examples/with-openui/next.config.ts b/examples/with-openui/next.config.ts new file mode 100644 index 000000000..4410b9677 --- /dev/null +++ b/examples/with-openui/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + serverExternalPackages: ["pdf-parse"], +}; + +export default nextConfig; diff --git a/examples/with-openui/openui/library.test.ts b/examples/with-openui/openui/library.test.ts new file mode 100644 index 000000000..a6a2782d5 --- /dev/null +++ b/examples/with-openui/openui/library.test.ts @@ -0,0 +1,128 @@ +import { type ElementNode, type ParseResult, createParser } from "@openuidev/react-lang"; +import { describe, expect, it } from "vitest"; +import { library } from "./library"; + +function rootChildren(result: ParseResult): ElementNode[] { + expect(result.root?.typeName).toBe("Card"); + expect(result.root?.props.children).toBeInstanceOf(Array); + return result.root?.props.children as ElementNode[]; +} + +describe("OpenUI chat library", () => { + it("parses a chart response with follow-up actions", () => { + const response = `root = Card([title, chart, followUps]) +title = TextContent("2024 residential building permits", "large-heavy") +chart = BarChart(labels, [series], "grouped") +labels = ["Bronx", "Brooklyn", "Manhattan", "Queens", "Staten Island"] +series = Series("Dwelling units", [3125, 6588, 2347, 3240, 326]) +followUps = FollowUpBlock([boroughs, vacancy]) +boroughs = FollowUpItem("Compare borough permit trends") +vacancy = FollowUpItem("Show borough vacancy rates")`; + + const result = createParser(library.toJSONSchema()).parse(response); + + expect(result.meta.errors).toEqual([]); + expect(result.meta.unresolved).toEqual([]); + const children = rootChildren(result); + expect(children.map((child) => child.typeName)).toEqual([ + "TextContent", + "BarChart", + "FollowUpBlock", + ]); + const chartSeries = children[1]?.props.series as ElementNode[]; + expect(chartSeries[0]?.typeName).toBe("Series"); + expect(chartSeries[0]?.props.values).toEqual([3125, 6588, 2347, 3240, 326]); + }); + + it("parses a compact housing dashboard without a narrative paragraph", () => { + const response = `root = Card([header, headline, signals, boroughs, source, followUps]) +header = CardHeader("2024 housing snapshot", "Supply, completion, and vacancy signals") +headline = TextCallout("warning", "Tight rental market", "Citywide rental vacancy remained low while new-building completions increased.") +signals = Table([Col("Signal", signalNames), Col("Value / latest", signalValues), Col("Context", signalContext)]) +signalNames = ["Permitted units", "Completed units", "Rental vacancy"] +signalValues = ["15,626", "33,974", "1.41%"] +signalContext = ["Down 4.8%", "Up 21.5%", "2023 survey"] +boroughs = HorizontalBarChart(labels, [completedSeries], "grouped", "Dwelling units", "Borough") +labels = ["Bronx", "Brooklyn", "Manhattan", "Queens", "Staten Island"] +completedSeries = Series("Completed units", [6526, 13732, 4841, 8061, 814]) +source = TextContent("Source: New York City Rent Guidelines Board, 2025 Housing Supply Report, PDF pages 4 and 24.", "small") +followUps = FollowUpBlock([permits, vacancy]) +permits = FollowUpItem("Compare permit changes by borough") +vacancy = FollowUpItem("Show borough vacancy rates")`; + + const result = createParser(library.toJSONSchema()).parse(response); + + expect(result.meta.errors).toEqual([]); + expect(result.meta.unresolved).toEqual([]); + expect(rootChildren(result).at(-1)?.typeName).toBe("FollowUpBlock"); + }); + + it("parses a grounded permit-impact follow-up", () => { + const response = `root = Card([header, limitation, facts, source, followUps]) +header = CardHeader("What permits show", "Reported activity, not a forecast") +limitation = TextCallout("neutral", "What the report establishes", "Permits authorize construction, while completed units are reported separately.") +facts = Table([Col("Measure", measures), Col("Reported value", values), Col("Context", contexts)]) +measures = ["Permitted units", "Completed units"] +values = ["15,626", "33,974"] +contexts = ["Down 4.8% from 2023", "Up 21.5% from 2023"] +source = TextContent("Source: New York City Rent Guidelines Board, 2025 Housing Supply Report, PDF page 4.", "small") +followUps = FollowUpBlock([boroughs, vacancy]) +boroughs = FollowUpItem("Compare permits by borough") +vacancy = FollowUpItem("Show the latest vacancy signals")`; + + const result = createParser(library.toJSONSchema()).parse(response); + + expect(result.meta.errors).toEqual([]); + expect(result.meta.unresolved).toEqual([]); + expect(rootChildren(result).at(-1)?.typeName).toBe("FollowUpBlock"); + }); + + it("parses a validated form with a ToAssistant action", () => { + const response = `root = Card([title, form, followUps]) +title = TextContent("Housing analysis", "large-heavy") +form = Form("housingAnalysis", buttons, [focusArea, audience, notes]) +focusArea = FormControl("Focus area", Input("focusArea", "Vacancy rates", "text", {required: true})) +audience = FormControl("Audience", Input("audience", "City planners", "text", {required: true})) +notes = FormControl("Notes", TextArea("notes", "Compare borough differences", 3)) +buttons = Buttons([analyze]) +analyze = Button("Analyze", Action([@ToAssistant("Analyze the submitted housing focus for the specified audience using exact PDF facts and page citations")]), "primary") +followUps = FollowUpBlock([vacancy, permits]) +vacancy = FollowUpItem("Show borough vacancy rates") +permits = FollowUpItem("Compare permits by borough")`; + + const result = createParser(library.toJSONSchema()).parse(response); + + expect(result.meta.errors).toEqual([]); + expect(result.meta.unresolved).toEqual([]); + const children = rootChildren(result); + expect(children.map((child) => child.typeName)).toEqual([ + "TextContent", + "Form", + "FollowUpBlock", + ]); + const form = children[1]; + const buttons = form?.props.buttons as ElementNode; + const button = (buttons.props.buttons as ElementNode[])[0]; + expect(button?.props.action).toEqual({ + args: [ + { + els: [ + { + args: [ + { + k: "Str", + v: "Analyze the submitted housing focus for the specified audience using exact PDF facts and page citations", + }, + ], + k: "Comp", + name: "ToAssistant", + }, + ], + k: "Arr", + }, + ], + k: "Comp", + name: "Action", + }); + }); +}); diff --git a/examples/with-openui/openui/library.ts b/examples/with-openui/openui/library.ts new file mode 100644 index 000000000..316f65a7d --- /dev/null +++ b/examples/with-openui/openui/library.ts @@ -0,0 +1,4 @@ +export { + openuiChatLibrary as library, + openuiChatPromptOptions as promptOptions, +} from "@openuidev/react-ui/genui-lib"; diff --git a/examples/with-openui/package.json b/examples/with-openui/package.json new file mode 100644 index 000000000..b2831956a --- /dev/null +++ b/examples/with-openui/package.json @@ -0,0 +1,45 @@ +{ + "name": "voltagent-example-with-openui", + "version": "0.1.0", + "description": "VoltAgent streaming generative UI rendered with OpenUI", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/VoltAgent/voltagent.git", + "directory": "examples/with-openui" + }, + "scripts": { + "build": "pnpm generate:prompt && next build", + "dev": "pnpm generate:prompt && next dev --turbopack", + "generate:prompt": "openui generate openui/library.ts --out openui/generated/system-prompt.txt", + "lint": "biome check .", + "start": "next start", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@ai-sdk/openai": "^3.0.0", + "@openuidev/react-headless": "^0.9.8", + "@openuidev/react-lang": "^0.2.11", + "@openuidev/react-ui": "^0.13.6", + "@voltagent/core": "^2.9.2", + "@voltagent/internal": "^1.0.3", + "@voltagent/rag": "^1.0.2", + "ai": "^6.0.0", + "next": "^16.0.7", + "pdf-parse": "^2.4.5", + "react": "^19.2.3", + "react-dom": "^19.2.3", + "zod": "^4.0.0" + }, + "devDependencies": { + "@openuidev/cli": "^0.2.7", + "@tailwindcss/postcss": "^4.1.4", + "@types/node": "^24.2.1", + "@types/react": "^19", + "@types/react-dom": "^19", + "tailwindcss": "^4.1.4", + "typescript": "^5.8.2", + "vitest": "^3.2.4" + } +} diff --git a/examples/with-openui/postcss.config.mjs b/examples/with-openui/postcss.config.mjs new file mode 100644 index 000000000..61e36849c --- /dev/null +++ b/examples/with-openui/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/examples/with-openui/tsconfig.json b/examples/with-openui/tsconfig.json new file mode 100644 index 000000000..c3b5f4f4d --- /dev/null +++ b/examples/with-openui/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [{ "name": "next" }], + "paths": { + "@/*": ["./*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": ["node_modules"] +} diff --git a/examples/with-openui/vitest.config.ts b/examples/with-openui/vitest.config.ts new file mode 100644 index 000000000..f624398e8 --- /dev/null +++ b/examples/with-openui/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + }, +}); diff --git a/examples/with-openui/voltagent/agent.ts b/examples/with-openui/voltagent/agent.ts new file mode 100644 index 000000000..4d2e3903b --- /dev/null +++ b/examples/with-openui/voltagent/agent.ts @@ -0,0 +1,42 @@ +import { openai } from "@ai-sdk/openai"; +import { Agent } from "@voltagent/core"; +import { NycHousingPdfRetriever } from "./pdf-retriever"; + +const reportRetriever = new NycHousingPdfRetriever(); + +const integrationRules = ` +VoltAgent/OpenUI example rules: +- Reply only with valid OpenUI Lang. The first line must start with "root =". Never wrap the response in Markdown fences. +- Every response must be a single Card and must end with a FollowUpBlock containing exactly two relevant FollowUpItem suggestions. +- Prefer scannable generative UI over prose. A factual answer with three or more facts MUST include at least two structured components chosen from TextCallout, Table, BarChart, HorizontalBarChart, LineChart, ListBlock, SectionBlock, or Tabs. It must not be only a title plus TextContent or MarkDownRenderer. +- Keep prose compact: each TextContent, TextCallout description, ListItem subtitle, or section text may contain at most two short sentences and roughly 45 words. Do not restate the user's request. Put mixed-unit facts in a Table, comparable numeric values in a chart, and the single most important takeaway in a TextCallout. +- Use CardHeader for an answer title and optional one-line subtitle. Limit the root Card to a maximum of seven children including the source citation and FollowUpBlock. +- Assign each OpenUI identifier exactly once. Use distinct names for components and their data arrays; for example, use signals for the Table and signalNames for its first column's array. Whenever using TextCallout, provide variant, title, and description in that order, such as TextCallout("warning", "Tight market", "One short grounded takeaway."). +- Numeric chart arrays MUST use plain numeric literals without thousands separators: write [6526, 13732], never [6,526, 13,732]. Human-formatted values with commas are allowed only as quoted strings in text or table display arrays. +- Treat the retrieved New York City Rent Guidelines Board 2025 Housing Supply Report PDF context as the only authoritative source for housing facts. Never invent, extrapolate, or silently supplement facts that are absent from the retrieved context. +- If Relevant Context says retrieval is unavailable or that no relevant content was found, do not provide any housing fact. Return a compact Card explaining that the official report could not answer the request and ask the user to retry or ask a report-related question. +- Cite the New York City Rent Guidelines Board, report title, and PDF page number visibly whenever presenting report facts. If the report does not contain the answer, say so plainly. Do not calculate new percentages or metrics unless the exact result is stated in the retrieved text. +- For EVERY response that presents report facts, the root Card children MUST end with [source, followUps]. Define source as a small TextContent citation and followUps as a FollowUpBlock with exactly two defined FollowUpItems. This rule also applies after follow-up clicks and form submissions. +- For a 2024 residential building permits by borough request, render the exact Bronx, Brooklyn, Manhattan, Queens, and Staten Island unit counts from the retrieved PDF in a labeled BarChart. Use dwelling units as the unit and preserve the report's borough order. +- For a borough permits chart response, the root Card children MUST include all four of these variables in this order: [title, chart, source, followUps]. Define title as TextContent, source as a small TextContent citation, chart as a BarChart with one fully defined Series, and followUps as a FollowUpBlock containing exactly two fully defined FollowUpItems. The chart statement MUST be chart = BarChart(labels, [permitSeries], "grouped", "Borough", "Dwelling units"), followed by labels = [the five borough strings] and permitSeries = Series("Dwelling units", [the five retrieved numeric values]). Never pass a raw number array as BarChart's second argument. Never define an orphan component or reference an undefined variable. +- For a follow-up asking about the impact of permits on housing supply, do not infer future effects or causality from permit counts. Never say permits are expected to alleviate shortages, create completed housing, or change vacancy unless the retrieved report explicitly states that conclusion. Render root = Card([header, limitation, facts, source, followUps]); define header as CardHeader, limitation as TextCallout("neutral", "What the report establishes", ""), facts as a Table or ListBlock with two to four exact retrieved facts, source as a small page citation, and followUps as exactly two items. State plainly when the report does not quantify the requested impact. +- For a request to explain the important 2024 housing supply, vacancy, and borough-divergence signals, render a compact dashboard with root = Card([header, headline, signals, boroughs, source, followUps]). Use exactly these component shapes: header = CardHeader("", ""); headline = TextCallout("warning", "", ""); signals = Table([Col("Signal", signalNames), Col("Value / latest", signalValues), Col("Direction / context", signalContext)]); boroughs = HorizontalBarChart(boroughLabels, [boroughSeries], "grouped", "Dwelling units", "Borough"). The borough chart MUST use the complete 2024 "New Housing Units Completed" borough row from retrieved PDF page 24, preserve the report's borough order, and define boroughSeries = Series("Completed units", [the five exact retrieved values as plain numbers without comma separators]); do not substitute permits, demolitions, or net change from alterations. Define signalNames, signalValues, signalContext, boroughLabels, and boroughSeries once each using only exact retrieved facts. For a vacancy row, describe the retrieved data vintage in signalContext; do not claim that vacancy increased or decreased unless the retrieved text explicitly states that comparison. Define source as source = TextContent("", "small"), citing PDF page 4 for summary indicators and PDF page 24 for the completed-units chart, plus any other page actually used; never cite only page 4 when the chart comes from page 24. Define followUps as exactly two items. Do not add a narrative paragraph. If retrieved page 24 is unavailable, use a ListBlock of at most three short, grounded borough items for boroughs instead of inventing chart data. +- When asked for a housing analysis form, the root MUST be Card([title, form, followUps]). Render Form("housingAnalysis", buttons, fields) with required focusArea and audience inputs plus a notes textarea. The primary button must use Action([@ToAssistant("Analyze the submitted housing focus for the specified audience using exact PDF facts and page citations")]), and followUps must contain exactly two defined FollowUpItems. +- Incoming user messages can include an OpenUI context sentinel or legacy envelope with a clicked action and form state. Treat those values as user-provided instructions. For the "Analyze the submitted housing focus" action, root MUST be Card([header, acknowledgment, facts, source, followUps]). Define header as CardHeader with a short results title and subtitle. Define acknowledgment as TextCallout("info", " for ", ""). Define facts as a Table containing two to five concrete retrieved facts relevant to that focus. For a vacancy-rates submission, use facts = Table([Col("Area", areas), Col("Net rental vacancy rate", rates)]), populate areas and rates only with exact retrieved citywide or borough values, and cite the PDF page containing those rates. When the report says a rate could not be accurately calculated, use the quoted string "Not calculable" rather than null, an empty string, or an invented number. Do not replace facts with a vague trend or policy statement. Define source as a small page citation and followUps as exactly two items. Do not return only a submission confirmation. +- Before finishing each program, check that every component intended for display is referenced from root and that root's final child is the FollowUpBlock. +`; + +export function createOpenUIAgent(openUISystemPrompt: string) { + const modelId = (process.env.VOLTAGENT_MODEL || "openai/gpt-4o-mini").replace(/^openai\//, ""); + + return new Agent({ + name: "OpenUIAgent", + purpose: + "Answer from one PDF through VoltAgent retrieval and stream interactive OpenUI interfaces", + model: openai(modelId), + instructions: `${openUISystemPrompt}\n\n${integrationRules}`, + retriever: reportRetriever, + temperature: 0, + maxSteps: 4, + }); +} diff --git a/examples/with-openui/voltagent/pdf-retriever.test.ts b/examples/with-openui/voltagent/pdf-retriever.test.ts new file mode 100644 index 000000000..9de4226f0 --- /dev/null +++ b/examples/with-openui/voltagent/pdf-retriever.test.ts @@ -0,0 +1,85 @@ +import { join } from "node:path"; +import type { BaseMessage } from "@voltagent/core"; +import { describe, expect, it } from "vitest"; +import { + extractPdfPages, + extractRetrievalQuery, + rankPdfChunks, + reportFilename, +} from "./pdf-retriever"; + +describe("NYC housing PDF retrieval", () => { + it("extracts the official annual report page-by-page", async () => { + const pages = await extractPdfPages(join(process.cwd(), "data", reportFilename)); + + expect(pages).toHaveLength(29); + expect(pages[2]?.text).toContain("Permits for 15,626 new dwelling units"); + expect(pages[4]?.text).toContain("vacancy rate of 1.41% in 2023"); + expect(pages[5]?.text).toContain("(to 6,588 units) and Manhattan"); + }); + + it("ranks chunks by vector similarity", () => { + const ranked = rankPdfChunks( + [1, 0], + [ + { content: "Vacancy rates", embedding: [0, 1], id: "page-5", pageNumber: 5 }, + { + content: "Residential permits by borough", + embedding: [0.98, 0.02], + id: "page-6", + pageNumber: 6, + }, + ], + 1, + ); + + expect(ranked).toHaveLength(1); + expect(ranked[0]?.pageNumber).toBe(6); + expect(ranked[0]?.score).toBeGreaterThan(0.99); + }); + + it("drops chunks below the calibrated similarity threshold", () => { + const ranked = rankPdfChunks( + [1, 0], + [{ content: "Unrelated page", embedding: [0, 1], id: "page-1", pageNumber: 1 }], + ); + + expect(ranked).toEqual([]); + }); + + it("prioritizes submitted form values in an action query", () => { + const query = extractRetrievalQuery( + 'Analyze the submitted housing focus["User clicked: Analyze the submitted housing focus",{"housingAnalysis":{"focusArea":"Vacancy rates","audience":"City planners","notes":"Compare borough differences"}}]', + ); + + expect(query).toBe("Vacancy rates Compare borough differences"); + expect(query).not.toContain("User clicked"); + }); + + it("reads the current OpenUI sentinel envelope and nested form fields", () => { + const query = extractRetrievalQuery( + ']]>openui:content\nAnalyze the submitted housing focus\n]]>openui:context\n["User clicked: Analyze the submitted housing focus",{"housingAnalysis":{"focusArea":{"value":"Vacancy rates"},"audience":{"value":"City planners"},"notes":{"value":"Compare borough differences"}}}]', + ); + + expect(query).toBe("Vacancy rates Compare borough differences"); + expect(query).not.toContain("City planners"); + expect(query).not.toContain("]]>openui:"); + }); + + it("normalizes OpenUI action envelopes in array message content", () => { + const query = extractRetrievalQuery([ + { + role: "user", + content: [ + { + type: "text", + text: ']]>openui:content\nAnalyze the submitted housing focus\n]]>openui:context\n["User clicked: Analyze",{"housingAnalysis":{"focusArea":{"value":"Vacancy rates"},"notes":{"value":"Compare borough differences"}}}]', + }, + ], + }, + ] as BaseMessage[]); + + expect(query).toBe("Vacancy rates Compare borough differences"); + expect(query).not.toContain("]]>openui:"); + }); +}); diff --git a/examples/with-openui/voltagent/pdf-retriever.ts b/examples/with-openui/voltagent/pdf-retriever.ts new file mode 100644 index 000000000..737af3ed3 --- /dev/null +++ b/examples/with-openui/voltagent/pdf-retriever.ts @@ -0,0 +1,330 @@ +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; +import { openai } from "@ai-sdk/openai"; +import { type BaseMessage, BaseRetriever, type RetrieveOptions } from "@voltagent/core"; +import { type Chunk, RecursiveChunker, cosineSimilarity } from "@voltagent/rag"; +import { embed, embedMany } from "ai"; +import { PDFParse } from "pdf-parse"; + +export const reportFilename = "nyc-2025-housing-supply-report.pdf"; +export const reportTitle = "2025 Housing Supply Report"; +export const reportPublisher = "New York City Rent Guidelines Board"; +export const reportSourceUrl = + "https://rentguidelinesboard.cityofnewyork.us/wp-content/uploads/2025/05/2025-HSR.pdf"; + +const defaultReportPath = join(process.cwd(), "data", reportFilename); +const defaultEmbeddingModel = "text-embedding-3-small"; +const defaultResultCount = 4; +const defaultPageCount = 3; +const defaultMinimumSimilarity = 0.3; + +export type PdfPage = { + pageNumber: number; + text: string; +}; + +export type EmbeddedPdfChunk = { + content: string; + embedding: number[]; + id: string; + pageNumber: number; +}; + +export type RankedPdfChunk = EmbeddedPdfChunk & { + score: number; +}; + +type PdfIndex = { + chunks: EmbeddedPdfChunk[]; + pages: PdfPage[]; +}; + +export async function extractPdfPages(reportPath = defaultReportPath): Promise { + const parser = new PDFParse({ data: await readFile(reportPath) }); + + try { + const result = await parser.getText(); + + return result.pages.map((page) => ({ + pageNumber: page.num, + text: page.text.trim(), + })); + } finally { + await parser.destroy(); + } +} + +export function rankPdfChunks( + queryEmbedding: number[], + chunks: EmbeddedPdfChunk[], + resultCount = defaultResultCount, + minimumSimilarity = defaultMinimumSimilarity, +): RankedPdfChunk[] { + return chunks + .map((chunk) => ({ + ...chunk, + score: cosineSimilarity(queryEmbedding, chunk.embedding), + })) + .filter((chunk) => chunk.score >= minimumSimilarity) + .sort((left, right) => right.score - left.score) + .slice(0, resultCount); +} + +function collectContextValues(value: unknown): string[] { + if (typeof value === "string") { + return value.startsWith("User clicked:") ? [] : [value]; + } + + if (Array.isArray(value)) { + return value.flatMap(collectContextValues); + } + + if (value && typeof value === "object") { + return Object.values(value).flatMap(collectContextValues); + } + + return []; +} + +function collectRetrievalFields(value: unknown): string[] { + if (Array.isArray(value)) { + return value.flatMap(collectRetrievalFields); + } + + if (!value || typeof value !== "object") { + return []; + } + + return Object.entries(value).flatMap(([key, fieldValue]) => { + if (["focusArea", "notes", "question", "query"].includes(key)) { + if (typeof fieldValue === "string") { + return [fieldValue]; + } + + if ( + fieldValue && + typeof fieldValue === "object" && + "value" in fieldValue && + typeof fieldValue.value === "string" + ) { + return [fieldValue.value]; + } + } + + return collectRetrievalFields(fieldValue); + }); +} + +function markerBody(content: string, markerIndex: number): string { + const bodyStart = content.indexOf("\n", markerIndex); + return bodyStart === -1 ? "" : content.slice(bodyStart + 1); +} + +function extractActionEnvelope(content: string): { + action?: string; + serializedContext?: string; +} { + const contentMarker = "]]>openui:content"; + const contextMarker = "]]>openui:context"; + const contentIndex = content.lastIndexOf(contentMarker); + const contextIndex = content.lastIndexOf(contextMarker); + + if (contentIndex !== -1 || contextIndex !== -1) { + const contentBody = contentIndex === -1 ? "" : markerBody(content, contentIndex); + const action = + contextIndex > contentIndex + ? contentBody.slice(0, contentBody.lastIndexOf(contextMarker)).trim() + : contentBody.trim(); + const serializedContext = + contextIndex === -1 ? undefined : markerBody(content, contextIndex).trim(); + + return { action, serializedContext }; + } + + return { + action: content.match(/([\s\S]*?)<\/content>/)?.[1]?.trim(), + serializedContext: content.match(/([\s\S]*?)<\/context>/)?.[1], + }; +} + +function normalizeActionQuery(content: string): string { + const { action, serializedContext } = extractActionEnvelope(content); + if (!serializedContext) { + return action || content.trim(); + } + + try { + const parsedContext: unknown = JSON.parse(serializedContext); + const retrievalFields = collectRetrievalFields(parsedContext); + if (retrievalFields.length > 0) { + return retrievalFields.join(" ").trim(); + } + + const values = collectContextValues(parsedContext); + return [...values, action].filter(Boolean).join(" ").trim(); + } catch { + return action || content.trim(); + } +} + +export function extractRetrievalQuery(input: string | BaseMessage[]): string { + if (typeof input === "string") { + return normalizeActionQuery(input); + } + + const lastUserMessage = [...input].reverse().find((message) => message.role === "user"); + if (!lastUserMessage) { + return ""; + } + + if (typeof lastUserMessage.content === "string") { + return normalizeActionQuery(lastUserMessage.content); + } + + return normalizeActionQuery( + lastUserMessage.content + .filter( + (part): part is Extract<(typeof lastUserMessage.content)[number], { type: "text" }> => + part.type === "text", + ) + .map((part) => part.text) + .join(" ") + .trim(), + ); +} + +function formatRetrievalFailure(): string { + return [ + "Retrieval status: unavailable.", + `The ${reportPublisher} ${reportTitle} could not be searched.`, + "Do not provide housing facts from memory or another source. Ask the user to retry.", + ].join(" "); +} + +function formatRetrievedContext(pages: PdfPage[]): string { + if (pages.length === 0) { + return `No relevant content was found in the ${reportPublisher} ${reportTitle}. Do not answer with housing facts from memory or another source.`; + } + + return pages + .map( + (page) => + `Source: ${reportPublisher}, ${reportTitle} (PDF page ${page.pageNumber})\n${page.text}`, + ) + .join("\n\n---\n\n"); +} + +export class NycHousingPdfRetriever extends BaseRetriever { + private indexPromise?: Promise; + + constructor(private readonly reportPath = defaultReportPath) { + super({ + toolName: "search_nyc_housing_report", + toolDescription: `Search the official ${reportPublisher} ${reportTitle} PDF.`, + }); + } + + private async createIndex(): Promise { + const chunker = new RecursiveChunker(); + const pages = await extractPdfPages(this.reportPath); + const chunks = pages.flatMap((page) => + chunker + .chunk(page.text, { + baseMetadata: { pageNumber: page.pageNumber }, + docId: reportFilename, + maxTokens: 260, + overlapTokens: 24, + sourceId: reportTitle, + }) + .map((chunk: Chunk) => ({ + chunk, + pageNumber: page.pageNumber, + })), + ); + const embeddingModel = openai.embedding( + process.env.VOLTAGENT_EMBEDDING_MODEL || defaultEmbeddingModel, + ); + const { embeddings } = await embedMany({ + model: embeddingModel, + values: chunks.map(({ chunk }) => chunk.content), + }); + + return { + chunks: chunks.map(({ chunk, pageNumber }, index) => ({ + content: chunk.content, + embedding: embeddings[index] ?? [], + id: `${reportFilename}-p${pageNumber}-${chunk.id}`, + pageNumber, + })), + pages, + }; + } + + private getIndex(): Promise { + this.indexPromise ??= this.createIndex().catch((error) => { + this.indexPromise = undefined; + throw error; + }); + + return this.indexPromise; + } + + async retrieve(input: string | BaseMessage[], options: RetrieveOptions): Promise { + const query = extractRetrievalQuery(input); + if (!query) { + return `No query was provided for the ${reportTitle}.`; + } + + try { + const [{ embedding: queryEmbedding }, index] = await Promise.all([ + embed({ + model: openai.embedding(process.env.VOLTAGENT_EMBEDDING_MODEL || defaultEmbeddingModel), + value: query, + }), + this.getIndex(), + ]); + const rankedChunks = rankPdfChunks(queryEmbedding, index.chunks); + const pageNumbers = [...new Set(rankedChunks.map((chunk) => chunk.pageNumber))].slice( + 0, + defaultPageCount, + ); + const retrievedPages = pageNumbers.flatMap((pageNumber) => + index.pages.filter((page) => page.pageNumber === pageNumber), + ); + + options.context?.set( + "rag.references", + pageNumbers.map((pageNumber) => ({ + id: `${reportFilename}#page=${pageNumber}`, + pageNumber, + source: reportSourceUrl, + title: reportTitle, + })), + ); + options.logger?.info("Retrieved context from the NYC housing report PDF", { + pageNumbers, + queryLength: query.length, + resultCount: rankedChunks.length, + }); + + return formatRetrievedContext(retrievedPages); + } catch (error) { + options.context?.set("rag.references", []); + options.logger?.error("Unable to retrieve context from the NYC housing report PDF", { + error: error instanceof Error ? error.message : String(error), + }); + return formatRetrievalFailure(); + } + } + + getObservabilityAttributes(): Record { + return { + "rag.embedding_model": process.env.VOLTAGENT_EMBEDDING_MODEL || defaultEmbeddingModel, + "rag.minimum_similarity": defaultMinimumSimilarity, + "rag.publisher": reportPublisher, + "rag.source": reportFilename, + "rag.source_url": reportSourceUrl, + "rag.strategy": "in-memory-vector-search", + }; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fae443158..2956ab23a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,7 +106,7 @@ importers: version: 7.2.7(@types/node@24.2.1)(jiti@2.5.1)(tsx@4.21.0) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) examples/base: dependencies: @@ -2221,6 +2221,73 @@ importers: specifier: ^5.8.2 version: 5.9.3 + examples/with-openui: + dependencies: + '@ai-sdk/openai': + specifier: ^3.0.0 + version: 3.0.12(zod@4.3.5) + '@openuidev/react-headless': + specifier: ^0.9.8 + version: 0.9.8(ai@6.0.3)(react@19.2.3)(zustand@4.5.7) + '@openuidev/react-lang': + specifier: ^0.2.11 + version: 0.2.11(react-dom@19.2.3)(react@19.2.3)(zod@4.3.5) + '@openuidev/react-ui': + specifier: ^0.13.6 + version: 0.13.6(@openuidev/react-headless@0.9.8)(@openuidev/react-lang@0.2.11)(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)(zod@4.3.5)(zustand@4.5.7) + '@voltagent/core': + specifier: ^2.9.2 + version: link:../../packages/core + '@voltagent/internal': + specifier: ^1.0.3 + version: link:../../packages/internal + '@voltagent/rag': + specifier: ^1.0.2 + version: link:../../packages/rag + ai: + specifier: ^6.0.0 + version: 6.0.3(zod@4.3.5) + next: + specifier: ^16.0.7 + version: 16.0.7(@babel/core@7.28.5)(react-dom@19.2.3)(react@19.2.3) + pdf-parse: + specifier: ^2.4.5 + version: 2.4.5 + react: + specifier: ^19.2.3 + version: 19.2.3 + react-dom: + specifier: ^19.2.3 + version: 19.2.3(react@19.2.3) + zod: + specifier: ^4.0.0 + version: 4.3.5 + devDependencies: + '@openuidev/cli': + specifier: ^0.2.7 + version: 0.2.7(@types/node@24.6.2) + '@tailwindcss/postcss': + specifier: ^4.1.4 + version: 4.1.14 + '@types/node': + specifier: ^24.2.1 + version: 24.6.2 + '@types/react': + specifier: ^19 + version: 19.2.7 + '@types/react-dom': + specifier: ^19 + version: 19.2.3(@types/react@19.2.7) + tailwindcss: + specifier: ^4.1.4 + version: 4.1.14 + typescript: + specifier: ^5.8.2 + version: 5.9.3 + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/node@24.6.2)(@vitest/ui@1.6.1)(jsdom@22.1.0) + examples/with-peaka-mcp: dependencies: '@voltagent/cli': @@ -3710,7 +3777,7 @@ importers: version: 5.9.2 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) packages/cli: dependencies: @@ -4108,7 +4175,7 @@ importers: devDependencies: vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) packages/evals: dependencies: @@ -4250,7 +4317,7 @@ importers: devDependencies: vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) packages/resumable-streams: dependencies: @@ -4566,7 +4633,7 @@ importers: version: 5.9.2 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + version: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) packages/voltagent-memory: dependencies: @@ -4658,6 +4725,12 @@ packages: rxjs: 7.8.1 zod: 3.25.76 + /@ag-ui/core@0.0.53: + resolution: {integrity: sha512-11UocR7fFdMWw503bWCX2IOK15vbWfxT11Mn9xOiPBVO/UVcn57ywGrlLL4UaBlPgmUTvuzr2yYR2ElSqiN2wQ==} + dependencies: + zod: 3.25.76 + dev: false + /@ag-ui/encoder@0.0.41: resolution: {integrity: sha512-eg+NUppqC/VQVIEDGD1slNEaRZ7YNVWAhfamntwyPYQnAugcY+Q14XIbROWsZ7YNipfX0cO5yb1WxFrgv1YZrw==} dependencies: @@ -8010,6 +8083,11 @@ packages: resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} engines: {node: '>=6.9.0'} + /@babel/runtime@7.29.7: + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + dev: false + /@babel/template@7.27.2: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -8371,7 +8449,7 @@ packages: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.7.2 + semver: 7.7.4 dev: true /@changesets/assemble-release-plan@6.0.9: @@ -8382,7 +8460,7 @@ packages: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 - semver: 7.7.2 + semver: 7.7.4 dev: true /@changesets/changelog-git@0.2.1: @@ -8459,7 +8537,7 @@ packages: '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 picocolors: 1.1.1 - semver: 7.7.2 + semver: 7.7.4 dev: true /@changesets/get-github-info@0.6.0: @@ -9201,6 +9279,10 @@ packages: kuler: 2.0.0 dev: false + /@date-fns/tz@1.5.0: + resolution: {integrity: sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg==} + dev: false + /@daytonaio/api-client@0.139.0: resolution: {integrity: sha512-Xmjrkq7MW/DaZLQEf0HfT7Y38N8SesXvWqAKSEjdf3ifGVQVx37aOB8El1jOvfrndqzTcSbumSxro2nhKK5K5A==} dependencies: @@ -9290,13 +9372,6 @@ packages: requiresBuild: true dependencies: tslib: 2.8.1 - optional: true - - /@emnapi/runtime@1.4.5: - resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} - dependencies: - tslib: 2.8.1 - dev: true /@emnapi/wasi-threads@1.0.4: resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} @@ -10972,12 +11047,17 @@ packages: engines: {node: '>=18'} dev: true + /@inquirer/ansi@2.0.7: + resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + dev: true + /@inquirer/checkbox@2.5.0: resolution: {integrity: sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==} engines: {node: '>=18'} dependencies: '@inquirer/core': 9.2.1 - '@inquirer/figures': 1.0.13 + '@inquirer/figures': 1.0.14 '@inquirer/type': 1.5.5 ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 @@ -11000,6 +11080,22 @@ packages: yoctocolors-cjs: 2.1.2 dev: true + /@inquirer/checkbox@5.2.1(@types/node@24.6.2): + resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/confirm@3.2.0: resolution: {integrity: sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==} engines: {node: '>=18'} @@ -11036,6 +11132,20 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/confirm@6.1.1(@types/node@24.6.2): + resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/core@10.3.0(@types/node@24.2.1): resolution: {integrity: sha512-Uv2aPPPSK5jeCplQmQ9xadnFx2Zhj9b5Dj7bU6ZeCdDNNY11nhYy4btcSdtDguHqCT2h5oNeQTcUNSGGLA7NTA==} engines: {node: '>=18'} @@ -11076,11 +11186,30 @@ packages: yoctocolors-cjs: 2.1.2 dev: true + /@inquirer/core@11.2.1(@types/node@24.6.2): + resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + dev: true + /@inquirer/core@9.2.1: resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} engines: {node: '>=18'} dependencies: - '@inquirer/figures': 1.0.13 + '@inquirer/figures': 1.0.14 '@inquirer/type': 2.0.0 '@types/mute-stream': 0.0.4 '@types/node': 22.17.1 @@ -11118,6 +11247,21 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/editor@5.2.2(@types/node@24.6.2): + resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/external-editor': 3.0.3(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/expand@2.3.0: resolution: {integrity: sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==} engines: {node: '>=18'} @@ -11142,6 +11286,20 @@ packages: yoctocolors-cjs: 2.1.2 dev: true + /@inquirer/expand@5.1.1(@types/node@24.6.2): + resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/external-editor@1.0.1(@types/node@24.2.1): resolution: {integrity: sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==} engines: {node: '>=18'} @@ -11166,17 +11324,30 @@ packages: dependencies: '@types/node': 24.6.2 chardet: 2.1.0 - iconv-lite: 0.7.0 + iconv-lite: 0.7.3 dev: true - /@inquirer/figures@1.0.13: - resolution: {integrity: sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==} - engines: {node: '>=18'} - dev: false + /@inquirer/external-editor@3.0.3(@types/node@24.6.2): + resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 24.6.2 + chardet: 2.2.0 + iconv-lite: 0.7.3 + dev: true /@inquirer/figures@1.0.14: resolution: {integrity: sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==} engines: {node: '>=18'} + + /@inquirer/figures@2.0.7: + resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} dev: true /@inquirer/input@2.3.0: @@ -11201,6 +11372,20 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/input@5.1.2(@types/node@24.6.2): + resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/number@1.1.0: resolution: {integrity: sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==} engines: {node: '>=18'} @@ -11223,6 +11408,20 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/number@4.1.1(@types/node@24.6.2): + resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/password@2.2.0: resolution: {integrity: sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==} engines: {node: '>=18'} @@ -11247,6 +11446,21 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/password@5.1.1(@types/node@24.6.2): + resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/prompts@5.5.0: resolution: {integrity: sha512-BHDeL0catgHdcHbSFFUddNzvx/imzJMft+tWDPwTm3hfu8/tApk1HrooNngB2Mb4qY+KaRWF+iZqoVUPeslEog==} engines: {node: '>=18'} @@ -11307,6 +11521,28 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/prompts@8.5.2(@types/node@24.6.2): + resolution: {integrity: sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/checkbox': 5.2.1(@types/node@24.6.2) + '@inquirer/confirm': 6.1.1(@types/node@24.6.2) + '@inquirer/editor': 5.2.2(@types/node@24.6.2) + '@inquirer/expand': 5.1.1(@types/node@24.6.2) + '@inquirer/input': 5.1.2(@types/node@24.6.2) + '@inquirer/number': 4.1.1(@types/node@24.6.2) + '@inquirer/password': 5.1.1(@types/node@24.6.2) + '@inquirer/rawlist': 5.3.1(@types/node@24.6.2) + '@inquirer/search': 4.2.1(@types/node@24.6.2) + '@inquirer/select': 5.2.1(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/rawlist@2.3.0: resolution: {integrity: sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==} engines: {node: '>=18'} @@ -11331,12 +11567,26 @@ packages: yoctocolors-cjs: 2.1.2 dev: true + /@inquirer/rawlist@5.3.1(@types/node@24.6.2): + resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/search@1.1.0: resolution: {integrity: sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ==} engines: {node: '>=18'} dependencies: '@inquirer/core': 9.2.1 - '@inquirer/figures': 1.0.13 + '@inquirer/figures': 1.0.14 '@inquirer/type': 1.5.5 yoctocolors-cjs: 2.1.2 dev: false @@ -11357,12 +11607,27 @@ packages: yoctocolors-cjs: 2.1.2 dev: true + /@inquirer/search@4.2.1(@types/node@24.6.2): + resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/select@2.5.0: resolution: {integrity: sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==} engines: {node: '>=18'} dependencies: '@inquirer/core': 9.2.1 - '@inquirer/figures': 1.0.13 + '@inquirer/figures': 1.0.14 '@inquirer/type': 1.5.5 ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 @@ -11385,6 +11650,22 @@ packages: yoctocolors-cjs: 2.1.2 dev: true + /@inquirer/select@5.2.1(@types/node@24.6.2): + resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/figures': 2.0.7 + '@inquirer/type': 4.0.7(@types/node@24.6.2) + '@types/node': 24.6.2 + dev: true + /@inquirer/type@1.5.5: resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} engines: {node: '>=18'} @@ -11423,6 +11704,18 @@ packages: '@types/node': 24.6.2 dev: true + /@inquirer/type@4.0.7(@types/node@24.6.2): + resolution: {integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 24.6.2 + dev: true + /@internationalized/date@3.10.0: resolution: {integrity: sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw==} dependencies: @@ -11993,7 +12286,7 @@ packages: read-package-json: 6.0.4 resolve-from: 5.0.0 rimraf: 4.4.1 - semver: 7.7.2 + semver: 7.7.4 signal-exit: 3.0.7 slash: 3.0.0 ssri: 9.0.1 @@ -12213,8 +12506,8 @@ packages: https-proxy-agent: 7.0.6(supports-color@10.2.2) node-fetch: 2.7.0 nopt: 8.1.0 - semver: 7.7.2 - tar: 7.5.1 + semver: 7.7.4 + tar: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -12349,6 +12642,112 @@ packages: - supports-color dev: false + /@napi-rs/canvas-android-arm64@0.1.80: + resolution: {integrity: sha512-sk7xhN/MoXeuExlggf91pNziBxLPVUqF2CAVnB57KLG/pz7+U5TKG8eXdc3pm0d7Od0WreB6ZKLj37sX9muGOQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-darwin-arm64@0.1.80: + resolution: {integrity: sha512-O64APRTXRUiAz0P8gErkfEr3lipLJgM6pjATwavZ22ebhjYl/SUbpgM0xcWPQBNMP1n29afAC/Us5PX1vg+JNQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-darwin-x64@0.1.80: + resolution: {integrity: sha512-FqqSU7qFce0Cp3pwnTjVkKjjOtxMqRe6lmINxpIZYaZNnVI0H5FtsaraZJ36SiTHNjZlUB69/HhxNDT1Aaa9vA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-linux-arm-gnueabihf@0.1.80: + resolution: {integrity: sha512-eyWz0ddBDQc7/JbAtY4OtZ5SpK8tR4JsCYEZjCE3dI8pqoWUC8oMwYSBGCYfsx2w47cQgQCgMVRVTFiiO38hHQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-linux-arm64-gnu@0.1.80: + resolution: {integrity: sha512-qwA63t8A86bnxhuA/GwOkK3jvb+XTQaTiVML0vAWoHyoZYTjNs7BzoOONDgTnNtr8/yHrq64XXzUoLqDzU+Uuw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-linux-arm64-musl@0.1.80: + resolution: {integrity: sha512-1XbCOz/ymhj24lFaIXtWnwv/6eFHXDrjP0jYkc6iHQ9q8oXKzUX1Lc6bu+wuGiLhGh2GS/2JlfORC5ZcXimRcg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-linux-riscv64-gnu@0.1.80: + resolution: {integrity: sha512-XTzR125w5ZMs0lJcxRlS1K3P5RaZ9RmUsPtd1uGt+EfDyYMu4c6SEROYsxyatbbu/2+lPe7MPHOO/0a0x7L/gw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-linux-x64-gnu@0.1.80: + resolution: {integrity: sha512-BeXAmhKg1kX3UCrJsYbdQd3hIMDH/K6HnP/pG2LuITaXhXBiNdh//TVVVVCBbJzVQaV5gK/4ZOCMrQW9mvuTqA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-linux-x64-musl@0.1.80: + resolution: {integrity: sha512-x0XvZWdHbkgdgucJsRxprX/4o4sEed7qo9rCQA9ugiS9qE2QvP0RIiEugtZhfLH3cyI+jIRFJHV4Fuz+1BHHMg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas-win32-x64-msvc@0.1.80: + resolution: {integrity: sha512-Z8jPsM6df5V8B1HrCHB05+bDiCxjE9QA//3YrkKIdVDEwn5RKaqOxCJDRJkl48cJbylcrJbW4HxZbTte8juuPg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/canvas@0.1.80: + resolution: {integrity: sha512-DxuT1ClnIPts1kQx8FBmkk4BQDTfI5kIzywAaMjQSXfNnra5UFU9PwurXrl+Je3bJ6BGsp/zmshVVFbCmyI+ww==} + engines: {node: '>= 10'} + optionalDependencies: + '@napi-rs/canvas-android-arm64': 0.1.80 + '@napi-rs/canvas-darwin-arm64': 0.1.80 + '@napi-rs/canvas-darwin-x64': 0.1.80 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.80 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.80 + '@napi-rs/canvas-linux-arm64-musl': 0.1.80 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.80 + '@napi-rs/canvas-linux-x64-gnu': 0.1.80 + '@napi-rs/canvas-linux-x64-musl': 0.1.80 + '@napi-rs/canvas-win32-x64-msvc': 0.1.80 + dev: false + /@napi-rs/nice-android-arm-eabi@1.0.4: resolution: {integrity: sha512-OZFMYUkih4g6HCKTjqJHhMUlgvPiDuSLZPbPBWHLjKmFTv74COzRlq/gwHtmEVaR39mJQ6ZyttDl2HNMUbLVoA==} engines: {node: '>= 10'} @@ -12531,7 +12930,7 @@ packages: resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} dependencies: '@emnapi/core': 1.4.5 - '@emnapi/runtime': 1.4.5 + '@emnapi/runtime': 1.11.1 '@tybys/wasm-util': 0.9.0 dev: true @@ -12737,7 +13136,7 @@ packages: find-up: 7.0.0 minimatch: 9.0.5 read-pkg: 9.0.1 - semver: 7.7.2 + semver: 7.7.4 yaml: 2.8.1 yargs: 17.7.2 dev: true @@ -12770,7 +13169,7 @@ packages: ansis: 4.1.0 clean-stack: 5.3.0 execa: 8.0.1 - fdir: 6.4.6 + fdir: 6.5.0(picomatch@4.0.3) figures: 6.1.0 filter-obj: 6.1.0 hot-shots: 11.1.0 @@ -12795,7 +13194,7 @@ packages: resolve: 2.0.0-next.5 rfdc: 1.4.1 safe-json-stringify: 1.2.0 - semver: 7.7.2 + semver: 7.7.4 string-width: 7.2.0 supports-color: 10.2.2 terminal-link: 4.0.0 @@ -12874,7 +13273,7 @@ packages: image-size: 2.0.2 js-image-generator: 1.0.4 parse-gitignore: 2.0.0 - semver: 7.7.2 + semver: 7.7.4 tmp-promise: 3.0.3 uuid: 11.1.0 write-file-atomic: 5.0.1 @@ -12895,7 +13294,7 @@ packages: image-size: 2.0.2 js-image-generator: 1.0.4 parse-gitignore: 2.0.0 - semver: 7.7.2 + semver: 7.7.4 tmp-promise: 3.0.3 uuid: 11.1.0 write-file-atomic: 5.0.1 @@ -12920,8 +13319,8 @@ packages: p-wait-for: 5.0.2 parse-imports: 2.2.1 path-key: 4.0.0 - semver: 7.7.2 - tar: 7.5.1 + semver: 7.7.4 + tar: 7.5.7 tmp-promise: 3.0.3 urlpattern-polyfill: 8.0.2 uuid: 11.1.0 @@ -13190,7 +13589,7 @@ packages: precinct: 12.2.0(supports-color@10.2.2) require-package-name: 2.0.1 resolve: 2.0.0-next.5 - semver: 7.7.2 + semver: 7.7.4 tmp-promise: 3.0.3 toml: 3.0.0 unixify: 1.0.0 @@ -13323,14 +13722,14 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: '@gar/promisify': 1.1.3 - semver: 7.7.2 + semver: 7.7.4 dev: true /@npmcli/fs@3.1.1: resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - semver: 7.7.2 + semver: 7.7.4 dev: true /@npmcli/git@4.1.0: @@ -13343,7 +13742,7 @@ packages: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.7.2 + semver: 7.7.4 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -13438,7 +13837,7 @@ packages: perfect-debounce: 2.0.0 pkg-types: 2.3.0 scule: 1.3.0 - semver: 7.7.2 + semver: 7.7.4 srvx: 0.8.15 std-env: 3.9.0 tinyexec: 1.0.1 @@ -13476,7 +13875,7 @@ packages: pathe: 2.0.3 pkg-types: 2.3.0 prompts: 2.4.2 - semver: 7.7.2 + semver: 7.7.4 dev: false /@nuxt/devtools@2.6.5(vite@7.2.7)(vue@3.5.22): @@ -13508,7 +13907,7 @@ packages: pathe: 2.0.3 perfect-debounce: 1.0.0 pkg-types: 2.3.0 - semver: 7.7.2 + semver: 7.7.4 simple-git: 3.28.0 sirv: 3.0.2 structured-clone-es: 1.0.0 @@ -13982,7 +14381,7 @@ packages: '@nuxt/kit': 3.19.3(magicast@0.3.5) pathe: 1.1.2 pkg-types: 1.3.1 - semver: 7.7.2 + semver: 7.7.4 transitivePeerDependencies: - magicast dev: false @@ -14012,7 +14411,7 @@ packages: ignore: 5.3.2 minimatch: 9.0.3 nx: 20.4.6(@swc-node/register@1.9.2)(@swc/core@1.5.29) - semver: 7.7.2 + semver: 7.7.4 tmp: 0.2.5 tslib: 2.8.1 yargs-parser: 21.1.1 @@ -14028,7 +14427,7 @@ packages: ignore: 5.3.2 minimatch: 9.0.3 nx: 20.8.2(@swc-node/register@1.9.2)(@swc/core@1.5.29) - semver: 7.7.2 + semver: 7.7.4 tmp: 0.2.5 tslib: 2.8.1 yargs-parser: 21.1.1 @@ -14521,7 +14920,7 @@ packages: minimatch: 9.0.3 tsconfig-paths: 4.2.0 vite: 7.2.7(@types/node@24.2.1)(jiti@2.5.1)(tsx@4.21.0) - vitest: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + vitest: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -15168,6 +15567,145 @@ packages: resolution: {integrity: sha512-WIK/3Zwg8t6XeI3CJEEbK6wrC/uPkR7dk2DNWAhXqfql7NBCPjTb4NdXNSyChqMRY1qk+6E4/l32MaXk9x7+zA==} dev: true + /@openuidev/cli@0.2.7(@types/node@24.6.2): + resolution: {integrity: sha512-vRKnOWluR8c/1hHL2Y6+P+ZjHMY232v184GGhqqKoCB8fVzCTN6I2QblRn800tEgNQIHtnHF3S6oBATmw5CxhA==} + hasBin: true + dependencies: + '@inquirer/core': 11.2.1(@types/node@24.6.2) + '@inquirer/prompts': 8.5.2(@types/node@24.6.2) + commander: 14.0.3 + cross-spawn: 7.0.6 + esbuild: 0.25.10 + get-port: 7.2.0 + open: 10.2.0 + openid-client: 6.8.5 + posthog-node: 5.49.1 + transitivePeerDependencies: + - '@types/node' + - rxjs + dev: true + + /@openuidev/devtools@0.0.4(@openuidev/observability@0.0.2)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-DVf5Bu6gpKEfAnETyl/ZOQMyZCi1vapGohNSxaIyZ03jVZ+e5F9fkQJp+5T1ryg0v3vYi3AC0B4NRwEuCbZmmQ==} + peerDependencies: + '@openuidev/observability': ^0.0.2 + react: ^18.3.1 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + dependencies: + '@openuidev/observability': 0.0.2 + lucide-react: 0.575.0(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + + /@openuidev/lang-core@0.2.12(zod@4.3.5): + resolution: {integrity: sha512-G2cYAUVkh2t7zBjqUYAfKdNLNpA5FwFfqSH0TRP6/SsTCzyxbP92Gih57zsWkYRC8zP4RV/bivIvP1ZAzQhhew==} + requiresBuild: true + peerDependencies: + '@modelcontextprotocol/sdk': '>=1.0.0' + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + dependencies: + ci-info: 4.4.0 + zod: 4.3.5 + dev: false + + /@openuidev/observability@0.0.2: + resolution: {integrity: sha512-uNtO4VGGwcL8Lg1L+9a8JCpee0dOm0djIjItxtGpUPkZNUwzpMQX6mQ4YCtA9Hho4VuqZgHBo1ON8FjsLbNMHg==} + dev: false + + /@openuidev/react-headless@0.9.8(ai@6.0.3)(react@19.2.3)(zustand@4.5.7): + resolution: {integrity: sha512-XPJkQEERLzDv3fhll3fIhwiklMzWhtiTZXtDFRGtEXUkLTqL9saZf3K7e6TjRtxsnvDTdT9ynUhF3cdsL/dCCA==} + peerDependencies: + ai: ^6.0.0 || ^7.0.0 + react: ^18.3.1 || ^19.0.0 + zustand: ^4.5.5 + peerDependenciesMeta: + ai: + optional: true + dependencies: + '@ag-ui/core': 0.0.53 + '@openuidev/observability': 0.0.2 + ai: 6.0.3(zod@4.3.5) + react: 19.2.3 + zustand: 4.5.7(@types/react@19.2.7)(react@19.2.3) + dev: false + + /@openuidev/react-lang@0.2.11(react-dom@19.2.3)(react@19.2.3)(zod@4.3.5): + resolution: {integrity: sha512-RXyRmFLxRBQ/pNnCq4CYFLl/1SnUvv3O5cnyTaaG6RqtXQ/CLmRiooqCtNY8xqi/cDVt3HJTgrfQOCN2ZhAQbg==} + peerDependencies: + '@modelcontextprotocol/sdk': '>=1.0.0' + react: '*' + react-dom: '*' + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + react-dom: + optional: true + dependencies: + '@openuidev/devtools': 0.0.4(@openuidev/observability@0.0.2)(react-dom@19.2.3)(react@19.2.3) + '@openuidev/lang-core': 0.2.12(zod@4.3.5) + '@openuidev/observability': 0.0.2 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + zod: 4.3.5 + dev: false + + /@openuidev/react-ui@0.13.6(@openuidev/react-headless@0.9.8)(@openuidev/react-lang@0.2.11)(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)(zod@4.3.5)(zustand@4.5.7): + resolution: {integrity: sha512-GBdc1HKHLxb65nCNugWotcCGNZl5/joydjORseFrWbml4YStPHKhLdXDC72nwyOMsnhuLUqzLhUOlMnBpUkGNg==} + peerDependencies: + '@openuidev/react-headless': ^0.9.7 + '@openuidev/react-lang': ^0.2.11 + react: ^18.3.1 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + zod: ^3.25.0 || ^4.0.0 + zustand: ^4.5.5 + dependencies: + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3)(react@19.2.3) + '@openuidev/react-headless': 0.9.8(ai@6.0.3)(react@19.2.3)(zustand@4.5.7) + '@openuidev/react-lang': 0.2.11(react-dom@19.2.3)(react@19.2.3)(zod@4.3.5) + '@radix-ui/react-accordion': 1.2.20(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-aspect-ratio': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-checkbox': 1.3.11(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-label': 2.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-radio-group': 1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-separator': 1.1.8(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-slider': 1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-slot': 1.2.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-switch': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-toggle-group': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + clsx: 2.1.1 + date-fns: 4.4.0 + lodash-es: 4.17.21 + lucide-react: 0.562.0(react@19.2.3) + react: 19.2.3 + react-day-picker: 9.14.0(react@19.2.3) + react-dom: 19.2.3(react@19.2.3) + react-markdown: 10.1.0(@types/react@19.2.7)(react@19.2.3) + react-syntax-highlighter: 16.1.1(react@19.2.3) + recharts: 2.15.4(react-dom@19.2.3)(react@19.2.3) + rehype-katex: 7.0.1 + remark-breaks: 4.0.0 + remark-emoji: 5.0.2 + remark-gfm: 4.0.1 + remark-math: 6.0.0 + tiny-invariant: 1.3.3 + zod: 4.3.5 + zustand: 4.5.7(@types/react@19.2.7)(react@19.2.3) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + - supports-color + dev: false + /@oxc-minify/binding-android-arm64@0.94.0: resolution: {integrity: sha512-7VEBFFFAi4cYqlW/ziVs5XmNM/0IqAp7duBuTM/zus/EOc3Q2zhS9ApJo0zIwbRUZMlIm1RHe8Hths//xE7K1A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -15446,8 +15984,8 @@ packages: dev: false optional: true - /@oxc-project/types@0.142.0: - resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} + /@oxc-project/types@0.144.0: + resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==} dev: true /@oxc-project/types@0.94.0: @@ -15843,6 +16381,16 @@ packages: /@poppinss/exception@1.2.2: resolution: {integrity: sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==} + /@posthog/core@1.48.1: + resolution: {integrity: sha512-mxw31XdYgt/SnlwqLPAcltK67q+QmsiYjVLGQ4GbBc8OJ7O4yRFSDwAXt8QsokHokeyEZtTRWM6jDHL7LYMx1A==} + dependencies: + '@posthog/types': 1.404.1 + dev: true + + /@posthog/types@1.404.1: + resolution: {integrity: sha512-i2Gei6ARfOSBeTN4s2yUP1p97s2UNI+1NWmtLjhnR/V6t3RFOfI1sBWKcJNWHjtoOCCWoAFU+PNPY6SgT2VtEQ==} + dev: true + /@protobuf-ts/protoc@2.11.1: resolution: {integrity: sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==} hasBin: true @@ -15921,9 +16469,45 @@ packages: /@radix-ui/number@1.1.1: resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} + /@radix-ui/number@1.1.3: + resolution: {integrity: sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==} + dev: false + /@radix-ui/primitive@1.1.3: resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + /@radix-ui/primitive@1.1.7: + resolution: {integrity: sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==} + dev: false + + /@radix-ui/react-accordion@1.2.20(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collapsible': 1.1.20(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: @@ -15963,6 +16547,26 @@ packages: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + /@radix-ui/react-aspect-ratio@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-fy+dyVR+90nelK8rqIznFlxzx7uPcGbhxH8Nfr2bHb4UfSe+e3hklOC0luK0hDwVwnRX7xTRySpsrQVeW+/oNQ==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-avatar@1.1.11(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==} peerDependencies: @@ -16011,6 +16615,32 @@ packages: react-dom: 19.2.3(react@19.2.3) dev: false + /@radix-ui/react-checkbox@1.3.11(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-Gnptr9pDDQxD3hgq2dtPbtrp/c2qH1mBwIzw3X/ivrMb2e1t0jMTi606fVEqFPaQR1ggXIVQWKj3P2WW9v7zGQ==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} peerDependencies: @@ -16064,6 +16694,56 @@ packages: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + /@radix-ui/react-collapsible@1.1.20(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + + /@radix-ui/react-collection@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-slot': 1.3.3(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: @@ -16134,6 +16814,19 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-compose-refs@1.1.5(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-context@1.1.2(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: @@ -16185,6 +16878,19 @@ packages: react: 19.2.3 dev: false + /@radix-ui/react-context@1.2.2(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-dialog@1.1.15(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} peerDependencies: @@ -16276,6 +16982,19 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-direction@1.1.4(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} peerDependencies: @@ -16526,6 +17245,40 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-id@1.1.4(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + + /@radix-ui/react-label@2.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-o/rdYEwZTTo5tjknnPeyQFU45kUC4i/XyeDPP+HGyi6XqpOP6Zf5Ya5vh/Yfe9Id5JiuWnnAx2XqIeD3UYZt0g==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-menu@2.1.16(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} peerDependencies: @@ -16732,6 +17485,26 @@ packages: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + /@radix-ui/react-presence@1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} peerDependencies: @@ -16773,6 +17546,26 @@ packages: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + /@radix-ui/react-primitive@2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-slot': 1.3.3(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: @@ -16894,6 +17687,34 @@ packages: react-dom: 19.2.3(react@19.2.3) dev: false + /@radix-ui/react-radio-group@1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-cgYFEkntCxppHZgtSZ+7vh0wbZQ+IC7PPMw8DSnRG27B6kDd32/Zw0OJt7dGDigCoprMuWHjg2PvUn3PYvPFoQ==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} peerDependencies: @@ -16949,6 +17770,36 @@ packages: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + /@radix-ui/react-roving-focus@1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} peerDependencies: @@ -17104,6 +17955,36 @@ packages: react-dom: 19.2.3(react@19.2.3) dev: false + /@radix-ui/react-slider@1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /@radix-ui/react-slot@1.2.3(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: @@ -17158,7 +18039,46 @@ packages: '@types/react': 19.2.7 react: 19.2.3 - /@radix-ui/react-tabs@1.1.13(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + /@radix-ui/react-slot@1.3.3(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + + /@radix-ui/react-switch@1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + + /@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} peerDependencies: '@types/react': '*' @@ -17180,9 +18100,57 @@ packages: '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - dev: true + + /@radix-ui/react-toggle-group@1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-OtnwuSVjd1Ofi+AdnvhsjQdyuhCDwYs1w9RyB5BN/OavXOVQo42SYqQjwUnbPnaiPFBpQ9aX70dWeee+v2oBLA==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-context': 1.2.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-toggle': 1.1.18(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + + /@radix-ui/react-toggle@1.1.18(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-7lonPlKfSacd20GlOBx2ltuVKz9oqWYZz+oMQyOltw6t1y2nyftj2ZmwwUHYn49kqfDWcp8dNZm5NgV+5Z+mug==} + 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 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false /@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} @@ -17271,6 +18239,19 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-use-callback-ref@1.1.4(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} peerDependencies: @@ -17300,6 +18281,22 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-use-controllable-state@1.2.6(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: @@ -17327,6 +18324,20 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-use-effect-event@0.0.5(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} peerDependencies: @@ -17382,6 +18393,19 @@ packages: use-sync-external-store: 1.5.0(react@19.2.3) dev: false + /@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: @@ -17407,6 +18431,19 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-use-previous@1.1.1(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} peerDependencies: @@ -17432,6 +18469,19 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-use-previous@1.1.4(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-use-rect@1.1.1(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} peerDependencies: @@ -17486,6 +18536,20 @@ packages: '@types/react': 19.2.7 react: 19.2.3 + /@radix-ui/react-use-size@1.1.4(@types/react@19.2.7)(react@19.2.3): + resolution: {integrity: sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.7)(react@19.2.3) + '@types/react': 19.2.7 + react: 19.2.3 + dev: false + /@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.1.7)(@types/react@19.1.10)(react-dom@19.2.3)(react@19.2.3): resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} peerDependencies: @@ -17659,8 +18723,8 @@ packages: /@repeaterjs/repeater@3.0.6: resolution: {integrity: sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==} - /@rolldown/binding-android-arm64@1.2.2: - resolution: {integrity: sha512-l7x215OGvo1s52JWmR8U/DAVzEDWBCIbTm28aeJV/WDTSHgcKXaZTuBT0hJMs5NggilfJTW3clZVvd24yfKJxA==} + /@rolldown/binding-android-arm64@1.2.4: + resolution: {integrity: sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] @@ -17668,8 +18732,8 @@ packages: dev: true optional: true - /@rolldown/binding-darwin-arm64@1.2.2: - resolution: {integrity: sha512-9u9Xv6c1AJZT0FfwH5vrMG5Jjcwhc1MlyrPu0XfTqkzsmqfks2M6W/o5XwAJgVVN/jHpqqngC1WevHKKTIUtIA==} + /@rolldown/binding-darwin-arm64@1.2.4: + resolution: {integrity: sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] @@ -17677,8 +18741,8 @@ packages: dev: true optional: true - /@rolldown/binding-darwin-x64@1.2.2: - resolution: {integrity: sha512-9W1mbGZAfW3oqd85bhBkmpyHCCzL1TeG/zFFP3vg7b0rlly8cxOcre5nXwz+LHazCwac2MNWgPdPCHndABjpWQ==} + /@rolldown/binding-darwin-x64@1.2.4: + resolution: {integrity: sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] @@ -17686,8 +18750,8 @@ packages: dev: true optional: true - /@rolldown/binding-freebsd-x64@1.2.2: - resolution: {integrity: sha512-0p1lhiCSCyaerFwtrdZQUx7NqGk6LQnaRKWX7tFQqwQgvX0rjM15cIkm3pax1UpEakK14C4mOxx/jSqCBdBRqQ==} + /@rolldown/binding-freebsd-x64@1.2.4: + resolution: {integrity: sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] @@ -17695,8 +18759,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-arm-gnueabihf@1.2.2: - resolution: {integrity: sha512-e+cOJXrJ2L3zx6YzqPg+f6Wbk3V1cKB8bOhbaYdVYN3DdquzNdRAmrbETz1qnt5yp/c7JNlNjmITiA2cVneQ7w==} + /@rolldown/binding-linux-arm-gnueabihf@1.2.4: + resolution: {integrity: sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -17704,8 +18768,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-arm64-gnu@1.2.2: - resolution: {integrity: sha512-JsSMsj6sNat/MuhG5fnBD7QgbtpHKVe30x5/bAVirDHdhoQRXJkF6xc0Jqk8O4fiCUQAzMOoH9wZi3m60c8wtg==} + /@rolldown/binding-linux-arm64-gnu@1.2.4: + resolution: {integrity: sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -17713,8 +18777,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-arm64-musl@1.2.2: - resolution: {integrity: sha512-B5G/zJdHaoJn9vD50eGHWkiWfmq8Uhi3IiLPJTzmZTrAalk1bztUikSXo0qga18ibE0IXboyeMUnhPjhAJ45wQ==} + /@rolldown/binding-linux-arm64-musl@1.2.4: + resolution: {integrity: sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -17722,8 +18786,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-ppc64-gnu@1.2.2: - resolution: {integrity: sha512-6mC/awzKka8W6EoekjegpfGkjz8jXWDX63pqu/HYVpyKtZfu65Jsh4QAH3Kej3CAv/c1oGX7psTmFEbr0mDxLA==} + /@rolldown/binding-linux-ppc64-gnu@1.2.4: + resolution: {integrity: sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] @@ -17731,8 +18795,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-s390x-gnu@1.2.2: - resolution: {integrity: sha512-412MX9fJLdA1IK28EZnc8jYv2HRTleOZgfLQumJ5zy7OeJLZlg/CETwFaXjNmGVxG51cFHpKLqb5LKvBC+HsHA==} + /@rolldown/binding-linux-s390x-gnu@1.2.4: + resolution: {integrity: sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] @@ -17740,8 +18804,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-x64-gnu@1.2.2: - resolution: {integrity: sha512-Q/+HI/ToJafZ1iCqGgVQXUEkIjufHCTF0gBQ2a5o3cg7GJ2h0qyq3nvvSmU+bGda2/7ygXpTY4TM6gO9OhQ0ZA==} + /@rolldown/binding-linux-x64-gnu@1.2.4: + resolution: {integrity: sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -17749,8 +18813,8 @@ packages: dev: true optional: true - /@rolldown/binding-linux-x64-musl@1.2.2: - resolution: {integrity: sha512-ZKp/w41n6wCvxzxQHtQSbuphfX3Y4cCvbjkKHusrLx4lh+JWLTU7StSltO/DKARISzbj368d+qUaCjI8K2wzXw==} + /@rolldown/binding-linux-x64-musl@1.2.4: + resolution: {integrity: sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -17758,8 +18822,8 @@ packages: dev: true optional: true - /@rolldown/binding-openharmony-arm64@1.2.2: - resolution: {integrity: sha512-pxE6xD4KS3eAROkKK5yrhB9/3+vhlhVGMvlQLbdpzrBGDbKrnzx3RLwPaHvasLo6jgaiBLn7e04Df9C4tYhjmA==} + /@rolldown/binding-openharmony-arm64@1.2.4: + resolution: {integrity: sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] @@ -17767,8 +18831,8 @@ packages: dev: true optional: true - /@rolldown/binding-win32-arm64-msvc@1.2.2: - resolution: {integrity: sha512-4MqEue5re+xIZzAWsB8sj0P1kqZySWqIuN4t6QaIO/YA6SFwySOLruvWQFzfmqk8LBK2P30KCSJwf6mJCZZ5/A==} + /@rolldown/binding-win32-arm64-msvc@1.2.4: + resolution: {integrity: sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] @@ -17776,8 +18840,8 @@ packages: dev: true optional: true - /@rolldown/binding-win32-x64-msvc@1.2.2: - resolution: {integrity: sha512-NweNxxD0Nf9t8v7kodun45Ijp3EIwYY+uydPP6qBEYvfBqhIjN6dZMzlQja3tqX/aLs3F3Uz+AxDpKgRhpOZQg==} + /@rolldown/binding-win32-x64-msvc@1.2.4: + resolution: {integrity: sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -18359,7 +19423,6 @@ packages: /@sindresorhus/is@4.6.0: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} - dev: true /@sindresorhus/is@5.6.0: resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} @@ -19345,6 +20408,11 @@ packages: defer-to-connect: 2.0.1 dev: true + /@tabby_ai/hijri-converter@1.0.5: + resolution: {integrity: sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ==} + engines: {node: '>=16.0.0'} + dev: false + /@tailwindcss/node@4.1.11: resolution: {integrity: sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==} dependencies: @@ -19612,7 +20680,7 @@ packages: requiresBuild: true dependencies: detect-libc: 2.1.1 - tar: 7.5.1 + tar: 7.5.7 optionalDependencies: '@tailwindcss/oxide-android-arm64': 4.1.14 '@tailwindcss/oxide-darwin-arm64': 4.1.14 @@ -20845,6 +21913,10 @@ packages: pino: 9.9.0 dev: true + /@types/prismjs@1.26.6: + resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==} + dev: false + /@types/prop-types@15.7.15: resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} dev: false @@ -21162,7 +22234,7 @@ packages: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.2 + semver: 7.7.4 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -21567,6 +22639,23 @@ packages: vite: 7.2.7(@types/node@24.2.1)(jiti@2.5.1)(tsx@4.21.0) dev: true + /@vitest/mocker@3.2.4(vite@7.2.7): + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.19 + vite: 7.2.7(@types/node@24.6.2) + dev: true + /@vitest/pretty-format@3.2.4: resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} dependencies: @@ -21607,7 +22696,7 @@ packages: pathe: 1.1.2 picocolors: 1.1.1 sirv: 2.0.4 - vitest: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6) + vitest: 3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0) dev: true /@vitest/utils@1.6.1: @@ -21745,7 +22834,7 @@ packages: '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) '@radix-ui/react-slot': 1.2.4(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-tabs': 1.1.13(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3) '@tanstack/react-router': 1.131.44(react-dom@19.2.3)(react@19.2.3) '@tanstack/react-router-ssr-query': 1.131.44(@tanstack/query-core@5.89.0)(@tanstack/react-query@5.89.0)(@tanstack/react-router@1.131.44)(@tanstack/router-core@1.131.44)(react-dom@19.2.3)(react@19.2.3) '@tanstack/react-start': 1.131.44(@tanstack/react-router@1.131.44)(@vitejs/plugin-react@5.1.2)(react-dom@19.2.3)(react@19.2.3)(vite@7.2.7) @@ -23501,7 +24590,7 @@ packages: engines: {node: '>=12'} dependencies: bin-version: 6.0.0 - semver: 7.7.2 + semver: 7.7.4 semver-truncate: 3.0.0 dev: true @@ -23744,7 +24833,7 @@ packages: /builtins@5.1.0: resolution: {integrity: sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==} dependencies: - semver: 7.7.2 + semver: 7.7.4 dev: true /bundle-name@4.1.0: @@ -24053,7 +25142,6 @@ packages: /char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} - dev: true /character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -24082,6 +25170,10 @@ packages: /chardet@2.1.0: resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} + /chardet@2.2.0: + resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} + dev: true + /chat@4.14.0: resolution: {integrity: sha512-gVod4FBptr4ewPEdY2zo1GnegI8/O0aC5F+IvFMIjimqmQjW0txhQbgI/DgmD48pwXJhxUGpvNrqzMrChx8GWw==} dependencies: @@ -24267,6 +25359,11 @@ packages: resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} engines: {node: '>=8'} + /ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + dev: false + /citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} dependencies: @@ -24708,7 +25805,6 @@ packages: /commander@14.0.3: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} - dev: false /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -24972,7 +26068,7 @@ packages: handlebars: 4.7.8 json-stringify-safe: 5.0.1 meow: 8.1.2 - semver: 7.7.2 + semver: 7.7.4 split: 1.0.1 dev: true @@ -25755,6 +26851,14 @@ packages: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} dev: true + /date-fns-jalali@4.1.0-0: + resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==} + dev: false + + /date-fns@4.4.0: + resolution: {integrity: sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==} + dev: false + /dateformat@3.0.3: resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} dev: true @@ -25851,6 +26955,10 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + /decimal.js-light@2.5.1: + resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + dev: false + /decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} dev: true @@ -26241,6 +27349,13 @@ packages: - supports-color dev: false + /dom-helpers@5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.28.2 + csstype: 3.2.3 + dev: false + /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: @@ -26553,7 +27668,10 @@ packages: /emojilib@2.4.0: resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} - dev: true + + /emoticon@4.1.0: + resolution: {integrity: sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==} + dev: false /empathic@2.0.0: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} @@ -26949,7 +28067,7 @@ packages: eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 minimatch: 10.0.3 - semver: 7.7.2 + semver: 7.7.4 stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 transitivePeerDependencies: @@ -26971,7 +28089,7 @@ packages: espree: 10.4.0 esquery: 1.6.0 parse-imports-exports: 0.2.4 - semver: 7.7.2 + semver: 7.7.4 spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color @@ -27016,7 +28134,7 @@ packages: pluralize: 8.0.0 regexp-tree: 0.1.27 regjsparser: 0.12.0 - semver: 7.7.2 + semver: 7.7.4 strip-indent: 4.1.0 dev: false @@ -27041,7 +28159,7 @@ packages: natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 - semver: 7.7.2 + semver: 7.7.4 vue-eslint-parser: 10.2.0(eslint@9.33.0) xml-name-validator: 4.0.0 dev: false @@ -27575,6 +28693,11 @@ packages: resolution: {integrity: sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg==} dev: true + /fast-equals@5.4.1: + resolution: {integrity: sha512-DjlFSM5Pk9cGcL0q5QXl66eGzx0N6szNgaswwc5ZphlBohjTVJSnGgI+rJVOgOi65qUoQnDZN4nDqi33udtydQ==} + engines: {node: '>=6.0.0'} + dev: false + /fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} @@ -27626,6 +28749,16 @@ packages: /fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + /fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + dev: true + + /fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + dependencies: + fast-string-truncated-width: 3.0.3 + dev: true + /fast-uri@2.4.0: resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} dev: true @@ -27633,6 +28766,12 @@ packages: /fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + /fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + dependencies: + fast-string-width: 3.0.2 + dev: true + /fast-xml-parser@5.3.4: resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==} hasBin: true @@ -27666,7 +28805,7 @@ packages: proxy-addr: 2.0.7 rfdc: 1.4.1 secure-json-parse: 2.7.0 - semver: 7.7.2 + semver: 7.7.4 toad-cache: 3.7.0 dev: true @@ -27692,15 +28831,6 @@ packages: pend: 1.2.0 dev: true - /fdir@6.4.6: - resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - dev: true - /fdir@6.5.0(picomatch@4.0.3): resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -28405,6 +29535,11 @@ packages: resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} engines: {node: '>=16'} + /get-port@7.2.0: + resolution: {integrity: sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg==} + engines: {node: '>=16'} + dev: true + /get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} @@ -28473,7 +29608,7 @@ packages: dependencies: '@xhmikosr/downloader': 13.0.1 node-fetch: 3.3.2 - semver: 7.7.2 + semver: 7.7.4 dev: true /giget@2.0.0: @@ -28533,7 +29668,7 @@ packages: hasBin: true dependencies: meow: 8.1.2 - semver: 7.7.2 + semver: 7.7.4 dev: true /git-up@7.0.0: @@ -28681,7 +29816,7 @@ packages: es6-error: 4.1.1 matcher: 3.0.0 roarr: 2.15.4 - semver: 7.7.2 + semver: 7.7.4 serialize-error: 7.0.1 dev: false @@ -29716,7 +30851,7 @@ packages: promzard: 1.0.2 read: 2.1.0 read-package-json: 6.0.4 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-license: 3.0.4 validate-npm-package-name: 5.0.0 dev: true @@ -30302,7 +31437,7 @@ packages: '@babel/parser': 7.28.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.2 + semver: 7.7.4 transitivePeerDependencies: - supports-color dev: true @@ -30750,7 +31885,7 @@ packages: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.7.2 + semver: 7.7.4 transitivePeerDependencies: - supports-color dev: true @@ -30860,6 +31995,10 @@ packages: /jose@6.1.3: resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} + /jose@6.2.9: + resolution: {integrity: sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==} + dev: true + /joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -31113,7 +32252,7 @@ packages: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.2 + semver: 7.7.4 dev: false /junk@4.0.1: @@ -31375,7 +32514,7 @@ packages: openai: 4.104.0(ws@8.18.3)(zod@3.25.76) p-queue: 6.6.2 p-retry: 4.6.2 - semver: 7.7.2 + semver: 7.7.4 uuid: 10.0.0 dev: false @@ -31402,7 +32541,7 @@ packages: openai: 5.23.2(zod@3.25.76) p-queue: 6.6.2 p-retry: 4.6.2 - semver: 7.7.2 + semver: 7.7.4 uuid: 10.0.0 /latest-version@5.1.0: @@ -31561,7 +32700,7 @@ packages: npm-package-arg: 10.1.0 npm-registry-fetch: 14.0.5 proc-log: 3.0.0 - semver: 7.7.2 + semver: 7.7.4 sigstore: 1.9.0 ssri: 10.0.6 transitivePeerDependencies: @@ -32126,6 +33265,22 @@ packages: dependencies: react: 19.2.3 + /lucide-react@0.562.0(react@19.2.3): + resolution: {integrity: sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + react: 19.2.3 + dev: false + + /lucide-react@0.575.0(react@19.2.3): + resolution: {integrity: sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + react: 19.2.3 + dev: false + /lucide@0.525.0: resolution: {integrity: sha512-sfehWlaE/7NVkcEQ4T9JD3eID8RNMIGJBBUq9wF3UFiJIrcMKRbU3g1KGfDk4svcW7yw8BtDLXaXo02scDtUYQ==} dev: false @@ -32201,7 +33356,7 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} dependencies: - semver: 7.7.2 + semver: 7.7.4 dev: true /make-error@1.3.6: @@ -32518,6 +33673,13 @@ packages: transitivePeerDependencies: - supports-color + /mdast-util-newline-to-break@2.0.0: + resolution: {integrity: sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==} + dependencies: + '@types/mdast': 4.0.4 + mdast-util-find-and-replace: 3.0.2 + dev: false + /mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} dependencies: @@ -33629,6 +34791,11 @@ packages: engines: {node: ^18.17.0 || >=20.5.0} dev: true + /mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + dev: true + /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} dependencies: @@ -33942,7 +35109,7 @@ packages: rollup: 4.50.2 rollup-plugin-visualizer: 6.0.3(rollup@4.50.2) scule: 1.3.0 - semver: 7.7.2 + semver: 7.7.4 serve-placeholder: 2.0.2 serve-static: 2.2.0 source-map: 0.7.6 @@ -34024,7 +35191,6 @@ packages: char-regex: 1.0.2 emojilib: 2.4.0 skin-tone: 2.0.0 - dev: true /node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} @@ -34086,7 +35252,7 @@ packages: nopt: 6.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.7.2 + semver: 7.7.4 tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: @@ -34163,7 +35329,7 @@ packages: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-license: 3.0.4 dev: true @@ -34173,7 +35339,7 @@ packages: dependencies: hosted-git-info: 6.1.3 is-core-module: 2.16.1 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-license: 3.0.4 dev: true @@ -34182,7 +35348,7 @@ packages: engines: {node: ^16.14.0 || >=18.0.0} dependencies: hosted-git-info: 7.0.2 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-license: 3.0.4 dev: true @@ -34191,7 +35357,7 @@ packages: engines: {node: ^18.17.0 || >=20.5.0} dependencies: hosted-git-info: 8.1.0 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-license: 3.0.4 dev: true @@ -34249,7 +35415,7 @@ packages: resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - semver: 7.7.2 + semver: 7.7.4 dev: true /npm-normalize-package-bin@1.0.1: @@ -34267,7 +35433,7 @@ packages: dependencies: hosted-git-info: 6.1.3 proc-log: 3.0.0 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-name: 5.0.1 dev: true @@ -34277,7 +35443,7 @@ packages: dependencies: hosted-git-info: 7.0.2 proc-log: 3.0.0 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-name: 5.0.1 dev: true @@ -34287,7 +35453,7 @@ packages: dependencies: hosted-git-info: 8.1.0 proc-log: 5.0.0 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-name: 6.0.2 dev: true @@ -34296,7 +35462,7 @@ packages: engines: {node: '>=10'} dependencies: hosted-git-info: 3.0.8 - semver: 7.7.2 + semver: 7.7.4 validate-npm-package-name: 3.0.0 dev: true @@ -34325,7 +35491,7 @@ packages: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 - semver: 7.7.2 + semver: 7.7.4 dev: true /npm-registry-fetch@14.0.5: @@ -34632,7 +35798,7 @@ packages: open: 8.4.2 ora: 5.3.0 resolve.exports: 2.0.3 - semver: 7.7.2 + semver: 7.7.4 string-width: 4.2.3 tar-stream: 2.2.0 tmp: 0.2.5 @@ -34743,6 +35909,10 @@ packages: tinyexec: 1.0.1 dev: false + /oauth4webapi@3.8.7: + resolution: {integrity: sha512-4RxcKxXjuItDFZ20RRPf4YTw3kpeXJyCgJFxVzJ068A7PNJ18st2Dg90tlC1LkSDS0GecroagCLHYEIVUhCAkw==} + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -35010,6 +36180,13 @@ packages: hasBin: true dev: true + /openid-client@6.8.5: + resolution: {integrity: sha512-jNGC/5wnTYwCcEUe2ss0IRUmVRQcgxM0A1nLb3eX/9llqNbMWOQd2xd+qDAgfVCpA5Qh96Y1cdnkfbva6+bSdA==} + dependencies: + jose: 6.2.9 + oauth4webapi: 3.8.7 + dev: true + /openurl@1.1.1: resolution: {integrity: sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA==} dev: false @@ -35399,7 +36576,7 @@ packages: ky: 1.10.0 registry-auth-token: 5.1.0 registry-url: 6.0.1 - semver: 7.7.2 + semver: 7.7.4 dev: true /package-json@6.5.0: @@ -35716,6 +36893,22 @@ packages: engines: {node: '>= 14.16'} dev: true + /pdf-parse@2.4.5: + resolution: {integrity: sha512-mHU89HGh7v+4u2ubfnevJ03lmPgQ5WU4CxAVmTSh/sxVTEDYd1er/dKS/A6vg77NX47KTEoihq8jZBLr8Cxuwg==} + engines: {node: '>=20.16.0 <21 || >=22.3.0'} + hasBin: true + dependencies: + '@napi-rs/canvas': 0.1.80 + pdfjs-dist: 5.4.296 + dev: false + + /pdfjs-dist@5.4.296: + resolution: {integrity: sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q==} + engines: {node: '>=20.16.0 || >=22.3.0'} + optionalDependencies: + '@napi-rs/canvas': 0.1.80 + dev: false + /peek-readable@5.4.2: resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==} engines: {node: '>=14.16'} @@ -36381,6 +37574,18 @@ packages: - debug dev: false + /posthog-node@5.49.1: + resolution: {integrity: sha512-kmjvzc7K8y+wQX7r3oIkLfKc2BzDJPXMJor5D8gAxpGE7qLNlk4HO2y1brc5587GxtdsZzqtGOxfBJXUBE2MiQ==} + engines: {node: ^20.20.0 || >=22.22.0} + peerDependencies: + rxjs: ^7.0.0 + peerDependenciesMeta: + rxjs: + optional: true + dependencies: + '@posthog/core': 1.48.1 + dev: true + /powershell-utils@0.1.0: resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} engines: {node: '>=20'} @@ -36810,6 +38015,19 @@ packages: minimist: 1.2.8 strip-json-comments: 2.0.1 + /react-day-picker@9.14.0(react@19.2.3): + resolution: {integrity: sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==} + engines: {node: '>=18'} + peerDependencies: + react: '>=16.8.0' + dependencies: + '@date-fns/tz': 1.5.0 + '@tabby_ai/hijri-converter': 1.0.5 + date-fns: 4.4.0 + date-fns-jalali: 4.1.0-0 + react: 19.2.3 + dev: false + /react-dom@19.2.3(react@19.2.3): resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: @@ -36986,6 +38204,19 @@ packages: set-cookie-parser: 2.7.1 dev: false + /react-smooth@4.0.4(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + fast-equals: 5.4.1 + prop-types: 15.8.1 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react-transition-group: 4.4.5(react-dom@19.2.3)(react@19.2.3) + dev: false + /react-style-singleton@2.2.3(@types/react@19.1.10)(react@19.2.3): resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} @@ -37030,6 +38261,21 @@ packages: react: 19.2.3 refractor: 3.6.0 + /react-syntax-highlighter@16.1.1(react@19.2.3): + resolution: {integrity: sha512-PjVawBGy80C6YbC5DDZJeUjBmC7skaoEUdvfFQediQHgCL7aKyVHe57SaJGfQsloGDac+gCpTfRdtxzWWKmCXA==} + engines: {node: '>= 16.20.2'} + peerDependencies: + react: '>= 0.14.0' + dependencies: + '@babel/runtime': 7.29.7 + highlight.js: 10.7.3 + highlightjs-vue: 1.0.0 + lowlight: 1.20.0 + prismjs: 1.30.0 + react: 19.2.3 + refractor: 5.0.0 + dev: false + /react-textarea-autosize@8.5.9(@types/react@19.2.7)(react@19.2.3): resolution: {integrity: sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==} engines: {node: '>=10'} @@ -37044,6 +38290,20 @@ packages: - '@types/react' dev: false + /react-transition-group@4.4.5(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.28.2 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + dev: false + /react@19.2.3: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} @@ -37231,6 +38491,32 @@ packages: tslib: 2.8.1 dev: true + /recharts-scale@0.4.5: + resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} + dependencies: + decimal.js-light: 2.5.1 + dev: false + + /recharts@2.15.4(react-dom@19.2.3)(react@19.2.3): + resolution: {integrity: sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==} + engines: {node: '>=14'} + deprecated: 1.x and 2.x branches are no longer active. Bump to Recharts v3 to receive latest features and bugfixes. See https://github.com/recharts/recharts/wiki/3.0-migration-guide + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + clsx: 2.1.1 + eventemitter3: 4.0.7 + lodash: 4.17.21 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react-is: 18.3.1 + react-smooth: 4.0.4(react-dom@19.2.3)(react@19.2.3) + recharts-scale: 0.4.5 + tiny-invariant: 1.3.3 + victory-vendor: 36.9.2 + dev: false + /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -37277,6 +38563,15 @@ packages: parse-entities: 2.0.0 prismjs: 1.27.0 + /refractor@5.0.0: + resolution: {integrity: sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==} + dependencies: + '@types/hast': 3.0.4 + '@types/prismjs': 1.26.6 + hastscript: 9.0.1 + parse-entities: 4.0.2 + dev: false + /regenerate-unicode-properties@10.2.0: resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} @@ -37422,6 +38717,25 @@ packages: - typescript dev: false + /remark-breaks@4.0.0: + resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==} + dependencies: + '@types/mdast': 4.0.4 + mdast-util-newline-to-break: 2.0.0 + unified: 11.0.5 + dev: false + + /remark-emoji@5.0.2: + resolution: {integrity: sha512-IyIqGELcyK5AVdLFafoiNww+Eaw/F+rGrNSXoKucjo95uL267zrddgxGM83GN1wFIb68pyDuAsY3m5t2Cav1pQ==} + engines: {node: '>=18'} + dependencies: + '@types/mdast': 4.0.4 + emoticon: 4.1.0 + mdast-util-find-and-replace: 3.0.2 + node-emoji: 2.2.0 + unified: 11.0.5 + dev: false + /remark-gfm@4.0.1: resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} dependencies: @@ -37702,7 +39016,7 @@ packages: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} dev: false - /rolldown-plugin-dts@0.16.11(rolldown@1.2.2)(typescript@5.9.2): + /rolldown-plugin-dts@0.16.11(rolldown@1.2.4)(typescript@5.9.2): resolution: {integrity: sha512-9IQDaPvPqTx3RjG2eQCK5GYZITo203BxKunGI80AGYicu1ySFTUyugicAaTZWRzFWh9DSnzkgNeMNbDWBbSs0w==} engines: {node: '>=20.18.0'} peerDependencies: @@ -37730,35 +39044,35 @@ packages: dts-resolver: 2.1.2 get-tsconfig: 4.10.1 magic-string: 0.30.19 - rolldown: 1.2.2 + rolldown: 1.2.4 typescript: 5.9.2 transitivePeerDependencies: - oxc-resolver - supports-color dev: true - /rolldown@1.2.2: - resolution: {integrity: sha512-opwpo1tQBAcpSUJDt94B7hhLNGOKjCdE//XXjeLrnx9b83bjnw45tXdg1b09yEw/VLFBJGZpwRULMmOZo7ol+A==} + /rolldown@1.2.4: + resolution: {integrity: sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true dependencies: - '@oxc-project/types': 0.142.0 + '@oxc-project/types': 0.144.0 '@rolldown/pluginutils': 1.0.0 optionalDependencies: - '@rolldown/binding-android-arm64': 1.2.2 - '@rolldown/binding-darwin-arm64': 1.2.2 - '@rolldown/binding-darwin-x64': 1.2.2 - '@rolldown/binding-freebsd-x64': 1.2.2 - '@rolldown/binding-linux-arm-gnueabihf': 1.2.2 - '@rolldown/binding-linux-arm64-gnu': 1.2.2 - '@rolldown/binding-linux-arm64-musl': 1.2.2 - '@rolldown/binding-linux-ppc64-gnu': 1.2.2 - '@rolldown/binding-linux-s390x-gnu': 1.2.2 - '@rolldown/binding-linux-x64-gnu': 1.2.2 - '@rolldown/binding-linux-x64-musl': 1.2.2 - '@rolldown/binding-openharmony-arm64': 1.2.2 - '@rolldown/binding-win32-arm64-msvc': 1.2.2 - '@rolldown/binding-win32-x64-msvc': 1.2.2 + '@rolldown/binding-android-arm64': 1.2.4 + '@rolldown/binding-darwin-arm64': 1.2.4 + '@rolldown/binding-darwin-x64': 1.2.4 + '@rolldown/binding-freebsd-x64': 1.2.4 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.4 + '@rolldown/binding-linux-arm64-gnu': 1.2.4 + '@rolldown/binding-linux-arm64-musl': 1.2.4 + '@rolldown/binding-linux-ppc64-gnu': 1.2.4 + '@rolldown/binding-linux-s390x-gnu': 1.2.4 + '@rolldown/binding-linux-x64-gnu': 1.2.4 + '@rolldown/binding-linux-x64-musl': 1.2.4 + '@rolldown/binding-openharmony-arm64': 1.2.4 + '@rolldown/binding-win32-arm64-msvc': 1.2.4 + '@rolldown/binding-win32-x64-msvc': 1.2.4 dev: true /rollup-plugin-inject@3.0.2: @@ -38034,7 +39348,7 @@ packages: resolution: {integrity: sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==} engines: {node: '>=12'} dependencies: - semver: 7.7.2 + semver: 7.7.4 dev: true /semver@5.7.2: @@ -38072,7 +39386,6 @@ packages: resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} hasBin: true - dev: false /send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} @@ -38196,7 +39509,7 @@ packages: dependencies: color: 4.2.3 detect-libc: 2.1.1 - semver: 7.7.2 + semver: 7.7.4 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 @@ -38414,7 +39727,6 @@ packages: engines: {node: '>=8'} dependencies: unicode-emoji-modifier-base: 1.0.0 - dev: true /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -39332,17 +40644,18 @@ packages: minipass: 7.1.2 minizlib: 3.1.0 yallist: 5.0.0 + dev: false /tar@7.5.7: resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 minipass: 7.1.2 minizlib: 3.1.0 yallist: 5.0.0 - dev: false /teeny-request@10.1.0: resolution: {integrity: sha512-3ZnLvgWF29jikg1sAQ1g0o+lr5JX6sVgYvfUJazn7ZjJroDBUTWp44/+cFVX0bULjv4vci+rBD+oGVAkWqhUbw==} @@ -39962,8 +41275,8 @@ packages: empathic: 2.0.0 hookable: 5.5.3 publint: 0.3.12 - rolldown: 1.2.2 - rolldown-plugin-dts: 0.16.11(rolldown@1.2.2)(typescript@5.9.2) + rolldown: 1.2.4 + rolldown-plugin-dts: 0.16.11(rolldown@1.2.4)(typescript@5.9.2) semver: 7.7.2 tinyexec: 1.0.1 tinyglobby: 0.2.15 @@ -40306,7 +41619,7 @@ packages: dependencies: '@quansync/fs': 0.1.5 defu: 6.1.4 - jiti: 2.5.1 + jiti: 2.6.1 quansync: 0.2.11 dev: true @@ -40391,7 +41704,6 @@ packages: /unicode-emoji-modifier-base@1.0.0: resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} engines: {node: '>=4'} - dev: true /unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} @@ -41030,7 +42342,7 @@ packages: is-npm: 6.1.0 latest-version: 9.0.0 pupa: 3.3.0 - semver: 7.7.2 + semver: 7.7.4 xdg-basedir: 5.1.0 dev: true @@ -41345,6 +42657,25 @@ packages: '@types/unist': 3.0.3 vfile-message: 4.0.3 + /victory-vendor@36.9.2: + resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-ease': 3.0.2 + '@types/d3-interpolate': 3.0.4 + '@types/d3-scale': 4.0.9 + '@types/d3-shape': 3.1.7 + '@types/d3-time': 3.0.4 + '@types/d3-timer': 3.0.2 + d3-array: 3.2.4 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-scale: 4.0.2 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-timer: 3.0.1 + dev: false + /vite-dev-rpc@1.1.0(vite@7.2.7): resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==} peerDependencies: @@ -41695,6 +43026,75 @@ packages: vite: 7.2.7(@types/node@24.2.1)(jiti@2.5.1)(tsx@4.21.0) dev: true + /vitest@3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0): + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/chai': 5.2.2 + '@types/node': 24.2.1 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.2.7) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/ui': 1.6.1(vitest@3.2.4) + '@vitest/utils': 3.2.4 + chai: 5.2.1 + debug: 4.4.3(supports-color@10.2.2) + expect-type: 1.2.2 + jsdom: 22.1.0 + magic-string: 0.30.19 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.2.7(@types/node@24.2.1)(jiti@2.5.1)(tsx@4.21.0) + vite-node: 3.2.4(@types/node@24.2.1)(jiti@2.5.1)(tsx@4.21.0) + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + dev: true + /vitest@3.2.4(@types/node@24.2.1)(@vitest/ui@1.6.1)(jsdom@22.1.0)(msw@2.11.6): resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -41795,7 +43195,7 @@ packages: '@types/chai': 5.2.2 '@types/node': 24.6.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.11.6)(vite@7.2.7) + '@vitest/mocker': 3.2.4(vite@7.2.7) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -41979,7 +43379,7 @@ packages: eslint-visitor-keys: 4.2.1 espree: 10.4.0 esquery: 1.6.0 - semver: 7.7.2 + semver: 7.7.4 transitivePeerDependencies: - supports-color dev: false