veryfront 0.0.58 → 0.0.59

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.
@@ -1,929 +0,0 @@
1
- // src/ai/react/components/theme.ts
2
- var defaultChatTheme = {
3
- container: "flex flex-col h-full overflow-hidden bg-white dark:bg-neutral-900",
4
- message: {
5
- user: "bg-blue-500 text-white rounded-[20px] rounded-br-[4px] px-4 py-2.5 max-w-[75%]",
6
- assistant: "bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 rounded-[20px] rounded-bl-[4px] px-4 py-2.5 max-w-[75%]",
7
- system: "bg-neutral-100 dark:bg-neutral-800 text-neutral-500 dark:text-neutral-400 rounded-2xl px-4 py-2 text-sm mx-auto text-center",
8
- tool: "bg-neutral-50 dark:bg-neutral-800 text-neutral-600 dark:text-neutral-300 rounded-xl px-3 py-2 text-sm font-mono border border-neutral-200 dark:border-neutral-700"
9
- },
10
- input: "flex-1 px-4 py-2.5 bg-neutral-100 dark:bg-neutral-800 border-0 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500/30 dark:text-neutral-100 placeholder-neutral-400 dark:placeholder-neutral-500 text-[15px]",
11
- button: "w-9 h-9 flex items-center justify-center bg-blue-500 hover:bg-blue-600 active:scale-95 text-white rounded-full transition-all disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-blue-500 disabled:active:scale-100",
12
- loading: "w-1.5 h-1.5 bg-neutral-400 rounded-full animate-bounce"
13
- };
14
- var defaultAgentTheme = {
15
- container: "border border-neutral-200 dark:border-neutral-800 rounded-2xl p-6 space-y-4 bg-white dark:bg-neutral-900",
16
- status: "inline-flex items-center px-3 py-1.5 rounded-full text-sm font-medium",
17
- thinking: "bg-amber-50 dark:bg-amber-900/20 rounded-xl px-4 py-3 italic text-neutral-700 dark:text-neutral-300 border border-amber-200 dark:border-amber-800",
18
- tool: "rounded-xl px-4 py-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800",
19
- toolResult: "mt-2 p-3 bg-neutral-100 dark:bg-neutral-800 rounded-xl font-mono text-sm overflow-x-auto"
20
- };
21
- function mergeThemes(defaultTheme, userTheme) {
22
- if (!userTheme)
23
- return defaultTheme;
24
- const merged = { ...defaultTheme };
25
- for (const key in userTheme) {
26
- const value = userTheme[key];
27
- if (value === void 0) {
28
- continue;
29
- }
30
- if (typeof value === "object" && !Array.isArray(value)) {
31
- merged[key] = { ...defaultTheme[key], ...value };
32
- } else {
33
- merged[key] = value;
34
- }
35
- }
36
- return merged;
37
- }
38
- function cn(...classes) {
39
- return classes.filter(Boolean).join(" ");
40
- }
41
-
42
- // src/ai/react/components/chat.tsx
43
- import * as React7 from "react";
44
-
45
- // src/ai/react/primitives/chat-container.tsx
46
- import * as React from "react";
47
- import { jsx } from "react/jsx-runtime";
48
- var ChatContainer = React.forwardRef(
49
- ({ className, children, ...props }, ref) => {
50
- return /* @__PURE__ */ jsx(
51
- "div",
52
- {
53
- ref,
54
- className,
55
- "data-chat-container": "",
56
- ...props,
57
- children
58
- }
59
- );
60
- }
61
- );
62
- ChatContainer.displayName = "ChatContainer";
63
-
64
- // src/ai/react/primitives/message-list.tsx
65
- import * as React2 from "react";
66
- import { jsx as jsx2 } from "react/jsx-runtime";
67
- var MessageList = React2.forwardRef(
68
- ({ className, children, ...props }, ref) => {
69
- return /* @__PURE__ */ jsx2(
70
- "div",
71
- {
72
- ref,
73
- className,
74
- "data-message-list": "",
75
- role: "log",
76
- "aria-live": "polite",
77
- ...props,
78
- children
79
- }
80
- );
81
- }
82
- );
83
- MessageList.displayName = "MessageList";
84
- var MessageItem = React2.forwardRef(
85
- ({ className, role, content, children, ...props }, ref) => {
86
- return /* @__PURE__ */ jsx2(
87
- "div",
88
- {
89
- ref,
90
- className,
91
- "data-message-item": "",
92
- "data-role": role,
93
- ...props,
94
- children: children || content
95
- }
96
- );
97
- }
98
- );
99
- MessageItem.displayName = "MessageItem";
100
- var MessageRole = React2.forwardRef(
101
- ({ className, children, ...props }, ref) => {
102
- return /* @__PURE__ */ jsx2(
103
- "span",
104
- {
105
- ref,
106
- className,
107
- "data-message-role": "",
108
- ...props,
109
- children
110
- }
111
- );
112
- }
113
- );
114
- MessageRole.displayName = "MessageRole";
115
- var MessageContent = React2.forwardRef(({ className, children, ...props }, ref) => {
116
- return /* @__PURE__ */ jsx2(
117
- "div",
118
- {
119
- ref,
120
- className,
121
- "data-message-content": "",
122
- ...props,
123
- children
124
- }
125
- );
126
- });
127
- MessageContent.displayName = "MessageContent";
128
-
129
- // src/ai/react/primitives/input-box.tsx
130
- import * as React3 from "react";
131
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
132
- var InputBox = React3.forwardRef(({ className, value, onChange, onSubmit, multiline, ...props }, ref) => {
133
- const handleKeyDown = (e) => {
134
- if (e.key === "Enter" && !e.shiftKey && onSubmit) {
135
- e.preventDefault();
136
- onSubmit();
137
- }
138
- };
139
- if (multiline) {
140
- return /* @__PURE__ */ jsx3(
141
- "textarea",
142
- {
143
- ref,
144
- className,
145
- value,
146
- onChange,
147
- onKeyDown: handleKeyDown,
148
- "data-input-box": "",
149
- "data-multiline": "true",
150
- rows: 3,
151
- ...props
152
- }
153
- );
154
- }
155
- return /* @__PURE__ */ jsx3(
156
- "input",
157
- {
158
- ref,
159
- type: "text",
160
- className,
161
- value,
162
- onChange,
163
- onKeyDown: handleKeyDown,
164
- "data-input-box": "",
165
- ...props
166
- }
167
- );
168
- });
169
- InputBox.displayName = "InputBox";
170
- var SubmitIcon = () => /* @__PURE__ */ jsx3("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx3("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) });
171
- var StopIcon = () => /* @__PURE__ */ jsx3("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx3("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2" }) });
172
- var VoiceIcon = () => /* @__PURE__ */ jsxs(
173
- "svg",
174
- {
175
- width: "16",
176
- height: "16",
177
- viewBox: "0 0 24 24",
178
- fill: "none",
179
- stroke: "currentColor",
180
- strokeWidth: "2",
181
- strokeLinecap: "round",
182
- strokeLinejoin: "round",
183
- children: [
184
- /* @__PURE__ */ jsx3("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
185
- /* @__PURE__ */ jsx3("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
186
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
187
- ]
188
- }
189
- );
190
- var SubmitButton = React3.forwardRef(({ className, isLoading, hasInput, onStop, onVoice, icons, disabled, children, ...props }, ref) => {
191
- const showStop = isLoading;
192
- const showVoice = !isLoading && !hasInput && onVoice;
193
- const handleClick = (e) => {
194
- if (showStop && onStop) {
195
- e.preventDefault();
196
- onStop();
197
- } else if (showVoice && onVoice) {
198
- e.preventDefault();
199
- onVoice();
200
- }
201
- };
202
- let icon;
203
- let ariaLabel;
204
- if (showStop) {
205
- icon = icons?.stop || /* @__PURE__ */ jsx3(StopIcon, {});
206
- ariaLabel = "Stop generating";
207
- } else if (showVoice) {
208
- icon = icons?.voice || /* @__PURE__ */ jsx3(VoiceIcon, {});
209
- ariaLabel = "Voice input";
210
- } else {
211
- icon = icons?.submit || /* @__PURE__ */ jsx3(SubmitIcon, {});
212
- ariaLabel = "Send message";
213
- }
214
- return /* @__PURE__ */ jsx3(
215
- "button",
216
- {
217
- ref,
218
- type: showStop || showVoice ? "button" : "submit",
219
- className,
220
- disabled: disabled && !showStop,
221
- onClick: handleClick,
222
- "data-submit-button": "",
223
- "data-state": showStop ? "stop" : showVoice ? "voice" : "submit",
224
- "data-loading": isLoading,
225
- "aria-label": ariaLabel,
226
- ...props,
227
- children: children || icon
228
- }
229
- );
230
- });
231
- SubmitButton.displayName = "SubmitButton";
232
- var LoadingIndicator = React3.forwardRef(({ className, ...props }, ref) => {
233
- return /* @__PURE__ */ jsx3(
234
- "div",
235
- {
236
- ref,
237
- className,
238
- "data-loading-indicator": "",
239
- role: "status",
240
- "aria-label": "Loading",
241
- ...props
242
- }
243
- );
244
- });
245
- LoadingIndicator.displayName = "LoadingIndicator";
246
-
247
- // src/ai/react/primitives/agent-primitives.tsx
248
- import * as React4 from "react";
249
- import { jsx as jsx4 } from "react/jsx-runtime";
250
- var AgentContainer = React4.forwardRef(({ className, children, ...props }, ref) => {
251
- return /* @__PURE__ */ jsx4(
252
- "div",
253
- {
254
- ref,
255
- className,
256
- "data-agent-container": "",
257
- ...props,
258
- children
259
- }
260
- );
261
- });
262
- AgentContainer.displayName = "AgentContainer";
263
- var AgentStatus = React4.forwardRef(
264
- ({ className, status, label, ...props }, ref) => {
265
- const displayLabel = label || formatStatus(status);
266
- return /* @__PURE__ */ jsx4(
267
- "div",
268
- {
269
- ref,
270
- className,
271
- "data-agent-status": "",
272
- "data-status": status,
273
- role: "status",
274
- "aria-label": `Agent status: ${displayLabel}`,
275
- ...props,
276
- children: displayLabel
277
- }
278
- );
279
- }
280
- );
281
- AgentStatus.displayName = "AgentStatus";
282
- var ThinkingIndicator = React4.forwardRef(({ className, children, ...props }, ref) => {
283
- return /* @__PURE__ */ jsx4(
284
- "div",
285
- {
286
- ref,
287
- className,
288
- "data-thinking-indicator": "",
289
- role: "status",
290
- "aria-live": "polite",
291
- ...props,
292
- children
293
- }
294
- );
295
- });
296
- ThinkingIndicator.displayName = "ThinkingIndicator";
297
- function formatStatus(status) {
298
- switch (status) {
299
- case "idle":
300
- return "Idle";
301
- case "thinking":
302
- return "Thinking...";
303
- case "tool_execution":
304
- return "Using tools...";
305
- case "streaming":
306
- return "Responding...";
307
- case "completed":
308
- return "Completed";
309
- case "error":
310
- return "Error";
311
- default:
312
- return String(status);
313
- }
314
- }
315
-
316
- // src/ai/react/primitives/tool-primitives.tsx
317
- import * as React5 from "react";
318
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
319
- var ToolInvocation = React5.forwardRef(({ className, name, args, status, children, ...props }, ref) => {
320
- return /* @__PURE__ */ jsxs2(
321
- "div",
322
- {
323
- ref,
324
- className,
325
- "data-tool-invocation": "",
326
- "data-tool-name": name,
327
- "data-status": status,
328
- ...props,
329
- children: [
330
- /* @__PURE__ */ jsxs2("div", { "data-tool-header": "", children: [
331
- /* @__PURE__ */ jsx5("span", { "data-tool-name": "", children: name }),
332
- status && /* @__PURE__ */ jsxs2("span", { "data-tool-status": "", children: [
333
- "(",
334
- status,
335
- ")"
336
- ] })
337
- ] }),
338
- args && /* @__PURE__ */ jsx5("div", { "data-tool-args": "", children: /* @__PURE__ */ jsx5("pre", { children: JSON.stringify(args, null, 2) }) }),
339
- children
340
- ]
341
- }
342
- );
343
- });
344
- ToolInvocation.displayName = "ToolInvocation";
345
- var ToolResult = React5.forwardRef(
346
- ({ className, result, renderResult, ...props }, ref) => {
347
- const content = renderResult ? renderResult(result) : JSON.stringify(result, null, 2);
348
- return /* @__PURE__ */ jsx5(
349
- "div",
350
- {
351
- ref,
352
- className,
353
- "data-tool-result": "",
354
- ...props,
355
- children: typeof content === "string" ? /* @__PURE__ */ jsx5("pre", { children: content }) : content
356
- }
357
- );
358
- }
359
- );
360
- ToolResult.displayName = "ToolResult";
361
- var ToolList = React5.forwardRef(
362
- ({ className, toolCalls, renderTool, ...props }, ref) => {
363
- return /* @__PURE__ */ jsx5(
364
- "div",
365
- {
366
- ref,
367
- className,
368
- "data-tool-list": "",
369
- ...props,
370
- children: toolCalls.map(
371
- (tool) => renderTool ? /* @__PURE__ */ jsx5(React5.Fragment, { children: renderTool(tool) }, tool.id) : /* @__PURE__ */ jsx5(
372
- ToolInvocation,
373
- {
374
- name: tool.name,
375
- args: tool.args,
376
- status: tool.status,
377
- children: tool.result !== void 0 && /* @__PURE__ */ jsx5(ToolResult, { result: tool.result })
378
- },
379
- tool.id
380
- )
381
- )
382
- }
383
- );
384
- }
385
- );
386
- ToolList.displayName = "ToolList";
387
-
388
- // src/ai/react/hooks/use-voice-input.ts
389
- import * as React6 from "react";
390
- function useVoiceInput(options = {}) {
391
- const {
392
- language,
393
- continuous = false,
394
- interimResults = true,
395
- onTranscript,
396
- onError,
397
- onStart,
398
- onEnd
399
- } = options;
400
- const [isListening, setIsListening] = React6.useState(false);
401
- const [transcript, setTranscript] = React6.useState("");
402
- const [error, setError] = React6.useState(null);
403
- const recognitionRef = React6.useRef(null);
404
- const isSupported = React6.useMemo(() => {
405
- if (typeof globalThis === "undefined")
406
- return false;
407
- const g = globalThis;
408
- return !!(g.SpeechRecognition || g.webkitSpeechRecognition);
409
- }, []);
410
- React6.useEffect(() => {
411
- if (!isSupported)
412
- return;
413
- const g = globalThis;
414
- const SpeechRecognitionAPI = g.SpeechRecognition || g.webkitSpeechRecognition;
415
- if (!SpeechRecognitionAPI)
416
- return;
417
- const recognition = new SpeechRecognitionAPI();
418
- recognition.continuous = continuous;
419
- recognition.interimResults = interimResults;
420
- if (language) {
421
- recognition.lang = language;
422
- }
423
- recognition.onresult = (event) => {
424
- let finalTranscript = "";
425
- let interimTranscript = "";
426
- for (let i = event.resultIndex; i < event.results.length; i++) {
427
- const result = event.results[i];
428
- if (!result || !result[0])
429
- continue;
430
- if (result.isFinal) {
431
- finalTranscript += result[0].transcript;
432
- } else {
433
- interimTranscript += result[0].transcript;
434
- }
435
- }
436
- const currentTranscript = finalTranscript || interimTranscript;
437
- setTranscript(currentTranscript);
438
- if (onTranscript) {
439
- onTranscript(currentTranscript, !!finalTranscript);
440
- }
441
- };
442
- recognition.onerror = (event) => {
443
- const errorMessage = getErrorMessage(event.error);
444
- setError(errorMessage);
445
- setIsListening(false);
446
- if (onError) {
447
- onError(errorMessage);
448
- }
449
- };
450
- recognition.onstart = () => {
451
- setIsListening(true);
452
- setError(null);
453
- if (onStart) {
454
- onStart();
455
- }
456
- };
457
- recognition.onend = () => {
458
- setIsListening(false);
459
- if (onEnd) {
460
- onEnd();
461
- }
462
- };
463
- recognitionRef.current = recognition;
464
- return () => {
465
- recognition.abort();
466
- };
467
- }, [isSupported, language, continuous, interimResults, onTranscript, onError, onStart, onEnd]);
468
- const start = React6.useCallback(() => {
469
- if (!recognitionRef.current || isListening)
470
- return;
471
- setTranscript("");
472
- setError(null);
473
- try {
474
- recognitionRef.current.start();
475
- } catch {
476
- console.warn("Speech recognition already started");
477
- }
478
- }, [isListening]);
479
- const stop = React6.useCallback(() => {
480
- if (!recognitionRef.current || !isListening)
481
- return;
482
- recognitionRef.current.stop();
483
- }, [isListening]);
484
- const toggle = React6.useCallback(() => {
485
- if (isListening) {
486
- stop();
487
- } else {
488
- start();
489
- }
490
- }, [isListening, start, stop]);
491
- const clear = React6.useCallback(() => {
492
- setTranscript("");
493
- }, []);
494
- return {
495
- isSupported,
496
- isListening,
497
- transcript,
498
- start,
499
- stop,
500
- toggle,
501
- clear,
502
- error
503
- };
504
- }
505
- function getErrorMessage(error) {
506
- switch (error) {
507
- case "no-speech":
508
- return "No speech detected. Please try again.";
509
- case "audio-capture":
510
- return "No microphone found. Please check your device.";
511
- case "not-allowed":
512
- return "Microphone permission denied. Please allow access.";
513
- case "network":
514
- return "Network error. Please check your connection.";
515
- case "aborted":
516
- return "Speech recognition was aborted.";
517
- case "language-not-supported":
518
- return "Language not supported.";
519
- case "service-not-allowed":
520
- return "Speech recognition service not allowed.";
521
- default:
522
- return `Speech recognition error: ${error}`;
523
- }
524
- }
525
-
526
- // src/ai/react/components/chat.tsx
527
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
528
- var Chat = React7.forwardRef(
529
- ({
530
- messages,
531
- input,
532
- onChange,
533
- handleInputChange,
534
- onSubmit,
535
- handleSubmit,
536
- stop,
537
- enableVoice = false,
538
- onVoice,
539
- setInput,
540
- isLoading,
541
- error,
542
- placeholder = "Type a message...",
543
- maxHeight = "100%",
544
- className,
545
- theme: userTheme,
546
- renderMessage,
547
- renderTool: _renderTool,
548
- multiline = false
549
- }, ref) => {
550
- const theme = mergeThemes(defaultChatTheme, userTheme);
551
- const messagesEndRef = React7.useRef(null);
552
- const inputChangeHandler = onChange || handleInputChange || (() => {
553
- });
554
- const submitHandler = onSubmit || handleSubmit;
555
- const voice = useVoiceInput({
556
- onTranscript: (transcript, isFinal) => {
557
- if (setInput && isFinal) {
558
- setInput(transcript);
559
- }
560
- }
561
- });
562
- const voiceHandler = React7.useMemo(() => {
563
- if (onVoice)
564
- return onVoice;
565
- if (enableVoice && voice.isSupported && setInput) {
566
- return voice.toggle;
567
- }
568
- return void 0;
569
- }, [onVoice, enableVoice, voice.isSupported, voice.toggle, setInput]);
570
- React7.useEffect(() => {
571
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
572
- }, [messages]);
573
- return /* @__PURE__ */ jsxs3(
574
- ChatContainer,
575
- {
576
- ref,
577
- className: cn(theme.container, className),
578
- style: { maxHeight },
579
- children: [
580
- /* @__PURE__ */ jsx6(MessageList, { className: "flex-1 min-h-0 overflow-y-auto", children: /* @__PURE__ */ jsxs3("div", { className: "max-w-2xl mx-auto px-4 py-4 space-y-2", children: [
581
- messages.map(
582
- (msg) => renderMessage ? /* @__PURE__ */ jsx6(React7.Fragment, { children: renderMessage(msg) }, msg.id) : /* @__PURE__ */ jsx6(
583
- MessageItem,
584
- {
585
- role: msg.role,
586
- className: cn(
587
- "flex",
588
- msg.role === "user" ? "justify-end" : "justify-start"
589
- ),
590
- children: /* @__PURE__ */ jsx6("div", { className: theme.message?.[msg.role] || theme.message?.assistant, children: /* @__PURE__ */ jsx6("p", { className: "whitespace-pre-wrap text-[15px] leading-relaxed", children: msg.content }) })
591
- },
592
- msg.id
593
- )
594
- ),
595
- isLoading && /* @__PURE__ */ jsx6("div", { className: "flex justify-start", children: /* @__PURE__ */ jsx6("div", { className: "bg-neutral-100 dark:bg-neutral-800 rounded-[20px] rounded-bl-[4px] px-4 py-3", children: /* @__PURE__ */ jsxs3("div", { className: "flex gap-1.5 items-center", children: [
596
- /* @__PURE__ */ jsx6("span", { className: cn(theme.loading) }),
597
- /* @__PURE__ */ jsx6("span", { className: cn(theme.loading), style: { animationDelay: "0.15s" } }),
598
- /* @__PURE__ */ jsx6("span", { className: cn(theme.loading), style: { animationDelay: "0.3s" } })
599
- ] }) }) }),
600
- /* @__PURE__ */ jsx6("div", { ref: messagesEndRef })
601
- ] }) }),
602
- error && /* @__PURE__ */ jsx6("div", { className: "mx-4 mb-2 px-4 py-3 bg-red-50 dark:bg-red-900/20 rounded-2xl text-red-600 dark:text-red-400 text-sm", children: error.message }),
603
- /* @__PURE__ */ jsx6("div", { className: "flex-shrink-0 bg-white dark:bg-neutral-900 border-t border-neutral-200 dark:border-neutral-800", children: /* @__PURE__ */ jsx6(
604
- "form",
605
- {
606
- onSubmit: submitHandler,
607
- className: "max-w-2xl mx-auto px-4 py-3",
608
- children: /* @__PURE__ */ jsxs3("div", { className: "flex gap-2 items-center", children: [
609
- /* @__PURE__ */ jsx6(
610
- InputBox,
611
- {
612
- value: voice.isListening ? voice.transcript || input : input,
613
- onChange: inputChangeHandler,
614
- placeholder: voice.isListening ? "Listening..." : placeholder,
615
- disabled: isLoading || voice.isListening,
616
- multiline,
617
- className: theme.input
618
- }
619
- ),
620
- /* @__PURE__ */ jsx6(
621
- SubmitButton,
622
- {
623
- isLoading: isLoading || voice.isListening,
624
- hasInput: !!input.trim(),
625
- onStop: voice.isListening ? voice.stop : stop,
626
- onVoice: voiceHandler,
627
- disabled: !input.trim(),
628
- className: theme.button
629
- }
630
- )
631
- ] })
632
- }
633
- ) })
634
- ]
635
- }
636
- );
637
- }
638
- );
639
- Chat.displayName = "Chat";
640
- var ChatHeader = React7.forwardRef(({ className, children, ...props }, ref) => {
641
- return /* @__PURE__ */ jsx6(
642
- "div",
643
- {
644
- ref,
645
- className: cn(
646
- "border-b border-gray-200 dark:border-gray-800 p-4 bg-gray-50 dark:bg-gray-900",
647
- className
648
- ),
649
- ...props,
650
- children
651
- }
652
- );
653
- });
654
- ChatHeader.displayName = "ChatHeader";
655
- var ChatMessages = MessageList;
656
- ChatMessages.displayName = "ChatMessages";
657
- var ChatInput = React7.forwardRef(({ className, ...props }, ref) => {
658
- return /* @__PURE__ */ jsx6("div", { className: "border-t border-gray-200 dark:border-gray-800 p-4", children: /* @__PURE__ */ jsx6("div", { className: "flex gap-2", children: /* @__PURE__ */ jsx6(
659
- InputBox,
660
- {
661
- ref,
662
- className: cn(defaultChatTheme.input, className),
663
- ...props
664
- }
665
- ) }) });
666
- });
667
- ChatInput.displayName = "ChatInput";
668
- var ChatFooter = React7.forwardRef(({ className, children, ...props }, ref) => {
669
- return /* @__PURE__ */ jsx6(
670
- "div",
671
- {
672
- ref,
673
- className: cn(
674
- "border-t border-gray-200 dark:border-gray-800 p-4 text-sm text-gray-500",
675
- className
676
- ),
677
- ...props,
678
- children
679
- }
680
- );
681
- });
682
- ChatFooter.displayName = "ChatFooter";
683
- var ChatComponents = Object.assign(Chat, {
684
- Header: ChatHeader,
685
- Messages: ChatMessages,
686
- Input: ChatInput,
687
- Footer: ChatFooter
688
- });
689
-
690
- // src/ai/react/components/agent-card.tsx
691
- import * as React8 from "react";
692
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
693
- var AgentCard = React8.forwardRef(
694
- ({
695
- messages,
696
- toolCalls = [],
697
- status,
698
- thinking,
699
- className,
700
- theme: userTheme,
701
- renderTool
702
- }, ref) => {
703
- const theme = mergeThemes(defaultAgentTheme, userTheme);
704
- return /* @__PURE__ */ jsxs4(AgentContainer, { ref, className: cn(theme.container, className), children: [
705
- /* @__PURE__ */ jsx7(
706
- AgentStatus,
707
- {
708
- status,
709
- className: cn(theme.status, getStatusColor(status))
710
- }
711
- ),
712
- thinking && /* @__PURE__ */ jsxs4(ThinkingIndicator, { className: theme.thinking, children: [
713
- /* @__PURE__ */ jsx7("span", { className: "font-semibold", children: "Thinking:" }),
714
- thinking
715
- ] }),
716
- toolCalls.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "space-y-3", children: [
717
- /* @__PURE__ */ jsx7("h3", { className: "text-sm font-semibold text-neutral-700 dark:text-neutral-300", children: "Tool Calls" }),
718
- /* @__PURE__ */ jsx7(
719
- ToolList,
720
- {
721
- toolCalls,
722
- className: "space-y-3",
723
- renderTool: renderTool || ((tool) => /* @__PURE__ */ jsxs4(
724
- ToolInvocation,
725
- {
726
- name: tool.name,
727
- args: tool.args,
728
- status: tool.status,
729
- className: theme.tool,
730
- children: [
731
- tool.result !== void 0 && /* @__PURE__ */ jsx7(ToolResult, { result: tool.result, className: theme.toolResult }),
732
- tool.error && /* @__PURE__ */ jsxs4("div", { className: "mt-2 p-3 bg-red-50 dark:bg-red-900/20 text-red-900 dark:text-red-100 rounded-xl text-sm border border-red-200 dark:border-red-800", children: [
733
- "Error: ",
734
- tool.error
735
- ] })
736
- ]
737
- }
738
- ))
739
- }
740
- )
741
- ] }),
742
- messages && messages.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "space-y-3", children: [
743
- /* @__PURE__ */ jsx7("h3", { className: "text-sm font-semibold text-neutral-700 dark:text-neutral-300", children: "Messages" }),
744
- /* @__PURE__ */ jsx7("div", { className: "space-y-2 max-h-96 overflow-y-auto", children: messages.map((msg) => /* @__PURE__ */ jsxs4(
745
- "div",
746
- {
747
- className: "text-sm p-3 rounded-xl bg-neutral-50 dark:bg-neutral-800",
748
- children: [
749
- /* @__PURE__ */ jsxs4("span", { className: "font-semibold capitalize text-neutral-900 dark:text-neutral-100", children: [
750
- msg.role,
751
- ":"
752
- ] }),
753
- /* @__PURE__ */ jsxs4("span", { className: "text-neutral-600 dark:text-neutral-400 ml-1", children: [
754
- msg.content.substring(0, 200),
755
- "..."
756
- ] })
757
- ]
758
- },
759
- msg.id
760
- )) })
761
- ] })
762
- ] });
763
- }
764
- );
765
- AgentCard.displayName = "AgentCard";
766
- function getStatusColor(status) {
767
- switch (status) {
768
- case "idle":
769
- return "bg-neutral-100 text-neutral-700 dark:bg-neutral-800 dark:text-neutral-300";
770
- case "thinking":
771
- return "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300";
772
- case "tool_execution":
773
- return "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-300";
774
- case "streaming":
775
- return "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300";
776
- case "completed":
777
- return "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300";
778
- case "error":
779
- return "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300";
780
- default:
781
- return "bg-neutral-100 text-neutral-700 dark:bg-neutral-800 dark:text-neutral-300";
782
- }
783
- }
784
-
785
- // src/ai/react/components/message.tsx
786
- import * as React9 from "react";
787
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
788
- var Message = React9.forwardRef(
789
- ({ message, className, theme: userTheme, showRole = false, showTimestamp = false }, ref) => {
790
- const theme = mergeThemes(defaultChatTheme, userTheme);
791
- return /* @__PURE__ */ jsx8(
792
- MessageItem,
793
- {
794
- ref,
795
- role: message.role,
796
- className: cn(
797
- "flex",
798
- message.role === "user" ? "justify-end" : "justify-start",
799
- className
800
- ),
801
- children: /* @__PURE__ */ jsxs5("div", { className: theme.message?.[message.role] || theme.message?.assistant, children: [
802
- showRole && /* @__PURE__ */ jsx8(MessageRole, { className: "block text-xs font-semibold mb-1 opacity-75 uppercase", children: message.role }),
803
- /* @__PURE__ */ jsx8(MessageContent, { children: message.content }),
804
- showTimestamp && message.timestamp && /* @__PURE__ */ jsx8("div", { className: "text-xs opacity-60 mt-1", children: new Date(message.timestamp).toLocaleTimeString() })
805
- ] })
806
- }
807
- );
808
- }
809
- );
810
- Message.displayName = "Message";
811
- var StreamingMessage = React9.forwardRef(({ content, showCursor = true, className, theme: userTheme }, ref) => {
812
- const theme = mergeThemes(defaultChatTheme, userTheme);
813
- return /* @__PURE__ */ jsx8(
814
- MessageItem,
815
- {
816
- ref,
817
- role: "assistant",
818
- className: cn("flex justify-start", className),
819
- children: /* @__PURE__ */ jsx8("div", { className: theme.message?.assistant, children: /* @__PURE__ */ jsxs5(MessageContent, { children: [
820
- content,
821
- showCursor && /* @__PURE__ */ jsx8("span", { className: "inline-block w-1 h-4 bg-current ml-1 animate-pulse" })
822
- ] }) })
823
- }
824
- );
825
- });
826
- StreamingMessage.displayName = "StreamingMessage";
827
-
828
- // src/ai/react/components/error-boundary.tsx
829
- import * as React10 from "react";
830
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
831
- var AIErrorBoundary = class extends React10.Component {
832
- constructor(props) {
833
- super(props);
834
- this.reset = () => {
835
- this.setState({ hasError: false, error: null });
836
- };
837
- this.state = { hasError: false, error: null };
838
- }
839
- static getDerivedStateFromError(error) {
840
- return { hasError: true, error };
841
- }
842
- componentDidCatch(error, errorInfo) {
843
- console.error("[AIErrorBoundary] Caught error:", error, errorInfo);
844
- if (this.props.onError) {
845
- this.props.onError(error, errorInfo);
846
- }
847
- }
848
- render() {
849
- if (this.state.hasError && this.state.error) {
850
- if (this.props.fallback) {
851
- if (typeof this.props.fallback === "function") {
852
- return this.props.fallback(this.state.error, this.reset);
853
- }
854
- return this.props.fallback;
855
- }
856
- return /* @__PURE__ */ jsx9(
857
- "div",
858
- {
859
- className: "border border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/20 rounded-2xl p-6",
860
- role: "alert",
861
- children: /* @__PURE__ */ jsxs6("div", { className: "flex items-start gap-4", children: [
862
- /* @__PURE__ */ jsx9("div", { className: "w-10 h-10 rounded-full bg-red-100 dark:bg-red-900/40 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx9(
863
- "svg",
864
- {
865
- className: "w-5 h-5 text-red-600 dark:text-red-400",
866
- fill: "none",
867
- viewBox: "0 0 24 24",
868
- stroke: "currentColor",
869
- children: /* @__PURE__ */ jsx9(
870
- "path",
871
- {
872
- strokeLinecap: "round",
873
- strokeLinejoin: "round",
874
- strokeWidth: 2,
875
- d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
876
- }
877
- )
878
- }
879
- ) }),
880
- /* @__PURE__ */ jsxs6("div", { className: "flex-1 min-w-0", children: [
881
- /* @__PURE__ */ jsx9("h3", { className: "text-base font-semibold text-red-900 dark:text-red-100", children: this.props.errorMessage || "An error occurred in the AI component" }),
882
- /* @__PURE__ */ jsx9("p", { className: "mt-1.5 text-sm text-red-700 dark:text-red-300 leading-relaxed", children: this.state.error.message }),
883
- /* @__PURE__ */ jsx9(
884
- "button",
885
- {
886
- type: "button",
887
- onClick: this.reset,
888
- className: "mt-4 px-5 py-2.5 text-sm font-medium text-white bg-red-500 hover:bg-red-600 active:scale-[0.98] rounded-full transition-all",
889
- children: "Try Again"
890
- }
891
- )
892
- ] })
893
- ] })
894
- }
895
- );
896
- }
897
- return this.props.children;
898
- }
899
- };
900
- function useAIErrorHandler() {
901
- const [error, setError] = React10.useState(null);
902
- const handleError = React10.useCallback((error2) => {
903
- console.error("[useAIErrorHandler] Error:", error2);
904
- setError(error2);
905
- }, []);
906
- const clearError = React10.useCallback(() => {
907
- setError(null);
908
- }, []);
909
- return {
910
- error,
911
- handleError,
912
- clearError,
913
- hasError: error !== null
914
- };
915
- }
916
- export {
917
- AIErrorBoundary,
918
- AgentCard,
919
- Chat,
920
- ChatComponents,
921
- Message,
922
- StreamingMessage,
923
- cn,
924
- defaultAgentTheme,
925
- defaultChatTheme,
926
- mergeThemes,
927
- useAIErrorHandler
928
- };
929
- //# sourceMappingURL=components.js.map