diff --git a/docs/messages.mdx b/docs/messages.mdx index a0398ec67..79abfac65 100644 --- a/docs/messages.mdx +++ b/docs/messages.mdx @@ -50,9 +50,14 @@ If you want to get MessageDocs, you can use `listMessages` instead. ## Showing messages in React -See [ChatStreaming.tsx](../example/ui/chat/ChatStreaming.tsx) for a streaming -example, or [ChatBasic.tsx](../example/ui/chat/ChatBasic.tsx) for a -non-streaming example. +Examples: + +- [ChatBasic.tsx](../example/ui/chat/ChatBasic.tsx): non-streaming messages. +- [ChatStreaming.tsx](../example/ui/chat/ChatStreaming.tsx): streaming messages + with custom React components. +- [ChatAssistantUI.tsx](../example/ui/chat/ChatAssistantUI.tsx): streaming + messages and tool approvals with + [assistant-ui](https://www.assistant-ui.com/). ### `useUIMessages` hook diff --git a/docs/streaming.mdx b/docs/streaming.mdx index 30a94a017..658ef0af8 100644 --- a/docs/streaming.mdx +++ b/docs/streaming.mdx @@ -29,6 +29,8 @@ Example: - Server: [streaming.ts](../example/convex/chat/streaming.ts) - Client: [ChatStreaming.tsx](../example/ui/chat/ChatStreaming.tsx) +- Client with assistant-ui: + [ChatAssistantUI.tsx](../example/ui/chat/ChatAssistantUI.tsx) ## Streaming message deltas diff --git a/docs/tool-approval.mdx b/docs/tool-approval.mdx index 220d3af82..aa6a0ea4f 100644 --- a/docs/tool-approval.mdx +++ b/docs/tool-approval.mdx @@ -12,8 +12,8 @@ action before it happens. ## Defining tools with approval -Add `needsApproval` to any tool created with `createTool`. It can be a -boolean or an async function that receives the tool context and input: +Add `needsApproval` to any tool created with `createTool`. It can be a boolean +or an async function that receives the tool context and input: ```ts import { createTool } from "@convex-dev/agent"; @@ -56,11 +56,13 @@ The typical approval flow involves four server functions: 1. **Save the user's message** and schedule generation. 2. **Generate a response.** If the model calls a tool that needs approval, - generation pauses and the `tool-approval-request` is persisted in the - thread. + generation pauses and the `tool-approval-request` is persisted in the thread. 3. **Submit an approval or denial** for each pending tool call. `approveToolCall` and `denyToolCall` work from both mutations and actions. -4. **Continue generation** from the returned message ID. +4. **Continue generation** by running the same action with the returned message + ID as the prompt. Schedule it from the mutation that saves the last pending + decision in the step, so continuation does not depend on the client staying + connected. ```ts import { approvalAgent } from "../agents/approval"; @@ -81,7 +83,7 @@ export const sendMessage = mutation({ }, }); -// 2. Generate (stops if approval is needed) +// 2. Generate (stops if approval is needed). Also continues after approvals. export const generateResponse = internalAction({ args: { promptMessageId: v.string(), threadId: v.string() }, handler: async (ctx, { promptMessageId, threadId }) => { @@ -106,29 +108,21 @@ export const submitApproval = mutation({ handler: async (ctx, { threadId, approvalId, approved, reason }) => { const { messageId } = approved ? await approvalAgent.approveToolCall(ctx, { - threadId, approvalId, reason, + threadId, + approvalId, + reason, }) : await approvalAgent.denyToolCall(ctx, { - threadId, approvalId, reason, + threadId, + approvalId, + reason, }); + // 4. If no approval request in this step is still undecided, schedule + // generateResponse with promptMessageId: messageId. See the example + // files below. return { messageId }; }, }); - -// 4. Continue generation from the saved approval decision. -// Pass the last approval message ID as promptMessageId so the agent -// resumes generation from where the approval was issued. -export const continueAfterApprovals = internalAction({ - args: { threadId: v.string(), lastApprovalMessageId: v.string() }, - handler: async (ctx, { threadId, lastApprovalMessageId }) => { - const result = await approvalAgent.streamText( - ctx, - { threadId }, - { promptMessageId: lastApprovalMessageId }, - ); - await result.consumeStream(); - }, -}); ``` @@ -142,9 +136,9 @@ For example, an action can call `approveToolCall` and then immediately call ## Handling multiple tool calls When the model calls several tools in a single step, some or all of them may -require approval. Submit decisions from the same assistant request together -with `respondToToolCallApprovals`. The batch uses one bounded lookup and one -write, and either every decision is saved or none are. +require approval. Submit decisions from the same assistant request together with +`respondToToolCallApprovals`. The batch uses one bounded lookup and one write, +and either every decision is saved or none are. ```ts const { messageId } = await approvalAgent.respondToToolCallApprovals(ctx, { @@ -169,12 +163,12 @@ single-decision helpers so the request history is read only once. If a partial continuation requests another approval, that newer request also remains pending while you resume an earlier sibling. -If an unrelated generation starts while approvals are still unresolved, they -are **automatically denied** with the reason -`"auto-denied: new generation started"`. This prevents broken message -histories where tool calls lack results. These denials are synthetic and only -added to the model's context for that request; they are not saved, so the -approvals remain pending in storage. +If an unrelated generation starts while approvals are still unresolved, they are +**automatically denied** with the reason +`"auto-denied: new generation started"`. This prevents broken message histories +where tool calls lack results. These denials are synthetic and only added to the +model's context for that request; they are not saved, so the approvals remain +pending in storage. This does not apply when resuming approvals: on that continuation, earlier approvals that were not part of the resume are omitted from that model request. @@ -187,14 +181,11 @@ Approve/Deny buttons. Tool parts with `state === "approval-requested"` are waiting for a decision. ```tsx -import { useEffect, useRef } from "react"; import { useMutation } from "convex/react"; import { useUIMessages, type UIMessage } from "@convex-dev/agent/react"; import type { ToolUIPart } from "ai"; function Chat({ threadId }: { threadId: string }) { - const lastApprovalMessageIdRef = useRef(null); - const { results: messages } = useUIMessages( api.chat.approval.listThreadMessages, { threadId }, @@ -202,9 +193,6 @@ function Chat({ threadId }: { threadId: string }) { ); const submitApproval = useMutation(api.chat.approval.submitApproval); - const triggerContinuation = useMutation( - api.chat.approval.triggerContinuation, - ); const hasPendingApprovals = messages.some((m) => m.parts.some( @@ -214,36 +202,29 @@ function Chat({ threadId }: { threadId: string }) { ), ); - // When all approvals are resolved, trigger continuation - useEffect(() => { - if (!hasPendingApprovals && lastApprovalMessageIdRef.current) { - void triggerContinuation({ - threadId, - lastApprovalMessageId: lastApprovalMessageIdRef.current, - }); - lastApprovalMessageIdRef.current = null; - } - }, [hasPendingApprovals, threadId, triggerContinuation]); - // Render approval buttons for tool parts with state "approval-requested" + // and call submitApproval. The server continues generation. // ... } ``` The `ToolUIPart` states relevant to approval are: -| State | Meaning | -|-------|---------| -| `approval-requested` | Waiting for the user to approve or deny | +| State | Meaning | +| -------------------- | ---------------------------------------------------- | +| `approval-requested` | Waiting for the user to approve or deny | | `approval-responded` | User responded; tool is being executed (if approved) | -| `output-available` | Tool executed successfully | -| `output-denied` | Tool was denied | -| `output-error` | Tool execution failed | +| `output-available` | Tool executed successfully | +| `output-denied` | Tool was denied | +| `output-error` | Tool execution failed | ## Example files For a complete working example, see: -- **Agent definition:** [`example/convex/agents/approval.ts`](https://github.com/convex/agent/blob/main/example/convex/agents/approval.ts) -- **Server functions:** [`example/convex/chat/approval.ts`](https://github.com/convex/agent/blob/main/example/convex/chat/approval.ts) -- **React UI:** [`example/ui/chat/ChatApproval.tsx`](https://github.com/convex/agent/blob/main/example/ui/chat/ChatApproval.tsx) +- **Agent definition:** + [`example/convex/agents/approval.ts`](https://github.com/convex/agent/blob/main/example/convex/agents/approval.ts) +- **Server functions:** + [`example/convex/chat/approval.ts`](https://github.com/convex/agent/blob/main/example/convex/chat/approval.ts) +- **React UI:** + [`example/ui/chat/ChatApproval.tsx`](https://github.com/convex/agent/blob/main/example/ui/chat/ChatApproval.tsx) diff --git a/example/README.md b/example/README.md index 7d3bdf092..2a2674694 100644 --- a/example/README.md +++ b/example/README.md @@ -25,3 +25,23 @@ cd agent npm run setup npm run dev ``` + +## assistant-ui chat + +`/chat-assistant-ui` renders the tool approval agent with +[assistant-ui](https://www.assistant-ui.com/) primitives. It uses the same +backend as the Tool Approval example (`convex/chat/approval.ts`). + +- `ui/chat/assistant-ui/useConvexRuntime.ts` connects `useUIMessages` to + `useExternalStoreRuntime`. Sending runs `sendMessage` with + `optimisticallySendMessage`, and approvals go through `submitApproval`, which + resumes generation once every approval in the step is answered. Stop calls + `abortStreamByOrder`. +- `ui/chat/assistant-ui/convertMessage.ts` maps `UIMessage` parts to + assistant-ui parts, keyed by the message's stable `key`. +- `ui/chat/assistant-ui/Thread.tsx` composes the UI from assistant-ui + primitives. + +With no provider key and no Convex AI gateway, the demo model replies with mock +text and never calls tools, so approvals need a real model (see +`convex/modelsForDemo.ts`). diff --git a/example/convex/chat/approval.test.ts b/example/convex/chat/approval.test.ts new file mode 100644 index 000000000..13434d51e --- /dev/null +++ b/example/convex/chat/approval.test.ts @@ -0,0 +1,91 @@ +import { describe, expect, test } from "vitest"; +import { createThread, saveMessages } from "@convex-dev/agent"; +import { api, components } from "../_generated/api"; +import { initConvexTest } from "../setup.test"; + +async function setup(approvalIds: string[]) { + const t = initConvexTest(); + const threadId = await t.run(async (ctx) => { + const threadId = await createThread(ctx, components.agent, {}); + await saveMessages(ctx, components.agent, { + threadId, + messages: [ + { role: "user", content: "Delete both files" }, + { + role: "assistant", + content: approvalIds.flatMap((approvalId) => [ + { + type: "tool-call" as const, + toolCallId: `call-${approvalId}`, + toolName: "deleteFile", + input: { filename: `${approvalId}.txt` }, + }, + { + type: "tool-approval-request" as const, + toolCallId: `call-${approvalId}`, + approvalId, + }, + ]), + }, + ], + }); + return threadId; + }); + const decide = (approvalId: string, approved = true) => + t.mutation(api.chat.approval.submitApproval, { + threadId, + approvalId, + approved, + }); + const scheduled = () => + t.run(async (ctx) => + (await ctx.db.system.query("_scheduled_functions").collect()).map( + ({ name, args }) => ({ name, args }), + ), + ); + return { threadId, decide, scheduled }; +} + +const continuation = (threadId: string, promptMessageId: string) => ({ + name: "chat/approval:generateResponse", + args: [{ threadId, promptMessageId }], +}); + +describe("submitApproval", () => { + test("continues once, after the last of parallel decisions", async () => { + const { threadId, decide, scheduled } = await setup(["a", "b"]); + await decide("a"); + expect(await scheduled()).toEqual([]); + const { messageId } = await decide("b"); + expect(await scheduled()).toEqual([continuation(threadId, messageId)]); + }); + + test("continues when a step's decisions fill the lookup window", async () => { + const ids = Array.from({ length: 100 }, (_, i) => `a${i}`); + const { threadId, decide, scheduled } = await setup(ids); + for (const id of ids.slice(0, -1)) await decide(id); + expect(await scheduled()).toEqual([]); + const { messageId } = await decide(ids.at(-1)!); + expect(await scheduled()).toEqual([continuation(threadId, messageId)]); + }, 30_000); + + test("continues after a single decision", async () => { + const { threadId, decide, scheduled } = await setup(["a"]); + const { messageId } = await decide("a"); + expect(await scheduled()).toEqual([continuation(threadId, messageId)]); + }); + + test("counts a denial as a decision", async () => { + const { threadId, decide, scheduled } = await setup(["a", "b"]); + await decide("a"); + const { messageId } = await decide("b", false); + expect(await scheduled()).toEqual([continuation(threadId, messageId)]); + }); + + test("rejects a decision for a step that already continued", async () => { + const { threadId, decide, scheduled } = await setup(["a"]); + const { messageId } = await decide("a"); + await expect(decide("a", false)).rejects.toThrow(/already handled/); + expect(await scheduled()).toEqual([continuation(threadId, messageId)]); + }); +}); diff --git a/example/convex/chat/approval.ts b/example/convex/chat/approval.ts index edf55b928..c12e05da6 100644 --- a/example/convex/chat/approval.ts +++ b/example/convex/chat/approval.ts @@ -4,7 +4,8 @@ // 1. User sends message → model calls a tool with needsApproval // 2. Generation stops with a tool-approval-request in the response // 3. Client shows Approve/Deny buttons to the user -// 4. User clicks Approve or Deny → saves response, schedules continuation +// 4. User clicks Approve or Deny → saves response; the last decision in the +// step schedules continuation // 5. AI SDK automatically handles the approval: executes tool (if approved) // or creates execution-denied result (if denied), then continues generation import { paginationOptsValidator } from "convex/server"; @@ -38,8 +39,9 @@ export const sendMessage = mutation({ }); /** - * Generate a response. If a tool requires approval, generation stops - * and the approval-request is persisted in the thread. + * Generate a response to a prompt, or continue from the last approval + * decision in a step. If a tool requires approval, generation stops and the + * approval-request is persisted in the thread. */ export const generateResponse = internalAction({ args: { promptMessageId: v.string(), threadId: v.string() }, @@ -55,9 +57,10 @@ export const generateResponse = internalAction({ }); /** - * Submit an approval decision for a single tool call. - * Saves the decision but does NOT continue generation — the client - * calls continueAfterApprovals once all pending approvals are resolved. + * Submit an approval decision for a single tool call. The decision that + * resolves the last pending approval in its step schedules continuation. + * Mutations are serializable, so with concurrent decisions exactly one sees + * every approval decided. */ export const submitApproval = mutation({ args: { @@ -69,6 +72,23 @@ export const submitApproval = mutation({ returns: v.object({ messageId: v.string() }), handler: async (ctx, { threadId, approvalId, approved, reason }) => { await authorizeThreadAccess(ctx, threadId); + const { page } = await approvalAgent.listMessages(ctx, { + threadId, + paginationOpts: { cursor: null, numItems: 100 }, + }); + const decided = new Set([approvalId]); + let step: string[] | undefined; + for (const { message } of page) { + if (!Array.isArray(message?.content)) continue; + const requested: string[] = []; + for (const part of message.content) { + if (part.type === "tool-approval-response") + decided.add(part.approvalId); + if (part.type === "tool-approval-request") + requested.push(part.approvalId); + } + if (requested.includes(approvalId)) step = requested; + } const { messageId } = approved ? await approvalAgent.approveToolCall(ctx, { threadId, @@ -76,49 +96,16 @@ export const submitApproval = mutation({ reason, }) : await approvalAgent.denyToolCall(ctx, { threadId, approvalId, reason }); + if (step?.every((id) => decided.has(id))) { + await ctx.scheduler.runAfter(0, internal.chat.approval.generateResponse, { + threadId, + promptMessageId: messageId, + }); + } return { messageId }; }, }); -/** - * Continue generation after all approvals in a step have been resolved. - * The client calls this once every pending tool call has been approved or denied. - */ -export const continueAfterApprovals = internalAction({ - args: { - threadId: v.string(), - lastApprovalMessageId: v.string(), - }, - handler: async (ctx, { threadId, lastApprovalMessageId }) => { - const result = await approvalAgent.streamText( - ctx, - { threadId }, - { promptMessageId: lastApprovalMessageId }, - { saveStreamDeltas: { chunking: "word", throttleMs: 100 } }, - ); - await result.consumeStream(); - }, -}); - -/** - * Schedule continuation after all approvals are resolved. - * Called by the client when hasPendingApprovals becomes false. - */ -export const triggerContinuation = mutation({ - args: { - threadId: v.string(), - lastApprovalMessageId: v.string(), - }, - handler: async (ctx, { threadId, lastApprovalMessageId }) => { - await authorizeThreadAccess(ctx, threadId); - await ctx.scheduler.runAfter( - 0, - internal.chat.approval.continueAfterApprovals, - { threadId, lastApprovalMessageId }, - ); - }, -}); - /** * Query messages with streaming support. */ diff --git a/example/ui/chat/ChatApproval.tsx b/example/ui/chat/ChatApproval.tsx index daf7001ed..c78dc75e1 100644 --- a/example/ui/chat/ChatApproval.tsx +++ b/example/ui/chat/ChatApproval.tsx @@ -51,15 +51,6 @@ function Chat({ threadId, reset }: { threadId: string; reset: () => void }) { ); const submitApproval = useMutation(api.chat.approval.submitApproval); - const triggerContinuation = useMutation( - api.chat.approval.triggerContinuation, - ); - - // Track the last approval messageId so we can use it for continuation. - const lastApprovalMessageIdRef = useRef(null); - // Track whether we've already triggered continuation for this batch. - const continuationTriggeredRef = useRef(false); - const hasPendingApprovals = messages.some((m) => m.parts.some( (p) => @@ -68,36 +59,6 @@ function Chat({ threadId, reset }: { threadId: string; reset: () => void }) { ), ); - // When all approvals are resolved (hasPendingApprovals goes false) - // and we have a saved messageId, trigger continuation. - useEffect(() => { - if ( - !hasPendingApprovals && - lastApprovalMessageIdRef.current && - !continuationTriggeredRef.current - ) { - continuationTriggeredRef.current = true; - void triggerContinuation({ - threadId, - lastApprovalMessageId: lastApprovalMessageIdRef.current, - }); - lastApprovalMessageIdRef.current = null; - } - if (hasPendingApprovals) { - continuationTriggeredRef.current = false; - } - }, [hasPendingApprovals, threadId, triggerContinuation]); - - async function handleApproval(args: { - threadId: string; - approvalId: string; - approved: boolean; - reason?: string; - }) { - const { messageId } = await submitApproval(args); - lastApprovalMessageIdRef.current = messageId; - } - const [prompt, setPrompt] = useState( "Delete the file important.txt and transfer $500 to account savings-123", ); @@ -126,7 +87,7 @@ function Chat({ threadId, reset }: { threadId: string; reset: () => void }) { key={m.key} message={m} threadId={threadId} - onApproval={handleApproval} + onApproval={submitApproval} /> ))}
@@ -171,8 +132,6 @@ function Chat({ threadId, reset }: { threadId: string; reset: () => void }) { className="px-4 py-2 rounded-lg bg-red-100 text-red-700 hover:bg-red-200 transition font-medium" onClick={() => { reset(); - lastApprovalMessageIdRef.current = null; - continuationTriggeredRef.current = false; setPrompt( "Delete the file important.txt and transfer $500 to account savings-123", ); diff --git a/example/ui/chat/ChatAssistantUI.tsx b/example/ui/chat/ChatAssistantUI.tsx new file mode 100644 index 000000000..fd247fbdf --- /dev/null +++ b/example/ui/chat/ChatAssistantUI.tsx @@ -0,0 +1,85 @@ +import { AssistantRuntimeProvider, AuiIf } from "@assistant-ui/react"; +import { useState } from "react"; +import { useDemoThread } from "../hooks/use-demo-thread"; +import { Thread } from "./assistant-ui/Thread"; +import { useConvexRuntime } from "./assistant-ui/useConvexRuntime"; + +export default function ChatAssistantUI() { + const { threadId, resetThread } = useDemoThread("assistant-ui Chat Example"); + return threadId ? ( + + ) : ( +

+ Loading conversation… +

+ ); +} + +function Conversation({ + threadId, + resetThread, +}: { + threadId: string; + resetThread: () => Promise; +}) { + const runtime = useConvexRuntime(threadId); + const [isCreatingThread, setIsCreatingThread] = useState(false); + const [newThreadError, setNewThreadError] = useState(); + + const handleNewThread = async () => { + setNewThreadError(undefined); + setIsCreatingThread(true); + try { + await resetThread(); + } catch (cause) { + setNewThreadError( + cause instanceof Error + ? cause.message + : "Unable to create a new conversation.", + ); + } finally { + setIsCreatingThread(false); + } + }; + + return ( + +
+
+
+

+ Approval Agent +

+

+ Convex Agent + assistant-ui +

+
+ !s.thread.isRunning}> + + +
+ {newThreadError && ( +

+ {newThreadError} +

+ )} + +
+
+ ); +} diff --git a/example/ui/chat/assistant-ui/Thread.tsx b/example/ui/chat/assistant-ui/Thread.tsx new file mode 100644 index 000000000..e2feb9030 --- /dev/null +++ b/example/ui/chat/assistant-ui/Thread.tsx @@ -0,0 +1,240 @@ +import { + ActionBarPrimitive, + AuiIf, + ComposerPrimitive, + MessagePrimitive, + ThreadPrimitive, + type ReasoningMessagePartProps, + type ToolApprovalResponse, + type ToolCallMessagePartProps, +} from "@assistant-ui/react"; +import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown"; +import { ArrowDown, ArrowUp, Check, Copy, Square } from "lucide-react"; +import { useState } from "react"; + +export function Thread() { + return ( + + +
+ s.thread.isLoading}> +

+ Loading conversation… +

+
+ s.thread.hasEarlier}> + + Load earlier messages + + + s.thread.isEmpty}> +
+

+ Tools that ask first. +

+

+ Ask the agent to delete a file, transfer money, or check a + balance. +

+ + Delete important.txt and transfer $500 + +
+
+ + s.thread.isRunning}> +

+ Working… +

+
+
+ + + + + + + !s.thread.isRunning}> + + + + + s.thread.isRunning}> + + + + + + +
+
+ ); +} + +function UserMessage() { + return ( + + + + ); +} + +function AssistantMessage() { + return ( + +
+ +
+ s.message.status?.type === "incomplete"}> +

+ This response ended before completion. +

+
+ + + s.message.isCopied}> + + + !s.message.isCopied}> + + + + +
+ ); +} + +function Reasoning({ text }: ReasoningMessagePartProps) { + return ( +
+ Reasoning +

{text}

+
+ ); +} + +function ToolCall({ + toolName, + argsText, + result, + isError, + status, + approval, + respondToApproval, +}: ToolCallMessagePartProps) { + const [error, setError] = useState(); + const [responding, setResponding] = useState(false); + const awaitingApproval = + approval !== undefined && + approval.approved === undefined && + approval.resolution === undefined; + const respond = async (response: ToolApprovalResponse) => { + setError(undefined); + setResponding(true); + try { + await respondToApproval(response); + } catch (cause) { + setError(cause instanceof Error ? cause.message : String(cause)); + } finally { + setResponding(false); + } + }; + return ( +
+ + {toolName} · {toolStatus({ result, isError, status, approval })} + +
+        {argsText}
+      
+ {result !== undefined && ( +
+          {JSON.stringify(result, null, 2)}
+        
+ )} + {awaitingApproval && ( +
+ + +
+ )} + {error && ( +

+ {error} +

+ )} +
+ ); +} + +function toolStatus({ + result, + isError, + status, + approval, +}: Pick< + ToolCallMessagePartProps, + "result" | "isError" | "status" | "approval" +>) { + if (approval?.approved === false) { + return `Denied${approval.reason ? `: ${approval.reason}` : ""}`; + } + if (isError) return "Failed"; + if (result !== undefined) return "Complete"; + if (status.type === "running") return "Running…"; + if (approval && status.type !== "incomplete") { + return approval.approved ? "Approved" : "Needs approval"; + } + return status.type === "complete" ? "Complete" : "Stopped"; +} + +function MarkdownText() { + return ; +} diff --git a/example/ui/chat/assistant-ui/convertMessage.test.ts b/example/ui/chat/assistant-ui/convertMessage.test.ts new file mode 100644 index 000000000..0d550a275 --- /dev/null +++ b/example/ui/chat/assistant-ui/convertMessage.test.ts @@ -0,0 +1,301 @@ +import type { UIMessage } from "@convex-dev/agent/react"; +import { describe, expect, it } from "vitest"; +import { convertMessage } from "./convertMessage"; + +const message: UIMessage = { + id: "stream-id", + key: "thread-1-0", + role: "assistant", + parts: [{ type: "text", text: "Once upon a time" }], + text: "Once upon a time", + status: "streaming", + order: 1, + stepOrder: 0, + _creationTime: 1_700_000_000_000, +}; + +describe("convertMessage", () => { + it("keeps the same runtime ID when a streamed message is persisted", () => { + const streaming = convertMessage(message); + const saved = convertMessage({ + ...message, + id: "database-id", + status: "success", + }); + expect(streaming.id).toBe(message.key); + expect(saved.id).toBe(streaming.id); + expect(streaming.status).toEqual({ type: "running" }); + expect(saved.status).toEqual({ type: "complete", reason: "stop" }); + expect(saved.createdAt).toEqual(new Date(message._creationTime)); + }); + + it("preserves ordered text, reasoning, and tool results", () => { + expect( + convertMessage({ + ...message, + status: "success", + parts: [ + { type: "step-start" }, + { type: "reasoning", text: "I need two characters." }, + { + type: "tool-getCharacterNames", + toolCallId: "call-1", + state: "output-available", + input: { count: 2 }, + output: ["Alice", "Bob"], + }, + { type: "text", text: "Alice met Bob." }, + ], + }).content, + ).toEqual([ + { type: "reasoning", text: "I need two characters." }, + { + type: "tool-call", + toolCallId: "call-1", + toolName: "getCharacterNames", + argsText: '{"count":2}', + result: ["Alice", "Bob"], + }, + { type: "text", text: "Alice met Bob." }, + ]); + }); + + it("represents a tool call while its input is still streaming", () => { + expect( + convertMessage({ + ...message, + parts: [ + { + type: "dynamic-tool", + toolName: "getCharacterNames", + toolCallId: "call-1", + state: "input-streaming", + }, + ], + }).content, + ).toEqual([ + { + type: "tool-call", + toolName: "getCharacterNames", + toolCallId: "call-1", + argsText: "{}", + }, + ]); + }); + + it("exposes tool failures and incomplete assistant responses", () => { + const result = convertMessage({ + ...message, + status: "failed", + parts: [ + { + type: "tool-getCharacterNames", + toolCallId: "call-1", + state: "output-error", + input: {}, + errorText: "Tool unavailable", + }, + ], + }); + expect(result.content).toEqual([ + { + type: "tool-call", + toolName: "getCharacterNames", + toolCallId: "call-1", + argsText: "{}", + result: "Tool unavailable", + isError: true, + }, + ]); + expect(result.status).toEqual({ type: "incomplete", reason: "error" }); + }); + + it("keeps pending assistant messages running", () => { + expect( + convertMessage({ ...message, status: "pending", parts: [] }).status, + ).toEqual({ type: "running" }); + }); + + it("does not assign assistant status to a user message", () => { + const result = convertMessage({ + ...message, + role: "user", + status: "success", + }); + expect(result.role).toBe("user"); + expect(result.content).toEqual(message.parts); + expect(result.status).toBeUndefined(); + }); + it("maps each approval state to assistant-ui's approval gate", () => { + const input = { filename: "important.txt" }; + const call = { + type: "tool-call", + toolCallId: "call-1", + toolName: "deleteFile", + argsText: '{"filename":"important.txt"}', + }; + const result = convertMessage({ + ...message, + status: "success", + parts: [ + { + type: "tool-deleteFile", + toolCallId: "call-1", + state: "approval-requested", + input, + approval: { id: "approval-1" }, + }, + ], + }); + expect(result.status).toEqual({ + type: "requires-action", + reason: "tool-calls", + }); + expect(result.content).toEqual([ + { ...call, approval: { id: "approval-1" } }, + ]); + + expect( + convertMessage({ + ...message, + status: "success", + parts: [ + { + type: "tool-deleteFile", + toolCallId: "call-1", + state: "approval-responded", + input, + approval: { id: "approval-1", approved: true }, + }, + ], + }), + ).toMatchObject({ + status: { type: "complete" }, + content: [{ ...call, approval: { id: "approval-1", approved: true } }], + }); + + expect( + convertMessage({ + ...message, + status: "success", + parts: [ + { + type: "tool-deleteFile", + toolCallId: "call-1", + state: "output-available", + input, + output: "Deleted", + approval: { id: "approval-1", approved: true }, + }, + ], + }).content, + ).toEqual([ + { + ...call, + approval: { id: "approval-1", approved: true }, + result: "Deleted", + }, + ]); + }); + + it("reports a denied tool call as an error carrying the reason", () => { + const denied = (reason?: string) => + convertMessage({ + ...message, + status: "success", + parts: [ + { + type: "dynamic-tool", + toolName: "deleteFile", + toolCallId: "call-1", + state: "output-denied", + input: {}, + approval: { id: "approval-1", approved: false, reason }, + }, + ], + }).content; + expect(denied("Keep that file")).toEqual([ + { + type: "tool-call", + toolCallId: "call-1", + toolName: "deleteFile", + argsText: "{}", + approval: { + id: "approval-1", + approved: false, + reason: "Keep that file", + }, + result: { error: "Keep that file" }, + isError: true, + }, + ]); + expect(denied()).toMatchObject([ + { result: { error: "Tool approval denied" }, isError: true }, + ]); + }); + + it("maps sources, files, and data parts, and drops parts with no equivalent", () => { + expect( + convertMessage({ + ...message, + status: "success", + parts: [ + { type: "step-start" }, + { + type: "source-url", + sourceId: "s-1", + url: "https://docs.convex.dev", + title: "Docs", + }, + { + type: "source-document", + sourceId: "s-2", + mediaType: "application/pdf", + title: "Spec", + }, + { + type: "file", + mediaType: "image/png", + url: "https://example.com/a.png", + }, + { + type: "file", + mediaType: "text/plain", + url: "https://example.com/a.txt", + filename: "a.txt", + }, + { type: "data-progress", data: { done: 1 } }, + { type: "custom", kind: "provider.thing" }, + { + type: "reasoning-file", + mediaType: "image/png", + url: "https://example.com/r.png", + }, + ], + }).content, + ).toEqual([ + { + type: "source", + sourceType: "url", + id: "s-1", + url: "https://docs.convex.dev", + title: "Docs", + }, + { + type: "source", + sourceType: "document", + id: "s-2", + mediaType: "application/pdf", + title: "Spec", + }, + { type: "image", image: "https://example.com/a.png" }, + { + type: "file", + data: "https://example.com/a.txt", + mimeType: "text/plain", + filename: "a.txt", + }, + { type: "data-progress", data: { done: 1 } }, + ]); + }); +}); diff --git a/example/ui/chat/assistant-ui/convertMessage.ts b/example/ui/chat/assistant-ui/convertMessage.ts new file mode 100644 index 000000000..c898492dd --- /dev/null +++ b/example/ui/chat/assistant-ui/convertMessage.ts @@ -0,0 +1,128 @@ +import type { MessageStatus, ThreadMessageLike } from "@assistant-ui/react"; +import type { UIMessage } from "@convex-dev/agent/react"; +import { + getToolName, + isDataUIPart, + isToolUIPart, + type DynamicToolUIPart, + type ToolUIPart, +} from "ai"; + +type Part = Exclude[number]; + +export function convertMessage(message: UIMessage): ThreadMessageLike { + return { + // Convex's key survives the transition from streamed to persisted messages. + id: message.key, + role: message.role, + createdAt: new Date(message._creationTime), + content: message.parts.flatMap(convertPart), + ...(message.role === "assistant" ? { status: convertStatus(message) } : {}), + }; +} + +export function pendingApprovalIds(message: UIMessage | undefined) { + return (message?.parts ?? []).flatMap((part) => + isToolUIPart(part) && part.state === "approval-requested" + ? [part.approval.id] + : [], + ); +} + +function convertStatus(message: UIMessage): MessageStatus { + switch (message.status) { + case "pending": + case "streaming": + return { type: "running" }; + case "failed": + return { type: "incomplete", reason: "error" }; + case "success": + return pendingApprovalIds(message).length + ? { type: "requires-action", reason: "tool-calls" } + : { type: "complete", reason: "stop" }; + } +} + +function convertPart(part: UIMessage["parts"][number]): Part[] { + switch (part.type) { + case "text": + case "reasoning": + return [{ type: part.type, text: part.text }]; + case "dynamic-tool": + return [convertToolPart(part)]; + case "source-url": + return [ + { + type: "source", + sourceType: "url", + id: part.sourceId, + url: part.url, + title: part.title, + }, + ]; + case "source-document": + return [ + { + type: "source", + sourceType: "document", + id: part.sourceId, + title: part.title, + mediaType: part.mediaType, + filename: part.filename, + }, + ]; + case "file": + return [ + part.mediaType.startsWith("image") + ? { type: "image", image: part.url, filename: part.filename } + : { + type: "file", + data: part.url, + mimeType: part.mediaType, + filename: part.filename, + }, + ]; + // assistant-ui has no equivalent for these. + case "step-start": + case "custom": + case "reasoning-file": + return []; + default: + if (isToolUIPart(part)) return [convertToolPart(part)]; + if (isDataUIPart(part)) return [{ type: part.type, data: part.data }]; + return part satisfies never; + } +} + +function convertToolPart(part: ToolUIPart | DynamicToolUIPart): Part { + const call = { + type: "tool-call", + toolCallId: part.toolCallId, + toolName: getToolName(part), + argsText: JSON.stringify(part.input ?? {}), + } as const; + switch (part.state) { + case "input-streaming": + case "input-available": + return call; + case "approval-requested": + case "approval-responded": + return { ...call, approval: part.approval }; + case "output-available": + return { ...call, approval: part.approval, result: part.output }; + case "output-error": + return { + ...call, + approval: part.approval, + result: part.errorText, + isError: true, + }; + case "output-denied": + return { + ...call, + approval: part.approval, + result: { error: part.approval.reason ?? "Tool approval denied" }, + isError: true, + }; + } +} diff --git a/example/ui/chat/assistant-ui/useConvexRuntime.ts b/example/ui/chat/assistant-ui/useConvexRuntime.ts new file mode 100644 index 000000000..bd59511c0 --- /dev/null +++ b/example/ui/chat/assistant-ui/useConvexRuntime.ts @@ -0,0 +1,58 @@ +import { + MessageNotSentError, + useExternalStoreRuntime, +} from "@assistant-ui/react"; +import { + optimisticallySendMessage, + useUIMessages, +} from "@convex-dev/agent/react"; +import { useMutation } from "convex/react"; +import { api } from "../../../convex/_generated/api"; +import { convertMessage, pendingApprovalIds } from "./convertMessage"; + +export function useConvexRuntime(threadId: string) { + const { results, status, loadMore } = useUIMessages( + api.chat.approval.listThreadMessages, + { threadId }, + { initialNumItems: 10, stream: true }, + ); + const sendMessage = useMutation( + api.chat.approval.sendMessage, + ).withOptimisticUpdate( + optimisticallySendMessage(api.chat.approval.listThreadMessages), + ); + const submitApproval = useMutation(api.chat.approval.submitApproval); + const abortStream = useMutation(api.chat.streamAbort.abortStreamByOrder); + const latest = results.findLast((message) => message.role === "assistant"); + + return useExternalStoreRuntime({ + messages: results, + convertMessage, + isLoading: status === "LoadingFirstPage", + isDisabled: status === "LoadingFirstPage", + isSendDisabled: pendingApprovalIds(latest).length > 0, + isRunning: latest?.status === "pending" || latest?.status === "streaming", + hasEarlier: status === "CanLoadMore", + onLoadEarlier: async () => loadMore(10), + onNew: async ({ content: [part, ...rest] }) => { + if (part?.type !== "text" || rest.length) { + throw new MessageNotSentError("This example accepts text only."); + } + try { + await sendMessage({ threadId, prompt: part.text }); + } catch (cause) { + throw new MessageNotSentError(String(cause)); + } + }, + onRespondToToolApproval: async ({ approvalId, approved, reason }) => { + await submitApproval({ threadId, approvalId, approved, reason }); + }, + ...(latest?.status === "streaming" + ? { + onCancel: async () => { + await abortStream({ threadId, order: latest.order }); + }, + } + : {}), + }); +} diff --git a/example/ui/main.tsx b/example/ui/main.tsx index 23a02b52e..737f8f30e 100644 --- a/example/ui/main.tsx +++ b/example/ui/main.tsx @@ -9,9 +9,10 @@ import FilesImages from "./files/FilesImages"; import RateLimiting from "./rate_limiting/RateLimiting"; import { WeatherFashion } from "./workflows/WeatherFashion"; import RagBasic from "./rag/RagBasic"; -import { StrictMode } from "react"; +import { lazy, StrictMode, Suspense } from "react"; import StreamArray from "./objects/StreamArray"; import ChatApproval from "./chat/ChatApproval"; +const ChatAssistantUI = lazy(() => import("./chat/ChatAssistantUI")); const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string); @@ -42,6 +43,20 @@ export function App() { } /> } /> } /> + + Loading chat… +

+ } + > + + + } + /> } /> } /> } /> @@ -90,6 +105,18 @@ function Index() { streaming!).

+
  • + + assistant-ui Chat + +

    + The tool approval agent in an assistant-ui chat, with streaming, + approvals, history, and cancellation. +

    +
  • =26" + } + }, + "node_modules/@assistant-ui/react": { + "version": "0.15.25", + "resolved": "https://registry.npmjs.org/@assistant-ui/react/-/react-0.15.25.tgz", + "integrity": "sha512-uKAtDwMbdF2NY/F1L/sQNuNGU85tf7eyNSCZ2lBX4yddbsjP5FB3v46HxojRiIoeEyxsqe+6GS8p/RBb/YImuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@assistant-ui/core": "^0.3.24", + "@assistant-ui/store": "^0.3.17", + "@assistant-ui/tap": "^0.9.21", + "assistant-cloud": "^0.2.5", + "assistant-stream": "^0.3.48", + "radix-ui": "^1.6.7", + "react-textarea-autosize": "^8.5.9", + "safe-content-frame": "^0.0.33", + "zod": "^4.6.5", + "zustand": "^5.0.15" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@assistant-ui/react-markdown": { + "version": "0.14.19", + "resolved": "https://registry.npmjs.org/@assistant-ui/react-markdown/-/react-markdown-0.14.19.tgz", + "integrity": "sha512-OO1DbDkLNE+sjqlSW5MxP+KjI0w8QJtOpyfe9ARVfROfuhIalmv64FMGcuUXVCJN0i9axdj+xyz1fJhSM3OUNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "^2.1.10", + "@radix-ui/react-use-callback-ref": "^1.1.4", + "@types/hast": "^3.0.5", + "classnames": "^2.5.1", + "micromark-util-html-tag-name": "^2.0.1", + "react-markdown": "^10.1.0" + }, + "peerDependencies": { + "@assistant-ui/react": "^0.15.0", + "@types/react": "*", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@assistant-ui/react/node_modules/zod": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@assistant-ui/store": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@assistant-ui/store/-/store-0.3.19.tgz", + "integrity": "sha512-lxmbfbQCBx7ijIQYmP2OQJMa1aUCvRkvb/Y09fmbkxIhYAcNhSIRcINALe940dGtia+cGn63m8HxYNVoJEcFqg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@assistant-ui/tap": "^0.9.22", + "@types/react": "*", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@assistant-ui/tap": { + "version": "0.9.23", + "resolved": "https://registry.npmjs.org/@assistant-ui/tap/-/tap-0.9.23.tgz", + "integrity": "sha512-VnWoJLDv8/98YknvgB+Cjy+hwM4+BiW9nZMsKvaPdl3dUhuRdLDOZZs6gvE7x6x40NAeP4Wsq9WBDfmus5k31w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -514,6 +671,16 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.10.tgz", + "integrity": "sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", @@ -1049,34 +1216,34 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", - "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.10" + "@floating-ui/utils": "^0.2.12" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", - "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.3", - "@floating-ui/utils": "^0.2.10" + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", - "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.7.4" + "@floating-ui/dom": "^1.8.0" }, "peerDependencies": { "react": ">=16.8.0", @@ -1084,9 +1251,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", "dev": true, "license": "MIT" }, @@ -1732,35 +1899,27 @@ } }, "node_modules/@radix-ui/number": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", - "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.3.tgz", + "integrity": "sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==", "dev": true, "license": "MIT" }, "node_modules/@radix-ui/primitive": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.2.0.tgz", + "integrity": "sha512-KABY+VMIRPJL+Vyzv/335FEhXXD/xDv8BMb1kl48/aXJZMH0LtHCTx5ga5RnxaEP3nZHtmTLf1P9vanmFX46bw==", "dev": true, "license": "MIT" }, - "node_modules/@radix-ui/react-accordion": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", - "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "node_modules/@radix-ui/react-accessible-icon": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.2.0.tgz", + "integrity": "sha512-BB4+HHkFl3HipEAhm/mLhrpXV+2kRX7MvY4AaImUcQVeWQt5KhV1JEByNs8NGfJOcr95RcQGijt9+OrCo68xGA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collapsible": "1.1.12", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" + "@radix-ui/react-visually-hidden": "1.2.13" }, "peerDependencies": { "@types/react": "*", @@ -1777,14 +1936,22 @@ } } }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "node_modules/@radix-ui/react-accordion": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.3.1.tgz", + "integrity": "sha512-lCZ6sbGS/7WO0j84yx4srIgOf0MRJ/sZ13RonADXxvKBym8xrxNCq5f6DibGcr38sIlwPk8/52uYdXeOPsbEDw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collapsible": "1.2.1", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0" }, "peerDependencies": { "@types/react": "*", @@ -1801,21 +1968,18 @@ } } }, - "node_modules/@radix-ui/react-checkbox": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", - "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.2.1.tgz", + "integrity": "sha512-MWC4N7RY+qsbNrFNo7yQ9ZbdoZEW+B5DtpWxJfUnVCqcQxxqqg3qis3RMPTDbCNaTIdHJSn5XDkl9ZdVWXknLg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dialog": "1.3.1", + "@radix-ui/react-primitive": "2.2.0" }, "peerDependencies": { "@types/react": "*", @@ -1832,21 +1996,14 @@ } } }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", - "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.17.tgz", + "integrity": "sha512-67jjcVvxjXCCStnTW3Z+M7jmaFMuMR7M2JgpDzH4w7JSRrikmzhjfYgP/09ECb8n7whnsgh1ifJ+Ie96qEj+pQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/react-primitive": "2.2.0" }, "peerDependencies": { "@types/react": "*", @@ -1863,17 +2020,14 @@ } } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "node_modules/@radix-ui/react-aspect-ratio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.2.0.tgz", + "integrity": "sha512-gHEU+Lx8DlT/FYIjZQvvBJrFSwUngXTjh7FeL9QvJaNALDLez6pgDj2axCUihBjtPBy82LN0gNb25+sTcSXNmA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-primitive": "2.2.0" }, "peerDependencies": { "@types/react": "*", @@ -1890,105 +2044,144 @@ } } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "node_modules/@radix-ui/react-avatar": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.3.1.tgz", + "integrity": "sha512-ssZOkfQNkFpYVmCPQlr978xSaU7moSrGXdwg4j2Xs2WlGl/1KsSZtfpK+WnLnx0Rwll1BAh6oUrAy/uR31SBvQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 } } }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "node_modules/@radix-ui/react-checkbox": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.4.1.tgz", + "integrity": "sha512-KWtwhh+98ML3seZ9vO9yRY2OwaQG90dCiDAxjpSNY2AaZ3Hik3B0dsk6m0ILywo/no3A9/SozadyPMNweVT8yw==", "dev": true, "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-size": "1.1.5" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 } } }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@radix-ui/react-collapsible": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.2.1.tgz", + "integrity": "sha512-fSzLb/qy1wuZSxQBcxpW0hNXYHDMWiIXDGyJGdA4+FSLknOWZsNRrTCUavxb4PI8b8lvHo/CysO6NVi5zLpo5g==", "dev": true, "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 } } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "node_modules/@radix-ui/react-collection": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.2.0.tgz", + "integrity": "sha512-+yiQzqcc7Sy7/5s0jrMCjpPRFB3538VNrXPWdTLZhE/SCfgEws4aI6lHWN/vvcnyhHndROWBzqmqB4QBrITZ9Q==", "dev": true, "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 } } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", - "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz", + "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==", "dev": true, "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" - }, "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" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", - "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "node_modules/@radix-ui/react-context": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.3.0.tgz", + "integrity": "sha512-v5AYEocMISkbJ+1fTXzZpiFv7NRr3D2WiYbLIKf+FkmJ8VkP6d503eV2n34MFussHXY1pcoq3yfJiQH77dc4Mg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2001,16 +2194,18 @@ } } }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "node_modules/@radix-ui/react-context-menu": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.4.1.tgz", + "integrity": "sha512-Pddn3Z8lio3/ChxyXaEP3jHTTo1LTHCWwF8+mG1chQlWijP+ttVHBKwezrQTiV6Mj670ojvumqvuGh+mdv33iQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-menu": "2.2.1", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0" }, "peerDependencies": { "@types/react": "*", @@ -2027,15 +2222,50 @@ } } }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "node_modules/@radix-ui/react-dialog": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.3.1.tgz", + "integrity": "sha512-+0E4qvVTwjAWra9sEhJ+9BTsvHE00zkUuNw1VGh7S+Gc13dfYk+S1PVQdchWDj+XYHhAai7Z7IpzXVDCGsDplg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-guards": "1.2.0", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.2.0.tgz", + "integrity": "sha512-FtRA52a/r+LKStFT+neLUm+8vSe7wbzkbQGGeU8ixFiwC8NU14Evoq9ATECqL3eGbcUzJR4fyfA4KkK/q6dfqg==", "dev": true, "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2046,14 +2276,18 @@ } } }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", - "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.2.1.tgz", + "integrity": "sha512-KIfDcAsx+oVylFZ4xryVKusJUrLLhTQmfnJW4kwk4Km5myvhHCrj04hnWWUC166+xD4DHdH8tQGylwYX1h6+Pg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.4" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-effect-event": "0.0.5" }, "peerDependencies": { "@types/react": "*", @@ -2070,14 +2304,20 @@ } } }, - "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", - "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.2.1.tgz", + "integrity": "sha512-XsHcmYG2AcqnvTqrOXXWcMrhquEIlqucizuDH1MV/qMRW+DndpBCMvNeTRXOxqmG1H5j89M/+I0/34Zdd+zDcQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.4" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-menu": "2.2.1", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0" }, "peerDependencies": { "@types/react": "*", @@ -2094,23 +2334,32 @@ } } }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", - "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.2.0.tgz", + "integrity": "sha512-MPm5R0iRGUDrDnPNxmLBkv+X7pN4XKzt+MbWJEuJQsH3NFH4omrbpXpucyYCCKTSt+na/ZxGhEWQrWTZ0285cA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.3.1.tgz", + "integrity": "sha512-ugeMhbXt4y5S2T1GnIqbWDKEN962PDwnX1fN0eKOOgf5f63Dh2mn8F1FUySlgW0iF6GiVsRF32DzuDIWTUyQJg==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-rect": "1.1.1", - "@radix-ui/react-use-size": "1.1.1", - "@radix-ui/rect": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5" }, "peerDependencies": { "@types/react": "*", @@ -2127,15 +2376,19 @@ } } }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "node_modules/@radix-ui/react-form": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.3.0.tgz", + "integrity": "sha512-KnmrCM27m7Jo1R8S6cFDPrEeq20Jfn5dqde0SZrJr2lVXlj6/QZSUCyFoYh1d8ti0uUrMNK5Lx6dUDuINT+f4Q==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-label": "2.1.17", + "@radix-ui/react-primitive": "2.2.0" }, "peerDependencies": { "@types/react": "*", @@ -2152,15 +2405,23 @@ } } }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "node_modules/@radix-ui/react-hover-card": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.2.1.tgz", + "integrity": "sha512-4QooHxgmpCKRjj1Pft+hETKidYcrbPKcVwMGtk2Oa5DcWY2IH1fHuQt9LG6q5hUQBBV2MhQxSvtx6B/C1xfiTw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-popper": "1.4.0", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0" }, "peerDependencies": { "@types/react": "*", @@ -2177,77 +2438,721 @@ } } }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-id": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz", + "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "node_modules/@radix-ui/react-label": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.17.tgz", + "integrity": "sha512-xmj7MN/drx1oUAXkfiFIvyDmGNUIN/omGobvA5oAoNqu9zO2MkISYGZOkBcqSzs/UZXXwV+/3ACRE7q7mGcmkA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" + "@radix-ui/react-primitive": "2.2.0" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.2.1.tgz", + "integrity": "sha512-G34BsU90SBj5foYpz8pQqq/Q0Dlfyyl6KitWEfRwXC0QvfwhWNAwS49DWP2+rRJ0iwv20Z2Qx7Sk+T03bGo5JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-guards": "1.2.0", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.4.0", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-menubar": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.2.1.tgz", + "integrity": "sha512-bRTYtS9JITV2dUYqYZb7+N5SooQBkZrNRejfmyrSKe3Y57aXhKgx//kBUP0kY7pEpsWR/U1AHsAJRzjwCrK3PA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-menu": "2.2.1", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-use-controllable-state": "1.3.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-navigation-menu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.4.1.tgz", + "integrity": "sha512-XPPZjkeyCSMNNvt0FyDv/PUauG7Ow4GwHQ/XZSwW36F/TS7rR4HFTsXH8ewLnXTOLn3x96/pmTPNQIVoTX/86g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-previous": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.13" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-one-time-password-field": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-one-time-password-field/-/react-one-time-password-field-0.2.1.tgz", + "integrity": "sha512-KtHdcgnaAK6rohQ/MMJoGYcbgSRJsIuGBdHrFeTB1/9SaKlDs14oSOniW6BL6M43HqvgCO3u4WuVdFLkuc6sqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.3", + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-password-toggle-field": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-password-toggle-field/-/react-password-toggle-field-0.2.1.tgz", + "integrity": "sha512-vu4+ZoJAaFjdI7l1lDSZRs+4dEv83Jmu7lyzajPrAeQzX74y84n0rUNWbWSgN9XB5NE8IY86Z02kGH6oRrzR+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-is-hydrated": "0.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.3.1.tgz", + "integrity": "sha512-ZNxvXRx5W2Wos4fXCXb5lpdqN0Z5chf+mStOUOTr4ik7d+62MRvoe9rzCA/eGNg36lxXqSrKEKmwuZEcUrIstw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-guards": "1.2.0", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.4.0", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.4.0.tgz", + "integrity": "sha512-yCWRvLeGv9Pz3+efwHqGPp70mZ56r3kfIgQVF56Oj2aAa4uP/Tb+IE59wNcc+758rctqbCKx4LbK8II/r7Bn0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.17", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-rect": "1.1.4", + "@radix-ui/react-use-size": "1.1.5", + "@radix-ui/rect": "1.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.2.0.tgz", + "integrity": "sha512-StX7xXnaRU41VvFtMm9zlhVGz8XF6GmWWTXftkQaY+tqVkbs/R9UmAp5mLzHHapk5hM9RMZQvO/3usyIP/g42g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.11.tgz", + "integrity": "sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.2.0.tgz", + "integrity": "sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.5.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.2.1.tgz", + "integrity": "sha512-yQBiM6J3YM8Ums1orkEFpbznK47geKxa0igikzcaS1xHgdba3DdAQBsGbCTt5BVfR8zhEvgxQ0poGcINaD3lvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-primitive": "2.2.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.5.1.tgz", + "integrity": "sha512-QbyVT1ddnjqB9H+CUYKkNWdU9fIK3QHCYtjf7mS6ekSqiuXkWtWn5UZW9mhA8qtl3vrVyIsmR9gePstAtKrqkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-size": "1.1.5" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.2.1.tgz", + "integrity": "sha512-UwraORzVUeEPMclhO1p0vz0qI+TbdDLO9i+FiOqhJyHKwdpCRCck9yVEscUnAMIzCiuNoQa8D4A9bIpOPXGt6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.4.0.tgz", + "integrity": "sha512-CFrLqHNejWq5FhKAcj9V/WPGRsol76HBQto81NdOBVFEOqIEkJkKIJt0Z824A/9hHLCtoiR/Kw3euRgzXP2pxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.3", + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.4.1.tgz", + "integrity": "sha512-888ZwW0Md6GyptuqYABRX9nLKgoYfcooCyBBvVaX5Jp3e+8Jp2i4Zo/Uy50Hm+Ysn2JfloQXstW4U36w8teVtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.3", + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-guards": "1.2.0", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.4.0", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.13", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.2.0.tgz", + "integrity": "sha512-1jUAap0wZEqVP05Ou7kJgRxe/W+Qftng+rUNWGa0qkKbv9r5pWTG3E7a3ELKo2eJoHKMECnzuYrZpSyO1YgcYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.2.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-slider": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.6.1.tgz", + "integrity": "sha512-IRNRR90moPqxfwCJ0XbMJIxo70W0/1ZExT/sNCxEHMaPx0SF9HoQrcPEC75+H28cFKa0b+KH63anfLYJmwKacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.3", + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-size": "1.1.5" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.5.0.tgz", + "integrity": "sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.4.1.tgz", + "integrity": "sha512-NpBGwc40rY02ZmSvuyeKk0Bvc8ZsNeTMi4qHvJ+ZH4EiYCv0zIXEgdCW4bVdzgIUeP9xxbLJSxKOUfqITYNmkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-size": "1.1.5" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.2.1.tgz", + "integrity": "sha512-hRoJlode+hg5ZNlR+3tkfkUliIybdTpD5lkAvHQ9yaXseGf7XVO9Ib2GPEIOuaJJbo7YWYbNpDDRfo8Dhf6/xA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-use-controllable-state": "1.3.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-toast": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.3.1.tgz", + "integrity": "sha512-iQvL0J7XK4HtJNGkkWMyYrboNseI7vtotFeUkIno8YNxVA9oM7B6//fh0Mc6TSKI96+zioLWi98lQLso88yJmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.13" + }, + "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 } } }, - "node_modules/@radix-ui/react-select": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", - "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" + "node_modules/@radix-ui/react-toggle": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.2.1.tgz", + "integrity": "sha512-+3MUq+WyiBplXYqQ0EIYlq8R4sLQ0T5NbOK7DMdDLCKO93pe2uE0DUJTWWfTBprpJJXxfoF3eMW0xpakVZrYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-controllable-state": "1.3.0" }, "peerDependencies": { "@types/react": "*", @@ -2264,63 +3169,87 @@ } } }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.2.1.tgz", + "integrity": "sha512-O8Ldx5ao4p4KoW+DO8/PmkOe5mdKNi3F2SseqjVj88wvDGDHe60cUmO0Zm/uHsKrvNgQGV8Efpuh95Tht/h4vw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-toggle": "1.2.1", + "@radix-ui/react-use-controllable-state": "1.3.0" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 } } }, - "node_modules/@radix-ui/react-slot": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", - "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "node_modules/@radix-ui/react-toolbar": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.2.1.tgz", + "integrity": "sha512-Cm8m7JTEeUdbfA6T9xgyu8HfOpyvSx8pB/wj0DlEuWaJe9FilIs4Az9wci/lU9RbthV/UkltszMw5WnnD+m/Ug==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-separator": "1.2.0", + "@radix-ui/react-toggle-group": "1.2.1" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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 } } }, - "node_modules/@radix-ui/react-toast": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", - "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", + "node_modules/@radix-ui/react-tooltip": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.4.1.tgz", + "integrity": "sha512-NxLFGSFtZ78zVfcoOhTwR1xwqo5qx1Jh8Pw6FMZ9McCaqfRzz7/gIRahs2Oy5XlPgQ+8QkUcKbN5B0U44J/kCg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.4.0", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.13" }, "peerDependencies": { "@types/react": "*", @@ -2338,11 +3267,14 @@ } }, "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.5.tgz", + "integrity": "sha512-Y5GBf4NKeADoXI1geiMlMuMoURT3k9MizzzKhGb/m55H94aGigZ01PIpkvsO6lML13BA6XYAXSJ6gza7vTn5nw==", "dev": true, "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2354,14 +3286,15 @@ } }, "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.3.0.tgz", + "integrity": "sha512-TAcBI7bw2ljYCbv4+zuTSd6zICu8pRt6SDN2vJ/Z06K2MXh6I9WYFe/A9ovlFDtR5HVHGm5iDxDoABm/++dbKg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -2374,13 +3307,13 @@ } }, "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz", + "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -2393,14 +3326,30 @@ } }, "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.6.tgz", + "integrity": "sha512-9cRullnQRv+kqnRmFlmh0WC3kAPuGmHiQ9VwsXdrYk//sBhgCKEttcpPEPgIQbyx6TGUmooVEHYTyohwz/lSJg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" + "@radix-ui/react-use-callback-ref": "1.1.5" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.3.tgz", + "integrity": "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==", + "dev": true, + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2412,9 +3361,9 @@ } }, "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz", + "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2428,9 +3377,9 @@ } }, "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.4.tgz", + "integrity": "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2444,13 +3393,13 @@ } }, "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz", + "integrity": "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/rect": "1.1.1" + "@radix-ui/rect": "1.1.3" }, "peerDependencies": { "@types/react": "*", @@ -2463,13 +3412,13 @@ } }, "node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.5.tgz", + "integrity": "sha512-V1McDQkMGzgivwqdu7u96APs7oi0Jvj9LTzgq3WWrDZqxWdAqU9yZnZQqk5OizGFR8badUQwZsrlao7MOlWYOA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -2482,13 +3431,13 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", - "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.13.tgz", + "integrity": "sha512-feijiN1oPk4rck4u9Dm9tsU4mT6Wp9oeEEhaz1WUEs1VuqLf8xzsFG+Qk+uWq6TnMH9O+WRECRg0NftyP9E4Fw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3" + "@radix-ui/react-primitive": "2.2.0" }, "peerDependencies": { "@types/react": "*", @@ -2506,9 +3455,9 @@ } }, "node_modules/@radix-ui/rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.3.tgz", + "integrity": "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==", "dev": true, "license": "MIT" }, @@ -3296,6 +4245,72 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", @@ -3404,9 +4419,9 @@ } }, "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", "dev": true, "license": "MIT", "dependencies": { @@ -4108,6 +5123,84 @@ "node": ">=12" } }, + "node_modules/assistant-cloud": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/assistant-cloud/-/assistant-cloud-0.2.7.tgz", + "integrity": "sha512-w9Nq03JwNVkQovlStrIQb22K/VIyuZ7ioTzjpQTLIggFdL1dUz++DEA1W3VYTFzSHIptseuHvaWSUM05hs5uVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "assistant-stream": "^0.3.49" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/exporter-trace-otlp-http": ">=0.200.0", + "@opentelemetry/sdk-trace-base": "^2.1.0", + "ai": "^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@opentelemetry/exporter-trace-otlp-http": { + "optional": true + }, + "@opentelemetry/sdk-trace-base": { + "optional": true + }, + "ai": { + "optional": true + } + } + }, + "node_modules/assistant-stream": { + "version": "0.3.50", + "resolved": "https://registry.npmjs.org/assistant-stream/-/assistant-stream-0.3.50.tgz", + "integrity": "sha512-IaH+fesbKJE/2R1lH69DPRUfvv87lNE6j3hFf2RZaCCf79UCyF8dtaI1NK5k792p8eIQpxSLbgHs09fX5H8A6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/json-schema": "^7.0.15", + "nanoid": "^6.0.2", + "secure-json-parse": "^4.1.0" + }, + "peerDependencies": { + "ai": "^6.0.0 || ^7.0.0", + "ioredis": "^5.10.1 || ^6.0.0", + "redis": "^5.12.1" + }, + "peerDependenciesMeta": { + "ai": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "redis": { + "optional": true + } + } + }, + "node_modules/assistant-stream/node_modules/nanoid": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-6.0.2.tgz", + "integrity": "sha512-hIvVOb9Qr1p/9CNNLOe0OlWvgx/ziTsVwKN/GDSsuArN2K0wDiafP3s0SWmsm7o2BdnyS8Z9Z64NFBUbn6ziBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^22 || ^24 || >=26" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -4541,6 +5634,13 @@ "url": "https://polar.sh/cva" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true, + "license": "MIT" + }, "node_modules/cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -9015,6 +10115,84 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/radix-ui": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.8.1.tgz", + "integrity": "sha512-HPfpVGizO9xANlsFSauruLhRe/3+iOt3vPX0MXYle/UQi3gorQrSYtBcdiv0BZYewcl2rvL59qrIuLFMGAmUrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-accessible-icon": "1.2.0", + "@radix-ui/react-accordion": "1.3.1", + "@radix-ui/react-alert-dialog": "1.2.1", + "@radix-ui/react-arrow": "1.1.17", + "@radix-ui/react-aspect-ratio": "1.2.0", + "@radix-ui/react-avatar": "1.3.1", + "@radix-ui/react-checkbox": "1.4.1", + "@radix-ui/react-collapsible": "1.2.1", + "@radix-ui/react-collection": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-context-menu": "2.4.1", + "@radix-ui/react-dialog": "1.3.1", + "@radix-ui/react-direction": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-dropdown-menu": "2.2.1", + "@radix-ui/react-focus-guards": "1.2.0", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-form": "0.3.0", + "@radix-ui/react-hover-card": "1.2.1", + "@radix-ui/react-label": "2.1.17", + "@radix-ui/react-menu": "2.2.1", + "@radix-ui/react-menubar": "1.2.1", + "@radix-ui/react-navigation-menu": "1.4.1", + "@radix-ui/react-one-time-password-field": "0.2.1", + "@radix-ui/react-password-toggle-field": "0.2.1", + "@radix-ui/react-popover": "1.3.1", + "@radix-ui/react-popper": "1.4.0", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-progress": "1.2.1", + "@radix-ui/react-radio-group": "1.5.1", + "@radix-ui/react-roving-focus": "1.2.1", + "@radix-ui/react-scroll-area": "1.4.0", + "@radix-ui/react-select": "2.4.1", + "@radix-ui/react-separator": "1.2.0", + "@radix-ui/react-slider": "1.6.1", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-switch": "1.4.1", + "@radix-ui/react-tabs": "1.2.1", + "@radix-ui/react-toast": "1.3.1", + "@radix-ui/react-toggle": "1.2.1", + "@radix-ui/react-toggle-group": "1.2.1", + "@radix-ui/react-toolbar": "1.2.1", + "@radix-ui/react-tooltip": "1.4.1", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-escape-keydown": "1.1.6", + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-size": "1.1.5", + "@radix-ui/react-visually-hidden": "1.2.13" + }, + "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 + } + } + }, "node_modules/react": { "version": "19.2.4", "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", @@ -9091,9 +10269,9 @@ } }, "node_modules/react-remove-scroll": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", - "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9202,6 +10380,24 @@ } } }, + "node_modules/react-textarea-autosize": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", + "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -9400,6 +10596,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-content-frame": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/safe-content-frame/-/safe-content-frame-0.0.33.tgz", + "integrity": "sha512-JvBLoQu8rhu80MwijhnJ2zA057uCmatyOxqLbcfpMZ3XM2bI+lmu0x7e1ne92m9wHGi4eB25VcJMnSDeoQNg6w==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -9442,6 +10645,23 @@ "dev": true, "license": "MIT" }, + "node_modules/secure-json-parse": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.1.tgz", + "integrity": "sha512-lnd81MQEZKjhW/Gd2TQqdd4XP6QYNdDW/EP+I7nTrFHP9y2LmaGPIHk9xsnzcOiEr1c39c/e84xFgGviQKBTRw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -10403,6 +11623,54 @@ } } }, + "node_modules/use-composed-ref": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", + "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sidecar": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", @@ -11091,6 +12359,36 @@ "zod": "^3.25.0 || ^4.0.0" } }, + "node_modules/zustand": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.15.tgz", + "integrity": "sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index 25c76d499..29ffd94d4 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,8 @@ "@ai-sdk/otel": "1.0.28", "@ai-sdk/provider": "4.0.3", "@ai-sdk/provider-utils": "5.0.10", + "@assistant-ui/react": "0.15.25", + "@assistant-ui/react-markdown": "0.14.19", "@convex-dev/ai-sdk-provider": "^0.1.0", "@convex-dev/eslint-plugin": "5.0.0", "@convex-dev/rag": "0.7.6", @@ -109,12 +111,12 @@ "@opentelemetry/exporter-trace-otlp-http": "0.219.0", "@opentelemetry/resources": "2.8.0", "@opentelemetry/sdk-trace-base": "2.8.0", - "@radix-ui/react-accordion": "1.2.12", - "@radix-ui/react-checkbox": "1.3.3", - "@radix-ui/react-label": "2.1.8", - "@radix-ui/react-select": "2.2.6", - "@radix-ui/react-slot": "1.2.4", - "@radix-ui/react-toast": "1.2.15", + "@radix-ui/react-accordion": "1.3.1", + "@radix-ui/react-checkbox": "1.4.1", + "@radix-ui/react-label": "2.1.17", + "@radix-ui/react-select": "2.4.1", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-toast": "1.3.1", "@tailwindcss/typography": "0.5.19", "@tailwindcss/vite": "4.3.3", "@types/node": "24.13.3",