@nextclaw/agent-chat-ui 0.2.18 → 0.2.19
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.d.ts +22 -1
- package/dist/index.js +455 -149
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -151,17 +151,38 @@ type ChatInputBarProps = {
|
|
|
151
151
|
toolbar: ChatInputBarToolbarProps;
|
|
152
152
|
};
|
|
153
153
|
type ChatMessageRole = "user" | "assistant" | "tool" | "system" | "message";
|
|
154
|
+
type ChatFileOperationLineViewModel = {
|
|
155
|
+
kind: "context" | "add" | "remove";
|
|
156
|
+
text: string;
|
|
157
|
+
oldLineNumber?: number;
|
|
158
|
+
newLineNumber?: number;
|
|
159
|
+
};
|
|
160
|
+
type ChatFileOperationBlockViewModel = {
|
|
161
|
+
key: string;
|
|
162
|
+
path: string;
|
|
163
|
+
display?: "preview" | "diff";
|
|
164
|
+
caption?: string;
|
|
165
|
+
lines: ChatFileOperationLineViewModel[];
|
|
166
|
+
rawText?: string;
|
|
167
|
+
truncated?: boolean;
|
|
168
|
+
};
|
|
154
169
|
type ChatToolPartViewModel = {
|
|
155
170
|
kind: "call" | "result";
|
|
156
171
|
toolName: string;
|
|
157
172
|
summary?: string;
|
|
173
|
+
inputLabel?: string;
|
|
174
|
+
input?: string;
|
|
158
175
|
output?: string;
|
|
176
|
+
outputData?: unknown;
|
|
159
177
|
hasResult: boolean;
|
|
160
178
|
statusTone: "running" | "success" | "error" | "cancelled";
|
|
161
179
|
statusLabel: string;
|
|
162
180
|
titleLabel: string;
|
|
163
181
|
outputLabel: string;
|
|
164
182
|
emptyLabel: string;
|
|
183
|
+
fileOperation?: {
|
|
184
|
+
blocks: ChatFileOperationBlockViewModel[];
|
|
185
|
+
};
|
|
165
186
|
};
|
|
166
187
|
type ChatInlineTokenViewModel = {
|
|
167
188
|
kind: string;
|
|
@@ -299,4 +320,4 @@ declare function resolveChatComposerSlashTrigger(nodes: ChatComposerNode[], sele
|
|
|
299
320
|
end: number;
|
|
300
321
|
} | null;
|
|
301
322
|
|
|
302
|
-
export { type ChatComposerNode, type ChatComposerSelection, type ChatComposerTextNode, type ChatComposerTokenKind, type ChatComposerTokenNode, type ChatInlineContentSegmentViewModel, type ChatInlineHint, type ChatInlineTokenViewModel, ChatInputBar, type ChatInputBarActionsProps, type ChatInputBarHandle, type ChatInputBarProps, type ChatInputBarToolbarProps, ChatMessageList, type ChatMessageListProps, type ChatMessagePartViewModel, type ChatMessageRole, type ChatMessageTexts, type ChatMessageViewModel, type ChatSelectedItem, type ChatSkillPickerOption, type ChatSkillPickerProps, type ChatSlashItem, type ChatSlashMenuProps, type ChatTexts, type ChatToolPartViewModel, type ChatToolbarAccessory, type ChatToolbarAccessoryIcon, type ChatToolbarIcon, type ChatToolbarSelect, type ChatToolbarSelectGroup, type ChatToolbarSelectOption, copyText, createChatComposerNodesFromText, createChatComposerTextNode, createChatComposerTokenNode, createEmptyChatComposerNodes, extractChatComposerTokenKeys, normalizeChatComposerNodes, removeChatComposerTokenNodes, replaceChatComposerRange, resolveChatComposerSlashTrigger, serializeChatComposerDocument, serializeChatComposerPlainText, useActiveItemScroll, useCopyFeedback, useElementWidth, useStickyBottomScroll };
|
|
323
|
+
export { type ChatComposerNode, type ChatComposerSelection, type ChatComposerTextNode, type ChatComposerTokenKind, type ChatComposerTokenNode, type ChatFileOperationBlockViewModel, type ChatFileOperationLineViewModel, type ChatInlineContentSegmentViewModel, type ChatInlineHint, type ChatInlineTokenViewModel, ChatInputBar, type ChatInputBarActionsProps, type ChatInputBarHandle, type ChatInputBarProps, type ChatInputBarToolbarProps, ChatMessageList, type ChatMessageListProps, type ChatMessagePartViewModel, type ChatMessageRole, type ChatMessageTexts, type ChatMessageViewModel, type ChatSelectedItem, type ChatSkillPickerOption, type ChatSkillPickerProps, type ChatSlashItem, type ChatSlashMenuProps, type ChatTexts, type ChatToolPartViewModel, type ChatToolbarAccessory, type ChatToolbarAccessoryIcon, type ChatToolbarIcon, type ChatToolbarSelect, type ChatToolbarSelectGroup, type ChatToolbarSelectOption, copyText, createChatComposerNodesFromText, createChatComposerTextNode, createChatComposerTokenNode, createEmptyChatComposerNodes, extractChatComposerTokenKeys, normalizeChatComposerNodes, removeChatComposerTokenNodes, replaceChatComposerRange, resolveChatComposerSlashTrigger, serializeChatComposerDocument, serializeChatComposerPlainText, useActiveItemScroll, useCopyFeedback, useElementWidth, useStickyBottomScroll };
|
package/dist/index.js
CHANGED
|
@@ -2314,8 +2314,8 @@ function ChatInlineTokenBadge({
|
|
|
2314
2314
|
"span",
|
|
2315
2315
|
{
|
|
2316
2316
|
className: cn(
|
|
2317
|
-
"mx-[2px] inline-flex h-7 max-w-full items-center gap-1.5 rounded-
|
|
2318
|
-
isSkill ? isUser ? "border-
|
|
2317
|
+
"mx-[2px] inline-flex h-7 max-w-full items-center gap-1.5 rounded-xl border px-2.5 align-baseline text-[11px] font-medium shadow-[0_0_0_1px_rgba(15,23,42,0.03)]",
|
|
2318
|
+
isSkill ? isUser ? "border-emerald-200/35 bg-emerald-400/18 text-emerald-50/95" : "border-emerald-200/70 bg-emerald-50 text-emerald-700" : isUser ? "border-white/30 bg-white/18 text-white" : "border-slate-200/80 bg-slate-100 text-slate-700"
|
|
2319
2319
|
),
|
|
2320
2320
|
title: label,
|
|
2321
2321
|
children: [
|
|
@@ -2324,7 +2324,7 @@ function ChatInlineTokenBadge({
|
|
|
2324
2324
|
{
|
|
2325
2325
|
className: cn(
|
|
2326
2326
|
"inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center",
|
|
2327
|
-
isSkill ? isUser ? "text-
|
|
2327
|
+
isSkill ? isUser ? "text-emerald-100/90" : "text-emerald-600" : isUser ? "text-white/70" : "text-slate-500"
|
|
2328
2328
|
),
|
|
2329
2329
|
children: /* @__PURE__ */ jsx15(ChatInlineSkillIcon, {})
|
|
2330
2330
|
}
|
|
@@ -2801,9 +2801,10 @@ function ToolCardHeader({
|
|
|
2801
2801
|
icon: Icon2,
|
|
2802
2802
|
expanded,
|
|
2803
2803
|
canExpand,
|
|
2804
|
+
hideSummary = false,
|
|
2804
2805
|
onToggle
|
|
2805
2806
|
}) {
|
|
2806
|
-
const summaryPart = card.summary?.replace(/^(command|path|args|query|input):\s*/i, "");
|
|
2807
|
+
const summaryPart = hideSummary ? "" : card.summary?.replace(/^(command|path|args|query|input):\s*/i, "") ?? "";
|
|
2807
2808
|
return /* @__PURE__ */ jsxs12(
|
|
2808
2809
|
"div",
|
|
2809
2810
|
{
|
|
@@ -2832,56 +2833,379 @@ function ToolCardHeader({
|
|
|
2832
2833
|
);
|
|
2833
2834
|
}
|
|
2834
2835
|
|
|
2835
|
-
// src/components/chat/ui/chat-message-list/tool-card/tool-card-
|
|
2836
|
-
import { Fragment as Fragment4
|
|
2837
|
-
|
|
2836
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation.tsx
|
|
2837
|
+
import { Fragment as Fragment4 } from "react";
|
|
2838
|
+
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2839
|
+
function formatLineNumber(value) {
|
|
2840
|
+
return typeof value === "number" ? String(value) : "";
|
|
2841
|
+
}
|
|
2842
|
+
function readVisibleLineNumber(line) {
|
|
2843
|
+
return formatLineNumber(line.newLineNumber ?? line.oldLineNumber);
|
|
2844
|
+
}
|
|
2845
|
+
function isPreviewBlock(block) {
|
|
2846
|
+
return block.display === "preview";
|
|
2847
|
+
}
|
|
2848
|
+
function getCaptionTone(part) {
|
|
2849
|
+
if (/^\+\d+$/.test(part)) {
|
|
2850
|
+
return "text-emerald-700";
|
|
2851
|
+
}
|
|
2852
|
+
if (/^-\d+$/.test(part)) {
|
|
2853
|
+
return "text-rose-700";
|
|
2854
|
+
}
|
|
2855
|
+
return "text-stone-500";
|
|
2856
|
+
}
|
|
2857
|
+
function renderCaption(caption) {
|
|
2858
|
+
const parts = caption.split("\xB7").map((part) => part.trim()).filter((part) => /^\+\d+$/.test(part) || /^-\d+$/.test(part));
|
|
2859
|
+
if (parts.length === 0) {
|
|
2860
|
+
return null;
|
|
2861
|
+
}
|
|
2862
|
+
return /* @__PURE__ */ jsx21("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__ */ jsxs13(Fragment4, { children: [
|
|
2863
|
+
index > 0 ? /* @__PURE__ */ jsx21("span", { className: "text-stone-300", children: "\xB7" }) : null,
|
|
2864
|
+
/* @__PURE__ */ jsx21("span", { className: cn(getCaptionTone(part)), children: part })
|
|
2865
|
+
] }, `${part}-${index}`)) });
|
|
2866
|
+
}
|
|
2867
|
+
function renderDiffGutterRow(line, index) {
|
|
2868
|
+
const gutterTone = line.kind === "add" ? "border-r border-emerald-200 bg-emerald-100 text-emerald-700" : line.kind === "remove" ? "border-r border-rose-200 bg-rose-100 text-rose-700" : "border-r border-stone-200 bg-stone-100 text-stone-500";
|
|
2869
|
+
return /* @__PURE__ */ jsx21(
|
|
2870
|
+
"div",
|
|
2871
|
+
{
|
|
2872
|
+
className: "font-mono text-[11px] leading-relaxed",
|
|
2873
|
+
children: /* @__PURE__ */ jsx21("span", { className: cn("flex h-full w-11 items-center justify-center px-1 py-1 tabular-nums", gutterTone), children: readVisibleLineNumber(line) })
|
|
2874
|
+
},
|
|
2875
|
+
`diff-gutter-${index}-${line.oldLineNumber ?? "x"}-${line.newLineNumber ?? "x"}`
|
|
2876
|
+
);
|
|
2877
|
+
}
|
|
2878
|
+
function renderPreviewGutterRow(line, index) {
|
|
2879
|
+
return /* @__PURE__ */ jsx21(
|
|
2880
|
+
"div",
|
|
2881
|
+
{
|
|
2882
|
+
className: "font-mono text-[11px] leading-relaxed",
|
|
2883
|
+
children: /* @__PURE__ */ jsx21("span", { className: "flex h-full w-11 items-center justify-center border-r border-stone-200 bg-stone-100 px-1 py-1.5 tabular-nums text-stone-500", children: readVisibleLineNumber(line) })
|
|
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(
|
|
2891
|
+
"div",
|
|
2892
|
+
{
|
|
2893
|
+
className: cn(
|
|
2894
|
+
"min-w-full whitespace-pre px-3 py-1 font-mono text-[11px] leading-relaxed",
|
|
2895
|
+
rowTone
|
|
2896
|
+
),
|
|
2897
|
+
children: line.text || " "
|
|
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"}`
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
function FileOperationBlock({
|
|
2913
|
+
block,
|
|
2914
|
+
showPathRow,
|
|
2915
|
+
isFirst
|
|
2916
|
+
}) {
|
|
2917
|
+
const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;
|
|
2918
|
+
const previewBlock = isPreviewBlock(block);
|
|
2919
|
+
const showMetaRow = showPathRow || Boolean(block.caption);
|
|
2920
|
+
return /* @__PURE__ */ jsxs13("section", { className: cn("overflow-hidden bg-white", !isFirst && "border-t border-stone-200/80"), children: [
|
|
2921
|
+
showMetaRow ? /* @__PURE__ */ jsxs13(
|
|
2922
|
+
"div",
|
|
2923
|
+
{
|
|
2924
|
+
className: cn(
|
|
2925
|
+
"flex items-center justify-between gap-4 border-b border-stone-200/80 px-4 text-stone-700",
|
|
2926
|
+
showPathRow ? "py-3" : "py-2"
|
|
2927
|
+
),
|
|
2928
|
+
children: [
|
|
2929
|
+
/* @__PURE__ */ jsx21("div", { className: "min-w-0 flex-1", children: showPathRow ? /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 250, children: /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
2930
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(
|
|
2931
|
+
"div",
|
|
2932
|
+
{
|
|
2933
|
+
className: "truncate whitespace-nowrap font-mono text-[12px] font-medium text-stone-700",
|
|
2934
|
+
title: block.path,
|
|
2935
|
+
children: block.path
|
|
2936
|
+
}
|
|
2937
|
+
) }),
|
|
2938
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "top", className: "max-w-[420px] text-xs font-mono break-all", children: block.path })
|
|
2939
|
+
] }) }) : null }),
|
|
2940
|
+
block.caption ? renderCaption(block.caption) : null
|
|
2941
|
+
]
|
|
2942
|
+
}
|
|
2943
|
+
) : null,
|
|
2944
|
+
block.lines.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "max-h-72 overflow-auto bg-white custom-scrollbar-amber", children: /* @__PURE__ */ jsxs13(
|
|
2945
|
+
"div",
|
|
2946
|
+
{
|
|
2947
|
+
className: cn(
|
|
2948
|
+
"grid min-w-0 max-w-full",
|
|
2949
|
+
"grid-cols-[2.75rem_minmax(0,1fr)]"
|
|
2950
|
+
),
|
|
2951
|
+
children: [
|
|
2952
|
+
/* @__PURE__ */ jsx21("div", { className: "overflow-hidden", children: block.lines.map(previewBlock ? renderPreviewGutterRow : renderDiffGutterRow) }),
|
|
2953
|
+
/* @__PURE__ */ jsx21("div", { className: "overflow-x-auto custom-scrollbar-amber bg-white", children: /* @__PURE__ */ jsx21("div", { className: "min-w-max", children: block.lines.map(previewBlock ? renderPreviewCodeRow : renderDiffCodeRow) }) })
|
|
2954
|
+
]
|
|
2955
|
+
}
|
|
2956
|
+
) }) : block.rawText ? /* @__PURE__ */ jsx21("pre", { className: "max-h-72 min-w-full w-max overflow-auto bg-white px-4 py-3 font-mono text-[11px] leading-relaxed text-amber-950/80 whitespace-pre custom-scrollbar-amber", children: block.rawText }) : null,
|
|
2957
|
+
block.truncated && !previewBlock ? /* @__PURE__ */ jsx21("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
|
|
2958
|
+
] });
|
|
2959
|
+
}
|
|
2960
|
+
function ToolCardFileOperationContent({
|
|
2961
|
+
card,
|
|
2962
|
+
className
|
|
2963
|
+
}) {
|
|
2964
|
+
const blocks = card.fileOperation?.blocks ?? [];
|
|
2838
2965
|
const output = card.output?.trim() ?? "";
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2966
|
+
if (blocks.length === 0 && !output) {
|
|
2967
|
+
return null;
|
|
2968
|
+
}
|
|
2969
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("overflow-hidden bg-white", className), children: [
|
|
2970
|
+
blocks.map((block, index) => {
|
|
2971
|
+
return /* @__PURE__ */ jsx21(
|
|
2972
|
+
FileOperationBlock,
|
|
2973
|
+
{
|
|
2974
|
+
block,
|
|
2975
|
+
showPathRow: true,
|
|
2976
|
+
isFirst: index === 0
|
|
2977
|
+
},
|
|
2978
|
+
block.key
|
|
2979
|
+
);
|
|
2980
|
+
}),
|
|
2981
|
+
output ? /* @__PURE__ */ jsx21("pre", { className: cn(
|
|
2982
|
+
"max-h-56 min-w-full w-max overflow-auto bg-white px-4 py-3 font-mono text-[11px] leading-relaxed text-amber-950/80 whitespace-pre custom-scrollbar-amber",
|
|
2983
|
+
blocks.length > 0 && "border-t border-stone-200/80"
|
|
2984
|
+
), children: output }) : null
|
|
2985
|
+
] });
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2988
|
+
// src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx
|
|
2989
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2990
|
+
var TOOL_CARD_AUTO_EXPAND_DELAY_MS = 200;
|
|
2991
|
+
var ANSI_ESCAPE_PREFIX = String.fromCharCode(27);
|
|
2992
|
+
var ANSI_ESCAPE_PATTERN = new RegExp(`${ANSI_ESCAPE_PREFIX}\\[[0-?]*[ -/]*[@-~]`, "g");
|
|
2993
|
+
function readNonEmptyString(value) {
|
|
2994
|
+
if (typeof value !== "string") {
|
|
2995
|
+
return null;
|
|
2996
|
+
}
|
|
2997
|
+
return value.length > 0 ? value : null;
|
|
2998
|
+
}
|
|
2999
|
+
function isRecord(value) {
|
|
3000
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3001
|
+
}
|
|
3002
|
+
function stripAnsi(value) {
|
|
3003
|
+
return value.replace(ANSI_ESCAPE_PATTERN, "");
|
|
3004
|
+
}
|
|
3005
|
+
function isStructuredTerminalRecord(record) {
|
|
3006
|
+
return "command" in record || "workingDir" in record || "exitCode" in record || "durationMs" in record || "stdout" in record || "stderr" in record || "aggregated_output" in record || "combinedOutput" in record;
|
|
3007
|
+
}
|
|
3008
|
+
function extractTerminalOutputFromRecord(record) {
|
|
3009
|
+
const aggregatedOutput = readNonEmptyString(record.aggregated_output) ?? readNonEmptyString(record.combinedOutput) ?? readNonEmptyString(record.output);
|
|
3010
|
+
if (aggregatedOutput) {
|
|
3011
|
+
return aggregatedOutput;
|
|
3012
|
+
}
|
|
3013
|
+
const stdout = readNonEmptyString(record.stdout);
|
|
3014
|
+
const stderr = readNonEmptyString(record.stderr);
|
|
3015
|
+
if (!stdout && !stderr) {
|
|
3016
|
+
return null;
|
|
3017
|
+
}
|
|
3018
|
+
return [stdout, stderr].filter((value) => Boolean(value)).join("\n");
|
|
3019
|
+
}
|
|
3020
|
+
function normalizeTerminalOutput(rawOutput, structuredOutput) {
|
|
3021
|
+
if (isRecord(structuredOutput)) {
|
|
3022
|
+
const terminalOutput = extractTerminalOutputFromRecord(structuredOutput);
|
|
3023
|
+
if (terminalOutput) {
|
|
3024
|
+
return stripAnsi(terminalOutput);
|
|
3025
|
+
}
|
|
3026
|
+
if (isStructuredTerminalRecord(structuredOutput)) {
|
|
3027
|
+
return "";
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
if (!rawOutput) {
|
|
3031
|
+
return "";
|
|
3032
|
+
}
|
|
3033
|
+
const trimmed = rawOutput.trim();
|
|
3034
|
+
if (!trimmed.startsWith("{")) {
|
|
3035
|
+
return stripAnsi(rawOutput);
|
|
3036
|
+
}
|
|
3037
|
+
try {
|
|
3038
|
+
const parsed = JSON.parse(trimmed);
|
|
3039
|
+
if (!isRecord(parsed)) {
|
|
3040
|
+
return stripAnsi(rawOutput);
|
|
3041
|
+
}
|
|
3042
|
+
const terminalOutput = extractTerminalOutputFromRecord(parsed);
|
|
3043
|
+
if (terminalOutput) {
|
|
3044
|
+
return stripAnsi(terminalOutput);
|
|
3045
|
+
}
|
|
3046
|
+
if (isStructuredTerminalRecord(parsed)) {
|
|
3047
|
+
return "";
|
|
3048
|
+
}
|
|
3049
|
+
return stripAnsi(rawOutput);
|
|
3050
|
+
} catch {
|
|
3051
|
+
return stripAnsi(rawOutput);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
function useToolCardExpandedState({
|
|
3055
|
+
canExpand,
|
|
3056
|
+
isRunning,
|
|
3057
|
+
autoExpandWhileRunning = true,
|
|
3058
|
+
expandOnError = false,
|
|
3059
|
+
statusTone
|
|
3060
|
+
}) {
|
|
3061
|
+
const [expanded, setExpanded] = useState7(false);
|
|
2843
3062
|
const [hasUserToggled, setHasUserToggled] = useState7(false);
|
|
3063
|
+
const expandTimerRef = useRef6(null);
|
|
2844
3064
|
const prevRunningRef = useRef6(isRunning);
|
|
3065
|
+
const isFirstRenderRef = useRef6(true);
|
|
3066
|
+
useEffect7(() => {
|
|
3067
|
+
return () => {
|
|
3068
|
+
if (expandTimerRef.current !== null) {
|
|
3069
|
+
window.clearTimeout(expandTimerRef.current);
|
|
3070
|
+
}
|
|
3071
|
+
};
|
|
3072
|
+
}, []);
|
|
2845
3073
|
useEffect7(() => {
|
|
2846
|
-
if (
|
|
3074
|
+
if (expandOnError && statusTone === "error" && canExpand && !hasUserToggled) {
|
|
3075
|
+
if (expandTimerRef.current !== null) {
|
|
3076
|
+
window.clearTimeout(expandTimerRef.current);
|
|
3077
|
+
expandTimerRef.current = null;
|
|
3078
|
+
}
|
|
2847
3079
|
setExpanded(true);
|
|
2848
|
-
|
|
3080
|
+
prevRunningRef.current = isRunning;
|
|
3081
|
+
isFirstRenderRef.current = false;
|
|
3082
|
+
return;
|
|
2849
3083
|
}
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
3084
|
+
if (autoExpandWhileRunning && isRunning && canExpand && !hasUserToggled && !expanded && (isFirstRenderRef.current || !prevRunningRef.current)) {
|
|
3085
|
+
expandTimerRef.current = window.setTimeout(() => {
|
|
3086
|
+
setExpanded(true);
|
|
3087
|
+
expandTimerRef.current = null;
|
|
3088
|
+
}, TOOL_CARD_AUTO_EXPAND_DELAY_MS);
|
|
3089
|
+
}
|
|
3090
|
+
if (!isRunning) {
|
|
3091
|
+
if (expandTimerRef.current !== null) {
|
|
3092
|
+
window.clearTimeout(expandTimerRef.current);
|
|
3093
|
+
expandTimerRef.current = null;
|
|
3094
|
+
}
|
|
3095
|
+
if (prevRunningRef.current && !hasUserToggled) {
|
|
3096
|
+
setExpanded(false);
|
|
3097
|
+
}
|
|
2854
3098
|
}
|
|
2855
3099
|
prevRunningRef.current = isRunning;
|
|
2856
|
-
|
|
3100
|
+
isFirstRenderRef.current = false;
|
|
3101
|
+
}, [autoExpandWhileRunning, canExpand, expandOnError, expanded, hasUserToggled, isRunning, statusTone]);
|
|
2857
3102
|
const onToggle = () => {
|
|
2858
|
-
if (!
|
|
2859
|
-
|
|
3103
|
+
if (!canExpand) {
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
if (expandTimerRef.current !== null) {
|
|
3107
|
+
window.clearTimeout(expandTimerRef.current);
|
|
3108
|
+
expandTimerRef.current = null;
|
|
3109
|
+
}
|
|
3110
|
+
setExpanded((current) => !current);
|
|
2860
3111
|
setHasUserToggled(true);
|
|
2861
3112
|
};
|
|
3113
|
+
return { expanded, onToggle };
|
|
3114
|
+
}
|
|
3115
|
+
function GenericToolSection({
|
|
3116
|
+
label,
|
|
3117
|
+
tone,
|
|
3118
|
+
children
|
|
3119
|
+
}) {
|
|
3120
|
+
const tones = {
|
|
3121
|
+
input: {
|
|
3122
|
+
shell: "border-stone-200/80 bg-stone-50/90",
|
|
3123
|
+
header: "border-stone-200/80 bg-stone-100/85 text-stone-500",
|
|
3124
|
+
dot: "bg-stone-400/80",
|
|
3125
|
+
body: "text-stone-700"
|
|
3126
|
+
},
|
|
3127
|
+
output: {
|
|
3128
|
+
shell: "border-amber-200/70 bg-white/90",
|
|
3129
|
+
header: "border-amber-200/70 bg-amber-50/90 text-amber-700",
|
|
3130
|
+
dot: "bg-amber-500/80",
|
|
3131
|
+
body: "text-amber-950/80"
|
|
3132
|
+
},
|
|
3133
|
+
error: {
|
|
3134
|
+
shell: "border-rose-200/80 bg-rose-50/85",
|
|
3135
|
+
header: "border-rose-200/80 bg-rose-100/80 text-rose-700",
|
|
3136
|
+
dot: "bg-rose-500/80",
|
|
3137
|
+
body: "text-rose-950/85"
|
|
3138
|
+
}
|
|
3139
|
+
};
|
|
3140
|
+
const style = tones[tone];
|
|
3141
|
+
return /* @__PURE__ */ jsxs14(
|
|
3142
|
+
"section",
|
|
3143
|
+
{
|
|
3144
|
+
className: cn(
|
|
3145
|
+
"overflow-hidden rounded-md border shadow-[inset_0_1px_0_rgba(255,255,255,0.45)]",
|
|
3146
|
+
style.shell
|
|
3147
|
+
),
|
|
3148
|
+
children: [
|
|
3149
|
+
/* @__PURE__ */ jsxs14(
|
|
3150
|
+
"div",
|
|
3151
|
+
{
|
|
3152
|
+
className: cn(
|
|
3153
|
+
"flex items-center gap-2 border-b px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.16em]",
|
|
3154
|
+
style.header
|
|
3155
|
+
),
|
|
3156
|
+
children: [
|
|
3157
|
+
/* @__PURE__ */ jsx22("span", { className: cn("h-1.5 w-1.5 rounded-full", style.dot) }),
|
|
3158
|
+
/* @__PURE__ */ jsx22("span", { children: label })
|
|
3159
|
+
]
|
|
3160
|
+
}
|
|
3161
|
+
),
|
|
3162
|
+
/* @__PURE__ */ jsx22("div", { className: "w-full overflow-hidden", children: /* @__PURE__ */ jsx22(
|
|
3163
|
+
"pre",
|
|
3164
|
+
{
|
|
3165
|
+
className: cn(
|
|
3166
|
+
"w-full max-w-full min-w-0 max-h-64 overflow-x-auto overflow-y-auto px-3 py-2.5 font-mono text-[12px] leading-relaxed whitespace-pre custom-scrollbar-amber",
|
|
3167
|
+
style.body
|
|
3168
|
+
),
|
|
3169
|
+
children
|
|
3170
|
+
}
|
|
3171
|
+
) })
|
|
3172
|
+
]
|
|
3173
|
+
}
|
|
3174
|
+
);
|
|
3175
|
+
}
|
|
3176
|
+
function TerminalExecutionView({ card }) {
|
|
3177
|
+
const output = normalizeTerminalOutput(card.output, card.outputData);
|
|
3178
|
+
const isRunning = card.statusTone === "running";
|
|
3179
|
+
const hasContent = !!(card.summary?.trim() || output.trim().length > 0);
|
|
3180
|
+
const { expanded, onToggle } = useToolCardExpandedState({
|
|
3181
|
+
canExpand: output.trim().length > 0 || isRunning,
|
|
3182
|
+
isRunning,
|
|
3183
|
+
expandOnError: hasContent,
|
|
3184
|
+
statusTone: card.statusTone
|
|
3185
|
+
});
|
|
2862
3186
|
const commandPart = card.summary?.replace(/^(command|path|args|query|input):\s*/i, "");
|
|
2863
|
-
return /* @__PURE__ */
|
|
2864
|
-
/* @__PURE__ */
|
|
3187
|
+
return /* @__PURE__ */ jsxs14(ToolCardRoot, { children: [
|
|
3188
|
+
/* @__PURE__ */ jsx22(
|
|
2865
3189
|
ToolCardHeader,
|
|
2866
3190
|
{
|
|
2867
3191
|
card,
|
|
2868
3192
|
icon: Terminal,
|
|
2869
3193
|
expanded,
|
|
2870
|
-
canExpand:
|
|
3194
|
+
canExpand: output.trim().length > 0 || isRunning,
|
|
2871
3195
|
onToggle
|
|
2872
3196
|
}
|
|
2873
3197
|
),
|
|
2874
|
-
expanded && /* @__PURE__ */
|
|
2875
|
-
/* @__PURE__ */
|
|
2876
|
-
/* @__PURE__ */
|
|
2877
|
-
/* @__PURE__ */
|
|
3198
|
+
expanded && /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
3199
|
+
/* @__PURE__ */ jsx22("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__ */ jsxs14("div", { className: "flex items-start gap-2 leading-relaxed", children: [
|
|
3200
|
+
/* @__PURE__ */ jsx22("span", { className: "text-amber-500/50 font-medium shrink-0 select-none mt-[1px]", children: "$" }),
|
|
3201
|
+
/* @__PURE__ */ jsx22("div", { className: "flex-1 min-w-0", children: commandPart ? /* @__PURE__ */ jsxs14("div", { className: "text-amber-950/80 break-words whitespace-pre-wrap tracking-tight font-medium inline-block", children: [
|
|
2878
3202
|
commandPart,
|
|
2879
|
-
isRunning && !output && /* @__PURE__ */
|
|
2880
|
-
] }) : /* @__PURE__ */
|
|
3203
|
+
isRunning && !output && /* @__PURE__ */ jsx22("span", { className: "inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle" })
|
|
3204
|
+
] }) : /* @__PURE__ */ jsx22("div", { className: "h-3 w-32 bg-amber-200/30 rounded animate-pulse mt-2" }) })
|
|
2881
3205
|
] }) }),
|
|
2882
|
-
output && /* @__PURE__ */
|
|
3206
|
+
output && /* @__PURE__ */ jsx22(ToolCardContent, { children: /* @__PURE__ */ jsxs14("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: [
|
|
2883
3207
|
output,
|
|
2884
|
-
isRunning && /* @__PURE__ */
|
|
3208
|
+
isRunning && /* @__PURE__ */ jsx22("span", { className: "inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle" })
|
|
2885
3209
|
] }) })
|
|
2886
3210
|
] })
|
|
2887
3211
|
] });
|
|
@@ -2889,75 +3213,50 @@ function TerminalExecutionView({ card }) {
|
|
|
2889
3213
|
function FileOperationView({ card }) {
|
|
2890
3214
|
const output = card.output?.trim() ?? "";
|
|
2891
3215
|
const isRunning = card.statusTone === "running";
|
|
2892
|
-
const
|
|
2893
|
-
const
|
|
2894
|
-
const
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
] }, idx);
|
|
2914
|
-
}
|
|
2915
|
-
if (line.startsWith("-") && !line.startsWith("---")) {
|
|
2916
|
-
return /* @__PURE__ */ jsxs13("div", { className: "bg-rose-500/10 text-rose-700 px-2 py-0.5 w-full break-all whitespace-pre-wrap", children: [
|
|
2917
|
-
/* @__PURE__ */ jsx21("span", { className: "select-none opacity-40 mr-2 w-3 inline-block shrink-0", children: "-" }),
|
|
2918
|
-
/* @__PURE__ */ jsx21("span", { className: "line-through decoration-rose-400/50", children: line.slice(1) })
|
|
2919
|
-
] }, idx);
|
|
2920
|
-
}
|
|
2921
|
-
}
|
|
2922
|
-
return /* @__PURE__ */ jsx21("div", { className: "py-0.5 text-amber-950/80 w-full break-all whitespace-pre-wrap", children: /* @__PURE__ */ jsx21("span", { children: line }) }, idx);
|
|
2923
|
-
};
|
|
2924
|
-
const lines = output.split("\n");
|
|
2925
|
-
const maxLines = 15;
|
|
2926
|
-
const isLong = lines.length > maxLines;
|
|
2927
|
-
const displayLines = !expanded && isLong ? lines.slice(0, maxLines) : lines;
|
|
2928
|
-
return /* @__PURE__ */ jsxs13(ToolCardRoot, { children: [
|
|
2929
|
-
/* @__PURE__ */ jsx21(
|
|
3216
|
+
const hasStructuredPreview = Boolean(card.fileOperation?.blocks.length);
|
|
3217
|
+
const hasContent = hasStructuredPreview || Boolean(output);
|
|
3218
|
+
const previewBlocks = card.fileOperation?.blocks ?? [];
|
|
3219
|
+
const previewLineCount = previewBlocks.reduce((count, block) => count + block.lines.length, 0);
|
|
3220
|
+
const previewCharCount = previewBlocks.reduce((count, block) => {
|
|
3221
|
+
if (block.rawText) {
|
|
3222
|
+
return count + block.rawText.length;
|
|
3223
|
+
}
|
|
3224
|
+
return count + block.lines.reduce((lineCount, line) => lineCount + line.text.length + 1, 0);
|
|
3225
|
+
}, 0);
|
|
3226
|
+
const shouldAutoExpandWhileRunning = !(isRunning && card.toolName === "write_file" && (previewLineCount > 24 || previewCharCount > 1200));
|
|
3227
|
+
const { expanded, onToggle } = useToolCardExpandedState({
|
|
3228
|
+
canExpand: hasContent || isRunning,
|
|
3229
|
+
isRunning,
|
|
3230
|
+
autoExpandWhileRunning: shouldAutoExpandWhileRunning,
|
|
3231
|
+
expandOnError: hasContent,
|
|
3232
|
+
statusTone: card.statusTone
|
|
3233
|
+
});
|
|
3234
|
+
const isEdit = card.toolName === "edit_file" || card.toolName === "write_file" || card.toolName === "apply_patch" || card.toolName === "file_change";
|
|
3235
|
+
return /* @__PURE__ */ jsxs14(ToolCardRoot, { children: [
|
|
3236
|
+
/* @__PURE__ */ jsx22(
|
|
2930
3237
|
ToolCardHeader,
|
|
2931
3238
|
{
|
|
2932
3239
|
card,
|
|
2933
3240
|
icon: isEdit ? Code2 : FileText,
|
|
2934
3241
|
expanded,
|
|
2935
|
-
canExpand:
|
|
3242
|
+
canExpand: hasContent || isRunning,
|
|
3243
|
+
hideSummary: expanded && hasStructuredPreview,
|
|
2936
3244
|
onToggle
|
|
2937
3245
|
}
|
|
2938
3246
|
),
|
|
2939
|
-
expanded &&
|
|
3247
|
+
expanded && hasContent && /* @__PURE__ */ jsx22(ToolCardContent, { className: "border-t border-amber-200/20 bg-transparent px-0 pt-0 pb-0", children: /* @__PURE__ */ jsx22(ToolCardFileOperationContent, { card }) })
|
|
2940
3248
|
] });
|
|
2941
3249
|
}
|
|
2942
3250
|
function SearchSnippetView({ card }) {
|
|
2943
3251
|
const isRunning = card.statusTone === "running";
|
|
2944
|
-
const [expanded, setExpanded] = useState7(isRunning);
|
|
2945
|
-
const [hasUserToggled, setHasUserToggled] = useState7(false);
|
|
2946
|
-
const prevRunningRef = useRef6(isRunning);
|
|
2947
3252
|
const output = card.output?.trim() ?? "";
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
if (!output && !isRunning) return;
|
|
2956
|
-
setExpanded(!expanded);
|
|
2957
|
-
setHasUserToggled(true);
|
|
2958
|
-
};
|
|
2959
|
-
return /* @__PURE__ */ jsxs13(ToolCardRoot, { children: [
|
|
2960
|
-
/* @__PURE__ */ jsx21(
|
|
3253
|
+
const { expanded, onToggle } = useToolCardExpandedState({
|
|
3254
|
+
canExpand: !!output || isRunning,
|
|
3255
|
+
isRunning,
|
|
3256
|
+
statusTone: card.statusTone
|
|
3257
|
+
});
|
|
3258
|
+
return /* @__PURE__ */ jsxs14(ToolCardRoot, { children: [
|
|
3259
|
+
/* @__PURE__ */ jsx22(
|
|
2961
3260
|
ToolCardHeader,
|
|
2962
3261
|
{
|
|
2963
3262
|
card,
|
|
@@ -2967,51 +3266,58 @@ function SearchSnippetView({ card }) {
|
|
|
2967
3266
|
onToggle
|
|
2968
3267
|
}
|
|
2969
3268
|
),
|
|
2970
|
-
expanded && output && /* @__PURE__ */
|
|
3269
|
+
expanded && output && /* @__PURE__ */ jsx22(ToolCardContent, { children: /* @__PURE__ */ jsx22("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 }) })
|
|
2971
3270
|
] });
|
|
2972
3271
|
}
|
|
2973
3272
|
function GenericToolCard({ card }) {
|
|
3273
|
+
const input = card.input?.trim() ?? "";
|
|
2974
3274
|
const output = card.output?.trim() ?? "";
|
|
2975
3275
|
const isRunning = card.statusTone === "running";
|
|
2976
|
-
const
|
|
2977
|
-
const
|
|
2978
|
-
const
|
|
2979
|
-
const
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
}
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
setExpanded(!expanded);
|
|
2989
|
-
setHasUserToggled(true);
|
|
2990
|
-
};
|
|
2991
|
-
return /* @__PURE__ */ jsxs13(ToolCardRoot, { children: [
|
|
2992
|
-
/* @__PURE__ */ jsx21(
|
|
3276
|
+
const hasInputSection = input.length > 0;
|
|
3277
|
+
const hasOutputSection = output.length > 0;
|
|
3278
|
+
const hasContent = hasInputSection || hasOutputSection;
|
|
3279
|
+
const inputLabel = card.inputLabel?.trim() || "Input";
|
|
3280
|
+
const outputLabel = card.outputLabel?.trim() || "Output";
|
|
3281
|
+
const { expanded, onToggle } = useToolCardExpandedState({
|
|
3282
|
+
canExpand: hasContent || isRunning,
|
|
3283
|
+
isRunning,
|
|
3284
|
+
statusTone: card.statusTone
|
|
3285
|
+
});
|
|
3286
|
+
return /* @__PURE__ */ jsxs14(ToolCardRoot, { children: [
|
|
3287
|
+
/* @__PURE__ */ jsx22(
|
|
2993
3288
|
ToolCardHeader,
|
|
2994
3289
|
{
|
|
2995
3290
|
card,
|
|
2996
3291
|
icon: Globe,
|
|
2997
3292
|
expanded,
|
|
2998
|
-
canExpand:
|
|
3293
|
+
canExpand: hasContent || isRunning,
|
|
2999
3294
|
onToggle
|
|
3000
3295
|
}
|
|
3001
3296
|
),
|
|
3002
|
-
expanded &&
|
|
3297
|
+
expanded && hasContent && /* @__PURE__ */ jsxs14(ToolCardContent, { className: "bg-transparent px-2.5 py-2.5", children: [
|
|
3298
|
+
hasInputSection && /* @__PURE__ */ jsx22(GenericToolSection, { label: inputLabel, tone: "input", children: input }),
|
|
3299
|
+
hasInputSection && hasOutputSection && /* @__PURE__ */ jsx22("div", { className: "h-2" }),
|
|
3300
|
+
hasOutputSection && /* @__PURE__ */ jsx22(
|
|
3301
|
+
GenericToolSection,
|
|
3302
|
+
{
|
|
3303
|
+
label: outputLabel,
|
|
3304
|
+
tone: card.statusTone === "error" ? "error" : "output",
|
|
3305
|
+
children: output
|
|
3306
|
+
}
|
|
3307
|
+
)
|
|
3308
|
+
] })
|
|
3003
3309
|
] });
|
|
3004
3310
|
}
|
|
3005
3311
|
|
|
3006
3312
|
// src/components/chat/ui/chat-message-list/chat-tool-card.tsx
|
|
3007
|
-
import { jsx as
|
|
3313
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
3008
3314
|
function isTerminalTool(name) {
|
|
3009
3315
|
const lowered = name.toLowerCase();
|
|
3010
|
-
return lowered === "exec" || lowered === "execute_command" || lowered === "bash" || lowered === "shell" || lowered.includes("run_");
|
|
3316
|
+
return lowered === "exec" || lowered === "exec_command" || lowered === "execute_command" || lowered === "command_execution" || lowered === "bash" || lowered === "shell" || lowered.includes("run_");
|
|
3011
3317
|
}
|
|
3012
3318
|
function isFileEditTool(name) {
|
|
3013
3319
|
const lowered = name.toLowerCase();
|
|
3014
|
-
return lowered === "read_file" || lowered === "write_file" || lowered === "edit_file" || lowered === "apply_patch";
|
|
3320
|
+
return lowered === "read_file" || lowered === "write_file" || lowered === "edit_file" || lowered === "apply_patch" || lowered === "file_change";
|
|
3015
3321
|
}
|
|
3016
3322
|
function isSearchTool(name) {
|
|
3017
3323
|
const lowered = name.toLowerCase();
|
|
@@ -3019,48 +3325,48 @@ function isSearchTool(name) {
|
|
|
3019
3325
|
}
|
|
3020
3326
|
function ChatToolCard({ card }) {
|
|
3021
3327
|
if (isTerminalTool(card.toolName)) {
|
|
3022
|
-
return /* @__PURE__ */
|
|
3328
|
+
return /* @__PURE__ */ jsx23(TerminalExecutionView, { card });
|
|
3023
3329
|
}
|
|
3024
3330
|
if (isFileEditTool(card.toolName)) {
|
|
3025
|
-
return /* @__PURE__ */
|
|
3331
|
+
return /* @__PURE__ */ jsx23(FileOperationView, { card });
|
|
3026
3332
|
}
|
|
3027
3333
|
if (isSearchTool(card.toolName)) {
|
|
3028
|
-
return /* @__PURE__ */
|
|
3334
|
+
return /* @__PURE__ */ jsx23(SearchSnippetView, { card });
|
|
3029
3335
|
}
|
|
3030
|
-
return /* @__PURE__ */
|
|
3336
|
+
return /* @__PURE__ */ jsx23(GenericToolCard, { card });
|
|
3031
3337
|
}
|
|
3032
3338
|
|
|
3033
3339
|
// src/components/chat/ui/chat-message-list/chat-unknown-part.tsx
|
|
3034
|
-
import { jsx as
|
|
3340
|
+
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3035
3341
|
function ChatUnknownPart(props) {
|
|
3036
|
-
return /* @__PURE__ */
|
|
3037
|
-
/* @__PURE__ */
|
|
3342
|
+
return /* @__PURE__ */ jsxs15("div", { className: "rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600", children: [
|
|
3343
|
+
/* @__PURE__ */ jsxs15("div", { className: "font-semibold text-gray-700", children: [
|
|
3038
3344
|
props.label,
|
|
3039
3345
|
": ",
|
|
3040
3346
|
props.rawType
|
|
3041
3347
|
] }),
|
|
3042
|
-
props.text ? /* @__PURE__ */
|
|
3348
|
+
props.text ? /* @__PURE__ */ jsx24("pre", { className: "mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500", children: props.text }) : null
|
|
3043
3349
|
] });
|
|
3044
3350
|
}
|
|
3045
3351
|
|
|
3046
3352
|
// src/components/chat/ui/chat-message-list/chat-message.tsx
|
|
3047
|
-
import { jsx as
|
|
3353
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
3048
3354
|
var ChatMessage = memo(function ChatMessage2(props) {
|
|
3049
3355
|
const { message, texts } = props;
|
|
3050
3356
|
const { role } = message;
|
|
3051
3357
|
const isUser = role === "user";
|
|
3052
3358
|
const isMessageInProgress = message.status === "pending" || message.status === "streaming";
|
|
3053
|
-
return /* @__PURE__ */
|
|
3359
|
+
return /* @__PURE__ */ jsx25(
|
|
3054
3360
|
"div",
|
|
3055
3361
|
{
|
|
3056
3362
|
className: cn(
|
|
3057
3363
|
"inline-block w-fit max-w-full rounded-2xl border px-4 shadow-sm",
|
|
3058
3364
|
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"
|
|
3059
3365
|
),
|
|
3060
|
-
children: /* @__PURE__ */
|
|
3366
|
+
children: /* @__PURE__ */ jsx25("div", { className: "space-y-2", children: message.parts.map((part, index) => {
|
|
3061
3367
|
const { type } = part;
|
|
3062
3368
|
if (type === "markdown") {
|
|
3063
|
-
return /* @__PURE__ */
|
|
3369
|
+
return /* @__PURE__ */ jsx25(
|
|
3064
3370
|
ChatMessageMarkdown,
|
|
3065
3371
|
{
|
|
3066
3372
|
text: part.text,
|
|
@@ -3071,7 +3377,7 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3071
3377
|
);
|
|
3072
3378
|
}
|
|
3073
3379
|
if (type === "inline-content") {
|
|
3074
|
-
return /* @__PURE__ */
|
|
3380
|
+
return /* @__PURE__ */ jsx25(
|
|
3075
3381
|
ChatMessageInlineContent,
|
|
3076
3382
|
{
|
|
3077
3383
|
segments: part.segments,
|
|
@@ -3082,7 +3388,7 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3082
3388
|
);
|
|
3083
3389
|
}
|
|
3084
3390
|
if (type === "reasoning") {
|
|
3085
|
-
return /* @__PURE__ */
|
|
3391
|
+
return /* @__PURE__ */ jsx25(
|
|
3086
3392
|
ChatReasoningBlock,
|
|
3087
3393
|
{
|
|
3088
3394
|
label: part.label,
|
|
@@ -3094,10 +3400,10 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3094
3400
|
);
|
|
3095
3401
|
}
|
|
3096
3402
|
if (type === "tool-card") {
|
|
3097
|
-
return /* @__PURE__ */
|
|
3403
|
+
return /* @__PURE__ */ jsx25("div", { className: "mt-0.5", children: /* @__PURE__ */ jsx25(ChatToolCard, { card: part.card }) }, `tool-${index}`);
|
|
3098
3404
|
}
|
|
3099
3405
|
if (type === "file") {
|
|
3100
|
-
return /* @__PURE__ */
|
|
3406
|
+
return /* @__PURE__ */ jsx25(
|
|
3101
3407
|
ChatMessageFile,
|
|
3102
3408
|
{
|
|
3103
3409
|
file: part.file,
|
|
@@ -3107,7 +3413,7 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3107
3413
|
);
|
|
3108
3414
|
}
|
|
3109
3415
|
if (type === "unknown") {
|
|
3110
|
-
return /* @__PURE__ */
|
|
3416
|
+
return /* @__PURE__ */ jsx25(
|
|
3111
3417
|
ChatUnknownPart,
|
|
3112
3418
|
{
|
|
3113
3419
|
label: part.label,
|
|
@@ -3124,9 +3430,9 @@ var ChatMessage = memo(function ChatMessage2(props) {
|
|
|
3124
3430
|
});
|
|
3125
3431
|
|
|
3126
3432
|
// src/components/chat/ui/chat-message-list/chat-message-meta.tsx
|
|
3127
|
-
import { jsxs as
|
|
3433
|
+
import { jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3128
3434
|
function ChatMessageMeta(props) {
|
|
3129
|
-
return /* @__PURE__ */
|
|
3435
|
+
return /* @__PURE__ */ jsxs16(
|
|
3130
3436
|
"div",
|
|
3131
3437
|
{
|
|
3132
3438
|
className: cn(
|
|
@@ -3145,7 +3451,7 @@ function ChatMessageMeta(props) {
|
|
|
3145
3451
|
// src/components/chat/ui/chat-message-list/chat-message-action-copy.tsx
|
|
3146
3452
|
import { useMemo as useMemo6 } from "react";
|
|
3147
3453
|
import { Check as Check5, Copy as Copy2 } from "lucide-react";
|
|
3148
|
-
import { jsx as
|
|
3454
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
3149
3455
|
function ChatMessageActionCopy({
|
|
3150
3456
|
message,
|
|
3151
3457
|
texts
|
|
@@ -3159,7 +3465,7 @@ function ChatMessageActionCopy({
|
|
|
3159
3465
|
}, [message.parts]);
|
|
3160
3466
|
const { copied, copy } = useCopyFeedback({ text: messageText });
|
|
3161
3467
|
if (!messageText) return null;
|
|
3162
|
-
return /* @__PURE__ */
|
|
3468
|
+
return /* @__PURE__ */ jsx26(
|
|
3163
3469
|
"button",
|
|
3164
3470
|
{
|
|
3165
3471
|
type: "button",
|
|
@@ -3167,13 +3473,13 @@ function ChatMessageActionCopy({
|
|
|
3167
3473
|
className: "text-gray-400 hover:text-gray-600 transition-colors p-1 rounded-md hover:bg-gray-100 flex items-center justify-center",
|
|
3168
3474
|
"aria-label": copied ? texts.copiedMessageLabel : texts.copyMessageLabel,
|
|
3169
3475
|
title: copied ? texts.copiedMessageLabel : texts.copyMessageLabel,
|
|
3170
|
-
children: copied ? /* @__PURE__ */
|
|
3476
|
+
children: copied ? /* @__PURE__ */ jsx26(Check5, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx26(Copy2, { className: "h-3.5 w-3.5" })
|
|
3171
3477
|
}
|
|
3172
3478
|
);
|
|
3173
3479
|
}
|
|
3174
3480
|
|
|
3175
3481
|
// src/components/chat/ui/chat-message-list/chat-message-list.tsx
|
|
3176
|
-
import { Fragment as
|
|
3482
|
+
import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3177
3483
|
var INVISIBLE_ONLY_TEXT_PATTERN = /\u200B|\u200C|\u200D|\u2060|\uFEFF/g;
|
|
3178
3484
|
function hasRenderableText(value) {
|
|
3179
3485
|
const trimmed = value.trim();
|
|
@@ -3191,10 +3497,10 @@ function hasRenderableMessageContent(message) {
|
|
|
3191
3497
|
});
|
|
3192
3498
|
}
|
|
3193
3499
|
function ChatMessageTypingFooter() {
|
|
3194
|
-
return /* @__PURE__ */
|
|
3195
|
-
/* @__PURE__ */
|
|
3196
|
-
/* @__PURE__ */
|
|
3197
|
-
/* @__PURE__ */
|
|
3500
|
+
return /* @__PURE__ */ jsx27("div", { className: "flex items-center gap-2 px-1 py-0.5 text-[11px] text-gray-400", children: /* @__PURE__ */ jsxs17("div", { className: "flex space-x-1 items-center h-full", children: [
|
|
3501
|
+
/* @__PURE__ */ jsx27("div", { className: "h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse" }),
|
|
3502
|
+
/* @__PURE__ */ jsx27("div", { className: "h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:200ms]" }),
|
|
3503
|
+
/* @__PURE__ */ jsx27("div", { className: "h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:400ms]" })
|
|
3198
3504
|
] }) });
|
|
3199
3505
|
}
|
|
3200
3506
|
function ChatMessageList(props) {
|
|
@@ -3202,25 +3508,25 @@ function ChatMessageList(props) {
|
|
|
3202
3508
|
const hasRenderableAssistantDraft = visibleMessages.some(
|
|
3203
3509
|
(message) => message.role === "assistant" && (message.status === "streaming" || message.status === "pending")
|
|
3204
3510
|
);
|
|
3205
|
-
return /* @__PURE__ */
|
|
3511
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn("space-y-5", props.className), children: [
|
|
3206
3512
|
visibleMessages.map((message) => {
|
|
3207
3513
|
const isUser = message.role === "user";
|
|
3208
3514
|
const isGenerating = !isUser && (message.status === "streaming" || message.status === "pending");
|
|
3209
|
-
return /* @__PURE__ */
|
|
3210
|
-
!isUser ? /* @__PURE__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
3212
|
-
/* @__PURE__ */
|
|
3213
|
-
/* @__PURE__ */
|
|
3214
|
-
/* @__PURE__ */
|
|
3215
|
-
!isUser ? /* @__PURE__ */
|
|
3515
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn("flex gap-3", isUser ? "justify-end" : "justify-start"), children: [
|
|
3516
|
+
!isUser ? /* @__PURE__ */ jsx27(ChatMessageAvatar, { role: message.role }) : null,
|
|
3517
|
+
/* @__PURE__ */ jsxs17("div", { className: cn("w-fit max-w-[92%] space-y-2", isUser && "flex flex-col items-end"), children: [
|
|
3518
|
+
/* @__PURE__ */ jsx27(ChatMessage, { message, texts: props.texts }),
|
|
3519
|
+
/* @__PURE__ */ jsx27("div", { className: cn("flex items-center gap-2", isUser && "justify-end"), children: isGenerating ? /* @__PURE__ */ jsx27(ChatMessageTypingFooter, {}) : /* @__PURE__ */ jsxs17(Fragment6, { children: [
|
|
3520
|
+
/* @__PURE__ */ jsx27(ChatMessageMeta, { roleLabel: message.roleLabel, timestampLabel: message.timestampLabel, isUser }),
|
|
3521
|
+
!isUser ? /* @__PURE__ */ jsx27(ChatMessageActionCopy, { message, texts: props.texts }) : null
|
|
3216
3522
|
] }) })
|
|
3217
3523
|
] }),
|
|
3218
|
-
isUser ? /* @__PURE__ */
|
|
3524
|
+
isUser ? /* @__PURE__ */ jsx27(ChatMessageAvatar, { role: message.role }) : null
|
|
3219
3525
|
] }, message.id);
|
|
3220
3526
|
}),
|
|
3221
|
-
props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */
|
|
3222
|
-
/* @__PURE__ */
|
|
3223
|
-
/* @__PURE__ */
|
|
3527
|
+
props.isSending && !hasRenderableAssistantDraft ? /* @__PURE__ */ jsxs17("div", { className: "flex justify-start gap-3", children: [
|
|
3528
|
+
/* @__PURE__ */ jsx27(ChatMessageAvatar, { role: "assistant" }),
|
|
3529
|
+
/* @__PURE__ */ jsx27("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 })
|
|
3224
3530
|
] }) : null
|
|
3225
3531
|
] });
|
|
3226
3532
|
}
|