@blade-hq/agent-react 1.2.1-beta.1 → 1.2.1-beta.11
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/README.md +8 -1
- package/dist/components/AssistantTurnBlock.d.ts +3 -1
- package/dist/components/FileCard.d.ts +16 -0
- package/dist/components/MarkdownContent.d.ts +8 -4
- package/dist/components/MessageList.d.ts +3 -1
- package/dist/index.js +399 -163
- package/dist/index.js.map +1 -1
- package/dist/lib/media-tags.d.ts +24 -0
- package/dist/style.css +146 -2
- package/package.json +2 -2
- package/public-api.md +2 -1
package/dist/index.js
CHANGED
|
@@ -173,6 +173,13 @@ var createLucideIcon = (iconName, iconNode) => {
|
|
|
173
173
|
return Component2;
|
|
174
174
|
};
|
|
175
175
|
|
|
176
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/archive.js
|
|
177
|
+
var Archive = createLucideIcon("Archive", [
|
|
178
|
+
["rect", { width: "20", height: "5", x: "2", y: "3", rx: "1", key: "1wp1u1" }],
|
|
179
|
+
["path", { d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8", key: "1s80jp" }],
|
|
180
|
+
["path", { d: "M10 12h4", key: "a56b0p" }]
|
|
181
|
+
]);
|
|
182
|
+
|
|
176
183
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-up.js
|
|
177
184
|
var ArrowUp = createLucideIcon("ArrowUp", [
|
|
178
185
|
["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
|
|
@@ -240,6 +247,31 @@ var Copy = createLucideIcon("Copy", [
|
|
|
240
247
|
["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
|
|
241
248
|
]);
|
|
242
249
|
|
|
250
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/download.js
|
|
251
|
+
var Download = createLucideIcon("Download", [
|
|
252
|
+
["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }],
|
|
253
|
+
["polyline", { points: "7 10 12 15 17 10", key: "2ggqvy" }],
|
|
254
|
+
["line", { x1: "12", x2: "12", y1: "15", y2: "3", key: "1vk2je" }]
|
|
255
|
+
]);
|
|
256
|
+
|
|
257
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-code-2.js
|
|
258
|
+
var FileCode2 = createLucideIcon("FileCode2", [
|
|
259
|
+
["path", { d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4", key: "1pf5j1" }],
|
|
260
|
+
["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
|
|
261
|
+
["path", { d: "m5 12-3 3 3 3", key: "oke12k" }],
|
|
262
|
+
["path", { d: "m9 18 3-3-3-3", key: "112psh" }]
|
|
263
|
+
]);
|
|
264
|
+
|
|
265
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js
|
|
266
|
+
var FileSpreadsheet = createLucideIcon("FileSpreadsheet", [
|
|
267
|
+
["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
|
|
268
|
+
["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
|
|
269
|
+
["path", { d: "M8 13h2", key: "yr2amv" }],
|
|
270
|
+
["path", { d: "M14 13h2", key: "un5t4a" }],
|
|
271
|
+
["path", { d: "M8 17h2", key: "2yhykz" }],
|
|
272
|
+
["path", { d: "M14 17h2", key: "10kma7" }]
|
|
273
|
+
]);
|
|
274
|
+
|
|
243
275
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-text.js
|
|
244
276
|
var FileText = createLucideIcon("FileText", [
|
|
245
277
|
["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
|
|
@@ -249,6 +281,31 @@ var FileText = createLucideIcon("FileText", [
|
|
|
249
281
|
["path", { d: "M16 17H8", key: "z1uh3a" }]
|
|
250
282
|
]);
|
|
251
283
|
|
|
284
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file.js
|
|
285
|
+
var File = createLucideIcon("File", [
|
|
286
|
+
["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
|
|
287
|
+
["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }]
|
|
288
|
+
]);
|
|
289
|
+
|
|
290
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/film.js
|
|
291
|
+
var Film = createLucideIcon("Film", [
|
|
292
|
+
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
|
|
293
|
+
["path", { d: "M7 3v18", key: "bbkbws" }],
|
|
294
|
+
["path", { d: "M3 7.5h4", key: "zfgn84" }],
|
|
295
|
+
["path", { d: "M3 12h18", key: "1i2n21" }],
|
|
296
|
+
["path", { d: "M3 16.5h4", key: "1230mu" }],
|
|
297
|
+
["path", { d: "M17 3v18", key: "in4fa5" }],
|
|
298
|
+
["path", { d: "M17 7.5h4", key: "myr1c1" }],
|
|
299
|
+
["path", { d: "M17 16.5h4", key: "go4c1d" }]
|
|
300
|
+
]);
|
|
301
|
+
|
|
302
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/image.js
|
|
303
|
+
var Image = createLucideIcon("Image", [
|
|
304
|
+
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
|
|
305
|
+
["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
|
|
306
|
+
["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
|
|
307
|
+
]);
|
|
308
|
+
|
|
252
309
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/layers.js
|
|
253
310
|
var Layers = createLucideIcon("Layers", [
|
|
254
311
|
[
|
|
@@ -312,6 +369,13 @@ var MessageSquare = createLucideIcon("MessageSquare", [
|
|
|
312
369
|
["path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z", key: "1lielz" }]
|
|
313
370
|
]);
|
|
314
371
|
|
|
372
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/music.js
|
|
373
|
+
var Music = createLucideIcon("Music", [
|
|
374
|
+
["path", { d: "M9 18V5l12-2v13", key: "1jmyc2" }],
|
|
375
|
+
["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
|
|
376
|
+
["circle", { cx: "18", cy: "16", r: "3", key: "1hluhg" }]
|
|
377
|
+
]);
|
|
378
|
+
|
|
315
379
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/square.js
|
|
316
380
|
var Square = createLucideIcon("Square", [
|
|
317
381
|
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]
|
|
@@ -337,7 +401,7 @@ var X = createLucideIcon("X", [
|
|
|
337
401
|
]);
|
|
338
402
|
|
|
339
403
|
// src/components/ChatView.tsx
|
|
340
|
-
import { useEffect as useEffect6, useState as
|
|
404
|
+
import { useEffect as useEffect6, useState as useState9 } from "react";
|
|
341
405
|
|
|
342
406
|
// src/lib/utils.ts
|
|
343
407
|
function cn(...inputs) {
|
|
@@ -378,7 +442,7 @@ function ChatInput({
|
|
|
378
442
|
void handleSend();
|
|
379
443
|
}
|
|
380
444
|
};
|
|
381
|
-
return /* @__PURE__ */ jsx2("div", { className: cn("blade-chat-input border-t border-[hsl(var(--border))]
|
|
445
|
+
return /* @__PURE__ */ jsx2("div", { className: cn("blade-chat-input border-t border-[hsl(var(--border))] py-3", className), children: /* @__PURE__ */ jsxs("div", { className: "blade-chat-input-inner mx-auto flex max-w-[748px] items-end gap-2 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2", children: [
|
|
382
446
|
/* @__PURE__ */ jsx2(
|
|
383
447
|
"textarea",
|
|
384
448
|
{
|
|
@@ -877,7 +941,7 @@ function useStickToBottomContext() {
|
|
|
877
941
|
|
|
878
942
|
// src/components/AssistantTurnBlock.tsx
|
|
879
943
|
import { getTextContent, normalizeMessageContent } from "@blade-hq/agent-client";
|
|
880
|
-
import { useState as
|
|
944
|
+
import { useState as useState8 } from "react";
|
|
881
945
|
|
|
882
946
|
// src/components/AgentLoopBlock.tsx
|
|
883
947
|
import { useState as useState3 } from "react";
|
|
@@ -1080,14 +1144,142 @@ import {
|
|
|
1080
1144
|
useEffect as useEffect3,
|
|
1081
1145
|
useMemo as useMemo4,
|
|
1082
1146
|
useRef as useRef4,
|
|
1083
|
-
useState as
|
|
1147
|
+
useState as useState5
|
|
1084
1148
|
} from "react";
|
|
1149
|
+
|
|
1150
|
+
// src/lib/media-tags.ts
|
|
1151
|
+
var FILE_CARD_TAG = "blade-file-card";
|
|
1152
|
+
var MEDIA_LINE_RE = /^[ \t]*(?:[-*+][ \t]+|\d+\.[ \t]+)?(?<wrap>[`"'*_]*)MEDIA:[ \t]*(?<path>.+?)\k<wrap>[ \t]*[。,、;;,]?[ \t]*\r?$/gm;
|
|
1153
|
+
var MEDIA_LINE_START_RE = /^[ \t]*(?:[-*+][ \t]+|\d+\.[ \t]+)?[`"'*_]*MEDIA:/;
|
|
1154
|
+
function basename(path) {
|
|
1155
|
+
return path.split(/[/\\]/).filter(Boolean).pop() || path;
|
|
1156
|
+
}
|
|
1157
|
+
function unwrapMediaPath(path) {
|
|
1158
|
+
if (!path.startsWith("<")) return path;
|
|
1159
|
+
const closingBracket = path.indexOf(">");
|
|
1160
|
+
if (closingBracket < 0) return null;
|
|
1161
|
+
return `${path.slice(1, closingBracket)}${path.slice(closingBracket + 1)}`;
|
|
1162
|
+
}
|
|
1163
|
+
function isSafeMediaPath(path) {
|
|
1164
|
+
if (!path) return false;
|
|
1165
|
+
return !path.split(/[/\\]/).includes("..");
|
|
1166
|
+
}
|
|
1167
|
+
function escapeAttribute(value) {
|
|
1168
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
1169
|
+
}
|
|
1170
|
+
function foldMediaLines(text) {
|
|
1171
|
+
return text.replace(MEDIA_LINE_RE, (match, _wrap, rawPath) => {
|
|
1172
|
+
const path = unwrapMediaPath(rawPath);
|
|
1173
|
+
if (path === null) return match;
|
|
1174
|
+
const name = basename(path);
|
|
1175
|
+
if (!isSafeMediaPath(path)) {
|
|
1176
|
+
return `\`${name}\``;
|
|
1177
|
+
}
|
|
1178
|
+
return `<${FILE_CARD_TAG} data-path="${escapeAttribute(path)}" data-name="${escapeAttribute(name)}">${escapeAttribute(name)}</${FILE_CARD_TAG}>`;
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
function collapseMediaTags(text, options) {
|
|
1182
|
+
if (!text.includes("MEDIA:")) return text;
|
|
1183
|
+
if (!options?.streaming) return foldMediaLines(text);
|
|
1184
|
+
const newlineIndex = text.lastIndexOf("\n");
|
|
1185
|
+
const head = newlineIndex < 0 ? "" : text.slice(0, newlineIndex + 1);
|
|
1186
|
+
const lastLine = newlineIndex < 0 ? text : text.slice(newlineIndex + 1);
|
|
1187
|
+
if (MEDIA_LINE_START_RE.test(lastLine)) {
|
|
1188
|
+
return foldMediaLines(head);
|
|
1189
|
+
}
|
|
1190
|
+
return foldMediaLines(head) + lastLine;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/components/FileCard.tsx
|
|
1194
|
+
import { useState as useState4 } from "react";
|
|
1085
1195
|
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1196
|
+
var IMAGE_EXTS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "svg", "webp", "ico", "bmp"]);
|
|
1197
|
+
var SHEET_EXTS = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb", "csv"]);
|
|
1198
|
+
var TEXT_EXTS = /* @__PURE__ */ new Set(["txt", "md", "markdown", "pdf", "doc", "docx", "rtf"]);
|
|
1199
|
+
var CODE_EXTS = /* @__PURE__ */ new Set(["js", "jsx", "ts", "tsx", "py", "go", "json", "yaml", "yml", "html", "css"]);
|
|
1200
|
+
var VIDEO_EXTS = /* @__PURE__ */ new Set(["mp4", "webm", "mov", "mkv", "avi"]);
|
|
1201
|
+
var AUDIO_EXTS = /* @__PURE__ */ new Set(["mp3", "wav", "ogg", "m4a", "flac"]);
|
|
1202
|
+
var ARCHIVE_EXTS = /* @__PURE__ */ new Set(["zip", "tar", "gz", "tgz", "rar", "7z"]);
|
|
1203
|
+
function getFileIcon(name) {
|
|
1204
|
+
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
|
1205
|
+
if (IMAGE_EXTS.has(ext)) return Image;
|
|
1206
|
+
if (SHEET_EXTS.has(ext)) return FileSpreadsheet;
|
|
1207
|
+
if (TEXT_EXTS.has(ext)) return FileText;
|
|
1208
|
+
if (CODE_EXTS.has(ext)) return FileCode2;
|
|
1209
|
+
if (VIDEO_EXTS.has(ext)) return Film;
|
|
1210
|
+
if (AUDIO_EXTS.has(ext)) return Music;
|
|
1211
|
+
if (ARCHIVE_EXTS.has(ext)) return Archive;
|
|
1212
|
+
return File;
|
|
1213
|
+
}
|
|
1214
|
+
function stringValue(value) {
|
|
1215
|
+
return typeof value === "string" ? value : void 0;
|
|
1216
|
+
}
|
|
1217
|
+
function extractChildrenText(children) {
|
|
1218
|
+
if (typeof children === "string") return children;
|
|
1219
|
+
if (Array.isArray(children)) return children.map(extractChildrenText).join("");
|
|
1220
|
+
if (children && typeof children === "object" && "props" in children) {
|
|
1221
|
+
return extractChildrenText(children.props?.children);
|
|
1222
|
+
}
|
|
1223
|
+
return "";
|
|
1224
|
+
}
|
|
1225
|
+
function FileCard({
|
|
1226
|
+
node,
|
|
1227
|
+
"data-path": pathAttribute,
|
|
1228
|
+
"data-name": nameAttribute,
|
|
1229
|
+
dataPath,
|
|
1230
|
+
dataName,
|
|
1231
|
+
sessionId,
|
|
1232
|
+
children,
|
|
1233
|
+
className,
|
|
1234
|
+
...props
|
|
1235
|
+
}) {
|
|
1236
|
+
const client = useBladeClient();
|
|
1237
|
+
const [downloading, setDownloading] = useState4(false);
|
|
1238
|
+
const [failed, setFailed] = useState4(false);
|
|
1239
|
+
const nodeProperties = node && typeof node === "object" && "properties" in node ? node.properties : void 0;
|
|
1240
|
+
const path = pathAttribute ?? dataPath ?? stringValue(nodeProperties?.["data-path"]) ?? stringValue(nodeProperties?.dataPath) ?? "";
|
|
1241
|
+
const name = nameAttribute ?? dataName ?? stringValue(nodeProperties?.["data-name"]) ?? stringValue(nodeProperties?.dataName) ?? extractChildrenText(children) ?? "";
|
|
1242
|
+
const disabled = !sessionId || !isSafeMediaPath(path);
|
|
1243
|
+
const Icon2 = getFileIcon(name);
|
|
1244
|
+
const handleDownload = async () => {
|
|
1245
|
+
if (disabled || downloading || !sessionId) return;
|
|
1246
|
+
setDownloading(true);
|
|
1247
|
+
setFailed(false);
|
|
1248
|
+
try {
|
|
1249
|
+
await client.sessions.downloadFile(sessionId, path, name);
|
|
1250
|
+
} catch {
|
|
1251
|
+
setFailed(true);
|
|
1252
|
+
} finally {
|
|
1253
|
+
setDownloading(false);
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
return /* @__PURE__ */ jsxs4("span", { ...props, className: cn("blade-chat-file-card", className), children: [
|
|
1257
|
+
/* @__PURE__ */ jsxs4(
|
|
1258
|
+
"button",
|
|
1259
|
+
{
|
|
1260
|
+
type: "button",
|
|
1261
|
+
onClick: handleDownload,
|
|
1262
|
+
disabled: disabled || downloading,
|
|
1263
|
+
"aria-label": `\u4E0B\u8F7D\u6587\u4EF6\uFF1A${name}`,
|
|
1264
|
+
title: failed ? "\u4E0B\u8F7D\u5931\u8D25\uFF0C\u70B9\u51FB\u91CD\u8BD5" : `\u4E0B\u8F7D ${name}`,
|
|
1265
|
+
children: [
|
|
1266
|
+
/* @__PURE__ */ jsx5("span", { className: "blade-chat-file-card-icon", children: downloading ? /* @__PURE__ */ jsx5(LoaderCircle, { size: 15, className: "animate-spin" }) : /* @__PURE__ */ jsx5(Icon2, { size: 15 }) }),
|
|
1267
|
+
/* @__PURE__ */ jsx5("span", { className: "blade-chat-file-card-name", children: name }),
|
|
1268
|
+
/* @__PURE__ */ jsx5(Download, { size: 13, className: "blade-chat-file-card-action" })
|
|
1269
|
+
]
|
|
1270
|
+
}
|
|
1271
|
+
),
|
|
1272
|
+
failed && /* @__PURE__ */ jsx5("span", { className: "blade-chat-file-card-error", children: "\u4E0B\u8F7D\u5931\u8D25" })
|
|
1273
|
+
] });
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
// src/components/MarkdownContent.tsx
|
|
1277
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1086
1278
|
var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
1087
1279
|
function CodeBlockPre({ children, node: _node, ...props }) {
|
|
1088
1280
|
const preRef = useRef4(null);
|
|
1089
|
-
const [copied, setCopied] =
|
|
1090
|
-
const [language, setLanguage] =
|
|
1281
|
+
const [copied, setCopied] = useState5(false);
|
|
1282
|
+
const [language, setLanguage] = useState5("");
|
|
1091
1283
|
useEffect3(() => {
|
|
1092
1284
|
const codeEl = preRef.current?.querySelector("code");
|
|
1093
1285
|
setLanguage(codeEl?.className.match(/language-(\S+)/)?.[1] ?? "");
|
|
@@ -1099,10 +1291,10 @@ function CodeBlockPre({ children, node: _node, ...props }) {
|
|
|
1099
1291
|
setTimeout(() => setCopied(false), 2e3);
|
|
1100
1292
|
}
|
|
1101
1293
|
};
|
|
1102
|
-
return /* @__PURE__ */
|
|
1103
|
-
/* @__PURE__ */
|
|
1104
|
-
/* @__PURE__ */
|
|
1105
|
-
/* @__PURE__ */
|
|
1294
|
+
return /* @__PURE__ */ jsxs5("div", { className: "blade-chat-codeblock not-prose my-3 overflow-hidden rounded-xl border border-[hsl(var(--border))]", children: [
|
|
1295
|
+
/* @__PURE__ */ jsxs5("div", { className: "blade-chat-codeblock-header flex h-[34px] items-center justify-between border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] pl-3.5 pr-1.5", children: [
|
|
1296
|
+
/* @__PURE__ */ jsx6("span", { className: "font-mono text-[12px] text-[hsl(var(--muted-foreground))]", children: language || "code" }),
|
|
1297
|
+
/* @__PURE__ */ jsxs5(
|
|
1106
1298
|
"button",
|
|
1107
1299
|
{
|
|
1108
1300
|
type: "button",
|
|
@@ -1112,13 +1304,13 @@ function CodeBlockPre({ children, node: _node, ...props }) {
|
|
|
1112
1304
|
copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"
|
|
1113
1305
|
),
|
|
1114
1306
|
children: [
|
|
1115
|
-
copied ? /* @__PURE__ */
|
|
1116
|
-
/* @__PURE__ */
|
|
1307
|
+
copied ? /* @__PURE__ */ jsx6(Check, { size: 12 }) : /* @__PURE__ */ jsx6(Copy, { size: 12 }),
|
|
1308
|
+
/* @__PURE__ */ jsx6("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
|
|
1117
1309
|
]
|
|
1118
1310
|
}
|
|
1119
1311
|
)
|
|
1120
1312
|
] }),
|
|
1121
|
-
/* @__PURE__ */
|
|
1313
|
+
/* @__PURE__ */ jsx6(
|
|
1122
1314
|
"pre",
|
|
1123
1315
|
{
|
|
1124
1316
|
ref: preRef,
|
|
@@ -1130,37 +1322,54 @@ function CodeBlockPre({ children, node: _node, ...props }) {
|
|
|
1130
1322
|
] });
|
|
1131
1323
|
}
|
|
1132
1324
|
function ExternalAnchor({ node: _node, children, ...props }) {
|
|
1133
|
-
return /* @__PURE__ */
|
|
1325
|
+
return /* @__PURE__ */ jsx6("a", { ...props, target: "_blank", rel: "noopener noreferrer", children });
|
|
1134
1326
|
}
|
|
1135
1327
|
var MARKDOWN_COMPONENTS = {
|
|
1136
1328
|
pre: CodeBlockPre,
|
|
1137
1329
|
a: ExternalAnchor
|
|
1138
1330
|
};
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1331
|
+
var CUSTOM_ALLOWED_TAGS = {
|
|
1332
|
+
[FILE_CARD_TAG]: ["dataPath", "dataName", "data-path", "data-name"]
|
|
1333
|
+
};
|
|
1334
|
+
function MarkdownContent({ children, className, mode, sessionId }) {
|
|
1335
|
+
const streaming = mode === "streaming";
|
|
1336
|
+
const resolvedChildren = useMemo4(() => {
|
|
1337
|
+
const withoutReminders = children.replace(SYSTEM_REMINDER_RE, "");
|
|
1338
|
+
if (!sessionId) return withoutReminders;
|
|
1339
|
+
return collapseMediaTags(withoutReminders, { streaming });
|
|
1340
|
+
}, [children, sessionId, streaming]);
|
|
1341
|
+
const components = useMemo4(
|
|
1342
|
+
() => ({
|
|
1343
|
+
...MARKDOWN_COMPONENTS,
|
|
1344
|
+
[FILE_CARD_TAG]: (fileCardProps) => /* @__PURE__ */ jsx6(FileCard, { ...fileCardProps, sessionId })
|
|
1345
|
+
}),
|
|
1346
|
+
[sessionId]
|
|
1347
|
+
);
|
|
1348
|
+
return /* @__PURE__ */ jsx6(
|
|
1142
1349
|
_r,
|
|
1143
1350
|
{
|
|
1144
1351
|
className: cn("blade-chat-markdown break-words", className),
|
|
1145
1352
|
mode: mode ?? "static",
|
|
1146
|
-
components
|
|
1353
|
+
components,
|
|
1354
|
+
allowedTags: CUSTOM_ALLOWED_TAGS,
|
|
1147
1355
|
children: resolvedChildren
|
|
1148
|
-
}
|
|
1356
|
+
},
|
|
1357
|
+
sessionId ?? "no-session"
|
|
1149
1358
|
);
|
|
1150
1359
|
}
|
|
1151
1360
|
|
|
1152
1361
|
// src/components/Shimmer.tsx
|
|
1153
|
-
import { jsx as
|
|
1362
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1154
1363
|
function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
|
|
1155
|
-
return /* @__PURE__ */
|
|
1364
|
+
return /* @__PURE__ */ jsx7("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
|
|
1156
1365
|
}
|
|
1157
1366
|
|
|
1158
1367
|
// src/components/ToolCallBlock.tsx
|
|
1159
|
-
import { useState as
|
|
1368
|
+
import { useState as useState7 } from "react";
|
|
1160
1369
|
|
|
1161
1370
|
// src/components/AskUserQuestionBlock.tsx
|
|
1162
|
-
import { useEffect as useEffect4, useMemo as useMemo5, useState as
|
|
1163
|
-
import { jsx as
|
|
1371
|
+
import { useEffect as useEffect4, useMemo as useMemo5, useState as useState6 } from "react";
|
|
1372
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1164
1373
|
function AskUserQuestionBlock({
|
|
1165
1374
|
data,
|
|
1166
1375
|
answered,
|
|
@@ -1169,10 +1378,10 @@ function AskUserQuestionBlock({
|
|
|
1169
1378
|
answerData,
|
|
1170
1379
|
onAnswer
|
|
1171
1380
|
}) {
|
|
1172
|
-
const [selections, setSelections] =
|
|
1173
|
-
const [customTexts, setCustomTexts] =
|
|
1174
|
-
const [usingCustom, setUsingCustom] =
|
|
1175
|
-
const [submitted, setSubmitted] =
|
|
1381
|
+
const [selections, setSelections] = useState6(/* @__PURE__ */ new Map());
|
|
1382
|
+
const [customTexts, setCustomTexts] = useState6(/* @__PURE__ */ new Map());
|
|
1383
|
+
const [usingCustom, setUsingCustom] = useState6(/* @__PURE__ */ new Set());
|
|
1384
|
+
const [submitted, setSubmitted] = useState6(false);
|
|
1176
1385
|
useEffect4(() => {
|
|
1177
1386
|
if (sessionStatus === "failed" || sessionStatus === "interrupted") {
|
|
1178
1387
|
setSubmitted(false);
|
|
@@ -1263,7 +1472,7 @@ ${parts.join("\n")}`;
|
|
|
1263
1472
|
setSubmitted(true);
|
|
1264
1473
|
onAnswer(text, toolCallId, nextAnswerData);
|
|
1265
1474
|
};
|
|
1266
|
-
return /* @__PURE__ */
|
|
1475
|
+
return /* @__PURE__ */ jsxs6(
|
|
1267
1476
|
"div",
|
|
1268
1477
|
{
|
|
1269
1478
|
className: cn(
|
|
@@ -1271,12 +1480,12 @@ ${parts.join("\n")}`;
|
|
|
1271
1480
|
answered ? "max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80" : "max-w-lg space-y-5 p-4 text-sm"
|
|
1272
1481
|
),
|
|
1273
1482
|
children: [
|
|
1274
|
-
data.source_loop?.description && /* @__PURE__ */
|
|
1483
|
+
data.source_loop?.description && /* @__PURE__ */ jsxs6("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
|
|
1275
1484
|
"\u5B50\u667A\u80FD\u4F53\u300C",
|
|
1276
1485
|
data.source_loop.description,
|
|
1277
1486
|
"\u300D\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54"
|
|
1278
1487
|
] }),
|
|
1279
|
-
data.questions.map((q, qIdx) => /* @__PURE__ */
|
|
1488
|
+
data.questions.map((q, qIdx) => /* @__PURE__ */ jsx8(
|
|
1280
1489
|
QuestionCard,
|
|
1281
1490
|
{
|
|
1282
1491
|
question: q,
|
|
@@ -1291,7 +1500,7 @@ ${parts.join("\n")}`;
|
|
|
1291
1500
|
},
|
|
1292
1501
|
q.question
|
|
1293
1502
|
)),
|
|
1294
|
-
!answered && !submitted && onAnswer && /* @__PURE__ */
|
|
1503
|
+
!answered && !submitted && onAnswer && /* @__PURE__ */ jsx8(
|
|
1295
1504
|
"button",
|
|
1296
1505
|
{
|
|
1297
1506
|
type: "button",
|
|
@@ -1301,14 +1510,14 @@ ${parts.join("\n")}`;
|
|
|
1301
1510
|
children: allAnswered ? "\u786E\u8BA4" : "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u9009\u9879"
|
|
1302
1511
|
}
|
|
1303
1512
|
),
|
|
1304
|
-
submitted && !answered && /* @__PURE__ */
|
|
1513
|
+
submitted && !answered && /* @__PURE__ */ jsxs6(
|
|
1305
1514
|
"button",
|
|
1306
1515
|
{
|
|
1307
1516
|
type: "button",
|
|
1308
1517
|
disabled: true,
|
|
1309
1518
|
className: "flex w-full items-center justify-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] opacity-80",
|
|
1310
1519
|
children: [
|
|
1311
|
-
/* @__PURE__ */
|
|
1520
|
+
/* @__PURE__ */ jsx8(LoaderCircle, { size: 14, className: "animate-spin" }),
|
|
1312
1521
|
"\u786E\u8BA4\u4E2D"
|
|
1313
1522
|
]
|
|
1314
1523
|
}
|
|
@@ -1329,30 +1538,30 @@ function QuestionCard({
|
|
|
1329
1538
|
onCustomChange
|
|
1330
1539
|
}) {
|
|
1331
1540
|
const multi = question.multiSelect ?? false;
|
|
1332
|
-
return /* @__PURE__ */
|
|
1333
|
-
/* @__PURE__ */
|
|
1334
|
-
/* @__PURE__ */
|
|
1541
|
+
return /* @__PURE__ */ jsxs6("div", { children: [
|
|
1542
|
+
/* @__PURE__ */ jsxs6("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
|
|
1543
|
+
/* @__PURE__ */ jsx8(
|
|
1335
1544
|
MessageSquareMore,
|
|
1336
1545
|
{
|
|
1337
1546
|
size: answered ? 12 : 13,
|
|
1338
1547
|
className: "mt-0.5 shrink-0 text-[hsl(var(--primary))]"
|
|
1339
1548
|
}
|
|
1340
1549
|
),
|
|
1341
|
-
/* @__PURE__ */
|
|
1550
|
+
/* @__PURE__ */ jsx8(
|
|
1342
1551
|
"div",
|
|
1343
1552
|
{
|
|
1344
1553
|
className: cn(
|
|
1345
1554
|
"min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]",
|
|
1346
1555
|
answered ? "text-xs" : "text-sm"
|
|
1347
1556
|
),
|
|
1348
|
-
children: /* @__PURE__ */
|
|
1557
|
+
children: /* @__PURE__ */ jsx8(MarkdownContent, { className: "blade-chat-prose", children: question.question })
|
|
1349
1558
|
}
|
|
1350
1559
|
)
|
|
1351
1560
|
] }),
|
|
1352
|
-
/* @__PURE__ */
|
|
1561
|
+
/* @__PURE__ */ jsxs6("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
|
|
1353
1562
|
question.options.map((opt, optIdx) => {
|
|
1354
1563
|
const isSel = selected.has(optIdx);
|
|
1355
|
-
return /* @__PURE__ */
|
|
1564
|
+
return /* @__PURE__ */ jsxs6(
|
|
1356
1565
|
"button",
|
|
1357
1566
|
{
|
|
1358
1567
|
type: "button",
|
|
@@ -1366,14 +1575,14 @@ function QuestionCard({
|
|
|
1366
1575
|
answered && "cursor-default opacity-70"
|
|
1367
1576
|
),
|
|
1368
1577
|
children: [
|
|
1369
|
-
multi && /* @__PURE__ */
|
|
1578
|
+
multi && /* @__PURE__ */ jsx8(
|
|
1370
1579
|
"div",
|
|
1371
1580
|
{
|
|
1372
1581
|
className: cn(
|
|
1373
1582
|
"mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
|
|
1374
1583
|
isSel && !answered ? "border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]" : isSel ? "border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]" : "border-[hsl(var(--border))]"
|
|
1375
1584
|
),
|
|
1376
|
-
children: isSel && /* @__PURE__ */
|
|
1585
|
+
children: isSel && /* @__PURE__ */ jsx8(
|
|
1377
1586
|
Check,
|
|
1378
1587
|
{
|
|
1379
1588
|
size: 9,
|
|
@@ -1382,9 +1591,9 @@ function QuestionCard({
|
|
|
1382
1591
|
)
|
|
1383
1592
|
}
|
|
1384
1593
|
),
|
|
1385
|
-
/* @__PURE__ */
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
opt.description && /* @__PURE__ */
|
|
1594
|
+
/* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
|
|
1595
|
+
/* @__PURE__ */ jsx8("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
|
|
1596
|
+
opt.description && /* @__PURE__ */ jsx8(
|
|
1388
1597
|
"div",
|
|
1389
1598
|
{
|
|
1390
1599
|
className: cn(
|
|
@@ -1401,7 +1610,7 @@ function QuestionCard({
|
|
|
1401
1610
|
opt.label
|
|
1402
1611
|
);
|
|
1403
1612
|
}),
|
|
1404
|
-
answered && !isCustom ? null : /* @__PURE__ */
|
|
1613
|
+
answered && !isCustom ? null : /* @__PURE__ */ jsxs6(
|
|
1405
1614
|
"div",
|
|
1406
1615
|
{
|
|
1407
1616
|
className: cn(
|
|
@@ -1411,8 +1620,8 @@ function QuestionCard({
|
|
|
1411
1620
|
answered && "cursor-default opacity-70"
|
|
1412
1621
|
),
|
|
1413
1622
|
children: [
|
|
1414
|
-
/* @__PURE__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1623
|
+
/* @__PURE__ */ jsx8("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
|
|
1624
|
+
/* @__PURE__ */ jsx8(
|
|
1416
1625
|
"input",
|
|
1417
1626
|
{
|
|
1418
1627
|
type: "text",
|
|
@@ -1480,7 +1689,7 @@ function normalizeOptionItem(value) {
|
|
|
1480
1689
|
}
|
|
1481
1690
|
|
|
1482
1691
|
// src/components/ToolCallBlock.tsx
|
|
1483
|
-
import { Fragment, jsx as
|
|
1692
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1484
1693
|
function ToolCallBlock({
|
|
1485
1694
|
toolCall,
|
|
1486
1695
|
onAnswer,
|
|
@@ -1489,19 +1698,19 @@ function ToolCallBlock({
|
|
|
1489
1698
|
sessionStatus,
|
|
1490
1699
|
renderer
|
|
1491
1700
|
}) {
|
|
1492
|
-
const [expanded, setExpanded] =
|
|
1701
|
+
const [expanded, setExpanded] = useState7(false);
|
|
1493
1702
|
const normalizedName = formatToolName(toolCall.name);
|
|
1494
1703
|
if (renderer) {
|
|
1495
1704
|
const custom = renderer(toolCall);
|
|
1496
1705
|
if (custom !== null && custom !== void 0) {
|
|
1497
|
-
return /* @__PURE__ */
|
|
1706
|
+
return /* @__PURE__ */ jsx9(Fragment, { children: custom });
|
|
1498
1707
|
}
|
|
1499
1708
|
}
|
|
1500
1709
|
if (normalizedName === "AskUserQuestion") {
|
|
1501
1710
|
const askData = parseAskUserQuestion(typeof toolCall.result === "string" ? toolCall.result : null) ?? parseAskUserQuestion(buildAskUserPayload(toolCall.arguments));
|
|
1502
1711
|
const canAnswer = toolCall.status === "awaiting_answer" && Boolean(onAnswer);
|
|
1503
1712
|
if (askData) {
|
|
1504
|
-
return /* @__PURE__ */
|
|
1713
|
+
return /* @__PURE__ */ jsx9(
|
|
1505
1714
|
AskUserQuestionBlock,
|
|
1506
1715
|
{
|
|
1507
1716
|
data: askData,
|
|
@@ -1514,24 +1723,24 @@ function ToolCallBlock({
|
|
|
1514
1723
|
);
|
|
1515
1724
|
}
|
|
1516
1725
|
if (toolCall.status === "pending") {
|
|
1517
|
-
return /* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1726
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx9(LoaderCircle, { size: 14, className: "animate-spin" }),
|
|
1728
|
+
/* @__PURE__ */ jsx9("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
|
|
1520
1729
|
] });
|
|
1521
1730
|
}
|
|
1522
|
-
return /* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1731
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
|
|
1732
|
+
/* @__PURE__ */ jsx9("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
|
|
1733
|
+
/* @__PURE__ */ jsx9("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" })
|
|
1525
1734
|
] });
|
|
1526
1735
|
}
|
|
1527
1736
|
const tone = getToolTone(toolCall.status);
|
|
1528
1737
|
const displayName = getToolDisplayLabel(toolCall);
|
|
1529
1738
|
const toneClass = tone === "red" ? "border-l-[hsl(var(--muted-foreground)/0.5)]" : tone === "amber" ? "border-l-amber-400" : tone === "blue" ? "border-l-blue-500" : "border-l-[hsl(var(--primary))]";
|
|
1530
|
-
const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */
|
|
1739
|
+
const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx9(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx9(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx9(X, { size: 11 }) : /* @__PURE__ */ jsx9(Check, { size: 11 });
|
|
1531
1740
|
const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
|
|
1532
|
-
return /* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1741
|
+
return /* @__PURE__ */ jsxs7("div", { className: "blade-chat-tool ml-4 text-xs", children: [
|
|
1742
|
+
/* @__PURE__ */ jsxs7("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
|
|
1743
|
+
/* @__PURE__ */ jsxs7(
|
|
1535
1744
|
"button",
|
|
1536
1745
|
{
|
|
1537
1746
|
type: "button",
|
|
@@ -1539,7 +1748,7 @@ function ToolCallBlock({
|
|
|
1539
1748
|
className: "flex min-w-0 flex-1 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
|
|
1540
1749
|
"aria-expanded": expanded,
|
|
1541
1750
|
children: [
|
|
1542
|
-
/* @__PURE__ */
|
|
1751
|
+
/* @__PURE__ */ jsx9(
|
|
1543
1752
|
ChevronRight,
|
|
1544
1753
|
{
|
|
1545
1754
|
size: 11,
|
|
@@ -1549,24 +1758,24 @@ function ToolCallBlock({
|
|
|
1549
1758
|
)
|
|
1550
1759
|
}
|
|
1551
1760
|
),
|
|
1552
|
-
/* @__PURE__ */
|
|
1761
|
+
/* @__PURE__ */ jsxs7("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
|
|
1553
1762
|
statusIcon,
|
|
1554
|
-
/* @__PURE__ */
|
|
1763
|
+
/* @__PURE__ */ jsx9("span", { children: getToolStatusLabel(toolCall.status) })
|
|
1555
1764
|
] }),
|
|
1556
|
-
/* @__PURE__ */
|
|
1765
|
+
/* @__PURE__ */ jsx9("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
|
|
1557
1766
|
]
|
|
1558
1767
|
}
|
|
1559
1768
|
),
|
|
1560
|
-
typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */
|
|
1769
|
+
typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx9("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
|
|
1561
1770
|
] }),
|
|
1562
|
-
expanded && /* @__PURE__ */
|
|
1563
|
-
/* @__PURE__ */
|
|
1564
|
-
/* @__PURE__ */
|
|
1565
|
-
/* @__PURE__ */
|
|
1566
|
-
/* @__PURE__ */
|
|
1567
|
-
toolCall.result != null && /* @__PURE__ */
|
|
1568
|
-
/* @__PURE__ */
|
|
1569
|
-
/* @__PURE__ */
|
|
1771
|
+
expanded && /* @__PURE__ */ jsxs7("div", { className: "blade-chat-tool-detail ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
|
|
1772
|
+
/* @__PURE__ */ jsx9("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
|
|
1773
|
+
/* @__PURE__ */ jsx9("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
|
|
1774
|
+
/* @__PURE__ */ jsx9("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
|
|
1775
|
+
/* @__PURE__ */ jsx9("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
|
|
1776
|
+
toolCall.result != null && /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
1777
|
+
/* @__PURE__ */ jsx9("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
|
|
1778
|
+
/* @__PURE__ */ jsx9("pre", { className: "max-h-[400px] overflow-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolResult(toolCall.result) })
|
|
1570
1779
|
] })
|
|
1571
1780
|
] })
|
|
1572
1781
|
] });
|
|
@@ -1584,11 +1793,11 @@ function buildAskUserPayload(argumentsJson) {
|
|
|
1584
1793
|
}
|
|
1585
1794
|
|
|
1586
1795
|
// src/components/AssistantTurnBlock.tsx
|
|
1587
|
-
import { jsx as
|
|
1796
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1588
1797
|
function ThinkingBlock({ reasoning, isStreaming }) {
|
|
1589
|
-
const [open, setOpen] =
|
|
1590
|
-
return /* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1798
|
+
const [open, setOpen] = useState8(false);
|
|
1799
|
+
return /* @__PURE__ */ jsxs8("div", { className: "blade-chat-thinking ml-4 text-sm", children: [
|
|
1800
|
+
/* @__PURE__ */ jsxs8(
|
|
1592
1801
|
"button",
|
|
1593
1802
|
{
|
|
1594
1803
|
type: "button",
|
|
@@ -1596,9 +1805,14 @@ function ThinkingBlock({ reasoning, isStreaming }) {
|
|
|
1596
1805
|
"aria-expanded": open,
|
|
1597
1806
|
className: "inline-flex items-center gap-1.5 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
|
|
1598
1807
|
children: [
|
|
1599
|
-
/* @__PURE__ */
|
|
1600
|
-
isStreaming ? /* @__PURE__ */
|
|
1601
|
-
/* @__PURE__ */
|
|
1808
|
+
/* @__PURE__ */ jsx10(Brain, { size: 12, className: "shrink-0" }),
|
|
1809
|
+
isStreaming ? /* @__PURE__ */ jsx10(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }) : /* @__PURE__ */ jsx10("span", { children: "\u601D\u8003\u8FC7\u7A0B" }),
|
|
1810
|
+
/* @__PURE__ */ jsxs8("span", { className: "text-[hsl(var(--muted-foreground))]/70", children: [
|
|
1811
|
+
"\xB7 ",
|
|
1812
|
+
new Intl.NumberFormat("zh-CN").format(reasoning.length),
|
|
1813
|
+
" \u5B57"
|
|
1814
|
+
] }),
|
|
1815
|
+
/* @__PURE__ */ jsx10(
|
|
1602
1816
|
ChevronDown,
|
|
1603
1817
|
{
|
|
1604
1818
|
size: 12,
|
|
@@ -1608,47 +1822,57 @@ function ThinkingBlock({ reasoning, isStreaming }) {
|
|
|
1608
1822
|
]
|
|
1609
1823
|
}
|
|
1610
1824
|
),
|
|
1611
|
-
open && /* @__PURE__ */
|
|
1825
|
+
open && /* @__PURE__ */ jsx10("div", { className: "mt-1.5 whitespace-pre-wrap border-l-2 border-[hsl(var(--border))] pl-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: reasoning })
|
|
1612
1826
|
] });
|
|
1613
1827
|
}
|
|
1614
1828
|
function getMessageText(message) {
|
|
1615
1829
|
return getTextContent(normalizeMessageContent(message.content)).trim();
|
|
1616
1830
|
}
|
|
1831
|
+
function findLatestReasoningMessageIndex(messages) {
|
|
1832
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
1833
|
+
if (messages[index].reasoning) return index;
|
|
1834
|
+
}
|
|
1835
|
+
return -1;
|
|
1836
|
+
}
|
|
1617
1837
|
function AssistantTurnBlock({
|
|
1618
1838
|
messages,
|
|
1619
1839
|
isStreaming = false,
|
|
1620
1840
|
askAnswers,
|
|
1621
1841
|
onAnswer,
|
|
1622
1842
|
sessionStatus,
|
|
1623
|
-
toolCallRenderer
|
|
1843
|
+
toolCallRenderer,
|
|
1844
|
+
sessionId
|
|
1624
1845
|
}) {
|
|
1625
1846
|
const hasInterrupted = messages.some((message) => message.status === "interrupted");
|
|
1626
1847
|
const hasAnyContent = messages.some(
|
|
1627
1848
|
(message) => getMessageText(message) || message.reasoning || (message.tool_calls?.length ?? 0) > 0
|
|
1628
1849
|
);
|
|
1629
|
-
|
|
1630
|
-
|
|
1850
|
+
const latestReasoningIndex = isStreaming ? findLatestReasoningMessageIndex(messages) : -1;
|
|
1851
|
+
return /* @__PURE__ */ jsxs8("div", { className: "blade-chat-assistant-turn flex flex-col gap-3", children: [
|
|
1852
|
+
hasInterrupted && /* @__PURE__ */ jsx10("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
|
|
1631
1853
|
messages.map((message, index) => {
|
|
1632
1854
|
const isLast = index === messages.length - 1;
|
|
1633
1855
|
const streamingThis = isStreaming && isLast;
|
|
1634
1856
|
const text = getMessageText(message);
|
|
1635
1857
|
const toolCalls = message.tool_calls ?? [];
|
|
1636
|
-
|
|
1858
|
+
const showReasoning = !!message.reasoning && (!isStreaming || index === latestReasoningIndex);
|
|
1859
|
+
return /* @__PURE__ */ jsxs8(
|
|
1637
1860
|
"div",
|
|
1638
1861
|
{
|
|
1639
1862
|
className: "flex flex-col gap-3",
|
|
1640
1863
|
children: [
|
|
1641
|
-
message.reasoning && /* @__PURE__ */
|
|
1642
|
-
text && /* @__PURE__ */
|
|
1864
|
+
showReasoning && message.reasoning && /* @__PURE__ */ jsx10(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }),
|
|
1865
|
+
text && /* @__PURE__ */ jsx10("div", { className: "blade-chat-assistant-text text-[15px] leading-8 text-[hsl(var(--foreground))]", children: /* @__PURE__ */ jsx10(
|
|
1643
1866
|
MarkdownContent,
|
|
1644
1867
|
{
|
|
1645
1868
|
mode: streamingThis ? "streaming" : "static",
|
|
1646
1869
|
className: "blade-chat-prose",
|
|
1870
|
+
sessionId,
|
|
1647
1871
|
children: text
|
|
1648
1872
|
}
|
|
1649
1873
|
) }),
|
|
1650
|
-
toolCalls.length > 0 && /* @__PURE__ */
|
|
1651
|
-
(toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */
|
|
1874
|
+
toolCalls.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-2", children: toolCalls.map(
|
|
1875
|
+
(toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx10(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx10(
|
|
1652
1876
|
ToolCallBlock,
|
|
1653
1877
|
{
|
|
1654
1878
|
toolCall,
|
|
@@ -1666,13 +1890,13 @@ function AssistantTurnBlock({
|
|
|
1666
1890
|
message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
|
|
1667
1891
|
);
|
|
1668
1892
|
}),
|
|
1669
|
-
isStreaming && !hasAnyContent && /* @__PURE__ */
|
|
1893
|
+
isStreaming && !hasAnyContent && /* @__PURE__ */ jsx10(Shimmer, { className: "ml-4", children: "\u6B63\u5728\u751F\u6210..." })
|
|
1670
1894
|
] });
|
|
1671
1895
|
}
|
|
1672
1896
|
|
|
1673
1897
|
// src/components/RenderErrorBoundary.tsx
|
|
1674
1898
|
import { Component } from "react";
|
|
1675
|
-
import { jsx as
|
|
1899
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1676
1900
|
function getFirstComponentName(componentStack) {
|
|
1677
1901
|
const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
|
|
1678
1902
|
return match?.[1] ?? null;
|
|
@@ -1705,18 +1929,18 @@ var RenderErrorBoundary = class extends Component {
|
|
|
1705
1929
|
return children;
|
|
1706
1930
|
}
|
|
1707
1931
|
const componentName = getFirstComponentName(componentStack);
|
|
1708
|
-
return /* @__PURE__ */
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
1932
|
+
return /* @__PURE__ */ jsx11("div", { className: "blade-chat-render-error rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-2", children: [
|
|
1933
|
+
/* @__PURE__ */ jsx11(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
|
|
1934
|
+
/* @__PURE__ */ jsxs9("div", { className: "min-w-0 flex-1", children: [
|
|
1935
|
+
/* @__PURE__ */ jsxs9("div", { className: "font-medium", children: [
|
|
1712
1936
|
label,
|
|
1713
1937
|
"\u6E32\u67D3\u5931\u8D25"
|
|
1714
1938
|
] }),
|
|
1715
|
-
/* @__PURE__ */
|
|
1939
|
+
/* @__PURE__ */ jsxs9("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
|
|
1716
1940
|
componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
|
|
1717
1941
|
error.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
|
|
1718
1942
|
] }),
|
|
1719
|
-
details ? /* @__PURE__ */
|
|
1943
|
+
details ? /* @__PURE__ */ jsx11("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
|
|
1720
1944
|
] })
|
|
1721
1945
|
] }) });
|
|
1722
1946
|
}
|
|
@@ -1724,7 +1948,7 @@ var RenderErrorBoundary = class extends Component {
|
|
|
1724
1948
|
|
|
1725
1949
|
// src/components/UserMessageBubble.tsx
|
|
1726
1950
|
import { getFileParts, getImageParts, getTextContent as getTextContent2 } from "@blade-hq/agent-client";
|
|
1727
|
-
import { jsx as
|
|
1951
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1728
1952
|
function isUserMessage(message) {
|
|
1729
1953
|
return message.role === "user";
|
|
1730
1954
|
}
|
|
@@ -1736,8 +1960,8 @@ function UserMessageBubble({ message, className }) {
|
|
|
1736
1960
|
const text = getTextContent2(message.content).trim();
|
|
1737
1961
|
const fileParts = getFileParts(message.content);
|
|
1738
1962
|
const imageParts = getImageParts(message.content);
|
|
1739
|
-
return /* @__PURE__ */
|
|
1740
|
-
imageParts.length > 0 && /* @__PURE__ */
|
|
1963
|
+
return /* @__PURE__ */ jsx12("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsxs10("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: [
|
|
1964
|
+
imageParts.length > 0 && /* @__PURE__ */ jsx12("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx12(
|
|
1741
1965
|
"img",
|
|
1742
1966
|
{
|
|
1743
1967
|
src: part.image_url.url,
|
|
@@ -1746,21 +1970,21 @@ function UserMessageBubble({ message, className }) {
|
|
|
1746
1970
|
},
|
|
1747
1971
|
part.image_url.url
|
|
1748
1972
|
)) }),
|
|
1749
|
-
fileParts.length > 0 && /* @__PURE__ */
|
|
1973
|
+
fileParts.length > 0 && /* @__PURE__ */ jsx12("div", { className: "flex flex-col items-end gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs10(
|
|
1750
1974
|
"div",
|
|
1751
1975
|
{
|
|
1752
1976
|
className: "flex items-center gap-1.5 rounded-lg border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--muted)/0.3)] px-2.5 py-1.5 text-xs text-[hsl(var(--muted-foreground))]",
|
|
1753
1977
|
children: [
|
|
1754
|
-
/* @__PURE__ */
|
|
1755
|
-
/* @__PURE__ */
|
|
1978
|
+
/* @__PURE__ */ jsx12(FileText, { size: 12, className: "shrink-0" }),
|
|
1979
|
+
/* @__PURE__ */ jsx12("span", { className: "max-w-56 truncate", title: part.name, children: part.name })
|
|
1756
1980
|
]
|
|
1757
1981
|
},
|
|
1758
1982
|
`${part.name}-${part.data.length}`
|
|
1759
1983
|
)) }),
|
|
1760
|
-
text && /* @__PURE__ */
|
|
1761
|
-
text && isSending(message) && /* @__PURE__ */
|
|
1762
|
-
/* @__PURE__ */
|
|
1763
|
-
/* @__PURE__ */
|
|
1984
|
+
text && /* @__PURE__ */ jsx12("div", { className: "blade-chat-user-bubble max-w-full rounded-[20px] rounded-br-[6px] border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-[18px] py-[13px] text-sm leading-[1.65] text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx12(MarkdownContent, { className: "blade-chat-prose", children: text }) }),
|
|
1985
|
+
text && isSending(message) && /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
|
|
1986
|
+
/* @__PURE__ */ jsx12(LoaderCircle, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
|
|
1987
|
+
/* @__PURE__ */ jsx12("span", { children: "\u53D1\u9001\u4E2D" })
|
|
1764
1988
|
] })
|
|
1765
1989
|
] }) });
|
|
1766
1990
|
}
|
|
@@ -1769,11 +1993,11 @@ function ErrorMessageBlock({
|
|
|
1769
1993
|
className
|
|
1770
1994
|
}) {
|
|
1771
1995
|
const text = getTextContent2(message.content);
|
|
1772
|
-
return /* @__PURE__ */
|
|
1996
|
+
return /* @__PURE__ */ jsx12("div", { className: cn("blade-chat-error-row flex justify-center", className), children: /* @__PURE__ */ jsx12("div", { className: "blade-chat-error-block max-w-[85%] border-l-[3px] border-[hsl(var(--destructive))] px-4 py-1 text-sm leading-7 text-[hsl(var(--destructive))]", children: text }) });
|
|
1773
1997
|
}
|
|
1774
1998
|
|
|
1775
1999
|
// src/components/MessageList.tsx
|
|
1776
|
-
import { jsx as
|
|
2000
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1777
2001
|
function parseModeChange(message) {
|
|
1778
2002
|
if (message.kind !== "mode_change" || typeof message.content !== "string") {
|
|
1779
2003
|
return null;
|
|
@@ -1813,7 +2037,8 @@ function MessageList({
|
|
|
1813
2037
|
onAnswer,
|
|
1814
2038
|
toolCallRenderer,
|
|
1815
2039
|
emptyState,
|
|
1816
|
-
className
|
|
2040
|
+
className,
|
|
2041
|
+
sessionId
|
|
1817
2042
|
}) {
|
|
1818
2043
|
const renderBlocks = useMemo6(() => {
|
|
1819
2044
|
const visible = messages.filter((message) => {
|
|
@@ -1888,24 +2113,24 @@ function MessageList({
|
|
|
1888
2113
|
}
|
|
1889
2114
|
return blocks;
|
|
1890
2115
|
}, [messages, isStreaming]);
|
|
1891
|
-
return /* @__PURE__ */
|
|
1892
|
-
/* @__PURE__ */
|
|
1893
|
-
renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
1895
|
-
/* @__PURE__ */
|
|
1896
|
-
/* @__PURE__ */
|
|
2116
|
+
return /* @__PURE__ */ jsx13("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: /* @__PURE__ */ jsxs11(StickToBottom, { className: "h-full overflow-y-hidden", initial: "instant", resize: "instant", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx13(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsx13("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-col", children: [
|
|
2118
|
+
renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs11("div", { className: "blade-chat-empty", children: [
|
|
2119
|
+
/* @__PURE__ */ jsx13(MessageSquare, { size: 40, strokeWidth: 1.5 }),
|
|
2120
|
+
/* @__PURE__ */ jsx13("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
|
|
2121
|
+
/* @__PURE__ */ jsx13("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
|
|
1897
2122
|
] }) : renderBlocks.map((block) => {
|
|
1898
2123
|
if (block.type === "message") {
|
|
1899
|
-
return /* @__PURE__ */
|
|
2124
|
+
return /* @__PURE__ */ jsx13("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx13(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx13(ErrorMessageBlock, { message: block.message }) : null }, block.key);
|
|
1900
2125
|
}
|
|
1901
2126
|
if (block.type === "assistant_turn") {
|
|
1902
|
-
return /* @__PURE__ */
|
|
2127
|
+
return /* @__PURE__ */ jsx13("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsx13(
|
|
1903
2128
|
RenderErrorBoundary,
|
|
1904
2129
|
{
|
|
1905
2130
|
label: "\u52A9\u624B\u6D88\u606F",
|
|
1906
2131
|
details: block.key,
|
|
1907
2132
|
resetKey: getMessageResetSignature(block.messages),
|
|
1908
|
-
children: /* @__PURE__ */
|
|
2133
|
+
children: /* @__PURE__ */ jsx13(
|
|
1909
2134
|
AssistantTurnBlock,
|
|
1910
2135
|
{
|
|
1911
2136
|
messages: block.messages,
|
|
@@ -1913,31 +2138,32 @@ function MessageList({
|
|
|
1913
2138
|
askAnswers,
|
|
1914
2139
|
onAnswer,
|
|
1915
2140
|
sessionStatus,
|
|
1916
|
-
toolCallRenderer
|
|
2141
|
+
toolCallRenderer,
|
|
2142
|
+
sessionId
|
|
1917
2143
|
}
|
|
1918
2144
|
)
|
|
1919
2145
|
}
|
|
1920
2146
|
) }, block.key);
|
|
1921
2147
|
}
|
|
1922
2148
|
if (block.type === "compaction") {
|
|
1923
|
-
return /* @__PURE__ */
|
|
2149
|
+
return /* @__PURE__ */ jsxs11(
|
|
1924
2150
|
"div",
|
|
1925
2151
|
{
|
|
1926
2152
|
className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]",
|
|
1927
2153
|
children: [
|
|
1928
|
-
/* @__PURE__ */
|
|
1929
|
-
/* @__PURE__ */
|
|
2154
|
+
/* @__PURE__ */ jsx13(Layers, { size: 12 }),
|
|
2155
|
+
/* @__PURE__ */ jsx13("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
|
|
1930
2156
|
]
|
|
1931
2157
|
},
|
|
1932
2158
|
block.key
|
|
1933
2159
|
);
|
|
1934
2160
|
}
|
|
1935
|
-
return /* @__PURE__ */
|
|
2161
|
+
return /* @__PURE__ */ jsx13(PlanningDivider, { kind: block.kind }, block.key);
|
|
1936
2162
|
}),
|
|
1937
|
-
sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */
|
|
2163
|
+
sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx13("div", { className: "flex", children: /* @__PURE__ */ jsx13("div", { className: "rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }) }) : null
|
|
1938
2164
|
] }) }) }),
|
|
1939
|
-
/* @__PURE__ */
|
|
1940
|
-
/* @__PURE__ */
|
|
2165
|
+
/* @__PURE__ */ jsx13(AutoScrollOnUserSend, { userMessageCount: messages.filter((m) => isUserMessage(m)).length }),
|
|
2166
|
+
/* @__PURE__ */ jsx13(ScrollToBottomButton, {})
|
|
1941
2167
|
] }) });
|
|
1942
2168
|
}
|
|
1943
2169
|
function AutoScrollOnUserSend({ userMessageCount }) {
|
|
@@ -1954,38 +2180,39 @@ function AutoScrollOnUserSend({ userMessageCount }) {
|
|
|
1954
2180
|
function ScrollToBottomButton() {
|
|
1955
2181
|
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
|
|
1956
2182
|
if (isAtBottom) return null;
|
|
1957
|
-
return /* @__PURE__ */
|
|
2183
|
+
return /* @__PURE__ */ jsxs11(
|
|
1958
2184
|
"button",
|
|
1959
2185
|
{
|
|
1960
2186
|
type: "button",
|
|
1961
2187
|
onClick: () => scrollToBottom(),
|
|
1962
|
-
|
|
2188
|
+
"aria-label": "\u6EDA\u52A8\u5230\u5E95\u90E8",
|
|
2189
|
+
className: "blade-chat-scroll-bottom absolute bottom-4 right-4 flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-1.5 text-xs text-[hsl(var(--muted-foreground))] shadow-lg transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
|
|
1963
2190
|
children: [
|
|
1964
|
-
/* @__PURE__ */
|
|
1965
|
-
/* @__PURE__ */
|
|
2191
|
+
/* @__PURE__ */ jsx13(ChevronDown, { size: 14 }),
|
|
2192
|
+
/* @__PURE__ */ jsx13("span", { className: "blade-chat-scroll-bottom-label", children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
|
|
1966
2193
|
]
|
|
1967
2194
|
}
|
|
1968
2195
|
);
|
|
1969
2196
|
}
|
|
1970
2197
|
function PlanningDivider({ kind }) {
|
|
1971
|
-
return /* @__PURE__ */
|
|
1972
|
-
/* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
1975
|
-
/* @__PURE__ */
|
|
2198
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3 py-1", children: [
|
|
2199
|
+
/* @__PURE__ */ jsx13("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
|
|
2200
|
+
/* @__PURE__ */ jsxs11("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-amber-500/30 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-300", children: [
|
|
2201
|
+
/* @__PURE__ */ jsx13(Lightbulb, { size: 12 }),
|
|
2202
|
+
/* @__PURE__ */ jsx13("span", { children: kind === "enter" ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
|
|
1976
2203
|
] }),
|
|
1977
|
-
/* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsx13("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
|
|
1978
2205
|
] });
|
|
1979
2206
|
}
|
|
1980
2207
|
|
|
1981
2208
|
// src/components/ChatView.tsx
|
|
1982
|
-
import { jsx as
|
|
2209
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1983
2210
|
function isUnauthorizedError(error) {
|
|
1984
2211
|
return error instanceof BladeApiError && error.status === 401;
|
|
1985
2212
|
}
|
|
1986
2213
|
function LoginCard({ client, onLoggedIn }) {
|
|
1987
|
-
const [loggingIn, setLoggingIn] =
|
|
1988
|
-
const [loginError, setLoginError] =
|
|
2214
|
+
const [loggingIn, setLoggingIn] = useState9(false);
|
|
2215
|
+
const [loginError, setLoginError] = useState9(null);
|
|
1989
2216
|
const handleLogin = async () => {
|
|
1990
2217
|
setLoggingIn(true);
|
|
1991
2218
|
setLoginError(null);
|
|
@@ -1998,11 +2225,11 @@ function LoginCard({ client, onLoggedIn }) {
|
|
|
1998
2225
|
setLoggingIn(false);
|
|
1999
2226
|
}
|
|
2000
2227
|
};
|
|
2001
|
-
return /* @__PURE__ */
|
|
2002
|
-
/* @__PURE__ */
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
/* @__PURE__ */
|
|
2005
|
-
/* @__PURE__ */
|
|
2228
|
+
return /* @__PURE__ */ jsx14("div", { className: "blade-chat-login flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs12("div", { className: "flex w-full max-w-sm flex-col items-center gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-6 py-8 text-center", children: [
|
|
2229
|
+
/* @__PURE__ */ jsx14(LockKeyhole, { size: 28, className: "text-[hsl(var(--muted-foreground))]" }),
|
|
2230
|
+
/* @__PURE__ */ jsx14("div", { className: "text-base font-medium text-[hsl(var(--foreground))]", children: "\u9700\u8981\u767B\u5F55\u540E\u4F7F\u7528" }),
|
|
2231
|
+
/* @__PURE__ */ jsx14("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u767B\u5F55\u540E\u5373\u53EF\u4E0E\u667A\u80FD\u4F53\u5BF9\u8BDD\uFF0C\u4F60\u7684\u4F1A\u8BDD\u5185\u5BB9\u4EC5\u81EA\u5DF1\u53EF\u89C1\u3002" }),
|
|
2232
|
+
/* @__PURE__ */ jsx14(
|
|
2006
2233
|
"button",
|
|
2007
2234
|
{
|
|
2008
2235
|
type: "button",
|
|
@@ -2012,15 +2239,15 @@ function LoginCard({ client, onLoggedIn }) {
|
|
|
2012
2239
|
children: loggingIn ? "\u767B\u5F55\u4E2D\u2026" : "\u767B\u5F55"
|
|
2013
2240
|
}
|
|
2014
2241
|
),
|
|
2015
|
-
loginError && /* @__PURE__ */
|
|
2242
|
+
loginError && /* @__PURE__ */ jsx14("div", { className: "text-xs text-[hsl(var(--destructive))]", children: loginError })
|
|
2016
2243
|
] }) });
|
|
2017
2244
|
}
|
|
2018
2245
|
function ChatView(props) {
|
|
2019
2246
|
const client = useBladeClient();
|
|
2020
|
-
const [attempt, setAttempt] =
|
|
2021
|
-
const [needLogin, setNeedLogin] =
|
|
2247
|
+
const [attempt, setAttempt] = useState9(0);
|
|
2248
|
+
const [needLogin, setNeedLogin] = useState9(() => !client.hasToken());
|
|
2022
2249
|
if (needLogin) {
|
|
2023
|
-
return /* @__PURE__ */
|
|
2250
|
+
return /* @__PURE__ */ jsx14("div", { className: cn("blade-chat flex min-h-0 flex-1 flex-col", props.classNames?.root), children: /* @__PURE__ */ jsx14(
|
|
2024
2251
|
LoginCard,
|
|
2025
2252
|
{
|
|
2026
2253
|
client,
|
|
@@ -2031,7 +2258,7 @@ function ChatView(props) {
|
|
|
2031
2258
|
}
|
|
2032
2259
|
) });
|
|
2033
2260
|
}
|
|
2034
|
-
return /* @__PURE__ */
|
|
2261
|
+
return /* @__PURE__ */ jsx14(ChatSessionView, { ...props, onUnauthorized: () => setNeedLogin(true) }, attempt);
|
|
2035
2262
|
}
|
|
2036
2263
|
function ChatSessionView({
|
|
2037
2264
|
sessionId,
|
|
@@ -2049,8 +2276,8 @@ function ChatSessionView({
|
|
|
2049
2276
|
createOptions,
|
|
2050
2277
|
onSessionCreated
|
|
2051
2278
|
});
|
|
2052
|
-
const [stopRequested, setStopRequested] =
|
|
2053
|
-
const [inputText, setInputText] =
|
|
2279
|
+
const [stopRequested, setStopRequested] = useState9(false);
|
|
2280
|
+
const [inputText, setInputText] = useState9("");
|
|
2054
2281
|
useEffect6(() => {
|
|
2055
2282
|
if (session) {
|
|
2056
2283
|
onSessionReady?.(session);
|
|
@@ -2098,7 +2325,7 @@ ${content}`);
|
|
|
2098
2325
|
setStopRequested(true);
|
|
2099
2326
|
void session?.stop();
|
|
2100
2327
|
};
|
|
2101
|
-
return /* @__PURE__ */
|
|
2328
|
+
return /* @__PURE__ */ jsxs12(
|
|
2102
2329
|
"div",
|
|
2103
2330
|
{
|
|
2104
2331
|
className: cn(
|
|
@@ -2106,19 +2333,19 @@ ${content}`);
|
|
|
2106
2333
|
classNames?.root
|
|
2107
2334
|
),
|
|
2108
2335
|
children: [
|
|
2109
|
-
/* @__PURE__ */
|
|
2336
|
+
/* @__PURE__ */ jsx14(
|
|
2110
2337
|
ConnectionBanner,
|
|
2111
2338
|
{
|
|
2112
2339
|
connection: state?.connection ?? "connecting",
|
|
2113
2340
|
className: classNames?.banner
|
|
2114
2341
|
}
|
|
2115
2342
|
),
|
|
2116
|
-
errorMessage && /* @__PURE__ */
|
|
2117
|
-
/* @__PURE__ */
|
|
2118
|
-
/* @__PURE__ */
|
|
2343
|
+
errorMessage && /* @__PURE__ */ jsxs12("div", { className: "blade-chat-error-bar flex items-start gap-2 border-b border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800 dark:border-red-800/30 dark:bg-red-950/30 dark:text-red-300", children: [
|
|
2344
|
+
/* @__PURE__ */ jsx14(CircleAlert, { size: 16, className: "mt-0.5 shrink-0" }),
|
|
2345
|
+
/* @__PURE__ */ jsx14("span", { children: errorMessage })
|
|
2119
2346
|
] }),
|
|
2120
2347
|
slots?.header,
|
|
2121
|
-
/* @__PURE__ */
|
|
2348
|
+
/* @__PURE__ */ jsx14(
|
|
2122
2349
|
MessageList,
|
|
2123
2350
|
{
|
|
2124
2351
|
messages: state?.messages ?? [],
|
|
@@ -2133,10 +2360,11 @@ ${content}`);
|
|
|
2133
2360
|
},
|
|
2134
2361
|
toolCallRenderer: renderers?.toolCall,
|
|
2135
2362
|
emptyState: slots?.emptyState,
|
|
2136
|
-
className: classNames?.messageList
|
|
2363
|
+
className: classNames?.messageList,
|
|
2364
|
+
sessionId: session?.sessionId
|
|
2137
2365
|
}
|
|
2138
2366
|
),
|
|
2139
|
-
/* @__PURE__ */
|
|
2367
|
+
/* @__PURE__ */ jsx14(
|
|
2140
2368
|
ChatInput,
|
|
2141
2369
|
{
|
|
2142
2370
|
value: inputText,
|
|
@@ -2170,6 +2398,7 @@ lucide-react/dist/esm/shared/src/utils.js:
|
|
|
2170
2398
|
lucide-react/dist/esm/defaultAttributes.js:
|
|
2171
2399
|
lucide-react/dist/esm/Icon.js:
|
|
2172
2400
|
lucide-react/dist/esm/createLucideIcon.js:
|
|
2401
|
+
lucide-react/dist/esm/icons/archive.js:
|
|
2173
2402
|
lucide-react/dist/esm/icons/arrow-up.js:
|
|
2174
2403
|
lucide-react/dist/esm/icons/bot.js:
|
|
2175
2404
|
lucide-react/dist/esm/icons/brain.js:
|
|
@@ -2178,13 +2407,20 @@ lucide-react/dist/esm/icons/chevron-down.js:
|
|
|
2178
2407
|
lucide-react/dist/esm/icons/chevron-right.js:
|
|
2179
2408
|
lucide-react/dist/esm/icons/circle-alert.js:
|
|
2180
2409
|
lucide-react/dist/esm/icons/copy.js:
|
|
2410
|
+
lucide-react/dist/esm/icons/download.js:
|
|
2411
|
+
lucide-react/dist/esm/icons/file-code-2.js:
|
|
2412
|
+
lucide-react/dist/esm/icons/file-spreadsheet.js:
|
|
2181
2413
|
lucide-react/dist/esm/icons/file-text.js:
|
|
2414
|
+
lucide-react/dist/esm/icons/file.js:
|
|
2415
|
+
lucide-react/dist/esm/icons/film.js:
|
|
2416
|
+
lucide-react/dist/esm/icons/image.js:
|
|
2182
2417
|
lucide-react/dist/esm/icons/layers.js:
|
|
2183
2418
|
lucide-react/dist/esm/icons/lightbulb.js:
|
|
2184
2419
|
lucide-react/dist/esm/icons/loader-circle.js:
|
|
2185
2420
|
lucide-react/dist/esm/icons/lock-keyhole.js:
|
|
2186
2421
|
lucide-react/dist/esm/icons/message-square-more.js:
|
|
2187
2422
|
lucide-react/dist/esm/icons/message-square.js:
|
|
2423
|
+
lucide-react/dist/esm/icons/music.js:
|
|
2188
2424
|
lucide-react/dist/esm/icons/square.js:
|
|
2189
2425
|
lucide-react/dist/esm/icons/triangle-alert.js:
|
|
2190
2426
|
lucide-react/dist/esm/icons/x.js:
|