@nextclaw/agent-chat-ui 0.2.8 → 0.2.10
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/index.js +301 -95
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2523,109 +2523,315 @@ function ChatReasoningBlock(props) {
|
|
|
2523
2523
|
] });
|
|
2524
2524
|
}
|
|
2525
2525
|
|
|
2526
|
-
// src/components/chat/ui/chat-message-list/
|
|
2527
|
-
import {
|
|
2528
|
-
import {
|
|
2529
|
-
|
|
2526
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx
|
|
2527
|
+
import { Terminal, FileText, Code2, Search as Search2, Globe } from "lucide-react";
|
|
2528
|
+
import { useState as useState6, useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
2529
|
+
|
|
2530
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-root.tsx
|
|
2531
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2532
|
+
function ToolCardRoot({ children, className }) {
|
|
2533
|
+
return /* @__PURE__ */ jsx17(
|
|
2534
|
+
"div",
|
|
2535
|
+
{
|
|
2536
|
+
className: cn(
|
|
2537
|
+
"my-2 rounded-lg border border-amber-200/50 bg-amber-100/30 shadow-sm overflow-hidden text-[12px]",
|
|
2538
|
+
"w-[280px] sm:w-[360px] md:w-[480px] min-w-full max-w-full transition-all flex flex-col",
|
|
2539
|
+
className
|
|
2540
|
+
),
|
|
2541
|
+
children
|
|
2542
|
+
}
|
|
2543
|
+
);
|
|
2544
|
+
}
|
|
2545
|
+
function ToolCardContent({ children, className }) {
|
|
2546
|
+
return /* @__PURE__ */ jsx17("div", { className: cn("border-t border-amber-200/15 bg-amber-50/50 p-3 w-full overflow-hidden", className), children });
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-header.tsx
|
|
2550
|
+
import { ChevronDown as ChevronDown2, ChevronRight } from "lucide-react";
|
|
2551
|
+
|
|
2552
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-status.tsx
|
|
2553
|
+
import { Check as Check4, Loader2, AlertTriangle, Minus } from "lucide-react";
|
|
2554
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2530
2555
|
var STATUS_STYLES = {
|
|
2531
|
-
running: {
|
|
2532
|
-
|
|
2533
|
-
},
|
|
2534
|
-
|
|
2535
|
-
text: "text-amber-700/80"
|
|
2536
|
-
},
|
|
2537
|
-
error: {
|
|
2538
|
-
text: "text-amber-700/80"
|
|
2539
|
-
},
|
|
2540
|
-
cancelled: {
|
|
2541
|
-
text: "text-amber-700/80"
|
|
2542
|
-
}
|
|
2556
|
+
running: { text: "text-amber-500/80", icon: Loader2, spin: true },
|
|
2557
|
+
success: { text: "text-amber-500/80", icon: Check4, spin: false },
|
|
2558
|
+
error: { text: "text-amber-500/80", icon: AlertTriangle, spin: false },
|
|
2559
|
+
cancelled: { text: "text-amber-500/80", icon: Minus, spin: false }
|
|
2543
2560
|
};
|
|
2544
|
-
function
|
|
2545
|
-
const
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
}
|
|
2552
|
-
if (lowered.includes("fetch") || lowered.includes("http") || lowered.includes("web")) {
|
|
2553
|
-
return /* @__PURE__ */ jsx17(Globe, { className: "h-3.5 w-3.5" });
|
|
2554
|
-
}
|
|
2555
|
-
if (lowered.includes("read") || lowered.includes("file")) {
|
|
2556
|
-
return /* @__PURE__ */ jsx17(FileSearch, { className: "h-3.5 w-3.5" });
|
|
2557
|
-
}
|
|
2558
|
-
if (lowered.includes("message") || lowered.includes("send")) {
|
|
2559
|
-
return /* @__PURE__ */ jsx17(SendHorizontal, { className: "h-3.5 w-3.5" });
|
|
2560
|
-
}
|
|
2561
|
-
if (lowered.includes("cron") || lowered.includes("schedule")) {
|
|
2562
|
-
return /* @__PURE__ */ jsx17(Clock3, { className: "h-3.5 w-3.5" });
|
|
2563
|
-
}
|
|
2564
|
-
return /* @__PURE__ */ jsx17(Wrench2, { className: "h-3.5 w-3.5" });
|
|
2561
|
+
function ToolStatusLabel({ card }) {
|
|
2562
|
+
const style = STATUS_STYLES[card.statusTone] || STATUS_STYLES.cancelled;
|
|
2563
|
+
const Icon2 = style.icon;
|
|
2564
|
+
return /* @__PURE__ */ jsxs10("span", { className: cn("inline-flex items-center gap-1.5 text-[11px] font-medium leading-none shrink-0", style.text), children: [
|
|
2565
|
+
/* @__PURE__ */ jsx18(Icon2, { className: cn("h-3.5 w-3.5", style.spin && "animate-spin"), strokeWidth: 3 }),
|
|
2566
|
+
card.statusTone === "running" ? card.statusLabel : null
|
|
2567
|
+
] });
|
|
2565
2568
|
}
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2569
|
+
|
|
2570
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-header.tsx
|
|
2571
|
+
import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2572
|
+
function ToolCardHeader({
|
|
2573
|
+
card,
|
|
2574
|
+
icon: Icon2,
|
|
2575
|
+
expanded,
|
|
2576
|
+
canExpand,
|
|
2577
|
+
onToggle
|
|
2578
|
+
}) {
|
|
2579
|
+
const summaryPart = card.summary?.replace(/^(command|path|args|query|input):\s*/i, "");
|
|
2580
|
+
return /* @__PURE__ */ jsxs11(
|
|
2581
|
+
"div",
|
|
2582
|
+
{
|
|
2583
|
+
className: cn(
|
|
2584
|
+
"flex items-center justify-between px-3 py-2.5 transition-colors bg-transparent",
|
|
2585
|
+
canExpand ? "cursor-pointer hover:bg-amber-100/30" : ""
|
|
2586
|
+
),
|
|
2587
|
+
onClick: onToggle,
|
|
2588
|
+
children: [
|
|
2589
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 font-mono min-w-0 max-w-[calc(100%-80px)] text-amber-950/80", children: [
|
|
2590
|
+
/* @__PURE__ */ jsx19(Icon2, { className: "h-4 w-4 text-amber-600/80 shrink-0", strokeWidth: 3 }),
|
|
2591
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
2592
|
+
/* @__PURE__ */ jsx19("span", { className: "font-bold shrink-0 tracking-tight", children: card.toolName }),
|
|
2593
|
+
summaryPart && /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2594
|
+
/* @__PURE__ */ jsx19("span", { className: "text-amber-300 font-bold select-none shrink-0", children: "\u203A" }),
|
|
2595
|
+
/* @__PURE__ */ jsx19("span", { className: "truncate flex-1 min-w-0 font-normal", title: summaryPart, children: summaryPart })
|
|
2596
|
+
] })
|
|
2597
|
+
] })
|
|
2598
|
+
] }),
|
|
2599
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3 shrink-0", children: [
|
|
2600
|
+
/* @__PURE__ */ jsx19(ToolStatusLabel, { card }),
|
|
2601
|
+
canExpand && (expanded ? /* @__PURE__ */ jsx19(ChevronDown2, { className: "h-4 w-4 text-amber-400/80", strokeWidth: 3 }) : /* @__PURE__ */ jsx19(ChevronRight, { className: "h-4 w-4 text-amber-400/80", strokeWidth: 3 }))
|
|
2602
|
+
] })
|
|
2603
|
+
]
|
|
2604
|
+
}
|
|
2605
|
+
);
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx
|
|
2609
|
+
import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2610
|
+
function TerminalExecutionView({ card }) {
|
|
2611
|
+
const output = card.output?.trim() ?? "";
|
|
2612
|
+
const isRunning = card.statusTone === "running";
|
|
2613
|
+
const hasContent = !!(card.summary?.trim() || output.length > 0);
|
|
2614
|
+
const wasEmptyRef = useRef5(!hasContent);
|
|
2615
|
+
const [expanded, setExpanded] = useState6(hasContent && (isRunning || card.statusTone === "error" || output.length < 500));
|
|
2616
|
+
const [hasUserToggled, setHasUserToggled] = useState6(false);
|
|
2617
|
+
const prevRunningRef = useRef5(isRunning);
|
|
2618
|
+
useEffect6(() => {
|
|
2619
|
+
if (wasEmptyRef.current && hasContent && isRunning) {
|
|
2620
|
+
setExpanded(true);
|
|
2621
|
+
wasEmptyRef.current = false;
|
|
2622
|
+
}
|
|
2623
|
+
}, [hasContent, isRunning]);
|
|
2624
|
+
useEffect6(() => {
|
|
2625
|
+
if (prevRunningRef.current && !isRunning && !hasUserToggled) {
|
|
2626
|
+
setExpanded(false);
|
|
2627
|
+
}
|
|
2628
|
+
prevRunningRef.current = isRunning;
|
|
2629
|
+
}, [isRunning, hasUserToggled]);
|
|
2630
|
+
const onToggle = () => {
|
|
2631
|
+
if (!output && !isRunning) return;
|
|
2632
|
+
setExpanded(!expanded);
|
|
2633
|
+
setHasUserToggled(true);
|
|
2634
|
+
};
|
|
2635
|
+
const commandPart = card.summary?.replace(/^(command|path|args|query|input):\s*/i, "");
|
|
2636
|
+
return /* @__PURE__ */ jsxs12(ToolCardRoot, { children: [
|
|
2637
|
+
/* @__PURE__ */ jsx20(
|
|
2638
|
+
ToolCardHeader,
|
|
2639
|
+
{
|
|
2640
|
+
card,
|
|
2641
|
+
icon: Terminal,
|
|
2642
|
+
expanded,
|
|
2643
|
+
canExpand: !!output || isRunning,
|
|
2644
|
+
onToggle
|
|
2645
|
+
}
|
|
2646
|
+
),
|
|
2647
|
+
expanded && /* @__PURE__ */ jsxs12(Fragment3, { children: [
|
|
2648
|
+
/* @__PURE__ */ jsx20("div", { className: "px-3 pb-0.5 font-mono w-full max-h-48 overflow-y-auto custom-scrollbar-amber min-h-0 text-[12px]", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2 leading-relaxed", children: [
|
|
2649
|
+
/* @__PURE__ */ jsx20("span", { className: "text-amber-500/50 font-medium shrink-0 select-none mt-[1px]", children: "$" }),
|
|
2650
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: commandPart ? /* @__PURE__ */ jsx20("span", { className: "text-amber-950/80 break-words whitespace-pre-wrap tracking-tight font-medium", children: commandPart }) : /* @__PURE__ */ jsx20("div", { className: "h-3 w-32 bg-amber-200/30 rounded animate-pulse mt-2" }) })
|
|
2651
|
+
] }) }),
|
|
2652
|
+
(output || isRunning && hasContent) && /* @__PURE__ */ jsx20(ToolCardContent, { className: "mt-2", children: /* @__PURE__ */ jsxs12("pre", { className: "font-mono text-[12px] text-amber-950/70 whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber leading-relaxed", children: [
|
|
2653
|
+
output,
|
|
2654
|
+
isRunning && /* @__PURE__ */ jsx20("span", { className: "inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle" })
|
|
2655
|
+
] }) })
|
|
2656
|
+
] })
|
|
2578
2657
|
] });
|
|
2579
2658
|
}
|
|
2580
|
-
function
|
|
2659
|
+
function FileOperationView({ card }) {
|
|
2660
|
+
const output = card.output?.trim() ?? "";
|
|
2661
|
+
const isRunning = card.statusTone === "running";
|
|
2662
|
+
const [expanded, setExpanded] = useState6(false);
|
|
2663
|
+
const [hasUserToggled, setHasUserToggled] = useState6(false);
|
|
2664
|
+
const prevRunningRef = useRef5(isRunning);
|
|
2665
|
+
useEffect6(() => {
|
|
2666
|
+
if (prevRunningRef.current && !isRunning && !hasUserToggled) {
|
|
2667
|
+
setExpanded(false);
|
|
2668
|
+
}
|
|
2669
|
+
prevRunningRef.current = isRunning;
|
|
2670
|
+
}, [isRunning, hasUserToggled]);
|
|
2671
|
+
const onToggle = () => {
|
|
2672
|
+
if (!output && !isRunning) return;
|
|
2673
|
+
setExpanded(!expanded);
|
|
2674
|
+
setHasUserToggled(true);
|
|
2675
|
+
};
|
|
2676
|
+
const isEdit = card.toolName === "edit_file" || card.toolName === "write_file";
|
|
2677
|
+
const renderLine = (line, idx) => {
|
|
2678
|
+
if (isEdit) {
|
|
2679
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
2680
|
+
return /* @__PURE__ */ jsxs12("div", { className: "bg-emerald-500/10 text-emerald-700 px-2 py-0.5 w-full break-all whitespace-pre-wrap", children: [
|
|
2681
|
+
/* @__PURE__ */ jsx20("span", { className: "select-none opacity-40 mr-2 w-3 inline-block shrink-0", children: "+" }),
|
|
2682
|
+
/* @__PURE__ */ jsx20("span", { children: line.slice(1) })
|
|
2683
|
+
] }, idx);
|
|
2684
|
+
}
|
|
2685
|
+
if (line.startsWith("-") && !line.startsWith("---")) {
|
|
2686
|
+
return /* @__PURE__ */ jsxs12("div", { className: "bg-rose-500/10 text-rose-700 px-2 py-0.5 w-full break-all whitespace-pre-wrap", children: [
|
|
2687
|
+
/* @__PURE__ */ jsx20("span", { className: "select-none opacity-40 mr-2 w-3 inline-block shrink-0", children: "-" }),
|
|
2688
|
+
/* @__PURE__ */ jsx20("span", { className: "line-through decoration-rose-400/50", children: line.slice(1) })
|
|
2689
|
+
] }, idx);
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
return /* @__PURE__ */ jsxs12("div", { className: "px-2 py-0.5 text-amber-950/80 w-full break-all whitespace-pre-wrap", children: [
|
|
2693
|
+
/* @__PURE__ */ jsx20("span", { className: "select-none opacity-0 mr-2 w-3 inline-block shrink-0", children: " " }),
|
|
2694
|
+
/* @__PURE__ */ jsx20("span", { children: line })
|
|
2695
|
+
] }, idx);
|
|
2696
|
+
};
|
|
2697
|
+
const lines = output.split("\n");
|
|
2698
|
+
const maxLines = 15;
|
|
2699
|
+
const isLong = lines.length > maxLines;
|
|
2700
|
+
const displayLines = !expanded && isLong ? lines.slice(0, maxLines) : lines;
|
|
2701
|
+
return /* @__PURE__ */ jsxs12(ToolCardRoot, { children: [
|
|
2702
|
+
/* @__PURE__ */ jsx20(
|
|
2703
|
+
ToolCardHeader,
|
|
2704
|
+
{
|
|
2705
|
+
card,
|
|
2706
|
+
icon: isEdit ? Code2 : FileText,
|
|
2707
|
+
expanded,
|
|
2708
|
+
canExpand: !!output || isRunning,
|
|
2709
|
+
onToggle
|
|
2710
|
+
}
|
|
2711
|
+
),
|
|
2712
|
+
expanded && output && /* @__PURE__ */ jsx20(ToolCardContent, { children: /* @__PURE__ */ jsx20("div", { className: "font-mono text-[12px] leading-relaxed py-2 max-h-48 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber text-amber-950/80 w-full px-1", children: displayLines.map(renderLine) }) })
|
|
2713
|
+
] });
|
|
2714
|
+
}
|
|
2715
|
+
function SearchSnippetView({ card }) {
|
|
2716
|
+
const isRunning = card.statusTone === "running";
|
|
2717
|
+
const [expanded, setExpanded] = useState6(isRunning);
|
|
2718
|
+
const [hasUserToggled, setHasUserToggled] = useState6(false);
|
|
2719
|
+
const prevRunningRef = useRef5(isRunning);
|
|
2581
2720
|
const output = card.output?.trim() ?? "";
|
|
2582
|
-
|
|
2583
|
-
|
|
2721
|
+
useEffect6(() => {
|
|
2722
|
+
if (prevRunningRef.current && !isRunning && !hasUserToggled) {
|
|
2723
|
+
setExpanded(false);
|
|
2724
|
+
}
|
|
2725
|
+
prevRunningRef.current = isRunning;
|
|
2726
|
+
}, [isRunning, hasUserToggled]);
|
|
2727
|
+
const onToggle = () => {
|
|
2728
|
+
if (!output && !isRunning) return;
|
|
2729
|
+
setExpanded(!expanded);
|
|
2730
|
+
setHasUserToggled(true);
|
|
2731
|
+
};
|
|
2732
|
+
return /* @__PURE__ */ jsxs12(ToolCardRoot, { children: [
|
|
2733
|
+
/* @__PURE__ */ jsx20(
|
|
2734
|
+
ToolCardHeader,
|
|
2735
|
+
{
|
|
2736
|
+
card,
|
|
2737
|
+
icon: Search2,
|
|
2738
|
+
expanded,
|
|
2739
|
+
canExpand: !!output || isRunning,
|
|
2740
|
+
onToggle
|
|
2741
|
+
}
|
|
2742
|
+
),
|
|
2743
|
+
expanded && output && /* @__PURE__ */ jsx20(ToolCardContent, { children: /* @__PURE__ */ jsx20("pre", { className: "font-mono text-[12px] text-amber-950/70 whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber py-2 leading-relaxed", children: output }) })
|
|
2744
|
+
] });
|
|
2745
|
+
}
|
|
2746
|
+
function GenericToolCard({ card }) {
|
|
2747
|
+
const output = card.output?.trim() ?? "";
|
|
2748
|
+
const isRunning = card.statusTone === "running";
|
|
2749
|
+
const [expanded, setExpanded] = useState6(isRunning);
|
|
2750
|
+
const [hasUserToggled, setHasUserToggled] = useState6(false);
|
|
2751
|
+
const prevRunningRef = useRef5(isRunning);
|
|
2584
2752
|
const showOutputSection = card.kind === "result" || card.hasResult;
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2753
|
+
useEffect6(() => {
|
|
2754
|
+
if (prevRunningRef.current && !isRunning && !hasUserToggled) {
|
|
2755
|
+
setExpanded(false);
|
|
2756
|
+
}
|
|
2757
|
+
prevRunningRef.current = isRunning;
|
|
2758
|
+
}, [isRunning, hasUserToggled]);
|
|
2759
|
+
const onToggle = () => {
|
|
2760
|
+
if (!showOutputSection) return;
|
|
2761
|
+
setExpanded(!expanded);
|
|
2762
|
+
setHasUserToggled(true);
|
|
2763
|
+
};
|
|
2764
|
+
return /* @__PURE__ */ jsxs12(ToolCardRoot, { children: [
|
|
2765
|
+
/* @__PURE__ */ jsx20(
|
|
2766
|
+
ToolCardHeader,
|
|
2767
|
+
{
|
|
2768
|
+
card,
|
|
2769
|
+
icon: Globe,
|
|
2770
|
+
expanded,
|
|
2771
|
+
canExpand: showOutputSection,
|
|
2772
|
+
onToggle
|
|
2773
|
+
}
|
|
2774
|
+
),
|
|
2775
|
+
expanded && output && /* @__PURE__ */ jsx20(ToolCardContent, { children: /* @__PURE__ */ jsx20("pre", { className: "mt-1 text-amber-950/80 whitespace-pre-wrap break-all overflow-y-auto overflow-x-hidden max-h-64 custom-scrollbar-amber py-1 w-full min-w-0 max-w-full leading-relaxed", children: output }) })
|
|
2597
2776
|
] });
|
|
2598
2777
|
}
|
|
2599
2778
|
|
|
2779
|
+
// src/components/chat/ui/chat-message-list/chat-tool-card.tsx
|
|
2780
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
2781
|
+
function isTerminalTool(name) {
|
|
2782
|
+
const lowered = name.toLowerCase();
|
|
2783
|
+
return lowered === "exec" || lowered === "execute_command" || lowered === "bash" || lowered === "shell" || lowered.includes("run_");
|
|
2784
|
+
}
|
|
2785
|
+
function isFileEditTool(name) {
|
|
2786
|
+
const lowered = name.toLowerCase();
|
|
2787
|
+
return lowered === "read_file" || lowered === "write_file" || lowered === "edit_file" || lowered === "apply_patch";
|
|
2788
|
+
}
|
|
2789
|
+
function isSearchTool(name) {
|
|
2790
|
+
const lowered = name.toLowerCase();
|
|
2791
|
+
return lowered === "grep_search" || lowered === "find_files" || lowered.includes("search");
|
|
2792
|
+
}
|
|
2793
|
+
function ChatToolCard({ card }) {
|
|
2794
|
+
if (isTerminalTool(card.toolName)) {
|
|
2795
|
+
return /* @__PURE__ */ jsx21(TerminalExecutionView, { card });
|
|
2796
|
+
}
|
|
2797
|
+
if (isFileEditTool(card.toolName)) {
|
|
2798
|
+
return /* @__PURE__ */ jsx21(FileOperationView, { card });
|
|
2799
|
+
}
|
|
2800
|
+
if (isSearchTool(card.toolName)) {
|
|
2801
|
+
return /* @__PURE__ */ jsx21(SearchSnippetView, { card });
|
|
2802
|
+
}
|
|
2803
|
+
return /* @__PURE__ */ jsx21(GenericToolCard, { card });
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2600
2806
|
// src/components/chat/ui/chat-message-list/chat-unknown-part.tsx
|
|
2601
|
-
import { jsx as
|
|
2807
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2602
2808
|
function ChatUnknownPart(props) {
|
|
2603
|
-
return /* @__PURE__ */
|
|
2604
|
-
/* @__PURE__ */
|
|
2809
|
+
return /* @__PURE__ */ jsxs13("div", { className: "rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600", children: [
|
|
2810
|
+
/* @__PURE__ */ jsxs13("div", { className: "font-semibold text-gray-700", children: [
|
|
2605
2811
|
props.label,
|
|
2606
2812
|
": ",
|
|
2607
2813
|
props.rawType
|
|
2608
2814
|
] }),
|
|
2609
|
-
props.text ? /* @__PURE__ */
|
|
2815
|
+
props.text ? /* @__PURE__ */ jsx22("pre", { className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500", children: props.text }) : null
|
|
2610
2816
|
] });
|
|
2611
2817
|
}
|
|
2612
2818
|
|
|
2613
2819
|
// src/components/chat/ui/chat-message-list/chat-message.tsx
|
|
2614
|
-
import { jsx as
|
|
2820
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
2615
2821
|
function ChatMessage(props) {
|
|
2616
2822
|
const { message, texts } = props;
|
|
2617
2823
|
const { role } = message;
|
|
2618
2824
|
const isUser = role === "user";
|
|
2619
|
-
return /* @__PURE__ */
|
|
2825
|
+
return /* @__PURE__ */ jsx23(
|
|
2620
2826
|
"div",
|
|
2621
2827
|
{
|
|
2622
2828
|
className: cn(
|
|
2623
2829
|
"inline-block w-fit max-w-full rounded-2xl border px-4 py-3 shadow-sm",
|
|
2624
2830
|
isUser ? "border-primary bg-primary text-white" : role === "assistant" ? "border-gray-200 bg-white text-gray-900" : "border-orange-200/80 bg-orange-50/70 text-gray-900"
|
|
2625
2831
|
),
|
|
2626
|
-
children: /* @__PURE__ */
|
|
2832
|
+
children: /* @__PURE__ */ jsx23("div", { className: "space-y-2", children: message.parts.map((part, index) => {
|
|
2627
2833
|
if (part.type === "markdown") {
|
|
2628
|
-
return /* @__PURE__ */
|
|
2834
|
+
return /* @__PURE__ */ jsx23(
|
|
2629
2835
|
ChatMessageMarkdown,
|
|
2630
2836
|
{
|
|
2631
2837
|
text: part.text,
|
|
@@ -2636,7 +2842,7 @@ function ChatMessage(props) {
|
|
|
2636
2842
|
);
|
|
2637
2843
|
}
|
|
2638
2844
|
if (part.type === "reasoning") {
|
|
2639
|
-
return /* @__PURE__ */
|
|
2845
|
+
return /* @__PURE__ */ jsx23(
|
|
2640
2846
|
ChatReasoningBlock,
|
|
2641
2847
|
{
|
|
2642
2848
|
label: part.label,
|
|
@@ -2647,10 +2853,10 @@ function ChatMessage(props) {
|
|
|
2647
2853
|
);
|
|
2648
2854
|
}
|
|
2649
2855
|
if (part.type === "tool-card") {
|
|
2650
|
-
return /* @__PURE__ */
|
|
2856
|
+
return /* @__PURE__ */ jsx23("div", { className: "mt-0.5", children: /* @__PURE__ */ jsx23(ChatToolCard, { card: part.card }) }, `tool-${index}`);
|
|
2651
2857
|
}
|
|
2652
2858
|
if (part.type === "file") {
|
|
2653
|
-
return /* @__PURE__ */
|
|
2859
|
+
return /* @__PURE__ */ jsx23(
|
|
2654
2860
|
ChatMessageFile,
|
|
2655
2861
|
{
|
|
2656
2862
|
file: part.file,
|
|
@@ -2660,7 +2866,7 @@ function ChatMessage(props) {
|
|
|
2660
2866
|
);
|
|
2661
2867
|
}
|
|
2662
2868
|
if (part.type === "unknown") {
|
|
2663
|
-
return /* @__PURE__ */
|
|
2869
|
+
return /* @__PURE__ */ jsx23(
|
|
2664
2870
|
ChatUnknownPart,
|
|
2665
2871
|
{
|
|
2666
2872
|
label: part.label,
|
|
@@ -2677,9 +2883,9 @@ function ChatMessage(props) {
|
|
|
2677
2883
|
}
|
|
2678
2884
|
|
|
2679
2885
|
// src/components/chat/ui/chat-message-list/chat-message-meta.tsx
|
|
2680
|
-
import { jsxs as
|
|
2886
|
+
import { jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2681
2887
|
function ChatMessageMeta(props) {
|
|
2682
|
-
return /* @__PURE__ */
|
|
2888
|
+
return /* @__PURE__ */ jsxs14(
|
|
2683
2889
|
"div",
|
|
2684
2890
|
{
|
|
2685
2891
|
className: cn(
|
|
@@ -2696,7 +2902,7 @@ function ChatMessageMeta(props) {
|
|
|
2696
2902
|
}
|
|
2697
2903
|
|
|
2698
2904
|
// src/components/chat/ui/chat-message-list/chat-message-list.tsx
|
|
2699
|
-
import { jsx as
|
|
2905
|
+
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2700
2906
|
var INVISIBLE_ONLY_TEXT_PATTERN = /\u200B|\u200C|\u200D|\u2060|\uFEFF/g;
|
|
2701
2907
|
function hasRenderableText(value) {
|
|
2702
2908
|
const trimmed = value.trim();
|
|
@@ -2718,36 +2924,36 @@ function ChatMessageList(props) {
|
|
|
2718
2924
|
const hasRenderableAssistantDraft = visibleMessages.some(
|
|
2719
2925
|
(message) => message.role === "assistant" && (message.status === "streaming" || message.status === "pending")
|
|
2720
2926
|
);
|
|
2721
|
-
return /* @__PURE__ */
|
|
2927
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn("space-y-5", props.className), children: [
|
|
2722
2928
|
visibleMessages.map((message) => {
|
|
2723
2929
|
const isUser = message.role === "user";
|
|
2724
|
-
return /* @__PURE__ */
|
|
2725
|
-
!isUser ? /* @__PURE__ */
|
|
2726
|
-
/* @__PURE__ */
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2930
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn("flex gap-3", isUser ? "justify-end" : "justify-start"), children: [
|
|
2931
|
+
!isUser ? /* @__PURE__ */ jsx24(ChatMessageAvatar, { role: message.role }) : null,
|
|
2932
|
+
/* @__PURE__ */ jsxs15("div", { className: cn("w-fit max-w-[92%] space-y-2", isUser && "flex flex-col items-end"), children: [
|
|
2933
|
+
/* @__PURE__ */ jsx24(ChatMessage, { message, texts: props.texts }),
|
|
2934
|
+
/* @__PURE__ */ jsx24(ChatMessageMeta, { roleLabel: message.roleLabel, timestampLabel: message.timestampLabel, isUser })
|
|
2729
2935
|
] }),
|
|
2730
|
-
isUser ? /* @__PURE__ */
|
|
2936
|
+
isUser ? /* @__PURE__ */ jsx24(ChatMessageAvatar, { role: message.role }) : null
|
|
2731
2937
|
] }, message.id);
|
|
2732
2938
|
}),
|
|
2733
|
-
props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */
|
|
2734
|
-
/* @__PURE__ */
|
|
2735
|
-
/* @__PURE__ */
|
|
2939
|
+
props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */ jsxs15("div", { className: "flex justify-start gap-3", children: [
|
|
2940
|
+
/* @__PURE__ */ jsx24(ChatMessageAvatar, { role: "assistant" }),
|
|
2941
|
+
/* @__PURE__ */ jsx24("div", { className: "rounded-2xl border border-gray-200 bg-white px-4 py-3 text-sm text-gray-500 shadow-sm", children: props.texts.typingLabel })
|
|
2736
2942
|
] }) : null
|
|
2737
2943
|
] });
|
|
2738
2944
|
}
|
|
2739
2945
|
|
|
2740
2946
|
// src/components/chat/hooks/use-sticky-bottom-scroll.ts
|
|
2741
|
-
import { useCallback as useCallback2, useEffect as
|
|
2947
|
+
import { useCallback as useCallback2, useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef6 } from "react";
|
|
2742
2948
|
var DEFAULT_STICKY_THRESHOLD_PX = 10;
|
|
2743
2949
|
function scrollElementToBottom(element) {
|
|
2744
2950
|
element.scrollTop = element.scrollHeight;
|
|
2745
2951
|
}
|
|
2746
2952
|
function useStickyBottomScroll(params) {
|
|
2747
|
-
const isStickyRef =
|
|
2748
|
-
const isProgrammaticScrollRef =
|
|
2749
|
-
const previousResetKeyRef =
|
|
2750
|
-
const pendingInitialScrollRef =
|
|
2953
|
+
const isStickyRef = useRef6(true);
|
|
2954
|
+
const isProgrammaticScrollRef = useRef6(false);
|
|
2955
|
+
const previousResetKeyRef = useRef6(null);
|
|
2956
|
+
const pendingInitialScrollRef = useRef6(false);
|
|
2751
2957
|
const onScroll = useCallback2(() => {
|
|
2752
2958
|
if (isProgrammaticScrollRef.current) {
|
|
2753
2959
|
isProgrammaticScrollRef.current = false;
|
|
@@ -2760,7 +2966,7 @@ function useStickyBottomScroll(params) {
|
|
|
2760
2966
|
const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight;
|
|
2761
2967
|
isStickyRef.current = distanceFromBottom <= (params.stickyThresholdPx ?? DEFAULT_STICKY_THRESHOLD_PX);
|
|
2762
2968
|
}, [params.scrollRef, params.stickyThresholdPx]);
|
|
2763
|
-
|
|
2969
|
+
useEffect7(() => {
|
|
2764
2970
|
if (previousResetKeyRef.current === params.resetKey) {
|
|
2765
2971
|
return;
|
|
2766
2972
|
}
|