@ash-cloud/ash-ui 0.1.0 → 0.2.0
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/dist/design-tokens.cjs +20 -0
- package/dist/design-tokens.cjs.map +1 -1
- package/dist/design-tokens.d.cts +31 -1
- package/dist/design-tokens.d.ts +31 -1
- package/dist/design-tokens.js +20 -1
- package/dist/design-tokens.js.map +1 -1
- package/dist/icons.cjs +23 -0
- package/dist/icons.cjs.map +1 -1
- package/dist/icons.d.cts +4 -1
- package/dist/icons.d.ts +4 -1
- package/dist/icons.js +21 -1
- package/dist/icons.js.map +1 -1
- package/dist/index.cjs +2416 -1955
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +840 -641
- package/dist/index.d.ts +840 -641
- package/dist/index.js +2360 -1930
- package/dist/index.js.map +1 -1
- package/dist/styles-full.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/types.cjs +243 -6
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +197 -121
- package/dist/types.d.ts +197 -121
- package/dist/types.js +239 -6
- package/dist/types.js.map +1 -1
- package/dist/utils.cjs +0 -35
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +2 -28
- package/dist/utils.d.ts +2 -28
- package/dist/utils.js +1 -34
- package/dist/utils.js.map +1 -1
- package/package.json +22 -16
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
|
|
6
|
-
// src/components/
|
|
6
|
+
// src/components/Conversation.tsx
|
|
7
7
|
|
|
8
8
|
// src/utils.ts
|
|
9
9
|
function formatToolName(name) {
|
|
@@ -362,39 +362,6 @@ function truncate(str, maxLength) {
|
|
|
362
362
|
function cn(...classes) {
|
|
363
363
|
return classes.filter(Boolean).join(" ");
|
|
364
364
|
}
|
|
365
|
-
function groupEntriesForCompactMode(entries, config) {
|
|
366
|
-
const result = [];
|
|
367
|
-
let currentToolGroup = [];
|
|
368
|
-
let toolGroupCounter = 0;
|
|
369
|
-
const flushToolGroup = () => {
|
|
370
|
-
if (currentToolGroup.length > 0) {
|
|
371
|
-
result.push({
|
|
372
|
-
type: "tool_group",
|
|
373
|
-
entries: [...currentToolGroup],
|
|
374
|
-
id: `tool-group-${toolGroupCounter++}`
|
|
375
|
-
});
|
|
376
|
-
currentToolGroup = [];
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
for (const entry of entries) {
|
|
380
|
-
if (entry.entryType.type === "tool_call") {
|
|
381
|
-
currentToolGroup.push(entry);
|
|
382
|
-
if (config.breakEveryNToolCalls && config.breakEveryNToolCalls > 0 && currentToolGroup.length >= config.breakEveryNToolCalls) {
|
|
383
|
-
flushToolGroup();
|
|
384
|
-
}
|
|
385
|
-
} else {
|
|
386
|
-
flushToolGroup();
|
|
387
|
-
result.push({ type: "single", entry });
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
flushToolGroup();
|
|
391
|
-
return result;
|
|
392
|
-
}
|
|
393
|
-
function extractToolCallsFromGroup(entries) {
|
|
394
|
-
return entries.filter(
|
|
395
|
-
(e) => e.entryType.type === "tool_call"
|
|
396
|
-
).map((e) => e.entryType.toolCall);
|
|
397
|
-
}
|
|
398
365
|
function parseOptionsFromContent(content) {
|
|
399
366
|
const optionPattern = /(?:\*\*)?Option\s+(\d+)(?:\*\*)?[:\-]\s*([^\n]+)(?:\n((?:(?!\n(?:\*\*)?Option\s+\d).)*?))?/gi;
|
|
400
367
|
const options = [];
|
|
@@ -444,6 +411,376 @@ function parseOptionsFromContent(content) {
|
|
|
444
411
|
}
|
|
445
412
|
return null;
|
|
446
413
|
}
|
|
414
|
+
var ConversationContext = react.createContext(null);
|
|
415
|
+
function useConversation() {
|
|
416
|
+
const context = react.useContext(ConversationContext);
|
|
417
|
+
if (!context) {
|
|
418
|
+
throw new Error("useConversation must be used within a Conversation");
|
|
419
|
+
}
|
|
420
|
+
return context;
|
|
421
|
+
}
|
|
422
|
+
function Conversation({
|
|
423
|
+
children,
|
|
424
|
+
className,
|
|
425
|
+
autoScroll: initialAutoScroll = true,
|
|
426
|
+
scrollThreshold = 100
|
|
427
|
+
}) {
|
|
428
|
+
const containerRef = react.useRef(null);
|
|
429
|
+
const [isScrolledUp, setIsScrolledUp] = react.useState(false);
|
|
430
|
+
const [autoScroll, setAutoScroll] = react.useState(initialAutoScroll);
|
|
431
|
+
const scrollToBottom = react.useCallback((behavior = "smooth") => {
|
|
432
|
+
if (containerRef.current) {
|
|
433
|
+
containerRef.current.scrollTo({
|
|
434
|
+
top: containerRef.current.scrollHeight,
|
|
435
|
+
behavior
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}, []);
|
|
439
|
+
const handleScroll = react.useCallback(() => {
|
|
440
|
+
if (!containerRef.current) return;
|
|
441
|
+
const { scrollTop, scrollHeight, clientHeight } = containerRef.current;
|
|
442
|
+
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
|
|
443
|
+
const isAtBottom = distanceFromBottom < scrollThreshold;
|
|
444
|
+
setIsScrolledUp(!isAtBottom);
|
|
445
|
+
if (isAtBottom && !autoScroll) {
|
|
446
|
+
setAutoScroll(true);
|
|
447
|
+
}
|
|
448
|
+
}, [scrollThreshold, autoScroll]);
|
|
449
|
+
react.useEffect(() => {
|
|
450
|
+
if (autoScroll && !isScrolledUp) {
|
|
451
|
+
scrollToBottom("instant");
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
const contextValue = {
|
|
455
|
+
containerRef,
|
|
456
|
+
scrollToBottom,
|
|
457
|
+
isScrolledUp,
|
|
458
|
+
autoScroll,
|
|
459
|
+
setAutoScroll
|
|
460
|
+
};
|
|
461
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ConversationContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
462
|
+
"div",
|
|
463
|
+
{
|
|
464
|
+
ref: containerRef,
|
|
465
|
+
onScroll: handleScroll,
|
|
466
|
+
className: cn(
|
|
467
|
+
"ash-conversation flex flex-col overflow-y-auto",
|
|
468
|
+
"ash-scrollbar",
|
|
469
|
+
className
|
|
470
|
+
),
|
|
471
|
+
role: "log",
|
|
472
|
+
"aria-live": "polite",
|
|
473
|
+
children
|
|
474
|
+
}
|
|
475
|
+
) });
|
|
476
|
+
}
|
|
477
|
+
function ConversationContent({
|
|
478
|
+
children,
|
|
479
|
+
className
|
|
480
|
+
}) {
|
|
481
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
482
|
+
"div",
|
|
483
|
+
{
|
|
484
|
+
className: cn(
|
|
485
|
+
"ash-conversation-content flex flex-col",
|
|
486
|
+
"gap-[var(--ash-message-list-gap,0.25rem)]",
|
|
487
|
+
"p-[var(--ash-spacing-md,0.75rem)]",
|
|
488
|
+
className
|
|
489
|
+
),
|
|
490
|
+
children
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
function ConversationEmptyState({
|
|
495
|
+
children,
|
|
496
|
+
className
|
|
497
|
+
}) {
|
|
498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
499
|
+
"div",
|
|
500
|
+
{
|
|
501
|
+
className: cn(
|
|
502
|
+
"ash-conversation-empty flex flex-col items-center justify-center",
|
|
503
|
+
"flex-1 min-h-[200px] text-center",
|
|
504
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
505
|
+
className
|
|
506
|
+
),
|
|
507
|
+
children
|
|
508
|
+
}
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
function ConversationScrollButton({
|
|
512
|
+
className,
|
|
513
|
+
label = "Scroll to bottom"
|
|
514
|
+
}) {
|
|
515
|
+
const { isScrolledUp, scrollToBottom } = useConversation();
|
|
516
|
+
if (!isScrolledUp) return null;
|
|
517
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
518
|
+
"button",
|
|
519
|
+
{
|
|
520
|
+
onClick: () => scrollToBottom(),
|
|
521
|
+
className: cn(
|
|
522
|
+
"ash-conversation-scroll-btn",
|
|
523
|
+
"fixed bottom-20 left-1/2 -translate-x-1/2",
|
|
524
|
+
"px-4 py-2 rounded-full",
|
|
525
|
+
"bg-[var(--ash-surface-elevated,#111)] border border-[var(--ash-border,rgba(255,255,255,0.08))]",
|
|
526
|
+
"text-[var(--ash-text-secondary,rgba(255,255,255,0.7))] text-sm",
|
|
527
|
+
"hover:bg-[var(--ash-surface-card,#0c0c0c)] hover:border-[var(--ash-border-emphasis,rgba(255,255,255,0.15))]",
|
|
528
|
+
"transition-all duration-200",
|
|
529
|
+
"shadow-lg",
|
|
530
|
+
className
|
|
531
|
+
),
|
|
532
|
+
"aria-label": label,
|
|
533
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
|
|
534
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
535
|
+
"svg",
|
|
536
|
+
{
|
|
537
|
+
className: "w-4 h-4",
|
|
538
|
+
fill: "none",
|
|
539
|
+
stroke: "currentColor",
|
|
540
|
+
viewBox: "0 0 24 24",
|
|
541
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
542
|
+
"path",
|
|
543
|
+
{
|
|
544
|
+
strokeLinecap: "round",
|
|
545
|
+
strokeLinejoin: "round",
|
|
546
|
+
strokeWidth: 2,
|
|
547
|
+
d: "M19 14l-7 7m0 0l-7-7m7 7V3"
|
|
548
|
+
}
|
|
549
|
+
)
|
|
550
|
+
}
|
|
551
|
+
),
|
|
552
|
+
label
|
|
553
|
+
] })
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
var ReactMarkdown = react.lazy(() => import('react-markdown'));
|
|
558
|
+
function LazyMarkdown({ children, fallback, components, className }) {
|
|
559
|
+
const [mounted, setMounted] = react.useState(false);
|
|
560
|
+
react.useEffect(() => {
|
|
561
|
+
setMounted(true);
|
|
562
|
+
}, []);
|
|
563
|
+
const markdownComponents = react.useMemo(() => {
|
|
564
|
+
if (!components) return void 0;
|
|
565
|
+
return components;
|
|
566
|
+
}, [components]);
|
|
567
|
+
if (!mounted) {
|
|
568
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: fallback ?? children });
|
|
569
|
+
}
|
|
570
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: fallback ?? children }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown, { components: markdownComponents, children }) });
|
|
571
|
+
}
|
|
572
|
+
var MessageContext = react.createContext(null);
|
|
573
|
+
function useMessage() {
|
|
574
|
+
const context = react.useContext(MessageContext);
|
|
575
|
+
if (!context) {
|
|
576
|
+
throw new Error("useMessage must be used within a Message");
|
|
577
|
+
}
|
|
578
|
+
return context;
|
|
579
|
+
}
|
|
580
|
+
function Message({
|
|
581
|
+
from,
|
|
582
|
+
children,
|
|
583
|
+
className,
|
|
584
|
+
isStreaming,
|
|
585
|
+
toolInvocations,
|
|
586
|
+
id
|
|
587
|
+
}) {
|
|
588
|
+
const contextValue = {
|
|
589
|
+
from,
|
|
590
|
+
isStreaming,
|
|
591
|
+
toolInvocations
|
|
592
|
+
};
|
|
593
|
+
const roleMap = {
|
|
594
|
+
user: "user",
|
|
595
|
+
assistant: "assistant",
|
|
596
|
+
system: "system"
|
|
597
|
+
};
|
|
598
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MessageContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
599
|
+
"div",
|
|
600
|
+
{
|
|
601
|
+
className: cn(
|
|
602
|
+
"ash-message",
|
|
603
|
+
"flex gap-[var(--ash-message-gap,0.5rem)]",
|
|
604
|
+
from === "user" && "flex-row-reverse",
|
|
605
|
+
className
|
|
606
|
+
),
|
|
607
|
+
"data-message-role": roleMap[from],
|
|
608
|
+
"data-message-id": id,
|
|
609
|
+
children
|
|
610
|
+
}
|
|
611
|
+
) });
|
|
612
|
+
}
|
|
613
|
+
function MessageAvatar({ src, fallback, className }) {
|
|
614
|
+
const { from } = useMessage();
|
|
615
|
+
const defaultFallback = from === "user" ? "U" : from === "assistant" ? "A" : "S";
|
|
616
|
+
const displayFallback = fallback || defaultFallback;
|
|
617
|
+
const bgColorMap = {
|
|
618
|
+
user: "var(--ash-avatar-user-bg,rgba(255,255,255,0.1))",
|
|
619
|
+
assistant: "var(--ash-avatar-assistant-bg,#10a37f)",
|
|
620
|
+
system: "var(--ash-avatar-user-bg,rgba(255,255,255,0.1))"
|
|
621
|
+
};
|
|
622
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
623
|
+
"div",
|
|
624
|
+
{
|
|
625
|
+
className: cn(
|
|
626
|
+
"ash-message-avatar flex-shrink-0",
|
|
627
|
+
"w-[var(--ash-avatar-size,1.25rem)] h-[var(--ash-avatar-size,1.25rem)]",
|
|
628
|
+
"rounded-full flex items-center justify-center",
|
|
629
|
+
"text-[var(--ash-font-size-xs,10px)] font-medium",
|
|
630
|
+
from === "assistant" ? "text-white" : "text-[var(--ash-text-secondary,rgba(255,255,255,0.7))]",
|
|
631
|
+
className
|
|
632
|
+
),
|
|
633
|
+
style: { backgroundColor: bgColorMap[from] },
|
|
634
|
+
children: src ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
635
|
+
"img",
|
|
636
|
+
{
|
|
637
|
+
src,
|
|
638
|
+
alt: `${from} avatar`,
|
|
639
|
+
className: "w-full h-full rounded-full object-cover"
|
|
640
|
+
}
|
|
641
|
+
) : displayFallback
|
|
642
|
+
}
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
function MessageContent({ children, className }) {
|
|
646
|
+
const { from } = useMessage();
|
|
647
|
+
const roleStyles = {
|
|
648
|
+
user: cn(
|
|
649
|
+
"bg-[var(--ash-user-bg,#5B6EF5)]",
|
|
650
|
+
"text-[var(--ash-user-text,#ffffff)]",
|
|
651
|
+
"border-[var(--ash-user-border,transparent)]"
|
|
652
|
+
),
|
|
653
|
+
assistant: cn(
|
|
654
|
+
"bg-[var(--ash-assistant-bg,#1a1a1a)]",
|
|
655
|
+
"text-[var(--ash-assistant-text,rgba(255,255,255,0.9))]",
|
|
656
|
+
"border-[var(--ash-assistant-border,rgba(255,255,255,0.08))]"
|
|
657
|
+
),
|
|
658
|
+
system: cn(
|
|
659
|
+
"bg-[var(--ash-surface-elevated,#111111)]",
|
|
660
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
661
|
+
"border-[var(--ash-border,rgba(255,255,255,0.08))]"
|
|
662
|
+
)
|
|
663
|
+
};
|
|
664
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
665
|
+
"div",
|
|
666
|
+
{
|
|
667
|
+
className: cn(
|
|
668
|
+
"ash-message-content",
|
|
669
|
+
"flex-1 min-w-0",
|
|
670
|
+
"rounded-[var(--ash-radius-lg,0.75rem)]",
|
|
671
|
+
"p-[var(--ash-message-padding,0.5rem_0.75rem)]",
|
|
672
|
+
"border",
|
|
673
|
+
roleStyles[from],
|
|
674
|
+
from === "user" && "rounded-tr-sm",
|
|
675
|
+
from === "assistant" && "rounded-tl-sm",
|
|
676
|
+
className
|
|
677
|
+
),
|
|
678
|
+
children
|
|
679
|
+
}
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
function MessageResponse({
|
|
683
|
+
content,
|
|
684
|
+
isStreaming,
|
|
685
|
+
className,
|
|
686
|
+
components
|
|
687
|
+
}) {
|
|
688
|
+
if (!content) return null;
|
|
689
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
690
|
+
"div",
|
|
691
|
+
{
|
|
692
|
+
className: cn(
|
|
693
|
+
"ash-message-response",
|
|
694
|
+
"font-[var(--ash-font-size-base,13px)]",
|
|
695
|
+
"leading-relaxed",
|
|
696
|
+
isStreaming && "animate-pulse",
|
|
697
|
+
className
|
|
698
|
+
),
|
|
699
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(LazyMarkdown, { components, children: content })
|
|
700
|
+
}
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
function MessageActions({ children, className }) {
|
|
704
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
705
|
+
"div",
|
|
706
|
+
{
|
|
707
|
+
className: cn(
|
|
708
|
+
"ash-message-actions",
|
|
709
|
+
"flex items-center gap-1 mt-2",
|
|
710
|
+
"opacity-0 group-hover:opacity-100 transition-opacity",
|
|
711
|
+
className
|
|
712
|
+
),
|
|
713
|
+
children
|
|
714
|
+
}
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
function MessageAction({
|
|
718
|
+
icon,
|
|
719
|
+
label,
|
|
720
|
+
onClick,
|
|
721
|
+
className
|
|
722
|
+
}) {
|
|
723
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
724
|
+
"button",
|
|
725
|
+
{
|
|
726
|
+
onClick,
|
|
727
|
+
className: cn(
|
|
728
|
+
"ash-message-action",
|
|
729
|
+
"p-1.5 rounded-md",
|
|
730
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
731
|
+
"hover:text-[var(--ash-text-secondary,rgba(255,255,255,0.7))]",
|
|
732
|
+
"hover:bg-[var(--ash-surface-elevated,#111111)]",
|
|
733
|
+
"transition-colors",
|
|
734
|
+
className
|
|
735
|
+
),
|
|
736
|
+
title: label,
|
|
737
|
+
"aria-label": label,
|
|
738
|
+
children: icon || label
|
|
739
|
+
}
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
function MessageTimestamp({ timestamp, className }) {
|
|
743
|
+
const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
744
|
+
const formatted = date.toLocaleTimeString(void 0, {
|
|
745
|
+
hour: "numeric",
|
|
746
|
+
minute: "2-digit"
|
|
747
|
+
});
|
|
748
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
749
|
+
"span",
|
|
750
|
+
{
|
|
751
|
+
className: cn(
|
|
752
|
+
"ash-message-timestamp",
|
|
753
|
+
"text-[var(--ash-font-size-xs,10px)]",
|
|
754
|
+
"text-[var(--ash-text-faint,rgba(255,255,255,0.3))]",
|
|
755
|
+
className
|
|
756
|
+
),
|
|
757
|
+
children: formatted
|
|
758
|
+
}
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
function StatusIndicator({ status, size = "sm", className }) {
|
|
762
|
+
const sizeClasses = {
|
|
763
|
+
sm: "w-2 h-2",
|
|
764
|
+
md: "w-3 h-3",
|
|
765
|
+
lg: "w-4 h-4"
|
|
766
|
+
};
|
|
767
|
+
const statusClasses = {
|
|
768
|
+
pending: "ash-status-pending",
|
|
769
|
+
success: "ash-status-success",
|
|
770
|
+
failed: "ash-status-failed"
|
|
771
|
+
};
|
|
772
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
773
|
+
"div",
|
|
774
|
+
{
|
|
775
|
+
className: cn(
|
|
776
|
+
"rounded-full flex-shrink-0",
|
|
777
|
+
sizeClasses[size],
|
|
778
|
+
statusClasses[status],
|
|
779
|
+
className
|
|
780
|
+
)
|
|
781
|
+
}
|
|
782
|
+
);
|
|
783
|
+
}
|
|
447
784
|
function SunIcon({ className }) {
|
|
448
785
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
449
786
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "5" }),
|
|
@@ -694,57 +1031,25 @@ function ErrorIcon({ className }) {
|
|
|
694
1031
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
|
|
695
1032
|
] });
|
|
696
1033
|
}
|
|
697
|
-
function
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
pending: "ash-status-pending",
|
|
705
|
-
success: "ash-status-success",
|
|
706
|
-
failed: "ash-status-failed"
|
|
707
|
-
};
|
|
708
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
709
|
-
"div",
|
|
710
|
-
{
|
|
711
|
-
className: cn(
|
|
712
|
-
"rounded-full flex-shrink-0",
|
|
713
|
-
sizeClasses[size],
|
|
714
|
-
statusClasses[status],
|
|
715
|
-
className
|
|
716
|
-
)
|
|
717
|
-
}
|
|
718
|
-
);
|
|
1034
|
+
function MicrophoneIcon({ className }) {
|
|
1035
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1036
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
|
|
1037
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1038
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
|
|
1039
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
|
|
1040
|
+
] });
|
|
719
1041
|
}
|
|
720
|
-
function
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className });
|
|
732
|
-
case "glob":
|
|
733
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FolderSearchIcon, { className });
|
|
734
|
-
case "web_fetch":
|
|
735
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GlobeIcon, { className });
|
|
736
|
-
case "web_search":
|
|
737
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className });
|
|
738
|
-
case "mcp_tool":
|
|
739
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PlugIcon, { className });
|
|
740
|
-
case "todo_write":
|
|
741
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ListChecksIcon, { className });
|
|
742
|
-
case "agent_tool":
|
|
743
|
-
return /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className });
|
|
744
|
-
case "generic_tool":
|
|
745
|
-
default:
|
|
746
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ToolIcon, { className });
|
|
747
|
-
}
|
|
1042
|
+
function HomeIcon({ className }) {
|
|
1043
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1044
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }),
|
|
1045
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 22 9 12 15 12 15 22" })
|
|
1046
|
+
] });
|
|
1047
|
+
}
|
|
1048
|
+
function ArrowUpIcon({ className }) {
|
|
1049
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1050
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
|
|
1051
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "5 12 12 5 19 12" })
|
|
1052
|
+
] });
|
|
748
1053
|
}
|
|
749
1054
|
function CodeBlock({
|
|
750
1055
|
children,
|
|
@@ -754,14 +1059,41 @@ function CodeBlock({
|
|
|
754
1059
|
className
|
|
755
1060
|
}) {
|
|
756
1061
|
const [expanded, setExpanded] = react.useState(false);
|
|
1062
|
+
const [copied, setCopied] = react.useState(false);
|
|
757
1063
|
const lines = children.split("\n");
|
|
758
1064
|
const isLong = lines.length > 10 || children.length > 500;
|
|
759
|
-
|
|
1065
|
+
const handleCopy = react.useCallback(async () => {
|
|
1066
|
+
try {
|
|
1067
|
+
await navigator.clipboard.writeText(children);
|
|
1068
|
+
setCopied(true);
|
|
1069
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1070
|
+
} catch (err) {
|
|
1071
|
+
console.error("Failed to copy:", err);
|
|
1072
|
+
}
|
|
1073
|
+
}, [children]);
|
|
1074
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative rounded-lg overflow-hidden border border-white/10", className), children: [
|
|
1075
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2 bg-[var(--ash-code-header-bg)] border-b border-white/10", children: [
|
|
1076
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/60 font-medium", children: language || "code" }),
|
|
1077
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1078
|
+
"button",
|
|
1079
|
+
{
|
|
1080
|
+
onClick: handleCopy,
|
|
1081
|
+
className: "flex items-center gap-1.5 text-xs text-white/60 hover:text-white transition-colors",
|
|
1082
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1083
|
+
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "w-3.5 h-3.5" }),
|
|
1084
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copied!" })
|
|
1085
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1086
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { className: "w-3.5 h-3.5" }),
|
|
1087
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copy" })
|
|
1088
|
+
] })
|
|
1089
|
+
}
|
|
1090
|
+
)
|
|
1091
|
+
] }),
|
|
760
1092
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
761
1093
|
"pre",
|
|
762
1094
|
{
|
|
763
1095
|
className: cn(
|
|
764
|
-
"
|
|
1096
|
+
"text-xs font-mono text-white/90 p-4 bg-black/30 overflow-x-auto whitespace-pre-wrap break-words",
|
|
765
1097
|
!expanded && isLong && "overflow-y-hidden"
|
|
766
1098
|
),
|
|
767
1099
|
style: !expanded && isLong ? { maxHeight } : void 0,
|
|
@@ -794,1519 +1126,1173 @@ function JsonDisplay({ value, maxHeight, className }) {
|
|
|
794
1126
|
const formatted = JSON.stringify(value, null, 2);
|
|
795
1127
|
return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { maxHeight, className, children: formatted });
|
|
796
1128
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
1129
|
+
var ToolContext = react.createContext(null);
|
|
1130
|
+
function useTool() {
|
|
1131
|
+
const context = react.useContext(ToolContext);
|
|
1132
|
+
if (!context) {
|
|
1133
|
+
throw new Error("useTool must be used within a Tool");
|
|
1134
|
+
}
|
|
1135
|
+
return context;
|
|
1136
|
+
}
|
|
1137
|
+
function Tool({
|
|
1138
|
+
toolInvocation,
|
|
1139
|
+
children,
|
|
800
1140
|
className,
|
|
801
|
-
|
|
1141
|
+
defaultExpanded = false
|
|
802
1142
|
}) {
|
|
803
|
-
const [
|
|
804
|
-
const
|
|
805
|
-
const
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1143
|
+
const [isExpanded, setIsExpanded] = react.useState(defaultExpanded);
|
|
1144
|
+
const toggleExpanded = () => setIsExpanded((prev) => !prev);
|
|
1145
|
+
const contextValue = {
|
|
1146
|
+
toolInvocation,
|
|
1147
|
+
isExpanded,
|
|
1148
|
+
toggleExpanded
|
|
1149
|
+
};
|
|
1150
|
+
const status = toolInvocation.state === "result" ? "success" : "pending";
|
|
1151
|
+
const isErrorResult = Boolean(
|
|
1152
|
+
toolInvocation.result && typeof toolInvocation.result === "object" && "error" in toolInvocation.result
|
|
1153
|
+
);
|
|
1154
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToolContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1155
|
+
"div",
|
|
1156
|
+
{
|
|
1157
|
+
className: cn(
|
|
1158
|
+
"ash-tool",
|
|
1159
|
+
"rounded-[var(--ash-radius-md,0.5rem)]",
|
|
1160
|
+
"border border-[var(--ash-border,rgba(255,255,255,0.08))]",
|
|
1161
|
+
"bg-[var(--ash-tool-bg,var(--ash-surface-dark,#0a0a0a))]",
|
|
1162
|
+
"overflow-hidden",
|
|
1163
|
+
status === "pending" && "ash-tool-status-pending",
|
|
1164
|
+
isErrorResult && "border-red-500/30",
|
|
1165
|
+
className
|
|
1166
|
+
),
|
|
1167
|
+
"data-tool-name": toolInvocation.toolName,
|
|
1168
|
+
"data-tool-state": toolInvocation.state,
|
|
1169
|
+
children: children || /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1170
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolHeader, {}),
|
|
1171
|
+
isExpanded && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1172
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolInput, {}),
|
|
1173
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolOutput, {})
|
|
1174
|
+
] })
|
|
1175
|
+
] })
|
|
810
1176
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
const
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1177
|
+
) });
|
|
1178
|
+
}
|
|
1179
|
+
function ToolHeader({
|
|
1180
|
+
className,
|
|
1181
|
+
icon,
|
|
1182
|
+
showToggle = true
|
|
1183
|
+
}) {
|
|
1184
|
+
const { toolInvocation, isExpanded, toggleExpanded } = useTool();
|
|
1185
|
+
const status = toolInvocation.state === "result" ? "success" : "pending";
|
|
1186
|
+
const formattedName = formatToolName(toolInvocation.toolName);
|
|
1187
|
+
const toolIcon = icon;
|
|
1188
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1189
|
+
"button",
|
|
1190
|
+
{
|
|
1191
|
+
onClick: showToggle ? toggleExpanded : void 0,
|
|
1192
|
+
className: cn(
|
|
1193
|
+
"ash-tool-header",
|
|
1194
|
+
"w-full flex items-center gap-2",
|
|
1195
|
+
"px-3 py-2",
|
|
1196
|
+
"text-left",
|
|
1197
|
+
showToggle && "cursor-pointer hover:bg-white/[0.03] transition-colors",
|
|
1198
|
+
className
|
|
1199
|
+
),
|
|
1200
|
+
children: [
|
|
1201
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status, size: "sm" }),
|
|
1202
|
+
toolIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--ash-text-muted,rgba(255,255,255,0.5))]", children: toolIcon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--ash-text-muted,rgba(255,255,255,0.5))]", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
|
|
1203
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" }),
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })
|
|
1205
|
+
] }) }),
|
|
1206
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1207
|
+
"span",
|
|
1208
|
+
{
|
|
1209
|
+
className: cn(
|
|
1210
|
+
"flex-1 font-medium",
|
|
1211
|
+
"text-[var(--ash-font-size-sm,12px)]",
|
|
1212
|
+
"text-[var(--ash-text-primary,rgba(255,255,255,0.9))]"
|
|
1213
|
+
),
|
|
1214
|
+
children: formattedName
|
|
1215
|
+
}
|
|
1216
|
+
),
|
|
1217
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1218
|
+
"span",
|
|
1219
|
+
{
|
|
1220
|
+
className: cn(
|
|
1221
|
+
"text-[var(--ash-font-size-xs,10px)]",
|
|
1222
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1223
|
+
"truncate max-w-[200px]"
|
|
1224
|
+
),
|
|
1225
|
+
children: Object.keys(toolInvocation.args).length > 0 && `(${Object.keys(toolInvocation.args).join(", ")})`
|
|
1226
|
+
}
|
|
1227
|
+
),
|
|
1228
|
+
showToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1229
|
+
"svg",
|
|
1230
|
+
{
|
|
1231
|
+
className: cn(
|
|
1232
|
+
"w-4 h-4 text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1233
|
+
"transition-transform",
|
|
1234
|
+
isExpanded && "rotate-180"
|
|
1235
|
+
),
|
|
1236
|
+
fill: "none",
|
|
1237
|
+
stroke: "currentColor",
|
|
1238
|
+
viewBox: "0 0 24 24",
|
|
1239
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1240
|
+
"path",
|
|
1241
|
+
{
|
|
1242
|
+
strokeLinecap: "round",
|
|
1243
|
+
strokeLinejoin: "round",
|
|
1244
|
+
strokeWidth: 2,
|
|
1245
|
+
d: "M19 9l-7 7-7-7"
|
|
1246
|
+
}
|
|
1247
|
+
)
|
|
1248
|
+
}
|
|
1249
|
+
)
|
|
1250
|
+
]
|
|
838
1251
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
function ToolInput({ className, maxHeight = 200 }) {
|
|
1255
|
+
const { toolInvocation } = useTool();
|
|
1256
|
+
if (!toolInvocation.args || Object.keys(toolInvocation.args).length === 0) {
|
|
842
1257
|
return null;
|
|
843
1258
|
}
|
|
844
|
-
const { agentType, description, prompt } = agentData;
|
|
845
|
-
const indentClass = depth > 0 ? "ml-4" : "";
|
|
846
1259
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
847
1260
|
"div",
|
|
848
1261
|
{
|
|
849
1262
|
className: cn(
|
|
850
|
-
"
|
|
851
|
-
|
|
852
|
-
indentClass,
|
|
1263
|
+
"ash-tool-input",
|
|
1264
|
+
"border-t border-[var(--ash-border-subtle,rgba(255,255,255,0.04))]",
|
|
853
1265
|
className
|
|
854
1266
|
),
|
|
855
1267
|
children: [
|
|
856
|
-
/* @__PURE__ */ jsxRuntime.
|
|
857
|
-
|
|
1268
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-tool-section-header", children: "Input" }),
|
|
1269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1270
|
+
"div",
|
|
858
1271
|
{
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
children:
|
|
862
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
863
|
-
ChevronRightIcon,
|
|
864
|
-
{
|
|
865
|
-
className: cn(
|
|
866
|
-
"w-4 h-4 text-white/40 transition-transform duration-200 shrink-0",
|
|
867
|
-
expanded && "rotate-90"
|
|
868
|
-
)
|
|
869
|
-
}
|
|
870
|
-
),
|
|
871
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
872
|
-
"div",
|
|
873
|
-
{
|
|
874
|
-
className: cn(
|
|
875
|
-
"w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
|
|
876
|
-
isRunning ? "bg-yellow-500/20" : status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
|
|
877
|
-
),
|
|
878
|
-
children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
879
|
-
SpinnerIcon,
|
|
880
|
-
{
|
|
881
|
-
className: "w-3.5 h-3.5 text-yellow-400 animate-spin"
|
|
882
|
-
}
|
|
883
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
884
|
-
BotIcon,
|
|
885
|
-
{
|
|
886
|
-
className: cn(
|
|
887
|
-
"w-3.5 h-3.5",
|
|
888
|
-
status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
|
|
889
|
-
)
|
|
890
|
-
}
|
|
891
|
-
)
|
|
892
|
-
}
|
|
893
|
-
),
|
|
894
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
895
|
-
"span",
|
|
896
|
-
{
|
|
897
|
-
className: cn(
|
|
898
|
-
"px-2 py-0.5 rounded text-xs font-medium shrink-0",
|
|
899
|
-
isRunning ? "bg-yellow-500/20 text-yellow-400" : status === "failed" ? "bg-red-500/20 text-red-400" : "bg-white/10 text-white/70"
|
|
900
|
-
),
|
|
901
|
-
children: agentType
|
|
902
|
-
}
|
|
903
|
-
),
|
|
904
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-white/80 truncate flex-1 text-left", children: description || summary }),
|
|
905
|
-
toolCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/50 shrink-0", children: [
|
|
906
|
-
toolCount,
|
|
907
|
-
" tool call",
|
|
908
|
-
toolCount !== 1 ? "s" : ""
|
|
909
|
-
] }),
|
|
910
|
-
isRunning && elapsedTime && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-xs text-white/40 shrink-0", children: [
|
|
911
|
-
/* @__PURE__ */ jsxRuntime.jsx(ClockIcon, { className: "w-3 h-3" }),
|
|
912
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: elapsedTime })
|
|
913
|
-
] }),
|
|
914
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/30 shrink-0", children: "..." })
|
|
915
|
-
]
|
|
1272
|
+
className: "p-3 overflow-auto",
|
|
1273
|
+
style: { maxHeight },
|
|
1274
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: toolInvocation.args })
|
|
916
1275
|
}
|
|
917
|
-
)
|
|
918
|
-
expanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-white/5 bg-black/20", children: [
|
|
919
|
-
prompt && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-white/5", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/70 whitespace-pre-wrap", children: prompt.length > 500 ? prompt.substring(0, 500) + "..." : prompt }) }),
|
|
920
|
-
nestedToolCalls && nestedToolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 space-y-2", children: nestedToolCalls.map((nestedCall) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: nestedCall.actionType.action === "agent_tool" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
921
|
-
AgentToolCard,
|
|
922
|
-
{
|
|
923
|
-
toolCall: nestedCall,
|
|
924
|
-
defaultExpanded: false,
|
|
925
|
-
depth: depth + 1
|
|
926
|
-
}
|
|
927
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
928
|
-
ToolCallCard,
|
|
929
|
-
{
|
|
930
|
-
toolCall: nestedCall,
|
|
931
|
-
defaultExpanded: false
|
|
932
|
-
}
|
|
933
|
-
) }, nestedCall.id)) }),
|
|
934
|
-
(!nestedToolCalls || nestedToolCalls.length === 0) && isRunning && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-6 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-white/40", children: [
|
|
935
|
-
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "w-4 h-4 animate-spin" }),
|
|
936
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Agent is working..." })
|
|
937
|
-
] }) }),
|
|
938
|
-
(!nestedToolCalls || nestedToolCalls.length === 0) && !isRunning && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-4 text-sm text-white/40 text-center", children: "No tool calls recorded" })
|
|
939
|
-
] })
|
|
1276
|
+
)
|
|
940
1277
|
]
|
|
941
1278
|
}
|
|
942
1279
|
);
|
|
943
1280
|
}
|
|
944
|
-
function
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2", children });
|
|
949
|
-
}
|
|
950
|
-
function CommandRunDetails({ action }) {
|
|
951
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
952
|
-
action.command && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
953
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "COMMAND" }),
|
|
954
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: action.command }) })
|
|
955
|
-
] }),
|
|
956
|
-
action.result?.output && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
957
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "OUTPUT" }),
|
|
958
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SectionContent, { children: [
|
|
959
|
-
/* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { maxHeight: 300, children: action.result.output }),
|
|
960
|
-
action.result.exitCode !== void 0 && action.result.exitCode !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-xs text-red-400", children: [
|
|
961
|
-
"Exit code: ",
|
|
962
|
-
action.result.exitCode
|
|
963
|
-
] })
|
|
964
|
-
] })
|
|
965
|
-
] })
|
|
966
|
-
] });
|
|
967
|
-
}
|
|
968
|
-
function FileReadDetails({ action }) {
|
|
969
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
970
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "PATH" }),
|
|
971
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SectionContent, { children: [
|
|
972
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: action.path }),
|
|
973
|
-
(action.offset !== void 0 || action.limit !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 text-xs text-white/50", children: [
|
|
974
|
-
action.offset !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
975
|
-
"Offset: ",
|
|
976
|
-
action.offset
|
|
977
|
-
] }),
|
|
978
|
-
action.offset !== void 0 && action.limit !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { children: " \xB7 " }),
|
|
979
|
-
action.limit !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
980
|
-
"Limit: ",
|
|
981
|
-
action.limit
|
|
982
|
-
] })
|
|
983
|
-
] })
|
|
984
|
-
] })
|
|
985
|
-
] });
|
|
986
|
-
}
|
|
987
|
-
function FileEditDetails({ action }) {
|
|
988
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
989
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "PATH" }),
|
|
990
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: action.path }) }),
|
|
991
|
-
action.oldString && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
992
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "OLD" }),
|
|
993
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: action.oldString }) })
|
|
994
|
-
] }),
|
|
995
|
-
action.newString && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
996
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "NEW" }),
|
|
997
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: action.newString }) })
|
|
998
|
-
] })
|
|
999
|
-
] });
|
|
1000
|
-
}
|
|
1001
|
-
function FileWriteDetails({ action }) {
|
|
1002
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1003
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "PATH" }),
|
|
1004
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: action.path }) }),
|
|
1005
|
-
action.content && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1006
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "CONTENT" }),
|
|
1007
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { maxHeight: 300, children: action.content }) })
|
|
1008
|
-
] })
|
|
1009
|
-
] });
|
|
1010
|
-
}
|
|
1011
|
-
function SearchDetails({ action }) {
|
|
1012
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1013
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "PATTERN" }),
|
|
1014
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SectionContent, { children: [
|
|
1015
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: action.pattern }),
|
|
1016
|
-
(action.path || action.glob || action.type) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 text-xs text-white/50", children: [
|
|
1017
|
-
action.path && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1018
|
-
"Path: ",
|
|
1019
|
-
action.path
|
|
1020
|
-
] }),
|
|
1021
|
-
action.glob && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1022
|
-
"Glob: ",
|
|
1023
|
-
action.glob
|
|
1024
|
-
] }),
|
|
1025
|
-
action.type && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1026
|
-
"Type: ",
|
|
1027
|
-
action.type
|
|
1028
|
-
] })
|
|
1029
|
-
] })
|
|
1030
|
-
] })
|
|
1031
|
-
] });
|
|
1032
|
-
}
|
|
1033
|
-
function GlobDetails({ action }) {
|
|
1034
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1035
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "PATTERN" }),
|
|
1036
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SectionContent, { children: [
|
|
1037
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: action.pattern }),
|
|
1038
|
-
action.path && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 text-xs text-white/50", children: [
|
|
1039
|
-
"Path: ",
|
|
1040
|
-
action.path
|
|
1041
|
-
] })
|
|
1042
|
-
] })
|
|
1043
|
-
] });
|
|
1044
|
-
}
|
|
1045
|
-
function WebFetchDetails({ action }) {
|
|
1046
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1047
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "URL" }),
|
|
1048
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SectionContent, { children: [
|
|
1049
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1050
|
-
"a",
|
|
1051
|
-
{
|
|
1052
|
-
href: action.url,
|
|
1053
|
-
target: "_blank",
|
|
1054
|
-
rel: "noopener noreferrer",
|
|
1055
|
-
className: "text-xs text-blue-400 hover:text-blue-300 underline break-all",
|
|
1056
|
-
children: action.url
|
|
1057
|
-
}
|
|
1058
|
-
),
|
|
1059
|
-
action.prompt && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-xs text-white/50", children: action.prompt })
|
|
1060
|
-
] })
|
|
1061
|
-
] });
|
|
1062
|
-
}
|
|
1063
|
-
function WebSearchDetails({ action }) {
|
|
1064
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1065
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "QUERY" }),
|
|
1066
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-white/90", children: action.query }) })
|
|
1067
|
-
] });
|
|
1068
|
-
}
|
|
1069
|
-
function McpToolDetails({ action }) {
|
|
1070
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1071
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "TOOL" }),
|
|
1072
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsxs("code", { className: "text-xs font-mono bg-white/10 text-white/90 px-1 py-0.5 rounded", children: [
|
|
1073
|
-
action.serverName,
|
|
1074
|
-
":",
|
|
1075
|
-
action.toolName
|
|
1076
|
-
] }) }),
|
|
1077
|
-
action.arguments && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1078
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "ARGS" }),
|
|
1079
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.arguments }) })
|
|
1080
|
-
] }),
|
|
1081
|
-
action.result && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1082
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "RESULT" }),
|
|
1083
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: action.result.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: String(action.result.value) }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.result.value }) })
|
|
1084
|
-
] })
|
|
1085
|
-
] });
|
|
1086
|
-
}
|
|
1087
|
-
function GenericToolDetails({ action }) {
|
|
1088
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1089
|
-
action.arguments && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1090
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "ARGS" }),
|
|
1091
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.arguments }) })
|
|
1092
|
-
] }),
|
|
1093
|
-
action.result && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1094
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "RESULT" }),
|
|
1095
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: action.result.type === "markdown" ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { children: String(action.result.value) }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: action.result.value }) })
|
|
1096
|
-
] })
|
|
1097
|
-
] });
|
|
1098
|
-
}
|
|
1099
|
-
function TodoWriteDetails({ action }) {
|
|
1100
|
-
const { todos, stats } = action;
|
|
1101
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1102
|
-
stats && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1103
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "PROGRESS" }),
|
|
1104
|
-
/* @__PURE__ */ jsxRuntime.jsxs(SectionContent, { children: [
|
|
1105
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1106
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-2 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1107
|
-
"div",
|
|
1108
|
-
{
|
|
1109
|
-
className: "h-full bg-emerald-400 rounded-full transition-all duration-500 ease-out",
|
|
1110
|
-
style: { width: `${stats.total > 0 ? stats.completed / stats.total * 100 : 0}%` }
|
|
1111
|
-
}
|
|
1112
|
-
) }),
|
|
1113
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/60 tabular-nums", children: [
|
|
1114
|
-
stats.completed,
|
|
1115
|
-
"/",
|
|
1116
|
-
stats.total
|
|
1117
|
-
] })
|
|
1118
|
-
] }),
|
|
1119
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 mt-2 text-xs", children: [
|
|
1120
|
-
stats.inProgress > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-yellow-400", children: [
|
|
1121
|
-
stats.inProgress,
|
|
1122
|
-
" in progress"
|
|
1123
|
-
] }),
|
|
1124
|
-
stats.pending > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-white/40", children: [
|
|
1125
|
-
stats.pending,
|
|
1126
|
-
" pending"
|
|
1127
|
-
] })
|
|
1128
|
-
] })
|
|
1129
|
-
] })
|
|
1130
|
-
] }),
|
|
1131
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "TASKS" }),
|
|
1132
|
-
/* @__PURE__ */ jsxRuntime.jsx(SectionContent, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: todos.map((todo, index) => {
|
|
1133
|
-
const displayText = todo.status === "in_progress" ? todo.activeForm : todo.content;
|
|
1134
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1135
|
-
"div",
|
|
1136
|
-
{
|
|
1137
|
-
className: cn(
|
|
1138
|
-
"flex items-start gap-2 py-1 transition-all duration-200",
|
|
1139
|
-
todo.status === "completed" && "opacity-50",
|
|
1140
|
-
todo.status === "in_progress" && "bg-yellow-500/10 -mx-2 px-2 rounded"
|
|
1141
|
-
),
|
|
1142
|
-
children: [
|
|
1143
|
-
todo.status === "completed" ? /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, { className: "w-4 h-4 text-emerald-400 shrink-0 mt-0.5" }) : todo.status === "in_progress" ? /* @__PURE__ */ jsxRuntime.jsx(LoaderIcon, { className: "w-4 h-4 text-yellow-400 animate-spin shrink-0 mt-0.5" }) : /* @__PURE__ */ jsxRuntime.jsx(CircleIcon, { className: "w-4 h-4 text-white/30 shrink-0 mt-0.5" }),
|
|
1144
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1145
|
-
"span",
|
|
1146
|
-
{
|
|
1147
|
-
className: cn(
|
|
1148
|
-
"text-sm leading-relaxed",
|
|
1149
|
-
todo.status === "completed" ? "text-white/50 line-through" : "text-white/80"
|
|
1150
|
-
),
|
|
1151
|
-
children: [
|
|
1152
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-white/40 mr-1.5", children: [
|
|
1153
|
-
index + 1,
|
|
1154
|
-
"."
|
|
1155
|
-
] }),
|
|
1156
|
-
displayText
|
|
1157
|
-
]
|
|
1158
|
-
}
|
|
1159
|
-
)
|
|
1160
|
-
]
|
|
1161
|
-
},
|
|
1162
|
-
`${todo.content}-${index}`
|
|
1163
|
-
);
|
|
1164
|
-
}) }) })
|
|
1165
|
-
] });
|
|
1166
|
-
}
|
|
1167
|
-
function ToolDetails({ actionType }) {
|
|
1168
|
-
switch (actionType.action) {
|
|
1169
|
-
case "command_run":
|
|
1170
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CommandRunDetails, { action: actionType });
|
|
1171
|
-
case "file_read":
|
|
1172
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FileReadDetails, { action: actionType });
|
|
1173
|
-
case "file_edit":
|
|
1174
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FileEditDetails, { action: actionType });
|
|
1175
|
-
case "file_write":
|
|
1176
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FileWriteDetails, { action: actionType });
|
|
1177
|
-
case "search":
|
|
1178
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SearchDetails, { action: actionType });
|
|
1179
|
-
case "glob":
|
|
1180
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GlobDetails, { action: actionType });
|
|
1181
|
-
case "web_fetch":
|
|
1182
|
-
return /* @__PURE__ */ jsxRuntime.jsx(WebFetchDetails, { action: actionType });
|
|
1183
|
-
case "web_search":
|
|
1184
|
-
return /* @__PURE__ */ jsxRuntime.jsx(WebSearchDetails, { action: actionType });
|
|
1185
|
-
case "mcp_tool":
|
|
1186
|
-
return /* @__PURE__ */ jsxRuntime.jsx(McpToolDetails, { action: actionType });
|
|
1187
|
-
case "generic_tool":
|
|
1188
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GenericToolDetails, { action: actionType });
|
|
1189
|
-
case "todo_write":
|
|
1190
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TodoWriteDetails, { action: actionType });
|
|
1191
|
-
default:
|
|
1192
|
-
return null;
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
function hasDetails(actionType) {
|
|
1196
|
-
switch (actionType.action) {
|
|
1197
|
-
case "command_run":
|
|
1198
|
-
return Boolean(actionType.command || actionType.result?.output);
|
|
1199
|
-
case "file_read":
|
|
1200
|
-
return true;
|
|
1201
|
-
case "file_edit":
|
|
1202
|
-
return Boolean(actionType.oldString || actionType.newString);
|
|
1203
|
-
case "file_write":
|
|
1204
|
-
return Boolean(actionType.content);
|
|
1205
|
-
case "search":
|
|
1206
|
-
return true;
|
|
1207
|
-
case "glob":
|
|
1208
|
-
return true;
|
|
1209
|
-
case "web_fetch":
|
|
1210
|
-
return true;
|
|
1211
|
-
case "web_search":
|
|
1212
|
-
return true;
|
|
1213
|
-
case "mcp_tool":
|
|
1214
|
-
return Boolean(actionType.arguments || actionType.result);
|
|
1215
|
-
case "generic_tool":
|
|
1216
|
-
return Boolean(actionType.arguments || actionType.result);
|
|
1217
|
-
case "todo_write":
|
|
1218
|
-
return actionType.todos.length > 0;
|
|
1219
|
-
case "agent_tool":
|
|
1220
|
-
return true;
|
|
1221
|
-
// Always expandable (handled by AgentToolCard)
|
|
1222
|
-
default:
|
|
1223
|
-
return false;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
function ToolCallCard({ toolCall, defaultExpanded = false, className }) {
|
|
1227
|
-
const [expanded, setExpanded] = react.useState(defaultExpanded);
|
|
1228
|
-
const { actionType, status, summary } = toolCall;
|
|
1229
|
-
if (actionType.action === "agent_tool") {
|
|
1230
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1231
|
-
AgentToolCard,
|
|
1232
|
-
{
|
|
1233
|
-
toolCall,
|
|
1234
|
-
defaultExpanded,
|
|
1235
|
-
className
|
|
1236
|
-
}
|
|
1237
|
-
);
|
|
1281
|
+
function ToolOutput({ className, maxHeight = 300 }) {
|
|
1282
|
+
const { toolInvocation } = useTool();
|
|
1283
|
+
if (toolInvocation.state !== "result" || !toolInvocation.result) {
|
|
1284
|
+
return null;
|
|
1238
1285
|
}
|
|
1239
|
-
const
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
success: "border-white/10",
|
|
1243
|
-
failed: "border-red-500/30"
|
|
1244
|
-
};
|
|
1286
|
+
const result = toolInvocation.result;
|
|
1287
|
+
const isString = typeof result === "string";
|
|
1288
|
+
const isError = typeof result === "object" && result !== null && "error" in result;
|
|
1245
1289
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1246
1290
|
"div",
|
|
1247
1291
|
{
|
|
1248
1292
|
className: cn(
|
|
1249
|
-
"
|
|
1250
|
-
|
|
1293
|
+
"ash-tool-output",
|
|
1294
|
+
"border-t border-[var(--ash-border-subtle,rgba(255,255,255,0.04))]",
|
|
1295
|
+
isError && "bg-red-500/5",
|
|
1251
1296
|
className
|
|
1252
1297
|
),
|
|
1253
1298
|
children: [
|
|
1254
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1255
|
-
"
|
|
1299
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1300
|
+
"div",
|
|
1256
1301
|
{
|
|
1257
|
-
onClick: () => canExpand && setExpanded(!expanded),
|
|
1258
1302
|
className: cn(
|
|
1259
|
-
"
|
|
1260
|
-
|
|
1303
|
+
"ash-tool-section-header",
|
|
1304
|
+
isError && "text-red-400"
|
|
1261
1305
|
),
|
|
1262
|
-
|
|
1263
|
-
children: [
|
|
1264
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0 flex-1", children: [
|
|
1265
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
1266
|
-
"w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
|
|
1267
|
-
status === "pending" ? "bg-yellow-500/20" : status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
|
|
1268
|
-
), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1269
|
-
ActionIcon,
|
|
1270
|
-
{
|
|
1271
|
-
actionType,
|
|
1272
|
-
className: cn(
|
|
1273
|
-
"w-3.5 h-3.5",
|
|
1274
|
-
status === "pending" ? "text-yellow-400" : status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
|
|
1275
|
-
)
|
|
1276
|
-
}
|
|
1277
|
-
) }),
|
|
1278
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-white shrink-0", children: getActionLabel(actionType) }),
|
|
1279
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-sm truncate text-white/60 min-w-0", children: summary })
|
|
1280
|
-
] }),
|
|
1281
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
1282
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status, size: "sm" }),
|
|
1283
|
-
canExpand && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1284
|
-
ChevronDownIcon,
|
|
1285
|
-
{
|
|
1286
|
-
className: cn(
|
|
1287
|
-
"w-4 h-4 text-white/40 transition-transform duration-200",
|
|
1288
|
-
expanded && "rotate-180"
|
|
1289
|
-
)
|
|
1290
|
-
}
|
|
1291
|
-
)
|
|
1292
|
-
] })
|
|
1293
|
-
]
|
|
1306
|
+
children: isError ? "Error" : "Output"
|
|
1294
1307
|
}
|
|
1295
1308
|
),
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1309
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1310
|
+
"div",
|
|
1311
|
+
{
|
|
1312
|
+
className: "p-3 overflow-auto",
|
|
1313
|
+
style: { maxHeight },
|
|
1314
|
+
children: isString ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { maxHeight: maxHeight - 24, children: result }) : /* @__PURE__ */ jsxRuntime.jsx(JsonDisplay, { value: result })
|
|
1315
|
+
}
|
|
1316
|
+
)
|
|
1303
1317
|
]
|
|
1304
1318
|
}
|
|
1305
1319
|
);
|
|
1306
1320
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
}
|
|
1318
|
-
function DefaultMentionBadge({ segment }) {
|
|
1319
|
-
const bgColor = segment.color ? `${segment.color}20` : "rgba(34, 197, 94, 0.2)";
|
|
1320
|
-
const textColor = segment.color || "#22c55e";
|
|
1321
|
-
const borderColor = segment.color ? `${segment.color}40` : "rgba(34, 197, 94, 0.4)";
|
|
1322
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1323
|
-
"span",
|
|
1321
|
+
function ToolList({
|
|
1322
|
+
toolInvocations,
|
|
1323
|
+
className,
|
|
1324
|
+
defaultExpanded = false
|
|
1325
|
+
}) {
|
|
1326
|
+
if (!toolInvocations || toolInvocations.length === 0) {
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1330
|
+
"div",
|
|
1324
1331
|
{
|
|
1325
|
-
className:
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1332
|
+
className: cn(
|
|
1333
|
+
"ash-tool-list",
|
|
1334
|
+
"flex flex-col gap-2",
|
|
1335
|
+
className
|
|
1336
|
+
),
|
|
1337
|
+
children: toolInvocations.map((inv) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1338
|
+
Tool,
|
|
1339
|
+
{
|
|
1340
|
+
toolInvocation: inv,
|
|
1341
|
+
defaultExpanded
|
|
1342
|
+
},
|
|
1343
|
+
inv.toolCallId
|
|
1344
|
+
))
|
|
1336
1345
|
}
|
|
1337
1346
|
);
|
|
1338
1347
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1348
|
+
var ReasoningContext = react.createContext(null);
|
|
1349
|
+
function useReasoning() {
|
|
1350
|
+
const context = react.useContext(ReasoningContext);
|
|
1351
|
+
if (!context) {
|
|
1352
|
+
throw new Error("useReasoning must be used within a Reasoning");
|
|
1353
|
+
}
|
|
1354
|
+
return context;
|
|
1355
|
+
}
|
|
1356
|
+
function Reasoning({
|
|
1357
|
+
children,
|
|
1358
|
+
isStreaming = false,
|
|
1359
|
+
className,
|
|
1360
|
+
autoExpand = true,
|
|
1361
|
+
autoCollapse = true,
|
|
1362
|
+
initialDuration = 0
|
|
1343
1363
|
}) {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
if (renderers?.renderComponent) {
|
|
1356
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderers.renderComponent({ segment }) }, key);
|
|
1364
|
+
const [isOpen, setIsOpen] = react.useState(false);
|
|
1365
|
+
const [duration, setDuration] = react.useState(initialDuration);
|
|
1366
|
+
const startTimeRef = react.useRef(null);
|
|
1367
|
+
const intervalRef = react.useRef(null);
|
|
1368
|
+
react.useEffect(() => {
|
|
1369
|
+
if (isStreaming && autoExpand) {
|
|
1370
|
+
setIsOpen(true);
|
|
1371
|
+
startTimeRef.current = Date.now();
|
|
1372
|
+
intervalRef.current = setInterval(() => {
|
|
1373
|
+
if (startTimeRef.current) {
|
|
1374
|
+
setDuration(Math.floor((Date.now() - startTimeRef.current) / 1e3));
|
|
1357
1375
|
}
|
|
1358
|
-
|
|
1359
|
-
"[component: ",
|
|
1360
|
-
segment.componentType,
|
|
1361
|
-
"]"
|
|
1362
|
-
] }, key);
|
|
1363
|
-
default:
|
|
1364
|
-
return null;
|
|
1376
|
+
}, 1e3);
|
|
1365
1377
|
}
|
|
1366
|
-
|
|
1378
|
+
return () => {
|
|
1379
|
+
if (intervalRef.current) {
|
|
1380
|
+
clearInterval(intervalRef.current);
|
|
1381
|
+
intervalRef.current = null;
|
|
1382
|
+
}
|
|
1383
|
+
};
|
|
1384
|
+
}, [isStreaming, autoExpand]);
|
|
1385
|
+
react.useEffect(() => {
|
|
1386
|
+
if (!isStreaming && autoCollapse && startTimeRef.current) {
|
|
1387
|
+
const timeout = setTimeout(() => {
|
|
1388
|
+
setIsOpen(false);
|
|
1389
|
+
}, 500);
|
|
1390
|
+
startTimeRef.current = null;
|
|
1391
|
+
if (intervalRef.current) {
|
|
1392
|
+
clearInterval(intervalRef.current);
|
|
1393
|
+
intervalRef.current = null;
|
|
1394
|
+
}
|
|
1395
|
+
return () => clearTimeout(timeout);
|
|
1396
|
+
}
|
|
1397
|
+
return void 0;
|
|
1398
|
+
}, [isStreaming, autoCollapse]);
|
|
1399
|
+
const contextValue = {
|
|
1400
|
+
isOpen,
|
|
1401
|
+
setIsOpen,
|
|
1402
|
+
isStreaming,
|
|
1403
|
+
duration
|
|
1404
|
+
};
|
|
1405
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1406
|
+
"div",
|
|
1407
|
+
{
|
|
1408
|
+
className: cn(
|
|
1409
|
+
"ash-reasoning",
|
|
1410
|
+
"rounded-[var(--ash-radius-md,0.5rem)]",
|
|
1411
|
+
"border",
|
|
1412
|
+
isStreaming ? "border-[var(--ash-thinking-border,rgba(147,51,234,0.2))] bg-[var(--ash-thinking-bg,rgba(147,51,234,0.06))]" : "border-[var(--ash-border,rgba(255,255,255,0.08))] bg-[var(--ash-surface-dark,#0a0a0a)]",
|
|
1413
|
+
"overflow-hidden",
|
|
1414
|
+
className
|
|
1415
|
+
),
|
|
1416
|
+
"data-reasoning-streaming": isStreaming,
|
|
1417
|
+
"data-reasoning-open": isOpen,
|
|
1418
|
+
children
|
|
1419
|
+
}
|
|
1420
|
+
) });
|
|
1367
1421
|
}
|
|
1368
|
-
function
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1422
|
+
function ReasoningTrigger({
|
|
1423
|
+
className,
|
|
1424
|
+
label = "Thinking",
|
|
1425
|
+
showDuration = true
|
|
1426
|
+
}) {
|
|
1427
|
+
const { isOpen, setIsOpen, isStreaming, duration } = useReasoning();
|
|
1428
|
+
const formatDuration = (seconds) => {
|
|
1429
|
+
if (seconds < 60) return `${seconds}s`;
|
|
1430
|
+
const minutes = Math.floor(seconds / 60);
|
|
1431
|
+
const remainingSeconds = seconds % 60;
|
|
1432
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
1433
|
+
};
|
|
1434
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1372
1435
|
"button",
|
|
1373
1436
|
{
|
|
1374
|
-
onClick: () =>
|
|
1437
|
+
onClick: () => setIsOpen(!isOpen),
|
|
1375
1438
|
className: cn(
|
|
1376
|
-
"
|
|
1377
|
-
"
|
|
1378
|
-
"
|
|
1379
|
-
"
|
|
1380
|
-
"
|
|
1381
|
-
|
|
1439
|
+
"ash-reasoning-trigger",
|
|
1440
|
+
"w-full flex items-center gap-2",
|
|
1441
|
+
"px-3 py-2",
|
|
1442
|
+
"text-left",
|
|
1443
|
+
"cursor-pointer hover:bg-white/[0.03] transition-colors",
|
|
1444
|
+
className
|
|
1382
1445
|
),
|
|
1383
1446
|
children: [
|
|
1384
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
1385
|
-
"flex-shrink-0 w-6 h-6 rounded-lg",
|
|
1386
|
-
"bg-[var(--ash-accent)]/20 text-[var(--ash-accent)]",
|
|
1387
|
-
"flex items-center justify-center",
|
|
1388
|
-
"text-xs font-semibold",
|
|
1389
|
-
"group-hover:bg-[var(--ash-accent)]/30",
|
|
1390
|
-
"transition-colors duration-200"
|
|
1391
|
-
), children: option.id }),
|
|
1392
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1393
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-white/90 group-hover:text-white transition-colors", children: option.label }),
|
|
1394
|
-
option.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-white/50 mt-0.5 line-clamp-2 group-hover:text-white/60 transition-colors", children: option.description })
|
|
1395
|
-
] }),
|
|
1396
1447
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1397
|
-
"
|
|
1448
|
+
"span",
|
|
1398
1449
|
{
|
|
1399
1450
|
className: cn(
|
|
1400
|
-
"w-4 h-4
|
|
1401
|
-
"
|
|
1402
|
-
"transition-all duration-200"
|
|
1451
|
+
"w-4 h-4 flex items-center justify-center",
|
|
1452
|
+
isStreaming && "animate-pulse"
|
|
1403
1453
|
),
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1454
|
+
children: isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1455
|
+
"svg",
|
|
1456
|
+
{
|
|
1457
|
+
className: "w-4 h-4 text-purple-400 animate-spin",
|
|
1458
|
+
fill: "none",
|
|
1459
|
+
viewBox: "0 0 24 24",
|
|
1460
|
+
children: [
|
|
1461
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1462
|
+
"circle",
|
|
1463
|
+
{
|
|
1464
|
+
className: "opacity-25",
|
|
1465
|
+
cx: "12",
|
|
1466
|
+
cy: "12",
|
|
1467
|
+
r: "10",
|
|
1468
|
+
stroke: "currentColor",
|
|
1469
|
+
strokeWidth: "4"
|
|
1470
|
+
}
|
|
1471
|
+
),
|
|
1472
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1473
|
+
"path",
|
|
1474
|
+
{
|
|
1475
|
+
className: "opacity-75",
|
|
1476
|
+
fill: "currentColor",
|
|
1477
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
1478
|
+
}
|
|
1479
|
+
)
|
|
1480
|
+
]
|
|
1481
|
+
}
|
|
1482
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1483
|
+
"svg",
|
|
1484
|
+
{
|
|
1485
|
+
className: "w-4 h-4 text-purple-400",
|
|
1486
|
+
fill: "none",
|
|
1487
|
+
stroke: "currentColor",
|
|
1488
|
+
viewBox: "0 0 24 24",
|
|
1489
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1490
|
+
"path",
|
|
1491
|
+
{
|
|
1492
|
+
strokeLinecap: "round",
|
|
1493
|
+
strokeLinejoin: "round",
|
|
1494
|
+
strokeWidth: 2,
|
|
1495
|
+
d: "M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"
|
|
1496
|
+
}
|
|
1497
|
+
)
|
|
1498
|
+
}
|
|
1499
|
+
)
|
|
1409
1500
|
}
|
|
1410
|
-
)
|
|
1411
|
-
|
|
1412
|
-
},
|
|
1413
|
-
option.id
|
|
1414
|
-
)) });
|
|
1415
|
-
}
|
|
1416
|
-
function parseFilesFromContent(content) {
|
|
1417
|
-
const fileMarker = "[Uploaded files available at /uploads/]";
|
|
1418
|
-
const markerIndex = content.indexOf(fileMarker);
|
|
1419
|
-
if (markerIndex === -1) {
|
|
1420
|
-
return { text: content, files: [] };
|
|
1421
|
-
}
|
|
1422
|
-
const text = content.substring(0, markerIndex).trim();
|
|
1423
|
-
const fileSection = content.substring(markerIndex + fileMarker.length).trim();
|
|
1424
|
-
const files = fileSection.split("\n").filter((line) => line.startsWith("- ")).map((line) => line.substring(2).trim());
|
|
1425
|
-
return { text, files };
|
|
1426
|
-
}
|
|
1427
|
-
function UserMessage({ entry, className }) {
|
|
1428
|
-
const { text, files } = parseFilesFromContent(entry.content);
|
|
1429
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-3 justify-end ash-animate-fade-in", className), children: [
|
|
1430
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-[85%]", children: [
|
|
1431
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-2xl p-4 bg-[var(--ash-accent)] text-[var(--ash-accent-foreground)]", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-relaxed whitespace-pre-wrap", children: text || "(files attached)" }) }),
|
|
1432
|
-
files.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 pt-2 border-t border-[var(--ash-accent-foreground)]/20", children: [
|
|
1433
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-[var(--ash-accent-foreground)]/60 mb-1 flex items-center gap-1", children: [
|
|
1434
|
-
/* @__PURE__ */ jsxRuntime.jsx(PaperclipIcon, { className: "w-3 h-3" }),
|
|
1435
|
-
"Attached Files"
|
|
1436
|
-
] }),
|
|
1437
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: files.map((file, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1501
|
+
),
|
|
1502
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1438
1503
|
"span",
|
|
1439
1504
|
{
|
|
1440
|
-
className:
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
onOptionSelect(`Option ${option.id}: ${option.label}`);
|
|
1462
|
-
}
|
|
1463
|
-
};
|
|
1464
|
-
const renderContent = (textContent) => {
|
|
1465
|
-
if (entry.richContent && entry.richContent.length > 0) {
|
|
1466
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1467
|
-
RichContentRenderer,
|
|
1468
|
-
{
|
|
1469
|
-
content: entry.richContent,
|
|
1470
|
-
renderers: richContentRenderers
|
|
1471
|
-
}
|
|
1472
|
-
);
|
|
1473
|
-
}
|
|
1474
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LazyMarkdown, { children: textContent || entry.content });
|
|
1475
|
-
};
|
|
1476
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-3 ash-animate-fade-in", className), children: [
|
|
1477
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-[var(--ash-accent)]/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }) }),
|
|
1478
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 max-w-[85%]", children: [
|
|
1479
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-card-glass rounded-2xl p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ash-message-content prose prose-sm prose-invert max-w-none text-sm leading-relaxed", children: parsedOptions ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1480
|
-
parsedOptions.preamble && renderContent(parsedOptions.preamble),
|
|
1505
|
+
className: cn(
|
|
1506
|
+
"flex-1 font-medium",
|
|
1507
|
+
"text-[var(--ash-font-size-sm,12px)]",
|
|
1508
|
+
isStreaming ? "text-[var(--ash-thinking-text,rgb(196,181,253))]" : "text-[var(--ash-text-secondary,rgba(255,255,255,0.7))]"
|
|
1509
|
+
),
|
|
1510
|
+
children: [
|
|
1511
|
+
label,
|
|
1512
|
+
isStreaming && "..."
|
|
1513
|
+
]
|
|
1514
|
+
}
|
|
1515
|
+
),
|
|
1516
|
+
showDuration && duration > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1517
|
+
"span",
|
|
1518
|
+
{
|
|
1519
|
+
className: cn(
|
|
1520
|
+
"text-[var(--ash-font-size-xs,10px)]",
|
|
1521
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]"
|
|
1522
|
+
),
|
|
1523
|
+
children: formatDuration(duration)
|
|
1524
|
+
}
|
|
1525
|
+
),
|
|
1481
1526
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1482
|
-
|
|
1527
|
+
"svg",
|
|
1483
1528
|
{
|
|
1484
|
-
|
|
1485
|
-
|
|
1529
|
+
className: cn(
|
|
1530
|
+
"w-4 h-4 text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1531
|
+
"transition-transform",
|
|
1532
|
+
isOpen && "rotate-180"
|
|
1533
|
+
),
|
|
1534
|
+
fill: "none",
|
|
1535
|
+
stroke: "currentColor",
|
|
1536
|
+
viewBox: "0 0 24 24",
|
|
1537
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1538
|
+
"path",
|
|
1539
|
+
{
|
|
1540
|
+
strokeLinecap: "round",
|
|
1541
|
+
strokeLinejoin: "round",
|
|
1542
|
+
strokeWidth: 2,
|
|
1543
|
+
d: "M19 9l-7 7-7-7"
|
|
1544
|
+
}
|
|
1545
|
+
)
|
|
1486
1546
|
}
|
|
1487
1547
|
)
|
|
1488
|
-
]
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
] });
|
|
1492
|
-
}
|
|
1493
|
-
function ThinkingMessage({ entry, className }) {
|
|
1494
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-3 ash-animate-fade-in", className), children: [
|
|
1495
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-purple-500/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(SparklesIcon, { className: "w-4 h-4 text-purple-400" }) }),
|
|
1496
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 max-w-[85%]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl p-4 bg-purple-500/10 border border-purple-500/30", children: [
|
|
1497
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-purple-400 mb-2 font-medium", children: "Thinking" }),
|
|
1498
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-purple-300 italic opacity-80 whitespace-pre-wrap leading-relaxed", children: entry.content })
|
|
1499
|
-
] }) })
|
|
1500
|
-
] });
|
|
1501
|
-
}
|
|
1502
|
-
function ToolCallMessage({ entry, defaultExpanded = false, className }) {
|
|
1503
|
-
if (entry.entryType.type !== "tool_call") return null;
|
|
1504
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-3 ash-animate-fade-in", className), children: [
|
|
1505
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-[var(--ash-accent)]/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }) }),
|
|
1506
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(ToolCallCard, { toolCall: entry.entryType.toolCall, defaultExpanded }) })
|
|
1507
|
-
] });
|
|
1508
|
-
}
|
|
1509
|
-
function ErrorMessage({ entry, className }) {
|
|
1510
|
-
if (entry.entryType.type !== "error") return null;
|
|
1511
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-3 ash-animate-fade-in", className), children: [
|
|
1512
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-red-500/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(AlertTriangleIcon, { className: "w-4 h-4 text-red-400" }) }),
|
|
1513
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 max-w-[85%]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl p-4 bg-red-500/10 border border-red-500/30", children: [
|
|
1514
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-red-400 mb-2 font-medium", children: "Error" }),
|
|
1515
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-300", children: entry.entryType.message }),
|
|
1516
|
-
entry.entryType.code && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-red-400/70 mt-2 font-mono", children: [
|
|
1517
|
-
"Code: ",
|
|
1518
|
-
entry.entryType.code
|
|
1519
|
-
] })
|
|
1520
|
-
] }) })
|
|
1521
|
-
] });
|
|
1548
|
+
]
|
|
1549
|
+
}
|
|
1550
|
+
);
|
|
1522
1551
|
}
|
|
1523
|
-
function
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
richContentRenderers,
|
|
1528
|
-
className
|
|
1552
|
+
function ReasoningContent({
|
|
1553
|
+
children,
|
|
1554
|
+
className,
|
|
1555
|
+
maxHeight = 300
|
|
1529
1556
|
}) {
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1557
|
+
const { isOpen, isStreaming } = useReasoning();
|
|
1558
|
+
if (!isOpen) return null;
|
|
1559
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1560
|
+
"div",
|
|
1561
|
+
{
|
|
1562
|
+
className: cn(
|
|
1563
|
+
"ash-reasoning-content",
|
|
1564
|
+
"border-t border-[var(--ash-border-subtle,rgba(255,255,255,0.04))]",
|
|
1565
|
+
"ash-accordion-content",
|
|
1566
|
+
className
|
|
1567
|
+
),
|
|
1568
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1569
|
+
"div",
|
|
1536
1570
|
{
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1571
|
+
className: cn(
|
|
1572
|
+
"p-3 overflow-auto",
|
|
1573
|
+
"text-[var(--ash-font-size-sm,12px)]",
|
|
1574
|
+
"text-[var(--ash-text-secondary,rgba(255,255,255,0.7))]",
|
|
1575
|
+
"whitespace-pre-wrap font-mono",
|
|
1576
|
+
isStreaming && "animate-pulse"
|
|
1577
|
+
),
|
|
1578
|
+
style: { maxHeight },
|
|
1579
|
+
children
|
|
1541
1580
|
}
|
|
1542
|
-
)
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
case "tool_call":
|
|
1546
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ToolCallMessage, { entry, defaultExpanded, className });
|
|
1547
|
-
case "error":
|
|
1548
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { entry, className });
|
|
1549
|
-
default:
|
|
1550
|
-
return null;
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
function LoadingIndicator({ variant = "dots", size = "md", className }) {
|
|
1554
|
-
if (variant === "dots") {
|
|
1555
|
-
const dotSizes = {
|
|
1556
|
-
sm: "w-1 h-1",
|
|
1557
|
-
md: "w-1.5 h-1.5",
|
|
1558
|
-
lg: "w-2 h-2"
|
|
1559
|
-
};
|
|
1560
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-1", className), children: [
|
|
1561
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-[var(--ash-accent)] animate-pulse", dotSizes[size]) }),
|
|
1562
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-[var(--ash-accent)] animate-pulse", dotSizes[size]), style: { animationDelay: "150ms" } }),
|
|
1563
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-[var(--ash-accent)] animate-pulse", dotSizes[size]), style: { animationDelay: "300ms" } })
|
|
1564
|
-
] });
|
|
1565
|
-
}
|
|
1566
|
-
if (variant === "pulse") {
|
|
1567
|
-
const dotSizes = {
|
|
1568
|
-
sm: "w-1.5 h-1.5",
|
|
1569
|
-
md: "w-2 h-2",
|
|
1570
|
-
lg: "w-3 h-3"
|
|
1571
|
-
};
|
|
1572
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-1", className), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("bg-[var(--ash-accent)] rounded-full animate-pulse", dotSizes[size]) }) });
|
|
1573
|
-
}
|
|
1574
|
-
if (variant === "cursor") {
|
|
1575
|
-
const cursorSizes = {
|
|
1576
|
-
sm: "w-1 h-3",
|
|
1577
|
-
md: "w-1.5 h-4",
|
|
1578
|
-
lg: "w-2 h-5"
|
|
1579
|
-
};
|
|
1580
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1581
|
-
"span",
|
|
1582
|
-
{
|
|
1583
|
-
className: cn(
|
|
1584
|
-
"inline-block bg-[var(--ash-accent)]/50 ash-tool-status-pending",
|
|
1585
|
-
cursorSizes[size],
|
|
1586
|
-
className
|
|
1587
|
-
)
|
|
1588
|
-
}
|
|
1589
|
-
);
|
|
1590
|
-
}
|
|
1591
|
-
const spinnerSizes = {
|
|
1592
|
-
sm: "w-4 h-4",
|
|
1593
|
-
md: "w-6 h-6",
|
|
1594
|
-
lg: "w-8 h-8"
|
|
1595
|
-
};
|
|
1596
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("animate-spin text-[var(--ash-accent)]", spinnerSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1597
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", className: "opacity-25" }),
|
|
1598
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2a10 10 0 0 1 10 10", strokeLinecap: "round" })
|
|
1599
|
-
] }) });
|
|
1581
|
+
)
|
|
1582
|
+
}
|
|
1583
|
+
);
|
|
1600
1584
|
}
|
|
1601
|
-
function
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
renderMarkdown = true,
|
|
1585
|
+
function ThinkingIndicator({
|
|
1586
|
+
isActive = true,
|
|
1587
|
+
label = "Thinking",
|
|
1605
1588
|
className
|
|
1606
1589
|
}) {
|
|
1607
|
-
|
|
1608
|
-
/* @__PURE__ */ jsxRuntime.jsx(LazyMarkdown, { children: content }),
|
|
1609
|
-
isStreaming && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator, { variant: "cursor", size: "sm", className: "inline-block ml-0.5" })
|
|
1610
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "whitespace-pre-wrap text-sm leading-relaxed", children: [
|
|
1611
|
-
content,
|
|
1612
|
-
isStreaming && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator, { variant: "cursor", size: "sm", className: "inline-block ml-0.5" })
|
|
1613
|
-
] }) });
|
|
1614
|
-
}
|
|
1615
|
-
function getFilePath(actionType) {
|
|
1616
|
-
switch (actionType.action) {
|
|
1617
|
-
case "file_read":
|
|
1618
|
-
case "file_edit":
|
|
1619
|
-
case "file_write":
|
|
1620
|
-
return actionType.path;
|
|
1621
|
-
default:
|
|
1622
|
-
return null;
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
function getFileName(path) {
|
|
1626
|
-
const parts = path.split("/");
|
|
1627
|
-
return parts[parts.length - 1] || path;
|
|
1628
|
-
}
|
|
1629
|
-
function getFileExtension(path) {
|
|
1630
|
-
const fileName = getFileName(path);
|
|
1631
|
-
const dotIndex = fileName.lastIndexOf(".");
|
|
1632
|
-
if (dotIndex === -1) return null;
|
|
1633
|
-
return fileName.slice(dotIndex + 1).toLowerCase();
|
|
1634
|
-
}
|
|
1635
|
-
function getDiffStats(actionType) {
|
|
1636
|
-
switch (actionType.action) {
|
|
1637
|
-
case "file_edit": {
|
|
1638
|
-
const edit = actionType;
|
|
1639
|
-
if (edit.linesAdded !== void 0 || edit.linesRemoved !== void 0) {
|
|
1640
|
-
return { added: edit.linesAdded, removed: edit.linesRemoved };
|
|
1641
|
-
}
|
|
1642
|
-
return null;
|
|
1643
|
-
}
|
|
1644
|
-
case "file_read": {
|
|
1645
|
-
const read = actionType;
|
|
1646
|
-
if (read.linesRead !== void 0) {
|
|
1647
|
-
return { read: read.linesRead };
|
|
1648
|
-
}
|
|
1649
|
-
return null;
|
|
1650
|
-
}
|
|
1651
|
-
case "file_write": {
|
|
1652
|
-
const write = actionType;
|
|
1653
|
-
if (write.linesWritten !== void 0) {
|
|
1654
|
-
return { written: write.linesWritten };
|
|
1655
|
-
}
|
|
1656
|
-
return null;
|
|
1657
|
-
}
|
|
1658
|
-
default:
|
|
1659
|
-
return null;
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
function getFileTypeColor(ext) {
|
|
1663
|
-
switch (ext) {
|
|
1664
|
-
case "ts":
|
|
1665
|
-
case "tsx":
|
|
1666
|
-
return "text-blue-400";
|
|
1667
|
-
case "js":
|
|
1668
|
-
case "jsx":
|
|
1669
|
-
return "text-yellow-400";
|
|
1670
|
-
case "md":
|
|
1671
|
-
return "text-white/60";
|
|
1672
|
-
case "json":
|
|
1673
|
-
return "text-orange-400";
|
|
1674
|
-
case "sh":
|
|
1675
|
-
return "text-green-400";
|
|
1676
|
-
case "css":
|
|
1677
|
-
case "scss":
|
|
1678
|
-
return "text-pink-400";
|
|
1679
|
-
case "py":
|
|
1680
|
-
return "text-blue-300";
|
|
1681
|
-
default:
|
|
1682
|
-
return "text-white/70";
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
function CompactToolRow({ toolCall, showFullPath = false, className }) {
|
|
1686
|
-
const { actionType, status, summary } = toolCall;
|
|
1687
|
-
const label = getActionLabel(actionType);
|
|
1688
|
-
const filePath = getFilePath(actionType);
|
|
1689
|
-
const diffStats = getDiffStats(actionType);
|
|
1690
|
-
const displayPath = filePath ? showFullPath ? filePath : getFileName(filePath) : null;
|
|
1691
|
-
const ext = filePath ? getFileExtension(filePath) : null;
|
|
1692
|
-
const fileColor = getFileTypeColor(ext);
|
|
1693
|
-
const showSummary = !filePath && summary;
|
|
1590
|
+
if (!isActive) return null;
|
|
1694
1591
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1695
1592
|
"div",
|
|
1696
1593
|
{
|
|
1697
1594
|
className: cn(
|
|
1698
|
-
"
|
|
1595
|
+
"ash-thinking-indicator",
|
|
1596
|
+
"flex items-center gap-2",
|
|
1597
|
+
"px-3 py-2",
|
|
1598
|
+
"text-[var(--ash-font-size-sm,12px)]",
|
|
1599
|
+
"text-[var(--ash-thinking-text,rgb(196,181,253))]",
|
|
1699
1600
|
className
|
|
1700
1601
|
),
|
|
1701
1602
|
children: [
|
|
1702
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1703
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
actionType,
|
|
1707
|
-
className: cn(
|
|
1708
|
-
"w-3.5 h-3.5",
|
|
1709
|
-
status === "pending" ? "text-yellow-400" : status === "failed" ? "text-red-400" : "text-white/50"
|
|
1710
|
-
)
|
|
1711
|
-
}
|
|
1712
|
-
),
|
|
1713
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
1714
|
-
"font-medium",
|
|
1715
|
-
status === "pending" ? "text-white/90" : status === "failed" ? "text-red-400" : "text-white/60"
|
|
1716
|
-
), children: label })
|
|
1603
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex gap-1", children: [
|
|
1604
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 bg-current rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
|
|
1605
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 bg-current rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
|
|
1606
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 bg-current rounded-full animate-bounce", style: { animationDelay: "300ms" } })
|
|
1717
1607
|
] }),
|
|
1718
|
-
|
|
1719
|
-
"px-1.5 py-0.5 rounded bg-white/5 font-mono text-xs truncate max-w-[200px]",
|
|
1720
|
-
fileColor
|
|
1721
|
-
), children: displayPath }),
|
|
1722
|
-
diffStats && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0 font-mono", children: [
|
|
1723
|
-
diffStats.added !== void 0 && diffStats.added > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-emerald-400", children: [
|
|
1724
|
-
"+",
|
|
1725
|
-
diffStats.added
|
|
1726
|
-
] }),
|
|
1727
|
-
diffStats.removed !== void 0 && diffStats.removed > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-red-400", children: [
|
|
1728
|
-
"-",
|
|
1729
|
-
diffStats.removed
|
|
1730
|
-
] }),
|
|
1731
|
-
diffStats.read !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-white/40", children: [
|
|
1732
|
-
diffStats.read,
|
|
1733
|
-
" lines"
|
|
1734
|
-
] }),
|
|
1735
|
-
diffStats.written !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-emerald-400", children: [
|
|
1736
|
-
"+",
|
|
1737
|
-
diffStats.written
|
|
1738
|
-
] })
|
|
1739
|
-
] }),
|
|
1740
|
-
showSummary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/40 truncate min-w-0 text-xs", children: summary })
|
|
1608
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
|
|
1741
1609
|
]
|
|
1742
1610
|
}
|
|
1743
1611
|
);
|
|
1744
1612
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
const
|
|
1748
|
-
if (
|
|
1749
|
-
|
|
1750
|
-
}
|
|
1751
|
-
function getFileIcon(ext) {
|
|
1752
|
-
switch (ext) {
|
|
1753
|
-
case "ts":
|
|
1754
|
-
case "tsx":
|
|
1755
|
-
return "TS";
|
|
1756
|
-
case "js":
|
|
1757
|
-
case "jsx":
|
|
1758
|
-
return "JS";
|
|
1759
|
-
case "md":
|
|
1760
|
-
return "MD";
|
|
1761
|
-
case "json":
|
|
1762
|
-
return "{}";
|
|
1763
|
-
case "sh":
|
|
1764
|
-
return "$";
|
|
1765
|
-
case "css":
|
|
1766
|
-
case "scss":
|
|
1767
|
-
return "#";
|
|
1768
|
-
case "py":
|
|
1769
|
-
return "PY";
|
|
1770
|
-
default:
|
|
1771
|
-
return "";
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
function getFileBgColor(ext) {
|
|
1775
|
-
switch (ext) {
|
|
1776
|
-
case "ts":
|
|
1777
|
-
case "tsx":
|
|
1778
|
-
return "bg-blue-500/20";
|
|
1779
|
-
case "js":
|
|
1780
|
-
case "jsx":
|
|
1781
|
-
return "bg-yellow-500/20";
|
|
1782
|
-
case "md":
|
|
1783
|
-
return "bg-white/10";
|
|
1784
|
-
case "json":
|
|
1785
|
-
return "bg-orange-500/20";
|
|
1786
|
-
case "sh":
|
|
1787
|
-
return "bg-green-500/20";
|
|
1788
|
-
case "css":
|
|
1789
|
-
case "scss":
|
|
1790
|
-
return "bg-pink-500/20";
|
|
1791
|
-
case "py":
|
|
1792
|
-
return "bg-blue-400/20";
|
|
1793
|
-
default:
|
|
1794
|
-
return "bg-white/10";
|
|
1613
|
+
var TaskContext = react.createContext(null);
|
|
1614
|
+
function useTask() {
|
|
1615
|
+
const context = react.useContext(TaskContext);
|
|
1616
|
+
if (!context) {
|
|
1617
|
+
throw new Error("useTask must be used within a Task");
|
|
1795
1618
|
}
|
|
1619
|
+
return context;
|
|
1796
1620
|
}
|
|
1797
|
-
function
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
linesRemoved,
|
|
1801
|
-
showOnlyFilename = true,
|
|
1621
|
+
function Task({
|
|
1622
|
+
children,
|
|
1623
|
+
defaultOpen = false,
|
|
1802
1624
|
className
|
|
1803
1625
|
}) {
|
|
1804
|
-
const
|
|
1805
|
-
const
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1626
|
+
const [isOpen, setIsOpen] = react.useState(defaultOpen);
|
|
1627
|
+
const contextValue = {
|
|
1628
|
+
isOpen,
|
|
1629
|
+
setIsOpen
|
|
1630
|
+
};
|
|
1631
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TaskContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1632
|
+
"div",
|
|
1633
|
+
{
|
|
1634
|
+
className: cn(
|
|
1635
|
+
"ash-task",
|
|
1636
|
+
"rounded-[var(--ash-radius-md,0.5rem)]",
|
|
1637
|
+
"border border-[var(--ash-border,rgba(255,255,255,0.08))]",
|
|
1638
|
+
"bg-[var(--ash-surface-dark,#0a0a0a)]",
|
|
1639
|
+
"overflow-hidden",
|
|
1640
|
+
className
|
|
1641
|
+
),
|
|
1642
|
+
children
|
|
1643
|
+
}
|
|
1644
|
+
) });
|
|
1645
|
+
}
|
|
1646
|
+
function TaskTrigger({ children, className }) {
|
|
1647
|
+
const { isOpen, setIsOpen } = useTask();
|
|
1809
1648
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1810
|
-
"
|
|
1649
|
+
"button",
|
|
1811
1650
|
{
|
|
1651
|
+
onClick: () => setIsOpen(!isOpen),
|
|
1812
1652
|
className: cn(
|
|
1813
|
-
"
|
|
1814
|
-
|
|
1653
|
+
"ash-task-trigger",
|
|
1654
|
+
"w-full flex items-center gap-2",
|
|
1655
|
+
"px-3 py-2",
|
|
1656
|
+
"text-left",
|
|
1657
|
+
"cursor-pointer hover:bg-white/[0.03] transition-colors",
|
|
1815
1658
|
className
|
|
1816
1659
|
),
|
|
1817
1660
|
children: [
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
"
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1661
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1662
|
+
"svg",
|
|
1663
|
+
{
|
|
1664
|
+
className: "w-4 h-4 text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1665
|
+
fill: "none",
|
|
1666
|
+
stroke: "currentColor",
|
|
1667
|
+
viewBox: "0 0 24 24",
|
|
1668
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1669
|
+
"path",
|
|
1670
|
+
{
|
|
1671
|
+
strokeLinecap: "round",
|
|
1672
|
+
strokeLinejoin: "round",
|
|
1673
|
+
strokeWidth: 2,
|
|
1674
|
+
d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
|
|
1675
|
+
}
|
|
1676
|
+
)
|
|
1677
|
+
}
|
|
1678
|
+
),
|
|
1679
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1680
|
+
"span",
|
|
1681
|
+
{
|
|
1682
|
+
className: cn(
|
|
1683
|
+
"flex-1 font-medium",
|
|
1684
|
+
"text-[var(--ash-font-size-sm,12px)]",
|
|
1685
|
+
"text-[var(--ash-text-primary,rgba(255,255,255,0.9))]"
|
|
1686
|
+
),
|
|
1687
|
+
children
|
|
1688
|
+
}
|
|
1689
|
+
),
|
|
1690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1691
|
+
"svg",
|
|
1692
|
+
{
|
|
1693
|
+
className: cn(
|
|
1694
|
+
"w-4 h-4 text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1695
|
+
"transition-transform",
|
|
1696
|
+
isOpen && "rotate-180"
|
|
1697
|
+
),
|
|
1698
|
+
fill: "none",
|
|
1699
|
+
stroke: "currentColor",
|
|
1700
|
+
viewBox: "0 0 24 24",
|
|
1701
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1702
|
+
"path",
|
|
1703
|
+
{
|
|
1704
|
+
strokeLinecap: "round",
|
|
1705
|
+
strokeLinejoin: "round",
|
|
1706
|
+
strokeWidth: 2,
|
|
1707
|
+
d: "M19 9l-7 7-7-7"
|
|
1708
|
+
}
|
|
1709
|
+
)
|
|
1710
|
+
}
|
|
1711
|
+
)
|
|
1830
1712
|
]
|
|
1831
1713
|
}
|
|
1832
1714
|
);
|
|
1833
1715
|
}
|
|
1834
|
-
function
|
|
1835
|
-
const
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
linesAdded: edit.linesAdded,
|
|
1848
|
-
linesRemoved: edit.linesRemoved
|
|
1849
|
-
});
|
|
1850
|
-
}
|
|
1851
|
-
} else if (actionType.action === "file_write") {
|
|
1852
|
-
const write = actionType;
|
|
1853
|
-
if (!fileMap.has(write.path)) {
|
|
1854
|
-
fileMap.set(write.path, {
|
|
1855
|
-
path: write.path,
|
|
1856
|
-
linesAdded: write.linesWritten
|
|
1857
|
-
});
|
|
1858
|
-
}
|
|
1716
|
+
function TaskContent({ children, className }) {
|
|
1717
|
+
const { isOpen } = useTask();
|
|
1718
|
+
if (!isOpen) return null;
|
|
1719
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1720
|
+
"div",
|
|
1721
|
+
{
|
|
1722
|
+
className: cn(
|
|
1723
|
+
"ash-task-content",
|
|
1724
|
+
"border-t border-[var(--ash-border-subtle,rgba(255,255,255,0.04))]",
|
|
1725
|
+
"ash-accordion-content",
|
|
1726
|
+
className
|
|
1727
|
+
),
|
|
1728
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 space-y-1", children })
|
|
1859
1729
|
}
|
|
1860
|
-
|
|
1861
|
-
return Array.from(fileMap.values());
|
|
1862
|
-
}
|
|
1863
|
-
function countActionTypes(toolCalls) {
|
|
1864
|
-
const counts = {};
|
|
1865
|
-
for (const tc of toolCalls) {
|
|
1866
|
-
const action = tc.actionType.action;
|
|
1867
|
-
counts[action] = (counts[action] || 0) + 1;
|
|
1868
|
-
}
|
|
1869
|
-
return counts;
|
|
1870
|
-
}
|
|
1871
|
-
function getActionIconComponent(action) {
|
|
1872
|
-
switch (action) {
|
|
1873
|
-
case "file_read":
|
|
1874
|
-
return FileIcon;
|
|
1875
|
-
case "file_edit":
|
|
1876
|
-
case "file_write":
|
|
1877
|
-
return EditIcon;
|
|
1878
|
-
case "command_run":
|
|
1879
|
-
return TerminalIcon;
|
|
1880
|
-
case "search":
|
|
1881
|
-
case "glob":
|
|
1882
|
-
return SearchIcon;
|
|
1883
|
-
default:
|
|
1884
|
-
return null;
|
|
1885
|
-
}
|
|
1730
|
+
);
|
|
1886
1731
|
}
|
|
1887
|
-
function
|
|
1888
|
-
|
|
1889
|
-
|
|
1732
|
+
function TaskItem({
|
|
1733
|
+
children,
|
|
1734
|
+
status,
|
|
1735
|
+
activeForm,
|
|
1890
1736
|
className
|
|
1891
1737
|
}) {
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
const actionCounts = react.useMemo(() => countActionTypes(toolCalls), [toolCalls]);
|
|
1896
|
-
const displayActions = react.useMemo(() => {
|
|
1897
|
-
return Object.entries(actionCounts).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([action]) => action);
|
|
1898
|
-
}, [actionCounts]);
|
|
1899
|
-
const totalCount = toolCalls.length;
|
|
1900
|
-
if (toolCalls.length === 0) {
|
|
1901
|
-
return null;
|
|
1902
|
-
}
|
|
1903
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("ash-animate-fade-in", className), children: [
|
|
1904
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1905
|
-
"button",
|
|
1738
|
+
const statusIcons = {
|
|
1739
|
+
pending: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1740
|
+
"svg",
|
|
1906
1741
|
{
|
|
1907
|
-
|
|
1908
|
-
|
|
1742
|
+
className: "w-4 h-4 text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1743
|
+
fill: "none",
|
|
1744
|
+
stroke: "currentColor",
|
|
1745
|
+
viewBox: "0 0 24 24",
|
|
1746
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeWidth: 2 })
|
|
1747
|
+
}
|
|
1748
|
+
),
|
|
1749
|
+
in_progress: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1750
|
+
"svg",
|
|
1751
|
+
{
|
|
1752
|
+
className: "w-4 h-4 text-yellow-400 animate-spin",
|
|
1753
|
+
fill: "none",
|
|
1754
|
+
viewBox: "0 0 24 24",
|
|
1909
1755
|
children: [
|
|
1910
1756
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1911
|
-
|
|
1757
|
+
"circle",
|
|
1912
1758
|
{
|
|
1913
|
-
className:
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1759
|
+
className: "opacity-25",
|
|
1760
|
+
cx: "12",
|
|
1761
|
+
cy: "12",
|
|
1762
|
+
r: "10",
|
|
1763
|
+
stroke: "currentColor",
|
|
1764
|
+
strokeWidth: "4"
|
|
1917
1765
|
}
|
|
1918
1766
|
),
|
|
1919
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1928
|
-
IconComponent,
|
|
1929
|
-
{
|
|
1930
|
-
className: "w-3.5 h-3.5 text-white/30"
|
|
1931
|
-
},
|
|
1932
|
-
action
|
|
1933
|
-
);
|
|
1934
|
-
}) }),
|
|
1935
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
1936
|
-
!expanded && fileChanges.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap justify-end", children: [
|
|
1937
|
-
fileChanges.slice(0, 4).map((fc) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1938
|
-
FileBadge,
|
|
1939
|
-
{
|
|
1940
|
-
path: fc.path,
|
|
1941
|
-
linesAdded: fc.linesAdded,
|
|
1942
|
-
linesRemoved: fc.linesRemoved
|
|
1943
|
-
},
|
|
1944
|
-
fc.path
|
|
1945
|
-
)),
|
|
1946
|
-
fileChanges.length > 4 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/40", children: [
|
|
1947
|
-
"+",
|
|
1948
|
-
fileChanges.length - 4,
|
|
1949
|
-
" more"
|
|
1950
|
-
] })
|
|
1951
|
-
] })
|
|
1767
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1768
|
+
"path",
|
|
1769
|
+
{
|
|
1770
|
+
className: "opacity-75",
|
|
1771
|
+
fill: "currentColor",
|
|
1772
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
1773
|
+
}
|
|
1774
|
+
)
|
|
1952
1775
|
]
|
|
1953
1776
|
}
|
|
1954
1777
|
),
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
ToolCallCard,
|
|
1958
|
-
{
|
|
1959
|
-
toolCall,
|
|
1960
|
-
defaultExpanded: true
|
|
1961
|
-
}
|
|
1962
|
-
),
|
|
1963
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1964
|
-
"button",
|
|
1965
|
-
{
|
|
1966
|
-
onClick: () => setExpandedCardId(null),
|
|
1967
|
-
className: "text-xs text-white/40 hover:text-white/60 mt-1 pl-1",
|
|
1968
|
-
children: "Collapse"
|
|
1969
|
-
}
|
|
1970
|
-
)
|
|
1971
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1972
|
-
"button",
|
|
1778
|
+
completed: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1779
|
+
"svg",
|
|
1973
1780
|
{
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
const existing = fileMap.get(edit.path);
|
|
1988
|
-
if (existing) {
|
|
1989
|
-
existing.linesAdded = (existing.linesAdded || 0) + (edit.linesAdded || 0);
|
|
1990
|
-
existing.linesRemoved = (existing.linesRemoved || 0) + (edit.linesRemoved || 0);
|
|
1991
|
-
} else {
|
|
1992
|
-
fileMap.set(edit.path, {
|
|
1993
|
-
path: edit.path,
|
|
1994
|
-
linesAdded: edit.linesAdded,
|
|
1995
|
-
linesRemoved: edit.linesRemoved
|
|
1996
|
-
});
|
|
1997
|
-
}
|
|
1998
|
-
} else if (actionType.action === "file_write") {
|
|
1999
|
-
if (!fileMap.has(actionType.path)) {
|
|
2000
|
-
fileMap.set(actionType.path, {
|
|
2001
|
-
path: actionType.path,
|
|
2002
|
-
linesAdded: actionType.linesWritten
|
|
2003
|
-
});
|
|
1781
|
+
className: "w-4 h-4 text-[var(--ash-accent,#ccff00)]",
|
|
1782
|
+
fill: "none",
|
|
1783
|
+
stroke: "currentColor",
|
|
1784
|
+
viewBox: "0 0 24 24",
|
|
1785
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1786
|
+
"path",
|
|
1787
|
+
{
|
|
1788
|
+
strokeLinecap: "round",
|
|
1789
|
+
strokeLinejoin: "round",
|
|
1790
|
+
strokeWidth: 2,
|
|
1791
|
+
d: "M5 13l4 4L19 7"
|
|
1792
|
+
}
|
|
1793
|
+
)
|
|
2004
1794
|
}
|
|
1795
|
+
)
|
|
1796
|
+
};
|
|
1797
|
+
const statusColors = {
|
|
1798
|
+
pending: "text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1799
|
+
in_progress: "text-[var(--ash-text-primary,rgba(255,255,255,0.9))]",
|
|
1800
|
+
completed: "text-[var(--ash-text-secondary,rgba(255,255,255,0.7))] line-through"
|
|
1801
|
+
};
|
|
1802
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1803
|
+
"div",
|
|
1804
|
+
{
|
|
1805
|
+
className: cn(
|
|
1806
|
+
"ash-task-item",
|
|
1807
|
+
"flex items-center gap-2",
|
|
1808
|
+
"px-2 py-1.5 rounded-md",
|
|
1809
|
+
status === "in_progress" && "bg-yellow-400/10",
|
|
1810
|
+
className
|
|
1811
|
+
),
|
|
1812
|
+
"data-task-status": status,
|
|
1813
|
+
children: [
|
|
1814
|
+
statusIcons[status],
|
|
1815
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1816
|
+
"span",
|
|
1817
|
+
{
|
|
1818
|
+
className: cn(
|
|
1819
|
+
"flex-1",
|
|
1820
|
+
"text-[var(--ash-font-size-sm,12px)]",
|
|
1821
|
+
statusColors[status]
|
|
1822
|
+
),
|
|
1823
|
+
children: status === "in_progress" && activeForm ? activeForm : children
|
|
1824
|
+
}
|
|
1825
|
+
)
|
|
1826
|
+
]
|
|
2005
1827
|
}
|
|
2006
|
-
|
|
2007
|
-
return Array.from(fileMap.values());
|
|
2008
|
-
}
|
|
2009
|
-
function countActionTypes2(toolCalls) {
|
|
2010
|
-
const counts = {};
|
|
2011
|
-
for (const tc of toolCalls) {
|
|
2012
|
-
const action = tc.actionType.action;
|
|
2013
|
-
counts[action] = (counts[action] || 0) + 1;
|
|
2014
|
-
}
|
|
2015
|
-
return counts;
|
|
2016
|
-
}
|
|
2017
|
-
function getActionIconComponent2(action) {
|
|
2018
|
-
switch (action) {
|
|
2019
|
-
case "file_read":
|
|
2020
|
-
return FileIcon;
|
|
2021
|
-
case "file_edit":
|
|
2022
|
-
case "file_write":
|
|
2023
|
-
return EditIcon;
|
|
2024
|
-
case "command_run":
|
|
2025
|
-
return TerminalIcon;
|
|
2026
|
-
case "search":
|
|
2027
|
-
case "glob":
|
|
2028
|
-
return SearchIcon;
|
|
2029
|
-
default:
|
|
2030
|
-
return null;
|
|
2031
|
-
}
|
|
1828
|
+
);
|
|
2032
1829
|
}
|
|
2033
|
-
function
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
className
|
|
1830
|
+
function TaskList({
|
|
1831
|
+
items,
|
|
1832
|
+
defaultOpen = true,
|
|
1833
|
+
className,
|
|
1834
|
+
title
|
|
2039
1835
|
}) {
|
|
2040
|
-
const
|
|
2041
|
-
const
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
}
|
|
2048
|
-
}, [onToggle]);
|
|
2049
|
-
const fileChanges = react.useMemo(() => extractFileChanges2(toolCalls), [toolCalls]);
|
|
2050
|
-
const actionCounts = react.useMemo(() => countActionTypes2(toolCalls), [toolCalls]);
|
|
2051
|
-
const displayActions = react.useMemo(() => {
|
|
2052
|
-
return Object.entries(actionCounts).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([action]) => action);
|
|
2053
|
-
}, [actionCounts]);
|
|
2054
|
-
if (toolCalls.length === 0) {
|
|
2055
|
-
return null;
|
|
2056
|
-
}
|
|
2057
|
-
const totalCount = toolCalls.length;
|
|
2058
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("ash-animate-fade-in", className), children: [
|
|
2059
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2060
|
-
"button",
|
|
1836
|
+
const completed = items.filter((t) => t.status === "completed").length;
|
|
1837
|
+
const total = items.length;
|
|
1838
|
+
const displayTitle = title || `Tasks (${completed}/${total})`;
|
|
1839
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Task, { defaultOpen, className, children: [
|
|
1840
|
+
/* @__PURE__ */ jsxRuntime.jsx(TaskTrigger, { children: displayTitle }),
|
|
1841
|
+
/* @__PURE__ */ jsxRuntime.jsx(TaskContent, { children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1842
|
+
TaskItem,
|
|
2061
1843
|
{
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
{
|
|
2069
|
-
className: cn(
|
|
2070
|
-
"w-3.5 h-3.5 text-white/40 transition-transform duration-200 shrink-0",
|
|
2071
|
-
isExpanded && "rotate-90"
|
|
2072
|
-
)
|
|
2073
|
-
}
|
|
2074
|
-
),
|
|
2075
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-white/60", children: [
|
|
2076
|
-
totalCount,
|
|
2077
|
-
" tool call",
|
|
2078
|
-
totalCount !== 1 ? "s" : ""
|
|
2079
|
-
] }),
|
|
2080
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: displayActions.map((action) => {
|
|
2081
|
-
const IconComponent = getActionIconComponent2(action);
|
|
2082
|
-
if (!IconComponent) return null;
|
|
2083
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2084
|
-
IconComponent,
|
|
2085
|
-
{
|
|
2086
|
-
className: "w-3.5 h-3.5 text-white/30"
|
|
2087
|
-
},
|
|
2088
|
-
action
|
|
2089
|
-
);
|
|
2090
|
-
}) }),
|
|
2091
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
2092
|
-
!isExpanded && fileChanges.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap justify-end", children: [
|
|
2093
|
-
fileChanges.slice(0, 4).map((fc) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2094
|
-
FileBadge,
|
|
2095
|
-
{
|
|
2096
|
-
path: fc.path,
|
|
2097
|
-
linesAdded: fc.linesAdded,
|
|
2098
|
-
linesRemoved: fc.linesRemoved
|
|
2099
|
-
},
|
|
2100
|
-
fc.path
|
|
2101
|
-
)),
|
|
2102
|
-
fileChanges.length > 4 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/40", children: [
|
|
2103
|
-
"+",
|
|
2104
|
-
fileChanges.length - 4,
|
|
2105
|
-
" more"
|
|
2106
|
-
] })
|
|
2107
|
-
] })
|
|
2108
|
-
]
|
|
2109
|
-
}
|
|
2110
|
-
),
|
|
2111
|
-
isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-5 border-l border-white/10 ml-1.5 mt-1 space-y-0.5", children: toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx(CompactToolRow, { toolCall }, toolCall.id)) })
|
|
1844
|
+
status: item.status,
|
|
1845
|
+
activeForm: item.activeForm,
|
|
1846
|
+
children: item.content
|
|
1847
|
+
},
|
|
1848
|
+
index
|
|
1849
|
+
)) })
|
|
2112
1850
|
] });
|
|
2113
1851
|
}
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
return
|
|
2121
|
-
}
|
|
2122
|
-
function isFileEditAction(action) {
|
|
2123
|
-
return action.action === "file_edit";
|
|
2124
|
-
}
|
|
2125
|
-
function isFileWriteAction(action) {
|
|
2126
|
-
return action.action === "file_write";
|
|
2127
|
-
}
|
|
2128
|
-
function isSearchAction(action) {
|
|
2129
|
-
return action.action === "search";
|
|
2130
|
-
}
|
|
2131
|
-
function isGlobAction(action) {
|
|
2132
|
-
return action.action === "glob";
|
|
2133
|
-
}
|
|
2134
|
-
function isWebFetchAction(action) {
|
|
2135
|
-
return action.action === "web_fetch";
|
|
2136
|
-
}
|
|
2137
|
-
function isWebSearchAction(action) {
|
|
2138
|
-
return action.action === "web_search";
|
|
1852
|
+
var AttachmentContext = react.createContext(null);
|
|
1853
|
+
function useAttachment() {
|
|
1854
|
+
const context = react.useContext(AttachmentContext);
|
|
1855
|
+
if (!context) {
|
|
1856
|
+
throw new Error("useAttachment must be used within an Attachment");
|
|
1857
|
+
}
|
|
1858
|
+
return context;
|
|
2139
1859
|
}
|
|
2140
|
-
function
|
|
2141
|
-
|
|
1860
|
+
function Attachments({
|
|
1861
|
+
children,
|
|
1862
|
+
layout = "inline",
|
|
1863
|
+
className
|
|
1864
|
+
}) {
|
|
1865
|
+
const layoutStyles = {
|
|
1866
|
+
grid: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2",
|
|
1867
|
+
inline: "flex flex-wrap gap-2",
|
|
1868
|
+
list: "flex flex-col gap-1"
|
|
1869
|
+
};
|
|
1870
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1871
|
+
"div",
|
|
1872
|
+
{
|
|
1873
|
+
className: cn(
|
|
1874
|
+
"ash-attachments",
|
|
1875
|
+
layoutStyles[layout],
|
|
1876
|
+
className
|
|
1877
|
+
),
|
|
1878
|
+
"data-layout": layout,
|
|
1879
|
+
children
|
|
1880
|
+
}
|
|
1881
|
+
);
|
|
2142
1882
|
}
|
|
2143
|
-
function
|
|
2144
|
-
|
|
1883
|
+
function Attachment({
|
|
1884
|
+
file,
|
|
1885
|
+
children,
|
|
1886
|
+
removable = false,
|
|
1887
|
+
onRemove,
|
|
1888
|
+
className
|
|
1889
|
+
}) {
|
|
1890
|
+
const contextValue = {
|
|
1891
|
+
file,
|
|
1892
|
+
removable,
|
|
1893
|
+
onRemove
|
|
1894
|
+
};
|
|
1895
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AttachmentContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1896
|
+
"div",
|
|
1897
|
+
{
|
|
1898
|
+
className: cn(
|
|
1899
|
+
"ash-attachment relative group",
|
|
1900
|
+
"rounded-[var(--ash-radius-sm,0.375rem)]",
|
|
1901
|
+
"border border-[var(--ash-border,rgba(255,255,255,0.08))]",
|
|
1902
|
+
"bg-[var(--ash-surface-elevated,#111111)]",
|
|
1903
|
+
"overflow-hidden",
|
|
1904
|
+
"hover:border-[var(--ash-border-emphasis,rgba(255,255,255,0.15))]",
|
|
1905
|
+
"transition-colors",
|
|
1906
|
+
className
|
|
1907
|
+
),
|
|
1908
|
+
"data-file-type": file.type,
|
|
1909
|
+
children: children || /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1910
|
+
/* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, {}),
|
|
1911
|
+
/* @__PURE__ */ jsxRuntime.jsx(AttachmentInfo, {}),
|
|
1912
|
+
removable && /* @__PURE__ */ jsxRuntime.jsx(AttachmentRemove, {})
|
|
1913
|
+
] })
|
|
1914
|
+
}
|
|
1915
|
+
) });
|
|
2145
1916
|
}
|
|
2146
|
-
function
|
|
2147
|
-
|
|
1917
|
+
function AttachmentPreview({
|
|
1918
|
+
className,
|
|
1919
|
+
height = 80
|
|
1920
|
+
}) {
|
|
1921
|
+
const { file } = useAttachment();
|
|
1922
|
+
const isImage = file.type.startsWith("image/");
|
|
1923
|
+
const url = "url" in file ? file.url : "base64" in file ? `data:${file.type};base64,${file.base64}` : void 0;
|
|
1924
|
+
if (isImage && url) {
|
|
1925
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1926
|
+
"div",
|
|
1927
|
+
{
|
|
1928
|
+
className: cn(
|
|
1929
|
+
"ash-attachment-preview",
|
|
1930
|
+
"w-full bg-black/20 overflow-hidden",
|
|
1931
|
+
className
|
|
1932
|
+
),
|
|
1933
|
+
style: { height },
|
|
1934
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1935
|
+
"img",
|
|
1936
|
+
{
|
|
1937
|
+
src: url,
|
|
1938
|
+
alt: file.name,
|
|
1939
|
+
className: "w-full h-full object-cover"
|
|
1940
|
+
}
|
|
1941
|
+
)
|
|
1942
|
+
}
|
|
1943
|
+
);
|
|
1944
|
+
}
|
|
1945
|
+
const iconForType = () => {
|
|
1946
|
+
if (file.type.includes("pdf")) {
|
|
1947
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "w-8 h-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
|
|
1948
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }),
|
|
1949
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "7", y: "16", fontSize: "6", fill: "currentColor", stroke: "none", fontWeight: "bold", children: "PDF" })
|
|
1950
|
+
] });
|
|
1951
|
+
}
|
|
1952
|
+
if (file.type.includes("text") || file.type.includes("json")) {
|
|
1953
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-8 h-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
|
|
1954
|
+
}
|
|
1955
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-8 h-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) });
|
|
1956
|
+
};
|
|
1957
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1958
|
+
"div",
|
|
1959
|
+
{
|
|
1960
|
+
className: cn(
|
|
1961
|
+
"ash-attachment-preview",
|
|
1962
|
+
"w-full flex items-center justify-center",
|
|
1963
|
+
"bg-[var(--ash-surface-dark,#0a0a0a)]",
|
|
1964
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1965
|
+
className
|
|
1966
|
+
),
|
|
1967
|
+
style: { height },
|
|
1968
|
+
children: iconForType()
|
|
1969
|
+
}
|
|
1970
|
+
);
|
|
2148
1971
|
}
|
|
2149
|
-
function
|
|
2150
|
-
|
|
1972
|
+
function AttachmentInfo({
|
|
1973
|
+
className,
|
|
1974
|
+
showSize = true
|
|
1975
|
+
}) {
|
|
1976
|
+
const { file } = useAttachment();
|
|
1977
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1978
|
+
"div",
|
|
1979
|
+
{
|
|
1980
|
+
className: cn(
|
|
1981
|
+
"ash-attachment-info",
|
|
1982
|
+
"px-2 py-1.5",
|
|
1983
|
+
"truncate",
|
|
1984
|
+
className
|
|
1985
|
+
),
|
|
1986
|
+
children: [
|
|
1987
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1988
|
+
"div",
|
|
1989
|
+
{
|
|
1990
|
+
className: cn(
|
|
1991
|
+
"text-[var(--ash-font-size-xs,10px)]",
|
|
1992
|
+
"text-[var(--ash-text-primary,rgba(255,255,255,0.9))]",
|
|
1993
|
+
"truncate font-medium"
|
|
1994
|
+
),
|
|
1995
|
+
title: file.name,
|
|
1996
|
+
children: file.name
|
|
1997
|
+
}
|
|
1998
|
+
),
|
|
1999
|
+
showSize && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2000
|
+
"div",
|
|
2001
|
+
{
|
|
2002
|
+
className: cn(
|
|
2003
|
+
"text-[var(--ash-font-size-xs,10px)]",
|
|
2004
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]"
|
|
2005
|
+
),
|
|
2006
|
+
children: formatFileSize(file.size)
|
|
2007
|
+
}
|
|
2008
|
+
)
|
|
2009
|
+
]
|
|
2010
|
+
}
|
|
2011
|
+
);
|
|
2151
2012
|
}
|
|
2152
|
-
function
|
|
2153
|
-
|
|
2013
|
+
function AttachmentRemove({ className }) {
|
|
2014
|
+
const { onRemove, removable } = useAttachment();
|
|
2015
|
+
if (!removable || !onRemove) return null;
|
|
2016
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2017
|
+
"button",
|
|
2018
|
+
{
|
|
2019
|
+
onClick: (e) => {
|
|
2020
|
+
e.stopPropagation();
|
|
2021
|
+
onRemove();
|
|
2022
|
+
},
|
|
2023
|
+
className: cn(
|
|
2024
|
+
"ash-attachment-remove",
|
|
2025
|
+
"absolute top-1 right-1",
|
|
2026
|
+
"w-5 h-5 rounded-full",
|
|
2027
|
+
"flex items-center justify-center",
|
|
2028
|
+
"bg-black/60 text-white/80",
|
|
2029
|
+
"hover:bg-black/80 hover:text-white",
|
|
2030
|
+
"opacity-0 group-hover:opacity-100",
|
|
2031
|
+
"transition-opacity",
|
|
2032
|
+
className
|
|
2033
|
+
),
|
|
2034
|
+
"aria-label": "Remove attachment",
|
|
2035
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
2036
|
+
}
|
|
2037
|
+
);
|
|
2154
2038
|
}
|
|
2155
|
-
function
|
|
2156
|
-
|
|
2039
|
+
function FileBadgeCompact({
|
|
2040
|
+
file,
|
|
2041
|
+
removable = false,
|
|
2042
|
+
onRemove,
|
|
2043
|
+
className
|
|
2044
|
+
}) {
|
|
2045
|
+
const isImage = file.type.startsWith("image/");
|
|
2046
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2047
|
+
"div",
|
|
2048
|
+
{
|
|
2049
|
+
className: cn(
|
|
2050
|
+
"ash-file-badge group inline-flex items-center gap-1.5",
|
|
2051
|
+
"px-2 py-1 rounded-md",
|
|
2052
|
+
"bg-[var(--ash-surface-elevated,#111111)]",
|
|
2053
|
+
"border border-[var(--ash-border,rgba(255,255,255,0.08))]",
|
|
2054
|
+
"text-[var(--ash-font-size-xs,10px)]",
|
|
2055
|
+
className
|
|
2056
|
+
),
|
|
2057
|
+
children: [
|
|
2058
|
+
isImage ? /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3 text-[var(--ash-text-muted)]", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3 text-[var(--ash-text-muted)]", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) }),
|
|
2059
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--ash-text-primary)] truncate max-w-[100px]", children: file.name }),
|
|
2060
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--ash-text-muted)]", children: formatFileSize(file.size) }),
|
|
2061
|
+
removable && onRemove && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2062
|
+
"button",
|
|
2063
|
+
{
|
|
2064
|
+
onClick: (e) => {
|
|
2065
|
+
e.stopPropagation();
|
|
2066
|
+
onRemove();
|
|
2067
|
+
},
|
|
2068
|
+
className: cn(
|
|
2069
|
+
"ml-0.5 text-[var(--ash-text-muted)]",
|
|
2070
|
+
"hover:text-red-400 transition-colors",
|
|
2071
|
+
"opacity-0 group-hover:opacity-100"
|
|
2072
|
+
),
|
|
2073
|
+
"aria-label": "Remove",
|
|
2074
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
2075
|
+
}
|
|
2076
|
+
)
|
|
2077
|
+
]
|
|
2078
|
+
}
|
|
2079
|
+
);
|
|
2157
2080
|
}
|
|
2158
|
-
function
|
|
2159
|
-
|
|
2081
|
+
function Shimmer({
|
|
2082
|
+
children,
|
|
2083
|
+
className,
|
|
2084
|
+
isActive = true
|
|
2085
|
+
}) {
|
|
2086
|
+
if (!isActive) return null;
|
|
2087
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2088
|
+
"div",
|
|
2089
|
+
{
|
|
2090
|
+
className: cn(
|
|
2091
|
+
"ash-shimmer",
|
|
2092
|
+
"flex flex-col gap-2",
|
|
2093
|
+
className
|
|
2094
|
+
),
|
|
2095
|
+
role: "status",
|
|
2096
|
+
"aria-label": "Loading",
|
|
2097
|
+
children: children || /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2098
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShimmerLine, { width: "100%" }),
|
|
2099
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShimmerLine, { width: "80%" }),
|
|
2100
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShimmerLine, { width: "60%" })
|
|
2101
|
+
] })
|
|
2102
|
+
}
|
|
2103
|
+
);
|
|
2160
2104
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
mode: prev.mode === "inline" ? "compact" : "inline"
|
|
2183
|
-
}));
|
|
2184
|
-
}, []);
|
|
2185
|
-
const value = react.useMemo(
|
|
2186
|
-
() => ({ config, setMode, setConfig, toggleMode }),
|
|
2187
|
-
[config, setMode, setConfig, toggleMode]
|
|
2105
|
+
function ShimmerLine({
|
|
2106
|
+
width = "100%",
|
|
2107
|
+
height = 16,
|
|
2108
|
+
className
|
|
2109
|
+
}) {
|
|
2110
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2111
|
+
"div",
|
|
2112
|
+
{
|
|
2113
|
+
className: cn(
|
|
2114
|
+
"ash-shimmer-line",
|
|
2115
|
+
"rounded-md",
|
|
2116
|
+
"bg-gradient-to-r from-white/5 via-white/10 to-white/5",
|
|
2117
|
+
"bg-[length:200%_100%]",
|
|
2118
|
+
"animate-[shimmer_1.5s_ease-in-out_infinite]",
|
|
2119
|
+
className
|
|
2120
|
+
),
|
|
2121
|
+
style: {
|
|
2122
|
+
width: typeof width === "number" ? `${width}px` : width,
|
|
2123
|
+
height
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2188
2126
|
);
|
|
2189
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DisplayModeContext.Provider, { value, children });
|
|
2190
2127
|
}
|
|
2191
|
-
function
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2128
|
+
function ShimmerBlock({
|
|
2129
|
+
width = "100%",
|
|
2130
|
+
height = 100,
|
|
2131
|
+
rounded = "md",
|
|
2132
|
+
className
|
|
2133
|
+
}) {
|
|
2134
|
+
const roundedStyles = {
|
|
2135
|
+
none: "rounded-none",
|
|
2136
|
+
sm: "rounded-sm",
|
|
2137
|
+
md: "rounded-md",
|
|
2138
|
+
lg: "rounded-lg",
|
|
2139
|
+
full: "rounded-full"
|
|
2140
|
+
};
|
|
2141
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2142
|
+
"div",
|
|
2143
|
+
{
|
|
2144
|
+
className: cn(
|
|
2145
|
+
"ash-shimmer-block",
|
|
2146
|
+
roundedStyles[rounded],
|
|
2147
|
+
"bg-gradient-to-r from-white/5 via-white/10 to-white/5",
|
|
2148
|
+
"bg-[length:200%_100%]",
|
|
2149
|
+
"animate-[shimmer_1.5s_ease-in-out_infinite]",
|
|
2150
|
+
className
|
|
2151
|
+
),
|
|
2152
|
+
style: {
|
|
2153
|
+
width: typeof width === "number" ? `${width}px` : width,
|
|
2154
|
+
height
|
|
2201
2155
|
}
|
|
2202
|
-
}
|
|
2203
|
-
|
|
2204
|
-
return context;
|
|
2156
|
+
}
|
|
2157
|
+
);
|
|
2205
2158
|
}
|
|
2206
|
-
function
|
|
2207
|
-
|
|
2208
|
-
return config;
|
|
2209
|
-
}
|
|
2210
|
-
function MessageList({
|
|
2211
|
-
entries,
|
|
2212
|
-
loading,
|
|
2213
|
-
streamingContent,
|
|
2214
|
-
displayConfig: displayConfigProp,
|
|
2215
|
-
onOptionSelect,
|
|
2216
|
-
renderWidget,
|
|
2217
|
-
onWidgetAction,
|
|
2218
|
-
autoScroll = true,
|
|
2219
|
-
richContentRenderers,
|
|
2159
|
+
function ShimmerText({
|
|
2160
|
+
chars = 20,
|
|
2220
2161
|
className
|
|
2221
2162
|
}) {
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
});
|
|
2240
|
-
};
|
|
2241
|
-
},
|
|
2242
|
-
[onWidgetAction]
|
|
2163
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2164
|
+
"span",
|
|
2165
|
+
{
|
|
2166
|
+
className: cn(
|
|
2167
|
+
"ash-shimmer-text inline-block",
|
|
2168
|
+
"rounded",
|
|
2169
|
+
"bg-gradient-to-r from-white/5 via-white/10 to-white/5",
|
|
2170
|
+
"bg-[length:200%_100%]",
|
|
2171
|
+
"animate-[shimmer_1.5s_ease-in-out_infinite]",
|
|
2172
|
+
className
|
|
2173
|
+
),
|
|
2174
|
+
style: {
|
|
2175
|
+
width: `${chars}ch`,
|
|
2176
|
+
height: "1em",
|
|
2177
|
+
verticalAlign: "middle"
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2243
2180
|
);
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2181
|
+
}
|
|
2182
|
+
function LoadingDots({
|
|
2183
|
+
size = "md",
|
|
2184
|
+
className
|
|
2185
|
+
}) {
|
|
2186
|
+
const sizeStyles = {
|
|
2187
|
+
sm: "w-1 h-1",
|
|
2188
|
+
md: "w-1.5 h-1.5",
|
|
2189
|
+
lg: "w-2 h-2"
|
|
2190
|
+
};
|
|
2191
|
+
const gapStyles = {
|
|
2192
|
+
sm: "gap-0.5",
|
|
2193
|
+
md: "gap-1",
|
|
2194
|
+
lg: "gap-1.5"
|
|
2195
|
+
};
|
|
2196
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2197
|
+
"span",
|
|
2198
|
+
{
|
|
2199
|
+
className: cn(
|
|
2200
|
+
"ash-loading-dots inline-flex items-center",
|
|
2201
|
+
gapStyles[size],
|
|
2202
|
+
className
|
|
2203
|
+
),
|
|
2204
|
+
role: "status",
|
|
2205
|
+
"aria-label": "Loading",
|
|
2206
|
+
children: [0, 1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2207
|
+
"span",
|
|
2208
|
+
{
|
|
2209
|
+
className: cn(
|
|
2210
|
+
sizeStyles[size],
|
|
2211
|
+
"rounded-full",
|
|
2212
|
+
"bg-current",
|
|
2213
|
+
"animate-bounce"
|
|
2214
|
+
),
|
|
2215
|
+
style: { animationDelay: `${i * 150}ms` }
|
|
2216
|
+
},
|
|
2217
|
+
i
|
|
2218
|
+
))
|
|
2251
2219
|
}
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
function LoadingSpinner({
|
|
2223
|
+
size = "md",
|
|
2224
|
+
className
|
|
2225
|
+
}) {
|
|
2226
|
+
const sizeStyles = {
|
|
2227
|
+
sm: "w-4 h-4",
|
|
2228
|
+
md: "w-6 h-6",
|
|
2229
|
+
lg: "w-8 h-8"
|
|
2230
|
+
};
|
|
2231
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2232
|
+
"svg",
|
|
2233
|
+
{
|
|
2234
|
+
className: cn(
|
|
2235
|
+
"ash-loading-spinner animate-spin",
|
|
2236
|
+
sizeStyles[size],
|
|
2237
|
+
className
|
|
2238
|
+
),
|
|
2239
|
+
fill: "none",
|
|
2240
|
+
viewBox: "0 0 24 24",
|
|
2241
|
+
role: "status",
|
|
2242
|
+
"aria-label": "Loading",
|
|
2243
|
+
children: [
|
|
2244
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2245
|
+
"circle",
|
|
2272
2246
|
{
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-full bg-[var(--ash-accent)]/20 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "w-4 h-4 text-[var(--ash-accent)]" }) }),
|
|
2284
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: config.mode === "accordion" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2285
|
-
StepAccordion,
|
|
2247
|
+
className: "opacity-25",
|
|
2248
|
+
cx: "12",
|
|
2249
|
+
cy: "12",
|
|
2250
|
+
r: "10",
|
|
2251
|
+
stroke: "currentColor",
|
|
2252
|
+
strokeWidth: "4"
|
|
2253
|
+
}
|
|
2254
|
+
),
|
|
2255
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2256
|
+
"path",
|
|
2286
2257
|
{
|
|
2287
|
-
|
|
2288
|
-
|
|
2258
|
+
className: "opacity-75",
|
|
2259
|
+
fill: "currentColor",
|
|
2260
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
2289
2261
|
}
|
|
2290
|
-
)
|
|
2291
|
-
|
|
2262
|
+
)
|
|
2263
|
+
]
|
|
2264
|
+
}
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
function MessageShimmer({
|
|
2268
|
+
role = "assistant",
|
|
2269
|
+
className
|
|
2270
|
+
}) {
|
|
2271
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2272
|
+
"div",
|
|
2273
|
+
{
|
|
2274
|
+
className: cn(
|
|
2275
|
+
"ash-message-shimmer flex gap-2",
|
|
2276
|
+
role === "user" && "flex-row-reverse",
|
|
2277
|
+
className
|
|
2278
|
+
),
|
|
2279
|
+
children: [
|
|
2280
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2281
|
+
ShimmerBlock,
|
|
2292
2282
|
{
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2283
|
+
width: 20,
|
|
2284
|
+
height: 20,
|
|
2285
|
+
rounded: "full"
|
|
2296
2286
|
}
|
|
2297
|
-
)
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl p-3 bg-white/5", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator, { variant: "dots" }) })
|
|
2307
|
-
] }),
|
|
2308
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
|
|
2309
|
-
] });
|
|
2287
|
+
),
|
|
2288
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-2 max-w-[80%]", children: [
|
|
2289
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShimmerLine, { width: "100%", height: 14 }),
|
|
2290
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShimmerLine, { width: "85%", height: 14 }),
|
|
2291
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShimmerLine, { width: "70%", height: 14 })
|
|
2292
|
+
] })
|
|
2293
|
+
]
|
|
2294
|
+
}
|
|
2295
|
+
);
|
|
2310
2296
|
}
|
|
2311
2297
|
function getLevelIcon(level) {
|
|
2312
2298
|
switch (level) {
|
|
@@ -2452,208 +2438,6 @@ function LogsPanel({
|
|
|
2452
2438
|
}
|
|
2453
2439
|
);
|
|
2454
2440
|
}
|
|
2455
|
-
function CompactToolStatusLine({
|
|
2456
|
-
toolCall,
|
|
2457
|
-
previousToolCall,
|
|
2458
|
-
animationDuration = 300,
|
|
2459
|
-
className
|
|
2460
|
-
}) {
|
|
2461
|
-
const [isAnimating, setIsAnimating] = react.useState(false);
|
|
2462
|
-
const [displayedToolCall, setDisplayedToolCall] = react.useState(toolCall);
|
|
2463
|
-
const [exitingToolCall, setExitingToolCall] = react.useState(null);
|
|
2464
|
-
const prevToolCallRef = react.useRef(null);
|
|
2465
|
-
react.useEffect(() => {
|
|
2466
|
-
if (toolCall.id !== prevToolCallRef.current) {
|
|
2467
|
-
if (prevToolCallRef.current !== null && previousToolCall) {
|
|
2468
|
-
setExitingToolCall(previousToolCall);
|
|
2469
|
-
setIsAnimating(true);
|
|
2470
|
-
const timer = setTimeout(() => {
|
|
2471
|
-
setDisplayedToolCall(toolCall);
|
|
2472
|
-
setExitingToolCall(null);
|
|
2473
|
-
setIsAnimating(false);
|
|
2474
|
-
}, animationDuration);
|
|
2475
|
-
prevToolCallRef.current = toolCall.id;
|
|
2476
|
-
return () => clearTimeout(timer);
|
|
2477
|
-
} else {
|
|
2478
|
-
setDisplayedToolCall(toolCall);
|
|
2479
|
-
prevToolCallRef.current = toolCall.id;
|
|
2480
|
-
}
|
|
2481
|
-
} else {
|
|
2482
|
-
setDisplayedToolCall(toolCall);
|
|
2483
|
-
}
|
|
2484
|
-
return void 0;
|
|
2485
|
-
}, [toolCall, previousToolCall, animationDuration]);
|
|
2486
|
-
const statusClasses = {
|
|
2487
|
-
pending: "border-yellow-500/30",
|
|
2488
|
-
success: "border-[var(--ash-accent)]/30",
|
|
2489
|
-
failed: "border-red-500/30"
|
|
2490
|
-
};
|
|
2491
|
-
const renderToolCallContent = (tc, isExiting) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2492
|
-
"div",
|
|
2493
|
-
{
|
|
2494
|
-
className: cn(
|
|
2495
|
-
"flex items-center gap-3 px-4 py-2.5",
|
|
2496
|
-
isExiting ? "ash-status-line-exit" : isAnimating ? "ash-status-line-enter" : ""
|
|
2497
|
-
),
|
|
2498
|
-
style: {
|
|
2499
|
-
animationDuration: `${animationDuration}ms`
|
|
2500
|
-
},
|
|
2501
|
-
children: [
|
|
2502
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2503
|
-
"div",
|
|
2504
|
-
{
|
|
2505
|
-
className: cn(
|
|
2506
|
-
"w-6 h-6 rounded-lg flex items-center justify-center shrink-0",
|
|
2507
|
-
tc.status === "pending" ? "bg-yellow-500/20" : tc.status === "failed" ? "bg-red-500/20" : "bg-[var(--ash-accent)]/20"
|
|
2508
|
-
),
|
|
2509
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2510
|
-
ActionIcon,
|
|
2511
|
-
{
|
|
2512
|
-
actionType: tc.actionType,
|
|
2513
|
-
className: cn(
|
|
2514
|
-
"w-3.5 h-3.5",
|
|
2515
|
-
tc.status === "pending" ? "text-yellow-400" : tc.status === "failed" ? "text-red-400" : "text-[var(--ash-accent)]"
|
|
2516
|
-
)
|
|
2517
|
-
}
|
|
2518
|
-
)
|
|
2519
|
-
}
|
|
2520
|
-
),
|
|
2521
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-white shrink-0", children: getActionLabel(tc.actionType) }),
|
|
2522
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-sm truncate text-white/60 flex-1 min-w-0", children: tc.summary }),
|
|
2523
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status: tc.status, size: "sm" })
|
|
2524
|
-
]
|
|
2525
|
-
}
|
|
2526
|
-
);
|
|
2527
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2528
|
-
"div",
|
|
2529
|
-
{
|
|
2530
|
-
className: cn(
|
|
2531
|
-
"relative rounded-xl border bg-[var(--ash-surface-dark,#0a0a0a)] overflow-hidden",
|
|
2532
|
-
statusClasses[displayedToolCall.status],
|
|
2533
|
-
displayedToolCall.status === "pending" && "ash-tool-status-pending",
|
|
2534
|
-
className
|
|
2535
|
-
),
|
|
2536
|
-
children: [
|
|
2537
|
-
exitingToolCall && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0", children: renderToolCallContent(exitingToolCall, true) }),
|
|
2538
|
-
renderToolCallContent(displayedToolCall, false)
|
|
2539
|
-
]
|
|
2540
|
-
}
|
|
2541
|
-
);
|
|
2542
|
-
}
|
|
2543
|
-
function TodoStatusIcon({ status, className = "w-4 h-4" }) {
|
|
2544
|
-
switch (status) {
|
|
2545
|
-
case "completed":
|
|
2546
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, { className: cn(className, "text-emerald-400") });
|
|
2547
|
-
case "in_progress":
|
|
2548
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LoaderIcon, { className: cn(className, "text-yellow-400 animate-spin") });
|
|
2549
|
-
case "pending":
|
|
2550
|
-
default:
|
|
2551
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CircleIcon, { className: cn(className, "text-white/30") });
|
|
2552
|
-
}
|
|
2553
|
-
}
|
|
2554
|
-
function TodoListItem({ todo, index, compact = false }) {
|
|
2555
|
-
const displayText = todo.status === "in_progress" ? todo.activeForm : todo.content;
|
|
2556
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2557
|
-
"div",
|
|
2558
|
-
{
|
|
2559
|
-
className: cn(
|
|
2560
|
-
"flex items-start gap-2 transition-all duration-200",
|
|
2561
|
-
compact ? "py-1" : "py-1.5",
|
|
2562
|
-
todo.status === "completed" && "opacity-60",
|
|
2563
|
-
todo.status === "in_progress" && "bg-yellow-500/5 -mx-2 px-2 rounded-md"
|
|
2564
|
-
),
|
|
2565
|
-
children: [
|
|
2566
|
-
/* @__PURE__ */ jsxRuntime.jsx(TodoStatusIcon, { status: todo.status, className: compact ? "w-3.5 h-3.5 mt-0.5" : "w-4 h-4 mt-0.5" }),
|
|
2567
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2568
|
-
"span",
|
|
2569
|
-
{
|
|
2570
|
-
className: cn(
|
|
2571
|
-
"flex-1 text-white/80",
|
|
2572
|
-
compact ? "text-xs" : "text-sm",
|
|
2573
|
-
todo.status === "completed" && "line-through text-white/50"
|
|
2574
|
-
),
|
|
2575
|
-
children: [
|
|
2576
|
-
!compact && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-white/40 mr-1.5", children: [
|
|
2577
|
-
index + 1,
|
|
2578
|
-
"."
|
|
2579
|
-
] }),
|
|
2580
|
-
displayText
|
|
2581
|
-
]
|
|
2582
|
-
}
|
|
2583
|
-
)
|
|
2584
|
-
]
|
|
2585
|
-
}
|
|
2586
|
-
);
|
|
2587
|
-
}
|
|
2588
|
-
function TodoProgress({ completed, total, className }) {
|
|
2589
|
-
const percentage = total > 0 ? Math.round(completed / total * 100) : 0;
|
|
2590
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
|
|
2591
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-1.5 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2592
|
-
"div",
|
|
2593
|
-
{
|
|
2594
|
-
className: "h-full bg-emerald-400 rounded-full transition-all duration-500 ease-out",
|
|
2595
|
-
style: { width: `${percentage}%` }
|
|
2596
|
-
}
|
|
2597
|
-
) }),
|
|
2598
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/50 tabular-nums min-w-[3rem] text-right", children: [
|
|
2599
|
-
completed,
|
|
2600
|
-
"/",
|
|
2601
|
-
total
|
|
2602
|
-
] })
|
|
2603
|
-
] });
|
|
2604
|
-
}
|
|
2605
|
-
function TodoPanel({
|
|
2606
|
-
todos,
|
|
2607
|
-
title,
|
|
2608
|
-
compact = false,
|
|
2609
|
-
showProgress = true,
|
|
2610
|
-
className
|
|
2611
|
-
}) {
|
|
2612
|
-
const stats = react.useMemo(() => {
|
|
2613
|
-
return {
|
|
2614
|
-
total: todos.length,
|
|
2615
|
-
completed: todos.filter((t) => t.status === "completed").length,
|
|
2616
|
-
inProgress: todos.filter((t) => t.status === "in_progress").length,
|
|
2617
|
-
pending: todos.filter((t) => t.status === "pending").length
|
|
2618
|
-
};
|
|
2619
|
-
}, [todos]);
|
|
2620
|
-
if (todos.length === 0) {
|
|
2621
|
-
return null;
|
|
2622
|
-
}
|
|
2623
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2624
|
-
"div",
|
|
2625
|
-
{
|
|
2626
|
-
className: cn(
|
|
2627
|
-
"rounded-lg border border-white/10 bg-white/5 overflow-hidden",
|
|
2628
|
-
className
|
|
2629
|
-
),
|
|
2630
|
-
children: [
|
|
2631
|
-
(title || showProgress) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("border-b border-white/5", compact ? "px-2 py-1.5" : "px-3 py-2"), children: [
|
|
2632
|
-
title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("font-medium text-white/90 mb-1.5", compact ? "text-xs" : "text-sm"), children: title }),
|
|
2633
|
-
showProgress && /* @__PURE__ */ jsxRuntime.jsx(TodoProgress, { completed: stats.completed, total: stats.total })
|
|
2634
|
-
] }),
|
|
2635
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(compact ? "px-2 py-1.5" : "px-3 py-2"), children: todos.map((todo, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2636
|
-
TodoListItem,
|
|
2637
|
-
{
|
|
2638
|
-
todo,
|
|
2639
|
-
index,
|
|
2640
|
-
compact
|
|
2641
|
-
},
|
|
2642
|
-
`${todo.content}-${index}`
|
|
2643
|
-
)) }),
|
|
2644
|
-
!compact && stats.inProgress > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-t border-white/5 bg-yellow-500/5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-yellow-400", children: [
|
|
2645
|
-
/* @__PURE__ */ jsxRuntime.jsx(LoaderIcon, { className: "w-3 h-3 animate-spin" }),
|
|
2646
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2647
|
-
stats.inProgress,
|
|
2648
|
-
" task",
|
|
2649
|
-
stats.inProgress !== 1 ? "s" : "",
|
|
2650
|
-
" in progress"
|
|
2651
|
-
] })
|
|
2652
|
-
] }) })
|
|
2653
|
-
]
|
|
2654
|
-
}
|
|
2655
|
-
);
|
|
2656
|
-
}
|
|
2657
2441
|
function EnvVarsPanel({
|
|
2658
2442
|
envVars,
|
|
2659
2443
|
onChange,
|
|
@@ -2785,236 +2569,90 @@ function EnvVarsPanel({
|
|
|
2785
2569
|
onClick: handleAddEnvVar,
|
|
2786
2570
|
disabled: !newEnvKey.trim(),
|
|
2787
2571
|
className: "ash-env-vars-add-button",
|
|
2788
|
-
children: "Add"
|
|
2789
|
-
}
|
|
2790
|
-
)
|
|
2791
|
-
] }),
|
|
2792
|
-
helperText && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ash-env-vars-helper", children: helperText })
|
|
2793
|
-
] })
|
|
2794
|
-
] });
|
|
2795
|
-
}
|
|
2796
|
-
function DisplayModeToggle({
|
|
2797
|
-
className,
|
|
2798
|
-
showLabel = true,
|
|
2799
|
-
labels = { inline: "Inline", compact: "Compact", accordion: "Steps" },
|
|
2800
|
-
modes = ["inline", "compact", "accordion"]
|
|
2801
|
-
}) {
|
|
2802
|
-
const { config, setMode } = useDisplayMode();
|
|
2803
|
-
const currentMode = config.mode;
|
|
2804
|
-
const currentIndex = modes.indexOf(currentMode);
|
|
2805
|
-
const effectiveIndex = currentIndex === -1 ? 0 : currentIndex;
|
|
2806
|
-
const nextIndex = (effectiveIndex + 1) % modes.length;
|
|
2807
|
-
const nextMode = modes[nextIndex];
|
|
2808
|
-
const handleClick = () => {
|
|
2809
|
-
setMode(nextMode);
|
|
2810
|
-
};
|
|
2811
|
-
const getIcon = (mode) => {
|
|
2812
|
-
switch (mode) {
|
|
2813
|
-
case "inline":
|
|
2814
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2815
|
-
"svg",
|
|
2816
|
-
{
|
|
2817
|
-
className: "ash-display-mode-icon",
|
|
2818
|
-
viewBox: "0 0 24 24",
|
|
2819
|
-
fill: "none",
|
|
2820
|
-
stroke: "currentColor",
|
|
2821
|
-
strokeWidth: "1.5",
|
|
2822
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2823
|
-
"path",
|
|
2824
|
-
{
|
|
2825
|
-
strokeLinecap: "round",
|
|
2826
|
-
strokeLinejoin: "round",
|
|
2827
|
-
d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
|
|
2828
|
-
}
|
|
2829
|
-
)
|
|
2572
|
+
children: "Add"
|
|
2830
2573
|
}
|
|
2831
|
-
)
|
|
2832
|
-
|
|
2833
|
-
|
|
2574
|
+
)
|
|
2575
|
+
] }),
|
|
2576
|
+
helperText && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ash-env-vars-helper", children: helperText })
|
|
2577
|
+
] })
|
|
2578
|
+
] });
|
|
2579
|
+
}
|
|
2580
|
+
function OptionCards({ options, onSelect, className }) {
|
|
2581
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-2 mt-3", className), style: {
|
|
2582
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))"
|
|
2583
|
+
}, children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2584
|
+
"button",
|
|
2585
|
+
{
|
|
2586
|
+
onClick: () => onSelect(option),
|
|
2587
|
+
className: cn(
|
|
2588
|
+
"flex items-start gap-3 p-3 rounded-xl text-left",
|
|
2589
|
+
"bg-white/5 border border-white/10",
|
|
2590
|
+
"hover:bg-[var(--ash-accent)]/10 hover:border-[var(--ash-accent)]/30",
|
|
2591
|
+
"focus:outline-none focus:ring-2 focus:ring-[var(--ash-accent)]/50",
|
|
2592
|
+
"transition-all duration-200 cursor-pointer",
|
|
2593
|
+
"group"
|
|
2594
|
+
),
|
|
2595
|
+
children: [
|
|
2596
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
2597
|
+
"flex-shrink-0 w-6 h-6 rounded-lg",
|
|
2598
|
+
"bg-[var(--ash-accent)]/20 text-[var(--ash-accent)]",
|
|
2599
|
+
"flex items-center justify-center",
|
|
2600
|
+
"text-xs font-semibold",
|
|
2601
|
+
"group-hover:bg-[var(--ash-accent)]/30",
|
|
2602
|
+
"transition-colors duration-200"
|
|
2603
|
+
), children: option.id }),
|
|
2604
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2605
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-white/90 group-hover:text-white transition-colors", children: option.label }),
|
|
2606
|
+
option.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-white/50 mt-0.5 line-clamp-2 group-hover:text-white/60 transition-colors", children: option.description })
|
|
2607
|
+
] }),
|
|
2608
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2834
2609
|
"svg",
|
|
2835
2610
|
{
|
|
2836
|
-
className:
|
|
2837
|
-
|
|
2611
|
+
className: cn(
|
|
2612
|
+
"w-4 h-4 text-white/30 flex-shrink-0 mt-0.5",
|
|
2613
|
+
"group-hover:text-[var(--ash-accent)] group-hover:translate-x-0.5",
|
|
2614
|
+
"transition-all duration-200"
|
|
2615
|
+
),
|
|
2838
2616
|
fill: "none",
|
|
2839
|
-
stroke: "currentColor",
|
|
2840
|
-
strokeWidth: "1.5",
|
|
2841
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2842
|
-
"path",
|
|
2843
|
-
{
|
|
2844
|
-
strokeLinecap: "round",
|
|
2845
|
-
strokeLinejoin: "round",
|
|
2846
|
-
d: "M3.75 6.75h16.5M3.75 12h16.5M12 17.25h8.25"
|
|
2847
|
-
}
|
|
2848
|
-
)
|
|
2849
|
-
}
|
|
2850
|
-
);
|
|
2851
|
-
case "accordion":
|
|
2852
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2853
|
-
"svg",
|
|
2854
|
-
{
|
|
2855
|
-
className: "ash-display-mode-icon",
|
|
2856
2617
|
viewBox: "0 0 24 24",
|
|
2857
|
-
fill: "none",
|
|
2858
2618
|
stroke: "currentColor",
|
|
2859
|
-
strokeWidth:
|
|
2860
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2861
|
-
"path",
|
|
2862
|
-
{
|
|
2863
|
-
strokeLinecap: "round",
|
|
2864
|
-
strokeLinejoin: "round",
|
|
2865
|
-
d: "M8.25 6.75h12M8.25 12h12M8.25 17.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"
|
|
2866
|
-
}
|
|
2867
|
-
)
|
|
2619
|
+
strokeWidth: 2,
|
|
2620
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" })
|
|
2868
2621
|
}
|
|
2869
|
-
);
|
|
2870
|
-
}
|
|
2871
|
-
};
|
|
2872
|
-
const getLabel = (mode) => {
|
|
2873
|
-
return labels[mode] || mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
2874
|
-
};
|
|
2875
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2876
|
-
"button",
|
|
2877
|
-
{
|
|
2878
|
-
type: "button",
|
|
2879
|
-
onClick: handleClick,
|
|
2880
|
-
className: cn("ash-display-mode-toggle", className),
|
|
2881
|
-
title: `Switch to ${nextMode} mode`,
|
|
2882
|
-
children: [
|
|
2883
|
-
getIcon(currentMode),
|
|
2884
|
-
showLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ash-display-mode-label", children: getLabel(currentMode) })
|
|
2885
|
-
]
|
|
2886
|
-
}
|
|
2887
|
-
);
|
|
2888
|
-
}
|
|
2889
|
-
var DEFAULT_WORDS = [
|
|
2890
|
-
"Thinking",
|
|
2891
|
-
"Reasoning",
|
|
2892
|
-
"Pondering",
|
|
2893
|
-
"Analyzing",
|
|
2894
|
-
"Considering",
|
|
2895
|
-
"Processing",
|
|
2896
|
-
"Evaluating"
|
|
2897
|
-
];
|
|
2898
|
-
function TypewriterText({
|
|
2899
|
-
words = DEFAULT_WORDS,
|
|
2900
|
-
typeSpeed = 50,
|
|
2901
|
-
pauseBeforeErase = 800,
|
|
2902
|
-
eraseSpeed = 30,
|
|
2903
|
-
pauseBeforeType = 200,
|
|
2904
|
-
showCursor = true,
|
|
2905
|
-
className,
|
|
2906
|
-
cursorClassName
|
|
2907
|
-
}) {
|
|
2908
|
-
const [displayText, setDisplayText] = react.useState("");
|
|
2909
|
-
const [wordIndex, setWordIndex] = react.useState(0);
|
|
2910
|
-
const [isTyping, setIsTyping] = react.useState(true);
|
|
2911
|
-
const timeoutRef = react.useRef(null);
|
|
2912
|
-
react.useEffect(() => {
|
|
2913
|
-
const currentWord = words[wordIndex] ?? "";
|
|
2914
|
-
if (isTyping) {
|
|
2915
|
-
if (displayText.length < currentWord.length) {
|
|
2916
|
-
timeoutRef.current = setTimeout(() => {
|
|
2917
|
-
setDisplayText(currentWord.slice(0, displayText.length + 1));
|
|
2918
|
-
}, typeSpeed);
|
|
2919
|
-
} else {
|
|
2920
|
-
timeoutRef.current = setTimeout(() => {
|
|
2921
|
-
setIsTyping(false);
|
|
2922
|
-
}, pauseBeforeErase);
|
|
2923
|
-
}
|
|
2924
|
-
} else {
|
|
2925
|
-
if (displayText.length > 0) {
|
|
2926
|
-
timeoutRef.current = setTimeout(() => {
|
|
2927
|
-
setDisplayText(displayText.slice(0, -1));
|
|
2928
|
-
}, eraseSpeed);
|
|
2929
|
-
} else {
|
|
2930
|
-
timeoutRef.current = setTimeout(() => {
|
|
2931
|
-
setWordIndex((prev) => (prev + 1) % words.length);
|
|
2932
|
-
setIsTyping(true);
|
|
2933
|
-
}, pauseBeforeType);
|
|
2934
|
-
}
|
|
2935
|
-
}
|
|
2936
|
-
return () => {
|
|
2937
|
-
if (timeoutRef.current) {
|
|
2938
|
-
clearTimeout(timeoutRef.current);
|
|
2939
|
-
}
|
|
2940
|
-
};
|
|
2941
|
-
}, [displayText, wordIndex, isTyping, words, typeSpeed, pauseBeforeErase, eraseSpeed, pauseBeforeType]);
|
|
2942
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("inline-flex items-center", className), children: [
|
|
2943
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: displayText }),
|
|
2944
|
-
showCursor && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2945
|
-
"span",
|
|
2946
|
-
{
|
|
2947
|
-
className: cn(
|
|
2948
|
-
"w-0.5 h-4 bg-current ml-0.5 animate-pulse",
|
|
2949
|
-
cursorClassName
|
|
2950
2622
|
)
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
}
|
|
2955
|
-
var ThemeContext = react.createContext(void 0);
|
|
2956
|
-
var DEFAULT_STORAGE_KEY = "ash-ui-theme";
|
|
2957
|
-
function ThemeProvider({
|
|
2958
|
-
children,
|
|
2959
|
-
defaultTheme,
|
|
2960
|
-
storageKey = DEFAULT_STORAGE_KEY,
|
|
2961
|
-
listenToSystemChanges = true
|
|
2962
|
-
}) {
|
|
2963
|
-
const [theme, setThemeState] = react.useState(() => {
|
|
2964
|
-
if (typeof window !== "undefined") {
|
|
2965
|
-
const stored = localStorage.getItem(storageKey);
|
|
2966
|
-
if (stored === "dark" || stored === "light") {
|
|
2967
|
-
return stored;
|
|
2968
|
-
}
|
|
2969
|
-
if (!defaultTheme && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
2970
|
-
return "dark";
|
|
2971
|
-
}
|
|
2972
|
-
}
|
|
2973
|
-
return defaultTheme ?? "light";
|
|
2974
|
-
});
|
|
2975
|
-
const [mounted, setMounted] = react.useState(false);
|
|
2976
|
-
react.useEffect(() => {
|
|
2977
|
-
setMounted(true);
|
|
2978
|
-
}, []);
|
|
2979
|
-
react.useEffect(() => {
|
|
2980
|
-
if (!mounted) return;
|
|
2981
|
-
const root = document.documentElement;
|
|
2982
|
-
if (theme === "dark") {
|
|
2983
|
-
root.classList.add("dark");
|
|
2984
|
-
} else {
|
|
2985
|
-
root.classList.remove("dark");
|
|
2986
|
-
}
|
|
2987
|
-
localStorage.setItem(storageKey, theme);
|
|
2988
|
-
}, [theme, mounted, storageKey]);
|
|
2989
|
-
react.useEffect(() => {
|
|
2990
|
-
if (!listenToSystemChanges || typeof window === "undefined") return;
|
|
2991
|
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
2992
|
-
const handleChange = (e) => {
|
|
2993
|
-
const stored = localStorage.getItem(storageKey);
|
|
2994
|
-
if (!stored) {
|
|
2995
|
-
setThemeState(e.matches ? "dark" : "light");
|
|
2996
|
-
}
|
|
2997
|
-
};
|
|
2998
|
-
mediaQuery.addEventListener("change", handleChange);
|
|
2999
|
-
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
3000
|
-
}, [storageKey, listenToSystemChanges]);
|
|
3001
|
-
const toggleTheme = react.useCallback(() => {
|
|
3002
|
-
setThemeState((prev) => prev === "light" ? "dark" : "light");
|
|
3003
|
-
}, []);
|
|
3004
|
-
const setTheme = react.useCallback((newTheme) => {
|
|
3005
|
-
setThemeState(newTheme);
|
|
3006
|
-
}, []);
|
|
3007
|
-
if (!mounted) {
|
|
3008
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: { theme: defaultTheme ?? "light", toggleTheme, setTheme }, children });
|
|
3009
|
-
}
|
|
3010
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
|
|
2623
|
+
]
|
|
2624
|
+
},
|
|
2625
|
+
option.id
|
|
2626
|
+
)) });
|
|
3011
2627
|
}
|
|
3012
|
-
function
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
2628
|
+
function ActionIcon({ actionType, className = "w-4 h-4" }) {
|
|
2629
|
+
switch (actionType.action) {
|
|
2630
|
+
case "command_run":
|
|
2631
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TerminalIcon, { className });
|
|
2632
|
+
case "file_read":
|
|
2633
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { className });
|
|
2634
|
+
case "file_edit":
|
|
2635
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EditIcon, { className });
|
|
2636
|
+
case "file_write":
|
|
2637
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FilePlusIcon, { className });
|
|
2638
|
+
case "search":
|
|
2639
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className });
|
|
2640
|
+
case "glob":
|
|
2641
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FolderSearchIcon, { className });
|
|
2642
|
+
case "web_fetch":
|
|
2643
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GlobeIcon, { className });
|
|
2644
|
+
case "web_search":
|
|
2645
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className });
|
|
2646
|
+
case "mcp_tool":
|
|
2647
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PlugIcon, { className });
|
|
2648
|
+
case "todo_write":
|
|
2649
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ListChecksIcon, { className });
|
|
2650
|
+
case "agent_tool":
|
|
2651
|
+
return /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className });
|
|
2652
|
+
case "generic_tool":
|
|
2653
|
+
default:
|
|
2654
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToolIcon, { className });
|
|
3016
2655
|
}
|
|
3017
|
-
return context;
|
|
3018
2656
|
}
|
|
3019
2657
|
|
|
3020
2658
|
// src/design-tokens.ts
|
|
@@ -3120,6 +2758,21 @@ var typography = {
|
|
|
3120
2758
|
relaxed: "1.75"
|
|
3121
2759
|
}
|
|
3122
2760
|
};
|
|
2761
|
+
var cssVars = {
|
|
2762
|
+
fontSize: {
|
|
2763
|
+
base: "--ash-font-size-base",
|
|
2764
|
+
sm: "--ash-font-size-sm",
|
|
2765
|
+
xs: "--ash-font-size-xs",
|
|
2766
|
+
code: "--ash-font-size-code"
|
|
2767
|
+
},
|
|
2768
|
+
accent: "--ash-accent",
|
|
2769
|
+
accentForeground: "--ash-accent-foreground",
|
|
2770
|
+
surfaceDark: "--ash-surface-dark",
|
|
2771
|
+
surfaceDarker: "--ash-surface-darker",
|
|
2772
|
+
surfaceCard: "--ash-surface-card",
|
|
2773
|
+
surfaceElevated: "--ash-surface-elevated",
|
|
2774
|
+
surfaceBorder: "--ash-surface-border"
|
|
2775
|
+
};
|
|
3123
2776
|
var keyframes = {
|
|
3124
2777
|
slideUp: {
|
|
3125
2778
|
from: { opacity: "0", transform: "translateY(20px)" },
|
|
@@ -3238,42 +2891,332 @@ function tokensToCssVariables(prefix = "ash") {
|
|
|
3238
2891
|
if (key !== "DEFAULT") vars[`--${prefix}-border-${key}`] = value;
|
|
3239
2892
|
else vars[`--${prefix}-border`] = value;
|
|
3240
2893
|
});
|
|
2894
|
+
vars[`--${prefix}-font-size-base`] = "14px";
|
|
2895
|
+
vars[`--${prefix}-font-size-sm`] = "12px";
|
|
2896
|
+
vars[`--${prefix}-font-size-xs`] = "11px";
|
|
2897
|
+
vars[`--${prefix}-font-size-code`] = "13px";
|
|
3241
2898
|
return vars;
|
|
3242
2899
|
}
|
|
3243
|
-
var inlineStyles = {
|
|
3244
|
-
// Glass panel effect
|
|
3245
|
-
glassPanel: {
|
|
3246
|
-
backgroundColor: "rgba(255, 255, 255, 0.05)",
|
|
3247
|
-
backdropFilter: "blur(24px)",
|
|
3248
|
-
WebkitBackdropFilter: "blur(24px)",
|
|
3249
|
-
border: `1px solid ${colors.border.DEFAULT}`
|
|
3250
|
-
},
|
|
3251
|
-
// Accent button
|
|
3252
|
-
accentButton: {
|
|
3253
|
-
backgroundColor: colors.accent.DEFAULT,
|
|
3254
|
-
color: "#000000",
|
|
3255
|
-
border: `1px solid ${colors.accent.DEFAULT}`,
|
|
3256
|
-
boxShadow: shadows.glow.md
|
|
3257
|
-
},
|
|
3258
|
-
// Ghost button
|
|
3259
|
-
ghostButton: {
|
|
3260
|
-
backgroundColor: "transparent",
|
|
3261
|
-
color: colors.text.secondary,
|
|
3262
|
-
border: "1px solid transparent"
|
|
3263
|
-
},
|
|
3264
|
-
// User message bubble
|
|
3265
|
-
userMessage: {
|
|
3266
|
-
backgroundColor: colors.user.bg,
|
|
3267
|
-
border: `1px solid ${colors.user.border}`,
|
|
3268
|
-
borderRadius: borderRadius.lg
|
|
3269
|
-
},
|
|
3270
|
-
// Assistant message bubble
|
|
3271
|
-
assistantMessage: {
|
|
3272
|
-
backgroundColor: colors.assistant.bg,
|
|
3273
|
-
border: `1px solid ${colors.assistant.border}`,
|
|
3274
|
-
borderRadius: borderRadius.lg
|
|
2900
|
+
var inlineStyles = {
|
|
2901
|
+
// Glass panel effect
|
|
2902
|
+
glassPanel: {
|
|
2903
|
+
backgroundColor: "rgba(255, 255, 255, 0.05)",
|
|
2904
|
+
backdropFilter: "blur(24px)",
|
|
2905
|
+
WebkitBackdropFilter: "blur(24px)",
|
|
2906
|
+
border: `1px solid ${colors.border.DEFAULT}`
|
|
2907
|
+
},
|
|
2908
|
+
// Accent button
|
|
2909
|
+
accentButton: {
|
|
2910
|
+
backgroundColor: colors.accent.DEFAULT,
|
|
2911
|
+
color: "#000000",
|
|
2912
|
+
border: `1px solid ${colors.accent.DEFAULT}`,
|
|
2913
|
+
boxShadow: shadows.glow.md
|
|
2914
|
+
},
|
|
2915
|
+
// Ghost button
|
|
2916
|
+
ghostButton: {
|
|
2917
|
+
backgroundColor: "transparent",
|
|
2918
|
+
color: colors.text.secondary,
|
|
2919
|
+
border: "1px solid transparent"
|
|
2920
|
+
},
|
|
2921
|
+
// User message bubble
|
|
2922
|
+
userMessage: {
|
|
2923
|
+
backgroundColor: colors.user.bg,
|
|
2924
|
+
border: `1px solid ${colors.user.border}`,
|
|
2925
|
+
borderRadius: borderRadius.lg
|
|
2926
|
+
},
|
|
2927
|
+
// Assistant message bubble
|
|
2928
|
+
assistantMessage: {
|
|
2929
|
+
backgroundColor: colors.assistant.bg,
|
|
2930
|
+
border: `1px solid ${colors.assistant.border}`,
|
|
2931
|
+
borderRadius: borderRadius.lg
|
|
2932
|
+
}
|
|
2933
|
+
};
|
|
2934
|
+
|
|
2935
|
+
// src/types.ts
|
|
2936
|
+
function isCommandRunAction(action) {
|
|
2937
|
+
return action.action === "command_run";
|
|
2938
|
+
}
|
|
2939
|
+
function isFileReadAction(action) {
|
|
2940
|
+
return action.action === "file_read";
|
|
2941
|
+
}
|
|
2942
|
+
function isFileEditAction(action) {
|
|
2943
|
+
return action.action === "file_edit";
|
|
2944
|
+
}
|
|
2945
|
+
function isFileWriteAction(action) {
|
|
2946
|
+
return action.action === "file_write";
|
|
2947
|
+
}
|
|
2948
|
+
function isSearchAction(action) {
|
|
2949
|
+
return action.action === "search";
|
|
2950
|
+
}
|
|
2951
|
+
function isGlobAction(action) {
|
|
2952
|
+
return action.action === "glob";
|
|
2953
|
+
}
|
|
2954
|
+
function isWebFetchAction(action) {
|
|
2955
|
+
return action.action === "web_fetch";
|
|
2956
|
+
}
|
|
2957
|
+
function isWebSearchAction(action) {
|
|
2958
|
+
return action.action === "web_search";
|
|
2959
|
+
}
|
|
2960
|
+
function isMcpToolAction(action) {
|
|
2961
|
+
return action.action === "mcp_tool";
|
|
2962
|
+
}
|
|
2963
|
+
function isGenericToolAction(action) {
|
|
2964
|
+
return action.action === "generic_tool";
|
|
2965
|
+
}
|
|
2966
|
+
function isTodoWriteAction(action) {
|
|
2967
|
+
return action.action === "todo_write";
|
|
2968
|
+
}
|
|
2969
|
+
function isAgentToolAction(action) {
|
|
2970
|
+
return action.action === "agent_tool";
|
|
2971
|
+
}
|
|
2972
|
+
function isToolCallEntry(entry) {
|
|
2973
|
+
return entry.type === "tool_call";
|
|
2974
|
+
}
|
|
2975
|
+
function isErrorEntry(entry) {
|
|
2976
|
+
return entry.type === "error";
|
|
2977
|
+
}
|
|
2978
|
+
function isWidgetEntry(entry) {
|
|
2979
|
+
return entry.type === "widget";
|
|
2980
|
+
}
|
|
2981
|
+
var DEFAULT_STYLE_CONFIG = {
|
|
2982
|
+
userVariant: "bubble",
|
|
2983
|
+
assistantVariant: "bubble",
|
|
2984
|
+
scale: "compact",
|
|
2985
|
+
showTimestamp: true,
|
|
2986
|
+
showAvatars: true
|
|
2987
|
+
};
|
|
2988
|
+
function normalizedEntryToMessage(entry) {
|
|
2989
|
+
const { id, entryType, content, timestamp } = entry;
|
|
2990
|
+
const createdAt = timestamp ? new Date(timestamp) : void 0;
|
|
2991
|
+
switch (entryType.type) {
|
|
2992
|
+
case "user_message":
|
|
2993
|
+
return {
|
|
2994
|
+
id,
|
|
2995
|
+
role: "user",
|
|
2996
|
+
content,
|
|
2997
|
+
createdAt
|
|
2998
|
+
};
|
|
2999
|
+
case "assistant_message":
|
|
3000
|
+
return {
|
|
3001
|
+
id,
|
|
3002
|
+
role: "assistant",
|
|
3003
|
+
content,
|
|
3004
|
+
createdAt
|
|
3005
|
+
};
|
|
3006
|
+
case "thinking":
|
|
3007
|
+
return {
|
|
3008
|
+
id,
|
|
3009
|
+
role: "assistant",
|
|
3010
|
+
content: "",
|
|
3011
|
+
reasoning: content,
|
|
3012
|
+
createdAt
|
|
3013
|
+
};
|
|
3014
|
+
case "tool_call": {
|
|
3015
|
+
const { toolCall } = entryType;
|
|
3016
|
+
const toolInvocation = {
|
|
3017
|
+
state: toolCall.status === "pending" ? "call" : "result",
|
|
3018
|
+
toolCallId: toolCall.id,
|
|
3019
|
+
toolName: toolCall.toolName,
|
|
3020
|
+
args: toolCall.input || {},
|
|
3021
|
+
result: toolCall.output
|
|
3022
|
+
};
|
|
3023
|
+
return {
|
|
3024
|
+
id,
|
|
3025
|
+
role: "assistant",
|
|
3026
|
+
content: "",
|
|
3027
|
+
toolInvocations: [toolInvocation],
|
|
3028
|
+
createdAt
|
|
3029
|
+
};
|
|
3030
|
+
}
|
|
3031
|
+
case "error":
|
|
3032
|
+
return {
|
|
3033
|
+
id,
|
|
3034
|
+
role: "system",
|
|
3035
|
+
content: `Error: ${entryType.message}${entryType.code ? ` (${entryType.code})` : ""}`,
|
|
3036
|
+
createdAt
|
|
3037
|
+
};
|
|
3038
|
+
case "widget":
|
|
3039
|
+
return {
|
|
3040
|
+
id,
|
|
3041
|
+
role: "data",
|
|
3042
|
+
content: JSON.stringify({
|
|
3043
|
+
widgetType: entryType.widgetType,
|
|
3044
|
+
widgetData: entryType.widgetData
|
|
3045
|
+
}),
|
|
3046
|
+
createdAt
|
|
3047
|
+
};
|
|
3048
|
+
default:
|
|
3049
|
+
return null;
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
function messageToNormalizedEntry(message) {
|
|
3053
|
+
const { id, role, content, createdAt, toolInvocations, reasoning } = message;
|
|
3054
|
+
const timestamp = createdAt?.toISOString();
|
|
3055
|
+
if (toolInvocations && toolInvocations.length > 0) {
|
|
3056
|
+
const inv = toolInvocations[0];
|
|
3057
|
+
const toolCall = {
|
|
3058
|
+
id: inv.toolCallId,
|
|
3059
|
+
toolName: inv.toolName,
|
|
3060
|
+
actionType: {
|
|
3061
|
+
action: "generic_tool",
|
|
3062
|
+
toolName: inv.toolName,
|
|
3063
|
+
arguments: inv.args,
|
|
3064
|
+
result: inv.result ? { type: "json", value: inv.result } : void 0
|
|
3065
|
+
},
|
|
3066
|
+
status: inv.state === "result" ? "success" : "pending",
|
|
3067
|
+
summary: `${inv.toolName}(${Object.keys(inv.args).join(", ")})`,
|
|
3068
|
+
input: inv.args,
|
|
3069
|
+
output: inv.result
|
|
3070
|
+
};
|
|
3071
|
+
return {
|
|
3072
|
+
id,
|
|
3073
|
+
timestamp,
|
|
3074
|
+
entryType: { type: "tool_call", toolCall },
|
|
3075
|
+
content: toolCall.summary
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
if (reasoning) {
|
|
3079
|
+
return {
|
|
3080
|
+
id,
|
|
3081
|
+
timestamp,
|
|
3082
|
+
entryType: { type: "thinking" },
|
|
3083
|
+
content: reasoning
|
|
3084
|
+
};
|
|
3085
|
+
}
|
|
3086
|
+
if (role === "user") {
|
|
3087
|
+
return {
|
|
3088
|
+
id,
|
|
3089
|
+
timestamp,
|
|
3090
|
+
entryType: { type: "user_message" },
|
|
3091
|
+
content
|
|
3092
|
+
};
|
|
3093
|
+
}
|
|
3094
|
+
if (role === "assistant") {
|
|
3095
|
+
return {
|
|
3096
|
+
id,
|
|
3097
|
+
timestamp,
|
|
3098
|
+
entryType: { type: "assistant_message" },
|
|
3099
|
+
content
|
|
3100
|
+
};
|
|
3101
|
+
}
|
|
3102
|
+
if (role === "system") {
|
|
3103
|
+
if (content.startsWith("Error:")) {
|
|
3104
|
+
return {
|
|
3105
|
+
id,
|
|
3106
|
+
timestamp,
|
|
3107
|
+
entryType: { type: "error", message: content.replace("Error: ", "") },
|
|
3108
|
+
content
|
|
3109
|
+
};
|
|
3110
|
+
}
|
|
3111
|
+
return {
|
|
3112
|
+
id,
|
|
3113
|
+
timestamp,
|
|
3114
|
+
entryType: { type: "assistant_message" },
|
|
3115
|
+
content
|
|
3116
|
+
};
|
|
3117
|
+
}
|
|
3118
|
+
if (role === "data") {
|
|
3119
|
+
try {
|
|
3120
|
+
const data = JSON.parse(content);
|
|
3121
|
+
if (data.widgetType) {
|
|
3122
|
+
return {
|
|
3123
|
+
id,
|
|
3124
|
+
timestamp,
|
|
3125
|
+
entryType: {
|
|
3126
|
+
type: "widget",
|
|
3127
|
+
widgetType: data.widgetType,
|
|
3128
|
+
widgetData: data.widgetData
|
|
3129
|
+
},
|
|
3130
|
+
content: ""
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3133
|
+
} catch {
|
|
3134
|
+
}
|
|
3135
|
+
return {
|
|
3136
|
+
id,
|
|
3137
|
+
timestamp,
|
|
3138
|
+
entryType: { type: "assistant_message" },
|
|
3139
|
+
content
|
|
3140
|
+
};
|
|
3141
|
+
}
|
|
3142
|
+
return {
|
|
3143
|
+
id,
|
|
3144
|
+
timestamp,
|
|
3145
|
+
entryType: { type: "assistant_message" },
|
|
3146
|
+
content
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
3149
|
+
function normalizedEntriesToMessages(entries) {
|
|
3150
|
+
const messages = [];
|
|
3151
|
+
let currentAssistantMessage = null;
|
|
3152
|
+
for (const entry of entries) {
|
|
3153
|
+
const message = normalizedEntryToMessage(entry);
|
|
3154
|
+
if (!message) continue;
|
|
3155
|
+
if (message.role === "assistant") {
|
|
3156
|
+
if (currentAssistantMessage) {
|
|
3157
|
+
if (message.toolInvocations) {
|
|
3158
|
+
currentAssistantMessage.toolInvocations = [
|
|
3159
|
+
...currentAssistantMessage.toolInvocations || [],
|
|
3160
|
+
...message.toolInvocations
|
|
3161
|
+
];
|
|
3162
|
+
}
|
|
3163
|
+
if (message.content) {
|
|
3164
|
+
currentAssistantMessage.content = currentAssistantMessage.content ? `${currentAssistantMessage.content}
|
|
3165
|
+
${message.content}` : message.content;
|
|
3166
|
+
}
|
|
3167
|
+
if (message.reasoning) {
|
|
3168
|
+
currentAssistantMessage.reasoning = currentAssistantMessage.reasoning ? `${currentAssistantMessage.reasoning}
|
|
3169
|
+
${message.reasoning}` : message.reasoning;
|
|
3170
|
+
}
|
|
3171
|
+
} else {
|
|
3172
|
+
currentAssistantMessage = { ...message };
|
|
3173
|
+
}
|
|
3174
|
+
} else {
|
|
3175
|
+
if (currentAssistantMessage) {
|
|
3176
|
+
messages.push(currentAssistantMessage);
|
|
3177
|
+
currentAssistantMessage = null;
|
|
3178
|
+
}
|
|
3179
|
+
messages.push(message);
|
|
3180
|
+
}
|
|
3275
3181
|
}
|
|
3276
|
-
|
|
3182
|
+
if (currentAssistantMessage) {
|
|
3183
|
+
messages.push(currentAssistantMessage);
|
|
3184
|
+
}
|
|
3185
|
+
return messages;
|
|
3186
|
+
}
|
|
3187
|
+
function messagesToNormalizedEntries(messages) {
|
|
3188
|
+
const entries = [];
|
|
3189
|
+
for (const message of messages) {
|
|
3190
|
+
if (message.reasoning) {
|
|
3191
|
+
entries.push({
|
|
3192
|
+
id: `${message.id}-thinking`,
|
|
3193
|
+
timestamp: message.createdAt?.toISOString(),
|
|
3194
|
+
entryType: { type: "thinking" },
|
|
3195
|
+
content: message.reasoning
|
|
3196
|
+
});
|
|
3197
|
+
}
|
|
3198
|
+
if (message.content || !message.toolInvocations?.length) {
|
|
3199
|
+
entries.push(messageToNormalizedEntry({
|
|
3200
|
+
...message,
|
|
3201
|
+
toolInvocations: void 0,
|
|
3202
|
+
reasoning: void 0
|
|
3203
|
+
}));
|
|
3204
|
+
}
|
|
3205
|
+
if (message.toolInvocations) {
|
|
3206
|
+
for (const inv of message.toolInvocations) {
|
|
3207
|
+
const toolMessage = {
|
|
3208
|
+
id: inv.toolCallId,
|
|
3209
|
+
role: "assistant",
|
|
3210
|
+
content: "",
|
|
3211
|
+
toolInvocations: [inv],
|
|
3212
|
+
createdAt: message.createdAt
|
|
3213
|
+
};
|
|
3214
|
+
entries.push(messageToNormalizedEntry(toolMessage));
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
return entries;
|
|
3219
|
+
}
|
|
3277
3220
|
function useMessageQueue({
|
|
3278
3221
|
onProcessMessage,
|
|
3279
3222
|
canProcess = true
|
|
@@ -3493,19 +3436,95 @@ function useFileUpload({
|
|
|
3493
3436
|
openFilePicker
|
|
3494
3437
|
};
|
|
3495
3438
|
}
|
|
3439
|
+
|
|
3440
|
+
// src/hooks/middleware.ts
|
|
3441
|
+
async function applyRequestMiddleware(middlewares, request) {
|
|
3442
|
+
let current = { ...request };
|
|
3443
|
+
for (const mw of middlewares) {
|
|
3444
|
+
if (mw.onRequest) {
|
|
3445
|
+
try {
|
|
3446
|
+
const result = await mw.onRequest(current);
|
|
3447
|
+
if (result?.error) {
|
|
3448
|
+
return { request: current, error: result.error };
|
|
3449
|
+
}
|
|
3450
|
+
if (result) {
|
|
3451
|
+
current = {
|
|
3452
|
+
...current,
|
|
3453
|
+
prompt: result.prompt ?? current.prompt,
|
|
3454
|
+
sessionContext: result.sessionContext ?? current.sessionContext,
|
|
3455
|
+
metadata: {
|
|
3456
|
+
...current.metadata,
|
|
3457
|
+
...result.metadata
|
|
3458
|
+
}
|
|
3459
|
+
};
|
|
3460
|
+
}
|
|
3461
|
+
} catch (err) {
|
|
3462
|
+
const errorMessage = err instanceof Error ? err.message : "Middleware error";
|
|
3463
|
+
return { request: current, error: errorMessage };
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
return { request: current };
|
|
3468
|
+
}
|
|
3469
|
+
async function applyEventMiddleware(middlewares, event) {
|
|
3470
|
+
let current = event;
|
|
3471
|
+
for (const mw of middlewares) {
|
|
3472
|
+
if (!current) break;
|
|
3473
|
+
if (mw.onEvent) {
|
|
3474
|
+
try {
|
|
3475
|
+
current = await mw.onEvent(current);
|
|
3476
|
+
} catch (err) {
|
|
3477
|
+
console.error("[middleware] onEvent error:", err);
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
return current;
|
|
3482
|
+
}
|
|
3483
|
+
async function callMiddlewareComplete(middlewares, sessionId) {
|
|
3484
|
+
for (const mw of middlewares) {
|
|
3485
|
+
if (mw.onComplete) {
|
|
3486
|
+
try {
|
|
3487
|
+
await mw.onComplete(sessionId);
|
|
3488
|
+
} catch (err) {
|
|
3489
|
+
console.error("[middleware] onComplete error:", err);
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
async function callMiddlewareError(middlewares, error) {
|
|
3495
|
+
for (const mw of middlewares) {
|
|
3496
|
+
if (mw.onError) {
|
|
3497
|
+
try {
|
|
3498
|
+
await mw.onError(error);
|
|
3499
|
+
} catch (err) {
|
|
3500
|
+
console.error("[middleware] onError error:", err);
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
|
|
3506
|
+
// src/hooks/useAgentChat.ts
|
|
3496
3507
|
function useAgentChat(options) {
|
|
3497
3508
|
const {
|
|
3498
3509
|
createStream,
|
|
3510
|
+
subscribeToSession,
|
|
3499
3511
|
initialSessionId,
|
|
3500
3512
|
initialEntries = [],
|
|
3501
3513
|
onSessionStart,
|
|
3502
3514
|
onSessionEnd,
|
|
3503
3515
|
onError,
|
|
3504
|
-
onSandboxLog
|
|
3516
|
+
onSandboxLog,
|
|
3517
|
+
onReconnect,
|
|
3518
|
+
maxReconnectAttempts = 3,
|
|
3519
|
+
reconnectBaseDelay = 1e3,
|
|
3520
|
+
onBeforeSend,
|
|
3521
|
+
onEvent,
|
|
3522
|
+
middleware
|
|
3505
3523
|
} = options;
|
|
3506
3524
|
const [historyEntries, setHistoryEntries] = react.useState(initialEntries);
|
|
3507
3525
|
const [streamingEntries, setStreamingEntries] = react.useState([]);
|
|
3508
3526
|
const [isStreaming, setIsStreaming] = react.useState(false);
|
|
3527
|
+
const [isReconnecting, setIsReconnecting] = react.useState(false);
|
|
3509
3528
|
const [error, setError] = react.useState(null);
|
|
3510
3529
|
const [sessionId, setSessionId] = react.useState(initialSessionId || null);
|
|
3511
3530
|
const abortControllerRef = react.useRef(null);
|
|
@@ -3513,6 +3532,16 @@ function useAgentChat(options) {
|
|
|
3513
3532
|
const currentTextIdRef = react.useRef(null);
|
|
3514
3533
|
const pendingToolCallsRef = react.useRef(/* @__PURE__ */ new Map());
|
|
3515
3534
|
const hadToolCallSinceTextRef = react.useRef(false);
|
|
3535
|
+
const reconnectAttemptsRef = react.useRef(0);
|
|
3536
|
+
const eventCountRef = react.useRef(0);
|
|
3537
|
+
const sessionIdRef = react.useRef(sessionId);
|
|
3538
|
+
const streamingEntriesRef = react.useRef([]);
|
|
3539
|
+
react.useEffect(() => {
|
|
3540
|
+
sessionIdRef.current = sessionId;
|
|
3541
|
+
}, [sessionId]);
|
|
3542
|
+
react.useEffect(() => {
|
|
3543
|
+
streamingEntriesRef.current = streamingEntries;
|
|
3544
|
+
}, [streamingEntries]);
|
|
3516
3545
|
const entries = [...historyEntries, ...streamingEntries];
|
|
3517
3546
|
const emitStreamingEntries = react.useCallback((newEntries) => {
|
|
3518
3547
|
setStreamingEntries([...newEntries]);
|
|
@@ -3627,7 +3656,7 @@ function useAgentChat(options) {
|
|
|
3627
3656
|
setError(event.error);
|
|
3628
3657
|
onError?.(event.error);
|
|
3629
3658
|
newEntries.push({
|
|
3630
|
-
id: `error-${Date.now()}`,
|
|
3659
|
+
id: `error-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
3631
3660
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3632
3661
|
entryType: { type: "error", message: event.error, code: event.code },
|
|
3633
3662
|
content: event.error
|
|
@@ -3646,12 +3675,112 @@ function useAgentChat(options) {
|
|
|
3646
3675
|
}
|
|
3647
3676
|
return newEntries;
|
|
3648
3677
|
}, [sessionId, onSessionStart, onSessionEnd, onError, onSandboxLog, createTextEntry, resetStreamingState]);
|
|
3678
|
+
const attemptReconnect = react.useCallback(async (targetSessionId, currentEntries) => {
|
|
3679
|
+
if (!subscribeToSession) {
|
|
3680
|
+
return false;
|
|
3681
|
+
}
|
|
3682
|
+
const attempt = reconnectAttemptsRef.current + 1;
|
|
3683
|
+
if (attempt > maxReconnectAttempts) {
|
|
3684
|
+
console.warn(`[useAgentChat] Max reconnection attempts (${maxReconnectAttempts}) exceeded`);
|
|
3685
|
+
return false;
|
|
3686
|
+
}
|
|
3687
|
+
reconnectAttemptsRef.current = attempt;
|
|
3688
|
+
setIsReconnecting(true);
|
|
3689
|
+
onReconnect?.(attempt, targetSessionId);
|
|
3690
|
+
const delay = reconnectBaseDelay * Math.pow(2, attempt - 1);
|
|
3691
|
+
console.log(`[useAgentChat] Reconnection attempt ${attempt}/${maxReconnectAttempts} in ${delay}ms`);
|
|
3692
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3693
|
+
const controller = new AbortController();
|
|
3694
|
+
abortControllerRef.current = controller;
|
|
3695
|
+
try {
|
|
3696
|
+
const stream = subscribeToSession(targetSessionId, controller.signal);
|
|
3697
|
+
let localStreamingEntries = [...currentEntries];
|
|
3698
|
+
for await (const event of stream) {
|
|
3699
|
+
if (controller.signal.aborted) break;
|
|
3700
|
+
eventCountRef.current++;
|
|
3701
|
+
localStreamingEntries = processEvent(event, localStreamingEntries);
|
|
3702
|
+
emitStreamingEntries(localStreamingEntries);
|
|
3703
|
+
if (event.type === "complete" || event.type === "session_end" || event.type === "error") {
|
|
3704
|
+
reconnectAttemptsRef.current = 0;
|
|
3705
|
+
setIsReconnecting(false);
|
|
3706
|
+
if (event.type === "complete" && localStreamingEntries.length > 0) {
|
|
3707
|
+
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3708
|
+
setStreamingEntries([]);
|
|
3709
|
+
}
|
|
3710
|
+
return true;
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
reconnectAttemptsRef.current = 0;
|
|
3714
|
+
setIsReconnecting(false);
|
|
3715
|
+
if (localStreamingEntries.length > 0) {
|
|
3716
|
+
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3717
|
+
setStreamingEntries([]);
|
|
3718
|
+
}
|
|
3719
|
+
return true;
|
|
3720
|
+
} catch (err) {
|
|
3721
|
+
const isAbort = err.name === "AbortError" || err.message?.includes("aborted") || err.message?.includes("BodyStreamBuffer");
|
|
3722
|
+
if (isAbort && !controller.signal.aborted) {
|
|
3723
|
+
console.log(`[useAgentChat] Reconnection stream interrupted, will retry...`);
|
|
3724
|
+
setIsReconnecting(false);
|
|
3725
|
+
return attemptReconnect(targetSessionId, streamingEntriesRef.current);
|
|
3726
|
+
}
|
|
3727
|
+
setIsReconnecting(false);
|
|
3728
|
+
if (!controller.signal.aborted) {
|
|
3729
|
+
const errorMessage = err instanceof Error ? err.message : "Reconnection failed";
|
|
3730
|
+
console.error(`[useAgentChat] Reconnection failed:`, errorMessage);
|
|
3731
|
+
}
|
|
3732
|
+
return false;
|
|
3733
|
+
}
|
|
3734
|
+
}, [subscribeToSession, maxReconnectAttempts, reconnectBaseDelay, onReconnect, processEvent, emitStreamingEntries]);
|
|
3649
3735
|
const send = react.useCallback(async (prompt) => {
|
|
3650
3736
|
if (isStreaming) return;
|
|
3737
|
+
let finalPrompt = prompt;
|
|
3738
|
+
let additionalMetadata = {};
|
|
3739
|
+
let additionalContext;
|
|
3740
|
+
if (onBeforeSend) {
|
|
3741
|
+
try {
|
|
3742
|
+
const result = await onBeforeSend({
|
|
3743
|
+
prompt,
|
|
3744
|
+
sessionId,
|
|
3745
|
+
entries: [...historyEntries, ...streamingEntries]
|
|
3746
|
+
});
|
|
3747
|
+
if (result?.cancel) {
|
|
3748
|
+
return;
|
|
3749
|
+
}
|
|
3750
|
+
if (result?.prompt !== void 0) finalPrompt = result.prompt;
|
|
3751
|
+
if (result?.metadata) additionalMetadata = result.metadata;
|
|
3752
|
+
if (result?.sessionContext) additionalContext = result.sessionContext;
|
|
3753
|
+
} catch (err) {
|
|
3754
|
+
const errorMessage = err instanceof Error ? err.message : "Send cancelled";
|
|
3755
|
+
setError(errorMessage);
|
|
3756
|
+
onError?.(errorMessage);
|
|
3757
|
+
return;
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
if (middleware?.length) {
|
|
3761
|
+
const middlewareRequest = {
|
|
3762
|
+
prompt: finalPrompt,
|
|
3763
|
+
sessionId,
|
|
3764
|
+
metadata: additionalMetadata,
|
|
3765
|
+
sessionContext: additionalContext
|
|
3766
|
+
};
|
|
3767
|
+
const { request, error: middlewareError } = await applyRequestMiddleware(middleware, middlewareRequest);
|
|
3768
|
+
if (middlewareError) {
|
|
3769
|
+
setError(middlewareError);
|
|
3770
|
+
onError?.(middlewareError);
|
|
3771
|
+
await callMiddlewareError(middleware, middlewareError);
|
|
3772
|
+
return;
|
|
3773
|
+
}
|
|
3774
|
+
finalPrompt = request.prompt;
|
|
3775
|
+
additionalMetadata = request.metadata || {};
|
|
3776
|
+
additionalContext = request.sessionContext;
|
|
3777
|
+
}
|
|
3651
3778
|
setIsStreaming(true);
|
|
3652
3779
|
setError(null);
|
|
3780
|
+
reconnectAttemptsRef.current = 0;
|
|
3781
|
+
eventCountRef.current = 0;
|
|
3653
3782
|
const userEntry = {
|
|
3654
|
-
id: `user-${Date.now()}`,
|
|
3783
|
+
id: `user-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
3655
3784
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3656
3785
|
entryType: { type: "user_message" },
|
|
3657
3786
|
content: prompt
|
|
@@ -3661,39 +3790,91 @@ function useAgentChat(options) {
|
|
|
3661
3790
|
const controller = new AbortController();
|
|
3662
3791
|
abortControllerRef.current = controller;
|
|
3663
3792
|
let localStreamingEntries = [];
|
|
3793
|
+
let completedSessionId = null;
|
|
3664
3794
|
try {
|
|
3665
|
-
const stream = createStream(
|
|
3795
|
+
const stream = createStream(finalPrompt, sessionId || void 0, {
|
|
3796
|
+
signal: controller.signal,
|
|
3797
|
+
metadata: Object.keys(additionalMetadata).length > 0 ? additionalMetadata : void 0,
|
|
3798
|
+
sessionContext: additionalContext
|
|
3799
|
+
});
|
|
3666
3800
|
for await (const event of stream) {
|
|
3667
3801
|
if (controller.signal.aborted) break;
|
|
3668
|
-
|
|
3802
|
+
eventCountRef.current++;
|
|
3803
|
+
if (event.type === "session_start" && event.sessionId) {
|
|
3804
|
+
completedSessionId = event.sessionId;
|
|
3805
|
+
}
|
|
3806
|
+
if (onEvent) {
|
|
3807
|
+
try {
|
|
3808
|
+
await onEvent(event);
|
|
3809
|
+
} catch (err) {
|
|
3810
|
+
console.error("[useAgentChat] onEvent error:", err);
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
let processedEvent = event;
|
|
3814
|
+
if (middleware?.length) {
|
|
3815
|
+
processedEvent = await applyEventMiddleware(middleware, event);
|
|
3816
|
+
}
|
|
3817
|
+
if (!processedEvent) continue;
|
|
3818
|
+
localStreamingEntries = processEvent(processedEvent, localStreamingEntries);
|
|
3669
3819
|
emitStreamingEntries(localStreamingEntries);
|
|
3670
3820
|
}
|
|
3671
3821
|
if (localStreamingEntries.length > 0) {
|
|
3672
3822
|
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3673
3823
|
setStreamingEntries([]);
|
|
3674
3824
|
}
|
|
3825
|
+
reconnectAttemptsRef.current = 0;
|
|
3826
|
+
if (middleware?.length && (completedSessionId || sessionIdRef.current)) {
|
|
3827
|
+
await callMiddlewareComplete(middleware, completedSessionId || sessionIdRef.current || "");
|
|
3828
|
+
}
|
|
3675
3829
|
} catch (err) {
|
|
3676
|
-
|
|
3830
|
+
const isAbort = err.name === "AbortError" || err.message?.includes("aborted") || err.message?.includes("BodyStreamBuffer");
|
|
3831
|
+
if (isAbort && !controller.signal.aborted) {
|
|
3832
|
+
const currentSessionId = sessionIdRef.current;
|
|
3833
|
+
const hadEvents = eventCountRef.current > 0;
|
|
3834
|
+
console.log(`[useAgentChat] Stream interrupted. sessionId=${currentSessionId}, events=${eventCountRef.current}`);
|
|
3835
|
+
if (currentSessionId && hadEvents && subscribeToSession) {
|
|
3836
|
+
console.log(`[useAgentChat] Attempting auto-reconnection...`);
|
|
3837
|
+
const reconnected = await attemptReconnect(currentSessionId, streamingEntriesRef.current);
|
|
3838
|
+
if (reconnected) {
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3841
|
+
const errorMsg = "Connection lost. Please try again.";
|
|
3842
|
+
setError(errorMsg);
|
|
3843
|
+
onError?.(errorMsg);
|
|
3844
|
+
if (middleware?.length) {
|
|
3845
|
+
await callMiddlewareError(middleware, errorMsg);
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
} else if (!isAbort) {
|
|
3677
3849
|
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
3678
3850
|
setError(errorMessage);
|
|
3679
3851
|
onError?.(errorMessage);
|
|
3852
|
+
if (middleware?.length) {
|
|
3853
|
+
await callMiddlewareError(middleware, errorMessage);
|
|
3854
|
+
}
|
|
3680
3855
|
}
|
|
3681
3856
|
} finally {
|
|
3682
3857
|
setIsStreaming(false);
|
|
3858
|
+
setIsReconnecting(false);
|
|
3683
3859
|
abortControllerRef.current = null;
|
|
3684
3860
|
resetStreamingState();
|
|
3685
3861
|
}
|
|
3686
|
-
}, [isStreaming, sessionId, createStream, processEvent, emitStreamingEntries, resetStreamingState, onError]);
|
|
3862
|
+
}, [isStreaming, sessionId, historyEntries, streamingEntries, createStream, subscribeToSession, processEvent, emitStreamingEntries, resetStreamingState, onError, attemptReconnect, onBeforeSend, onEvent, middleware]);
|
|
3687
3863
|
const stop = react.useCallback(() => {
|
|
3864
|
+
reconnectAttemptsRef.current = maxReconnectAttempts + 1;
|
|
3865
|
+
setIsReconnecting(false);
|
|
3688
3866
|
if (abortControllerRef.current) {
|
|
3689
3867
|
abortControllerRef.current.abort();
|
|
3690
3868
|
}
|
|
3691
|
-
}, []);
|
|
3869
|
+
}, [maxReconnectAttempts]);
|
|
3692
3870
|
const clear = react.useCallback(() => {
|
|
3693
3871
|
setHistoryEntries([]);
|
|
3694
3872
|
resetStreamingState();
|
|
3695
3873
|
setSessionId(initialSessionId || null);
|
|
3696
3874
|
setError(null);
|
|
3875
|
+
setIsReconnecting(false);
|
|
3876
|
+
reconnectAttemptsRef.current = 0;
|
|
3877
|
+
eventCountRef.current = 0;
|
|
3697
3878
|
}, [initialSessionId, resetStreamingState]);
|
|
3698
3879
|
const setEntries = react.useCallback((newEntries) => {
|
|
3699
3880
|
resetStreamingState();
|
|
@@ -3709,6 +3890,7 @@ function useAgentChat(options) {
|
|
|
3709
3890
|
return {
|
|
3710
3891
|
entries,
|
|
3711
3892
|
isStreaming,
|
|
3893
|
+
isReconnecting,
|
|
3712
3894
|
error,
|
|
3713
3895
|
sessionId,
|
|
3714
3896
|
send,
|
|
@@ -3717,6 +3899,254 @@ function useAgentChat(options) {
|
|
|
3717
3899
|
setEntries
|
|
3718
3900
|
};
|
|
3719
3901
|
}
|
|
3902
|
+
function generateId() {
|
|
3903
|
+
return `msg-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
3904
|
+
}
|
|
3905
|
+
function useChat(options) {
|
|
3906
|
+
const {
|
|
3907
|
+
createStream,
|
|
3908
|
+
// subscribeToSession, // TODO: implement reconnection support
|
|
3909
|
+
initialSessionId,
|
|
3910
|
+
initialMessages = [],
|
|
3911
|
+
onToolCall,
|
|
3912
|
+
onFinish,
|
|
3913
|
+
onError,
|
|
3914
|
+
onSessionStart,
|
|
3915
|
+
maxReconnectAttempts = 3,
|
|
3916
|
+
// reconnectBaseDelay = 1000, // TODO: implement reconnection support
|
|
3917
|
+
middleware
|
|
3918
|
+
} = options;
|
|
3919
|
+
const [messages, setMessages] = react.useState(initialMessages);
|
|
3920
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
3921
|
+
const [isReconnecting, setIsReconnecting] = react.useState(false);
|
|
3922
|
+
const [error, setError] = react.useState(void 0);
|
|
3923
|
+
const [sessionId, setSessionId] = react.useState(initialSessionId || null);
|
|
3924
|
+
const [input, setInput] = react.useState("");
|
|
3925
|
+
const abortControllerRef = react.useRef(null);
|
|
3926
|
+
const currentAssistantMessageRef = react.useRef(null);
|
|
3927
|
+
const reconnectAttemptsRef = react.useRef(0);
|
|
3928
|
+
const sessionIdRef = react.useRef(sessionId);
|
|
3929
|
+
react.useEffect(() => {
|
|
3930
|
+
sessionIdRef.current = sessionId;
|
|
3931
|
+
}, [sessionId]);
|
|
3932
|
+
const entries = messagesToNormalizedEntries(messages);
|
|
3933
|
+
const updateStreamingMessage = react.useCallback((updater) => {
|
|
3934
|
+
if (!currentAssistantMessageRef.current) return;
|
|
3935
|
+
currentAssistantMessageRef.current = updater(currentAssistantMessageRef.current);
|
|
3936
|
+
const currentMsg = currentAssistantMessageRef.current;
|
|
3937
|
+
setMessages((prev) => {
|
|
3938
|
+
const lastIndex = prev.length - 1;
|
|
3939
|
+
const lastMessage = prev[lastIndex];
|
|
3940
|
+
if (lastIndex >= 0 && lastMessage && currentMsg && lastMessage.id === currentMsg.id) {
|
|
3941
|
+
return [...prev.slice(0, lastIndex), currentMsg];
|
|
3942
|
+
}
|
|
3943
|
+
return prev;
|
|
3944
|
+
});
|
|
3945
|
+
}, []);
|
|
3946
|
+
const processEvent = react.useCallback((event) => {
|
|
3947
|
+
switch (event.type) {
|
|
3948
|
+
case "session_start":
|
|
3949
|
+
if (event.sessionId) {
|
|
3950
|
+
setSessionId(event.sessionId);
|
|
3951
|
+
onSessionStart?.(event.sessionId);
|
|
3952
|
+
}
|
|
3953
|
+
break;
|
|
3954
|
+
case "text_delta":
|
|
3955
|
+
if (event.delta) {
|
|
3956
|
+
updateStreamingMessage((msg) => ({
|
|
3957
|
+
...msg,
|
|
3958
|
+
content: msg.content + event.delta
|
|
3959
|
+
}));
|
|
3960
|
+
}
|
|
3961
|
+
break;
|
|
3962
|
+
case "tool_use":
|
|
3963
|
+
if (event.toolId && event.toolName) {
|
|
3964
|
+
const toolInvocation = {
|
|
3965
|
+
state: "call",
|
|
3966
|
+
toolCallId: event.toolId,
|
|
3967
|
+
toolName: event.toolName,
|
|
3968
|
+
args: event.input || {}
|
|
3969
|
+
};
|
|
3970
|
+
updateStreamingMessage((msg) => ({
|
|
3971
|
+
...msg,
|
|
3972
|
+
toolInvocations: [...msg.toolInvocations || [], toolInvocation]
|
|
3973
|
+
}));
|
|
3974
|
+
onToolCall?.({ toolCall: toolInvocation });
|
|
3975
|
+
}
|
|
3976
|
+
break;
|
|
3977
|
+
case "tool_result":
|
|
3978
|
+
if (event.toolId) {
|
|
3979
|
+
updateStreamingMessage((msg) => ({
|
|
3980
|
+
...msg,
|
|
3981
|
+
toolInvocations: msg.toolInvocations?.map(
|
|
3982
|
+
(inv) => inv.toolCallId === event.toolId ? { ...inv, state: "result", result: event.toolResult } : inv
|
|
3983
|
+
)
|
|
3984
|
+
}));
|
|
3985
|
+
}
|
|
3986
|
+
break;
|
|
3987
|
+
case "text":
|
|
3988
|
+
if (event.text && !currentAssistantMessageRef.current?.content) {
|
|
3989
|
+
updateStreamingMessage((msg) => ({
|
|
3990
|
+
...msg,
|
|
3991
|
+
content: event.text || ""
|
|
3992
|
+
}));
|
|
3993
|
+
}
|
|
3994
|
+
break;
|
|
3995
|
+
case "error":
|
|
3996
|
+
if (event.error) {
|
|
3997
|
+
const err = new Error(event.error);
|
|
3998
|
+
setError(err);
|
|
3999
|
+
onError?.(err);
|
|
4000
|
+
}
|
|
4001
|
+
break;
|
|
4002
|
+
case "complete":
|
|
4003
|
+
if (currentAssistantMessageRef.current) {
|
|
4004
|
+
onFinish?.(currentAssistantMessageRef.current);
|
|
4005
|
+
}
|
|
4006
|
+
break;
|
|
4007
|
+
}
|
|
4008
|
+
}, [updateStreamingMessage, onToolCall, onFinish, onError, onSessionStart]);
|
|
4009
|
+
const append = react.useCallback(async (messageOrContent, options2) => {
|
|
4010
|
+
if (isLoading) return null;
|
|
4011
|
+
const userMessage = typeof messageOrContent === "string" ? {
|
|
4012
|
+
id: generateId(),
|
|
4013
|
+
role: "user",
|
|
4014
|
+
content: messageOrContent,
|
|
4015
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
4016
|
+
} : {
|
|
4017
|
+
id: messageOrContent.id || generateId(),
|
|
4018
|
+
role: messageOrContent.role,
|
|
4019
|
+
content: messageOrContent.content,
|
|
4020
|
+
toolInvocations: messageOrContent.toolInvocations,
|
|
4021
|
+
reasoning: messageOrContent.reasoning,
|
|
4022
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
4023
|
+
};
|
|
4024
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
4025
|
+
setIsLoading(true);
|
|
4026
|
+
setError(void 0);
|
|
4027
|
+
reconnectAttemptsRef.current = 0;
|
|
4028
|
+
const assistantMessage = {
|
|
4029
|
+
id: generateId(),
|
|
4030
|
+
role: "assistant",
|
|
4031
|
+
content: "",
|
|
4032
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
4033
|
+
};
|
|
4034
|
+
currentAssistantMessageRef.current = assistantMessage;
|
|
4035
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
4036
|
+
const controller = new AbortController();
|
|
4037
|
+
abortControllerRef.current = controller;
|
|
4038
|
+
try {
|
|
4039
|
+
let finalPrompt = userMessage.content;
|
|
4040
|
+
let additionalMetadata = options2?.body || {};
|
|
4041
|
+
if (middleware?.length) {
|
|
4042
|
+
const middlewareRequest = {
|
|
4043
|
+
prompt: finalPrompt,
|
|
4044
|
+
sessionId: sessionIdRef.current,
|
|
4045
|
+
metadata: additionalMetadata
|
|
4046
|
+
};
|
|
4047
|
+
const { request, error: middlewareError } = await applyRequestMiddleware(middleware, middlewareRequest);
|
|
4048
|
+
if (middlewareError) {
|
|
4049
|
+
const err = new Error(middlewareError);
|
|
4050
|
+
setError(err);
|
|
4051
|
+
onError?.(err);
|
|
4052
|
+
setIsLoading(false);
|
|
4053
|
+
return null;
|
|
4054
|
+
}
|
|
4055
|
+
finalPrompt = request.prompt;
|
|
4056
|
+
additionalMetadata = request.metadata || {};
|
|
4057
|
+
}
|
|
4058
|
+
const streamOptions = {
|
|
4059
|
+
signal: controller.signal,
|
|
4060
|
+
metadata: Object.keys(additionalMetadata).length > 0 ? additionalMetadata : void 0
|
|
4061
|
+
};
|
|
4062
|
+
const stream = createStream(finalPrompt, sessionIdRef.current || void 0, streamOptions);
|
|
4063
|
+
for await (const event of stream) {
|
|
4064
|
+
if (controller.signal.aborted) break;
|
|
4065
|
+
let processedEvent = event;
|
|
4066
|
+
if (middleware?.length) {
|
|
4067
|
+
processedEvent = await applyEventMiddleware(middleware, event);
|
|
4068
|
+
}
|
|
4069
|
+
if (processedEvent) {
|
|
4070
|
+
processEvent(processedEvent);
|
|
4071
|
+
}
|
|
4072
|
+
}
|
|
4073
|
+
if (middleware?.length && sessionIdRef.current) {
|
|
4074
|
+
await callMiddlewareComplete(middleware, sessionIdRef.current);
|
|
4075
|
+
}
|
|
4076
|
+
return assistantMessage.id;
|
|
4077
|
+
} catch (err) {
|
|
4078
|
+
const isAbort = err.name === "AbortError";
|
|
4079
|
+
if (!isAbort) {
|
|
4080
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
4081
|
+
setError(error2);
|
|
4082
|
+
onError?.(error2);
|
|
4083
|
+
if (middleware?.length) {
|
|
4084
|
+
await callMiddlewareError(middleware, error2.message);
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
return null;
|
|
4088
|
+
} finally {
|
|
4089
|
+
setIsLoading(false);
|
|
4090
|
+
setIsReconnecting(false);
|
|
4091
|
+
abortControllerRef.current = null;
|
|
4092
|
+
currentAssistantMessageRef.current = null;
|
|
4093
|
+
}
|
|
4094
|
+
}, [isLoading, createStream, processEvent, middleware, onError]);
|
|
4095
|
+
const stop = react.useCallback(() => {
|
|
4096
|
+
reconnectAttemptsRef.current = maxReconnectAttempts + 1;
|
|
4097
|
+
setIsReconnecting(false);
|
|
4098
|
+
if (abortControllerRef.current) {
|
|
4099
|
+
abortControllerRef.current.abort();
|
|
4100
|
+
}
|
|
4101
|
+
}, [maxReconnectAttempts]);
|
|
4102
|
+
const reload = react.useCallback(async () => {
|
|
4103
|
+
let lastUserMessageIndex = -1;
|
|
4104
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
4105
|
+
if (messages[i]?.role === "user") {
|
|
4106
|
+
lastUserMessageIndex = i;
|
|
4107
|
+
break;
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
if (lastUserMessageIndex === -1) return null;
|
|
4111
|
+
const lastUserMessage = messages[lastUserMessageIndex];
|
|
4112
|
+
if (!lastUserMessage) return null;
|
|
4113
|
+
setMessages(messages.slice(0, lastUserMessageIndex + 1));
|
|
4114
|
+
return append(lastUserMessage);
|
|
4115
|
+
}, [messages, append]);
|
|
4116
|
+
const handleInputChange = react.useCallback((e) => {
|
|
4117
|
+
setInput(e.target.value);
|
|
4118
|
+
}, []);
|
|
4119
|
+
const handleSubmit = react.useCallback((e, options2) => {
|
|
4120
|
+
e?.preventDefault();
|
|
4121
|
+
if (!input.trim()) return;
|
|
4122
|
+
const message = input;
|
|
4123
|
+
setInput("");
|
|
4124
|
+
append(message, options2);
|
|
4125
|
+
}, [input, append]);
|
|
4126
|
+
react.useEffect(() => {
|
|
4127
|
+
return () => {
|
|
4128
|
+
if (abortControllerRef.current) {
|
|
4129
|
+
abortControllerRef.current.abort();
|
|
4130
|
+
}
|
|
4131
|
+
};
|
|
4132
|
+
}, []);
|
|
4133
|
+
return {
|
|
4134
|
+
messages,
|
|
4135
|
+
isLoading,
|
|
4136
|
+
error,
|
|
4137
|
+
sessionId,
|
|
4138
|
+
append,
|
|
4139
|
+
stop,
|
|
4140
|
+
setMessages,
|
|
4141
|
+
reload,
|
|
4142
|
+
input,
|
|
4143
|
+
setInput,
|
|
4144
|
+
handleInputChange,
|
|
4145
|
+
handleSubmit,
|
|
4146
|
+
isReconnecting,
|
|
4147
|
+
entries
|
|
4148
|
+
};
|
|
4149
|
+
}
|
|
3720
4150
|
function textToBase64(text) {
|
|
3721
4151
|
const encoder = new TextEncoder();
|
|
3722
4152
|
const bytes = encoder.encode(text);
|
|
@@ -3791,10 +4221,14 @@ function useLongTextConversion({
|
|
|
3791
4221
|
}
|
|
3792
4222
|
|
|
3793
4223
|
exports.ActionIcon = ActionIcon;
|
|
3794
|
-
exports.AgentToolCard = AgentToolCard;
|
|
3795
4224
|
exports.AlertCircleIcon = AlertCircleIcon;
|
|
3796
4225
|
exports.AlertTriangleIcon = AlertTriangleIcon;
|
|
3797
|
-
exports.
|
|
4226
|
+
exports.ArrowUpIcon = ArrowUpIcon;
|
|
4227
|
+
exports.Attachment = Attachment;
|
|
4228
|
+
exports.AttachmentInfo = AttachmentInfo;
|
|
4229
|
+
exports.AttachmentPreview = AttachmentPreview;
|
|
4230
|
+
exports.AttachmentRemove = AttachmentRemove;
|
|
4231
|
+
exports.Attachments = Attachments;
|
|
3798
4232
|
exports.BotIcon = BotIcon;
|
|
3799
4233
|
exports.BrainIcon = BrainIcon;
|
|
3800
4234
|
exports.BugIcon = BugIcon;
|
|
@@ -3809,73 +4243,92 @@ exports.ClipboardListIcon = ClipboardListIcon;
|
|
|
3809
4243
|
exports.ClockIcon = ClockIcon;
|
|
3810
4244
|
exports.CodeBlock = CodeBlock;
|
|
3811
4245
|
exports.CodeIcon = CodeIcon;
|
|
3812
|
-
exports.
|
|
3813
|
-
exports.
|
|
4246
|
+
exports.Conversation = Conversation;
|
|
4247
|
+
exports.ConversationContent = ConversationContent;
|
|
4248
|
+
exports.ConversationEmptyState = ConversationEmptyState;
|
|
4249
|
+
exports.ConversationScrollButton = ConversationScrollButton;
|
|
3814
4250
|
exports.CopyIcon = CopyIcon;
|
|
3815
|
-
exports.
|
|
3816
|
-
exports.DisplayModeProvider = DisplayModeProvider;
|
|
3817
|
-
exports.DisplayModeToggle = DisplayModeToggle;
|
|
4251
|
+
exports.DEFAULT_STYLE_CONFIG = DEFAULT_STYLE_CONFIG;
|
|
3818
4252
|
exports.EditIcon = EditIcon;
|
|
3819
4253
|
exports.EnvVarsPanel = EnvVarsPanel;
|
|
3820
4254
|
exports.ErrorIcon = ErrorIcon;
|
|
3821
|
-
exports.
|
|
3822
|
-
exports.FileBadge = FileBadge;
|
|
4255
|
+
exports.FileBadgeCompact = FileBadgeCompact;
|
|
3823
4256
|
exports.FileIcon = FileIcon;
|
|
3824
4257
|
exports.FilePlusIcon = FilePlusIcon;
|
|
3825
4258
|
exports.FolderSearchIcon = FolderSearchIcon;
|
|
3826
4259
|
exports.GlobeIcon = GlobeIcon;
|
|
4260
|
+
exports.HomeIcon = HomeIcon;
|
|
3827
4261
|
exports.InfoIcon = InfoIcon;
|
|
3828
4262
|
exports.JsonDisplay = JsonDisplay;
|
|
3829
4263
|
exports.LazyMarkdown = LazyMarkdown;
|
|
3830
4264
|
exports.ListChecksIcon = ListChecksIcon;
|
|
3831
4265
|
exports.LoaderIcon = LoaderIcon;
|
|
3832
|
-
exports.
|
|
4266
|
+
exports.LoadingDots = LoadingDots;
|
|
4267
|
+
exports.LoadingSpinner = LoadingSpinner;
|
|
3833
4268
|
exports.LogsPanel = LogsPanel;
|
|
3834
|
-
exports.
|
|
3835
|
-
exports.
|
|
4269
|
+
exports.Message = Message;
|
|
4270
|
+
exports.MessageAction = MessageAction;
|
|
4271
|
+
exports.MessageActions = MessageActions;
|
|
4272
|
+
exports.MessageAvatar = MessageAvatar;
|
|
4273
|
+
exports.MessageContent = MessageContent;
|
|
4274
|
+
exports.MessageResponse = MessageResponse;
|
|
4275
|
+
exports.MessageShimmer = MessageShimmer;
|
|
3836
4276
|
exports.MessageSquareIcon = MessageSquareIcon;
|
|
4277
|
+
exports.MessageTimestamp = MessageTimestamp;
|
|
4278
|
+
exports.MicrophoneIcon = MicrophoneIcon;
|
|
3837
4279
|
exports.MoonIcon = MoonIcon;
|
|
3838
4280
|
exports.OptionCards = OptionCards;
|
|
3839
4281
|
exports.PaperclipIcon = PaperclipIcon;
|
|
3840
4282
|
exports.PlugIcon = PlugIcon;
|
|
3841
|
-
exports.
|
|
4283
|
+
exports.Reasoning = Reasoning;
|
|
4284
|
+
exports.ReasoningContent = ReasoningContent;
|
|
4285
|
+
exports.ReasoningTrigger = ReasoningTrigger;
|
|
3842
4286
|
exports.SearchIcon = SearchIcon;
|
|
3843
4287
|
exports.SendIcon = SendIcon;
|
|
4288
|
+
exports.Shimmer = Shimmer;
|
|
4289
|
+
exports.ShimmerBlock = ShimmerBlock;
|
|
4290
|
+
exports.ShimmerLine = ShimmerLine;
|
|
4291
|
+
exports.ShimmerText = ShimmerText;
|
|
3844
4292
|
exports.SparklesIcon = SparklesIcon;
|
|
3845
4293
|
exports.SpinnerIcon = SpinnerIcon;
|
|
3846
4294
|
exports.StatusIndicator = StatusIndicator;
|
|
3847
|
-
exports.StepAccordion = StepAccordion;
|
|
3848
4295
|
exports.StopCircleIcon = StopCircleIcon;
|
|
3849
|
-
exports.StreamingText = StreamingText;
|
|
3850
4296
|
exports.SunIcon = SunIcon;
|
|
4297
|
+
exports.Task = Task;
|
|
4298
|
+
exports.TaskContent = TaskContent;
|
|
4299
|
+
exports.TaskItem = TaskItem;
|
|
4300
|
+
exports.TaskList = TaskList;
|
|
4301
|
+
exports.TaskTrigger = TaskTrigger;
|
|
3851
4302
|
exports.TerminalIcon = TerminalIcon;
|
|
3852
|
-
exports.
|
|
3853
|
-
exports.
|
|
3854
|
-
exports.
|
|
3855
|
-
exports.ToolCallCard = ToolCallCard;
|
|
3856
|
-
exports.ToolCallMessage = ToolCallMessage;
|
|
3857
|
-
exports.ToolExecutionGroup = ToolExecutionGroup;
|
|
4303
|
+
exports.ThinkingIndicator = ThinkingIndicator;
|
|
4304
|
+
exports.Tool = Tool;
|
|
4305
|
+
exports.ToolHeader = ToolHeader;
|
|
3858
4306
|
exports.ToolIcon = ToolIcon;
|
|
3859
|
-
exports.
|
|
4307
|
+
exports.ToolInput = ToolInput;
|
|
4308
|
+
exports.ToolList = ToolList;
|
|
4309
|
+
exports.ToolOutput = ToolOutput;
|
|
3860
4310
|
exports.UserIcon = UserIcon;
|
|
3861
|
-
exports.UserMessage = UserMessage;
|
|
3862
4311
|
exports.XCircleIcon = XCircleIcon;
|
|
3863
4312
|
exports.XIcon = XIcon;
|
|
3864
4313
|
exports.allKeyframesCss = allKeyframesCss;
|
|
4314
|
+
exports.applyEventMiddleware = applyEventMiddleware;
|
|
4315
|
+
exports.applyRequestMiddleware = applyRequestMiddleware;
|
|
3865
4316
|
exports.borderRadius = borderRadius;
|
|
4317
|
+
exports.callMiddlewareComplete = callMiddlewareComplete;
|
|
4318
|
+
exports.callMiddlewareError = callMiddlewareError;
|
|
3866
4319
|
exports.cn = cn;
|
|
3867
4320
|
exports.colors = colors;
|
|
3868
4321
|
exports.createToolCall = createToolCall;
|
|
4322
|
+
exports.cssVars = cssVars;
|
|
3869
4323
|
exports.extractTextContent = extractTextContent;
|
|
3870
|
-
exports.extractToolCallsFromGroup = extractToolCallsFromGroup;
|
|
3871
4324
|
exports.formatElapsedTime = formatElapsedTime;
|
|
3872
4325
|
exports.formatFileSize = formatFileSize;
|
|
4326
|
+
exports.formatFileSizeHook = formatFileSize2;
|
|
3873
4327
|
exports.formatTimestamp = formatTimestamp;
|
|
3874
4328
|
exports.formatToolName = formatToolName;
|
|
3875
4329
|
exports.generateToolSummary = generateToolSummary;
|
|
3876
4330
|
exports.getActionIcon = getActionIcon;
|
|
3877
4331
|
exports.getActionLabel = getActionLabel;
|
|
3878
|
-
exports.groupEntriesForCompactMode = groupEntriesForCompactMode;
|
|
3879
4332
|
exports.inlineStyles = inlineStyles;
|
|
3880
4333
|
exports.isAgentToolAction = isAgentToolAction;
|
|
3881
4334
|
exports.isCommandRunAction = isCommandRunAction;
|
|
@@ -3895,7 +4348,11 @@ exports.isWidgetEntry = isWidgetEntry;
|
|
|
3895
4348
|
exports.keyframes = keyframes;
|
|
3896
4349
|
exports.keyframesCss = keyframesCss;
|
|
3897
4350
|
exports.mapToolToActionType = mapToolToActionType;
|
|
4351
|
+
exports.messageToNormalizedEntry = messageToNormalizedEntry;
|
|
4352
|
+
exports.messagesToNormalizedEntries = messagesToNormalizedEntries;
|
|
3898
4353
|
exports.normalizeToolResult = normalizeToolResult;
|
|
4354
|
+
exports.normalizedEntriesToMessages = normalizedEntriesToMessages;
|
|
4355
|
+
exports.normalizedEntryToMessage = normalizedEntryToMessage;
|
|
3899
4356
|
exports.parseCommandResult = parseCommandResult;
|
|
3900
4357
|
exports.parseMcpToolName = parseMcpToolName;
|
|
3901
4358
|
exports.parseOptionsFromContent = parseOptionsFromContent;
|
|
@@ -3907,13 +4364,17 @@ exports.truncate = truncate;
|
|
|
3907
4364
|
exports.typography = typography;
|
|
3908
4365
|
exports.updateToolCallWithResult = updateToolCallWithResult;
|
|
3909
4366
|
exports.useAgentChat = useAgentChat;
|
|
3910
|
-
exports.
|
|
3911
|
-
exports.
|
|
4367
|
+
exports.useAttachment = useAttachment;
|
|
4368
|
+
exports.useChat = useChat;
|
|
4369
|
+
exports.useConversation = useConversation;
|
|
3912
4370
|
exports.useFileUpload = useFileUpload;
|
|
3913
4371
|
exports.useLongTextConversion = useLongTextConversion;
|
|
4372
|
+
exports.useMessage = useMessage;
|
|
3914
4373
|
exports.useMessageQueue = useMessageQueue;
|
|
4374
|
+
exports.useReasoning = useReasoning;
|
|
3915
4375
|
exports.useStopExecution = useStopExecution;
|
|
3916
|
-
exports.
|
|
4376
|
+
exports.useTask = useTask;
|
|
4377
|
+
exports.useTool = useTool;
|
|
3917
4378
|
exports.widget = widget;
|
|
3918
4379
|
exports.zIndex = zIndex;
|
|
3919
4380
|
//# sourceMappingURL=index.cjs.map
|