@blade-hq/agent-kit 0.5.0 → 0.5.1

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.
@@ -8,13 +8,13 @@ import {
8
8
  getCodeLanguageFromFilename,
9
9
  parseAskUserQuestion,
10
10
  useHighlightedCodeHtml
11
- } from "./chunk-2FTEBWEM.js";
11
+ } from "./chunk-DAFIIANJ.js";
12
12
  import {
13
13
  Collapsible,
14
14
  CollapsibleContent,
15
15
  CollapsibleTrigger,
16
16
  resolveSessionFilePreviewTarget
17
- } from "./chunk-CFZDKYT3.js";
17
+ } from "./chunk-UPHYN7CQ.js";
18
18
  import {
19
19
  buildMessageContent,
20
20
  buildToolPreviewKey,
@@ -23,6 +23,7 @@ import {
23
23
  extractToolFilePath,
24
24
  formatToolName,
25
25
  getAuthedUrl,
26
+ getBackgroundTask,
26
27
  getClient,
27
28
  getFileParts,
28
29
  getImageParts,
@@ -56,7 +57,7 @@ import {
56
57
  useUiBridgeStore,
57
58
  useUiStore,
58
59
  writeFile
59
- } from "./chunk-C7VSMOXN.js";
60
+ } from "./chunk-DSBIKYKQ.js";
60
61
  import {
61
62
  registerBridgeIframe,
62
63
  tapBridgeEvent
@@ -152,7 +153,7 @@ import {
152
153
  ChevronDown,
153
154
  File as File2,
154
155
  FileCode2,
155
- FileText,
156
+ FileText as FileText2,
156
157
  Film,
157
158
  FolderUp,
158
159
  CircleHelp,
@@ -171,7 +172,7 @@ import {
171
172
  Send,
172
173
  Sparkles as Sparkles2,
173
174
  Share2,
174
- Square,
175
+ Square as Square2,
175
176
  X as X2
176
177
  } from "lucide-react";
177
178
  import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
@@ -180,7 +181,7 @@ import {
180
181
  useEffectEvent as useEffectEvent2,
181
182
  useMemo as useMemo7,
182
183
  useRef as useRef4,
183
- useState as useState6
184
+ useState as useState7
184
185
  } from "react";
185
186
  import { createRoot } from "react-dom/client";
186
187
  import { toast } from "sonner";
@@ -1258,11 +1259,177 @@ var SkillCompletionMenu = forwardRef2(
1258
1259
  }
1259
1260
  );
1260
1261
 
1262
+ // src/react/components/chat/BackgroundTasksPill.tsx
1263
+ import { FileText, Square, Terminal } from "lucide-react";
1264
+ import { useState as useState6 } from "react";
1265
+
1266
+ // src/react/hooks/use-background-tasks.ts
1267
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
1268
+ var EMPTY_TASKS = [];
1269
+ function useBackgroundTasks(sessionId) {
1270
+ const setTasks = useBackgroundStore((state) => state.setTasks);
1271
+ const tasks = useBackgroundStore((state) => sessionId ? state.tasks[sessionId] : void 0);
1272
+ const query = useQuery2({
1273
+ queryKey: ["background-tasks", sessionId],
1274
+ queryFn: ({ signal }) => listBackgroundTasks(sessionId, { signal }).then((items) => {
1275
+ setTasks(sessionId, items);
1276
+ return items;
1277
+ }),
1278
+ enabled: Boolean(sessionId)
1279
+ });
1280
+ return {
1281
+ data: tasks ?? query.data ?? EMPTY_TASKS,
1282
+ loading: query.isLoading,
1283
+ error: query.error,
1284
+ refetch: query.refetch
1285
+ };
1286
+ }
1287
+
1288
+ // src/react/components/chat/BackgroundTasksPill.tsx
1289
+ import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1290
+ function formatStartedAt(value) {
1291
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
1292
+ return "\u542F\u52A8\u65F6\u95F4\u672A\u77E5";
1293
+ }
1294
+ return new Intl.DateTimeFormat("zh-CN", {
1295
+ hour: "2-digit",
1296
+ minute: "2-digit"
1297
+ }).format(new Date(value * 1e3));
1298
+ }
1299
+ function statusLabel(status) {
1300
+ if (status === "running") return "\u8FD0\u884C\u4E2D";
1301
+ if (status === "failed") return "\u5931\u8D25";
1302
+ if (status === "cancelled") return "\u5DF2\u505C\u6B62";
1303
+ if (status === "done" || status === "succeeded") return "\u5DF2\u7ED3\u675F";
1304
+ return status || "\u672A\u77E5";
1305
+ }
1306
+ function statusClass(status) {
1307
+ if (status === "running") return "border-amber-500/35 bg-amber-500/10 text-amber-500";
1308
+ if (status === "failed") return "border-rose-500/35 bg-rose-500/10 text-rose-500";
1309
+ return "border-[hsl(var(--border))] bg-[hsl(var(--muted))]/40 text-[hsl(var(--muted-foreground))]";
1310
+ }
1311
+ function BackgroundTasksPill({ sessionId }) {
1312
+ const { data: tasks } = useBackgroundTasks(sessionId);
1313
+ const [open, setOpen] = useState6(false);
1314
+ const [logTask, setLogTask] = useState6(null);
1315
+ if (tasks.length === 0) return null;
1316
+ const runningCount = tasks.filter((task) => task.status === "running").length;
1317
+ const openTaskLog = async (task) => {
1318
+ const title = `${task.id} ${task.description || task.command || "\u540E\u53F0\u4EFB\u52A1"}`;
1319
+ setLogTask({ id: task.id, title, output: "", loading: true, error: null });
1320
+ try {
1321
+ const detail = await getBackgroundTask(sessionId, task.id, 300);
1322
+ setLogTask({
1323
+ id: task.id,
1324
+ title,
1325
+ output: detail.output || "\u6682\u65E0\u8F93\u51FA",
1326
+ loading: false,
1327
+ error: null
1328
+ });
1329
+ } catch (error) {
1330
+ setLogTask({
1331
+ id: task.id,
1332
+ title,
1333
+ output: "",
1334
+ loading: false,
1335
+ error: error instanceof Error ? error.message : "\u65E5\u5FD7\u52A0\u8F7D\u5931\u8D25"
1336
+ });
1337
+ }
1338
+ };
1339
+ const requestStopTask = (task) => {
1340
+ const name = `${task.id}\uFF08${task.description || task.command || "\u540E\u53F0\u4EFB\u52A1"}\uFF09`;
1341
+ getSocket().send(
1342
+ sessionId,
1343
+ `\u8BF7\u5148\u5411\u6211\u4E8C\u6B21\u786E\u8BA4\uFF0C\u7136\u540E\u5E2E\u6211\u505C\u6B62\u540E\u53F0\u4EFB\u52A1 ${name}\u3002`,
1344
+ "executing"
1345
+ );
1346
+ setOpen(false);
1347
+ };
1348
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
1349
+ logTask ? /* @__PURE__ */ jsx5("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/55 p-4", children: /* @__PURE__ */ jsxs4("div", { className: "flex max-h-[82vh] w-full max-w-3xl flex-col overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl", children: [
1350
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-3", children: [
1351
+ /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
1352
+ /* @__PURE__ */ jsx5("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: logTask.title }),
1353
+ /* @__PURE__ */ jsx5("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u540E\u53F0\u4EFB\u52A1\u65E5\u5FD7" })
1354
+ ] }),
1355
+ /* @__PURE__ */ jsx5(
1356
+ "button",
1357
+ {
1358
+ type: "button",
1359
+ onClick: () => setLogTask(null),
1360
+ className: "rounded-md border border-[hsl(var(--border))] px-2.5 py-1 text-xs text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]",
1361
+ children: "\u5173\u95ED"
1362
+ }
1363
+ )
1364
+ ] }),
1365
+ /* @__PURE__ */ jsx5("pre", { className: "min-h-64 flex-1 overflow-auto whitespace-pre-wrap p-4 font-mono text-xs leading-5 text-[hsl(var(--foreground))]", children: logTask.loading ? "\u52A0\u8F7D\u4E2D..." : logTask.error || logTask.output })
1366
+ ] }) }) : null,
1367
+ /* @__PURE__ */ jsxs4("div", { className: "relative mb-2 flex justify-start", children: [
1368
+ /* @__PURE__ */ jsxs4(
1369
+ "button",
1370
+ {
1371
+ type: "button",
1372
+ onClick: () => setOpen((value) => !value),
1373
+ className: cn(
1374
+ "inline-flex h-8 items-center gap-2 rounded-full border px-3 text-xs font-medium shadow-sm transition-colors",
1375
+ runningCount > 0 ? "border-amber-500/35 bg-amber-500/10 text-amber-600" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--muted-foreground))]"
1376
+ ),
1377
+ children: [
1378
+ /* @__PURE__ */ jsx5(Terminal, { size: 13 }),
1379
+ "\u540E\u53F0\u4EFB\u52A1 ",
1380
+ tasks.length,
1381
+ runningCount > 0 ? /* @__PURE__ */ jsxs4("span", { children: [
1382
+ "\u8FD0\u884C\u4E2D ",
1383
+ runningCount
1384
+ ] }) : null
1385
+ ]
1386
+ }
1387
+ ),
1388
+ open ? /* @__PURE__ */ jsx5("div", { className: "absolute bottom-full left-0 z-40 mb-2 w-[min(24rem,calc(100vw-2rem))] rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-2 text-xs text-[hsl(var(--popover-foreground))] shadow-xl", children: /* @__PURE__ */ jsx5("div", { className: "max-h-72 space-y-2 overflow-y-auto", children: tasks.map((task) => /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-[hsl(var(--border))] p-2", children: [
1389
+ /* @__PURE__ */ jsx5("div", { className: "flex items-start justify-between gap-2", children: /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
1390
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1391
+ /* @__PURE__ */ jsx5("span", { className: "font-mono font-semibold", children: task.id }),
1392
+ /* @__PURE__ */ jsx5("span", { className: cn("rounded-full border px-1.5 py-0.5 text-[10px]", statusClass(task.status)), children: statusLabel(task.status) })
1393
+ ] }),
1394
+ /* @__PURE__ */ jsx5("div", { className: "mt-1 break-words text-[hsl(var(--foreground))]", children: task.description || task.command }),
1395
+ /* @__PURE__ */ jsx5("div", { className: "mt-1 text-[11px] text-[hsl(var(--muted-foreground))]", children: formatStartedAt(task.started_at) })
1396
+ ] }) }),
1397
+ /* @__PURE__ */ jsxs4("div", { className: "mt-2 flex items-center gap-1.5", children: [
1398
+ /* @__PURE__ */ jsxs4(
1399
+ "button",
1400
+ {
1401
+ type: "button",
1402
+ onClick: () => void openTaskLog(task),
1403
+ className: "inline-flex h-6 items-center gap-1 rounded-md border border-[hsl(var(--border))] px-2 text-[11px] hover:bg-[hsl(var(--accent))]",
1404
+ children: [
1405
+ /* @__PURE__ */ jsx5(FileText, { size: 11 }),
1406
+ "\u65E5\u5FD7"
1407
+ ]
1408
+ }
1409
+ ),
1410
+ task.status === "running" ? /* @__PURE__ */ jsxs4(
1411
+ "button",
1412
+ {
1413
+ type: "button",
1414
+ onClick: () => requestStopTask(task),
1415
+ className: "inline-flex h-6 items-center gap-1 rounded-md border border-rose-500/35 px-2 text-[11px] text-rose-500 hover:bg-rose-500/10",
1416
+ children: [
1417
+ /* @__PURE__ */ jsx5(Square, { size: 10 }),
1418
+ "\u505C\u6B62"
1419
+ ]
1420
+ }
1421
+ ) : null
1422
+ ] })
1423
+ ] }, task.id)) }) }) : null
1424
+ ] })
1425
+ ] });
1426
+ }
1427
+
1261
1428
  // src/react/components/chat/FileSizeLimitDialog.tsx
1262
1429
  import { X } from "lucide-react";
1263
1430
  import { useEffect as useEffect6 } from "react";
1264
1431
  import { createPortal } from "react-dom";
1265
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1432
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1266
1433
  function FileSizeLimitDialog({
1267
1434
  open,
1268
1435
  onOpenChange,
@@ -1284,7 +1451,7 @@ function FileSizeLimitDialog({
1284
1451
  }
1285
1452
  const limitText = formatFileSize(limitBytes);
1286
1453
  return createPortal(
1287
- /* @__PURE__ */ jsx5(
1454
+ /* @__PURE__ */ jsx6(
1288
1455
  "div",
1289
1456
  {
1290
1457
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",
@@ -1297,45 +1464,45 @@ function FileSizeLimitDialog({
1297
1464
  role: "dialog",
1298
1465
  "aria-modal": "true",
1299
1466
  "aria-labelledby": "file-size-limit-dialog-title",
1300
- children: /* @__PURE__ */ jsxs4(
1467
+ children: /* @__PURE__ */ jsxs5(
1301
1468
  "div",
1302
1469
  {
1303
1470
  className: "w-full max-w-lg overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl",
1304
1471
  onClick: (event) => event.stopPropagation(),
1305
1472
  onKeyDown: (event) => event.stopPropagation(),
1306
1473
  children: [
1307
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
1308
- /* @__PURE__ */ jsxs4("div", { children: [
1309
- /* @__PURE__ */ jsx5("h3", { id: "file-size-limit-dialog-title", className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
1310
- /* @__PURE__ */ jsxs4("p", { className: "mt-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
1474
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
1475
+ /* @__PURE__ */ jsxs5("div", { children: [
1476
+ /* @__PURE__ */ jsx6("h3", { id: "file-size-limit-dialog-title", className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u9644\u4EF6\u8D85\u8FC7\u5927\u5C0F\u9650\u5236" }),
1477
+ /* @__PURE__ */ jsxs5("p", { className: "mt-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
1311
1478
  "\u5355\u4E2A\u9644\u4EF6\u6700\u5927\u652F\u6301 ",
1312
1479
  limitText,
1313
1480
  "\u3002\u4EE5\u4E0B\u6587\u4EF6\u672A\u52A0\u5165\u9644\u4EF6\u5217\u8868\u3002"
1314
1481
  ] })
1315
1482
  ] }),
1316
- /* @__PURE__ */ jsx5(
1483
+ /* @__PURE__ */ jsx6(
1317
1484
  "button",
1318
1485
  {
1319
1486
  type: "button",
1320
1487
  onClick: () => onOpenChange(false),
1321
1488
  title: "\u5173\u95ED",
1322
1489
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
1323
- children: /* @__PURE__ */ jsx5(X, { size: 14 })
1490
+ children: /* @__PURE__ */ jsx6(X, { size: 14 })
1324
1491
  }
1325
1492
  )
1326
1493
  ] }),
1327
- /* @__PURE__ */ jsx5("div", { className: "max-h-[min(50vh,24rem)] overflow-auto px-4 py-3", children: /* @__PURE__ */ jsx5("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsxs4(
1494
+ /* @__PURE__ */ jsx6("div", { className: "max-h-[min(50vh,24rem)] overflow-auto px-4 py-3", children: /* @__PURE__ */ jsx6("div", { className: "flex flex-col gap-2", children: files.map((file) => /* @__PURE__ */ jsxs5(
1328
1495
  "div",
1329
1496
  {
1330
1497
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-3 py-2",
1331
1498
  children: [
1332
- /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
1333
- /* @__PURE__ */ jsx5("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatFileSize(file.size) })
1499
+ /* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate text-sm text-[hsl(var(--foreground))]", children: file.name }),
1500
+ /* @__PURE__ */ jsx6("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatFileSize(file.size) })
1334
1501
  ]
1335
1502
  },
1336
1503
  `${file.name}:${file.size}`
1337
1504
  )) }) }),
1338
- /* @__PURE__ */ jsx5("div", { className: "flex justify-end border-t border-[hsl(var(--border))] px-4 py-3", children: /* @__PURE__ */ jsx5(
1505
+ /* @__PURE__ */ jsx6("div", { className: "flex justify-end border-t border-[hsl(var(--border))] px-4 py-3", children: /* @__PURE__ */ jsx6(
1339
1506
  "button",
1340
1507
  {
1341
1508
  type: "button",
@@ -1358,28 +1525,6 @@ import { useQuery as useQuery5 } from "@tanstack/react-query";
1358
1525
  import { RefreshCw } from "lucide-react";
1359
1526
  import { useMemo as useMemo6 } from "react";
1360
1527
 
1361
- // src/react/hooks/use-background-tasks.ts
1362
- import { useQuery as useQuery2 } from "@tanstack/react-query";
1363
- var EMPTY_TASKS = [];
1364
- function useBackgroundTasks(sessionId) {
1365
- const setTasks = useBackgroundStore((state) => state.setTasks);
1366
- const tasks = useBackgroundStore((state) => sessionId ? state.tasks[sessionId] : void 0);
1367
- const query = useQuery2({
1368
- queryKey: ["background-tasks", sessionId],
1369
- queryFn: ({ signal }) => listBackgroundTasks(sessionId, { signal }).then((items) => {
1370
- setTasks(sessionId, items);
1371
- return items;
1372
- }),
1373
- enabled: Boolean(sessionId)
1374
- });
1375
- return {
1376
- data: tasks ?? query.data ?? EMPTY_TASKS,
1377
- loading: query.isLoading,
1378
- error: query.error,
1379
- refetch: query.refetch
1380
- };
1381
- }
1382
-
1383
1528
  // src/react/hooks/use-context-stats.ts
1384
1529
  import { useQuery as useQuery3 } from "@tanstack/react-query";
1385
1530
  var EMPTY_CONTEXT_STATS = {
@@ -1455,7 +1600,7 @@ function useTokenPressure(sessionId) {
1455
1600
  }
1456
1601
 
1457
1602
  // src/react/components/chat/ProgressCircle.tsx
1458
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1603
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1459
1604
  var LEVEL_STYLES = {
1460
1605
  normal: {
1461
1606
  strokeClass: "stroke-slate-400",
@@ -1486,15 +1631,15 @@ function ProgressCircle({
1486
1631
  const circumference = 2 * Math.PI * radius;
1487
1632
  const dashOffset = circumference * (1 - clamped / 100);
1488
1633
  const styles = LEVEL_STYLES[level];
1489
- return /* @__PURE__ */ jsxs5("div", { className: cn("group relative inline-flex", className), children: [
1490
- /* @__PURE__ */ jsx6(
1634
+ return /* @__PURE__ */ jsxs6("div", { className: cn("group relative inline-flex", className), children: [
1635
+ /* @__PURE__ */ jsx7(
1491
1636
  "button",
1492
1637
  {
1493
1638
  type: "button",
1494
1639
  "aria-label": `\u4E0A\u4E0B\u6587\u5DF2\u4F7F\u7528 ${Math.round(clamped)}%`,
1495
1640
  className: "relative inline-flex cursor-help items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--background))]",
1496
- children: /* @__PURE__ */ jsxs5("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": "true", children: [
1497
- /* @__PURE__ */ jsx6(
1641
+ children: /* @__PURE__ */ jsxs6("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": "true", children: [
1642
+ /* @__PURE__ */ jsx7(
1498
1643
  "circle",
1499
1644
  {
1500
1645
  cx: size / 2,
@@ -1505,7 +1650,7 @@ function ProgressCircle({
1505
1650
  className: styles.trackClass
1506
1651
  }
1507
1652
  ),
1508
- /* @__PURE__ */ jsx6(
1653
+ /* @__PURE__ */ jsx7(
1509
1654
  "circle",
1510
1655
  {
1511
1656
  cx: size / 2,
@@ -1523,12 +1668,12 @@ function ProgressCircle({
1523
1668
  ] })
1524
1669
  }
1525
1670
  ),
1526
- detail ? /* @__PURE__ */ jsx6("div", { className: "pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block group-focus-within:block", children: detail }) : null
1671
+ detail ? /* @__PURE__ */ jsx7("div", { className: "pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block group-focus-within:block", children: detail }) : null
1527
1672
  ] });
1528
1673
  }
1529
1674
 
1530
1675
  // src/react/components/chat/SkillStatusBar.tsx
1531
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1676
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1532
1677
  var COMPACT_NUMBER_FORMATTER = new Intl.NumberFormat("zh-CN", {
1533
1678
  notation: "compact",
1534
1679
  maximumFractionDigits: 1
@@ -1572,8 +1717,8 @@ function HoverPanel({
1572
1717
  title,
1573
1718
  children
1574
1719
  }) {
1575
- return /* @__PURE__ */ jsxs6("div", { className: "pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block", children: [
1576
- /* @__PURE__ */ jsx7("div", { className: "mb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-400", children: title }),
1720
+ return /* @__PURE__ */ jsxs7("div", { className: "absolute bottom-full left-1/2 z-20 mb-2 hidden w-80 max-w-[min(22rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block", children: [
1721
+ /* @__PURE__ */ jsx8("div", { className: "mb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-400", children: title }),
1577
1722
  children
1578
1723
  ] });
1579
1724
  }
@@ -1592,13 +1737,10 @@ function SkillStatusBar({
1592
1737
  enabled: Boolean(sessionId)
1593
1738
  });
1594
1739
  const { data: contextStats } = useContextStats(sessionId);
1595
- const { data: tasks } = useBackgroundTasks(sessionId);
1596
1740
  const tokenPressure = useTokenPressure(sessionId);
1597
1741
  const connectionStatus = useConnectionStore((state) => state.status);
1598
1742
  const reconnectAttempt = useConnectionStore((state) => state.reconnectAttempt);
1599
1743
  const hasEverConnected = useConnectionStore((state) => state.hasEverConnected);
1600
- const runningTaskItems = tasks.filter((task) => task.status === "running");
1601
- const runningTasks = runningTaskItems.length;
1602
1744
  const statsReady = !loading && !error;
1603
1745
  const skillStoreConnected = statsReady && skillStats.remote_connected;
1604
1746
  const connectionMeta = useMemo6(
@@ -1610,11 +1752,6 @@ function SkillStatusBar({
1610
1752
  [connectionStatus, reconnectAttempt, hasEverConnected]
1611
1753
  );
1612
1754
  const items = [
1613
- {
1614
- key: "bg",
1615
- dotClass: runningTasks > 0 ? "bg-amber-400" : "bg-[hsl(var(--muted-foreground))]",
1616
- text: `\u540E\u53F0\u4EFB\u52A1 ${runningTasks}`
1617
- },
1618
1755
  {
1619
1756
  key: "loaded",
1620
1757
  dotClass: statsReady ? "bg-emerald-500" : "bg-[hsl(var(--muted-foreground))]",
@@ -1628,18 +1765,18 @@ function SkillStatusBar({
1628
1765
  ].filter((item) => item.key !== "total" || skillStats.remote_configured);
1629
1766
  const tokenSummary = useMemo6(() => {
1630
1767
  return {
1631
- detail: /* @__PURE__ */ jsxs6("div", { className: "space-y-1", children: [
1632
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3 border-t border-slate-800 pt-1", children: [
1633
- /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "\u5DF2\u7528" }),
1634
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: formatTokenNumber(contextStats.tokens_used) })
1768
+ detail: /* @__PURE__ */ jsxs7("div", { className: "space-y-1", children: [
1769
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3 border-t border-slate-800 pt-1", children: [
1770
+ /* @__PURE__ */ jsx8("span", { className: "text-slate-400", children: "\u5DF2\u7528" }),
1771
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: formatTokenNumber(contextStats.tokens_used) })
1635
1772
  ] }),
1636
- contextStats.context_window > 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3", children: [
1637
- /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "\u4E0A\u4E0B\u6587\u7A97\u53E3" }),
1638
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: formatCompactNumber(contextStats.context_window) })
1639
- ] }) : /* @__PURE__ */ jsx7("div", { className: "pt-1 text-slate-500", children: "\u672A\u914D\u7F6E\u4E0A\u4E0B\u6587\u7A97\u53E3\u5927\u5C0F\uFF0C\u53EF\u901A\u8FC7 CONTEXT_WINDOW \u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E" }),
1640
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3", children: [
1641
- /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "\u6574\u7406\u9608\u503C" }),
1642
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: contextStats.compaction_ratio > 0 ? `${Math.round(contextStats.compaction_ratio * 100)}%` : "\u5DF2\u7981\u7528" })
1773
+ contextStats.context_window > 0 ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3", children: [
1774
+ /* @__PURE__ */ jsx8("span", { className: "text-slate-400", children: "\u4E0A\u4E0B\u6587\u7A97\u53E3" }),
1775
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: formatCompactNumber(contextStats.context_window) })
1776
+ ] }) : /* @__PURE__ */ jsx8("div", { className: "pt-1 text-slate-500", children: "\u672A\u914D\u7F6E\u4E0A\u4E0B\u6587\u7A97\u53E3\u5927\u5C0F\uFF0C\u53EF\u901A\u8FC7 CONTEXT_WINDOW \u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E" }),
1777
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3", children: [
1778
+ /* @__PURE__ */ jsx8("span", { className: "text-slate-400", children: "\u6574\u7406\u9608\u503C" }),
1779
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: contextStats.compaction_ratio > 0 ? `${Math.round(contextStats.compaction_ratio * 100)}%` : "\u5DF2\u7981\u7528" })
1643
1780
  ] })
1644
1781
  ] }),
1645
1782
  label: contextStats.context_window > 0 ? `${formatTokensK(contextStats.tokens_used)} / ${formatTokensK(contextStats.context_window)} \u4E0A\u4E0B\u6587` : `${formatTokensK(contextStats.tokens_used)} \u4E0A\u4E0B\u6587`,
@@ -1649,9 +1786,9 @@ function SkillStatusBar({
1649
1786
  const containerClass = vertical ? "text-[11px] text-[hsl(var(--muted-foreground))]" : "bg-[hsl(var(--background))] px-5 pt-2";
1650
1787
  const innerClass = vertical ? "" : "mx-auto max-w-3xl";
1651
1788
  const listClass = vertical ? "flex flex-col items-stretch gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]" : "flex flex-wrap items-center gap-2 text-[10px] text-[hsl(var(--muted-foreground))]";
1652
- return /* @__PURE__ */ jsx7("div", { className: cn(containerClass, className), children: /* @__PURE__ */ jsx7("div", { className: cn(innerClass, innerClassName), children: /* @__PURE__ */ jsxs6("div", { className: listClass, children: [
1653
- tokenSummary ? /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1", children: [
1654
- /* @__PURE__ */ jsx7(
1789
+ return /* @__PURE__ */ jsx8("div", { className: cn(containerClass, className), children: /* @__PURE__ */ jsx8("div", { className: cn(innerClass, innerClassName), children: /* @__PURE__ */ jsxs7("div", { className: listClass, children: [
1790
+ tokenSummary ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1", children: [
1791
+ /* @__PURE__ */ jsx8(
1655
1792
  ProgressCircle,
1656
1793
  {
1657
1794
  percentage: tokenPressure.ratio * 100,
@@ -1659,10 +1796,10 @@ function SkillStatusBar({
1659
1796
  detail: tokenSummary.detail
1660
1797
  }
1661
1798
  ),
1662
- /* @__PURE__ */ jsx7("span", { className: "font-mono", children: tokenSummary.label }),
1663
- tokenSummary.warn ? /* @__PURE__ */ jsx7("span", { className: "rounded-full border border-rose-500/25 bg-rose-500/10 px-1.5 py-0.5 text-[10px] font-medium text-rose-200", children: "\u5EFA\u8BAE\u6574\u7406\u5BF9\u8BDD" }) : null
1799
+ /* @__PURE__ */ jsx8("span", { className: "font-mono", children: tokenSummary.label }),
1800
+ tokenSummary.warn ? /* @__PURE__ */ jsx8("span", { className: "rounded-full border border-rose-500/25 bg-rose-500/10 px-1.5 py-0.5 text-[10px] font-medium text-rose-200", children: "\u5EFA\u8BAE\u6574\u7406\u5BF9\u8BDD" }) : null
1664
1801
  ] }) : null,
1665
- connectionStatus !== "connected" ? /* @__PURE__ */ jsxs6(
1802
+ connectionStatus !== "connected" ? /* @__PURE__ */ jsxs7(
1666
1803
  "div",
1667
1804
  {
1668
1805
  className: cn(
@@ -1670,30 +1807,21 @@ function SkillStatusBar({
1670
1807
  connectionMeta.toneClass
1671
1808
  ),
1672
1809
  children: [
1673
- /* @__PURE__ */ jsx7("span", { className: cn("inline-block h-1.5 w-1.5 rounded-full", connectionMeta.dotClass) }),
1674
- /* @__PURE__ */ jsx7("span", { children: connectionMeta.label })
1810
+ /* @__PURE__ */ jsx8("span", { className: cn("inline-block h-1.5 w-1.5 rounded-full", connectionMeta.dotClass) }),
1811
+ /* @__PURE__ */ jsx8("span", { children: connectionMeta.label })
1675
1812
  ]
1676
1813
  }
1677
1814
  ) : null,
1678
- items.map((item, index) => /* @__PURE__ */ jsxs6(
1815
+ items.map((item, index) => /* @__PURE__ */ jsxs7(
1679
1816
  "div",
1680
1817
  {
1681
1818
  className: "flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1",
1682
1819
  children: [
1683
- index > 0 && !tokenPressure && /* @__PURE__ */ jsx7("span", { className: "hidden text-[hsl(var(--border))]", children: "\xB7" }),
1684
- /* @__PURE__ */ jsx7("span", { className: `inline-block h-1.5 w-1.5 rounded-full ${item.dotClass}` }),
1685
- item.key === "bg" ? /* @__PURE__ */ jsxs6("div", { className: "group relative", children: [
1686
- /* @__PURE__ */ jsx7("span", { className: "cursor-help font-mono", children: item.text }),
1687
- runningTaskItems.length > 0 ? /* @__PURE__ */ jsx7(HoverPanel, { title: "\u8FD0\u884C\u4E2D\u4EFB\u52A1", children: /* @__PURE__ */ jsx7("div", { className: "max-h-40 overflow-y-auto", children: runningTaskItems.map((task) => /* @__PURE__ */ jsxs6("div", { className: "flex items-start gap-2 py-1 leading-relaxed", children: [
1688
- /* @__PURE__ */ jsx7("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-amber-300 bg-transparent" }),
1689
- /* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
1690
- /* @__PURE__ */ jsx7("div", { className: "font-medium", children: task.id }),
1691
- /* @__PURE__ */ jsx7("div", { className: "break-words text-slate-300/85", children: task.description || task.command })
1692
- ] })
1693
- ] }, task.id)) }) }) : null
1694
- ] }) : item.key === "loaded" ? /* @__PURE__ */ jsxs6("div", { className: "group relative flex items-center gap-1.5", children: [
1695
- /* @__PURE__ */ jsx7("span", { className: "cursor-help font-mono", children: item.text }),
1696
- onResync ? /* @__PURE__ */ jsx7(
1820
+ index > 0 && !tokenPressure && /* @__PURE__ */ jsx8("span", { className: "hidden text-[hsl(var(--border))]", children: "\xB7" }),
1821
+ /* @__PURE__ */ jsx8("span", { className: `inline-block h-1.5 w-1.5 rounded-full ${item.dotClass}` }),
1822
+ item.key === "loaded" ? /* @__PURE__ */ jsxs7("div", { className: "group relative flex items-center gap-1.5", children: [
1823
+ /* @__PURE__ */ jsx8("span", { className: "cursor-help font-mono", children: item.text }),
1824
+ onResync ? /* @__PURE__ */ jsx8(
1697
1825
  "button",
1698
1826
  {
1699
1827
  type: "button",
@@ -1701,21 +1829,21 @@ function SkillStatusBar({
1701
1829
  disabled: isResyncing,
1702
1830
  "aria-label": "\u540C\u6B65\u6280\u80FD",
1703
1831
  className: "inline-flex h-5 w-5 items-center justify-center rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--background))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
1704
- children: /* @__PURE__ */ jsx7(RefreshCw, { size: 11, className: isResyncing ? "animate-spin" : "" })
1832
+ children: /* @__PURE__ */ jsx8(RefreshCw, { size: 11, className: isResyncing ? "animate-spin" : "" })
1705
1833
  }
1706
1834
  ) : null,
1707
- statsReady && sessionSkills.length > 0 ? /* @__PURE__ */ jsx7(HoverPanel, { title: "\u5DF2\u52A0\u8F7D\u6280\u80FD", children: /* @__PURE__ */ jsx7("div", { className: "max-h-40 overflow-y-auto", children: sessionSkills.map((skill) => /* @__PURE__ */ jsxs6(
1835
+ statsReady && sessionSkills.length > 0 ? /* @__PURE__ */ jsx8(HoverPanel, { title: "\u5DF2\u52A0\u8F7D\u6280\u80FD", children: /* @__PURE__ */ jsx8("div", { className: "max-h-40 overflow-y-auto", children: sessionSkills.map((skill) => /* @__PURE__ */ jsxs7(
1708
1836
  "div",
1709
1837
  {
1710
1838
  className: "flex items-start gap-2 py-1 leading-relaxed",
1711
1839
  children: [
1712
- /* @__PURE__ */ jsx7("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-emerald-300 bg-transparent" }),
1713
- /* @__PURE__ */ jsx7("span", { className: "break-words", children: skillDisplayName(skill) })
1840
+ /* @__PURE__ */ jsx8("span", { className: "mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-emerald-300 bg-transparent" }),
1841
+ /* @__PURE__ */ jsx8("span", { className: "break-words", children: skillDisplayName(skill) })
1714
1842
  ]
1715
1843
  },
1716
1844
  skill.skill_id
1717
1845
  )) }) }) : null
1718
- ] }) : /* @__PURE__ */ jsx7("span", { className: "font-mono", children: item.text })
1846
+ ] }) : /* @__PURE__ */ jsx8("span", { className: "font-mono", children: item.text })
1719
1847
  ]
1720
1848
  },
1721
1849
  item.key
@@ -1850,7 +1978,7 @@ var SkillMention = Mention2.extend({
1850
1978
  });
1851
1979
 
1852
1980
  // src/react/components/chat/ChatInput.tsx
1853
- import { Fragment, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1981
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1854
1982
  function getEditorText(editor) {
1855
1983
  return editor?.getText({ blockSeparator: "\n" }) ?? "";
1856
1984
  }
@@ -1890,7 +2018,7 @@ function getFileCardIcon(attachment) {
1890
2018
  return FileCode2;
1891
2019
  }
1892
2020
  if (attachment.mimeType.startsWith("text/") || /\.(txt|pdf|doc|docx|rtf|odt)$/.test(lowerName)) {
1893
- return FileText;
2021
+ return FileText2;
1894
2022
  }
1895
2023
  return File2;
1896
2024
  }
@@ -1966,21 +2094,21 @@ function ComposerFilePill({
1966
2094
  const isFile = attachment.kind === "file";
1967
2095
  const isFailed = isFile && attachment.status === "failed";
1968
2096
  const isUploading = isFile && attachment.status === "uploading";
1969
- return /* @__PURE__ */ jsxs7(
2097
+ return /* @__PURE__ */ jsxs8(
1970
2098
  "div",
1971
2099
  {
1972
2100
  className: `flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] ${isFailed ? "border-red-500/30 bg-red-500/5 text-red-400" : "border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]"}`,
1973
2101
  children: [
1974
- isUploading ? /* @__PURE__ */ jsx8(Loader22, { size: 12, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx8(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
1975
- /* @__PURE__ */ jsx8("span", { className: "max-w-32 truncate", children: attachment.name }),
1976
- /* @__PURE__ */ jsx8(
2102
+ isUploading ? /* @__PURE__ */ jsx9(Loader22, { size: 12, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx9(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
2103
+ /* @__PURE__ */ jsx9("span", { className: "max-w-32 truncate", children: attachment.name }),
2104
+ /* @__PURE__ */ jsx9(
1977
2105
  "button",
1978
2106
  {
1979
2107
  type: "button",
1980
2108
  onClick: () => onRemove(attachment.id),
1981
2109
  "aria-label": `\u79FB\u9664 ${attachment.name}`,
1982
2110
  className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
1983
- children: /* @__PURE__ */ jsx8(X2, { size: 10 })
2111
+ children: /* @__PURE__ */ jsx9(X2, { size: 10 })
1984
2112
  }
1985
2113
  )
1986
2114
  ]
@@ -1993,13 +2121,13 @@ function AddContextDialog({
1993
2121
  onAdd
1994
2122
  }) {
1995
2123
  const CONTEXT_INLINE_THRESHOLD = 200;
1996
- const [label, setLabel] = useState6("");
1997
- const [content, setContent] = useState6("");
1998
- const [showSessionPicker, setShowSessionPicker] = useState6(false);
1999
- const [sessions, setSessions] = useState6([]);
2000
- const [loadingSessions, setLoadingSessions] = useState6(false);
2001
- const [importingId, setImportingId] = useState6(null);
2002
- const [isImportProcessing, setIsImportProcessing] = useState6(false);
2124
+ const [label, setLabel] = useState7("");
2125
+ const [content, setContent] = useState7("");
2126
+ const [showSessionPicker, setShowSessionPicker] = useState7(false);
2127
+ const [sessions, setSessions] = useState7([]);
2128
+ const [loadingSessions, setLoadingSessions] = useState7(false);
2129
+ const [importingId, setImportingId] = useState7(null);
2130
+ const [isImportProcessing, setIsImportProcessing] = useState7(false);
2003
2131
  const sanitizeContextFolderName = (raw) => {
2004
2132
  const normalized = raw.trim().toLowerCase();
2005
2133
  const safe = normalized.replace(/[^\w\-.\u4e00-\u9fa5]+/g, "_").replace(/^_+|_+$/g, "");
@@ -2099,7 +2227,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2099
2227
  setImportingId(null);
2100
2228
  }
2101
2229
  };
2102
- return /* @__PURE__ */ jsx8(
2230
+ return /* @__PURE__ */ jsx9(
2103
2231
  "div",
2104
2232
  {
2105
2233
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-4",
@@ -2107,44 +2235,44 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2107
2235
  onKeyDown: (e) => {
2108
2236
  if (e.key === "Escape") onClose();
2109
2237
  },
2110
- children: /* @__PURE__ */ jsxs7(
2238
+ children: /* @__PURE__ */ jsxs8(
2111
2239
  "div",
2112
2240
  {
2113
2241
  className: "w-full max-w-lg flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl",
2114
2242
  onClick: (e) => e.stopPropagation(),
2115
2243
  onKeyDown: (e) => e.stopPropagation(),
2116
2244
  children: [
2117
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
2118
- /* @__PURE__ */ jsx8("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
2119
- /* @__PURE__ */ jsx8(
2245
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3", children: [
2246
+ /* @__PURE__ */ jsx9("h4", { className: "text-sm font-semibold text-[hsl(var(--foreground))]", children: "\u6DFB\u52A0\u4E0A\u4E0B\u6587" }),
2247
+ /* @__PURE__ */ jsx9(
2120
2248
  "button",
2121
2249
  {
2122
2250
  type: "button",
2123
2251
  onClick: onClose,
2124
2252
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2125
- children: /* @__PURE__ */ jsx8(X2, { size: 14 })
2253
+ children: /* @__PURE__ */ jsx9(X2, { size: 14 })
2126
2254
  }
2127
2255
  )
2128
2256
  ] }),
2129
- /* @__PURE__ */ jsxs7("div", { className: "px-5 py-4 space-y-3", children: [
2130
- /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
2131
- /* @__PURE__ */ jsxs7(
2257
+ /* @__PURE__ */ jsxs8("div", { className: "px-5 py-4 space-y-3", children: [
2258
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
2259
+ /* @__PURE__ */ jsxs8(
2132
2260
  "button",
2133
2261
  {
2134
2262
  type: "button",
2135
2263
  onClick: handleLoadSessions,
2136
2264
  className: "inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--border))] px-2.5 py-1.5 text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]",
2137
2265
  children: [
2138
- /* @__PURE__ */ jsx8(Import, { size: 12 }),
2266
+ /* @__PURE__ */ jsx9(Import, { size: 12 }),
2139
2267
  "\u4ECE\u5176\u4ED6\u4F1A\u8BDD\u5BFC\u5165",
2140
- /* @__PURE__ */ jsx8(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
2268
+ /* @__PURE__ */ jsx9(ChevronDown, { size: 10, className: `transition-transform ${showSessionPicker ? "rotate-180" : ""}` })
2141
2269
  ]
2142
2270
  }
2143
2271
  ),
2144
- showSessionPicker && /* @__PURE__ */ jsx8("div", { className: "absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-lg", children: loadingSessions ? /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
2145
- /* @__PURE__ */ jsx8(Loader22, { size: 12, className: "animate-spin" }),
2272
+ showSessionPicker && /* @__PURE__ */ jsx9("div", { className: "absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-lg", children: loadingSessions ? /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: [
2273
+ /* @__PURE__ */ jsx9(Loader22, { size: 12, className: "animate-spin" }),
2146
2274
  "\u52A0\u8F7D\u4F1A\u8BDD\u5217\u8868\u2026"
2147
- ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx8("div", { className: "px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5176\u4ED6\u4F1A\u8BDD" }) : sessions.map((s) => /* @__PURE__ */ jsxs7(
2275
+ ] }) : sessions.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5176\u4ED6\u4F1A\u8BDD" }) : sessions.map((s) => /* @__PURE__ */ jsxs8(
2148
2276
  "button",
2149
2277
  {
2150
2278
  type: "button",
@@ -2152,16 +2280,16 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2152
2280
  onClick: () => handleImportSession(s.id),
2153
2281
  className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))] disabled:opacity-50",
2154
2282
  children: [
2155
- importingId === s.id && /* @__PURE__ */ jsx8(Loader22, { size: 10, className: "shrink-0 animate-spin" }),
2156
- /* @__PURE__ */ jsx8("span", { className: "truncate", children: s.intent })
2283
+ importingId === s.id && /* @__PURE__ */ jsx9(Loader22, { size: 10, className: "shrink-0 animate-spin" }),
2284
+ /* @__PURE__ */ jsx9("span", { className: "truncate", children: s.intent })
2157
2285
  ]
2158
2286
  },
2159
2287
  s.id
2160
2288
  )) })
2161
2289
  ] }),
2162
- /* @__PURE__ */ jsxs7("div", { children: [
2163
- /* @__PURE__ */ jsx8("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
2164
- /* @__PURE__ */ jsx8(
2290
+ /* @__PURE__ */ jsxs8("div", { children: [
2291
+ /* @__PURE__ */ jsx9("label", { htmlFor: "ctx-label", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u6807\u7B7E" }),
2292
+ /* @__PURE__ */ jsx9(
2165
2293
  "input",
2166
2294
  {
2167
2295
  id: "ctx-label",
@@ -2172,13 +2300,13 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2172
2300
  }
2173
2301
  )
2174
2302
  ] }),
2175
- /* @__PURE__ */ jsxs7("div", { children: [
2176
- /* @__PURE__ */ jsx8("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
2177
- isImportProcessing && /* @__PURE__ */ jsxs7("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
2178
- /* @__PURE__ */ jsx8(Loader22, { size: 11, className: "animate-spin" }),
2303
+ /* @__PURE__ */ jsxs8("div", { children: [
2304
+ /* @__PURE__ */ jsx9("label", { htmlFor: "ctx-content", className: "block text-xs font-medium text-[hsl(var(--foreground))] mb-1", children: "\u5185\u5BB9" }),
2305
+ isImportProcessing && /* @__PURE__ */ jsxs8("div", { className: "mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
2306
+ /* @__PURE__ */ jsx9(Loader22, { size: 11, className: "animate-spin" }),
2179
2307
  "\u6B63\u5728\u5904\u7406\u5BFC\u5165\u5185\u5BB9\u5E76\u5199\u5165 workspace/context\uFF0C\u5B8C\u6210\u540E\u53EF\u70B9\u51FB\u201C\u786E\u5B9A\u201D"
2180
2308
  ] }),
2181
- /* @__PURE__ */ jsx8(
2309
+ /* @__PURE__ */ jsx9(
2182
2310
  "textarea",
2183
2311
  {
2184
2312
  id: "ctx-content",
@@ -2191,8 +2319,8 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2191
2319
  )
2192
2320
  ] })
2193
2321
  ] }),
2194
- /* @__PURE__ */ jsxs7("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
2195
- /* @__PURE__ */ jsx8(
2322
+ /* @__PURE__ */ jsxs8("div", { className: "flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3", children: [
2323
+ /* @__PURE__ */ jsx9(
2196
2324
  "button",
2197
2325
  {
2198
2326
  type: "button",
@@ -2201,7 +2329,7 @@ ${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`
2201
2329
  children: "\u53D6\u6D88"
2202
2330
  }
2203
2331
  ),
2204
- /* @__PURE__ */ jsx8(
2332
+ /* @__PURE__ */ jsx9(
2205
2333
  "button",
2206
2334
  {
2207
2335
  type: "button",
@@ -2229,11 +2357,11 @@ function ComposerContextPill({
2229
2357
  content,
2230
2358
  onRemove
2231
2359
  }) {
2232
- const [showDetail, setShowDetail] = useState6(false);
2360
+ const [showDetail, setShowDetail] = useState7(false);
2233
2361
  const tokenK = formatTokenK(content);
2234
- return /* @__PURE__ */ jsxs7(Fragment, { children: [
2235
- /* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
2236
- /* @__PURE__ */ jsx8(
2362
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
2363
+ /* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]", children: [
2364
+ /* @__PURE__ */ jsx9(
2237
2365
  "button",
2238
2366
  {
2239
2367
  type: "button",
@@ -2243,7 +2371,7 @@ function ComposerContextPill({
2243
2371
  children: label
2244
2372
  }
2245
2373
  ),
2246
- /* @__PURE__ */ jsx8(
2374
+ /* @__PURE__ */ jsx9(
2247
2375
  "span",
2248
2376
  {
2249
2377
  className: "shrink-0 rounded bg-[hsl(var(--background))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -2251,18 +2379,18 @@ function ComposerContextPill({
2251
2379
  children: tokenK
2252
2380
  }
2253
2381
  ),
2254
- /* @__PURE__ */ jsx8(
2382
+ /* @__PURE__ */ jsx9(
2255
2383
  "button",
2256
2384
  {
2257
2385
  type: "button",
2258
2386
  onClick: () => onRemove(id),
2259
2387
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${label}`,
2260
2388
  className: "ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400",
2261
- children: /* @__PURE__ */ jsx8(X2, { size: 10 })
2389
+ children: /* @__PURE__ */ jsx9(X2, { size: 10 })
2262
2390
  }
2263
2391
  )
2264
2392
  ] }),
2265
- showDetail && /* @__PURE__ */ jsx8(
2393
+ showDetail && /* @__PURE__ */ jsx9(
2266
2394
  "div",
2267
2395
  {
2268
2396
  className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-6",
@@ -2270,26 +2398,26 @@ function ComposerContextPill({
2270
2398
  onKeyDown: (e) => {
2271
2399
  if (e.key === "Escape") setShowDetail(false);
2272
2400
  },
2273
- children: /* @__PURE__ */ jsxs7(
2401
+ children: /* @__PURE__ */ jsxs8(
2274
2402
  "div",
2275
2403
  {
2276
2404
  className: "w-full max-w-4xl max-h-[85vh] flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl",
2277
2405
  onClick: (e) => e.stopPropagation(),
2278
2406
  onKeyDown: (e) => e.stopPropagation(),
2279
2407
  children: [
2280
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
2281
- /* @__PURE__ */ jsx8("h4", { className: "text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
2282
- /* @__PURE__ */ jsx8(
2408
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3", children: [
2409
+ /* @__PURE__ */ jsx9("h4", { className: "text-xs font-semibold text-[hsl(var(--foreground))]", children: label }),
2410
+ /* @__PURE__ */ jsx9(
2283
2411
  "button",
2284
2412
  {
2285
2413
  type: "button",
2286
2414
  onClick: () => setShowDetail(false),
2287
2415
  className: "rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
2288
- children: /* @__PURE__ */ jsx8(X2, { size: 14 })
2416
+ children: /* @__PURE__ */ jsx9(X2, { size: 14 })
2289
2417
  }
2290
2418
  )
2291
2419
  ] }),
2292
- /* @__PURE__ */ jsx8("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: /* @__PURE__ */ jsx8("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content }) })
2420
+ /* @__PURE__ */ jsx9("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-4", children: /* @__PURE__ */ jsx9("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]", children: content }) })
2293
2421
  ]
2294
2422
  }
2295
2423
  )
@@ -2443,7 +2571,7 @@ function ChatInput({
2443
2571
  onResyncSkills,
2444
2572
  isResyncingSkills = false
2445
2573
  }) {
2446
- const [input, setInputInternal] = useState6(externalDraft?.value ?? "");
2574
+ const [input, setInputInternal] = useState7(externalDraft?.value ?? "");
2447
2575
  const setInput = useEffectEvent2((value) => {
2448
2576
  setInputInternal(value);
2449
2577
  externalDraft?.setValue(value);
@@ -2459,7 +2587,7 @@ function ChatInput({
2459
2587
  }
2460
2588
  setInputInternal(externalDraftValue);
2461
2589
  }, [externalDraftValue]);
2462
- const [composerAttachments, setComposerAttachmentsInternal] = useState6(
2590
+ const [composerAttachments, setComposerAttachmentsInternal] = useState7(
2463
2591
  externalAttachments?.value ?? []
2464
2592
  );
2465
2593
  const setComposerAttachments = useEffectEvent2(
@@ -2479,10 +2607,10 @@ function ChatInput({
2479
2607
  if (composerAttachmentsRef.current === externalAttachmentsValue) return;
2480
2608
  setComposerAttachmentsInternal(externalAttachmentsValue);
2481
2609
  }, [externalAttachmentsValue]);
2482
- const [dragging, setDragging] = useState6(false);
2483
- const [isEditorFocused, setIsEditorFocused] = useState6(false);
2484
- const [oversizedFiles, setOversizedFiles] = useState6([]);
2485
- const [selectedModel, setSelectedModel] = useState6("");
2610
+ const [dragging, setDragging] = useState7(false);
2611
+ const [isEditorFocused, setIsEditorFocused] = useState7(false);
2612
+ const [oversizedFiles, setOversizedFiles] = useState7([]);
2613
+ const [selectedModel, setSelectedModel] = useState7("");
2486
2614
  const { setPreferredModel } = usePreferredModel();
2487
2615
  const queryClient = useQueryClient2();
2488
2616
  const actionMenuRef = useRef4(null);
@@ -2522,7 +2650,7 @@ function ChatInput({
2522
2650
  const inputHistory = useInputHistory(activeSessionId);
2523
2651
  const getSessionId = useEffectEvent2(() => activeSessionId);
2524
2652
  const handleSlashCommand = useEffectEvent2((commandId) => onCommand?.(commandId));
2525
- const [localImageUrls, setLocalImageUrls] = useState6({});
2653
+ const [localImageUrls, setLocalImageUrls] = useState7({});
2526
2654
  useEffect7(() => {
2527
2655
  const closeActionMenu = (event) => {
2528
2656
  const menu = actionMenuRef.current;
@@ -2650,7 +2778,7 @@ function ChatInput({
2650
2778
  if (!container || !root) return;
2651
2779
  updateSuggestionPosition(container, props.clientRect);
2652
2780
  root.render(
2653
- /* @__PURE__ */ jsx8(
2781
+ /* @__PURE__ */ jsx9(
2654
2782
  FileCompletionMenu,
2655
2783
  {
2656
2784
  ref: (instance) => {
@@ -2727,7 +2855,7 @@ function ChatInput({
2727
2855
  if (!container || !root) return;
2728
2856
  updateSuggestionPosition(container, props.clientRect);
2729
2857
  root.render(
2730
- /* @__PURE__ */ jsx8(
2858
+ /* @__PURE__ */ jsx9(
2731
2859
  SkillCompletionMenu,
2732
2860
  {
2733
2861
  ref: (instance) => {
@@ -3055,7 +3183,7 @@ function ChatInput({
3055
3183
  const removeAttachment = (id) => {
3056
3184
  setComposerAttachments((prev) => prev.filter((attachment) => attachment.id !== id));
3057
3185
  };
3058
- const [showAddContext, setShowAddContext] = useState6(false);
3186
+ const [showAddContext, setShowAddContext] = useState7(false);
3059
3187
  const isPlanning = mode === "planning";
3060
3188
  const placeholder = isPlanning ? "\u89C4\u5212\u8FDB\u884C\u4E2D\u2026 \u53EF\u8F93\u5165\u8865\u5145\u9700\u6C42\u6216\u7B49\u5F85\u5B8C\u6210" : "\u8F93\u5165\u6D88\u606F\u2026";
3061
3189
  const attachments = renderAttachments?.() ?? null;
@@ -3074,385 +3202,388 @@ function ChatInput({
3074
3202
  );
3075
3203
  const hasValidAttachments = composerAttachments.some((attachment) => attachment.status !== "failed");
3076
3204
  const isSendDisabled = connectionStatus !== "connected" || hasUploadingFiles || !input.trim() && !hasValidAttachments && !hasRenderedAttachments && !hasPendingContexts;
3077
- return /* @__PURE__ */ jsxs7(Fragment, { children: [
3078
- /* @__PURE__ */ jsx8("div", { className: `bg-[hsl(var(--background))] px-5 py-3 ${className ?? ""}`, children: /* @__PURE__ */ jsx8("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: /* @__PURE__ */ jsx8(
3079
- "div",
3080
- {
3081
- className: "relative",
3082
- onDragOver: (event) => {
3083
- event.preventDefault();
3084
- setDragging(true);
3085
- },
3086
- onDragLeave: () => setDragging(false),
3087
- onDrop: (event) => {
3088
- event.preventDefault();
3089
- setDragging(false);
3090
- const fileRef = event.dataTransfer.getData("application/blade-file-ref");
3091
- if (fileRef) {
3092
- try {
3093
- const { path, name } = JSON.parse(fileRef);
3094
- const normalizedPath = path.replace(/^\.?\//, "");
3095
- const sandboxPath = path.startsWith("/") ? path : activeSessionId ? `/root/\u667A\u80FD\u52A9\u624B\u5DE5\u4F5C\u7A7A\u95F4/${activeSessionId}/${normalizedPath}` : normalizedPath;
3096
- const editor2 = editorRef.current;
3097
- if (editor2) {
3098
- editor2.commands.focus("end");
3099
- editor2.commands.insertContent([
3100
- { type: "fileMention", attrs: { path: sandboxPath, name } },
3101
- { type: "text", text: " " }
3102
- ]);
3205
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
3206
+ /* @__PURE__ */ jsx9("div", { className: `bg-[hsl(var(--background))] px-5 py-3 ${className ?? ""}`, children: /* @__PURE__ */ jsxs8("div", { className: `mx-auto ${maxWidthClassName} ${innerClassName ?? ""}`, children: [
3207
+ activeSessionId ? /* @__PURE__ */ jsx9(BackgroundTasksPill, { sessionId: activeSessionId }) : null,
3208
+ /* @__PURE__ */ jsx9(
3209
+ "div",
3210
+ {
3211
+ className: "relative",
3212
+ onDragOver: (event) => {
3213
+ event.preventDefault();
3214
+ setDragging(true);
3215
+ },
3216
+ onDragLeave: () => setDragging(false),
3217
+ onDrop: (event) => {
3218
+ event.preventDefault();
3219
+ setDragging(false);
3220
+ const fileRef = event.dataTransfer.getData("application/blade-file-ref");
3221
+ if (fileRef) {
3222
+ try {
3223
+ const { path, name } = JSON.parse(fileRef);
3224
+ const normalizedPath = path.replace(/^\.?\//, "");
3225
+ const sandboxPath = path.startsWith("/") ? path : activeSessionId ? `/root/\u667A\u80FD\u52A9\u624B\u5DE5\u4F5C\u7A7A\u95F4/${activeSessionId}/${normalizedPath}` : normalizedPath;
3226
+ const editor2 = editorRef.current;
3227
+ if (editor2) {
3228
+ editor2.commands.focus("end");
3229
+ editor2.commands.insertContent([
3230
+ { type: "fileMention", attrs: { path: sandboxPath, name } },
3231
+ { type: "text", text: " " }
3232
+ ]);
3233
+ }
3234
+ } catch {
3103
3235
  }
3104
- } catch {
3236
+ return;
3105
3237
  }
3106
- return;
3107
- }
3108
- void stableAppendFiles(event.dataTransfer.files);
3109
- },
3110
- children: /* @__PURE__ */ jsxs7(
3111
- "div",
3112
- {
3113
- className: `overflow-visible rounded-2xl border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${isRecording ? "border-emerald-400/70! shadow-[0_0_0_3px_rgba(52,211,153,0.18),0_0_24px_rgba(52,211,153,0.28)]" : dragging ? isPlanning ? "border-amber-400/60" : "border-[hsl(var(--primary)/0.6)]" : isEditorFocused ? isPlanning ? "border-amber-400/60" : "border-[hsl(var(--primary)/0.6)]" : isPlanning ? "border-amber-400/30" : "border-[hsl(var(--border))]"}`,
3114
- children: [
3115
- dragging && /* @__PURE__ */ jsx8("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.06)]", children: /* @__PURE__ */ jsx8("span", { className: "rounded-full bg-[hsl(var(--primary)/0.12)] px-4 py-2 text-sm font-medium text-[hsl(var(--primary))]", children: "\u677E\u624B\u5F15\u7528\u6587\u4EF6" }) }),
3116
- composerAttachments.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2", children: [
3117
- imageAttachments.length > 0 && /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs7(
3118
- "div",
3119
- {
3120
- className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
3121
- children: [
3122
- /* @__PURE__ */ jsx8(
3123
- "img",
3124
- {
3125
- src: getImagePreviewUrl(attachment, activeSessionId, localImageUrls),
3126
- alt: attachment.name || "\u56FE\u7247\u9884\u89C8",
3127
- className: "h-24 w-full object-cover"
3128
- }
3129
- ),
3130
- /* @__PURE__ */ jsx8(
3131
- "button",
3132
- {
3133
- type: "button",
3134
- onClick: () => removeAttachment(attachment.id),
3135
- "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
3136
- className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-full bg-[hsl(var(--background)/0.85)] text-[hsl(var(--foreground))]",
3137
- children: /* @__PURE__ */ jsx8(X2, { size: 12 })
3238
+ void stableAppendFiles(event.dataTransfer.files);
3239
+ },
3240
+ children: /* @__PURE__ */ jsxs8(
3241
+ "div",
3242
+ {
3243
+ 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))]"}`,
3244
+ children: [
3245
+ dragging && /* @__PURE__ */ jsx9("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.06)]", children: /* @__PURE__ */ jsx9("span", { className: "rounded-full bg-[hsl(var(--primary)/0.12)] px-4 py-2 text-sm font-medium text-[hsl(var(--primary))]", children: "\u677E\u624B\u5F15\u7528\u6587\u4EF6" }) }),
3246
+ composerAttachments.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2", children: [
3247
+ imageAttachments.length > 0 && /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-3 gap-2", children: imageAttachments.map((attachment) => /* @__PURE__ */ jsxs8(
3248
+ "div",
3249
+ {
3250
+ className: "relative overflow-hidden rounded-xl border border-[hsl(var(--border))]",
3251
+ children: [
3252
+ /* @__PURE__ */ jsx9(
3253
+ "img",
3254
+ {
3255
+ src: getImagePreviewUrl(attachment, activeSessionId, localImageUrls),
3256
+ alt: attachment.name || "\u56FE\u7247\u9884\u89C8",
3257
+ className: "h-24 w-full object-cover"
3258
+ }
3259
+ ),
3260
+ /* @__PURE__ */ jsx9(
3261
+ "button",
3262
+ {
3263
+ type: "button",
3264
+ onClick: () => removeAttachment(attachment.id),
3265
+ "aria-label": `\u79FB\u9664 ${attachment.name || "\u56FE\u7247"}`,
3266
+ 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))]",
3267
+ children: /* @__PURE__ */ jsx9(X2, { size: 12 })
3268
+ }
3269
+ )
3270
+ ]
3271
+ },
3272
+ attachment.id
3273
+ )) }),
3274
+ fileAttachments.length > 0 && /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx9(
3275
+ ComposerFilePill,
3276
+ {
3277
+ attachment,
3278
+ onRemove: removeAttachment
3279
+ },
3280
+ attachment.id
3281
+ )) })
3282
+ ] }),
3283
+ hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2", children: [
3284
+ pendingContexts?.map((context) => /* @__PURE__ */ jsx9(
3285
+ ComposerContextPill,
3286
+ {
3287
+ id: context.id,
3288
+ label: context.label,
3289
+ content: context.content,
3290
+ onRemove: (contextId) => {
3291
+ if (!activeSessionId) {
3292
+ return;
3138
3293
  }
3139
- )
3140
- ]
3141
- },
3142
- attachment.id
3143
- )) }),
3144
- fileAttachments.length > 0 && /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-1.5", children: fileAttachments.map((attachment) => /* @__PURE__ */ jsx8(
3145
- ComposerFilePill,
3146
- {
3147
- attachment,
3148
- onRemove: removeAttachment
3149
- },
3150
- attachment.id
3151
- )) })
3152
- ] }),
3153
- hasPendingContexts || isSkillEditor ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2", children: [
3154
- pendingContexts?.map((context) => /* @__PURE__ */ jsx8(
3155
- ComposerContextPill,
3156
- {
3157
- id: context.id,
3158
- label: context.label,
3159
- content: context.content,
3160
- onRemove: (contextId) => {
3161
- if (!activeSessionId) {
3162
- return;
3294
+ removePendingContext(activeSessionId, contextId);
3163
3295
  }
3164
- removePendingContext(activeSessionId, contextId);
3296
+ },
3297
+ context.id
3298
+ )),
3299
+ isSkillEditor && /* @__PURE__ */ jsx9(
3300
+ "button",
3301
+ {
3302
+ type: "button",
3303
+ onClick: () => setShowAddContext(true),
3304
+ title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
3305
+ 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))]",
3306
+ children: /* @__PURE__ */ jsx9(Plus, { size: 12 })
3165
3307
  }
3166
- },
3167
- context.id
3168
- )),
3169
- isSkillEditor && /* @__PURE__ */ jsx8(
3170
- "button",
3308
+ )
3309
+ ] }) : null,
3310
+ showAddContext && activeSessionId && /* @__PURE__ */ jsx9(
3311
+ AddContextDialog,
3171
3312
  {
3172
- type: "button",
3173
- onClick: () => setShowAddContext(true),
3174
- title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
3175
- className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-dashed border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]",
3176
- children: /* @__PURE__ */ jsx8(Plus, { size: 12 })
3177
- }
3178
- )
3179
- ] }) : null,
3180
- showAddContext && activeSessionId && /* @__PURE__ */ jsx8(
3181
- AddContextDialog,
3182
- {
3183
- sessionId: activeSessionId,
3184
- onClose: () => setShowAddContext(false),
3185
- onAdd: (label, content) => {
3186
- if (activeSessionId) {
3187
- useUiBridgeStore.getState().addPendingContext(activeSessionId, { label, content });
3313
+ sessionId: activeSessionId,
3314
+ onClose: () => setShowAddContext(false),
3315
+ onAdd: (label, content) => {
3316
+ if (activeSessionId) {
3317
+ useUiBridgeStore.getState().addPendingContext(activeSessionId, { label, content });
3318
+ }
3188
3319
  }
3189
3320
  }
3190
- }
3191
- ),
3192
- attachments ? /* @__PURE__ */ jsx8("div", { className: "border-b border-[hsl(var(--border))] px-3 py-3", children: attachments }) : null,
3193
- slotAboveTextarea ? /* @__PURE__ */ jsx8("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2", children: slotAboveTextarea }) : null,
3194
- /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
3195
- input.length === 0 && /* @__PURE__ */ jsx8("div", { className: "pointer-events-none absolute left-4 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground))]", children: placeholder }),
3196
- /* @__PURE__ */ jsx8(EditorContent, { editor })
3197
- ] }),
3198
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between border-t border-[hsl(var(--border))] px-3 py-1.5", children: [
3199
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
3200
- /* @__PURE__ */ jsx8(
3201
- "input",
3202
- {
3203
- ref: fileInputRef,
3204
- type: "file",
3205
- accept: "*/*",
3206
- multiple: true,
3207
- onChange: (event) => {
3208
- if (event.target.files) {
3209
- void appendFiles(event.target.files);
3210
- event.target.value = "";
3211
- }
3212
- },
3213
- className: "hidden"
3214
- }
3215
- ),
3216
- /* @__PURE__ */ jsx8(
3217
- "input",
3218
- {
3219
- ref: folderInputRef,
3220
- type: "file",
3221
- multiple: true,
3222
- onChange: (event) => {
3223
- if (event.target.files) {
3224
- void appendFiles(event.target.files);
3225
- event.target.value = "";
3226
- }
3227
- },
3228
- className: "hidden",
3229
- ...{ webkitdirectory: "" }
3230
- }
3231
- ),
3232
- /* @__PURE__ */ jsxs7("details", { ref: actionMenuRef, className: "group relative", children: [
3233
- /* @__PURE__ */ jsx8(
3234
- "summary",
3321
+ ),
3322
+ attachments ? /* @__PURE__ */ jsx9("div", { className: "border-b border-[hsl(var(--border))] px-3 py-3", children: attachments }) : null,
3323
+ slotAboveTextarea ? /* @__PURE__ */ jsx9("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2", children: slotAboveTextarea }) : null,
3324
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
3325
+ input.length === 0 && /* @__PURE__ */ jsx9("div", { className: "pointer-events-none absolute left-4 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground))]", children: placeholder }),
3326
+ /* @__PURE__ */ jsx9(EditorContent, { editor })
3327
+ ] }),
3328
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between border-t border-[hsl(var(--border))] px-3 py-1.5", children: [
3329
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
3330
+ /* @__PURE__ */ jsx9(
3331
+ "input",
3235
3332
  {
3236
- "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
3237
- title: "\u6DFB\u52A0\u5185\u5BB9",
3238
- className: "flex h-7 w-7 shrink-0 cursor-pointer list-none items-center justify-center rounded-lg border border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] [&::-webkit-details-marker]:hidden",
3239
- children: /* @__PURE__ */ jsx8(Plus, { size: 14 })
3333
+ ref: fileInputRef,
3334
+ type: "file",
3335
+ accept: "*/*",
3336
+ multiple: true,
3337
+ onChange: (event) => {
3338
+ if (event.target.files) {
3339
+ void appendFiles(event.target.files);
3340
+ event.target.value = "";
3341
+ }
3342
+ },
3343
+ className: "hidden"
3240
3344
  }
3241
3345
  ),
3242
- /* @__PURE__ */ jsxs7("div", { className: "absolute bottom-full left-0 z-30 mb-2 min-w-36 overflow-visible rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 text-[11px] text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3243
- /* @__PURE__ */ jsxs7(
3244
- "button",
3245
- {
3246
- type: "button",
3247
- onClick: () => {
3248
- actionMenuRef.current?.removeAttribute("open");
3249
- fileInputRef.current?.click();
3250
- },
3251
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3252
- children: [
3253
- /* @__PURE__ */ jsx8(Paperclip, { size: 13 }),
3254
- "\u4E0A\u4F20\u6587\u4EF6"
3255
- ]
3256
- }
3257
- ),
3258
- /* @__PURE__ */ jsxs7(
3259
- "button",
3346
+ /* @__PURE__ */ jsx9(
3347
+ "input",
3348
+ {
3349
+ ref: folderInputRef,
3350
+ type: "file",
3351
+ multiple: true,
3352
+ onChange: (event) => {
3353
+ if (event.target.files) {
3354
+ void appendFiles(event.target.files);
3355
+ event.target.value = "";
3356
+ }
3357
+ },
3358
+ className: "hidden",
3359
+ ...{ webkitdirectory: "" }
3360
+ }
3361
+ ),
3362
+ /* @__PURE__ */ jsxs8("details", { ref: actionMenuRef, className: "group relative", children: [
3363
+ /* @__PURE__ */ jsx9(
3364
+ "summary",
3260
3365
  {
3261
- type: "button",
3262
- onClick: () => {
3263
- actionMenuRef.current?.removeAttribute("open");
3264
- folderInputRef.current?.click();
3265
- },
3266
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3267
- children: [
3268
- /* @__PURE__ */ jsx8(FolderUp, { size: 13 }),
3269
- "\u4E0A\u4F20\u6587\u4EF6\u5939"
3270
- ]
3366
+ "aria-label": "\u6DFB\u52A0\u5185\u5BB9",
3367
+ title: "\u6DFB\u52A0\u5185\u5BB9",
3368
+ 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",
3369
+ children: /* @__PURE__ */ jsx9(Plus, { size: 14 })
3271
3370
  }
3272
3371
  ),
3273
- onCommand ? /* @__PURE__ */ jsxs7(Fragment, { children: [
3274
- /* @__PURE__ */ jsxs7(
3275
- "button",
3276
- {
3277
- type: "button",
3278
- onClick: () => {
3279
- actionMenuRef.current?.removeAttribute("open");
3280
- void onCommand("compact");
3281
- },
3282
- disabled: isStreaming,
3283
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50",
3284
- children: [
3285
- isStreaming ? /* @__PURE__ */ jsx8(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx8(Scissors, { size: 13 }),
3286
- "\u6574\u7406\u5BF9\u8BDD"
3287
- ]
3288
- }
3289
- ),
3290
- /* @__PURE__ */ jsxs7(
3372
+ /* @__PURE__ */ jsxs8("div", { className: "absolute bottom-full left-0 z-30 mb-2 min-w-36 overflow-visible rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 text-[11px] text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3373
+ /* @__PURE__ */ jsxs8(
3291
3374
  "button",
3292
3375
  {
3293
3376
  type: "button",
3294
3377
  onClick: () => {
3295
3378
  actionMenuRef.current?.removeAttribute("open");
3296
- void onCommand("download_session");
3379
+ fileInputRef.current?.click();
3297
3380
  },
3298
3381
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3299
3382
  children: [
3300
- /* @__PURE__ */ jsx8(Download, { size: 13 }),
3301
- "\u5BFC\u51FA\u4F1A\u8BDD"
3383
+ /* @__PURE__ */ jsx9(Paperclip, { size: 13 }),
3384
+ "\u4E0A\u4F20\u6587\u4EF6"
3302
3385
  ]
3303
3386
  }
3304
3387
  ),
3305
- canShareSession ? /* @__PURE__ */ jsxs7(
3306
- "button",
3307
- {
3308
- type: "button",
3309
- onClick: () => {
3310
- actionMenuRef.current?.removeAttribute("open");
3311
- void onCommand("share_session");
3312
- },
3313
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3314
- children: [
3315
- /* @__PURE__ */ jsx8(Share2, { size: 13 }),
3316
- "\u5206\u4EAB\u4F1A\u8BDD"
3317
- ]
3318
- }
3319
- ) : null,
3320
- /* @__PURE__ */ jsxs7(
3388
+ /* @__PURE__ */ jsxs8(
3321
3389
  "button",
3322
3390
  {
3323
3391
  type: "button",
3324
3392
  onClick: () => {
3325
3393
  actionMenuRef.current?.removeAttribute("open");
3326
- void onCommand("extract_skill");
3394
+ folderInputRef.current?.click();
3327
3395
  },
3328
3396
  className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3329
3397
  children: [
3330
- /* @__PURE__ */ jsx8(FlaskConical, { size: 13 }),
3331
- "\u63D0\u53D6\u6280\u80FD"
3398
+ /* @__PURE__ */ jsx9(FolderUp, { size: 13 }),
3399
+ "\u4E0A\u4F20\u6587\u4EF6\u5939"
3332
3400
  ]
3333
3401
  }
3334
3402
  ),
3335
- /* @__PURE__ */ jsxs7(
3336
- "button",
3337
- {
3338
- type: "button",
3339
- onClick: () => {
3340
- actionMenuRef.current?.removeAttribute("open");
3341
- void onCommand("generate_app");
3342
- },
3343
- className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3344
- children: [
3345
- /* @__PURE__ */ jsx8(Rocket, { size: 13 }),
3346
- "\u751F\u6210\u5E94\u7528"
3347
- ]
3348
- }
3349
- )
3350
- ] }) : null,
3351
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 px-3 py-2", children: [
3352
- /* @__PURE__ */ jsx8(Sparkles2, { size: 13 }),
3353
- /* @__PURE__ */ jsx8("span", { className: "shrink-0", children: "\u6A21\u578B" }),
3354
- /* @__PURE__ */ jsx8(
3355
- ModelSelector,
3356
- {
3357
- value: selectedModel,
3358
- onValueChange: (model) => {
3359
- setSelectedModel(model);
3360
- if (activeSessionId) {
3361
- patchSession(activeSessionId, { model });
3362
- }
3363
- setPreferredModel(model);
3364
- },
3365
- compact: true,
3366
- placement: "top"
3367
- }
3368
- )
3403
+ onCommand ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
3404
+ /* @__PURE__ */ jsxs8(
3405
+ "button",
3406
+ {
3407
+ type: "button",
3408
+ onClick: () => {
3409
+ actionMenuRef.current?.removeAttribute("open");
3410
+ void onCommand("compact");
3411
+ },
3412
+ disabled: isStreaming,
3413
+ 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",
3414
+ children: [
3415
+ isStreaming ? /* @__PURE__ */ jsx9(Loader22, { size: 13, className: "animate-spin" }) : /* @__PURE__ */ jsx9(Scissors, { size: 13 }),
3416
+ "\u6574\u7406\u5BF9\u8BDD"
3417
+ ]
3418
+ }
3419
+ ),
3420
+ /* @__PURE__ */ jsxs8(
3421
+ "button",
3422
+ {
3423
+ type: "button",
3424
+ onClick: () => {
3425
+ actionMenuRef.current?.removeAttribute("open");
3426
+ void onCommand("download_session");
3427
+ },
3428
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3429
+ children: [
3430
+ /* @__PURE__ */ jsx9(Download, { size: 13 }),
3431
+ "\u5BFC\u51FA\u4F1A\u8BDD"
3432
+ ]
3433
+ }
3434
+ ),
3435
+ canShareSession ? /* @__PURE__ */ jsxs8(
3436
+ "button",
3437
+ {
3438
+ type: "button",
3439
+ onClick: () => {
3440
+ actionMenuRef.current?.removeAttribute("open");
3441
+ void onCommand("share_session");
3442
+ },
3443
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3444
+ children: [
3445
+ /* @__PURE__ */ jsx9(Share2, { size: 13 }),
3446
+ "\u5206\u4EAB\u4F1A\u8BDD"
3447
+ ]
3448
+ }
3449
+ ) : null,
3450
+ /* @__PURE__ */ jsxs8(
3451
+ "button",
3452
+ {
3453
+ type: "button",
3454
+ onClick: () => {
3455
+ actionMenuRef.current?.removeAttribute("open");
3456
+ void onCommand("extract_skill");
3457
+ },
3458
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3459
+ children: [
3460
+ /* @__PURE__ */ jsx9(FlaskConical, { size: 13 }),
3461
+ "\u63D0\u53D6\u6280\u80FD"
3462
+ ]
3463
+ }
3464
+ ),
3465
+ /* @__PURE__ */ jsxs8(
3466
+ "button",
3467
+ {
3468
+ type: "button",
3469
+ onClick: () => {
3470
+ actionMenuRef.current?.removeAttribute("open");
3471
+ void onCommand("generate_app");
3472
+ },
3473
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]",
3474
+ children: [
3475
+ /* @__PURE__ */ jsx9(Rocket, { size: 13 }),
3476
+ "\u751F\u6210\u5E94\u7528"
3477
+ ]
3478
+ }
3479
+ )
3480
+ ] }) : null,
3481
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 px-3 py-2", children: [
3482
+ /* @__PURE__ */ jsx9(Sparkles2, { size: 13 }),
3483
+ /* @__PURE__ */ jsx9("span", { className: "shrink-0", children: "\u6A21\u578B" }),
3484
+ /* @__PURE__ */ jsx9(
3485
+ ModelSelector,
3486
+ {
3487
+ value: selectedModel,
3488
+ onValueChange: (model) => {
3489
+ setSelectedModel(model);
3490
+ if (activeSessionId) {
3491
+ patchSession(activeSessionId, { model });
3492
+ }
3493
+ setPreferredModel(model);
3494
+ },
3495
+ compact: true,
3496
+ placement: "top"
3497
+ }
3498
+ )
3499
+ ] })
3369
3500
  ] })
3370
- ] })
3371
- ] }),
3372
- /* @__PURE__ */ jsx8(
3373
- "button",
3374
- {
3375
- type: "button",
3376
- onClick: onToggleMode,
3377
- disabled: isStreaming || !onToggleMode,
3378
- "aria-pressed": isPlanning,
3379
- "aria-label": isPlanning ? "\u5173\u95ED\u89C4\u5212\u6A21\u5F0F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3380
- title: isPlanning ? "\u89C4\u5212\u6A21\u5F0F\u5DF2\u5F00\u542F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3381
- className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-lg border transition-colors ${isPlanning ? "border-amber-500/45 bg-amber-500/15 text-amber-400" : "border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-amber-500/35 hover:text-[hsl(var(--foreground))]"} disabled:cursor-not-allowed disabled:opacity-50`,
3382
- children: /* @__PURE__ */ jsx8(Lightbulb, { size: 13 })
3383
- }
3384
- )
3385
- ] }),
3386
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5", children: [
3387
- /* @__PURE__ */ jsxs7("div", { className: "group/help relative", children: [
3388
- /* @__PURE__ */ jsx8(
3501
+ ] }),
3502
+ /* @__PURE__ */ jsx9(
3389
3503
  "button",
3390
3504
  {
3391
3505
  type: "button",
3392
- "aria-label": "\u67E5\u770B\u8F93\u5165\u63D0\u793A",
3393
- className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
3394
- children: /* @__PURE__ */ jsx8(CircleHelp, { size: 13 })
3506
+ onClick: onToggleMode,
3507
+ disabled: isStreaming || !onToggleMode,
3508
+ "aria-pressed": isPlanning,
3509
+ "aria-label": isPlanning ? "\u5173\u95ED\u89C4\u5212\u6A21\u5F0F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3510
+ title: isPlanning ? "\u89C4\u5212\u6A21\u5F0F\u5DF2\u5F00\u542F" : "\u5F00\u542F\u89C4\u5212\u6A21\u5F0F",
3511
+ 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`,
3512
+ children: /* @__PURE__ */ jsx9(Lightbulb, { size: 13 })
3395
3513
  }
3396
- ),
3397
- /* @__PURE__ */ jsx8("div", { className: "pointer-events-auto absolute bottom-full right-0 z-30 hidden pb-2 group-hover/help:block group-focus-within/help:block", children: /* @__PURE__ */ jsxs7("div", { className: "min-w-64 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-left text-[11px] leading-5 text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3398
- activeSessionId ? /* @__PURE__ */ jsx8("div", { className: "mb-2 border-b border-[hsl(var(--border))] pb-2", children: /* @__PURE__ */ jsx8(
3399
- SkillStatusBarComponent,
3514
+ )
3515
+ ] }),
3516
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1.5", children: [
3517
+ /* @__PURE__ */ jsxs8("div", { className: "group/help relative", children: [
3518
+ /* @__PURE__ */ jsx9(
3519
+ "button",
3400
3520
  {
3401
- sessionId: activeSessionId,
3402
- onResync: onResyncSkills,
3403
- isResyncing: isResyncingSkills,
3404
- vertical: true,
3405
- className: skillStatusBarClassName,
3406
- innerClassName: skillStatusBarInnerClassName
3521
+ type: "button",
3522
+ "aria-label": "\u67E5\u770B\u8F93\u5165\u63D0\u793A",
3523
+ 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))]",
3524
+ children: /* @__PURE__ */ jsx9(CircleHelp, { size: 13 })
3407
3525
  }
3408
- ) }) : null,
3409
- /* @__PURE__ */ jsxs7("div", { className: "space-y-0.5", children: [
3410
- /* @__PURE__ */ jsx8("div", { children: "Shift+Enter \u6362\u884C" }),
3411
- /* @__PURE__ */ jsx8("div", { children: "/ \u8C03\u7528\u6280\u80FD" }),
3412
- /* @__PURE__ */ jsx8("div", { children: "@ \u5F15\u7528\u6587\u4EF6" })
3413
- ] })
3414
- ] }) })
3415
- ] }),
3416
- /* @__PURE__ */ jsx8(
3417
- "button",
3418
- {
3419
- type: "button",
3420
- onClick: asrEnabled ? voice.toggle : handleMicDisabledClick,
3421
- disabled: isStreaming,
3422
- "aria-label": !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
3423
- title: !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u8BED\u97F3\u8F93\u5165",
3424
- className: `flex items-center justify-center rounded-lg border transition-[width,height,border-color,background-color,color,box-shadow] duration-300 disabled:opacity-40 ${!asrEnabled ? "h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))]/50 hover:text-[hsl(var(--muted-foreground))]" : isRecording ? "h-9 w-9 border-emerald-400/80! bg-emerald-400/15 text-emerald-400 shadow-[0_0_0_2px_rgba(52,211,153,0.2),0_0_12px_rgba(52,211,153,0.35)]" : "h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]"}`,
3425
- children: !asrEnabled ? /* @__PURE__ */ jsx8(MicOff, { size: 13 }) : isRecording ? /* @__PURE__ */ jsx8(VoiceWaveform, { level: voiceLevel, size: 18 }) : /* @__PURE__ */ jsx8(Mic, { size: 13 })
3426
- }
3427
- ),
3428
- isStreaming ? /* @__PURE__ */ jsx8(
3429
- "button",
3430
- {
3431
- type: "button",
3432
- onClick: onStop,
3433
- "aria-label": "\u505C\u6B62\u751F\u6210",
3434
- className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80",
3435
- children: /* @__PURE__ */ jsx8(Square, { size: 13 })
3436
- }
3437
- ) : /* @__PURE__ */ jsx8(
3438
- "button",
3439
- {
3440
- type: "button",
3441
- onClick: handleSubmit,
3442
- disabled: isSendDisabled || isRecording,
3443
- "aria-label": "\u53D1\u9001\u6D88\u606F",
3444
- className: "flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-80 disabled:opacity-25",
3445
- children: /* @__PURE__ */ jsx8(Send, { size: 13 })
3446
- }
3447
- )
3526
+ ),
3527
+ /* @__PURE__ */ jsx9("div", { className: "pointer-events-auto absolute bottom-full right-0 z-30 hidden pb-2 group-hover/help:block group-focus-within/help:block", children: /* @__PURE__ */ jsxs8("div", { className: "min-w-64 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-left text-[11px] leading-5 text-[hsl(var(--popover-foreground))] shadow-lg", children: [
3528
+ activeSessionId ? /* @__PURE__ */ jsx9("div", { className: "mb-2 border-b border-[hsl(var(--border))] pb-2", children: /* @__PURE__ */ jsx9(
3529
+ SkillStatusBarComponent,
3530
+ {
3531
+ sessionId: activeSessionId,
3532
+ onResync: onResyncSkills,
3533
+ isResyncing: isResyncingSkills,
3534
+ vertical: true,
3535
+ className: skillStatusBarClassName,
3536
+ innerClassName: skillStatusBarInnerClassName
3537
+ }
3538
+ ) }) : null,
3539
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-0.5", children: [
3540
+ /* @__PURE__ */ jsx9("div", { children: "Shift+Enter \u6362\u884C" }),
3541
+ /* @__PURE__ */ jsx9("div", { children: "/ \u8C03\u7528\u6280\u80FD" }),
3542
+ /* @__PURE__ */ jsx9("div", { children: "@ \u5F15\u7528\u6587\u4EF6" })
3543
+ ] })
3544
+ ] }) })
3545
+ ] }),
3546
+ /* @__PURE__ */ jsx9(
3547
+ "button",
3548
+ {
3549
+ type: "button",
3550
+ onClick: asrEnabled ? voice.toggle : handleMicDisabledClick,
3551
+ disabled: isStreaming,
3552
+ "aria-label": !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u5F00\u59CB\u8BED\u97F3\u8F93\u5165",
3553
+ title: !asrEnabled ? "\u8BED\u97F3\u8F93\u5165\u672A\u5F00\u542F" : isRecording ? "\u505C\u6B62\u8BED\u97F3\u8F93\u5165" : "\u8BED\u97F3\u8F93\u5165",
3554
+ 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))]"}`,
3555
+ children: !asrEnabled ? /* @__PURE__ */ jsx9(MicOff, { size: 13 }) : isRecording ? /* @__PURE__ */ jsx9(VoiceWaveform, { level: voiceLevel, size: 18 }) : /* @__PURE__ */ jsx9(Mic, { size: 13 })
3556
+ }
3557
+ ),
3558
+ isStreaming ? /* @__PURE__ */ jsx9(
3559
+ "button",
3560
+ {
3561
+ type: "button",
3562
+ onClick: onStop,
3563
+ "aria-label": "\u505C\u6B62\u751F\u6210",
3564
+ 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",
3565
+ children: /* @__PURE__ */ jsx9(Square2, { size: 13 })
3566
+ }
3567
+ ) : /* @__PURE__ */ jsx9(
3568
+ "button",
3569
+ {
3570
+ type: "button",
3571
+ onClick: handleSubmit,
3572
+ disabled: isSendDisabled || isRecording,
3573
+ "aria-label": "\u53D1\u9001\u6D88\u606F",
3574
+ 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",
3575
+ children: /* @__PURE__ */ jsx9(Send, { size: 13 })
3576
+ }
3577
+ )
3578
+ ] })
3448
3579
  ] })
3449
- ] })
3450
- ]
3451
- }
3452
- )
3453
- }
3454
- ) }) }),
3455
- /* @__PURE__ */ jsx8(
3580
+ ]
3581
+ }
3582
+ )
3583
+ }
3584
+ )
3585
+ ] }) }),
3586
+ /* @__PURE__ */ jsx9(
3456
3587
  FileSizeLimitDialog,
3457
3588
  {
3458
3589
  open: oversizedFiles.length > 0,
@@ -3470,18 +3601,18 @@ function ChatInput({
3470
3601
 
3471
3602
  // src/react/components/chat/ConnectionBanner.tsx
3472
3603
  import { AlertTriangle, LoaderCircle } from "lucide-react";
3473
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3604
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3474
3605
  function getBannerCopy(status, reconnectAttempt, hasEverConnected) {
3475
3606
  if (status === "connecting") {
3476
3607
  return {
3477
- icon: /* @__PURE__ */ jsx9(LoaderCircle, { size: 14, className: "animate-spin" }),
3608
+ icon: /* @__PURE__ */ jsx10(LoaderCircle, { size: 14, className: "animate-spin" }),
3478
3609
  toneClass: "border-amber-500/25 bg-amber-500/10 text-amber-100",
3479
3610
  title: "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u91CD\u8FDE\u2026",
3480
3611
  detail: reconnectAttempt > 0 ? `\u6B63\u5728\u5C1D\u8BD5\u6062\u590D\u5B9E\u65F6\u8FDE\u63A5\uFF08\u7B2C ${reconnectAttempt} \u6B21\uFF09` : "\u6B63\u5728\u5C1D\u8BD5\u6062\u590D\u5B9E\u65F6\u8FDE\u63A5\uFF0C\u8BF7\u7A0D\u5019"
3481
3612
  };
3482
3613
  }
3483
3614
  return {
3484
- icon: /* @__PURE__ */ jsx9(AlertTriangle, { size: 14 }),
3615
+ icon: /* @__PURE__ */ jsx10(AlertTriangle, { size: 14 }),
3485
3616
  toneClass: "border-rose-500/25 bg-rose-500/10 text-rose-100",
3486
3617
  title: hasEverConnected ? "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u7B49\u5F85\u91CD\u8FDE\u2026" : "\u6682\u65F6\u65E0\u6CD5\u5EFA\u7ACB\u8FDE\u63A5",
3487
3618
  detail: hasEverConnected ? "\u6D88\u606F\u540C\u6B65\u53EF\u80FD\u4F1A\u5EF6\u8FDF\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" : "\u8BF7\u68C0\u67E5\u670D\u52A1\u662F\u5426\u53EF\u7528\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5"
@@ -3496,7 +3627,7 @@ function ConnectionBanner() {
3496
3627
  return null;
3497
3628
  }
3498
3629
  const copy = getBannerCopy(status, reconnectAttempt, hasEverConnected);
3499
- return /* @__PURE__ */ jsx9("div", { className: "bg-[hsl(var(--background))] px-5 pt-3", children: /* @__PURE__ */ jsxs8(
3630
+ return /* @__PURE__ */ jsx10("div", { className: "bg-[hsl(var(--background))] px-5 pt-3", children: /* @__PURE__ */ jsxs9(
3500
3631
  "div",
3501
3632
  {
3502
3633
  className: cn(
@@ -3504,10 +3635,10 @@ function ConnectionBanner() {
3504
3635
  copy.toneClass
3505
3636
  ),
3506
3637
  children: [
3507
- /* @__PURE__ */ jsx9("span", { className: "mt-0.5 shrink-0", children: copy.icon }),
3508
- /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
3509
- /* @__PURE__ */ jsx9("div", { className: "text-sm font-medium", children: copy.title }),
3510
- /* @__PURE__ */ jsx9("div", { className: "text-xs opacity-80", children: copy.detail })
3638
+ /* @__PURE__ */ jsx10("span", { className: "mt-0.5 shrink-0", children: copy.icon }),
3639
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
3640
+ /* @__PURE__ */ jsx10("div", { className: "text-sm font-medium", children: copy.title }),
3641
+ /* @__PURE__ */ jsx10("div", { className: "text-xs opacity-80", children: copy.detail })
3511
3642
  ] })
3512
3643
  ]
3513
3644
  }
@@ -3522,11 +3653,11 @@ import {
3522
3653
  useEffectEvent as useEffectEvent4,
3523
3654
  useMemo as useMemo17,
3524
3655
  useRef as useRef11,
3525
- useState as useState19
3656
+ useState as useState20
3526
3657
  } from "react";
3527
3658
 
3528
3659
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
3529
- import { useCallback as useCallback7, useMemo as useMemo8, useRef as useRef5, useState as useState7 } from "react";
3660
+ import { useCallback as useCallback7, useMemo as useMemo8, useRef as useRef5, useState as useState8 } from "react";
3530
3661
  var DEFAULT_SPRING_ANIMATION = {
3531
3662
  /**
3532
3663
  * A value from 0 to 1, on how much to damp the animation.
@@ -3563,9 +3694,9 @@ globalThis.document?.addEventListener("click", () => {
3563
3694
  mouseDown = false;
3564
3695
  });
3565
3696
  var useStickToBottom = (options = {}) => {
3566
- const [escapedFromLock, updateEscapedFromLock] = useState7(false);
3567
- const [isAtBottom, updateIsAtBottom] = useState7(options.initial !== false);
3568
- const [isNearBottom, setIsNearBottom] = useState7(false);
3697
+ const [escapedFromLock, updateEscapedFromLock] = useState8(false);
3698
+ const [isAtBottom, updateIsAtBottom] = useState8(options.initial !== false);
3699
+ const [isNearBottom, setIsNearBottom] = useState8(false);
3569
3700
  const optionsRef = useRef5(null);
3570
3701
  optionsRef.current = options;
3571
3702
  const isSelecting = useCallback7(() => {
@@ -3951,7 +4082,7 @@ function useStickToBottomContext() {
3951
4082
 
3952
4083
  // src/react/components/chat/AssistantTurnBlock.tsx
3953
4084
  import { AlertCircle, BookOpen, Check as Check4, ChevronRight as ChevronRight5 } from "lucide-react";
3954
- import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo15, useRef as useRef10, useState as useState16 } from "react";
4085
+ import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo15, useRef as useRef10, useState as useState17 } from "react";
3955
4086
 
3956
4087
  // src/react/routes.ts
3957
4088
  var MEMORIES_ROUTE = "/memories";
@@ -3970,7 +4101,7 @@ import {
3970
4101
  useEffect as useEffect9,
3971
4102
  useMemo as useMemo11,
3972
4103
  useRef as useRef7,
3973
- useState as useState8
4104
+ useState as useState9
3974
4105
  } from "react";
3975
4106
  import { createPortal as createPortal2 } from "react-dom";
3976
4107
  import { Streamdown } from "streamdown";
@@ -3978,7 +4109,7 @@ import { Streamdown } from "streamdown";
3978
4109
  // src/react/components/ai-elements/shimmer.tsx
3979
4110
  import { motion } from "motion/react";
3980
4111
  import { memo, useMemo as useMemo10 } from "react";
3981
- import { jsx as jsx10 } from "react/jsx-runtime";
4112
+ import { jsx as jsx11 } from "react/jsx-runtime";
3982
4113
  var motionComponentCache = /* @__PURE__ */ new Map();
3983
4114
  var getMotionComponent = (element) => {
3984
4115
  let component = motionComponentCache.get(element);
@@ -4002,7 +4133,7 @@ var ShimmerComponent = ({
4002
4133
  () => (children?.length ?? 0) * spread,
4003
4134
  [children, spread]
4004
4135
  );
4005
- return /* @__PURE__ */ jsx10(
4136
+ return /* @__PURE__ */ jsx11(
4006
4137
  MotionComponent,
4007
4138
  {
4008
4139
  animate: { backgroundPosition: "0% center" },
@@ -4028,7 +4159,7 @@ var ShimmerComponent = ({
4028
4159
  var Shimmer = memo(ShimmerComponent);
4029
4160
 
4030
4161
  // src/react/components/ai-elements/reasoning.tsx
4031
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
4162
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
4032
4163
  var ReasoningContext = createContext2(null);
4033
4164
  var useReasoning = () => {
4034
4165
  const context = useContext2(ReasoningContext);
@@ -4062,7 +4193,7 @@ var Reasoning = memo2(
4062
4193
  prop: durationProp
4063
4194
  });
4064
4195
  const hasEverStreamedRef = useRef7(isStreaming);
4065
- const [hasAutoClosed, setHasAutoClosed] = useState8(false);
4196
+ const [hasAutoClosed, setHasAutoClosed] = useState9(false);
4066
4197
  const startTimeRef = useRef7(null);
4067
4198
  useEffect9(() => {
4068
4199
  if (isStreaming) {
@@ -4099,7 +4230,7 @@ var Reasoning = memo2(
4099
4230
  () => ({ duration, isOpen, isStreaming, setIsOpen }),
4100
4231
  [duration, isOpen, isStreaming, setIsOpen]
4101
4232
  );
4102
- return /* @__PURE__ */ jsx11(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx11(
4233
+ return /* @__PURE__ */ jsx12(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx12(
4103
4234
  Collapsible,
4104
4235
  {
4105
4236
  className: cn("not-prose mb-4", className),
@@ -4113,12 +4244,12 @@ var Reasoning = memo2(
4113
4244
  );
4114
4245
  var defaultGetThinkingMessage = (isStreaming, duration) => {
4115
4246
  if (isStreaming || duration === 0) {
4116
- return /* @__PURE__ */ jsx11(Shimmer, { duration: 1, children: "\u6DF1\u5EA6\u601D\u8003\u4E2D..." });
4247
+ return /* @__PURE__ */ jsx12(Shimmer, { duration: 1, children: "\u6DF1\u5EA6\u601D\u8003\u4E2D..." });
4117
4248
  }
4118
4249
  if (duration === void 0) {
4119
- return /* @__PURE__ */ jsx11("p", { children: "\u5DF2\u6DF1\u5EA6\u601D\u8003" });
4250
+ return /* @__PURE__ */ jsx12("p", { children: "\u5DF2\u6DF1\u5EA6\u601D\u8003" });
4120
4251
  }
4121
- return /* @__PURE__ */ jsxs9("p", { children: [
4252
+ return /* @__PURE__ */ jsxs10("p", { children: [
4122
4253
  "\u5DF2\u6DF1\u5EA6\u601D\u8003 ",
4123
4254
  duration,
4124
4255
  " \u79D2"
@@ -4132,7 +4263,7 @@ var ReasoningTrigger = memo2(
4132
4263
  ...props
4133
4264
  }) => {
4134
4265
  const { isStreaming, isOpen, duration } = useReasoning();
4135
- return /* @__PURE__ */ jsx11(
4266
+ return /* @__PURE__ */ jsx12(
4136
4267
  CollapsibleTrigger,
4137
4268
  {
4138
4269
  className: cn(
@@ -4140,10 +4271,10 @@ var ReasoningTrigger = memo2(
4140
4271
  className
4141
4272
  ),
4142
4273
  ...props,
4143
- children: children ?? /* @__PURE__ */ jsxs9(Fragment2, { children: [
4144
- /* @__PURE__ */ jsx11(BrainIcon, { className: "size-4" }),
4274
+ children: children ?? /* @__PURE__ */ jsxs10(Fragment3, { children: [
4275
+ /* @__PURE__ */ jsx12(BrainIcon, { className: "size-4" }),
4145
4276
  getThinkingMessage(isStreaming, duration),
4146
- /* @__PURE__ */ jsx11(
4277
+ /* @__PURE__ */ jsx12(
4147
4278
  ChevronDownIcon,
4148
4279
  {
4149
4280
  className: cn(
@@ -4160,7 +4291,7 @@ var ReasoningTrigger = memo2(
4160
4291
  var streamdownPlugins = { cjk, math, mermaid };
4161
4292
  var streamdownComponents = { code: CardCodeBlock };
4162
4293
  var ReasoningContent = memo2(
4163
- ({ className, children, ...props }) => /* @__PURE__ */ jsx11(
4294
+ ({ className, children, ...props }) => /* @__PURE__ */ jsx12(
4164
4295
  CollapsibleContent,
4165
4296
  {
4166
4297
  className: cn(
@@ -4169,7 +4300,7 @@ var ReasoningContent = memo2(
4169
4300
  className
4170
4301
  ),
4171
4302
  ...props,
4172
- children: /* @__PURE__ */ jsx11(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children })
4303
+ children: /* @__PURE__ */ jsx12(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children })
4173
4304
  }
4174
4305
  )
4175
4306
  );
@@ -4178,8 +4309,8 @@ function compactReasoningText(text) {
4178
4309
  }
4179
4310
  function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4180
4311
  const compactReasoning = compactReasoningText(reasoning);
4181
- const [open, setOpen] = useState8(false);
4182
- return /* @__PURE__ */ jsxs9(
4312
+ const [open, setOpen] = useState9(false);
4313
+ return /* @__PURE__ */ jsxs10(
4183
4314
  "span",
4184
4315
  {
4185
4316
  className: cn(
@@ -4187,7 +4318,7 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4187
4318
  variant === "inline" ? "ml-1" : "ml-1 shrink-0"
4188
4319
  ),
4189
4320
  children: [
4190
- /* @__PURE__ */ jsx11(
4321
+ /* @__PURE__ */ jsx12(
4191
4322
  "button",
4192
4323
  {
4193
4324
  type: "button",
@@ -4202,7 +4333,7 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4202
4333
  }
4203
4334
  ),
4204
4335
  open ? createPortal2(
4205
- /* @__PURE__ */ jsx11(
4336
+ /* @__PURE__ */ jsx12(
4206
4337
  "div",
4207
4338
  {
4208
4339
  className: "fixed inset-0 z-[70] flex items-center justify-center bg-black/10 p-6",
@@ -4218,26 +4349,26 @@ function ThinkingBadge({ reasoning, variant = "inline", onClick }) {
4218
4349
  setOpen(false);
4219
4350
  }
4220
4351
  },
4221
- children: /* @__PURE__ */ jsxs9(
4352
+ children: /* @__PURE__ */ jsxs10(
4222
4353
  "div",
4223
4354
  {
4224
4355
  className: "m-0 flex max-h-[min(520px,calc(100vh-48px))] w-[min(760px,calc(100vw-48px))] flex-col overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] text-left text-[13px] leading-6 text-[hsl(var(--popover-foreground))] shadow-xl",
4225
4356
  "aria-label": "\u601D\u8003\u8BE6\u60C5",
4226
4357
  children: [
4227
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2", children: [
4228
- /* @__PURE__ */ jsx11("span", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u601D\u8003\u8BE6\u60C5" }),
4229
- /* @__PURE__ */ jsx11(
4358
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2", children: [
4359
+ /* @__PURE__ */ jsx12("span", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u601D\u8003\u8BE6\u60C5" }),
4360
+ /* @__PURE__ */ jsx12(
4230
4361
  "button",
4231
4362
  {
4232
4363
  type: "button",
4233
4364
  onClick: () => setOpen(false),
4234
4365
  className: "inline-flex h-6 w-6 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
4235
4366
  "aria-label": "\u5173\u95ED\u601D\u8003\u8BE6\u60C5",
4236
- children: /* @__PURE__ */ jsx11(XIcon, { size: 14, "aria-hidden": "true" })
4367
+ children: /* @__PURE__ */ jsx12(XIcon, { size: 14, "aria-hidden": "true" })
4237
4368
  }
4238
4369
  )
4239
4370
  ] }),
4240
- /* @__PURE__ */ jsx11("div", { className: "overflow-auto px-4 py-3 whitespace-normal [&_*]:whitespace-normal [&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1.5 [&_ol]:my-1.5", children: /* @__PURE__ */ jsx11(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children: compactReasoning }) })
4371
+ /* @__PURE__ */ jsx12("div", { className: "overflow-auto px-4 py-3 whitespace-normal [&_*]:whitespace-normal [&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1.5 [&_ol]:my-1.5", children: /* @__PURE__ */ jsx12(Streamdown, { components: streamdownComponents, plugins: streamdownPlugins, children: compactReasoning }) })
4241
4372
  ]
4242
4373
  }
4243
4374
  )
@@ -4254,12 +4385,12 @@ ReasoningTrigger.displayName = "ReasoningTrigger";
4254
4385
  ReasoningContent.displayName = "ReasoningContent";
4255
4386
 
4256
4387
  // src/react/components/chat/AgentLoopBlock.tsx
4257
- import { Bot, Check as Check3, ChevronRight as ChevronRight4, FileText as FileText5, Loader2 as Loader24, MessageSquareMore as MessageSquareMore2 } from "lucide-react";
4258
- import { useEffect as useEffect13, useMemo as useMemo14, useState as useState15 } from "react";
4388
+ import { Bot, Check as Check3, ChevronRight as ChevronRight4, FileText as FileText6, Loader2 as Loader24, MessageSquareMore as MessageSquareMore2 } from "lucide-react";
4389
+ import { useEffect as useEffect13, useMemo as useMemo14, useState as useState16 } from "react";
4259
4390
 
4260
4391
  // src/react/components/chat/ResourceIframe.tsx
4261
- import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as useRef8, useState as useState9 } from "react";
4262
- import { jsx as jsx12 } from "react/jsx-runtime";
4392
+ import { useEffect as useEffect10, useEffectEvent as useEffectEvent3, useRef as useRef8, useState as useState10 } from "react";
4393
+ import { jsx as jsx13 } from "react/jsx-runtime";
4263
4394
  function isResourceBridgeMessage(value) {
4264
4395
  return typeof value === "object" && value !== null && value.__resourceBridge === true && typeof value.action === "string";
4265
4396
  }
@@ -4276,7 +4407,7 @@ function ResourceIframe({ ui, sessionId }) {
4276
4407
  const theme = useUiStore((state) => state.theme);
4277
4408
  const resourceUri = ui.resourceUri ?? ui.resourceURI;
4278
4409
  const iframeLabel = ui.title ?? resourceUri ?? "\u5DE5\u5177\u754C\u9762";
4279
- const [autoHeight, setAutoHeight] = useState9(null);
4410
+ const [autoHeight, setAutoHeight] = useState10(null);
4280
4411
  useEffect10(() => {
4281
4412
  setAutoHeight(null);
4282
4413
  }, [ui.resourceHTML, resourceUri]);
@@ -4365,7 +4496,7 @@ function ResourceIframe({ ui, sessionId }) {
4365
4496
  }
4366
4497
  const inlineHeight = autoHeight ?? ui.height;
4367
4498
  const sandbox = resourceUri ? "allow-scripts allow-same-origin" : "allow-scripts";
4368
- return /* @__PURE__ */ jsx12(
4499
+ return /* @__PURE__ */ jsx13(
4369
4500
  "iframe",
4370
4501
  {
4371
4502
  ref: iframeRef,
@@ -4387,10 +4518,10 @@ function ResourceIframe({ ui, sessionId }) {
4387
4518
 
4388
4519
  // src/react/components/chat/ToolCallBlock.tsx
4389
4520
  import { Check, ChevronRight as ChevronRight3, Loader2 as Loader23, MessageSquareMore, PanelRightOpen, X as X4 } from "lucide-react";
4390
- import { useMemo as useMemo12, useState as useState12 } from "react";
4521
+ import { useMemo as useMemo12, useState as useState13 } from "react";
4391
4522
 
4392
4523
  // src/react/components/chat/tool-renderers/shared.tsx
4393
- import { jsx as jsx13 } from "react/jsx-runtime";
4524
+ import { jsx as jsx14 } from "react/jsx-runtime";
4394
4525
  function getResultText(result) {
4395
4526
  if (typeof result === "string") return result;
4396
4527
  if (Array.isArray(result)) {
@@ -4457,7 +4588,7 @@ function CodePreview({
4457
4588
  }) {
4458
4589
  const { highlightedHtml } = useHighlightedCodeHtml(content, getCodeLanguage(filePath));
4459
4590
  if (!content.trim()) {
4460
- return /* @__PURE__ */ jsx13(
4591
+ return /* @__PURE__ */ jsx14(
4461
4592
  "pre",
4462
4593
  {
4463
4594
  className: cn(
@@ -4465,11 +4596,11 @@ function CodePreview({
4465
4596
  "bg-[hsl(var(--muted))]/35 p-3 font-mono text-[11px] text-[hsl(var(--muted-foreground))]",
4466
4597
  className
4467
4598
  ),
4468
- children: /* @__PURE__ */ jsx13("code", { children: emptyLabel })
4599
+ children: /* @__PURE__ */ jsx14("code", { children: emptyLabel })
4469
4600
  }
4470
4601
  );
4471
4602
  }
4472
- return /* @__PURE__ */ jsx13(
4603
+ return /* @__PURE__ */ jsx14(
4473
4604
  "pre",
4474
4605
  {
4475
4606
  className: cn(
@@ -4477,19 +4608,19 @@ function CodePreview({
4477
4608
  "bg-[hsl(var(--muted))]/35 p-3 text-[11px]",
4478
4609
  className
4479
4610
  ),
4480
- children: highlightedHtml ? /* @__PURE__ */ jsx13(
4611
+ children: highlightedHtml ? /* @__PURE__ */ jsx14(
4481
4612
  "code",
4482
4613
  {
4483
4614
  className: "font-mono",
4484
4615
  dangerouslySetInnerHTML: { __html: highlightedHtml }
4485
4616
  }
4486
- ) : /* @__PURE__ */ jsx13("code", { className: "whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]", children: content })
4617
+ ) : /* @__PURE__ */ jsx14("code", { className: "whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]", children: content })
4487
4618
  }
4488
4619
  );
4489
4620
  }
4490
4621
 
4491
4622
  // src/react/components/chat/tool-renderers/BashRenderer.tsx
4492
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
4623
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4493
4624
  function pickOutputField(data) {
4494
4625
  if (!data) return null;
4495
4626
  for (const key of ["output", "stdout", "stderr"]) {
@@ -4499,7 +4630,7 @@ function pickOutputField(data) {
4499
4630
  return null;
4500
4631
  }
4501
4632
  function MetaPill({ label }) {
4502
- return /* @__PURE__ */ jsx14("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground", children: label });
4633
+ return /* @__PURE__ */ jsx15("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground", children: label });
4503
4634
  }
4504
4635
  function BashRenderer({ toolCall }) {
4505
4636
  const argsValue = parseJsonValue(toolCall.arguments);
@@ -4522,16 +4653,16 @@ function BashRenderer({ toolCall }) {
4522
4653
  const rawFallbackOutput = result === null && typeof resultStr === "string" && resultStr.trim().length > 0 ? resultStr : null;
4523
4654
  const output = structuredOutput !== null ? structuredOutput : errorMessage ?? rawFallbackOutput ?? (normalizedName === "BgBash" ? "" : null);
4524
4655
  const hasFailure = toolCall.status === "error" || timedOut || exitCode !== null && exitCode !== 0;
4525
- return /* @__PURE__ */ jsxs10("div", { className: "space-y-3", children: [
4526
- (description || cwd) && /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
4527
- description ? /* @__PURE__ */ jsx14("span", { children: description }) : null,
4528
- cwd ? /* @__PURE__ */ jsx14("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: cwd }) : null
4656
+ return /* @__PURE__ */ jsxs11("div", { className: "space-y-3", children: [
4657
+ (description || cwd) && /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
4658
+ description ? /* @__PURE__ */ jsx15("span", { children: description }) : null,
4659
+ cwd ? /* @__PURE__ */ jsx15("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: cwd }) : null
4529
4660
  ] }),
4530
- /* @__PURE__ */ jsxs10("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [
4531
- /* @__PURE__ */ jsx14("div", { className: "border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u547D\u4EE4" }),
4532
- /* @__PURE__ */ jsx14("pre", { className: "overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx14("code", { children: `$ ${command || "\uFF08\u672A\u63D0\u4F9B\u547D\u4EE4\uFF09"}` }) })
4661
+ /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden rounded-lg border border-border bg-card", children: [
4662
+ /* @__PURE__ */ jsx15("div", { className: "border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u547D\u4EE4" }),
4663
+ /* @__PURE__ */ jsx15("pre", { className: "overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx15("code", { children: `$ ${command || "\uFF08\u672A\u63D0\u4F9B\u547D\u4EE4\uFF09"}` }) })
4533
4664
  ] }),
4534
- /* @__PURE__ */ jsxs10(
4665
+ /* @__PURE__ */ jsxs11(
4535
4666
  "div",
4536
4667
  {
4537
4668
  className: cn(
@@ -4539,26 +4670,26 @@ function BashRenderer({ toolCall }) {
4539
4670
  hasFailure ? "border-red-500/50" : "border-border"
4540
4671
  ),
4541
4672
  children: [
4542
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
4543
- /* @__PURE__ */ jsx14("div", { className: "text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u8F93\u51FA" }),
4544
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-1.5", children: [
4545
- taskId ? /* @__PURE__ */ jsx14(MetaPill, { label: `\u4EFB\u52A1 ${taskId}` }) : null,
4546
- exitCode !== null ? /* @__PURE__ */ jsx14(MetaPill, { label: `\u9000\u51FA\u7801 ${exitCode}` }) : null,
4547
- timedOut ? /* @__PURE__ */ jsx14(MetaPill, { label: "\u5DF2\u8D85\u65F6" }) : null,
4548
- truncated ? /* @__PURE__ */ jsx14(MetaPill, { label: "\u8F93\u51FA\u5DF2\u622A\u65AD" }) : null,
4549
- normalizedName === "BgBash" && !taskId ? /* @__PURE__ */ jsx14(MetaPill, { label: "\u540E\u53F0\u4EFB\u52A1" }) : null
4673
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2", children: [
4674
+ /* @__PURE__ */ jsx15("div", { className: "text-[10px] uppercase tracking-[0.16em] text-muted-foreground", children: "\u8F93\u51FA" }),
4675
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-1.5", children: [
4676
+ taskId ? /* @__PURE__ */ jsx15(MetaPill, { label: `\u4EFB\u52A1 ${taskId}` }) : null,
4677
+ exitCode !== null ? /* @__PURE__ */ jsx15(MetaPill, { label: `\u9000\u51FA\u7801 ${exitCode}` }) : null,
4678
+ timedOut ? /* @__PURE__ */ jsx15(MetaPill, { label: "\u5DF2\u8D85\u65F6" }) : null,
4679
+ truncated ? /* @__PURE__ */ jsx15(MetaPill, { label: "\u8F93\u51FA\u5DF2\u622A\u65AD" }) : null,
4680
+ normalizedName === "BgBash" && !taskId ? /* @__PURE__ */ jsx15(MetaPill, { label: "\u540E\u53F0\u4EFB\u52A1" }) : null
4550
4681
  ] })
4551
4682
  ] }),
4552
- /* @__PURE__ */ jsx14("pre", { className: "max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx14("code", { className: "whitespace-pre-wrap break-words", children: output !== null && output.trim().length > 0 ? output : normalizedName === "BgBash" ? "\u4EFB\u52A1\u5DF2\u8FDB\u5165\u540E\u53F0\u6267\u884C\uFF0C\u8F93\u51FA\u4F1A\u5728\u540E\u53F0\u4EFB\u52A1\u9762\u677F\u4E2D\u7EE7\u7EED\u66F4\u65B0\u3002" : output !== null && output.trim().length === 0 && hasFailure ? "\u547D\u4EE4\u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u6355\u83B7\u5230\u7EC8\u7AEF\u8F93\u51FA\uFF08\u8BF7\u67E5\u770B\u9000\u51FA\u7801\uFF09\u3002" : "\u547D\u4EE4\u672A\u8FD4\u56DE\u8F93\u51FA\u3002" }) })
4683
+ /* @__PURE__ */ jsx15("pre", { className: "max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground", children: /* @__PURE__ */ jsx15("code", { className: "whitespace-pre-wrap break-words", children: output !== null && output.trim().length > 0 ? output : normalizedName === "BgBash" ? "\u4EFB\u52A1\u5DF2\u8FDB\u5165\u540E\u53F0\u6267\u884C\uFF0C\u8F93\u51FA\u4F1A\u5728\u540E\u53F0\u4EFB\u52A1\u9762\u677F\u4E2D\u7EE7\u7EED\u66F4\u65B0\u3002" : output !== null && output.trim().length === 0 && hasFailure ? "\u547D\u4EE4\u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u6355\u83B7\u5230\u7EC8\u7AEF\u8F93\u51FA\uFF08\u8BF7\u67E5\u770B\u9000\u51FA\u7801\uFF09\u3002" : "\u547D\u4EE4\u672A\u8FD4\u56DE\u8F93\u51FA\u3002" }) })
4553
4684
  ]
4554
4685
  }
4555
4686
  ),
4556
- cwdResetNote ? /* @__PURE__ */ jsx14("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: cwdResetNote }) : null
4687
+ cwdResetNote ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: cwdResetNote }) : null
4557
4688
  ] });
4558
4689
  }
4559
4690
 
4560
4691
  // src/react/components/chat/tool-renderers/FileEditRenderer.tsx
4561
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4692
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4562
4693
  var MAX_DIFF_LINES = 200;
4563
4694
  function computeDiff(oldText, newText) {
4564
4695
  const oldLines = oldText.split("\n");
@@ -4635,6 +4766,26 @@ function buildWritePreview(content) {
4635
4766
  newLine: index + 1
4636
4767
  }));
4637
4768
  }
4769
+ function buildEditPreview(args) {
4770
+ const edits = Array.isArray(args?.edits) ? args.edits : null;
4771
+ if (edits) {
4772
+ return edits.flatMap((rawEdit, index) => {
4773
+ if (!isPlainObject(rawEdit)) {
4774
+ return [];
4775
+ }
4776
+ const oldText = getStringValue(rawEdit, "old_text") ?? "";
4777
+ const newText = getStringValue(rawEdit, "new_text") ?? "";
4778
+ const lines = computeDiff(oldText, newText);
4779
+ return index === 0 ? lines : [
4780
+ { type: "unchanged", value: "", oldLine: null, newLine: null },
4781
+ ...lines
4782
+ ];
4783
+ });
4784
+ }
4785
+ const oldString = getStringValue(args, "old_string") ?? "";
4786
+ const newString = getStringValue(args, "new_string") ?? "";
4787
+ return computeDiff(oldString, newString);
4788
+ }
4638
4789
  function extractChecksum(result) {
4639
4790
  const text = typeof result === "string" ? result : null;
4640
4791
  const match = text?.match(/\[checksum:\s*([^\]]+)\]/);
@@ -4648,26 +4799,26 @@ function FileEditRenderer({ toolCall }) {
4648
4799
  const fileName = getFileName(filePath);
4649
4800
  const errorMessage = extractErrorMessage(toolCall.result);
4650
4801
  const checksum = extractChecksum(toolCall.result);
4802
+ const description = getStringValue(args, "description");
4651
4803
  const writeContent = getStringValue(args, "content") ?? "";
4652
- const oldString = getStringValue(args, "old_string") ?? "";
4653
- const newString = getStringValue(args, "new_string") ?? "";
4654
- const diffLines = normalizedName === "Write" ? buildWritePreview(writeContent) : computeDiff(oldString, newString);
4804
+ const diffLines = normalizedName === "Write" ? buildWritePreview(writeContent) : buildEditPreview(args);
4655
4805
  const resultStr = typeof toolCall.result === "string" ? toolCall.result : null;
4656
4806
  const summaryText = resultStr?.trim() && !errorMessage ? resultStr.trim() : null;
4657
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-3", children: [
4658
- /* @__PURE__ */ jsxs11("div", { className: "flex items-start justify-between gap-3", children: [
4659
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
4660
- /* @__PURE__ */ jsx15("div", { className: "text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5199\u5165\u6587\u4EF6" : "\u7F16\u8F91\u6587\u4EF6" }),
4661
- /* @__PURE__ */ jsx15("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: filePath ?? fileName })
4807
+ return /* @__PURE__ */ jsxs12("div", { className: "space-y-3", children: [
4808
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between gap-3", children: [
4809
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
4810
+ /* @__PURE__ */ jsx16("div", { className: "text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5199\u5165\u6587\u4EF6" : "\u7F16\u8F91\u6587\u4EF6" }),
4811
+ /* @__PURE__ */ jsx16("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: filePath ?? fileName })
4662
4812
  ] }),
4663
- checksum ? /* @__PURE__ */ jsx15("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
4813
+ checksum ? /* @__PURE__ */ jsx16("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
4664
4814
  ] }),
4665
- errorMessage ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
4666
- /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20", children: [
4667
- /* @__PURE__ */ jsx15("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5185\u5BB9\u9884\u89C8" : "\u53D8\u66F4\u9884\u89C8" }),
4668
- /* @__PURE__ */ jsx15("pre", { className: "max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5", children: diffLines.length > 0 ? diffLines.map((line, index) => {
4815
+ description ? /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: description }) : null,
4816
+ errorMessage ? /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
4817
+ /* @__PURE__ */ jsxs12("div", { className: "overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20", children: [
4818
+ /* @__PURE__ */ jsx16("div", { className: "border-b border-[hsl(var(--border))] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: normalizedName === "Write" ? "\u5185\u5BB9\u9884\u89C8" : "\u53D8\u66F4\u9884\u89C8" }),
4819
+ /* @__PURE__ */ jsx16("pre", { className: "max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5", children: diffLines.length > 0 ? diffLines.map((line, index) => {
4669
4820
  const prefix = line.type === "added" ? "+ " : line.type === "removed" ? "- " : " ";
4670
- return /* @__PURE__ */ jsxs11(
4821
+ return /* @__PURE__ */ jsxs12(
4671
4822
  "div",
4672
4823
  {
4673
4824
  className: cn(
@@ -4677,9 +4828,9 @@ function FileEditRenderer({ toolCall }) {
4677
4828
  line.type === "unchanged" && "text-[hsl(var(--foreground))]"
4678
4829
  ),
4679
4830
  children: [
4680
- /* @__PURE__ */ jsx15("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.oldLine ?? "" }),
4681
- /* @__PURE__ */ jsx15("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.newLine ?? "" }),
4682
- /* @__PURE__ */ jsxs11("span", { className: "min-w-0 whitespace-pre-wrap break-words py-0.5", children: [
4831
+ /* @__PURE__ */ jsx16("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.oldLine ?? "" }),
4832
+ /* @__PURE__ */ jsx16("span", { className: "select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]", children: line.newLine ?? "" }),
4833
+ /* @__PURE__ */ jsxs12("span", { className: "min-w-0 whitespace-pre-wrap break-words py-0.5", children: [
4683
4834
  prefix,
4684
4835
  line.value
4685
4836
  ] })
@@ -4687,24 +4838,24 @@ function FileEditRenderer({ toolCall }) {
4687
4838
  },
4688
4839
  `${line.type}-${line.oldLine}-${line.newLine}-${index}`
4689
4840
  );
4690
- }) : /* @__PURE__ */ jsx15("div", { className: "px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u672A\u68C0\u6D4B\u5230\u53EF\u9884\u89C8\u7684\u53D8\u66F4\u3002" }) })
4841
+ }) : /* @__PURE__ */ jsx16("div", { className: "px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u672A\u68C0\u6D4B\u5230\u53EF\u9884\u89C8\u7684\u53D8\u66F4\u3002" }) })
4691
4842
  ] }),
4692
- summaryText ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: summaryText }) : null
4843
+ summaryText ? /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: summaryText }) : null
4693
4844
  ] });
4694
4845
  }
4695
4846
 
4696
4847
  // src/react/components/chat/tool-renderers/FileReadRenderer.tsx
4697
- import { useState as useState11 } from "react";
4848
+ import { useState as useState12 } from "react";
4698
4849
 
4699
4850
  // src/react/components/chat/ImageLightbox.tsx
4700
4851
  import { ChevronLeft, ChevronRight as ChevronRight2, Download as Download2, ExternalLink, Minus, Plus as Plus2, RotateCcw, X as X3 } from "lucide-react";
4701
- import { useCallback as useCallback10, useEffect as useEffect11, useRef as useRef9, useState as useState10 } from "react";
4852
+ import { useCallback as useCallback10, useEffect as useEffect11, useRef as useRef9, useState as useState11 } from "react";
4702
4853
  import { createPortal as createPortal3 } from "react-dom";
4703
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4854
+ import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
4704
4855
  function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4705
- const [currentIndex, setCurrentIndex] = useState10(initialIndex);
4706
- const [scale, setScale] = useState10(1);
4707
- const [translate, setTranslate] = useState10({ x: 0, y: 0 });
4856
+ const [currentIndex, setCurrentIndex] = useState11(initialIndex);
4857
+ const [scale, setScale] = useState11(1);
4858
+ const [translate, setTranslate] = useState11({ x: 0, y: 0 });
4708
4859
  const dragging = useRef9(false);
4709
4860
  const dragStart = useRef9({ x: 0, y: 0 });
4710
4861
  const translateStart = useRef9({ x: 0, y: 0 });
@@ -4810,22 +4961,22 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4810
4961
  if (images.length === 0) {
4811
4962
  return createPortal3(
4812
4963
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect
4813
- /* @__PURE__ */ jsxs12(
4964
+ /* @__PURE__ */ jsxs13(
4814
4965
  "div",
4815
4966
  {
4816
4967
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80",
4817
4968
  onClick: close,
4818
4969
  children: [
4819
- /* @__PURE__ */ jsx16(
4970
+ /* @__PURE__ */ jsx17(
4820
4971
  "button",
4821
4972
  {
4822
4973
  type: "button",
4823
4974
  onClick: close,
4824
4975
  className: "absolute right-4 top-4 z-10 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4825
- children: /* @__PURE__ */ jsx16(X3, { size: 20 })
4976
+ children: /* @__PURE__ */ jsx17(X3, { size: 20 })
4826
4977
  }
4827
4978
  ),
4828
- /* @__PURE__ */ jsx16("span", { className: "text-sm text-white/60", children: "\u52A0\u8F7D\u4E2D..." })
4979
+ /* @__PURE__ */ jsx17("span", { className: "text-sm text-white/60", children: "\u52A0\u8F7D\u4E2D..." })
4829
4980
  ]
4830
4981
  }
4831
4982
  ),
@@ -4836,46 +4987,46 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4836
4987
  const showNav = images.length > 1;
4837
4988
  return createPortal3(
4838
4989
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect
4839
- /* @__PURE__ */ jsxs12("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: handleAreaClick, children: [
4840
- /* @__PURE__ */ jsxs12(
4990
+ /* @__PURE__ */ jsxs13("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: handleAreaClick, children: [
4991
+ /* @__PURE__ */ jsxs13(
4841
4992
  "div",
4842
4993
  {
4843
4994
  className: "absolute right-4 top-4 z-10 flex items-center gap-1.5",
4844
4995
  onClick: (e) => e.stopPropagation(),
4845
4996
  children: [
4846
- /* @__PURE__ */ jsx16(
4997
+ /* @__PURE__ */ jsx17(
4847
4998
  "button",
4848
4999
  {
4849
5000
  type: "button",
4850
5001
  onClick: handleDownload,
4851
5002
  title: "\u4E0B\u8F7D\u56FE\u7247",
4852
5003
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4853
- children: /* @__PURE__ */ jsx16(Download2, { size: 18 })
5004
+ children: /* @__PURE__ */ jsx17(Download2, { size: 18 })
4854
5005
  }
4855
5006
  ),
4856
- /* @__PURE__ */ jsx16(
5007
+ /* @__PURE__ */ jsx17(
4857
5008
  "button",
4858
5009
  {
4859
5010
  type: "button",
4860
5011
  onClick: handleOpenInNewTab,
4861
5012
  title: "\u65B0\u6807\u7B7E\u9875\u6253\u5F00",
4862
5013
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4863
- children: /* @__PURE__ */ jsx16(ExternalLink, { size: 18 })
5014
+ children: /* @__PURE__ */ jsx17(ExternalLink, { size: 18 })
4864
5015
  }
4865
5016
  ),
4866
- /* @__PURE__ */ jsx16(
5017
+ /* @__PURE__ */ jsx17(
4867
5018
  "button",
4868
5019
  {
4869
5020
  type: "button",
4870
5021
  onClick: close,
4871
5022
  className: "rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4872
- children: /* @__PURE__ */ jsx16(X3, { size: 20 })
5023
+ children: /* @__PURE__ */ jsx17(X3, { size: 20 })
4873
5024
  }
4874
5025
  )
4875
5026
  ]
4876
5027
  }
4877
5028
  ),
4878
- showNav && currentIndex > 0 && /* @__PURE__ */ jsx16(
5029
+ showNav && currentIndex > 0 && /* @__PURE__ */ jsx17(
4879
5030
  "button",
4880
5031
  {
4881
5032
  type: "button",
@@ -4884,10 +5035,10 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4884
5035
  goPrev();
4885
5036
  },
4886
5037
  className: "absolute left-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4887
- children: /* @__PURE__ */ jsx16(ChevronLeft, { size: 24 })
5038
+ children: /* @__PURE__ */ jsx17(ChevronLeft, { size: 24 })
4888
5039
  }
4889
5040
  ),
4890
- showNav && currentIndex < images.length - 1 && /* @__PURE__ */ jsx16(
5041
+ showNav && currentIndex < images.length - 1 && /* @__PURE__ */ jsx17(
4891
5042
  "button",
4892
5043
  {
4893
5044
  type: "button",
@@ -4896,51 +5047,51 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4896
5047
  goNext();
4897
5048
  },
4898
5049
  className: "absolute right-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white",
4899
- children: /* @__PURE__ */ jsx16(ChevronRight2, { size: 24 })
5050
+ children: /* @__PURE__ */ jsx17(ChevronRight2, { size: 24 })
4900
5051
  }
4901
5052
  ),
4902
- /* @__PURE__ */ jsxs12("div", { className: "absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 items-center gap-1 rounded-full bg-black/50 px-2 py-1", children: [
4903
- /* @__PURE__ */ jsx16(
5053
+ /* @__PURE__ */ jsxs13("div", { className: "absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 items-center gap-1 rounded-full bg-black/50 px-2 py-1", children: [
5054
+ /* @__PURE__ */ jsx17(
4904
5055
  "button",
4905
5056
  {
4906
5057
  type: "button",
4907
5058
  onClick: zoomOut,
4908
5059
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
4909
- children: /* @__PURE__ */ jsx16(Minus, { size: 16 })
5060
+ children: /* @__PURE__ */ jsx17(Minus, { size: 16 })
4910
5061
  }
4911
5062
  ),
4912
- /* @__PURE__ */ jsxs12("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5063
+ /* @__PURE__ */ jsxs13("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
4913
5064
  Math.round(scale * 100),
4914
5065
  "%"
4915
5066
  ] }),
4916
- /* @__PURE__ */ jsx16(
5067
+ /* @__PURE__ */ jsx17(
4917
5068
  "button",
4918
5069
  {
4919
5070
  type: "button",
4920
5071
  onClick: zoomIn,
4921
5072
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
4922
- children: /* @__PURE__ */ jsx16(Plus2, { size: 16 })
5073
+ children: /* @__PURE__ */ jsx17(Plus2, { size: 16 })
4923
5074
  }
4924
5075
  ),
4925
- /* @__PURE__ */ jsx16(
5076
+ /* @__PURE__ */ jsx17(
4926
5077
  "button",
4927
5078
  {
4928
5079
  type: "button",
4929
5080
  onClick: reset,
4930
5081
  className: "rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white",
4931
- children: /* @__PURE__ */ jsx16(RotateCcw, { size: 16 })
5082
+ children: /* @__PURE__ */ jsx17(RotateCcw, { size: 16 })
4932
5083
  }
4933
5084
  ),
4934
- showNav && /* @__PURE__ */ jsxs12(Fragment3, { children: [
4935
- /* @__PURE__ */ jsx16("div", { className: "mx-1 h-4 w-px bg-white/20" }),
4936
- /* @__PURE__ */ jsxs12("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
5085
+ showNav && /* @__PURE__ */ jsxs13(Fragment4, { children: [
5086
+ /* @__PURE__ */ jsx17("div", { className: "mx-1 h-4 w-px bg-white/20" }),
5087
+ /* @__PURE__ */ jsxs13("span", { className: "min-w-[3rem] text-center text-xs text-white/80", children: [
4937
5088
  currentIndex + 1,
4938
5089
  " / ",
4939
5090
  images.length
4940
5091
  ] })
4941
5092
  ] })
4942
5093
  ] }),
4943
- /* @__PURE__ */ jsx16(
5094
+ /* @__PURE__ */ jsx17(
4944
5095
  "div",
4945
5096
  {
4946
5097
  className: "flex h-full w-full items-center justify-center overflow-hidden p-12",
@@ -4951,7 +5102,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4951
5102
  onMouseUp: handleMouseUp,
4952
5103
  onMouseLeave: handleMouseUp,
4953
5104
  onDoubleClick: handleDoubleClick,
4954
- children: /* @__PURE__ */ jsx16(
5105
+ children: /* @__PURE__ */ jsx17(
4955
5106
  "img",
4956
5107
  {
4957
5108
  ref: imgRef,
@@ -4973,7 +5124,7 @@ function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }) {
4973
5124
  }
4974
5125
 
4975
5126
  // src/react/components/chat/tool-renderers/FileReadRenderer.tsx
4976
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
5127
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4977
5128
  var NUMBERED_LINE_RE = /^(\s*\d+)\t([\s\S]*)$/;
4978
5129
  function parseReadResult(result) {
4979
5130
  if (!result) {
@@ -5017,11 +5168,12 @@ function formatLineRange(startLine, endLine) {
5017
5168
  return startLine === endLine ? `\u7B2C ${startLine} \u884C` : `\u7B2C ${startLine}-${endLine} \u884C`;
5018
5169
  }
5019
5170
  function FileReadRenderer({ toolCall }) {
5020
- const [lightboxIndex, setLightboxIndex] = useState11(null);
5171
+ const [lightboxIndex, setLightboxIndex] = useState12(null);
5021
5172
  const argsValue = parseJsonValue(toolCall.arguments);
5022
5173
  const args = isPlainObject(argsValue) ? argsValue : null;
5023
5174
  const filePath = extractToolFilePath(toolCall);
5024
5175
  const fileName = getFileName(filePath);
5176
+ const description = getStringValue(args, "description");
5025
5177
  const resultText = getResultText(toolCall.result);
5026
5178
  const imageUrls = getResultImageUrls(toolCall.result);
5027
5179
  const isImageResult = imageUrls.length > 0;
@@ -5032,27 +5184,28 @@ function FileReadRenderer({ toolCall }) {
5032
5184
  const resolvedStartLine = startLine ?? (lineCount > 0 ? fallbackStart : null);
5033
5185
  const resolvedEndLine = endLine ?? (resolvedStartLine !== null && lineCount > 0 ? resolvedStartLine + lineCount - 1 : null);
5034
5186
  const lineRange = formatLineRange(resolvedStartLine, resolvedEndLine);
5035
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
5036
- /* @__PURE__ */ jsxs13("div", { className: "flex items-start justify-between gap-3", children: [
5037
- /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
5038
- /* @__PURE__ */ jsx17("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: fileName }),
5039
- filePath ? /* @__PURE__ */ jsx17("div", { className: "truncate text-[10px] text-[hsl(var(--muted-foreground))]", children: filePath }) : null
5187
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5188
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-start justify-between gap-3", children: [
5189
+ /* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
5190
+ /* @__PURE__ */ jsx18("div", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: fileName }),
5191
+ filePath ? /* @__PURE__ */ jsx18("div", { className: "truncate text-[10px] text-[hsl(var(--muted-foreground))]", children: filePath }) : null
5040
5192
  ] }),
5041
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
5042
- lineRange ? /* @__PURE__ */ jsx17("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: lineRange }) : null,
5043
- checksum ? /* @__PURE__ */ jsx17("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
5193
+ /* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
5194
+ lineRange ? /* @__PURE__ */ jsx18("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: lineRange }) : null,
5195
+ checksum ? /* @__PURE__ */ jsx18("span", { className: "rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: checksum }) : null
5044
5196
  ] })
5045
5197
  ] }),
5046
- errorMessage ? /* @__PURE__ */ jsx17("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage }) : null,
5047
- isImageResult ? /* @__PURE__ */ jsxs13("div", { className: "grid gap-2", children: [
5048
- imageUrls.map((url, idx) => /* @__PURE__ */ jsx17(
5198
+ 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,
5199
+ 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,
5200
+ isImageResult ? /* @__PURE__ */ jsxs14("div", { className: "grid gap-2", children: [
5201
+ imageUrls.map((url, idx) => /* @__PURE__ */ jsx18(
5049
5202
  "button",
5050
5203
  {
5051
5204
  type: "button",
5052
5205
  onClick: () => setLightboxIndex(idx),
5053
5206
  className: "cursor-zoom-in",
5054
5207
  title: "\u67E5\u770B\u5927\u56FE",
5055
- children: /* @__PURE__ */ jsx17(
5208
+ children: /* @__PURE__ */ jsx18(
5056
5209
  "img",
5057
5210
  {
5058
5211
  src: url,
@@ -5063,7 +5216,7 @@ function FileReadRenderer({ toolCall }) {
5063
5216
  },
5064
5217
  url.slice(0, 64)
5065
5218
  )),
5066
- /* @__PURE__ */ jsx17(
5219
+ /* @__PURE__ */ jsx18(
5067
5220
  ImageLightbox,
5068
5221
  {
5069
5222
  open: lightboxIndex != null,
@@ -5074,15 +5227,15 @@ function FileReadRenderer({ toolCall }) {
5074
5227
  initialIndex: lightboxIndex ?? 0
5075
5228
  }
5076
5229
  ),
5077
- content ? /* @__PURE__ */ jsx17("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: content }) : null
5078
- ] }) : !errorMessage ? /* @__PURE__ */ jsx17(CodePreview, { content, filePath, className: "max-h-[360px]" }) : null,
5079
- note ? /* @__PURE__ */ jsx17("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: note }) : null
5230
+ content ? /* @__PURE__ */ jsx18("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: content }) : null
5231
+ ] }) : !errorMessage ? /* @__PURE__ */ jsx18(CodePreview, { content, filePath, className: "max-h-[360px]" }) : null,
5232
+ note ? /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: note }) : null
5080
5233
  ] });
5081
5234
  }
5082
5235
 
5083
5236
  // src/react/components/chat/tool-renderers/SearchRenderer.tsx
5084
- import { ExternalLink as ExternalLink2, FileText as FileText2, Folder as Folder2, Globe2 } from "lucide-react";
5085
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
5237
+ import { ExternalLink as ExternalLink2, FileText as FileText3, Folder as Folder2, Globe2 } from "lucide-react";
5238
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5086
5239
  function toRecordArray(value) {
5087
5240
  return Array.isArray(value) ? value.filter(isPlainObject) : [];
5088
5241
  }
@@ -5144,7 +5297,7 @@ function parseWebFetchResult(result) {
5144
5297
  };
5145
5298
  }
5146
5299
  function renderEmptyState(label) {
5147
- return /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: label });
5300
+ return /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]", children: label });
5148
5301
  }
5149
5302
  function SearchRenderer({ toolCall }) {
5150
5303
  const normalizedName = formatToolName(toolCall.name);
@@ -5153,26 +5306,26 @@ function SearchRenderer({ toolCall }) {
5153
5306
  const resultStr = getResultText(toolCall.result);
5154
5307
  const errorMessage = extractErrorMessage(resultStr);
5155
5308
  if (errorMessage) {
5156
- return /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage });
5309
+ return /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300", children: errorMessage });
5157
5310
  }
5158
5311
  if (normalizedName === "Ls" || normalizedName === "Glob") {
5159
5312
  const items = parseDirectoryItems(resultStr);
5160
5313
  const path = getStringValue(args, "path");
5161
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5162
- path ? /* @__PURE__ */ jsxs14("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5314
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5315
+ path ? /* @__PURE__ */ jsxs15("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5163
5316
  "\u76EE\u5F55\uFF1A",
5164
5317
  path
5165
5318
  ] }) : null,
5166
- items.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "grid gap-2", children: items.map((item) => /* @__PURE__ */ jsxs14(
5319
+ items.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: items.map((item) => /* @__PURE__ */ jsxs15(
5167
5320
  "div",
5168
5321
  {
5169
5322
  className: "flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2",
5170
5323
  children: [
5171
- /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 items-center gap-2", children: [
5172
- item.isDir ? /* @__PURE__ */ jsx18(Folder2, { size: 14, className: "shrink-0 text-blue-300" }) : /* @__PURE__ */ jsx18(FileText2, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5173
- /* @__PURE__ */ jsx18("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: item.name })
5324
+ /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 items-center gap-2", children: [
5325
+ item.isDir ? /* @__PURE__ */ jsx19(Folder2, { size: 14, className: "shrink-0 text-blue-300" }) : /* @__PURE__ */ jsx19(FileText3, { size: 14, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5326
+ /* @__PURE__ */ jsx19("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: item.name })
5174
5327
  ] }),
5175
- /* @__PURE__ */ jsx18("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: item.isDir ? "\u76EE\u5F55" : formatBytes(item.size) ?? "\u6587\u4EF6" })
5328
+ /* @__PURE__ */ jsx19("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: item.isDir ? "\u76EE\u5F55" : formatBytes(item.size) ?? "\u6587\u4EF6" })
5176
5329
  ]
5177
5330
  },
5178
5331
  `${item.name}-${item.size}-${item.isDir}`
@@ -5182,28 +5335,28 @@ function SearchRenderer({ toolCall }) {
5182
5335
  if (normalizedName === "Grep") {
5183
5336
  const { matches, searchPath } = parseGrepResult(resultStr);
5184
5337
  const pattern = getStringValue(args, "pattern");
5185
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5186
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5187
- pattern ? /* @__PURE__ */ jsx18("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: pattern }) : null,
5188
- searchPath ? /* @__PURE__ */ jsxs14("span", { children: [
5338
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5339
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5340
+ pattern ? /* @__PURE__ */ jsx19("span", { className: "rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono", children: pattern }) : null,
5341
+ searchPath ? /* @__PURE__ */ jsxs15("span", { children: [
5189
5342
  "\u8303\u56F4\uFF1A",
5190
5343
  searchPath
5191
5344
  ] }) : null
5192
5345
  ] }),
5193
- matches.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "grid gap-2", children: matches.map((match) => /* @__PURE__ */ jsxs14(
5346
+ matches.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: matches.map((match) => /* @__PURE__ */ jsxs15(
5194
5347
  "div",
5195
5348
  {
5196
5349
  className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2",
5197
5350
  children: [
5198
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-3", children: [
5199
- /* @__PURE__ */ jsx18("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: match.path }),
5200
- match.lineNumber !== null ? /* @__PURE__ */ jsxs14("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5351
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between gap-3", children: [
5352
+ /* @__PURE__ */ jsx19("span", { className: "truncate font-mono text-[11px] text-[hsl(var(--foreground))]", children: match.path }),
5353
+ match.lineNumber !== null ? /* @__PURE__ */ jsxs15("span", { className: "shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5201
5354
  "\u7B2C ",
5202
5355
  match.lineNumber,
5203
5356
  " \u884C"
5204
5357
  ] }) : null
5205
5358
  ] }),
5206
- /* @__PURE__ */ jsx18("pre", { className: "mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx18("code", { children: match.line }) })
5359
+ /* @__PURE__ */ jsx19("pre", { className: "mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx19("code", { children: match.line }) })
5207
5360
  ]
5208
5361
  },
5209
5362
  `${match.path}-${match.lineNumber}-${match.line}`
@@ -5212,16 +5365,16 @@ function SearchRenderer({ toolCall }) {
5212
5365
  }
5213
5366
  const { results, summary } = normalizedName === "WebFetch" ? parseWebFetchResult(resultStr) : { results: parseWebResults(resultStr), summary: null };
5214
5367
  const query = getStringValue(args, "query");
5215
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
5216
- query ? /* @__PURE__ */ jsxs14("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5368
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
5369
+ query ? /* @__PURE__ */ jsxs15("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: [
5217
5370
  "\u67E5\u8BE2\uFF1A",
5218
5371
  query
5219
5372
  ] }) : null,
5220
- summary ? /* @__PURE__ */ jsxs14("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3", children: [
5221
- /* @__PURE__ */ jsx18("div", { className: "mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: "\u6458\u8981" }),
5222
- /* @__PURE__ */ jsx18("p", { className: "whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]", children: summary })
5373
+ summary ? /* @__PURE__ */ jsxs15("div", { className: "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3", children: [
5374
+ /* @__PURE__ */ jsx19("div", { className: "mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]", children: "\u6458\u8981" }),
5375
+ /* @__PURE__ */ jsx19("p", { className: "whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]", children: summary })
5223
5376
  ] }) : null,
5224
- results.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "grid gap-2", children: results.map((item, index) => /* @__PURE__ */ jsx18(
5377
+ results.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "grid gap-2", children: results.map((item, index) => /* @__PURE__ */ jsx19(
5225
5378
  "a",
5226
5379
  {
5227
5380
  href: item.url ?? void 0,
@@ -5231,12 +5384,12 @@ function SearchRenderer({ toolCall }) {
5231
5384
  "rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3 transition-colors",
5232
5385
  item.url && "hover:border-[hsl(var(--ring))] hover:bg-[hsl(var(--muted))]/35"
5233
5386
  ),
5234
- children: /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3", children: [
5235
- /* @__PURE__ */ jsx18(Globe2, { size: 15, className: "mt-0.5 shrink-0 text-blue-300" }),
5236
- /* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
5237
- /* @__PURE__ */ jsxs14("div", { className: "flex items-start justify-between gap-3", children: [
5238
- /* @__PURE__ */ jsx18("span", { className: "line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]", children: item.title ?? item.url ?? "\u672A\u547D\u540D\u7ED3\u679C" }),
5239
- item.url ? /* @__PURE__ */ jsx18(
5387
+ children: /* @__PURE__ */ jsxs15("div", { className: "flex items-start gap-3", children: [
5388
+ /* @__PURE__ */ jsx19(Globe2, { size: 15, className: "mt-0.5 shrink-0 text-blue-300" }),
5389
+ /* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
5390
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-3", children: [
5391
+ /* @__PURE__ */ jsx19("span", { className: "line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]", children: item.title ?? item.url ?? "\u672A\u547D\u540D\u7ED3\u679C" }),
5392
+ item.url ? /* @__PURE__ */ jsx19(
5240
5393
  ExternalLink2,
5241
5394
  {
5242
5395
  size: 12,
@@ -5244,8 +5397,8 @@ function SearchRenderer({ toolCall }) {
5244
5397
  }
5245
5398
  ) : null
5246
5399
  ] }),
5247
- item.url ? /* @__PURE__ */ jsx18("div", { className: "mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.url }) : null,
5248
- item.description ? /* @__PURE__ */ jsx18("p", { className: "mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: item.description }) : null
5400
+ item.url ? /* @__PURE__ */ jsx19("div", { className: "mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.url }) : null,
5401
+ item.description ? /* @__PURE__ */ jsx19("p", { className: "mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: item.description }) : null
5249
5402
  ] })
5250
5403
  ] })
5251
5404
  },
@@ -5272,7 +5425,7 @@ function getRenderer(toolName) {
5272
5425
  }
5273
5426
 
5274
5427
  // src/react/components/chat/ToolCallBlock.tsx
5275
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5428
+ import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5276
5429
  function FilePathLink({ filePath, sessionId }) {
5277
5430
  const activeSessionId = useSessionStore((s) => s.activeSessionId);
5278
5431
  const pushArtifact = useUiStore((s) => s.pushArtifact);
@@ -5290,14 +5443,14 @@ function FilePathLink({ filePath, sessionId }) {
5290
5443
  } catch {
5291
5444
  }
5292
5445
  };
5293
- return /* @__PURE__ */ jsx19(
5446
+ return /* @__PURE__ */ jsx20(
5294
5447
  "button",
5295
5448
  {
5296
5449
  type: "button",
5297
5450
  onClick: handleClick,
5298
5451
  className: "flex min-w-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer font-mono",
5299
5452
  title: `\u9884\u89C8 ${filePath}`,
5300
- children: /* @__PURE__ */ jsx19("span", { className: "truncate", children: fileName })
5453
+ children: /* @__PURE__ */ jsx20("span", { className: "truncate", children: fileName })
5301
5454
  }
5302
5455
  );
5303
5456
  }
@@ -5313,7 +5466,7 @@ function ToolCallBlock({
5313
5466
  reasoning,
5314
5467
  customization
5315
5468
  }) {
5316
- const [expanded, setExpanded] = useState12(false);
5469
+ const [expanded, setExpanded] = useState13(false);
5317
5470
  const activeSessionId = useSessionStore((s) => s.activeSessionId);
5318
5471
  const sessions = useSessionStore((s) => s.sessions);
5319
5472
  const pushArtifact = useUiStore((s) => s.pushArtifact);
@@ -5340,7 +5493,7 @@ function ToolCallBlock({
5340
5493
  const canAnswer = toolCall.status === "awaiting_answer" && Boolean(resolvedOnAnswer) && Boolean(resolvedSessionStatus);
5341
5494
  const shouldRenderQuestion = Boolean(askData) && (canAnswer || resolvedAnswered || toolCall.status === "done");
5342
5495
  if (askData && shouldRenderQuestion) {
5343
- const questionBlock = /* @__PURE__ */ jsx19(
5496
+ const questionBlock = /* @__PURE__ */ jsx20(
5344
5497
  AskUserQuestionBlock,
5345
5498
  {
5346
5499
  data: askData,
@@ -5354,9 +5507,9 @@ function ToolCallBlock({
5354
5507
  if (!reasoning) {
5355
5508
  return questionBlock;
5356
5509
  }
5357
- return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-1", children: [
5510
+ return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1", children: [
5358
5511
  questionBlock,
5359
- /* @__PURE__ */ jsx19("div", { className: "ml-4", children: /* @__PURE__ */ jsx19(ThinkingBadge, { reasoning, variant: "block" }) })
5512
+ /* @__PURE__ */ jsx20("div", { className: "ml-4", children: /* @__PURE__ */ jsx20(ThinkingBadge, { reasoning, variant: "block" }) })
5360
5513
  ] });
5361
5514
  }
5362
5515
  }
@@ -5368,11 +5521,11 @@ function ToolCallBlock({
5368
5521
  const borderWidthClass = level === 2 ? "border-l-[2px]" : "border-l-[3px]";
5369
5522
  const indentClass = level === 2 ? "ml-3" : "ml-4";
5370
5523
  const toneClass = tone === "red" ? "border-l-[hsl(var(--muted-foreground)/0.5)]" : tone === "amber" ? "border-l-amber-400" : tone === "blue" ? "border-l-blue-500" : "border-l-[hsl(var(--primary))]";
5371
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx19(Loader23, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx19(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx19(X4, { size: 11 }) : /* @__PURE__ */ jsx19(Check, { size: 11 });
5524
+ const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx20(Loader23, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx20(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx20(X4, { size: 11 }) : /* @__PURE__ */ jsx20(Check, { size: 11 });
5372
5525
  const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
5373
- return /* @__PURE__ */ jsxs15("div", { className: cn(indentClass, "text-xs", customization?.classNames?.toolCall), children: [
5374
- /* @__PURE__ */ jsxs15("div", { className: cn(borderWidthClass, toneClass, "flex items-center gap-2 px-3 py-2"), children: [
5375
- /* @__PURE__ */ jsxs15(
5526
+ return /* @__PURE__ */ jsxs16("div", { className: cn(indentClass, "text-xs", customization?.classNames?.toolCall), children: [
5527
+ /* @__PURE__ */ jsxs16("div", { className: cn(borderWidthClass, toneClass, "flex items-center gap-2 px-3 py-2"), children: [
5528
+ /* @__PURE__ */ jsxs16(
5376
5529
  "button",
5377
5530
  {
5378
5531
  type: "button",
@@ -5380,7 +5533,7 @@ function ToolCallBlock({
5380
5533
  className: "flex min-w-0 flex-1 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
5381
5534
  "aria-expanded": expanded,
5382
5535
  children: [
5383
- /* @__PURE__ */ jsx19(
5536
+ /* @__PURE__ */ jsx20(
5384
5537
  ChevronRight3,
5385
5538
  {
5386
5539
  size: 11,
@@ -5390,19 +5543,19 @@ function ToolCallBlock({
5390
5543
  )
5391
5544
  }
5392
5545
  ),
5393
- /* @__PURE__ */ jsxs15("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
5546
+ /* @__PURE__ */ jsxs16("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
5394
5547
  statusIcon,
5395
- /* @__PURE__ */ jsx19("span", { children: getToolStatusLabel(toolCall.status) })
5548
+ /* @__PURE__ */ jsx20("span", { children: getToolStatusLabel(toolCall.status) })
5396
5549
  ] }),
5397
- /* @__PURE__ */ jsxs15("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: [
5550
+ /* @__PURE__ */ jsxs16("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: [
5398
5551
  displayName,
5399
5552
  toolCall.status === "error" ? "\uFF08\u5F85\u91CD\u8BD5\uFF09" : ""
5400
5553
  ] })
5401
5554
  ]
5402
5555
  }
5403
5556
  ),
5404
- filePath && /* @__PURE__ */ jsx19("span", { className: "flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx19(FilePathLink, { filePath, sessionId: resolvedSessionId }) }),
5405
- loadedSkillName ? /* @__PURE__ */ jsx19(
5557
+ filePath && /* @__PURE__ */ jsx20("span", { className: "flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsx20(FilePathLink, { filePath, sessionId: resolvedSessionId }) }),
5558
+ loadedSkillName ? /* @__PURE__ */ jsx20(
5406
5559
  "span",
5407
5560
  {
5408
5561
  className: "min-w-0 max-w-[50%] shrink truncate text-[hsl(var(--foreground))]",
@@ -5410,9 +5563,9 @@ function ToolCallBlock({
5410
5563
  children: loadedSkillName
5411
5564
  }
5412
5565
  ) : null,
5413
- reasoning ? /* @__PURE__ */ jsx19(ThinkingBadge, { reasoning, variant: "block" }) : null,
5414
- typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx19("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) }),
5415
- uiMeta?.target === "preview" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? /* @__PURE__ */ jsxs15(
5566
+ reasoning ? /* @__PURE__ */ jsx20(ThinkingBadge, { reasoning, variant: "block" }) : null,
5567
+ typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx20("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) }),
5568
+ uiMeta?.target === "preview" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? /* @__PURE__ */ jsxs16(
5416
5569
  "button",
5417
5570
  {
5418
5571
  type: "button",
@@ -5430,18 +5583,18 @@ function ToolCallBlock({
5430
5583
  className: "inline-flex shrink-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer",
5431
5584
  title: `\u6253\u5F00 ${uiMeta.title ?? displayName}`,
5432
5585
  children: [
5433
- /* @__PURE__ */ jsx19(PanelRightOpen, { size: 11 }),
5434
- /* @__PURE__ */ jsx19("span", { children: uiMeta.title ?? displayName })
5586
+ /* @__PURE__ */ jsx20(PanelRightOpen, { size: 11 }),
5587
+ /* @__PURE__ */ jsx20("span", { children: uiMeta.title ?? displayName })
5435
5588
  ]
5436
5589
  }
5437
5590
  ) : null
5438
5591
  ] }),
5439
- expanded && /* @__PURE__ */ jsx19("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: Renderer ? /* @__PURE__ */ jsx19(Renderer, { toolCall, sessionId: resolvedSessionId }) : /* @__PURE__ */ jsxs15(Fragment4, { children: [
5440
- /* @__PURE__ */ jsx19("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
5441
- /* @__PURE__ */ jsx19("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatArgs(toolCall.arguments) }),
5442
- toolCall.result != null && /* @__PURE__ */ jsxs15(Fragment4, { children: [
5443
- /* @__PURE__ */ jsx19("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
5444
- /* @__PURE__ */ jsx19(
5592
+ expanded && /* @__PURE__ */ jsx20("div", { className: "ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: Renderer ? /* @__PURE__ */ jsx20(Renderer, { toolCall, sessionId: resolvedSessionId }) : /* @__PURE__ */ jsxs16(Fragment5, { children: [
5593
+ /* @__PURE__ */ jsx20("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
5594
+ /* @__PURE__ */ jsx20("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatArgs(toolCall.arguments) }),
5595
+ toolCall.result != null && /* @__PURE__ */ jsxs16(Fragment5, { children: [
5596
+ /* @__PURE__ */ jsx20("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
5597
+ /* @__PURE__ */ jsx20(
5445
5598
  "pre",
5446
5599
  {
5447
5600
  className: cn(
@@ -5517,7 +5670,7 @@ function buildAskUserPayload(argumentsJson) {
5517
5670
  }
5518
5671
 
5519
5672
  // src/react/components/chat/UserMessageBubble.tsx
5520
- import { useState as useState14 } from "react";
5673
+ import { useState as useState15 } from "react";
5521
5674
 
5522
5675
  // src/react/lib/preview-dispatch.ts
5523
5676
  var IMAGE_EXTS = [
@@ -5662,7 +5815,7 @@ import { Download as Download3, X as X5 } from "lucide-react";
5662
5815
  import { useEffect as useEffect12 } from "react";
5663
5816
  import { createPortal as createPortal4 } from "react-dom";
5664
5817
  import { useQuery as useQuery6 } from "@tanstack/react-query";
5665
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5818
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5666
5819
  function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5667
5820
  useEffect12(() => {
5668
5821
  if (!open) return;
@@ -5690,7 +5843,7 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5690
5843
  staleTime: 6e4
5691
5844
  });
5692
5845
  if (!open) return null;
5693
- const body = /* @__PURE__ */ jsx20(
5846
+ const body = /* @__PURE__ */ jsx21(
5694
5847
  "div",
5695
5848
  {
5696
5849
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",
@@ -5701,17 +5854,17 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5701
5854
  role: "dialog",
5702
5855
  "aria-modal": "true",
5703
5856
  "aria-labelledby": "attachment-preview-title",
5704
- children: /* @__PURE__ */ jsxs16(
5857
+ children: /* @__PURE__ */ jsxs17(
5705
5858
  "div",
5706
5859
  {
5707
5860
  className: "max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl",
5708
5861
  onClick: (e) => e.stopPropagation(),
5709
5862
  onKeyDown: (e) => e.stopPropagation(),
5710
5863
  children: [
5711
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
5712
- /* @__PURE__ */ jsx20("h3", { id: "attachment-preview-title", className: "truncate text-sm font-semibold text-[hsl(var(--foreground))]", children: filename }),
5713
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
5714
- url && /* @__PURE__ */ jsx20(
5864
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3", children: [
5865
+ /* @__PURE__ */ jsx21("h3", { id: "attachment-preview-title", className: "truncate text-sm font-semibold text-[hsl(var(--foreground))]", children: filename }),
5866
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
5867
+ url && /* @__PURE__ */ jsx21(
5715
5868
  "a",
5716
5869
  {
5717
5870
  href: url,
@@ -5720,22 +5873,22 @@ function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }) {
5720
5873
  rel: "noopener noreferrer",
5721
5874
  title: "\u4E0B\u8F7D",
5722
5875
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
5723
- children: /* @__PURE__ */ jsx20(Download3, { size: 14 })
5876
+ children: /* @__PURE__ */ jsx21(Download3, { size: 14 })
5724
5877
  }
5725
5878
  ),
5726
- /* @__PURE__ */ jsx20(
5879
+ /* @__PURE__ */ jsx21(
5727
5880
  "button",
5728
5881
  {
5729
5882
  type: "button",
5730
5883
  onClick: () => onOpenChange(false),
5731
5884
  title: "\u5173\u95ED",
5732
5885
  className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
5733
- children: /* @__PURE__ */ jsx20(X5, { size: 14 })
5886
+ children: /* @__PURE__ */ jsx21(X5, { size: 14 })
5734
5887
  }
5735
5888
  )
5736
5889
  ] })
5737
5890
  ] }),
5738
- /* @__PURE__ */ jsx20("div", { className: "max-h-[calc(90vh-56px)] overflow-auto px-4 py-3 text-sm text-[hsl(var(--foreground))]", children: renderContent({ mode, url, content, error }) })
5891
+ /* @__PURE__ */ jsx21("div", { className: "max-h-[calc(90vh-56px)] overflow-auto px-4 py-3 text-sm text-[hsl(var(--foreground))]", children: renderContent({ mode, url, content, error }) })
5739
5892
  ]
5740
5893
  }
5741
5894
  )
@@ -5750,43 +5903,43 @@ function renderContent({
5750
5903
  error
5751
5904
  }) {
5752
5905
  if (!url) {
5753
- return /* @__PURE__ */ jsx20("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B64\u9644\u4EF6\u6682\u65E0\u53EF\u7528\u9884\u89C8\u5730\u5740\u3002" });
5906
+ return /* @__PURE__ */ jsx21("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B64\u9644\u4EF6\u6682\u65E0\u53EF\u7528\u9884\u89C8\u5730\u5740\u3002" });
5754
5907
  }
5755
5908
  if (mode === "default") {
5756
- return /* @__PURE__ */ jsxs16("p", { className: "text-[hsl(var(--muted-foreground))]", children: [
5909
+ return /* @__PURE__ */ jsxs17("p", { className: "text-[hsl(var(--muted-foreground))]", children: [
5757
5910
  "\u6B64\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u5185\u5D4C\u9884\u89C8\u3002\u8BF7\u70B9\u51FB\u53F3\u4E0A\u89D2",
5758
- /* @__PURE__ */ jsx20("span", { className: "mx-1 font-medium text-[hsl(var(--foreground))]", children: "\u4E0B\u8F7D" }),
5911
+ /* @__PURE__ */ jsx21("span", { className: "mx-1 font-medium text-[hsl(var(--foreground))]", children: "\u4E0B\u8F7D" }),
5759
5912
  "\u6309\u94AE\u67E5\u770B\u3002"
5760
5913
  ] });
5761
5914
  }
5762
5915
  if (error) {
5763
- return /* @__PURE__ */ jsxs16("p", { className: "text-[hsl(var(--destructive))]", children: [
5916
+ return /* @__PURE__ */ jsxs17("p", { className: "text-[hsl(var(--destructive))]", children: [
5764
5917
  "\u52A0\u8F7D\u5931\u8D25\uFF1A",
5765
5918
  String(error?.message ?? error)
5766
5919
  ] });
5767
5920
  }
5768
5921
  if (content == null) {
5769
- return /* @__PURE__ */ jsx20("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u4E2D\u2026" });
5922
+ return /* @__PURE__ */ jsx21("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u52A0\u8F7D\u4E2D\u2026" });
5770
5923
  }
5771
5924
  if (mode === "markdown") {
5772
- return /* @__PURE__ */ jsx20(MarkdownContent, { className: "prose prose-sm prose-invert max-w-none", children: content });
5925
+ return /* @__PURE__ */ jsx21(MarkdownContent, { className: "prose prose-sm prose-invert max-w-none", children: content });
5773
5926
  }
5774
- return /* @__PURE__ */ jsx20("pre", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed", children: content });
5927
+ return /* @__PURE__ */ jsx21("pre", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed", children: content });
5775
5928
  }
5776
5929
 
5777
5930
  // src/react/components/chat/MessageContextPills.tsx
5778
5931
  import { Bookmark } from "lucide-react";
5779
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5932
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
5780
5933
  function MessageContextPills({ contexts }) {
5781
5934
  if (contexts.length === 0) return null;
5782
- return /* @__PURE__ */ jsx21("div", { className: "flex flex-wrap gap-1.5", children: contexts.map((ctx, index) => /* @__PURE__ */ jsxs17(
5935
+ return /* @__PURE__ */ jsx22("div", { className: "flex flex-wrap gap-1.5", children: contexts.map((ctx, index) => /* @__PURE__ */ jsxs18(
5783
5936
  "div",
5784
5937
  {
5785
5938
  className: "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--primary)/0.25)] bg-[hsl(var(--primary)/0.1)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary)/0.85)]",
5786
5939
  title: ctx.content,
5787
5940
  children: [
5788
- /* @__PURE__ */ jsx21(Bookmark, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.65)]" }),
5789
- /* @__PURE__ */ jsx21("span", { className: "max-w-56 truncate", children: ctx.label })
5941
+ /* @__PURE__ */ jsx22(Bookmark, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.65)]" }),
5942
+ /* @__PURE__ */ jsx22("span", { className: "max-w-56 truncate", children: ctx.label })
5790
5943
  ]
5791
5944
  },
5792
5945
  `${ctx.label}:${index}`
@@ -5794,8 +5947,8 @@ function MessageContextPills({ contexts }) {
5794
5947
  }
5795
5948
 
5796
5949
  // src/react/components/chat/MessageFileAttachmentList.tsx
5797
- import { Archive as Archive2, File as File3, FileCode2 as FileCode22, FileText as FileText3, Film as Film2, Music as Music2 } from "lucide-react";
5798
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
5950
+ import { Archive as Archive2, File as File3, FileCode2 as FileCode22, FileText as FileText4, Film as Film2, Music as Music2 } from "lucide-react";
5951
+ import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
5799
5952
  function getFileIcon(fileName) {
5800
5953
  const lowerName = fileName.toLowerCase();
5801
5954
  if (/\.(zip|rar|7z|tar|gz|bz2|xz)$/.test(lowerName)) {
@@ -5811,7 +5964,7 @@ function getFileIcon(fileName) {
5811
5964
  return Film2;
5812
5965
  }
5813
5966
  if (/\.(txt|pdf|doc|docx|rtf|odt)$/.test(lowerName)) {
5814
- return FileText3;
5967
+ return FileText4;
5815
5968
  }
5816
5969
  return File3;
5817
5970
  }
@@ -5824,15 +5977,15 @@ function MessageFileAttachmentList({
5824
5977
  return null;
5825
5978
  }
5826
5979
  const pillClass = "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]";
5827
- return /* @__PURE__ */ jsx22("div", { className: cn("flex flex-wrap gap-1.5", className), children: files.map((file) => {
5980
+ return /* @__PURE__ */ jsx23("div", { className: cn("flex flex-wrap gap-1.5", className), children: files.map((file) => {
5828
5981
  const Icon = getFileIcon(file.name);
5829
5982
  const key = `${file.name}-${file.data.slice(0, 32)}`;
5830
- const content = /* @__PURE__ */ jsxs18(Fragment5, { children: [
5831
- /* @__PURE__ */ jsx22(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5832
- /* @__PURE__ */ jsx22("span", { className: "max-w-32 truncate", children: file.name })
5983
+ const content = /* @__PURE__ */ jsxs19(Fragment6, { children: [
5984
+ /* @__PURE__ */ jsx23(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]" }),
5985
+ /* @__PURE__ */ jsx23("span", { className: "max-w-32 truncate", children: file.name })
5833
5986
  ] });
5834
5987
  if (onPreview) {
5835
- return /* @__PURE__ */ jsx22(
5988
+ return /* @__PURE__ */ jsx23(
5836
5989
  "button",
5837
5990
  {
5838
5991
  type: "button",
@@ -5844,16 +5997,16 @@ function MessageFileAttachmentList({
5844
5997
  key
5845
5998
  );
5846
5999
  }
5847
- return /* @__PURE__ */ jsx22("div", { className: pillClass, title: file.name, children: content }, key);
6000
+ return /* @__PURE__ */ jsx23("div", { className: pillClass, title: file.name, children: content }, key);
5848
6001
  }) });
5849
6002
  }
5850
6003
 
5851
6004
  // src/react/components/chat/MessageActions.tsx
5852
6005
  import { Check as Check2, Copy } from "lucide-react";
5853
- import { useState as useState13 } from "react";
5854
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
6006
+ import { useState as useState14 } from "react";
6007
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5855
6008
  function MessageActions({ content, className }) {
5856
- const [copied, setCopied] = useState13(false);
6009
+ const [copied, setCopied] = useState14(false);
5857
6010
  const handleCopy = async () => {
5858
6011
  const ok = await copyToClipboard(content);
5859
6012
  if (ok) {
@@ -5861,7 +6014,7 @@ function MessageActions({ content, className }) {
5861
6014
  setTimeout(() => setCopied(false), 2e3);
5862
6015
  }
5863
6016
  };
5864
- return /* @__PURE__ */ jsx23("div", { className: cn("flex items-center gap-1 mt-1.5", className), children: /* @__PURE__ */ jsxs19(
6017
+ return /* @__PURE__ */ jsx24("div", { className: cn("flex items-center gap-1 mt-1.5", className), children: /* @__PURE__ */ jsxs20(
5865
6018
  "button",
5866
6019
  {
5867
6020
  type: "button",
@@ -5871,16 +6024,16 @@ function MessageActions({ content, className }) {
5871
6024
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]"
5872
6025
  ),
5873
6026
  children: [
5874
- copied ? /* @__PURE__ */ jsx23(Check2, { size: 12 }) : /* @__PURE__ */ jsx23(Copy, { size: 12 }),
5875
- /* @__PURE__ */ jsx23("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
6027
+ copied ? /* @__PURE__ */ jsx24(Check2, { size: 12 }) : /* @__PURE__ */ jsx24(Copy, { size: 12 }),
6028
+ /* @__PURE__ */ jsx24("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
5876
6029
  ]
5877
6030
  }
5878
6031
  ) });
5879
6032
  }
5880
6033
 
5881
6034
  // src/react/components/chat/TextAttachmentPills.tsx
5882
- import { Archive as Archive3, File as File4, FileCode2 as FileCode23, FileText as FileText4, Film as Film3, Music as Music3, FileSpreadsheet, Image } from "lucide-react";
5883
- import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
6035
+ import { Archive as Archive3, File as File4, FileCode2 as FileCode23, FileText as FileText5, Film as Film3, Music as Music3, FileSpreadsheet, Image } from "lucide-react";
6036
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
5884
6037
  function getFileIcon2(fileName) {
5885
6038
  const lower2 = fileName.toLowerCase();
5886
6039
  if (/\.(zip|rar|7z|tar|gz)$/.test(lower2)) return Archive3;
@@ -5889,21 +6042,21 @@ function getFileIcon2(fileName) {
5889
6042
  if (/\.(mp4|mov|mkv|avi|webm)$/.test(lower2)) return Film3;
5890
6043
  if (/\.(png|jpg|jpeg|gif|svg|webp|bmp)$/.test(lower2)) return Image;
5891
6044
  if (/\.(xlsx?|csv)$/.test(lower2)) return FileSpreadsheet;
5892
- if (/\.(txt|pdf|docx?|rtf|md)$/.test(lower2)) return FileText4;
6045
+ if (/\.(txt|pdf|docx?|rtf|md)$/.test(lower2)) return FileText5;
5893
6046
  return File4;
5894
6047
  }
5895
6048
  function TextAttachmentPills({ attachments, onPreview }) {
5896
6049
  if (attachments.length === 0) return null;
5897
6050
  const pillClass = "flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--primary)/0.08)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary)/0.8)]";
5898
- return /* @__PURE__ */ jsx24("div", { className: "flex flex-wrap gap-1.5", children: attachments.map((att, index) => {
6051
+ return /* @__PURE__ */ jsx25("div", { className: "flex flex-wrap gap-1.5", children: attachments.map((att, index) => {
5899
6052
  const Icon = getFileIcon2(att.name);
5900
6053
  const key = `${att.uploadedPath ?? att.name}:${att.name}:${index}`;
5901
- const content = /* @__PURE__ */ jsxs20(Fragment6, { children: [
5902
- /* @__PURE__ */ jsx24(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.6)]" }),
5903
- /* @__PURE__ */ jsx24("span", { className: "max-w-40 truncate", children: att.name })
6054
+ const content = /* @__PURE__ */ jsxs21(Fragment7, { children: [
6055
+ /* @__PURE__ */ jsx25(Icon, { size: 12, className: "shrink-0 text-[hsl(var(--primary)/0.6)]" }),
6056
+ /* @__PURE__ */ jsx25("span", { className: "max-w-40 truncate", children: att.name })
5904
6057
  ] });
5905
6058
  if (onPreview) {
5906
- return /* @__PURE__ */ jsx24(
6059
+ return /* @__PURE__ */ jsx25(
5907
6060
  "button",
5908
6061
  {
5909
6062
  type: "button",
@@ -5915,7 +6068,7 @@ function TextAttachmentPills({ attachments, onPreview }) {
5915
6068
  key
5916
6069
  );
5917
6070
  }
5918
- return /* @__PURE__ */ jsx24("div", { className: pillClass, title: att.name, children: content }, key);
6071
+ return /* @__PURE__ */ jsx25("div", { className: pillClass, title: att.name, children: content }, key);
5919
6072
  }) });
5920
6073
  }
5921
6074
 
@@ -5924,34 +6077,34 @@ import { RefreshCcw } from "lucide-react";
5924
6077
 
5925
6078
  // src/react/components/chat/whatif-quote-context.tsx
5926
6079
  import { createContext as createContext3, useContext as useContext3, useMemo as useMemo13 } from "react";
5927
- import { jsx as jsx25 } from "react/jsx-runtime";
6080
+ import { jsx as jsx26 } from "react/jsx-runtime";
5928
6081
  var WhatIfQuoteContext = createContext3({});
5929
6082
  function WhatIfQuoteProvider({
5930
6083
  onJumpToStep,
5931
6084
  children
5932
6085
  }) {
5933
6086
  const value = useMemo13(() => ({ onJumpToStep }), [onJumpToStep]);
5934
- return /* @__PURE__ */ jsx25(WhatIfQuoteContext.Provider, { value, children });
6087
+ return /* @__PURE__ */ jsx26(WhatIfQuoteContext.Provider, { value, children });
5935
6088
  }
5936
6089
  function useWhatIfQuoteContext() {
5937
6090
  return useContext3(WhatIfQuoteContext);
5938
6091
  }
5939
6092
 
5940
6093
  // src/react/components/chat/WhatIfUserBubble.tsx
5941
- import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
6094
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
5942
6095
  function WhatIfUserBubble({ parsed, onQuoteClick }) {
5943
6096
  const { onJumpToStep } = useWhatIfQuoteContext();
5944
6097
  const handleQuoteClick = onQuoteClick ?? onJumpToStep;
5945
6098
  const { fromStep, quotes, userText } = parsed;
5946
- return /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-end gap-2", children: [
5947
- /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
5948
- /* @__PURE__ */ jsx26(RefreshCcw, { size: 10 }),
5949
- /* @__PURE__ */ jsx26("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
6099
+ return /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-end gap-2", children: [
6100
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: [
6101
+ /* @__PURE__ */ jsx27(RefreshCcw, { size: 10 }),
6102
+ /* @__PURE__ */ jsx27("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
5950
6103
  ] }),
5951
- quotes.length > 0 && /* @__PURE__ */ jsx26("div", { className: "flex flex-wrap justify-end gap-1.5", children: quotes.map((q, i) => {
6104
+ quotes.length > 0 && /* @__PURE__ */ jsx27("div", { className: "flex flex-wrap justify-end gap-1.5", children: quotes.map((q, i) => {
5952
6105
  const clickable = q.stepNumber != null && !!handleQuoteClick;
5953
6106
  const label = q.stepNumber != null ? `\u6B65\u9AA4${q.stepNumber} \xB7 ${q.label}` : q.label;
5954
- return /* @__PURE__ */ jsxs21(
6107
+ return /* @__PURE__ */ jsxs22(
5955
6108
  "button",
5956
6109
  {
5957
6110
  type: "button",
@@ -5960,14 +6113,14 @@ function WhatIfUserBubble({ parsed, onQuoteClick }) {
5960
6113
  className: "inline-flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-0.5 text-[11px] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring)/0.5)] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] disabled:cursor-default disabled:hover:border-[hsl(var(--border))] disabled:hover:bg-[hsl(var(--card))]",
5961
6114
  title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0,
5962
6115
  children: [
5963
- /* @__PURE__ */ jsx26("span", { children: "\u21B3" }),
5964
- /* @__PURE__ */ jsx26("span", { className: "max-w-[14rem] truncate", children: label })
6116
+ /* @__PURE__ */ jsx27("span", { children: "\u21B3" }),
6117
+ /* @__PURE__ */ jsx27("span", { className: "max-w-[14rem] truncate", children: label })
5965
6118
  ]
5966
6119
  },
5967
6120
  `${q.stepNumber ?? "x"}-${i}`
5968
6121
  );
5969
6122
  }) }),
5970
- userText && /* @__PURE__ */ jsx26("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx26(
6123
+ userText && /* @__PURE__ */ jsx27("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx27(
5971
6124
  MarkdownContent,
5972
6125
  {
5973
6126
  className: "prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0",
@@ -5979,7 +6132,7 @@ function WhatIfUserBubble({ parsed, onQuoteClick }) {
5979
6132
  }
5980
6133
 
5981
6134
  // src/react/components/chat/UserMessageBubble.tsx
5982
- import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
6135
+ import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
5983
6136
  function isUserMessage(message) {
5984
6137
  return message.role === "user";
5985
6138
  }
@@ -6007,9 +6160,9 @@ function UserMessageBubble({ message, className }) {
6007
6160
  const trimmedClean = cleanText.trim();
6008
6161
  const whatifParsed = trimmedClean && imageParts.length === 0 && fileParts.length === 0 && textAttachments.length === 0 ? parseWhatIfPrompt(cleanText) : null;
6009
6162
  if (whatifParsed) {
6010
- return /* @__PURE__ */ jsx27("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs22("div", { className: "group flex max-w-[72%] flex-col items-end gap-2", children: [
6011
- /* @__PURE__ */ jsx27(WhatIfUserBubble, { parsed: whatifParsed }),
6012
- whatifParsed.userText && /* @__PURE__ */ jsx27(
6163
+ return /* @__PURE__ */ jsx28("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs23("div", { className: "group flex max-w-[72%] flex-col items-end gap-2", children: [
6164
+ /* @__PURE__ */ jsx28(WhatIfUserBubble, { parsed: whatifParsed }),
6165
+ whatifParsed.userText && /* @__PURE__ */ jsx28(
6013
6166
  MessageActions,
6014
6167
  {
6015
6168
  content: whatifParsed.userText,
@@ -6043,8 +6196,8 @@ function UserMessageBubble({ message, className }) {
6043
6196
  alt: attachment.name || "\u7528\u6237\u4E0A\u4F20\u7684\u56FE\u7247"
6044
6197
  }))
6045
6198
  ];
6046
- const [lightboxIndex, setLightboxIndex] = useState14(null);
6047
- const [preview, setPreview] = useState14(null);
6199
+ const [lightboxIndex, setLightboxIndex] = useState15(null);
6200
+ const [preview, setPreview] = useState15(null);
6048
6201
  const handleTextAttachmentPreview = (attachment) => {
6049
6202
  if (!activeSessionId) return;
6050
6203
  const pathForUrl = attachment.uploadedPath ?? attachment.name;
@@ -6063,16 +6216,16 @@ function UserMessageBubble({ message, className }) {
6063
6216
  const mode = kind === "text" ? lower2.endsWith(".md") ? "markdown" : "text" : "default";
6064
6217
  setPreview({ filename: attachment.name, url, mode });
6065
6218
  };
6066
- return /* @__PURE__ */ jsx27("div", { className: cn("flex justify-end", className), children: /* @__PURE__ */ jsxs22("div", { className: "group flex max-w-[72%] flex-col items-end gap-3", children: [
6067
- (imageParts.length > 0 || imageTextAttachments.length > 0) && /* @__PURE__ */ jsxs22("div", { className: "grid gap-2", children: [
6068
- imageParts.map((part, idx) => /* @__PURE__ */ jsx27(
6219
+ return /* @__PURE__ */ jsx28("div", { className: cn("flex justify-end", className), children: /* @__PURE__ */ jsxs23("div", { className: "group flex max-w-[72%] flex-col items-end gap-3", children: [
6220
+ (imageParts.length > 0 || imageTextAttachments.length > 0) && /* @__PURE__ */ jsxs23("div", { className: "grid gap-2", children: [
6221
+ imageParts.map((part, idx) => /* @__PURE__ */ jsx28(
6069
6222
  "button",
6070
6223
  {
6071
6224
  type: "button",
6072
6225
  onClick: () => setLightboxIndex(idx),
6073
6226
  className: "cursor-zoom-in",
6074
6227
  title: "\u67E5\u770B\u5927\u56FE",
6075
- children: /* @__PURE__ */ jsx27(
6228
+ children: /* @__PURE__ */ jsx28(
6076
6229
  "img",
6077
6230
  {
6078
6231
  src: part.image_url.url,
@@ -6083,14 +6236,14 @@ function UserMessageBubble({ message, className }) {
6083
6236
  },
6084
6237
  part.image_url.url
6085
6238
  )),
6086
- imageTextAttachments.map((attachment, idx) => /* @__PURE__ */ jsx27(
6239
+ imageTextAttachments.map((attachment, idx) => /* @__PURE__ */ jsx28(
6087
6240
  "button",
6088
6241
  {
6089
6242
  type: "button",
6090
6243
  onClick: () => setLightboxIndex(imageParts.length + idx),
6091
6244
  className: "cursor-zoom-in",
6092
6245
  title: "\u67E5\u770B\u5927\u56FE",
6093
- children: /* @__PURE__ */ jsx27(
6246
+ children: /* @__PURE__ */ jsx28(
6094
6247
  "img",
6095
6248
  {
6096
6249
  src: attachment.url,
@@ -6102,7 +6255,7 @@ function UserMessageBubble({ message, className }) {
6102
6255
  `${attachment.uploadedPath}:${attachment.name}`
6103
6256
  ))
6104
6257
  ] }),
6105
- lightboxImages.length > 0 && /* @__PURE__ */ jsx27(
6258
+ lightboxImages.length > 0 && /* @__PURE__ */ jsx28(
6106
6259
  ImageLightbox,
6107
6260
  {
6108
6261
  open: lightboxIndex != null,
@@ -6113,15 +6266,15 @@ function UserMessageBubble({ message, className }) {
6113
6266
  initialIndex: lightboxIndex ?? 0
6114
6267
  }
6115
6268
  ),
6116
- /* @__PURE__ */ jsx27(MessageFileAttachmentList, { files: fileParts }),
6117
- /* @__PURE__ */ jsx27(
6269
+ /* @__PURE__ */ jsx28(MessageFileAttachmentList, { files: fileParts }),
6270
+ /* @__PURE__ */ jsx28(
6118
6271
  TextAttachmentPills,
6119
6272
  {
6120
6273
  attachments: nonImageTextAttachments,
6121
6274
  onPreview: handleTextAttachmentPreview
6122
6275
  }
6123
6276
  ),
6124
- preview && /* @__PURE__ */ jsx27(
6277
+ preview && /* @__PURE__ */ jsx28(
6125
6278
  AttachmentPreviewDialog,
6126
6279
  {
6127
6280
  open: preview != null,
@@ -6133,8 +6286,8 @@ function UserMessageBubble({ message, className }) {
6133
6286
  mode: preview.mode
6134
6287
  }
6135
6288
  ),
6136
- /* @__PURE__ */ jsx27(MessageContextPills, { contexts: textContexts }),
6137
- trimmedClean && /* @__PURE__ */ jsx27("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx27(
6289
+ /* @__PURE__ */ jsx28(MessageContextPills, { contexts: textContexts }),
6290
+ trimmedClean && /* @__PURE__ */ jsx28("div", { className: "rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: /* @__PURE__ */ jsx28(
6138
6291
  MarkdownContent,
6139
6292
  {
6140
6293
  className: "prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0",
@@ -6142,7 +6295,7 @@ function UserMessageBubble({ message, className }) {
6142
6295
  children: cleanText
6143
6296
  }
6144
6297
  ) }),
6145
- trimmedClean && /* @__PURE__ */ jsx27(
6298
+ trimmedClean && /* @__PURE__ */ jsx28(
6146
6299
  MessageActions,
6147
6300
  {
6148
6301
  content: trimmedClean,
@@ -6157,14 +6310,14 @@ function ErrorMessageBlock({
6157
6310
  }) {
6158
6311
  const text = getTextContent(message.content);
6159
6312
  const looksLikeModelUnavailable = /no source matches this model|404/i.test(text);
6160
- return /* @__PURE__ */ jsx27("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsxs22("div", { className: "max-w-[85%] border-l-[3px] border-[hsl(var(--destructive))] px-4 py-1 text-sm leading-7 text-[hsl(var(--destructive))]", children: [
6313
+ return /* @__PURE__ */ jsx28("div", { className: cn("flex justify-center", className), children: /* @__PURE__ */ jsxs23("div", { className: "max-w-[85%] border-l-[3px] border-[hsl(var(--destructive))] px-4 py-1 text-sm leading-7 text-[hsl(var(--destructive))]", children: [
6161
6314
  text,
6162
- looksLikeModelUnavailable ? /* @__PURE__ */ jsx27("div", { className: "mt-1 opacity-80", children: "\u6A21\u578B\u53EF\u80FD\u672A\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" }) : null
6315
+ looksLikeModelUnavailable ? /* @__PURE__ */ jsx28("div", { className: "mt-1 opacity-80", children: "\u6A21\u578B\u53EF\u80FD\u672A\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" }) : null
6163
6316
  ] }) });
6164
6317
  }
6165
6318
 
6166
6319
  // src/react/components/chat/AgentLoopBlock.tsx
6167
- import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
6320
+ import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
6168
6321
  var EMPTY_MESSAGES2 = [];
6169
6322
  var EMPTY_AGENT_LOOPS = {};
6170
6323
  var COLLAPSED_SUMMARY_HIDDEN_TOOLS = /* @__PURE__ */ new Set([
@@ -6211,7 +6364,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6211
6364
  () => visibleLoopToolCalls.some((childToolCall) => childToolCall.status === "awaiting_answer"),
6212
6365
  [visibleLoopToolCalls]
6213
6366
  );
6214
- const [expanded, setExpanded] = useState15(hasAwaitingAnswer);
6367
+ const [expanded, setExpanded] = useState16(hasAwaitingAnswer);
6215
6368
  const completedToolLabels = useMemo14(
6216
6369
  () => visibleLoopToolCalls.flatMap((childToolCall) => {
6217
6370
  const isCompleted = childToolCall.status === "done" || childToolCall.status !== "pending" && childToolCall.status !== "awaiting_answer" && childToolCall.status !== "error" && childToolCall.status !== "cancelled";
@@ -6257,7 +6410,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6257
6410
  const description = safeParseDescription(toolCall.arguments);
6258
6411
  const status = hasAwaitingAnswer || toolCall.status === "awaiting_answer" ? "awaiting_answer" : toolCall.status === "pending" || loopEntry?.info.status === "running" ? "running" : "done";
6259
6412
  const cardStyles = getLoopCardStyles(status);
6260
- return /* @__PURE__ */ jsxs23(
6413
+ return /* @__PURE__ */ jsxs24(
6261
6414
  "div",
6262
6415
  {
6263
6416
  className: cn(
@@ -6265,8 +6418,8 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6265
6418
  cardStyles.borderClass
6266
6419
  ),
6267
6420
  children: [
6268
- status === "running" || status === "awaiting_answer" ? /* @__PURE__ */ jsxs23(Fragment7, { children: [
6269
- /* @__PURE__ */ jsxs23(
6421
+ status === "running" || status === "awaiting_answer" ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
6422
+ /* @__PURE__ */ jsxs24(
6270
6423
  "div",
6271
6424
  {
6272
6425
  className: cn(
@@ -6274,24 +6427,24 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6274
6427
  cardStyles.headerClass
6275
6428
  ),
6276
6429
  children: [
6277
- /* @__PURE__ */ jsx28(
6430
+ /* @__PURE__ */ jsx29(
6278
6431
  "button",
6279
6432
  {
6280
6433
  type: "button",
6281
6434
  onClick: toggleExpanded,
6282
6435
  "aria-expanded": expanded,
6283
6436
  className: "flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6284
- children: /* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex items-center gap-2", children: [
6285
- status === "awaiting_answer" ? /* @__PURE__ */ jsx28(MessageSquareMore2, { size: 14, className: "shrink-0 text-amber-500" }) : /* @__PURE__ */ jsx28(Bot, { size: 14, className: "shrink-0 text-blue-500" }),
6286
- /* @__PURE__ */ jsxs23("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: [
6437
+ children: /* @__PURE__ */ jsxs24("span", { className: "min-w-0 flex items-center gap-2", children: [
6438
+ status === "awaiting_answer" ? /* @__PURE__ */ jsx29(MessageSquareMore2, { size: 14, className: "shrink-0 text-amber-500" }) : /* @__PURE__ */ jsx29(Bot, { size: 14, className: "shrink-0 text-blue-500" }),
6439
+ /* @__PURE__ */ jsxs24("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: [
6287
6440
  description,
6288
6441
  status === "awaiting_answer" ? " \u2014 \u7B49\u5F85\u56DE\u7B54" : ""
6289
6442
  ] })
6290
6443
  ] })
6291
6444
  }
6292
6445
  ),
6293
- reasoning ? /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning, variant: "block" }) : null,
6294
- /* @__PURE__ */ jsx28(
6446
+ reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null,
6447
+ /* @__PURE__ */ jsx29(
6295
6448
  Bot,
6296
6449
  {
6297
6450
  size: 13,
@@ -6299,14 +6452,14 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6299
6452
  "aria-label": "\u5B50\u667A\u80FD\u4F53"
6300
6453
  }
6301
6454
  ),
6302
- /* @__PURE__ */ jsx28(
6455
+ /* @__PURE__ */ jsx29(
6303
6456
  "button",
6304
6457
  {
6305
6458
  type: "button",
6306
6459
  onClick: toggleExpanded,
6307
6460
  "aria-expanded": expanded,
6308
6461
  className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6309
- children: /* @__PURE__ */ jsx28(
6462
+ children: /* @__PURE__ */ jsx29(
6310
6463
  ChevronRight4,
6311
6464
  {
6312
6465
  size: 14,
@@ -6321,7 +6474,7 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6321
6474
  ]
6322
6475
  }
6323
6476
  ),
6324
- !expanded ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-1 py-2", children: visibleLoopToolCalls.length > 0 ? visibleLoopToolCalls.map((childToolCall) => /* @__PURE__ */ jsx28(
6477
+ !expanded ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-1 py-2", children: visibleLoopToolCalls.length > 0 ? visibleLoopToolCalls.map((childToolCall) => /* @__PURE__ */ jsx29(
6325
6478
  ToolCallBlock,
6326
6479
  {
6327
6480
  toolCall: childToolCall,
@@ -6329,12 +6482,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6329
6482
  level: 2
6330
6483
  },
6331
6484
  childToolCall.id
6332
- )) : /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
6333
- /* @__PURE__ */ jsx28(Loader24, { size: 12, className: "shrink-0 animate-spin text-blue-500" }),
6334
- /* @__PURE__ */ jsx28("span", { children: "\u6B63\u5728\u542F\u52A8..." })
6335
- ] }) }) : status === "awaiting_answer" ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-1 py-2", children: /* @__PURE__ */ jsx28("div", { className: "px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u8BF7\u5728\u4E0B\u65B9\u5B50\u667A\u80FD\u4F53\u5BF9\u8BDD\u4E2D\u5B8C\u6210\u786E\u8BA4" }) }) : null
6336
- ] }) : /* @__PURE__ */ jsxs23(Fragment7, { children: [
6337
- /* @__PURE__ */ jsxs23(
6485
+ )) : /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
6486
+ /* @__PURE__ */ jsx29(Loader24, { size: 12, className: "shrink-0 animate-spin text-blue-500" }),
6487
+ /* @__PURE__ */ jsx29("span", { children: "\u6B63\u5728\u542F\u52A8..." })
6488
+ ] }) }) : status === "awaiting_answer" ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-1 py-2", children: /* @__PURE__ */ jsx29("div", { className: "px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u8BF7\u5728\u4E0B\u65B9\u5B50\u667A\u80FD\u4F53\u5BF9\u8BDD\u4E2D\u5B8C\u6210\u786E\u8BA4" }) }) : null
6489
+ ] }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
6490
+ /* @__PURE__ */ jsxs24(
6338
6491
  "div",
6339
6492
  {
6340
6493
  className: cn(
@@ -6342,21 +6495,21 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6342
6495
  cardStyles.headerClass
6343
6496
  ),
6344
6497
  children: [
6345
- /* @__PURE__ */ jsx28(
6498
+ /* @__PURE__ */ jsx29(
6346
6499
  "button",
6347
6500
  {
6348
6501
  type: "button",
6349
6502
  onClick: toggleExpanded,
6350
6503
  "aria-expanded": expanded,
6351
6504
  className: "flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6352
- children: /* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex items-center gap-2", children: [
6353
- /* @__PURE__ */ jsx28(Check3, { size: 14, className: "shrink-0 text-emerald-500" }),
6354
- /* @__PURE__ */ jsx28("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: description })
6505
+ children: /* @__PURE__ */ jsxs24("span", { className: "min-w-0 flex items-center gap-2", children: [
6506
+ /* @__PURE__ */ jsx29(Check3, { size: 14, className: "shrink-0 text-emerald-500" }),
6507
+ /* @__PURE__ */ jsx29("span", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: description })
6355
6508
  ] })
6356
6509
  }
6357
6510
  ),
6358
- reasoning ? /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning, variant: "block" }) : null,
6359
- /* @__PURE__ */ jsx28(
6511
+ reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null,
6512
+ /* @__PURE__ */ jsx29(
6360
6513
  Bot,
6361
6514
  {
6362
6515
  size: 13,
@@ -6364,14 +6517,14 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6364
6517
  "aria-label": "\u5B50\u667A\u80FD\u4F53"
6365
6518
  }
6366
6519
  ),
6367
- /* @__PURE__ */ jsx28(
6520
+ /* @__PURE__ */ jsx29(
6368
6521
  "button",
6369
6522
  {
6370
6523
  type: "button",
6371
6524
  onClick: toggleExpanded,
6372
6525
  "aria-expanded": expanded,
6373
6526
  className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6374
- children: /* @__PURE__ */ jsx28(
6527
+ children: /* @__PURE__ */ jsx29(
6375
6528
  ChevronRight4,
6376
6529
  {
6377
6530
  size: 14,
@@ -6386,9 +6539,9 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6386
6539
  ]
6387
6540
  }
6388
6541
  ),
6389
- !expanded ? /* @__PURE__ */ jsxs23(Fragment7, { children: [
6390
- /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1.5 px-4 py-2", children: completedToolLabels.length > 0 ? completedToolLabels.map(
6391
- (item) => item.kind === "file" ? /* @__PURE__ */ jsxs23(
6542
+ !expanded ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
6543
+ /* @__PURE__ */ jsx29("div", { className: "flex flex-wrap gap-1.5 px-4 py-2", children: completedToolLabels.length > 0 ? completedToolLabels.map(
6544
+ (item) => item.kind === "file" ? /* @__PURE__ */ jsxs24(
6392
6545
  "span",
6393
6546
  {
6394
6547
  className: "inline-flex min-w-0 items-center gap-1 rounded-md border px-2 py-0.5 text-xs font-semibold dark:border-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-300",
@@ -6399,12 +6552,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6399
6552
  },
6400
6553
  title: item.label,
6401
6554
  children: [
6402
- /* @__PURE__ */ jsx28(FileText5, { size: 12, className: "shrink-0", "aria-hidden": "true" }),
6403
- /* @__PURE__ */ jsx28("span", { className: "truncate", children: item.label })
6555
+ /* @__PURE__ */ jsx29(FileText6, { size: 12, className: "shrink-0", "aria-hidden": "true" }),
6556
+ /* @__PURE__ */ jsx29("span", { className: "truncate", children: item.label })
6404
6557
  ]
6405
6558
  },
6406
6559
  item.key
6407
- ) : /* @__PURE__ */ jsx28(
6560
+ ) : /* @__PURE__ */ jsx29(
6408
6561
  "span",
6409
6562
  {
6410
6563
  className: "inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-semibold dark:border-blue-300 dark:bg-blue-400/10 dark:text-blue-300",
@@ -6417,12 +6570,12 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6417
6570
  },
6418
6571
  item.key
6419
6572
  )
6420
- ) : /* @__PURE__ */ jsx28("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5DE5\u5177\u8C03\u7528" }) }),
6421
- inlineToolUiBlocks.length > 0 ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-2 px-4 pb-3", children: inlineToolUiBlocks.map((block) => /* @__PURE__ */ jsx28(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null
6573
+ ) : /* @__PURE__ */ jsx29("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u5DE5\u5177\u8C03\u7528" }) }),
6574
+ inlineToolUiBlocks.length > 0 ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2 px-4 pb-3", children: inlineToolUiBlocks.map((block) => /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null
6422
6575
  ] }) : null
6423
6576
  ] }),
6424
- expanded && /* @__PURE__ */ jsx28("div", { className: "border-t border-[hsl(var(--border))] py-2", children: childMessages.length > 0 ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-3 px-3", children: childMessages.map(
6425
- (message, index) => message.role === "assistant" ? /* @__PURE__ */ jsx28(
6577
+ expanded && /* @__PURE__ */ jsx29("div", { className: "border-t border-[hsl(var(--border))] py-2", children: childMessages.length > 0 ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-3 px-3", children: childMessages.map(
6578
+ (message, index) => message.role === "assistant" ? /* @__PURE__ */ jsx29(
6426
6579
  ExpandedChildAssistantMessage,
6427
6580
  {
6428
6581
  message,
@@ -6430,13 +6583,13 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6430
6583
  isStreaming: message.status === "streaming"
6431
6584
  },
6432
6585
  message.entry_id ?? `${message.timestamp ?? "child"}-${index}`
6433
- ) : message.role === "user" ? /* @__PURE__ */ jsx28(
6586
+ ) : message.role === "user" ? /* @__PURE__ */ jsx29(
6434
6587
  ExpandedChildUserMessage,
6435
6588
  {
6436
6589
  message
6437
6590
  },
6438
6591
  message.entry_id ?? `${message.timestamp ?? "user"}-${index}`
6439
- ) : message.role === "error" ? /* @__PURE__ */ jsx28(
6592
+ ) : message.role === "error" ? /* @__PURE__ */ jsx29(
6440
6593
  "div",
6441
6594
  {
6442
6595
  className: "border-l-[2px] border-l-red-500 px-3 py-2 text-[11px] text-red-200",
@@ -6444,16 +6597,16 @@ function AgentLoopBlock({ toolCall, sessionId, reasoning }) {
6444
6597
  },
6445
6598
  message.entry_id ?? `${message.timestamp ?? "error"}-${index}`
6446
6599
  ) : null
6447
- ) }) : status === "running" ? /* @__PURE__ */ jsxs23("div", { className: "px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
6448
- /* @__PURE__ */ jsx28(Loader24, { size: 12, className: "mr-1.5 inline animate-spin" }),
6600
+ ) }) : status === "running" ? /* @__PURE__ */ jsxs24("div", { className: "px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
6601
+ /* @__PURE__ */ jsx29(Loader24, { size: 12, className: "mr-1.5 inline animate-spin" }),
6449
6602
  "\u6B63\u5728\u542F\u52A8..."
6450
- ] }) : toolCall.result ? /* @__PURE__ */ jsx28("pre", { className: "max-h-[400px] overflow-auto px-3 py-2 whitespace-pre-wrap text-[11px] text-[hsl(var(--muted-foreground))]", children: typeof toolCall.result === "string" ? toolCall.result : JSON.stringify(toolCall.result, null, 2) }) : null })
6603
+ ] }) : toolCall.result ? /* @__PURE__ */ jsx29("pre", { className: "max-h-[400px] overflow-auto px-3 py-2 whitespace-pre-wrap text-[11px] text-[hsl(var(--muted-foreground))]", children: typeof toolCall.result === "string" ? toolCall.result : JSON.stringify(toolCall.result, null, 2) }) : null })
6451
6604
  ]
6452
6605
  }
6453
6606
  );
6454
6607
  }
6455
6608
  function ExpandedChildUserMessage({ message }) {
6456
- return /* @__PURE__ */ jsx28("div", { className: "pl-8", children: /* @__PURE__ */ jsx28(UserMessageBubble, { message }) });
6609
+ return /* @__PURE__ */ jsx29("div", { className: "pl-8", children: /* @__PURE__ */ jsx29(UserMessageBubble, { message }) });
6457
6610
  }
6458
6611
  function ExpandedChildAssistantMessage({
6459
6612
  message,
@@ -6466,12 +6619,12 @@ function ExpandedChildAssistantMessage({
6466
6619
  const firstToolCallId = toolCalls[0]?.id;
6467
6620
  const toolReasoning = !isStreaming && !text && hasToolCalls ? message.reasoning : void 0;
6468
6621
  const standaloneReasoning = !isStreaming && !text && !hasToolCalls ? message.reasoning : void 0;
6469
- return /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
6470
- message.reasoning && isStreaming && /* @__PURE__ */ jsxs23(Reasoning, { isStreaming, children: [
6471
- /* @__PURE__ */ jsx28(ReasoningTrigger, {}),
6472
- /* @__PURE__ */ jsx28(ReasoningContent, { children: message.reasoning })
6622
+ return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-2", children: [
6623
+ message.reasoning && isStreaming && /* @__PURE__ */ jsxs24(Reasoning, { isStreaming, children: [
6624
+ /* @__PURE__ */ jsx29(ReasoningTrigger, {}),
6625
+ /* @__PURE__ */ jsx29(ReasoningContent, { children: message.reasoning })
6473
6626
  ] }),
6474
- text ? /* @__PURE__ */ jsx28(
6627
+ text ? /* @__PURE__ */ jsx29(
6475
6628
  ChildText,
6476
6629
  {
6477
6630
  text,
@@ -6480,10 +6633,10 @@ function ExpandedChildAssistantMessage({
6480
6633
  reasoning: !isStreaming ? message.reasoning : void 0
6481
6634
  }
6482
6635
  ) : null,
6483
- !text && isStreaming && /* @__PURE__ */ jsx28("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
6484
- standaloneReasoning ? /* @__PURE__ */ jsx28("div", { className: "pl-8", children: /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning: standaloneReasoning, variant: "block" }) }) : null,
6485
- hasToolCalls && /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-2", children: toolCalls.map(
6486
- (toolCall, index) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx28(
6636
+ !text && isStreaming && /* @__PURE__ */ jsx29("span", { className: "pl-8 text-[12px] text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
6637
+ standaloneReasoning ? /* @__PURE__ */ jsx29("div", { className: "pl-8", children: /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning: standaloneReasoning, variant: "block" }) }) : null,
6638
+ hasToolCalls && /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: toolCalls.map(
6639
+ (toolCall, index) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx29(
6487
6640
  AgentLoopBlock,
6488
6641
  {
6489
6642
  toolCall,
@@ -6491,7 +6644,7 @@ function ExpandedChildAssistantMessage({
6491
6644
  reasoning: toolCall.id === firstToolCallId ? toolReasoning : void 0
6492
6645
  },
6493
6646
  toolCall.id
6494
- ) : /* @__PURE__ */ jsx28(
6647
+ ) : /* @__PURE__ */ jsx29(
6495
6648
  ToolCallBlock,
6496
6649
  {
6497
6650
  toolCall,
@@ -6503,8 +6656,8 @@ function ExpandedChildAssistantMessage({
6503
6656
  toolCall.id
6504
6657
  )
6505
6658
  ) }),
6506
- message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-2", children: message.blocks.map(
6507
- (block, index) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx28("div", { className: "ml-4", children: /* @__PURE__ */ jsx28(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${index}`) : null
6659
+ message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: message.blocks.map(
6660
+ (block, index) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx29("div", { className: "ml-4", children: /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${index}`) : null
6508
6661
  ) }) : null
6509
6662
  ] });
6510
6663
  }
@@ -6514,8 +6667,8 @@ function ChildText({
6514
6667
  sessionId,
6515
6668
  reasoning
6516
6669
  }) {
6517
- return /* @__PURE__ */ jsxs23("div", { className: "pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]", children: [
6518
- /* @__PURE__ */ jsx28(
6670
+ return /* @__PURE__ */ jsxs24("div", { className: "pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]", children: [
6671
+ /* @__PURE__ */ jsx29(
6519
6672
  MarkdownContent,
6520
6673
  {
6521
6674
  mode: "streaming",
@@ -6525,8 +6678,8 @@ function ChildText({
6525
6678
  children: text
6526
6679
  }
6527
6680
  ),
6528
- isStreaming && /* @__PURE__ */ jsx28("span", { className: "ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60" }),
6529
- reasoning ? /* @__PURE__ */ jsx28(ThinkingBadge, { reasoning }) : null
6681
+ isStreaming && /* @__PURE__ */ jsx29("span", { className: "ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60" }),
6682
+ reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning }) : null
6530
6683
  ] });
6531
6684
  }
6532
6685
  function getLoopCardStyles(status) {
@@ -6566,7 +6719,7 @@ function getLoopCardStyles(status) {
6566
6719
  }
6567
6720
 
6568
6721
  // src/react/components/chat/AssistantTurnBlock.tsx
6569
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
6722
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
6570
6723
  function defaultTurnDisplayMode({
6571
6724
  forceExpanded,
6572
6725
  hasActionableToolCall
@@ -6720,7 +6873,7 @@ function AssistantTurnBlock({
6720
6873
  ),
6721
6874
  [allToolCalls]
6722
6875
  );
6723
- const [displayMode, setDisplayMode] = useState16(
6876
+ const [displayMode, setDisplayMode] = useState17(
6724
6877
  defaultTurnDisplayMode({ forceExpanded, hasActionableToolCall })
6725
6878
  );
6726
6879
  const wasStreamingRef = useRef10(isStreaming);
@@ -6741,7 +6894,7 @@ function AssistantTurnBlock({
6741
6894
  const hasInterruptedState = messages.some((message) => message.status === "interrupted");
6742
6895
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
6743
6896
  const memoryRefs = Array.isArray(messages[0]?.memory_refs) ? messages[0].memory_refs : [];
6744
- return /* @__PURE__ */ jsxs24(
6897
+ return /* @__PURE__ */ jsxs25(
6745
6898
  "div",
6746
6899
  {
6747
6900
  className: cn(
@@ -6750,17 +6903,17 @@ function AssistantTurnBlock({
6750
6903
  customization?.classNames?.assistantTurn
6751
6904
  ),
6752
6905
  children: [
6753
- memoryRefs.length > 0 && /* @__PURE__ */ jsx29(MemoryRefsHint, { refs: memoryRefs }),
6754
- hasInterruptedState && /* @__PURE__ */ jsx29("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
6755
- !isStreaming && /* @__PURE__ */ jsx29("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs24(
6906
+ memoryRefs.length > 0 && /* @__PURE__ */ jsx30(MemoryRefsHint, { refs: memoryRefs }),
6907
+ hasInterruptedState && /* @__PURE__ */ jsx30("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
6908
+ !isStreaming && /* @__PURE__ */ jsx30("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs25(
6756
6909
  "button",
6757
6910
  {
6758
6911
  type: "button",
6759
6912
  onClick: () => setDisplayMode(displayMode === "detail" ? "compact" : "detail"),
6760
6913
  className: "inline-flex shrink-0 items-center gap-1 text-xs text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
6761
6914
  children: [
6762
- /* @__PURE__ */ jsx29("span", { children: effectiveMode === "detail" ? "\u7CBE\u7B80" : "\u8BE6\u7EC6" }),
6763
- /* @__PURE__ */ jsx29(
6915
+ /* @__PURE__ */ jsx30("span", { children: effectiveMode === "detail" ? "\u7CBE\u7B80" : "\u8BE6\u7EC6" }),
6916
+ /* @__PURE__ */ jsx30(
6764
6917
  ChevronRight5,
6765
6918
  {
6766
6919
  size: 18,
@@ -6770,7 +6923,7 @@ function AssistantTurnBlock({
6770
6923
  ]
6771
6924
  }
6772
6925
  ) }),
6773
- effectiveMode === "detail" ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx29(
6926
+ effectiveMode === "detail" ? /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx30(
6774
6927
  AssistantMessages,
6775
6928
  {
6776
6929
  messages,
@@ -6783,15 +6936,15 @@ function AssistantTurnBlock({
6783
6936
  showToolDetails: true,
6784
6937
  customization
6785
6938
  }
6786
- ) }) : /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-4", children: [
6787
- resourceBlocks.length > 0 ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-3", children: resourceBlocks.map((block) => /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null,
6788
- finalMessage ? /* @__PURE__ */ jsx29(
6939
+ ) }) : /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-4", children: [
6940
+ resourceBlocks.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-3", children: resourceBlocks.map((block) => /* @__PURE__ */ jsx30(ResourceIframe, { ui: block.ui, sessionId }, block.key)) }) : null,
6941
+ finalMessage ? /* @__PURE__ */ jsx30(
6789
6942
  "div",
6790
6943
  {
6791
6944
  className: cn(
6792
6945
  resourceBlocks.length > 0 && "border-t border-[hsl(var(--border))] pt-4"
6793
6946
  ),
6794
- children: /* @__PURE__ */ jsx29(
6947
+ children: /* @__PURE__ */ jsx30(
6795
6948
  AssistantMessageContent,
6796
6949
  {
6797
6950
  message: finalMessage,
@@ -6802,7 +6955,7 @@ function AssistantTurnBlock({
6802
6955
  }
6803
6956
  )
6804
6957
  }
6805
- ) : isStreaming ? /* @__PURE__ */ jsx29("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }) : null
6958
+ ) : isStreaming ? /* @__PURE__ */ jsx30("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }) : null
6806
6959
  ] }) })
6807
6960
  ]
6808
6961
  }
@@ -6832,16 +6985,16 @@ function AssistantMessages({
6832
6985
  const toolRenderItems = groupDetailedToolCalls(toolCalls);
6833
6986
  const toolReasoning = hasReasoning && !hasText && !hasAttachments && hasToolCalls && !isStreamingLastMessage ? reasoning : void 0;
6834
6987
  const contentReasoning = hasReasoning && !isStreamingLastMessage && (hasText || hasAttachments || !hasToolCalls) ? reasoning : void 0;
6835
- return /* @__PURE__ */ jsxs24(
6988
+ return /* @__PURE__ */ jsxs25(
6836
6989
  "div",
6837
6990
  {
6838
6991
  className: "flex flex-col gap-3",
6839
6992
  children: [
6840
- hasReasoning && isStreamingLastMessage && /* @__PURE__ */ jsxs24(Reasoning, { isStreaming: isStreamingLastMessage, children: [
6841
- /* @__PURE__ */ jsx29(ReasoningTrigger, {}),
6842
- /* @__PURE__ */ jsx29(ReasoningContent, { children: reasoning })
6993
+ hasReasoning && isStreamingLastMessage && /* @__PURE__ */ jsxs25(Reasoning, { isStreaming: isStreamingLastMessage, children: [
6994
+ /* @__PURE__ */ jsx30(ReasoningTrigger, {}),
6995
+ /* @__PURE__ */ jsx30(ReasoningContent, { children: reasoning })
6843
6996
  ] }),
6844
- /* @__PURE__ */ jsx29(
6997
+ /* @__PURE__ */ jsx30(
6845
6998
  AssistantMessageContent,
6846
6999
  {
6847
7000
  message,
@@ -6851,9 +7004,9 @@ function AssistantMessages({
6851
7004
  className: customization?.classNames?.assistantText
6852
7005
  }
6853
7006
  ),
6854
- hasToolCalls && showToolDetails && /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: toolRenderItems.map((item) => {
7007
+ hasToolCalls && showToolDetails && /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-2", children: toolRenderItems.map((item) => {
6855
7008
  if (item.kind === "read_group" || item.kind === "load_skill_group") {
6856
- return /* @__PURE__ */ jsx29(
7009
+ return /* @__PURE__ */ jsx30(
6857
7010
  CompactToolGroupBlock,
6858
7011
  {
6859
7012
  toolCalls: item.toolCalls,
@@ -6871,7 +7024,7 @@ function AssistantMessages({
6871
7024
  );
6872
7025
  }
6873
7026
  const { toolCall } = item;
6874
- return formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx29(
7027
+ return formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx30(
6875
7028
  AgentLoopBlock,
6876
7029
  {
6877
7030
  toolCall,
@@ -6879,7 +7032,7 @@ function AssistantMessages({
6879
7032
  reasoning: toolCall.id === firstToolCallId ? toolReasoning : void 0
6880
7033
  },
6881
7034
  toolCall.id
6882
- ) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx29(
7035
+ ) : customization?.components?.ToolCall ? /* @__PURE__ */ jsx30(
6883
7036
  customization.components.ToolCall,
6884
7037
  {
6885
7038
  toolCall,
@@ -6894,7 +7047,7 @@ function AssistantMessages({
6894
7047
  customization
6895
7048
  },
6896
7049
  toolCall.id
6897
- ) : /* @__PURE__ */ jsx29(
7050
+ ) : /* @__PURE__ */ jsx30(
6898
7051
  ToolCallBlock,
6899
7052
  {
6900
7053
  toolCall,
@@ -6911,8 +7064,8 @@ function AssistantMessages({
6911
7064
  toolCall.id
6912
7065
  );
6913
7066
  }) }),
6914
- showToolDetails && message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-2", children: message.blocks.map(
6915
- (block, blockIndex) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx29("div", { className: "ml-4", children: /* @__PURE__ */ jsx29(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${blockIndex}`) : null
7067
+ showToolDetails && message.blocks?.some((block) => block.type === "tool_ui") ? /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-2", children: message.blocks.map(
7068
+ (block, blockIndex) => block.type === "tool_ui" && block.tool_call_id && isUiMeta(block.content) && block.content.target === "inline" ? /* @__PURE__ */ jsx30("div", { className: "ml-4", children: /* @__PURE__ */ jsx30(ResourceIframe, { ui: block.content, sessionId }) }, `${block.tool_call_id}-${blockIndex}`) : null
6916
7069
  ) }) : null
6917
7070
  ]
6918
7071
  },
@@ -6947,7 +7100,7 @@ function CompactToolGroupBlock({
6947
7100
  level,
6948
7101
  customization
6949
7102
  }) {
6950
- const [expanded, setExpanded] = useState16(false);
7103
+ const [expanded, setExpanded] = useState17(false);
6951
7104
  const indentClass = level === 2 ? "ml-3" : "ml-4";
6952
7105
  const hasError = toolCalls.some(
6953
7106
  (tc) => tc.status === "error" || tc.status === "cancelled"
@@ -6962,12 +7115,12 @@ function CompactToolGroupBlock({
6962
7115
  });
6963
7116
  const tags = kind === "read_group" ? fileNames : toolCalls.map(getLoadedSkillName);
6964
7117
  const title = kind === "read_group" ? `\u8BFB\u53D6 ${toolCalls.length} \u4E2A\u6587\u4EF6` : toolCalls.length > 1 ? `\u52A0\u8F7D ${toolCalls.length} \u4E2A\u6280\u80FD` : "\u52A0\u8F7D\u6280\u80FD";
6965
- return /* @__PURE__ */ jsxs24("div", { className: cn(indentClass, "text-xs"), children: [
6966
- /* @__PURE__ */ jsxs24("div", { className: cn(
7118
+ return /* @__PURE__ */ jsxs25("div", { className: cn(indentClass, "text-xs"), children: [
7119
+ /* @__PURE__ */ jsxs25("div", { className: cn(
6967
7120
  "flex items-center gap-2 border-l-[3px] px-3 py-2",
6968
7121
  hasError ? "border-l-[hsl(var(--destructive))]" : "border-l-[hsl(var(--primary))]"
6969
7122
  ), children: [
6970
- /* @__PURE__ */ jsxs24(
7123
+ /* @__PURE__ */ jsxs25(
6971
7124
  "button",
6972
7125
  {
6973
7126
  type: "button",
@@ -6975,7 +7128,7 @@ function CompactToolGroupBlock({
6975
7128
  className: "flex min-w-0 shrink-0 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
6976
7129
  "aria-expanded": expanded,
6977
7130
  children: [
6978
- /* @__PURE__ */ jsx29(
7131
+ /* @__PURE__ */ jsx30(
6979
7132
  ChevronRight5,
6980
7133
  {
6981
7134
  size: 11,
@@ -6985,18 +7138,18 @@ function CompactToolGroupBlock({
6985
7138
  )
6986
7139
  }
6987
7140
  ),
6988
- hasError ? /* @__PURE__ */ jsxs24("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]", children: [
6989
- /* @__PURE__ */ jsx29(AlertCircle, { size: 11 }),
6990
- /* @__PURE__ */ jsx29("span", { children: "\u5931\u8D25" })
6991
- ] }) : /* @__PURE__ */ jsxs24("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]", children: [
6992
- /* @__PURE__ */ jsx29(Check4, { size: 11 }),
6993
- /* @__PURE__ */ jsx29("span", { children: "\u5B8C\u6210" })
7141
+ hasError ? /* @__PURE__ */ jsxs25("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]", children: [
7142
+ /* @__PURE__ */ jsx30(AlertCircle, { size: 11 }),
7143
+ /* @__PURE__ */ jsx30("span", { children: "\u5931\u8D25" })
7144
+ ] }) : /* @__PURE__ */ jsxs25("span", { className: "flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]", children: [
7145
+ /* @__PURE__ */ jsx30(Check4, { size: 11 }),
7146
+ /* @__PURE__ */ jsx30("span", { children: "\u5B8C\u6210" })
6994
7147
  ] }),
6995
- /* @__PURE__ */ jsx29("span", { className: "min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]", children: title })
7148
+ /* @__PURE__ */ jsx30("span", { className: "min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]", children: title })
6996
7149
  ]
6997
7150
  }
6998
7151
  ),
6999
- /* @__PURE__ */ jsx29("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: tags.map((tag, index) => /* @__PURE__ */ jsx29(
7152
+ /* @__PURE__ */ jsx30("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: tags.map((tag, index) => /* @__PURE__ */ jsx30(
7000
7153
  "span",
7001
7154
  {
7002
7155
  className: "max-w-40 truncate rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.35)] px-1.5 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]",
@@ -7005,12 +7158,12 @@ function CompactToolGroupBlock({
7005
7158
  },
7006
7159
  `${tag}-${index}`
7007
7160
  )) }),
7008
- reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null,
7009
- totalDurationMs > 0 ? /* @__PURE__ */ jsx29("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration2(totalDurationMs) }) : null
7161
+ reasoning ? /* @__PURE__ */ jsx30(ThinkingBadge, { reasoning, variant: "block" }) : null,
7162
+ totalDurationMs > 0 ? /* @__PURE__ */ jsx30("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration2(totalDurationMs) }) : null
7010
7163
  ] }),
7011
- expanded ? /* @__PURE__ */ jsx29("div", { className: "mt-1 flex flex-col gap-1", children: toolCalls.map((toolCall) => {
7164
+ expanded ? /* @__PURE__ */ jsx30("div", { className: "mt-1 flex flex-col gap-1", children: toolCalls.map((toolCall) => {
7012
7165
  const CustomToolCall = customization?.components?.ToolCall;
7013
- return CustomToolCall ? /* @__PURE__ */ jsx29(
7166
+ return CustomToolCall ? /* @__PURE__ */ jsx30(
7014
7167
  CustomToolCall,
7015
7168
  {
7016
7169
  toolCall,
@@ -7024,7 +7177,7 @@ function CompactToolGroupBlock({
7024
7177
  customization
7025
7178
  },
7026
7179
  toolCall.id
7027
- ) : /* @__PURE__ */ jsx29(
7180
+ ) : /* @__PURE__ */ jsx30(
7028
7181
  ToolCallBlock,
7029
7182
  {
7030
7183
  toolCall,
@@ -7055,8 +7208,8 @@ function AssistantMessageContent({
7055
7208
  if (!text && imageParts.length === 0 && fileParts.length === 0 && !isStreaming && !reasoning) {
7056
7209
  return null;
7057
7210
  }
7058
- return /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-3", children: [
7059
- imageParts.length > 0 && /* @__PURE__ */ jsx29("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx29(
7211
+ return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-3", children: [
7212
+ imageParts.length > 0 && /* @__PURE__ */ jsx30("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx30(
7060
7213
  "img",
7061
7214
  {
7062
7215
  src: part.image_url.url,
@@ -7065,8 +7218,8 @@ function AssistantMessageContent({
7065
7218
  },
7066
7219
  part.image_url.url
7067
7220
  )) }),
7068
- /* @__PURE__ */ jsx29(MessageFileAttachmentList, { files: fileParts }),
7069
- text ? /* @__PURE__ */ jsx29(
7221
+ /* @__PURE__ */ jsx30(MessageFileAttachmentList, { files: fileParts }),
7222
+ text ? /* @__PURE__ */ jsx30(
7070
7223
  AssistantText,
7071
7224
  {
7072
7225
  text,
@@ -7076,8 +7229,8 @@ function AssistantMessageContent({
7076
7229
  className
7077
7230
  }
7078
7231
  ) : null,
7079
- !text && isStreaming && /* @__PURE__ */ jsx29("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7080
- !text && reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning, variant: "block" }) : null
7232
+ !text && isStreaming && /* @__PURE__ */ jsx30("span", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u751F\u6210..." }),
7233
+ !text && reasoning ? /* @__PURE__ */ jsx30(ThinkingBadge, { reasoning, variant: "block" }) : null
7081
7234
  ] });
7082
7235
  }
7083
7236
  function AssistantText({
@@ -7097,8 +7250,8 @@ function AssistantText({
7097
7250
  () => ({ sessionId, messageId, sendMessage }),
7098
7251
  [sessionId, messageId, sendMessage]
7099
7252
  );
7100
- return /* @__PURE__ */ jsxs24("div", { className: cn("text-[15px] leading-8 text-[hsl(var(--foreground))]", className), children: [
7101
- /* @__PURE__ */ jsx29(CardContext.Provider, { value: cardCtx, children: /* @__PURE__ */ jsx29(
7253
+ return /* @__PURE__ */ jsxs25("div", { className: cn("text-[15px] leading-8 text-[hsl(var(--foreground))]", className), children: [
7254
+ /* @__PURE__ */ jsx30(CardContext.Provider, { value: cardCtx, children: /* @__PURE__ */ jsx30(
7102
7255
  MarkdownContent,
7103
7256
  {
7104
7257
  mode: "streaming",
@@ -7108,30 +7261,30 @@ function AssistantText({
7108
7261
  children: text
7109
7262
  }
7110
7263
  ) }),
7111
- reasoning ? /* @__PURE__ */ jsx29(ThinkingBadge, { reasoning }) : null
7264
+ reasoning ? /* @__PURE__ */ jsx30(ThinkingBadge, { reasoning }) : null
7112
7265
  ] });
7113
7266
  }
7114
7267
  function MemoryRefsHint({ refs: rawRefs }) {
7115
7268
  const refs = Array.isArray(rawRefs) ? rawRefs : [];
7116
- const [expanded, setExpanded] = useState16(false);
7269
+ const [expanded, setExpanded] = useState17(false);
7117
7270
  const hasSkill = refs.some((r3) => r3.skill_name);
7118
7271
  const label = hasSkill ? "\u53C2\u8003\u4E86\u8BE5\u6280\u80FD\u7684\u5386\u53F2\u7ECF\u9A8C" : "\u53C2\u8003\u4E86\u5386\u53F2\u7ECF\u9A8C";
7119
- return /* @__PURE__ */ jsxs24("div", { className: "ml-4", children: [
7120
- /* @__PURE__ */ jsxs24(
7272
+ return /* @__PURE__ */ jsxs25("div", { className: "ml-4", children: [
7273
+ /* @__PURE__ */ jsxs25(
7121
7274
  "button",
7122
7275
  {
7123
7276
  type: "button",
7124
7277
  onClick: () => setExpanded(!expanded),
7125
7278
  className: "inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--primary)/0.25)] bg-[hsl(var(--primary)/0.08)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary))] transition-colors hover:bg-[hsl(var(--primary)/0.12)]",
7126
7279
  children: [
7127
- /* @__PURE__ */ jsx29(BookOpen, { size: 12 }),
7128
- /* @__PURE__ */ jsxs24("span", { children: [
7280
+ /* @__PURE__ */ jsx30(BookOpen, { size: 12 }),
7281
+ /* @__PURE__ */ jsxs25("span", { children: [
7129
7282
  label,
7130
7283
  "\uFF08",
7131
7284
  refs.length,
7132
7285
  "\uFF09"
7133
7286
  ] }),
7134
- /* @__PURE__ */ jsx29(
7287
+ /* @__PURE__ */ jsx30(
7135
7288
  ChevronRight5,
7136
7289
  {
7137
7290
  size: 10,
@@ -7141,13 +7294,13 @@ function MemoryRefsHint({ refs: rawRefs }) {
7141
7294
  ]
7142
7295
  }
7143
7296
  ),
7144
- expanded && /* @__PURE__ */ jsxs24("div", { className: "mt-1.5 flex flex-col gap-1 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.45)] px-3 py-2", children: [
7145
- refs.map((ref) => /* @__PURE__ */ jsxs24("div", { className: "flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]", children: [
7146
- /* @__PURE__ */ jsx29("span", { className: "mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]", children: "\u2022" }),
7147
- /* @__PURE__ */ jsx29("span", { className: "line-clamp-1", children: ref.content_preview }),
7148
- ref.skill_name && /* @__PURE__ */ jsx29("span", { className: "ml-auto shrink-0 rounded bg-[hsl(var(--primary)/0.12)] px-1.5 py-0.5 text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name })
7297
+ expanded && /* @__PURE__ */ jsxs25("div", { className: "mt-1.5 flex flex-col gap-1 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.45)] px-3 py-2", children: [
7298
+ refs.map((ref) => /* @__PURE__ */ jsxs25("div", { className: "flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]", children: [
7299
+ /* @__PURE__ */ jsx30("span", { className: "mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]", children: "\u2022" }),
7300
+ /* @__PURE__ */ jsx30("span", { className: "line-clamp-1", children: ref.content_preview }),
7301
+ ref.skill_name && /* @__PURE__ */ jsx30("span", { className: "ml-auto shrink-0 rounded bg-[hsl(var(--primary)/0.12)] px-1.5 py-0.5 text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name })
7149
7302
  ] }, ref.id)),
7150
- /* @__PURE__ */ jsx29(
7303
+ /* @__PURE__ */ jsx30(
7151
7304
  "a",
7152
7305
  {
7153
7306
  href: MEMORIES_ROUTE,
@@ -7160,9 +7313,9 @@ function MemoryRefsHint({ refs: rawRefs }) {
7160
7313
  }
7161
7314
 
7162
7315
  // src/react/components/chat/CompactionCard.tsx
7163
- import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight6, Loader2 as Loader25, Square as Square2, XCircle } from "lucide-react";
7164
- import { useState as useState17 } from "react";
7165
- import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
7316
+ import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight6, Loader2 as Loader25, Square as Square3, XCircle } from "lucide-react";
7317
+ import { useState as useState18 } from "react";
7318
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
7166
7319
  var PERCENT_FORMATTER = new Intl.NumberFormat("zh-CN", {
7167
7320
  style: "percent",
7168
7321
  maximumFractionDigits: 0
@@ -7221,7 +7374,7 @@ function CompactionCard({
7221
7374
  ...compaction,
7222
7375
  status: status ?? "completed"
7223
7376
  } : activeCompaction;
7224
- const [expanded, setExpanded] = useState17(false);
7377
+ const [expanded, setExpanded] = useState18(false);
7225
7378
  if (!source || !source.compaction_id) {
7226
7379
  return null;
7227
7380
  }
@@ -7232,9 +7385,9 @@ function CompactionCard({
7232
7385
  const hasSummary = typeof source.summary_full === "string" && source.summary_full.trim().length > 0 && !isGenericArchiveSummary(source.summary_full);
7233
7386
  const hasFailureReason = source.status === "failed" && Boolean(source.failure_reason);
7234
7387
  const canExpand = source.status === "completed" && (hasSummary || archivedToolCalls.length > 0) || hasFailureReason;
7235
- return /* @__PURE__ */ jsxs25("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: [
7236
- /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between gap-2", children: [
7237
- /* @__PURE__ */ jsxs25(
7388
+ return /* @__PURE__ */ jsxs26("div", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: [
7389
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between gap-2", children: [
7390
+ /* @__PURE__ */ jsxs26(
7238
7391
  "button",
7239
7392
  {
7240
7393
  type: "button",
@@ -7245,21 +7398,21 @@ function CompactionCard({
7245
7398
  ),
7246
7399
  "aria-expanded": expanded,
7247
7400
  children: [
7248
- canExpand ? expanded ? /* @__PURE__ */ jsx30(ChevronDown2, { size: 12, className: "shrink-0" }) : /* @__PURE__ */ jsx30(ChevronRight6, { size: 12, className: "shrink-0" }) : null,
7249
- /* @__PURE__ */ jsx30("span", { children: source.status === "streaming" ? /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1", children: [
7250
- /* @__PURE__ */ jsx30(Loader25, { size: 12, className: "animate-spin" }),
7401
+ canExpand ? expanded ? /* @__PURE__ */ jsx31(ChevronDown2, { size: 12, className: "shrink-0" }) : /* @__PURE__ */ jsx31(ChevronRight6, { size: 12, className: "shrink-0" }) : null,
7402
+ /* @__PURE__ */ jsx31("span", { children: source.status === "streaming" ? /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1", children: [
7403
+ /* @__PURE__ */ jsx31(Loader25, { size: 12, className: "animate-spin" }),
7251
7404
  "\u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587"
7252
- ] }) : source.status === "failed" ? /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1 text-rose-500/80", children: [
7253
- /* @__PURE__ */ jsx30(XCircle, { size: 12 }),
7405
+ ] }) : source.status === "failed" ? /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1 text-rose-500/80", children: [
7406
+ /* @__PURE__ */ jsx31(XCircle, { size: 12 }),
7254
7407
  "\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25"
7255
- ] }) : source.status === "interrupted" ? /* @__PURE__ */ jsxs25("span", { className: "inline-flex items-center gap-1 text-amber-500/80", children: [
7256
- /* @__PURE__ */ jsx30(Square2, { size: 11 }),
7408
+ ] }) : source.status === "interrupted" ? /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1 text-amber-500/80", children: [
7409
+ /* @__PURE__ */ jsx31(Square3, { size: 11 }),
7257
7410
  "\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88"
7258
7411
  ] }) : "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
7259
7412
  ]
7260
7413
  }
7261
7414
  ),
7262
- canCancel ? /* @__PURE__ */ jsx30(
7415
+ canCancel ? /* @__PURE__ */ jsx31(
7263
7416
  "button",
7264
7417
  {
7265
7418
  type: "button",
@@ -7269,13 +7422,13 @@ function CompactionCard({
7269
7422
  }
7270
7423
  ) : null
7271
7424
  ] }),
7272
- expanded ? /* @__PURE__ */ jsxs25("div", { className: "mt-1 max-w-3xl rounded-lg border border-[hsl(var(--border))]/70 bg-[hsl(var(--card))]/80 px-3 py-2 text-[11px] leading-relaxed shadow-sm", children: [
7273
- /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]", children: [
7274
- /* @__PURE__ */ jsxs25("span", { children: [
7425
+ expanded ? /* @__PURE__ */ jsxs26("div", { className: "mt-1 max-w-3xl rounded-lg border border-[hsl(var(--border))]/70 bg-[hsl(var(--card))]/80 px-3 py-2 text-[11px] leading-relaxed shadow-sm", children: [
7426
+ /* @__PURE__ */ jsxs26("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]", children: [
7427
+ /* @__PURE__ */ jsxs26("span", { children: [
7275
7428
  "#",
7276
7429
  shortId(source.compaction_id)
7277
7430
  ] }),
7278
- /* @__PURE__ */ jsxs25("span", { children: [
7431
+ /* @__PURE__ */ jsxs26("span", { children: [
7279
7432
  "\u8282\u7701 ",
7280
7433
  formatSavedRatio(source.saved_ratio),
7281
7434
  "\uFF08",
@@ -7285,31 +7438,31 @@ function CompactionCard({
7285
7438
  formatTokens(source.tokens_after),
7286
7439
  " token\uFF09"
7287
7440
  ] }),
7288
- /* @__PURE__ */ jsxs25("span", { children: [
7441
+ /* @__PURE__ */ jsxs26("span", { children: [
7289
7442
  "\u5F52\u6863 ",
7290
7443
  archivedCount,
7291
7444
  " \u4E2A\u5DE5\u5177\u7ED3\u679C"
7292
7445
  ] })
7293
7446
  ] }),
7294
- archivedToolCalls.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "mt-2 space-y-1.5", children: archivedToolCalls.map((item, index) => {
7447
+ archivedToolCalls.length > 0 ? /* @__PURE__ */ jsx31("div", { className: "mt-2 space-y-1.5", children: archivedToolCalls.map((item, index) => {
7295
7448
  const archivePath = getArchivePath(item, archivedFiles);
7296
- return /* @__PURE__ */ jsxs25(
7449
+ return /* @__PURE__ */ jsxs26(
7297
7450
  "div",
7298
7451
  {
7299
7452
  className: "rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/35 px-2 py-1.5",
7300
7453
  children: [
7301
- /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]", children: [
7302
- /* @__PURE__ */ jsx30("span", { className: "font-medium", children: getArchivedToolLabel(item) }),
7303
- item.tool_call_id ? /* @__PURE__ */ jsx30("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.tool_call_id }) : null
7454
+ /* @__PURE__ */ jsxs26("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]", children: [
7455
+ /* @__PURE__ */ jsx31("span", { className: "font-medium", children: getArchivedToolLabel(item) }),
7456
+ item.tool_call_id ? /* @__PURE__ */ jsx31("span", { className: "font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: item.tool_call_id }) : null
7304
7457
  ] }),
7305
- archivePath ? /* @__PURE__ */ jsx30("div", { className: "mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: archivePath }) : null
7458
+ archivePath ? /* @__PURE__ */ jsx31("div", { className: "mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: archivePath }) : null
7306
7459
  ]
7307
7460
  },
7308
7461
  item.tool_call_id || item.entry_id || `${item.tool_name}-${index}`
7309
7462
  );
7310
7463
  }) }) : null,
7311
- hasSummary ? /* @__PURE__ */ jsx30("pre", { className: "mt-2 max-h-[360px] overflow-auto whitespace-pre-wrap rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/25 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-[hsl(var(--foreground))]", children: source.summary_full }) : null,
7312
- source.status === "failed" && source.failure_reason ? /* @__PURE__ */ jsxs25("div", { className: "mt-2 text-rose-500/90", children: [
7464
+ hasSummary ? /* @__PURE__ */ jsx31("pre", { className: "mt-2 max-h-[360px] overflow-auto whitespace-pre-wrap rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/25 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-[hsl(var(--foreground))]", children: source.summary_full }) : null,
7465
+ source.status === "failed" && source.failure_reason ? /* @__PURE__ */ jsxs26("div", { className: "mt-2 text-rose-500/90", children: [
7313
7466
  "\u5931\u8D25\u539F\u56E0\uFF1A",
7314
7467
  source.failure_reason
7315
7468
  ] }) : null
@@ -7320,7 +7473,7 @@ function CompactionCard({
7320
7473
  // src/react/components/chat/RenderErrorBoundary.tsx
7321
7474
  import { AlertTriangle as AlertTriangle2 } from "lucide-react";
7322
7475
  import { Component } from "react";
7323
- import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
7476
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7324
7477
  function getFirstComponentName(componentStack) {
7325
7478
  const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
7326
7479
  return match?.[1] ?? null;
@@ -7353,18 +7506,18 @@ var RenderErrorBoundary = class extends Component {
7353
7506
  return children;
7354
7507
  }
7355
7508
  const componentName = getFirstComponentName(componentStack);
7356
- return /* @__PURE__ */ jsx31("div", { className: "rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs26("div", { className: "flex items-start gap-2", children: [
7357
- /* @__PURE__ */ jsx31(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
7358
- /* @__PURE__ */ jsxs26("div", { className: "min-w-0 flex-1", children: [
7359
- /* @__PURE__ */ jsxs26("div", { className: "font-medium", children: [
7509
+ return /* @__PURE__ */ jsx32("div", { className: "rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs27("div", { className: "flex items-start gap-2", children: [
7510
+ /* @__PURE__ */ jsx32(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
7511
+ /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
7512
+ /* @__PURE__ */ jsxs27("div", { className: "font-medium", children: [
7360
7513
  label,
7361
7514
  "\u6E32\u67D3\u5931\u8D25"
7362
7515
  ] }),
7363
- /* @__PURE__ */ jsxs26("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
7516
+ /* @__PURE__ */ jsxs27("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
7364
7517
  componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
7365
7518
  error.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
7366
7519
  ] }),
7367
- details ? /* @__PURE__ */ jsx31("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
7520
+ details ? /* @__PURE__ */ jsx32("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
7368
7521
  ] })
7369
7522
  ] }) });
7370
7523
  }
@@ -7382,8 +7535,8 @@ import {
7382
7535
  TerminalSquare,
7383
7536
  WandSparkles
7384
7537
  } from "lucide-react";
7385
- import { useEffect as useEffect15, useMemo as useMemo16, useState as useState18 } from "react";
7386
- import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7538
+ import { useEffect as useEffect15, useMemo as useMemo16, useState as useState19 } from "react";
7539
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
7387
7540
  var EMPTY_EVENTS = [];
7388
7541
  function formatElapsedDuration(durationMs) {
7389
7542
  if (durationMs == null) return null;
@@ -7461,7 +7614,7 @@ function getTurnStartedAt(events) {
7461
7614
  return null;
7462
7615
  }
7463
7616
  function useElapsedDuration(startedAt, active) {
7464
- const [now, setNow] = useState18(() => Date.now());
7617
+ const [now, setNow] = useState19(() => Date.now());
7465
7618
  useEffect15(() => {
7466
7619
  if (!active || startedAt == null) {
7467
7620
  return;
@@ -7493,22 +7646,22 @@ function StickyStatusBar({
7493
7646
  }
7494
7647
  const elapsedLabel = formatElapsedDuration(elapsedDuration);
7495
7648
  const Icon = action.Icon;
7496
- return /* @__PURE__ */ jsxs27(
7649
+ return /* @__PURE__ */ jsxs28(
7497
7650
  "button",
7498
7651
  {
7499
7652
  type: "button",
7500
7653
  onClick: onJumpToLatest,
7501
7654
  className: "sticky top-0 z-20 mb-4 flex w-full items-center gap-3 rounded-2xl border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--background)/0.92)] px-4 py-3 text-left shadow-[0_12px_32px_-24px_hsl(var(--foreground)/0.6)] backdrop-blur",
7502
7655
  children: [
7503
- /* @__PURE__ */ jsx32("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]", children: /* @__PURE__ */ jsx32(Icon, { size: 18, className: Icon === LoaderCircle2 ? "animate-spin" : void 0 }) }),
7504
- /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
7505
- /* @__PURE__ */ jsx32("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: action.label }),
7506
- /* @__PURE__ */ jsxs27("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
7507
- elapsedLabel ? /* @__PURE__ */ jsxs27("span", { className: "font-mono", children: [
7656
+ /* @__PURE__ */ jsx33("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]", children: /* @__PURE__ */ jsx33(Icon, { size: 18, className: Icon === LoaderCircle2 ? "animate-spin" : void 0 }) }),
7657
+ /* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex-1", children: [
7658
+ /* @__PURE__ */ jsx33("div", { className: "truncate text-sm font-medium text-[hsl(var(--foreground))]", children: action.label }),
7659
+ /* @__PURE__ */ jsxs28("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
7660
+ elapsedLabel ? /* @__PURE__ */ jsxs28("span", { className: "font-mono", children: [
7508
7661
  "\u5DF2\u6301\u7EED ",
7509
7662
  elapsedLabel
7510
7663
  ] }) : null,
7511
- /* @__PURE__ */ jsx32("span", { children: "\u70B9\u51FB\u8DF3\u5230\u6700\u65B0\u4F4D\u7F6E" })
7664
+ /* @__PURE__ */ jsx33("span", { children: "\u70B9\u51FB\u8DF3\u5230\u6700\u65B0\u4F4D\u7F6E" })
7512
7665
  ] })
7513
7666
  ] })
7514
7667
  ]
@@ -7517,7 +7670,7 @@ function StickyStatusBar({
7517
7670
  }
7518
7671
 
7519
7672
  // src/react/components/chat/TurnNavRail.tsx
7520
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
7673
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
7521
7674
  function TurnNavRail({
7522
7675
  items,
7523
7676
  activeTurnId,
@@ -7526,14 +7679,14 @@ function TurnNavRail({
7526
7679
  if (items.length < 2) {
7527
7680
  return null;
7528
7681
  }
7529
- return /* @__PURE__ */ jsx33(
7682
+ return /* @__PURE__ */ jsx34(
7530
7683
  "nav",
7531
7684
  {
7532
7685
  "aria-label": "\u56DE\u5408\u5BFC\u822A",
7533
7686
  className: "absolute right-2 top-4 z-10 hidden flex-col items-end gap-0.5 md:flex",
7534
7687
  children: items.map((item, index) => {
7535
7688
  const isActive = item.id === activeTurnId;
7536
- return /* @__PURE__ */ jsxs28(
7689
+ return /* @__PURE__ */ jsxs29(
7537
7690
  "button",
7538
7691
  {
7539
7692
  type: "button",
@@ -7541,8 +7694,8 @@ function TurnNavRail({
7541
7694
  "aria-current": isActive ? "true" : void 0,
7542
7695
  className: "group relative flex h-3.5 items-center",
7543
7696
  children: [
7544
- /* @__PURE__ */ jsx33("span", { className: "pointer-events-none absolute right-full mr-2 hidden max-w-48 truncate whitespace-nowrap rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] px-2.5 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-lg group-hover:block", children: item.title || `\u7B2C ${index + 1} \u8F6E` }),
7545
- /* @__PURE__ */ jsx33(
7697
+ /* @__PURE__ */ jsx34("span", { className: "pointer-events-none absolute right-full mr-2 hidden max-w-48 truncate whitespace-nowrap rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] px-2.5 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-lg group-hover:block", children: item.title || `\u7B2C ${index + 1} \u8F6E` }),
7698
+ /* @__PURE__ */ jsx34(
7546
7699
  "span",
7547
7700
  {
7548
7701
  className: cn(
@@ -7561,7 +7714,7 @@ function TurnNavRail({
7561
7714
  }
7562
7715
 
7563
7716
  // src/react/components/chat/MessageList.tsx
7564
- import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
7717
+ import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
7565
7718
  function parseModeChange(message) {
7566
7719
  if (message.kind !== "mode_change" || typeof message.content !== "string") {
7567
7720
  return null;
@@ -7759,7 +7912,7 @@ function MessageList({
7759
7912
  const containerRef = useRef11(null);
7760
7913
  const scrollContainerRef = useRef11(null);
7761
7914
  const frameRef = useRef11(null);
7762
- const [activeTurnId, setActiveTurnId] = useState19(lastTurnId);
7915
+ const [activeTurnId, setActiveTurnId] = useState20(lastTurnId);
7763
7916
  const layoutSignature = useMemo17(
7764
7917
  () => getMessagesMeasureSignature(messages),
7765
7918
  [messages]
@@ -7822,13 +7975,13 @@ function MessageList({
7822
7975
  const handleSelectTurn = useCallback12((turnId) => {
7823
7976
  document.getElementById(turnId)?.scrollIntoView({ behavior: "smooth", block: "start" });
7824
7977
  }, []);
7825
- return /* @__PURE__ */ jsxs29(
7978
+ return /* @__PURE__ */ jsxs30(
7826
7979
  "div",
7827
7980
  {
7828
7981
  ref: containerRef,
7829
7982
  className: `relative min-h-0 flex-1 ${customization?.classNames?.messageListRoot ?? ""}`,
7830
7983
  children: [
7831
- turnNavItems.length > 1 ? /* @__PURE__ */ jsx34(
7984
+ turnNavItems.length > 1 ? /* @__PURE__ */ jsx35(
7832
7985
  TurnNavRail,
7833
7986
  {
7834
7987
  items: turnNavItems,
@@ -7836,8 +7989,8 @@ function MessageList({
7836
7989
  onSelectTurn: handleSelectTurn
7837
7990
  }
7838
7991
  ) : null,
7839
- /* @__PURE__ */ jsxs29(StickToBottom, { className: "h-full overflow-y-hidden", resize: "smooth", children: [
7840
- /* @__PURE__ */ jsx34(StickToBottom.Content, { className: "px-5 py-6", children: /* @__PURE__ */ jsx34(
7992
+ /* @__PURE__ */ jsxs30(StickToBottom, { className: "h-full overflow-y-hidden", resize: "smooth", children: [
7993
+ /* @__PURE__ */ jsx35(StickToBottom.Content, { className: "px-5 py-6", children: /* @__PURE__ */ jsx35(
7841
7994
  MessageListContent,
7842
7995
  {
7843
7996
  askAnswers,
@@ -7854,7 +8007,7 @@ function MessageList({
7854
8007
  customization
7855
8008
  }
7856
8009
  ) }),
7857
- /* @__PURE__ */ jsx34(ScrollToBottomButton, {})
8010
+ /* @__PURE__ */ jsx35(ScrollToBottomButton, {})
7858
8011
  ] })
7859
8012
  ]
7860
8013
  }
@@ -7882,8 +8035,8 @@ function MessageListContent({
7882
8035
  }
7883
8036
  scrollToBottom();
7884
8037
  }, [lastTurnId, scrollToBottom]);
7885
- return /* @__PURE__ */ jsx34("div", { className: `mx-auto max-w-3xl ${customization?.classNames?.messageListContent ?? ""}`, children: /* @__PURE__ */ jsxs29("div", { className: `min-w-0 flex flex-col gap-8 ${customization?.classNames?.messageListInner ?? ""}`, children: [
7886
- stickyTurn ? /* @__PURE__ */ jsx34(
8038
+ return /* @__PURE__ */ jsx35("div", { className: `mx-auto max-w-3xl ${customization?.classNames?.messageListContent ?? ""}`, children: /* @__PURE__ */ jsxs30("div", { className: `min-w-0 flex flex-col gap-8 ${customization?.classNames?.messageListInner ?? ""}`, children: [
8039
+ stickyTurn ? /* @__PURE__ */ jsx35(
7887
8040
  StickyStatusBar,
7888
8041
  {
7889
8042
  sessionId,
@@ -7893,31 +8046,31 @@ function MessageListContent({
7893
8046
  onJumpToLatest: handleJumpToLatest
7894
8047
  }
7895
8048
  ) : null,
7896
- renderBlocks.length === 0 ? customization?.components?.EmptyState ? /* @__PURE__ */ jsx34(customization.components.EmptyState, {}) : /* @__PURE__ */ jsxs29("div", { className: `flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))] ${customization?.classNames?.emptyState ?? ""}`, children: [
7897
- /* @__PURE__ */ jsx34(MessageSquare, { size: 40, strokeWidth: 1.5 }),
7898
- /* @__PURE__ */ jsx34("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
7899
- /* @__PURE__ */ jsx34("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
8049
+ renderBlocks.length === 0 ? customization?.components?.EmptyState ? /* @__PURE__ */ jsx35(customization.components.EmptyState, {}) : /* @__PURE__ */ jsxs30("div", { className: `flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))] ${customization?.classNames?.emptyState ?? ""}`, children: [
8050
+ /* @__PURE__ */ jsx35(MessageSquare, { size: 40, strokeWidth: 1.5 }),
8051
+ /* @__PURE__ */ jsx35("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
8052
+ /* @__PURE__ */ jsx35("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
7900
8053
  ] }) : renderBlocks.map((block, blockIndex) => {
7901
8054
  if (block.type === "message") {
7902
- return /* @__PURE__ */ jsx34("div", { className: "msg-animate", children: isUserMessage(block.message) ? customization?.components?.UserMessage ? /* @__PURE__ */ jsx34(
8055
+ return /* @__PURE__ */ jsx35("div", { className: "msg-animate", children: isUserMessage(block.message) ? customization?.components?.UserMessage ? /* @__PURE__ */ jsx35(
7903
8056
  customization.components.UserMessage,
7904
8057
  {
7905
8058
  message: block.message,
7906
8059
  className: customization.classNames?.userMessage
7907
8060
  }
7908
- ) : /* @__PURE__ */ jsx34(
8061
+ ) : /* @__PURE__ */ jsx35(
7909
8062
  UserMessageBubble,
7910
8063
  {
7911
8064
  message: block.message,
7912
8065
  className: customization?.classNames?.userMessage
7913
8066
  }
7914
- ) : isErrorMessage(block.message) ? customization?.components?.ErrorMessage ? /* @__PURE__ */ jsx34(
8067
+ ) : isErrorMessage(block.message) ? customization?.components?.ErrorMessage ? /* @__PURE__ */ jsx35(
7915
8068
  customization.components.ErrorMessage,
7916
8069
  {
7917
8070
  message: block.message,
7918
8071
  className: customization.classNames?.errorMessage
7919
8072
  }
7920
- ) : /* @__PURE__ */ jsx34(
8073
+ ) : /* @__PURE__ */ jsx35(
7921
8074
  ErrorMessageBlock,
7922
8075
  {
7923
8076
  message: block.message,
@@ -7934,20 +8087,20 @@ function MessageListContent({
7934
8087
  );
7935
8088
  const isFollowedByPlanningExit = nextBlock?.type === "planning_divider" && nextBlock.kind === "planning_exit";
7936
8089
  const showPlanCard = (hasExitPlan || isFollowedByPlanningExit) && onConfirmPlan && sessionStatus === "waiting_for_input";
7937
- return /* @__PURE__ */ jsxs29(
8090
+ return /* @__PURE__ */ jsxs30(
7938
8091
  "div",
7939
8092
  {
7940
8093
  id: block.anchorId,
7941
8094
  "data-turn-id": block.anchorId,
7942
8095
  className: "msg-animate flex scroll-mt-6 flex-col gap-4",
7943
8096
  children: [
7944
- /* @__PURE__ */ jsx34(
8097
+ /* @__PURE__ */ jsx35(
7945
8098
  RenderErrorBoundary,
7946
8099
  {
7947
8100
  label: "\u52A9\u624B\u6D88\u606F",
7948
8101
  details: block.key,
7949
8102
  resetKey: getMessagesRenderSignature(block.messages),
7950
- children: customization?.components?.AssistantTurn ? /* @__PURE__ */ jsx34(
8103
+ children: customization?.components?.AssistantTurn ? /* @__PURE__ */ jsx35(
7951
8104
  customization.components.AssistantTurn,
7952
8105
  {
7953
8106
  turnKey: block.key,
@@ -7960,7 +8113,7 @@ function MessageListContent({
7960
8113
  sessionStatus,
7961
8114
  customization
7962
8115
  }
7963
- ) : /* @__PURE__ */ jsx34(
8116
+ ) : /* @__PURE__ */ jsx35(
7964
8117
  AssistantTurnBlock,
7965
8118
  {
7966
8119
  turnKey: block.key,
@@ -7976,13 +8129,13 @@ function MessageListContent({
7976
8129
  )
7977
8130
  }
7978
8131
  ),
7979
- showPlanCard ? /* @__PURE__ */ jsx34(
8132
+ showPlanCard ? /* @__PURE__ */ jsx35(
7980
8133
  RenderErrorBoundary,
7981
8134
  {
7982
8135
  label: "\u89C4\u5212\u6458\u8981",
7983
8136
  details: block.key,
7984
8137
  resetKey: `${sessionStatus ?? ""}:${layoutSignature}`,
7985
- children: /* @__PURE__ */ jsx34(
8138
+ children: /* @__PURE__ */ jsx35(
7986
8139
  PlanSummaryCard,
7987
8140
  {
7988
8141
  messages: extractLatestPlanMessages(messages),
@@ -7998,7 +8151,7 @@ function MessageListContent({
7998
8151
  );
7999
8152
  }
8000
8153
  if (block.type === "compaction") {
8001
- return /* @__PURE__ */ jsx34("div", { className: "msg-animate", children: /* @__PURE__ */ jsx34(
8154
+ return /* @__PURE__ */ jsx35("div", { className: "msg-animate", children: /* @__PURE__ */ jsx35(
8002
8155
  CompactionCard,
8003
8156
  {
8004
8157
  sessionId,
@@ -8007,41 +8160,41 @@ function MessageListContent({
8007
8160
  }
8008
8161
  ) }, block.key);
8009
8162
  }
8010
- return /* @__PURE__ */ jsx34(PlanningDivider, { kind: block.kind }, block.key);
8163
+ return /* @__PURE__ */ jsx35(PlanningDivider, { kind: block.kind }, block.key);
8011
8164
  }),
8012
- sessionStatus === "interrupted" && !hasInterruptedTurn ? /* @__PURE__ */ jsx34("div", { className: "flex", children: /* @__PURE__ */ jsx34("div", { className: "rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }) }) : null
8165
+ sessionStatus === "interrupted" && !hasInterruptedTurn ? /* @__PURE__ */ jsx35("div", { className: "flex", children: /* @__PURE__ */ jsx35("div", { className: "rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }) }) : null
8013
8166
  ] }) });
8014
8167
  }
8015
8168
  function ScrollToBottomButton() {
8016
8169
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
8017
8170
  if (isAtBottom) return null;
8018
- return /* @__PURE__ */ jsxs29(
8171
+ return /* @__PURE__ */ jsxs30(
8019
8172
  "button",
8020
8173
  {
8021
8174
  type: "button",
8022
8175
  onClick: () => scrollToBottom(),
8023
8176
  className: "absolute bottom-4 right-4 flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-1.5 text-xs text-[hsl(var(--muted-foreground))] shadow-lg transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
8024
8177
  children: [
8025
- /* @__PURE__ */ jsx34(ChevronDown3, { size: 14 }),
8026
- /* @__PURE__ */ jsx34("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
8178
+ /* @__PURE__ */ jsx35(ChevronDown3, { size: 14 }),
8179
+ /* @__PURE__ */ jsx35("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
8027
8180
  ]
8028
8181
  }
8029
8182
  );
8030
8183
  }
8031
8184
  function PlanningDivider({ kind }) {
8032
8185
  const isEnter = kind === "planning_enter";
8033
- return /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-3 py-1", children: [
8034
- /* @__PURE__ */ jsx34("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
8035
- /* @__PURE__ */ jsxs29("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-amber-500/30 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-300", children: [
8036
- /* @__PURE__ */ jsx34(Lightbulb2, { size: 12 }),
8037
- /* @__PURE__ */ jsx34("span", { children: isEnter ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
8186
+ return /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-3 py-1", children: [
8187
+ /* @__PURE__ */ jsx35("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
8188
+ /* @__PURE__ */ jsxs30("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-amber-500/30 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-300", children: [
8189
+ /* @__PURE__ */ jsx35(Lightbulb2, { size: 12 }),
8190
+ /* @__PURE__ */ jsx35("span", { children: isEnter ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
8038
8191
  ] }),
8039
- /* @__PURE__ */ jsx34("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
8192
+ /* @__PURE__ */ jsx35("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
8040
8193
  ] });
8041
8194
  }
8042
8195
 
8043
8196
  // src/react/components/chat/ChatView.tsx
8044
- import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
8197
+ import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
8045
8198
  function ChatView({
8046
8199
  sessionId,
8047
8200
  renderAttachments,
@@ -8080,13 +8233,13 @@ function ChatView({
8080
8233
  );
8081
8234
  const customization = { classNames, components, renderers };
8082
8235
  const SkillStatus = components?.SkillStatusBar;
8083
- return /* @__PURE__ */ jsxs30("div", { className: `flex min-h-0 flex-1 flex-col overflow-hidden ${classNames?.root ?? ""}`, children: [
8084
- isViewer && /* @__PURE__ */ jsxs30("div", { className: `flex items-center justify-center gap-2 border-b border-[hsl(var(--border))] bg-[hsl(var(--card))] py-2 text-xs text-[hsl(var(--muted-foreground))] ${classNames?.viewerBanner ?? ""}`, children: [
8085
- /* @__PURE__ */ jsx35(Eye, { size: 14 }),
8236
+ return /* @__PURE__ */ jsxs31("div", { className: `flex min-h-0 flex-1 flex-col overflow-hidden ${classNames?.root ?? ""}`, children: [
8237
+ isViewer && /* @__PURE__ */ jsxs31("div", { className: `flex items-center justify-center gap-2 border-b border-[hsl(var(--border))] bg-[hsl(var(--card))] py-2 text-xs text-[hsl(var(--muted-foreground))] ${classNames?.viewerBanner ?? ""}`, children: [
8238
+ /* @__PURE__ */ jsx36(Eye, { size: 14 }),
8086
8239
  "\u4F60\u6B63\u5728\u67E5\u770B\u5206\u4EAB\u7684\u4F1A\u8BDD\uFF08\u53EA\u8BFB\uFF09"
8087
8240
  ] }),
8088
- !isViewer && /* @__PURE__ */ jsx35(ConnectionBanner, {}),
8089
- /* @__PURE__ */ jsx35(
8241
+ !isViewer && /* @__PURE__ */ jsx36(ConnectionBanner, {}),
8242
+ /* @__PURE__ */ jsx36(
8090
8243
  MessageList,
8091
8244
  {
8092
8245
  sessionId,
@@ -8098,7 +8251,7 @@ function ChatView({
8098
8251
  },
8099
8252
  sessionId
8100
8253
  ),
8101
- !isViewer && /* @__PURE__ */ jsx35(
8254
+ !isViewer && /* @__PURE__ */ jsx36(
8102
8255
  ChatInput,
8103
8256
  {
8104
8257
  onSend: (msg, _targetSessionId, model) => send(msg, mode, void 0, { model: model || void 0 }),
@@ -8173,4 +8326,4 @@ use-stick-to-bottom/dist/StickToBottom.js:
8173
8326
  * Licensed under the MIT License. See License.txt in the project root for license information.
8174
8327
  *--------------------------------------------------------------------------------------------*)
8175
8328
  */
8176
- //# sourceMappingURL=chunk-ZGM3H24C.js.map
8329
+ //# sourceMappingURL=chunk-75BPCDBW.js.map