better-cmdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # better-cmdk
2
+
3
+ A beautiful command palette component for React, built on [cmdk](https://github.com/dip/cmdk) and [Radix UI](https://www.radix-ui.com/). Styled with Tailwind CSS v4 using the shadcn/ui design system.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install better-cmdk
9
+ # or
10
+ pnpm add better-cmdk
11
+ # or
12
+ bun add better-cmdk
13
+ ```
14
+
15
+ ### Peer Dependencies
16
+
17
+ This library requires React 18+ and Tailwind CSS v4:
18
+
19
+ ```bash
20
+ npm install react react-dom tailwindcss
21
+ ```
22
+
23
+ ## Setup
24
+
25
+ ### 1. Configure Tailwind to scan the package
26
+
27
+ Add the package to your Tailwind CSS sources in your main CSS file:
28
+
29
+ ```css
30
+ @import "tailwindcss";
31
+ @source "node_modules/better-cmdk";
32
+ ```
33
+
34
+ ### 2. Add CSS variables
35
+
36
+ Add the required CSS variables to your global styles:
37
+
38
+ ```css
39
+ :root {
40
+ --background: 0 0% 100%;
41
+ --foreground: 240 10% 3.9%;
42
+ --popover: 0 0% 100%;
43
+ --popover-foreground: 240 10% 3.9%;
44
+ --primary: 240 5.9% 10%;
45
+ --primary-foreground: 0 0% 98%;
46
+ --muted: 240 4.8% 95.9%;
47
+ --muted-foreground: 240 3.8% 46.1%;
48
+ --accent: 240 4.8% 95.9%;
49
+ --accent-foreground: 240 5.9% 10%;
50
+ --border: 240 5.9% 90%;
51
+ --input: 240 5.9% 90%;
52
+ --ring: 240 5.9% 10%;
53
+ --radius: 0.5rem;
54
+ }
55
+
56
+ @theme inline {
57
+ --color-background: hsl(var(--background));
58
+ --color-foreground: hsl(var(--foreground));
59
+ --color-popover: hsl(var(--popover));
60
+ --color-popover-foreground: hsl(var(--popover-foreground));
61
+ --color-primary: hsl(var(--primary));
62
+ --color-primary-foreground: hsl(var(--primary-foreground));
63
+ --color-muted: hsl(var(--muted));
64
+ --color-muted-foreground: hsl(var(--muted-foreground));
65
+ --color-accent: hsl(var(--accent));
66
+ --color-accent-foreground: hsl(var(--accent-foreground));
67
+ --color-border: hsl(var(--border));
68
+ --color-input: hsl(var(--input));
69
+ --color-ring: hsl(var(--ring));
70
+ }
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ ```tsx
76
+ "use client";
77
+
78
+ import { useState, useEffect } from "react";
79
+ import {
80
+ CommandDialog,
81
+ CommandEmpty,
82
+ CommandGroup,
83
+ CommandInput,
84
+ CommandItem,
85
+ CommandList,
86
+ CommandSeparator,
87
+ CommandShortcut,
88
+ } from "better-cmdk";
89
+
90
+ export function CommandPalette() {
91
+ const [open, setOpen] = useState(false);
92
+
93
+ useEffect(() => {
94
+ const down = (e: KeyboardEvent) => {
95
+ if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
96
+ e.preventDefault();
97
+ setOpen((open) => !open);
98
+ }
99
+ };
100
+
101
+ document.addEventListener("keydown", down);
102
+ return () => document.removeEventListener("keydown", down);
103
+ }, []);
104
+
105
+ return (
106
+ <CommandDialog open={open} onOpenChange={setOpen}>
107
+ <CommandInput placeholder="Type a command or search..." />
108
+ <CommandList>
109
+ <CommandEmpty>No results found.</CommandEmpty>
110
+ <CommandGroup heading="Suggestions">
111
+ <CommandItem>
112
+ <span>Calendar</span>
113
+ </CommandItem>
114
+ <CommandItem>
115
+ <span>Search</span>
116
+ </CommandItem>
117
+ </CommandGroup>
118
+ <CommandSeparator />
119
+ <CommandGroup heading="Settings">
120
+ <CommandItem>
121
+ <span>Profile</span>
122
+ <CommandShortcut>⌘P</CommandShortcut>
123
+ </CommandItem>
124
+ <CommandItem>
125
+ <span>Settings</span>
126
+ <CommandShortcut>⌘S</CommandShortcut>
127
+ </CommandItem>
128
+ </CommandGroup>
129
+ </CommandList>
130
+ </CommandDialog>
131
+ );
132
+ }
133
+ ```
134
+
135
+ ## Components
136
+
137
+ ### CommandDialog
138
+
139
+ The main dialog wrapper. Opens as a modal command palette.
140
+
141
+ ```tsx
142
+ <CommandDialog
143
+ open={open}
144
+ onOpenChange={setOpen}
145
+ title="Command Palette" // optional, for accessibility
146
+ description="Search commands" // optional, for accessibility
147
+ >
148
+ {children}
149
+ </CommandDialog>
150
+ ```
151
+
152
+ ### CommandInput
153
+
154
+ Search input with built-in search icon.
155
+
156
+ ```tsx
157
+ <CommandInput placeholder="Search..." />
158
+ ```
159
+
160
+ ### CommandList
161
+
162
+ Scrollable container for command items.
163
+
164
+ ```tsx
165
+ <CommandList>{children}</CommandList>
166
+ ```
167
+
168
+ ### CommandGroup
169
+
170
+ Groups related commands with an optional heading.
171
+
172
+ ```tsx
173
+ <CommandGroup heading="Actions">{children}</CommandGroup>
174
+ ```
175
+
176
+ ### CommandItem
177
+
178
+ Individual selectable command item.
179
+
180
+ ```tsx
181
+ <CommandItem onSelect={() => console.log("Selected!")}>
182
+ <Icon className="mr-2 h-4 w-4" />
183
+ <span>Label</span>
184
+ </CommandItem>
185
+ ```
186
+
187
+ ### CommandShortcut
188
+
189
+ Displays keyboard shortcut hints.
190
+
191
+ ```tsx
192
+ <CommandShortcut>⌘K</CommandShortcut>
193
+ ```
194
+
195
+ ### CommandSeparator
196
+
197
+ Visual separator between groups.
198
+
199
+ ```tsx
200
+ <CommandSeparator />
201
+ ```
202
+
203
+ ### CommandEmpty
204
+
205
+ Shown when no results match the search.
206
+
207
+ ```tsx
208
+ <CommandEmpty>No results found.</CommandEmpty>
209
+ ```
210
+
211
+ ## Subpath Exports
212
+
213
+ Import specific components directly:
214
+
215
+ ```tsx
216
+ import { Command, CommandDialog } from "better-cmdk/command";
217
+ import { Dialog, DialogContent } from "better-cmdk/dialog";
218
+ import { Button } from "better-cmdk/button";
219
+ import { cn } from "better-cmdk/utils";
220
+ ```
221
+
222
+ ## Styling
223
+
224
+ The component uses Tailwind CSS with the shadcn/ui design tokens. Customize by:
225
+
226
+ 1. Overriding CSS variables
227
+ 2. Passing `className` props to components
228
+ 3. Using the `cn()` utility for conditional classes
229
+
230
+ ## License
231
+
232
+ MIT
@@ -0,0 +1,514 @@
1
+ import { cn } from "./lib/utils.js";
2
+ import { ComponentRegistry } from "@json-render/react";
3
+ import * as React$2 from "react";
4
+ import React$1, { CSSProperties, ComponentProps, HTMLAttributes, ReactNode } from "react";
5
+ import { z } from "zod";
6
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
7
+ import { Streamdown } from "streamdown";
8
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
9
+ import { VariantProps } from "class-variance-authority";
10
+ import { Dialog as Dialog$1 } from "radix-ui";
11
+ import { Command as Command$1 } from "cmdk";
12
+ import { ToolUIPart, UIMessage } from "ai";
13
+ import * as class_variance_authority_types0 from "class-variance-authority/types";
14
+ import { UITree } from "@json-render/core";
15
+
16
+ //#region components/ui/assistant-messages.d.ts
17
+ declare const ToolActionSchema: z.ZodObject<{
18
+ name: z.ZodString;
19
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ name: string;
22
+ options?: Record<string, unknown> | undefined;
23
+ }, {
24
+ name: string;
25
+ options?: Record<string, unknown> | undefined;
26
+ }>;
27
+ type ToolAction = z.infer<typeof ToolActionSchema>;
28
+ interface AssistantMessagesProps {
29
+ messages: UIMessage[];
30
+ sendMessage: (message: {
31
+ text: string;
32
+ }) => void;
33
+ addToolApprovalResponse: (response: {
34
+ id: string;
35
+ approved: boolean;
36
+ }) => void;
37
+ getActionDescription?: (action: ToolAction) => string;
38
+ }
39
+ declare function AssistantMessages({
40
+ messages,
41
+ sendMessage,
42
+ addToolApprovalResponse,
43
+ getActionDescription
44
+ }: AssistantMessagesProps): react_jsx_runtime0.JSX.Element;
45
+ //#endregion
46
+ //#region components/ui/button.d.ts
47
+ declare const buttonVariants: (props?: ({
48
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
49
+ size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
50
+ } & class_variance_authority_types0.ClassProp) | undefined) => string;
51
+ declare function Button({
52
+ className,
53
+ variant,
54
+ size,
55
+ asChild,
56
+ ...props
57
+ }: React$2.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
58
+ asChild?: boolean;
59
+ }): react_jsx_runtime0.JSX.Element;
60
+ //#endregion
61
+ //#region components/ui/chat.d.ts
62
+ interface ChatMessageListProps extends React$2.ComponentProps<"div"> {
63
+ children: React$2.ReactNode;
64
+ }
65
+ declare function ChatMessageList({
66
+ children,
67
+ className,
68
+ ...props
69
+ }: ChatMessageListProps): react_jsx_runtime0.JSX.Element;
70
+ interface ChatLoadingProps extends React$2.ComponentProps<"div"> {
71
+ text?: string;
72
+ }
73
+ declare function ChatLoading({
74
+ text,
75
+ className,
76
+ ...props
77
+ }: ChatLoadingProps): react_jsx_runtime0.JSX.Element;
78
+ interface ChatEmptyProps extends React$2.ComponentProps<"div"> {
79
+ title?: string;
80
+ description?: string;
81
+ }
82
+ declare function ChatEmpty({
83
+ title,
84
+ description,
85
+ className,
86
+ ...props
87
+ }: ChatEmptyProps): react_jsx_runtime0.JSX.Element;
88
+ //#endregion
89
+ //#region components/ui/collapsible.d.ts
90
+ declare function Collapsible({
91
+ ...props
92
+ }: React.ComponentProps<typeof CollapsiblePrimitive.Root>): react_jsx_runtime0.JSX.Element;
93
+ declare function CollapsibleTrigger({
94
+ ...props
95
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>): react_jsx_runtime0.JSX.Element;
96
+ declare function CollapsibleContent({
97
+ ...props
98
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>): react_jsx_runtime0.JSX.Element;
99
+ //#endregion
100
+ //#region components/ui/dialog.d.ts
101
+ declare function Dialog({
102
+ ...props
103
+ }: React$2.ComponentProps<typeof Dialog$1.Root>): react_jsx_runtime0.JSX.Element;
104
+ declare function DialogTrigger({
105
+ ...props
106
+ }: React$2.ComponentProps<typeof Dialog$1.Trigger>): react_jsx_runtime0.JSX.Element;
107
+ declare function DialogPortal({
108
+ ...props
109
+ }: React$2.ComponentProps<typeof Dialog$1.Portal>): react_jsx_runtime0.JSX.Element;
110
+ declare function DialogClose({
111
+ ...props
112
+ }: React$2.ComponentProps<typeof Dialog$1.Close>): react_jsx_runtime0.JSX.Element;
113
+ declare function DialogOverlay({
114
+ className,
115
+ ...props
116
+ }: React$2.ComponentProps<typeof Dialog$1.Overlay>): react_jsx_runtime0.JSX.Element;
117
+ declare function DialogContent({
118
+ className,
119
+ children,
120
+ showCloseButton,
121
+ ...props
122
+ }: React$2.ComponentProps<typeof Dialog$1.Content> & {
123
+ showCloseButton?: boolean;
124
+ }): react_jsx_runtime0.JSX.Element;
125
+ declare function DialogHeader({
126
+ className,
127
+ ...props
128
+ }: React$2.ComponentProps<"div">): react_jsx_runtime0.JSX.Element;
129
+ declare function DialogFooter({
130
+ className,
131
+ showCloseButton,
132
+ children,
133
+ ...props
134
+ }: React$2.ComponentProps<"div"> & {
135
+ showCloseButton?: boolean;
136
+ }): react_jsx_runtime0.JSX.Element;
137
+ declare function DialogTitle({
138
+ className,
139
+ ...props
140
+ }: React$2.ComponentProps<typeof Dialog$1.Title>): react_jsx_runtime0.JSX.Element;
141
+ declare function DialogDescription({
142
+ className,
143
+ ...props
144
+ }: React$2.ComponentProps<typeof Dialog$1.Description>): react_jsx_runtime0.JSX.Element;
145
+ //#endregion
146
+ //#region components/ui/command.d.ts
147
+ declare function Command({
148
+ className,
149
+ ...props
150
+ }: React$2.ComponentProps<typeof Command$1>): react_jsx_runtime0.JSX.Element;
151
+ declare function CommandDialogContent({
152
+ className,
153
+ children,
154
+ ...props
155
+ }: React$2.ComponentProps<typeof Dialog$1.Content>): react_jsx_runtime0.JSX.Element;
156
+ declare function CommandGroup({
157
+ className,
158
+ ...props
159
+ }: React$2.ComponentProps<typeof Command$1.Group>): react_jsx_runtime0.JSX.Element;
160
+ declare function CommandSeparator({
161
+ className,
162
+ ...props
163
+ }: React$2.ComponentProps<typeof Command$1.Separator>): react_jsx_runtime0.JSX.Element;
164
+ declare function CommandItem({
165
+ className,
166
+ style,
167
+ ...props
168
+ }: React$2.ComponentProps<typeof Command$1.Item>): react_jsx_runtime0.JSX.Element;
169
+ declare function CommandShortcut({
170
+ className,
171
+ ...props
172
+ }: React$2.ComponentProps<"span">): react_jsx_runtime0.JSX.Element;
173
+ //#endregion
174
+ //#region hooks/use-chat-history.d.ts
175
+ interface ChatConversation {
176
+ id: string;
177
+ title: string;
178
+ messages: UIMessage[];
179
+ createdAt: number;
180
+ updatedAt: number;
181
+ }
182
+ interface UseChatHistoryOptions {
183
+ storageKey?: string;
184
+ maxConversations?: number;
185
+ messages: UIMessage[];
186
+ setMessages?: (messages: UIMessage[] | ((msgs: UIMessage[]) => UIMessage[])) => void;
187
+ }
188
+ interface UseChatHistoryReturn {
189
+ conversations: ChatConversation[];
190
+ currentConversationId: string | null;
191
+ startNewChat: () => void;
192
+ loadConversation: (id: string) => void;
193
+ saveCurrentConversation: () => void;
194
+ }
195
+ declare function useChatHistory({
196
+ storageKey,
197
+ maxConversations,
198
+ messages,
199
+ setMessages
200
+ }: UseChatHistoryOptions): UseChatHistoryReturn;
201
+ //#endregion
202
+ //#region context/command-menu-context.d.ts
203
+ type CommandMenuMode = "command" | "chat";
204
+ type CommandMenuStatus = "idle" | "submitted" | "streaming" | "error";
205
+ interface ExternalChat {
206
+ messages: UIMessage[];
207
+ setMessages?: (messages: UIMessage[] | ((msgs: UIMessage[]) => UIMessage[])) => void;
208
+ sendMessage: (message: {
209
+ text: string;
210
+ }) => void;
211
+ status: "ready" | "submitted" | "streaming" | "error";
212
+ error: Error | null;
213
+ addToolApprovalResponse?: (response: {
214
+ id: string;
215
+ approved: boolean;
216
+ }) => void;
217
+ agenticActions?: CommandAction[];
218
+ }
219
+ interface CommandMenuContextValue {
220
+ mode: CommandMenuMode;
221
+ setMode: (mode: CommandMenuMode) => void;
222
+ inputValue: string;
223
+ setInputValue: (value: string) => void;
224
+ chatEndpoint: string | null;
225
+ status: CommandMenuStatus;
226
+ error: Error | null;
227
+ switchToChat: (initialQuery?: string) => void;
228
+ switchToCommand: () => void;
229
+ messages: UIMessage[];
230
+ sendMessage: (content: string) => Promise<void>;
231
+ isLoading: boolean;
232
+ isEnabled: boolean;
233
+ addToolApprovalResponse?: (response: {
234
+ id: string;
235
+ approved: boolean;
236
+ }) => void;
237
+ agenticActions?: CommandAction[];
238
+ requestClose?: () => void;
239
+ conversations: ChatConversation[];
240
+ currentConversationId: string | null;
241
+ startNewChat: () => void;
242
+ loadConversation: (id: string) => void;
243
+ }
244
+ declare const CommandMenuContext: React$2.Context<CommandMenuContextValue | null>;
245
+ interface CommandMenuProviderProps {
246
+ children: React$2.ReactNode;
247
+ chatEndpoint?: string | null;
248
+ chat?: ExternalChat;
249
+ onModeChange?: (mode: CommandMenuMode) => void;
250
+ onOpenChange?: (open: boolean) => void;
251
+ historyStorageKey?: string;
252
+ maxConversations?: number;
253
+ }
254
+ declare function CommandMenuProvider({
255
+ children,
256
+ chatEndpoint,
257
+ chat: externalChat,
258
+ onModeChange,
259
+ onOpenChange,
260
+ historyStorageKey,
261
+ maxConversations
262
+ }: CommandMenuProviderProps): react_jsx_runtime0.JSX.Element;
263
+ declare function useCommandMenuContext(): CommandMenuContextValue;
264
+ //#endregion
265
+ //#region components/ui/command-menu.d.ts
266
+ type CommandMenuCorners = "none" | "sm" | "md" | "lg" | "xl";
267
+ interface CommandMenuProps extends Omit<React$2.ComponentProps<typeof Dialog>, "children"> {
268
+ title?: string;
269
+ description?: string;
270
+ className?: string;
271
+ corners?: CommandMenuCorners;
272
+ borderColor?: string;
273
+ chatEndpoint?: string | null;
274
+ chat?: ExternalChat;
275
+ askAILabel?: string;
276
+ onModeChange?: (mode: CommandMenuMode) => void;
277
+ historyStorageKey?: string;
278
+ maxConversations?: number;
279
+ /** Declarative command definitions. Mutually exclusive with children. */
280
+ commands?: CommandDefinition[];
281
+ /** Placeholder for the command input when using `commands` prop. */
282
+ commandsPlaceholder?: string;
283
+ /** Label for the "Ask AI" trigger when using `commands` prop. */
284
+ commandsAskAILabel?: string;
285
+ children?: React$2.ReactNode | ((context: {
286
+ mode: CommandMenuMode;
287
+ messages: UIMessage[];
288
+ status: "idle" | "submitted" | "streaming" | "error";
289
+ isEnabled: boolean;
290
+ }) => React$2.ReactNode);
291
+ }
292
+ declare function CommandContent({
293
+ className,
294
+ children,
295
+ corners,
296
+ borderColor,
297
+ ...props
298
+ }: React$2.ComponentProps<typeof Dialog$1.Content> & {
299
+ corners?: CommandMenuCorners;
300
+ borderColor?: string;
301
+ }): react_jsx_runtime0.JSX.Element;
302
+ declare function CommandMenu({
303
+ chatEndpoint,
304
+ chat,
305
+ onModeChange,
306
+ onOpenChange,
307
+ historyStorageKey,
308
+ maxConversations,
309
+ commands,
310
+ commandsPlaceholder,
311
+ commandsAskAILabel,
312
+ ...props
313
+ }: CommandMenuProps): react_jsx_runtime0.JSX.Element;
314
+ interface CommandInputProps extends Omit<React$2.ComponentProps<typeof Command$1.Input>, "value" | "onValueChange"> {
315
+ showSendButton?: boolean;
316
+ }
317
+ declare function CommandInput({
318
+ className,
319
+ showSendButton,
320
+ ...props
321
+ }: CommandInputProps): react_jsx_runtime0.JSX.Element;
322
+ interface CommandEmptyProps extends React$2.ComponentProps<typeof Command$1.Item> {
323
+ label?: string;
324
+ description?: string;
325
+ }
326
+ declare function CommandEmpty({
327
+ label,
328
+ className,
329
+ ...props
330
+ }: CommandEmptyProps): react_jsx_runtime0.JSX.Element;
331
+ declare namespace CommandEmpty {
332
+ var displayName: string;
333
+ }
334
+ /**
335
+ * Describes a single option/parameter for an action.
336
+ * Compatible with ActionOption from modifywithai.
337
+ */
338
+ interface CommandActionOption {
339
+ type: string;
340
+ description?: string;
341
+ required?: boolean;
342
+ }
343
+ /**
344
+ * Minimal action interface compatible with ActionDefinition from modifywithai.
345
+ * Only `name` and `execute` are needed — all other ActionDefinition fields are ignored.
346
+ */
347
+ interface CommandAction {
348
+ name: string;
349
+ label?: string;
350
+ options?: Record<string, CommandActionOption>;
351
+ execute?: (options: Record<string, unknown>) => void;
352
+ }
353
+ /**
354
+ * Declarative command definition for the `commands` prop.
355
+ * Named CommandDefinition to avoid collision with cmdk's Command component.
356
+ */
357
+ interface CommandDefinition {
358
+ /** Unique key used as cmdk value */
359
+ name: string;
360
+ /** Display text (falls back to name) */
361
+ label?: string;
362
+ /** Group heading — commands with the same string appear in the same group */
363
+ group?: string;
364
+ /** Icon rendered before the label */
365
+ icon?: React$2.ReactNode;
366
+ /** Display-only shortcut hint (right-aligned) */
367
+ shortcut?: string;
368
+ /** Extra cmdk search terms */
369
+ keywords?: string[];
370
+ /** Grayed out, not selectable */
371
+ disabled?: boolean;
372
+ /** Called when the command is selected */
373
+ onSelect?: () => void;
374
+ }
375
+ interface CommandListProps extends React$2.ComponentProps<typeof Command$1.List> {
376
+ /** Actions to render as CommandItems. Compatible with ActionDefinition[]. */
377
+ actions?: CommandAction[];
378
+ /** Heading for the auto-rendered actions group */
379
+ actionsHeading?: string;
380
+ }
381
+ declare function CommandList({
382
+ className,
383
+ children,
384
+ actions,
385
+ actionsHeading,
386
+ ...props
387
+ }: CommandListProps): react_jsx_runtime0.JSX.Element;
388
+ //#endregion
389
+ //#region components/ui/confirmation.d.ts
390
+ type ToolUIPartApproval = {
391
+ id: string;
392
+ approved?: never;
393
+ reason?: never;
394
+ } | {
395
+ id: string;
396
+ approved: boolean;
397
+ reason?: string;
398
+ } | undefined;
399
+ type ConfirmationProps = Omit<ComponentProps<"div">, "className"> & {
400
+ approval?: ToolUIPartApproval;
401
+ state: ToolUIPart["state"];
402
+ };
403
+ declare function Confirmation({
404
+ approval,
405
+ state,
406
+ style,
407
+ ...props
408
+ }: ConfirmationProps & {
409
+ style?: CSSProperties;
410
+ }): react_jsx_runtime0.JSX.Element | null;
411
+ type ConfirmationTitleProps = Omit<ComponentProps<"p">, "className">;
412
+ declare function ConfirmationTitle(props: ConfirmationTitleProps): react_jsx_runtime0.JSX.Element;
413
+ type ConfirmationRequestProps = {
414
+ children?: ReactNode;
415
+ };
416
+ declare function ConfirmationRequest({
417
+ children
418
+ }: ConfirmationRequestProps): react_jsx_runtime0.JSX.Element | null;
419
+ type ConfirmationAcceptedProps = {
420
+ children?: ReactNode;
421
+ };
422
+ declare function ConfirmationAccepted({
423
+ children
424
+ }: ConfirmationAcceptedProps): react_jsx_runtime0.JSX.Element | null;
425
+ type ConfirmationRejectedProps = {
426
+ children?: ReactNode;
427
+ };
428
+ declare function ConfirmationRejected({
429
+ children
430
+ }: ConfirmationRejectedProps): react_jsx_runtime0.JSX.Element | null;
431
+ type ConfirmationActionsProps = Omit<ComponentProps<"div">, "className">;
432
+ declare function ConfirmationActions(props: ConfirmationActionsProps): react_jsx_runtime0.JSX.Element | null;
433
+ type ConfirmationActionProps = Omit<ComponentProps<"button">, "className"> & {
434
+ variant?: "default" | "outline" | "destructive";
435
+ };
436
+ declare function ConfirmationAction({
437
+ variant,
438
+ style,
439
+ ...props
440
+ }: ConfirmationActionProps & {
441
+ style?: CSSProperties;
442
+ }): react_jsx_runtime0.JSX.Element;
443
+ //#endregion
444
+ //#region components/ui/form-components.d.ts
445
+ declare const defaultFormRegistry: ComponentRegistry;
446
+ //#endregion
447
+ //#region components/ui/form-renderer.d.ts
448
+ interface AssistantFormRendererProps {
449
+ ui: UITree;
450
+ context?: Record<string, unknown>;
451
+ onSubmit: (formId: string, data: Record<string, string>) => void;
452
+ onCancel?: (formId: string) => void;
453
+ registry?: ComponentRegistry;
454
+ }
455
+ declare function AssistantFormRenderer({
456
+ ui,
457
+ context,
458
+ onSubmit,
459
+ onCancel,
460
+ registry
461
+ }: AssistantFormRendererProps): react_jsx_runtime0.JSX.Element;
462
+ //#endregion
463
+ //#region components/ui/message.d.ts
464
+ type MessageProps = Omit<HTMLAttributes<HTMLDivElement>, "className"> & {
465
+ from: UIMessage["role"];
466
+ };
467
+ declare function Message({
468
+ from,
469
+ ...props
470
+ }: MessageProps): react_jsx_runtime0.JSX.Element;
471
+ type MessageContentProps = Omit<HTMLAttributes<HTMLDivElement>, "className">;
472
+ declare function MessageContent({
473
+ children,
474
+ style,
475
+ ...props
476
+ }: MessageContentProps & {
477
+ style?: CSSProperties;
478
+ }): react_jsx_runtime0.JSX.Element;
479
+ type MessageResponseProps = Omit<ComponentProps<typeof Streamdown>, "className">;
480
+ declare const MessageResponse: React$1.MemoExoticComponent<(props: MessageResponseProps) => React$1.JSX.Element>;
481
+ //#endregion
482
+ //#region components/ui/task.d.ts
483
+ type TaskItemFileProps = Omit<ComponentProps<"div">, "className">;
484
+ declare function TaskItemFile({
485
+ children,
486
+ ...props
487
+ }: TaskItemFileProps): react_jsx_runtime0.JSX.Element;
488
+ type TaskItemProps = Omit<ComponentProps<"div">, "className">;
489
+ declare function TaskItem({
490
+ children,
491
+ ...props
492
+ }: TaskItemProps): react_jsx_runtime0.JSX.Element;
493
+ type TaskProps = Omit<ComponentProps<typeof Collapsible>, "className">;
494
+ declare function Task({
495
+ defaultOpen,
496
+ ...props
497
+ }: TaskProps): react_jsx_runtime0.JSX.Element;
498
+ type TaskTriggerProps = Omit<ComponentProps<typeof CollapsibleTrigger>, "className"> & {
499
+ title: string;
500
+ icon?: ReactNode;
501
+ };
502
+ declare function TaskTrigger({
503
+ children,
504
+ title,
505
+ icon,
506
+ ...props
507
+ }: TaskTriggerProps): react_jsx_runtime0.JSX.Element;
508
+ type TaskContentProps = Omit<ComponentProps<typeof CollapsibleContent>, "className">;
509
+ declare function TaskContent({
510
+ children,
511
+ ...props
512
+ }: TaskContentProps): react_jsx_runtime0.JSX.Element;
513
+ //#endregion
514
+ export { AssistantFormRenderer, type AssistantFormRendererProps, AssistantMessages, type AssistantMessagesProps, Button, type ChatConversation, ChatEmpty, type ChatEmptyProps, ChatLoading, type ChatLoadingProps, ChatMessageList, type ChatMessageListProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, type CommandAction, type CommandActionOption, CommandContent, type CommandDefinition, CommandMenu as CommandDialog, CommandMenu, CommandDialogContent, CommandEmpty, type CommandEmptyProps, CommandGroup, CommandInput, type CommandInputProps, CommandItem, CommandList, type CommandListProps, CommandMenuContext, type CommandMenuContextValue, type CommandMenuCorners, type CommandMenuMode, type CommandMenuProps, CommandMenuProvider, type CommandMenuProviderProps, type CommandMenuStatus, CommandSeparator, CommandShortcut, Confirmation, ConfirmationAccepted, type ConfirmationAcceptedProps, ConfirmationAction, type ConfirmationActionProps, ConfirmationActions, type ConfirmationActionsProps, type ConfirmationProps, ConfirmationRejected, type ConfirmationRejectedProps, ConfirmationRequest, type ConfirmationRequestProps, ConfirmationTitle, type ConfirmationTitleProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type ExternalChat, Message, MessageContent, type MessageContentProps, type MessageProps, MessageResponse, type MessageResponseProps, Task, TaskContent, type TaskContentProps, TaskItem, TaskItemFile, type TaskItemFileProps, type TaskItemProps, type TaskProps, TaskTrigger, type TaskTriggerProps, type ToolUIPartApproval, type UseChatHistoryOptions, type UseChatHistoryReturn, buttonVariants, cn, defaultFormRegistry, useChatHistory, useCommandMenuContext };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{cn as e}from"./lib/utils.js";import{JSONUIProvider as t,Renderer as n,flatToTree as r}from"@json-render/react";import*as i from"react";import{createContext as a,memo as o,useCallback as s,useContext as c,useEffect as l,useMemo as u,useRef as d,useState as f}from"react";import{z as p}from"zod";import{Fragment as m,jsx as h,jsxs as g}from"react/jsx-runtime";import{Streamdown as _}from"streamdown";import{ChevronDownIcon as v,CornerDownLeftIcon as y,LoaderIcon as b,MessageCircleIcon as x,SearchIcon as S,SparklesIcon as C,XIcon as w}from"lucide-react";import*as T from"@radix-ui/react-collapsible";import{cva as E}from"class-variance-authority";import{Dialog as D,Slot as O}from"radix-ui";import{Command as k,defaultFilter as ee,useCommandState as A}from"cmdk";import{useChat as te}from"@ai-sdk/react";import{DefaultChatTransport as ne}from"ai";import{BrowserClient as j,Scope as M,dedupeIntegration as N,defaultStackParser as P,linkedErrorsIntegration as F,makeFetchTransport as I}from"@sentry/browser";const re=a(null);function L(){let e=c(re);if(!e)throw Error(`Confirmation components must be used within Confirmation`);return e}function ie({approval:t,state:n,style:r,...i}){return!t||n===`input-streaming`||n===`input-available`?null:h(re.Provider,{value:{approval:t,state:n},children:h(`div`,{"data-slot":`confirmation`,"data-state":n,"data-approved":t?.approved,role:`alertdialog`,"aria-labelledby":`confirmation-title`,style:{borderRadius:`var(--cmdk-radius, 0.5rem)`,...r},className:e(`flex flex-col gap-2 border p-4`,`data-[state=approval-requested]:border-amber-500/50 data-[state=approval-requested]:bg-amber-50/50 dark:data-[state=approval-requested]:bg-amber-950/20`,`data-[approved=true]:border-green-500/50 data-[approved=true]:bg-green-50/50 dark:data-[approved=true]:bg-green-950/20`,`data-[approved=false]:border-red-500/50 data-[approved=false]:bg-red-50/50 dark:data-[approved=false]:bg-red-950/20`),...i})})}function ae(e){return h(`p`,{id:`confirmation-title`,"data-slot":`confirmation-title`,className:`text-sm font-medium`,...e})}function R({children:e}){let{state:t}=L();return t===`approval-requested`?h(`div`,{"data-slot":`confirmation-request`,children:e}):null}function oe({children:e}){let{approval:t,state:n}=L();return!t?.approved||n!==`approval-responded`&&n!==`output-denied`&&n!==`output-available`?null:h(`div`,{"data-slot":`confirmation-accepted`,children:e})}function se({children:e}){let{approval:t,state:n}=L();return t?.approved!==!1||n!==`approval-responded`&&n!==`output-denied`&&n!==`output-available`?null:h(`div`,{"data-slot":`confirmation-rejected`,children:e})}function ce(e){let{state:t}=L();return t===`approval-requested`?h(`div`,{"data-slot":`confirmation-actions`,className:`flex items-center justify-end gap-2 self-end`,...e}):null}function z({variant:t=`default`,style:n,...r}){return h(`button`,{"data-slot":`confirmation-action`,"data-variant":t,type:`button`,className:e(`inline-flex h-8 items-center justify-center gap-2 whitespace-nowrap px-3 text-sm font-medium transition-colors`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`,`disabled:pointer-events-none disabled:opacity-50`,t===`default`&&`bg-primary text-primary-foreground shadow hover:bg-primary/90`,t===`outline`&&`border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground`,t===`destructive`&&`bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90`),style:{borderRadius:`var(--cmdk-radius, 0.375rem)`,...n},...r})}function B(e){e.stopPropagation()}function le({element:t,children:n,onAction:r}){let{id:i=`form`,title:a,submitLabel:o=`Submit`}=t.props??{},s=e=>{e.preventDefault();let t=new FormData(e.currentTarget),n={};t.forEach((e,t)=>{typeof e==`string`&&(n[t]=e)}),r?.({name:`submit`,params:{formId:i,data:n}})};return g(`div`,{"data-slot":`form-card`,className:e(`w-full rounded-lg border bg-card text-card-foreground shadow-sm`),children:[a&&h(`div`,{className:`flex flex-col space-y-1.5 p-4 pb-3`,children:h(`h3`,{className:`text-base font-semibold leading-none tracking-tight`,children:a})}),h(`div`,{className:e(`p-4`,a?``:`pt-4`),children:g(`form`,{onSubmit:s,className:`space-y-4`,children:[n,g(`div`,{className:`flex justify-end gap-2 pt-2`,children:[h(`button`,{type:`button`,className:e(`inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium shadow-sm transition-colors`,`hover:bg-accent hover:text-accent-foreground`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`,`disabled:pointer-events-none disabled:opacity-50`),onClick:()=>r?.({name:`cancel`,params:{formId:i}}),children:`Cancel`}),h(`button`,{type:`submit`,className:e(`inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow transition-colors`,`hover:bg-primary/90`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`,`disabled:pointer-events-none disabled:opacity-50`),children:o})]})]})})]})}function ue({element:t}){let{name:n=`field`,label:r=`Field`,placeholder:i,required:a,defaultValue:o}=t.props??{};return g(`div`,{className:`space-y-1.5`,children:[g(`label`,{htmlFor:n,className:`text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70`,children:[r,a&&h(`span`,{className:`ml-1 text-destructive`,children:`*`})]}),h(`input`,{id:n,name:n,type:`text`,placeholder:i,required:a,defaultValue:o,autoComplete:`off`,onKeyDown:B,onKeyUp:B,className:e(`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors`,`placeholder:text-muted-foreground`,`focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`,`disabled:cursor-not-allowed disabled:opacity-50`)})]})}function de({element:t}){let{name:n=`field`,label:r=`Field`,placeholder:i,required:a,defaultValue:o,rows:s=3}=t.props??{};return g(`div`,{className:`space-y-1.5`,children:[g(`label`,{htmlFor:n,className:`text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70`,children:[r,a&&h(`span`,{className:`ml-1 text-destructive`,children:`*`})]}),h(`textarea`,{id:n,name:n,placeholder:i,required:a,defaultValue:o,rows:s,onKeyDown:B,onKeyUp:B,className:e(`flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors`,`placeholder:text-muted-foreground`,`focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`,`disabled:cursor-not-allowed disabled:opacity-50`)})]})}function fe({element:t}){let{name:n=`date`,label:r=`Date`,required:i,defaultValue:a,min:o,max:s}=t.props??{};return g(`div`,{className:`space-y-1.5`,children:[g(`label`,{htmlFor:n,className:`text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70`,children:[r,i&&h(`span`,{className:`ml-1 text-destructive`,children:`*`})]}),h(`input`,{type:`date`,id:n,name:n,required:i,defaultValue:a,min:o,max:s,onKeyDown:B,onKeyUp:B,className:e(`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors`,`focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`,`disabled:cursor-not-allowed disabled:opacity-50`)})]})}const V={Form:le,TextField:ue,TextArea:de,DateField:fe},pe=p.object({formId:p.string(),data:p.record(p.string(),p.string())}),me=p.object({formId:p.string()});function H({ui:e,context:r,onSubmit:i,onCancel:a,registry:o=V}){let c=s(e=>{let t=pe.safeParse(e);t.success?i(t.data.formId,t.data.data):console.warn(`Form submit: Invalid params`,t.error.flatten())},[i]),l=s(e=>{let t=me.safeParse(e);t.success?a?.(t.data.formId):console.warn(`Form cancel: Invalid params`,t.error.flatten())},[a]);return h(t,{registry:o,initialData:r,actionHandlers:u(()=>({submit:c,cancel:l}),[c,l]),children:h(n,{tree:e,registry:o})})}function he({from:t,...n}){return h(`div`,{"data-slot":`message`,"data-from":t,className:e(`group flex w-full max-w-[95%] flex-col gap-2`,t===`user`?`is-user ml-auto justify-end`:`is-assistant`),...n})}function ge({children:t,style:n,...r}){return h(`div`,{"data-slot":`message-content`,className:e(`flex w-fit min-w-0 max-w-full flex-col gap-2 overflow-hidden text-sm`,`group-[.is-user]:ml-auto group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground`,`group-[.is-assistant]:text-foreground`),style:{borderRadius:`var(--cmdk-radius, 0.5rem)`,...n},...r,children:t})}const _e=o(function(e){return h(_,{"data-slot":`message-response`,className:`size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0`,...e})},(e,t)=>e.children===t.children);function ve({...e}){return h(T.Root,{"data-slot":`collapsible`,...e})}function ye({...e}){return h(T.CollapsibleTrigger,{"data-slot":`collapsible-trigger`,...e})}function be({...e}){return h(T.CollapsibleContent,{"data-slot":`collapsible-content`,...e})}function xe({children:e,...t}){return h(`div`,{"data-slot":`task-item-file`,className:`inline-flex items-center gap-1 rounded-md border bg-secondary px-1.5 py-0.5 text-xs text-foreground`,...t,children:e})}function Se({children:e,...t}){return h(`div`,{"data-slot":`task-item`,className:`text-sm text-muted-foreground`,...t,children:e})}function Ce({defaultOpen:e=!0,...t}){return h(ve,{"data-slot":`task`,defaultOpen:e,...t})}function we({children:e,title:t,icon:n,...r}){return h(ye,{asChild:!0,className:`group`,...r,children:e??g(`div`,{className:`flex w-full cursor-pointer items-center gap-2 text-sm text-muted-foreground transition-colors hover:text-foreground`,children:[n??h(S,{className:`size-4`}),h(`p`,{className:`text-sm`,children:t}),h(v,{className:`size-4 transition-transform group-data-[state=open]:rotate-180`})]})})}function Te({children:t,...n}){return h(be,{"data-slot":`task-content`,className:e(`text-popover-foreground outline-none`,`data-[state=closed]:animate-out data-[state=open]:animate-in`,`data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0`,`data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2`),...n,children:h(`div`,{className:`mt-4 space-y-2 border-l-2 border-muted pl-4`,children:t})})}const Ee=p.object({name:p.string(),options:p.record(p.string(),p.unknown()).optional()}),De=p.object({actions:p.array(Ee).optional()}),Oe=p.object({id:p.string(),approved:p.boolean().optional()}),ke=p.object({type:p.string(),props:p.record(p.string(),p.unknown()).default({}),children:p.array(p.string()).optional(),parentKey:p.string().nullable().optional()}),Ae=p.object({ui:p.object({elements:p.record(p.string(),ke)}),context:p.record(p.string(),p.unknown()).optional()});function je(e){return e.name}function Me({messages:e,sendMessage:t,addToolApprovalResponse:n,getActionDescription:r=je}){let i=e.filter(e=>e.role===`user`||e.role===`assistant`);return h(m,{children:i.map((e,a)=>{let o=a===i.length-1;return h(he,{from:e.role,children:h(ge,{children:e.parts.map((i,a)=>h(Ne,{part:i,messageId:e.id,partIndex:a,isLastMessage:o,sendMessage:t,addToolApprovalResponse:n,getActionDescription:r},`${e.id}-${a}`))})},e.id)})})}function Ne({part:e,messageId:t,partIndex:n,isLastMessage:r,sendMessage:i,addToolApprovalResponse:a,getActionDescription:o}){if(e.type===`text`)return h(_e,{children:e.text});if(e.type===`tool-performActions`){let r=`input`in e?e.input:void 0,i=De.safeParse(r),s=i.success?i.data.actions??[]:[];if(s.length===0)return null;let c=s.length,l=`state`in e?e.state:void 0,u=`approval`in e?e.approval:void 0,d=Oe.safeParse(u),f=d.success?d.data:void 0;return f&&l?g(ie,{state:l,approval:f,children:[h(ae,{children:c===1?`Confirm action`:`Confirm ${c} actions`}),h(R,{children:h(`ul`,{className:`list-disc list-inside text-sm text-muted-foreground mt-2`,children:s.map((e,r)=>h(`li`,{children:o(e)},`${t}-${n}-${r}`))})}),h(oe,{children:h(`span`,{className:`text-sm text-muted-foreground`,children:c===1?`Action approved`:`${c} actions approved`})}),h(se,{children:h(`span`,{className:`text-sm text-muted-foreground`,children:c===1?`Action cancelled`:`${c} actions cancelled`})}),g(ce,{children:[h(z,{variant:`outline`,onClick:()=>a({id:f.id,approved:!1}),children:`Deny`}),h(z,{onClick:()=>a({id:f.id,approved:!0}),children:`Approve`})]})]}):g(Ce,{defaultOpen:!1,children:[h(we,{title:c===1?`Performing 1 action`:`Performing ${c} actions`}),h(Te,{children:s.map((e,r)=>h(Se,{children:o(e)},`${t}-${n}-${r}`))})]})}return e.type===`tool-renderUI`&&r&&(`state`in e?e.state:void 0)===`output-available`&&`output`in e?h(Pe,{output:e.output,sendMessage:i}):null}function Pe({output:e,sendMessage:t}){let n=i.useMemo(()=>{let t=Ae.safeParse(e);return t.success?{ui:r(Object.entries(t.data.ui.elements).map(([e,t])=>({...t,key:e}))),context:t.data.context}:null},[e]),a=i.useCallback((e,n)=>{t({text:`[Form:${e}] ${JSON.stringify(n)}`})},[t]),o=i.useCallback(e=>{t({text:`[Form:${e}] cancelled`})},[t]);return n?h(H,{ui:n.ui,context:n.context,onSubmit:a,onCancel:o}):null}const Fe=E(`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive`,{variants:{variant:{default:`bg-primary text-primary-foreground hover:bg-primary/90`,destructive:`bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60`,outline:`border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50`,secondary:`bg-secondary text-secondary-foreground hover:bg-secondary/80`,ghost:`hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50`,link:`text-primary underline-offset-4 hover:underline`},size:{default:`h-9 px-4 py-2 has-[>svg]:px-3`,xs:`h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3`,sm:`h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5`,lg:`h-10 rounded-md px-6 has-[>svg]:px-4`,icon:`size-9`,"icon-xs":`size-6 rounded-md [&_svg:not([class*='size-'])]:size-3`,"icon-sm":`size-8`,"icon-lg":`size-10`}},defaultVariants:{variant:`default`,size:`default`}});function Ie({className:t,variant:n=`default`,size:r=`default`,asChild:i=!1,...a}){return h(i?O.Root:`button`,{"data-slot":`button`,"data-variant":n,"data-size":r,className:e(Fe({variant:n,size:r,className:t})),...a})}function Le({children:t,className:n,...r}){let a=i.useRef(null);return i.useEffect(()=>{a.current&&(a.current.scrollTop=a.current.scrollHeight)},[t]),h(`div`,{ref:a,"data-slot":`chat-message-list`,className:e(`flex flex-col overflow-y-auto scroll-smooth`,n),...r,children:t})}function Re({text:t=`AI is thinking...`,className:n,...r}){return g(`div`,{"data-slot":`chat-loading`,className:e(`flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground`,n),...r,children:[h(b,{className:`size-4 animate-spin`}),h(`span`,{children:t})]})}function ze({title:t=`Start a conversation`,description:n=`Ask a question or describe what you need help with.`,className:r,...i}){return h(`div`,{"data-slot":`chat-empty`,className:e(`flex flex-col items-center justify-center gap-2 py-8 text-center`,r),...i,children:g(`div`,{className:`space-y-1`,children:[h(`h3`,{className:`text-sm font-medium`,children:t}),h(`p`,{className:`text-xs text-muted-foreground`,children:n})]})})}function Be({...e}){return h(D.Root,{"data-slot":`dialog`,...e})}function Ve({...e}){return h(D.Trigger,{"data-slot":`dialog-trigger`,...e})}function U({...e}){return h(D.Portal,{"data-slot":`dialog-portal`,...e})}function He({...e}){return h(D.Close,{"data-slot":`dialog-close`,...e})}function Ue({className:t,...n}){return h(D.Overlay,{"data-slot":`dialog-overlay`,className:e(`data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50`,t),...n})}function We({className:t,children:n,showCloseButton:r=!0,...i}){return g(U,{"data-slot":`dialog-portal`,children:[h(Ue,{}),g(D.Content,{"data-slot":`dialog-content`,className:e(`bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg`,t),...i,children:[n,r&&g(D.Close,{"data-slot":`dialog-close`,className:`ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,children:[h(w,{}),h(`span`,{className:`sr-only`,children:`Close`})]})]})]})}function Ge({className:t,...n}){return h(`div`,{"data-slot":`dialog-header`,className:e(`flex flex-col gap-2 text-center sm:text-left`,t),...n})}function Ke({className:t,showCloseButton:n=!1,children:r,...i}){return g(`div`,{"data-slot":`dialog-footer`,className:e(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,t),...i,children:[r,n&&h(D.Close,{asChild:!0,children:h(Ie,{variant:`outline`,children:`Close`})})]})}function qe({className:t,...n}){return h(D.Title,{"data-slot":`dialog-title`,className:e(`text-lg leading-none font-semibold`,t),...n})}function Je({className:t,...n}){return h(D.Description,{"data-slot":`dialog-description`,className:e(`text-muted-foreground text-sm`,t),...n})}function Ye({className:t,...n}){return h(k,{"data-slot":`command`,className:e(`bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md`,t),...n})}function Xe({className:t,children:n,...r}){return h(U,{"data-slot":`dialog-portal`,children:h(D.Content,{"data-slot":`dialog-content`,className:e(`bg-background fixed top-1/3 left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] overflow-hidden rounded-xl border-none p-2 shadow-2xl ring-4 ring-neutral-200/80 duration-200 outline-none sm:max-w-lg dark:bg-neutral-900 dark:ring-neutral-800`,t),...r,children:n})})}function Ze({className:t,...n}){return h(k.Empty,{"data-slot":`command-empty`,className:e(`text-muted-foreground py-6 text-center text-sm`,t),...n})}function W({className:t,...n}){return h(k.Group,{"data-slot":`command-group`,className:e(`text-foreground !p-0 [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden [&_[cmdk-group-heading]]:scroll-mt-16 [&_[cmdk-group-heading]]:pt-0! [&_[cmdk-group-heading]]:!p-3 [&_[cmdk-group-heading]]:!pb-1 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium`,t),...n})}function Qe({className:t,...n}){return h(k.Separator,{"data-slot":`command-separator`,className:e(`bg-border -mx-1 h-px`,t),...n})}function G({className:t,style:n,...r}){return h(k.Item,{"data-slot":`command-item`,className:e(`data-[selected=true]:border-input data-[selected=true]:bg-input/50 [&_svg:not([class*='text-'])]:text-muted-foreground relative flex h-9 cursor-default items-center gap-2 border border-transparent px-3 text-sm font-medium outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,t),style:{borderRadius:`var(--cmdk-radius, 0.375rem)`,...n},...r})}function $e({className:t,...n}){return h(`span`,{"data-slot":`command-shortcut`,className:e(`text-muted-foreground ml-auto text-xs tracking-widest`,t),...n})}function et(){return crypto.randomUUID()}function tt(e){let t=e.find(e=>e.role===`user`);if(!t)return`New conversation`;let n=t.parts?.filter(e=>e.type===`text`).map(e=>e.text).join(` `)||`New conversation`;return n.length>50?n.slice(0,50)+`...`:n}function nt(e){return typeof e!=`object`||!e||!(`version`in e)||e.version!==1||!(`conversations`in e)||!Array.isArray(e.conversations)?null:e}function rt({storageKey:e=`cmdk-chat-history`,maxConversations:t=50,messages:n,setMessages:r}){let[i,a]=f([]),[o,c]=f(null),[p,m]=f(!1),h=d(n);h.current=n;let g=d(r);g.current=r;let _=d(i);_.current=i;let v=d(o);v.current=o,l(()=>{try{let t=localStorage.getItem(e);if(t){let n=nt(JSON.parse(t));n?a(n.conversations):(console.warn(`Chat history: stored data failed validation. Discarding.`),localStorage.removeItem(e))}}catch(e){console.error(`Failed to load chat history:`,e)}finally{m(!0)}},[e]),l(()=>{if(p)try{let t={version:1,conversations:i};localStorage.setItem(e,JSON.stringify(t))}catch(e){console.error(`Failed to save chat history:`,e)}},[i,e,p]);let y=s(()=>{let e=h.current,n=v.current;!n||e.length===0||a(r=>{let i=Date.now();return r.find(e=>e.id===n)?r.map(t=>t.id===n?{...t,messages:e,title:tt(e),updatedAt:i}:t):[{id:n,title:tt(e),messages:e,createdAt:i,updatedAt:i},...r].slice(0,t)})},[t]),b=s(()=>{v.current&&h.current.length>0&&y(),g.current?.([]),c(et())},[y]),x=s(e=>{v.current&&h.current.length>0&&y();let t=_.current.find(t=>t.id===e);t&&(g.current?.(t.messages),c(e))},[y]);return u(()=>({conversations:i,currentConversationId:o,startNewChat:b,loadConversation:x,saveCurrentConversation:y}),[i,o,b,x,y])}let K=null,q=null;function it(){try{return typeof process<`u`&&process.env?.BETTER_CMDK_TELEMETRY_DISABLED===`1`}catch{return!1}}function at(e,t){return delete e.user,delete e.server_name,e.request&&(delete e.request.cookies,delete e.request.headers,delete e.request.env,delete e.request.data),e.breadcrumbs=[],e}function ot(){typeof window>`u`||K===null&&(it()||(K=new j({dsn:`https://7d9fc7e14e8769805297d46569e33c05@o4510706172755968.ingest.us.sentry.io/4510846832017408`,transport:I,stackParser:P,integrations:[N(),F()],beforeSend:at,sendDefaultPii:!1,tracesSampleRate:1}),q=new M,q.setClient(K),K.init()))}function J(e,t){!q||!K||(t?q.captureException(e,{captureContext:e=>(e.setExtras(t),e)}):q.captureException(e))}function st(e){try{let t=new Uint8Array(e/2);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,`0`)).join(``)}catch{let t=``;for(let n=0;n<e;n++)t+=Math.floor(Math.random()*16).toString(16);return t}}function ct(e,t,n){if(!q||!K)return n();let r=Date.now()/1e3,i=st(32),a=st(16),o=`ok`,s=()=>{let n=Date.now()/1e3;q.captureEvent({type:`transaction`,transaction:e,start_timestamp:r,timestamp:n,contexts:{trace:{trace_id:i,span_id:a,op:t,status:o}}})};try{let e=n();return e instanceof Promise?e.then(e=>(s(),e),e=>{throw o=`internal_error`,s(),e}):(s(),e)}catch(e){throw o=`internal_error`,s(),e}}const Y=i.createContext(null),lt=[];function ut({children:e,chatEndpoint:t=null,chat:n,onModeChange:r,onOpenChange:a,historyStorageKey:o,maxConversations:s}){let[c,l]=i.useState(`command`),[u,d]=i.useState(``),[f,p]=i.useState(`idle`),[m,g]=i.useState(null),_=i.useRef(n);_.current=n;let v=!!n;i.useEffect(()=>{ot()},[]);let y=i.useMemo(()=>{if(!(v||!t))return new ne({api:t})},[t,v]),b=te(i.useMemo(()=>y?{transport:y,onError:e=>{J(e,{source:`internalChat.onError`}),p(`error`),g(e)}}:{},[y])),x=n?.status,S=n?.error??null;i.useEffect(()=>{if(v)x===`ready`?p(`idle`):x===`streaming`?p(`streaming`):x===`submitted`?p(`submitted`):x===`error`&&p(`error`),g(S);else{let e=b.status;e===`streaming`?p(`streaming`):e===`submitted`?p(`submitted`):e===`error`?p(`error`):e===`ready`&&p(`idle`)}},[x,S,b.status,v]);let C=i.useCallback(e=>{l(e),r?.(e)},[r]),w=!!(n||t),T=i.useCallback(e=>{w&&ct(`switchToChat`,`ui.action`,()=>{C(`chat`),e&&d(e)})},[w,C]),E=i.useCallback(()=>{C(`command`),d(``),p(`idle`),g(null)},[C]),D=i.useCallback(async e=>{e.trim()&&await ct(`sendMessage`,`function`,async()=>{try{let t=_.current;if(t){d(``),t.sendMessage({text:e.trim()});return}if(!y)return;p(`submitted`),d(``),await b.sendMessage({text:e.trim()})}catch(e){throw J(e,{source:`sendMessage`}),e}})},[b,y]),O=f===`submitted`||f===`streaming`,k=n?n.messages:b.messages??lt,ee=n?.setMessages??b.setMessages,A=n?.addToolApprovalResponse,j=n?.agenticActions,M=rt({storageKey:o,maxConversations:s,messages:k,setMessages:ee}),N=i.useCallback(e=>{M.loadConversation(e),C(`chat`)},[M.loadConversation,C]),P=i.useRef(f);i.useEffect(()=>{let e=P.current;P.current=f,(e===`streaming`||e===`submitted`)&&f===`idle`&&k.length>0&&M.saveCurrentConversation()},[f,k.length,M.saveCurrentConversation]);let F=i.useCallback(()=>{a?.(!1)},[a]),I=i.useMemo(()=>({mode:c,setMode:C,inputValue:u,setInputValue:d,chatEndpoint:t,status:f,error:m,switchToChat:T,switchToCommand:E,messages:k,sendMessage:D,isLoading:O,isEnabled:w,addToolApprovalResponse:A,agenticActions:j,requestClose:F,conversations:M.conversations,currentConversationId:M.currentConversationId,startNewChat:M.startNewChat,loadConversation:N}),[c,C,u,t,f,m,T,E,k,D,O,w,A,j,F,M.conversations,M.currentConversationId,M.startNewChat,N]);return h(Y.Provider,{value:I,children:e})}function X(){let e=i.useContext(Y);if(!e)throw Error(`useCommandMenuContext must be used within a CommandMenuProvider`);return e}var dt=class extends i.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e,t){J(e,{componentStack:t.componentStack??void 0})}render(){return this.state.hasError?null:this.props.children}};const ft=e=>{},pt={none:`rounded-none`,sm:`rounded-sm`,md:`rounded-md`,lg:`rounded-lg`,xl:`rounded-xl`},mt={none:`0px`,sm:`0.125rem`,md:`0.375rem`,lg:`0.5rem`,xl:`0.75rem`};function ht(e){let t=Date.now()-e,n=Math.floor(t/6e4);if(n<1)return`just now`;if(n<60)return`${n}m ago`;let r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function gt({className:t,children:n,corners:r=`xl`,borderColor:i,...a}){return h(U,{"data-slot":`dialog-portal`,children:h(D.Content,{"data-slot":`dialog-content`,className:e(`bg-background fixed top-1/3 left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] overflow-hidden border-none p-2 shadow-2xl ring-4 ring-neutral-200/80 duration-200 outline-none sm:max-w-lg dark:bg-neutral-900 dark:ring-neutral-800`,pt[r],t),style:{"--cmdk-radius":mt[r],...i?{"--tw-ring-color":i}:{}},...a,children:n})})}const _t=g(m,{children:[h(Z,{placeholder:`Search or ask AI...`,showSendButton:!0}),h($,{children:h(Q,{})})]});function vt({title:t=`Command Palette`,description:n=`Search for a command to run...`,children:r,className:i,corners:a=`xl`,borderColor:o,commands:s,commandsPlaceholder:c=`Search or ask AI...`,commandsAskAILabel:l=`Ask AI`,...u}){let{mode:d,status:f,switchToCommand:p,messages:m,isEnabled:_,sendMessage:v,addToolApprovalResponse:y}=X(),b=()=>s&&s.length>0?h(xt,{commands:s,placeholder:c,askAILabel:l}):typeof r==`function`?r({mode:d,messages:m,status:f,isEnabled:_}):r??_t,x=e=>{d===`chat`&&(e.preventDefault(),p())};return h(Be,{...u,children:g(gt,{className:i,corners:a,borderColor:o,onEscapeKeyDown:x,children:[g(Ge,{className:`sr-only`,children:[h(qe,{children:t}),h(Je,{children:n})]}),h(k,{"data-slot":`command`,className:e(`**:data-[slot=command-input-wrapper]:bg-input/50 **:data-[slot=command-input-wrapper]:border-input rounded-none bg-transparent **:data-[slot=command-input]:!h-9 **:data-[slot=command-input]:py-0 **:data-[slot=command-input-wrapper]:mb-0 **:data-[slot=command-input-wrapper]:!h-9 **:data-[slot=command-input-wrapper]:border`,`bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden`),style:{borderRadius:`var(--cmdk-radius, 0.75rem)`},children:b()})]})})}function yt({chatEndpoint:e=null,chat:t,onModeChange:n,onOpenChange:r,historyStorageKey:i,maxConversations:a,commands:o,commandsPlaceholder:s,commandsAskAILabel:c,...l}){return h(ut,{chatEndpoint:e,chat:t,onModeChange:n,onOpenChange:r,historyStorageKey:i,maxConversations:a,children:h(dt,{children:h(vt,{onOpenChange:r,commands:o,commandsPlaceholder:s,commandsAskAILabel:c,...l})})})}function Z({className:t,showSendButton:n=!1,...r}){let{mode:i,inputValue:a,setInputValue:o,sendMessage:s,isLoading:c,switchToChat:l,startNewChat:u}=X(),d=()=>{a.trim()&&i===`chat`&&s(a)},f=e=>{if((e.metaKey||e.ctrlKey)&&e.key===`Enter`){e.preventDefault(),i===`command`&&a.trim()?(u(),l(),s(a)):i===`chat`&&a.trim()&&s(a);return}if(i===`chat`&&e.key===`Enter`&&!e.shiftKey){e.preventDefault(),a.trim()&&s(a);return}};return g(`div`,{"data-slot":`command-input-wrapper`,className:`order-2 flex h-9 items-center gap-2 border-t px-3 mt-2`,style:{borderRadius:`var(--cmdk-radius, 0.75rem)`},children:[i===`command`?h(S,{className:`size-4 shrink-0 opacity-50`}):h(C,{className:`size-4 shrink-0 text-primary`}),h(k.Input,{"data-slot":`command-input`,value:a,onValueChange:o,onKeyDown:f,className:e(`placeholder:text-muted-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50`,t),...r,placeholder:i===`chat`?`Ask AI...`:r.placeholder}),n&&i===`chat`&&h(`button`,{type:`button`,onClick:d,disabled:!a.trim()||c,className:`flex items-center justify-center size-6 bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,style:{borderRadius:`var(--cmdk-radius, 0.75rem)`},children:h(y,{className:`size-3`})})]})}function Q({label:t=`Ask AI`,className:n,...r}){let{inputValue:i,setInputValue:a,switchToChat:o,sendMessage:s,isEnabled:c,startNewChat:l}=X(),u=A(e=>e.filtered.count),d=()=>{if(c)if(i.trim()){let e=ee(`ask-ai`,i.trim())>0;u===0&&!e?(l(),o(),s(i)):(o(),a(``))}else o()};return c?h(k.Group,{forceMount:!0,children:g(k.Item,{"data-slot":`command-item`,value:`ask-ai`,onSelect:d,className:e(`data-[selected=true]:border-input data-[selected=true]:bg-input/50 relative flex cursor-default items-center gap-3 border border-transparent px-3 py-2 text-sm outline-hidden select-none`,n),style:{borderRadius:`var(--cmdk-radius, 0.75rem)`},...r,children:[h(C,{className:`size-4 shrink-0 text-primary`}),h(`div`,{className:`flex flex-col items-start gap-0.5`,children:h(`span`,{className:`font-medium`,children:t})})]})}):h(k.Empty,{"data-slot":`command-empty`,className:e(`text-muted-foreground py-6 text-center text-sm`,n),children:`No results found.`})}function bt(e){let t=[],n=new Map;for(let r of e){let e=r.group,i=n.get(e);i===void 0?(n.set(e,t.length),t.push({heading:e,items:[r]})):t[i].items.push(r)}let r=t.findIndex(e=>e.heading===void 0);if(r>0){let e=t.splice(r,1)[0];t.unshift(e)}return t}function xt({commands:e,placeholder:t,askAILabel:n}){let r=bt(e);return g(m,{children:[h(Z,{placeholder:t,showSendButton:!0}),g($,{children:[r.map((e,t)=>{let n=e.items.map(e=>{let t=e.label??e.name,n=[...e.keywords??[]];return e.label&&e.label!==e.name&&n.push(e.label),g(G,{value:e.name,keywords:n.length>0?n:void 0,disabled:e.disabled,onSelect:()=>e.onSelect?.(),children:[e.icon,t,e.shortcut&&h($e,{children:e.shortcut})]},e.name)});return e.heading?h(W,{heading:e.heading,children:n},e.heading):h(i.Fragment,{children:n},`__ungrouped_${t}`)}),h(Q,{label:n})]})]})}function $({className:t,children:n,actions:r,actionsHeading:a=`Actions`,...o}){let{mode:s,status:c,messages:l,sendMessage:u,addToolApprovalResponse:d,agenticActions:f,requestClose:p,switchToChat:m,startNewChat:_,conversations:v,loadConversation:y}=X(),b=i.useCallback(e=>u(e.text),[u]),S=d??ft;if(s===`chat`)return h(`div`,{"data-slot":`command-list`,className:e(`order-1 max-h-[300px] min-h-0 flex-1 overflow-hidden`,t),children:l.length===0?h(ze,{}):g(Le,{className:`max-h-[300px]`,children:[h(`div`,{className:`px-3 py-2 space-y-4`,children:h(Me,{messages:l,sendMessage:b,addToolApprovalResponse:S})}),c===`streaming`&&h(Re,{})]})});let C=i.Children.toArray(n),w=[],T=[];C.forEach(e=>{i.isValidElement(e)&&(e.type===Q||e.type.displayName===`CommandEmpty`)?w.push(e):i.isValidElement(e)&&e.type===Ze||T.push(e)});let E=(r??f)?.filter(e=>e.execute),D=e=>{let t=e.label??e.name;_(),m(),u(t)};return g(k.List,{"data-slot":`command-list`,className:e(`order-1 max-h-[300px] min-h-0 flex-1 overflow-x-hidden overflow-y-auto`,t),...o,children:[T,v.length>0&&h(W,{heading:`Recent Chats`,children:v.slice(0,5).map(e=>g(G,{value:`chat-history-${e.title}`,onSelect:()=>y(e.id),children:[h(x,{className:`size-4`}),h(`span`,{className:`truncate`,children:e.title}),h(`span`,{className:`ml-auto text-xs text-muted-foreground`,children:ht(e.updatedAt)})]},e.id))}),E&&E.length>0&&h(W,{heading:a,children:E.map(e=>h(G,{value:e.label??e.name,onSelect:()=>D(e),children:e.label??e.name},e.name))}),w]})}Q.displayName=`CommandEmpty`;export{H as AssistantFormRenderer,Me as AssistantMessages,Ie as Button,ze as ChatEmpty,Re as ChatLoading,Le as ChatMessageList,ve as Collapsible,be as CollapsibleContent,ye as CollapsibleTrigger,Ye as Command,gt as CommandContent,yt as CommandDialog,yt as CommandMenu,Xe as CommandDialogContent,Q as CommandEmpty,W as CommandGroup,Z as CommandInput,G as CommandItem,$ as CommandList,Y as CommandMenuContext,ut as CommandMenuProvider,Qe as CommandSeparator,$e as CommandShortcut,ie as Confirmation,oe as ConfirmationAccepted,z as ConfirmationAction,ce as ConfirmationActions,se as ConfirmationRejected,R as ConfirmationRequest,ae as ConfirmationTitle,Be as Dialog,He as DialogClose,We as DialogContent,Je as DialogDescription,Ke as DialogFooter,Ge as DialogHeader,Ue as DialogOverlay,U as DialogPortal,qe as DialogTitle,Ve as DialogTrigger,he as Message,ge as MessageContent,_e as MessageResponse,Ce as Task,Te as TaskContent,Se as TaskItem,xe as TaskItemFile,we as TaskTrigger,Fe as buttonVariants,e as cn,V as defaultFormRegistry,rt as useChatHistory,X as useCommandMenuContext};
@@ -0,0 +1,6 @@
1
+ import { ClassValue } from "clsx";
2
+
3
+ //#region lib/utils.d.ts
4
+ declare function cn(...inputs: ClassValue[]): string;
5
+ //#endregion
6
+ export { cn };
@@ -0,0 +1 @@
1
+ import{clsx as e}from"clsx";import{twMerge as t}from"tailwind-merge";function n(...n){return t(e(n))}export{n as cn};
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "better-cmdk",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "types": "./index.ts",
6
+ "exports": {
7
+ ".": "./dist/index.js",
8
+ "./lib/utils": "./dist/lib/utils.js",
9
+ "./package.json": "./package.json"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "bun run --bun tsdown"
16
+ },
17
+ "devDependencies": {
18
+ "@biomejs/biome": "^2.3.14",
19
+ "@types/bun": "latest",
20
+ "tsdown": "^0.20.3"
21
+ },
22
+ "peerDependencies": {
23
+ "react": "^18 || ^19",
24
+ "react-dom": "^18 || ^19",
25
+ "typescript": "^5"
26
+ },
27
+ "dependencies": {
28
+ "@ai-sdk/react": "^3.0.0",
29
+ "@json-render/core": "^0.2.0",
30
+ "@json-render/react": "^0.2.0",
31
+ "@radix-ui/react-collapsible": "^1.1.12",
32
+ "ai": "^6.0.0",
33
+ "class-variance-authority": "^0.7.1",
34
+ "clsx": "^2.1.1",
35
+ "cmdk": "^1.1.1",
36
+ "lucide-react": "^0.563.0",
37
+ "radix-ui": "^1.4.3",
38
+ "streamdown": "^2.1.0",
39
+ "tailwind-merge": "^3.4.0",
40
+ "zod": "^3.24.0",
41
+ "@sentry/browser": "^9.0.0"
42
+ }
43
+ }