@nextclaw/agent-chat-ui 0.2.19 → 0.2.20
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 +390 -252
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2752,7 +2752,7 @@ function ChatReasoningBlock({ label, text, isUser, isInProgress }) {
|
|
|
2752
2752
|
|
|
2753
2753
|
// src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx
|
|
2754
2754
|
import { Terminal, FileText, Code2, Search as Search2, Globe } from "lucide-react";
|
|
2755
|
-
import { useState as useState7, useEffect as
|
|
2755
|
+
import { useState as useState7, useEffect as useEffect8, useRef as useRef8 } from "react";
|
|
2756
2756
|
|
|
2757
2757
|
// src/components/chat/ui/chat-message-list/tool-card/tool-card-root.tsx
|
|
2758
2758
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
@@ -2833,18 +2833,230 @@ function ToolCardHeader({
|
|
|
2833
2833
|
);
|
|
2834
2834
|
}
|
|
2835
2835
|
|
|
2836
|
+
// src/components/chat/hooks/use-sticky-bottom-scroll.ts
|
|
2837
|
+
import { useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef6 } from "react";
|
|
2838
|
+
var DEFAULT_STICKY_THRESHOLD_PX = 10;
|
|
2839
|
+
function scrollElementToBottom(element) {
|
|
2840
|
+
element.scrollTop = element.scrollHeight;
|
|
2841
|
+
}
|
|
2842
|
+
function queueScrollToBottom(params) {
|
|
2843
|
+
const element = params.scrollRef.current;
|
|
2844
|
+
if (!element) {
|
|
2845
|
+
return;
|
|
2846
|
+
}
|
|
2847
|
+
if (params.scheduledScrollFrameRef.current !== null) {
|
|
2848
|
+
cancelAnimationFrame(params.scheduledScrollFrameRef.current);
|
|
2849
|
+
}
|
|
2850
|
+
params.scheduledScrollFrameRef.current = requestAnimationFrame(() => {
|
|
2851
|
+
params.scheduledScrollFrameRef.current = null;
|
|
2852
|
+
const currentElement = params.scrollRef.current;
|
|
2853
|
+
if (!currentElement) {
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
params.isProgrammaticScrollRef.current = true;
|
|
2857
|
+
scrollElementToBottom(currentElement);
|
|
2858
|
+
});
|
|
2859
|
+
}
|
|
2860
|
+
function useStickyBottomScroll(params) {
|
|
2861
|
+
const isStickyRef = useRef6(true);
|
|
2862
|
+
const isProgrammaticScrollRef = useRef6(false);
|
|
2863
|
+
const previousResetKeyRef = useRef6(null);
|
|
2864
|
+
const pendingInitialScrollRef = useRef6(false);
|
|
2865
|
+
const scheduledScrollFrameRef = useRef6(null);
|
|
2866
|
+
const onScroll = () => {
|
|
2867
|
+
if (isProgrammaticScrollRef.current) {
|
|
2868
|
+
isProgrammaticScrollRef.current = false;
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
const element = params.scrollRef.current;
|
|
2872
|
+
if (!element) {
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2875
|
+
const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight;
|
|
2876
|
+
isStickyRef.current = distanceFromBottom <= (params.stickyThresholdPx ?? DEFAULT_STICKY_THRESHOLD_PX);
|
|
2877
|
+
};
|
|
2878
|
+
useEffect7(() => {
|
|
2879
|
+
if (previousResetKeyRef.current === params.resetKey) {
|
|
2880
|
+
return;
|
|
2881
|
+
}
|
|
2882
|
+
previousResetKeyRef.current = params.resetKey;
|
|
2883
|
+
isStickyRef.current = true;
|
|
2884
|
+
pendingInitialScrollRef.current = true;
|
|
2885
|
+
}, [params.resetKey]);
|
|
2886
|
+
useEffect7(() => {
|
|
2887
|
+
const scheduledScrollFrame = scheduledScrollFrameRef.current;
|
|
2888
|
+
return () => {
|
|
2889
|
+
if (scheduledScrollFrame !== null) {
|
|
2890
|
+
cancelAnimationFrame(scheduledScrollFrame);
|
|
2891
|
+
}
|
|
2892
|
+
};
|
|
2893
|
+
}, []);
|
|
2894
|
+
useLayoutEffect2(() => {
|
|
2895
|
+
if (!pendingInitialScrollRef.current || params.isLoading || !params.hasContent) {
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
const element = params.scrollRef.current;
|
|
2899
|
+
if (!element) {
|
|
2900
|
+
return;
|
|
2901
|
+
}
|
|
2902
|
+
pendingInitialScrollRef.current = false;
|
|
2903
|
+
queueScrollToBottom({
|
|
2904
|
+
scrollRef: params.scrollRef,
|
|
2905
|
+
scheduledScrollFrameRef,
|
|
2906
|
+
isProgrammaticScrollRef
|
|
2907
|
+
});
|
|
2908
|
+
}, [params.hasContent, params.isLoading, params.scrollRef]);
|
|
2909
|
+
useLayoutEffect2(() => {
|
|
2910
|
+
if (!isStickyRef.current || !params.hasContent) {
|
|
2911
|
+
return;
|
|
2912
|
+
}
|
|
2913
|
+
const element = params.scrollRef.current;
|
|
2914
|
+
if (!element) {
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
queueScrollToBottom({
|
|
2918
|
+
scrollRef: params.scrollRef,
|
|
2919
|
+
scheduledScrollFrameRef,
|
|
2920
|
+
isProgrammaticScrollRef
|
|
2921
|
+
});
|
|
2922
|
+
}, [params.contentVersion, params.hasContent, params.scrollRef]);
|
|
2923
|
+
return { onScroll };
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2836
2926
|
// src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation.tsx
|
|
2837
|
-
import { Fragment as Fragment4 } from "react";
|
|
2927
|
+
import { Fragment as Fragment4, useRef as useRef7 } from "react";
|
|
2928
|
+
|
|
2929
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation-lines.tsx
|
|
2838
2930
|
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2931
|
+
var FILE_ROW_CLASS_NAME = "h-5 font-mono text-[11px] leading-5";
|
|
2932
|
+
var FILE_GUTTER_NUMBER_CELL_CLASS_NAME = "sticky left-0 z-[1] flex h-5 items-center justify-center px-2.5 tabular-nums select-none";
|
|
2839
2933
|
function formatLineNumber(value) {
|
|
2840
2934
|
return typeof value === "number" ? String(value) : "";
|
|
2841
2935
|
}
|
|
2842
2936
|
function readVisibleLineNumber(line) {
|
|
2843
2937
|
return formatLineNumber(line.newLineNumber ?? line.oldLineNumber);
|
|
2844
2938
|
}
|
|
2939
|
+
function readLineKey(prefix, line, index) {
|
|
2940
|
+
return `${prefix}-${index}-${line.oldLineNumber ?? "x"}-${line.newLineNumber ?? "x"}`;
|
|
2941
|
+
}
|
|
2942
|
+
function hasVisibleLineNumber(line) {
|
|
2943
|
+
return typeof line.newLineNumber === "number" || typeof line.oldLineNumber === "number";
|
|
2944
|
+
}
|
|
2945
|
+
function readHasBlockLineNumbers(block) {
|
|
2946
|
+
return block.lines.some(hasVisibleLineNumber);
|
|
2947
|
+
}
|
|
2948
|
+
function readLineNumberColumnWidth(block) {
|
|
2949
|
+
const maxDigits = block.lines.reduce((currentMax, line) => {
|
|
2950
|
+
if (!hasVisibleLineNumber(line)) {
|
|
2951
|
+
return currentMax;
|
|
2952
|
+
}
|
|
2953
|
+
return Math.max(currentMax, readVisibleLineNumber(line).length);
|
|
2954
|
+
}, 0);
|
|
2955
|
+
const width = Math.max(6.5, Math.min(8, maxDigits + 3.5));
|
|
2956
|
+
return `${width}ch`;
|
|
2957
|
+
}
|
|
2958
|
+
function buildRowTemplateColumns(params) {
|
|
2959
|
+
if (!params.showLineNumbers) {
|
|
2960
|
+
return void 0;
|
|
2961
|
+
}
|
|
2962
|
+
return {
|
|
2963
|
+
gridTemplateColumns: `${params.lineNumberColumnWidth} minmax(0, 1fr)`
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
|
+
function getLineNumberTone(line) {
|
|
2967
|
+
if (line.kind === "remove") {
|
|
2968
|
+
return "border-r border-rose-200 bg-rose-50 text-rose-700";
|
|
2969
|
+
}
|
|
2970
|
+
if (line.kind === "add") {
|
|
2971
|
+
return "border-r border-emerald-200 bg-emerald-50 text-emerald-700";
|
|
2972
|
+
}
|
|
2973
|
+
return "border-r border-stone-200 bg-stone-100 text-stone-500";
|
|
2974
|
+
}
|
|
2975
|
+
function getCodeRowTone(line) {
|
|
2976
|
+
if (line.kind === "remove") {
|
|
2977
|
+
return "bg-rose-50 text-rose-950";
|
|
2978
|
+
}
|
|
2979
|
+
if (line.kind === "add") {
|
|
2980
|
+
return "bg-emerald-50 text-emerald-950";
|
|
2981
|
+
}
|
|
2982
|
+
return "bg-white text-amber-950/80";
|
|
2983
|
+
}
|
|
2984
|
+
function FileOperationLineRow({
|
|
2985
|
+
line,
|
|
2986
|
+
showLineNumbers,
|
|
2987
|
+
lineNumberColumnWidth
|
|
2988
|
+
}) {
|
|
2989
|
+
return /* @__PURE__ */ jsxs13(
|
|
2990
|
+
"div",
|
|
2991
|
+
{
|
|
2992
|
+
"data-file-line-row": "true",
|
|
2993
|
+
className: cn("grid w-max min-w-full", FILE_ROW_CLASS_NAME),
|
|
2994
|
+
style: buildRowTemplateColumns({
|
|
2995
|
+
showLineNumbers,
|
|
2996
|
+
lineNumberColumnWidth
|
|
2997
|
+
}),
|
|
2998
|
+
children: [
|
|
2999
|
+
showLineNumbers ? /* @__PURE__ */ jsx21(
|
|
3000
|
+
"span",
|
|
3001
|
+
{
|
|
3002
|
+
"data-file-line-number-cell": "true",
|
|
3003
|
+
style: { width: lineNumberColumnWidth },
|
|
3004
|
+
className: cn(
|
|
3005
|
+
FILE_GUTTER_NUMBER_CELL_CLASS_NAME,
|
|
3006
|
+
getLineNumberTone(line)
|
|
3007
|
+
),
|
|
3008
|
+
children: readVisibleLineNumber(line)
|
|
3009
|
+
}
|
|
3010
|
+
) : null,
|
|
3011
|
+
/* @__PURE__ */ jsx21(
|
|
3012
|
+
"span",
|
|
3013
|
+
{
|
|
3014
|
+
"data-file-code-row": "true",
|
|
3015
|
+
className: cn(
|
|
3016
|
+
"block min-w-full whitespace-pre px-2.5",
|
|
3017
|
+
getCodeRowTone(line)
|
|
3018
|
+
),
|
|
3019
|
+
children: line.text || " "
|
|
3020
|
+
}
|
|
3021
|
+
)
|
|
3022
|
+
]
|
|
3023
|
+
}
|
|
3024
|
+
);
|
|
3025
|
+
}
|
|
3026
|
+
function FileOperationLinesGrid({
|
|
3027
|
+
block
|
|
3028
|
+
}) {
|
|
3029
|
+
const showLineNumbers = readHasBlockLineNumbers(block);
|
|
3030
|
+
const lineNumberColumnWidth = readLineNumberColumnWidth(block);
|
|
3031
|
+
return /* @__PURE__ */ jsx21("div", { className: "overflow-x-auto custom-scrollbar-amber bg-white", children: block.lines.map((line, index) => /* @__PURE__ */ jsx21(
|
|
3032
|
+
FileOperationLineRow,
|
|
3033
|
+
{
|
|
3034
|
+
line,
|
|
3035
|
+
showLineNumbers,
|
|
3036
|
+
lineNumberColumnWidth
|
|
3037
|
+
},
|
|
3038
|
+
readLineKey("row", line, index)
|
|
3039
|
+
)) });
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation.tsx
|
|
3043
|
+
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2845
3044
|
function isPreviewBlock(block) {
|
|
2846
3045
|
return block.display === "preview";
|
|
2847
3046
|
}
|
|
3047
|
+
function readFileOperationContentVersion(block) {
|
|
3048
|
+
if (block.rawText) {
|
|
3049
|
+
return block.rawText;
|
|
3050
|
+
}
|
|
3051
|
+
return block.lines.map(
|
|
3052
|
+
(line) => [
|
|
3053
|
+
line.kind,
|
|
3054
|
+
line.oldLineNumber ?? "",
|
|
3055
|
+
line.newLineNumber ?? "",
|
|
3056
|
+
line.text
|
|
3057
|
+
].join(":")
|
|
3058
|
+
).join("\n");
|
|
3059
|
+
}
|
|
2848
3060
|
function getCaptionTone(part) {
|
|
2849
3061
|
if (/^\+\d+$/.test(part)) {
|
|
2850
3062
|
return "text-emerald-700";
|
|
@@ -2859,54 +3071,39 @@ function renderCaption(caption) {
|
|
|
2859
3071
|
if (parts.length === 0) {
|
|
2860
3072
|
return null;
|
|
2861
3073
|
}
|
|
2862
|
-
return /* @__PURE__ */
|
|
2863
|
-
index > 0 ? /* @__PURE__ */
|
|
2864
|
-
/* @__PURE__ */
|
|
3074
|
+
return /* @__PURE__ */ jsx22("div", { className: "flex shrink-0 items-center gap-x-1 whitespace-nowrap text-[10px] font-medium uppercase tracking-[0.08em]", children: parts.map((part, index) => /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
3075
|
+
index > 0 ? /* @__PURE__ */ jsx22("span", { className: "text-stone-300", children: "\xB7" }) : null,
|
|
3076
|
+
/* @__PURE__ */ jsx22("span", { className: cn(getCaptionTone(part)), children: part })
|
|
2865
3077
|
] }, `${part}-${index}`)) });
|
|
2866
3078
|
}
|
|
2867
|
-
function
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
},
|
|
2885
|
-
`preview-gutter-${index}-${line.oldLineNumber ?? "x"}-${line.newLineNumber ?? "x"}`
|
|
2886
|
-
);
|
|
2887
|
-
}
|
|
2888
|
-
function renderDiffCodeRow(line, index) {
|
|
2889
|
-
const rowTone = line.kind === "add" ? "border-l-2 border-emerald-300 bg-emerald-50 text-emerald-950" : line.kind === "remove" ? "border-l-2 border-rose-300 bg-rose-50 text-rose-950" : "border-l-2 border-transparent text-amber-950/80";
|
|
2890
|
-
return /* @__PURE__ */ jsx21(
|
|
3079
|
+
function StickyFileOperationScrollArea({
|
|
3080
|
+
children,
|
|
3081
|
+
contentVersion,
|
|
3082
|
+
resetKey,
|
|
3083
|
+
className,
|
|
3084
|
+
scrollKind
|
|
3085
|
+
}) {
|
|
3086
|
+
const scrollRef = useRef7(null);
|
|
3087
|
+
const { onScroll } = useStickyBottomScroll({
|
|
3088
|
+
scrollRef,
|
|
3089
|
+
resetKey,
|
|
3090
|
+
isLoading: false,
|
|
3091
|
+
hasContent: true,
|
|
3092
|
+
contentVersion,
|
|
3093
|
+
stickyThresholdPx: 20
|
|
3094
|
+
});
|
|
3095
|
+
return /* @__PURE__ */ jsx22(
|
|
2891
3096
|
"div",
|
|
2892
3097
|
{
|
|
3098
|
+
ref: scrollRef,
|
|
3099
|
+
onScroll,
|
|
3100
|
+
"data-file-scroll-kind": scrollKind,
|
|
2893
3101
|
className: cn(
|
|
2894
|
-
"
|
|
2895
|
-
|
|
3102
|
+
"overflow-y-auto overscroll-contain bg-white custom-scrollbar-amber",
|
|
3103
|
+
className
|
|
2896
3104
|
),
|
|
2897
|
-
children
|
|
2898
|
-
}
|
|
2899
|
-
`diff-code-${index}-${line.oldLineNumber ?? "x"}-${line.newLineNumber ?? "x"}`
|
|
2900
|
-
);
|
|
2901
|
-
}
|
|
2902
|
-
function renderPreviewCodeRow(line, index) {
|
|
2903
|
-
return /* @__PURE__ */ jsx21(
|
|
2904
|
-
"div",
|
|
2905
|
-
{
|
|
2906
|
-
className: "min-w-full whitespace-pre px-3 py-1.5 font-mono text-[11px] leading-relaxed text-amber-950/85",
|
|
2907
|
-
children: line.text || " "
|
|
2908
|
-
},
|
|
2909
|
-
`preview-code-${index}-${line.oldLineNumber ?? "x"}-${line.newLineNumber ?? "x"}`
|
|
3105
|
+
children
|
|
3106
|
+
}
|
|
2910
3107
|
);
|
|
2911
3108
|
}
|
|
2912
3109
|
function FileOperationBlock({
|
|
@@ -2917,45 +3114,67 @@ function FileOperationBlock({
|
|
|
2917
3114
|
const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;
|
|
2918
3115
|
const previewBlock = isPreviewBlock(block);
|
|
2919
3116
|
const showMetaRow = showPathRow || Boolean(block.caption);
|
|
2920
|
-
return /* @__PURE__ */
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
3117
|
+
return /* @__PURE__ */ jsxs14(
|
|
3118
|
+
"section",
|
|
3119
|
+
{
|
|
3120
|
+
className: cn(
|
|
3121
|
+
"overflow-hidden bg-white",
|
|
3122
|
+
!isFirst && "border-t border-stone-200/80"
|
|
3123
|
+
),
|
|
3124
|
+
children: [
|
|
3125
|
+
showMetaRow ? /* @__PURE__ */ jsxs14(
|
|
3126
|
+
"div",
|
|
3127
|
+
{
|
|
3128
|
+
className: cn(
|
|
3129
|
+
"flex items-center justify-between gap-4 border-b border-stone-200/80 px-4 text-stone-700",
|
|
3130
|
+
showPathRow ? "py-2" : "py-1.5"
|
|
3131
|
+
),
|
|
3132
|
+
children: [
|
|
3133
|
+
/* @__PURE__ */ jsx22("div", { className: "min-w-0 flex-1", children: showPathRow ? /* @__PURE__ */ jsx22(TooltipProvider, { delayDuration: 250, children: /* @__PURE__ */ jsxs14(Tooltip, { children: [
|
|
3134
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3135
|
+
"div",
|
|
3136
|
+
{
|
|
3137
|
+
className: "truncate whitespace-nowrap font-mono text-[12px] font-medium text-stone-700",
|
|
3138
|
+
title: block.path,
|
|
3139
|
+
children: block.path
|
|
3140
|
+
}
|
|
3141
|
+
) }),
|
|
3142
|
+
/* @__PURE__ */ jsx22(
|
|
3143
|
+
TooltipContent,
|
|
3144
|
+
{
|
|
3145
|
+
side: "top",
|
|
3146
|
+
className: "max-w-[420px] text-xs font-mono break-all",
|
|
3147
|
+
children: block.path
|
|
3148
|
+
}
|
|
3149
|
+
)
|
|
3150
|
+
] }) }) : null }),
|
|
3151
|
+
block.caption ? renderCaption(block.caption) : null
|
|
3152
|
+
]
|
|
3153
|
+
}
|
|
3154
|
+
) : null,
|
|
3155
|
+
block.lines.length > 0 ? /* @__PURE__ */ jsx22(
|
|
3156
|
+
StickyFileOperationScrollArea,
|
|
3157
|
+
{
|
|
3158
|
+
resetKey: `block:${block.key}`,
|
|
3159
|
+
contentVersion: readFileOperationContentVersion(block),
|
|
3160
|
+
className: "max-h-72",
|
|
3161
|
+
scrollKind: "block",
|
|
3162
|
+
children: /* @__PURE__ */ jsx22(FileOperationLinesGrid, { block })
|
|
3163
|
+
}
|
|
3164
|
+
) : block.rawText ? /* @__PURE__ */ jsx22(
|
|
3165
|
+
StickyFileOperationScrollArea,
|
|
3166
|
+
{
|
|
3167
|
+
resetKey: `raw:${block.key}`,
|
|
3168
|
+
contentVersion: block.rawText,
|
|
3169
|
+
className: "max-h-72",
|
|
3170
|
+
scrollKind: "raw",
|
|
3171
|
+
children: /* @__PURE__ */ jsx22("div", { className: "overflow-x-auto custom-scrollbar-amber", children: /* @__PURE__ */ jsx22("pre", { className: "min-w-max whitespace-pre bg-white px-4 py-2 font-mono text-[11px] leading-5 text-amber-950/80", children: block.rawText }) })
|
|
3172
|
+
}
|
|
3173
|
+
) : null,
|
|
3174
|
+
block.truncated && !previewBlock ? /* @__PURE__ */ jsx22("div", { className: "border-t border-stone-200/85 bg-stone-50 px-4 py-2 text-[10px] text-stone-500", children: "Showing a shortened diff preview." }) : null
|
|
3175
|
+
]
|
|
3176
|
+
}
|
|
3177
|
+
);
|
|
2959
3178
|
}
|
|
2960
3179
|
function ToolCardFileOperationContent({
|
|
2961
3180
|
card,
|
|
@@ -2966,9 +3185,9 @@ function ToolCardFileOperationContent({
|
|
|
2966
3185
|
if (blocks.length === 0 && !output) {
|
|
2967
3186
|
return null;
|
|
2968
3187
|
}
|
|
2969
|
-
return /* @__PURE__ */
|
|
3188
|
+
return /* @__PURE__ */ jsxs14("div", { className: cn("overflow-hidden bg-white", className), children: [
|
|
2970
3189
|
blocks.map((block, index) => {
|
|
2971
|
-
return /* @__PURE__ */
|
|
3190
|
+
return /* @__PURE__ */ jsx22(
|
|
2972
3191
|
FileOperationBlock,
|
|
2973
3192
|
{
|
|
2974
3193
|
block,
|
|
@@ -2978,15 +3197,24 @@ function ToolCardFileOperationContent({
|
|
|
2978
3197
|
block.key
|
|
2979
3198
|
);
|
|
2980
3199
|
}),
|
|
2981
|
-
output ? /* @__PURE__ */
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
3200
|
+
output ? /* @__PURE__ */ jsx22(
|
|
3201
|
+
StickyFileOperationScrollArea,
|
|
3202
|
+
{
|
|
3203
|
+
resetKey: `output:${card.toolName}:${card.summary ?? "none"}`,
|
|
3204
|
+
contentVersion: output,
|
|
3205
|
+
className: cn(
|
|
3206
|
+
"max-h-56",
|
|
3207
|
+
blocks.length > 0 && "border-t border-stone-200/80"
|
|
3208
|
+
),
|
|
3209
|
+
scrollKind: "output",
|
|
3210
|
+
children: /* @__PURE__ */ jsx22("div", { className: "overflow-x-auto custom-scrollbar-amber", children: /* @__PURE__ */ jsx22("pre", { className: "min-w-max whitespace-pre bg-white px-4 py-2 font-mono text-[11px] leading-5 text-amber-950/80", children: output }) })
|
|
3211
|
+
}
|
|
3212
|
+
) : null
|
|
2985
3213
|
] });
|
|
2986
3214
|
}
|
|
2987
3215
|
|
|
2988
3216
|
// src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx
|
|
2989
|
-
import { Fragment as Fragment5, jsx as
|
|
3217
|
+
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2990
3218
|
var TOOL_CARD_AUTO_EXPAND_DELAY_MS = 200;
|
|
2991
3219
|
var ANSI_ESCAPE_PREFIX = String.fromCharCode(27);
|
|
2992
3220
|
var ANSI_ESCAPE_PATTERN = new RegExp(`${ANSI_ESCAPE_PREFIX}\\[[0-?]*[ -/]*[@-~]`, "g");
|
|
@@ -3060,17 +3288,17 @@ function useToolCardExpandedState({
|
|
|
3060
3288
|
}) {
|
|
3061
3289
|
const [expanded, setExpanded] = useState7(false);
|
|
3062
3290
|
const [hasUserToggled, setHasUserToggled] = useState7(false);
|
|
3063
|
-
const expandTimerRef =
|
|
3064
|
-
const prevRunningRef =
|
|
3065
|
-
const isFirstRenderRef =
|
|
3066
|
-
|
|
3291
|
+
const expandTimerRef = useRef8(null);
|
|
3292
|
+
const prevRunningRef = useRef8(isRunning);
|
|
3293
|
+
const isFirstRenderRef = useRef8(true);
|
|
3294
|
+
useEffect8(() => {
|
|
3067
3295
|
return () => {
|
|
3068
3296
|
if (expandTimerRef.current !== null) {
|
|
3069
3297
|
window.clearTimeout(expandTimerRef.current);
|
|
3070
3298
|
}
|
|
3071
3299
|
};
|
|
3072
3300
|
}, []);
|
|
3073
|
-
|
|
3301
|
+
useEffect8(() => {
|
|
3074
3302
|
if (expandOnError && statusTone === "error" && canExpand && !hasUserToggled) {
|
|
3075
3303
|
if (expandTimerRef.current !== null) {
|
|
3076
3304
|
window.clearTimeout(expandTimerRef.current);
|
|
@@ -3138,7 +3366,7 @@ function GenericToolSection({
|
|
|
3138
3366
|
}
|
|
3139
3367
|
};
|
|
3140
3368
|
const style = tones[tone];
|
|
3141
|
-
return /* @__PURE__ */
|
|
3369
|
+
return /* @__PURE__ */ jsxs15(
|
|
3142
3370
|
"section",
|
|
3143
3371
|
{
|
|
3144
3372
|
className: cn(
|
|
@@ -3146,7 +3374,7 @@ function GenericToolSection({
|
|
|
3146
3374
|
style.shell
|
|
3147
3375
|
),
|
|
3148
3376
|
children: [
|
|
3149
|
-
/* @__PURE__ */
|
|
3377
|
+
/* @__PURE__ */ jsxs15(
|
|
3150
3378
|
"div",
|
|
3151
3379
|
{
|
|
3152
3380
|
className: cn(
|
|
@@ -3154,12 +3382,12 @@ function GenericToolSection({
|
|
|
3154
3382
|
style.header
|
|
3155
3383
|
),
|
|
3156
3384
|
children: [
|
|
3157
|
-
/* @__PURE__ */
|
|
3158
|
-
/* @__PURE__ */
|
|
3385
|
+
/* @__PURE__ */ jsx23("span", { className: cn("h-1.5 w-1.5 rounded-full", style.dot) }),
|
|
3386
|
+
/* @__PURE__ */ jsx23("span", { children: label })
|
|
3159
3387
|
]
|
|
3160
3388
|
}
|
|
3161
3389
|
),
|
|
3162
|
-
/* @__PURE__ */
|
|
3390
|
+
/* @__PURE__ */ jsx23("div", { className: "w-full overflow-hidden", children: /* @__PURE__ */ jsx23(
|
|
3163
3391
|
"pre",
|
|
3164
3392
|
{
|
|
3165
3393
|
className: cn(
|
|
@@ -3184,8 +3412,8 @@ function TerminalExecutionView({ card }) {
|
|
|
3184
3412
|
statusTone: card.statusTone
|
|
3185
3413
|
});
|
|
3186
3414
|
const commandPart = card.summary?.replace(/^(command|path|args|query|input):\s*/i, "");
|
|
3187
|
-
return /* @__PURE__ */
|
|
3188
|
-
/* @__PURE__ */
|
|
3415
|
+
return /* @__PURE__ */ jsxs15(ToolCardRoot, { children: [
|
|
3416
|
+
/* @__PURE__ */ jsx23(
|
|
3189
3417
|
ToolCardHeader,
|
|
3190
3418
|
{
|
|
3191
3419
|
card,
|
|
@@ -3195,17 +3423,17 @@ function TerminalExecutionView({ card }) {
|
|
|
3195
3423
|
onToggle
|
|
3196
3424
|
}
|
|
3197
3425
|
),
|
|
3198
|
-
expanded && /* @__PURE__ */
|
|
3199
|
-
/* @__PURE__ */
|
|
3200
|
-
/* @__PURE__ */
|
|
3201
|
-
/* @__PURE__ */
|
|
3426
|
+
expanded && /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
3427
|
+
/* @__PURE__ */ jsx23("div", { className: "px-3 pb-2 font-mono w-full max-h-48 overflow-y-auto custom-scrollbar-amber min-h-0 text-[12px]", children: /* @__PURE__ */ jsxs15("div", { className: "flex items-start gap-2 leading-relaxed", children: [
|
|
3428
|
+
/* @__PURE__ */ jsx23("span", { className: "text-amber-500/50 font-medium shrink-0 select-none mt-[1px]", children: "$" }),
|
|
3429
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 min-w-0", children: commandPart ? /* @__PURE__ */ jsxs15("div", { className: "text-amber-950/80 break-words whitespace-pre-wrap tracking-tight font-medium inline-block", children: [
|
|
3202
3430
|
commandPart,
|
|
3203
|
-
isRunning && !output && /* @__PURE__ */
|
|
3204
|
-
] }) : /* @__PURE__ */
|
|
3431
|
+
isRunning && !output && /* @__PURE__ */ jsx23("span", { className: "inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle" })
|
|
3432
|
+
] }) : /* @__PURE__ */ jsx23("div", { className: "h-3 w-32 bg-amber-200/30 rounded animate-pulse mt-2" }) })
|
|
3205
3433
|
] }) }),
|
|
3206
|
-
output && /* @__PURE__ */
|
|
3434
|
+
output && /* @__PURE__ */ jsx23(ToolCardContent, { children: /* @__PURE__ */ jsxs15("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 px-0", children: [
|
|
3207
3435
|
output,
|
|
3208
|
-
isRunning && /* @__PURE__ */
|
|
3436
|
+
isRunning && /* @__PURE__ */ jsx23("span", { className: "inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle" })
|
|
3209
3437
|
] }) })
|
|
3210
3438
|
] })
|
|
3211
3439
|
] });
|
|
@@ -3232,8 +3460,8 @@ function FileOperationView({ card }) {
|
|
|
3232
3460
|
statusTone: card.statusTone
|
|
3233
3461
|
});
|
|
3234
3462
|
const isEdit = card.toolName === "edit_file" || card.toolName === "write_file" || card.toolName === "apply_patch" || card.toolName === "file_change";
|
|
3235
|
-
return /* @__PURE__ */
|
|
3236
|
-
/* @__PURE__ */
|
|
3463
|
+
return /* @__PURE__ */ jsxs15(ToolCardRoot, { children: [
|
|
3464
|
+
/* @__PURE__ */ jsx23(
|
|
3237
3465
|
ToolCardHeader,
|
|
3238
3466
|
{
|
|
3239
3467
|
card,
|
|
@@ -3244,7 +3472,7 @@ function FileOperationView({ card }) {
|
|
|
3244
3472
|
onToggle
|
|
3245
3473
|
}
|
|
3246
3474
|
),
|
|
3247
|
-
expanded && hasContent && /* @__PURE__ */
|
|
3475
|
+
expanded && hasContent && /* @__PURE__ */ jsx23(ToolCardContent, { className: "border-t border-amber-200/20 bg-transparent px-0 pt-0 pb-0", children: /* @__PURE__ */ jsx23(ToolCardFileOperationContent, { card }) })
|
|
3248
3476
|
] });
|
|
3249
3477
|
}
|
|
3250
3478
|
function SearchSnippetView({ card }) {
|
|
@@ -3255,8 +3483,8 @@ function SearchSnippetView({ card }) {
|
|
|
3255
3483
|
isRunning,
|
|
3256
3484
|
statusTone: card.statusTone
|
|
3257
3485
|
});
|
|
3258
|
-
return /* @__PURE__ */
|
|
3259
|
-
/* @__PURE__ */
|
|
3486
|
+
return /* @__PURE__ */ jsxs15(ToolCardRoot, { children: [
|
|
3487
|
+
/* @__PURE__ */ jsx23(
|
|
3260
3488
|
ToolCardHeader,
|
|
3261
3489
|
{
|
|
3262
3490
|
card,
|
|
@@ -3266,7 +3494,7 @@ function SearchSnippetView({ card }) {
|
|
|
3266
3494
|
onToggle
|
|
3267
3495
|
}
|
|
3268
3496
|
),
|
|
3269
|
-
expanded && output && /* @__PURE__ */
|
|
3497
|
+
expanded && output && /* @__PURE__ */ jsx23(ToolCardContent, { children: /* @__PURE__ */ jsx23("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: output }) })
|
|
3270
3498
|
] });
|
|
3271
3499
|
}
|
|
3272
3500
|
function GenericToolCard({ card }) {
|
|
@@ -3283,8 +3511,8 @@ function GenericToolCard({ card }) {
|
|
|
3283
3511
|
isRunning,
|
|
3284
3512
|
statusTone: card.statusTone
|
|
3285
3513
|
});
|
|
3286
|
-
return /* @__PURE__ */
|
|
3287
|
-
/* @__PURE__ */
|
|
3514
|
+
return /* @__PURE__ */ jsxs15(ToolCardRoot, { children: [
|
|
3515
|
+
/* @__PURE__ */ jsx23(
|
|
3288
3516
|
ToolCardHeader,
|
|
3289
3517
|
{
|
|
3290
3518
|
card,
|
|
@@ -3294,10 +3522,10 @@ function GenericToolCard({ card }) {
|
|
|
3294
3522
|
onToggle
|
|
3295
3523
|
}
|
|
3296
3524
|
),
|
|
3297
|
-
expanded && hasContent && /* @__PURE__ */
|
|
3298
|
-
hasInputSection && /* @__PURE__ */
|
|
3299
|
-
hasInputSection && hasOutputSection && /* @__PURE__ */
|
|
3300
|
-
hasOutputSection && /* @__PURE__ */
|
|
3525
|
+
expanded && hasContent && /* @__PURE__ */ jsxs15(ToolCardContent, { className: "bg-transparent px-2.5 py-2.5", children: [
|
|
3526
|
+
hasInputSection && /* @__PURE__ */ jsx23(GenericToolSection, { label: inputLabel, tone: "input", children: input }),
|
|
3527
|
+
hasInputSection && hasOutputSection && /* @__PURE__ */ jsx23("div", { className: "h-2" }),
|
|
3528
|
+
hasOutputSection && /* @__PURE__ */ jsx23(
|
|
3301
3529
|
GenericToolSection,
|
|
3302
3530
|
{
|
|
3303
3531
|
label: outputLabel,
|
|
@@ -3310,7 +3538,7 @@ function GenericToolCard({ card }) {
|
|
|
3310
3538
|
}
|
|
3311
3539
|
|
|
3312
3540
|
// src/components/chat/ui/chat-message-list/chat-tool-card.tsx
|
|
3313
|
-
import { jsx as
|
|
3541
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
3314
3542
|
function isTerminalTool(name) {
|
|
3315
3543
|
const lowered = name.toLowerCase();
|
|
3316
3544
|
return lowered === "exec" || lowered === "exec_command" || lowered === "execute_command" || lowered === "command_execution" || lowered === "bash" || lowered === "shell" || lowered.includes("run_");
|
|
@@ -3325,48 +3553,48 @@ function isSearchTool(name) {
|
|
|
3325
3553
|
}
|
|
3326
3554
|
function ChatToolCard({ card }) {
|
|
3327
3555
|
if (isTerminalTool(card.toolName)) {
|
|
3328
|
-
return /* @__PURE__ */
|
|
3556
|
+
return /* @__PURE__ */ jsx24(TerminalExecutionView, { card });
|
|
3329
3557
|
}
|
|
3330
3558
|
if (isFileEditTool(card.toolName)) {
|
|
3331
|
-
return /* @__PURE__ */
|
|
3559
|
+
return /* @__PURE__ */ jsx24(FileOperationView, { card });
|
|
3332
3560
|
}
|
|
3333
3561
|
if (isSearchTool(card.toolName)) {
|
|
3334
|
-
return /* @__PURE__ */
|
|
3562
|
+
return /* @__PURE__ */ jsx24(SearchSnippetView, { card });
|
|
3335
3563
|
}
|
|
3336
|
-
return /* @__PURE__ */
|
|
3564
|
+
return /* @__PURE__ */ jsx24(GenericToolCard, { card });
|
|
3337
3565
|
}
|
|
3338
3566
|
|
|
3339
3567
|
// src/components/chat/ui/chat-message-list/chat-unknown-part.tsx
|
|
3340
|
-
import { jsx as
|
|
3568
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3341
3569
|
function ChatUnknownPart(props) {
|
|
3342
|
-
return /* @__PURE__ */
|
|
3343
|
-
/* @__PURE__ */
|
|
3570
|
+
return /* @__PURE__ */ jsxs16("div", { className: "rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600", children: [
|
|
3571
|
+
/* @__PURE__ */ jsxs16("div", { className: "font-semibold text-gray-700", children: [
|
|
3344
3572
|
props.label,
|
|
3345
3573
|
": ",
|
|
3346
3574
|
props.rawType
|
|
3347
3575
|
] }),
|
|
3348
|
-
props.text ? /* @__PURE__ */
|
|
3576
|
+
props.text ? /* @__PURE__ */ jsx25("pre", { className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500", children: props.text }) : null
|
|
3349
3577
|
] });
|
|
3350
3578
|
}
|
|
3351
3579
|
|
|
3352
3580
|
// src/components/chat/ui/chat-message-list/chat-message.tsx
|
|
3353
|
-
import { jsx as
|
|
3581
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
3354
3582
|
var ChatMessage = memo(function ChatMessage2(props) {
|
|
3355
3583
|
const { message, texts } = props;
|
|
3356
3584
|
const { role } = message;
|
|
3357
3585
|
const isUser = role === "user";
|
|
3358
3586
|
const isMessageInProgress = message.status === "pending" || message.status === "streaming";
|
|
3359
|
-
return /* @__PURE__ */
|
|
3587
|
+
return /* @__PURE__ */ jsx26(
|
|
3360
3588
|
"div",
|
|
3361
3589
|
{
|
|
3362
3590
|
className: cn(
|
|
3363
3591
|
"inline-block w-fit max-w-full rounded-2xl border px-4 shadow-sm",
|
|
3364
3592
|
isUser ? "border-primary bg-primary py-3 text-white" : role === "assistant" ? "border-gray-200 bg-white pb-3 pt-4 text-gray-900" : "border-orange-200/80 bg-orange-50/70 py-3 text-gray-900"
|
|
3365
3593
|
),
|
|
3366
|
-
children: /* @__PURE__ */
|
|
3594
|
+
children: /* @__PURE__ */ jsx26("div", { className: "space-y-2", children: message.parts.map((part, index) => {
|
|
3367
3595
|
const { type } = part;
|
|
3368
3596
|
if (type === "markdown") {
|
|
3369
|
-
return /* @__PURE__ */
|
|
3597
|
+
return /* @__PURE__ */ jsx26(
|
|
3370
3598
|
ChatMessageMarkdown,
|
|
3371
3599
|
{
|
|
3372
3600
|
text: part.text,
|
|
@@ -3377,7 +3605,7 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3377
3605
|
);
|
|
3378
3606
|
}
|
|
3379
3607
|
if (type === "inline-content") {
|
|
3380
|
-
return /* @__PURE__ */
|
|
3608
|
+
return /* @__PURE__ */ jsx26(
|
|
3381
3609
|
ChatMessageInlineContent,
|
|
3382
3610
|
{
|
|
3383
3611
|
segments: part.segments,
|
|
@@ -3388,7 +3616,7 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3388
3616
|
);
|
|
3389
3617
|
}
|
|
3390
3618
|
if (type === "reasoning") {
|
|
3391
|
-
return /* @__PURE__ */
|
|
3619
|
+
return /* @__PURE__ */ jsx26(
|
|
3392
3620
|
ChatReasoningBlock,
|
|
3393
3621
|
{
|
|
3394
3622
|
label: part.label,
|
|
@@ -3400,10 +3628,10 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3400
3628
|
);
|
|
3401
3629
|
}
|
|
3402
3630
|
if (type === "tool-card") {
|
|
3403
|
-
return /* @__PURE__ */
|
|
3631
|
+
return /* @__PURE__ */ jsx26("div", { className: "mt-0.5", children: /* @__PURE__ */ jsx26(ChatToolCard, { card: part.card }) }, `tool-${index}`);
|
|
3404
3632
|
}
|
|
3405
3633
|
if (type === "file") {
|
|
3406
|
-
return /* @__PURE__ */
|
|
3634
|
+
return /* @__PURE__ */ jsx26(
|
|
3407
3635
|
ChatMessageFile,
|
|
3408
3636
|
{
|
|
3409
3637
|
file: part.file,
|
|
@@ -3413,7 +3641,7 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3413
3641
|
);
|
|
3414
3642
|
}
|
|
3415
3643
|
if (type === "unknown") {
|
|
3416
|
-
return /* @__PURE__ */
|
|
3644
|
+
return /* @__PURE__ */ jsx26(
|
|
3417
3645
|
ChatUnknownPart,
|
|
3418
3646
|
{
|
|
3419
3647
|
label: part.label,
|
|
@@ -3430,9 +3658,9 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3430
3658
|
});
|
|
3431
3659
|
|
|
3432
3660
|
// src/components/chat/ui/chat-message-list/chat-message-meta.tsx
|
|
3433
|
-
import { jsxs as
|
|
3661
|
+
import { jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3434
3662
|
function ChatMessageMeta(props) {
|
|
3435
|
-
return /* @__PURE__ */
|
|
3663
|
+
return /* @__PURE__ */ jsxs17(
|
|
3436
3664
|
"div",
|
|
3437
3665
|
{
|
|
3438
3666
|
className: cn(
|
|
@@ -3451,7 +3679,7 @@ function ChatMessageMeta(props) {
|
|
|
3451
3679
|
// src/components/chat/ui/chat-message-list/chat-message-action-copy.tsx
|
|
3452
3680
|
import { useMemo as useMemo6 } from "react";
|
|
3453
3681
|
import { Check as Check5, Copy as Copy2 } from "lucide-react";
|
|
3454
|
-
import { jsx as
|
|
3682
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
3455
3683
|
function ChatMessageActionCopy({
|
|
3456
3684
|
message,
|
|
3457
3685
|
texts
|
|
@@ -3465,7 +3693,7 @@ function ChatMessageActionCopy({
|
|
|
3465
3693
|
}, [message.parts]);
|
|
3466
3694
|
const { copied, copy } = useCopyFeedback({ text: messageText });
|
|
3467
3695
|
if (!messageText) return null;
|
|
3468
|
-
return /* @__PURE__ */
|
|
3696
|
+
return /* @__PURE__ */ jsx27(
|
|
3469
3697
|
"button",
|
|
3470
3698
|
{
|
|
3471
3699
|
type: "button",
|
|
@@ -3473,13 +3701,13 @@ function ChatMessageActionCopy({
|
|
|
3473
3701
|
className: "text-gray-400 hover:text-gray-600 transition-colors p-1 rounded-md hover:bg-gray-100 flex items-center justify-center",
|
|
3474
3702
|
"aria-label": copied ? texts.copiedMessageLabel : texts.copyMessageLabel,
|
|
3475
3703
|
title: copied ? texts.copiedMessageLabel : texts.copyMessageLabel,
|
|
3476
|
-
children: copied ? /* @__PURE__ */
|
|
3704
|
+
children: copied ? /* @__PURE__ */ jsx27(Check5, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx27(Copy2, { className: "h-3.5 w-3.5" })
|
|
3477
3705
|
}
|
|
3478
3706
|
);
|
|
3479
3707
|
}
|
|
3480
3708
|
|
|
3481
3709
|
// src/components/chat/ui/chat-message-list/chat-message-list.tsx
|
|
3482
|
-
import { Fragment as Fragment6, jsx as
|
|
3710
|
+
import { Fragment as Fragment6, jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3483
3711
|
var INVISIBLE_ONLY_TEXT_PATTERN = /\u200B|\u200C|\u200D|\u2060|\uFEFF/g;
|
|
3484
3712
|
function hasRenderableText(value) {
|
|
3485
3713
|
const trimmed = value.trim();
|
|
@@ -3497,10 +3725,10 @@ function hasRenderableMessageContent(message) {
|
|
|
3497
3725
|
});
|
|
3498
3726
|
}
|
|
3499
3727
|
function ChatMessageTypingFooter() {
|
|
3500
|
-
return /* @__PURE__ */
|
|
3501
|
-
/* @__PURE__ */
|
|
3502
|
-
/* @__PURE__ */
|
|
3503
|
-
/* @__PURE__ */
|
|
3728
|
+
return /* @__PURE__ */ jsx28("div", { className: "flex items-center gap-2 px-1 py-0.5 text-[11px] text-gray-400", children: /* @__PURE__ */ jsxs18("div", { className: "flex space-x-1 items-center h-full", children: [
|
|
3729
|
+
/* @__PURE__ */ jsx28("div", { className: "h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse" }),
|
|
3730
|
+
/* @__PURE__ */ jsx28("div", { className: "h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:200ms]" }),
|
|
3731
|
+
/* @__PURE__ */ jsx28("div", { className: "h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:400ms]" })
|
|
3504
3732
|
] }) });
|
|
3505
3733
|
}
|
|
3506
3734
|
function ChatMessageList(props) {
|
|
@@ -3508,118 +3736,28 @@ function ChatMessageList(props) {
|
|
|
3508
3736
|
const hasRenderableAssistantDraft = visibleMessages.some(
|
|
3509
3737
|
(message) => message.role === "assistant" && (message.status === "streaming" || message.status === "pending")
|
|
3510
3738
|
);
|
|
3511
|
-
return /* @__PURE__ */
|
|
3739
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("space-y-5", props.className), children: [
|
|
3512
3740
|
visibleMessages.map((message) => {
|
|
3513
3741
|
const isUser = message.role === "user";
|
|
3514
3742
|
const isGenerating = !isUser && (message.status === "streaming" || message.status === "pending");
|
|
3515
|
-
return /* @__PURE__ */
|
|
3516
|
-
!isUser ? /* @__PURE__ */
|
|
3517
|
-
/* @__PURE__ */
|
|
3518
|
-
/* @__PURE__ */
|
|
3519
|
-
/* @__PURE__ */
|
|
3520
|
-
/* @__PURE__ */
|
|
3521
|
-
!isUser ? /* @__PURE__ */
|
|
3743
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("flex gap-3", isUser ? "justify-end" : "justify-start"), children: [
|
|
3744
|
+
!isUser ? /* @__PURE__ */ jsx28(ChatMessageAvatar, { role: message.role }) : null,
|
|
3745
|
+
/* @__PURE__ */ jsxs18("div", { className: cn("w-fit max-w-[92%] space-y-2", isUser && "flex flex-col items-end"), children: [
|
|
3746
|
+
/* @__PURE__ */ jsx28(ChatMessage, { message, texts: props.texts }),
|
|
3747
|
+
/* @__PURE__ */ jsx28("div", { className: cn("flex items-center gap-2", isUser && "justify-end"), children: isGenerating ? /* @__PURE__ */ jsx28(ChatMessageTypingFooter, {}) : /* @__PURE__ */ jsxs18(Fragment6, { children: [
|
|
3748
|
+
/* @__PURE__ */ jsx28(ChatMessageMeta, { roleLabel: message.roleLabel, timestampLabel: message.timestampLabel, isUser }),
|
|
3749
|
+
!isUser ? /* @__PURE__ */ jsx28(ChatMessageActionCopy, { message, texts: props.texts }) : null
|
|
3522
3750
|
] }) })
|
|
3523
3751
|
] }),
|
|
3524
|
-
isUser ? /* @__PURE__ */
|
|
3752
|
+
isUser ? /* @__PURE__ */ jsx28(ChatMessageAvatar, { role: message.role }) : null
|
|
3525
3753
|
] }, message.id);
|
|
3526
3754
|
}),
|
|
3527
|
-
props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */
|
|
3528
|
-
/* @__PURE__ */
|
|
3529
|
-
/* @__PURE__ */
|
|
3755
|
+
props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */ jsxs18("div", { className: "flex justify-start gap-3", children: [
|
|
3756
|
+
/* @__PURE__ */ jsx28(ChatMessageAvatar, { role: "assistant" }),
|
|
3757
|
+
/* @__PURE__ */ jsx28("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 })
|
|
3530
3758
|
] }) : null
|
|
3531
3759
|
] });
|
|
3532
3760
|
}
|
|
3533
|
-
|
|
3534
|
-
// src/components/chat/hooks/use-sticky-bottom-scroll.ts
|
|
3535
|
-
import { useEffect as useEffect8, useLayoutEffect as useLayoutEffect2, useRef as useRef7 } from "react";
|
|
3536
|
-
var DEFAULT_STICKY_THRESHOLD_PX = 10;
|
|
3537
|
-
function scrollElementToBottom(element) {
|
|
3538
|
-
element.scrollTop = element.scrollHeight;
|
|
3539
|
-
}
|
|
3540
|
-
function queueScrollToBottom(params) {
|
|
3541
|
-
const element = params.scrollRef.current;
|
|
3542
|
-
if (!element) {
|
|
3543
|
-
return;
|
|
3544
|
-
}
|
|
3545
|
-
if (params.scheduledScrollFrameRef.current !== null) {
|
|
3546
|
-
cancelAnimationFrame(params.scheduledScrollFrameRef.current);
|
|
3547
|
-
}
|
|
3548
|
-
params.scheduledScrollFrameRef.current = requestAnimationFrame(() => {
|
|
3549
|
-
params.scheduledScrollFrameRef.current = null;
|
|
3550
|
-
const currentElement = params.scrollRef.current;
|
|
3551
|
-
if (!currentElement) {
|
|
3552
|
-
return;
|
|
3553
|
-
}
|
|
3554
|
-
params.isProgrammaticScrollRef.current = true;
|
|
3555
|
-
scrollElementToBottom(currentElement);
|
|
3556
|
-
});
|
|
3557
|
-
}
|
|
3558
|
-
function useStickyBottomScroll(params) {
|
|
3559
|
-
const isStickyRef = useRef7(true);
|
|
3560
|
-
const isProgrammaticScrollRef = useRef7(false);
|
|
3561
|
-
const previousResetKeyRef = useRef7(null);
|
|
3562
|
-
const pendingInitialScrollRef = useRef7(false);
|
|
3563
|
-
const scheduledScrollFrameRef = useRef7(null);
|
|
3564
|
-
const onScroll = () => {
|
|
3565
|
-
if (isProgrammaticScrollRef.current) {
|
|
3566
|
-
isProgrammaticScrollRef.current = false;
|
|
3567
|
-
return;
|
|
3568
|
-
}
|
|
3569
|
-
const element = params.scrollRef.current;
|
|
3570
|
-
if (!element) {
|
|
3571
|
-
return;
|
|
3572
|
-
}
|
|
3573
|
-
const distanceFromBottom = element.scrollHeight - element.scrollTop - element.clientHeight;
|
|
3574
|
-
isStickyRef.current = distanceFromBottom <= (params.stickyThresholdPx ?? DEFAULT_STICKY_THRESHOLD_PX);
|
|
3575
|
-
};
|
|
3576
|
-
useEffect8(() => {
|
|
3577
|
-
if (previousResetKeyRef.current === params.resetKey) {
|
|
3578
|
-
return;
|
|
3579
|
-
}
|
|
3580
|
-
previousResetKeyRef.current = params.resetKey;
|
|
3581
|
-
isStickyRef.current = true;
|
|
3582
|
-
pendingInitialScrollRef.current = true;
|
|
3583
|
-
}, [params.resetKey]);
|
|
3584
|
-
useEffect8(() => {
|
|
3585
|
-
const scheduledScrollFrame = scheduledScrollFrameRef.current;
|
|
3586
|
-
return () => {
|
|
3587
|
-
if (scheduledScrollFrame !== null) {
|
|
3588
|
-
cancelAnimationFrame(scheduledScrollFrame);
|
|
3589
|
-
}
|
|
3590
|
-
};
|
|
3591
|
-
}, []);
|
|
3592
|
-
useLayoutEffect2(() => {
|
|
3593
|
-
if (!pendingInitialScrollRef.current || params.isLoading || !params.hasContent) {
|
|
3594
|
-
return;
|
|
3595
|
-
}
|
|
3596
|
-
const element = params.scrollRef.current;
|
|
3597
|
-
if (!element) {
|
|
3598
|
-
return;
|
|
3599
|
-
}
|
|
3600
|
-
pendingInitialScrollRef.current = false;
|
|
3601
|
-
queueScrollToBottom({
|
|
3602
|
-
scrollRef: params.scrollRef,
|
|
3603
|
-
scheduledScrollFrameRef,
|
|
3604
|
-
isProgrammaticScrollRef
|
|
3605
|
-
});
|
|
3606
|
-
}, [params.hasContent, params.isLoading, params.scrollRef]);
|
|
3607
|
-
useLayoutEffect2(() => {
|
|
3608
|
-
if (!isStickyRef.current || !params.hasContent) {
|
|
3609
|
-
return;
|
|
3610
|
-
}
|
|
3611
|
-
const element = params.scrollRef.current;
|
|
3612
|
-
if (!element) {
|
|
3613
|
-
return;
|
|
3614
|
-
}
|
|
3615
|
-
queueScrollToBottom({
|
|
3616
|
-
scrollRef: params.scrollRef,
|
|
3617
|
-
scheduledScrollFrameRef,
|
|
3618
|
-
isProgrammaticScrollRef
|
|
3619
|
-
});
|
|
3620
|
-
}, [params.contentVersion, params.hasContent, params.scrollRef]);
|
|
3621
|
-
return { onScroll };
|
|
3622
|
-
}
|
|
3623
3761
|
export {
|
|
3624
3762
|
ChatInputBar,
|
|
3625
3763
|
ChatMessageList,
|