@blade-hq/agent-kit 0.5.0 → 0.5.2

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.
Files changed (34) hide show
  1. package/dist/{AskUserQuestionBlock-CjvG_pUY.d.ts → AskUserQuestionBlock---kOTouk.d.ts} +2 -2
  2. package/dist/{SkillStatusBar-B7-EU8A4.d.ts → SkillStatusBar-DpbkD4Jx.d.ts} +3 -3
  3. package/dist/{blade-client-BKiP6U73.d.ts → blade-client-CFvmjs5R.d.ts} +6 -2
  4. package/dist/{chunk-CFZDKYT3.js → chunk-4ZEOWH6U.js} +2 -2
  5. package/dist/{chunk-ROGNJYST.js → chunk-7JX26TWV.js} +4 -2
  6. package/dist/chunk-7JX26TWV.js.map +1 -0
  7. package/dist/{chunk-ZGM3H24C.js → chunk-EV225FLR.js} +1218 -1031
  8. package/dist/chunk-EV225FLR.js.map +1 -0
  9. package/dist/{chunk-2FTEBWEM.js → chunk-LVLGDM76.js} +45 -13
  10. package/dist/chunk-LVLGDM76.js.map +1 -0
  11. package/dist/{chunk-C7VSMOXN.js → chunk-PTMCGZFG.js} +14 -11
  12. package/dist/chunk-PTMCGZFG.js.map +1 -0
  13. package/dist/{chunk-M2ZCTKY7.js → chunk-YW2THJUX.js} +2 -2
  14. package/dist/client/index.d.ts +11 -7
  15. package/dist/client/index.js +1 -1
  16. package/dist/{projection-DIfyh6RK.d.ts → projection-BWYEFYNn.d.ts} +1 -1
  17. package/dist/react/api/vibe-coding.d.ts +3 -3
  18. package/dist/react/api/vibe-coding.js +2 -2
  19. package/dist/react/components/chat/index.d.ts +6 -6
  20. package/dist/react/components/chat/index.js +5 -5
  21. package/dist/react/components/plan/index.d.ts +3 -3
  22. package/dist/react/components/plan/index.js +3 -3
  23. package/dist/react/components/session/index.js +3 -3
  24. package/dist/react/components/workspace/index.js +3 -3
  25. package/dist/react/index.d.ts +10 -8
  26. package/dist/react/index.js +6 -6
  27. package/dist/style.css +1 -1
  28. package/package.json +1 -1
  29. package/dist/chunk-2FTEBWEM.js.map +0 -1
  30. package/dist/chunk-C7VSMOXN.js.map +0 -1
  31. package/dist/chunk-ROGNJYST.js.map +0 -1
  32. package/dist/chunk-ZGM3H24C.js.map +0 -1
  33. /package/dist/{chunk-CFZDKYT3.js.map → chunk-4ZEOWH6U.js.map} +0 -0
  34. /package/dist/{chunk-M2ZCTKY7.js.map → chunk-YW2THJUX.js.map} +0 -0
@@ -8,13 +8,13 @@ import {
8
8
  getCodeLanguageFromFilename,
9
9
  parseAskUserQuestion,
10
10
  useHighlightedCodeHtml
11
- } from "./chunk-2FTEBWEM.js";
11
+ } from "./chunk-LVLGDM76.js";
12
12
  import {
13
13
  Collapsible,
14
14
  CollapsibleContent,
15
15
  CollapsibleTrigger,
16
16
  resolveSessionFilePreviewTarget
17
- } from "./chunk-CFZDKYT3.js";
17
+ } from "./chunk-4ZEOWH6U.js";
18
18
  import {
19
19
  buildMessageContent,
20
20
  buildToolPreviewKey,
@@ -23,6 +23,7 @@ import {
23
23
  extractToolFilePath,
24
24
  formatToolName,
25
25
  getAuthedUrl,
26
+ getBackgroundTask,
26
27
  getClient,
27
28
  getFileParts,
28
29
  getImageParts,
@@ -56,7 +57,7 @@ import {
56
57
  useUiBridgeStore,
57
58
  useUiStore,
58
59
  writeFile
59
- } from "./chunk-C7VSMOXN.js";
60
+ } from "./chunk-PTMCGZFG.js";
60
61
  import {
61
62
  registerBridgeIframe,
62
63
  tapBridgeEvent
@@ -65,7 +66,7 @@ import {
65
66
  ModelOption,
66
67
  ModelsConfig,
67
68
  ModelsResource
68
- } from "./chunk-ROGNJYST.js";
69
+ } from "./chunk-7JX26TWV.js";
69
70
  import {
70
71
  cn,
71
72
  copyToClipboard
@@ -152,7 +153,7 @@ import {
152
153
  ChevronDown,
153
154
  File as File2,
154
155
  FileCode2,
155
- FileText,
156
+ FileText as FileText2,
156
157
  Film,
157
158
  FolderUp,
158
159
  CircleHelp,
@@ -171,7 +172,7 @@ import {
171
172
  Send,
172
173
  Sparkles as Sparkles2,
173
174
  Share2,
174
- Square,
175
+ Square as Square2,
175
176
  X as X2
176
177
  } from "lucide-react";
177
178
  import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
@@ -180,7 +181,7 @@ import {
180
181
  useEffectEvent as useEffectEvent2,
181
182
  useMemo as useMemo7,
182
183
  useRef as useRef4,
183
- useState as useState6
184
+ useState as useState7
184
185
  } from "react";
185
186
  import { createRoot } from "react-dom/client";
186
187
  import { toast } from "sonner";
@@ -703,6 +704,21 @@ function usePreferredModel() {
703
704
 
704
705
  // src/react/components/model/ModelSelector.tsx
705
706
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
707
+ var inputModalityLabels = {
708
+ text: "\u6587\u672C",
709
+ image: "\u56FE\u7247",
710
+ file: "\u6587\u4EF6",
711
+ audio: "\u97F3\u9891",
712
+ video: "\u89C6\u9891"
713
+ };
714
+ function getInputModalities(model) {
715
+ const values = model.inputModalities && model.inputModalities.length > 0 ? model.inputModalities : model.supportsImage ? ["text", "image"] : ["text"];
716
+ const normalized = values.map((value) => value.trim().toLowerCase()).filter((value) => value.length > 0);
717
+ return normalized.length > 0 ? Array.from(new Set(normalized)) : ["text"];
718
+ }
719
+ function formatInputModalities(model) {
720
+ return getInputModalities(model).map((value) => inputModalityLabels[value] ?? value).join("\u3001");
721
+ }
706
722
  function ModelSelector({
707
723
  value,
708
724
  onValueChange,
@@ -728,13 +744,21 @@ function ModelSelector({
728
744
  const normalized = query.trim().toLowerCase();
729
745
  if (!normalized) return models;
730
746
  return models.filter(
731
- (model) => model.id.toLowerCase().includes(normalized) || model.label.toLowerCase().includes(normalized)
747
+ (model) => {
748
+ const inputLabel = formatInputModalities(model).toLowerCase();
749
+ return model.id.toLowerCase().includes(normalized) || model.label.toLowerCase().includes(normalized) || inputLabel.includes(normalized);
750
+ }
732
751
  );
733
752
  }, [models, query]);
734
753
  const canSelect = models.length > 0;
735
- const selectedLabel = models.find((model) => model.id === value)?.label;
736
- const defaultLabel = models.find((model) => model.id === defaultModel)?.label;
754
+ const selectedModel = models.find((model) => model.id === value);
755
+ const defaultModelOption = models.find((model) => model.id === defaultModel);
756
+ const selectedLabel = selectedModel?.label;
757
+ const defaultLabel = defaultModelOption?.label;
737
758
  const label = isLoading ? "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B..." : models.length === 0 ? "\u65E0\u53EF\u7528\u6A21\u578B" : selectedLabel || defaultLabel || value.trim() || "\u672A\u8FDE\u63A5\u5230\u6A21\u578B";
759
+ const activeModel = selectedModel ?? defaultModelOption;
760
+ const activeInputLabel = activeModel ? formatInputModalities(activeModel) : "";
761
+ const selectorTitle = activeInputLabel ? `${label}\uFF0C\u652F\u6301\u8F93\u5165\uFF1A${activeInputLabel}` : label;
738
762
  const dropdownPosition = placement === "top" ? "bottom-[calc(100%+8px)]" : "top-[calc(100%+8px)]";
739
763
  if (!canSelect) {
740
764
  return /* @__PURE__ */ jsxs(
@@ -757,17 +781,24 @@ function ModelSelector({
757
781
  disabled,
758
782
  onClick: () => setIsOpen((current) => !current),
759
783
  className: "flex min-w-0 items-center gap-1 rounded-lg px-2.5 py-[5px] text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
760
- title: label,
784
+ title: selectorTitle,
761
785
  children: [
762
786
  /* @__PURE__ */ jsx2(Sparkles, { size: 14, "aria-hidden": "true" }),
763
- /* @__PURE__ */ jsx2("span", { className: `whitespace-nowrap text-xs ${compact ? "" : "max-w-[180px]"}`, children: label })
787
+ /* @__PURE__ */ jsx2(
788
+ "span",
789
+ {
790
+ className: `min-w-0 truncate whitespace-nowrap text-xs ${compact ? "max-w-[120px]" : "max-w-[180px]"}`,
791
+ children: label
792
+ }
793
+ ),
794
+ activeInputLabel ? /* @__PURE__ */ jsx2("span", { className: "shrink-0 rounded border border-[hsl(var(--border))] px-1 py-0 text-[10px] leading-4 text-[hsl(var(--muted-foreground))]", children: activeInputLabel }) : null
764
795
  ]
765
796
  }
766
797
  ),
767
798
  isOpen && /* @__PURE__ */ jsxs(
768
799
  "div",
769
800
  {
770
- className: `absolute left-0 z-50 w-[260px] overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] shadow-xl ${dropdownPosition}`,
801
+ className: `absolute left-0 z-50 w-[320px] overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] shadow-xl ${dropdownPosition}`,
771
802
  children: [
772
803
  /* @__PURE__ */ jsx2("div", { className: "border-b border-[hsl(var(--border))] p-2", children: /* @__PURE__ */ jsx2(
773
804
  "input",
@@ -778,21 +809,28 @@ function ModelSelector({
778
809
  className: "h-8 w-full rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--background))] px-2.5 text-xs text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground))] focus:border-[hsl(var(--ring))]"
779
810
  }
780
811
  ) }),
781
- /* @__PURE__ */ jsx2("div", { className: "max-h-[220px] overflow-y-auto p-1", children: filteredModels.length === 0 ? /* @__PURE__ */ jsx2("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B" }) : filteredModels.map((model) => /* @__PURE__ */ jsx2(
782
- "button",
783
- {
784
- type: "button",
785
- onClick: () => {
786
- onValueChange(model.id);
787
- setIsOpen(false);
788
- setQuery("");
812
+ /* @__PURE__ */ jsx2("div", { className: "max-h-[220px] overflow-y-auto p-1", children: filteredModels.length === 0 ? /* @__PURE__ */ jsx2("div", { className: "px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B" }) : filteredModels.map((model) => {
813
+ const inputLabel = formatInputModalities(model);
814
+ const title = model.id === model.label ? `${model.id}\uFF0C\u652F\u6301\u8F93\u5165\uFF1A${inputLabel}` : `${model.label} (${model.id})\uFF0C\u652F\u6301\u8F93\u5165\uFF1A${inputLabel}`;
815
+ return /* @__PURE__ */ jsxs(
816
+ "button",
817
+ {
818
+ type: "button",
819
+ onClick: () => {
820
+ onValueChange(model.id);
821
+ setIsOpen(false);
822
+ setQuery("");
823
+ },
824
+ className: `flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-xs transition-colors ${model.id === value ? "bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"}`,
825
+ title,
826
+ children: [
827
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: model.label }),
828
+ /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-[11px] text-[hsl(var(--muted-foreground))]", children: inputLabel })
829
+ ]
789
830
  },
790
- className: `block w-full truncate rounded-lg px-3 py-2 text-left text-xs transition-colors ${model.id === value ? "bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"}`,
791
- title: model.id === model.label ? model.id : `${model.label} (${model.id})`,
792
- children: model.label
793
- },
794
- model.id
795
- )) })
831
+ model.id
832
+ );
833
+ }) })
796
834
  ]
797
835
  }
798
836
  )
@@ -1258,11 +1296,177 @@ var SkillCompletionMenu = forwardRef2(
1258
1296
  }
1259
1297
  );
1260
1298
 
1299
+ // src/react/components/chat/BackgroundTasksPill.tsx
1300
+ import { FileText, Square, Terminal } from "lucide-react";
1301
+ import { useState as useState6 } from "react";
1302
+
1303
+ // src/react/hooks/use-background-tasks.ts
1304
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
1305
+ var EMPTY_TASKS = [];
1306
+ function useBackgroundTasks(sessionId) {
1307
+ const setTasks = useBackgroundStore((state) => state.setTasks);
1308
+ const tasks = useBackgroundStore((state) => sessionId ? state.tasks[sessionId] : void 0);
1309
+ const query = useQuery2({
1310
+ queryKey: ["background-tasks", sessionId],
1311
+ queryFn: ({ signal }) => listBackgroundTasks(sessionId, { signal }).then((items) => {
1312
+ setTasks(sessionId, items);
1313
+ return items;
1314
+ }),
1315
+ enabled: Boolean(sessionId)
1316
+ });
1317
+ return {
1318
+ data: tasks ?? query.data ?? EMPTY_TASKS,
1319
+ loading: query.isLoading,
1320
+ error: query.error,
1321
+ refetch: query.refetch
1322
+ };
1323
+ }
1324
+
1325
+ // src/react/components/chat/BackgroundTasksPill.tsx
1326
+ import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1327
+ function formatStartedAt(value) {
1328
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
1329
+ return "\u542F\u52A8\u65F6\u95F4\u672A\u77E5";
1330
+ }
1331
+ return new Intl.DateTimeFormat("zh-CN", {
1332
+ hour: "2-digit",
1333
+ minute: "2-digit"
1334
+ }).format(new Date(value * 1e3));
1335
+ }
1336
+ function statusLabel(status) {
1337
+ if (status === "running") return "\u8FD0\u884C\u4E2D";
1338
+ if (status === "failed") return "\u5931\u8D25";
1339
+ if (status === "cancelled") return "\u5DF2\u505C\u6B62";
1340
+ if (status === "done" || status === "succeeded") return "\u5DF2\u7ED3\u675F";
1341
+ return status || "\u672A\u77E5";
1342
+ }
1343
+ function statusClass(status) {
1344
+ if (status === "running") return "border-amber-500/35 bg-amber-500/10 text-amber-500";
1345
+ if (status === "failed") return "border-rose-500/35 bg-rose-500/10 text-rose-500";
1346
+ return "border-[hsl(var(--border))] bg-[hsl(var(--muted))]/40 text-[hsl(var(--muted-foreground))]";
1347
+ }
1348
+ function BackgroundTasksPill({ sessionId }) {
1349
+ const { data: tasks } = useBackgroundTasks(sessionId);
1350
+ const [open, setOpen] = useState6(false);
1351
+ const [logTask, setLogTask] = useState6(null);
1352
+ if (tasks.length === 0) return null;
1353
+ const runningCount = tasks.filter((task) => task.status === "running").length;
1354
+ const openTaskLog = async (task) => {
1355
+ const title = `${task.id} ${task.description || task.command || "\u540E\u53F0\u4EFB\u52A1"}`;
1356
+ setLogTask({ id: task.id, title, output: "", loading: true, error: null });
1357
+ try {
1358
+ const detail = await getBackgroundTask(sessionId, task.id, 300);
1359
+ setLogTask({
1360
+ id: task.id,
1361
+ title,
1362
+ output: detail.output || "\u6682\u65E0\u8F93\u51FA",
1363
+ loading: false,
1364
+ error: null
1365
+ });
1366
+ } catch (error) {
1367
+ setLogTask({
1368
+ id: task.id,
1369
+ title,
1370
+ output: "",
1371
+ loading: false,
1372
+ error: error instanceof Error ? error.message : "\u65E5\u5FD7\u52A0\u8F7D\u5931\u8D25"
1373
+ });
1374
+ }
1375
+ };
1376
+ const requestStopTask = (task) => {
1377
+ const name = `${task.id}\uFF08${task.description || task.command || "\u540E\u53F0\u4EFB\u52A1"}\uFF09`;
1378
+ getSocket().send(
1379
+ sessionId,
1380
+ `\u8BF7\u5148\u5411\u6211\u4E8C\u6B21\u786E\u8BA4\uFF0C\u7136\u540E\u5E2E\u6211\u505C\u6B62\u540E\u53F0\u4EFB\u52A1 ${name}\u3002`,
1381
+ "executing"
1382
+ );
1383
+ setOpen(false);
1384
+ };
1385
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
1386
+ logTask ? /* @__PURE__ */ jsx5("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/55 p-4", children: /* @__PURE__ */ jsxs4("div", { className: "flex max-h-[82vh] w-full max-w-3xl flex-col overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl", children: [
1387
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-3", children: [
1388
+ /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
1389
+ /* @__PURE__ */ jsx5("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: logTask.title }),
1390
+ /* @__PURE__ */ jsx5("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u540E\u53F0\u4EFB\u52A1\u65E5\u5FD7" })
1391
+ ] }),
1392
+ /* @__PURE__ */ jsx5(
1393
+ "button",
1394
+ {
1395
+ type: "button",
1396
+ onClick: () => setLogTask(null),
1397
+ className: "rounded-md border border-[hsl(var(--border))] px-2.5 py-1 text-xs text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]",
1398
+ children: "\u5173\u95ED"
1399
+ }
1400
+ )
1401
+ ] }),
1402
+ /* @__PURE__ */ jsx5("pre", { className: "min-h-64 flex-1 overflow-auto whitespace-pre-wrap p-4 font-mono text-xs leading-5 text-[hsl(var(--foreground))]", children: logTask.loading ? "\u52A0\u8F7D\u4E2D..." : logTask.error || logTask.output })
1403
+ ] }) }) : null,
1404
+ /* @__PURE__ */ jsxs4("div", { className: "relative mb-2 flex justify-start", children: [
1405
+ /* @__PURE__ */ jsxs4(
1406
+ "button",
1407
+ {
1408
+ type: "button",
1409
+ onClick: () => setOpen((value) => !value),
1410
+ className: cn(
1411
+ "inline-flex h-8 items-center gap-2 rounded-full border px-3 text-xs font-medium shadow-sm transition-colors",
1412
+ runningCount > 0 ? "border-amber-500/35 bg-amber-500/10 text-amber-600" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--muted-foreground))]"
1413
+ ),
1414
+ children: [
1415
+ /* @__PURE__ */ jsx5(Terminal, { size: 13 }),
1416
+ "\u540E\u53F0\u4EFB\u52A1 ",
1417
+ tasks.length,
1418
+ runningCount > 0 ? /* @__PURE__ */ jsxs4("span", { children: [
1419
+ "\u8FD0\u884C\u4E2D ",
1420
+ runningCount
1421
+ ] }) : null
1422
+ ]
1423
+ }
1424
+ ),
1425
+ open ? /* @__PURE__ */ jsx5("div", { className: "absolute bottom-full left-0 z-40 mb-2 w-[min(24rem,calc(100vw-2rem))] rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-2 text-xs text-[hsl(var(--popover-foreground))] shadow-xl", children: /* @__PURE__ */ jsx5("div", { className: "max-h-72 space-y-2 overflow-y-auto", children: tasks.map((task) => /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-[hsl(var(--border))] p-2", children: [
1426
+ /* @__PURE__ */ jsx5("div", { className: "flex items-start justify-between gap-2", children: /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
1427
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1428
+ /* @__PURE__ */ jsx5("span", { className: "font-mono font-semibold", children: task.id }),
1429
+ /* @__PURE__ */ jsx5("span", { className: cn("rounded-full border px-1.5 py-0.5 text-[10px]", statusClass(task.status)), children: statusLabel(task.status) })
1430
+ ] }),
1431
+ /* @__PURE__ */ jsx5("div", { className: "mt-1 break-words text-[hsl(var(--foreground))]", children: task.description || task.command }),
1432
+ /* @__PURE__ */ jsx5("div", { className: "mt-1 text-[11px] text-[hsl(var(--muted-foreground))]", children: formatStartedAt(task.started_at) })
1433
+ ] }) }),
1434
+ /* @__PURE__ */ jsxs4("div", { className: "mt-2 flex items-center gap-1.5", children: [
1435
+ /* @__PURE__ */ jsxs4(
1436
+ "button",
1437
+ {
1438
+ type: "button",
1439
+ onClick: () => void openTaskLog(task),
1440
+ className: "inline-flex h-6 items-center gap-1 rounded-md border border-[hsl(var(--border))] px-2 text-[11px] hover:bg-[hsl(var(--accent))]",
1441
+ children: [
1442
+ /* @__PURE__ */ jsx5(FileText, { size: 11 }),
1443
+ "\u65E5\u5FD7"
1444
+ ]
1445
+ }
1446
+ ),
1447
+ task.status === "running" ? /* @__PURE__ */ jsxs4(
1448
+ "button",
1449
+ {
1450
+ type: "button",
1451
+ onClick: () => requestStopTask(task),
1452
+ className: "inline-flex h-6 items-center gap-1 rounded-md border border-rose-500/35 px-2 text-[11px] text-rose-500 hover:bg-rose-500/10",
1453
+ children: [
1454
+ /* @__PURE__ */ jsx5(Square, { size: 10 }),
1455
+ "\u505C\u6B62"
1456
+ ]
1457
+ }
1458
+ ) : null
1459
+ ] })
1460
+ ] }, task.id)) }) }) : null
1461
+ ] })
1462
+ ] });
1463
+ }
1464
+
1261
1465
  // src/react/components/chat/FileSizeLimitDialog.tsx
1262
1466
  import { X } from "lucide-react";
1263
1467
  import { useEffect as useEffect6 } from "react";
1264
1468
  import { createPortal } from "react-dom";
1265
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1469
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1266
1470
  function FileSizeLimitDialog({
1267
1471
  open,
1268
1472
  onOpenChange,
@@ -1284,7 +1488,7 @@ function FileSizeLimitDialog({
1284
1488
  }
1285
1489
  const limitText = formatFileSize(limitBytes);
1286
1490
  return createPortal(
1287
- /* @__PURE__ */ jsx5(
1491
+ /* @__PURE__ */ jsx6(
1288
1492
  "div",
1289
1493
  {
1290
1494
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",
@@ -1297,45 +1501,45 @@ function FileSizeLimitDialog({
1297
1501
  role: "dialog",
1298
1502
  "aria-modal": "true",
1299
1503
  "aria-labelledby": "file-size-limit-dialog-title",
1300
- children: /* @__PURE__ */ jsxs4(
1504
+ children: /* @__PURE__ */ jsxs5(
1301
1505
  "div",
1302
1506
  {
1303
1507
  className: "w-full max-w-lg overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl",
1304
1508
  onClick: (event) => event.stopPropagation(),
1305
1509
  onKeyDown: (event) => event.stopPropagation(),
1306
1510
  children: [
1307
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
1308
- /* @__PURE__ */ jsxs4("div", { children: [
1309
- /* @__PURE__ */ jsx5("h3", { id: "file-size-limit-dialog-title", className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
1310
- /* @__PURE__ */ jsxs4("p", { className: "mt-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
1511
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
1512
+ /* @__PURE__ */ jsxs5("div", { children: [
1513
+ /* @__PURE__ */ jsx6("h3", { id: "file-size-limit-dialog-title", className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
1514
+ /* @__PURE__ */ jsxs5("p", { className: "mt-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
1311
1515
  "\u5355\u4E2A\u9644\u4EF6\u6700\u5927\u652F\u6301 ",
1312
1516
  limitText,
1313
1517
  "\u3002\u4EE5\u4E0B\u6587\u4EF6\u672A\u52A0\u5165\u9644\u4EF6\u5217\u8868\u3002"
1314
1518
  ] })
1315
1519
  ] }),
1316
- /* @__PURE__ */ jsx5(
1520
+ /* @__PURE__ */ jsx6(
1317
1521
  "button",
1318
1522
  {
1319
1523
  type: "button",
1320
1524
  onClick: () => onOpenChange(false),
1321
1525
  title: "\u5173\u95ED",
1322
1526
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
1323
- children: /* @__PURE__ */ jsx5(X, { size: 14 })
1527
+ children: /* @__PURE__ */ jsx6(X, { size: 14 })
1324
1528
  }
1325
1529
  )
1326
1530
  ] }),
1327
- /* @__PURE__ */ jsx5("div", { className: "max-h-[min(50vh,24rem)] overflow-auto px-4 py-3", children: /* @__PURE__ */ jsx5("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsxs4(
1531
+ /* @__PURE__ */ jsx6("div", { className: "max-h-[min(50vh,24rem)] overflow-auto px-4 py-3", children: /* @__PURE__ */ jsx6("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsxs5(
1328
1532
  "div",
1329
1533
  {
1330
1534
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-3 py-2",
1331
1535
  children: [
1332
- /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
1333
- /* @__PURE__ */ jsx5("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatFileSize(file.size) })
1536
+ /* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
1537
+ /* @__PURE__ */ jsx6("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatFileSize(file.size) })
1334
1538
  ]
1335
1539
  },
1336
1540
  `${file.name}:${file.size}`
1337
1541
  )) }) }),
1338
- /* @__PURE__ */ jsx5("div", { className: "flex justify-end border-t border-[hsl(var(--border))] px-4 py-3", children: /* @__PURE__ */ jsx5(
1542
+ /* @__PURE__ */ jsx6("div", { className: "flex justify-end border-t border-[hsl(var(--border))] px-4 py-3", children: /* @__PURE__ */ jsx6(
1339
1543
  "button",
1340
1544
  {
1341
1545
  type: "button",
@@ -1358,28 +1562,6 @@ import { useQuery as useQuery5 } from "@tanstack/react-query";
1358
1562
  import { RefreshCw } from "lucide-react";
1359
1563
  import { useMemo as useMemo6 } from "react";
1360
1564
 
1361
- // src/react/hooks/use-background-tasks.ts
1362
- import { useQuery as useQuery2 } from "@tanstack/react-query";
1363
- var EMPTY_TASKS = [];
1364
- function useBackgroundTasks(sessionId) {
1365
- const setTasks = useBackgroundStore((state) => state.setTasks);
1366
- const tasks = useBackgroundStore((state) => sessionId ? state.tasks[sessionId] : void 0);
1367
- const query = useQuery2({
1368
- queryKey: ["background-tasks", sessionId],
1369
- queryFn: ({ signal }) => listBackgroundTasks(sessionId, { signal }).then((items) => {
1370
- setTasks(sessionId, items);
1371
- return items;
1372
- }),
1373
- enabled: Boolean(sessionId)
1374
- });
1375
- return {
1376
- data: tasks ?? query.data ?? EMPTY_TASKS,
1377
- loading: query.isLoading,
1378
- error: query.error,
1379
- refetch: query.refetch
1380
- };
1381
- }
1382
-
1383
1565
  // src/react/hooks/use-context-stats.ts
1384
1566
  import { useQuery as useQuery3 } from "@tanstack/react-query";
1385
1567
  var EMPTY_CONTEXT_STATS = {
@@ -1455,7 +1637,7 @@ function useTokenPressure(sessionId) {
1455
1637
  }
1456
1638
 
1457
1639
  // src/react/components/chat/ProgressCircle.tsx
1458
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1640
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1459
1641
  var LEVEL_STYLES = {
1460
1642
  normal: {
1461
1643
  strokeClass: "stroke-slate-400",
@@ -1486,15 +1668,15 @@ function ProgressCircle({
1486
1668
  const circumference = 2 * Math.PI * radius;
1487
1669
  const dashOffset = circumference * (1 - clamped / 100);
1488
1670
  const styles = LEVEL_STYLES[level];
1489
- return /* @__PURE__ */ jsxs5("div", { className: cn("group relative inline-flex", className), children: [
1490
- /* @__PURE__ */ jsx6(
1671
+ return /* @__PURE__ */ jsxs6("div", { className: cn("group relative inline-flex", className), children: [
1672
+ /* @__PURE__ */ jsx7(
1491
1673
  "button",
1492
1674
  {
1493
1675
  type: "button",
1494
1676
  "aria-label": `\u4E0A\u4E0B\u6587\u5DF2\u4F7F\u7528 ${Math.round(clamped)}%`,
1495
1677
  className: "relative inline-flex cursor-help items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--background))]",
1496
- children: /* @__PURE__ */ jsxs5("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": "true", children: [
1497
- /* @__PURE__ */ jsx6(
1678
+ children: /* @__PURE__ */ jsxs6("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": "true", children: [
1679
+ /* @__PURE__ */ jsx7(
1498
1680
  "circle",
1499
1681
  {
1500
1682
  cx: size / 2,
@@ -1505,7 +1687,7 @@ function ProgressCircle({
1505
1687
  className: styles.trackClass
1506
1688
  }
1507
1689
  ),
1508
- /* @__PURE__ */ jsx6(
1690
+ /* @__PURE__ */ jsx7(
1509
1691
  "circle",
1510
1692
  {
1511
1693
  cx: size / 2,
@@ -1523,12 +1705,12 @@ function ProgressCircle({
1523
1705
  ] })
1524
1706
  }
1525
1707
  ),
1526
- detail ? /* @__PURE__ */ jsx6("div", { className: "pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block group-focus-within:block", children: detail }) : null
1708
+ detail ? /* @__PURE__ */ jsx7("div", { className: "pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block group-focus-within:block", children: detail }) : null
1527
1709
  ] });
1528
1710
  }
1529
1711
 
1530
1712
  // src/react/components/chat/SkillStatusBar.tsx
1531
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1713
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1532
1714
  var COMPACT_NUMBER_FORMATTER = new Intl.NumberFormat("zh-CN", {
1533
1715
  notation: "compact",
1534
1716
  maximumFractionDigits: 1
@@ -1572,8 +1754,8 @@ function HoverPanel({
1572
1754
  title,
1573
1755
  children
1574
1756
  }) {
1575
- return /* @__PURE__ */ jsxs6("div", { className: "pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block", children: [
1576
- /* @__PURE__ */ jsx7("div", { className: "mb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-400", children: title }),
1757
+ return /* @__PURE__ */ jsxs7("div", { className: "absolute bottom-full left-1/2 z-20 mb-2 hidden w-80 max-w-[min(22rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block", children: [
1758
+ /* @__PURE__ */ jsx8("div", { className: "mb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-400", children: title }),
1577
1759
  children
1578
1760
  ] });
1579
1761
  }
@@ -1592,13 +1774,10 @@ function SkillStatusBar({
1592
1774
  enabled: Boolean(sessionId)
1593
1775
  });
1594
1776
  const { data: contextStats } = useContextStats(sessionId);
1595
- const { data: tasks } = useBackgroundTasks(sessionId);
1596
1777
  const tokenPressure = useTokenPressure(sessionId);
1597
1778
  const connectionStatus = useConnectionStore((state) => state.status);
1598
1779
  const reconnectAttempt = useConnectionStore((state) => state.reconnectAttempt);
1599
1780
  const hasEverConnected = useConnectionStore((state) => state.hasEverConnected);
1600
- const runningTaskItems = tasks.filter((task) => task.status === "running");
1601
- const runningTasks = runningTaskItems.length;
1602
1781
  const statsReady = !loading && !error;
1603
1782
  const skillStoreConnected = statsReady && skillStats.remote_connected;
1604
1783
  const connectionMeta = useMemo6(
@@ -1610,11 +1789,6 @@ function SkillStatusBar({
1610
1789
  [connectionStatus, reconnectAttempt, hasEverConnected]
1611
1790
  );
1612
1791
  const items = [
1613
- {
1614
- key: "bg",
1615
- dotClass: runningTasks > 0 ? "bg-amber-400" : "bg-[hsl(var(--muted-foreground))]",
1616
- text: `\u540E\u53F0\u4EFB\u52A1 ${runningTasks}`
1617
- },
1618
1792
  {
1619
1793
  key: "loaded",
1620
1794
  dotClass: statsReady ? "bg-emerald-500" : "bg-[hsl(var(--muted-foreground))]",
@@ -1628,18 +1802,18 @@ function SkillStatusBar({
1628
1802
  ].filter((item) => item.key !== "total" || skillStats.remote_configured);
1629
1803
  const tokenSummary = useMemo6(() => {
1630
1804
  return {
1631
- detail: /* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
1632
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3 border-t border-slate-800 pt-1", children: [
1633
- /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "\u5DF2\u7528" }),
1634
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: formatTokenNumber(contextStats.tokens_used) })
1805
+ detail: /* @__PURE__ */ jsxs7("div", { className: "space-y-1", children: [
1806
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3 border-t border-slate-800 pt-1", children: [
1807
+ /* @__PURE__ */ jsx8("span", { className: "text-slate-400", children: "\u5DF2\u7528" }),
1808
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: formatTokenNumber(contextStats.tokens_used) })
1635
1809
  ] }),
1636
- contextStats.context_window > 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3", children: [
1637
- /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "\u4E0A\u4E0B\u6587\u7A97\u53E3" }),
1638
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: formatCompactNumber(contextStats.context_window) })
1639
- ] }) : /* @__PURE__ */ jsx7("div", { className: "pt-1 text-slate-500", children: "\u672A\u914D\u7F6E\u4E0A\u4E0B\u6587\u7A97\u53E3\u5927\u5C0F\uFF0C\u53EF\u901A\u8FC7 CONTEXT_WINDOW \u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E" }),
1640
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3", children: [
1641
- /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "\u6574\u7406\u9608\u503C" }),
1642
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: contextStats.compaction_ratio > 0 ? `${Math.round(contextStats.compaction_ratio * 100)}%` : "\u5DF2\u7981\u7528" })
1810
+ contextStats.context_window > 0 ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3", children: [
1811
+ /* @__PURE__ */ jsx8("span", { className: "text-slate-400", children: "\u4E0A\u4E0B\u6587\u7A97\u53E3" }),
1812
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: formatCompactNumber(contextStats.context_window) })
1813
+ ] }) : /* @__PURE__ */ jsx8("div", { className: "pt-1 text-slate-500", children: "\u672A\u914D\u7F6E\u4E0A\u4E0B\u6587\u7A97\u53E3\u5927\u5C0F\uFF0C\u53EF\u901A\u8FC7 CONTEXT_WINDOW \u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E" }),
1814
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3", children: [
1815
+ /* @__PURE__ */ jsx8("span", { className: "text-slate-400", children: "\u6574\u7406\u9608\u503C" }),
1816
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: contextStats.compaction_ratio > 0 ? `${Math.round(contextStats.compaction_ratio * 100)}%` : "\u5DF2\u7981\u7528" })
1643
1817
  ] })
1644
1818
  ] }),
1645
1819
  label: contextStats.context_window > 0 ? `${formatTokensK(contextStats.tokens_used)} / ${formatTokensK(contextStats.context_window)} \u4E0A\u4E0B\u6587` : `${formatTokensK(contextStats.tokens_used)} \u4E0A\u4E0B\u6587`,
@@ -1649,9 +1823,9 @@ function SkillStatusBar({
1649
1823
  const containerClass = vertical ? "text-[11px] text-[hsl(var(--muted-foreground))]" : "bg-[hsl(var(--background))] px-5 pt-2";
1650
1824
  const innerClass = vertical ? "" : "mx-auto max-w-3xl";
1651
1825
  const listClass = vertical ? "flex flex-col items-stretch gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]" : "flex flex-wrap items-center gap-2 text-[10px] text-[hsl(var(--muted-foreground))]";
1652
- return /* @__PURE__ */ jsx7("div", { className: cn(containerClass, className), children: /* @__PURE__ */ jsx7("div", { className: cn(innerClass, innerClassName), children: /* @__PURE__ */ jsxs6("div", { className: listClass, children: [
1653
- tokenSummary ? /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1", children: [
1654
- /* @__PURE__ */ jsx7(
1826
+ return /* @__PURE__ */ jsx8("div", { className: cn(containerClass, className), children: /* @__PURE__ */ jsx8("div", { className: cn(innerClass, innerClassName), children: /* @__PURE__ */ jsxs7("div", { className: listClass, children: [
1827
+ tokenSummary ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1", children: [
1828
+ /* @__PURE__ */ jsx8(
1655
1829
  ProgressCircle,
1656
1830
  {
1657
1831
  percentage: tokenPressure.ratio * 100,
@@ -1659,10 +1833,10 @@ function SkillStatusBar({
1659
1833
  detail: tokenSummary.detail
1660
1834
  }
1661
1835
  ),
1662
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: tokenSummary.label }),
1663
- tokenSummary.warn ? /* @__PURE__ */ jsx7("span", { className: "rounded-full border border-rose-500/25 bg-rose-500/10 px-1.5 py-0.5 text-[10px] font-medium text-rose-200", children: "\u5EFA\u8BAE\u6574\u7406\u5BF9\u8BDD" }) : null
1836
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: tokenSummary.label }),
1837
+ tokenSummary.warn ? /* @__PURE__ */ jsx8("span", { className: "rounded-full border border-rose-500/25 bg-rose-500/10 px-1.5 py-0.5 text-[10px] font-medium text-rose-200", children: "\u5EFA\u8BAE\u6574\u7406\u5BF9\u8BDD" }) : null
1664
1838
  ] }) : null,
1665
- connectionStatus !== "connected" ? /* @__PURE__ */ jsxs6(
1839
+ connectionStatus !== "connected" ? /* @__PURE__ */ jsxs7(
1666
1840
  "div",
1667
1841
  {
1668
1842
  className: cn(
@@ -1670,30 +1844,21 @@ function SkillStatusBar({
1670
1844
  connectionMeta.toneClass
1671
1845
  ),
1672
1846
  children: [
1673
- /* @__PURE__ */ jsx7("span", { className: cn("inline-block h-1.5 w-1.5 rounded-full", connectionMeta.dotClass) }),
1674
- /* @__PURE__ */ jsx7("span", { children: connectionMeta.label })
1847
+ /* @__PURE__ */ jsx8("span", { className: cn("inline-block h-1.5 w-1.5 rounded-full", connectionMeta.dotClass) }),
1848
+ /* @__PURE__ */ jsx8("span", { children: connectionMeta.label })
1675
1849
  ]
1676
1850
  }
1677
1851
  ) : null,
1678
- items.map((item, index) => /* @__PURE__ */ jsxs6(
1852
+ items.map((item, index) => /* @__PURE__ */ jsxs7(
1679
1853
  "div",
1680
1854
  {
1681
1855
  className: "flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1",
1682
1856
  children: [
1683
- index > 0 && !tokenPressure && /* @__PURE__ */ jsx7("span", { className: "hidden text-[hsl(var(--border))]", children: "\xB7" }),
1684
- /* @__PURE__ */ jsx7("span", { className: `inline-block h-1.5 w-1.5 rounded-full ${item.dotClass}` }),
1685
- item.key === "bg" ? /* @__PURE__ */ jsxs6("div", { className: "group relative", children: [
1686
- /* @__PURE__ */ jsx7("span", { className: "cursor-help font-mono", children: item.text }),
1687
- runningTaskItems.length > 0 ? /* @__PURE__ */ jsx7(HoverPanel, { title: "\u8FD0\u884C\u4E2D\u4EFB\u52A1", children: /* @__PURE__ */ jsx7("div", { className: "max-h-40 overflow-y-auto", children: runningTaskItems.map((task) => /* @__PURE__ */ jsxs6("div", { className: "flex items-start gap-2 py-1 leading-relaxed", children: [
1688
- /* @__PURE__ */ jsx7("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-amber-300 bg-transparent" }),
1689
- /* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
1690
- /* @__PURE__ */ jsx7("div", { className: "font-medium", children: task.id }),
1691
- /* @__PURE__ */ jsx7("div", { className: "break-words text-slate-300/85", children: task.description || task.command })
1692
- ] })
1693
- ] }, task.id)) }) }) : null
1694
- ] }) : item.key === "loaded" ? /* @__PURE__ */ jsxs6("div", { className: "group relative flex items-center gap-1.5", children: [
1695
- /* @__PURE__ */ jsx7("span", { className: "cursor-help font-mono", children: item.text }),
1696
- onResync ? /* @__PURE__ */ jsx7(
1857
+ index > 0 && !tokenPressure && /* @__PURE__ */ jsx8("span", { className: "hidden text-[hsl(var(--border))]", children: "\xB7" }),
1858
+ /* @__PURE__ */ jsx8("span", { className: `inline-block h-1.5 w-1.5 rounded-full ${item.dotClass}` }),
1859
+ item.key === "loaded" ? /* @__PURE__ */ jsxs7("div", { className: "group relative flex items-center gap-1.5", children: [
1860
+ /* @__PURE__ */ jsx8("span", { className: "cursor-help font-mono", children: item.text }),
1861
+ onResync ? /* @__PURE__ */ jsx8(
1697
1862
  "button",
1698
1863
  {
1699
1864
  type: "button",
@@ -1701,21 +1866,21 @@ function SkillStatusBar({
1701
1866
  disabled: isResyncing,
1702
1867
  "aria-label": "\u540C\u6B65\u6280\u80FD",
1703
1868
  className: "inline-flex h-5 w-5 items-center justify-center rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--background))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
1704
- children: /* @__PURE__ */ jsx7(RefreshCw, { size: 11, className: isResyncing ? "animate-spin" : "" })
1869
+ children: /* @__PURE__ */ jsx8(RefreshCw, { size: 11, className: isResyncing ? "animate-spin" : "" })
1705
1870
  }
1706
1871
  ) : null,
1707
- statsReady && sessionSkills.length > 0 ? /* @__PURE__ */ jsx7(HoverPanel, { title: "\u5DF2\u52A0\u8F7D\u6280\u80FD", children: /* @__PURE__ */ jsx7("div", { className: "max-h-40 overflow-y-auto", children: sessionSkills.map((skill) => /* @__PURE__ */ jsxs6(
1872
+ statsReady && sessionSkills.length > 0 ? /* @__PURE__ */ jsx8(HoverPanel, { title: "\u5DF2\u52A0\u8F7D\u6280\u80FD", children: /* @__PURE__ */ jsx8("div", { className: "max-h-40 overflow-y-auto", children: sessionSkills.map((skill) => /* @__PURE__ */ jsxs7(
1708
1873
  "div",
1709
1874
  {
1710
1875
  className: "flex items-start gap-2 py-1 leading-relaxed",
1711
1876
  children: [
1712
- /* @__PURE__ */ jsx7("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-emerald-300 bg-transparent" }),
1713
- /* @__PURE__ */ jsx7("span", { className: "break-words", children: skillDisplayName(skill) })
1877
+ /* @__PURE__ */ jsx8("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-emerald-300 bg-transparent" }),
1878
+ /* @__PURE__ */ jsx8("span", { className: "break-words", children: skillDisplayName(skill) })
1714
1879
  ]
1715
1880
  },
1716
1881
  skill.skill_id
1717
1882
  )) }) }) : null
1718
- ] }) : /* @__PURE__ */ jsx7("span", { className: "font-mono", children: item.text })
1883
+ ] }) : /* @__PURE__ */ jsx8("span", { className: "font-mono", children: item.text })
1719
1884
  ]
1720
1885
  },
1721
1886
  item.key
@@ -1850,7 +2015,7 @@ var SkillMention = Mention2.extend({
1850
2015
  });
1851
2016
 
1852
2017
  // src/react/components/chat/ChatInput.tsx
1853
- import { Fragment, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2018
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1854
2019
  function getEditorText(editor) {
1855
2020
  return editor?.getText({ blockSeparator: "\n" }) ?? "";
1856
2021
  }
@@ -1890,7 +2055,7 @@ function getFileCardIcon(attachment) {
1890
2055
  return FileCode2;
1891
2056
  }
1892
2057
  if (attachment.mimeType.startsWith("text/") || /\.(txt|pdf|doc|docx|rtf|odt)$/.test(lowerName)) {
1893
- return FileText;
2058
+ return FileText2;
1894
2059
  }
1895
2060
  return File2;
1896
2061
  }
@@ -1966,21 +2131,21 @@ function ComposerFilePill({
1966
2131
  const isFile = attachment.kind === "file";
1967
2132
  const isFailed = isFile && attachment.status === "failed";
1968
2133
  const isUploading = isFile && attachment.status === "uploading";
1969
- return /* @__PURE__ */ jsxs7(
2134
+ return /* @__PURE__ */ jsxs8(
1970
2135
  "div",
1971
2136
  {
1972
2137
  className: `flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] ${isFailed ? "border-red-500/30 bg-red-500/5 text-red-400" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]"}`,
1973
2138
  children: [
1974
- isUploading ? /* @__PURE__ */ jsx8(Loader22, { size: 12, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx8(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
1975
- /* @__PURE__ */ jsx8("span", { className: "max-w-32 truncate", children: attachment.name }),
1976
- /* @__PURE__ */ jsx8(
2139
+ isUploading ? /* @__PURE__ */ jsx9(Loader22, { size: 12, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx9(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
2140
+ /* @__PURE__ */ jsx9("span", { className: "max-w-32 truncate", children: attachment.name }),
2141
+ /* @__PURE__ */ jsx9(
1977
2142
  "button",
1978
2143
  {
1979
2144
  type: "button",
1980
2145
  onClick: () => onRemove(attachment.id),
1981
2146
  "aria-label": `\u79FB\u9664 ${attachment.name}`,
1982
2147
  className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
1983
- children: /* @__PURE__ */ jsx8(X2, { size: 10 })
2148
+ children: /* @__PURE__ */ jsx9(X2, { size: 10 })
1984
2149
  }
1985
2150
  )
1986
2151
  ]
@@ -1993,13 +2158,13 @@ function AddContextDialog({
1993
2158
  onAdd
1994
2159
  }) {
1995
2160
  const CONTEXT_INLINE_THRESHOLD = 200;
1996
- const [label, setLabel] = useState6("");
1997
- const [content, setContent] = useState6("");
1998
- const [showSessionPicker, setShowSessionPicker] = useState6(false);
1999
- const [sessions, setSessions] = useState6([]);
2000
- const [loadingSessions, setLoadingSessions] = useState6(false);
2001
- const [importingId, setImportingId] = useState6(null);
2002
- const [isImportProcessing, setIsImportProcessing] = useState6(false);
2161
+ const [label, setLabel] = useState7("");
2162
+ const [content, setContent] = useState7("");
2163
+ const [showSessionPicker, setShowSessionPicker] = useState7(false);
2164
+ const [sessions, setSessions] = useState7([]);
2165
+ const [loadingSessions, setLoadingSessions] = useState7(false);
2166
+ const [importingId, setImportingId] = useState7(null);
2167
+ const [isImportProcessing, setIsImportProcessing] = useState7(false);
2003
2168
  const sanitizeContextFolderName = (raw) => {
2004
2169
  const normalized = raw.trim().toLowerCase();
2005
2170
  const safe = normalized.replace(/[^\w\-.\u4e00-\u9fa5]+/g, "_").replace(/^_+|_+$/g, "");
@@ -2099,7 +2264,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2099
2264
  setImportingId(null);
2100
2265
  }
2101
2266
  };
2102
- return /* @__PURE__ */ jsx8(
2267
+ return /* @__PURE__ */ jsx9(
2103
2268
  "div",
2104
2269
  {
2105
2270
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-4",
@@ -2107,44 +2272,44 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2107
2272
  onKeyDown: (e) => {
2108
2273
  if (e.key === "Escape") onClose();
2109
2274
  },
2110
- children: /* @__PURE__ */ jsxs7(
2275
+ children: /* @__PURE__ */ jsxs8(
2111
2276
  "div",
2112
2277
  {
2113
2278
  className: "w-full max-w-lg flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl",
2114
2279
  onClick: (e) => e.stopPropagation(),
2115
2280
  onKeyDown: (e) => e.stopPropagation(),
2116
2281
  children: [
2117
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
2118
- /* @__PURE__ */ jsx8("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
2119
- /* @__PURE__ */ jsx8(
2282
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
2283
+ /* @__PURE__ */ jsx9("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
2284
+ /* @__PURE__ */ jsx9(
2120
2285
  "button",
2121
2286
  {
2122
2287
  type: "button",
2123
2288
  onClick: onClose,
2124
2289
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2125
- children: /* @__PURE__ */ jsx8(X2, { size: 14 })
2290
+ children: /* @__PURE__ */ jsx9(X2, { size: 14 })
2126
2291
  }
2127
2292
  )
2128
2293
  ] }),
2129
- /* @__PURE__ */ jsxs7("div", { className: "px-5 py-4 space-y-3", children: [
2130
- /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
2131
- /* @__PURE__ */ jsxs7(
2294
+ /* @__PURE__ */ jsxs8("div", { className: "px-5 py-4 space-y-3", children: [
2295
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
2296
+ /* @__PURE__ */ jsxs8(
2132
2297
  "button",
2133
2298
  {
2134
2299
  type: "button",
2135
2300
  onClick: handleLoadSessions,
2136
2301
  className: "inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--border))] px-2.5 py-1.5 text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]",
2137
2302
  children: [
2138
- /* @__PURE__ */ jsx8(Import, { size: 12 }),
2303
+ /* @__PURE__ */ jsx9(Import, { size: 12 }),
2139
2304
  "\u4ECE\u5176\u4ED6\u4F1A\u8BDD\u5BFC\u5165",
2140
- /* @__PURE__ */ jsx8(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
2305
+ /* @__PURE__ */ jsx9(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
2141
2306
  ]
2142
2307
  }
2143
2308
  ),
2144
- showSessionPicker && /* @__PURE__ */ jsx8("div", { className: "absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-lg", children: loadingSessions ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
2145
- /* @__PURE__ */ jsx8(Loader22, { size: 12, className: "animate-spin" }),
2309
+ showSessionPicker && /* @__PURE__ */ jsx9("div", { className: "absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-lg", children: loadingSessions ? /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
2310
+ /* @__PURE__ */ jsx9(Loader22, { size: 12, className: "animate-spin" }),
2146
2311
  "\u52A0\u8F7D\u4F1A\u8BDD\u5217\u8868\u2026"
2147
- ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx8("div", { className: "px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5176\u4ED6\u4F1A\u8BDD" }) : sessions.map((s) => /* @__PURE__ */ jsxs7(
2312
+ ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5176\u4ED6\u4F1A\u8BDD" }) : sessions.map((s) => /* @__PURE__ */ jsxs8(
2148
2313
  "button",
2149
2314
  {
2150
2315
  type: "button",
@@ -2152,16 +2317,16 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2152
2317
  onClick: () => handleImportSession(s.id),
2153
2318
  className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))] disabled:opacity-50",
2154
2319
  children: [
2155
- importingId === s.id && /* @__PURE__ */ jsx8(Loader22, { size: 10, className: "shrink-0 animate-spin" }),
2156
- /* @__PURE__ */ jsx8("span", { className: "truncate", children: s.intent })
2320
+ importingId === s.id && /* @__PURE__ */ jsx9(Loader22, { size: 10, className: "shrink-0 animate-spin" }),
2321
+ /* @__PURE__ */ jsx9("span", { className: "truncate", children: s.intent })
2157
2322
  ]
2158
2323
  },
2159
2324
  s.id
2160
2325
  )) })
2161
2326
  ] }),
2162
- /* @__PURE__ */ jsxs7("div", { children: [
2163
- /* @__PURE__ */ jsx8("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
2164
- /* @__PURE__ */ jsx8(
2327
+ /* @__PURE__ */ jsxs8("div", { children: [
2328
+ /* @__PURE__ */ jsx9("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
2329
+ /* @__PURE__ */ jsx9(
2165
2330
  "input",
2166
2331
  {
2167
2332
  id: "ctx-label",
@@ -2172,13 +2337,13 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2172
2337
  }
2173
2338
  )
2174
2339
  ] }),
2175
- /* @__PURE__ */ jsxs7("div", { children: [
2176
- /* @__PURE__ */ jsx8("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
2177
- isImportProcessing && /* @__PURE__ */ jsxs7("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
2178
- /* @__PURE__ */ jsx8(Loader22, { size: 11, className: "animate-spin" }),
2340
+ /* @__PURE__ */ jsxs8("div", { children: [
2341
+ /* @__PURE__ */ jsx9("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
2342
+ isImportProcessing && /* @__PURE__ */ jsxs8("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
2343
+ /* @__PURE__ */ jsx9(Loader22, { size: 11, className: "animate-spin" }),
2179
2344
  "\u6B63\u5728\u5904\u7406\u5BFC\u5165\u5185\u5BB9\u5E76\u5199\u5165 workspace/context\uFF0C\u5B8C\u6210\u540E\u53EF\u70B9\u51FB\u201C\u786E\u5B9A\u201D"
2180
2345
  ] }),
2181
- /* @__PURE__ */ jsx8(
2346
+ /* @__PURE__ */ jsx9(
2182
2347
  "textarea",
2183
2348
  {
2184
2349
  id: "ctx-content",
@@ -2191,8 +2356,8 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2191
2356
  )
2192
2357
  ] })
2193
2358
  ] }),
2194
- /* @__PURE__ */ jsxs7("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
2195
- /* @__PURE__ */ jsx8(
2359
+ /* @__PURE__ */ jsxs8("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
2360
+ /* @__PURE__ */ jsx9(
2196
2361
  "button",
2197
2362
  {
2198
2363
  type: "button",
@@ -2201,7 +2366,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2201
2366
  children: "\u53D6\u6D88"
2202
2367
  }
2203
2368
  ),
2204
- /* @__PURE__ */ jsx8(
2369
+ /* @__PURE__ */ jsx9(
2205
2370
  "button",
2206
2371
  {
2207
2372
  type: "button",
@@ -2229,11 +2394,11 @@ function ComposerContextPill({
2229
2394
  content,
2230
2395
  onRemove
2231
2396
  }) {
2232
- const [showDetail, setShowDetail] = useState6(false);
2397
+ const [showDetail, setShowDetail] = useState7(false);
2233
2398
  const tokenK = formatTokenK(content);
2234
- return /* @__PURE__ */ jsxs7(Fragment, { children: [
2235
- /* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
2236
- /* @__PURE__ */ jsx8(
2399
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
2400
+ /* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
2401
+ /* @__PURE__ */ jsx9(
2237
2402
  "button",
2238
2403
  {
2239
2404
  type: "button",
@@ -2243,7 +2408,7 @@ function ComposerContextPill({
2243
2408
  children: label
2244
2409
  }
2245
2410
  ),
2246
- /* @__PURE__ */ jsx8(
2411
+ /* @__PURE__ */ jsx9(
2247
2412
  "span",
2248
2413
  {
2249
2414
  className: "shrink-0 rounded bg-[hsl(var(--background))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -2251,18 +2416,18 @@ function ComposerContextPill({
2251
2416
  children: tokenK
2252
2417
  }
2253
2418
  ),
2254
- /* @__PURE__ */ jsx8(
2419
+ /* @__PURE__ */ jsx9(
2255
2420
  "button",
2256
2421
  {
2257
2422
  type: "button",
2258
2423
  onClick: () => onRemove(id),
2259
2424
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${label}`,
2260
2425
  className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
2261
- children: /* @__PURE__ */ jsx8(X2, { size: 10 })
2426
+ children: /* @__PURE__ */ jsx9(X2, { size: 10 })
2262
2427
  }
2263
2428
  )
2264
2429
  ] }),
2265
- showDetail && /* @__PURE__ */ jsx8(
2430
+ showDetail && /* @__PURE__ */ jsx9(
2266
2431
  "div",
2267
2432
  {
2268
2433
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-6",
@@ -2270,26 +2435,26 @@ function ComposerContextPill({
2270
2435
  onKeyDown: (e) => {
2271
2436
  if (e.key === "Escape") setShowDetail(false);
2272
2437
  },
2273
- children: /* @__PURE__ */ jsxs7(
2438
+ children: /* @__PURE__ */ jsxs8(
2274
2439
  "div",
2275
2440
  {
2276
2441
  className: "w-full max-w-4xl max-h-[85vh] flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl",
2277
2442
  onClick: (e) => e.stopPropagation(),
2278
2443
  onKeyDown: (e) => e.stopPropagation(),
2279
2444
  children: [
2280
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
2281
- /* @__PURE__ */ jsx8("h4", { className: "text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
2282
- /* @__PURE__ */ jsx8(
2445
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
2446
+ /* @__PURE__ */ jsx9("h4", { className: "text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
2447
+ /* @__PURE__ */ jsx9(
2283
2448
  "button",
2284
2449
  {
2285
2450
  type: "button",
2286
2451
  onClick: () => setShowDetail(false),
2287
2452
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2288
- children: /* @__PURE__ */ jsx8(X2, { size: 14 })
2453
+ children: /* @__PURE__ */ jsx9(X2, { size: 14 })
2289
2454
  }
2290
2455
  )
2291
2456
  ] }),
2292
- /* @__PURE__ */ jsx8("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: /* @__PURE__ */ jsx8("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content }) })
2457
+ /* @__PURE__ */ jsx9("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: /* @__PURE__ */ jsx9("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content }) })
2293
2458
  ]
2294
2459
  }
2295
2460
  )
@@ -2443,7 +2608,7 @@ function ChatInput({
2443
2608
  onResyncSkills,
2444
2609
  isResyncingSkills = false
2445
2610
  }) {
2446
- const [input, setInputInternal] = useState6(externalDraft?.value ?? "");
2611
+ const [input, setInputInternal] = useState7(externalDraft?.value ?? "");
2447
2612
  const setInput = useEffectEvent2((value) => {
2448
2613
  setInputInternal(value);
2449
2614
  externalDraft?.setValue(value);
@@ -2459,7 +2624,7 @@ function ChatInput({
2459
2624
  }
2460
2625
  setInputInternal(externalDraftValue);
2461
2626
  }, [externalDraftValue]);
2462
- const [composerAttachments, setComposerAttachmentsInternal] = useState6(
2627
+ const [composerAttachments, setComposerAttachmentsInternal] = useState7(
2463
2628
  externalAttachments?.value ?? []
2464
2629
  );
2465
2630
  const setComposerAttachments = useEffectEvent2(
@@ -2479,10 +2644,10 @@ function ChatInput({
2479
2644
  if (composerAttachmentsRef.current === externalAttachmentsValue) return;
2480
2645
  setComposerAttachmentsInternal(externalAttachmentsValue);
2481
2646
  }, [externalAttachmentsValue]);
2482
- const [dragging, setDragging] = useState6(false);
2483
- const [isEditorFocused, setIsEditorFocused] = useState6(false);
2484
- const [oversizedFiles, setOversizedFiles] = useState6([]);
2485
- const [selectedModel, setSelectedModel] = useState6("");
2647
+ const [dragging, setDragging] = useState7(false);
2648
+ const [isEditorFocused, setIsEditorFocused] = useState7(false);
2649
+ const [oversizedFiles, setOversizedFiles] = useState7([]);
2650
+ const [selectedModel, setSelectedModel] = useState7("");
2486
2651
  const { setPreferredModel } = usePreferredModel();
2487
2652
  const queryClient = useQueryClient2();
2488
2653
  const actionMenuRef = useRef4(null);
@@ -2522,7 +2687,7 @@ function ChatInput({
2522
2687
  const inputHistory = useInputHistory(activeSessionId);
2523
2688
  const getSessionId = useEffectEvent2(() => activeSessionId);
2524
2689
  const handleSlashCommand = useEffectEvent2((commandId) => onCommand?.(commandId));
2525
- const [localImageUrls, setLocalImageUrls] = useState6({});
2690
+ const [localImageUrls, setLocalImageUrls] = useState7({});
2526
2691
  useEffect7(() => {
2527
2692
  const closeActionMenu = (event) => {
2528
2693
  const menu = actionMenuRef.current;
@@ -2650,7 +2815,7 @@ function ChatInput({
2650
2815
  if (!container || !root) return;
2651
2816
  updateSuggestionPosition(container, props.clientRect);
2652
2817
  root.render(
2653
- /* @__PURE__ */ jsx8(
2818
+ /* @__PURE__ */ jsx9(
2654
2819
  FileCompletionMenu,
2655
2820
  {
2656
2821
  ref: (instance) => {
@@ -2727,7 +2892,7 @@ function ChatInput({
2727
2892
  if (!container || !root) return;
2728
2893
  updateSuggestionPosition(container, props.clientRect);
2729
2894
  root.render(
2730
- /* @__PURE__ */ jsx8(
2895
+ /* @__PURE__ */ jsx9(
2731
2896
  SkillCompletionMenu,
2732
2897
  {
2733
2898
  ref: (instance) => {
@@ -3055,7 +3220,7 @@ function ChatInput({
3055
3220
  const removeAttachment = (id) => {
3056
3221
  setComposerAttachments((prev) => prev.filter((attachment) => attachment.id !== id));
3057
3222
  };
3058
- const [showAddContext, setShowAddContext] = useState6(false);
3223
+ const [showAddContext, setShowAddContext] = useState7(false);
3059
3224
  const isPlanning = mode === "planning";
3060
3225
  const placeholder = isPlanning ? "\u89C4\u5212\u8FDB\u884C\u4E2D\u2026 \u53EF\u8F93\u5165\u8865\u5145\u9700\u6C42\u6216\u7B49\u5F85\u5B8C\u6210" : "\u8F93\u5165\u6D88\u606F\u2026";
3061
3226
  const attachments = renderAttachments?.() ?? null;
@@ -3074,385 +3239,388 @@ function ChatInput({
3074
3239
  );
3075
3240
  const hasValidAttachments = composerAttachments.some((attachment) => attachment.status !== "failed");
3076
3241
  const isSendDisabled = connectionStatus !== "connected" || hasUploadingFiles || !input.trim() && !hasValidAttachments && !hasRenderedAttachments && !hasPendingContexts;
3077
- return /* @__PURE__ */ jsxs7(Fragment, { children: [
3078
- /* @__PURE__ */ jsx8("div", { className: `bg-[hsl(var(--background))] px-5 py-3 ${className ?? ""}`, children: /* @__PURE__ */ jsx8("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: /* @__PURE__ */ jsx8(
3079
- "div",
3080
- {
3081
- className: "relative",
3082
- onDragOver: (event) => {
3083
- event.preventDefault();
3084
- setDragging(true);
3085
- },
3086
- onDragLeave: () => setDragging(false),
3087
- onDrop: (event) => {
3088
- event.preventDefault();
3089
- setDragging(false);
3090
- const fileRef = event.dataTransfer.getData("application/blade-file-ref");
3091
- if (fileRef) {
3092
- try {
3093
- const { path, name } = JSON.parse(fileRef);
3094
- const normalizedPath = path.replace(/^\.?\//, "");
3095
- const sandboxPath = path.startsWith("/") ? path : activeSessionId ? `/root/\u667A\u80FD\u52A9\u624B\u5DE5\u4F5C\u7A7A\u95F4/${activeSessionId}/${normalizedPath}` : normalizedPath;
3096
- const editor2 = editorRef.current;
3097
- if (editor2) {
3098
- editor2.commands.focus("end");
3099
- editor2.commands.insertContent([
3100
- { type: "fileMention", attrs: { path: sandboxPath, name } },
3101
- { type: "text", text: " " }
3102
- ]);
3242
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
3243
+ /* @__PURE__ */ jsx9("div", { className: `bg-[hsl(var(--background))] px-5 py-3 ${className ?? ""}`, children: /* @__PURE__ */ jsxs8("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
3244
+ activeSessionId ? /* @__PURE__ */ jsx9(BackgroundTasksPill, { sessionId: activeSessionId }) : null,
3245
+ /* @__PURE__ */ jsx9(
3246
+ "div",
3247
+ {
3248
+ className: "relative",
3249
+ onDragOver: (event) => {
3250
+ event.preventDefault();
3251
+ setDragging(true);
3252
+ },
3253
+ onDragLeave: () => setDragging(false),
3254
+ onDrop: (event) => {
3255
+ event.preventDefault();
3256
+ setDragging(false);
3257
+ const fileRef = event.dataTransfer.getData("application/blade-file-ref");
3258
+ if (fileRef) {
3259
+ try {
3260
+ const { path, name } = JSON.parse(fileRef);
3261
+ const normalizedPath = path.replace(/^\.?\//, "");
3262
+ const sandboxPath = path.startsWith("/") ? path : activeSessionId ? `/root/\u667A\u80FD\u52A9\u624B\u5DE5\u4F5C\u7A7A\u95F4/${activeSessionId}/${normalizedPath}` : normalizedPath;
3263
+ const editor2 = editorRef.current;
3264
+ if (editor2) {
3265
+ editor2.commands.focus("end");
3266
+ editor2.commands.insertContent([
3267
+ { type: "fileMention", attrs: { path: sandboxPath, name } },
3268
+ { type: "text", text: " " }
3269
+ ]);
3270
+ }
3271
+ } catch {
3103
3272
  }
3104
- } catch {
3273
+ return;
3105
3274
  }
3106
- return;
3107
- }
3108
- void stableAppendFiles(event.dataTransfer.files);
3109
- },
3110
- children: /* @__PURE__ */ jsxs7(
3111
- "div",
3112
- {
3113
- className: `overflow-visible rounded-2xl border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${isRecording ? "border-emerald-400/70! shadow-[0_0_0_3px_rgba(52,211,153,0.18),0_0_24px_rgba(52,211,153,0.28)]" : dragging ? isPlanning ? "border-amber-400/60" : "border-[hsl(var(--primary)/0.6)]" : isEditorFocused ? isPlanning ? "border-amber-400/60" : "border-[hsl(var(--primary)/0.6)]" : isPlanning ? "border-amber-400/30" : "border-[hsl(var(--border))]"}`,
3114
- children: [
3115
- dragging && /* @__PURE__ */ jsx8("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.06)]", children: /* @__PURE__ */ jsx8("span", { className: "rounded-full bg-[hsl(var(--primary)/0.12)] px-4 py-2 text-sm font-medium text-[hsl(var(--primary))]", children: "\u677E\u624B\u5F15\u7528\u6587\u4EF6" }) }),
3116
- composerAttachments.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2", children: [
3117
- imageAttachments.length > 0 && /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs7(
3118
- "div",
3119
- {
3120
- className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
3121
- children: [
3122
- /* @__PURE__ */ jsx8(
3123
- "img",
3124
- {
3125
- src: getImagePreviewUrl(attachment, activeSessionId, localImageUrls),
3126
- alt: attachment.name || "\u56FE\u7247\u9884\u89C8",
3127
- className: "h-24 w-full object-cover"
3128
- }
3129
- ),
3130
- /* @__PURE__ */ jsx8(
3131
- "button",
3132
- {
3133
- type: "button",
3134
- onClick: () => removeAttachment(attachment.id),
3135
- "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
3136
- className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-full bg-[hsl(var(--background)/0.85)] text-[hsl(var(--foreground))]",
3137
- children: /* @__PURE__ */ jsx8(X2, { size: 12 })
3275
+ void stableAppendFiles(event.dataTransfer.files);
3276
+ },
3277
+ children: /* @__PURE__ */ jsxs8(
3278
+ "div",
3279
+ {
3280
+ className: `overflow-visible rounded-2xl border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${isRecording ? "border-emerald-400/70! shadow-[0_0_0_3px_rgba(52,211,153,0.18),0_0_24px_rgba(52,211,153,0.28)]" : dragging ? isPlanning ? "border-amber-400/60" : "border-[hsl(var(--primary)/0.6)]" : isEditorFocused ? isPlanning ? "border-amber-400/60" : "border-[hsl(var(--primary)/0.6)]" : isPlanning ? "border-amber-400/30" : "border-[hsl(var(--border))]"}`,
3281
+ children: [
3282
+ dragging && /* @__PURE__ */ jsx9("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.06)]", children: /* @__PURE__ */ jsx9("span", { className: "rounded-full bg-[hsl(var(--primary)/0.12)] px-4 py-2 text-sm font-medium text-[hsl(var(--primary))]", children: "\u677E\u624B\u5F15\u7528\u6587\u4EF6" }) }),
3283
+ composerAttachments.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2", children: [
3284
+ imageAttachments.length > 0 && /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs8(
3285
+ "div",
3286
+ {
3287
+ className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
3288
+ children: [
3289
+ /* @__PURE__ */ jsx9(
3290
+ "img",
3291
+ {
3292
+ src: getImagePreviewUrl(attachment, activeSessionId, localImageUrls),
3293
+ alt: attachment.name || "\u56FE\u7247\u9884\u89C8",
3294
+ className: "h-24 w-full object-cover"
3295
+ }
3296
+ ),
3297
+ /* @__PURE__ */ jsx9(
3298
+ "button",
3299
+ {
3300
+ type: "button",
3301
+ onClick: () => removeAttachment(attachment.id),
3302
+ "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
3303
+ className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-full bg-[hsl(var(--background)/0.85)] text-[hsl(var(--foreground))]",
3304
+ children: /* @__PURE__ */ jsx9(X2, { size: 12 })
3305
+ }
3306
+ )
3307
+ ]
3308
+ },
3309
+ attachment.id
3310
+ )) }),
3311
+ fileAttachments.length > 0 && /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx9(
3312
+ ComposerFilePill,
3313
+ {
3314
+ attachment,
3315
+ onRemove: removeAttachment
3316
+ },
3317
+ attachment.id
3318
+ )) })
3319
+ ] }),
3320
+ hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2", children: [
3321
+ pendingContexts?.map((context) => /* @__PURE__ */ jsx9(
3322
+ ComposerContextPill,
3323
+ {
3324
+ id: context.id,
3325
+ label: context.label,
3326
+ content: context.content,
3327
+ onRemove: (contextId) => {
3328
+ if (!activeSessionId) {
3329
+ return;
3138
3330
  }
3139
- )
3140
- ]
3141
- },
3142
- attachment.id
3143
- )) }),
3144
- fileAttachments.length > 0 && /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx8(
3145
- ComposerFilePill,
3146
- {
3147
- attachment,
3148
- onRemove: removeAttachment
3149
- },
3150
- attachment.id
3151
- )) })
3152
- ] }),
3153
- hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2", children: [
3154
- pendingContexts?.map((context) => /* @__PURE__ */ jsx8(
3155
- ComposerContextPill,
3156
- {
3157
- id: context.id,
3158
- label: context.label,
3159
- content: context.content,
3160
- onRemove: (contextId) => {
3161
- if (!activeSessionId) {
3162
- return;
3331
+ removePendingContext(activeSessionId, contextId);
3163
3332
  }
3164
- removePendingContext(activeSessionId, contextId);
3333
+ },
3334
+ context.id
3335
+ )),
3336
+ isSkillEditor && /* @__PURE__ */ jsx9(
3337
+ "button",
3338
+ {
3339
+ type: "button",
3340
+ onClick: () => setShowAddContext(true),
3341
+ title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
3342
+ className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-dashed border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]",
3343
+ children: /* @__PURE__ */ jsx9(Plus, { size: 12 })
3165
3344
  }
3166
- },
3167
- context.id
3168
- )),
3169
- isSkillEditor && /* @__PURE__ */ jsx8(
3170
- "button",
3345
+ )
3346
+ ] }) : null,
3347
+ showAddContext && activeSessionId && /* @__PURE__ */ jsx9(
3348
+ AddContextDialog,
3171
3349
  {
3172
- type: "button",
3173
- onClick: () => setShowAddContext(true),
3174
- title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
3175
- className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-dashed border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]",
3176
- children: /* @__PURE__ */ jsx8(Plus, { size: 12 })
3177
- }
3178
- )
3179
- ] }) : null,
3180
- showAddContext && activeSessionId && /* @__PURE__ */ jsx8(
3181
- AddContextDialog,
3182
- {
3183
- sessionId: activeSessionId,
3184
- onClose: () => setShowAddContext(false),
3185
- onAdd: (label, content) => {
3186
- if (activeSessionId) {
3187
- useUiBridgeStore.getState().addPendingContext(activeSessionId, { label, content });
3350
+ sessionId: activeSessionId,
3351
+ onClose: () => setShowAddContext(false),
3352
+ onAdd: (label, content) => {
3353
+ if (activeSessionId) {
3354
+ useUiBridgeStore.getState().addPendingContext(activeSessionId, { label, content });
3355
+ }
3188
3356
  }
3189
3357
  }
3190
- }
3191
- ),
3192
- attachments ? /* @__PURE__ */ jsx8("div", { className: "border-b border-[hsl(var(--border))] px-3 py-3", children: attachments }) : null,
3193
- slotAboveTextarea ? /* @__PURE__ */ jsx8("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2", children: slotAboveTextarea }) : null,
3194
- /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
3195
- input.length === 0 && /* @__PURE__ */ jsx8("div", { className: "pointer-events-none absolute left-4 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground))]", children: placeholder }),
3196
- /* @__PURE__ */ jsx8(EditorContent, { editor })
3197
- ] }),
3198
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between border-t border-[hsl(var(--border))] px-3 py-1.5", children: [
3199
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
3200
- /* @__PURE__ */ jsx8(
3201
- "input",
3202
- {
3203
- ref: fileInputRef,
3204
- type: "file",
3205
- accept: "*/*",
3206
- multiple: true,
3207
- onChange: (event) => {
3208
- if (event.target.files) {
3209
- void appendFiles(event.target.files);
3210
- event.target.value = "";
3211
- }
3212
- },
3213
- className: "hidden"
3214
- }
3215
- ),
3216
- /* @__PURE__ */ jsx8(
3217
- "input",
3218
- {
3219
- ref: folderInputRef,
3220
- type: "file",
3221
- multiple: true,
3222
- onChange: (event) => {
3223
- if (event.target.files) {
3224
- void appendFiles(event.target.files);
3225
- event.target.value = "";
3226
- }
3227
- },
3228
- className: "hidden",
3229
- ...{ webkitdirectory: "" }
3230
- }
3231
- ),
3232
- /* @__PURE__ */ jsxs7("details", { ref: actionMenuRef, className: "group relative", children: [
3233
- /* @__PURE__ */ jsx8(
3234
- "summary",
3358
+ ),
3359
+ attachments ? /* @__PURE__ */ jsx9("div", { className: "border-b border-[hsl(var(--border))] px-3 py-3", children: attachments }) : null,
3360
+ slotAboveTextarea ? /* @__PURE__ */ jsx9("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2", children: slotAboveTextarea }) : null,
3361
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
3362
+ input.length === 0 && /* @__PURE__ */ jsx9("div", { className: "pointer-events-none absolute left-4 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground))]", children: placeholder }),
3363
+ /* @__PURE__ */ jsx9(EditorContent, { editor })
3364
+ ] }),
3365
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-t border-[hsl(var(--border))] px-3 py-1.5", children: [
3366
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
3367
+ /* @__PURE__ */ jsx9(
3368
+ "input",
3235
3369
  {
3236
- "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
3237
- title: "\u6DFB\u52A0\u5185\u5BB9",
3238
- className: "flex h-7 w-7 shrink-0 cursor-pointer list-none items-center justify-center rounded-lg border border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] [&::-webkit-details-marker]:hidden",
3239
- children: /* @__PURE__ */ jsx8(Plus, { size: 14 })
3370
+ ref: fileInputRef,
3371
+ type: "file",
3372
+ accept: "*/*",
3373
+ multiple: true,
3374
+ onChange: (event) => {
3375
+ if (event.target.files) {
3376
+ void appendFiles(event.target.files);
3377
+ event.target.value = "";
3378
+ }
3379
+ },
3380
+ className: "hidden"
3240
3381
  }
3241
3382
  ),
3242
- /* @__PURE__ */ jsxs7("div", { className: "absolute bottom-full left-0 z-30 mb-2 min-w-36 overflow-visible rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 text-[11px] text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3243
- /* @__PURE__ */ jsxs7(
3244
- "button",
3245
- {
3246
- type: "button",
3247
- onClick: () => {
3248
- actionMenuRef.current?.removeAttribute("open");
3249
- fileInputRef.current?.click();
3250
- },
3251
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3252
- children: [
3253
- /* @__PURE__ */ jsx8(Paperclip, { size: 13 }),
3254
- "\u4E0A\u4F20\u6587\u4EF6"
3255
- ]
3256
- }
3257
- ),
3258
- /* @__PURE__ */ jsxs7(
3259
- "button",
3383
+ /* @__PURE__ */ jsx9(
3384
+ "input",
3385
+ {
3386
+ ref: folderInputRef,
3387
+ type: "file",
3388
+ multiple: true,
3389
+ onChange: (event) => {
3390
+ if (event.target.files) {
3391
+ void appendFiles(event.target.files);
3392
+ event.target.value = "";
3393
+ }
3394
+ },
3395
+ className: "hidden",
3396
+ ...{ webkitdirectory: "" }
3397
+ }
3398
+ ),
3399
+ /* @__PURE__ */ jsxs8("details", { ref: actionMenuRef, className: "group relative", children: [
3400
+ /* @__PURE__ */ jsx9(
3401
+ "summary",
3260
3402
  {
3261
- type: "button",
3262
- onClick: () => {
3263
- actionMenuRef.current?.removeAttribute("open");
3264
- folderInputRef.current?.click();
3265
- },
3266
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3267
- children: [
3268
- /* @__PURE__ */ jsx8(FolderUp, { size: 13 }),
3269
- "\u4E0A\u4F20\u6587\u4EF6\u5939"
3270
- ]
3403
+ "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
3404
+ title: "\u6DFB\u52A0\u5185\u5BB9",
3405
+ className: "flex h-7 w-7 shrink-0 cursor-pointer list-none items-center justify-center rounded-lg border border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] [&::-webkit-details-marker]:hidden",
3406
+ children: /* @__PURE__ */ jsx9(Plus, { size: 14 })
3271
3407
  }
3272
3408
  ),
3273
- onCommand ? /* @__PURE__ */ jsxs7(Fragment, { children: [
3274
- /* @__PURE__ */ jsxs7(
3409
+ /* @__PURE__ */ jsxs8("div", { className: "absolute bottom-full left-0 z-30 mb-2 min-w-36 overflow-visible rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 text-[11px] text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3410
+ /* @__PURE__ */ jsxs8(
3275
3411
  "button",
3276
3412
  {
3277
3413
  type: "button",
3278
3414
  onClick: () => {
3279
3415
  actionMenuRef.current?.removeAttribute("open");
3280
- void onCommand("compact");
3281
- },
3282
- disabled: isStreaming,
3283
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
3284
- children: [
3285
- isStreaming ? /* @__PURE__ */ jsx8(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx8(Scissors, { size: 13 }),
3286
- "\u6574\u7406\u5BF9\u8BDD"
3287
- ]
3288
- }
3289
- ),
3290
- /* @__PURE__ */ jsxs7(
3291
- "button",
3292
- {
3293
- type: "button",
3294
- onClick: () => {
3295
- actionMenuRef.current?.removeAttribute("open");
3296
- void onCommand("download_session");
3416
+ fileInputRef.current?.click();
3297
3417
  },
3298
3418
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3299
3419
  children: [
3300
- /* @__PURE__ */ jsx8(Download, { size: 13 }),
3301
- "\u5BFC\u51FA\u4F1A\u8BDD"
3420
+ /* @__PURE__ */ jsx9(Paperclip, { size: 13 }),
3421
+ "\u4E0A\u4F20\u6587\u4EF6"
3302
3422
  ]
3303
3423
  }
3304
3424
  ),
3305
- canShareSession ? /* @__PURE__ */ jsxs7(
3306
- "button",
3307
- {
3308
- type: "button",
3309
- onClick: () => {
3310
- actionMenuRef.current?.removeAttribute("open");
3311
- void onCommand("share_session");
3312
- },
3313
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3314
- children: [
3315
- /* @__PURE__ */ jsx8(Share2, { size: 13 }),
3316
- "\u5206\u4EAB\u4F1A\u8BDD"
3317
- ]
3318
- }
3319
- ) : null,
3320
- /* @__PURE__ */ jsxs7(
3425
+ /* @__PURE__ */ jsxs8(
3321
3426
  "button",
3322
3427
  {
3323
3428
  type: "button",
3324
3429
  onClick: () => {
3325
3430
  actionMenuRef.current?.removeAttribute("open");
3326
- void onCommand("extract_skill");
3431
+ folderInputRef.current?.click();
3327
3432
  },
3328
3433
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3329
3434
  children: [
3330
- /* @__PURE__ */ jsx8(FlaskConical, { size: 13 }),
3331
- "\u63D0\u53D6\u6280\u80FD"
3435
+ /* @__PURE__ */ jsx9(FolderUp, { size: 13 }),
3436
+ "\u4E0A\u4F20\u6587\u4EF6\u5939"
3332
3437
  ]
3333
3438
  }
3334
3439
  ),
3335
- /* @__PURE__ */ jsxs7(
3336
- "button",
3337
- {
3338
- type: "button",
3339
- onClick: () => {
3340
- actionMenuRef.current?.removeAttribute("open");
3341
- void onCommand("generate_app");
3342
- },
3343
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3344
- children: [
3345
- /* @__PURE__ */ jsx8(Rocket, { size: 13 }),
3346
- "\u751F\u6210\u5E94\u7528"
3347
- ]
3348
- }
3349
- )
3350
- ] }) : null,
3351
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 px-3 py-2", children: [
3352
- /* @__PURE__ */ jsx8(Sparkles2, { size: 13 }),
3353
- /* @__PURE__ */ jsx8("span", { className: "shrink-0", children: "\u6A21\u578B" }),
3354
- /* @__PURE__ */ jsx8(
3355
- ModelSelector,
3356
- {
3357
- value: selectedModel,
3358
- onValueChange: (model) => {
3359
- setSelectedModel(model);
3360
- if (activeSessionId) {
3361
- patchSession(activeSessionId, { model });
3362
- }
3363
- setPreferredModel(model);
3364
- },
3365
- compact: true,
3366
- placement: "top"
3367
- }
3368
- )
3440
+ onCommand ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
3441
+ /* @__PURE__ */ jsxs8(
3442
+ "button",
3443
+ {
3444
+ type: "button",
3445
+ onClick: () => {
3446
+ actionMenuRef.current?.removeAttribute("open");
3447
+ void onCommand("compact");
3448
+ },
3449
+ disabled: isStreaming,
3450
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
3451
+ children: [
3452
+ isStreaming ? /* @__PURE__ */ jsx9(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx9(Scissors, { size: 13 }),
3453
+ "\u6574\u7406\u5BF9\u8BDD"
3454
+ ]
3455
+ }
3456
+ ),
3457
+ /* @__PURE__ */ jsxs8(
3458
+ "button",
3459
+ {
3460
+ type: "button",
3461
+ onClick: () => {
3462
+ actionMenuRef.current?.removeAttribute("open");
3463
+ void onCommand("download_session");
3464
+ },
3465
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3466
+ children: [
3467
+ /* @__PURE__ */ jsx9(Download, { size: 13 }),
3468
+ "\u5BFC\u51FA\u4F1A\u8BDD"
3469
+ ]
3470
+ }
3471
+ ),
3472
+ canShareSession ? /* @__PURE__ */ jsxs8(
3473
+ "button",
3474
+ {
3475
+ type: "button",
3476
+ onClick: () => {
3477
+ actionMenuRef.current?.removeAttribute("open");
3478
+ void onCommand("share_session");
3479
+ },
3480
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3481
+ children: [
3482
+ /* @__PURE__ */ jsx9(Share2, { size: 13 }),
3483
+ "\u5206\u4EAB\u4F1A\u8BDD"
3484
+ ]
3485
+ }
3486
+ ) : null,
3487
+ /* @__PURE__ */ jsxs8(
3488
+ "button",
3489
+ {
3490
+ type: "button",
3491
+ onClick: () => {
3492
+ actionMenuRef.current?.removeAttribute("open");
3493
+ void onCommand("extract_skill");
3494
+ },
3495
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3496
+ children: [
3497
+ /* @__PURE__ */ jsx9(FlaskConical, { size: 13 }),
3498
+ "\u63D0\u53D6\u6280\u80FD"
3499
+ ]
3500
+ }
3501
+ ),
3502
+ /* @__PURE__ */ jsxs8(
3503
+ "button",
3504
+ {
3505
+ type: "button",
3506
+ onClick: () => {
3507
+ actionMenuRef.current?.removeAttribute("open");
3508
+ void onCommand("generate_app");
3509
+ },
3510
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3511
+ children: [
3512
+ /* @__PURE__ */ jsx9(Rocket, { size: 13 }),
3513
+ "\u751F\u6210\u5E94\u7528"
3514
+ ]
3515
+ }
3516
+ )
3517
+ ] }) : null,
3518
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 px-3 py-2", children: [
3519
+ /* @__PURE__ */ jsx9(Sparkles2, { size: 13 }),
3520
+ /* @__PURE__ */ jsx9("span", { className: "shrink-0", children: "\u6A21\u578B" }),
3521
+ /* @__PURE__ */ jsx9(
3522
+ ModelSelector,
3523
+ {
3524
+ value: selectedModel,
3525
+ onValueChange: (model) => {
3526
+ setSelectedModel(model);
3527
+ if (activeSessionId) {
3528
+ patchSession(activeSessionId, { model });
3529
+ }
3530
+ setPreferredModel(model);
3531
+ },
3532
+ compact: true,
3533
+ placement: "top"
3534
+ }
3535
+ )
3536
+ ] })
3369
3537
  ] })
3370
- ] })
3371
- ] }),
3372
- /* @__PURE__ */ jsx8(
3373
- "button",
3374
- {
3375
- type: "button",
3376
- onClick: onToggleMode,
3377
- disabled: isStreaming || !onToggleMode,
3378
- "aria-pressed": isPlanning,
3379
- "aria-label": isPlanning ? "\u5173\u95ED\u89C4\u5212\u6A21\u5F0F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3380
- title: isPlanning ? "\u89C4\u5212\u6A21\u5F0F\u5DF2\u5F00\u542F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3381
- className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-lg border transition-colors ${isPlanning ? "border-amber-500/45 bg-amber-500/15 text-amber-400" : "border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-amber-500/35 hover:text-[hsl(var(--foreground))]"} disabled:cursor-not-allowed disabled:opacity-50`,
3382
- children: /* @__PURE__ */ jsx8(Lightbulb, { size: 13 })
3383
- }
3384
- )
3385
- ] }),
3386
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5", children: [
3387
- /* @__PURE__ */ jsxs7("div", { className: "group/help relative", children: [
3388
- /* @__PURE__ */ jsx8(
3538
+ ] }),
3539
+ /* @__PURE__ */ jsx9(
3389
3540
  "button",
3390
3541
  {
3391
3542
  type: "button",
3392
- "aria-label": "\u67E5\u770B\u8F93\u5165\u63D0\u793A",
3393
- className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
3394
- children: /* @__PURE__ */ jsx8(CircleHelp, { size: 13 })
3543
+ onClick: onToggleMode,
3544
+ disabled: isStreaming || !onToggleMode,
3545
+ "aria-pressed": isPlanning,
3546
+ "aria-label": isPlanning ? "\u5173\u95ED\u89C4\u5212\u6A21\u5F0F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3547
+ title: isPlanning ? "\u89C4\u5212\u6A21\u5F0F\u5DF2\u5F00\u542F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3548
+ className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-lg border transition-colors ${isPlanning ? "border-amber-500/45 bg-amber-500/15 text-amber-400" : "border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-amber-500/35 hover:text-[hsl(var(--foreground))]"} disabled:cursor-not-allowed disabled:opacity-50`,
3549
+ children: /* @__PURE__ */ jsx9(Lightbulb, { size: 13 })
3395
3550
  }
3396
- ),
3397
- /* @__PURE__ */ jsx8("div", { className: "pointer-events-auto absolute bottom-full right-0 z-30 hidden pb-2 group-hover/help:block group-focus-within/help:block", children: /* @__PURE__ */ jsxs7("div", { className: "min-w-64 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-left text-[11px] leading-5 text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3398
- activeSessionId ? /* @__PURE__ */ jsx8("div", { className: "mb-2 border-b border-[hsl(var(--border))] pb-2", children: /* @__PURE__ */ jsx8(
3399
- SkillStatusBarComponent,
3551
+ )
3552
+ ] }),
3553
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1.5", children: [
3554
+ /* @__PURE__ */ jsxs8("div", { className: "group/help relative", children: [
3555
+ /* @__PURE__ */ jsx9(
3556
+ "button",
3400
3557
  {
3401
- sessionId: activeSessionId,
3402
- onResync: onResyncSkills,
3403
- isResyncing: isResyncingSkills,
3404
- vertical: true,
3405
- className: skillStatusBarClassName,
3406
- innerClassName: skillStatusBarInnerClassName
3558
+ type: "button",
3559
+ "aria-label": "\u67E5\u770B\u8F93\u5165\u63D0\u793A",
3560
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
3561
+ children: /* @__PURE__ */ jsx9(CircleHelp, { size: 13 })
3407
3562
  }
3408
- ) }) : null,
3409
- /* @__PURE__ */ jsxs7("div", { className: "space-y-0.5", children: [
3410
- /* @__PURE__ */ jsx8("div", { children: "Shift+Enter \u6362\u884C" }),
3411
- /* @__PURE__ */ jsx8("div", { children: "/ \u8C03\u7528\u6280\u80FD" }),
3412
- /* @__PURE__ */ jsx8("div", { children: "@ \u5F15\u7528\u6587\u4EF6" })
3413
- ] })
3414
- ] }) })
3415
- ] }),
3416
- /* @__PURE__ */ jsx8(
3417
- "button",
3418
- {
3419
- type: "button",
3420
- onClick: asrEnabled ? voice.toggle : handleMicDisabledClick,
3421
- disabled: isStreaming,
3422
- "aria-label": !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
3423
- title: !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u8BED\u97F3\u8F93\u5165",
3424
- className: `flex items-center justify-center rounded-lg border transition-[width,height,border-color,background-color,color,box-shadow] duration-300 disabled:opacity-40 ${!asrEnabled ? "h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))]/50 hover:text-[hsl(var(--muted-foreground))]" : isRecording ? "h-9 w-9 border-emerald-400/80! bg-emerald-400/15 text-emerald-400 shadow-[0_0_0_2px_rgba(52,211,153,0.2),0_0_12px_rgba(52,211,153,0.35)]" : "h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]"}`,
3425
- children: !asrEnabled ? /* @__PURE__ */ jsx8(MicOff, { size: 13 }) : isRecording ? /* @__PURE__ */ jsx8(VoiceWaveform, { level: voiceLevel, size: 18 }) : /* @__PURE__ */ jsx8(Mic, { size: 13 })
3426
- }
3427
- ),
3428
- isStreaming ? /* @__PURE__ */ jsx8(
3429
- "button",
3430
- {
3431
- type: "button",
3432
- onClick: onStop,
3433
- "aria-label": "\u505C\u6B62\u751F\u6210",
3434
- className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80",
3435
- children: /* @__PURE__ */ jsx8(Square, { size: 13 })
3436
- }
3437
- ) : /* @__PURE__ */ jsx8(
3438
- "button",
3439
- {
3440
- type: "button",
3441
- onClick: handleSubmit,
3442
- disabled: isSendDisabled || isRecording,
3443
- "aria-label": "\u53D1\u9001\u6D88\u606F",
3444
- className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-80 disabled:opacity-25",
3445
- children: /* @__PURE__ */ jsx8(Send, { size: 13 })
3446
- }
3447
- )
3563
+ ),
3564
+ /* @__PURE__ */ jsx9("div", { className: "pointer-events-auto absolute bottom-full right-0 z-30 hidden pb-2 group-hover/help:block group-focus-within/help:block", children: /* @__PURE__ */ jsxs8("div", { className: "min-w-64 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-left text-[11px] leading-5 text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3565
+ activeSessionId ? /* @__PURE__ */ jsx9("div", { className: "mb-2 border-b border-[hsl(var(--border))] pb-2", children: /* @__PURE__ */ jsx9(
3566
+ SkillStatusBarComponent,
3567
+ {
3568
+ sessionId: activeSessionId,
3569
+ onResync: onResyncSkills,
3570
+ isResyncing: isResyncingSkills,
3571
+ vertical: true,
3572
+ className: skillStatusBarClassName,
3573
+ innerClassName: skillStatusBarInnerClassName
3574
+ }
3575
+ ) }) : null,
3576
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-0.5", children: [
3577
+ /* @__PURE__ */ jsx9("div", { children: "Shift+Enter \u6362\u884C" }),
3578
+ /* @__PURE__ */ jsx9("div", { children: "/ \u8C03\u7528\u6280\u80FD" }),
3579
+ /* @__PURE__ */ jsx9("div", { children: "@ \u5F15\u7528\u6587\u4EF6" })
3580
+ ] })
3581
+ ] }) })
3582
+ ] }),
3583
+ /* @__PURE__ */ jsx9(
3584
+ "button",
3585
+ {
3586
+ type: "button",
3587
+ onClick: asrEnabled ? voice.toggle : handleMicDisabledClick,
3588
+ disabled: isStreaming,
3589
+ "aria-label": !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
3590
+ title: !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u8BED\u97F3\u8F93\u5165",
3591
+ className: `flex items-center justify-center rounded-lg border transition-[width,height,border-color,background-color,color,box-shadow] duration-300 disabled:opacity-40 ${!asrEnabled ? "h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))]/50 hover:text-[hsl(var(--muted-foreground))]" : isRecording ? "h-9 w-9 border-emerald-400/80! bg-emerald-400/15 text-emerald-400 shadow-[0_0_0_2px_rgba(52,211,153,0.2),0_0_12px_rgba(52,211,153,0.35)]" : "h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]"}`,
3592
+ children: !asrEnabled ? /* @__PURE__ */ jsx9(MicOff, { size: 13 }) : isRecording ? /* @__PURE__ */ jsx9(VoiceWaveform, { level: voiceLevel, size: 18 }) : /* @__PURE__ */ jsx9(Mic, { size: 13 })
3593
+ }
3594
+ ),
3595
+ isStreaming ? /* @__PURE__ */ jsx9(
3596
+ "button",
3597
+ {
3598
+ type: "button",
3599
+ onClick: onStop,
3600
+ "aria-label": "\u505C\u6B62\u751F\u6210",
3601
+ className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80",
3602
+ children: /* @__PURE__ */ jsx9(Square2, { size: 13 })
3603
+ }
3604
+ ) : /* @__PURE__ */ jsx9(
3605
+ "button",
3606
+ {
3607
+ type: "button",
3608
+ onClick: handleSubmit,
3609
+ disabled: isSendDisabled || isRecording,
3610
+ "aria-label": "\u53D1\u9001\u6D88\u606F",
3611
+ className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-80 disabled:opacity-25",
3612
+ children: /* @__PURE__ */ jsx9(Send, { size: 13 })
3613
+ }
3614
+ )
3615
+ ] })
3448
3616
  ] })
3449
- ] })
3450
- ]
3451
- }
3452
- )
3453
- }
3454
- ) }) }),
3455
- /* @__PURE__ */ jsx8(
3617
+ ]
3618
+ }
3619
+ )
3620
+ }
3621
+ )
3622
+ ] }) }),
3623
+ /* @__PURE__ */ jsx9(
3456
3624
  FileSizeLimitDialog,
3457
3625
  {
3458
3626
  open: oversizedFiles.length > 0,
@@ -3470,18 +3638,18 @@ function ChatInput({
3470
3638
 
3471
3639
  // src/react/components/chat/ConnectionBanner.tsx
3472
3640
  import { AlertTriangle, LoaderCircle } from "lucide-react";
3473
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3641
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3474
3642
  function getBannerCopy(status, reconnectAttempt, hasEverConnected) {
3475
3643
  if (status === "connecting") {
3476
3644
  return {
3477
- icon: /* @__PURE__ */ jsx9(LoaderCircle, { size: 14, className: "animate-spin" }),
3645
+ icon: /* @__PURE__ */ jsx10(LoaderCircle, { size: 14, className: "animate-spin" }),
3478
3646
  toneClass: "border-amber-500/25 bg-amber-500/10 text-amber-100",
3479
3647
  title: "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u91CD\u8FDE\u2026",
3480
3648
  detail: reconnectAttempt > 0 ? `\u6B63\u5728\u5C1D\u8BD5\u6062\u590D\u5B9E\u65F6\u8FDE\u63A5\uFF08\u7B2C ${reconnectAttempt} \u6B21\uFF09` : "\u6B63\u5728\u5C1D\u8BD5\u6062\u590D\u5B9E\u65F6\u8FDE\u63A5\uFF0C\u8BF7\u7A0D\u5019"
3481
3649
  };
3482
3650
  }
3483
3651
  return {
3484
- icon: /* @__PURE__ */ jsx9(AlertTriangle, { size: 14 }),
3652
+ icon: /* @__PURE__ */ jsx10(AlertTriangle, { size: 14 }),
3485
3653
  toneClass: "border-rose-500/25 bg-rose-500/10 text-rose-100",
3486
3654
  title: hasEverConnected ? "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u7B49\u5F85\u91CD\u8FDE\u2026" : "\u6682\u65F6\u65E0\u6CD5\u5EFA\u7ACB\u8FDE\u63A5",
3487
3655
  detail: hasEverConnected ? "\u6D88\u606F\u540C\u6B65\u53EF\u80FD\u4F1A\u5EF6\u8FDF\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" : "\u8BF7\u68C0\u67E5\u670D\u52A1\u662F\u5426\u53EF\u7528\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5"
@@ -3496,7 +3664,7 @@ function ConnectionBanner() {
3496
3664
  return null;
3497
3665
  }
3498
3666
  const copy = getBannerCopy(status, reconnectAttempt, hasEverConnected);
3499
- return /* @__PURE__ */ jsx9("div", { className: "bg-[hsl(var(--background))] px-5 pt-3", children: /* @__PURE__ */ jsxs8(
3667
+ return /* @__PURE__ */ jsx10("div", { className: "bg-[hsl(var(--background))] px-5 pt-3", children: /* @__PURE__ */ jsxs9(
3500
3668
  "div",
3501
3669
  {
3502
3670
  className: cn(
@@ -3504,10 +3672,10 @@ function ConnectionBanner() {
3504
3672
  copy.toneClass
3505
3673
  ),
3506
3674
  children: [
3507
- /* @__PURE__ */ jsx9("span", { className: "mt-0.5 shrink-0", children: copy.icon }),
3508
- /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
3509
- /* @__PURE__ */ jsx9("div", { className: "text-sm font-medium", children: copy.title }),
3510
- /* @__PURE__ */ jsx9("div", { className: "text-xs opacity-80", children: copy.detail })
3675
+ /* @__PURE__ */ jsx10("span", { className: "mt-0.5 shrink-0", children: copy.icon }),
3676
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
3677
+ /* @__PURE__ */ jsx10("div", { className: "text-sm font-medium", children: copy.title }),
3678
+ /* @__PURE__ */ jsx10("div", { className: "text-xs opacity-80", children: copy.detail })
3511
3679
  ] })
3512
3680
  ]
3513
3681
  }
@@ -3522,11 +3690,11 @@ import {
3522
3690
  useEffectEvent as useEffectEvent4,
3523
3691
  useMemo as useMemo17,
3524
3692
  useRef as useRef11,
3525
- useState as useState19
3693
+ useState as useState20
3526
3694
  } from "react";
3527
3695
 
3528
3696
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
3529
- import { useCallback as useCallback7, useMemo as useMemo8, useRef as useRef5, useState as useState7 } from "react";
3697
+ import { useCallback as useCallback7, useMemo as useMemo8, useRef as useRef5, useState as useState8 } from "react";
3530
3698
  var DEFAULT_SPRING_ANIMATION = {
3531
3699
  /**
3532
3700
  * A value from 0 to 1, on how much to damp the animation.
@@ -3563,9 +3731,9 @@ globalThis.document?.addEventListener("click", () => {
3563
3731
  mouseDown = false;
3564
3732
  });
3565
3733
  var useStickToBottom = (options = {}) => {
3566
- const [escapedFromLock, updateEscapedFromLock] = useState7(false);
3567
- const [isAtBottom, updateIsAtBottom] = useState7(options.initial !== false);
3568
- const [isNearBottom, setIsNearBottom] = useState7(false);
3734
+ const [escapedFromLock, updateEscapedFromLock] = useState8(false);
3735
+ const [isAtBottom, updateIsAtBottom] = useState8(options.initial !== false);
3736
+ const [isNearBottom, setIsNearBottom] = useState8(false);
3569
3737
  const optionsRef = useRef5(null);
3570
3738
  optionsRef.current = options;
3571
3739
  const isSelecting = useCallback7(() => {
@@ -3951,7 +4119,7 @@ function useStickToBottomContext() {
3951
4119
 
3952
4120
  // src/react/components/chat/AssistantTurnBlock.tsx
3953
4121
  import { AlertCircle, BookOpen, Check as Check4, ChevronRight as ChevronRight5 } from "lucide-react";
3954
- import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo15, useRef as useRef10, useState as useState16 } from "react";
4122
+ import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo15, useRef as useRef10, useState as useState17 } from "react";
3955
4123
 
3956
4124
  // src/react/routes.ts
3957
4125
  var MEMORIES_ROUTE = "/memories";
@@ -3970,7 +4138,7 @@ import {
3970
4138
  useEffect as useEffect9,
3971
4139
  useMemo as useMemo11,
3972
4140
  useRef as useRef7,
3973
- useState as useState8
4141
+ useState as useState9
3974
4142
  } from "react";
3975
4143
  import { createPortal as createPortal2 } from "react-dom";
3976
4144
  import { Streamdown } from "streamdown";
@@ -3978,7 +4146,7 @@ import { Streamdown } from "streamdown";
3978
4146
  // src/react/components/ai-elements/shimmer.tsx
3979
4147
  import { motion } from "motion/react";
3980
4148
  import { memo, useMemo as useMemo10 } from "react";
3981
- import { jsx as jsx10 } from "react/jsx-runtime";
4149
+ import { jsx as jsx11 } from "react/jsx-runtime";
3982
4150
  var motionComponentCache = /* @__PURE__ */ new Map();
3983
4151
  var getMotionComponent = (element) => {
3984
4152
  let component = motionComponentCache.get(element);
@@ -4002,7 +4170,7 @@ var ShimmerComponent = ({
4002
4170
  () => (children?.length ?? 0) * spread,
4003
4171
  [children, spread]
4004
4172
  );
4005
- return /* @__PURE__ */ jsx10(
4173
+ return /* @__PURE__ */ jsx11(
4006
4174
  MotionComponent,
4007
4175
  {
4008
4176
  animate: { backgroundPosition: "0% center" },
@@ -4028,7 +4196,7 @@ var ShimmerComponent = ({
4028
4196
  var Shimmer = memo(ShimmerComponent);
4029
4197
 
4030
4198
  // src/react/components/ai-elements/reasoning.tsx
4031
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
4199
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
4032
4200
  var ReasoningContext = createContext2(null);
4033
4201
  var useReasoning = () => {
4034
4202
  const context = useContext2(ReasoningContext);
@@ -4062,7 +4230,7 @@ var Reasoning = memo2(
4062
4230
  prop: durationProp
4063
4231
  });
4064
4232
  const hasEverStreamedRef = useRef7(isStreaming);
4065
- const [hasAutoClosed, setHasAutoClosed] = useState8(false);
4233
+ const [hasAutoClosed, setHasAutoClosed] = useState9(false);
4066
4234
  const startTimeRef = useRef7(null);
4067
4235
  useEffect9(() => {
4068
4236
  if (isStreaming) {
@@ -4099,7 +4267,7 @@ var Reasoning = memo2(
4099
4267
  () => ({ duration, isOpen, isStreaming, setIsOpen }),
4100
4268
  [duration, isOpen, isStreaming, setIsOpen]
4101
4269
  );
4102
- return /* @__PURE__ */ jsx11(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx11(
4270
+ return /* @__PURE__ */ jsx12(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx12(
4103
4271
  Collapsible,
4104
4272
  {
4105
4273
  className: cn("not-prose mb-4", className),
@@ -4113,12 +4281,12 @@ var Reasoning = memo2(
4113
4281
  );
4114
4282
  var defaultGetThinkingMessage = (isStreaming, duration) => {
4115
4283
  if (isStreaming || duration === 0) {
4116
- return /* @__PURE__ */ jsx11(Shimmer, { duration: 1, children: "\u6DF1\u5EA6\u601D\u8003\u4E2D..." });
4284
+ return /* @__PURE__ */ jsx12(Shimmer, { duration: 1, children: "\u6DF1\u5EA6\u601D\u8003\u4E2D..." });
4117
4285
  }
4118
4286
  if (duration === void 0) {
4119
- return /* @__PURE__ */ jsx11("p", { children: "\u5DF2\u6DF1\u5EA6\u601D\u8003" });
4287
+ return /* @__PURE__ */ jsx12("p", { children: "\u5DF2\u6DF1\u5EA6\u601D\u8003" });
4120
4288
  }
4121
- return /* @__PURE__ */ jsxs9("p", { children: [
4289
+ return /* @__PURE__ */ jsxs10("p", { children: [
4122
4290
  "\u5DF2\u6DF1\u5EA6\u601D\u8003 ",
4123
4291
  duration,
4124
4292
  " \u79D2"
@@ -4132,7 +4300,7 @@ var ReasoningTrigger = memo2(
4132
4300
  ...props
4133
4301
  }) => {
4134
4302
  const { isStreaming, isOpen, duration } = useReasoning();
4135
- return /* @__PURE__ */ jsx11(
4303
+ return /* @__PURE__ */ jsx12(
4136
4304
  CollapsibleTrigger,
4137
4305
  {
4138
4306
  className: cn(
@@ -4140,10 +4308,10 @@ var ReasoningTrigger = memo2(
4140
4308
  className
4141
4309
  ),
4142
4310
  ...props,
4143
- children: children ?? /* @__PURE__ */ jsxs9(Fragment2, { children: [
4144
- /* @__PURE__ */ jsx11(BrainIcon, { className: "size-4" }),
4311
+ children: children ?? /* @__PURE__ */ jsxs10(Fragment3, { children: [
4312
+ /* @__PURE__ */ jsx12(BrainIcon, { className: "size-4" }),
4145
4313
  getThinkingMessage(isStreaming, duration),
4146
- /* @__PURE__ */ jsx11(
4314
+ /* @__PURE__ */ jsx12(
4147
4315
  ChevronDownIcon,
4148
4316
  {
4149
4317
  className: cn(
@@ -4160,7 +4328,7 @@ var ReasoningTrigger = memo2(
4160
4328
  var streamdownPlugins = { cjk, math, mermaid };
4161
4329
  var streamdownComponents = { code: CardCodeBlock };
4162
4330
  var ReasoningContent = memo2(
4163
- ({ className, children, ...props }) => /* @__PURE__ */ jsx11(
4331
+ ({ className, children, ...props }) => /* @__PURE__ */ jsx12(
4164
4332
  CollapsibleContent,
4165
4333
  {
4166
4334
  className: cn(
@@ -4169,7 +4337,7 @@ var ReasoningContent = memo2(
4169
4337
  className
4170
4338
  ),
4171
4339
  ...props,
4172
- children: /* @__PURE__ */ jsx11(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children })
4340
+ children: /* @__PURE__ */ jsx12(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children })
4173
4341
  }
4174
4342
  )
4175
4343
  );
@@ -4178,8 +4346,8 @@ function compactReasoningText(text) {
4178
4346
  }
4179
4347
  function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4180
4348
  const compactReasoning = compactReasoningText(reasoning);
4181
- const [open, setOpen] = useState8(false);
4182
- return /* @__PURE__ */ jsxs9(
4349
+ const [open, setOpen] = useState9(false);
4350
+ return /* @__PURE__ */ jsxs10(
4183
4351
  "span",
4184
4352
  {
4185
4353
  className: cn(
@@ -4187,7 +4355,7 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4187
4355
  variant === "inline" ? "ml-1" : "ml-1 shrink-0"
4188
4356
  ),
4189
4357
  children: [
4190
- /* @__PURE__ */ jsx11(
4358
+ /* @__PURE__ */ jsx12(
4191
4359
  "button",
4192
4360
  {
4193
4361
  type: "button",
@@ -4202,7 +4370,7 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4202
4370
  }
4203
4371
  ),
4204
4372
  open ? createPortal2(
4205
- /* @__PURE__ */ jsx11(
4373
+ /* @__PURE__ */ jsx12(
4206
4374
  "div",
4207
4375
  {
4208
4376
  className: "fixed inset-0 z-[70] flex items-center justify-center bg-black/10 p-6",
@@ -4218,26 +4386,26 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4218
4386
  setOpen(false);
4219
4387
  }
4220
4388
  },
4221
- children: /* @__PURE__ */ jsxs9(
4389
+ children: /* @__PURE__ */ jsxs10(
4222
4390
  "div",
4223
4391
  {
4224
4392
  className: "m-0 flex max-h-[min(520px,calc(100vh-48px))] w-[min(760px,calc(100vw-48px))] flex-col overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] text-left text-[13px] leading-6 text-[hsl(var(--popover-foreground))] shadow-xl",
4225
4393
  "aria-label": "\u601D\u8003\u8BE6\u60C5",
4226
4394
  children: [
4227
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2", children: [
4228
- /* @__PURE__ */ jsx11("span", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u601D\u8003\u8BE6\u60C5" }),
4229
- /* @__PURE__ */ jsx11(
4395
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2", children: [
4396
+ /* @__PURE__ */ jsx12("span", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u601D\u8003\u8BE6\u60C5" }),
4397
+ /* @__PURE__ */ jsx12(
4230
4398
  "button",
4231
4399
  {
4232
4400
  type: "button",
4233
4401
  onClick: () => setOpen(false),
4234
4402
  className: "inline-flex h-6 w-6 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
4235
4403
  "aria-label": "\u5173\u95ED\u601D\u8003\u8BE6\u60C5",
4236
- children: /* @__PURE__ */ jsx11(XIcon, { size: 14, "aria-hidden": "true" })
4404
+ children: /* @__PURE__ */ jsx12(XIcon, { size: 14, "aria-hidden": "true" })
4237
4405
  }
4238
4406
  )
4239
4407
  ] }),
4240
- /* @__PURE__ */ jsx11("div", { className: "overflow-auto px-4 py-3 whitespace-normal [&_*]:whitespace-normal [&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1.5 [&_ol]:my-1.5", children: /* @__PURE__ */ jsx11(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children: compactReasoning }) })
4408
+ /* @__PURE__ */ jsx12("div", { className: "overflow-auto px-4 py-3 whitespace-normal [&_*]:whitespace-normal [&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1.5 [&_ol]:my-1.5", children: /* @__PURE__ */ jsx12(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children: compactReasoning }) })
4241
4409
  ]
4242
4410
  }
4243
4411
  )
@@ -4254,12 +4422,12 @@ ReasoningTrigger.displayName = "ReasoningTrigger";
4254
4422
  ReasoningContent.displayName = "ReasoningContent";
4255
4423
 
4256
4424
  // src/react/components/chat/AgentLoopBlock.tsx
4257
- import { Bot, Check as Check3, ChevronRight as ChevronRight4, FileText as FileText5, Loader2 as Loader24, MessageSquareMore as MessageSquareMore2 } from "lucide-react";
4258
- import { useEffect as useEffect13, useMemo as useMemo14, useState as useState15 } from "react";
4425
+ import { Bot, Check as Check3, ChevronRight as ChevronRight4, FileText as FileText6, Loader2 as Loader24, MessageSquareMore as MessageSquareMore2 } from "lucide-react";
4426
+ import { useEffect as useEffect13, useMemo as useMemo14, useState as useState16 } from "react";
4259
4427
 
4260
4428
  // src/react/components/chat/ResourceIframe.tsx
4261
- import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as useRef8, useState as useState9 } from "react";
4262
- import { jsx as jsx12 } from "react/jsx-runtime";
4429
+ import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as useRef8, useState as useState10 } from "react";
4430
+ import { jsx as jsx13 } from "react/jsx-runtime";
4263
4431
  function isResourceBridgeMessage(value) {
4264
4432
  return typeof value === "object" && value !== null && value.__resourceBridge === true && typeof value.action === "string";
4265
4433
  }
@@ -4276,7 +4444,7 @@ function ResourceIframe({ ui, sessionId }) {
4276
4444
  const theme = useUiStore((state) => state.theme);
4277
4445
  const resourceUri = ui.resourceUri ?? ui.resourceURI;
4278
4446
  const iframeLabel = ui.title ?? resourceUri ?? "\u5DE5\u5177\u754C\u9762";
4279
- const [autoHeight, setAutoHeight] = useState9(null);
4447
+ const [autoHeight, setAutoHeight] = useState10(null);
4280
4448
  useEffect10(() => {
4281
4449
  setAutoHeight(null);
4282
4450
  }, [ui.resourceHTML, resourceUri]);
@@ -4365,7 +4533,7 @@ function ResourceIframe({ ui, sessionId }) {
4365
4533
  }
4366
4534
  const inlineHeight = autoHeight ?? ui.height;
4367
4535
  const sandbox = resourceUri ? "allow-scripts allow-same-origin" : "allow-scripts";
4368
- return /* @__PURE__ */ jsx12(
4536
+ return /* @__PURE__ */ jsx13(
4369
4537
  "iframe",
4370
4538
  {
4371
4539
  ref: iframeRef,
@@ -4387,10 +4555,10 @@ function ResourceIframe({ ui, sessionId }) {
4387
4555
 
4388
4556
  // src/react/components/chat/ToolCallBlock.tsx
4389
4557
  import { Check, ChevronRight as ChevronRight3, Loader2 as Loader23, MessageSquareMore, PanelRightOpen, X as X4 } from "lucide-react";
4390
- import { useMemo as useMemo12, useState as useState12 } from "react";
4558
+ import { useMemo as useMemo12, useState as useState13 } from "react";
4391
4559
 
4392
4560
  // src/react/components/chat/tool-renderers/shared.tsx
4393
- import { jsx as jsx13 } from "react/jsx-runtime";
4561
+ import { jsx as jsx14 } from "react/jsx-runtime";
4394
4562
  function getResultText(result) {
4395
4563
  if (typeof result === "string") return result;
4396
4564
  if (Array.isArray(result)) {
@@ -4457,7 +4625,7 @@ function CodePreview({
4457
4625
  }) {
4458
4626
  const { highlightedHtml } = useHighlightedCodeHtml(content, getCodeLanguage(filePath));
4459
4627
  if (!content.trim()) {
4460
- return /* @__PURE__ */ jsx13(
4628
+ return /* @__PURE__ */ jsx14(
4461
4629
  "pre",
4462
4630
  {
4463
4631
  className: cn(
@@ -4465,11 +4633,11 @@ function CodePreview({
4465
4633
  "bg-[hsl(var(--muted))]/35 p-3 font-mono text-[11px] text-[hsl(var(--muted-foreground))]",
4466
4634
  className
4467
4635
  ),
4468
- children: /* @__PURE__ */ jsx13("code", { children: emptyLabel })
4636
+ children: /* @__PURE__ */ jsx14("code", { children: emptyLabel })
4469
4637
  }
4470
4638
  );
4471
4639
  }
4472
- return /* @__PURE__ */ jsx13(
4640
+ return /* @__PURE__ */ jsx14(
4473
4641
  "pre",
4474
4642
  {
4475
4643
  className: cn(
@@ -4477,19 +4645,19 @@ function CodePreview({
4477
4645
  "bg-[hsl(var(--muted))]/35 p-3 text-[11px]",
4478
4646
  className
4479
4647
  ),
4480
- children: highlightedHtml ? /* @__PURE__ */ jsx13(
4648
+ children: highlightedHtml ? /* @__PURE__ */ jsx14(
4481
4649
  "code",
4482
4650
  {
4483
4651
  className: "font-mono",
4484
4652
  dangerouslySetInnerHTML: { __html: highlightedHtml }
4485
4653
  }
4486
- ) : /* @__PURE__ */ jsx13("code", { className: "whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]", children: content })
4654
+ ) : /* @__PURE__ */ jsx14("code", { className: "whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]", children: content })
4487
4655
  }
4488
4656
  );
4489
4657
  }
4490
4658
 
4491
4659
  // src/react/components/chat/tool-renderers/BashRenderer.tsx
4492
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
4660
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4493
4661
  function pickOutputField(data) {
4494
4662
  if (!data) return null;
4495
4663
  for (const key of ["output", "stdout", "stderr"]) {
@@ -4499,7 +4667,7 @@ function pickOutputField(data) {
4499
4667
  return null;
4500
4668
  }
4501
4669
  function MetaPill({ label }) {
4502
- return /* @__PURE__ */ jsx14("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground", children: label });
4670
+ return /* @__PURE__ */ jsx15("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground", children: label });
4503
4671
  }
4504
4672
  function BashRenderer({ toolCall }) {
4505
4673
  const argsValue = parseJsonValue(toolCall.arguments);
@@ -4522,16 +4690,16 @@ function BashRenderer({ toolCall }) {
4522
4690
  const rawFallbackOutput = result === null && typeof resultStr === "string" && resultStr.trim().length > 0 ? resultStr : null;
4523
4691
  const output = structuredOutput !== null ? structuredOutput : errorMessage ?? rawFallbackOutput ?? (normalizedName === "BgBash" ? "" : null);
4524
4692
  const hasFailure = toolCall.status === "error" || timedOut || exitCode !== null && exitCode !== 0;
4525
- return /* @__PURE__ */ jsxs10("div", { className: "space-y-3", children: [
4526
- (description || cwd) && /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
4527
- description ? /* @__PURE__ */ jsx14("span", { children: description }) : null,
4528
- cwd ? /* @__PURE__ */ jsx14("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: cwd }) : null
4693
+ return /* @__PURE__ */ jsxs11("div", { className: "space-y-3", children: [
4694
+ (description || cwd) && /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
4695
+ description ? /* @__PURE__ */ jsx15("span", { children: description }) : null,
4696
+ cwd ? /* @__PURE__ */ jsx15("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: cwd }) : null
4529
4697
  ] }),
4530
- /* @__PURE__ */ jsxs10("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [
4531
- /* @__PURE__ */ jsx14("div", { className: "border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u547D\u4EE4" }),
4532
- /* @__PURE__ */ jsx14("pre", { className: "overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx14("code", { children: `$ ${command || "\uFF08\u672A\u63D0\u4F9B\u547D\u4EE4\uFF09"}` }) })
4698
+ /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [
4699
+ /* @__PURE__ */ jsx15("div", { className: "border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u547D\u4EE4" }),
4700
+ /* @__PURE__ */ jsx15("pre", { className: "overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx15("code", { children: `$ ${command || "\uFF08\u672A\u63D0\u4F9B\u547D\u4EE4\uFF09"}` }) })
4533
4701
  ] }),
4534
- /* @__PURE__ */ jsxs10(
4702
+ /* @__PURE__ */ jsxs11(
4535
4703
  "div",
4536
4704
  {
4537
4705
  className: cn(
@@ -4539,26 +4707,26 @@ function BashRenderer({ toolCall }) {
4539
4707
  hasFailure ? "border-red-500/50" : "border-border"
4540
4708
  ),
4541
4709
  children: [
4542
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
4543
- /* @__PURE__ */ jsx14("div", { className: "text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u8F93\u51FA" }),
4544
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-1.5", children: [
4545
- taskId ? /* @__PURE__ */ jsx14(MetaPill, { label: `\u4EFB\u52A1 ${taskId}` }) : null,
4546
- exitCode !== null ? /* @__PURE__ */ jsx14(MetaPill, { label: `\u9000\u51FA\u7801 ${exitCode}` }) : null,
4547
- timedOut ? /* @__PURE__ */ jsx14(MetaPill, { label: "\u5DF2\u8D85\u65F6" }) : null,
4548
- truncated ? /* @__PURE__ */ jsx14(MetaPill, { label: "\u8F93\u51FA\u5DF2\u622A\u65AD" }) : null,
4549
- normalizedName === "BgBash" && !taskId ? /* @__PURE__ */ jsx14(MetaPill, { label: "\u540E\u53F0\u4EFB\u52A1" }) : null
4710
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
4711
+ /* @__PURE__ */ jsx15("div", { className: "text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u8F93\u51FA" }),
4712
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-1.5", children: [
4713
+ taskId ? /* @__PURE__ */ jsx15(MetaPill, { label: `\u4EFB\u52A1 ${taskId}` }) : null,
4714
+ exitCode !== null ? /* @__PURE__ */ jsx15(MetaPill, { label: `\u9000\u51FA\u7801 ${exitCode}` }) : null,
4715
+ timedOut ? /* @__PURE__ */ jsx15(MetaPill, { label: "\u5DF2\u8D85\u65F6" }) : null,
4716
+ truncated ? /* @__PURE__ */ jsx15(MetaPill, { label: "\u8F93\u51FA\u5DF2\u622A\u65AD" }) : null,
4717
+ normalizedName === "BgBash" && !taskId ? /* @__PURE__ */ jsx15(MetaPill, { label: "\u540E\u53F0\u4EFB\u52A1" }) : null
4550
4718
  ] })
4551
4719
  ] }),
4552
- /* @__PURE__ */ jsx14("pre", { className: "max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx14("code", { className: "whitespace-pre-wrap break-words", children: output !== null && output.trim().length > 0 ? output : normalizedName === "BgBash" ? "\u4EFB\u52A1\u5DF2\u8FDB\u5165\u540E\u53F0\u6267\u884C\uFF0C\u8F93\u51FA\u4F1A\u5728\u540E\u53F0\u4EFB\u52A1\u9762\u677F\u4E2D\u7EE7\u7EED\u66F4\u65B0\u3002" : output !== null && output.trim().length === 0 && hasFailure ? "\u547D\u4EE4\u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u6355\u83B7\u5230\u7EC8\u7AEF\u8F93\u51FA\uFF08\u8BF7\u67E5\u770B\u9000\u51FA\u7801\uFF09\u3002" : "\u547D\u4EE4\u672A\u8FD4\u56DE\u8F93\u51FA\u3002" }) })
4720
+ /* @__PURE__ */ jsx15("pre", { className: "max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx15("code", { className: "whitespace-pre-wrap break-words", children: output !== null && output.trim().length > 0 ? output : normalizedName === "BgBash" ? "\u4EFB\u52A1\u5DF2\u8FDB\u5165\u540E\u53F0\u6267\u884C\uFF0C\u8F93\u51FA\u4F1A\u5728\u540E\u53F0\u4EFB\u52A1\u9762\u677F\u4E2D\u7EE7\u7EED\u66F4\u65B0\u3002" : output !== null && output.trim().length === 0 && hasFailure ? "\u547D\u4EE4\u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u6355\u83B7\u5230\u7EC8\u7AEF\u8F93\u51FA\uFF08\u8BF7\u67E5\u770B\u9000\u51FA\u7801\uFF09\u3002" : "\u547D\u4EE4\u672A\u8FD4\u56DE\u8F93\u51FA\u3002" }) })
4553
4721
  ]
4554
4722
  }
4555
4723
  ),
4556
- cwdResetNote ? /* @__PURE__ */ jsx14("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: cwdResetNote }) : null
4724
+ cwdResetNote ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: cwdResetNote }) : null
4557
4725
  ] });
4558
4726
  }
4559
4727
 
4560
4728
  // src/react/components/chat/tool-renderers/FileEditRenderer.tsx
4561
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4729
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4562
4730
  var MAX_DIFF_LINES = 200;
4563
4731
  function computeDiff(oldText, newText) {
4564
4732
  const oldLines = oldText.split("\n");
@@ -4635,6 +4803,26 @@ function buildWritePreview(content) {
4635
4803
  newLine: index + 1
4636
4804
  }));
4637
4805
  }
4806
+ function buildEditPreview(args) {
4807
+ const edits = Array.isArray(args?.edits) ? args.edits : null;
4808
+ if (edits) {
4809
+ return edits.flatMap((rawEdit, index) => {
4810
+ if (!isPlainObject(rawEdit)) {
4811
+ return [];
4812
+ }
4813
+ const oldText = getStringValue(rawEdit, "old_text") ?? "";
4814
+ const newText = getStringValue(rawEdit, "new_text") ?? "";
4815
+ const lines = computeDiff(oldText, newText);
4816
+ return index === 0 ? lines : [
4817
+ { type: "unchanged", value: "", oldLine: null, newLine: null },
4818
+ ...lines
4819
+ ];
4820
+ });
4821
+ }
4822
+ const oldString = getStringValue(args, "old_string") ?? "";
4823
+ const newString = getStringValue(args, "new_string") ?? "";
4824
+ return computeDiff(oldString, newString);
4825
+ }
4638
4826
  function extractChecksum(result) {
4639
4827
  const text = typeof result === "string" ? result : null;
4640
4828
  const match = text?.match(/\[checksum:\s*([^\]]+)\]/);
@@ -4648,26 +4836,26 @@ function FileEditRenderer({ toolCall }) {
4648
4836
  const fileName = getFileName(filePath);
4649
4837
  const errorMessage = extractErrorMessage(toolCall.result);
4650
4838
  const checksum = extractChecksum(toolCall.result);
4839
+ const description = getStringValue(args, "description");
4651
4840
  const writeContent = getStringValue(args, "content") ?? "";
4652
- const oldString = getStringValue(args, "old_string") ?? "";
4653
- const newString = getStringValue(args, "new_string") ?? "";
4654
- const diffLines = normalizedName === "Write" ? buildWritePreview(writeContent) : computeDiff(oldString, newString);
4841
+ const diffLines = normalizedName === "Write" ? buildWritePreview(writeContent) : buildEditPreview(args);
4655
4842
  const resultStr = typeof toolCall.result === "string" ? toolCall.result : null;
4656
4843
  const summaryText = resultStr?.trim() && !errorMessage ? resultStr.trim() : null;
4657
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-3", children: [
4658
- /* @__PURE__ */ jsxs11("div", { className: "flex items-start justify-between gap-3", children: [
4659
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
4660
- /* @__PURE__ */ jsx15("div", { className: "text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5199\u5165\u6587\u4EF6" : "\u7F16\u8F91\u6587\u4EF6" }),
4661
- /* @__PURE__ */ jsx15("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: filePath ?? fileName })
4844
+ return /* @__PURE__ */ jsxs12("div", { className: "space-y-3", children: [
4845
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between gap-3", children: [
4846
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
4847
+ /* @__PURE__ */ jsx16("div", { className: "text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5199\u5165\u6587\u4EF6" : "\u7F16\u8F91\u6587\u4EF6" }),
4848
+ /* @__PURE__ */ jsx16("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: filePath ?? fileName })
4662
4849
  ] }),
4663
- checksum ? /* @__PURE__ */ jsx15("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
4850
+ checksum ? /* @__PURE__ */ jsx16("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
4664
4851
  ] }),
4665
- errorMessage ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
4666
- /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20", children: [
4667
- /* @__PURE__ */ jsx15("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5185\u5BB9\u9884\u89C8" : "\u53D8\u66F4\u9884\u89C8" }),
4668
- /* @__PURE__ */ jsx15("pre", { className: "max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5", children: diffLines.length > 0 ? diffLines.map((line, index) => {
4852
+ description ? /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: description }) : null,
4853
+ errorMessage ? /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
4854
+ /* @__PURE__ */ jsxs12("div", { className: "overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20", children: [
4855
+ /* @__PURE__ */ jsx16("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5185\u5BB9\u9884\u89C8" : "\u53D8\u66F4\u9884\u89C8" }),
4856
+ /* @__PURE__ */ jsx16("pre", { className: "max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5", children: diffLines.length > 0 ? diffLines.map((line, index) => {
4669
4857
  const prefix = line.type === "added" ? "+ " : line.type === "removed" ? "- " : " ";
4670
- return /* @__PURE__ */ jsxs11(
4858
+ return /* @__PURE__ */ jsxs12(
4671
4859
  "div",
4672
4860
  {
4673
4861
  className: cn(
@@ -4677,9 +4865,9 @@ function FileEditRenderer({ toolCall }) {
4677
4865
  line.type === "unchanged" && "text-[hsl(var(--foreground))]"
4678
4866
  ),
4679
4867
  children: [
4680
- /* @__PURE__ */ jsx15("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.oldLine ?? "" }),
4681
- /* @__PURE__ */ jsx15("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.newLine ?? "" }),
4682
- /* @__PURE__ */ jsxs11("span", { className: "min-w-0 whitespace-pre-wrap break-words py-0.5", children: [
4868
+ /* @__PURE__ */ jsx16("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.oldLine ?? "" }),
4869
+ /* @__PURE__ */ jsx16("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.newLine ?? "" }),
4870
+ /* @__PURE__ */ jsxs12("span", { className: "min-w-0 whitespace-pre-wrap break-words py-0.5", children: [
4683
4871
  prefix,
4684
4872
  line.value
4685
4873
  ] })
@@ -4687,24 +4875,24 @@ function FileEditRenderer({ toolCall }) {
4687
4875
  },
4688
4876
  `${line.type}-${line.oldLine}-${line.newLine}-${index}`
4689
4877
  );
4690
- }) : /* @__PURE__ */ jsx15("div", { className: "px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u672A\u68C0\u6D4B\u5230\u53EF\u9884\u89C8\u7684\u53D8\u66F4\u3002" }) })
4878
+ }) : /* @__PURE__ */ jsx16("div", { className: "px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u672A\u68C0\u6D4B\u5230\u53EF\u9884\u89C8\u7684\u53D8\u66F4\u3002" }) })
4691
4879
  ] }),
4692
- summaryText ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: summaryText }) : null
4880
+ summaryText ? /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: summaryText }) : null
4693
4881
  ] });
4694
4882
  }
4695
4883
 
4696
4884
  // src/react/components/chat/tool-renderers/FileReadRenderer.tsx
4697
- import { useState as useState11 } from "react";
4885
+ import { useState as useState12 } from "react";
4698
4886
 
4699
4887
  // src/react/components/chat/ImageLightbox.tsx
4700
4888
  import { ChevronLeft, ChevronRight as ChevronRight2, Download as Download2, ExternalLink, Minus, Plus as Plus2, RotateCcw, X as X3 } from "lucide-react";
4701
- import { useCallback as useCallback10, useEffect as useEffect11, useRef as useRef9, useState as useState10 } from "react";
4889
+ import { useCallback as useCallback10, useEffect as useEffect11, useRef as useRef9, useState as useState11 } from "react";
4702
4890
  import { createPortal as createPortal3 } from "react-dom";
4703
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4891
+ import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
4704
4892
  function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4705
- const [currentIndex, setCurrentIndex] = useState10(initialIndex);
4706
- const [scale, setScale] = useState10(1);
4707
- const [translate, setTranslate] = useState10({ x: 0, y: 0 });
4893
+ const [currentIndex, setCurrentIndex] = useState11(initialIndex);
4894
+ const [scale, setScale] = useState11(1);
4895
+ const [translate, setTranslate] = useState11({ x: 0, y: 0 });
4708
4896
  const dragging = useRef9(false);
4709
4897
  const dragStart = useRef9({ x: 0, y: 0 });
4710
4898
  const translateStart = useRef9({ x: 0, y: 0 });
@@ -4810,22 +4998,22 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4810
4998
  if (images.length === 0) {
4811
4999
  return createPortal3(
4812
5000
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect
4813
- /* @__PURE__ */ jsxs12(
5001
+ /* @__PURE__ */ jsxs13(
4814
5002
  "div",
4815
5003
  {
4816
5004
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80",
4817
5005
  onClick: close,
4818
5006
  children: [
4819
- /* @__PURE__ */ jsx16(
5007
+ /* @__PURE__ */ jsx17(
4820
5008
  "button",
4821
5009
  {
4822
5010
  type: "button",
4823
5011
  onClick: close,
4824
5012
  className: "absolute right-4 top-4 z-10 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4825
- children: /* @__PURE__ */ jsx16(X3, { size: 20 })
5013
+ children: /* @__PURE__ */ jsx17(X3, { size: 20 })
4826
5014
  }
4827
5015
  ),
4828
- /* @__PURE__ */ jsx16("span", { className: "text-sm text-white/60", children: "\u52A0\u8F7D\u4E2D..." })
5016
+ /* @__PURE__ */ jsx17("span", { className: "text-sm text-white/60", children: "\u52A0\u8F7D\u4E2D..." })
4829
5017
  ]
4830
5018
  }
4831
5019
  ),
@@ -4836,46 +5024,46 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4836
5024
  const showNav = images.length > 1;
4837
5025
  return createPortal3(
4838
5026
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect
4839
- /* @__PURE__ */ jsxs12("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: handleAreaClick, children: [
4840
- /* @__PURE__ */ jsxs12(
5027
+ /* @__PURE__ */ jsxs13("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: handleAreaClick, children: [
5028
+ /* @__PURE__ */ jsxs13(
4841
5029
  "div",
4842
5030
  {
4843
5031
  className: "absolute right-4 top-4 z-10 flex items-center gap-1.5",
4844
5032
  onClick: (e) => e.stopPropagation(),
4845
5033
  children: [
4846
- /* @__PURE__ */ jsx16(
5034
+ /* @__PURE__ */ jsx17(
4847
5035
  "button",
4848
5036
  {
4849
5037
  type: "button",
4850
5038
  onClick: handleDownload,
4851
5039
  title: "\u4E0B\u8F7D\u56FE\u7247",
4852
5040
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4853
- children: /* @__PURE__ */ jsx16(Download2, { size: 18 })
5041
+ children: /* @__PURE__ */ jsx17(Download2, { size: 18 })
4854
5042
  }
4855
5043
  ),
4856
- /* @__PURE__ */ jsx16(
5044
+ /* @__PURE__ */ jsx17(
4857
5045
  "button",
4858
5046
  {
4859
5047
  type: "button",
4860
5048
  onClick: handleOpenInNewTab,
4861
5049
  title: "\u65B0\u6807\u7B7E\u9875\u6253\u5F00",
4862
5050
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4863
- children: /* @__PURE__ */ jsx16(ExternalLink, { size: 18 })
5051
+ children: /* @__PURE__ */ jsx17(ExternalLink, { size: 18 })
4864
5052
  }
4865
5053
  ),
4866
- /* @__PURE__ */ jsx16(
5054
+ /* @__PURE__ */ jsx17(
4867
5055
  "button",
4868
5056
  {
4869
5057
  type: "button",
4870
5058
  onClick: close,
4871
5059
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4872
- children: /* @__PURE__ */ jsx16(X3, { size: 20 })
5060
+ children: /* @__PURE__ */ jsx17(X3, { size: 20 })
4873
5061
  }
4874
5062
  )
4875
5063
  ]
4876
5064
  }
4877
5065
  ),
4878
- showNav && currentIndex > 0 && /* @__PURE__ */ jsx16(
5066
+ showNav && currentIndex > 0 && /* @__PURE__ */ jsx17(
4879
5067
  "button",
4880
5068
  {
4881
5069
  type: "button",
@@ -4884,10 +5072,10 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4884
5072
  goPrev();
4885
5073
  },
4886
5074
  className: "absolute left-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4887
- children: /* @__PURE__ */ jsx16(ChevronLeft, { size: 24 })
5075
+ children: /* @__PURE__ */ jsx17(ChevronLeft, { size: 24 })
4888
5076
  }
4889
5077
  ),
4890
- showNav && currentIndex < images.length - 1 && /* @__PURE__ */ jsx16(
5078
+ showNav && currentIndex < images.length - 1 && /* @__PURE__ */ jsx17(
4891
5079
  "button",
4892
5080
  {
4893
5081
  type: "button",
@@ -4896,51 +5084,51 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4896
5084
  goNext();
4897
5085
  },
4898
5086
  className: "absolute right-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4899
- children: /* @__PURE__ */ jsx16(ChevronRight2, { size: 24 })
5087
+ children: /* @__PURE__ */ jsx17(ChevronRight2, { size: 24 })
4900
5088
  }
4901
5089
  ),
4902
- /* @__PURE__ */ jsxs12("div", { className: "absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 items-center gap-1 rounded-full bg-black/50 px-2 py-1", children: [
4903
- /* @__PURE__ */ jsx16(
5090
+ /* @__PURE__ */ jsxs13("div", { className: "absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 items-center gap-1 rounded-full bg-black/50 px-2 py-1", children: [
5091
+ /* @__PURE__ */ jsx17(
4904
5092
  "button",
4905
5093
  {
4906
5094
  type: "button",
4907
5095
  onClick: zoomOut,
4908
5096
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
4909
- children: /* @__PURE__ */ jsx16(Minus, { size: 16 })
5097
+ children: /* @__PURE__ */ jsx17(Minus, { size: 16 })
4910
5098
  }
4911
5099
  ),
4912
- /* @__PURE__ */ jsxs12("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5100
+ /* @__PURE__ */ jsxs13("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
4913
5101
  Math.round(scale * 100),
4914
5102
  "%"
4915
5103
  ] }),
4916
- /* @__PURE__ */ jsx16(
5104
+ /* @__PURE__ */ jsx17(
4917
5105
  "button",
4918
5106
  {
4919
5107
  type: "button",
4920
5108
  onClick: zoomIn,
4921
5109
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
4922
- children: /* @__PURE__ */ jsx16(Plus2, { size: 16 })
5110
+ children: /* @__PURE__ */ jsx17(Plus2, { size: 16 })
4923
5111
  }
4924
5112
  ),
4925
- /* @__PURE__ */ jsx16(
5113
+ /* @__PURE__ */ jsx17(
4926
5114
  "button",
4927
5115
  {
4928
5116
  type: "button",
4929
5117
  onClick: reset,
4930
5118
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
4931
- children: /* @__PURE__ */ jsx16(RotateCcw, { size: 16 })
5119
+ children: /* @__PURE__ */ jsx17(RotateCcw, { size: 16 })
4932
5120
  }
4933
5121
  ),
4934
- showNav && /* @__PURE__ */ jsxs12(Fragment3, { children: [
4935
- /* @__PURE__ */ jsx16("div", { className: "mx-1 h-4 w-px bg-white/20" }),
4936
- /* @__PURE__ */ jsxs12("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5122
+ showNav && /* @__PURE__ */ jsxs13(Fragment4, { children: [
5123
+ /* @__PURE__ */ jsx17("div", { className: "mx-1 h-4 w-px bg-white/20" }),
5124
+ /* @__PURE__ */ jsxs13("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
4937
5125
  currentIndex + 1,
4938
5126
  " / ",
4939
5127
  images.length
4940
5128
  ] })
4941
5129
  ] })
4942
5130
  ] }),
4943
- /* @__PURE__ */ jsx16(
5131
+ /* @__PURE__ */ jsx17(
4944
5132
  "div",
4945
5133
  {
4946
5134
  className: "flex h-full w-full items-center justify-center overflow-hidden p-12",
@@ -4951,7 +5139,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4951
5139
  onMouseUp: handleMouseUp,
4952
5140
  onMouseLeave: handleMouseUp,
4953
5141
  onDoubleClick: handleDoubleClick,
4954
- children: /* @__PURE__ */ jsx16(
5142
+ children: /* @__PURE__ */ jsx17(
4955
5143
  "img",
4956
5144
  {
4957
5145
  ref: imgRef,
@@ -4973,7 +5161,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4973
5161
  }
4974
5162
 
4975
5163
  // src/react/components/chat/tool-renderers/FileReadRenderer.tsx
4976
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
5164
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4977
5165
  var NUMBERED_LINE_RE = /^(\s*\d+)\t([\s\S]*)$/;
4978
5166
  function parseReadResult(result) {
4979
5167
  if (!result) {
@@ -5017,11 +5205,12 @@ function formatLineRange(startLine, endLine) {
5017
5205
  return startLine === endLine ? `\u7B2C ${startLine} \u884C` : `\u7B2C ${startLine}-${endLine} \u884C`;
5018
5206
  }
5019
5207
  function FileReadRenderer({ toolCall }) {
5020
- const [lightboxIndex, setLightboxIndex] = useState11(null);
5208
+ const [lightboxIndex, setLightboxIndex] = useState12(null);
5021
5209
  const argsValue = parseJsonValue(toolCall.arguments);
5022
5210
  const args = isPlainObject(argsValue) ? argsValue : null;
5023
5211
  const filePath = extractToolFilePath(toolCall);
5024
5212
  const fileName = getFileName(filePath);
5213
+ const description = getStringValue(args, "description");
5025
5214
  const resultText = getResultText(toolCall.result);
5026
5215
  const imageUrls = getResultImageUrls(toolCall.result);
5027
5216
  const isImageResult = imageUrls.length > 0;
@@ -5032,27 +5221,28 @@ function FileReadRenderer({ toolCall }) {
5032
5221
  const resolvedStartLine = startLine ?? (lineCount > 0 ? fallbackStart : null);
5033
5222
  const resolvedEndLine = endLine ?? (resolvedStartLine !== null && lineCount > 0 ? resolvedStartLine + lineCount - 1 : null);
5034
5223
  const lineRange = formatLineRange(resolvedStartLine, resolvedEndLine);
5035
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
5036
- /* @__PURE__ */ jsxs13("div", { className: "flex items-start justify-between gap-3", children: [
5037
- /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
5038
- /* @__PURE__ */ jsx17("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: fileName }),
5039
- filePath ? /* @__PURE__ */ jsx17("div", { className: "truncate text-[10px] text-[hsl(var(--muted-foreground))]", children: filePath }) : null
5224
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5225
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-start justify-between gap-3", children: [
5226
+ /* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
5227
+ /* @__PURE__ */ jsx18("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: fileName }),
5228
+ filePath ? /* @__PURE__ */ jsx18("div", { className: "truncate text-[10px] text-[hsl(var(--muted-foreground))]", children: filePath }) : null
5040
5229
  ] }),
5041
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
5042
- lineRange ? /* @__PURE__ */ jsx17("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: lineRange }) : null,
5043
- checksum ? /* @__PURE__ */ jsx17("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
5230
+ /* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
5231
+ lineRange ? /* @__PURE__ */ jsx18("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: lineRange }) : null,
5232
+ checksum ? /* @__PURE__ */ jsx18("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
5044
5233
  ] })
5045
5234
  ] }),
5046
- errorMessage ? /* @__PURE__ */ jsx17("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
5047
- isImageResult ? /* @__PURE__ */ jsxs13("div", { className: "grid gap-2", children: [
5048
- imageUrls.map((url, idx) => /* @__PURE__ */ jsx17(
5235
+ description ? /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: description }) : null,
5236
+ errorMessage ? /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
5237
+ isImageResult ? /* @__PURE__ */ jsxs14("div", { className: "grid gap-2", children: [
5238
+ imageUrls.map((url, idx) => /* @__PURE__ */ jsx18(
5049
5239
  "button",
5050
5240
  {
5051
5241
  type: "button",
5052
5242
  onClick: () => setLightboxIndex(idx),
5053
5243
  className: "cursor-zoom-in",
5054
5244
  title: "\u67E5\u770B\u5927\u56FE",
5055
- children: /* @__PURE__ */ jsx17(
5245
+ children: /* @__PURE__ */ jsx18(
5056
5246
  "img",
5057
5247
  {
5058
5248
  src: url,
@@ -5063,7 +5253,7 @@ function FileReadRenderer({ toolCall }) {
5063
5253
  },
5064
5254
  url.slice(0, 64)
5065
5255
  )),
5066
- /* @__PURE__ */ jsx17(
5256
+ /* @__PURE__ */ jsx18(
5067
5257
  ImageLightbox,
5068
5258
  {
5069
5259
  open: lightboxIndex != null,
@@ -5074,15 +5264,15 @@ function FileReadRenderer({ toolCall }) {
5074
5264
  initialIndex: lightboxIndex ?? 0
5075
5265
  }
5076
5266
  ),
5077
- content ? /* @__PURE__ */ jsx17("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: content }) : null
5078
- ] }) : !errorMessage ? /* @__PURE__ */ jsx17(CodePreview, { content, filePath, className: "max-h-[360px]" }) : null,
5079
- note ? /* @__PURE__ */ jsx17("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: note }) : null
5267
+ content ? /* @__PURE__ */ jsx18("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: content }) : null
5268
+ ] }) : !errorMessage ? /* @__PURE__ */ jsx18(CodePreview, { content, filePath, className: "max-h-[360px]" }) : null,
5269
+ note ? /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: note }) : null
5080
5270
  ] });
5081
5271
  }
5082
5272
 
5083
5273
  // src/react/components/chat/tool-renderers/SearchRenderer.tsx
5084
- import { ExternalLink as ExternalLink2, FileText as FileText2, Folder as Folder2, Globe2 } from "lucide-react";
5085
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
5274
+ import { ExternalLink as ExternalLink2, FileText as FileText3, Folder as Folder2, Globe2 } from "lucide-react";
5275
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5086
5276
  function toRecordArray(value) {
5087
5277
  return Array.isArray(value) ? value.filter(isPlainObject) : [];
5088
5278
  }
@@ -5144,7 +5334,7 @@ function parseWebFetchResult(result) {
5144
5334
  };
5145
5335
  }
5146
5336
  function renderEmptyState(label) {
5147
- return /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: label });
5337
+ return /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: label });
5148
5338
  }
5149
5339
  function SearchRenderer({ toolCall }) {
5150
5340
  const normalizedName = formatToolName(toolCall.name);
@@ -5153,26 +5343,26 @@ function SearchRenderer({ toolCall }) {
5153
5343
  const resultStr = getResultText(toolCall.result);
5154
5344
  const errorMessage = extractErrorMessage(resultStr);
5155
5345
  if (errorMessage) {
5156
- return /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage });
5346
+ return /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage });
5157
5347
  }
5158
5348
  if (normalizedName === "Ls" || normalizedName === "Glob") {
5159
5349
  const items = parseDirectoryItems(resultStr);
5160
5350
  const path = getStringValue(args, "path");
5161
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5162
- path ? /* @__PURE__ */ jsxs14("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5351
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5352
+ path ? /* @__PURE__ */ jsxs15("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5163
5353
  "\u76EE\u5F55\uFF1A",
5164
5354
  path
5165
5355
  ] }) : null,
5166
- items.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "grid gap-2", children: items.map((item) => /* @__PURE__ */ jsxs14(
5356
+ items.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: items.map((item) => /* @__PURE__ */ jsxs15(
5167
5357
  "div",
5168
5358
  {
5169
5359
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2",
5170
5360
  children: [
5171
- /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 items-center gap-2", children: [
5172
- item.isDir ? /* @__PURE__ */ jsx18(Folder2, { size: 14, className: "shrink-0 text-blue-300" }) : /* @__PURE__ */ jsx18(FileText2, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5173
- /* @__PURE__ */ jsx18("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: item.name })
5361
+ /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 items-center gap-2", children: [
5362
+ item.isDir ? /* @__PURE__ */ jsx19(Folder2, { size: 14, className: "shrink-0 text-blue-300" }) : /* @__PURE__ */ jsx19(FileText3, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5363
+ /* @__PURE__ */ jsx19("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: item.name })
5174
5364
  ] }),
5175
- /* @__PURE__ */ jsx18("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: item.isDir ? "\u76EE\u5F55" : formatBytes(item.size) ?? "\u6587\u4EF6" })
5365
+ /* @__PURE__ */ jsx19("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: item.isDir ? "\u76EE\u5F55" : formatBytes(item.size) ?? "\u6587\u4EF6" })
5176
5366
  ]
5177
5367
  },
5178
5368
  `${item.name}-${item.size}-${item.isDir}`
@@ -5182,28 +5372,28 @@ function SearchRenderer({ toolCall }) {
5182
5372
  if (normalizedName === "Grep") {
5183
5373
  const { matches, searchPath } = parseGrepResult(resultStr);
5184
5374
  const pattern = getStringValue(args, "pattern");
5185
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5186
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5187
- pattern ? /* @__PURE__ */ jsx18("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: pattern }) : null,
5188
- searchPath ? /* @__PURE__ */ jsxs14("span", { children: [
5375
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5376
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5377
+ pattern ? /* @__PURE__ */ jsx19("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: pattern }) : null,
5378
+ searchPath ? /* @__PURE__ */ jsxs15("span", { children: [
5189
5379
  "\u8303\u56F4\uFF1A",
5190
5380
  searchPath
5191
5381
  ] }) : null
5192
5382
  ] }),
5193
- matches.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "grid gap-2", children: matches.map((match) => /* @__PURE__ */ jsxs14(
5383
+ matches.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: matches.map((match) => /* @__PURE__ */ jsxs15(
5194
5384
  "div",
5195
5385
  {
5196
5386
  className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2",
5197
5387
  children: [
5198
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-3", children: [
5199
- /* @__PURE__ */ jsx18("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: match.path }),
5200
- match.lineNumber !== null ? /* @__PURE__ */ jsxs14("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5388
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between gap-3", children: [
5389
+ /* @__PURE__ */ jsx19("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: match.path }),
5390
+ match.lineNumber !== null ? /* @__PURE__ */ jsxs15("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5201
5391
  "\u7B2C ",
5202
5392
  match.lineNumber,
5203
5393
  " \u884C"
5204
5394
  ] }) : null
5205
5395
  ] }),
5206
- /* @__PURE__ */ jsx18("pre", { className: "mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx18("code", { children: match.line }) })
5396
+ /* @__PURE__ */ jsx19("pre", { className: "mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx19("code", { children: match.line }) })
5207
5397
  ]
5208
5398
  },
5209
5399
  `${match.path}-${match.lineNumber}-${match.line}`
@@ -5212,16 +5402,16 @@ function SearchRenderer({ toolCall }) {
5212
5402
  }
5213
5403
  const { results, summary } = normalizedName === "WebFetch" ? parseWebFetchResult(resultStr) : { results: parseWebResults(resultStr), summary: null };
5214
5404
  const query = getStringValue(args, "query");
5215
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5216
- query ? /* @__PURE__ */ jsxs14("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5405
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5406
+ query ? /* @__PURE__ */ jsxs15("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5217
5407
  "\u67E5\u8BE2\uFF1A",
5218
5408
  query
5219
5409
  ] }) : null,
5220
- summary ? /* @__PURE__ */ jsxs14("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3", children: [
5221
- /* @__PURE__ */ jsx18("div", { className: "mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: "\u6458\u8981" }),
5222
- /* @__PURE__ */ jsx18("p", { className: "whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]", children: summary })
5410
+ summary ? /* @__PURE__ */ jsxs15("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3", children: [
5411
+ /* @__PURE__ */ jsx19("div", { className: "mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: "\u6458\u8981" }),
5412
+ /* @__PURE__ */ jsx19("p", { className: "whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]", children: summary })
5223
5413
  ] }) : null,
5224
- results.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "grid gap-2", children: results.map((item, index) => /* @__PURE__ */ jsx18(
5414
+ results.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: results.map((item, index) => /* @__PURE__ */ jsx19(
5225
5415
  "a",
5226
5416
  {
5227
5417
  href: item.url ?? void 0,
@@ -5231,12 +5421,12 @@ function SearchRenderer({ toolCall }) {
5231
5421
  "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3 transition-colors",
5232
5422
  item.url && "hover:border-[hsl(var(--ring))] hover:bg-[hsl(var(--muted))]/35"
5233
5423
  ),
5234
- children: /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3", children: [
5235
- /* @__PURE__ */ jsx18(Globe2, { size: 15, className: "mt-0.5 shrink-0 text-blue-300" }),
5236
- /* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
5237
- /* @__PURE__ */ jsxs14("div", { className: "flex items-start justify-between gap-3", children: [
5238
- /* @__PURE__ */ jsx18("span", { className: "line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]", children: item.title ?? item.url ?? "\u672A\u547D\u540D\u7ED3\u679C" }),
5239
- item.url ? /* @__PURE__ */ jsx18(
5424
+ children: /* @__PURE__ */ jsxs15("div", { className: "flex items-start gap-3", children: [
5425
+ /* @__PURE__ */ jsx19(Globe2, { size: 15, className: "mt-0.5 shrink-0 text-blue-300" }),
5426
+ /* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
5427
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-3", children: [
5428
+ /* @__PURE__ */ jsx19("span", { className: "line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]", children: item.title ?? item.url ?? "\u672A\u547D\u540D\u7ED3\u679C" }),
5429
+ item.url ? /* @__PURE__ */ jsx19(
5240
5430
  ExternalLink2,
5241
5431
  {
5242
5432
  size: 12,
@@ -5244,8 +5434,8 @@ function SearchRenderer({ toolCall }) {
5244
5434
  }
5245
5435
  ) : null
5246
5436
  ] }),
5247
- item.url ? /* @__PURE__ */ jsx18("div", { className: "mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.url }) : null,
5248
- item.description ? /* @__PURE__ */ jsx18("p", { className: "mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: item.description }) : null
5437
+ item.url ? /* @__PURE__ */ jsx19("div", { className: "mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.url }) : null,
5438
+ item.description ? /* @__PURE__ */ jsx19("p", { className: "mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: item.description }) : null
5249
5439
  ] })
5250
5440
  ] })
5251
5441
  },
@@ -5272,7 +5462,7 @@ function getRenderer(toolName) {
5272
5462
  }
5273
5463
 
5274
5464
  // src/react/components/chat/ToolCallBlock.tsx
5275
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5465
+ import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5276
5466
  function FilePathLink({ filePath, sessionId }) {
5277
5467
  const activeSessionId = useSessionStore((s) => s.activeSessionId);
5278
5468
  const pushArtifact = useUiStore((s) => s.pushArtifact);
@@ -5290,14 +5480,14 @@ function FilePathLink({ filePath, sessionId }) {
5290
5480
  } catch {
5291
5481
  }
5292
5482
  };
5293
- return /* @__PURE__ */ jsx19(
5483
+ return /* @__PURE__ */ jsx20(
5294
5484
  "button",
5295
5485
  {
5296
5486
  type: "button",
5297
5487
  onClick: handleClick,
5298
5488
  className: "flex min-w-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer font-mono",
5299
5489
  title: `\u9884\u89C8 ${filePath}`,
5300
- children: /* @__PURE__ */ jsx19("span", { className: "truncate", children: fileName })
5490
+ children: /* @__PURE__ */ jsx20("span", { className: "truncate", children: fileName })
5301
5491
  }
5302
5492
  );
5303
5493
  }
@@ -5313,7 +5503,7 @@ function ToolCallBlock({
5313
5503
  reasoning,
5314
5504
  customization
5315
5505
  }) {
5316
- const [expanded, setExpanded] = useState12(false);
5506
+ const [expanded, setExpanded] = useState13(false);
5317
5507
  const activeSessionId = useSessionStore((s) => s.activeSessionId);
5318
5508
  const sessions = useSessionStore((s) => s.sessions);
5319
5509
  const pushArtifact = useUiStore((s) => s.pushArtifact);
@@ -5340,7 +5530,7 @@ function ToolCallBlock({
5340
5530
  const canAnswer = toolCall.status === "awaiting_answer" && Boolean(resolvedOnAnswer) && Boolean(resolvedSessionStatus);
5341
5531
  const shouldRenderQuestion = Boolean(askData) && (canAnswer || resolvedAnswered || toolCall.status === "done");
5342
5532
  if (askData && shouldRenderQuestion) {
5343
- const questionBlock = /* @__PURE__ */ jsx19(
5533
+ const questionBlock = /* @__PURE__ */ jsx20(
5344
5534
  AskUserQuestionBlock,
5345
5535
  {
5346
5536
  data: askData,
@@ -5354,9 +5544,9 @@ function ToolCallBlock({
5354
5544
  if (!reasoning) {
5355
5545
  return questionBlock;
5356
5546
  }
5357
- return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-1", children: [
5547
+ return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1", children: [
5358
5548
  questionBlock,
5359
- /* @__PURE__ */ jsx19("div", { className: "ml-4", children: /* @__PURE__ */ jsx19(ThinkingBadge, { reasoning, variant: "block" }) })
5549
+ /* @__PURE__ */ jsx20("div", { className: "ml-4", children: /* @__PURE__ */ jsx20(ThinkingBadge, { reasoning, variant: "block" }) })
5360
5550
  ] });
5361
5551
  }
5362
5552
  }
@@ -5368,11 +5558,11 @@ function ToolCallBlock({
5368
5558
  const borderWidthClass = level === 2 ? "border-l-[2px]" : "border-l-[3px]";
5369
5559
  const indentClass = level === 2 ? "ml-3" : "ml-4";
5370
5560
  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))]";
5371
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx19(Loader23, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx19(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx19(X4, { size: 11 }) : /* @__PURE__ */ jsx19(Check, { size: 11 });
5561
+ const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx20(Loader23, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx20(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx20(X4, { size: 11 }) : /* @__PURE__ */ jsx20(Check, { size: 11 });
5372
5562
  const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
5373
- return /* @__PURE__ */ jsxs15("div", { className: cn(indentClass, "text-xs", customization?.classNames?.toolCall), children: [
5374
- /* @__PURE__ */ jsxs15("div", { className: cn(borderWidthClass, toneClass, "flex items-center gap-2 px-3 py-2"), children: [
5375
- /* @__PURE__ */ jsxs15(
5563
+ return /* @__PURE__ */ jsxs16("div", { className: cn(indentClass, "text-xs", customization?.classNames?.toolCall), children: [
5564
+ /* @__PURE__ */ jsxs16("div", { className: cn(borderWidthClass, toneClass, "flex items-center gap-2 px-3 py-2"), children: [
5565
+ /* @__PURE__ */ jsxs16(
5376
5566
  "button",
5377
5567
  {
5378
5568
  type: "button",
@@ -5380,7 +5570,7 @@ function ToolCallBlock({
5380
5570
  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",
5381
5571
  "aria-expanded": expanded,
5382
5572
  children: [
5383
- /* @__PURE__ */ jsx19(
5573
+ /* @__PURE__ */ jsx20(
5384
5574
  ChevronRight3,
5385
5575
  {
5386
5576
  size: 11,
@@ -5390,19 +5580,19 @@ function ToolCallBlock({
5390
5580
  )
5391
5581
  }
5392
5582
  ),
5393
- /* @__PURE__ */ jsxs15("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
5583
+ /* @__PURE__ */ jsxs16("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
5394
5584
  statusIcon,
5395
- /* @__PURE__ */ jsx19("span", { children: getToolStatusLabel(toolCall.status) })
5585
+ /* @__PURE__ */ jsx20("span", { children: getToolStatusLabel(toolCall.status) })
5396
5586
  ] }),
5397
- /* @__PURE__ */ jsxs15("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: [
5587
+ /* @__PURE__ */ jsxs16("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: [
5398
5588
  displayName,
5399
5589
  toolCall.status === "error" ? "\uFF08\u5F85\u91CD\u8BD5\uFF09" : ""
5400
5590
  ] })
5401
5591
  ]
5402
5592
  }
5403
5593
  ),
5404
- filePath && /* @__PURE__ */ jsx19("span", { className: "flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx19(FilePathLink, { filePath, sessionId: resolvedSessionId }) }),
5405
- loadedSkillName ? /* @__PURE__ */ jsx19(
5594
+ filePath && /* @__PURE__ */ jsx20("span", { className: "flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx20(FilePathLink, { filePath, sessionId: resolvedSessionId }) }),
5595
+ loadedSkillName ? /* @__PURE__ */ jsx20(
5406
5596
  "span",
5407
5597
  {
5408
5598
  className: "min-w-0 max-w-[50%] shrink truncate text-[hsl(var(--foreground))]",
@@ -5410,9 +5600,9 @@ function ToolCallBlock({
5410
5600
  children: loadedSkillName
5411
5601
  }
5412
5602
  ) : null,
5413
- reasoning ? /* @__PURE__ */ jsx19(ThinkingBadge, { reasoning, variant: "block" }) : null,
5414
- typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx19("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) }),
5415
- uiMeta?.target === "preview" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? /* @__PURE__ */ jsxs15(
5603
+ reasoning ? /* @__PURE__ */ jsx20(ThinkingBadge, { reasoning, variant: "block" }) : null,
5604
+ typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx20("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) }),
5605
+ uiMeta?.target === "preview" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? /* @__PURE__ */ jsxs16(
5416
5606
  "button",
5417
5607
  {
5418
5608
  type: "button",
@@ -5430,18 +5620,18 @@ function ToolCallBlock({
5430
5620
  className: "inline-flex shrink-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer",
5431
5621
  title: `\u6253\u5F00 ${uiMeta.title ?? displayName}`,
5432
5622
  children: [
5433
- /* @__PURE__ */ jsx19(PanelRightOpen, { size: 11 }),
5434
- /* @__PURE__ */ jsx19("span", { children: uiMeta.title ?? displayName })
5623
+ /* @__PURE__ */ jsx20(PanelRightOpen, { size: 11 }),
5624
+ /* @__PURE__ */ jsx20("span", { children: uiMeta.title ?? displayName })
5435
5625
  ]
5436
5626
  }
5437
5627
  ) : null
5438
5628
  ] }),
5439
- expanded && /* @__PURE__ */ jsx19("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: Renderer ? /* @__PURE__ */ jsx19(Renderer, { toolCall, sessionId: resolvedSessionId }) : /* @__PURE__ */ jsxs15(Fragment4, { children: [
5440
- /* @__PURE__ */ jsx19("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
5441
- /* @__PURE__ */ jsx19("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: formatArgs(toolCall.arguments) }),
5442
- toolCall.result != null && /* @__PURE__ */ jsxs15(Fragment4, { children: [
5443
- /* @__PURE__ */ jsx19("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
5444
- /* @__PURE__ */ jsx19(
5629
+ expanded && /* @__PURE__ */ jsx20("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: Renderer ? /* @__PURE__ */ jsx20(Renderer, { toolCall, sessionId: resolvedSessionId }) : /* @__PURE__ */ jsxs16(Fragment5, { children: [
5630
+ /* @__PURE__ */ jsx20("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
5631
+ /* @__PURE__ */ jsx20("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: formatArgs(toolCall.arguments) }),
5632
+ toolCall.result != null && /* @__PURE__ */ jsxs16(Fragment5, { children: [
5633
+ /* @__PURE__ */ jsx20("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
5634
+ /* @__PURE__ */ jsx20(
5445
5635
  "pre",
5446
5636
  {
5447
5637
  className: cn(
@@ -5517,7 +5707,7 @@ function buildAskUserPayload(argumentsJson) {
5517
5707
  }
5518
5708
 
5519
5709
  // src/react/components/chat/UserMessageBubble.tsx
5520
- import { useState as useState14 } from "react";
5710
+ import { useState as useState15 } from "react";
5521
5711
 
5522
5712
  // src/react/lib/preview-dispatch.ts
5523
5713
  var IMAGE_EXTS = [
@@ -5662,7 +5852,7 @@ import { Download as Download3, X as X5 } from "lucide-react";
5662
5852
  import { useEffect as useEffect12 } from "react";
5663
5853
  import { createPortal as createPortal4 } from "react-dom";
5664
5854
  import { useQuery as useQuery6 } from "@tanstack/react-query";
5665
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5855
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5666
5856
  function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5667
5857
  useEffect12(() => {
5668
5858
  if (!open) return;
@@ -5690,7 +5880,7 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5690
5880
  staleTime: 6e4
5691
5881
  });
5692
5882
  if (!open) return null;
5693
- const body = /* @__PURE__ */ jsx20(
5883
+ const body = /* @__PURE__ */ jsx21(
5694
5884
  "div",
5695
5885
  {
5696
5886
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",
@@ -5701,17 +5891,17 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5701
5891
  role: "dialog",
5702
5892
  "aria-modal": "true",
5703
5893
  "aria-labelledby": "attachment-preview-title",
5704
- children: /* @__PURE__ */ jsxs16(
5894
+ children: /* @__PURE__ */ jsxs17(
5705
5895
  "div",
5706
5896
  {
5707
5897
  className: "max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl",
5708
5898
  onClick: (e) => e.stopPropagation(),
5709
5899
  onKeyDown: (e) => e.stopPropagation(),
5710
5900
  children: [
5711
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
5712
- /* @__PURE__ */ jsx20("h3", { id: "attachment-preview-title", className: "truncate text-sm font-semibold text-[hsl(var(--foreground))]", children: filename }),
5713
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
5714
- url && /* @__PURE__ */ jsx20(
5901
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
5902
+ /* @__PURE__ */ jsx21("h3", { id: "attachment-preview-title", className: "truncate text-sm font-semibold text-[hsl(var(--foreground))]", children: filename }),
5903
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
5904
+ url && /* @__PURE__ */ jsx21(
5715
5905
  "a",
5716
5906
  {
5717
5907
  href: url,
@@ -5720,22 +5910,22 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5720
5910
  rel: "noopener noreferrer",
5721
5911
  title: "\u4E0B\u8F7D",
5722
5912
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
5723
- children: /* @__PURE__ */ jsx20(Download3, { size: 14 })
5913
+ children: /* @__PURE__ */ jsx21(Download3, { size: 14 })
5724
5914
  }
5725
5915
  ),
5726
- /* @__PURE__ */ jsx20(
5916
+ /* @__PURE__ */ jsx21(
5727
5917
  "button",
5728
5918
  {
5729
5919
  type: "button",
5730
5920
  onClick: () => onOpenChange(false),
5731
5921
  title: "\u5173\u95ED",
5732
5922
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
5733
- children: /* @__PURE__ */ jsx20(X5, { size: 14 })
5923
+ children: /* @__PURE__ */ jsx21(X5, { size: 14 })
5734
5924
  }
5735
5925
  )
5736
5926
  ] })
5737
5927
  ] }),
5738
- /* @__PURE__ */ jsx20("div", { className: "max-h-[calc(90vh-56px)] overflow-auto px-4 py-3 text-sm text-[hsl(var(--foreground))]", children: renderContent({ mode, url, content, error }) })
5928
+ /* @__PURE__ */ jsx21("div", { className: "max-h-[calc(90vh-56px)] overflow-auto px-4 py-3 text-sm text-[hsl(var(--foreground))]", children: renderContent({ mode, url, content, error }) })
5739
5929
  ]
5740
5930
  }
5741
5931
  )
@@ -5750,43 +5940,43 @@ function renderContent({
5750
5940
  error
5751
5941
  }) {
5752
5942
  if (!url) {
5753
- return /* @__PURE__ */ jsx20("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B64\u9644\u4EF6\u6682\u65E0\u53EF\u7528\u9884\u89C8\u5730\u5740\u3002" });
5943
+ return /* @__PURE__ */ jsx21("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B64\u9644\u4EF6\u6682\u65E0\u53EF\u7528\u9884\u89C8\u5730\u5740\u3002" });
5754
5944
  }
5755
5945
  if (mode === "default") {
5756
- return /* @__PURE__ */ jsxs16("p", { className: "text-[hsl(var(--muted-foreground))]", children: [
5946
+ return /* @__PURE__ */ jsxs17("p", { className: "text-[hsl(var(--muted-foreground))]", children: [
5757
5947
  "\u6B64\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u5185\u5D4C\u9884\u89C8\u3002\u8BF7\u70B9\u51FB\u53F3\u4E0A\u89D2",
5758
- /* @__PURE__ */ jsx20("span", { className: "mx-1 font-medium text-[hsl(var(--foreground))]", children: "\u4E0B\u8F7D" }),
5948
+ /* @__PURE__ */ jsx21("span", { className: "mx-1 font-medium text-[hsl(var(--foreground))]", children: "\u4E0B\u8F7D" }),
5759
5949
  "\u6309\u94AE\u67E5\u770B\u3002"
5760
5950
  ] });
5761
5951
  }
5762
5952
  if (error) {
5763
- return /* @__PURE__ */ jsxs16("p", { className: "text-[hsl(var(--destructive))]", children: [
5953
+ return /* @__PURE__ */ jsxs17("p", { className: "text-[hsl(var(--destructive))]", children: [
5764
5954
  "\u52A0\u8F7D\u5931\u8D25\uFF1A",
5765
5955
  String(error?.message ?? error)
5766
5956
  ] });
5767
5957
  }
5768
5958
  if (content == null) {
5769
- return /* @__PURE__ */ jsx20("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u4E2D\u2026" });
5959
+ return /* @__PURE__ */ jsx21("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u4E2D\u2026" });
5770
5960
  }
5771
5961
  if (mode === "markdown") {
5772
- return /* @__PURE__ */ jsx20(MarkdownContent, { className: "prose prose-sm prose-invert max-w-none", children: content });
5962
+ return /* @__PURE__ */ jsx21(MarkdownContent, { className: "prose prose-sm prose-invert max-w-none", children: content });
5773
5963
  }
5774
- return /* @__PURE__ */ jsx20("pre", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed", children: content });
5964
+ return /* @__PURE__ */ jsx21("pre", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed", children: content });
5775
5965
  }
5776
5966
 
5777
5967
  // src/react/components/chat/MessageContextPills.tsx
5778
5968
  import { Bookmark } from "lucide-react";
5779
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5969
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
5780
5970
  function MessageContextPills({ contexts }) {
5781
5971
  if (contexts.length === 0) return null;
5782
- return /* @__PURE__ */ jsx21("div", { className: "flex flex-wrap gap-1.5", children: contexts.map((ctx, index) => /* @__PURE__ */ jsxs17(
5972
+ return /* @__PURE__ */ jsx22("div", { className: "flex flex-wrap gap-1.5", children: contexts.map((ctx, index) => /* @__PURE__ */ jsxs18(
5783
5973
  "div",
5784
5974
  {
5785
5975
  className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--primary)/0.25)] bg-[hsl(var(--primary)/0.1)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary)/0.85)]",
5786
5976
  title: ctx.content,
5787
5977
  children: [
5788
- /* @__PURE__ */ jsx21(Bookmark, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.65)]" }),
5789
- /* @__PURE__ */ jsx21("span", { className: "max-w-56 truncate", children: ctx.label })
5978
+ /* @__PURE__ */ jsx22(Bookmark, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.65)]" }),
5979
+ /* @__PURE__ */ jsx22("span", { className: "max-w-56 truncate", children: ctx.label })
5790
5980
  ]
5791
5981
  },
5792
5982
  `${ctx.label}:${index}`
@@ -5794,8 +5984,8 @@ function MessageContextPills({ contexts }) {
5794
5984
  }
5795
5985
 
5796
5986
  // src/react/components/chat/MessageFileAttachmentList.tsx
5797
- import { Archive as Archive2, File as File3, FileCode2 as FileCode22, FileText as FileText3, Film as Film2, Music as Music2 } from "lucide-react";
5798
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
5987
+ import { Archive as Archive2, File as File3, FileCode2 as FileCode22, FileText as FileText4, Film as Film2, Music as Music2 } from "lucide-react";
5988
+ import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
5799
5989
  function getFileIcon(fileName) {
5800
5990
  const lowerName = fileName.toLowerCase();
5801
5991
  if (/\.(zip|rar|7z|tar|gz|bz2|xz)$/.test(lowerName)) {
@@ -5811,7 +6001,7 @@ function getFileIcon(fileName) {
5811
6001
  return Film2;
5812
6002
  }
5813
6003
  if (/\.(txt|pdf|doc|docx|rtf|odt)$/.test(lowerName)) {
5814
- return FileText3;
6004
+ return FileText4;
5815
6005
  }
5816
6006
  return File3;
5817
6007
  }
@@ -5824,15 +6014,15 @@ function MessageFileAttachmentList({
5824
6014
  return null;
5825
6015
  }
5826
6016
  const pillClass = "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]";
5827
- return /* @__PURE__ */ jsx22("div", { className: cn("flex flex-wrap gap-1.5", className), children: files.map((file) => {
6017
+ return /* @__PURE__ */ jsx23("div", { className: cn("flex flex-wrap gap-1.5", className), children: files.map((file) => {
5828
6018
  const Icon = getFileIcon(file.name);
5829
6019
  const key = `${file.name}-${file.data.slice(0, 32)}`;
5830
- const content = /* @__PURE__ */ jsxs18(Fragment5, { children: [
5831
- /* @__PURE__ */ jsx22(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5832
- /* @__PURE__ */ jsx22("span", { className: "max-w-32 truncate", children: file.name })
6020
+ const content = /* @__PURE__ */ jsxs19(Fragment6, { children: [
6021
+ /* @__PURE__ */ jsx23(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
6022
+ /* @__PURE__ */ jsx23("span", { className: "max-w-32 truncate", children: file.name })
5833
6023
  ] });
5834
6024
  if (onPreview) {
5835
- return /* @__PURE__ */ jsx22(
6025
+ return /* @__PURE__ */ jsx23(
5836
6026
  "button",
5837
6027
  {
5838
6028
  type: "button",
@@ -5844,16 +6034,16 @@ function MessageFileAttachmentList({
5844
6034
  key
5845
6035
  );
5846
6036
  }
5847
- return /* @__PURE__ */ jsx22("div", { className: pillClass, title: file.name, children: content }, key);
6037
+ return /* @__PURE__ */ jsx23("div", { className: pillClass, title: file.name, children: content }, key);
5848
6038
  }) });
5849
6039
  }
5850
6040
 
5851
6041
  // src/react/components/chat/MessageActions.tsx
5852
6042
  import { Check as Check2, Copy } from "lucide-react";
5853
- import { useState as useState13 } from "react";
5854
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
6043
+ import { useState as useState14 } from "react";
6044
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5855
6045
  function MessageActions({ content, className }) {
5856
- const [copied, setCopied] = useState13(false);
6046
+ const [copied, setCopied] = useState14(false);
5857
6047
  const handleCopy = async () => {
5858
6048
  const ok = await copyToClipboard(content);
5859
6049
  if (ok) {
@@ -5861,7 +6051,7 @@ function MessageActions({ content, className }) {
5861
6051
  setTimeout(() => setCopied(false), 2e3);
5862
6052
  }
5863
6053
  };
5864
- return /* @__PURE__ */ jsx23("div", { className: cn("flex items-center gap-1 mt-1.5", className), children: /* @__PURE__ */ jsxs19(
6054
+ return /* @__PURE__ */ jsx24("div", { className: cn("flex items-center gap-1 mt-1.5", className), children: /* @__PURE__ */ jsxs20(
5865
6055
  "button",
5866
6056
  {
5867
6057
  type: "button",
@@ -5871,16 +6061,16 @@ function MessageActions({ content, className }) {
5871
6061
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]"
5872
6062
  ),
5873
6063
  children: [
5874
- copied ? /* @__PURE__ */ jsx23(Check2, { size: 12 }) : /* @__PURE__ */ jsx23(Copy, { size: 12 }),
5875
- /* @__PURE__ */ jsx23("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
6064
+ copied ? /* @__PURE__ */ jsx24(Check2, { size: 12 }) : /* @__PURE__ */ jsx24(Copy, { size: 12 }),
6065
+ /* @__PURE__ */ jsx24("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
5876
6066
  ]
5877
6067
  }
5878
6068
  ) });
5879
6069
  }
5880
6070
 
5881
6071
  // src/react/components/chat/TextAttachmentPills.tsx
5882
- import { Archive as Archive3, File as File4, FileCode2 as FileCode23, FileText as FileText4, Film as Film3, Music as Music3, FileSpreadsheet, Image } from "lucide-react";
5883
- import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
6072
+ import { Archive as Archive3, File as File4, FileCode2 as FileCode23, FileText as FileText5, Film as Film3, Music as Music3, FileSpreadsheet, Image } from "lucide-react";
6073
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
5884
6074
  function getFileIcon2(fileName) {
5885
6075
  const lower2 = fileName.toLowerCase();
5886
6076
  if (/\.(zip|rar|7z|tar|gz)$/.test(lower2)) return Archive3;
@@ -5889,21 +6079,21 @@ function getFileIcon2(fileName) {
5889
6079
  if (/\.(mp4|mov|mkv|avi|webm)$/.test(lower2)) return Film3;
5890
6080
  if (/\.(png|jpg|jpeg|gif|svg|webp|bmp)$/.test(lower2)) return Image;
5891
6081
  if (/\.(xlsx?|csv)$/.test(lower2)) return FileSpreadsheet;
5892
- if (/\.(txt|pdf|docx?|rtf|md)$/.test(lower2)) return FileText4;
6082
+ if (/\.(txt|pdf|docx?|rtf|md)$/.test(lower2)) return FileText5;
5893
6083
  return File4;
5894
6084
  }
5895
6085
  function TextAttachmentPills({ attachments, onPreview }) {
5896
6086
  if (attachments.length === 0) return null;
5897
6087
  const pillClass = "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--primary)/0.08)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary)/0.8)]";
5898
- return /* @__PURE__ */ jsx24("div", { className: "flex flex-wrap gap-1.5", children: attachments.map((att, index) => {
6088
+ return /* @__PURE__ */ jsx25("div", { className: "flex flex-wrap gap-1.5", children: attachments.map((att, index) => {
5899
6089
  const Icon = getFileIcon2(att.name);
5900
6090
  const key = `${att.uploadedPath ?? att.name}:${att.name}:${index}`;
5901
- const content = /* @__PURE__ */ jsxs20(Fragment6, { children: [
5902
- /* @__PURE__ */ jsx24(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.6)]" }),
5903
- /* @__PURE__ */ jsx24("span", { className: "max-w-40 truncate", children: att.name })
6091
+ const content = /* @__PURE__ */ jsxs21(Fragment7, { children: [
6092
+ /* @__PURE__ */ jsx25(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.6)]" }),
6093
+ /* @__PURE__ */ jsx25("span", { className: "max-w-40 truncate", children: att.name })
5904
6094
  ] });
5905
6095
  if (onPreview) {
5906
- return /* @__PURE__ */ jsx24(
6096
+ return /* @__PURE__ */ jsx25(
5907
6097
  "button",
5908
6098
  {
5909
6099
  type: "button",
@@ -5915,7 +6105,7 @@ function TextAttachmentPills({ attachments, onPreview }) {
5915
6105
  key
5916
6106
  );
5917
6107
  }
5918
- return /* @__PURE__ */ jsx24("div", { className: pillClass, title: att.name, children: content }, key);
6108
+ return /* @__PURE__ */ jsx25("div", { className: pillClass, title: att.name, children: content }, key);
5919
6109
  }) });
5920
6110
  }
5921
6111
 
@@ -5924,34 +6114,34 @@ import { RefreshCcw } from "lucide-react";
5924
6114
 
5925
6115
  // src/react/components/chat/whatif-quote-context.tsx
5926
6116
  import { createContext as createContext3, useContext as useContext3, useMemo as useMemo13 } from "react";
5927
- import { jsx as jsx25 } from "react/jsx-runtime";
6117
+ import { jsx as jsx26 } from "react/jsx-runtime";
5928
6118
  var WhatIfQuoteContext = createContext3({});
5929
6119
  function WhatIfQuoteProvider({
5930
6120
  onJumpToStep,
5931
6121
  children
5932
6122
  }) {
5933
6123
  const value = useMemo13(() => ({ onJumpToStep }), [onJumpToStep]);
5934
- return /* @__PURE__ */ jsx25(WhatIfQuoteContext.Provider, { value, children });
6124
+ return /* @__PURE__ */ jsx26(WhatIfQuoteContext.Provider, { value, children });
5935
6125
  }
5936
6126
  function useWhatIfQuoteContext() {
5937
6127
  return useContext3(WhatIfQuoteContext);
5938
6128
  }
5939
6129
 
5940
6130
  // src/react/components/chat/WhatIfUserBubble.tsx
5941
- import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
6131
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
5942
6132
  function WhatIfUserBubble({ parsed, onQuoteClick }) {
5943
6133
  const { onJumpToStep } = useWhatIfQuoteContext();
5944
6134
  const handleQuoteClick = onQuoteClick ?? onJumpToStep;
5945
6135
  const { fromStep, quotes, userText } = parsed;
5946
- return /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-end gap-2", children: [
5947
- /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5948
- /* @__PURE__ */ jsx26(RefreshCcw, { size: 10 }),
5949
- /* @__PURE__ */ jsx26("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
6136
+ return /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-end gap-2", children: [
6137
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
6138
+ /* @__PURE__ */ jsx27(RefreshCcw, { size: 10 }),
6139
+ /* @__PURE__ */ jsx27("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
5950
6140
  ] }),
5951
- quotes.length > 0 && /* @__PURE__ */ jsx26("div", { className: "flex flex-wrap justify-end gap-1.5", children: quotes.map((q, i) => {
6141
+ quotes.length > 0 && /* @__PURE__ */ jsx27("div", { className: "flex flex-wrap justify-end gap-1.5", children: quotes.map((q, i) => {
5952
6142
  const clickable = q.stepNumber != null && !!handleQuoteClick;
5953
6143
  const label = q.stepNumber != null ? `\u6B65\u9AA4${q.stepNumber} \xB7 ${q.label}` : q.label;
5954
- return /* @__PURE__ */ jsxs21(
6144
+ return /* @__PURE__ */ jsxs22(
5955
6145
  "button",
5956
6146
  {
5957
6147
  type: "button",
@@ -5960,14 +6150,14 @@ function WhatIfUserBubble({ parsed, onQuoteClick }) {
5960
6150
  className: "inline-flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-0.5 text-[11px] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring)/0.5)] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] disabled:cursor-default disabled:hover:border-[hsl(var(--border))] disabled:hover:bg-[hsl(var(--card))]",
5961
6151
  title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0,
5962
6152
  children: [
5963
- /* @__PURE__ */ jsx26("span", { children: "\u21B3" }),
5964
- /* @__PURE__ */ jsx26("span", { className: "max-w-[14rem] truncate", children: label })
6153
+ /* @__PURE__ */ jsx27("span", { children: "\u21B3" }),
6154
+ /* @__PURE__ */ jsx27("span", { className: "max-w-[14rem] truncate", children: label })
5965
6155
  ]
5966
6156
  },
5967
6157
  `${q.stepNumber ?? "x"}-${i}`
5968
6158
  );
5969
6159
  }) }),
5970
- userText && /* @__PURE__ */ jsx26("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx26(
6160
+ userText && /* @__PURE__ */ jsx27("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx27(
5971
6161
  MarkdownContent,
5972
6162
  {
5973
6163
  className: "prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0",
@@ -5979,7 +6169,7 @@ function WhatIfUserBubble({ parsed, onQuoteClick }) {
5979
6169
  }
5980
6170
 
5981
6171
  // src/react/components/chat/UserMessageBubble.tsx
5982
- import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
6172
+ import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
5983
6173
  function isUserMessage(message) {
5984
6174
  return message.role === "user";
5985
6175
  }
@@ -6007,9 +6197,9 @@ function UserMessageBubble({ message, className }) {
6007
6197
  const trimmedClean = cleanText.trim();
6008
6198
  const whatifParsed = trimmedClean && imageParts.length === 0 && fileParts.length === 0 && textAttachments.length === 0 ? parseWhatIfPrompt(cleanText) : null;
6009
6199
  if (whatifParsed) {
6010
- return /* @__PURE__ */ jsx27("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs22("div", { className: "group flex max-w-[72%] flex-col items-end gap-2", children: [
6011
- /* @__PURE__ */ jsx27(WhatIfUserBubble, { parsed: whatifParsed }),
6012
- whatifParsed.userText && /* @__PURE__ */ jsx27(
6200
+ return /* @__PURE__ */ jsx28("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs23("div", { className: "group flex max-w-[72%] flex-col items-end gap-2", children: [
6201
+ /* @__PURE__ */ jsx28(WhatIfUserBubble, { parsed: whatifParsed }),
6202
+ whatifParsed.userText && /* @__PURE__ */ jsx28(
6013
6203
  MessageActions,
6014
6204
  {
6015
6205
  content: whatifParsed.userText,
@@ -6043,8 +6233,8 @@ function UserMessageBubble({ message, className }) {
6043
6233
  alt: attachment.name || "\u7528\u6237\u4E0A\u4F20\u7684\u56FE\u7247"
6044
6234
  }))
6045
6235
  ];
6046
- const [lightboxIndex, setLightboxIndex] = useState14(null);
6047
- const [preview, setPreview] = useState14(null);
6236
+ const [lightboxIndex, setLightboxIndex] = useState15(null);
6237
+ const [preview, setPreview] = useState15(null);
6048
6238
  const handleTextAttachmentPreview = (attachment) => {
6049
6239
  if (!activeSessionId) return;
6050
6240
  const pathForUrl = attachment.uploadedPath ?? attachment.name;
@@ -6063,16 +6253,16 @@ function UserMessageBubble({ message, className }) {
6063
6253
  const mode = kind === "text" ? lower2.endsWith(".md") ? "markdown" : "text" : "default";
6064
6254
  setPreview({ filename: attachment.name, url, mode });
6065
6255
  };
6066
- return /* @__PURE__ */ jsx27("div", { className: cn("flex justify-end", className), children: /* @__PURE__ */ jsxs22("div", { className: "group flex max-w-[72%] flex-col items-end gap-3", children: [
6067
- (imageParts.length > 0 || imageTextAttachments.length > 0) && /* @__PURE__ */ jsxs22("div", { className: "grid gap-2", children: [
6068
- imageParts.map((part, idx) => /* @__PURE__ */ jsx27(
6256
+ return /* @__PURE__ */ jsx28("div", { className: cn("flex justify-end", className), children: /* @__PURE__ */ jsxs23("div", { className: "group flex max-w-[72%] flex-col items-end gap-3", children: [
6257
+ (imageParts.length > 0 || imageTextAttachments.length > 0) && /* @__PURE__ */ jsxs23("div", { className: "grid gap-2", children: [
6258
+ imageParts.map((part, idx) => /* @__PURE__ */ jsx28(
6069
6259
  "button",
6070
6260
  {
6071
6261
  type: "button",
6072
6262
  onClick: () => setLightboxIndex(idx),
6073
6263
  className: "cursor-zoom-in",
6074
6264
  title: "\u67E5\u770B\u5927\u56FE",
6075
- children: /* @__PURE__ */ jsx27(
6265
+ children: /* @__PURE__ */ jsx28(
6076
6266
  "img",
6077
6267
  {
6078
6268
  src: part.image_url.url,
@@ -6083,14 +6273,14 @@ function UserMessageBubble({ message, className }) {
6083
6273
  },
6084
6274
  part.image_url.url
6085
6275
  )),
6086
- imageTextAttachments.map((attachment, idx) => /* @__PURE__ */ jsx27(
6276
+ imageTextAttachments.map((attachment, idx) => /* @__PURE__ */ jsx28(
6087
6277
  "button",
6088
6278
  {
6089
6279
  type: "button",
6090
6280
  onClick: () => setLightboxIndex(imageParts.length + idx),
6091
6281
  className: "cursor-zoom-in",
6092
6282
  title: "\u67E5\u770B\u5927\u56FE",
6093
- children: /* @__PURE__ */ jsx27(
6283
+ children: /* @__PURE__ */ jsx28(
6094
6284
  "img",
6095
6285
  {
6096
6286
  src: attachment.url,
@@ -6102,7 +6292,7 @@ function UserMessageBubble({ message, className }) {
6102
6292
  `${attachment.uploadedPath}:${attachment.name}`
6103
6293
  ))
6104
6294
  ] }),
6105
- lightboxImages.length > 0 && /* @__PURE__ */ jsx27(
6295
+ lightboxImages.length > 0 && /* @__PURE__ */ jsx28(
6106
6296
  ImageLightbox,
6107
6297
  {
6108
6298
  open: lightboxIndex != null,
@@ -6113,15 +6303,15 @@ function UserMessageBubble({ message, className }) {
6113
6303
  initialIndex: lightboxIndex ?? 0
6114
6304
  }
6115
6305
  ),
6116
- /* @__PURE__ */ jsx27(MessageFileAttachmentList, { files: fileParts }),
6117
- /* @__PURE__ */ jsx27(
6306
+ /* @__PURE__ */ jsx28(MessageFileAttachmentList, { files: fileParts }),
6307
+ /* @__PURE__ */ jsx28(
6118
6308
  TextAttachmentPills,
6119
6309
  {
6120
6310
  attachments: nonImageTextAttachments,
6121
6311
  onPreview: handleTextAttachmentPreview
6122
6312
  }
6123
6313
  ),
6124
- preview && /* @__PURE__ */ jsx27(
6314
+ preview && /* @__PURE__ */ jsx28(
6125
6315
  AttachmentPreviewDialog,
6126
6316
  {
6127
6317
  open: preview != null,
@@ -6133,8 +6323,8 @@ function UserMessageBubble({ message, className }) {
6133
6323
  mode: preview.mode
6134
6324
  }
6135
6325
  ),
6136
- /* @__PURE__ */ jsx27(MessageContextPills, { contexts: textContexts }),
6137
- trimmedClean && /* @__PURE__ */ jsx27("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx27(
6326
+ /* @__PURE__ */ jsx28(MessageContextPills, { contexts: textContexts }),
6327
+ trimmedClean && /* @__PURE__ */ jsx28("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx28(
6138
6328
  MarkdownContent,
6139
6329
  {
6140
6330
  className: "prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0",
@@ -6142,7 +6332,7 @@ function UserMessageBubble({ message, className }) {
6142
6332
  children: cleanText
6143
6333
  }
6144
6334
  ) }),
6145
- trimmedClean && /* @__PURE__ */ jsx27(
6335
+ trimmedClean && /* @__PURE__ */ jsx28(
6146
6336
  MessageActions,
6147
6337
  {
6148
6338
  content: trimmedClean,
@@ -6157,14 +6347,14 @@ function ErrorMessageBlock({
6157
6347
  }) {
6158
6348
  const text = getTextContent(message.content);
6159
6349
  const looksLikeModelUnavailable = /no source matches this model|404/i.test(text);
6160
- return /* @__PURE__ */ jsx27("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsxs22("div", { className: "max-w-[85%] border-l-[3px] border-[hsl(var(--destructive))] px-4 py-1 text-sm leading-7 text-[hsl(var(--destructive))]", children: [
6350
+ return /* @__PURE__ */ jsx28("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsxs23("div", { className: "max-w-[85%] border-l-[3px] border-[hsl(var(--destructive))] px-4 py-1 text-sm leading-7 text-[hsl(var(--destructive))]", children: [
6161
6351
  text,
6162
- looksLikeModelUnavailable ? /* @__PURE__ */ jsx27("div", { className: "mt-1 opacity-80", children: "\u6A21\u578B\u53EF\u80FD\u672A\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" }) : null
6352
+ looksLikeModelUnavailable ? /* @__PURE__ */ jsx28("div", { className: "mt-1 opacity-80", children: "\u6A21\u578B\u53EF\u80FD\u672A\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" }) : null
6163
6353
  ] }) });
6164
6354
  }
6165
6355
 
6166
6356
  // src/react/components/chat/AgentLoopBlock.tsx
6167
- import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
6357
+ import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
6168
6358
  var EMPTY_MESSAGES2 = [];
6169
6359
  var EMPTY_AGENT_LOOPS = {};
6170
6360
  var COLLAPSED_SUMMARY_HIDDEN_TOOLS = /* @__PURE__ */ new Set([
@@ -6211,7 +6401,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6211
6401
  () => visibleLoopToolCalls.some((childToolCall) => childToolCall.status === "awaiting_answer"),
6212
6402
  [visibleLoopToolCalls]
6213
6403
  );
6214
- const [expanded, setExpanded] = useState15(hasAwaitingAnswer);
6404
+ const [expanded, setExpanded] = useState16(hasAwaitingAnswer);
6215
6405
  const completedToolLabels = useMemo14(
6216
6406
  () => visibleLoopToolCalls.flatMap((childToolCall) => {
6217
6407
  const isCompleted = childToolCall.status === "done" || childToolCall.status !== "pending" && childToolCall.status !== "awaiting_answer" && childToolCall.status !== "error" && childToolCall.status !== "cancelled";
@@ -6257,7 +6447,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6257
6447
  const description = safeParseDescription(toolCall.arguments);
6258
6448
  const status = hasAwaitingAnswer || toolCall.status === "awaiting_answer" ? "awaiting_answer" : toolCall.status === "pending" || loopEntry?.info.status === "running" ? "running" : "done";
6259
6449
  const cardStyles = getLoopCardStyles(status);
6260
- return /* @__PURE__ */ jsxs23(
6450
+ return /* @__PURE__ */ jsxs24(
6261
6451
  "div",
6262
6452
  {
6263
6453
  className: cn(
@@ -6265,8 +6455,8 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6265
6455
  cardStyles.borderClass
6266
6456
  ),
6267
6457
  children: [
6268
- status === "running" || status === "awaiting_answer" ? /* @__PURE__ */ jsxs23(Fragment7, { children: [
6269
- /* @__PURE__ */ jsxs23(
6458
+ status === "running" || status === "awaiting_answer" ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
6459
+ /* @__PURE__ */ jsxs24(
6270
6460
  "div",
6271
6461
  {
6272
6462
  className: cn(
@@ -6274,24 +6464,24 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6274
6464
  cardStyles.headerClass
6275
6465
  ),
6276
6466
  children: [
6277
- /* @__PURE__ */ jsx28(
6467
+ /* @__PURE__ */ jsx29(
6278
6468
  "button",
6279
6469
  {
6280
6470
  type: "button",
6281
6471
  onClick: toggleExpanded,
6282
6472
  "aria-expanded": expanded,
6283
6473
  className: "flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6284
- children: /* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex items-center gap-2", children: [
6285
- status === "awaiting_answer" ? /* @__PURE__ */ jsx28(MessageSquareMore2, { size: 14, className: "shrink-0 text-amber-500" }) : /* @__PURE__ */ jsx28(Bot, { size: 14, className: "shrink-0 text-blue-500" }),
6286
- /* @__PURE__ */ jsxs23("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: [
6474
+ children: /* @__PURE__ */ jsxs24("span", { className: "min-w-0 flex items-center gap-2", children: [
6475
+ status === "awaiting_answer" ? /* @__PURE__ */ jsx29(MessageSquareMore2, { size: 14, className: "shrink-0 text-amber-500" }) : /* @__PURE__ */ jsx29(Bot, { size: 14, className: "shrink-0 text-blue-500" }),
6476
+ /* @__PURE__ */ jsxs24("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: [
6287
6477
  description,
6288
6478
  status === "awaiting_answer" ? " \u2014 \u7B49\u5F85\u56DE\u7B54" : ""
6289
6479
  ] })
6290
6480
  ] })
6291
6481
  }
6292
6482
  ),
6293
- reasoning ? /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning, variant: "block" }) : null,
6294
- /* @__PURE__ */ jsx28(
6483
+ reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null,
6484
+ /* @__PURE__ */ jsx29(
6295
6485
  Bot,
6296
6486
  {
6297
6487
  size: 13,
@@ -6299,14 +6489,14 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6299
6489
  "aria-label": "\u5B50\u667A\u80FD\u4F53"
6300
6490
  }
6301
6491
  ),
6302
- /* @__PURE__ */ jsx28(
6492
+ /* @__PURE__ */ jsx29(
6303
6493
  "button",
6304
6494
  {
6305
6495
  type: "button",
6306
6496
  onClick: toggleExpanded,
6307
6497
  "aria-expanded": expanded,
6308
6498
  className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6309
- children: /* @__PURE__ */ jsx28(
6499
+ children: /* @__PURE__ */ jsx29(
6310
6500
  ChevronRight4,
6311
6501
  {
6312
6502
  size: 14,
@@ -6321,7 +6511,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6321
6511
  ]
6322
6512
  }
6323
6513
  ),
6324
- !expanded ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-1 py-2", children: visibleLoopToolCalls.length > 0 ? visibleLoopToolCalls.map((childToolCall) => /* @__PURE__ */ jsx28(
6514
+ !expanded ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-1 py-2", children: visibleLoopToolCalls.length > 0 ? visibleLoopToolCalls.map((childToolCall) => /* @__PURE__ */ jsx29(
6325
6515
  ToolCallBlock,
6326
6516
  {
6327
6517
  toolCall: childToolCall,
@@ -6329,12 +6519,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6329
6519
  level: 2
6330
6520
  },
6331
6521
  childToolCall.id
6332
- )) : /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
6333
- /* @__PURE__ */ jsx28(Loader24, { size: 12, className: "shrink-0 animate-spin text-blue-500" }),
6334
- /* @__PURE__ */ jsx28("span", { children: "\u6B63\u5728\u542F\u52A8..." })
6335
- ] }) }) : status === "awaiting_answer" ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-1 py-2", children: /* @__PURE__ */ jsx28("div", { className: "px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u8BF7\u5728\u4E0B\u65B9\u5B50\u667A\u80FD\u4F53\u5BF9\u8BDD\u4E2D\u5B8C\u6210\u786E\u8BA4" }) }) : null
6336
- ] }) : /* @__PURE__ */ jsxs23(Fragment7, { children: [
6337
- /* @__PURE__ */ jsxs23(
6522
+ )) : /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
6523
+ /* @__PURE__ */ jsx29(Loader24, { size: 12, className: "shrink-0 animate-spin text-blue-500" }),
6524
+ /* @__PURE__ */ jsx29("span", { children: "\u6B63\u5728\u542F\u52A8..." })
6525
+ ] }) }) : status === "awaiting_answer" ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-1 py-2", children: /* @__PURE__ */ jsx29("div", { className: "px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u8BF7\u5728\u4E0B\u65B9\u5B50\u667A\u80FD\u4F53\u5BF9\u8BDD\u4E2D\u5B8C\u6210\u786E\u8BA4" }) }) : null
6526
+ ] }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
6527
+ /* @__PURE__ */ jsxs24(
6338
6528
  "div",
6339
6529
  {
6340
6530
  className: cn(
@@ -6342,21 +6532,21 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6342
6532
  cardStyles.headerClass
6343
6533
  ),
6344
6534
  children: [
6345
- /* @__PURE__ */ jsx28(
6535
+ /* @__PURE__ */ jsx29(
6346
6536
  "button",
6347
6537
  {
6348
6538
  type: "button",
6349
6539
  onClick: toggleExpanded,
6350
6540
  "aria-expanded": expanded,
6351
6541
  className: "flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6352
- children: /* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex items-center gap-2", children: [
6353
- /* @__PURE__ */ jsx28(Check3, { size: 14, className: "shrink-0 text-emerald-500" }),
6354
- /* @__PURE__ */ jsx28("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: description })
6542
+ children: /* @__PURE__ */ jsxs24("span", { className: "min-w-0 flex items-center gap-2", children: [
6543
+ /* @__PURE__ */ jsx29(Check3, { size: 14, className: "shrink-0 text-emerald-500" }),
6544
+ /* @__PURE__ */ jsx29("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: description })
6355
6545
  ] })
6356
6546
  }
6357
6547
  ),
6358
- reasoning ? /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning, variant: "block" }) : null,
6359
- /* @__PURE__ */ jsx28(
6548
+ reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null,
6549
+ /* @__PURE__ */ jsx29(
6360
6550
  Bot,
6361
6551
  {
6362
6552
  size: 13,
@@ -6364,14 +6554,14 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6364
6554
  "aria-label": "\u5B50\u667A\u80FD\u4F53"
6365
6555
  }
6366
6556
  ),
6367
- /* @__PURE__ */ jsx28(
6557
+ /* @__PURE__ */ jsx29(
6368
6558
  "button",
6369
6559
  {
6370
6560
  type: "button",
6371
6561
  onClick: toggleExpanded,
6372
6562
  "aria-expanded": expanded,
6373
6563
  className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6374
- children: /* @__PURE__ */ jsx28(
6564
+ children: /* @__PURE__ */ jsx29(
6375
6565
  ChevronRight4,
6376
6566
  {
6377
6567
  size: 14,
@@ -6386,9 +6576,9 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6386
6576
  ]
6387
6577
  }
6388
6578
  ),
6389
- !expanded ? /* @__PURE__ */ jsxs23(Fragment7, { children: [
6390
- /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1.5 px-4 py-2", children: completedToolLabels.length > 0 ? completedToolLabels.map(
6391
- (item) => item.kind === "file" ? /* @__PURE__ */ jsxs23(
6579
+ !expanded ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
6580
+ /* @__PURE__ */ jsx29("div", { className: "flex flex-wrap gap-1.5 px-4 py-2", children: completedToolLabels.length > 0 ? completedToolLabels.map(
6581
+ (item) => item.kind === "file" ? /* @__PURE__ */ jsxs24(
6392
6582
  "span",
6393
6583
  {
6394
6584
  className: "inline-flex min-w-0 items-center gap-1 rounded-md border px-2 py-0.5 text-xs font-semibold dark:border-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-300",
@@ -6399,12 +6589,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6399
6589
  },
6400
6590
  title: item.label,
6401
6591
  children: [
6402
- /* @__PURE__ */ jsx28(FileText5, { size: 12, className: "shrink-0", "aria-hidden": "true" }),
6403
- /* @__PURE__ */ jsx28("span", { className: "truncate", children: item.label })
6592
+ /* @__PURE__ */ jsx29(FileText6, { size: 12, className: "shrink-0", "aria-hidden": "true" }),
6593
+ /* @__PURE__ */ jsx29("span", { className: "truncate", children: item.label })
6404
6594
  ]
6405
6595
  },
6406
6596
  item.key
6407
- ) : /* @__PURE__ */ jsx28(
6597
+ ) : /* @__PURE__ */ jsx29(
6408
6598
  "span",
6409
6599
  {
6410
6600
  className: "inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-semibold dark:border-blue-300 dark:bg-blue-400/10 dark:text-blue-300",
@@ -6417,12 +6607,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6417
6607
  },
6418
6608
  item.key
6419
6609
  )
6420
- ) : /* @__PURE__ */ jsx28("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5DE5\u5177\u8C03\u7528" }) }),
6421
- inlineToolUiBlocks.length > 0 ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-2 px-4 pb-3", children: inlineToolUiBlocks.map((block) => /* @__PURE__ */ jsx28(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null
6610
+ ) : /* @__PURE__ */ jsx29("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5DE5\u5177\u8C03\u7528" }) }),
6611
+ inlineToolUiBlocks.length > 0 ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2 px-4 pb-3", children: inlineToolUiBlocks.map((block) => /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null
6422
6612
  ] }) : null
6423
6613
  ] }),
6424
- expanded && /* @__PURE__ */ jsx28("div", { className: "border-t border-[hsl(var(--border))] py-2", children: childMessages.length > 0 ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-3 px-3", children: childMessages.map(
6425
- (message, index) => message.role === "assistant" ? /* @__PURE__ */ jsx28(
6614
+ expanded && /* @__PURE__ */ jsx29("div", { className: "border-t border-[hsl(var(--border))] py-2", children: childMessages.length > 0 ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-3 px-3", children: childMessages.map(
6615
+ (message, index) => message.role === "assistant" ? /* @__PURE__ */ jsx29(
6426
6616
  ExpandedChildAssistantMessage,
6427
6617
  {
6428
6618
  message,
@@ -6430,13 +6620,13 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6430
6620
  isStreaming: message.status === "streaming"
6431
6621
  },
6432
6622
  message.entry_id ?? `${message.timestamp ?? "child"}-${index}`
6433
- ) : message.role === "user" ? /* @__PURE__ */ jsx28(
6623
+ ) : message.role === "user" ? /* @__PURE__ */ jsx29(
6434
6624
  ExpandedChildUserMessage,
6435
6625
  {
6436
6626
  message
6437
6627
  },
6438
6628
  message.entry_id ?? `${message.timestamp ?? "user"}-${index}`
6439
- ) : message.role === "error" ? /* @__PURE__ */ jsx28(
6629
+ ) : message.role === "error" ? /* @__PURE__ */ jsx29(
6440
6630
  "div",
6441
6631
  {
6442
6632
  className: "border-l-[2px] border-l-red-500 px-3 py-2 text-[11px] text-red-200",
@@ -6444,16 +6634,16 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6444
6634
  },
6445
6635
  message.entry_id ?? `${message.timestamp ?? "error"}-${index}`
6446
6636
  ) : null
6447
- ) }) : status === "running" ? /* @__PURE__ */ jsxs23("div", { className: "px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
6448
- /* @__PURE__ */ jsx28(Loader24, { size: 12, className: "mr-1.5 inline animate-spin" }),
6637
+ ) }) : status === "running" ? /* @__PURE__ */ jsxs24("div", { className: "px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
6638
+ /* @__PURE__ */ jsx29(Loader24, { size: 12, className: "mr-1.5 inline animate-spin" }),
6449
6639
  "\u6B63\u5728\u542F\u52A8..."
6450
- ] }) : toolCall.result ? /* @__PURE__ */ jsx28("pre", { className: "max-h-[400px] overflow-auto px-3 py-2 whitespace-pre-wrap text-[11px] text-[hsl(var(--muted-foreground))]", children: typeof toolCall.result === "string" ? toolCall.result : JSON.stringify(toolCall.result, null, 2) }) : null })
6640
+ ] }) : toolCall.result ? /* @__PURE__ */ jsx29("pre", { className: "max-h-[400px] overflow-auto px-3 py-2 whitespace-pre-wrap text-[11px] text-[hsl(var(--muted-foreground))]", children: typeof toolCall.result === "string" ? toolCall.result : JSON.stringify(toolCall.result, null, 2) }) : null })
6451
6641
  ]
6452
6642
  }
6453
6643
  );
6454
6644
  }
6455
6645
  function ExpandedChildUserMessage({ message }) {
6456
- return /* @__PURE__ */ jsx28("div", { className: "pl-8", children: /* @__PURE__ */ jsx28(UserMessageBubble, { message }) });
6646
+ return /* @__PURE__ */ jsx29("div", { className: "pl-8", children: /* @__PURE__ */ jsx29(UserMessageBubble, { message }) });
6457
6647
  }
6458
6648
  function ExpandedChildAssistantMessage({
6459
6649
  message,
@@ -6466,12 +6656,12 @@ function ExpandedChildAssistantMessage({
6466
6656
  const firstToolCallId = toolCalls[0]?.id;
6467
6657
  const toolReasoning = !isStreaming && !text && hasToolCalls ? message.reasoning : void 0;
6468
6658
  const standaloneReasoning = !isStreaming && !text && !hasToolCalls ? message.reasoning : void 0;
6469
- return /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
6470
- message.reasoning && isStreaming && /* @__PURE__ */ jsxs23(Reasoning, { isStreaming, children: [
6471
- /* @__PURE__ */ jsx28(ReasoningTrigger, {}),
6472
- /* @__PURE__ */ jsx28(ReasoningContent, { children: message.reasoning })
6659
+ return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-2", children: [
6660
+ message.reasoning && isStreaming && /* @__PURE__ */ jsxs24(Reasoning, { isStreaming, children: [
6661
+ /* @__PURE__ */ jsx29(ReasoningTrigger, {}),
6662
+ /* @__PURE__ */ jsx29(ReasoningContent, { children: message.reasoning })
6473
6663
  ] }),
6474
- text ? /* @__PURE__ */ jsx28(
6664
+ text ? /* @__PURE__ */ jsx29(
6475
6665
  ChildText,
6476
6666
  {
6477
6667
  text,
@@ -6480,10 +6670,10 @@ function ExpandedChildAssistantMessage({
6480
6670
  reasoning: !isStreaming ? message.reasoning : void 0
6481
6671
  }
6482
6672
  ) : null,
6483
- !text && isStreaming && /* @__PURE__ */ jsx28("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
6484
- standaloneReasoning ? /* @__PURE__ */ jsx28("div", { className: "pl-8", children: /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning: standaloneReasoning, variant: "block" }) }) : null,
6485
- hasToolCalls && /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-2", children: toolCalls.map(
6486
- (toolCall, index) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx28(
6673
+ !text && isStreaming && /* @__PURE__ */ jsx29("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
6674
+ standaloneReasoning ? /* @__PURE__ */ jsx29("div", { className: "pl-8", children: /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning: standaloneReasoning, variant: "block" }) }) : null,
6675
+ hasToolCalls && /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: toolCalls.map(
6676
+ (toolCall, index) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx29(
6487
6677
  AgentLoopBlock,
6488
6678
  {
6489
6679
  toolCall,
@@ -6491,7 +6681,7 @@ function ExpandedChildAssistantMessage({
6491
6681
  reasoning: toolCall.id === firstToolCallId ? toolReasoning : void 0
6492
6682
  },
6493
6683
  toolCall.id
6494
- ) : /* @__PURE__ */ jsx28(
6684
+ ) : /* @__PURE__ */ jsx29(
6495
6685
  ToolCallBlock,
6496
6686
  {
6497
6687
  toolCall,
@@ -6503,8 +6693,8 @@ function ExpandedChildAssistantMessage({
6503
6693
  toolCall.id
6504
6694
  )
6505
6695
  ) }),
6506
- message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-2", children: message.blocks.map(
6507
- (block, index) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx28("div", { className: "ml-4", children: /* @__PURE__ */ jsx28(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${index}`) : null
6696
+ message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: message.blocks.map(
6697
+ (block, index) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx29("div", { className: "ml-4", children: /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${index}`) : null
6508
6698
  ) }) : null
6509
6699
  ] });
6510
6700
  }
@@ -6514,8 +6704,8 @@ function ChildText({
6514
6704
  sessionId,
6515
6705
  reasoning
6516
6706
  }) {
6517
- return /* @__PURE__ */ jsxs23("div", { className: "pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]", children: [
6518
- /* @__PURE__ */ jsx28(
6707
+ return /* @__PURE__ */ jsxs24("div", { className: "pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]", children: [
6708
+ /* @__PURE__ */ jsx29(
6519
6709
  MarkdownContent,
6520
6710
  {
6521
6711
  mode: "streaming",
@@ -6525,8 +6715,8 @@ function ChildText({
6525
6715
  children: text
6526
6716
  }
6527
6717
  ),
6528
- isStreaming && /* @__PURE__ */ jsx28("span", { className: "ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60" }),
6529
- reasoning ? /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning }) : null
6718
+ isStreaming && /* @__PURE__ */ jsx29("span", { className: "ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60" }),
6719
+ reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning }) : null
6530
6720
  ] });
6531
6721
  }
6532
6722
  function getLoopCardStyles(status) {
@@ -6566,7 +6756,7 @@ function getLoopCardStyles(status) {
6566
6756
  }
6567
6757
 
6568
6758
  // src/react/components/chat/AssistantTurnBlock.tsx
6569
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
6759
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
6570
6760
  function defaultTurnDisplayMode({
6571
6761
  forceExpanded,
6572
6762
  hasActionableToolCall
@@ -6720,7 +6910,7 @@ function AssistantTurnBlock({
6720
6910
  ),
6721
6911
  [allToolCalls]
6722
6912
  );
6723
- const [displayMode, setDisplayMode] = useState16(
6913
+ const [displayMode, setDisplayMode] = useState17(
6724
6914
  defaultTurnDisplayMode({ forceExpanded, hasActionableToolCall })
6725
6915
  );
6726
6916
  const wasStreamingRef = useRef10(isStreaming);
@@ -6741,7 +6931,7 @@ function AssistantTurnBlock({
6741
6931
  const hasInterruptedState = messages.some((message) => message.status === "interrupted");
6742
6932
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
6743
6933
  const memoryRefs = Array.isArray(messages[0]?.memory_refs) ? messages[0].memory_refs : [];
6744
- return /* @__PURE__ */ jsxs24(
6934
+ return /* @__PURE__ */ jsxs25(
6745
6935
  "div",
6746
6936
  {
6747
6937
  className: cn(
@@ -6750,17 +6940,17 @@ function AssistantTurnBlock({
6750
6940
  customization?.classNames?.assistantTurn
6751
6941
  ),
6752
6942
  children: [
6753
- memoryRefs.length > 0 && /* @__PURE__ */ jsx29(MemoryRefsHint, { refs: memoryRefs }),
6754
- hasInterruptedState && /* @__PURE__ */ jsx29("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" }),
6755
- !isStreaming && /* @__PURE__ */ jsx29("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs24(
6943
+ memoryRefs.length > 0 && /* @__PURE__ */ jsx30(MemoryRefsHint, { refs: memoryRefs }),
6944
+ hasInterruptedState && /* @__PURE__ */ jsx30("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" }),
6945
+ !isStreaming && /* @__PURE__ */ jsx30("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs25(
6756
6946
  "button",
6757
6947
  {
6758
6948
  type: "button",
6759
6949
  onClick: () => setDisplayMode(displayMode === "detail" ? "compact" : "detail"),
6760
6950
  className: "inline-flex shrink-0 items-center gap-1 text-xs text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
6761
6951
  children: [
6762
- /* @__PURE__ */ jsx29("span", { children: effectiveMode === "detail" ? "\u7CBE\u7B80" : "\u8BE6\u7EC6" }),
6763
- /* @__PURE__ */ jsx29(
6952
+ /* @__PURE__ */ jsx30("span", { children: effectiveMode === "detail" ? "\u7CBE\u7B80" : "\u8BE6\u7EC6" }),
6953
+ /* @__PURE__ */ jsx30(
6764
6954
  ChevronRight5,
6765
6955
  {
6766
6956
  size: 18,
@@ -6770,7 +6960,7 @@ function AssistantTurnBlock({
6770
6960
  ]
6771
6961
  }
6772
6962
  ) }),
6773
- effectiveMode === "detail" ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx29(
6963
+ effectiveMode === "detail" ? /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx30(
6774
6964
  AssistantMessages,
6775
6965
  {
6776
6966
  messages,
@@ -6783,15 +6973,15 @@ function AssistantTurnBlock({
6783
6973
  showToolDetails: true,
6784
6974
  customization
6785
6975
  }
6786
- ) }) : /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-4", children: [
6787
- resourceBlocks.length > 0 ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-3", children: resourceBlocks.map((block) => /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null,
6788
- finalMessage ? /* @__PURE__ */ jsx29(
6976
+ ) }) : /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-4", children: [
6977
+ resourceBlocks.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-3", children: resourceBlocks.map((block) => /* @__PURE__ */ jsx30(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null,
6978
+ finalMessage ? /* @__PURE__ */ jsx30(
6789
6979
  "div",
6790
6980
  {
6791
6981
  className: cn(
6792
6982
  resourceBlocks.length > 0 && "border-t border-[hsl(var(--border))] pt-4"
6793
6983
  ),
6794
- children: /* @__PURE__ */ jsx29(
6984
+ children: /* @__PURE__ */ jsx30(
6795
6985
  AssistantMessageContent,
6796
6986
  {
6797
6987
  message: finalMessage,
@@ -6802,7 +6992,7 @@ function AssistantTurnBlock({
6802
6992
  }
6803
6993
  )
6804
6994
  }
6805
- ) : isStreaming ? /* @__PURE__ */ jsx29("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }) : null
6995
+ ) : isStreaming ? /* @__PURE__ */ jsx30("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }) : null
6806
6996
  ] }) })
6807
6997
  ]
6808
6998
  }
@@ -6832,16 +7022,16 @@ function AssistantMessages({
6832
7022
  const toolRenderItems = groupDetailedToolCalls(toolCalls);
6833
7023
  const toolReasoning = hasReasoning && !hasText && !hasAttachments && hasToolCalls && !isStreamingLastMessage ? reasoning : void 0;
6834
7024
  const contentReasoning = hasReasoning && !isStreamingLastMessage && (hasText || hasAttachments || !hasToolCalls) ? reasoning : void 0;
6835
- return /* @__PURE__ */ jsxs24(
7025
+ return /* @__PURE__ */ jsxs25(
6836
7026
  "div",
6837
7027
  {
6838
7028
  className: "flex flex-col gap-3",
6839
7029
  children: [
6840
- hasReasoning && isStreamingLastMessage && /* @__PURE__ */ jsxs24(Reasoning, { isStreaming: isStreamingLastMessage, children: [
6841
- /* @__PURE__ */ jsx29(ReasoningTrigger, {}),
6842
- /* @__PURE__ */ jsx29(ReasoningContent, { children: reasoning })
7030
+ hasReasoning && isStreamingLastMessage && /* @__PURE__ */ jsxs25(Reasoning, { isStreaming: isStreamingLastMessage, children: [
7031
+ /* @__PURE__ */ jsx30(ReasoningTrigger, {}),
7032
+ /* @__PURE__ */ jsx30(ReasoningContent, { children: reasoning })
6843
7033
  ] }),
6844
- /* @__PURE__ */ jsx29(
7034
+ /* @__PURE__ */ jsx30(
6845
7035
  AssistantMessageContent,
6846
7036
  {
6847
7037
  message,
@@ -6851,9 +7041,9 @@ function AssistantMessages({
6851
7041
  className: customization?.classNames?.assistantText
6852
7042
  }
6853
7043
  ),
6854
- hasToolCalls && showToolDetails && /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: toolRenderItems.map((item) => {
7044
+ hasToolCalls && showToolDetails && /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-2", children: toolRenderItems.map((item) => {
6855
7045
  if (item.kind === "read_group" || item.kind === "load_skill_group") {
6856
- return /* @__PURE__ */ jsx29(
7046
+ return /* @__PURE__ */ jsx30(
6857
7047
  CompactToolGroupBlock,
6858
7048
  {
6859
7049
  toolCalls: item.toolCalls,
@@ -6871,7 +7061,7 @@ function AssistantMessages({
6871
7061
  );
6872
7062
  }
6873
7063
  const { toolCall } = item;
6874
- return formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx29(
7064
+ return formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx30(
6875
7065
  AgentLoopBlock,
6876
7066
  {
6877
7067
  toolCall,
@@ -6879,7 +7069,7 @@ function AssistantMessages({
6879
7069
  reasoning: toolCall.id === firstToolCallId ? toolReasoning : void 0
6880
7070
  },
6881
7071
  toolCall.id
6882
- ) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx29(
7072
+ ) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx30(
6883
7073
  customization.components.ToolCall,
6884
7074
  {
6885
7075
  toolCall,
@@ -6894,7 +7084,7 @@ function AssistantMessages({
6894
7084
  customization
6895
7085
  },
6896
7086
  toolCall.id
6897
- ) : /* @__PURE__ */ jsx29(
7087
+ ) : /* @__PURE__ */ jsx30(
6898
7088
  ToolCallBlock,
6899
7089
  {
6900
7090
  toolCall,
@@ -6911,8 +7101,8 @@ function AssistantMessages({
6911
7101
  toolCall.id
6912
7102
  );
6913
7103
  }) }),
6914
- showToolDetails && message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: message.blocks.map(
6915
- (block, blockIndex) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx29("div", { className: "ml-4", children: /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${blockIndex}`) : null
7104
+ showToolDetails && message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-2", children: message.blocks.map(
7105
+ (block, blockIndex) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx30("div", { className: "ml-4", children: /* @__PURE__ */ jsx30(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${blockIndex}`) : null
6916
7106
  ) }) : null
6917
7107
  ]
6918
7108
  },
@@ -6947,7 +7137,7 @@ function CompactToolGroupBlock({
6947
7137
  level,
6948
7138
  customization
6949
7139
  }) {
6950
- const [expanded, setExpanded] = useState16(false);
7140
+ const [expanded, setExpanded] = useState17(false);
6951
7141
  const indentClass = level === 2 ? "ml-3" : "ml-4";
6952
7142
  const hasError = toolCalls.some(
6953
7143
  (tc) => tc.status === "error" || tc.status === "cancelled"
@@ -6962,12 +7152,12 @@ function CompactToolGroupBlock({
6962
7152
  });
6963
7153
  const tags = kind === "read_group" ? fileNames : toolCalls.map(getLoadedSkillName);
6964
7154
  const title = kind === "read_group" ? `\u8BFB\u53D6 ${toolCalls.length} \u4E2A\u6587\u4EF6` : toolCalls.length > 1 ? `\u52A0\u8F7D ${toolCalls.length} \u4E2A\u6280\u80FD` : "\u52A0\u8F7D\u6280\u80FD";
6965
- return /* @__PURE__ */ jsxs24("div", { className: cn(indentClass, "text-xs"), children: [
6966
- /* @__PURE__ */ jsxs24("div", { className: cn(
7155
+ return /* @__PURE__ */ jsxs25("div", { className: cn(indentClass, "text-xs"), children: [
7156
+ /* @__PURE__ */ jsxs25("div", { className: cn(
6967
7157
  "flex items-center gap-2 border-l-[3px] px-3 py-2",
6968
7158
  hasError ? "border-l-[hsl(var(--destructive))]" : "border-l-[hsl(var(--primary))]"
6969
7159
  ), children: [
6970
- /* @__PURE__ */ jsxs24(
7160
+ /* @__PURE__ */ jsxs25(
6971
7161
  "button",
6972
7162
  {
6973
7163
  type: "button",
@@ -6975,7 +7165,7 @@ function CompactToolGroupBlock({
6975
7165
  className: "flex min-w-0 shrink-0 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",
6976
7166
  "aria-expanded": expanded,
6977
7167
  children: [
6978
- /* @__PURE__ */ jsx29(
7168
+ /* @__PURE__ */ jsx30(
6979
7169
  ChevronRight5,
6980
7170
  {
6981
7171
  size: 11,
@@ -6985,18 +7175,18 @@ function CompactToolGroupBlock({
6985
7175
  )
6986
7176
  }
6987
7177
  ),
6988
- hasError ? /* @__PURE__ */ jsxs24("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]", children: [
6989
- /* @__PURE__ */ jsx29(AlertCircle, { size: 11 }),
6990
- /* @__PURE__ */ jsx29("span", { children: "\u5931\u8D25" })
6991
- ] }) : /* @__PURE__ */ jsxs24("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]", children: [
6992
- /* @__PURE__ */ jsx29(Check4, { size: 11 }),
6993
- /* @__PURE__ */ jsx29("span", { children: "\u5B8C\u6210" })
7178
+ hasError ? /* @__PURE__ */ jsxs25("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]", children: [
7179
+ /* @__PURE__ */ jsx30(AlertCircle, { size: 11 }),
7180
+ /* @__PURE__ */ jsx30("span", { children: "\u5931\u8D25" })
7181
+ ] }) : /* @__PURE__ */ jsxs25("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]", children: [
7182
+ /* @__PURE__ */ jsx30(Check4, { size: 11 }),
7183
+ /* @__PURE__ */ jsx30("span", { children: "\u5B8C\u6210" })
6994
7184
  ] }),
6995
- /* @__PURE__ */ jsx29("span", { className: "min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]", children: title })
7185
+ /* @__PURE__ */ jsx30("span", { className: "min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]", children: title })
6996
7186
  ]
6997
7187
  }
6998
7188
  ),
6999
- /* @__PURE__ */ jsx29("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: tags.map((tag, index) => /* @__PURE__ */ jsx29(
7189
+ /* @__PURE__ */ jsx30("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: tags.map((tag, index) => /* @__PURE__ */ jsx30(
7000
7190
  "span",
7001
7191
  {
7002
7192
  className: "max-w-40 truncate rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.35)] px-1.5 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -7005,12 +7195,12 @@ function CompactToolGroupBlock({
7005
7195
  },
7006
7196
  `${tag}-${index}`
7007
7197
  )) }),
7008
- reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null,
7009
- totalDurationMs > 0 ? /* @__PURE__ */ jsx29("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration2(totalDurationMs) }) : null
7198
+ reasoning ? /* @__PURE__ */ jsx30(ThinkingBadge, { reasoning, variant: "block" }) : null,
7199
+ totalDurationMs > 0 ? /* @__PURE__ */ jsx30("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration2(totalDurationMs) }) : null
7010
7200
  ] }),
7011
- expanded ? /* @__PURE__ */ jsx29("div", { className: "mt-1 flex flex-col gap-1", children: toolCalls.map((toolCall) => {
7201
+ expanded ? /* @__PURE__ */ jsx30("div", { className: "mt-1 flex flex-col gap-1", children: toolCalls.map((toolCall) => {
7012
7202
  const CustomToolCall = customization?.components?.ToolCall;
7013
- return CustomToolCall ? /* @__PURE__ */ jsx29(
7203
+ return CustomToolCall ? /* @__PURE__ */ jsx30(
7014
7204
  CustomToolCall,
7015
7205
  {
7016
7206
  toolCall,
@@ -7024,7 +7214,7 @@ function CompactToolGroupBlock({
7024
7214
  customization
7025
7215
  },
7026
7216
  toolCall.id
7027
- ) : /* @__PURE__ */ jsx29(
7217
+ ) : /* @__PURE__ */ jsx30(
7028
7218
  ToolCallBlock,
7029
7219
  {
7030
7220
  toolCall,
@@ -7055,8 +7245,8 @@ function AssistantMessageContent({
7055
7245
  if (!text && imageParts.length === 0 && fileParts.length === 0 && !isStreaming && !reasoning) {
7056
7246
  return null;
7057
7247
  }
7058
- return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-3", children: [
7059
- imageParts.length > 0 && /* @__PURE__ */ jsx29("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx29(
7248
+ return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-3", children: [
7249
+ imageParts.length > 0 && /* @__PURE__ */ jsx30("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx30(
7060
7250
  "img",
7061
7251
  {
7062
7252
  src: part.image_url.url,
@@ -7065,8 +7255,8 @@ function AssistantMessageContent({
7065
7255
  },
7066
7256
  part.image_url.url
7067
7257
  )) }),
7068
- /* @__PURE__ */ jsx29(MessageFileAttachmentList, { files: fileParts }),
7069
- text ? /* @__PURE__ */ jsx29(
7258
+ /* @__PURE__ */ jsx30(MessageFileAttachmentList, { files: fileParts }),
7259
+ text ? /* @__PURE__ */ jsx30(
7070
7260
  AssistantText,
7071
7261
  {
7072
7262
  text,
@@ -7076,8 +7266,8 @@ function AssistantMessageContent({
7076
7266
  className
7077
7267
  }
7078
7268
  ) : null,
7079
- !text && isStreaming && /* @__PURE__ */ jsx29("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7080
- !text && reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null
7269
+ !text && isStreaming && /* @__PURE__ */ jsx30("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7270
+ !text && reasoning ? /* @__PURE__ */ jsx30(ThinkingBadge, { reasoning, variant: "block" }) : null
7081
7271
  ] });
7082
7272
  }
7083
7273
  function AssistantText({
@@ -7097,8 +7287,8 @@ function AssistantText({
7097
7287
  () => ({ sessionId, messageId, sendMessage }),
7098
7288
  [sessionId, messageId, sendMessage]
7099
7289
  );
7100
- return /* @__PURE__ */ jsxs24("div", { className: cn("text-[15px] leading-8 text-[hsl(var(--foreground))]", className), children: [
7101
- /* @__PURE__ */ jsx29(CardContext.Provider, { value: cardCtx, children: /* @__PURE__ */ jsx29(
7290
+ return /* @__PURE__ */ jsxs25("div", { className: cn("text-[15px] leading-8 text-[hsl(var(--foreground))]", className), children: [
7291
+ /* @__PURE__ */ jsx30(CardContext.Provider, { value: cardCtx, children: /* @__PURE__ */ jsx30(
7102
7292
  MarkdownContent,
7103
7293
  {
7104
7294
  mode: "streaming",
@@ -7108,30 +7298,30 @@ function AssistantText({
7108
7298
  children: text
7109
7299
  }
7110
7300
  ) }),
7111
- reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning }) : null
7301
+ reasoning ? /* @__PURE__ */ jsx30(ThinkingBadge, { reasoning }) : null
7112
7302
  ] });
7113
7303
  }
7114
7304
  function MemoryRefsHint({ refs: rawRefs }) {
7115
7305
  const refs = Array.isArray(rawRefs) ? rawRefs : [];
7116
- const [expanded, setExpanded] = useState16(false);
7306
+ const [expanded, setExpanded] = useState17(false);
7117
7307
  const hasSkill = refs.some((r3) => r3.skill_name);
7118
7308
  const label = hasSkill ? "\u53C2\u8003\u4E86\u8BE5\u6280\u80FD\u7684\u5386\u53F2\u7ECF\u9A8C" : "\u53C2\u8003\u4E86\u5386\u53F2\u7ECF\u9A8C";
7119
- return /* @__PURE__ */ jsxs24("div", { className: "ml-4", children: [
7120
- /* @__PURE__ */ jsxs24(
7309
+ return /* @__PURE__ */ jsxs25("div", { className: "ml-4", children: [
7310
+ /* @__PURE__ */ jsxs25(
7121
7311
  "button",
7122
7312
  {
7123
7313
  type: "button",
7124
7314
  onClick: () => setExpanded(!expanded),
7125
7315
  className: "inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--primary)/0.25)] bg-[hsl(var(--primary)/0.08)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary))] transition-colors hover:bg-[hsl(var(--primary)/0.12)]",
7126
7316
  children: [
7127
- /* @__PURE__ */ jsx29(BookOpen, { size: 12 }),
7128
- /* @__PURE__ */ jsxs24("span", { children: [
7317
+ /* @__PURE__ */ jsx30(BookOpen, { size: 12 }),
7318
+ /* @__PURE__ */ jsxs25("span", { children: [
7129
7319
  label,
7130
7320
  "\uFF08",
7131
7321
  refs.length,
7132
7322
  "\uFF09"
7133
7323
  ] }),
7134
- /* @__PURE__ */ jsx29(
7324
+ /* @__PURE__ */ jsx30(
7135
7325
  ChevronRight5,
7136
7326
  {
7137
7327
  size: 10,
@@ -7141,13 +7331,13 @@ function MemoryRefsHint({ refs: rawRefs }) {
7141
7331
  ]
7142
7332
  }
7143
7333
  ),
7144
- expanded && /* @__PURE__ */ jsxs24("div", { className: "mt-1.5 flex flex-col gap-1 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.45)] px-3 py-2", children: [
7145
- refs.map((ref) => /* @__PURE__ */ jsxs24("div", { className: "flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]", children: [
7146
- /* @__PURE__ */ jsx29("span", { className: "mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]", children: "\u2022" }),
7147
- /* @__PURE__ */ jsx29("span", { className: "line-clamp-1", children: ref.content_preview }),
7148
- ref.skill_name && /* @__PURE__ */ jsx29("span", { className: "ml-auto shrink-0 rounded bg-[hsl(var(--primary)/0.12)] px-1.5 py-0.5 text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name })
7334
+ expanded && /* @__PURE__ */ jsxs25("div", { className: "mt-1.5 flex flex-col gap-1 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.45)] px-3 py-2", children: [
7335
+ refs.map((ref) => /* @__PURE__ */ jsxs25("div", { className: "flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]", children: [
7336
+ /* @__PURE__ */ jsx30("span", { className: "mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]", children: "\u2022" }),
7337
+ /* @__PURE__ */ jsx30("span", { className: "line-clamp-1", children: ref.content_preview }),
7338
+ ref.skill_name && /* @__PURE__ */ jsx30("span", { className: "ml-auto shrink-0 rounded bg-[hsl(var(--primary)/0.12)] px-1.5 py-0.5 text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name })
7149
7339
  ] }, ref.id)),
7150
- /* @__PURE__ */ jsx29(
7340
+ /* @__PURE__ */ jsx30(
7151
7341
  "a",
7152
7342
  {
7153
7343
  href: MEMORIES_ROUTE,
@@ -7160,9 +7350,9 @@ function MemoryRefsHint({ refs: rawRefs }) {
7160
7350
  }
7161
7351
 
7162
7352
  // src/react/components/chat/CompactionCard.tsx
7163
- import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight6, Loader2 as Loader25, Square as Square2, XCircle } from "lucide-react";
7164
- import { useState as useState17 } from "react";
7165
- import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
7353
+ import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight6, Loader2 as Loader25, Square as Square3, XCircle } from "lucide-react";
7354
+ import { useState as useState18 } from "react";
7355
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
7166
7356
  var PERCENT_FORMATTER = new Intl.NumberFormat("zh-CN", {
7167
7357
  style: "percent",
7168
7358
  maximumFractionDigits: 0
@@ -7221,7 +7411,7 @@ function CompactionCard({
7221
7411
  ...compaction,
7222
7412
  status: status ?? "completed"
7223
7413
  } : activeCompaction;
7224
- const [expanded, setExpanded] = useState17(false);
7414
+ const [expanded, setExpanded] = useState18(false);
7225
7415
  if (!source || !source.compaction_id) {
7226
7416
  return null;
7227
7417
  }
@@ -7232,9 +7422,9 @@ function CompactionCard({
7232
7422
  const hasSummary = typeof source.summary_full === "string" && source.summary_full.trim().length > 0 && !isGenericArchiveSummary(source.summary_full);
7233
7423
  const hasFailureReason = source.status === "failed" && Boolean(source.failure_reason);
7234
7424
  const canExpand = source.status === "completed" && (hasSummary || archivedToolCalls.length > 0) || hasFailureReason;
7235
- return /* @__PURE__ */ jsxs25("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: [
7236
- /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between gap-2", children: [
7237
- /* @__PURE__ */ jsxs25(
7425
+ return /* @__PURE__ */ jsxs26("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: [
7426
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between gap-2", children: [
7427
+ /* @__PURE__ */ jsxs26(
7238
7428
  "button",
7239
7429
  {
7240
7430
  type: "button",
@@ -7245,21 +7435,21 @@ function CompactionCard({
7245
7435
  ),
7246
7436
  "aria-expanded": expanded,
7247
7437
  children: [
7248
- canExpand ? expanded ? /* @__PURE__ */ jsx30(ChevronDown2, { size: 12, className: "shrink-0" }) : /* @__PURE__ */ jsx30(ChevronRight6, { size: 12, className: "shrink-0" }) : null,
7249
- /* @__PURE__ */ jsx30("span", { children: source.status === "streaming" ? /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1", children: [
7250
- /* @__PURE__ */ jsx30(Loader25, { size: 12, className: "animate-spin" }),
7438
+ canExpand ? expanded ? /* @__PURE__ */ jsx31(ChevronDown2, { size: 12, className: "shrink-0" }) : /* @__PURE__ */ jsx31(ChevronRight6, { size: 12, className: "shrink-0" }) : null,
7439
+ /* @__PURE__ */ jsx31("span", { children: source.status === "streaming" ? /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1", children: [
7440
+ /* @__PURE__ */ jsx31(Loader25, { size: 12, className: "animate-spin" }),
7251
7441
  "\u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587"
7252
- ] }) : source.status === "failed" ? /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1 text-rose-500/80", children: [
7253
- /* @__PURE__ */ jsx30(XCircle, { size: 12 }),
7442
+ ] }) : source.status === "failed" ? /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1 text-rose-500/80", children: [
7443
+ /* @__PURE__ */ jsx31(XCircle, { size: 12 }),
7254
7444
  "\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25"
7255
- ] }) : source.status === "interrupted" ? /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1 text-amber-500/80", children: [
7256
- /* @__PURE__ */ jsx30(Square2, { size: 11 }),
7445
+ ] }) : source.status === "interrupted" ? /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1 text-amber-500/80", children: [
7446
+ /* @__PURE__ */ jsx31(Square3, { size: 11 }),
7257
7447
  "\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88"
7258
7448
  ] }) : "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
7259
7449
  ]
7260
7450
  }
7261
7451
  ),
7262
- canCancel ? /* @__PURE__ */ jsx30(
7452
+ canCancel ? /* @__PURE__ */ jsx31(
7263
7453
  "button",
7264
7454
  {
7265
7455
  type: "button",
@@ -7269,13 +7459,13 @@ function CompactionCard({
7269
7459
  }
7270
7460
  ) : null
7271
7461
  ] }),
7272
- expanded ? /* @__PURE__ */ jsxs25("div", { className: "mt-1 max-w-3xl rounded-lg border border-[hsl(var(--border))]/70 bg-[hsl(var(--card))]/80 px-3 py-2 text-[11px] leading-relaxed shadow-sm", children: [
7273
- /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]", children: [
7274
- /* @__PURE__ */ jsxs25("span", { children: [
7462
+ expanded ? /* @__PURE__ */ jsxs26("div", { className: "mt-1 max-w-3xl rounded-lg border border-[hsl(var(--border))]/70 bg-[hsl(var(--card))]/80 px-3 py-2 text-[11px] leading-relaxed shadow-sm", children: [
7463
+ /* @__PURE__ */ jsxs26("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]", children: [
7464
+ /* @__PURE__ */ jsxs26("span", { children: [
7275
7465
  "#",
7276
7466
  shortId(source.compaction_id)
7277
7467
  ] }),
7278
- /* @__PURE__ */ jsxs25("span", { children: [
7468
+ /* @__PURE__ */ jsxs26("span", { children: [
7279
7469
  "\u8282\u7701 ",
7280
7470
  formatSavedRatio(source.saved_ratio),
7281
7471
  "\uFF08",
@@ -7285,31 +7475,31 @@ function CompactionCard({
7285
7475
  formatTokens(source.tokens_after),
7286
7476
  " token\uFF09"
7287
7477
  ] }),
7288
- /* @__PURE__ */ jsxs25("span", { children: [
7478
+ /* @__PURE__ */ jsxs26("span", { children: [
7289
7479
  "\u5F52\u6863 ",
7290
7480
  archivedCount,
7291
7481
  " \u4E2A\u5DE5\u5177\u7ED3\u679C"
7292
7482
  ] })
7293
7483
  ] }),
7294
- archivedToolCalls.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "mt-2 space-y-1.5", children: archivedToolCalls.map((item, index) => {
7484
+ archivedToolCalls.length > 0 ? /* @__PURE__ */ jsx31("div", { className: "mt-2 space-y-1.5", children: archivedToolCalls.map((item, index) => {
7295
7485
  const archivePath = getArchivePath(item, archivedFiles);
7296
- return /* @__PURE__ */ jsxs25(
7486
+ return /* @__PURE__ */ jsxs26(
7297
7487
  "div",
7298
7488
  {
7299
7489
  className: "rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/35 px-2 py-1.5",
7300
7490
  children: [
7301
- /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]", children: [
7302
- /* @__PURE__ */ jsx30("span", { className: "font-medium", children: getArchivedToolLabel(item) }),
7303
- item.tool_call_id ? /* @__PURE__ */ jsx30("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.tool_call_id }) : null
7491
+ /* @__PURE__ */ jsxs26("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]", children: [
7492
+ /* @__PURE__ */ jsx31("span", { className: "font-medium", children: getArchivedToolLabel(item) }),
7493
+ item.tool_call_id ? /* @__PURE__ */ jsx31("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.tool_call_id }) : null
7304
7494
  ] }),
7305
- archivePath ? /* @__PURE__ */ jsx30("div", { className: "mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: archivePath }) : null
7495
+ archivePath ? /* @__PURE__ */ jsx31("div", { className: "mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: archivePath }) : null
7306
7496
  ]
7307
7497
  },
7308
7498
  item.tool_call_id || item.entry_id || `${item.tool_name}-${index}`
7309
7499
  );
7310
7500
  }) }) : null,
7311
- hasSummary ? /* @__PURE__ */ jsx30("pre", { className: "mt-2 max-h-[360px] overflow-auto whitespace-pre-wrap rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/25 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-[hsl(var(--foreground))]", children: source.summary_full }) : null,
7312
- source.status === "failed" && source.failure_reason ? /* @__PURE__ */ jsxs25("div", { className: "mt-2 text-rose-500/90", children: [
7501
+ hasSummary ? /* @__PURE__ */ jsx31("pre", { className: "mt-2 max-h-[360px] overflow-auto whitespace-pre-wrap rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/25 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-[hsl(var(--foreground))]", children: source.summary_full }) : null,
7502
+ source.status === "failed" && source.failure_reason ? /* @__PURE__ */ jsxs26("div", { className: "mt-2 text-rose-500/90", children: [
7313
7503
  "\u5931\u8D25\u539F\u56E0\uFF1A",
7314
7504
  source.failure_reason
7315
7505
  ] }) : null
@@ -7320,7 +7510,7 @@ function CompactionCard({
7320
7510
  // src/react/components/chat/RenderErrorBoundary.tsx
7321
7511
  import { AlertTriangle as AlertTriangle2 } from "lucide-react";
7322
7512
  import { Component } from "react";
7323
- import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
7513
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7324
7514
  function getFirstComponentName(componentStack) {
7325
7515
  const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
7326
7516
  return match?.[1] ?? null;
@@ -7353,18 +7543,18 @@ var RenderErrorBoundary = class extends Component {
7353
7543
  return children;
7354
7544
  }
7355
7545
  const componentName = getFirstComponentName(componentStack);
7356
- return /* @__PURE__ */ jsx31("div", { className: "rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs26("div", { className: "flex items-start gap-2", children: [
7357
- /* @__PURE__ */ jsx31(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
7358
- /* @__PURE__ */ jsxs26("div", { className: "min-w-0 flex-1", children: [
7359
- /* @__PURE__ */ jsxs26("div", { className: "font-medium", children: [
7546
+ return /* @__PURE__ */ jsx32("div", { className: "rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs27("div", { className: "flex items-start gap-2", children: [
7547
+ /* @__PURE__ */ jsx32(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
7548
+ /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
7549
+ /* @__PURE__ */ jsxs27("div", { className: "font-medium", children: [
7360
7550
  label,
7361
7551
  "\u6E32\u67D3\u5931\u8D25"
7362
7552
  ] }),
7363
- /* @__PURE__ */ jsxs26("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
7553
+ /* @__PURE__ */ jsxs27("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
7364
7554
  componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
7365
7555
  error.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
7366
7556
  ] }),
7367
- details ? /* @__PURE__ */ jsx31("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
7557
+ details ? /* @__PURE__ */ jsx32("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
7368
7558
  ] })
7369
7559
  ] }) });
7370
7560
  }
@@ -7382,8 +7572,8 @@ import {
7382
7572
  TerminalSquare,
7383
7573
  WandSparkles
7384
7574
  } from "lucide-react";
7385
- import { useEffect as useEffect15, useMemo as useMemo16, useState as useState18 } from "react";
7386
- import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7575
+ import { useEffect as useEffect15, useMemo as useMemo16, useState as useState19 } from "react";
7576
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
7387
7577
  var EMPTY_EVENTS = [];
7388
7578
  function formatElapsedDuration(durationMs) {
7389
7579
  if (durationMs == null) return null;
@@ -7461,7 +7651,7 @@ function getTurnStartedAt(events) {
7461
7651
  return null;
7462
7652
  }
7463
7653
  function useElapsedDuration(startedAt, active) {
7464
- const [now, setNow] = useState18(() => Date.now());
7654
+ const [now, setNow] = useState19(() => Date.now());
7465
7655
  useEffect15(() => {
7466
7656
  if (!active || startedAt == null) {
7467
7657
  return;
@@ -7493,22 +7683,22 @@ function StickyStatusBar({
7493
7683
  }
7494
7684
  const elapsedLabel = formatElapsedDuration(elapsedDuration);
7495
7685
  const Icon = action.Icon;
7496
- return /* @__PURE__ */ jsxs27(
7686
+ return /* @__PURE__ */ jsxs28(
7497
7687
  "button",
7498
7688
  {
7499
7689
  type: "button",
7500
7690
  onClick: onJumpToLatest,
7501
7691
  className: "sticky top-0 z-20 mb-4 flex w-full items-center gap-3 rounded-2xl border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--background)/0.92)] px-4 py-3 text-left shadow-[0_12px_32px_-24px_hsl(var(--foreground)/0.6)] backdrop-blur",
7502
7692
  children: [
7503
- /* @__PURE__ */ jsx32("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]", children: /* @__PURE__ */ jsx32(Icon, { size: 18, className: Icon === LoaderCircle2 ? "animate-spin" : void 0 }) }),
7504
- /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
7505
- /* @__PURE__ */ jsx32("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: action.label }),
7506
- /* @__PURE__ */ jsxs27("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
7507
- elapsedLabel ? /* @__PURE__ */ jsxs27("span", { className: "font-mono", children: [
7693
+ /* @__PURE__ */ jsx33("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]", children: /* @__PURE__ */ jsx33(Icon, { size: 18, className: Icon === LoaderCircle2 ? "animate-spin" : void 0 }) }),
7694
+ /* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex-1", children: [
7695
+ /* @__PURE__ */ jsx33("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: action.label }),
7696
+ /* @__PURE__ */ jsxs28("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
7697
+ elapsedLabel ? /* @__PURE__ */ jsxs28("span", { className: "font-mono", children: [
7508
7698
  "\u5DF2\u6301\u7EED ",
7509
7699
  elapsedLabel
7510
7700
  ] }) : null,
7511
- /* @__PURE__ */ jsx32("span", { children: "\u70B9\u51FB\u8DF3\u5230\u6700\u65B0\u4F4D\u7F6E" })
7701
+ /* @__PURE__ */ jsx33("span", { children: "\u70B9\u51FB\u8DF3\u5230\u6700\u65B0\u4F4D\u7F6E" })
7512
7702
  ] })
7513
7703
  ] })
7514
7704
  ]
@@ -7517,7 +7707,7 @@ function StickyStatusBar({
7517
7707
  }
7518
7708
 
7519
7709
  // src/react/components/chat/TurnNavRail.tsx
7520
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
7710
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
7521
7711
  function TurnNavRail({
7522
7712
  items,
7523
7713
  activeTurnId,
@@ -7526,14 +7716,14 @@ function TurnNavRail({
7526
7716
  if (items.length < 2) {
7527
7717
  return null;
7528
7718
  }
7529
- return /* @__PURE__ */ jsx33(
7719
+ return /* @__PURE__ */ jsx34(
7530
7720
  "nav",
7531
7721
  {
7532
7722
  "aria-label": "\u56DE\u5408\u5BFC\u822A",
7533
7723
  className: "absolute right-2 top-4 z-10 hidden flex-col items-end gap-0.5 md:flex",
7534
7724
  children: items.map((item, index) => {
7535
7725
  const isActive = item.id === activeTurnId;
7536
- return /* @__PURE__ */ jsxs28(
7726
+ return /* @__PURE__ */ jsxs29(
7537
7727
  "button",
7538
7728
  {
7539
7729
  type: "button",
@@ -7541,8 +7731,8 @@ function TurnNavRail({
7541
7731
  "aria-current": isActive ? "true" : void 0,
7542
7732
  className: "group relative flex h-3.5 items-center",
7543
7733
  children: [
7544
- /* @__PURE__ */ jsx33("span", { className: "pointer-events-none absolute right-full mr-2 hidden max-w-48 truncate whitespace-nowrap rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] px-2.5 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-lg group-hover:block", children: item.title || `\u7B2C ${index + 1} \u8F6E` }),
7545
- /* @__PURE__ */ jsx33(
7734
+ /* @__PURE__ */ jsx34("span", { className: "pointer-events-none absolute right-full mr-2 hidden max-w-48 truncate whitespace-nowrap rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] px-2.5 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-lg group-hover:block", children: item.title || `\u7B2C ${index + 1} \u8F6E` }),
7735
+ /* @__PURE__ */ jsx34(
7546
7736
  "span",
7547
7737
  {
7548
7738
  className: cn(
@@ -7561,7 +7751,7 @@ function TurnNavRail({
7561
7751
  }
7562
7752
 
7563
7753
  // src/react/components/chat/MessageList.tsx
7564
- import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
7754
+ import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
7565
7755
  function parseModeChange(message) {
7566
7756
  if (message.kind !== "mode_change" || typeof message.content !== "string") {
7567
7757
  return null;
@@ -7576,15 +7766,12 @@ function parseModeChange(message) {
7576
7766
  return null;
7577
7767
  }
7578
7768
  function getPlanningDividerKind(message) {
7579
- if (message.kind === "planning_enter" || message.kind === "planning_exit") {
7580
- return message.kind;
7581
- }
7582
7769
  const modeChange = parseModeChange(message);
7583
7770
  if (modeChange?.to === "planning") {
7584
- return "planning_enter";
7771
+ return "enter";
7585
7772
  }
7586
7773
  if (modeChange?.from === "planning") {
7587
- return "planning_exit";
7774
+ return "exit";
7588
7775
  }
7589
7776
  return null;
7590
7777
  }
@@ -7759,7 +7946,7 @@ function MessageList({
7759
7946
  const containerRef = useRef11(null);
7760
7947
  const scrollContainerRef = useRef11(null);
7761
7948
  const frameRef = useRef11(null);
7762
- const [activeTurnId, setActiveTurnId] = useState19(lastTurnId);
7949
+ const [activeTurnId, setActiveTurnId] = useState20(lastTurnId);
7763
7950
  const layoutSignature = useMemo17(
7764
7951
  () => getMessagesMeasureSignature(messages),
7765
7952
  [messages]
@@ -7822,13 +8009,13 @@ function MessageList({
7822
8009
  const handleSelectTurn = useCallback12((turnId) => {
7823
8010
  document.getElementById(turnId)?.scrollIntoView({ behavior: "smooth", block: "start" });
7824
8011
  }, []);
7825
- return /* @__PURE__ */ jsxs29(
8012
+ return /* @__PURE__ */ jsxs30(
7826
8013
  "div",
7827
8014
  {
7828
8015
  ref: containerRef,
7829
8016
  className: `relative min-h-0 flex-1 ${customization?.classNames?.messageListRoot ?? ""}`,
7830
8017
  children: [
7831
- turnNavItems.length > 1 ? /* @__PURE__ */ jsx34(
8018
+ turnNavItems.length > 1 ? /* @__PURE__ */ jsx35(
7832
8019
  TurnNavRail,
7833
8020
  {
7834
8021
  items: turnNavItems,
@@ -7836,8 +8023,8 @@ function MessageList({
7836
8023
  onSelectTurn: handleSelectTurn
7837
8024
  }
7838
8025
  ) : null,
7839
- /* @__PURE__ */ jsxs29(StickToBottom, { className: "h-full overflow-y-hidden", resize: "smooth", children: [
7840
- /* @__PURE__ */ jsx34(StickToBottom.Content, { className: "px-5 py-6", children: /* @__PURE__ */ jsx34(
8026
+ /* @__PURE__ */ jsxs30(StickToBottom, { className: "h-full overflow-y-hidden", resize: "smooth", children: [
8027
+ /* @__PURE__ */ jsx35(StickToBottom.Content, { className: "px-5 py-6", children: /* @__PURE__ */ jsx35(
7841
8028
  MessageListContent,
7842
8029
  {
7843
8030
  askAnswers,
@@ -7854,7 +8041,7 @@ function MessageList({
7854
8041
  customization
7855
8042
  }
7856
8043
  ) }),
7857
- /* @__PURE__ */ jsx34(ScrollToBottomButton, {})
8044
+ /* @__PURE__ */ jsx35(ScrollToBottomButton, {})
7858
8045
  ] })
7859
8046
  ]
7860
8047
  }
@@ -7882,8 +8069,8 @@ function MessageListContent({
7882
8069
  }
7883
8070
  scrollToBottom();
7884
8071
  }, [lastTurnId, scrollToBottom]);
7885
- return /* @__PURE__ */ jsx34("div", { className: `mx-auto max-w-3xl ${customization?.classNames?.messageListContent ?? ""}`, children: /* @__PURE__ */ jsxs29("div", { className: `min-w-0 flex flex-col gap-8 ${customization?.classNames?.messageListInner ?? ""}`, children: [
7886
- stickyTurn ? /* @__PURE__ */ jsx34(
8072
+ return /* @__PURE__ */ jsx35("div", { className: `mx-auto max-w-3xl ${customization?.classNames?.messageListContent ?? ""}`, children: /* @__PURE__ */ jsxs30("div", { className: `min-w-0 flex flex-col gap-8 ${customization?.classNames?.messageListInner ?? ""}`, children: [
8073
+ stickyTurn ? /* @__PURE__ */ jsx35(
7887
8074
  StickyStatusBar,
7888
8075
  {
7889
8076
  sessionId,
@@ -7893,31 +8080,31 @@ function MessageListContent({
7893
8080
  onJumpToLatest: handleJumpToLatest
7894
8081
  }
7895
8082
  ) : null,
7896
- renderBlocks.length === 0 ? customization?.components?.EmptyState ? /* @__PURE__ */ jsx34(customization.components.EmptyState, {}) : /* @__PURE__ */ jsxs29("div", { className: `flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))] ${customization?.classNames?.emptyState ?? ""}`, children: [
7897
- /* @__PURE__ */ jsx34(MessageSquare, { size: 40, strokeWidth: 1.5 }),
7898
- /* @__PURE__ */ jsx34("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
7899
- /* @__PURE__ */ jsx34("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
8083
+ renderBlocks.length === 0 ? customization?.components?.EmptyState ? /* @__PURE__ */ jsx35(customization.components.EmptyState, {}) : /* @__PURE__ */ jsxs30("div", { className: `flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))] ${customization?.classNames?.emptyState ?? ""}`, children: [
8084
+ /* @__PURE__ */ jsx35(MessageSquare, { size: 40, strokeWidth: 1.5 }),
8085
+ /* @__PURE__ */ jsx35("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
8086
+ /* @__PURE__ */ jsx35("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
7900
8087
  ] }) : renderBlocks.map((block, blockIndex) => {
7901
8088
  if (block.type === "message") {
7902
- return /* @__PURE__ */ jsx34("div", { className: "msg-animate", children: isUserMessage(block.message) ? customization?.components?.UserMessage ? /* @__PURE__ */ jsx34(
8089
+ return /* @__PURE__ */ jsx35("div", { className: "msg-animate", children: isUserMessage(block.message) ? customization?.components?.UserMessage ? /* @__PURE__ */ jsx35(
7903
8090
  customization.components.UserMessage,
7904
8091
  {
7905
8092
  message: block.message,
7906
8093
  className: customization.classNames?.userMessage
7907
8094
  }
7908
- ) : /* @__PURE__ */ jsx34(
8095
+ ) : /* @__PURE__ */ jsx35(
7909
8096
  UserMessageBubble,
7910
8097
  {
7911
8098
  message: block.message,
7912
8099
  className: customization?.classNames?.userMessage
7913
8100
  }
7914
- ) : isErrorMessage(block.message) ? customization?.components?.ErrorMessage ? /* @__PURE__ */ jsx34(
8101
+ ) : isErrorMessage(block.message) ? customization?.components?.ErrorMessage ? /* @__PURE__ */ jsx35(
7915
8102
  customization.components.ErrorMessage,
7916
8103
  {
7917
8104
  message: block.message,
7918
8105
  className: customization.classNames?.errorMessage
7919
8106
  }
7920
- ) : /* @__PURE__ */ jsx34(
8107
+ ) : /* @__PURE__ */ jsx35(
7921
8108
  ErrorMessageBlock,
7922
8109
  {
7923
8110
  message: block.message,
@@ -7932,22 +8119,22 @@ function MessageListContent({
7932
8119
  (toolCall) => formatToolName(toolCall.name) === "ExitPlanMode" && toolCall.status !== "error" && toolCall.status !== "cancelled"
7933
8120
  )
7934
8121
  );
7935
- const isFollowedByPlanningExit = nextBlock?.type === "planning_divider" && nextBlock.kind === "planning_exit";
8122
+ const isFollowedByPlanningExit = nextBlock?.type === "planning_divider" && nextBlock.kind === "exit";
7936
8123
  const showPlanCard = (hasExitPlan || isFollowedByPlanningExit) && onConfirmPlan && sessionStatus === "waiting_for_input";
7937
- return /* @__PURE__ */ jsxs29(
8124
+ return /* @__PURE__ */ jsxs30(
7938
8125
  "div",
7939
8126
  {
7940
8127
  id: block.anchorId,
7941
8128
  "data-turn-id": block.anchorId,
7942
8129
  className: "msg-animate flex scroll-mt-6 flex-col gap-4",
7943
8130
  children: [
7944
- /* @__PURE__ */ jsx34(
8131
+ /* @__PURE__ */ jsx35(
7945
8132
  RenderErrorBoundary,
7946
8133
  {
7947
8134
  label: "\u52A9\u624B\u6D88\u606F",
7948
8135
  details: block.key,
7949
8136
  resetKey: getMessagesRenderSignature(block.messages),
7950
- children: customization?.components?.AssistantTurn ? /* @__PURE__ */ jsx34(
8137
+ children: customization?.components?.AssistantTurn ? /* @__PURE__ */ jsx35(
7951
8138
  customization.components.AssistantTurn,
7952
8139
  {
7953
8140
  turnKey: block.key,
@@ -7960,7 +8147,7 @@ function MessageListContent({
7960
8147
  sessionStatus,
7961
8148
  customization
7962
8149
  }
7963
- ) : /* @__PURE__ */ jsx34(
8150
+ ) : /* @__PURE__ */ jsx35(
7964
8151
  AssistantTurnBlock,
7965
8152
  {
7966
8153
  turnKey: block.key,
@@ -7976,13 +8163,13 @@ function MessageListContent({
7976
8163
  )
7977
8164
  }
7978
8165
  ),
7979
- showPlanCard ? /* @__PURE__ */ jsx34(
8166
+ showPlanCard ? /* @__PURE__ */ jsx35(
7980
8167
  RenderErrorBoundary,
7981
8168
  {
7982
8169
  label: "\u89C4\u5212\u6458\u8981",
7983
8170
  details: block.key,
7984
8171
  resetKey: `${sessionStatus ?? ""}:${layoutSignature}`,
7985
- children: /* @__PURE__ */ jsx34(
8172
+ children: /* @__PURE__ */ jsx35(
7986
8173
  PlanSummaryCard,
7987
8174
  {
7988
8175
  messages: extractLatestPlanMessages(messages),
@@ -7998,7 +8185,7 @@ function MessageListContent({
7998
8185
  );
7999
8186
  }
8000
8187
  if (block.type === "compaction") {
8001
- return /* @__PURE__ */ jsx34("div", { className: "msg-animate", children: /* @__PURE__ */ jsx34(
8188
+ return /* @__PURE__ */ jsx35("div", { className: "msg-animate", children: /* @__PURE__ */ jsx35(
8002
8189
  CompactionCard,
8003
8190
  {
8004
8191
  sessionId,
@@ -8007,41 +8194,41 @@ function MessageListContent({
8007
8194
  }
8008
8195
  ) }, block.key);
8009
8196
  }
8010
- return /* @__PURE__ */ jsx34(PlanningDivider, { kind: block.kind }, block.key);
8197
+ return /* @__PURE__ */ jsx35(PlanningDivider, { kind: block.kind }, block.key);
8011
8198
  }),
8012
- sessionStatus === "interrupted" && !hasInterruptedTurn ? /* @__PURE__ */ jsx34("div", { className: "flex", children: /* @__PURE__ */ jsx34("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
8199
+ sessionStatus === "interrupted" && !hasInterruptedTurn ? /* @__PURE__ */ jsx35("div", { className: "flex", children: /* @__PURE__ */ jsx35("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
8013
8200
  ] }) });
8014
8201
  }
8015
8202
  function ScrollToBottomButton() {
8016
8203
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
8017
8204
  if (isAtBottom) return null;
8018
- return /* @__PURE__ */ jsxs29(
8205
+ return /* @__PURE__ */ jsxs30(
8019
8206
  "button",
8020
8207
  {
8021
8208
  type: "button",
8022
8209
  onClick: () => scrollToBottom(),
8023
8210
  className: "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))]",
8024
8211
  children: [
8025
- /* @__PURE__ */ jsx34(ChevronDown3, { size: 14 }),
8026
- /* @__PURE__ */ jsx34("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
8212
+ /* @__PURE__ */ jsx35(ChevronDown3, { size: 14 }),
8213
+ /* @__PURE__ */ jsx35("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
8027
8214
  ]
8028
8215
  }
8029
8216
  );
8030
8217
  }
8031
8218
  function PlanningDivider({ kind }) {
8032
- const isEnter = kind === "planning_enter";
8033
- return /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-3 py-1", children: [
8034
- /* @__PURE__ */ jsx34("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
8035
- /* @__PURE__ */ jsxs29("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: [
8036
- /* @__PURE__ */ jsx34(Lightbulb2, { size: 12 }),
8037
- /* @__PURE__ */ jsx34("span", { children: isEnter ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
8219
+ const isEnter = kind === "enter";
8220
+ return /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-3 py-1", children: [
8221
+ /* @__PURE__ */ jsx35("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
8222
+ /* @__PURE__ */ jsxs30("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: [
8223
+ /* @__PURE__ */ jsx35(Lightbulb2, { size: 12 }),
8224
+ /* @__PURE__ */ jsx35("span", { children: isEnter ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
8038
8225
  ] }),
8039
- /* @__PURE__ */ jsx34("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
8226
+ /* @__PURE__ */ jsx35("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
8040
8227
  ] });
8041
8228
  }
8042
8229
 
8043
8230
  // src/react/components/chat/ChatView.tsx
8044
- import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
8231
+ import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
8045
8232
  function ChatView({
8046
8233
  sessionId,
8047
8234
  renderAttachments,
@@ -8080,13 +8267,13 @@ function ChatView({
8080
8267
  );
8081
8268
  const customization = { classNames, components, renderers };
8082
8269
  const SkillStatus = components?.SkillStatusBar;
8083
- return /* @__PURE__ */ jsxs30("div", { className: `flex min-h-0 flex-1 flex-col overflow-hidden ${classNames?.root ?? ""}`, children: [
8084
- isViewer && /* @__PURE__ */ jsxs30("div", { className: `flex items-center justify-center gap-2 border-b border-[hsl(var(--border))] bg-[hsl(var(--card))] py-2 text-xs text-[hsl(var(--muted-foreground))] ${classNames?.viewerBanner ?? ""}`, children: [
8085
- /* @__PURE__ */ jsx35(Eye, { size: 14 }),
8270
+ return /* @__PURE__ */ jsxs31("div", { className: `flex min-h-0 flex-1 flex-col overflow-hidden ${classNames?.root ?? ""}`, children: [
8271
+ isViewer && /* @__PURE__ */ jsxs31("div", { className: `flex items-center justify-center gap-2 border-b border-[hsl(var(--border))] bg-[hsl(var(--card))] py-2 text-xs text-[hsl(var(--muted-foreground))] ${classNames?.viewerBanner ?? ""}`, children: [
8272
+ /* @__PURE__ */ jsx36(Eye, { size: 14 }),
8086
8273
  "\u4F60\u6B63\u5728\u67E5\u770B\u5206\u4EAB\u7684\u4F1A\u8BDD\uFF08\u53EA\u8BFB\uFF09"
8087
8274
  ] }),
8088
- !isViewer && /* @__PURE__ */ jsx35(ConnectionBanner, {}),
8089
- /* @__PURE__ */ jsx35(
8275
+ !isViewer && /* @__PURE__ */ jsx36(ConnectionBanner, {}),
8276
+ /* @__PURE__ */ jsx36(
8090
8277
  MessageList,
8091
8278
  {
8092
8279
  sessionId,
@@ -8098,7 +8285,7 @@ function ChatView({
8098
8285
  },
8099
8286
  sessionId
8100
8287
  ),
8101
- !isViewer && /* @__PURE__ */ jsx35(
8288
+ !isViewer && /* @__PURE__ */ jsx36(
8102
8289
  ChatInput,
8103
8290
  {
8104
8291
  onSend: (msg, _targetSessionId, model) => send(msg, mode, void 0, { model: model || void 0 }),
@@ -8173,4 +8360,4 @@ use-stick-to-bottom/dist/StickToBottom.js:
8173
8360
  * Licensed under the MIT License. See License.txt in the project root for license information.
8174
8361
  *--------------------------------------------------------------------------------------------*)
8175
8362
  */
8176
- //# sourceMappingURL=chunk-ZGM3H24C.js.map
8363
+ //# sourceMappingURL=chunk-EV225FLR.js.map