@blade-hq/agent-kit 1.0.30 → 1.0.32

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 (42) hide show
  1. package/dist/{chunk-7OEW3P7R.js → chunk-E7FQV4IX.js} +56 -35
  2. package/dist/chunk-E7FQV4IX.js.map +1 -0
  3. package/dist/{chunk-6G5LCDOS.js → chunk-EGGBOVVF.js} +2 -2
  4. package/dist/{chunk-L4C2TY6S.js → chunk-F4Y7SUBC.js} +2 -2
  5. package/dist/{chunk-GAVSC2AW.js → chunk-FK4CV6R2.js} +46 -2
  6. package/dist/chunk-FK4CV6R2.js.map +1 -0
  7. package/dist/{chunk-WOKDHXS7.js → chunk-IDVNG3YJ.js} +37 -12
  8. package/dist/chunk-IDVNG3YJ.js.map +1 -0
  9. package/dist/{chunk-3XDPNPE3.js → chunk-IGMLETZX.js} +1001 -713
  10. package/dist/chunk-IGMLETZX.js.map +1 -0
  11. package/dist/{chunk-MJPVAXJN.js → chunk-OICNN4K4.js} +2 -2
  12. package/dist/client/index.js +1 -1
  13. package/dist/client/types/rest.d.ts +65 -136
  14. package/dist/react/api/published-apps.js +3 -3
  15. package/dist/react/api/sessions.js +2 -2
  16. package/dist/react/components/chat/FileDeliveryCards.d.ts +11 -0
  17. package/dist/react/components/chat/MessageList.d.ts +1 -0
  18. package/dist/react/components/chat/PlanningToggle.d.ts +7 -0
  19. package/dist/react/components/chat/ResourceIframe.d.ts +1 -1
  20. package/dist/react/components/chat/UserMessageBubble.d.ts +1 -1
  21. package/dist/react/components/chat/index.d.ts +1 -0
  22. package/dist/react/components/chat/index.js +7 -5
  23. package/dist/react/components/plan/index.js +4 -4
  24. package/dist/react/components/session/index.js +3 -3
  25. package/dist/react/components/workspace/index.js +61 -42
  26. package/dist/react/components/workspace/index.js.map +1 -1
  27. package/dist/react/hooks/use-model-preferences.d.ts +2 -0
  28. package/dist/react/index.d.ts +1 -1
  29. package/dist/react/index.js +9 -7
  30. package/dist/react/index.js.map +1 -1
  31. package/dist/react/lib/ui-meta.d.ts +1 -0
  32. package/dist/react/stores/ui-store.d.ts +5 -0
  33. package/dist/react/types/solution.d.ts +1 -0
  34. package/dist/style.css +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-3XDPNPE3.js.map +0 -1
  37. package/dist/chunk-7OEW3P7R.js.map +0 -1
  38. package/dist/chunk-GAVSC2AW.js.map +0 -1
  39. package/dist/chunk-WOKDHXS7.js.map +0 -1
  40. /package/dist/{chunk-6G5LCDOS.js.map → chunk-EGGBOVVF.js.map} +0 -0
  41. /package/dist/{chunk-L4C2TY6S.js.map → chunk-F4Y7SUBC.js.map} +0 -0
  42. /package/dist/{chunk-MJPVAXJN.js.map → chunk-OICNN4K4.js.map} +0 -0
@@ -13,10 +13,11 @@ import {
13
13
  getCodeLanguageFromFilename,
14
14
  parseAskUserQuestion,
15
15
  useHighlightedCodeHtml
16
- } from "./chunk-7OEW3P7R.js";
16
+ } from "./chunk-E7FQV4IX.js";
17
17
  import {
18
+ getSessionFilePath,
18
19
  resolveSessionFilePreviewTarget
19
- } from "./chunk-MJPVAXJN.js";
20
+ } from "./chunk-OICNN4K4.js";
20
21
  import {
21
22
  apiFetchResponse,
22
23
  buildMessageContent,
@@ -45,6 +46,8 @@ import {
45
46
  listDir,
46
47
  listSessionSkills,
47
48
  listSessions,
49
+ normalizeMessageContent,
50
+ resolveBrowserResourceUri,
48
51
  resolveEffectiveTheme,
49
52
  resourceBridgeDispatch,
50
53
  searchSkills,
@@ -60,7 +63,7 @@ import {
60
63
  useUiBridgeStore,
61
64
  useUiStore,
62
65
  writeFile
63
- } from "./chunk-WOKDHXS7.js";
66
+ } from "./chunk-IDVNG3YJ.js";
64
67
  import {
65
68
  registerBridgeIframe,
66
69
  tapBridgeEvent
@@ -69,7 +72,7 @@ import {
69
72
  ModelOption,
70
73
  ModelsConfig,
71
74
  ModelsResource
72
- } from "./chunk-GAVSC2AW.js";
75
+ } from "./chunk-FK4CV6R2.js";
73
76
  import {
74
77
  cn,
75
78
  copyToClipboard
@@ -81,7 +84,7 @@ import {
81
84
  // src/react/components/chat/ChatView.tsx
82
85
  import { CircleAlert as CircleAlert2 } from "lucide-react";
83
86
  import { Eye } from "lucide-react";
84
- import { useCallback as useCallback13, useMemo as useMemo19 } from "react";
87
+ import { useCallback as useCallback13, useMemo as useMemo20 } from "react";
85
88
 
86
89
  // src/react/hooks/use-chat.ts
87
90
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -190,7 +193,6 @@ import {
190
193
  Download,
191
194
  FlaskConical,
192
195
  Import,
193
- Lightbulb,
194
196
  Loader2 as Loader22,
195
197
  Mic,
196
198
  MicOff,
@@ -693,19 +695,20 @@ var MODEL_CONFIG_QUERY_KEY = ["model-config"];
693
695
  var PREFERRED_MODEL_QUERY_KEY = ["user-preference", PREFERRED_MODEL_KEY];
694
696
  var THINKING_ENABLED_QUERY_KEY = ["user-preference", THINKING_ENABLED_KEY];
695
697
  function useModelConfig() {
696
- const { data, isLoading } = useQuery({
698
+ const { data, isLoading, isFetching, refetch } = useQuery({
697
699
  queryKey: MODEL_CONFIG_QUERY_KEY,
698
700
  queryFn: () => getModelsConfig(),
699
- staleTime: 5 * 60 * 1e3,
700
- // 全局 QueryClient 默认关闭 refetchOnWindowFocus,这里显式开启,
701
- // 让模型列表在 staleTime 过期后能随窗口聚焦自动刷新
702
- refetchOnWindowFocus: true
701
+ staleTime: 0
703
702
  });
704
703
  return {
705
704
  models: data?.models ?? [],
706
705
  defaultModel: data?.default ?? "",
707
706
  thinkingAvailable: data?.thinkingAvailable ?? false,
708
- isLoading
707
+ isLoading,
708
+ isFetching,
709
+ refresh: async () => {
710
+ await refetch();
711
+ }
709
712
  };
710
713
  }
711
714
  function usePreferredModel() {
@@ -790,7 +793,7 @@ function ModelSelector({
790
793
  compact = false,
791
794
  placement = "bottom"
792
795
  }) {
793
- const { models, defaultModel, isLoading } = useModelConfig();
796
+ const { models, defaultModel, isLoading, isFetching, refresh } = useModelConfig();
794
797
  const [isOpen, setIsOpen] = useState3(false);
795
798
  const [query, setQuery] = useState3("");
796
799
  const rootRef = useRef4(null);
@@ -831,7 +834,10 @@ function ModelSelector({
831
834
  className: "flex min-w-0 items-center gap-1 rounded-lg px-2.5 py-[5px] text-[hsl(var(--muted-foreground))]",
832
835
  title: label,
833
836
  children: [
834
- isLoading ? /* @__PURE__ */ jsx2(Loader2, { size: 14, className: "animate-spin", "aria-hidden": "true" }) : /* @__PURE__ */ jsx2(Sparkles, { size: 14, "aria-hidden": "true" }),
837
+ isLoading ? /* @__PURE__ */ jsx2(Loader2, { size: 14, className: "animate-spin", "aria-hidden": "true" }) : compact ? null : (
838
+ // compact 用于「+」菜单的「模型」行,行首已有图标,触发器内不再重复。
839
+ /* @__PURE__ */ jsx2(Sparkles, { size: 14, "aria-hidden": "true" })
840
+ ),
835
841
  /* @__PURE__ */ jsx2("span", { className: `whitespace-nowrap text-xs ${compact ? "" : "max-w-[180px]"}`, children: label })
836
842
  ]
837
843
  }
@@ -843,11 +849,18 @@ function ModelSelector({
843
849
  {
844
850
  type: "button",
845
851
  disabled,
846
- onClick: () => setIsOpen((current) => !current),
852
+ onClick: () => {
853
+ if (isOpen) {
854
+ setIsOpen(false);
855
+ return;
856
+ }
857
+ setIsOpen(true);
858
+ void refresh();
859
+ },
847
860
  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",
848
861
  title: selectorTitle,
849
862
  children: [
850
- /* @__PURE__ */ jsx2(Sparkles, { size: 14, "aria-hidden": "true" }),
863
+ compact ? null : /* @__PURE__ */ jsx2(Sparkles, { size: 14, "aria-hidden": "true" }),
851
864
  /* @__PURE__ */ jsx2(
852
865
  "span",
853
866
  {
@@ -873,7 +886,16 @@ function ModelSelector({
873
886
  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))]"
874
887
  }
875
888
  ) }),
876
- /* @__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) => {
889
+ /* @__PURE__ */ jsx2("div", { className: "max-h-[220px] overflow-y-auto p-1", children: isFetching ? /* @__PURE__ */ jsxs(
890
+ "output",
891
+ {
892
+ className: "flex items-center justify-center gap-2 px-3 py-6 text-xs text-[hsl(var(--muted-foreground))]",
893
+ children: [
894
+ /* @__PURE__ */ jsx2(Loader2, { size: 14, className: "animate-spin", "aria-hidden": "true" }),
895
+ "\u6B63\u5728\u52A0\u8F7D\u5019\u9009\u6A21\u578B..."
896
+ ]
897
+ }
898
+ ) : 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) => {
877
899
  const inputLabel = formatInputModalities(model);
878
900
  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}`;
879
901
  return /* @__PURE__ */ jsxs(
@@ -2110,6 +2132,7 @@ function ThinkingToggle({ enabled, onChange, disabled }) {
2110
2132
  role: "switch",
2111
2133
  "aria-checked": enabled,
2112
2134
  "aria-label": enabled ? "\u5173\u95ED\u601D\u8003\u6A21\u5F0F" : "\u5F00\u542F\u601D\u8003\u6A21\u5F0F",
2135
+ title: "\u601D\u8003\u6A21\u5F0F\uFF1A\u8BA9\u6A21\u578B\u5728\u56DE\u7B54\u524D\u8FDB\u884C\u66F4\u6DF1\u5165\u7684\u63A8\u7406\uFF0C\u7ED3\u679C\u66F4\u4E25\u8C28\uFF0C\u4F46\u54CD\u5E94\u4F1A\u66F4\u6162",
2113
2136
  onClick: () => onChange(!enabled),
2114
2137
  disabled,
2115
2138
  className: "flex w-full items-center justify-between gap-3 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
@@ -2134,8 +2157,44 @@ function ThinkingToggle({ enabled, onChange, disabled }) {
2134
2157
  );
2135
2158
  }
2136
2159
 
2160
+ // src/react/components/chat/PlanningToggle.tsx
2161
+ import { Lightbulb } from "lucide-react";
2162
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2163
+ function PlanningToggle({ enabled, onChange, disabled }) {
2164
+ return /* @__PURE__ */ jsxs9(
2165
+ "button",
2166
+ {
2167
+ type: "button",
2168
+ role: "switch",
2169
+ "aria-checked": enabled,
2170
+ "aria-label": enabled ? "\u5173\u95ED\u89C4\u5212\u6A21\u5F0F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
2171
+ title: "\u89C4\u5212\u6A21\u5F0F\uFF1A\u5148\u68B3\u7406\u4EFB\u52A1\u6B65\u9AA4\u548C\u8BA1\u5212\u3001\u4E0E\u4F60\u786E\u8BA4\u540E\u518D\u6267\u884C\uFF0C\u9002\u5408\u8F83\u590D\u6742\u7684\u4EFB\u52A1",
2172
+ onClick: () => onChange(!enabled),
2173
+ disabled,
2174
+ className: "flex w-full items-center justify-between gap-3 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
2175
+ children: [
2176
+ /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-2", children: [
2177
+ /* @__PURE__ */ jsx10(Lightbulb, { size: 14, className: "text-[#F97316]", "aria-hidden": "true" }),
2178
+ "\u89C4\u5212\u6A21\u5F0F"
2179
+ ] }),
2180
+ /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-2", children: [
2181
+ /* @__PURE__ */ jsx10("span", { className: "text-[10px] text-[hsl(var(--muted-foreground))]", children: enabled ? "\u5F00" : "\u5173" }),
2182
+ /* @__PURE__ */ jsx10(
2183
+ "span",
2184
+ {
2185
+ className: `flex h-4 w-7 items-center rounded-full p-0.5 transition-colors ${enabled ? "justify-end bg-[hsl(var(--primary))]" : "justify-start bg-[hsl(var(--muted))]"}`,
2186
+ "aria-hidden": "true",
2187
+ children: /* @__PURE__ */ jsx10("span", { className: "h-3 w-3 rounded-full bg-[hsl(var(--background))] shadow-sm" })
2188
+ }
2189
+ )
2190
+ ] })
2191
+ ]
2192
+ }
2193
+ );
2194
+ }
2195
+
2137
2196
  // src/react/components/chat/ChatInput.tsx
2138
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2197
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2139
2198
  var DOUBLE_ESCAPE_MS = 450;
2140
2199
  function getEditorText(editor) {
2141
2200
  return editor?.getText({ blockSeparator: "\n" }) ?? "";
@@ -2301,38 +2360,39 @@ function ComposerFilePill({
2301
2360
  const isFailed = isFile && attachment.status === "failed";
2302
2361
  const isUploading = isFile && attachment.status === "uploading";
2303
2362
  const uploadPercent = isUploading && typeof attachment.uploadProgress === "number" ? Math.max(0, Math.min(100, Math.round(attachment.uploadProgress * 100))) : null;
2304
- return /* @__PURE__ */ jsxs9(
2363
+ return /* @__PURE__ */ jsxs10(
2305
2364
  "div",
2306
2365
  {
2307
2366
  className: `relative flex shrink-0 items-center gap-1.5 overflow-hidden 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))]"}`,
2308
2367
  children: [
2309
- uploadPercent !== null ? /* @__PURE__ */ jsx10(
2368
+ uploadPercent !== null ? /* @__PURE__ */ jsx11(
2310
2369
  "span",
2311
2370
  {
2312
2371
  className: "absolute inset-y-0 left-0 bg-[hsl(var(--primary))]/10 transition-[width]",
2313
2372
  style: { width: `${uploadPercent}%` }
2314
2373
  }
2315
2374
  ) : null,
2316
- isUploading ? /* @__PURE__ */ jsx10(
2375
+ isUploading ? /* @__PURE__ */ jsx11(
2317
2376
  Loader22,
2318
2377
  {
2319
2378
  size: 12,
2320
2379
  className: "relative z-10 shrink-0 animate-spin text-[hsl(var(--muted-foreground))]"
2321
2380
  }
2322
- ) : /* @__PURE__ */ jsx10(Icon, { size: 12, className: "relative z-10 shrink-0 text-[hsl(var(--muted-foreground))]" }),
2323
- /* @__PURE__ */ jsx10("span", { className: "relative z-10 max-w-32 truncate", children: attachment.name }),
2324
- uploadPercent !== null ? /* @__PURE__ */ jsxs9("span", { className: "relative z-10 font-mono text-[10px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
2381
+ ) : /* @__PURE__ */ jsx11(Icon, { size: 12, className: "relative z-10 shrink-0 text-[hsl(var(--muted-foreground))]" }),
2382
+ /* @__PURE__ */ jsx11("span", { className: "relative z-10 max-w-32 truncate", children: attachment.name }),
2383
+ uploadPercent !== null ? /* @__PURE__ */ jsxs10("span", { className: "relative z-10 font-mono text-[10px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
2325
2384
  uploadPercent,
2326
2385
  "%"
2327
2386
  ] }) : null,
2328
- /* @__PURE__ */ jsx10(
2387
+ /* @__PURE__ */ jsx11(
2329
2388
  "button",
2330
2389
  {
2331
2390
  type: "button",
2332
2391
  onClick: () => onRemove(attachment.id),
2333
2392
  "aria-label": `\u79FB\u9664 ${attachment.name}`,
2393
+ title: "\u79FB\u9664",
2334
2394
  className: "relative z-10 ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
2335
- children: /* @__PURE__ */ jsx10(X2, { size: 10 })
2395
+ children: /* @__PURE__ */ jsx11(X2, { size: 10 })
2336
2396
  }
2337
2397
  )
2338
2398
  ]
@@ -2451,7 +2511,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2451
2511
  setImportingId(null);
2452
2512
  }
2453
2513
  };
2454
- return /* @__PURE__ */ jsx10(
2514
+ return /* @__PURE__ */ jsx11(
2455
2515
  "div",
2456
2516
  {
2457
2517
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-4",
@@ -2459,44 +2519,44 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2459
2519
  onKeyDown: (e) => {
2460
2520
  if (e.key === "Escape") onClose();
2461
2521
  },
2462
- children: /* @__PURE__ */ jsxs9(
2522
+ children: /* @__PURE__ */ jsxs10(
2463
2523
  "div",
2464
2524
  {
2465
2525
  className: "w-full max-w-lg flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl",
2466
2526
  onClick: (e) => e.stopPropagation(),
2467
2527
  onKeyDown: (e) => e.stopPropagation(),
2468
2528
  children: [
2469
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
2470
- /* @__PURE__ */ jsx10("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
2471
- /* @__PURE__ */ jsx10(
2529
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
2530
+ /* @__PURE__ */ jsx11("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
2531
+ /* @__PURE__ */ jsx11(
2472
2532
  "button",
2473
2533
  {
2474
2534
  type: "button",
2475
2535
  onClick: onClose,
2476
2536
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2477
- children: /* @__PURE__ */ jsx10(X2, { size: 14 })
2537
+ children: /* @__PURE__ */ jsx11(X2, { size: 14 })
2478
2538
  }
2479
2539
  )
2480
2540
  ] }),
2481
- /* @__PURE__ */ jsxs9("div", { className: "px-5 py-4 space-y-3", children: [
2482
- /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
2483
- /* @__PURE__ */ jsxs9(
2541
+ /* @__PURE__ */ jsxs10("div", { className: "px-5 py-4 space-y-3", children: [
2542
+ /* @__PURE__ */ jsxs10("div", { className: "relative", children: [
2543
+ /* @__PURE__ */ jsxs10(
2484
2544
  "button",
2485
2545
  {
2486
2546
  type: "button",
2487
2547
  onClick: handleLoadSessions,
2488
2548
  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))]",
2489
2549
  children: [
2490
- /* @__PURE__ */ jsx10(Import, { size: 12 }),
2550
+ /* @__PURE__ */ jsx11(Import, { size: 12 }),
2491
2551
  "\u4ECE\u5176\u4ED6\u4F1A\u8BDD\u5BFC\u5165",
2492
- /* @__PURE__ */ jsx10(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
2552
+ /* @__PURE__ */ jsx11(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
2493
2553
  ]
2494
2554
  }
2495
2555
  ),
2496
- showSessionPicker && /* @__PURE__ */ jsx10("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__ */ jsxs9("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
2497
- /* @__PURE__ */ jsx10(Loader22, { size: 12, className: "animate-spin" }),
2556
+ showSessionPicker && /* @__PURE__ */ jsx11("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__ */ jsxs10("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
2557
+ /* @__PURE__ */ jsx11(Loader22, { size: 12, className: "animate-spin" }),
2498
2558
  "\u52A0\u8F7D\u4F1A\u8BDD\u5217\u8868\u2026"
2499
- ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx10("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__ */ jsxs9(
2559
+ ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx11("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__ */ jsxs10(
2500
2560
  "button",
2501
2561
  {
2502
2562
  type: "button",
@@ -2504,16 +2564,16 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2504
2564
  onClick: () => handleImportSession(s.id),
2505
2565
  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",
2506
2566
  children: [
2507
- importingId === s.id && /* @__PURE__ */ jsx10(Loader22, { size: 10, className: "shrink-0 animate-spin" }),
2508
- /* @__PURE__ */ jsx10("span", { className: "truncate", children: s.intent })
2567
+ importingId === s.id && /* @__PURE__ */ jsx11(Loader22, { size: 10, className: "shrink-0 animate-spin" }),
2568
+ /* @__PURE__ */ jsx11("span", { className: "truncate", children: s.intent })
2509
2569
  ]
2510
2570
  },
2511
2571
  s.id
2512
2572
  )) })
2513
2573
  ] }),
2514
- /* @__PURE__ */ jsxs9("div", { children: [
2515
- /* @__PURE__ */ jsx10("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
2516
- /* @__PURE__ */ jsx10(
2574
+ /* @__PURE__ */ jsxs10("div", { children: [
2575
+ /* @__PURE__ */ jsx11("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
2576
+ /* @__PURE__ */ jsx11(
2517
2577
  "input",
2518
2578
  {
2519
2579
  id: "ctx-label",
@@ -2524,13 +2584,13 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2524
2584
  }
2525
2585
  )
2526
2586
  ] }),
2527
- /* @__PURE__ */ jsxs9("div", { children: [
2528
- /* @__PURE__ */ jsx10("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
2529
- isImportProcessing && /* @__PURE__ */ jsxs9("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
2530
- /* @__PURE__ */ jsx10(Loader22, { size: 11, className: "animate-spin" }),
2587
+ /* @__PURE__ */ jsxs10("div", { children: [
2588
+ /* @__PURE__ */ jsx11("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
2589
+ isImportProcessing && /* @__PURE__ */ jsxs10("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
2590
+ /* @__PURE__ */ jsx11(Loader22, { size: 11, className: "animate-spin" }),
2531
2591
  "\u6B63\u5728\u5904\u7406\u5BFC\u5165\u5185\u5BB9\u5E76\u5199\u5165 workspace/context\uFF0C\u5B8C\u6210\u540E\u53EF\u70B9\u51FB\u201C\u786E\u5B9A\u201D"
2532
2592
  ] }),
2533
- /* @__PURE__ */ jsx10(
2593
+ /* @__PURE__ */ jsx11(
2534
2594
  "textarea",
2535
2595
  {
2536
2596
  id: "ctx-content",
@@ -2543,8 +2603,8 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2543
2603
  )
2544
2604
  ] })
2545
2605
  ] }),
2546
- /* @__PURE__ */ jsxs9("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
2547
- /* @__PURE__ */ jsx10(
2606
+ /* @__PURE__ */ jsxs10("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
2607
+ /* @__PURE__ */ jsx11(
2548
2608
  "button",
2549
2609
  {
2550
2610
  type: "button",
@@ -2553,7 +2613,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2553
2613
  children: "\u53D6\u6D88"
2554
2614
  }
2555
2615
  ),
2556
- /* @__PURE__ */ jsx10(
2616
+ /* @__PURE__ */ jsx11(
2557
2617
  "button",
2558
2618
  {
2559
2619
  type: "button",
@@ -2584,19 +2644,19 @@ function ComposerContextPill({
2584
2644
  }) {
2585
2645
  const [showDetail, setShowDetail] = useState8(false);
2586
2646
  const tokenK = formatTokenK(content);
2587
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
2588
- /* @__PURE__ */ jsxs9("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: [
2589
- imageUrl ? /* @__PURE__ */ jsx10(
2647
+ return /* @__PURE__ */ jsxs10(Fragment2, { children: [
2648
+ /* @__PURE__ */ jsxs10("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: [
2649
+ imageUrl ? /* @__PURE__ */ jsx11(
2590
2650
  "button",
2591
2651
  {
2592
2652
  type: "button",
2593
2653
  onClick: () => setShowDetail(true),
2594
2654
  className: "h-6 w-6 overflow-hidden rounded-md border border-[hsl(var(--border))] bg-white",
2595
2655
  title: "\u67E5\u770B\u9009\u4E2D\u533A\u57DF\u622A\u56FE",
2596
- children: /* @__PURE__ */ jsx10("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "h-full w-full object-cover" })
2656
+ children: /* @__PURE__ */ jsx11("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "h-full w-full object-cover" })
2597
2657
  }
2598
2658
  ) : null,
2599
- /* @__PURE__ */ jsx10(
2659
+ /* @__PURE__ */ jsx11(
2600
2660
  "button",
2601
2661
  {
2602
2662
  type: "button",
@@ -2606,7 +2666,7 @@ function ComposerContextPill({
2606
2666
  children: label
2607
2667
  }
2608
2668
  ),
2609
- /* @__PURE__ */ jsx10(
2669
+ /* @__PURE__ */ jsx11(
2610
2670
  "span",
2611
2671
  {
2612
2672
  className: "shrink-0 rounded bg-[hsl(var(--background))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -2614,18 +2674,19 @@ function ComposerContextPill({
2614
2674
  children: tokenK
2615
2675
  }
2616
2676
  ),
2617
- /* @__PURE__ */ jsx10(
2677
+ /* @__PURE__ */ jsx11(
2618
2678
  "button",
2619
2679
  {
2620
2680
  type: "button",
2621
2681
  onClick: () => onRemove(id),
2622
2682
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${label}`,
2683
+ title: "\u79FB\u9664",
2623
2684
  className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
2624
- children: /* @__PURE__ */ jsx10(X2, { size: 10 })
2685
+ children: /* @__PURE__ */ jsx11(X2, { size: 10 })
2625
2686
  }
2626
2687
  )
2627
2688
  ] }),
2628
- showDetail && /* @__PURE__ */ jsx10(
2689
+ showDetail && /* @__PURE__ */ jsx11(
2629
2690
  "div",
2630
2691
  {
2631
2692
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-6",
@@ -2633,31 +2694,31 @@ function ComposerContextPill({
2633
2694
  onKeyDown: (e) => {
2634
2695
  if (e.key === "Escape") setShowDetail(false);
2635
2696
  },
2636
- children: /* @__PURE__ */ jsxs9(
2697
+ children: /* @__PURE__ */ jsxs10(
2637
2698
  "div",
2638
2699
  {
2639
2700
  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",
2640
2701
  onClick: (e) => e.stopPropagation(),
2641
2702
  onKeyDown: (e) => e.stopPropagation(),
2642
2703
  children: [
2643
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
2644
- /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
2645
- /* @__PURE__ */ jsx10("h4", { className: "truncate text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
2646
- imageUrl ? /* @__PURE__ */ jsx10("p", { className: "mt-0.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u9644\u52A0\u9009\u4E2D\u533A\u57DF\u622A\u56FE\uFF0C\u975E\u591A\u6A21\u6001\u6A21\u578B\u4F1A\u81EA\u52A8\u5FFD\u7565\u56FE\u7247\u3002" }) : null
2704
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
2705
+ /* @__PURE__ */ jsxs10("div", { className: "min-w-0", children: [
2706
+ /* @__PURE__ */ jsx11("h4", { className: "truncate text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
2707
+ imageUrl ? /* @__PURE__ */ jsx11("p", { className: "mt-0.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u9644\u52A0\u9009\u4E2D\u533A\u57DF\u622A\u56FE\uFF0C\u975E\u591A\u6A21\u6001\u6A21\u578B\u4F1A\u81EA\u52A8\u5FFD\u7565\u56FE\u7247\u3002" }) : null
2647
2708
  ] }),
2648
- /* @__PURE__ */ jsx10(
2709
+ /* @__PURE__ */ jsx11(
2649
2710
  "button",
2650
2711
  {
2651
2712
  type: "button",
2652
2713
  onClick: () => setShowDetail(false),
2653
2714
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2654
- children: /* @__PURE__ */ jsx10(X2, { size: 14 })
2715
+ children: /* @__PURE__ */ jsx11(X2, { size: 14 })
2655
2716
  }
2656
2717
  )
2657
2718
  ] }),
2658
- /* @__PURE__ */ jsxs9("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: [
2659
- imageUrl ? /* @__PURE__ */ jsx10("div", { className: "mb-4 rounded-xl border border-[hsl(var(--border))] bg-white p-2", children: /* @__PURE__ */ jsx10("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "max-h-72 max-w-full rounded-lg object-contain" }) }) : null,
2660
- /* @__PURE__ */ jsx10("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content })
2719
+ /* @__PURE__ */ jsxs10("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: [
2720
+ imageUrl ? /* @__PURE__ */ jsx11("div", { className: "mb-4 rounded-xl border border-[hsl(var(--border))] bg-white p-2", children: /* @__PURE__ */ jsx11("img", { src: imageUrl, alt: "\u9009\u4E2D\u533A\u57DF\u622A\u56FE", className: "max-h-72 max-w-full rounded-lg object-contain" }) }) : null,
2721
+ /* @__PURE__ */ jsx11("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content })
2661
2722
  ] })
2662
2723
  ]
2663
2724
  }
@@ -2799,24 +2860,25 @@ function HelpPopover({
2799
2860
  composerHint
2800
2861
  }) {
2801
2862
  const [hovered, setHovered] = useState8(false);
2802
- return /* @__PURE__ */ jsxs9(
2863
+ return /* @__PURE__ */ jsxs10(
2803
2864
  "div",
2804
2865
  {
2805
2866
  className: "group/help relative",
2806
2867
  onMouseEnter: () => setHovered(true),
2807
2868
  onFocusCapture: () => setHovered(true),
2808
2869
  children: [
2809
- /* @__PURE__ */ jsx10(
2870
+ /* @__PURE__ */ jsx11(
2810
2871
  "button",
2811
2872
  {
2812
2873
  type: "button",
2813
2874
  "aria-label": "\u67E5\u770B\u8F93\u5165\u63D0\u793A",
2814
- 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))]",
2815
- children: /* @__PURE__ */ jsx10(CircleHelp, { size: 13 })
2875
+ title: "\u8F93\u5165\u63D0\u793A",
2876
+ className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2877
+ children: /* @__PURE__ */ jsx11(CircleHelp, { size: 19 })
2816
2878
  }
2817
2879
  ),
2818
- /* @__PURE__ */ jsx10("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__ */ jsxs9("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: [
2819
- activeSessionId && hovered ? /* @__PURE__ */ jsx10("div", { className: "mb-2 border-b border-[hsl(var(--border))] pb-2", children: /* @__PURE__ */ jsx10(
2880
+ /* @__PURE__ */ jsx11("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__ */ jsxs10("div", { className: "min-w-64 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3.5 text-left text-[12px] leading-5 text-[hsl(var(--popover-foreground))] shadow-lg", children: [
2881
+ activeSessionId && hovered ? /* @__PURE__ */ jsx11("div", { className: "mb-2.5 border-b border-[hsl(var(--border))] pb-2.5", children: /* @__PURE__ */ jsx11(
2820
2882
  SkillStatusBarComponent,
2821
2883
  {
2822
2884
  sessionId: activeSessionId,
@@ -2827,11 +2889,16 @@ function HelpPopover({
2827
2889
  innerClassName: skillStatusBarInnerClassName
2828
2890
  }
2829
2891
  ) }) : null,
2830
- /* @__PURE__ */ jsxs9("div", { className: "space-y-0.5", children: [
2831
- /* @__PURE__ */ jsx10("div", { children: "Shift+Enter \u6362\u884C" }),
2832
- /* @__PURE__ */ jsx10("div", { children: "/ \u8C03\u7528\u6280\u80FD" }),
2833
- /* @__PURE__ */ jsx10("div", { children: "@ \u5F15\u7528\u6587\u4EF6" }),
2834
- composerHint && /* @__PURE__ */ jsx10("div", { children: composerHint })
2892
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-1.5", children: [
2893
+ [
2894
+ { keys: "Shift + Enter", label: "\u6362\u884C" },
2895
+ { keys: "/", label: "\u8C03\u7528\u6280\u80FD" },
2896
+ { keys: "@", label: "\u5F15\u7528\u6587\u4EF6" }
2897
+ ].map((item) => /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2.5", children: [
2898
+ /* @__PURE__ */ jsx11("kbd", { className: "inline-flex h-[20px] min-w-[20px] shrink-0 items-center justify-center rounded-[5px] border border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] px-1.5 font-mono text-[11px] leading-none text-[hsl(var(--muted-foreground))]", children: item.keys }),
2899
+ /* @__PURE__ */ jsx11("span", { className: "text-[hsl(var(--foreground))]", children: item.label })
2900
+ ] }, item.keys)),
2901
+ composerHint && /* @__PURE__ */ jsx11("div", { className: "pt-0.5 text-[hsl(var(--muted-foreground))]", children: composerHint })
2835
2902
  ] })
2836
2903
  ] }) })
2837
2904
  ]
@@ -3088,7 +3155,7 @@ function ChatInput({
3088
3155
  if (!container || !root) return;
3089
3156
  updateSuggestionPosition(container, props.clientRect);
3090
3157
  root.render(
3091
- /* @__PURE__ */ jsx10(
3158
+ /* @__PURE__ */ jsx11(
3092
3159
  FileCompletionMenu,
3093
3160
  {
3094
3161
  ref: (instance) => {
@@ -3165,7 +3232,7 @@ function ChatInput({
3165
3232
  if (!container || !root) return;
3166
3233
  updateSuggestionPosition(container, props.clientRect);
3167
3234
  root.render(
3168
- /* @__PURE__ */ jsx10(
3235
+ /* @__PURE__ */ jsx11(
3169
3236
  SkillCompletionMenu,
3170
3237
  {
3171
3238
  ref: (instance) => {
@@ -3220,7 +3287,7 @@ function ChatInput({
3220
3287
  "aria-label": resolvedInputLabel,
3221
3288
  "data-testid": "chat-message-input",
3222
3289
  "data-blade-input-label": resolvedInputLabel,
3223
- class: "min-h-[40px] max-h-[240px] overflow-y-auto px-4 py-3 text-sm leading-relaxed text-[hsl(var(--foreground))] focus:outline-none [&_.file-mention-pill]:inline-flex [&_.file-mention-pill]:items-center [&_.file-mention-pill]:rounded-full [&_.file-mention-pill]:bg-[hsl(var(--accent))] [&_.file-mention-pill]:px-2 [&_.file-mention-pill]:py-0.5 [&_.file-mention-pill]:font-medium [&_.file-mention-pill]:text-[hsl(var(--primary))] [&_.file-mention-pill]:select-none [&_.file-mention-pill]:whitespace-nowrap [&_.skill-mention-pill]:inline-flex [&_.skill-mention-pill]:items-center [&_.skill-mention-pill]:rounded-full [&_.skill-mention-pill]:bg-[hsl(var(--primary)/0.15)] [&_.skill-mention-pill]:px-2 [&_.skill-mention-pill]:py-0.5 [&_.skill-mention-pill]:font-medium [&_.skill-mention-pill]:text-[hsl(var(--primary))] [&_.skill-mention-pill]:select-none [&_.skill-mention-pill]:whitespace-nowrap [&_p:first-child]:mt-0 [&_p:last-child]:mb-0"
3290
+ class: "min-h-[34px] max-h-[240px] overflow-y-auto px-4 py-2 text-sm leading-relaxed text-[hsl(var(--foreground))] focus:outline-none [&_.file-mention-pill]:inline-flex [&_.file-mention-pill]:items-center [&_.file-mention-pill]:rounded-full [&_.file-mention-pill]:bg-[hsl(var(--accent))] [&_.file-mention-pill]:px-2 [&_.file-mention-pill]:py-0.5 [&_.file-mention-pill]:font-medium [&_.file-mention-pill]:text-[hsl(var(--primary))] [&_.file-mention-pill]:select-none [&_.file-mention-pill]:whitespace-nowrap [&_.skill-mention-pill]:inline-flex [&_.skill-mention-pill]:items-center [&_.skill-mention-pill]:rounded-full [&_.skill-mention-pill]:bg-[hsl(var(--primary)/0.15)] [&_.skill-mention-pill]:px-2 [&_.skill-mention-pill]:py-0.5 [&_.skill-mention-pill]:font-medium [&_.skill-mention-pill]:text-[hsl(var(--primary))] [&_.skill-mention-pill]:select-none [&_.skill-mention-pill]:whitespace-nowrap [&_p:first-child]:mt-0 [&_p:last-child]:mb-0"
3224
3291
  },
3225
3292
  handleDOMEvents: {
3226
3293
  focus: () => {
@@ -3590,11 +3657,11 @@ function ChatInput({
3590
3657
  );
3591
3658
  const hasValidAttachments = composerAttachments.some((attachment) => attachment.status !== "failed");
3592
3659
  const isSendDisabled = connectionStatus !== "connected" || isModelLoading || !hasAvailableModel || isSubmitting || hasUploadingFiles || !input.trim() && !hasValidAttachments && !hasRenderedAttachments && !hasPendingContexts;
3593
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
3594
- /* @__PURE__ */ jsx10("div", { className: `bg-[hsl(var(--background))] px-5 py-3 ${className ?? ""}`, children: /* @__PURE__ */ jsxs9("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
3595
- activeSessionId ? /* @__PURE__ */ jsx10(BackgroundTasksPill, { sessionId: activeSessionId }) : null,
3596
- !isModelLoading && !hasAvailableModel ? /* @__PURE__ */ jsx10("div", { className: "mb-2 rounded-lg border border-[hsl(var(--destructive))]/30 bg-[hsl(var(--destructive))]/8 px-3 py-2 text-xs text-[hsl(var(--destructive))]", children: "\u6CA1\u6709\u53EF\u7528\u6A21\u578B\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u670D\u52A1\u914D\u7F6E" }) : null,
3597
- /* @__PURE__ */ jsx10(
3660
+ return /* @__PURE__ */ jsxs10(Fragment2, { children: [
3661
+ /* @__PURE__ */ jsx11("div", { className: `bg-[hsl(var(--background))] px-5 py-3 ${className ?? ""}`, children: /* @__PURE__ */ jsxs10("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
3662
+ activeSessionId ? /* @__PURE__ */ jsx11(BackgroundTasksPill, { sessionId: activeSessionId }) : null,
3663
+ !isModelLoading && !hasAvailableModel ? /* @__PURE__ */ jsx11("div", { className: "mb-2 rounded-lg border border-[hsl(var(--destructive))]/30 bg-[hsl(var(--destructive))]/8 px-3 py-2 text-xs text-[hsl(var(--destructive))]", children: "\u6CA1\u6709\u53EF\u7528\u6A21\u578B\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u670D\u52A1\u914D\u7F6E" }) : null,
3664
+ /* @__PURE__ */ jsx11(
3598
3665
  "div",
3599
3666
  {
3600
3667
  className: "relative",
@@ -3628,19 +3695,19 @@ function ChatInput({
3628
3695
  if (files.length > 0) void stableAppendFiles(files);
3629
3696
  });
3630
3697
  },
3631
- children: /* @__PURE__ */ jsxs9(
3698
+ children: /* @__PURE__ */ jsxs10(
3632
3699
  "div",
3633
3700
  {
3634
- 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))]"}`,
3701
+ className: `overflow-visible rounded-[22px] 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))]"}`,
3635
3702
  children: [
3636
- dragging && /* @__PURE__ */ jsx10("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__ */ jsx10("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" }) }),
3637
- composerAttachments.length > 0 && /* @__PURE__ */ jsxs9("div", { className: "flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2", children: [
3638
- imageAttachments.length > 0 && /* @__PURE__ */ jsx10("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs9(
3703
+ dragging && /* @__PURE__ */ jsx11("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__ */ jsx11("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" }) }),
3704
+ composerAttachments.length > 0 && /* @__PURE__ */ jsxs10("div", { className: "flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2", children: [
3705
+ imageAttachments.length > 0 && /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs10(
3639
3706
  "div",
3640
3707
  {
3641
3708
  className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
3642
3709
  children: [
3643
- /* @__PURE__ */ jsx10(
3710
+ /* @__PURE__ */ jsx11(
3644
3711
  "img",
3645
3712
  {
3646
3713
  src: getImagePreviewUrl(attachment, activeSessionId, localImageUrls),
@@ -3648,21 +3715,22 @@ function ChatInput({
3648
3715
  className: "h-24 w-full object-cover"
3649
3716
  }
3650
3717
  ),
3651
- /* @__PURE__ */ jsx10(
3718
+ /* @__PURE__ */ jsx11(
3652
3719
  "button",
3653
3720
  {
3654
3721
  type: "button",
3655
3722
  onClick: () => removeAttachment(attachment.id),
3656
3723
  "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
3724
+ title: "\u79FB\u9664",
3657
3725
  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))]",
3658
- children: /* @__PURE__ */ jsx10(X2, { size: 12 })
3726
+ children: /* @__PURE__ */ jsx11(X2, { size: 12 })
3659
3727
  }
3660
3728
  )
3661
3729
  ]
3662
3730
  },
3663
3731
  attachment.id
3664
3732
  )) }),
3665
- fileAttachments.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx10(
3733
+ fileAttachments.length > 0 && /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx11(
3666
3734
  ComposerFilePill,
3667
3735
  {
3668
3736
  attachment,
@@ -3671,8 +3739,8 @@ function ChatInput({
3671
3739
  attachment.id
3672
3740
  )) })
3673
3741
  ] }),
3674
- hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2", children: [
3675
- pendingContexts?.map((context) => /* @__PURE__ */ jsx10(
3742
+ hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2", children: [
3743
+ pendingContexts?.map((context) => /* @__PURE__ */ jsx11(
3676
3744
  ComposerContextPill,
3677
3745
  {
3678
3746
  id: context.id,
@@ -3688,18 +3756,18 @@ function ChatInput({
3688
3756
  },
3689
3757
  context.id
3690
3758
  )),
3691
- isSkillEditor && /* @__PURE__ */ jsx10(
3759
+ isSkillEditor && /* @__PURE__ */ jsx11(
3692
3760
  "button",
3693
3761
  {
3694
3762
  type: "button",
3695
3763
  onClick: () => setShowAddContext(true),
3696
3764
  title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
3697
3765
  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))]",
3698
- children: /* @__PURE__ */ jsx10(Plus, { size: 12 })
3766
+ children: /* @__PURE__ */ jsx11(Plus, { size: 12 })
3699
3767
  }
3700
3768
  )
3701
3769
  ] }) : null,
3702
- showAddContext && activeSessionId && /* @__PURE__ */ jsx10(
3770
+ showAddContext && activeSessionId && /* @__PURE__ */ jsx11(
3703
3771
  AddContextDialog,
3704
3772
  {
3705
3773
  sessionId: activeSessionId,
@@ -3711,15 +3779,15 @@ function ChatInput({
3711
3779
  }
3712
3780
  }
3713
3781
  ),
3714
- attachments ? /* @__PURE__ */ jsx10("div", { className: "border-b border-[hsl(var(--border))] px-3 py-3", children: attachments }) : null,
3715
- slotAboveTextarea ? /* @__PURE__ */ jsx10("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2", children: slotAboveTextarea }) : null,
3716
- /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
3717
- input.length === 0 && /* @__PURE__ */ jsx10("div", { className: "pointer-events-none absolute left-4 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground))]", children: placeholder }),
3718
- /* @__PURE__ */ jsx10(EditorContent, { editor })
3782
+ attachments ? /* @__PURE__ */ jsx11("div", { className: "border-b border-[hsl(var(--border))] px-3 py-3", children: attachments }) : null,
3783
+ slotAboveTextarea ? /* @__PURE__ */ jsx11("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2", children: slotAboveTextarea }) : null,
3784
+ /* @__PURE__ */ jsxs10("div", { className: "relative", children: [
3785
+ input.length === 0 && /* @__PURE__ */ jsx11("div", { className: "pointer-events-none absolute left-4 top-2 text-sm leading-relaxed text-[hsl(var(--muted-foreground)/0.6)]", children: placeholder }),
3786
+ /* @__PURE__ */ jsx11(EditorContent, { editor })
3719
3787
  ] }),
3720
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-t border-[hsl(var(--border))] px-3 py-1.5", children: [
3721
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
3722
- /* @__PURE__ */ jsx10(
3788
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between px-3 pb-2.5 pt-1", children: [
3789
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
3790
+ /* @__PURE__ */ jsx11(
3723
3791
  "input",
3724
3792
  {
3725
3793
  ref: fileInputRef,
@@ -3735,7 +3803,7 @@ function ChatInput({
3735
3803
  className: "hidden"
3736
3804
  }
3737
3805
  ),
3738
- /* @__PURE__ */ jsx10(
3806
+ /* @__PURE__ */ jsx11(
3739
3807
  "input",
3740
3808
  {
3741
3809
  ref: folderInputRef,
@@ -3751,18 +3819,18 @@ function ChatInput({
3751
3819
  ...{ webkitdirectory: "" }
3752
3820
  }
3753
3821
  ),
3754
- /* @__PURE__ */ jsxs9("details", { ref: actionMenuRef, className: "group relative", children: [
3755
- /* @__PURE__ */ jsx10(
3822
+ /* @__PURE__ */ jsxs10("details", { ref: actionMenuRef, className: "group relative", children: [
3823
+ /* @__PURE__ */ jsx11(
3756
3824
  "summary",
3757
3825
  {
3758
3826
  "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
3759
3827
  title: "\u6DFB\u52A0\u5185\u5BB9",
3760
- 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",
3761
- children: /* @__PURE__ */ jsx10(Plus, { size: 14 })
3828
+ className: "flex h-9 w-9 shrink-0 cursor-pointer list-none items-center justify-center rounded-full 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",
3829
+ children: /* @__PURE__ */ jsx11(Plus, { size: 14 })
3762
3830
  }
3763
3831
  ),
3764
- /* @__PURE__ */ jsxs9("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: [
3765
- /* @__PURE__ */ jsxs9(
3832
+ /* @__PURE__ */ jsxs10("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: [
3833
+ /* @__PURE__ */ jsxs10(
3766
3834
  "button",
3767
3835
  {
3768
3836
  type: "button",
@@ -3772,12 +3840,12 @@ function ChatInput({
3772
3840
  },
3773
3841
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3774
3842
  children: [
3775
- /* @__PURE__ */ jsx10(Paperclip, { size: 13 }),
3843
+ /* @__PURE__ */ jsx11(Paperclip, { size: 13 }),
3776
3844
  "\u4E0A\u4F20\u6587\u4EF6"
3777
3845
  ]
3778
3846
  }
3779
3847
  ),
3780
- /* @__PURE__ */ jsxs9(
3848
+ /* @__PURE__ */ jsxs10(
3781
3849
  "button",
3782
3850
  {
3783
3851
  type: "button",
@@ -3787,12 +3855,12 @@ function ChatInput({
3787
3855
  },
3788
3856
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3789
3857
  children: [
3790
- /* @__PURE__ */ jsx10(FolderUp, { size: 13 }),
3858
+ /* @__PURE__ */ jsx11(FolderUp, { size: 13 }),
3791
3859
  "\u4E0A\u4F20\u6587\u4EF6\u5939"
3792
3860
  ]
3793
3861
  }
3794
3862
  ),
3795
- onDoubleEscape ? /* @__PURE__ */ jsxs9(
3863
+ onDoubleEscape ? /* @__PURE__ */ jsxs10(
3796
3864
  "button",
3797
3865
  {
3798
3866
  type: "button",
@@ -3804,13 +3872,13 @@ function ChatInput({
3804
3872
  },
3805
3873
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3806
3874
  children: [
3807
- /* @__PURE__ */ jsx10(RotateCcw, { size: 13 }),
3875
+ /* @__PURE__ */ jsx11(RotateCcw, { size: 13 }),
3808
3876
  "\u56DE\u5230\u4E4B\u524D\u7684\u67D0\u4E00\u6B65"
3809
3877
  ]
3810
3878
  }
3811
3879
  ) : null,
3812
- onCommand ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
3813
- /* @__PURE__ */ jsxs9(
3880
+ onCommand ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
3881
+ /* @__PURE__ */ jsxs10(
3814
3882
  "button",
3815
3883
  {
3816
3884
  type: "button",
@@ -3821,12 +3889,12 @@ function ChatInput({
3821
3889
  disabled: isStreaming,
3822
3890
  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",
3823
3891
  children: [
3824
- isStreaming ? /* @__PURE__ */ jsx10(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx10(Scissors, { size: 13 }),
3892
+ isStreaming ? /* @__PURE__ */ jsx11(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx11(Scissors, { size: 13 }),
3825
3893
  "\u6574\u7406\u5BF9\u8BDD"
3826
3894
  ]
3827
3895
  }
3828
3896
  ),
3829
- /* @__PURE__ */ jsxs9(
3897
+ /* @__PURE__ */ jsxs10(
3830
3898
  "button",
3831
3899
  {
3832
3900
  type: "button",
@@ -3836,12 +3904,12 @@ function ChatInput({
3836
3904
  },
3837
3905
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3838
3906
  children: [
3839
- /* @__PURE__ */ jsx10(Download, { size: 13 }),
3907
+ /* @__PURE__ */ jsx11(Download, { size: 13 }),
3840
3908
  "\u5BFC\u51FA\u4F1A\u8BDD"
3841
3909
  ]
3842
3910
  }
3843
3911
  ),
3844
- canShareSession ? /* @__PURE__ */ jsxs9(
3912
+ canShareSession ? /* @__PURE__ */ jsxs10(
3845
3913
  "button",
3846
3914
  {
3847
3915
  type: "button",
@@ -3851,12 +3919,12 @@ function ChatInput({
3851
3919
  },
3852
3920
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3853
3921
  children: [
3854
- /* @__PURE__ */ jsx10(Share2, { size: 13 }),
3922
+ /* @__PURE__ */ jsx11(Share2, { size: 13 }),
3855
3923
  "\u5206\u4EAB\u4F1A\u8BDD"
3856
3924
  ]
3857
3925
  }
3858
3926
  ) : null,
3859
- /* @__PURE__ */ jsxs9(
3927
+ /* @__PURE__ */ jsxs10(
3860
3928
  "button",
3861
3929
  {
3862
3930
  type: "button",
@@ -3866,12 +3934,12 @@ function ChatInput({
3866
3934
  },
3867
3935
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3868
3936
  children: [
3869
- /* @__PURE__ */ jsx10(FlaskConical, { size: 13 }),
3937
+ /* @__PURE__ */ jsx11(FlaskConical, { size: 13 }),
3870
3938
  "\u63D0\u53D6\u6280\u80FD"
3871
3939
  ]
3872
3940
  }
3873
3941
  ),
3874
- /* @__PURE__ */ jsxs9(
3942
+ /* @__PURE__ */ jsxs10(
3875
3943
  "button",
3876
3944
  {
3877
3945
  type: "button",
@@ -3881,13 +3949,24 @@ function ChatInput({
3881
3949
  },
3882
3950
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3883
3951
  children: [
3884
- /* @__PURE__ */ jsx10(Rocket, { size: 13 }),
3952
+ /* @__PURE__ */ jsx11(Rocket, { size: 13 }),
3885
3953
  "\u751F\u6210\u5E94\u7528"
3886
3954
  ]
3887
3955
  }
3888
3956
  )
3889
3957
  ] }) : null,
3890
- thinkingAvailable ? /* @__PURE__ */ jsx10(
3958
+ onToggleMode ? /* @__PURE__ */ jsx11(
3959
+ PlanningToggle,
3960
+ {
3961
+ enabled: isPlanning,
3962
+ onChange: () => {
3963
+ actionMenuRef.current?.removeAttribute("open");
3964
+ onToggleMode();
3965
+ },
3966
+ disabled: isStreaming
3967
+ }
3968
+ ) : null,
3969
+ thinkingAvailable ? /* @__PURE__ */ jsx11(
3891
3970
  ThinkingToggle,
3892
3971
  {
3893
3972
  enabled: thinkingEnabled,
@@ -3897,10 +3976,10 @@ function ChatInput({
3897
3976
  }
3898
3977
  }
3899
3978
  ) : null,
3900
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 px-3 py-2", children: [
3901
- /* @__PURE__ */ jsx10(Sparkles2, { size: 13 }),
3902
- /* @__PURE__ */ jsx10("span", { className: "shrink-0", children: "\u6A21\u578B" }),
3903
- /* @__PURE__ */ jsx10(
3979
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 px-3 py-2", children: [
3980
+ /* @__PURE__ */ jsx11(Sparkles2, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
3981
+ /* @__PURE__ */ jsx11("span", { className: "shrink-0", children: "\u6A21\u578B" }),
3982
+ /* @__PURE__ */ jsx11(
3904
3983
  ModelSelector,
3905
3984
  {
3906
3985
  value: selectedModel,
@@ -3917,23 +3996,10 @@ function ChatInput({
3917
3996
  )
3918
3997
  ] })
3919
3998
  ] })
3920
- ] }),
3921
- /* @__PURE__ */ jsx10(
3922
- "button",
3923
- {
3924
- type: "button",
3925
- onClick: onToggleMode,
3926
- disabled: isStreaming || !onToggleMode,
3927
- "aria-pressed": isPlanning,
3928
- "aria-label": isPlanning ? "\u5173\u95ED\u89C4\u5212\u6A21\u5F0F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3929
- title: isPlanning ? "\u89C4\u5212\u6A21\u5F0F\u5DF2\u5F00\u542F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3930
- 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`,
3931
- children: /* @__PURE__ */ jsx10(Lightbulb, { size: 13 })
3932
- }
3933
- )
3999
+ ] })
3934
4000
  ] }),
3935
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1.5", children: [
3936
- /* @__PURE__ */ jsx10(
4001
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1.5", children: [
4002
+ /* @__PURE__ */ jsx11(
3937
4003
  HelpPopover,
3938
4004
  {
3939
4005
  activeSessionId,
@@ -3945,7 +4011,7 @@ function ChatInput({
3945
4011
  composerHint
3946
4012
  }
3947
4013
  ),
3948
- /* @__PURE__ */ jsx10(
4014
+ /* @__PURE__ */ jsx11(
3949
4015
  "button",
3950
4016
  {
3951
4017
  type: "button",
@@ -3953,22 +4019,23 @@ function ChatInput({
3953
4019
  disabled: isStreaming,
3954
4020
  "aria-label": !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
3955
4021
  title: !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u8BED\u97F3\u8F93\u5165",
3956
- 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))]"}`,
3957
- children: !asrEnabled ? /* @__PURE__ */ jsx10(MicOff, { size: 13 }) : isRecording ? /* @__PURE__ */ jsx10(VoiceWaveform, { level: voiceLevel, size: 18 }) : /* @__PURE__ */ jsx10(Mic, { size: 13 })
4022
+ className: `flex items-center justify-center rounded-full transition-[width,height,background-color,color,box-shadow] duration-300 disabled:opacity-40 ${!asrEnabled ? "h-9 w-9 text-[hsl(var(--muted-foreground))]/50 hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--muted-foreground))]" : isRecording ? "h-10 w-10 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-9 w-9 text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"}`,
4023
+ children: !asrEnabled ? /* @__PURE__ */ jsx11(MicOff, { size: 19 }) : isRecording ? /* @__PURE__ */ jsx11(VoiceWaveform, { level: voiceLevel, size: 20 }) : /* @__PURE__ */ jsx11(Mic, { size: 19 })
3958
4024
  }
3959
4025
  ),
3960
4026
  slotBeforeSend,
3961
- isStreaming ? /* @__PURE__ */ jsx10(
4027
+ isStreaming ? /* @__PURE__ */ jsx11(
3962
4028
  "button",
3963
4029
  {
3964
4030
  type: "button",
3965
4031
  onClick: () => void onStop(),
3966
4032
  disabled: isStopping,
3967
4033
  "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
3968
- 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 disabled:cursor-wait disabled:opacity-70",
3969
- children: isStopping ? /* @__PURE__ */ jsx10(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx10(Square2, { size: 13 })
4034
+ title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u751F\u6210",
4035
+ className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80 disabled:cursor-wait disabled:opacity-70",
4036
+ children: isStopping ? /* @__PURE__ */ jsx11(Loader22, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx11(Square2, { size: 16 })
3970
4037
  }
3971
- ) : /* @__PURE__ */ jsx10(
4038
+ ) : /* @__PURE__ */ jsx11(
3972
4039
  "button",
3973
4040
  {
3974
4041
  type: "button",
@@ -3976,8 +4043,8 @@ function ChatInput({
3976
4043
  disabled: isSendDisabled || isRecording,
3977
4044
  "aria-label": "\u53D1\u9001\u6D88\u606F",
3978
4045
  title: isModelLoading ? "\u6B63\u5728\u52A0\u8F7D\u6A21\u578B\u914D\u7F6E" : !hasAvailableModel ? "\u6CA1\u6709\u53EF\u7528\u6A21\u578B\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u670D\u52A1\u914D\u7F6E" : "\u53D1\u9001\u6D88\u606F",
3979
- 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",
3980
- children: isSubmitting ? /* @__PURE__ */ jsx10(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx10(Send, { size: 13 })
4046
+ className: "flex h-10 w-10 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] shadow-[0_8px_18px_-8px_rgba(20,87,255,0.7)] transition-opacity hover:opacity-80 disabled:opacity-25 disabled:shadow-none",
4047
+ children: isSubmitting ? /* @__PURE__ */ jsx11(Loader22, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsx11(Send, { size: 16 })
3981
4048
  }
3982
4049
  )
3983
4050
  ] })
@@ -3988,7 +4055,7 @@ function ChatInput({
3988
4055
  }
3989
4056
  )
3990
4057
  ] }) }),
3991
- /* @__PURE__ */ jsx10(
4058
+ /* @__PURE__ */ jsx11(
3992
4059
  FileSizeLimitDialog,
3993
4060
  {
3994
4061
  open: oversizedFiles.length > 0,
@@ -4006,18 +4073,18 @@ function ChatInput({
4006
4073
 
4007
4074
  // src/react/components/chat/ConnectionBanner.tsx
4008
4075
  import { AlertTriangle, LoaderCircle } from "lucide-react";
4009
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
4076
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
4010
4077
  function getBannerCopy(status, reconnectAttempt, hasEverConnected) {
4011
4078
  if (status === "connecting") {
4012
4079
  return {
4013
- icon: /* @__PURE__ */ jsx11(LoaderCircle, { size: 14, className: "animate-spin" }),
4080
+ icon: /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin" }),
4014
4081
  toneClass: "border-amber-500/25 bg-amber-500/10 text-amber-100",
4015
4082
  title: "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u91CD\u8FDE\u2026",
4016
4083
  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"
4017
4084
  };
4018
4085
  }
4019
4086
  return {
4020
- icon: /* @__PURE__ */ jsx11(AlertTriangle, { size: 14 }),
4087
+ icon: /* @__PURE__ */ jsx12(AlertTriangle, { size: 14 }),
4021
4088
  toneClass: "border-rose-500/25 bg-rose-500/10 text-rose-100",
4022
4089
  title: hasEverConnected ? "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u7B49\u5F85\u91CD\u8FDE\u2026" : "\u6682\u65F6\u65E0\u6CD5\u5EFA\u7ACB\u8FDE\u63A5",
4023
4090
  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"
@@ -4032,7 +4099,7 @@ function ConnectionBanner() {
4032
4099
  return null;
4033
4100
  }
4034
4101
  const copy = getBannerCopy(status, reconnectAttempt, hasEverConnected);
4035
- return /* @__PURE__ */ jsx11("div", { className: "bg-[hsl(var(--background))] px-5 pt-3", children: /* @__PURE__ */ jsxs10(
4102
+ return /* @__PURE__ */ jsx12("div", { className: "bg-[hsl(var(--background))] px-5 pt-3", children: /* @__PURE__ */ jsxs11(
4036
4103
  "div",
4037
4104
  {
4038
4105
  className: cn(
@@ -4040,10 +4107,10 @@ function ConnectionBanner() {
4040
4107
  copy.toneClass
4041
4108
  ),
4042
4109
  children: [
4043
- /* @__PURE__ */ jsx11("span", { className: "mt-0.5 shrink-0", children: copy.icon }),
4044
- /* @__PURE__ */ jsxs10("div", { className: "min-w-0", children: [
4045
- /* @__PURE__ */ jsx11("div", { className: "text-sm font-medium", children: copy.title }),
4046
- /* @__PURE__ */ jsx11("div", { className: "text-xs opacity-80", children: copy.detail })
4110
+ /* @__PURE__ */ jsx12("span", { className: "mt-0.5 shrink-0", children: copy.icon }),
4111
+ /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
4112
+ /* @__PURE__ */ jsx12("div", { className: "text-sm font-medium", children: copy.title }),
4113
+ /* @__PURE__ */ jsx12("div", { className: "text-xs opacity-80", children: copy.detail })
4047
4114
  ] })
4048
4115
  ]
4049
4116
  }
@@ -4051,14 +4118,14 @@ function ConnectionBanner() {
4051
4118
  }
4052
4119
 
4053
4120
  // src/react/components/chat/MessageList.tsx
4054
- import { ChevronDown as ChevronDown3, Lightbulb as Lightbulb2, MessageSquare } from "lucide-react";
4121
+ import { ChevronDown as ChevronDown4, Lightbulb as Lightbulb2, MessageSquare } from "lucide-react";
4055
4122
  import {
4056
4123
  useCallback as useCallback12,
4057
4124
  useEffect as useEffect18,
4058
4125
  useEffectEvent as useEffectEvent4,
4059
- useMemo as useMemo18,
4126
+ useMemo as useMemo19,
4060
4127
  useRef as useRef13,
4061
- useState as useState21
4128
+ useState as useState22
4062
4129
  } from "react";
4063
4130
 
4064
4131
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
@@ -4486,8 +4553,8 @@ function useStickToBottomContext() {
4486
4553
  }
4487
4554
 
4488
4555
  // src/react/components/chat/AssistantTurnBlock.tsx
4489
- import { AlertCircle, BookOpen, Check as Check5, ChevronRight as ChevronRight5 } from "lucide-react";
4490
- import { memo as memo3, useCallback as useCallback11, useEffect as useEffect16, useMemo as useMemo16, useRef as useRef12, useState as useState18 } from "react";
4556
+ import { AlertCircle, BookOpen, Check as Check5, ChevronDown as ChevronDown2, ChevronRight as ChevronRight5 } from "lucide-react";
4557
+ import { memo as memo3, useCallback as useCallback11, useEffect as useEffect16, useMemo as useMemo17, useRef as useRef12, useState as useState19 } from "react";
4491
4558
 
4492
4559
  // src/react/routes.ts
4493
4560
  var MEMORIES_ROUTE = "/memories";
@@ -4514,7 +4581,7 @@ import { Streamdown } from "streamdown";
4514
4581
  // src/react/components/ai-elements/shimmer.tsx
4515
4582
  import { motion } from "motion/react";
4516
4583
  import { memo, useMemo as useMemo11 } from "react";
4517
- import { jsx as jsx12 } from "react/jsx-runtime";
4584
+ import { jsx as jsx13 } from "react/jsx-runtime";
4518
4585
  var motionComponentCache = /* @__PURE__ */ new Map();
4519
4586
  var getMotionComponent = (element) => {
4520
4587
  let component = motionComponentCache.get(element);
@@ -4538,7 +4605,7 @@ var ShimmerComponent = ({
4538
4605
  () => (children?.length ?? 0) * spread,
4539
4606
  [children, spread]
4540
4607
  );
4541
- return /* @__PURE__ */ jsx12(
4608
+ return /* @__PURE__ */ jsx13(
4542
4609
  MotionComponent,
4543
4610
  {
4544
4611
  animate: { backgroundPosition: "0% center" },
@@ -4564,7 +4631,7 @@ var ShimmerComponent = ({
4564
4631
  var Shimmer = memo(ShimmerComponent);
4565
4632
 
4566
4633
  // src/react/components/ai-elements/reasoning.tsx
4567
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
4634
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
4568
4635
  var ReasoningContext = createContext2(null);
4569
4636
  var useReasoning = () => {
4570
4637
  const context = useContext2(ReasoningContext);
@@ -4615,7 +4682,7 @@ var Reasoning = memo2(
4615
4682
  () => ({ duration, isOpen, isStreaming, setIsOpen }),
4616
4683
  [duration, isOpen, isStreaming, setIsOpen]
4617
4684
  );
4618
- return /* @__PURE__ */ jsx13(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx13(
4685
+ return /* @__PURE__ */ jsx14(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx14(
4619
4686
  Collapsible,
4620
4687
  {
4621
4688
  className: cn("not-prose", className),
@@ -4640,7 +4707,7 @@ var ReasoningTrigger = memo2(
4640
4707
  const { isStreaming, isOpen, duration } = useReasoning();
4641
4708
  const status = isStreaming || duration === 0 ? "\u6B63\u5728\u601D\u8003" : "\u5DF2\u601D\u8003";
4642
4709
  const detail = `${formatWordCount(wordCount)} \u5B57`;
4643
- return /* @__PURE__ */ jsx13(
4710
+ return /* @__PURE__ */ jsx14(
4644
4711
  CollapsibleTrigger,
4645
4712
  {
4646
4713
  className: cn(
@@ -4648,16 +4715,16 @@ var ReasoningTrigger = memo2(
4648
4715
  className
4649
4716
  ),
4650
4717
  ...props,
4651
- children: children ?? /* @__PURE__ */ jsxs11(Fragment3, { children: [
4652
- /* @__PURE__ */ jsx13(BrainIcon, { className: "size-4" }),
4653
- /* @__PURE__ */ jsxs11("span", { className: "inline-flex items-center gap-1.5", children: [
4654
- isStreaming || duration === 0 ? /* @__PURE__ */ jsx13(Shimmer, { duration: 1, children: status }) : /* @__PURE__ */ jsx13("span", { children: status }),
4655
- /* @__PURE__ */ jsxs11("span", { className: "text-[hsl(var(--muted-foreground))]/70", children: [
4718
+ children: children ?? /* @__PURE__ */ jsxs12(Fragment3, { children: [
4719
+ /* @__PURE__ */ jsx14(BrainIcon, { className: "size-4" }),
4720
+ /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1.5", children: [
4721
+ isStreaming || duration === 0 ? /* @__PURE__ */ jsx14(Shimmer, { duration: 1, children: status }) : /* @__PURE__ */ jsx14("span", { children: status }),
4722
+ /* @__PURE__ */ jsxs12("span", { className: "text-[hsl(var(--muted-foreground))]/70", children: [
4656
4723
  "\xB7 ",
4657
4724
  detail
4658
4725
  ] })
4659
4726
  ] }),
4660
- /* @__PURE__ */ jsx13(
4727
+ /* @__PURE__ */ jsx14(
4661
4728
  ChevronDownIcon,
4662
4729
  {
4663
4730
  className: cn(
@@ -4674,7 +4741,7 @@ var ReasoningTrigger = memo2(
4674
4741
  var streamdownPlugins = { cjk, math, mermaid };
4675
4742
  var streamdownComponents = { code: CardCodeBlock };
4676
4743
  var ReasoningContent = memo2(
4677
- ({ className, children, ...props }) => /* @__PURE__ */ jsx13(
4744
+ ({ className, children, ...props }) => /* @__PURE__ */ jsx14(
4678
4745
  CollapsibleContent,
4679
4746
  {
4680
4747
  className: cn(
@@ -4683,7 +4750,7 @@ var ReasoningContent = memo2(
4683
4750
  className
4684
4751
  ),
4685
4752
  ...props,
4686
- children: /* @__PURE__ */ jsx13(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children })
4753
+ children: /* @__PURE__ */ jsx14(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children })
4687
4754
  }
4688
4755
  )
4689
4756
  );
@@ -4693,7 +4760,7 @@ function compactReasoningText(text) {
4693
4760
  function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4694
4761
  const compactReasoning = compactReasoningText(reasoning);
4695
4762
  const [open, setOpen] = useState10(false);
4696
- return /* @__PURE__ */ jsxs11(
4763
+ return /* @__PURE__ */ jsxs12(
4697
4764
  "span",
4698
4765
  {
4699
4766
  className: cn(
@@ -4701,7 +4768,7 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4701
4768
  variant === "inline" ? "ml-1" : "ml-1 shrink-0"
4702
4769
  ),
4703
4770
  children: [
4704
- /* @__PURE__ */ jsx13(
4771
+ /* @__PURE__ */ jsx14(
4705
4772
  "button",
4706
4773
  {
4707
4774
  type: "button",
@@ -4716,7 +4783,7 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4716
4783
  }
4717
4784
  ),
4718
4785
  open ? createPortal2(
4719
- /* @__PURE__ */ jsx13(
4786
+ /* @__PURE__ */ jsx14(
4720
4787
  "div",
4721
4788
  {
4722
4789
  className: "fixed inset-0 z-[70] flex items-center justify-center bg-black/10 p-6",
@@ -4732,26 +4799,26 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4732
4799
  setOpen(false);
4733
4800
  }
4734
4801
  },
4735
- children: /* @__PURE__ */ jsxs11(
4802
+ children: /* @__PURE__ */ jsxs12(
4736
4803
  "div",
4737
4804
  {
4738
4805
  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",
4739
4806
  "aria-label": "\u601D\u8003\u8BE6\u60C5",
4740
4807
  children: [
4741
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2", children: [
4742
- /* @__PURE__ */ jsx13("span", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u601D\u8003\u8BE6\u60C5" }),
4743
- /* @__PURE__ */ jsx13(
4808
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2", children: [
4809
+ /* @__PURE__ */ jsx14("span", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u601D\u8003\u8BE6\u60C5" }),
4810
+ /* @__PURE__ */ jsx14(
4744
4811
  "button",
4745
4812
  {
4746
4813
  type: "button",
4747
4814
  onClick: () => setOpen(false),
4748
4815
  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",
4749
4816
  "aria-label": "\u5173\u95ED\u601D\u8003\u8BE6\u60C5",
4750
- children: /* @__PURE__ */ jsx13(XIcon, { size: 14, "aria-hidden": "true" })
4817
+ children: /* @__PURE__ */ jsx14(XIcon, { size: 14, "aria-hidden": "true" })
4751
4818
  }
4752
4819
  )
4753
4820
  ] }),
4754
- /* @__PURE__ */ jsx13("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__ */ jsx13(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children: compactReasoning }) })
4821
+ /* @__PURE__ */ jsx14("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__ */ jsx14(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children: compactReasoning }) })
4755
4822
  ]
4756
4823
  }
4757
4824
  )
@@ -4773,7 +4840,7 @@ import { useEffect as useEffect15, useMemo as useMemo15, useState as useState17
4773
4840
 
4774
4841
  // src/react/components/chat/ResourceIframe.tsx
4775
4842
  import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as useRef9, useState as useState11 } from "react";
4776
- import { jsx as jsx14 } from "react/jsx-runtime";
4843
+ import { jsx as jsx15 } from "react/jsx-runtime";
4777
4844
  function isResourceBridgeMessage(value) {
4778
4845
  return typeof value === "object" && value !== null && value.__resourceBridge === true && typeof value.action === "string";
4779
4846
  }
@@ -4788,7 +4855,8 @@ function ResourceIframe({ ui, sessionId }) {
4788
4855
  const activeSessionId = useSessionStore((state) => state.activeSessionId);
4789
4856
  const isStreaming = useChatStore((state) => state.isStreaming[sessionId] ?? false);
4790
4857
  const theme = useUiStore((state) => state.theme);
4791
- const resourceUri = ui.resourceUri ?? ui.resourceURI;
4858
+ const rawResourceUri = ui.resourceUri ?? ui.resourceURI;
4859
+ const resourceUri = rawResourceUri ? resolveBrowserResourceUri(rawResourceUri) : void 0;
4792
4860
  const iframeLabel = ui.title ?? resourceUri ?? "\u5DE5\u5177\u754C\u9762";
4793
4861
  const [autoHeight, setAutoHeight] = useState11(null);
4794
4862
  useEffect10(() => {
@@ -4880,7 +4948,7 @@ function ResourceIframe({ ui, sessionId }) {
4880
4948
  const inlineHeight = autoHeight ?? ui.height;
4881
4949
  const sandbox = resourceUri ? "allow-scripts allow-same-origin" : "allow-scripts";
4882
4950
  const srcDoc = ui.resourceHTML ? injectBaseTag(ui.resourceHTML) : void 0;
4883
- return /* @__PURE__ */ jsx14(
4951
+ return /* @__PURE__ */ jsx15(
4884
4952
  "iframe",
4885
4953
  {
4886
4954
  ref: iframeRef,
@@ -4919,7 +4987,7 @@ import { Check as Check2, ChevronRight as ChevronRight3, Loader2 as Loader23, Me
4919
4987
  import { useEffect as useEffect12, useMemo as useMemo13, useState as useState14 } from "react";
4920
4988
 
4921
4989
  // src/react/components/chat/tool-renderers/shared.tsx
4922
- import { jsx as jsx15 } from "react/jsx-runtime";
4990
+ import { jsx as jsx16 } from "react/jsx-runtime";
4923
4991
  function getResultText(result) {
4924
4992
  if (typeof result === "string") return result;
4925
4993
  if (Array.isArray(result)) {
@@ -4986,7 +5054,7 @@ function CodePreview({
4986
5054
  }) {
4987
5055
  const { highlightedHtml } = useHighlightedCodeHtml(content, getCodeLanguage(filePath));
4988
5056
  if (!content.trim()) {
4989
- return /* @__PURE__ */ jsx15(
5057
+ return /* @__PURE__ */ jsx16(
4990
5058
  "pre",
4991
5059
  {
4992
5060
  className: cn(
@@ -4994,11 +5062,11 @@ function CodePreview({
4994
5062
  "bg-[hsl(var(--muted))]/35 p-3 font-mono text-[11px] text-[hsl(var(--muted-foreground))]",
4995
5063
  className
4996
5064
  ),
4997
- children: /* @__PURE__ */ jsx15("code", { children: emptyLabel })
5065
+ children: /* @__PURE__ */ jsx16("code", { children: emptyLabel })
4998
5066
  }
4999
5067
  );
5000
5068
  }
5001
- return /* @__PURE__ */ jsx15(
5069
+ return /* @__PURE__ */ jsx16(
5002
5070
  "pre",
5003
5071
  {
5004
5072
  className: cn(
@@ -5006,19 +5074,19 @@ function CodePreview({
5006
5074
  "bg-[hsl(var(--muted))]/35 p-3 text-[11px]",
5007
5075
  className
5008
5076
  ),
5009
- children: highlightedHtml ? /* @__PURE__ */ jsx15(
5077
+ children: highlightedHtml ? /* @__PURE__ */ jsx16(
5010
5078
  "code",
5011
5079
  {
5012
5080
  className: "font-mono",
5013
5081
  dangerouslySetInnerHTML: { __html: highlightedHtml }
5014
5082
  }
5015
- ) : /* @__PURE__ */ jsx15("code", { className: "whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]", children: content })
5083
+ ) : /* @__PURE__ */ jsx16("code", { className: "whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]", children: content })
5016
5084
  }
5017
5085
  );
5018
5086
  }
5019
5087
 
5020
5088
  // src/react/components/chat/tool-renderers/BashRenderer.tsx
5021
- import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
5089
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
5022
5090
  function pickOutputField(data) {
5023
5091
  if (!data) return null;
5024
5092
  for (const key of ["output", "stdout", "stderr"]) {
@@ -5028,7 +5096,7 @@ function pickOutputField(data) {
5028
5096
  return null;
5029
5097
  }
5030
5098
  function MetaPill({ label }) {
5031
- return /* @__PURE__ */ jsx16("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground", children: label });
5099
+ return /* @__PURE__ */ jsx17("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground", children: label });
5032
5100
  }
5033
5101
  function BashRenderer({ toolCall }) {
5034
5102
  const argsValue = parseJsonValue(toolCall.arguments);
@@ -5051,16 +5119,16 @@ function BashRenderer({ toolCall }) {
5051
5119
  const rawFallbackOutput = result === null && typeof resultStr === "string" && resultStr.trim().length > 0 ? resultStr : null;
5052
5120
  const output = structuredOutput !== null ? structuredOutput : errorMessage ?? rawFallbackOutput ?? (normalizedName === "BgBash" ? "" : null);
5053
5121
  const hasFailure = toolCall.status === "error" || timedOut || exitCode !== null && exitCode !== 0;
5054
- return /* @__PURE__ */ jsxs12("div", { className: "space-y-3", children: [
5055
- (description || cwd) && /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5056
- description ? /* @__PURE__ */ jsx16("span", { children: description }) : null,
5057
- cwd ? /* @__PURE__ */ jsx16("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: cwd }) : null
5122
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
5123
+ (description || cwd) && /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5124
+ description ? /* @__PURE__ */ jsx17("span", { children: description }) : null,
5125
+ cwd ? /* @__PURE__ */ jsx17("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: cwd }) : null
5058
5126
  ] }),
5059
- /* @__PURE__ */ jsxs12("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [
5060
- /* @__PURE__ */ jsx16("div", { className: "border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u547D\u4EE4" }),
5061
- /* @__PURE__ */ jsx16("pre", { className: "overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx16("code", { children: `$ ${command || "\uFF08\u672A\u63D0\u4F9B\u547D\u4EE4\uFF09"}` }) })
5127
+ /* @__PURE__ */ jsxs13("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [
5128
+ /* @__PURE__ */ jsx17("div", { className: "border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u547D\u4EE4" }),
5129
+ /* @__PURE__ */ jsx17("pre", { className: "overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx17("code", { children: `$ ${command || "\uFF08\u672A\u63D0\u4F9B\u547D\u4EE4\uFF09"}` }) })
5062
5130
  ] }),
5063
- /* @__PURE__ */ jsxs12(
5131
+ /* @__PURE__ */ jsxs13(
5064
5132
  "div",
5065
5133
  {
5066
5134
  className: cn(
@@ -5068,26 +5136,26 @@ function BashRenderer({ toolCall }) {
5068
5136
  hasFailure ? "border-red-500/50" : "border-border"
5069
5137
  ),
5070
5138
  children: [
5071
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
5072
- /* @__PURE__ */ jsx16("div", { className: "text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u8F93\u51FA" }),
5073
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-1.5", children: [
5074
- taskId ? /* @__PURE__ */ jsx16(MetaPill, { label: `\u4EFB\u52A1 ${taskId}` }) : null,
5075
- exitCode !== null ? /* @__PURE__ */ jsx16(MetaPill, { label: `\u9000\u51FA\u7801 ${exitCode}` }) : null,
5076
- timedOut ? /* @__PURE__ */ jsx16(MetaPill, { label: "\u5DF2\u8D85\u65F6" }) : null,
5077
- truncated ? /* @__PURE__ */ jsx16(MetaPill, { label: "\u8F93\u51FA\u5DF2\u622A\u65AD" }) : null,
5078
- normalizedName === "BgBash" && !taskId ? /* @__PURE__ */ jsx16(MetaPill, { label: "\u540E\u53F0\u4EFB\u52A1" }) : null
5139
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
5140
+ /* @__PURE__ */ jsx17("div", { className: "text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u8F93\u51FA" }),
5141
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-1.5", children: [
5142
+ taskId ? /* @__PURE__ */ jsx17(MetaPill, { label: `\u4EFB\u52A1 ${taskId}` }) : null,
5143
+ exitCode !== null ? /* @__PURE__ */ jsx17(MetaPill, { label: `\u9000\u51FA\u7801 ${exitCode}` }) : null,
5144
+ timedOut ? /* @__PURE__ */ jsx17(MetaPill, { label: "\u5DF2\u8D85\u65F6" }) : null,
5145
+ truncated ? /* @__PURE__ */ jsx17(MetaPill, { label: "\u8F93\u51FA\u5DF2\u622A\u65AD" }) : null,
5146
+ normalizedName === "BgBash" && !taskId ? /* @__PURE__ */ jsx17(MetaPill, { label: "\u540E\u53F0\u4EFB\u52A1" }) : null
5079
5147
  ] })
5080
5148
  ] }),
5081
- /* @__PURE__ */ jsx16("pre", { className: "max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx16("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" }) })
5149
+ /* @__PURE__ */ jsx17("pre", { className: "max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx17("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" }) })
5082
5150
  ]
5083
5151
  }
5084
5152
  ),
5085
- cwdResetNote ? /* @__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: cwdResetNote }) : null
5153
+ cwdResetNote ? /* @__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: cwdResetNote }) : null
5086
5154
  ] });
5087
5155
  }
5088
5156
 
5089
5157
  // src/react/components/chat/tool-renderers/FileEditRenderer.tsx
5090
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
5158
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
5091
5159
  var MAX_DIFF_LINES = 200;
5092
5160
  var FILE_PATH_FIELDS = ["file_path", "path"];
5093
5161
  function computeDiff(oldText, newText) {
@@ -5294,21 +5362,21 @@ function FileEditRenderer({ toolCall }) {
5294
5362
  const diffLines = normalizedName === "Write" ? buildWritePreview(writeContent) : buildEditPreview(args, rawArguments);
5295
5363
  const resultStr = typeof toolCall.result === "string" ? toolCall.result : null;
5296
5364
  const summaryText = resultStr?.trim() && !errorMessage ? resultStr.trim() : null;
5297
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
5298
- /* @__PURE__ */ jsxs13("div", { className: "flex items-start justify-between gap-3", children: [
5299
- /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
5300
- /* @__PURE__ */ jsx17("div", { className: "text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5199\u5165\u6587\u4EF6" : "\u7F16\u8F91\u6587\u4EF6" }),
5301
- /* @__PURE__ */ jsx17("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: filePath ?? fileName })
5365
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5366
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-start justify-between gap-3", children: [
5367
+ /* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
5368
+ /* @__PURE__ */ jsx18("div", { className: "text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5199\u5165\u6587\u4EF6" : "\u7F16\u8F91\u6587\u4EF6" }),
5369
+ /* @__PURE__ */ jsx18("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: filePath ?? fileName })
5302
5370
  ] }),
5303
- 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
5371
+ 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
5304
5372
  ] }),
5305
- description ? /* @__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: description }) : null,
5306
- 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,
5307
- /* @__PURE__ */ jsxs13("div", { className: "overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20", children: [
5308
- /* @__PURE__ */ jsx17("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" }),
5309
- /* @__PURE__ */ jsx17("pre", { className: "max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5", children: diffLines.length > 0 ? diffLines.map((line, index) => {
5373
+ 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,
5374
+ 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,
5375
+ /* @__PURE__ */ jsxs14("div", { className: "overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20", children: [
5376
+ /* @__PURE__ */ jsx18("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" }),
5377
+ /* @__PURE__ */ jsx18("pre", { className: "max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5", children: diffLines.length > 0 ? diffLines.map((line, index) => {
5310
5378
  const prefix = line.type === "added" ? "+ " : line.type === "removed" ? "- " : " ";
5311
- return /* @__PURE__ */ jsxs13(
5379
+ return /* @__PURE__ */ jsxs14(
5312
5380
  "div",
5313
5381
  {
5314
5382
  className: cn(
@@ -5318,9 +5386,9 @@ function FileEditRenderer({ toolCall }) {
5318
5386
  line.type === "unchanged" && "text-[hsl(var(--foreground))]"
5319
5387
  ),
5320
5388
  children: [
5321
- /* @__PURE__ */ jsx17("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.oldLine ?? "" }),
5322
- /* @__PURE__ */ jsx17("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.newLine ?? "" }),
5323
- /* @__PURE__ */ jsxs13("span", { className: "min-w-0 whitespace-pre-wrap break-words py-0.5", children: [
5389
+ /* @__PURE__ */ jsx18("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.oldLine ?? "" }),
5390
+ /* @__PURE__ */ jsx18("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.newLine ?? "" }),
5391
+ /* @__PURE__ */ jsxs14("span", { className: "min-w-0 whitespace-pre-wrap break-words py-0.5", children: [
5324
5392
  prefix,
5325
5393
  line.value
5326
5394
  ] })
@@ -5328,9 +5396,9 @@ function FileEditRenderer({ toolCall }) {
5328
5396
  },
5329
5397
  `${line.type}-${line.oldLine}-${line.newLine}-${index}`
5330
5398
  );
5331
- }) : /* @__PURE__ */ jsx17("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" }) })
5399
+ }) : /* @__PURE__ */ jsx18("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" }) })
5332
5400
  ] }),
5333
- summaryText ? /* @__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: summaryText }) : null
5401
+ summaryText ? /* @__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: summaryText }) : null
5334
5402
  ] });
5335
5403
  }
5336
5404
 
@@ -5341,7 +5409,7 @@ import { useState as useState13 } from "react";
5341
5409
  import { ChevronLeft, ChevronRight as ChevronRight2, Download as Download2, ExternalLink, Minus, Plus as Plus2, RotateCcw as RotateCcw2, X as X3 } from "lucide-react";
5342
5410
  import { useCallback as useCallback10, useEffect as useEffect11, useRef as useRef10, useState as useState12 } from "react";
5343
5411
  import { createPortal as createPortal3 } from "react-dom";
5344
- import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
5412
+ import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5345
5413
  function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5346
5414
  const [currentIndex, setCurrentIndex] = useState12(initialIndex);
5347
5415
  const [scale, setScale] = useState12(1);
@@ -5451,22 +5519,22 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5451
5519
  if (images.length === 0) {
5452
5520
  return createPortal3(
5453
5521
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect
5454
- /* @__PURE__ */ jsxs14(
5522
+ /* @__PURE__ */ jsxs15(
5455
5523
  "div",
5456
5524
  {
5457
5525
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80",
5458
5526
  onClick: close,
5459
5527
  children: [
5460
- /* @__PURE__ */ jsx18(
5528
+ /* @__PURE__ */ jsx19(
5461
5529
  "button",
5462
5530
  {
5463
5531
  type: "button",
5464
5532
  onClick: close,
5465
5533
  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",
5466
- children: /* @__PURE__ */ jsx18(X3, { size: 20 })
5534
+ children: /* @__PURE__ */ jsx19(X3, { size: 20 })
5467
5535
  }
5468
5536
  ),
5469
- /* @__PURE__ */ jsx18("span", { className: "text-sm text-white/60", children: "\u52A0\u8F7D\u4E2D..." })
5537
+ /* @__PURE__ */ jsx19("span", { className: "text-sm text-white/60", children: "\u52A0\u8F7D\u4E2D..." })
5470
5538
  ]
5471
5539
  }
5472
5540
  ),
@@ -5477,46 +5545,46 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5477
5545
  const showNav = images.length > 1;
5478
5546
  return createPortal3(
5479
5547
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect
5480
- /* @__PURE__ */ jsxs14("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: handleAreaClick, children: [
5481
- /* @__PURE__ */ jsxs14(
5548
+ /* @__PURE__ */ jsxs15("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: handleAreaClick, children: [
5549
+ /* @__PURE__ */ jsxs15(
5482
5550
  "div",
5483
5551
  {
5484
5552
  className: "absolute right-4 top-4 z-10 flex items-center gap-1.5",
5485
5553
  onClick: (e) => e.stopPropagation(),
5486
5554
  children: [
5487
- /* @__PURE__ */ jsx18(
5555
+ /* @__PURE__ */ jsx19(
5488
5556
  "button",
5489
5557
  {
5490
5558
  type: "button",
5491
5559
  onClick: handleDownload,
5492
5560
  title: "\u4E0B\u8F7D\u56FE\u7247",
5493
5561
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
5494
- children: /* @__PURE__ */ jsx18(Download2, { size: 18 })
5562
+ children: /* @__PURE__ */ jsx19(Download2, { size: 18 })
5495
5563
  }
5496
5564
  ),
5497
- /* @__PURE__ */ jsx18(
5565
+ /* @__PURE__ */ jsx19(
5498
5566
  "button",
5499
5567
  {
5500
5568
  type: "button",
5501
5569
  onClick: handleOpenInNewTab,
5502
5570
  title: "\u65B0\u6807\u7B7E\u9875\u6253\u5F00",
5503
5571
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
5504
- children: /* @__PURE__ */ jsx18(ExternalLink, { size: 18 })
5572
+ children: /* @__PURE__ */ jsx19(ExternalLink, { size: 18 })
5505
5573
  }
5506
5574
  ),
5507
- /* @__PURE__ */ jsx18(
5575
+ /* @__PURE__ */ jsx19(
5508
5576
  "button",
5509
5577
  {
5510
5578
  type: "button",
5511
5579
  onClick: close,
5512
5580
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
5513
- children: /* @__PURE__ */ jsx18(X3, { size: 20 })
5581
+ children: /* @__PURE__ */ jsx19(X3, { size: 20 })
5514
5582
  }
5515
5583
  )
5516
5584
  ]
5517
5585
  }
5518
5586
  ),
5519
- showNav && currentIndex > 0 && /* @__PURE__ */ jsx18(
5587
+ showNav && currentIndex > 0 && /* @__PURE__ */ jsx19(
5520
5588
  "button",
5521
5589
  {
5522
5590
  type: "button",
@@ -5525,10 +5593,10 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5525
5593
  goPrev();
5526
5594
  },
5527
5595
  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",
5528
- children: /* @__PURE__ */ jsx18(ChevronLeft, { size: 24 })
5596
+ children: /* @__PURE__ */ jsx19(ChevronLeft, { size: 24 })
5529
5597
  }
5530
5598
  ),
5531
- showNav && currentIndex < images.length - 1 && /* @__PURE__ */ jsx18(
5599
+ showNav && currentIndex < images.length - 1 && /* @__PURE__ */ jsx19(
5532
5600
  "button",
5533
5601
  {
5534
5602
  type: "button",
@@ -5537,51 +5605,51 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5537
5605
  goNext();
5538
5606
  },
5539
5607
  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",
5540
- children: /* @__PURE__ */ jsx18(ChevronRight2, { size: 24 })
5608
+ children: /* @__PURE__ */ jsx19(ChevronRight2, { size: 24 })
5541
5609
  }
5542
5610
  ),
5543
- /* @__PURE__ */ jsxs14("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: [
5544
- /* @__PURE__ */ jsx18(
5611
+ /* @__PURE__ */ jsxs15("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: [
5612
+ /* @__PURE__ */ jsx19(
5545
5613
  "button",
5546
5614
  {
5547
5615
  type: "button",
5548
5616
  onClick: zoomOut,
5549
5617
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
5550
- children: /* @__PURE__ */ jsx18(Minus, { size: 16 })
5618
+ children: /* @__PURE__ */ jsx19(Minus, { size: 16 })
5551
5619
  }
5552
5620
  ),
5553
- /* @__PURE__ */ jsxs14("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5621
+ /* @__PURE__ */ jsxs15("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5554
5622
  Math.round(scale * 100),
5555
5623
  "%"
5556
5624
  ] }),
5557
- /* @__PURE__ */ jsx18(
5625
+ /* @__PURE__ */ jsx19(
5558
5626
  "button",
5559
5627
  {
5560
5628
  type: "button",
5561
5629
  onClick: zoomIn,
5562
5630
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
5563
- children: /* @__PURE__ */ jsx18(Plus2, { size: 16 })
5631
+ children: /* @__PURE__ */ jsx19(Plus2, { size: 16 })
5564
5632
  }
5565
5633
  ),
5566
- /* @__PURE__ */ jsx18(
5634
+ /* @__PURE__ */ jsx19(
5567
5635
  "button",
5568
5636
  {
5569
5637
  type: "button",
5570
5638
  onClick: reset,
5571
5639
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
5572
- children: /* @__PURE__ */ jsx18(RotateCcw2, { size: 16 })
5640
+ children: /* @__PURE__ */ jsx19(RotateCcw2, { size: 16 })
5573
5641
  }
5574
5642
  ),
5575
- showNav && /* @__PURE__ */ jsxs14(Fragment4, { children: [
5576
- /* @__PURE__ */ jsx18("div", { className: "mx-1 h-4 w-px bg-white/20" }),
5577
- /* @__PURE__ */ jsxs14("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5643
+ showNav && /* @__PURE__ */ jsxs15(Fragment4, { children: [
5644
+ /* @__PURE__ */ jsx19("div", { className: "mx-1 h-4 w-px bg-white/20" }),
5645
+ /* @__PURE__ */ jsxs15("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5578
5646
  currentIndex + 1,
5579
5647
  " / ",
5580
5648
  images.length
5581
5649
  ] })
5582
5650
  ] })
5583
5651
  ] }),
5584
- /* @__PURE__ */ jsx18(
5652
+ /* @__PURE__ */ jsx19(
5585
5653
  "div",
5586
5654
  {
5587
5655
  className: "flex h-full w-full items-center justify-center overflow-hidden p-12",
@@ -5592,7 +5660,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5592
5660
  onMouseUp: handleMouseUp,
5593
5661
  onMouseLeave: handleMouseUp,
5594
5662
  onDoubleClick: handleDoubleClick,
5595
- children: /* @__PURE__ */ jsx18(
5663
+ children: /* @__PURE__ */ jsx19(
5596
5664
  "img",
5597
5665
  {
5598
5666
  ref: imgRef,
@@ -5614,7 +5682,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
5614
5682
  }
5615
5683
 
5616
5684
  // src/react/components/chat/tool-renderers/FileReadRenderer.tsx
5617
- import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5685
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5618
5686
  var NUMBERED_LINE_RE = /^(\s*\d+)\t([\s\S]*)$/;
5619
5687
  function parseReadResult(result) {
5620
5688
  if (!result) {
@@ -5674,28 +5742,28 @@ function FileReadRenderer({ toolCall }) {
5674
5742
  const resolvedStartLine = startLine ?? (lineCount > 0 ? fallbackStart : null);
5675
5743
  const resolvedEndLine = endLine ?? (resolvedStartLine !== null && lineCount > 0 ? resolvedStartLine + lineCount - 1 : null);
5676
5744
  const lineRange = formatLineRange(resolvedStartLine, resolvedEndLine);
5677
- return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5678
- /* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-3", children: [
5679
- /* @__PURE__ */ jsxs15("div", { className: "min-w-0", children: [
5680
- /* @__PURE__ */ jsx19("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: fileName }),
5681
- filePath ? /* @__PURE__ */ jsx19("div", { className: "truncate text-[10px] text-[hsl(var(--muted-foreground))]", children: filePath }) : null
5745
+ return /* @__PURE__ */ jsxs16("div", { className: "space-y-3", children: [
5746
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between gap-3", children: [
5747
+ /* @__PURE__ */ jsxs16("div", { className: "min-w-0", children: [
5748
+ /* @__PURE__ */ jsx20("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: fileName }),
5749
+ filePath ? /* @__PURE__ */ jsx20("div", { className: "truncate text-[10px] text-[hsl(var(--muted-foreground))]", children: filePath }) : null
5682
5750
  ] }),
5683
- /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
5684
- lineRange ? /* @__PURE__ */ jsx19("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,
5685
- checksum ? /* @__PURE__ */ jsx19("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
5751
+ /* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
5752
+ lineRange ? /* @__PURE__ */ jsx20("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,
5753
+ checksum ? /* @__PURE__ */ jsx20("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
5686
5754
  ] })
5687
5755
  ] }),
5688
- description ? /* @__PURE__ */ jsx19("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,
5689
- errorMessage ? /* @__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 }) : null,
5690
- isImageResult ? /* @__PURE__ */ jsxs15("div", { className: "grid gap-2", children: [
5691
- imageUrls.map((url, idx) => /* @__PURE__ */ jsx19(
5756
+ description ? /* @__PURE__ */ jsx20("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,
5757
+ errorMessage ? /* @__PURE__ */ jsx20("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,
5758
+ isImageResult ? /* @__PURE__ */ jsxs16("div", { className: "grid gap-2", children: [
5759
+ imageUrls.map((url, idx) => /* @__PURE__ */ jsx20(
5692
5760
  "button",
5693
5761
  {
5694
5762
  type: "button",
5695
5763
  onClick: () => setLightboxIndex(idx),
5696
5764
  className: "cursor-zoom-in",
5697
5765
  title: "\u67E5\u770B\u5927\u56FE",
5698
- children: /* @__PURE__ */ jsx19(
5766
+ children: /* @__PURE__ */ jsx20(
5699
5767
  "img",
5700
5768
  {
5701
5769
  src: url,
@@ -5706,7 +5774,7 @@ function FileReadRenderer({ toolCall }) {
5706
5774
  },
5707
5775
  url.slice(0, 64)
5708
5776
  )),
5709
- /* @__PURE__ */ jsx19(
5777
+ /* @__PURE__ */ jsx20(
5710
5778
  ImageLightbox,
5711
5779
  {
5712
5780
  open: lightboxIndex != null,
@@ -5717,15 +5785,15 @@ function FileReadRenderer({ toolCall }) {
5717
5785
  initialIndex: lightboxIndex ?? 0
5718
5786
  }
5719
5787
  ),
5720
- content ? /* @__PURE__ */ jsx19("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: content }) : null
5721
- ] }) : !errorMessage ? /* @__PURE__ */ jsx19(CodePreview, { content, filePath, className: "max-h-[360px]" }) : null,
5722
- note ? /* @__PURE__ */ jsx19("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
5788
+ content ? /* @__PURE__ */ jsx20("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: content }) : null
5789
+ ] }) : !errorMessage ? /* @__PURE__ */ jsx20(CodePreview, { content, filePath, className: "max-h-[360px]" }) : null,
5790
+ note ? /* @__PURE__ */ jsx20("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
5723
5791
  ] });
5724
5792
  }
5725
5793
 
5726
5794
  // src/react/components/chat/tool-renderers/SearchRenderer.tsx
5727
5795
  import { ExternalLink as ExternalLink2, FileText as FileText3, Folder as Folder2, Globe2 } from "lucide-react";
5728
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5796
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5729
5797
  function toRecordArray(value) {
5730
5798
  return Array.isArray(value) ? value.filter(isPlainObject) : [];
5731
5799
  }
@@ -5787,7 +5855,7 @@ function parseWebFetchResult(result) {
5787
5855
  };
5788
5856
  }
5789
5857
  function renderEmptyState(label) {
5790
- return /* @__PURE__ */ jsx20("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 });
5858
+ return /* @__PURE__ */ jsx21("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 });
5791
5859
  }
5792
5860
  function SearchRenderer({ toolCall }) {
5793
5861
  const normalizedName = formatToolName(toolCall.name);
@@ -5796,26 +5864,26 @@ function SearchRenderer({ toolCall }) {
5796
5864
  const resultStr = getResultText(toolCall.result);
5797
5865
  const errorMessage = extractErrorMessage(resultStr);
5798
5866
  if (errorMessage) {
5799
- return /* @__PURE__ */ jsx20("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage });
5867
+ return /* @__PURE__ */ jsx21("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage });
5800
5868
  }
5801
5869
  if (normalizedName === "Ls" || normalizedName === "Glob") {
5802
5870
  const items = parseDirectoryItems(resultStr);
5803
5871
  const path = getStringValue(args, "path");
5804
- return /* @__PURE__ */ jsxs16("div", { className: "space-y-3", children: [
5805
- path ? /* @__PURE__ */ jsxs16("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5872
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-3", children: [
5873
+ path ? /* @__PURE__ */ jsxs17("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5806
5874
  "\u76EE\u5F55\uFF1A",
5807
5875
  path
5808
5876
  ] }) : null,
5809
- items.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "grid gap-2", children: items.map((item) => /* @__PURE__ */ jsxs16(
5877
+ items.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "grid gap-2", children: items.map((item) => /* @__PURE__ */ jsxs17(
5810
5878
  "div",
5811
5879
  {
5812
5880
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2",
5813
5881
  children: [
5814
- /* @__PURE__ */ jsxs16("div", { className: "flex min-w-0 items-center gap-2", children: [
5815
- item.isDir ? /* @__PURE__ */ jsx20(Folder2, { size: 14, className: "shrink-0 text-blue-300" }) : /* @__PURE__ */ jsx20(FileText3, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5816
- /* @__PURE__ */ jsx20("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: item.name })
5882
+ /* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 items-center gap-2", children: [
5883
+ item.isDir ? /* @__PURE__ */ jsx21(Folder2, { size: 14, className: "shrink-0 text-blue-300" }) : /* @__PURE__ */ jsx21(FileText3, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5884
+ /* @__PURE__ */ jsx21("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: item.name })
5817
5885
  ] }),
5818
- /* @__PURE__ */ jsx20("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: item.isDir ? "\u76EE\u5F55" : formatBytes(item.size) ?? "\u6587\u4EF6" })
5886
+ /* @__PURE__ */ jsx21("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: item.isDir ? "\u76EE\u5F55" : formatBytes(item.size) ?? "\u6587\u4EF6" })
5819
5887
  ]
5820
5888
  },
5821
5889
  `${item.name}-${item.size}-${item.isDir}`
@@ -5825,28 +5893,28 @@ function SearchRenderer({ toolCall }) {
5825
5893
  if (normalizedName === "Grep") {
5826
5894
  const { matches, searchPath } = parseGrepResult(resultStr);
5827
5895
  const pattern = getStringValue(args, "pattern");
5828
- return /* @__PURE__ */ jsxs16("div", { className: "space-y-3", children: [
5829
- /* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5830
- pattern ? /* @__PURE__ */ jsx20("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: pattern }) : null,
5831
- searchPath ? /* @__PURE__ */ jsxs16("span", { children: [
5896
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-3", children: [
5897
+ /* @__PURE__ */ jsxs17("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5898
+ pattern ? /* @__PURE__ */ jsx21("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: pattern }) : null,
5899
+ searchPath ? /* @__PURE__ */ jsxs17("span", { children: [
5832
5900
  "\u8303\u56F4\uFF1A",
5833
5901
  searchPath
5834
5902
  ] }) : null
5835
5903
  ] }),
5836
- matches.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "grid gap-2", children: matches.map((match) => /* @__PURE__ */ jsxs16(
5904
+ matches.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "grid gap-2", children: matches.map((match) => /* @__PURE__ */ jsxs17(
5837
5905
  "div",
5838
5906
  {
5839
5907
  className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2",
5840
5908
  children: [
5841
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between gap-3", children: [
5842
- /* @__PURE__ */ jsx20("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: match.path }),
5843
- match.lineNumber !== null ? /* @__PURE__ */ jsxs16("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5909
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between gap-3", children: [
5910
+ /* @__PURE__ */ jsx21("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: match.path }),
5911
+ match.lineNumber !== null ? /* @__PURE__ */ jsxs17("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5844
5912
  "\u7B2C ",
5845
5913
  match.lineNumber,
5846
5914
  " \u884C"
5847
5915
  ] }) : null
5848
5916
  ] }),
5849
- /* @__PURE__ */ jsx20("pre", { className: "mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx20("code", { children: match.line }) })
5917
+ /* @__PURE__ */ jsx21("pre", { className: "mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx21("code", { children: match.line }) })
5850
5918
  ]
5851
5919
  },
5852
5920
  `${match.path}-${match.lineNumber}-${match.line}`
@@ -5855,16 +5923,16 @@ function SearchRenderer({ toolCall }) {
5855
5923
  }
5856
5924
  const { results, summary } = normalizedName === "WebFetch" ? parseWebFetchResult(resultStr) : { results: parseWebResults(resultStr), summary: null };
5857
5925
  const query = getStringValue(args, "query");
5858
- return /* @__PURE__ */ jsxs16("div", { className: "space-y-3", children: [
5859
- query ? /* @__PURE__ */ jsxs16("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5926
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-3", children: [
5927
+ query ? /* @__PURE__ */ jsxs17("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5860
5928
  "\u67E5\u8BE2\uFF1A",
5861
5929
  query
5862
5930
  ] }) : null,
5863
- summary ? /* @__PURE__ */ jsxs16("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3", children: [
5864
- /* @__PURE__ */ jsx20("div", { className: "mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: "\u6458\u8981" }),
5865
- /* @__PURE__ */ jsx20("p", { className: "whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]", children: summary })
5931
+ summary ? /* @__PURE__ */ jsxs17("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3", children: [
5932
+ /* @__PURE__ */ jsx21("div", { className: "mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: "\u6458\u8981" }),
5933
+ /* @__PURE__ */ jsx21("p", { className: "whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]", children: summary })
5866
5934
  ] }) : null,
5867
- results.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "grid gap-2", children: results.map((item, index) => /* @__PURE__ */ jsx20(
5935
+ results.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "grid gap-2", children: results.map((item, index) => /* @__PURE__ */ jsx21(
5868
5936
  "a",
5869
5937
  {
5870
5938
  href: item.url ?? void 0,
@@ -5874,12 +5942,12 @@ function SearchRenderer({ toolCall }) {
5874
5942
  "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3 transition-colors",
5875
5943
  item.url && "hover:border-[hsl(var(--ring))] hover:bg-[hsl(var(--muted))]/35"
5876
5944
  ),
5877
- children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-3", children: [
5878
- /* @__PURE__ */ jsx20(Globe2, { size: 15, className: "mt-0.5 shrink-0 text-blue-300" }),
5879
- /* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1", children: [
5880
- /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between gap-3", children: [
5881
- /* @__PURE__ */ jsx20("span", { className: "line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]", children: item.title ?? item.url ?? "\u672A\u547D\u540D\u7ED3\u679C" }),
5882
- item.url ? /* @__PURE__ */ jsx20(
5945
+ children: /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-3", children: [
5946
+ /* @__PURE__ */ jsx21(Globe2, { size: 15, className: "mt-0.5 shrink-0 text-blue-300" }),
5947
+ /* @__PURE__ */ jsxs17("div", { className: "min-w-0 flex-1", children: [
5948
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-start justify-between gap-3", children: [
5949
+ /* @__PURE__ */ jsx21("span", { className: "line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]", children: item.title ?? item.url ?? "\u672A\u547D\u540D\u7ED3\u679C" }),
5950
+ item.url ? /* @__PURE__ */ jsx21(
5883
5951
  ExternalLink2,
5884
5952
  {
5885
5953
  size: 12,
@@ -5887,8 +5955,8 @@ function SearchRenderer({ toolCall }) {
5887
5955
  }
5888
5956
  ) : null
5889
5957
  ] }),
5890
- item.url ? /* @__PURE__ */ jsx20("div", { className: "mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.url }) : null,
5891
- item.description ? /* @__PURE__ */ jsx20("p", { className: "mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: item.description }) : null
5958
+ item.url ? /* @__PURE__ */ jsx21("div", { className: "mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.url }) : null,
5959
+ item.description ? /* @__PURE__ */ jsx21("p", { className: "mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: item.description }) : null
5892
5960
  ] })
5893
5961
  ] })
5894
5962
  },
@@ -5899,7 +5967,7 @@ function SearchRenderer({ toolCall }) {
5899
5967
 
5900
5968
  // src/react/components/chat/tool-renderers/SubmitResultRenderer.tsx
5901
5969
  import { CheckCircle2, CircleAlert } from "lucide-react";
5902
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5970
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
5903
5971
  function extractText(value, key) {
5904
5972
  if (!isPlainObject(value)) return null;
5905
5973
  const field = value[key];
@@ -5920,25 +5988,25 @@ function SubmitResultRenderer({ toolCall }) {
5920
5988
  const { description, result, error, status } = parsePayload(toolCall);
5921
5989
  const isError = toolCall.status === "error" || Boolean(error);
5922
5990
  const Icon = isError ? CircleAlert : CheckCircle2;
5923
- return /* @__PURE__ */ jsxs17("div", { className: "overflow-hidden rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-sm", children: [
5924
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-3 border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))]/25 px-4 py-3", children: [
5925
- /* @__PURE__ */ jsx21("div", { className: isError ? "text-red-500" : "text-emerald-500", children: /* @__PURE__ */ jsx21(Icon, { size: 18 }) }),
5926
- /* @__PURE__ */ jsxs17("div", { className: "min-w-0 flex-1", children: [
5927
- /* @__PURE__ */ jsx21("div", { className: "font-medium text-[hsl(var(--foreground))]", children: description || (isError ? "\u4EFB\u52A1\u6267\u884C\u5931\u8D25" : "\u4EFB\u52A1\u7ED3\u679C\u5DF2\u63D0\u4EA4") }),
5928
- description ? /* @__PURE__ */ jsx21("div", { className: "mt-0.5 text-xs text-[hsl(var(--muted-foreground))]", children: isError ? "\u4EFB\u52A1\u6267\u884C\u5931\u8D25" : "\u4EFB\u52A1\u7ED3\u679C\u5DF2\u63D0\u4EA4" }) : null,
5929
- status ? /* @__PURE__ */ jsxs17("div", { className: "mt-0.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
5991
+ return /* @__PURE__ */ jsxs18("div", { className: "overflow-hidden rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-sm", children: [
5992
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-3 border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))]/25 px-4 py-3", children: [
5993
+ /* @__PURE__ */ jsx22("div", { className: isError ? "text-red-500" : "text-emerald-500", children: /* @__PURE__ */ jsx22(Icon, { size: 18 }) }),
5994
+ /* @__PURE__ */ jsxs18("div", { className: "min-w-0 flex-1", children: [
5995
+ /* @__PURE__ */ jsx22("div", { className: "font-medium text-[hsl(var(--foreground))]", children: description || (isError ? "\u4EFB\u52A1\u6267\u884C\u5931\u8D25" : "\u4EFB\u52A1\u7ED3\u679C\u5DF2\u63D0\u4EA4") }),
5996
+ description ? /* @__PURE__ */ jsx22("div", { className: "mt-0.5 text-xs text-[hsl(var(--muted-foreground))]", children: isError ? "\u4EFB\u52A1\u6267\u884C\u5931\u8D25" : "\u4EFB\u52A1\u7ED3\u679C\u5DF2\u63D0\u4EA4" }) : null,
5997
+ status ? /* @__PURE__ */ jsxs18("div", { className: "mt-0.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
5930
5998
  "\u72B6\u6001\uFF1A",
5931
5999
  status
5932
6000
  ] }) : null
5933
6001
  ] })
5934
6002
  ] }),
5935
- /* @__PURE__ */ jsxs17("div", { className: "space-y-3 px-4 py-4 text-sm leading-6 text-[hsl(var(--foreground))]", children: [
5936
- result ? /* @__PURE__ */ jsx21("p", { className: "whitespace-pre-wrap", children: result }) : null,
5937
- error ? /* @__PURE__ */ jsxs17("div", { className: "rounded-xl border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-700 dark:text-red-200", children: [
5938
- /* @__PURE__ */ jsx21("div", { className: "mb-1 font-medium", children: "\u9519\u8BEF\u4FE1\u606F" }),
5939
- /* @__PURE__ */ jsx21("div", { className: "whitespace-pre-wrap", children: error })
6003
+ /* @__PURE__ */ jsxs18("div", { className: "space-y-3 px-4 py-4 text-sm leading-6 text-[hsl(var(--foreground))]", children: [
6004
+ result ? /* @__PURE__ */ jsx22("p", { className: "whitespace-pre-wrap", children: result }) : null,
6005
+ error ? /* @__PURE__ */ jsxs18("div", { className: "rounded-xl border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-700 dark:text-red-200", children: [
6006
+ /* @__PURE__ */ jsx22("div", { className: "mb-1 font-medium", children: "\u9519\u8BEF\u4FE1\u606F" }),
6007
+ /* @__PURE__ */ jsx22("div", { className: "whitespace-pre-wrap", children: error })
5940
6008
  ] }) : null,
5941
- !result && !error ? /* @__PURE__ */ jsx21("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u667A\u80FD\u4F53\u5DF2\u7ED3\u675F\u672C\u8F6E\u4EFB\u52A1\u3002" }) : null
6009
+ !result && !error ? /* @__PURE__ */ jsx22("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u667A\u80FD\u4F53\u5DF2\u7ED3\u675F\u672C\u8F6E\u4EFB\u52A1\u3002" }) : null
5942
6010
  ] })
5943
6011
  ] });
5944
6012
  }
@@ -5962,7 +6030,7 @@ function getRenderer(toolName) {
5962
6030
  }
5963
6031
 
5964
6032
  // src/react/components/chat/ToolCallBlock.tsx
5965
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
6033
+ import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
5966
6034
  function FilePathLink({ filePath, sessionId }) {
5967
6035
  const activeSessionId = useSessionStore((s) => s.activeSessionId);
5968
6036
  const pushArtifact = useUiStore((s) => s.pushArtifact);
@@ -5980,14 +6048,14 @@ function FilePathLink({ filePath, sessionId }) {
5980
6048
  } catch {
5981
6049
  }
5982
6050
  };
5983
- return /* @__PURE__ */ jsx22(
6051
+ return /* @__PURE__ */ jsx23(
5984
6052
  "button",
5985
6053
  {
5986
6054
  type: "button",
5987
6055
  onClick: handleClick,
5988
6056
  className: "flex min-w-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer font-mono",
5989
6057
  title: `\u9884\u89C8 ${filePath}`,
5990
- children: /* @__PURE__ */ jsx22("span", { className: "truncate", children: fileName })
6058
+ children: /* @__PURE__ */ jsx23("span", { className: "truncate", children: fileName })
5991
6059
  }
5992
6060
  );
5993
6061
  }
@@ -6038,7 +6106,7 @@ function ToolCallBlock({
6038
6106
  const askData = parseAskUserQuestion(typeof toolCall.result === "string" ? toolCall.result : null) ?? parseAskUserQuestion(buildAskUserPayload(toolCall.arguments));
6039
6107
  const canAnswer = toolCall.status === "awaiting_answer" && resolvedSessionStatus === "waiting_for_input" && Boolean(resolvedOnAnswer);
6040
6108
  if (askData) {
6041
- const questionBlock = /* @__PURE__ */ jsx22(
6109
+ const questionBlock = /* @__PURE__ */ jsx23(
6042
6110
  AskUserQuestionBlock,
6043
6111
  {
6044
6112
  data: askData,
@@ -6052,16 +6120,28 @@ function ToolCallBlock({
6052
6120
  if (!reasoning) {
6053
6121
  return questionBlock;
6054
6122
  }
6055
- return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1", children: [
6123
+ return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1", children: [
6056
6124
  questionBlock,
6057
- /* @__PURE__ */ jsx22("div", { className: "ml-4", children: /* @__PURE__ */ jsx22(ThinkingBadge, { reasoning, variant: "block" }) })
6125
+ /* @__PURE__ */ jsx23("div", { className: "ml-4", children: /* @__PURE__ */ jsx23(ThinkingBadge, { reasoning, variant: "block" }) })
6126
+ ] });
6127
+ }
6128
+ if (toolCall.status === "error") {
6129
+ return /* @__PURE__ */ jsxs19("div", { className: "ml-4 max-w-lg rounded-xl border border-red-500/30 bg-red-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
6130
+ /* @__PURE__ */ jsx23("div", { className: "font-semibold", children: "\u8FD9\u6B21\u63D0\u95EE\u672A\u80FD\u751F\u6210" }),
6131
+ /* @__PURE__ */ jsx23("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: "\u63D0\u95EE\u9009\u9879\u7684\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5F53\u524D\u6CA1\u6709\u7B49\u5F85\u4F60\u56DE\u7B54\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" })
6132
+ ] });
6133
+ }
6134
+ if (toolCall.status === "pending") {
6135
+ return /* @__PURE__ */ jsxs19("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
6136
+ /* @__PURE__ */ jsx23(Loader23, { size: 14, className: "animate-spin" }),
6137
+ /* @__PURE__ */ jsx23("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
6058
6138
  ] });
6059
6139
  }
6060
- return /* @__PURE__ */ jsxs18("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
6061
- /* @__PURE__ */ jsx22("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
6062
- /* @__PURE__ */ jsxs18("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: [
6140
+ return /* @__PURE__ */ jsxs19("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
6141
+ /* @__PURE__ */ jsx23("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
6142
+ /* @__PURE__ */ jsxs19("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: [
6063
6143
  "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u6216\u7248\u672C\u4E0D\u517C\u5BB9\u3002\u8BF7\u91CD\u8BD5\uFF1B\u82E5\u95EE\u9898\u6301\u7EED\uFF0C\u8BF7\u63D0\u4F9B\u4EA4\u4E92\u7F16\u53F7",
6064
- /* @__PURE__ */ jsx22("span", { className: "ml-1 font-mono", children: toolCall.id }),
6144
+ /* @__PURE__ */ jsx23("span", { className: "ml-1 font-mono", children: toolCall.id }),
6065
6145
  "\u3002"
6066
6146
  ] })
6067
6147
  ] });
@@ -6073,11 +6153,11 @@ function ToolCallBlock({
6073
6153
  const borderWidthClass = level === 2 ? "border-l-[2px]" : "border-l-[3px]";
6074
6154
  const indentClass = level === 2 ? "ml-3" : "ml-4";
6075
6155
  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))]";
6076
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx22(Loader23, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx22(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx22(X4, { size: 11 }) : /* @__PURE__ */ jsx22(Check2, { size: 11 });
6156
+ const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx23(Loader23, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx23(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx23(X4, { size: 11 }) : /* @__PURE__ */ jsx23(Check2, { size: 11 });
6077
6157
  const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
6078
- return /* @__PURE__ */ jsxs18("div", { className: cn(indentClass, "text-xs", customization?.classNames?.toolCall), children: [
6079
- /* @__PURE__ */ jsxs18("div", { className: cn(borderWidthClass, toneClass, "flex items-center gap-2 px-3 py-2"), children: [
6080
- /* @__PURE__ */ jsxs18(
6158
+ return /* @__PURE__ */ jsxs19("div", { className: cn(indentClass, "text-xs", customization?.classNames?.toolCall), children: [
6159
+ /* @__PURE__ */ jsxs19("div", { className: cn(borderWidthClass, toneClass, "flex items-center gap-2 px-3 py-2"), children: [
6160
+ /* @__PURE__ */ jsxs19(
6081
6161
  "button",
6082
6162
  {
6083
6163
  type: "button",
@@ -6085,7 +6165,7 @@ function ToolCallBlock({
6085
6165
  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",
6086
6166
  "aria-expanded": expanded,
6087
6167
  children: [
6088
- /* @__PURE__ */ jsx22(
6168
+ /* @__PURE__ */ jsx23(
6089
6169
  ChevronRight3,
6090
6170
  {
6091
6171
  size: 11,
@@ -6095,21 +6175,21 @@ function ToolCallBlock({
6095
6175
  )
6096
6176
  }
6097
6177
  ),
6098
- /* @__PURE__ */ jsxs18("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
6178
+ /* @__PURE__ */ jsxs19("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
6099
6179
  statusIcon,
6100
- /* @__PURE__ */ jsx22("span", { children: getToolStatusLabel(toolCall.status) })
6180
+ /* @__PURE__ */ jsx23("span", { children: getToolStatusLabel(toolCall.status) })
6101
6181
  ] }),
6102
- /* @__PURE__ */ jsxs18("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: [
6182
+ /* @__PURE__ */ jsxs19("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: [
6103
6183
  displayName,
6104
6184
  toolCall.status === "error" ? "\uFF08\u5F85\u91CD\u8BD5\uFF09" : ""
6105
6185
  ] })
6106
6186
  ]
6107
6187
  }
6108
6188
  ),
6109
- filePath && /* @__PURE__ */ jsx22("span", { className: "flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx22(FilePathLink, { filePath, sessionId: resolvedSessionId }) }),
6110
- reasoning ? /* @__PURE__ */ jsx22(ThinkingBadge, { reasoning, variant: "block" }) : null,
6111
- typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx22("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) }),
6112
- uiMeta?.target === "preview" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? /* @__PURE__ */ jsxs18(
6189
+ filePath && /* @__PURE__ */ jsx23("span", { className: "flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx23(FilePathLink, { filePath, sessionId: resolvedSessionId }) }),
6190
+ reasoning ? /* @__PURE__ */ jsx23(ThinkingBadge, { reasoning, variant: "block" }) : null,
6191
+ typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx23("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) }),
6192
+ uiMeta?.target === "preview" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? /* @__PURE__ */ jsxs19(
6113
6193
  "button",
6114
6194
  {
6115
6195
  type: "button",
@@ -6127,20 +6207,20 @@ function ToolCallBlock({
6127
6207
  className: "inline-flex shrink-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer",
6128
6208
  title: `\u6253\u5F00 ${uiMeta.title ?? displayName}`,
6129
6209
  children: [
6130
- /* @__PURE__ */ jsx22(PanelRightOpen, { size: 11 }),
6131
- /* @__PURE__ */ jsx22("span", { children: uiMeta.title ?? displayName })
6210
+ /* @__PURE__ */ jsx23(PanelRightOpen, { size: 11 }),
6211
+ /* @__PURE__ */ jsx23("span", { children: uiMeta.title ?? displayName })
6132
6212
  ]
6133
6213
  }
6134
6214
  ) : null
6135
6215
  ] }),
6136
- expanded && /* @__PURE__ */ jsx22("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: Renderer ? /* @__PURE__ */ jsx22(Renderer, { toolCall, sessionId: resolvedSessionId }) : /* @__PURE__ */ jsxs18(Fragment5, { children: [
6137
- /* @__PURE__ */ jsx22("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
6138
- /* @__PURE__ */ jsx22("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
6139
- /* @__PURE__ */ jsx22("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
6140
- /* @__PURE__ */ jsx22("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) }),
6141
- toolCall.result != null && /* @__PURE__ */ jsxs18(Fragment5, { children: [
6142
- /* @__PURE__ */ jsx22("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
6143
- /* @__PURE__ */ jsx22(
6216
+ expanded && /* @__PURE__ */ jsx23("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: Renderer ? /* @__PURE__ */ jsx23(Renderer, { toolCall, sessionId: resolvedSessionId }) : /* @__PURE__ */ jsxs19(Fragment5, { children: [
6217
+ /* @__PURE__ */ jsx23("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
6218
+ /* @__PURE__ */ jsx23("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
6219
+ /* @__PURE__ */ jsx23("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
6220
+ /* @__PURE__ */ jsx23("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) }),
6221
+ toolCall.result != null && /* @__PURE__ */ jsxs19(Fragment5, { children: [
6222
+ /* @__PURE__ */ jsx23("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
6223
+ /* @__PURE__ */ jsx23(
6144
6224
  "pre",
6145
6225
  {
6146
6226
  className: cn(
@@ -6332,7 +6412,7 @@ import { Download as Download3, X as X5 } from "lucide-react";
6332
6412
  import { useEffect as useEffect13 } from "react";
6333
6413
  import { createPortal as createPortal4 } from "react-dom";
6334
6414
  import { useQuery as useQuery6 } from "@tanstack/react-query";
6335
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
6415
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
6336
6416
  function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
6337
6417
  useEffect13(() => {
6338
6418
  if (!open) return;
@@ -6360,7 +6440,7 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
6360
6440
  staleTime: 6e4
6361
6441
  });
6362
6442
  if (!open) return null;
6363
- const body = /* @__PURE__ */ jsx23(
6443
+ const body = /* @__PURE__ */ jsx24(
6364
6444
  "div",
6365
6445
  {
6366
6446
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",
@@ -6371,17 +6451,17 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
6371
6451
  role: "dialog",
6372
6452
  "aria-modal": "true",
6373
6453
  "aria-labelledby": "attachment-preview-title",
6374
- children: /* @__PURE__ */ jsxs19(
6454
+ children: /* @__PURE__ */ jsxs20(
6375
6455
  "div",
6376
6456
  {
6377
6457
  className: "max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl",
6378
6458
  onClick: (e) => e.stopPropagation(),
6379
6459
  onKeyDown: (e) => e.stopPropagation(),
6380
6460
  children: [
6381
- /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
6382
- /* @__PURE__ */ jsx23("h3", { id: "attachment-preview-title", className: "truncate text-sm font-semibold text-[hsl(var(--foreground))]", children: filename }),
6383
- /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1", children: [
6384
- url && /* @__PURE__ */ jsx23(
6461
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
6462
+ /* @__PURE__ */ jsx24("h3", { id: "attachment-preview-title", className: "truncate text-sm font-semibold text-[hsl(var(--foreground))]", children: filename }),
6463
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-1", children: [
6464
+ url && /* @__PURE__ */ jsx24(
6385
6465
  "a",
6386
6466
  {
6387
6467
  href: url,
@@ -6390,22 +6470,22 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
6390
6470
  rel: "noopener noreferrer",
6391
6471
  title: "\u4E0B\u8F7D",
6392
6472
  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))]",
6393
- children: /* @__PURE__ */ jsx23(Download3, { size: 14 })
6473
+ children: /* @__PURE__ */ jsx24(Download3, { size: 14 })
6394
6474
  }
6395
6475
  ),
6396
- /* @__PURE__ */ jsx23(
6476
+ /* @__PURE__ */ jsx24(
6397
6477
  "button",
6398
6478
  {
6399
6479
  type: "button",
6400
6480
  onClick: () => onOpenChange(false),
6401
6481
  title: "\u5173\u95ED",
6402
6482
  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))]",
6403
- children: /* @__PURE__ */ jsx23(X5, { size: 14 })
6483
+ children: /* @__PURE__ */ jsx24(X5, { size: 14 })
6404
6484
  }
6405
6485
  )
6406
6486
  ] })
6407
6487
  ] }),
6408
- /* @__PURE__ */ jsx23("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 }) })
6488
+ /* @__PURE__ */ jsx24("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 }) })
6409
6489
  ]
6410
6490
  }
6411
6491
  )
@@ -6420,43 +6500,43 @@ function renderContent({
6420
6500
  error
6421
6501
  }) {
6422
6502
  if (!url) {
6423
- return /* @__PURE__ */ jsx23("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B64\u9644\u4EF6\u6682\u65E0\u53EF\u7528\u9884\u89C8\u5730\u5740\u3002" });
6503
+ return /* @__PURE__ */ jsx24("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B64\u9644\u4EF6\u6682\u65E0\u53EF\u7528\u9884\u89C8\u5730\u5740\u3002" });
6424
6504
  }
6425
6505
  if (mode === "default") {
6426
- return /* @__PURE__ */ jsxs19("p", { className: "text-[hsl(var(--muted-foreground))]", children: [
6506
+ return /* @__PURE__ */ jsxs20("p", { className: "text-[hsl(var(--muted-foreground))]", children: [
6427
6507
  "\u6B64\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u5185\u5D4C\u9884\u89C8\u3002\u8BF7\u70B9\u51FB\u53F3\u4E0A\u89D2",
6428
- /* @__PURE__ */ jsx23("span", { className: "mx-1 font-medium text-[hsl(var(--foreground))]", children: "\u4E0B\u8F7D" }),
6508
+ /* @__PURE__ */ jsx24("span", { className: "mx-1 font-medium text-[hsl(var(--foreground))]", children: "\u4E0B\u8F7D" }),
6429
6509
  "\u6309\u94AE\u67E5\u770B\u3002"
6430
6510
  ] });
6431
6511
  }
6432
6512
  if (error) {
6433
- return /* @__PURE__ */ jsxs19("p", { className: "text-[hsl(var(--destructive))]", children: [
6513
+ return /* @__PURE__ */ jsxs20("p", { className: "text-[hsl(var(--destructive))]", children: [
6434
6514
  "\u52A0\u8F7D\u5931\u8D25\uFF1A",
6435
6515
  String(error?.message ?? error)
6436
6516
  ] });
6437
6517
  }
6438
6518
  if (content == null) {
6439
- return /* @__PURE__ */ jsx23("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u4E2D\u2026" });
6519
+ return /* @__PURE__ */ jsx24("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u4E2D\u2026" });
6440
6520
  }
6441
6521
  if (mode === "markdown") {
6442
- return /* @__PURE__ */ jsx23(MarkdownContent, { className: "prose prose-sm prose-invert max-w-none", children: content });
6522
+ return /* @__PURE__ */ jsx24(MarkdownContent, { className: "prose prose-sm prose-invert max-w-none", children: content });
6443
6523
  }
6444
- return /* @__PURE__ */ jsx23("pre", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed", children: content });
6524
+ return /* @__PURE__ */ jsx24("pre", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed", children: content });
6445
6525
  }
6446
6526
 
6447
6527
  // src/react/components/chat/MessageContextPills.tsx
6448
6528
  import { Bookmark } from "lucide-react";
6449
- import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
6529
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
6450
6530
  function MessageContextPills({ contexts }) {
6451
6531
  if (contexts.length === 0) return null;
6452
- return /* @__PURE__ */ jsx24("div", { className: "flex flex-wrap gap-1.5", children: contexts.map((ctx, index) => /* @__PURE__ */ jsxs20(
6532
+ return /* @__PURE__ */ jsx25("div", { className: "flex flex-wrap gap-1.5", children: contexts.map((ctx, index) => /* @__PURE__ */ jsxs21(
6453
6533
  "div",
6454
6534
  {
6455
6535
  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)]",
6456
6536
  title: ctx.content,
6457
6537
  children: [
6458
- /* @__PURE__ */ jsx24(Bookmark, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.65)]" }),
6459
- /* @__PURE__ */ jsx24("span", { className: "max-w-56 truncate", children: ctx.label })
6538
+ /* @__PURE__ */ jsx25(Bookmark, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.65)]" }),
6539
+ /* @__PURE__ */ jsx25("span", { className: "max-w-56 truncate", children: ctx.label })
6460
6540
  ]
6461
6541
  },
6462
6542
  `${ctx.label}:${index}`
@@ -6465,7 +6545,7 @@ function MessageContextPills({ contexts }) {
6465
6545
 
6466
6546
  // src/react/components/chat/MessageFileAttachmentList.tsx
6467
6547
  import { Archive as Archive2, File as File3, FileCode2 as FileCode22, FileText as FileText4, Film as Film2, Music as Music2 } from "lucide-react";
6468
- import { Fragment as Fragment6, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
6548
+ import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
6469
6549
  function getFileIcon(fileName) {
6470
6550
  const lowerName = fileName.toLowerCase();
6471
6551
  if (/\.(zip|rar|7z|tar|gz|bz2|xz)$/.test(lowerName)) {
@@ -6494,15 +6574,15 @@ function MessageFileAttachmentList({
6494
6574
  return null;
6495
6575
  }
6496
6576
  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))]";
6497
- return /* @__PURE__ */ jsx25("div", { className: cn("flex flex-wrap gap-1.5", className), children: files.map((file) => {
6577
+ return /* @__PURE__ */ jsx26("div", { className: cn("flex flex-wrap gap-1.5", className), children: files.map((file) => {
6498
6578
  const Icon = getFileIcon(file.name);
6499
6579
  const key = `${file.name}-${file.data.slice(0, 32)}`;
6500
- const content = /* @__PURE__ */ jsxs21(Fragment6, { children: [
6501
- /* @__PURE__ */ jsx25(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
6502
- /* @__PURE__ */ jsx25("span", { className: "max-w-32 truncate", children: file.name })
6580
+ const content = /* @__PURE__ */ jsxs22(Fragment6, { children: [
6581
+ /* @__PURE__ */ jsx26(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
6582
+ /* @__PURE__ */ jsx26("span", { className: "max-w-32 truncate", children: file.name })
6503
6583
  ] });
6504
6584
  if (onPreview) {
6505
- return /* @__PURE__ */ jsx25(
6585
+ return /* @__PURE__ */ jsx26(
6506
6586
  "button",
6507
6587
  {
6508
6588
  type: "button",
@@ -6514,14 +6594,14 @@ function MessageFileAttachmentList({
6514
6594
  key
6515
6595
  );
6516
6596
  }
6517
- return /* @__PURE__ */ jsx25("div", { className: pillClass, title: file.name, children: content }, key);
6597
+ return /* @__PURE__ */ jsx26("div", { className: pillClass, title: file.name, children: content }, key);
6518
6598
  }) });
6519
6599
  }
6520
6600
 
6521
6601
  // src/react/components/chat/MessageActions.tsx
6522
6602
  import { Check as Check3, Copy } from "lucide-react";
6523
6603
  import { useState as useState15 } from "react";
6524
- import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
6604
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
6525
6605
  function MessageActions({ content, className }) {
6526
6606
  const [copied, setCopied] = useState15(false);
6527
6607
  const handleCopy = async () => {
@@ -6531,7 +6611,7 @@ function MessageActions({ content, className }) {
6531
6611
  setTimeout(() => setCopied(false), 2e3);
6532
6612
  }
6533
6613
  };
6534
- return /* @__PURE__ */ jsx26("div", { className: cn("flex items-center gap-1 mt-1.5", className), children: /* @__PURE__ */ jsxs22(
6614
+ return /* @__PURE__ */ jsx27("div", { className: cn("flex items-center gap-1 mt-1.5", className), children: /* @__PURE__ */ jsxs23(
6535
6615
  "button",
6536
6616
  {
6537
6617
  type: "button",
@@ -6541,8 +6621,8 @@ function MessageActions({ content, className }) {
6541
6621
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]"
6542
6622
  ),
6543
6623
  children: [
6544
- copied ? /* @__PURE__ */ jsx26(Check3, { size: 12 }) : /* @__PURE__ */ jsx26(Copy, { size: 12 }),
6545
- /* @__PURE__ */ jsx26("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
6624
+ copied ? /* @__PURE__ */ jsx27(Check3, { size: 12 }) : /* @__PURE__ */ jsx27(Copy, { size: 12 }),
6625
+ /* @__PURE__ */ jsx27("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
6546
6626
  ]
6547
6627
  }
6548
6628
  ) });
@@ -6550,7 +6630,7 @@ function MessageActions({ content, className }) {
6550
6630
 
6551
6631
  // src/react/components/chat/TextAttachmentPills.tsx
6552
6632
  import { Archive as Archive3, File as File4, FileCode2 as FileCode23, FileText as FileText5, Film as Film3, Music as Music3, FileSpreadsheet, Image } from "lucide-react";
6553
- import { Fragment as Fragment7, jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
6633
+ import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
6554
6634
  function getFileIcon2(fileName) {
6555
6635
  const lower2 = fileName.toLowerCase();
6556
6636
  if (/\.(zip|rar|7z|tar|gz)$/.test(lower2)) return Archive3;
@@ -6565,15 +6645,15 @@ function getFileIcon2(fileName) {
6565
6645
  function TextAttachmentPills({ attachments, onPreview }) {
6566
6646
  if (attachments.length === 0) return null;
6567
6647
  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)]";
6568
- return /* @__PURE__ */ jsx27("div", { className: "flex flex-wrap gap-1.5", children: attachments.map((att, index) => {
6648
+ return /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1.5", children: attachments.map((att, index) => {
6569
6649
  const Icon = getFileIcon2(att.name);
6570
6650
  const key = `${att.uploadedPath ?? att.name}:${att.name}:${index}`;
6571
- const content = /* @__PURE__ */ jsxs23(Fragment7, { children: [
6572
- /* @__PURE__ */ jsx27(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.6)]" }),
6573
- /* @__PURE__ */ jsx27("span", { className: "max-w-40 truncate", children: att.name })
6651
+ const content = /* @__PURE__ */ jsxs24(Fragment7, { children: [
6652
+ /* @__PURE__ */ jsx28(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.6)]" }),
6653
+ /* @__PURE__ */ jsx28("span", { className: "max-w-40 truncate", children: att.name })
6574
6654
  ] });
6575
6655
  if (onPreview) {
6576
- return /* @__PURE__ */ jsx27(
6656
+ return /* @__PURE__ */ jsx28(
6577
6657
  "button",
6578
6658
  {
6579
6659
  type: "button",
@@ -6585,7 +6665,7 @@ function TextAttachmentPills({ attachments, onPreview }) {
6585
6665
  key
6586
6666
  );
6587
6667
  }
6588
- return /* @__PURE__ */ jsx27("div", { className: pillClass, title: att.name, children: content }, key);
6668
+ return /* @__PURE__ */ jsx28("div", { className: pillClass, title: att.name, children: content }, key);
6589
6669
  }) });
6590
6670
  }
6591
6671
 
@@ -6594,34 +6674,34 @@ import { RefreshCcw } from "lucide-react";
6594
6674
 
6595
6675
  // src/react/components/chat/whatif-quote-context.tsx
6596
6676
  import { createContext as createContext3, useContext as useContext3, useMemo as useMemo14 } from "react";
6597
- import { jsx as jsx28 } from "react/jsx-runtime";
6677
+ import { jsx as jsx29 } from "react/jsx-runtime";
6598
6678
  var WhatIfQuoteContext = createContext3({});
6599
6679
  function WhatIfQuoteProvider({
6600
6680
  onJumpToStep,
6601
6681
  children
6602
6682
  }) {
6603
6683
  const value = useMemo14(() => ({ onJumpToStep }), [onJumpToStep]);
6604
- return /* @__PURE__ */ jsx28(WhatIfQuoteContext.Provider, { value, children });
6684
+ return /* @__PURE__ */ jsx29(WhatIfQuoteContext.Provider, { value, children });
6605
6685
  }
6606
6686
  function useWhatIfQuoteContext() {
6607
6687
  return useContext3(WhatIfQuoteContext);
6608
6688
  }
6609
6689
 
6610
6690
  // src/react/components/chat/WhatIfUserBubble.tsx
6611
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
6691
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
6612
6692
  function WhatIfUserBubble({ parsed, onQuoteClick }) {
6613
6693
  const { onJumpToStep } = useWhatIfQuoteContext();
6614
6694
  const handleQuoteClick = onQuoteClick ?? onJumpToStep;
6615
6695
  const { fromStep, quotes, userText } = parsed;
6616
- return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col items-end gap-2", children: [
6617
- /* @__PURE__ */ jsxs24("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: [
6618
- /* @__PURE__ */ jsx29(RefreshCcw, { size: 10 }),
6619
- /* @__PURE__ */ jsx29("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
6696
+ return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col items-end gap-2", children: [
6697
+ /* @__PURE__ */ jsxs25("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: [
6698
+ /* @__PURE__ */ jsx30(RefreshCcw, { size: 10 }),
6699
+ /* @__PURE__ */ jsx30("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
6620
6700
  ] }),
6621
- quotes.length > 0 && /* @__PURE__ */ jsx29("div", { className: "flex flex-wrap justify-end gap-1.5", children: quotes.map((q, i) => {
6701
+ quotes.length > 0 && /* @__PURE__ */ jsx30("div", { className: "flex flex-wrap justify-end gap-1.5", children: quotes.map((q, i) => {
6622
6702
  const clickable = q.stepNumber != null && !!handleQuoteClick;
6623
6703
  const label = q.stepNumber != null ? `\u6B65\u9AA4${q.stepNumber} \xB7 ${q.label}` : q.label;
6624
- return /* @__PURE__ */ jsxs24(
6704
+ return /* @__PURE__ */ jsxs25(
6625
6705
  "button",
6626
6706
  {
6627
6707
  type: "button",
@@ -6630,14 +6710,14 @@ function WhatIfUserBubble({ parsed, onQuoteClick }) {
6630
6710
  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))]",
6631
6711
  title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0,
6632
6712
  children: [
6633
- /* @__PURE__ */ jsx29("span", { children: "\u21B3" }),
6634
- /* @__PURE__ */ jsx29("span", { className: "max-w-[14rem] truncate", children: label })
6713
+ /* @__PURE__ */ jsx30("span", { children: "\u21B3" }),
6714
+ /* @__PURE__ */ jsx30("span", { className: "max-w-[14rem] truncate", children: label })
6635
6715
  ]
6636
6716
  },
6637
6717
  `${q.stepNumber ?? "x"}-${i}`
6638
6718
  );
6639
6719
  }) }),
6640
- userText && /* @__PURE__ */ jsx29("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__ */ jsx29(
6720
+ userText && /* @__PURE__ */ jsx30("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__ */ jsx30(
6641
6721
  MarkdownContent,
6642
6722
  {
6643
6723
  className: "prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0",
@@ -6649,14 +6729,14 @@ function WhatIfUserBubble({ parsed, onQuoteClick }) {
6649
6729
  }
6650
6730
 
6651
6731
  // src/react/components/chat/UserMessageBubble.tsx
6652
- import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
6732
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
6653
6733
  function isUserMessage(message) {
6654
6734
  return message.role === "user";
6655
6735
  }
6656
6736
  function isErrorMessage(message) {
6657
6737
  return message.role === "error";
6658
6738
  }
6659
- var USER_MESSAGE_MARKDOWN_CLASS = "prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_li>p]:whitespace-pre-wrap [&_p]:mb-3 [&_p]:whitespace-pre-wrap [&_p:last-child]:mb-0";
6739
+ var USER_MESSAGE_MARKDOWN_CLASS = "prose prose-invert chat-prose max-w-none [&_li>p]:inline [&_li>p]:whitespace-pre-wrap [&_p]:whitespace-pre-wrap";
6660
6740
  function isImageTextAttachment(name, uploadedPath) {
6661
6741
  return isImageFilename(name) || isImageFilename(uploadedPath ?? "");
6662
6742
  }
@@ -6679,9 +6759,9 @@ function UserMessageBubble({ message, className }) {
6679
6759
  const trimmedClean = cleanText.trim();
6680
6760
  const whatifParsed = trimmedClean && imageParts.length === 0 && fileParts.length === 0 && textAttachments.length === 0 ? parseWhatIfPrompt(cleanText) : null;
6681
6761
  if (whatifParsed) {
6682
- return /* @__PURE__ */ jsx30("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs25("div", { className: "group flex max-w-[72%] flex-col items-end gap-2", children: [
6683
- /* @__PURE__ */ jsx30(WhatIfUserBubble, { parsed: whatifParsed }),
6684
- whatifParsed.userText && /* @__PURE__ */ jsx30(
6762
+ return /* @__PURE__ */ jsx31("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs26("div", { className: "group flex max-w-[72%] flex-col items-end gap-2", children: [
6763
+ /* @__PURE__ */ jsx31(WhatIfUserBubble, { parsed: whatifParsed }),
6764
+ whatifParsed.userText && /* @__PURE__ */ jsx31(
6685
6765
  MessageActions,
6686
6766
  {
6687
6767
  content: whatifParsed.userText,
@@ -6753,16 +6833,16 @@ function UserMessageBubble({ message, className }) {
6753
6833
  const mode = kind === "text" ? lower2.endsWith(".md") ? "markdown" : "text" : "default";
6754
6834
  setPreview({ filename: attachment.name, url, mode });
6755
6835
  };
6756
- return /* @__PURE__ */ jsx30("div", { className: cn("flex justify-end", className), children: /* @__PURE__ */ jsxs25("div", { className: "group flex max-w-[72%] flex-col items-end gap-3", children: [
6757
- (imageParts.length > 0 || imageTextAttachmentMeta.length > 0) && /* @__PURE__ */ jsxs25("div", { className: "grid gap-2", children: [
6758
- imageParts.map((part, idx) => /* @__PURE__ */ jsx30(
6836
+ return /* @__PURE__ */ jsx31("div", { className: cn("flex justify-end", className), children: /* @__PURE__ */ jsxs26("div", { className: "group flex max-w-[72%] flex-col items-end gap-3", children: [
6837
+ (imageParts.length > 0 || imageTextAttachmentMeta.length > 0) && /* @__PURE__ */ jsxs26("div", { className: "grid gap-2", children: [
6838
+ imageParts.map((part, idx) => /* @__PURE__ */ jsx31(
6759
6839
  "button",
6760
6840
  {
6761
6841
  type: "button",
6762
6842
  onClick: () => setLightboxIndex(idx),
6763
6843
  className: "cursor-zoom-in",
6764
6844
  title: "\u67E5\u770B\u5927\u56FE",
6765
- children: /* @__PURE__ */ jsx30(
6845
+ children: /* @__PURE__ */ jsx31(
6766
6846
  "img",
6767
6847
  {
6768
6848
  src: part.image_url.url,
@@ -6775,14 +6855,14 @@ function UserMessageBubble({ message, className }) {
6775
6855
  )),
6776
6856
  imageTextAttachmentMeta.map((att, idx) => {
6777
6857
  const blobUrl = imageAttachmentQueries[idx]?.data;
6778
- return blobUrl ? /* @__PURE__ */ jsx30(
6858
+ return blobUrl ? /* @__PURE__ */ jsx31(
6779
6859
  "button",
6780
6860
  {
6781
6861
  type: "button",
6782
6862
  onClick: () => setLightboxIndex(imageParts.length + idx),
6783
6863
  className: "cursor-zoom-in",
6784
6864
  title: "\u67E5\u770B\u5927\u56FE",
6785
- children: /* @__PURE__ */ jsx30(
6865
+ children: /* @__PURE__ */ jsx31(
6786
6866
  "img",
6787
6867
  {
6788
6868
  src: blobUrl,
@@ -6792,7 +6872,7 @@ function UserMessageBubble({ message, className }) {
6792
6872
  )
6793
6873
  },
6794
6874
  `${att.uploadedPath}:${att.name}`
6795
- ) : imageAttachmentQueries[idx]?.isError ? null : /* @__PURE__ */ jsx30(
6875
+ ) : imageAttachmentQueries[idx]?.isError ? null : /* @__PURE__ */ jsx31(
6796
6876
  "div",
6797
6877
  {
6798
6878
  className: "flex h-20 items-center justify-center rounded-xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--muted)/0.3)] text-xs text-[hsl(var(--muted-foreground))]",
@@ -6802,7 +6882,7 @@ function UserMessageBubble({ message, className }) {
6802
6882
  );
6803
6883
  })
6804
6884
  ] }),
6805
- lightboxImages.length > 0 && /* @__PURE__ */ jsx30(
6885
+ lightboxImages.length > 0 && /* @__PURE__ */ jsx31(
6806
6886
  ImageLightbox,
6807
6887
  {
6808
6888
  open: lightboxIndex != null,
@@ -6813,15 +6893,15 @@ function UserMessageBubble({ message, className }) {
6813
6893
  initialIndex: lightboxIndex ?? 0
6814
6894
  }
6815
6895
  ),
6816
- /* @__PURE__ */ jsx30(MessageFileAttachmentList, { files: fileParts }),
6817
- /* @__PURE__ */ jsx30(
6896
+ /* @__PURE__ */ jsx31(MessageFileAttachmentList, { files: fileParts }),
6897
+ /* @__PURE__ */ jsx31(
6818
6898
  TextAttachmentPills,
6819
6899
  {
6820
6900
  attachments: nonImageTextAttachments,
6821
6901
  onPreview: handleTextAttachmentPreview
6822
6902
  }
6823
6903
  ),
6824
- preview && /* @__PURE__ */ jsx30(
6904
+ preview && /* @__PURE__ */ jsx31(
6825
6905
  AttachmentPreviewDialog,
6826
6906
  {
6827
6907
  open: preview != null,
@@ -6833,8 +6913,9 @@ function UserMessageBubble({ message, className }) {
6833
6913
  mode: preview.mode
6834
6914
  }
6835
6915
  ),
6836
- /* @__PURE__ */ jsx30(MessageContextPills, { contexts: textContexts }),
6837
- trimmedClean && /* @__PURE__ */ jsx30("div", { className: "max-w-full 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__ */ jsx30(
6916
+ /* @__PURE__ */ jsx31(MessageContextPills, { contexts: textContexts }),
6917
+ trimmedClean && // 原型:不对称圆角(指向发送侧的一角收窄),无边框、无内阴影。
6918
+ /* @__PURE__ */ jsx31("div", { className: "max-w-full rounded-[20px] rounded-br-[6px] border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-[18px] py-[13px] text-sm leading-[1.65] text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx31(
6838
6919
  MarkdownContent,
6839
6920
  {
6840
6921
  className: USER_MESSAGE_MARKDOWN_CLASS,
@@ -6842,10 +6923,10 @@ function UserMessageBubble({ message, className }) {
6842
6923
  children: cleanText
6843
6924
  }
6844
6925
  ) }),
6845
- trimmedClean && (isSending(message) ? /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-1.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
6846
- /* @__PURE__ */ jsx30(Loader24, { size: 12, className: "animate-spin" }),
6847
- /* @__PURE__ */ jsx30("span", { children: "\u53D1\u9001\u4E2D" })
6848
- ] }) : /* @__PURE__ */ jsx30(
6926
+ trimmedClean && (isSending(message) ? /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
6927
+ /* @__PURE__ */ jsx31(Loader24, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
6928
+ /* @__PURE__ */ jsx31("span", { children: "\u53D1\u9001\u4E2D" })
6929
+ ] }) : /* @__PURE__ */ jsx31(
6849
6930
  MessageActions,
6850
6931
  {
6851
6932
  content: cleanText,
@@ -6860,14 +6941,14 @@ function ErrorMessageBlock({
6860
6941
  }) {
6861
6942
  const text = getTextContent(message.content);
6862
6943
  const looksLikeModelUnavailable = /no source matches this model|404/i.test(text);
6863
- return /* @__PURE__ */ jsx30("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsxs25("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: [
6944
+ return /* @__PURE__ */ jsx31("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsxs26("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: [
6864
6945
  text,
6865
- looksLikeModelUnavailable ? /* @__PURE__ */ jsx30("div", { className: "mt-1 opacity-80", children: "\u6A21\u578B\u53EF\u80FD\u672A\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" }) : null
6946
+ looksLikeModelUnavailable ? /* @__PURE__ */ jsx31("div", { className: "mt-1 opacity-80", children: "\u6A21\u578B\u53EF\u80FD\u672A\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" }) : null
6866
6947
  ] }) });
6867
6948
  }
6868
6949
 
6869
6950
  // src/react/components/chat/AgentLoopBlock.tsx
6870
- import { Fragment as Fragment8, jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
6951
+ import { Fragment as Fragment8, jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
6871
6952
  var EMPTY_MESSAGES2 = [];
6872
6953
  var EMPTY_AGENT_LOOPS = {};
6873
6954
  var COLLAPSED_SUMMARY_HIDDEN_TOOLS = /* @__PURE__ */ new Set(["ReadSkill", "Read"]);
@@ -6967,7 +7048,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6967
7048
  const description = safeParseDescription(toolCall.arguments);
6968
7049
  const status = hasAwaitingAnswer || toolCall.status === "awaiting_answer" ? "awaiting_answer" : toolCall.status === "pending" || loopEntry?.info.status === "running" ? "running" : "done";
6969
7050
  const cardStyles = getLoopCardStyles(status);
6970
- return /* @__PURE__ */ jsxs26(
7051
+ return /* @__PURE__ */ jsxs27(
6971
7052
  "div",
6972
7053
  {
6973
7054
  className: cn(
@@ -6975,8 +7056,8 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6975
7056
  cardStyles.borderClass
6976
7057
  ),
6977
7058
  children: [
6978
- status === "running" || status === "awaiting_answer" ? /* @__PURE__ */ jsxs26(Fragment8, { children: [
6979
- /* @__PURE__ */ jsxs26(
7059
+ status === "running" || status === "awaiting_answer" ? /* @__PURE__ */ jsxs27(Fragment8, { children: [
7060
+ /* @__PURE__ */ jsxs27(
6980
7061
  "div",
6981
7062
  {
6982
7063
  className: cn(
@@ -6984,24 +7065,24 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6984
7065
  cardStyles.headerClass
6985
7066
  ),
6986
7067
  children: [
6987
- /* @__PURE__ */ jsx31(
7068
+ /* @__PURE__ */ jsx32(
6988
7069
  "button",
6989
7070
  {
6990
7071
  type: "button",
6991
7072
  onClick: toggleExpanded,
6992
7073
  "aria-expanded": expanded,
6993
7074
  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",
6994
- children: /* @__PURE__ */ jsxs26("span", { className: "min-w-0 flex items-center gap-2", children: [
6995
- status === "awaiting_answer" ? /* @__PURE__ */ jsx31(MessageSquareMore2, { size: 14, className: "shrink-0 text-amber-500" }) : /* @__PURE__ */ jsx31(Bot, { size: 14, className: "shrink-0 text-blue-500" }),
6996
- /* @__PURE__ */ jsxs26("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: [
7075
+ children: /* @__PURE__ */ jsxs27("span", { className: "min-w-0 flex items-center gap-2", children: [
7076
+ status === "awaiting_answer" ? /* @__PURE__ */ jsx32(MessageSquareMore2, { size: 14, className: "shrink-0 text-amber-500" }) : /* @__PURE__ */ jsx32(Bot, { size: 14, className: "shrink-0 text-blue-500" }),
7077
+ /* @__PURE__ */ jsxs27("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: [
6997
7078
  description,
6998
7079
  status === "awaiting_answer" ? " \u2014 \u7B49\u5F85\u56DE\u7B54" : ""
6999
7080
  ] })
7000
7081
  ] })
7001
7082
  }
7002
7083
  ),
7003
- reasoning ? /* @__PURE__ */ jsx31(ThinkingBadge, { reasoning, variant: "block" }) : null,
7004
- /* @__PURE__ */ jsx31(
7084
+ reasoning ? /* @__PURE__ */ jsx32(ThinkingBadge, { reasoning, variant: "block" }) : null,
7085
+ /* @__PURE__ */ jsx32(
7005
7086
  Bot,
7006
7087
  {
7007
7088
  size: 13,
@@ -7009,14 +7090,14 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7009
7090
  "aria-label": "\u5B50\u667A\u80FD\u4F53"
7010
7091
  }
7011
7092
  ),
7012
- /* @__PURE__ */ jsx31(
7093
+ /* @__PURE__ */ jsx32(
7013
7094
  "button",
7014
7095
  {
7015
7096
  type: "button",
7016
7097
  onClick: toggleExpanded,
7017
7098
  "aria-expanded": expanded,
7018
7099
  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",
7019
- children: /* @__PURE__ */ jsx31(
7100
+ children: /* @__PURE__ */ jsx32(
7020
7101
  ChevronRight4,
7021
7102
  {
7022
7103
  size: 14,
@@ -7031,7 +7112,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7031
7112
  ]
7032
7113
  }
7033
7114
  ),
7034
- !expanded ? /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-1 py-2", children: visibleLoopToolCalls.length > 0 ? visibleLoopToolCalls.map((childToolCall) => /* @__PURE__ */ jsx31(
7115
+ !expanded ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-1 py-2", children: visibleLoopToolCalls.length > 0 ? visibleLoopToolCalls.map((childToolCall) => /* @__PURE__ */ jsx32(
7035
7116
  ToolCallBlock,
7036
7117
  {
7037
7118
  toolCall: childToolCall,
@@ -7039,12 +7120,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7039
7120
  level: 2
7040
7121
  },
7041
7122
  childToolCall.id
7042
- )) : /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
7043
- /* @__PURE__ */ jsx31(Loader25, { size: 12, className: "shrink-0 animate-spin text-blue-500" }),
7044
- /* @__PURE__ */ jsx31("span", { children: "\u6B63\u5728\u542F\u52A8..." })
7045
- ] }) }) : status === "awaiting_answer" ? /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-1 py-2", children: /* @__PURE__ */ jsx31("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
7046
- ] }) : /* @__PURE__ */ jsxs26(Fragment8, { children: [
7047
- /* @__PURE__ */ jsxs26(
7123
+ )) : /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
7124
+ /* @__PURE__ */ jsx32(Loader25, { size: 12, className: "shrink-0 animate-spin text-blue-500" }),
7125
+ /* @__PURE__ */ jsx32("span", { children: "\u6B63\u5728\u542F\u52A8..." })
7126
+ ] }) }) : status === "awaiting_answer" ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-1 py-2", children: /* @__PURE__ */ jsx32("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
7127
+ ] }) : /* @__PURE__ */ jsxs27(Fragment8, { children: [
7128
+ /* @__PURE__ */ jsxs27(
7048
7129
  "div",
7049
7130
  {
7050
7131
  className: cn(
@@ -7052,21 +7133,21 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7052
7133
  cardStyles.headerClass
7053
7134
  ),
7054
7135
  children: [
7055
- /* @__PURE__ */ jsx31(
7136
+ /* @__PURE__ */ jsx32(
7056
7137
  "button",
7057
7138
  {
7058
7139
  type: "button",
7059
7140
  onClick: toggleExpanded,
7060
7141
  "aria-expanded": expanded,
7061
7142
  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",
7062
- children: /* @__PURE__ */ jsxs26("span", { className: "min-w-0 flex items-center gap-2", children: [
7063
- /* @__PURE__ */ jsx31(Check4, { size: 14, className: "shrink-0 text-emerald-500" }),
7064
- /* @__PURE__ */ jsx31("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: description })
7143
+ children: /* @__PURE__ */ jsxs27("span", { className: "min-w-0 flex items-center gap-2", children: [
7144
+ /* @__PURE__ */ jsx32(Check4, { size: 14, className: "shrink-0 text-emerald-500" }),
7145
+ /* @__PURE__ */ jsx32("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: description })
7065
7146
  ] })
7066
7147
  }
7067
7148
  ),
7068
- reasoning ? /* @__PURE__ */ jsx31(ThinkingBadge, { reasoning, variant: "block" }) : null,
7069
- /* @__PURE__ */ jsx31(
7149
+ reasoning ? /* @__PURE__ */ jsx32(ThinkingBadge, { reasoning, variant: "block" }) : null,
7150
+ /* @__PURE__ */ jsx32(
7070
7151
  Bot,
7071
7152
  {
7072
7153
  size: 13,
@@ -7074,14 +7155,14 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7074
7155
  "aria-label": "\u5B50\u667A\u80FD\u4F53"
7075
7156
  }
7076
7157
  ),
7077
- /* @__PURE__ */ jsx31(
7158
+ /* @__PURE__ */ jsx32(
7078
7159
  "button",
7079
7160
  {
7080
7161
  type: "button",
7081
7162
  onClick: toggleExpanded,
7082
7163
  "aria-expanded": expanded,
7083
7164
  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",
7084
- children: /* @__PURE__ */ jsx31(
7165
+ children: /* @__PURE__ */ jsx32(
7085
7166
  ChevronRight4,
7086
7167
  {
7087
7168
  size: 14,
@@ -7096,9 +7177,9 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7096
7177
  ]
7097
7178
  }
7098
7179
  ),
7099
- !expanded ? /* @__PURE__ */ jsxs26(Fragment8, { children: [
7100
- /* @__PURE__ */ jsx31("div", { className: "flex flex-wrap gap-1.5 px-4 py-2", children: completedToolLabels.length > 0 ? completedToolLabels.map(
7101
- (item) => item.kind === "file" ? /* @__PURE__ */ jsxs26(
7180
+ !expanded ? /* @__PURE__ */ jsxs27(Fragment8, { children: [
7181
+ /* @__PURE__ */ jsx32("div", { className: "flex flex-wrap gap-1.5 px-4 py-2", children: completedToolLabels.length > 0 ? completedToolLabels.map(
7182
+ (item) => item.kind === "file" ? /* @__PURE__ */ jsxs27(
7102
7183
  "span",
7103
7184
  {
7104
7185
  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",
@@ -7109,12 +7190,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7109
7190
  },
7110
7191
  title: item.label,
7111
7192
  children: [
7112
- /* @__PURE__ */ jsx31(FileText6, { size: 12, className: "shrink-0", "aria-hidden": "true" }),
7113
- /* @__PURE__ */ jsx31("span", { className: "truncate", children: item.label })
7193
+ /* @__PURE__ */ jsx32(FileText6, { size: 12, className: "shrink-0", "aria-hidden": "true" }),
7194
+ /* @__PURE__ */ jsx32("span", { className: "truncate", children: item.label })
7114
7195
  ]
7115
7196
  },
7116
7197
  item.key
7117
- ) : /* @__PURE__ */ jsx31(
7198
+ ) : /* @__PURE__ */ jsx32(
7118
7199
  "span",
7119
7200
  {
7120
7201
  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",
@@ -7127,20 +7208,20 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7127
7208
  },
7128
7209
  item.key
7129
7210
  )
7130
- ) : /* @__PURE__ */ jsx31("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5DE5\u5177\u8C03\u7528" }) }),
7131
- inlineToolUiBlocks.length > 0 ? /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-2 px-4 pb-3", children: inlineToolUiBlocks.map((block) => /* @__PURE__ */ jsx31(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null
7211
+ ) : /* @__PURE__ */ jsx32("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5DE5\u5177\u8C03\u7528" }) }),
7212
+ inlineToolUiBlocks.length > 0 ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-2 px-4 pb-3", children: inlineToolUiBlocks.map((block) => /* @__PURE__ */ jsx32(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null
7132
7213
  ] }) : null
7133
7214
  ] }),
7134
- expanded && /* @__PURE__ */ jsxs26("div", { className: "border-t border-[hsl(var(--border))] py-2", children: [
7215
+ expanded && /* @__PURE__ */ jsxs27("div", { className: "border-t border-[hsl(var(--border))] py-2", children: [
7135
7216
  (() => {
7136
7217
  const taskPrompt = safeParsePrompt(toolCall.arguments);
7137
- return taskPrompt ? /* @__PURE__ */ jsxs26("details", { className: "mx-3 mb-2 rounded-md bg-[hsl(var(--muted))]/40", children: [
7138
- /* @__PURE__ */ jsx31("summary", { className: "cursor-pointer px-3 py-1.5 text-[11px] font-medium text-[hsl(var(--muted-foreground))]", children: "\u4EFB\u52A1" }),
7139
- /* @__PURE__ */ jsx31("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsx31("pre", { className: "whitespace-pre-wrap text-[11px] leading-relaxed text-[hsl(var(--foreground))]", children: taskPrompt }) })
7218
+ return taskPrompt ? /* @__PURE__ */ jsxs27("details", { className: "mx-3 mb-2 rounded-md bg-[hsl(var(--muted))]/40", children: [
7219
+ /* @__PURE__ */ jsx32("summary", { className: "cursor-pointer px-3 py-1.5 text-[11px] font-medium text-[hsl(var(--muted-foreground))]", children: "\u4EFB\u52A1" }),
7220
+ /* @__PURE__ */ jsx32("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsx32("pre", { className: "whitespace-pre-wrap text-[11px] leading-relaxed text-[hsl(var(--foreground))]", children: taskPrompt }) })
7140
7221
  ] }) : null;
7141
7222
  })(),
7142
- childMessages.length > 0 ? /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-3 px-3", children: childMessages.map(
7143
- (message, index) => message.role === "assistant" ? /* @__PURE__ */ jsx31(
7223
+ childMessages.length > 0 ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-3 px-3", children: childMessages.map(
7224
+ (message, index) => message.role === "assistant" ? /* @__PURE__ */ jsx32(
7144
7225
  ExpandedChildAssistantMessage,
7145
7226
  {
7146
7227
  message,
@@ -7148,13 +7229,13 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7148
7229
  isStreaming: message.status === "streaming"
7149
7230
  },
7150
7231
  message.entry_id ?? `${message.timestamp ?? "child"}-${index}`
7151
- ) : message.role === "user" ? /* @__PURE__ */ jsx31(
7232
+ ) : message.role === "user" ? /* @__PURE__ */ jsx32(
7152
7233
  ExpandedChildUserMessage,
7153
7234
  {
7154
7235
  message
7155
7236
  },
7156
7237
  message.entry_id ?? `${message.timestamp ?? "user"}-${index}`
7157
- ) : message.role === "error" ? /* @__PURE__ */ jsx31(
7238
+ ) : message.role === "error" ? /* @__PURE__ */ jsx32(
7158
7239
  "div",
7159
7240
  {
7160
7241
  className: "border-l-[2px] border-l-red-500 px-3 py-2 text-[11px] text-red-200",
@@ -7162,17 +7243,17 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
7162
7243
  },
7163
7244
  message.entry_id ?? `${message.timestamp ?? "error"}-${index}`
7164
7245
  ) : null
7165
- ) }) : status === "running" ? /* @__PURE__ */ jsxs26("div", { className: "px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
7166
- /* @__PURE__ */ jsx31(Loader25, { size: 12, className: "mr-1.5 inline animate-spin" }),
7246
+ ) }) : status === "running" ? /* @__PURE__ */ jsxs27("div", { className: "px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
7247
+ /* @__PURE__ */ jsx32(Loader25, { size: 12, className: "mr-1.5 inline animate-spin" }),
7167
7248
  "\u6B63\u5728\u542F\u52A8..."
7168
- ] }) : toolCall.result ? /* @__PURE__ */ jsx31("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
7249
+ ] }) : toolCall.result ? /* @__PURE__ */ jsx32("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
7169
7250
  ] })
7170
7251
  ]
7171
7252
  }
7172
7253
  );
7173
7254
  }
7174
7255
  function ExpandedChildUserMessage({ message }) {
7175
- return /* @__PURE__ */ jsx31("div", { className: "pl-8", children: /* @__PURE__ */ jsx31(UserMessageBubble, { message }) });
7256
+ return /* @__PURE__ */ jsx32("div", { className: "pl-8", children: /* @__PURE__ */ jsx32(UserMessageBubble, { message }) });
7176
7257
  }
7177
7258
  function ExpandedChildAssistantMessage({
7178
7259
  message,
@@ -7182,12 +7263,12 @@ function ExpandedChildAssistantMessage({
7182
7263
  const text = typeof message.content === "string" ? message.content.trim() : message.content.filter((part) => part.type === "text").map((part) => part.text).join("").trim();
7183
7264
  const toolCalls = message.tool_calls ?? [];
7184
7265
  const hasToolCalls = toolCalls.length > 0;
7185
- return /* @__PURE__ */ jsxs26("div", { className: "flex flex-col gap-2", children: [
7186
- message.reasoning && /* @__PURE__ */ jsxs26(Reasoning, { isStreaming, children: [
7187
- /* @__PURE__ */ jsx31(ReasoningTrigger, { wordCount: message.reasoning.length }),
7188
- /* @__PURE__ */ jsx31(ReasoningContent, { children: message.reasoning })
7266
+ return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-2", children: [
7267
+ message.reasoning && /* @__PURE__ */ jsxs27(Reasoning, { isStreaming, children: [
7268
+ /* @__PURE__ */ jsx32(ReasoningTrigger, { wordCount: message.reasoning.length }),
7269
+ /* @__PURE__ */ jsx32(ReasoningContent, { children: message.reasoning })
7189
7270
  ] }),
7190
- text ? /* @__PURE__ */ jsx31(
7271
+ text ? /* @__PURE__ */ jsx32(
7191
7272
  ChildText,
7192
7273
  {
7193
7274
  text,
@@ -7196,9 +7277,9 @@ function ExpandedChildAssistantMessage({
7196
7277
  reasoning: void 0
7197
7278
  }
7198
7279
  ) : null,
7199
- !text && isStreaming && /* @__PURE__ */ jsx31("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7200
- hasToolCalls && /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-2", children: toolCalls.map(
7201
- (toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx31(
7280
+ !text && isStreaming && /* @__PURE__ */ jsx32("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7281
+ hasToolCalls && /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-2", children: toolCalls.map(
7282
+ (toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx32(
7202
7283
  AgentLoopBlock,
7203
7284
  {
7204
7285
  toolCall,
@@ -7206,7 +7287,7 @@ function ExpandedChildAssistantMessage({
7206
7287
  reasoning: void 0
7207
7288
  },
7208
7289
  toolCall.id
7209
- ) : /* @__PURE__ */ jsx31(
7290
+ ) : /* @__PURE__ */ jsx32(
7210
7291
  ToolCallBlock,
7211
7292
  {
7212
7293
  toolCall,
@@ -7218,8 +7299,8 @@ function ExpandedChildAssistantMessage({
7218
7299
  toolCall.id
7219
7300
  )
7220
7301
  ) }),
7221
- message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-2", children: message.blocks.map(
7222
- (block, index) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx31("div", { className: "ml-4", children: /* @__PURE__ */ jsx31(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${index}`) : null
7302
+ message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-2", children: message.blocks.map(
7303
+ (block, index) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx32("div", { className: "ml-4", children: /* @__PURE__ */ jsx32(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${index}`) : null
7223
7304
  ) }) : null
7224
7305
  ] });
7225
7306
  }
@@ -7229,8 +7310,8 @@ function ChildText({
7229
7310
  sessionId,
7230
7311
  reasoning
7231
7312
  }) {
7232
- return /* @__PURE__ */ jsxs26("div", { className: "pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]", children: [
7233
- /* @__PURE__ */ jsx31(
7313
+ return /* @__PURE__ */ jsxs27("div", { className: "pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]", children: [
7314
+ /* @__PURE__ */ jsx32(
7234
7315
  MarkdownContent,
7235
7316
  {
7236
7317
  mode: "streaming",
@@ -7240,8 +7321,8 @@ function ChildText({
7240
7321
  children: text
7241
7322
  }
7242
7323
  ),
7243
- isStreaming && /* @__PURE__ */ jsx31("span", { className: "ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60" }),
7244
- reasoning ? /* @__PURE__ */ jsx31(ThinkingBadge, { reasoning }) : null
7324
+ isStreaming && /* @__PURE__ */ jsx32("span", { className: "ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60" }),
7325
+ reasoning ? /* @__PURE__ */ jsx32(ThinkingBadge, { reasoning }) : null
7245
7326
  ] });
7246
7327
  }
7247
7328
  function getLoopCardStyles(status) {
@@ -7280,8 +7361,155 @@ function getLoopCardStyles(status) {
7280
7361
  };
7281
7362
  }
7282
7363
 
7364
+ // src/react/components/chat/FileDeliveryCards.tsx
7365
+ import { Download as Download4, Loader2 as Loader26 } from "lucide-react";
7366
+ import { useMemo as useMemo16, useState as useState18 } from "react";
7367
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
7368
+ var AGENT_WORKSPACE_DIR_NAME = "\u667A\u80FD\u52A9\u624B\u5DE5\u4F5C\u7A7A\u95F4";
7369
+ var EXT_LABELS = {
7370
+ py: "Python",
7371
+ js: "JavaScript",
7372
+ ts: "TypeScript",
7373
+ tsx: "TypeScript",
7374
+ jsx: "JavaScript",
7375
+ md: "Markdown",
7376
+ html: "HTML",
7377
+ css: "CSS",
7378
+ json: "JSON",
7379
+ csv: "CSV",
7380
+ xlsx: "Excel",
7381
+ docx: "Word",
7382
+ pptx: "PPT",
7383
+ pdf: "PDF",
7384
+ sh: "Shell",
7385
+ sql: "SQL"
7386
+ };
7387
+ function toWorkspaceRelPath(rawPath, sessionId) {
7388
+ const sessionRoot = `/root/${AGENT_WORKSPACE_DIR_NAME}/${sessionId}`;
7389
+ let relPath;
7390
+ if (rawPath.startsWith(`${sessionRoot}/`)) {
7391
+ relPath = rawPath.slice(sessionRoot.length + 1);
7392
+ } else if (!rawPath.startsWith("/")) {
7393
+ relPath = rawPath.replace(/^\.\//, "");
7394
+ } else {
7395
+ return null;
7396
+ }
7397
+ if (!relPath || relPath.startsWith("../") || relPath.includes("/../")) return null;
7398
+ if (relPath.split("/").some((segment) => segment.startsWith("."))) return null;
7399
+ return relPath;
7400
+ }
7401
+ function basename(path) {
7402
+ return path.split("/").filter(Boolean).pop() || path;
7403
+ }
7404
+ function getExtLabel(name) {
7405
+ const ext = name.split(".").pop()?.toLowerCase() ?? "";
7406
+ if (!ext || ext === name.toLowerCase()) return "\u6587\u4EF6";
7407
+ return EXT_LABELS[ext] ?? ext.toUpperCase();
7408
+ }
7409
+ function collectDeliveredFiles(toolCalls, sessionId) {
7410
+ const seen = /* @__PURE__ */ new Set();
7411
+ const files = [];
7412
+ for (const toolCall of toolCalls) {
7413
+ if (toolCall.status !== "done") continue;
7414
+ const toolName = formatToolName(toolCall.name);
7415
+ if (toolName !== "Write" && toolName !== "Edit") continue;
7416
+ const rawPath = extractToolFilePath(toolCall);
7417
+ if (!rawPath) continue;
7418
+ const relPath = toWorkspaceRelPath(rawPath, sessionId);
7419
+ if (!relPath || seen.has(relPath)) continue;
7420
+ seen.add(relPath);
7421
+ files.push({ relPath, name: basename(relPath) });
7422
+ }
7423
+ return files;
7424
+ }
7425
+ function DeliveryCard({ relPath, name, sessionId }) {
7426
+ const [opening, setOpening] = useState18(false);
7427
+ const handleOpen = async () => {
7428
+ if (opening) return;
7429
+ setOpening(true);
7430
+ try {
7431
+ const target = await resolveSessionFilePreviewTarget(sessionId, relPath, name);
7432
+ const uiStore = useUiStore.getState();
7433
+ uiStore.setRightPanelCollapsed(false);
7434
+ uiStore.setActiveRightTab("preview");
7435
+ uiStore.pushArtifact(target);
7436
+ } finally {
7437
+ setOpening(false);
7438
+ }
7439
+ };
7440
+ const downloadUrl = useMemo16(
7441
+ () => getAuthedUrl(getSessionFilePath(sessionId, relPath)),
7442
+ [sessionId, relPath]
7443
+ );
7444
+ return /* @__PURE__ */ jsxs28("div", { className: "group/delivery relative flex w-[320px] max-w-full items-center self-start rounded-[14px] border border-[hsl(var(--border))] bg-[hsl(var(--card))] transition-colors duration-150 hover:border-[hsl(var(--primary)/0.3)] hover:bg-[hsl(var(--muted)/0.6)] focus-within:ring-1 focus-within:ring-[hsl(var(--ring))]", children: [
7445
+ /* @__PURE__ */ jsxs28(
7446
+ "button",
7447
+ {
7448
+ type: "button",
7449
+ onClick: () => void handleOpen(),
7450
+ disabled: opening,
7451
+ className: "flex min-w-0 flex-1 items-center gap-3 rounded-[14px] px-[15px] py-[13px] text-left focus:outline-none disabled:cursor-wait",
7452
+ "aria-label": `\u6253\u5F00\u6587\u4EF6\uFF1A${name}`,
7453
+ children: [
7454
+ /* @__PURE__ */ jsx33("span", { className: "flex h-[42px] w-[42px] shrink-0 items-center justify-center rounded-[11px] bg-gradient-to-br from-[hsl(var(--primary))/0.1] to-[hsl(var(--primary))/0.2] text-[hsl(var(--primary))]", children: opening ? /* @__PURE__ */ jsx33(Loader26, { size: 21, className: "animate-spin", "aria-hidden": "true" }) : /* @__PURE__ */ jsx33(FileGlyph, {}) }),
7455
+ /* @__PURE__ */ jsxs28("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
7456
+ /* @__PURE__ */ jsx33("span", { className: "truncate text-[15px] font-semibold text-[hsl(var(--foreground))]", children: name }),
7457
+ /* @__PURE__ */ jsxs28("span", { className: "flex items-center gap-1.5 text-[12.5px] text-[hsl(var(--muted-foreground))]", children: [
7458
+ /* @__PURE__ */ jsx33("span", { className: "font-mono", children: getExtLabel(name) }),
7459
+ /* @__PURE__ */ jsx33("span", { "aria-hidden": "true", children: "\xB7" }),
7460
+ /* @__PURE__ */ jsx33("span", { className: "text-[hsl(var(--primary))]", children: "AI \u751F\u6210" })
7461
+ ] })
7462
+ ] })
7463
+ ]
7464
+ }
7465
+ ),
7466
+ /* @__PURE__ */ jsx33(
7467
+ "a",
7468
+ {
7469
+ href: downloadUrl,
7470
+ download: name,
7471
+ onClick: (event) => event.stopPropagation(),
7472
+ className: "absolute right-3 top-1/2 grid h-8 w-8 -translate-y-1/2 place-items-center rounded-lg text-[hsl(var(--muted-foreground))] opacity-0 transition-opacity hover:bg-[hsl(var(--background))] hover:text-[hsl(var(--foreground))] focus:opacity-100 focus:outline-none group-hover/delivery:opacity-100",
7473
+ title: "\u4E0B\u8F7D\u6587\u4EF6",
7474
+ "aria-label": `\u4E0B\u8F7D\u6587\u4EF6\uFF1A${name}`,
7475
+ children: /* @__PURE__ */ jsx33(Download4, { size: 16, "aria-hidden": "true" })
7476
+ }
7477
+ )
7478
+ ] });
7479
+ }
7480
+ function FileGlyph() {
7481
+ return /* @__PURE__ */ jsxs28(
7482
+ "svg",
7483
+ {
7484
+ width: "21",
7485
+ height: "21",
7486
+ viewBox: "0 0 24 24",
7487
+ fill: "none",
7488
+ stroke: "currentColor",
7489
+ strokeWidth: "1.9",
7490
+ strokeLinecap: "round",
7491
+ strokeLinejoin: "round",
7492
+ "aria-hidden": "true",
7493
+ children: [
7494
+ /* @__PURE__ */ jsx33("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z" }),
7495
+ /* @__PURE__ */ jsx33("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }),
7496
+ /* @__PURE__ */ jsx33("path", { d: "m10 13-2 2 2 2" }),
7497
+ /* @__PURE__ */ jsx33("path", { d: "m14 17 2-2-2-2" })
7498
+ ]
7499
+ }
7500
+ );
7501
+ }
7502
+ function FileDeliveryCards({
7503
+ toolCalls,
7504
+ sessionId
7505
+ }) {
7506
+ const files = useMemo16(() => collectDeliveredFiles(toolCalls, sessionId), [toolCalls, sessionId]);
7507
+ if (files.length === 0) return null;
7508
+ return /* @__PURE__ */ jsx33("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsx33(DeliveryCard, { relPath: file.relPath, name: file.name, sessionId }, file.relPath)) });
7509
+ }
7510
+
7283
7511
  // src/react/components/chat/AssistantTurnBlock.tsx
7284
- import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7512
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
7285
7513
  var EMPTY_MESSAGES3 = [];
7286
7514
  var EMPTY_AGENT_LOOPS2 = {};
7287
7515
  function defaultTurnDisplayMode({
@@ -7413,18 +7641,18 @@ function AssistantTurnBlockBase({
7413
7641
  customization
7414
7642
  }) {
7415
7643
  const messages = Array.isArray(rawMessages) ? rawMessages : [];
7416
- const allToolCalls = useMemo16(() => messages.flatMap((m) => m.tool_calls ?? []), [messages]);
7417
- const hasAgentToolCall = useMemo16(
7644
+ const allToolCalls = useMemo17(() => messages.flatMap((m) => m.tool_calls ?? []), [messages]);
7645
+ const hasAgentToolCall = useMemo17(
7418
7646
  () => allToolCalls.some((toolCall) => formatToolName(toolCall.name) === "Agent"),
7419
7647
  [allToolCalls]
7420
7648
  );
7421
- const hasActionableToolCall = useMemo16(
7649
+ const hasActionableToolCall = useMemo17(
7422
7650
  () => allToolCalls.some(
7423
7651
  (tc) => tc.status === "error" || tc.status === "cancelled" || formatToolName(tc.name) === "AskUserQuestion" && tc.status === "awaiting_answer"
7424
7652
  ),
7425
7653
  [allToolCalls]
7426
7654
  );
7427
- const [displayMode, setDisplayMode] = useState18(
7655
+ const [displayMode, setDisplayMode] = useState19(
7428
7656
  defaultTurnDisplayMode({ forceExpanded, hasActionableToolCall })
7429
7657
  );
7430
7658
  const wasStreamingRef = useRef12(isStreaming);
@@ -7440,16 +7668,24 @@ function AssistantTurnBlockBase({
7440
7668
  const agentLoops = useChatStore(
7441
7669
  (state) => hasAgentToolCall ? state.agentLoops[sessionId] ?? EMPTY_AGENT_LOOPS2 : EMPTY_AGENT_LOOPS2
7442
7670
  );
7443
- const turnMessages = useMemo16(
7671
+ const turnMessages = useMemo17(
7444
7672
  () => hasAgentToolCall ? collectTurnMessages({ rootMessages: messages, sessionMessages, agentLoops }) : messages,
7445
7673
  [agentLoops, hasAgentToolCall, messages, sessionMessages]
7446
7674
  );
7447
- const resourceBlocks = useMemo16(() => getInlineResourceBlocks(turnMessages), [turnMessages]);
7448
- const finalMessage = useMemo16(() => getLastTextMessage(turnMessages), [turnMessages]);
7675
+ const turnToolCalls = useMemo17(
7676
+ () => turnMessages.flatMap((m) => m.tool_calls ?? []),
7677
+ [turnMessages]
7678
+ );
7679
+ const resourceBlocks = useMemo17(() => getInlineResourceBlocks(turnMessages), [turnMessages]);
7680
+ const finalMessage = useMemo17(() => getLastTextMessage(turnMessages), [turnMessages]);
7681
+ const finalMessageText = useMemo17(
7682
+ () => finalMessage ? getTextContent(normalizeMessageContent(finalMessage.content)).trim() : "",
7683
+ [finalMessage]
7684
+ );
7449
7685
  const hasInterruptedState = messages.some((message) => message.status === "interrupted");
7450
7686
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
7451
7687
  const memoryRefs = Array.isArray(messages[0]?.memory_refs) ? messages[0].memory_refs : [];
7452
- return /* @__PURE__ */ jsxs27(
7688
+ return /* @__PURE__ */ jsxs29(
7453
7689
  "div",
7454
7690
  {
7455
7691
  className: cn(
@@ -7458,48 +7694,68 @@ function AssistantTurnBlockBase({
7458
7694
  customization?.classNames?.assistantTurn
7459
7695
  ),
7460
7696
  children: [
7461
- memoryRefs.length > 0 && /* @__PURE__ */ jsx32(MemoryRefsHint, { refs: memoryRefs }),
7462
- hasInterruptedState && /* @__PURE__ */ jsx32("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" }),
7463
- !isStreaming && /* @__PURE__ */ jsx32("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs27(
7697
+ memoryRefs.length > 0 && /* @__PURE__ */ jsx34(MemoryRefsHint, { refs: memoryRefs }),
7698
+ hasInterruptedState && /* @__PURE__ */ jsx34("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" }),
7699
+ !isStreaming && allToolCalls.length > 0 && // 详情药丸(原型):左对齐,展示步骤数;展开后是带左边线的步骤卡。
7700
+ /* @__PURE__ */ jsxs29(
7464
7701
  "button",
7465
7702
  {
7466
7703
  type: "button",
7467
7704
  onClick: () => setDisplayMode(displayMode === "detail" ? "compact" : "detail"),
7468
- className: "inline-flex shrink-0 items-center gap-1 text-xs text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
7705
+ "aria-expanded": effectiveMode === "detail",
7706
+ className: "inline-flex h-[30px] shrink-0 select-none items-center gap-1.5 self-start rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.35)] pl-2.5 pr-3 text-[13px] text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
7469
7707
  children: [
7470
- /* @__PURE__ */ jsx32("span", { children: effectiveMode === "detail" ? "\u7CBE\u7B80" : "\u8BE6\u7EC6" }),
7471
- /* @__PURE__ */ jsx32(
7472
- ChevronRight5,
7708
+ /* @__PURE__ */ jsx34(Check5, { size: 14, className: "shrink-0 text-emerald-500", "aria-hidden": "true" }),
7709
+ /* @__PURE__ */ jsxs29("span", { children: [
7710
+ "\u8BE6\u60C5 \xB7 ",
7711
+ allToolCalls.length,
7712
+ " \u4E2A\u6B65\u9AA4"
7713
+ ] }),
7714
+ /* @__PURE__ */ jsx34(
7715
+ ChevronDown2,
7473
7716
  {
7474
- size: 18,
7475
- className: cn("transition-transform", effectiveMode === "detail" && "rotate-180")
7717
+ size: 14,
7718
+ className: cn("shrink-0 transition-transform", effectiveMode === "detail" && "rotate-180"),
7719
+ "aria-hidden": "true"
7476
7720
  }
7477
7721
  )
7478
7722
  ]
7479
7723
  }
7480
- ) }),
7481
- effectiveMode === "detail" ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx32(
7482
- AssistantMessages,
7483
- {
7484
- messages,
7485
- isStreaming,
7486
- sessionId,
7487
- askAnswers,
7488
- onAnswer,
7489
- sessionStatus,
7490
- level,
7491
- showToolDetails: true,
7492
- customization
7493
- }
7494
- ) }) : /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-4", children: [
7495
- resourceBlocks.length > 0 ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-3", children: resourceBlocks.map((block) => /* @__PURE__ */ jsx32(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null,
7496
- finalMessage ? /* @__PURE__ */ jsx32(
7724
+ ),
7725
+ effectiveMode === "detail" ? (
7726
+ // 展开态:左边线把步骤收拢成一组,和正文拉开层次(原型)。
7727
+ /* @__PURE__ */ jsx34(
7728
+ "div",
7729
+ {
7730
+ className: cn(
7731
+ "flex flex-col gap-3",
7732
+ allToolCalls.length > 0 && "ml-1.5 border-l-2 border-[hsl(var(--border))] pl-4"
7733
+ ),
7734
+ children: /* @__PURE__ */ jsx34(
7735
+ AssistantMessages,
7736
+ {
7737
+ messages,
7738
+ isStreaming,
7739
+ sessionId,
7740
+ askAnswers,
7741
+ onAnswer,
7742
+ sessionStatus,
7743
+ level,
7744
+ showToolDetails: true,
7745
+ customization
7746
+ }
7747
+ )
7748
+ }
7749
+ )
7750
+ ) : /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs29("div", { className: "flex flex-col gap-4", children: [
7751
+ resourceBlocks.length > 0 ? /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-3", children: resourceBlocks.map((block) => /* @__PURE__ */ jsx34(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null,
7752
+ finalMessage ? /* @__PURE__ */ jsx34(
7497
7753
  "div",
7498
7754
  {
7499
7755
  className: cn(
7500
7756
  resourceBlocks.length > 0 && "border-t border-[hsl(var(--border))] pt-4"
7501
7757
  ),
7502
- children: /* @__PURE__ */ jsx32(
7758
+ children: /* @__PURE__ */ jsx34(
7503
7759
  AssistantMessageContent,
7504
7760
  {
7505
7761
  message: finalMessage,
@@ -7510,8 +7766,14 @@ function AssistantTurnBlockBase({
7510
7766
  }
7511
7767
  )
7512
7768
  }
7513
- ) : isStreaming ? /* @__PURE__ */ jsx32("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }) : null
7514
- ] }) })
7769
+ ) : isStreaming ? /* @__PURE__ */ jsx34("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }) : null
7770
+ ] }) }),
7771
+ level === 1 && // 用合并后的轮次消息:子智能体(fork Agent)写入的文件也要出交付卡片。
7772
+ /* @__PURE__ */ jsx34(FileDeliveryCards, { toolCalls: turnToolCalls, sessionId }),
7773
+ level === 1 && !isStreaming && finalMessageText ? (
7774
+ // 反馈行(原型):轮次底部的复制入口。
7775
+ /* @__PURE__ */ jsx34(MessageActions, { content: finalMessageText, className: "-mt-1.5" })
7776
+ ) : null
7515
7777
  ]
7516
7778
  }
7517
7779
  );
@@ -7539,16 +7801,16 @@ function AssistantMessages({
7539
7801
  const toolCalls = message.tool_calls ?? [];
7540
7802
  const hasToolCalls = toolCalls.length > 0;
7541
7803
  const toolRenderItems = groupDetailedToolCalls(toolCalls);
7542
- return /* @__PURE__ */ jsxs27(
7804
+ return /* @__PURE__ */ jsxs29(
7543
7805
  "div",
7544
7806
  {
7545
7807
  className: "flex flex-col gap-3",
7546
7808
  children: [
7547
- hasReasoning && /* @__PURE__ */ jsxs27(Reasoning, { isStreaming: isStreamingLastMessage, children: [
7548
- /* @__PURE__ */ jsx32(ReasoningTrigger, { wordCount: reasoning.length }),
7549
- /* @__PURE__ */ jsx32(ReasoningContent, { children: reasoning })
7809
+ hasReasoning && /* @__PURE__ */ jsxs29(Reasoning, { isStreaming: isStreamingLastMessage, children: [
7810
+ /* @__PURE__ */ jsx34(ReasoningTrigger, { wordCount: reasoning.length }),
7811
+ /* @__PURE__ */ jsx34(ReasoningContent, { children: reasoning })
7550
7812
  ] }),
7551
- /* @__PURE__ */ jsx32(
7813
+ /* @__PURE__ */ jsx34(
7552
7814
  AssistantMessageContent,
7553
7815
  {
7554
7816
  message,
@@ -7558,9 +7820,9 @@ function AssistantMessages({
7558
7820
  className: customization?.classNames?.assistantText
7559
7821
  }
7560
7822
  ),
7561
- hasToolCalls && showToolDetails && /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-2", children: toolRenderItems.map((item) => {
7823
+ hasToolCalls && showToolDetails && /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-2", children: toolRenderItems.map((item) => {
7562
7824
  if (item.kind === "read_group") {
7563
- return /* @__PURE__ */ jsx32(
7825
+ return /* @__PURE__ */ jsx34(
7564
7826
  CompactToolGroupBlock,
7565
7827
  {
7566
7828
  toolCalls: item.toolCalls,
@@ -7577,7 +7839,7 @@ function AssistantMessages({
7577
7839
  );
7578
7840
  }
7579
7841
  const { toolCall } = item;
7580
- return formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx32(
7842
+ return formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx34(
7581
7843
  AgentLoopBlock,
7582
7844
  {
7583
7845
  toolCall,
@@ -7585,7 +7847,7 @@ function AssistantMessages({
7585
7847
  reasoning: void 0
7586
7848
  },
7587
7849
  toolCall.id
7588
- ) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx32(
7850
+ ) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx34(
7589
7851
  customization.components.ToolCall,
7590
7852
  {
7591
7853
  toolCall,
@@ -7600,7 +7862,7 @@ function AssistantMessages({
7600
7862
  customization
7601
7863
  },
7602
7864
  toolCall.id
7603
- ) : /* @__PURE__ */ jsx32(
7865
+ ) : /* @__PURE__ */ jsx34(
7604
7866
  ToolCallBlock,
7605
7867
  {
7606
7868
  toolCall,
@@ -7617,8 +7879,8 @@ function AssistantMessages({
7617
7879
  toolCall.id
7618
7880
  );
7619
7881
  }) }),
7620
- showToolDetails && message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-2", children: message.blocks.map(
7621
- (block, blockIndex) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx32("div", { className: "ml-4", children: /* @__PURE__ */ jsx32(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${blockIndex}`) : null
7882
+ showToolDetails && message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-2", children: message.blocks.map(
7883
+ (block, blockIndex) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx34("div", { className: "ml-4", children: /* @__PURE__ */ jsx34(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${blockIndex}`) : null
7622
7884
  ) }) : null
7623
7885
  ]
7624
7886
  },
@@ -7652,7 +7914,7 @@ function CompactToolGroupBlock({
7652
7914
  level,
7653
7915
  customization
7654
7916
  }) {
7655
- const [expanded, setExpanded] = useState18(false);
7917
+ const [expanded, setExpanded] = useState19(false);
7656
7918
  const indentClass = level === 2 ? "ml-3" : "ml-4";
7657
7919
  const hasError = toolCalls.some(
7658
7920
  (tc) => tc.status === "error" || tc.status === "cancelled"
@@ -7666,12 +7928,12 @@ function CompactToolGroupBlock({
7666
7928
  return filePath ? formatFileName(filePath) : "\u672A\u77E5\u6587\u4EF6";
7667
7929
  });
7668
7930
  const title = `\u8BFB\u53D6 ${toolCalls.length} \u4E2A\u6587\u4EF6`;
7669
- return /* @__PURE__ */ jsxs27("div", { className: cn(indentClass, "text-xs"), children: [
7670
- /* @__PURE__ */ jsxs27("div", { className: cn(
7931
+ return /* @__PURE__ */ jsxs29("div", { className: cn(indentClass, "text-xs"), children: [
7932
+ /* @__PURE__ */ jsxs29("div", { className: cn(
7671
7933
  "flex items-center gap-2 border-l-[3px] px-3 py-2",
7672
7934
  hasError ? "border-l-[hsl(var(--destructive))]" : "border-l-[hsl(var(--primary))]"
7673
7935
  ), children: [
7674
- /* @__PURE__ */ jsxs27(
7936
+ /* @__PURE__ */ jsxs29(
7675
7937
  "button",
7676
7938
  {
7677
7939
  type: "button",
@@ -7679,7 +7941,7 @@ function CompactToolGroupBlock({
7679
7941
  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",
7680
7942
  "aria-expanded": expanded,
7681
7943
  children: [
7682
- /* @__PURE__ */ jsx32(
7944
+ /* @__PURE__ */ jsx34(
7683
7945
  ChevronRight5,
7684
7946
  {
7685
7947
  size: 11,
@@ -7689,18 +7951,18 @@ function CompactToolGroupBlock({
7689
7951
  )
7690
7952
  }
7691
7953
  ),
7692
- hasError ? /* @__PURE__ */ jsxs27("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]", children: [
7693
- /* @__PURE__ */ jsx32(AlertCircle, { size: 11 }),
7694
- /* @__PURE__ */ jsx32("span", { children: "\u5931\u8D25" })
7695
- ] }) : /* @__PURE__ */ jsxs27("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]", children: [
7696
- /* @__PURE__ */ jsx32(Check5, { size: 11 }),
7697
- /* @__PURE__ */ jsx32("span", { children: "\u5B8C\u6210" })
7954
+ hasError ? /* @__PURE__ */ jsxs29("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]", children: [
7955
+ /* @__PURE__ */ jsx34(AlertCircle, { size: 11 }),
7956
+ /* @__PURE__ */ jsx34("span", { children: "\u5931\u8D25" })
7957
+ ] }) : /* @__PURE__ */ jsxs29("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]", children: [
7958
+ /* @__PURE__ */ jsx34(Check5, { size: 11 }),
7959
+ /* @__PURE__ */ jsx34("span", { children: "\u5B8C\u6210" })
7698
7960
  ] }),
7699
- /* @__PURE__ */ jsx32("span", { className: "min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]", children: title })
7961
+ /* @__PURE__ */ jsx34("span", { className: "min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]", children: title })
7700
7962
  ]
7701
7963
  }
7702
7964
  ),
7703
- /* @__PURE__ */ jsx32("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: tags.map((tag, index) => /* @__PURE__ */ jsx32(
7965
+ /* @__PURE__ */ jsx34("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: tags.map((tag, index) => /* @__PURE__ */ jsx34(
7704
7966
  "span",
7705
7967
  {
7706
7968
  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))]",
@@ -7709,12 +7971,12 @@ function CompactToolGroupBlock({
7709
7971
  },
7710
7972
  `${tag}-${index}`
7711
7973
  )) }),
7712
- reasoning ? /* @__PURE__ */ jsx32(ThinkingBadge, { reasoning, variant: "block" }) : null,
7713
- totalDurationMs > 0 ? /* @__PURE__ */ jsx32("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration2(totalDurationMs) }) : null
7974
+ reasoning ? /* @__PURE__ */ jsx34(ThinkingBadge, { reasoning, variant: "block" }) : null,
7975
+ totalDurationMs > 0 ? /* @__PURE__ */ jsx34("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration2(totalDurationMs) }) : null
7714
7976
  ] }),
7715
- expanded ? /* @__PURE__ */ jsx32("div", { className: "mt-1 flex flex-col gap-1", children: toolCalls.map((toolCall) => {
7977
+ expanded ? /* @__PURE__ */ jsx34("div", { className: "mt-1 flex flex-col gap-1", children: toolCalls.map((toolCall) => {
7716
7978
  const CustomToolCall = customization?.components?.ToolCall;
7717
- return CustomToolCall ? /* @__PURE__ */ jsx32(
7979
+ return CustomToolCall ? /* @__PURE__ */ jsx34(
7718
7980
  CustomToolCall,
7719
7981
  {
7720
7982
  toolCall,
@@ -7728,7 +7990,7 @@ function CompactToolGroupBlock({
7728
7990
  customization
7729
7991
  },
7730
7992
  toolCall.id
7731
- ) : /* @__PURE__ */ jsx32(
7993
+ ) : /* @__PURE__ */ jsx34(
7732
7994
  ToolCallBlock,
7733
7995
  {
7734
7996
  toolCall,
@@ -7759,8 +8021,8 @@ function AssistantMessageContent({
7759
8021
  if (!text && imageParts.length === 0 && fileParts.length === 0 && !isStreaming && !reasoning) {
7760
8022
  return null;
7761
8023
  }
7762
- return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-3", children: [
7763
- imageParts.length > 0 && /* @__PURE__ */ jsx32("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx32(
8024
+ return /* @__PURE__ */ jsxs29("div", { className: "flex flex-col gap-3", children: [
8025
+ imageParts.length > 0 && /* @__PURE__ */ jsx34("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx34(
7764
8026
  "img",
7765
8027
  {
7766
8028
  src: part.image_url.url,
@@ -7769,8 +8031,8 @@ function AssistantMessageContent({
7769
8031
  },
7770
8032
  part.image_url.url
7771
8033
  )) }),
7772
- /* @__PURE__ */ jsx32(MessageFileAttachmentList, { files: fileParts }),
7773
- text ? /* @__PURE__ */ jsx32(
8034
+ /* @__PURE__ */ jsx34(MessageFileAttachmentList, { files: fileParts }),
8035
+ text ? /* @__PURE__ */ jsx34(
7774
8036
  AssistantText,
7775
8037
  {
7776
8038
  text,
@@ -7780,8 +8042,8 @@ function AssistantMessageContent({
7780
8042
  className
7781
8043
  }
7782
8044
  ) : null,
7783
- !text && isStreaming && /* @__PURE__ */ jsx32("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7784
- !text && reasoning ? /* @__PURE__ */ jsx32(ThinkingBadge, { reasoning, variant: "block" }) : null
8045
+ !text && isStreaming && /* @__PURE__ */ jsx34("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
8046
+ !text && reasoning ? /* @__PURE__ */ jsx34(ThinkingBadge, { reasoning, variant: "block" }) : null
7785
8047
  ] });
7786
8048
  }
7787
8049
  function AssistantText({
@@ -7797,45 +8059,45 @@ function AssistantText({
7797
8059
  },
7798
8060
  [sessionId]
7799
8061
  );
7800
- const cardCtx = useMemo16(
8062
+ const cardCtx = useMemo17(
7801
8063
  () => ({ sessionId, messageId, sendMessage }),
7802
8064
  [sessionId, messageId, sendMessage]
7803
8065
  );
7804
- return /* @__PURE__ */ jsxs27("div", { className: cn("text-[15px] leading-8 text-[hsl(var(--foreground))]", className), children: [
7805
- /* @__PURE__ */ jsx32(CardContext.Provider, { value: cardCtx, children: /* @__PURE__ */ jsx32(
8066
+ return /* @__PURE__ */ jsxs29("div", { className: cn("text-[15px] leading-8 text-[hsl(var(--foreground))]", className), children: [
8067
+ /* @__PURE__ */ jsx34(CardContext.Provider, { value: cardCtx, children: /* @__PURE__ */ jsx34(
7806
8068
  MarkdownContent,
7807
8069
  {
7808
8070
  mode: "streaming",
7809
8071
  sessionId,
7810
- className: "prose prose-sm prose-invert inline max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0 [&_p:last-child]:inline",
8072
+ className: "prose prose-invert chat-prose inline max-w-none [&_li>p]:inline [&_p:last-child]:inline",
7811
8073
  controls: { code: true },
7812
8074
  children: text
7813
8075
  }
7814
8076
  ) }),
7815
- reasoning ? /* @__PURE__ */ jsx32(ThinkingBadge, { reasoning }) : null
8077
+ reasoning ? /* @__PURE__ */ jsx34(ThinkingBadge, { reasoning }) : null
7816
8078
  ] });
7817
8079
  }
7818
8080
  function MemoryRefsHint({ refs: rawRefs }) {
7819
8081
  const refs = Array.isArray(rawRefs) ? rawRefs : [];
7820
- const [expanded, setExpanded] = useState18(false);
8082
+ const [expanded, setExpanded] = useState19(false);
7821
8083
  const hasSkill = refs.some((r3) => r3.skill_name);
7822
8084
  const label = hasSkill ? "\u53C2\u8003\u4E86\u8BE5\u6280\u80FD\u7684\u5386\u53F2\u7ECF\u9A8C" : "\u53C2\u8003\u4E86\u5386\u53F2\u7ECF\u9A8C";
7823
- return /* @__PURE__ */ jsxs27("div", { className: "ml-4", children: [
7824
- /* @__PURE__ */ jsxs27(
8085
+ return /* @__PURE__ */ jsxs29("div", { className: "ml-4", children: [
8086
+ /* @__PURE__ */ jsxs29(
7825
8087
  "button",
7826
8088
  {
7827
8089
  type: "button",
7828
8090
  onClick: () => setExpanded(!expanded),
7829
8091
  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)]",
7830
8092
  children: [
7831
- /* @__PURE__ */ jsx32(BookOpen, { size: 12 }),
7832
- /* @__PURE__ */ jsxs27("span", { children: [
8093
+ /* @__PURE__ */ jsx34(BookOpen, { size: 12 }),
8094
+ /* @__PURE__ */ jsxs29("span", { children: [
7833
8095
  label,
7834
8096
  "\uFF08",
7835
8097
  refs.length,
7836
8098
  "\uFF09"
7837
8099
  ] }),
7838
- /* @__PURE__ */ jsx32(
8100
+ /* @__PURE__ */ jsx34(
7839
8101
  ChevronRight5,
7840
8102
  {
7841
8103
  size: 10,
@@ -7845,13 +8107,13 @@ function MemoryRefsHint({ refs: rawRefs }) {
7845
8107
  ]
7846
8108
  }
7847
8109
  ),
7848
- expanded && /* @__PURE__ */ jsxs27("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: [
7849
- refs.map((ref) => /* @__PURE__ */ jsxs27("div", { className: "flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]", children: [
7850
- /* @__PURE__ */ jsx32("span", { className: "mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]", children: "\u2022" }),
7851
- /* @__PURE__ */ jsx32("span", { className: "line-clamp-1", children: ref.content_preview }),
7852
- ref.skill_name && /* @__PURE__ */ jsx32("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 })
8110
+ expanded && /* @__PURE__ */ jsxs29("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: [
8111
+ refs.map((ref) => /* @__PURE__ */ jsxs29("div", { className: "flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]", children: [
8112
+ /* @__PURE__ */ jsx34("span", { className: "mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]", children: "\u2022" }),
8113
+ /* @__PURE__ */ jsx34("span", { className: "line-clamp-1", children: ref.content_preview }),
8114
+ ref.skill_name && /* @__PURE__ */ jsx34("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 })
7853
8115
  ] }, ref.id)),
7854
- /* @__PURE__ */ jsx32(
8116
+ /* @__PURE__ */ jsx34(
7855
8117
  "a",
7856
8118
  {
7857
8119
  href: MEMORIES_ROUTE,
@@ -7864,9 +8126,9 @@ function MemoryRefsHint({ refs: rawRefs }) {
7864
8126
  }
7865
8127
 
7866
8128
  // src/react/components/chat/CompactionCard.tsx
7867
- import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight6, Loader2 as Loader26, Square as Square3, XCircle } from "lucide-react";
7868
- import { useState as useState19 } from "react";
7869
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
8129
+ import { ChevronDown as ChevronDown3, ChevronRight as ChevronRight6, Loader2 as Loader27, Square as Square3, XCircle } from "lucide-react";
8130
+ import { useState as useState20 } from "react";
8131
+ import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
7870
8132
  var PERCENT_FORMATTER = new Intl.NumberFormat("zh-CN", {
7871
8133
  style: "percent",
7872
8134
  maximumFractionDigits: 0
@@ -7915,7 +8177,7 @@ function CompactionCard({
7915
8177
  ...compaction,
7916
8178
  status: status ?? "completed"
7917
8179
  } : activeCompaction;
7918
- const [expanded, setExpanded] = useState19(false);
8180
+ const [expanded, setExpanded] = useState20(false);
7919
8181
  if (!source || !source.compaction_id) {
7920
8182
  return null;
7921
8183
  }
@@ -7926,9 +8188,9 @@ function CompactionCard({
7926
8188
  const hasSummary = typeof source.summary_full === "string" && source.summary_full.trim().length > 0 && !isGenericArchiveSummary(source.summary_full);
7927
8189
  const hasFailureReason = source.status === "failed" && Boolean(source.failure_reason);
7928
8190
  const canExpand = source.status === "completed" && (hasSummary || archivedToolCalls.length > 0) || hasFailureReason;
7929
- return /* @__PURE__ */ jsxs28("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: [
7930
- /* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between gap-2", children: [
7931
- /* @__PURE__ */ jsxs28(
8191
+ return /* @__PURE__ */ jsxs30("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: [
8192
+ /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between gap-2", children: [
8193
+ /* @__PURE__ */ jsxs30(
7932
8194
  "button",
7933
8195
  {
7934
8196
  type: "button",
@@ -7939,21 +8201,21 @@ function CompactionCard({
7939
8201
  ),
7940
8202
  "aria-expanded": expanded,
7941
8203
  children: [
7942
- canExpand ? expanded ? /* @__PURE__ */ jsx33(ChevronDown2, { size: 12, className: "shrink-0" }) : /* @__PURE__ */ jsx33(ChevronRight6, { size: 12, className: "shrink-0" }) : null,
7943
- /* @__PURE__ */ jsx33("span", { children: source.status === "streaming" ? /* @__PURE__ */ jsxs28("span", { className: "inline-flex items-center gap-1", children: [
7944
- /* @__PURE__ */ jsx33(Loader26, { size: 12, className: "animate-spin" }),
8204
+ canExpand ? expanded ? /* @__PURE__ */ jsx35(ChevronDown3, { size: 12, className: "shrink-0" }) : /* @__PURE__ */ jsx35(ChevronRight6, { size: 12, className: "shrink-0" }) : null,
8205
+ /* @__PURE__ */ jsx35("span", { children: source.status === "streaming" ? /* @__PURE__ */ jsxs30("span", { className: "inline-flex items-center gap-1", children: [
8206
+ /* @__PURE__ */ jsx35(Loader27, { size: 12, className: "animate-spin" }),
7945
8207
  "\u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587"
7946
- ] }) : source.status === "failed" ? /* @__PURE__ */ jsxs28("span", { className: "inline-flex items-center gap-1 text-rose-500/80", children: [
7947
- /* @__PURE__ */ jsx33(XCircle, { size: 12 }),
8208
+ ] }) : source.status === "failed" ? /* @__PURE__ */ jsxs30("span", { className: "inline-flex items-center gap-1 text-rose-500/80", children: [
8209
+ /* @__PURE__ */ jsx35(XCircle, { size: 12 }),
7948
8210
  "\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25"
7949
- ] }) : source.status === "interrupted" ? /* @__PURE__ */ jsxs28("span", { className: "inline-flex items-center gap-1 text-amber-500/80", children: [
7950
- /* @__PURE__ */ jsx33(Square3, { size: 11 }),
8211
+ ] }) : source.status === "interrupted" ? /* @__PURE__ */ jsxs30("span", { className: "inline-flex items-center gap-1 text-amber-500/80", children: [
8212
+ /* @__PURE__ */ jsx35(Square3, { size: 11 }),
7951
8213
  "\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88"
7952
8214
  ] }) : "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
7953
8215
  ]
7954
8216
  }
7955
8217
  ),
7956
- canCancel ? /* @__PURE__ */ jsx33(
8218
+ canCancel ? /* @__PURE__ */ jsx35(
7957
8219
  "button",
7958
8220
  {
7959
8221
  type: "button",
@@ -7963,13 +8225,13 @@ function CompactionCard({
7963
8225
  }
7964
8226
  ) : null
7965
8227
  ] }),
7966
- expanded ? /* @__PURE__ */ jsxs28("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: [
7967
- /* @__PURE__ */ jsxs28("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]", children: [
7968
- /* @__PURE__ */ jsxs28("span", { children: [
8228
+ expanded ? /* @__PURE__ */ jsxs30("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: [
8229
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]", children: [
8230
+ /* @__PURE__ */ jsxs30("span", { children: [
7969
8231
  "#",
7970
8232
  shortId(source.compaction_id)
7971
8233
  ] }),
7972
- /* @__PURE__ */ jsxs28("span", { children: [
8234
+ /* @__PURE__ */ jsxs30("span", { children: [
7973
8235
  "\u8282\u7701 ",
7974
8236
  formatSavedRatio(source.saved_ratio),
7975
8237
  "\uFF08",
@@ -7979,31 +8241,31 @@ function CompactionCard({
7979
8241
  formatTokens(source.tokens_after),
7980
8242
  " token\uFF09"
7981
8243
  ] }),
7982
- /* @__PURE__ */ jsxs28("span", { children: [
8244
+ /* @__PURE__ */ jsxs30("span", { children: [
7983
8245
  "\u5F52\u6863 ",
7984
8246
  archivedCount,
7985
8247
  " \u4E2A\u5DE5\u5177\u7ED3\u679C"
7986
8248
  ] })
7987
8249
  ] }),
7988
- archivedToolCalls.length > 0 ? /* @__PURE__ */ jsx33("div", { className: "mt-2 space-y-1.5", children: archivedToolCalls.map((item, index) => {
8250
+ archivedToolCalls.length > 0 ? /* @__PURE__ */ jsx35("div", { className: "mt-2 space-y-1.5", children: archivedToolCalls.map((item, index) => {
7989
8251
  const archivePath = getArchivePath(item, archivedFiles);
7990
- return /* @__PURE__ */ jsxs28(
8252
+ return /* @__PURE__ */ jsxs30(
7991
8253
  "div",
7992
8254
  {
7993
8255
  className: "rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/35 px-2 py-1.5",
7994
8256
  children: [
7995
- /* @__PURE__ */ jsxs28("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]", children: [
7996
- /* @__PURE__ */ jsx33("span", { className: "font-medium", children: getArchivedToolLabel(item) }),
7997
- item.tool_call_id ? /* @__PURE__ */ jsx33("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.tool_call_id }) : null
8257
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]", children: [
8258
+ /* @__PURE__ */ jsx35("span", { className: "font-medium", children: getArchivedToolLabel(item) }),
8259
+ item.tool_call_id ? /* @__PURE__ */ jsx35("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.tool_call_id }) : null
7998
8260
  ] }),
7999
- archivePath ? /* @__PURE__ */ jsx33("div", { className: "mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: archivePath }) : null
8261
+ archivePath ? /* @__PURE__ */ jsx35("div", { className: "mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: archivePath }) : null
8000
8262
  ]
8001
8263
  },
8002
8264
  item.tool_call_id || item.entry_id || `${item.tool_name}-${index}`
8003
8265
  );
8004
8266
  }) }) : null,
8005
- hasSummary ? /* @__PURE__ */ jsx33("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,
8006
- source.status === "failed" && source.failure_reason ? /* @__PURE__ */ jsxs28("div", { className: "mt-2 text-rose-500/90", children: [
8267
+ hasSummary ? /* @__PURE__ */ jsx35("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,
8268
+ source.status === "failed" && source.failure_reason ? /* @__PURE__ */ jsxs30("div", { className: "mt-2 text-rose-500/90", children: [
8007
8269
  "\u5931\u8D25\u539F\u56E0\uFF1A",
8008
8270
  source.failure_reason
8009
8271
  ] }) : null
@@ -8014,7 +8276,7 @@ function CompactionCard({
8014
8276
  // src/react/components/chat/RenderErrorBoundary.tsx
8015
8277
  import { AlertTriangle as AlertTriangle2 } from "lucide-react";
8016
8278
  import { Component } from "react";
8017
- import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
8279
+ import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
8018
8280
  function getFirstComponentName(componentStack) {
8019
8281
  const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
8020
8282
  return match?.[1] ?? null;
@@ -8047,18 +8309,18 @@ var RenderErrorBoundary = class extends Component {
8047
8309
  return children;
8048
8310
  }
8049
8311
  const componentName = getFirstComponentName(componentStack);
8050
- return /* @__PURE__ */ jsx34("div", { className: "rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs29("div", { className: "flex items-start gap-2", children: [
8051
- /* @__PURE__ */ jsx34(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
8052
- /* @__PURE__ */ jsxs29("div", { className: "min-w-0 flex-1", children: [
8053
- /* @__PURE__ */ jsxs29("div", { className: "font-medium", children: [
8312
+ return /* @__PURE__ */ jsx36("div", { className: "rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs31("div", { className: "flex items-start gap-2", children: [
8313
+ /* @__PURE__ */ jsx36(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
8314
+ /* @__PURE__ */ jsxs31("div", { className: "min-w-0 flex-1", children: [
8315
+ /* @__PURE__ */ jsxs31("div", { className: "font-medium", children: [
8054
8316
  label,
8055
8317
  "\u6E32\u67D3\u5931\u8D25"
8056
8318
  ] }),
8057
- /* @__PURE__ */ jsxs29("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
8319
+ /* @__PURE__ */ jsxs31("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
8058
8320
  componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
8059
8321
  error.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
8060
8322
  ] }),
8061
- details ? /* @__PURE__ */ jsx34("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
8323
+ details ? /* @__PURE__ */ jsx36("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
8062
8324
  ] })
8063
8325
  ] }) });
8064
8326
  }
@@ -8076,8 +8338,8 @@ import {
8076
8338
  TerminalSquare,
8077
8339
  WandSparkles
8078
8340
  } from "lucide-react";
8079
- import { useEffect as useEffect17, useMemo as useMemo17, useState as useState20 } from "react";
8080
- import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
8341
+ import { useEffect as useEffect17, useMemo as useMemo18, useState as useState21 } from "react";
8342
+ import { jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
8081
8343
  var EMPTY_EVENTS = [];
8082
8344
  function formatElapsedDuration(durationMs) {
8083
8345
  if (durationMs == null) return null;
@@ -8155,7 +8417,7 @@ function getTurnStartedAt(events) {
8155
8417
  return null;
8156
8418
  }
8157
8419
  function useElapsedDuration(startedAt, active) {
8158
- const [now, setNow] = useState20(() => Date.now());
8420
+ const [now, setNow] = useState21(() => Date.now());
8159
8421
  useEffect17(() => {
8160
8422
  if (!active || startedAt == null) {
8161
8423
  return;
@@ -8179,30 +8441,30 @@ function StickyStatusBar({
8179
8441
  onJumpToLatest
8180
8442
  }) {
8181
8443
  const events = useRuntimeStore((state) => state.events[sessionId] ?? EMPTY_EVENTS);
8182
- const startedAt = useMemo17(() => getTurnStartedAt(events), [events]);
8444
+ const startedAt = useMemo18(() => getTurnStartedAt(events), [events]);
8183
8445
  const elapsedDuration = useElapsedDuration(startedAt, isStreaming && isLastTurn);
8184
- const action = useMemo17(() => getCurrentAction(messages), [messages]);
8446
+ const action = useMemo18(() => getCurrentAction(messages), [messages]);
8185
8447
  if (!isStreaming || !isLastTurn) {
8186
8448
  return null;
8187
8449
  }
8188
8450
  const elapsedLabel = formatElapsedDuration(elapsedDuration);
8189
8451
  const Icon = action.Icon;
8190
- return /* @__PURE__ */ jsxs30(
8452
+ return /* @__PURE__ */ jsxs32(
8191
8453
  "button",
8192
8454
  {
8193
8455
  type: "button",
8194
8456
  onClick: onJumpToLatest,
8195
8457
  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",
8196
8458
  children: [
8197
- /* @__PURE__ */ jsx35("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__ */ jsx35(Icon, { size: 18, className: Icon === LoaderCircle2 ? "animate-spin" : void 0 }) }),
8198
- /* @__PURE__ */ jsxs30("div", { className: "min-w-0 flex-1", children: [
8199
- /* @__PURE__ */ jsx35("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: action.label }),
8200
- /* @__PURE__ */ jsxs30("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
8201
- elapsedLabel ? /* @__PURE__ */ jsxs30("span", { className: "font-mono", children: [
8459
+ /* @__PURE__ */ jsx37("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__ */ jsx37(Icon, { size: 18, className: Icon === LoaderCircle2 ? "animate-spin" : void 0 }) }),
8460
+ /* @__PURE__ */ jsxs32("div", { className: "min-w-0 flex-1", children: [
8461
+ /* @__PURE__ */ jsx37("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: action.label }),
8462
+ /* @__PURE__ */ jsxs32("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
8463
+ elapsedLabel ? /* @__PURE__ */ jsxs32("span", { className: "font-mono", children: [
8202
8464
  "\u5DF2\u6301\u7EED ",
8203
8465
  elapsedLabel
8204
8466
  ] }) : null,
8205
- /* @__PURE__ */ jsx35("span", { children: "\u70B9\u51FB\u8DF3\u5230\u6700\u65B0\u4F4D\u7F6E" })
8467
+ /* @__PURE__ */ jsx37("span", { children: "\u70B9\u51FB\u8DF3\u5230\u6700\u65B0\u4F4D\u7F6E" })
8206
8468
  ] })
8207
8469
  ] })
8208
8470
  ]
@@ -8211,7 +8473,7 @@ function StickyStatusBar({
8211
8473
  }
8212
8474
 
8213
8475
  // src/react/components/chat/TurnNavRail.tsx
8214
- import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
8476
+ import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
8215
8477
  function TurnNavRail({
8216
8478
  items,
8217
8479
  activeTurnId,
@@ -8220,14 +8482,14 @@ function TurnNavRail({
8220
8482
  if (items.length < 2) {
8221
8483
  return null;
8222
8484
  }
8223
- return /* @__PURE__ */ jsx36(
8485
+ return /* @__PURE__ */ jsx38(
8224
8486
  "nav",
8225
8487
  {
8226
8488
  "aria-label": "\u56DE\u5408\u5BFC\u822A",
8227
8489
  className: "absolute right-2 top-4 z-10 hidden flex-col items-end gap-0.5 md:flex",
8228
8490
  children: items.map((item, index) => {
8229
8491
  const isActive = item.id === activeTurnId;
8230
- return /* @__PURE__ */ jsxs31(
8492
+ return /* @__PURE__ */ jsxs33(
8231
8493
  "button",
8232
8494
  {
8233
8495
  type: "button",
@@ -8235,8 +8497,8 @@ function TurnNavRail({
8235
8497
  "aria-current": isActive ? "true" : void 0,
8236
8498
  className: "group relative flex h-3.5 items-center",
8237
8499
  children: [
8238
- /* @__PURE__ */ jsx36("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` }),
8239
- /* @__PURE__ */ jsx36(
8500
+ /* @__PURE__ */ jsx38("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` }),
8501
+ /* @__PURE__ */ jsx38(
8240
8502
  "span",
8241
8503
  {
8242
8504
  className: cn(
@@ -8270,7 +8532,10 @@ function calculateAnchoredScrollTop({
8270
8532
  }
8271
8533
 
8272
8534
  // src/react/components/chat/MessageList.tsx
8273
- import { jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
8535
+ import { jsx as jsx39, jsxs as jsxs34 } from "react/jsx-runtime";
8536
+ function shouldAppendPendingAssistantTurn(sessionIsStreaming, lastMessage) {
8537
+ return sessionIsStreaming && lastMessage !== void 0 && isUserMessage(lastMessage);
8538
+ }
8274
8539
  function parseModeChange(message) {
8275
8540
  if (message.kind !== "mode_change" || typeof message.content !== "string") {
8276
8541
  return null;
@@ -8366,10 +8631,10 @@ function MessageList({
8366
8631
  const agentLoops = useChatStore((state) => state.agentLoops[sessionId]);
8367
8632
  const askAnswers = useChatStore((state) => state.askAnswers[sessionId]);
8368
8633
  const sessionIsStreaming = useChatStore((state) => !!state.isStreaming[sessionId]);
8369
- const agentLoopNameSet = useMemo18(() => new Set(Object.keys(agentLoops ?? {})), [agentLoops]);
8634
+ const agentLoopNameSet = useMemo19(() => new Set(Object.keys(agentLoops ?? {})), [agentLoops]);
8370
8635
  const assistantMessagesCacheRef = useRef13(/* @__PURE__ */ new Map());
8371
8636
  const stickContextRef = useRef13(null);
8372
- const renderBlocks = useMemo18(() => {
8637
+ const renderBlocks = useMemo19(() => {
8373
8638
  const stableAssistantMessages = (key, buffer) => {
8374
8639
  const previous = assistantMessagesCacheRef.current.get(key);
8375
8640
  if (previous && previous.length === buffer.length && previous.every((message, index) => message === buffer[index])) {
@@ -8449,6 +8714,28 @@ function MessageList({
8449
8714
  if (last?.type === "assistant_turn") {
8450
8715
  ;
8451
8716
  last.isStreaming = true;
8717
+ } else if (shouldAppendPendingAssistantTurn(
8718
+ sessionIsStreaming,
8719
+ last?.type === "message" ? last.message : void 0
8720
+ )) {
8721
+ assistantTurnCount += 1;
8722
+ const pendingKey = `pending-assistant-${last.key}`;
8723
+ blocks.push({
8724
+ type: "assistant_turn",
8725
+ messages: [
8726
+ {
8727
+ role: "assistant",
8728
+ content: "",
8729
+ entry_id: pendingKey,
8730
+ status: "streaming",
8731
+ loop_name: "root"
8732
+ }
8733
+ ],
8734
+ key: pendingKey,
8735
+ anchorId: `chat-turn-${assistantTurnCount}`,
8736
+ isStreaming: true,
8737
+ railTitle: lastUserPreview || "\u672C\u8F6E\u56DE\u590D"
8738
+ });
8452
8739
  }
8453
8740
  }
8454
8741
  const activeAssistantKeys = new Set(
@@ -8461,13 +8748,13 @@ function MessageList({
8461
8748
  }
8462
8749
  return blocks;
8463
8750
  }, [agentLoopNameSet, messages, sessionIsStreaming]);
8464
- const hasInterruptedTurn = useMemo18(
8751
+ const hasInterruptedTurn = useMemo19(
8465
8752
  () => renderBlocks.some(
8466
8753
  (block) => block.type === "assistant_turn" && block.messages.some((message) => message.status === "interrupted")
8467
8754
  ),
8468
8755
  [renderBlocks]
8469
8756
  );
8470
- const lastTurnId = useMemo18(() => {
8757
+ const lastTurnId = useMemo19(() => {
8471
8758
  for (let index = renderBlocks.length - 1; index >= 0; index -= 1) {
8472
8759
  const block = renderBlocks[index];
8473
8760
  if (block.type === "assistant_turn") return block.anchorId;
@@ -8475,20 +8762,20 @@ function MessageList({
8475
8762
  }
8476
8763
  return null;
8477
8764
  }, [renderBlocks]);
8478
- const turnNavItems = useMemo18(
8765
+ const turnNavItems = useMemo19(
8479
8766
  () => renderBlocks.filter((block) => block.type === "assistant_turn").map((block) => ({
8480
8767
  id: block.anchorId,
8481
8768
  title: block.railTitle
8482
8769
  })),
8483
8770
  [renderBlocks]
8484
8771
  );
8485
- const stickyTurn = useMemo18(
8772
+ const stickyTurn = useMemo19(
8486
8773
  () => renderBlocks.find(
8487
8774
  (block) => block.type === "assistant_turn" && block.anchorId === lastTurnId && block.isStreaming
8488
8775
  ) ?? null,
8489
8776
  [lastTurnId, renderBlocks]
8490
8777
  );
8491
- const scrollEntryId = useMemo18(() => normalizeScrollEntryKey(scrollToEntryKey), [scrollToEntryKey]);
8778
+ const scrollEntryId = useMemo19(() => normalizeScrollEntryKey(scrollToEntryKey), [scrollToEntryKey]);
8492
8779
  const shouldAnchorEntry = Boolean(scrollEntryId);
8493
8780
  const hasMessages = messages.length > 0;
8494
8781
  const containerRef = useRef13(null);
@@ -8500,8 +8787,8 @@ function MessageList({
8500
8787
  const entryScrollTimeoutRefs = useRef13([]);
8501
8788
  const appliedStartScrollKeyRef = useRef13(null);
8502
8789
  const appliedEntryScrollKeyRef = useRef13(null);
8503
- const [activeTurnId, setActiveTurnId] = useState21(lastTurnId);
8504
- const layoutSignature = useMemo18(
8790
+ const [activeTurnId, setActiveTurnId] = useState22(lastTurnId);
8791
+ const layoutSignature = useMemo19(
8505
8792
  () => getMessagesMeasureSignature(messages),
8506
8793
  [messages]
8507
8794
  );
@@ -8680,13 +8967,13 @@ function MessageList({
8680
8967
  const handleSelectTurn = useCallback12((turnId) => {
8681
8968
  document.getElementById(turnId)?.scrollIntoView({ behavior: "smooth", block: "start" });
8682
8969
  }, []);
8683
- return /* @__PURE__ */ jsxs32(
8970
+ return /* @__PURE__ */ jsxs34(
8684
8971
  "div",
8685
8972
  {
8686
8973
  ref: containerRef,
8687
8974
  className: `relative min-h-0 flex-1 ${customization?.classNames?.messageListRoot ?? ""}`,
8688
8975
  children: [
8689
- turnNavItems.length > 1 ? /* @__PURE__ */ jsx37(
8976
+ turnNavItems.length > 1 ? /* @__PURE__ */ jsx39(
8690
8977
  TurnNavRail,
8691
8978
  {
8692
8979
  items: turnNavItems,
@@ -8694,7 +8981,7 @@ function MessageList({
8694
8981
  onSelectTurn: handleSelectTurn
8695
8982
  }
8696
8983
  ) : null,
8697
- /* @__PURE__ */ jsxs32(
8984
+ /* @__PURE__ */ jsxs34(
8698
8985
  StickToBottom,
8699
8986
  {
8700
8987
  contextRef: stickContextRef,
@@ -8703,7 +8990,7 @@ function MessageList({
8703
8990
  resize: stickyTurn ? { damping: 0.8, stiffness: 0.08, mass: 1 } : "instant",
8704
8991
  targetScrollTop: shouldAnchorEntry ? getAnchorTargetScrollTop : void 0,
8705
8992
  children: [
8706
- /* @__PURE__ */ jsx37(StickToBottom.Content, { className: "px-5 py-6", children: /* @__PURE__ */ jsx37(
8993
+ /* @__PURE__ */ jsx39(StickToBottom.Content, { className: "px-5 pb-7 pt-8 sm:px-10 sm:pt-10", children: /* @__PURE__ */ jsx39(
8707
8994
  MessageListContent,
8708
8995
  {
8709
8996
  askAnswers,
@@ -8720,7 +9007,7 @@ function MessageList({
8720
9007
  customization
8721
9008
  }
8722
9009
  ) }),
8723
- /* @__PURE__ */ jsx37(ScrollToBottomButton, {})
9010
+ /* @__PURE__ */ jsx39(ScrollToBottomButton, {})
8724
9011
  ]
8725
9012
  },
8726
9013
  scrollEntryId ?? "latest"
@@ -8751,8 +9038,8 @@ function MessageListContent({
8751
9038
  }
8752
9039
  scrollToBottom();
8753
9040
  }, [lastTurnId, scrollToBottom]);
8754
- return /* @__PURE__ */ jsx37("div", { className: `mx-auto max-w-3xl ${customization?.classNames?.messageListContent ?? ""}`, children: /* @__PURE__ */ jsxs32("div", { className: `min-w-0 flex flex-col gap-8 ${customization?.classNames?.messageListInner ?? ""}`, children: [
8755
- stickyTurn ? /* @__PURE__ */ jsx37(
9041
+ return /* @__PURE__ */ jsx39("div", { className: `mx-auto max-w-[748px] ${customization?.classNames?.messageListContent ?? ""}`, children: /* @__PURE__ */ jsxs34("div", { className: `min-w-0 flex flex-col gap-9 ${customization?.classNames?.messageListInner ?? ""}`, children: [
9042
+ stickyTurn ? /* @__PURE__ */ jsx39(
8756
9043
  StickyStatusBar,
8757
9044
  {
8758
9045
  sessionId,
@@ -8762,37 +9049,37 @@ function MessageListContent({
8762
9049
  onJumpToLatest: handleJumpToLatest
8763
9050
  }
8764
9051
  ) : null,
8765
- renderBlocks.length === 0 ? customization?.components?.EmptyState ? /* @__PURE__ */ jsx37(customization.components.EmptyState, {}) : /* @__PURE__ */ jsxs32("div", { className: `flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))] ${customization?.classNames?.emptyState ?? ""}`, children: [
8766
- /* @__PURE__ */ jsx37(MessageSquare, { size: 40, strokeWidth: 1.5 }),
8767
- /* @__PURE__ */ jsx37("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
8768
- /* @__PURE__ */ jsx37("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
9052
+ renderBlocks.length === 0 ? customization?.components?.EmptyState ? /* @__PURE__ */ jsx39(customization.components.EmptyState, {}) : /* @__PURE__ */ jsxs34("div", { className: `flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))] ${customization?.classNames?.emptyState ?? ""}`, children: [
9053
+ /* @__PURE__ */ jsx39(MessageSquare, { size: 40, strokeWidth: 1.5 }),
9054
+ /* @__PURE__ */ jsx39("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
9055
+ /* @__PURE__ */ jsx39("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
8769
9056
  ] }) : renderBlocks.map((block, blockIndex) => {
8770
9057
  if (block.type === "message") {
8771
- return /* @__PURE__ */ jsx37(
9058
+ return /* @__PURE__ */ jsx39(
8772
9059
  "div",
8773
9060
  {
8774
9061
  id: block.anchorId ?? void 0,
8775
9062
  "data-entry-id": block.message.entry_id,
8776
9063
  className: "msg-animate scroll-mt-6",
8777
- children: isUserMessage(block.message) ? customization?.components?.UserMessage ? /* @__PURE__ */ jsx37(
9064
+ children: isUserMessage(block.message) ? customization?.components?.UserMessage ? /* @__PURE__ */ jsx39(
8778
9065
  customization.components.UserMessage,
8779
9066
  {
8780
9067
  message: block.message,
8781
9068
  className: customization.classNames?.userMessage
8782
9069
  }
8783
- ) : /* @__PURE__ */ jsx37(
9070
+ ) : /* @__PURE__ */ jsx39(
8784
9071
  UserMessageBubble,
8785
9072
  {
8786
9073
  message: block.message,
8787
9074
  className: customization?.classNames?.userMessage
8788
9075
  }
8789
- ) : isErrorMessage(block.message) ? customization?.components?.ErrorMessage ? /* @__PURE__ */ jsx37(
9076
+ ) : isErrorMessage(block.message) ? customization?.components?.ErrorMessage ? /* @__PURE__ */ jsx39(
8790
9077
  customization.components.ErrorMessage,
8791
9078
  {
8792
9079
  message: block.message,
8793
9080
  className: customization.classNames?.errorMessage
8794
9081
  }
8795
- ) : /* @__PURE__ */ jsx37(
9082
+ ) : /* @__PURE__ */ jsx39(
8796
9083
  ErrorMessageBlock,
8797
9084
  {
8798
9085
  message: block.message,
@@ -8812,7 +9099,7 @@ function MessageListContent({
8812
9099
  );
8813
9100
  const isFollowedByPlanningExit = nextBlock?.type === "planning_divider" && nextBlock.kind === "exit";
8814
9101
  const showPlanCard = (hasExitPlan || isFollowedByPlanningExit) && onConfirmPlan && sessionStatus === "waiting_for_input";
8815
- return /* @__PURE__ */ jsxs32(
9102
+ return /* @__PURE__ */ jsxs34(
8816
9103
  "div",
8817
9104
  {
8818
9105
  id: block.anchorId,
@@ -8820,13 +9107,13 @@ function MessageListContent({
8820
9107
  "data-entry-id": block.messages[0]?.entry_id,
8821
9108
  className: "msg-animate flex scroll-mt-6 flex-col gap-4",
8822
9109
  children: [
8823
- /* @__PURE__ */ jsx37(
9110
+ /* @__PURE__ */ jsx39(
8824
9111
  RenderErrorBoundary,
8825
9112
  {
8826
9113
  label: "\u52A9\u624B\u6D88\u606F",
8827
9114
  details: block.key,
8828
9115
  resetKey: getMessagesResetSignature(block.messages),
8829
- children: customization?.components?.AssistantTurn ? /* @__PURE__ */ jsx37(
9116
+ children: customization?.components?.AssistantTurn ? /* @__PURE__ */ jsx39(
8830
9117
  customization.components.AssistantTurn,
8831
9118
  {
8832
9119
  turnKey: block.key,
@@ -8839,7 +9126,7 @@ function MessageListContent({
8839
9126
  sessionStatus,
8840
9127
  customization
8841
9128
  }
8842
- ) : /* @__PURE__ */ jsx37(
9129
+ ) : /* @__PURE__ */ jsx39(
8843
9130
  AssistantTurnBlock,
8844
9131
  {
8845
9132
  turnKey: block.key,
@@ -8855,13 +9142,13 @@ function MessageListContent({
8855
9142
  )
8856
9143
  }
8857
9144
  ),
8858
- showPlanCard ? /* @__PURE__ */ jsx37(
9145
+ showPlanCard ? /* @__PURE__ */ jsx39(
8859
9146
  RenderErrorBoundary,
8860
9147
  {
8861
9148
  label: "\u89C4\u5212\u6458\u8981",
8862
9149
  details: block.key,
8863
9150
  resetKey: `${sessionStatus ?? ""}:${layoutSignature}`,
8864
- children: /* @__PURE__ */ jsx37(
9151
+ children: /* @__PURE__ */ jsx39(
8865
9152
  PlanSummaryCard,
8866
9153
  {
8867
9154
  messages: extractLatestPlanMessages(messages),
@@ -8877,7 +9164,7 @@ function MessageListContent({
8877
9164
  );
8878
9165
  }
8879
9166
  if (block.type === "compaction") {
8880
- return /* @__PURE__ */ jsx37("div", { className: "msg-animate", children: /* @__PURE__ */ jsx37(
9167
+ return /* @__PURE__ */ jsx39("div", { className: "msg-animate", children: /* @__PURE__ */ jsx39(
8881
9168
  CompactionCard,
8882
9169
  {
8883
9170
  sessionId,
@@ -8886,41 +9173,41 @@ function MessageListContent({
8886
9173
  }
8887
9174
  ) }, block.key);
8888
9175
  }
8889
- return /* @__PURE__ */ jsx37(PlanningDivider, { kind: block.kind }, block.key);
9176
+ return /* @__PURE__ */ jsx39(PlanningDivider, { kind: block.kind }, block.key);
8890
9177
  }),
8891
- sessionStatus === "interrupted" && !hasInterruptedTurn ? /* @__PURE__ */ jsx37("div", { className: "flex", children: /* @__PURE__ */ jsx37("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
9178
+ sessionStatus === "interrupted" && !hasInterruptedTurn ? /* @__PURE__ */ jsx39("div", { className: "flex", children: /* @__PURE__ */ jsx39("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
8892
9179
  ] }) });
8893
9180
  }
8894
9181
  function ScrollToBottomButton() {
8895
9182
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
8896
9183
  if (isAtBottom) return null;
8897
- return /* @__PURE__ */ jsxs32(
9184
+ return /* @__PURE__ */ jsxs34(
8898
9185
  "button",
8899
9186
  {
8900
9187
  type: "button",
8901
9188
  onClick: () => scrollToBottom(),
8902
9189
  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))]",
8903
9190
  children: [
8904
- /* @__PURE__ */ jsx37(ChevronDown3, { size: 14 }),
8905
- /* @__PURE__ */ jsx37("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
9191
+ /* @__PURE__ */ jsx39(ChevronDown4, { size: 14 }),
9192
+ /* @__PURE__ */ jsx39("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
8906
9193
  ]
8907
9194
  }
8908
9195
  );
8909
9196
  }
8910
9197
  function PlanningDivider({ kind }) {
8911
9198
  const isEnter = kind === "enter";
8912
- return /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-3 py-1", children: [
8913
- /* @__PURE__ */ jsx37("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
8914
- /* @__PURE__ */ jsxs32("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: [
8915
- /* @__PURE__ */ jsx37(Lightbulb2, { size: 12 }),
8916
- /* @__PURE__ */ jsx37("span", { children: isEnter ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
9199
+ return /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-3 py-1", children: [
9200
+ /* @__PURE__ */ jsx39("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
9201
+ /* @__PURE__ */ jsxs34("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: [
9202
+ /* @__PURE__ */ jsx39(Lightbulb2, { size: 12 }),
9203
+ /* @__PURE__ */ jsx39("span", { children: isEnter ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
8917
9204
  ] }),
8918
- /* @__PURE__ */ jsx37("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
9205
+ /* @__PURE__ */ jsx39("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
8919
9206
  ] });
8920
9207
  }
8921
9208
 
8922
9209
  // src/react/components/chat/ChatView.tsx
8923
- import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
9210
+ import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
8924
9211
  function ChatView({
8925
9212
  sessionId,
8926
9213
  renderAttachments,
@@ -8965,22 +9252,22 @@ function ChatView({
8965
9252
  },
8966
9253
  [send]
8967
9254
  );
8968
- const customization = useMemo19(
9255
+ const customization = useMemo20(
8969
9256
  () => ({ classNames, components, renderers }),
8970
9257
  [classNames, components, renderers]
8971
9258
  );
8972
9259
  const SkillStatus = components?.SkillStatusBar;
8973
- return /* @__PURE__ */ jsxs33("div", { className: `flex min-h-0 flex-1 flex-col overflow-hidden ${classNames?.root ?? ""}`, children: [
8974
- isViewer && /* @__PURE__ */ jsxs33("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: [
8975
- /* @__PURE__ */ jsx38(Eye, { size: 14 }),
9260
+ return /* @__PURE__ */ jsxs35("div", { className: `flex min-h-0 flex-1 flex-col overflow-hidden ${classNames?.root ?? ""}`, children: [
9261
+ isViewer && /* @__PURE__ */ jsxs35("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: [
9262
+ /* @__PURE__ */ jsx40(Eye, { size: 14 }),
8976
9263
  "\u4F60\u6B63\u5728\u67E5\u770B\u5206\u4EAB\u7684\u4F1A\u8BDD\uFF08\u53EA\u8BFB\uFF09"
8977
9264
  ] }),
8978
- !isViewer && /* @__PURE__ */ jsx38(ConnectionBanner, {}),
8979
- errorMessage && /* @__PURE__ */ jsxs33("div", { className: "flex items-start gap-2 border-b border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800 dark:border-red-800/30 dark:bg-red-950/30 dark:text-red-300", children: [
8980
- /* @__PURE__ */ jsx38(CircleAlert2, { size: 16, className: "mt-0.5 shrink-0" }),
8981
- /* @__PURE__ */ jsx38("span", { children: errorMessage })
9265
+ !isViewer && /* @__PURE__ */ jsx40(ConnectionBanner, {}),
9266
+ errorMessage && /* @__PURE__ */ jsxs35("div", { className: "flex items-start gap-2 border-b border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800 dark:border-red-800/30 dark:bg-red-950/30 dark:text-red-300", children: [
9267
+ /* @__PURE__ */ jsx40(CircleAlert2, { size: 16, className: "mt-0.5 shrink-0" }),
9268
+ /* @__PURE__ */ jsx40("span", { children: errorMessage })
8982
9269
  ] }),
8983
- /* @__PURE__ */ jsx38(
9270
+ /* @__PURE__ */ jsx40(
8984
9271
  MessageList,
8985
9272
  {
8986
9273
  sessionId,
@@ -8994,7 +9281,7 @@ function ChatView({
8994
9281
  },
8995
9282
  sessionId
8996
9283
  ),
8997
- !isViewer && /* @__PURE__ */ jsx38(
9284
+ !isViewer && /* @__PURE__ */ jsx40(
8998
9285
  ChatInput,
8999
9286
  {
9000
9287
  onSend: (msg, options) => send(msg, mode, void 0, {
@@ -9053,6 +9340,7 @@ export {
9053
9340
  skillMentionSuggestionKey,
9054
9341
  SkillMention,
9055
9342
  ThinkingToggle,
9343
+ PlanningToggle,
9056
9344
  ChatInput,
9057
9345
  ResourceIframe,
9058
9346
  ImageLightbox,
@@ -9079,4 +9367,4 @@ use-stick-to-bottom/dist/StickToBottom.js:
9079
9367
  * Licensed under the MIT License. See License.txt in the project root for license information.
9080
9368
  *--------------------------------------------------------------------------------------------*)
9081
9369
  */
9082
- //# sourceMappingURL=chunk-3XDPNPE3.js.map
9370
+ //# sourceMappingURL=chunk-IGMLETZX.js.map