@blade-hq/agent-react 2610.0.0-beta.48 → 2610.0.0-beta.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1147,7 +1147,145 @@ var X = createLucideIcon("X", [
1147
1147
  ]);
1148
1148
 
1149
1149
  // src/components/AgentChat.tsx
1150
- import { useCallback as useCallback8, useEffect as useEffect12, useMemo as useMemo8, useState as useState15 } from "react";
1150
+ import { useCallback as useCallback8, useEffect as useEffect13, useMemo as useMemo8, useState as useState16 } from "react";
1151
+
1152
+ // src/components/SessionPluginSelector.tsx
1153
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1154
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1155
+ function SessionPluginSelector(props) {
1156
+ return /* @__PURE__ */ jsx2(PluginSelectorState, { ...props }, props.sessionId);
1157
+ }
1158
+ function PluginSelectorState({ client, sessionId, className, side = "bottom", onChange }) {
1159
+ const [open, setOpen] = useState4(false);
1160
+ const [plugins, setPlugins] = useState4([]);
1161
+ const [loading, setLoading] = useState4(false);
1162
+ const [busy, setBusy] = useState4(false);
1163
+ const [listError, setListError] = useState4(false);
1164
+ const [mutationError, setMutationError] = useState4(false);
1165
+ const alive = useRef4(true);
1166
+ const generation = useRef4(0);
1167
+ const mutationGenerations = useRef4(/* @__PURE__ */ new Map());
1168
+ const desiredActivations = useRef4(/* @__PURE__ */ new Map());
1169
+ const pendingMutations = useRef4(/* @__PURE__ */ new Map());
1170
+ const lifetime = useRef4(0);
1171
+ const request = useRef4(null);
1172
+ useEffect4(() => {
1173
+ alive.current = true;
1174
+ setPlugins([]);
1175
+ setOpen(false);
1176
+ setLoading(false);
1177
+ setBusy(false);
1178
+ setListError(false);
1179
+ setMutationError(false);
1180
+ desiredActivations.current.clear();
1181
+ mutationGenerations.current.clear();
1182
+ pendingMutations.current.clear();
1183
+ return () => {
1184
+ alive.current = false;
1185
+ lifetime.current++;
1186
+ generation.current++;
1187
+ request.current?.abort();
1188
+ };
1189
+ }, [client]);
1190
+ const load = async () => {
1191
+ if (!alive.current) return;
1192
+ request.current?.abort();
1193
+ const controller = new AbortController();
1194
+ request.current = controller;
1195
+ const current = ++generation.current;
1196
+ setLoading(true);
1197
+ setListError(false);
1198
+ try {
1199
+ const result = await client.sessions.listSessionPlugins(sessionId, { signal: controller.signal });
1200
+ if (alive.current && current === generation.current) {
1201
+ setPlugins(result.plugins.map((item) => {
1202
+ const pending = pendingMutations.current.has(item.name);
1203
+ const desired = desiredActivations.current.get(item.name);
1204
+ return pending && desired !== void 0 ? { ...item, active: desired } : item;
1205
+ }));
1206
+ }
1207
+ } catch {
1208
+ if (alive.current && current === generation.current && !controller.signal.aborted) setListError(true);
1209
+ } finally {
1210
+ if (alive.current && current === generation.current) setLoading(false);
1211
+ }
1212
+ };
1213
+ const select = async (name, active) => {
1214
+ desiredActivations.current.set(name, active);
1215
+ const currentLifetime = lifetime.current;
1216
+ const currentMutation = (mutationGenerations.current.get(name) ?? 0) + 1;
1217
+ mutationGenerations.current.set(name, currentMutation);
1218
+ pendingMutations.current.set(name, currentMutation);
1219
+ request.current?.abort();
1220
+ generation.current++;
1221
+ setLoading(false);
1222
+ setBusy(true);
1223
+ setMutationError(false);
1224
+ setPlugins((current) => current.map((item) => item.name === name ? { ...item, active } : item));
1225
+ try {
1226
+ const { plugin } = await client.sessions.setSessionPluginActivation(sessionId, name, active);
1227
+ if (!alive.current || currentLifetime !== lifetime.current) return;
1228
+ if (currentMutation !== mutationGenerations.current.get(name)) {
1229
+ const desired = desiredActivations.current.get(name);
1230
+ if (desired !== void 0 && desired !== plugin.active) void select(name, desired);
1231
+ return;
1232
+ }
1233
+ pendingMutations.current.delete(name);
1234
+ setBusy(pendingMutations.current.size > 0);
1235
+ setPlugins((current) => current.map((item) => item.name === plugin.name ? { ...item, ...plugin } : item));
1236
+ onChange?.(plugin);
1237
+ await load();
1238
+ } catch {
1239
+ if (alive.current && currentLifetime === lifetime.current && currentMutation === mutationGenerations.current.get(name)) {
1240
+ pendingMutations.current.delete(name);
1241
+ setBusy(pendingMutations.current.size > 0);
1242
+ setMutationError(true);
1243
+ void load();
1244
+ }
1245
+ }
1246
+ };
1247
+ return /* @__PURE__ */ jsxs("div", { className: `relative text-xs ${className ?? ""}`, children: [
1248
+ /* @__PURE__ */ jsx2(
1249
+ "button",
1250
+ {
1251
+ type: "button",
1252
+ disabled: !sessionId,
1253
+ "aria-expanded": open,
1254
+ onClick: () => {
1255
+ setOpen(!open);
1256
+ if (!open) void load();
1257
+ },
1258
+ className: "rounded-full border border-[hsl(var(--border))] px-2.5 py-1",
1259
+ children: "\u4F1A\u8BDD\u63D2\u4EF6"
1260
+ }
1261
+ ),
1262
+ open ? /* @__PURE__ */ jsxs("div", { className: `absolute left-0 z-40 my-2 max-h-72 w-72 max-w-[calc(100vw-2rem)] overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-[hsl(var(--popover-foreground))] shadow-lg ${side === "top" ? "bottom-full" : "top-full"}`, children: [
1263
+ loading ? /* @__PURE__ */ jsx2("div", { children: "\u6B63\u5728\u83B7\u53D6\u63D2\u4EF6\u2026" }) : null,
1264
+ listError ? /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => void load(), children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5" }) : null,
1265
+ !loading && !listError && !plugins.length ? /* @__PURE__ */ jsx2("div", { children: "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6" }) : null,
1266
+ plugins.map((plugin) => /* @__PURE__ */ jsxs("div", { className: "py-1", children: [
1267
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center justify-between gap-2", children: [
1268
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: plugin.name }),
1269
+ /* @__PURE__ */ jsx2(
1270
+ "input",
1271
+ {
1272
+ type: "checkbox",
1273
+ checked: plugin.active,
1274
+ disabled: busy && !plugin.active || !plugin.installed && !plugin.active,
1275
+ onChange: (event) => void select(plugin.name, event.target.checked),
1276
+ "aria-label": `${plugin.name} \u4F1A\u8BDD\u6FC0\u6D3B`
1277
+ }
1278
+ )
1279
+ ] }),
1280
+ plugin.active && plugin.status !== "valid" ? /* @__PURE__ */ jsxs("div", { className: "text-[hsl(var(--muted-foreground))]", children: [
1281
+ plugin.reason || "\u63D2\u4EF6\u6682\u4E0D\u53EF\u7528",
1282
+ /* @__PURE__ */ jsx2("button", { type: "button", disabled: busy, onClick: () => void select(plugin.name, true), className: "ml-2 underline", children: "\u91CD\u8BD5" })
1283
+ ] }) : null
1284
+ ] }, plugin.name)),
1285
+ mutationError ? /* @__PURE__ */ jsx2("div", { children: "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5" }) : null
1286
+ ] }) : null
1287
+ ] });
1288
+ }
1151
1289
 
1152
1290
  // src/lib/utils.ts
1153
1291
  function cn(...inputs) {
@@ -1179,7 +1317,7 @@ async function copyToClipboard(text) {
1179
1317
  }
1180
1318
 
1181
1319
  // src/components/ReplayBar.tsx
1182
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1320
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1183
1321
  var SPEED_OPTIONS = [1, 2, 5];
1184
1322
  function ReplayBar({
1185
1323
  isReplay,
@@ -1190,7 +1328,7 @@ function ReplayBar({
1190
1328
  className
1191
1329
  }) {
1192
1330
  if (!isReplay) return null;
1193
- return /* @__PURE__ */ jsxs(
1331
+ return /* @__PURE__ */ jsxs2(
1194
1332
  "div",
1195
1333
  {
1196
1334
  className: cn(
@@ -1198,13 +1336,13 @@ function ReplayBar({
1198
1336
  className
1199
1337
  ),
1200
1338
  children: [
1201
- /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 font-medium text-[hsl(var(--foreground))]", children: [
1202
- /* @__PURE__ */ jsx2(Play, { size: 13 }),
1339
+ /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-1.5 font-medium text-[hsl(var(--foreground))]", children: [
1340
+ /* @__PURE__ */ jsx3(Play, { size: 13 }),
1203
1341
  "\u56DE\u653E\u6A21\u5F0F"
1204
1342
  ] }),
1205
- /* @__PURE__ */ jsx2("span", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u91CD\u73B0\u4E4B\u524D\u7684\u5BF9\u8BDD" }),
1206
- /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
1207
- /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-0.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-0.5", children: SPEED_OPTIONS.map((option) => /* @__PURE__ */ jsxs(
1343
+ /* @__PURE__ */ jsx3("span", { className: "text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u91CD\u73B0\u4E4B\u524D\u7684\u5BF9\u8BDD" }),
1344
+ /* @__PURE__ */ jsxs2("div", { className: "ml-auto flex items-center gap-2", children: [
1345
+ /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-0.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-0.5", children: SPEED_OPTIONS.map((option) => /* @__PURE__ */ jsxs2(
1208
1346
  "button",
1209
1347
  {
1210
1348
  type: "button",
@@ -1223,7 +1361,7 @@ function ReplayBar({
1223
1361
  },
1224
1362
  option
1225
1363
  )) }),
1226
- /* @__PURE__ */ jsx2(
1364
+ /* @__PURE__ */ jsx3(
1227
1365
  "button",
1228
1366
  {
1229
1367
  type: "button",
@@ -1243,10 +1381,10 @@ function ReplayBar({
1243
1381
  }
1244
1382
 
1245
1383
  // src/components/ReplayMismatchPrompt.tsx
1246
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1384
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1247
1385
  function ReplayMismatchPrompt({ mismatch, className }) {
1248
1386
  if (!mismatch) return null;
1249
- return /* @__PURE__ */ jsxs2(
1387
+ return /* @__PURE__ */ jsxs3(
1250
1388
  "div",
1251
1389
  {
1252
1390
  className: cn(
@@ -1254,19 +1392,19 @@ function ReplayMismatchPrompt({ mismatch, className }) {
1254
1392
  className
1255
1393
  ),
1256
1394
  children: [
1257
- /* @__PURE__ */ jsx3("div", { className: "font-medium text-[hsl(var(--foreground))]", children: "\u8FD9\u53E5\u8BDD\u548C\u4E4B\u524D\u5F55\u5236\u7684\u4E0D\u4E00\u6837" }),
1258
- /* @__PURE__ */ jsxs2("dl", { className: "mt-2 space-y-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
1259
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
1260
- /* @__PURE__ */ jsx3("dt", { className: "shrink-0", children: "\u5F55\u5236\u7684\u662F" }),
1261
- /* @__PURE__ */ jsx3("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.expectedMessage || "\uFF08\u7A7A\uFF09" })
1395
+ /* @__PURE__ */ jsx4("div", { className: "font-medium text-[hsl(var(--foreground))]", children: "\u8FD9\u53E5\u8BDD\u548C\u4E4B\u524D\u5F55\u5236\u7684\u4E0D\u4E00\u6837" }),
1396
+ /* @__PURE__ */ jsxs3("dl", { className: "mt-2 space-y-1 text-xs text-[hsl(var(--muted-foreground))]", children: [
1397
+ /* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
1398
+ /* @__PURE__ */ jsx4("dt", { className: "shrink-0", children: "\u5F55\u5236\u7684\u662F" }),
1399
+ /* @__PURE__ */ jsx4("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.expectedMessage || "\uFF08\u7A7A\uFF09" })
1262
1400
  ] }),
1263
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
1264
- /* @__PURE__ */ jsx3("dt", { className: "shrink-0", children: "\u4F60\u8F93\u5165\u7684" }),
1265
- /* @__PURE__ */ jsx3("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.actualMessage || "\uFF08\u7A7A\uFF09" })
1401
+ /* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
1402
+ /* @__PURE__ */ jsx4("dt", { className: "shrink-0", children: "\u4F60\u8F93\u5165\u7684" }),
1403
+ /* @__PURE__ */ jsx4("dd", { className: "min-w-0 break-words text-[hsl(var(--foreground))]", children: mismatch.actualMessage || "\uFF08\u7A7A\uFF09" })
1266
1404
  ] })
1267
1405
  ] }),
1268
- /* @__PURE__ */ jsxs2("div", { className: "mt-3 flex flex-wrap gap-2", children: [
1269
- /* @__PURE__ */ jsx3(
1406
+ /* @__PURE__ */ jsxs3("div", { className: "mt-3 flex flex-wrap gap-2", children: [
1407
+ /* @__PURE__ */ jsx4(
1270
1408
  "button",
1271
1409
  {
1272
1410
  type: "button",
@@ -1275,7 +1413,7 @@ function ReplayMismatchPrompt({ mismatch, className }) {
1275
1413
  children: "\u6309\u5F55\u5236\u5185\u5BB9\u7EE7\u7EED"
1276
1414
  }
1277
1415
  ),
1278
- /* @__PURE__ */ jsx3(
1416
+ /* @__PURE__ */ jsx4(
1279
1417
  "button",
1280
1418
  {
1281
1419
  type: "button",
@@ -1291,7 +1429,7 @@ function ReplayMismatchPrompt({ mismatch, className }) {
1291
1429
  }
1292
1430
 
1293
1431
  // src/components/PlanUpdateBlock.tsx
1294
- import { useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1432
+ import { useEffect as useEffect5, useRef as useRef5, useState as useState5 } from "react";
1295
1433
 
1296
1434
  // src/components/display-utils.ts
1297
1435
  var TOOL_NAME_ALIASES = {
@@ -1435,7 +1573,7 @@ function formatToolResult(result) {
1435
1573
  }
1436
1574
 
1437
1575
  // src/components/PlanUpdateBlock.tsx
1438
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1576
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1439
1577
  var PLAN_STEP_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed"]);
1440
1578
  var PLAN_AUTO_COLLAPSE_MS = 5e3;
1441
1579
  function isPlanUpdateTool(toolCall) {
@@ -1490,12 +1628,12 @@ function PlanStepIcon({
1490
1628
  running = false
1491
1629
  }) {
1492
1630
  if (status === "completed") {
1493
- return /* @__PURE__ */ jsx4(Check, { size, strokeWidth: 2, className: "shrink-0 text-emerald-500" });
1631
+ return /* @__PURE__ */ jsx5(Check, { size, strokeWidth: 2, className: "shrink-0 text-emerald-500" });
1494
1632
  }
1495
1633
  if (status === "in_progress") {
1496
- return running ? /* @__PURE__ */ jsx4(LoaderCircle, { size, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx4(CircleDot, { size, className: "shrink-0 text-amber-500" });
1634
+ return running ? /* @__PURE__ */ jsx5(LoaderCircle, { size, className: "shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : /* @__PURE__ */ jsx5(CircleDot, { size, className: "shrink-0 text-amber-500" });
1497
1635
  }
1498
- return /* @__PURE__ */ jsx4(Circle, { size, className: "shrink-0 text-[hsl(var(--muted-foreground))]/60" });
1636
+ return /* @__PURE__ */ jsx5(Circle, { size, className: "shrink-0 text-[hsl(var(--muted-foreground))]/60" });
1499
1637
  }
1500
1638
  function PlanUpdateBlock({
1501
1639
  toolCall,
@@ -1504,10 +1642,10 @@ function PlanUpdateBlock({
1504
1642
  }) {
1505
1643
  const updateKey = `${toolCall.id}:${toolCall.arguments}`;
1506
1644
  const revealKey = autoReveal ? updateKey : null;
1507
- const [collapsed, setCollapsed] = useState4(!autoReveal);
1508
- const collapseTimerRef = useRef4(null);
1645
+ const [collapsed, setCollapsed] = useState5(!autoReveal);
1646
+ const collapseTimerRef = useRef5(null);
1509
1647
  const data = parsePlanUpdate(toolCall.arguments);
1510
- useEffect4(() => {
1648
+ useEffect5(() => {
1511
1649
  if (!revealKey) return;
1512
1650
  if (collapseTimerRef.current) clearTimeout(collapseTimerRef.current);
1513
1651
  setCollapsed(false);
@@ -1516,7 +1654,7 @@ function PlanUpdateBlock({
1516
1654
  collapseTimerRef.current = null;
1517
1655
  }, PLAN_AUTO_COLLAPSE_MS);
1518
1656
  }, [revealKey]);
1519
- useEffect4(
1657
+ useEffect5(
1520
1658
  () => () => {
1521
1659
  if (collapseTimerRef.current) clearTimeout(collapseTimerRef.current);
1522
1660
  },
@@ -1526,8 +1664,8 @@ function PlanUpdateBlock({
1526
1664
  const completed = data.plan.filter((item) => item.status === "completed").length;
1527
1665
  const currentStep = pickCurrentPlanStep(data.plan);
1528
1666
  const pausedAtCurrentStep = !running && currentStep?.status === "in_progress";
1529
- return /* @__PURE__ */ jsxs3("section", { className: "overflow-hidden", children: [
1530
- /* @__PURE__ */ jsxs3(
1667
+ return /* @__PURE__ */ jsxs4("section", { className: "overflow-hidden", children: [
1668
+ /* @__PURE__ */ jsxs4(
1531
1669
  "button",
1532
1670
  {
1533
1671
  type: "button",
@@ -1544,21 +1682,21 @@ function PlanUpdateBlock({
1544
1682
  !collapsed && "border-b border-[hsl(var(--border))]"
1545
1683
  ),
1546
1684
  children: [
1547
- collapsed && currentStep ? /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-xs text-[hsl(var(--foreground))]", children: [
1548
- /* @__PURE__ */ jsx4(PlanStepIcon, { status: currentStep.status, size: 14, running }),
1549
- /* @__PURE__ */ jsx4("span", { className: "truncate", children: currentStep.step }),
1550
- pausedAtCurrentStep ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-[11px] text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
1551
- ] }) : /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
1552
- /* @__PURE__ */ jsx4(ListChecks, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
1553
- /* @__PURE__ */ jsx4("span", { className: "truncate", children: "\u4EFB\u52A1\u8FDB\u5EA6" }),
1554
- pausedAtCurrentStep ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
1685
+ collapsed && currentStep ? /* @__PURE__ */ jsxs4("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-xs text-[hsl(var(--foreground))]", children: [
1686
+ /* @__PURE__ */ jsx5(PlanStepIcon, { status: currentStep.status, size: 14, running }),
1687
+ /* @__PURE__ */ jsx5("span", { className: "truncate", children: currentStep.step }),
1688
+ pausedAtCurrentStep ? /* @__PURE__ */ jsx5("span", { className: "shrink-0 text-[11px] text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
1689
+ ] }) : /* @__PURE__ */ jsxs4("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
1690
+ /* @__PURE__ */ jsx5(ListChecks, { size: 14, className: "shrink-0", "aria-hidden": "true" }),
1691
+ /* @__PURE__ */ jsx5("span", { className: "truncate", children: "\u4EFB\u52A1\u8FDB\u5EA6" }),
1692
+ pausedAtCurrentStep ? /* @__PURE__ */ jsx5("span", { className: "shrink-0 text-amber-500", children: "\u5DF2\u6682\u505C" }) : null
1555
1693
  ] }),
1556
- /* @__PURE__ */ jsxs3("span", { className: "shrink-0 text-[11px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
1694
+ /* @__PURE__ */ jsxs4("span", { className: "shrink-0 text-[11px] tabular-nums text-[hsl(var(--muted-foreground))]", children: [
1557
1695
  completed,
1558
1696
  "/",
1559
1697
  data.plan.length
1560
1698
  ] }),
1561
- /* @__PURE__ */ jsx4(
1699
+ /* @__PURE__ */ jsx5(
1562
1700
  ChevronDown,
1563
1701
  {
1564
1702
  size: 14,
@@ -1571,7 +1709,7 @@ function PlanUpdateBlock({
1571
1709
  ]
1572
1710
  }
1573
1711
  ),
1574
- /* @__PURE__ */ jsx4(
1712
+ /* @__PURE__ */ jsx5(
1575
1713
  "div",
1576
1714
  {
1577
1715
  "aria-hidden": collapsed,
@@ -1579,9 +1717,9 @@ function PlanUpdateBlock({
1579
1717
  "grid transition-[grid-template-rows,opacity] duration-300 ease-out motion-reduce:transition-none",
1580
1718
  collapsed ? "grid-rows-[0fr] opacity-0" : "grid-rows-[1fr] opacity-100"
1581
1719
  ),
1582
- children: /* @__PURE__ */ jsx4("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx4("div", { className: "flex max-h-40 flex-col gap-0.5 overflow-y-auto px-3 py-2", children: data.plan.length === 0 ? /* @__PURE__ */ jsx4("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u4EFB\u52A1\u6B65\u9AA4" }) : data.plan.map((item, index) => /* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-2 py-0.5", children: [
1583
- /* @__PURE__ */ jsx4("span", { className: "mt-[3px] flex shrink-0", children: /* @__PURE__ */ jsx4(PlanStepIcon, { status: item.status, size: 14, running }) }),
1584
- /* @__PURE__ */ jsx4(
1720
+ children: /* @__PURE__ */ jsx5("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx5("div", { className: "flex max-h-40 flex-col gap-0.5 overflow-y-auto px-3 py-2", children: data.plan.length === 0 ? /* @__PURE__ */ jsx5("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6682\u65E0\u4EFB\u52A1\u6B65\u9AA4" }) : data.plan.map((item, index) => /* @__PURE__ */ jsxs4("div", { className: "flex items-start gap-2 py-0.5", children: [
1721
+ /* @__PURE__ */ jsx5("span", { className: "mt-[3px] flex shrink-0", children: /* @__PURE__ */ jsx5(PlanStepIcon, { status: item.status, size: 14, running }) }),
1722
+ /* @__PURE__ */ jsx5(
1585
1723
  "span",
1586
1724
  {
1587
1725
  className: cn(
@@ -1604,19 +1742,19 @@ function CurrentPlanPanel({
1604
1742
  className
1605
1743
  }) {
1606
1744
  const { current, updating } = getPlanUpdateDisplayState(messages);
1607
- const revealBaselinesRef = useRef4(/* @__PURE__ */ new Map([[sessionId, revealRevision]]));
1745
+ const revealBaselinesRef = useRef5(/* @__PURE__ */ new Map([[sessionId, revealRevision]]));
1608
1746
  const autoReveal = (revealBaselinesRef.current.get(sessionId) ?? 0) !== revealRevision;
1609
- useEffect4(() => {
1747
+ useEffect5(() => {
1610
1748
  if (!current) return;
1611
1749
  revealBaselinesRef.current.set(sessionId, revealRevision);
1612
1750
  }, [current, revealRevision, sessionId]);
1613
1751
  if (!current && !updating) return null;
1614
- return /* @__PURE__ */ jsxs3("div", { className: cn("blade-chat-plan mx-auto w-full max-w-[748px] px-4", className), children: [
1615
- updating ? /* @__PURE__ */ jsxs3("div", { className: "mb-2 flex items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
1616
- /* @__PURE__ */ jsx4(LoaderCircle, { size: 14, className: "shrink-0 animate-spin" }),
1617
- /* @__PURE__ */ jsx4("span", { children: "\u6B63\u5728\u66F4\u65B0\u4EFB\u52A1\u8FDB\u5EA6\u2026" })
1752
+ return /* @__PURE__ */ jsxs4("div", { className: cn("blade-chat-plan mx-auto w-full max-w-[748px] px-4", className), children: [
1753
+ updating ? /* @__PURE__ */ jsxs4("div", { className: "mb-2 flex items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
1754
+ /* @__PURE__ */ jsx5(LoaderCircle, { size: 14, className: "shrink-0 animate-spin" }),
1755
+ /* @__PURE__ */ jsx5("span", { children: "\u6B63\u5728\u66F4\u65B0\u4EFB\u52A1\u8FDB\u5EA6\u2026" })
1618
1756
  ] }) : null,
1619
- current ? /* @__PURE__ */ jsx4(
1757
+ current ? /* @__PURE__ */ jsx5(
1620
1758
  PlanUpdateBlock,
1621
1759
  {
1622
1760
  toolCall: current,
@@ -1632,8 +1770,8 @@ function CurrentPlanPanel({
1632
1770
  import { chatErrorForDisplay as chatErrorForDisplay2 } from "@blade-hq/agent-client";
1633
1771
 
1634
1772
  // src/components/ChatInput.tsx
1635
- import { useState as useState5 } from "react";
1636
- import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1773
+ import { useState as useState6 } from "react";
1774
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1637
1775
  function isImeCompositionKey(event) {
1638
1776
  return event.isComposing || event.keyCode === 229;
1639
1777
  }
@@ -1653,7 +1791,7 @@ function ChatInput({
1653
1791
  queueKey
1654
1792
  }) {
1655
1793
  const trimmed = value.trim();
1656
- const [sendMode, setSendMode] = useState5("queue");
1794
+ const [sendMode, setSendMode] = useState6("queue");
1657
1795
  void queueKey;
1658
1796
  const canSend = trimmed.length > 0 && (!isStreaming || !isStopping && sendMode === "queue" && !!onAppend);
1659
1797
  const handleSend = async () => {
@@ -1684,14 +1822,14 @@ function ChatInput({
1684
1822
  void handleSend();
1685
1823
  }
1686
1824
  };
1687
- return /* @__PURE__ */ jsxs4("div", { className: cn("blade-chat-input border-t border-[hsl(var(--border))] py-3", className), children: [
1688
- /* @__PURE__ */ jsx5("div", { className: "mx-auto mb-2 flex max-w-[748px] items-center justify-between px-1 text-xs text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsxs4("fieldset", { className: "flex items-center gap-1 rounded-md border border-[hsl(var(--border))] p-0.5", children: [
1689
- /* @__PURE__ */ jsx5("legend", { className: "sr-only", children: "\u53D1\u9001\u65B9\u5F0F" }),
1690
- /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => setSendMode("direct"), "aria-pressed": sendMode === "direct", disabled: isStreaming && !onAppend, className: `rounded px-2 py-1 ${sendMode === "direct" ? "bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]" : ""}`, children: "\u76F4\u63A5\u63D2\u5165" }),
1691
- /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => setSendMode("queue"), "aria-pressed": sendMode === "queue", className: `rounded px-2 py-1 ${sendMode === "queue" ? "bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]" : ""}`, children: "\u6392\u961F\u6267\u884C" })
1825
+ return /* @__PURE__ */ jsxs5("div", { className: cn("blade-chat-input border-t border-[hsl(var(--border))] py-3", className), children: [
1826
+ /* @__PURE__ */ jsx6("div", { className: "mx-auto mb-2 flex max-w-[748px] items-center justify-between px-1 text-xs text-[hsl(var(--muted-foreground))]", children: /* @__PURE__ */ jsxs5("fieldset", { className: "flex items-center gap-1 rounded-md border border-[hsl(var(--border))] p-0.5", children: [
1827
+ /* @__PURE__ */ jsx6("legend", { className: "sr-only", children: "\u53D1\u9001\u65B9\u5F0F" }),
1828
+ /* @__PURE__ */ jsx6("button", { type: "button", onClick: () => setSendMode("direct"), "aria-pressed": sendMode === "direct", disabled: isStreaming && !onAppend, className: `rounded px-2 py-1 ${sendMode === "direct" ? "bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]" : ""}`, children: "\u76F4\u63A5\u63D2\u5165" }),
1829
+ /* @__PURE__ */ jsx6("button", { type: "button", onClick: () => setSendMode("queue"), "aria-pressed": sendMode === "queue", className: `rounded px-2 py-1 ${sendMode === "queue" ? "bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]" : ""}`, children: "\u6392\u961F\u6267\u884C" })
1692
1830
  ] }) }),
1693
- /* @__PURE__ */ jsxs4("div", { className: "blade-chat-input-inner mx-auto flex max-w-[748px] items-end gap-2 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2", children: [
1694
- /* @__PURE__ */ jsx5(
1831
+ /* @__PURE__ */ jsxs5("div", { className: "blade-chat-input-inner mx-auto flex max-w-[748px] items-end gap-2 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-2", children: [
1832
+ /* @__PURE__ */ jsx6(
1695
1833
  "textarea",
1696
1834
  {
1697
1835
  value,
@@ -1708,10 +1846,10 @@ function ChatInput({
1708
1846
  className: "blade-chat-textarea max-h-48 min-h-[28px] flex-1 resize-none bg-transparent py-1 text-sm leading-6 text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground)/0.6)]"
1709
1847
  }
1710
1848
  ),
1711
- isStreaming ? /* @__PURE__ */ jsxs4(Fragment, { children: [
1712
- sendMode === "queue" ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: handleSend, disabled: !canSend, "aria-label": "\u52A0\u5165\u6392\u961F", title: "\u52A0\u5165\u6392\u961F", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] disabled:opacity-40", children: /* @__PURE__ */ jsx5(ArrowUp, { size: 15 }) }) : null,
1713
- /* @__PURE__ */ jsx5("button", { type: "button", onClick: onStop, disabled: isStopping, "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--muted))] text-[hsl(var(--foreground))] transition-opacity hover:opacity-90 disabled:opacity-60", children: isStopping ? /* @__PURE__ */ jsx5(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx5(Square, { size: 12, fill: "currentColor" }) })
1714
- ] }) : /* @__PURE__ */ jsx5(
1849
+ isStreaming ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1850
+ sendMode === "queue" ? /* @__PURE__ */ jsx6("button", { type: "button", onClick: handleSend, disabled: !canSend, "aria-label": "\u52A0\u5165\u6392\u961F", title: "\u52A0\u5165\u6392\u961F", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] disabled:opacity-40", children: /* @__PURE__ */ jsx6(ArrowUp, { size: 15 }) }) : null,
1851
+ /* @__PURE__ */ jsx6("button", { type: "button", onClick: onStop, disabled: isStopping, "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D", className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--muted))] text-[hsl(var(--foreground))] transition-opacity hover:opacity-90 disabled:opacity-60", children: isStopping ? /* @__PURE__ */ jsx6(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx6(Square, { size: 12, fill: "currentColor" }) })
1852
+ ] }) : /* @__PURE__ */ jsx6(
1715
1853
  "button",
1716
1854
  {
1717
1855
  type: "button",
@@ -1720,7 +1858,7 @@ function ChatInput({
1720
1858
  "aria-label": "\u53D1\u9001\u6D88\u606F",
1721
1859
  title: "\u53D1\u9001\u6D88\u606F",
1722
1860
  className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40",
1723
- children: /* @__PURE__ */ jsx5(ArrowUp, { size: 15 })
1861
+ children: /* @__PURE__ */ jsx6(ArrowUp, { size: 15 })
1724
1862
  }
1725
1863
  )
1726
1864
  ] })
@@ -1728,16 +1866,16 @@ function ChatInput({
1728
1866
  }
1729
1867
 
1730
1868
  // src/components/ConnectionBanner.tsx
1731
- import { useEffect as useEffect5, useRef as useRef5, useState as useState6 } from "react";
1732
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1869
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState7 } from "react";
1870
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1733
1871
  var CONNECTION_NOTICE_DELAY_MS = 3e3;
1734
1872
  var CONNECTION_ERROR_DELAY_MS = 15e3;
1735
1873
  function useConnectionNoticePhase(connected) {
1736
- const [phase, setPhase] = useState6("hidden");
1737
- const connectedRef = useRef5(connected);
1738
- const timersRef = useRef5([]);
1874
+ const [phase, setPhase] = useState7("hidden");
1875
+ const connectedRef = useRef6(connected);
1876
+ const timersRef = useRef6([]);
1739
1877
  connectedRef.current = connected;
1740
- useEffect5(() => {
1878
+ useEffect6(() => {
1741
1879
  const clearTimers = () => {
1742
1880
  for (const timer of timersRef.current) clearTimeout(timer);
1743
1881
  timersRef.current = [];
@@ -1777,14 +1915,14 @@ function useConnectionNoticePhase(connected) {
1777
1915
  return phase;
1778
1916
  }
1779
1917
  function ConnectionBanner({ connection, className }) {
1780
- const hasConnectedRef = useRef5(connection === "connected" || connection === "reconnecting");
1918
+ const hasConnectedRef = useRef6(connection === "connected" || connection === "reconnecting");
1781
1919
  if (connection === "connected") hasConnectedRef.current = true;
1782
1920
  const connected = connection === "connected";
1783
1921
  const phase = useConnectionNoticePhase(connected);
1784
1922
  if (connected || phase === "hidden") return null;
1785
1923
  const recovering = phase === "recovering";
1786
1924
  const firstConnection = !hasConnectedRef.current;
1787
- return /* @__PURE__ */ jsx6("div", { className: cn("blade-chat-banner bg-[hsl(var(--background))] px-5 pt-3", className), children: /* @__PURE__ */ jsxs5(
1925
+ return /* @__PURE__ */ jsx7("div", { className: cn("blade-chat-banner bg-[hsl(var(--background))] px-5 pt-3", className), children: /* @__PURE__ */ jsxs6(
1788
1926
  "div",
1789
1927
  {
1790
1928
  className: cn(
@@ -1792,10 +1930,10 @@ function ConnectionBanner({ connection, className }) {
1792
1930
  recovering ? "border-amber-500/25 bg-amber-500/10 text-amber-100" : "border-rose-500/25 bg-rose-500/10 text-rose-100"
1793
1931
  ),
1794
1932
  children: [
1795
- /* @__PURE__ */ jsx6("span", { className: "mt-0.5 shrink-0", children: recovering ? /* @__PURE__ */ jsx6(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx6(TriangleAlert, { size: 14 }) }),
1796
- /* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
1797
- /* @__PURE__ */ jsx6("div", { className: "text-sm font-medium", children: recovering ? firstConnection ? "\u6B63\u5728\u8FDE\u63A5\u2026" : "\u6B63\u5728\u6062\u590D\u8FDE\u63A5\u2026" : "\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5" }),
1798
- /* @__PURE__ */ jsx6("div", { className: "text-xs opacity-80", children: recovering ? "\u6062\u590D\u540E\u4F1A\u81EA\u52A8\u540C\u6B65\u6700\u65B0\u6D88\u606F\uFF0C\u8BF7\u7A0D\u5019" : "\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u670D\u52A1\u72B6\u6001\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" })
1933
+ /* @__PURE__ */ jsx7("span", { className: "mt-0.5 shrink-0", children: recovering ? /* @__PURE__ */ jsx7(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx7(TriangleAlert, { size: 14 }) }),
1934
+ /* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
1935
+ /* @__PURE__ */ jsx7("div", { className: "text-sm font-medium", children: recovering ? firstConnection ? "\u6B63\u5728\u8FDE\u63A5\u2026" : "\u6B63\u5728\u6062\u590D\u8FDE\u63A5\u2026" : "\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5" }),
1936
+ /* @__PURE__ */ jsx7("div", { className: "text-xs opacity-80", children: recovering ? "\u6062\u590D\u540E\u4F1A\u81EA\u52A8\u540C\u6B65\u6700\u65B0\u6D88\u606F\uFF0C\u8BF7\u7A0D\u5019" : "\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u670D\u52A1\u72B6\u6001\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" })
1799
1937
  ] })
1800
1938
  ]
1801
1939
  }
@@ -1804,10 +1942,10 @@ function ConnectionBanner({ connection, className }) {
1804
1942
 
1805
1943
  // src/components/MessageList.tsx
1806
1944
  import { isHiddenInternalMessage } from "@blade-hq/agent-client";
1807
- import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo7, useRef as useRef12, useState as useState14 } from "react";
1945
+ import { useCallback as useCallback7, useEffect as useEffect12, useMemo as useMemo7, useRef as useRef13, useState as useState15 } from "react";
1808
1946
 
1809
1947
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
1810
- import { useCallback as useCallback4, useMemo as useMemo3, useRef as useRef6, useState as useState7 } from "react";
1948
+ import { useCallback as useCallback4, useMemo as useMemo3, useRef as useRef7, useState as useState8 } from "react";
1811
1949
  var DEFAULT_SPRING_ANIMATION = {
1812
1950
  /**
1813
1951
  * A value from 0 to 1, on how much to damp the animation.
@@ -1844,10 +1982,10 @@ globalThis.document?.addEventListener("click", () => {
1844
1982
  mouseDown = false;
1845
1983
  });
1846
1984
  var useStickToBottom = (options = {}) => {
1847
- const [escapedFromLock, updateEscapedFromLock] = useState7(false);
1848
- const [isAtBottom, updateIsAtBottom] = useState7(options.initial !== false);
1849
- const [isNearBottom, setIsNearBottom] = useState7(false);
1850
- const optionsRef = useRef6(null);
1985
+ const [escapedFromLock, updateEscapedFromLock] = useState8(false);
1986
+ const [isAtBottom, updateIsAtBottom] = useState8(options.initial !== false);
1987
+ const [isNearBottom, setIsNearBottom] = useState8(false);
1988
+ const optionsRef = useRef7(null);
1851
1989
  optionsRef.current = options;
1852
1990
  const isSelecting = useCallback4(() => {
1853
1991
  if (!mouseDown) {
@@ -2151,11 +2289,11 @@ function mergeAnimations(...animations) {
2151
2289
 
2152
2290
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/StickToBottom.js
2153
2291
  import * as React from "react";
2154
- import { createContext as createContext2, useContext as useContext2, useEffect as useEffect6, useImperativeHandle, useLayoutEffect, useMemo as useMemo4, useRef as useRef7 } from "react";
2292
+ import { createContext as createContext2, useContext as useContext2, useEffect as useEffect7, useImperativeHandle, useLayoutEffect, useMemo as useMemo4, useRef as useRef8 } from "react";
2155
2293
  var StickToBottomContext = createContext2(null);
2156
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect6;
2294
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect7;
2157
2295
  function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {
2158
- const customTargetScrollTop = useRef7(null);
2296
+ const customTargetScrollTop = useRef8(null);
2159
2297
  const targetScrollTop = React.useCallback((target, elements) => {
2160
2298
  const get = context?.targetScrollTop ?? currentTargetScrollTop;
2161
2299
  return get?.(target, elements) ?? target;
@@ -2237,11 +2375,11 @@ import {
2237
2375
  getTextContent,
2238
2376
  normalizeMessageContent
2239
2377
  } from "@blade-hq/agent-client";
2240
- import { useEffect as useEffect9, useRef as useRef10, useState as useState12 } from "react";
2378
+ import { useEffect as useEffect10, useRef as useRef11, useState as useState13 } from "react";
2241
2379
 
2242
2380
  // src/components/AgentLoopBlock.tsx
2243
- import { useState as useState8 } from "react";
2244
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2381
+ import { useState as useState9 } from "react";
2382
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2245
2383
  function parseAgentDescription(argumentsJson) {
2246
2384
  try {
2247
2385
  const parsed = JSON.parse(argumentsJson);
@@ -2251,7 +2389,7 @@ function parseAgentDescription(argumentsJson) {
2251
2389
  }
2252
2390
  }
2253
2391
  function AgentLoopBlock({ toolCall }) {
2254
- const [expanded, setExpanded] = useState8(false);
2392
+ const [expanded, setExpanded] = useState9(false);
2255
2393
  const description = parseAgentDescription(toolCall.arguments);
2256
2394
  const running = toolCall.status === "pending" || toolCall.status === "awaiting_answer";
2257
2395
  const failed = toolCall.status === "error" || toolCall.status === "cancelled";
@@ -2260,8 +2398,8 @@ function AgentLoopBlock({ toolCall }) {
2260
2398
  "size-3.5 shrink-0",
2261
2399
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
2262
2400
  );
2263
- return /* @__PURE__ */ jsxs6("div", { className: "blade-chat-agent-loop text-xs leading-[22px]", children: [
2264
- /* @__PURE__ */ jsxs6(
2401
+ return /* @__PURE__ */ jsxs7("div", { className: "blade-chat-agent-loop text-xs leading-[22px]", children: [
2402
+ /* @__PURE__ */ jsxs7(
2265
2403
  "button",
2266
2404
  {
2267
2405
  type: "button",
@@ -2276,12 +2414,12 @@ function AgentLoopBlock({ toolCall }) {
2276
2414
  ),
2277
2415
  title: `\u5B50\u4EFB\u52A1\uFF1A${description}`,
2278
2416
  children: [
2279
- running ? /* @__PURE__ */ jsx7(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx7(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx7(X, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx7(Bot, { className: iconClass, "aria-hidden": "true" }),
2280
- /* @__PURE__ */ jsxs6("span", { className: "min-w-0 truncate", children: [
2417
+ running ? /* @__PURE__ */ jsx8(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx8(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx8(X, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx8(Bot, { className: iconClass, "aria-hidden": "true" }),
2418
+ /* @__PURE__ */ jsxs7("span", { className: "min-w-0 truncate", children: [
2281
2419
  "\u5B50\u4EFB\u52A1\uFF1A",
2282
2420
  description
2283
2421
  ] }),
2284
- hasResult ? /* @__PURE__ */ jsx7(
2422
+ hasResult ? /* @__PURE__ */ jsx8(
2285
2423
  ChevronRight,
2286
2424
  {
2287
2425
  size: 14,
@@ -2296,18 +2434,18 @@ function AgentLoopBlock({ toolCall }) {
2296
2434
  ]
2297
2435
  }
2298
2436
  ),
2299
- expanded && hasResult ? /* @__PURE__ */ jsx7("div", { className: "ml-[18px] mt-1.5 max-h-[400px] overflow-auto whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: formatToolResult(toolCall.result) }) : null
2437
+ expanded && hasResult ? /* @__PURE__ */ jsx8("div", { className: "ml-[18px] mt-1.5 max-h-[400px] overflow-auto whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: formatToolResult(toolCall.result) }) : null
2300
2438
  ] });
2301
2439
  }
2302
2440
 
2303
2441
  // src/components/MarkdownContent.tsx
2304
2442
  import {
2305
- useEffect as useEffect7,
2443
+ useEffect as useEffect8,
2306
2444
  useMemo as useMemo5,
2307
- useRef as useRef8,
2308
- useState as useState9
2445
+ useRef as useRef9,
2446
+ useState as useState10
2309
2447
  } from "react";
2310
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2448
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2311
2449
  var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
2312
2450
  function normalizeAdjacentUrlFormatting(value) {
2313
2451
  const protectedSegments = [];
@@ -2322,10 +2460,10 @@ function normalizeAdjacentUrlFormatting(value) {
2322
2460
  return normalized.replace(/blade-url-protected-(\d+)-marker/g, (_, index) => protectedSegments[Number(index)]);
2323
2461
  }
2324
2462
  function CodeBlockPre({ children, node: _node, ...props }) {
2325
- const preRef = useRef8(null);
2326
- const [copied, setCopied] = useState9(false);
2327
- const [language, setLanguage] = useState9("");
2328
- useEffect7(() => {
2463
+ const preRef = useRef9(null);
2464
+ const [copied, setCopied] = useState10(false);
2465
+ const [language, setLanguage] = useState10("");
2466
+ useEffect8(() => {
2329
2467
  const codeEl = preRef.current?.querySelector("code");
2330
2468
  setLanguage(codeEl?.className.match(/language-(\S+)/)?.[1] ?? "");
2331
2469
  }, []);
@@ -2336,10 +2474,10 @@ function CodeBlockPre({ children, node: _node, ...props }) {
2336
2474
  setTimeout(() => setCopied(false), 2e3);
2337
2475
  }
2338
2476
  };
2339
- return /* @__PURE__ */ jsxs7("div", { className: "blade-chat-codeblock not-prose my-3 overflow-hidden rounded-xl border border-[hsl(var(--border))]", children: [
2340
- /* @__PURE__ */ jsxs7("div", { className: "blade-chat-codeblock-header flex h-[34px] items-center justify-between border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] pl-3.5 pr-1.5", children: [
2341
- /* @__PURE__ */ jsx8("span", { className: "font-mono text-[12px] text-[hsl(var(--muted-foreground))]", children: language || "code" }),
2342
- /* @__PURE__ */ jsxs7(
2477
+ return /* @__PURE__ */ jsxs8("div", { className: "blade-chat-codeblock not-prose my-3 overflow-hidden rounded-xl border border-[hsl(var(--border))]", children: [
2478
+ /* @__PURE__ */ jsxs8("div", { className: "blade-chat-codeblock-header flex h-[34px] items-center justify-between border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] pl-3.5 pr-1.5", children: [
2479
+ /* @__PURE__ */ jsx9("span", { className: "font-mono text-[12px] text-[hsl(var(--muted-foreground))]", children: language || "code" }),
2480
+ /* @__PURE__ */ jsxs8(
2343
2481
  "button",
2344
2482
  {
2345
2483
  type: "button",
@@ -2349,13 +2487,13 @@ function CodeBlockPre({ children, node: _node, ...props }) {
2349
2487
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"
2350
2488
  ),
2351
2489
  children: [
2352
- copied ? /* @__PURE__ */ jsx8(Check, { size: 12 }) : /* @__PURE__ */ jsx8(Copy, { size: 12 }),
2353
- /* @__PURE__ */ jsx8("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
2490
+ copied ? /* @__PURE__ */ jsx9(Check, { size: 12 }) : /* @__PURE__ */ jsx9(Copy, { size: 12 }),
2491
+ /* @__PURE__ */ jsx9("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
2354
2492
  ]
2355
2493
  }
2356
2494
  )
2357
2495
  ] }),
2358
- /* @__PURE__ */ jsx8(
2496
+ /* @__PURE__ */ jsx9(
2359
2497
  "pre",
2360
2498
  {
2361
2499
  ref: preRef,
@@ -2367,7 +2505,7 @@ function CodeBlockPre({ children, node: _node, ...props }) {
2367
2505
  ] });
2368
2506
  }
2369
2507
  function ExternalAnchor({ node: _node, children, ...props }) {
2370
- return /* @__PURE__ */ jsx8("a", { ...props, target: "_blank", rel: "noopener noreferrer", children });
2508
+ return /* @__PURE__ */ jsx9("a", { ...props, target: "_blank", rel: "noopener noreferrer", children });
2371
2509
  }
2372
2510
  var MARKDOWN_COMPONENTS = {
2373
2511
  pre: CodeBlockPre,
@@ -2377,7 +2515,7 @@ function MarkdownContent({ children, className, mode, sessionId }) {
2377
2515
  const resolvedChildren = useMemo5(() => {
2378
2516
  return normalizeAdjacentUrlFormatting(children.replace(SYSTEM_REMINDER_RE, ""));
2379
2517
  }, [children]);
2380
- return /* @__PURE__ */ jsx8(
2518
+ return /* @__PURE__ */ jsx9(
2381
2519
  _r,
2382
2520
  {
2383
2521
  className: cn("blade-chat-markdown break-words", className),
@@ -2390,17 +2528,17 @@ function MarkdownContent({ children, className, mode, sessionId }) {
2390
2528
  }
2391
2529
 
2392
2530
  // src/components/Shimmer.tsx
2393
- import { jsx as jsx9 } from "react/jsx-runtime";
2531
+ import { jsx as jsx10 } from "react/jsx-runtime";
2394
2532
  function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
2395
- return /* @__PURE__ */ jsx9("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
2533
+ return /* @__PURE__ */ jsx10("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
2396
2534
  }
2397
2535
 
2398
2536
  // src/components/ToolCallBlock.tsx
2399
- import { useState as useState11 } from "react";
2537
+ import { useState as useState12 } from "react";
2400
2538
 
2401
2539
  // src/components/AskUserQuestionBlock.tsx
2402
- import { useEffect as useEffect8, useMemo as useMemo6, useRef as useRef9, useState as useState10 } from "react";
2403
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2540
+ import { useEffect as useEffect9, useMemo as useMemo6, useRef as useRef10, useState as useState11 } from "react";
2541
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2404
2542
  var CUSTOM_TEXTAREA_MAX_HEIGHT = 160;
2405
2543
  function resizeCustomTextarea(textarea) {
2406
2544
  textarea.style.height = "auto";
@@ -2408,12 +2546,12 @@ function resizeCustomTextarea(textarea) {
2408
2546
  textarea.style.overflowY = textarea.scrollHeight > CUSTOM_TEXTAREA_MAX_HEIGHT ? "auto" : "hidden";
2409
2547
  }
2410
2548
  function useAutoResizeTextarea(value) {
2411
- const textareaRef = useRef9(null);
2412
- useEffect8(() => {
2549
+ const textareaRef = useRef10(null);
2550
+ useEffect9(() => {
2413
2551
  const textarea = textareaRef.current;
2414
2552
  if (textarea?.value === value) resizeCustomTextarea(textarea);
2415
2553
  }, [value]);
2416
- useEffect8(() => {
2554
+ useEffect9(() => {
2417
2555
  const textarea = textareaRef.current;
2418
2556
  if (!textarea || typeof ResizeObserver === "undefined") return;
2419
2557
  let previousWidth = textarea.clientWidth;
@@ -2438,12 +2576,12 @@ function AskUserQuestionBlock({
2438
2576
  answerData,
2439
2577
  onAnswer
2440
2578
  }) {
2441
- const [selections, setSelections] = useState10(/* @__PURE__ */ new Map());
2442
- const [customTexts, setCustomTexts] = useState10(/* @__PURE__ */ new Map());
2443
- const [usingCustom, setUsingCustom] = useState10(/* @__PURE__ */ new Set());
2444
- const [note, setNote] = useState10("");
2445
- const [submitted, setSubmitted] = useState10(false);
2446
- useEffect8(() => {
2579
+ const [selections, setSelections] = useState11(/* @__PURE__ */ new Map());
2580
+ const [customTexts, setCustomTexts] = useState11(/* @__PURE__ */ new Map());
2581
+ const [usingCustom, setUsingCustom] = useState11(/* @__PURE__ */ new Set());
2582
+ const [note, setNote] = useState11("");
2583
+ const [submitted, setSubmitted] = useState11(false);
2584
+ useEffect9(() => {
2447
2585
  if (sessionStatus === "failed" || sessionStatus === "interrupted") {
2448
2586
  setSubmitted(false);
2449
2587
  }
@@ -2541,7 +2679,7 @@ ${parts.join("\n")}`,
2541
2679
  setSubmitted(true);
2542
2680
  onAnswer(text, toolCallId, nextAnswerData);
2543
2681
  };
2544
- return /* @__PURE__ */ jsxs8(
2682
+ return /* @__PURE__ */ jsxs9(
2545
2683
  "div",
2546
2684
  {
2547
2685
  className: cn(
@@ -2549,12 +2687,12 @@ ${parts.join("\n")}`,
2549
2687
  answered ? "max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80" : "max-w-lg space-y-5 p-4 text-sm"
2550
2688
  ),
2551
2689
  children: [
2552
- data.source_loop?.description && /* @__PURE__ */ jsxs8("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
2690
+ data.source_loop?.description && /* @__PURE__ */ jsxs9("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
2553
2691
  "\u5B50\u667A\u80FD\u4F53\u300C",
2554
2692
  data.source_loop.description,
2555
2693
  "\u300D\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54"
2556
2694
  ] }),
2557
- data.questions.map((q, qIdx) => /* @__PURE__ */ jsx10(
2695
+ data.questions.map((q, qIdx) => /* @__PURE__ */ jsx11(
2558
2696
  QuestionCard,
2559
2697
  {
2560
2698
  question: q,
@@ -2569,7 +2707,7 @@ ${parts.join("\n")}`,
2569
2707
  },
2570
2708
  q.question
2571
2709
  )),
2572
- /* @__PURE__ */ jsx10(
2710
+ /* @__PURE__ */ jsx11(
2573
2711
  NoteField,
2574
2712
  {
2575
2713
  answered,
@@ -2578,7 +2716,7 @@ ${parts.join("\n")}`,
2578
2716
  onChange: setNote
2579
2717
  }
2580
2718
  ),
2581
- !answered && !submitted && onAnswer && /* @__PURE__ */ jsx10(
2719
+ !answered && !submitted && onAnswer && /* @__PURE__ */ jsx11(
2582
2720
  "button",
2583
2721
  {
2584
2722
  type: "button",
@@ -2588,14 +2726,14 @@ ${parts.join("\n")}`,
2588
2726
  children: allAnswered ? "\u786E\u8BA4" : "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u9009\u9879"
2589
2727
  }
2590
2728
  ),
2591
- submitted && !answered && /* @__PURE__ */ jsxs8(
2729
+ submitted && !answered && /* @__PURE__ */ jsxs9(
2592
2730
  "button",
2593
2731
  {
2594
2732
  type: "button",
2595
2733
  disabled: true,
2596
2734
  className: "flex w-full items-center justify-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] opacity-80",
2597
2735
  children: [
2598
- /* @__PURE__ */ jsx10(LoaderCircle, { size: 14, className: "animate-spin" }),
2736
+ /* @__PURE__ */ jsx11(LoaderCircle, { size: 14, className: "animate-spin" }),
2599
2737
  "\u786E\u8BA4\u4E2D"
2600
2738
  ]
2601
2739
  }
@@ -2617,30 +2755,30 @@ function QuestionCard({
2617
2755
  }) {
2618
2756
  const multi = question.multiSelect ?? false;
2619
2757
  const customTextareaRef = useAutoResizeTextarea(customText);
2620
- return /* @__PURE__ */ jsxs8("div", { children: [
2621
- /* @__PURE__ */ jsxs8("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
2622
- /* @__PURE__ */ jsx10(
2758
+ return /* @__PURE__ */ jsxs9("div", { children: [
2759
+ /* @__PURE__ */ jsxs9("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
2760
+ /* @__PURE__ */ jsx11(
2623
2761
  MessageSquareMore,
2624
2762
  {
2625
2763
  size: answered ? 12 : 13,
2626
2764
  className: "mt-0.5 shrink-0 text-[hsl(var(--primary))]"
2627
2765
  }
2628
2766
  ),
2629
- /* @__PURE__ */ jsx10(
2767
+ /* @__PURE__ */ jsx11(
2630
2768
  "div",
2631
2769
  {
2632
2770
  className: cn(
2633
2771
  "min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]",
2634
2772
  answered ? "text-xs" : "text-sm"
2635
2773
  ),
2636
- children: /* @__PURE__ */ jsx10(MarkdownContent, { className: "blade-chat-prose", children: question.question })
2774
+ children: /* @__PURE__ */ jsx11(MarkdownContent, { className: "blade-chat-prose", children: question.question })
2637
2775
  }
2638
2776
  )
2639
2777
  ] }),
2640
- /* @__PURE__ */ jsxs8("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
2778
+ /* @__PURE__ */ jsxs9("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
2641
2779
  question.options.map((opt, optIdx) => {
2642
2780
  const isSel = selected.has(optIdx);
2643
- return /* @__PURE__ */ jsxs8(
2781
+ return /* @__PURE__ */ jsxs9(
2644
2782
  "button",
2645
2783
  {
2646
2784
  type: "button",
@@ -2654,14 +2792,14 @@ function QuestionCard({
2654
2792
  answered && "cursor-default opacity-70"
2655
2793
  ),
2656
2794
  children: [
2657
- multi && /* @__PURE__ */ jsx10(
2795
+ multi && /* @__PURE__ */ jsx11(
2658
2796
  "div",
2659
2797
  {
2660
2798
  className: cn(
2661
2799
  "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
2662
2800
  isSel && !answered ? "border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]" : isSel ? "border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]" : "border-[hsl(var(--border))]"
2663
2801
  ),
2664
- children: isSel && /* @__PURE__ */ jsx10(
2802
+ children: isSel && /* @__PURE__ */ jsx11(
2665
2803
  Check,
2666
2804
  {
2667
2805
  size: 9,
@@ -2670,9 +2808,9 @@ function QuestionCard({
2670
2808
  )
2671
2809
  }
2672
2810
  ),
2673
- /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
2674
- /* @__PURE__ */ jsx10("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
2675
- opt.description && /* @__PURE__ */ jsx10(
2811
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
2812
+ /* @__PURE__ */ jsx11("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
2813
+ opt.description && /* @__PURE__ */ jsx11(
2676
2814
  "div",
2677
2815
  {
2678
2816
  className: cn(
@@ -2689,7 +2827,7 @@ function QuestionCard({
2689
2827
  opt.label
2690
2828
  );
2691
2829
  }),
2692
- answered && !isCustom ? null : /* @__PURE__ */ jsxs8(
2830
+ answered && !isCustom ? null : /* @__PURE__ */ jsxs9(
2693
2831
  "div",
2694
2832
  {
2695
2833
  className: cn(
@@ -2699,8 +2837,8 @@ function QuestionCard({
2699
2837
  answered && "cursor-default opacity-70"
2700
2838
  ),
2701
2839
  children: [
2702
- /* @__PURE__ */ jsx10("span", { className: "shrink-0 pt-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
2703
- /* @__PURE__ */ jsx10(
2840
+ /* @__PURE__ */ jsx11("span", { className: "shrink-0 pt-1 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
2841
+ /* @__PURE__ */ jsx11(
2704
2842
  "textarea",
2705
2843
  {
2706
2844
  ref: customTextareaRef,
@@ -2732,7 +2870,7 @@ function NoteField({
2732
2870
  const textareaRef = useAutoResizeTextarea(note);
2733
2871
  const readOnly = answered || submitted;
2734
2872
  if (answered && !note.trim()) return null;
2735
- return /* @__PURE__ */ jsxs8(
2873
+ return /* @__PURE__ */ jsxs9(
2736
2874
  "label",
2737
2875
  {
2738
2876
  className: cn(
@@ -2742,8 +2880,8 @@ function NoteField({
2742
2880
  readOnly && "cursor-default opacity-70"
2743
2881
  ),
2744
2882
  children: [
2745
- /* @__PURE__ */ jsx10("span", { className: "mb-1.5 block text-xs text-[hsl(var(--muted-foreground))]", children: "\u8865\u5145\u8BF4\u660E\uFF08\u53EF\u9009\uFF09" }),
2746
- /* @__PURE__ */ jsx10(
2883
+ /* @__PURE__ */ jsx11("span", { className: "mb-1.5 block text-xs text-[hsl(var(--muted-foreground))]", children: "\u8865\u5145\u8BF4\u660E\uFF08\u53EF\u9009\uFF09" }),
2884
+ /* @__PURE__ */ jsx11(
2747
2885
  "textarea",
2748
2886
  {
2749
2887
  ref: textareaRef,
@@ -2832,7 +2970,7 @@ function normalizeOptionItem(value) {
2832
2970
  }
2833
2971
 
2834
2972
  // src/components/ToolCallBlock.tsx
2835
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2973
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2836
2974
  function resolveAskQuestionState({
2837
2975
  toolStatus,
2838
2976
  hasAnswerData,
@@ -2854,12 +2992,12 @@ function ToolCallBlock({
2854
2992
  isActiveQuestion,
2855
2993
  renderer
2856
2994
  }) {
2857
- const [expanded, setExpanded] = useState11(false);
2995
+ const [expanded, setExpanded] = useState12(false);
2858
2996
  const normalizedName = formatToolName(toolCall.name);
2859
2997
  if (renderer) {
2860
2998
  const custom = renderer(toolCall);
2861
2999
  if (custom !== null && custom !== void 0) {
2862
- return /* @__PURE__ */ jsx11(Fragment2, { children: custom });
3000
+ return /* @__PURE__ */ jsx12(Fragment2, { children: custom });
2863
3001
  }
2864
3002
  }
2865
3003
  if (normalizedName === "AskUserQuestion") {
@@ -2872,7 +3010,7 @@ function ToolCallBlock({
2872
3010
  });
2873
3011
  const canAnswer = questionState.awaitingAnswer && Boolean(onAnswer);
2874
3012
  if (askData) {
2875
- return /* @__PURE__ */ jsx11(
3013
+ return /* @__PURE__ */ jsx12(
2876
3014
  AskUserQuestionBlock,
2877
3015
  {
2878
3016
  data: askData,
@@ -2885,31 +3023,31 @@ function ToolCallBlock({
2885
3023
  );
2886
3024
  }
2887
3025
  if (toolCall.status === "pending") {
2888
- return /* @__PURE__ */ jsxs9("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
2889
- /* @__PURE__ */ jsx11(LoaderCircle, { size: 14, className: "animate-spin" }),
2890
- /* @__PURE__ */ jsx11("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
3026
+ return /* @__PURE__ */ jsxs10("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
3027
+ /* @__PURE__ */ jsx12(LoaderCircle, { size: 14, className: "animate-spin" }),
3028
+ /* @__PURE__ */ jsx12("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
2891
3029
  ] });
2892
3030
  }
2893
3031
  const errorDetail = parseAskUserQuestionError(
2894
3032
  typeof toolCall.result === "string" ? toolCall.result : null
2895
3033
  );
2896
- return /* @__PURE__ */ jsxs9("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
2897
- /* @__PURE__ */ jsx11("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
2898
- /* @__PURE__ */ jsx11("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: errorDetail?.message ?? "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" }),
2899
- errorDetail?.detail ? /* @__PURE__ */ jsxs9("details", { className: "mt-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
2900
- /* @__PURE__ */ jsx11("summary", { className: "cursor-pointer", children: "\u67E5\u770B\u5177\u4F53\u539F\u56E0" }),
2901
- /* @__PURE__ */ jsx11("div", { className: "mt-1 break-words font-mono", children: errorDetail.detail })
3034
+ return /* @__PURE__ */ jsxs10("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
3035
+ /* @__PURE__ */ jsx12("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
3036
+ /* @__PURE__ */ jsx12("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: errorDetail?.message ?? "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" }),
3037
+ errorDetail?.detail ? /* @__PURE__ */ jsxs10("details", { className: "mt-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
3038
+ /* @__PURE__ */ jsx12("summary", { className: "cursor-pointer", children: "\u67E5\u770B\u5177\u4F53\u539F\u56E0" }),
3039
+ /* @__PURE__ */ jsx12("div", { className: "mt-1 break-words font-mono", children: errorDetail.detail })
2902
3040
  ] }) : null
2903
3041
  ] });
2904
3042
  }
2905
3043
  const tone = getToolTone(toolCall.status);
2906
3044
  const displayName = getToolDisplayLabel(toolCall);
2907
3045
  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))]";
2908
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx11(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx11(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx11(X, { size: 11 }) : /* @__PURE__ */ jsx11(Check, { size: 11 });
3046
+ const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx12(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx12(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx12(X, { size: 11 }) : /* @__PURE__ */ jsx12(Check, { size: 11 });
2909
3047
  const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
2910
- return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-tool ml-4 text-xs", children: [
2911
- /* @__PURE__ */ jsxs9("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
2912
- /* @__PURE__ */ jsxs9(
3048
+ return /* @__PURE__ */ jsxs10("div", { className: "blade-chat-tool ml-4 text-xs", children: [
3049
+ /* @__PURE__ */ jsxs10("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
3050
+ /* @__PURE__ */ jsxs10(
2913
3051
  "button",
2914
3052
  {
2915
3053
  type: "button",
@@ -2917,7 +3055,7 @@ function ToolCallBlock({
2917
3055
  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",
2918
3056
  "aria-expanded": expanded,
2919
3057
  children: [
2920
- /* @__PURE__ */ jsx11(
3058
+ /* @__PURE__ */ jsx12(
2921
3059
  ChevronRight,
2922
3060
  {
2923
3061
  size: 11,
@@ -2927,24 +3065,24 @@ function ToolCallBlock({
2927
3065
  )
2928
3066
  }
2929
3067
  ),
2930
- /* @__PURE__ */ jsxs9("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
3068
+ /* @__PURE__ */ jsxs10("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
2931
3069
  statusIcon,
2932
- /* @__PURE__ */ jsx11("span", { children: getToolStatusLabel(toolCall.status) })
3070
+ /* @__PURE__ */ jsx12("span", { children: getToolStatusLabel(toolCall.status) })
2933
3071
  ] }),
2934
- /* @__PURE__ */ jsx11("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
3072
+ /* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
2935
3073
  ]
2936
3074
  }
2937
3075
  ),
2938
- typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx11("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
3076
+ typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx12("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
2939
3077
  ] }),
2940
- expanded && /* @__PURE__ */ jsxs9("div", { className: "blade-chat-tool-detail ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
2941
- /* @__PURE__ */ jsx11("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
2942
- /* @__PURE__ */ jsx11("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
2943
- /* @__PURE__ */ jsx11("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
2944
- /* @__PURE__ */ jsx11("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
2945
- toolCall.result != null && /* @__PURE__ */ jsxs9(Fragment2, { children: [
2946
- /* @__PURE__ */ jsx11("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
2947
- /* @__PURE__ */ jsx11("pre", { className: "max-h-[400px] overflow-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolResult(toolCall.result) })
3078
+ expanded && /* @__PURE__ */ jsxs10("div", { className: "blade-chat-tool-detail ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
3079
+ /* @__PURE__ */ jsx12("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
3080
+ /* @__PURE__ */ jsx12("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
3081
+ /* @__PURE__ */ jsx12("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
3082
+ /* @__PURE__ */ jsx12("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
3083
+ toolCall.result != null && /* @__PURE__ */ jsxs10(Fragment2, { children: [
3084
+ /* @__PURE__ */ jsx12("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
3085
+ /* @__PURE__ */ jsx12("pre", { className: "max-h-[400px] overflow-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolResult(toolCall.result) })
2948
3086
  ] })
2949
3087
  ] })
2950
3088
  ] });
@@ -2962,12 +3100,12 @@ function buildAskUserPayload(argumentsJson) {
2962
3100
  }
2963
3101
 
2964
3102
  // src/components/AssistantTurnBlock.tsx
2965
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
3103
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2966
3104
  function ThinkingBlock({ reasoning, isStreaming }) {
2967
- const [open, setOpen] = useState12(false);
3105
+ const [open, setOpen] = useState13(false);
2968
3106
  if (!isStreaming) return null;
2969
- return /* @__PURE__ */ jsxs10("div", { className: "blade-chat-thinking text-xs", children: [
2970
- /* @__PURE__ */ jsxs10(
3107
+ return /* @__PURE__ */ jsxs11("div", { className: "blade-chat-thinking text-xs", children: [
3108
+ /* @__PURE__ */ jsxs11(
2971
3109
  "button",
2972
3110
  {
2973
3111
  type: "button",
@@ -2975,8 +3113,8 @@ function ThinkingBlock({ reasoning, isStreaming }) {
2975
3113
  "aria-expanded": open,
2976
3114
  className: "group/thinking inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
2977
3115
  children: [
2978
- /* @__PURE__ */ jsx12(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }),
2979
- /* @__PURE__ */ jsx12(
3116
+ /* @__PURE__ */ jsx13(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }),
3117
+ /* @__PURE__ */ jsx13(
2980
3118
  ChevronRight,
2981
3119
  {
2982
3120
  size: 14,
@@ -2989,7 +3127,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
2989
3127
  ]
2990
3128
  }
2991
3129
  ),
2992
- open ? /* @__PURE__ */ jsx12("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning }) : null
3130
+ open ? /* @__PURE__ */ jsx13("div", { className: "mt-1.5 whitespace-pre-wrap text-xs leading-[22px] text-[hsl(var(--muted-foreground))]", children: reasoning }) : null
2993
3131
  ] });
2994
3132
  }
2995
3133
  function getMessageText(message) {
@@ -3181,14 +3319,14 @@ function ExecutionToolRow({ toolCall }) {
3181
3319
  "size-3.5 shrink-0",
3182
3320
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
3183
3321
  );
3184
- const icon = toolCall.status === "pending" ? /* @__PURE__ */ jsx12(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx12(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx12(X, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "WebSearch" || normalizedName === "WebFetch" ? /* @__PURE__ */ jsx12(Earth, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Bash" || normalizedName === "BgBash" ? /* @__PURE__ */ jsx12(Terminal, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit" ? /* @__PURE__ */ jsx12(FilePenLine, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Read" || normalizedName === "ReadSkill" || normalizedName === "get_skill_content" ? /* @__PURE__ */ jsx12(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Grep" || normalizedName === "Glob" || normalizedName === "search_skills" ? /* @__PURE__ */ jsx12(Search, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Agent" ? /* @__PURE__ */ jsx12(Bot, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx12(Wrench, { className: iconClass, "aria-hidden": "true" });
3322
+ const icon = toolCall.status === "pending" ? /* @__PURE__ */ jsx13(LoaderCircle, { className: cn(iconClass, "animate-spin"), "aria-hidden": "true" }) : toolCall.status === "error" ? /* @__PURE__ */ jsx13(CircleAlert, { className: iconClass, "aria-hidden": "true" }) : toolCall.status === "cancelled" ? /* @__PURE__ */ jsx13(X, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "WebSearch" || normalizedName === "WebFetch" ? /* @__PURE__ */ jsx13(Earth, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Bash" || normalizedName === "BgBash" ? /* @__PURE__ */ jsx13(Terminal, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Write" || normalizedName === "Edit" || normalizedName === "MultiEdit" ? /* @__PURE__ */ jsx13(FilePenLine, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Read" || normalizedName === "ReadSkill" || normalizedName === "get_skill_content" ? /* @__PURE__ */ jsx13(BookOpen, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Grep" || normalizedName === "Glob" || normalizedName === "search_skills" ? /* @__PURE__ */ jsx13(Search, { className: iconClass, "aria-hidden": "true" }) : normalizedName === "Agent" ? /* @__PURE__ */ jsx13(Bot, { className: iconClass, "aria-hidden": "true" }) : /* @__PURE__ */ jsx13(Wrench, { className: iconClass, "aria-hidden": "true" });
3185
3323
  const rowClassName = cn(
3186
3324
  "flex min-w-0 items-center gap-1 py-1.5 text-xs leading-[22px]",
3187
3325
  failed ? "text-red-500" : "text-[hsl(var(--muted-foreground))]"
3188
3326
  );
3189
- return /* @__PURE__ */ jsxs10("div", { "data-testid": "execution-tool-intent", className: rowClassName, title: label, children: [
3327
+ return /* @__PURE__ */ jsxs11("div", { "data-testid": "execution-tool-intent", className: rowClassName, title: label, children: [
3190
3328
  icon,
3191
- /* @__PURE__ */ jsx12("span", { className: "min-w-0 truncate", children: label })
3329
+ /* @__PURE__ */ jsx13("span", { className: "min-w-0 truncate", children: label })
3192
3330
  ] });
3193
3331
  }
3194
3332
  function AssistantTurnBlock({
@@ -3234,12 +3372,12 @@ function AssistantTurnBlock({
3234
3372
  )
3235
3373
  );
3236
3374
  const activeQuestionId = questionToolCalls.filter((toolCall) => toolCall.status === "pending").at(-1)?.id;
3237
- const [displayMode, setDisplayMode] = useState12(
3375
+ const [displayMode, setDisplayMode] = useState13(
3238
3376
  () => isStreaming || hasActionableToolCall ? "detail" : "compact"
3239
3377
  );
3240
- const userSelectedDisplayModeRef = useRef10(false);
3241
- const wasStreamingRef = useRef10(isStreaming);
3242
- useEffect9(() => {
3378
+ const userSelectedDisplayModeRef = useRef11(false);
3379
+ const wasStreamingRef = useRef11(isStreaming);
3380
+ useEffect10(() => {
3243
3381
  if (wasStreamingRef.current && !isStreaming && !userSelectedDisplayModeRef.current) {
3244
3382
  setDisplayMode(hasActionableToolCall ? "detail" : "compact");
3245
3383
  }
@@ -3247,11 +3385,11 @@ function AssistantTurnBlock({
3247
3385
  }, [hasActionableToolCall, isStreaming]);
3248
3386
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
3249
3387
  const executionDurationMs = getExecutionDurationMs({ messages, isStreaming });
3250
- const [clock, setClock] = useState12(() => Date.now());
3388
+ const [clock, setClock] = useState13(() => Date.now());
3251
3389
  const hasLiveStartTime = messages.some(
3252
3390
  (message) => message.timestamp != null && Number.isFinite(Date.parse(message.timestamp))
3253
3391
  );
3254
- useEffect9(() => {
3392
+ useEffect10(() => {
3255
3393
  if (!isStreaming || !hasLiveStartTime) return;
3256
3394
  const timer = window.setInterval(() => setClock(Date.now()), 1e3);
3257
3395
  return () => window.clearInterval(timer);
@@ -3259,21 +3397,21 @@ function AssistantTurnBlock({
3259
3397
  const liveExecutionDurationMs = isStreaming ? getExecutionDurationMs({ messages, isStreaming, now: clock }) : executionDurationMs;
3260
3398
  const memoryRefs = collectMemoryRefs(messages);
3261
3399
  if (!hasExecutionProcess) {
3262
- return /* @__PURE__ */ jsxs10(
3400
+ return /* @__PURE__ */ jsxs11(
3263
3401
  "div",
3264
3402
  {
3265
3403
  "aria-busy": isStreaming || void 0,
3266
3404
  className: "blade-chat-assistant-turn flex flex-col gap-3",
3267
3405
  children: [
3268
- memoryRefs.length > 0 ? /* @__PURE__ */ jsx12(MemoryRefsHint, { refs: memoryRefs }) : null,
3269
- hasInterrupted && /* @__PURE__ */ jsx12("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" }),
3270
- hasFailedWithoutContent && /* @__PURE__ */ jsx12("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
3406
+ memoryRefs.length > 0 ? /* @__PURE__ */ jsx13(MemoryRefsHint, { refs: memoryRefs }) : null,
3407
+ hasInterrupted && /* @__PURE__ */ jsx13("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" }),
3408
+ hasFailedWithoutContent && /* @__PURE__ */ jsx13("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
3271
3409
  messages.map((message, index) => {
3272
- return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx12(
3410
+ return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx13(
3273
3411
  "div",
3274
3412
  {
3275
3413
  className: "flex flex-col gap-3",
3276
- children: /* @__PURE__ */ jsx12(
3414
+ children: /* @__PURE__ */ jsx13(
3277
3415
  AssistantMessageContent,
3278
3416
  {
3279
3417
  message,
@@ -3289,26 +3427,26 @@ function AssistantTurnBlock({
3289
3427
  }
3290
3428
  );
3291
3429
  }
3292
- return /* @__PURE__ */ jsxs10(
3430
+ return /* @__PURE__ */ jsxs11(
3293
3431
  "div",
3294
3432
  {
3295
3433
  "aria-busy": isStreaming || void 0,
3296
3434
  className: "blade-chat-assistant-turn flex flex-col gap-3",
3297
3435
  children: [
3298
- memoryRefs.length > 0 ? /* @__PURE__ */ jsx12(MemoryRefsHint, { refs: memoryRefs }) : null,
3299
- hasInterrupted && /* @__PURE__ */ jsx12("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" }),
3300
- hasFailedWithoutContent && /* @__PURE__ */ jsx12("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
3301
- /* @__PURE__ */ jsxs10("div", { className: "flex w-full items-start gap-2.5", children: [
3302
- /* @__PURE__ */ jsx12(
3436
+ memoryRefs.length > 0 ? /* @__PURE__ */ jsx13(MemoryRefsHint, { refs: memoryRefs }) : null,
3437
+ hasInterrupted && /* @__PURE__ */ jsx13("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" }),
3438
+ hasFailedWithoutContent && /* @__PURE__ */ jsx13("div", { className: "ml-4 w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }),
3439
+ /* @__PURE__ */ jsxs11("div", { className: "flex w-full items-start gap-2.5", children: [
3440
+ /* @__PURE__ */ jsx13(
3303
3441
  "span",
3304
3442
  {
3305
3443
  className: "grid size-[30px] shrink-0 place-items-center rounded-full bg-[hsl(var(--muted)/0.55)] text-[hsl(var(--foreground))]",
3306
3444
  "aria-hidden": "true",
3307
- children: /* @__PURE__ */ jsx12(Bot, { size: 16 })
3445
+ children: /* @__PURE__ */ jsx13(Bot, { size: 16 })
3308
3446
  }
3309
3447
  ),
3310
- /* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1 pt-0.5", children: [
3311
- /* @__PURE__ */ jsxs10(
3448
+ /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1 pt-0.5", children: [
3449
+ /* @__PURE__ */ jsxs11(
3312
3450
  "button",
3313
3451
  {
3314
3452
  type: "button",
@@ -3321,14 +3459,14 @@ function AssistantTurnBlock({
3321
3459
  "data-testid": "assistant-execution-summary",
3322
3460
  className: "inline-flex min-w-0 max-w-full select-none items-center gap-1 bg-transparent p-0 text-left text-xs leading-[22px] text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
3323
3461
  children: [
3324
- /* @__PURE__ */ jsx12("span", { className: "min-w-0 truncate", children: executionSummaryLabel({
3462
+ /* @__PURE__ */ jsx13("span", { className: "min-w-0 truncate", children: executionSummaryLabel({
3325
3463
  messages,
3326
3464
  isStreaming,
3327
3465
  durationMs: liveExecutionDurationMs,
3328
3466
  sessionStatus,
3329
3467
  askAnswers
3330
3468
  }) }),
3331
- /* @__PURE__ */ jsx12(
3469
+ /* @__PURE__ */ jsx13(
3332
3470
  ChevronRight,
3333
3471
  {
3334
3472
  size: 14,
@@ -3343,10 +3481,10 @@ function AssistantTurnBlock({
3343
3481
  ]
3344
3482
  }
3345
3483
  ),
3346
- /* @__PURE__ */ jsx12("div", { className: "mt-3 h-px w-full bg-[hsl(var(--border)/0.75)]" })
3484
+ /* @__PURE__ */ jsx13("div", { className: "mt-3 h-px w-full bg-[hsl(var(--border)/0.75)]" })
3347
3485
  ] })
3348
3486
  ] }),
3349
- effectiveMode === "detail" ? /* @__PURE__ */ jsx12("div", { className: "ml-10 flex flex-col gap-3 pt-1", children: messages.map((message, index) => {
3487
+ effectiveMode === "detail" ? /* @__PURE__ */ jsx13("div", { className: "ml-10 flex flex-col gap-3 pt-1", children: messages.map((message, index) => {
3350
3488
  const isLast = index === messages.length - 1;
3351
3489
  const streamingThis = isStreaming && isLast;
3352
3490
  const text = getMessageText(message);
@@ -3355,14 +3493,14 @@ function AssistantTurnBlock({
3355
3493
  );
3356
3494
  const orderedParts = getOrderedMessageParts(message, toolCalls);
3357
3495
  const showReasoning = !!message.reasoning && isStreaming && index === latestReasoningIndex;
3358
- return /* @__PURE__ */ jsxs10(
3496
+ return /* @__PURE__ */ jsxs11(
3359
3497
  "div",
3360
3498
  {
3361
3499
  className: "flex flex-col gap-3",
3362
3500
  children: [
3363
- showReasoning && message.reasoning ? /* @__PURE__ */ jsx12(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }) : null,
3501
+ showReasoning && message.reasoning ? /* @__PURE__ */ jsx13(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }) : null,
3364
3502
  orderedParts.length > 0 ? orderedParts.map(
3365
- (part) => part.type === "text" ? /* @__PURE__ */ jsx12(
3503
+ (part) => part.type === "text" ? /* @__PURE__ */ jsx13(
3366
3504
  AssistantMessageContent,
3367
3505
  {
3368
3506
  message: { ...message, content: part.content, tool_calls: turnToolCalls },
@@ -3371,11 +3509,11 @@ function AssistantTurnBlock({
3371
3509
  compact: true
3372
3510
  },
3373
3511
  part.key
3374
- ) : /* @__PURE__ */ jsx12("div", { className: "flex flex-col gap-0.5", children: part.toolCalls.map((toolCall) => {
3512
+ ) : /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-0.5", children: part.toolCalls.map((toolCall) => {
3375
3513
  const custom = toolCallRenderer?.(toolCall);
3376
- return custom !== null && custom !== void 0 ? /* @__PURE__ */ jsx12("div", { children: custom }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx12(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx12(ExecutionToolRow, { toolCall }, toolCall.id);
3514
+ return custom !== null && custom !== void 0 ? /* @__PURE__ */ jsx13("div", { children: custom }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx13(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx13(ExecutionToolRow, { toolCall }, toolCall.id);
3377
3515
  }) }, part.key)
3378
- ) : hasRenderableMessageContent(message) && message !== finalMessage ? /* @__PURE__ */ jsx12(
3516
+ ) : hasRenderableMessageContent(message) && message !== finalMessage ? /* @__PURE__ */ jsx13(
3379
3517
  AssistantMessageContent,
3380
3518
  {
3381
3519
  message,
@@ -3384,16 +3522,16 @@ function AssistantTurnBlock({
3384
3522
  compact: true
3385
3523
  }
3386
3524
  ) : null,
3387
- orderedParts.length === 0 && toolCalls.length > 0 ? /* @__PURE__ */ jsx12("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((toolCall) => {
3525
+ orderedParts.length === 0 && toolCalls.length > 0 ? /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((toolCall) => {
3388
3526
  const custom = toolCallRenderer?.(toolCall);
3389
- return custom !== null && custom !== void 0 ? /* @__PURE__ */ jsx12("div", { children: custom }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx12(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx12(ExecutionToolRow, { toolCall }, toolCall.id);
3527
+ return custom !== null && custom !== void 0 ? /* @__PURE__ */ jsx13("div", { children: custom }, toolCall.id) : formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx13(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx13(ExecutionToolRow, { toolCall }, toolCall.id);
3390
3528
  }) }) : null
3391
3529
  ]
3392
3530
  },
3393
3531
  message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
3394
3532
  );
3395
3533
  }) }) : null,
3396
- finalMessage && (effectiveMode === "compact" || finalOrderedParts.length === 0) ? /* @__PURE__ */ jsx12("div", { className: "ml-10", children: /* @__PURE__ */ jsx12(
3534
+ finalMessage && (effectiveMode === "compact" || finalOrderedParts.length === 0) ? /* @__PURE__ */ jsx13("div", { className: "ml-10", children: /* @__PURE__ */ jsx13(
3397
3535
  AssistantMessageContent,
3398
3536
  {
3399
3537
  message: finalMessage,
@@ -3401,7 +3539,7 @@ function AssistantTurnBlock({
3401
3539
  streaming: isStreaming && finalMessage === messages[messages.length - 1]
3402
3540
  }
3403
3541
  ) }) : null,
3404
- questionToolCalls.map((toolCall) => /* @__PURE__ */ jsx12(
3542
+ questionToolCalls.map((toolCall) => /* @__PURE__ */ jsx13(
3405
3543
  ToolCallBlock,
3406
3544
  {
3407
3545
  toolCall,
@@ -3426,22 +3564,22 @@ function collectMemoryRefs(messages) {
3426
3564
  return [...refs.values()];
3427
3565
  }
3428
3566
  function MemoryRefsHint({ refs }) {
3429
- const [expanded, setExpanded] = useState12(false);
3567
+ const [expanded, setExpanded] = useState13(false);
3430
3568
  const label = refs.some((ref) => ref.skill_name) ? "\u53C2\u8003\u4E86\u8BE5\u6280\u80FD\u7684\u5386\u53F2\u7ECF\u9A8C" : "\u53C2\u8003\u4E86\u5386\u53F2\u7ECF\u9A8C";
3431
- return /* @__PURE__ */ jsxs10("div", { className: "blade-chat-memory-refs ml-1 w-full max-w-[680px]", children: [
3432
- /* @__PURE__ */ jsxs10("button", { type: "button", onClick: () => setExpanded((value) => !value), className: "inline-flex h-8 items-center gap-1.5 rounded-lg border border-[hsl(var(--primary)/0.22)] bg-[hsl(var(--primary)/0.07)] px-3 text-xs font-medium text-[hsl(var(--primary))]", children: [
3433
- /* @__PURE__ */ jsx12(BookOpen, { size: 12 }),
3434
- /* @__PURE__ */ jsxs10("span", { children: [
3569
+ return /* @__PURE__ */ jsxs11("div", { className: "blade-chat-memory-refs ml-1 w-full max-w-[680px]", children: [
3570
+ /* @__PURE__ */ jsxs11("button", { type: "button", onClick: () => setExpanded((value) => !value), className: "inline-flex h-8 items-center gap-1.5 rounded-lg border border-[hsl(var(--primary)/0.22)] bg-[hsl(var(--primary)/0.07)] px-3 text-xs font-medium text-[hsl(var(--primary))]", children: [
3571
+ /* @__PURE__ */ jsx13(BookOpen, { size: 12 }),
3572
+ /* @__PURE__ */ jsxs11("span", { children: [
3435
3573
  label,
3436
3574
  "\uFF08",
3437
3575
  refs.length,
3438
3576
  "\uFF09"
3439
3577
  ] }),
3440
- /* @__PURE__ */ jsx12(ChevronRight, { size: 10, className: cn("transition-transform", expanded && "rotate-90") })
3578
+ /* @__PURE__ */ jsx13(ChevronRight, { size: 10, className: cn("transition-transform", expanded && "rotate-90") })
3441
3579
  ] }),
3442
- expanded ? /* @__PURE__ */ jsx12("div", { className: "mt-2 flex flex-col gap-2 rounded-xl border border-[hsl(var(--border)/0.8)] bg-[hsl(var(--muted)/0.28)] p-2.5", children: refs.map((ref) => /* @__PURE__ */ jsxs10("div", { className: "rounded-lg border border-[hsl(var(--border)/0.55)] bg-[hsl(var(--background)/0.72)] px-3 py-2.5 text-xs", children: [
3443
- /* @__PURE__ */ jsx12("p", { className: "line-clamp-2 break-words leading-5", children: ref.content_preview }),
3444
- ref.skill_name ? /* @__PURE__ */ jsx12("span", { className: "mt-1 inline-flex text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name }) : null
3580
+ expanded ? /* @__PURE__ */ jsx13("div", { className: "mt-2 flex flex-col gap-2 rounded-xl border border-[hsl(var(--border)/0.8)] bg-[hsl(var(--muted)/0.28)] p-2.5", children: refs.map((ref) => /* @__PURE__ */ jsxs11("div", { className: "rounded-lg border border-[hsl(var(--border)/0.55)] bg-[hsl(var(--background)/0.72)] px-3 py-2.5 text-xs", children: [
3581
+ /* @__PURE__ */ jsx13("p", { className: "line-clamp-2 break-words leading-5", children: ref.content_preview }),
3582
+ ref.skill_name ? /* @__PURE__ */ jsx13("span", { className: "mt-1 inline-flex text-[10px] text-[hsl(var(--primary))]", children: ref.skill_name }) : null
3445
3583
  ] }, ref.id)) }) : null
3446
3584
  ] });
3447
3585
  }
@@ -3455,15 +3593,15 @@ function AssistantMessageContent({
3455
3593
  const imageParts = getImageParts(message.content);
3456
3594
  const fileParts = getFileParts(message.content);
3457
3595
  const failed = message.status === "failed";
3458
- const failedBadge = failed ? /* @__PURE__ */ jsx12("div", { className: "w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }) : null;
3459
- const textContent = text ? /* @__PURE__ */ jsx12(
3596
+ const failedBadge = failed ? /* @__PURE__ */ jsx13("div", { className: "w-fit rounded-full border border-red-500/30 bg-red-500/10 px-2.5 py-1 text-[10px] font-medium text-red-400", children: "\u751F\u6210\u5931\u8D25" }) : null;
3597
+ const textContent = text ? /* @__PURE__ */ jsx13(
3460
3598
  "div",
3461
3599
  {
3462
3600
  className: cn(
3463
3601
  "blade-chat-assistant-text",
3464
3602
  compact ? "text-xs leading-[22px] text-[hsl(var(--foreground))]" : "text-[15px] leading-8 text-[hsl(var(--foreground))]"
3465
3603
  ),
3466
- children: /* @__PURE__ */ jsx12(
3604
+ children: /* @__PURE__ */ jsx13(
3467
3605
  MarkdownContent,
3468
3606
  {
3469
3607
  mode: streaming ? "streaming" : "static",
@@ -3476,14 +3614,14 @@ function AssistantMessageContent({
3476
3614
  ) : null;
3477
3615
  if (imageParts.length === 0 && fileParts.length === 0) {
3478
3616
  if (!failed) return textContent;
3479
- return failedBadge || textContent ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-2", children: [
3617
+ return failedBadge || textContent ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2", children: [
3480
3618
  failedBadge,
3481
3619
  textContent
3482
3620
  ] }) : null;
3483
3621
  }
3484
- return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3", children: [
3622
+ return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3", children: [
3485
3623
  failedBadge,
3486
- imageParts.length > 0 ? /* @__PURE__ */ jsx12("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx12(
3624
+ imageParts.length > 0 ? /* @__PURE__ */ jsx13("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx13(
3487
3625
  "img",
3488
3626
  {
3489
3627
  src: part.image_url.url,
@@ -3492,14 +3630,14 @@ function AssistantMessageContent({
3492
3630
  },
3493
3631
  part.image_url.url
3494
3632
  )) }) : null,
3495
- fileParts.length > 0 ? /* @__PURE__ */ jsx12("div", { className: "flex flex-wrap gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs10(
3633
+ fileParts.length > 0 ? /* @__PURE__ */ jsx13("div", { className: "flex flex-wrap gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs11(
3496
3634
  "div",
3497
3635
  {
3498
3636
  className: "flex min-w-0 items-center gap-1.5 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.3)] px-2.5 py-1.5 text-xs text-[hsl(var(--muted-foreground))]",
3499
3637
  title: part.name,
3500
3638
  children: [
3501
- /* @__PURE__ */ jsx12(FileText, { size: 12, className: "shrink-0" }),
3502
- /* @__PURE__ */ jsx12("span", { className: "max-w-56 truncate", children: part.name })
3639
+ /* @__PURE__ */ jsx13(FileText, { size: 12, className: "shrink-0" }),
3640
+ /* @__PURE__ */ jsx13("span", { className: "max-w-56 truncate", children: part.name })
3503
3641
  ]
3504
3642
  },
3505
3643
  `${part.name}-${part.data.slice(0, 32)}`
@@ -3510,7 +3648,7 @@ function AssistantMessageContent({
3510
3648
 
3511
3649
  // src/components/RenderErrorBoundary.tsx
3512
3650
  import { Component } from "react";
3513
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3651
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3514
3652
  function getFirstComponentName(componentStack) {
3515
3653
  const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
3516
3654
  return match?.[1] ?? null;
@@ -3543,26 +3681,26 @@ var RenderErrorBoundary = class extends Component {
3543
3681
  return children;
3544
3682
  }
3545
3683
  const componentName = getFirstComponentName(componentStack);
3546
- return /* @__PURE__ */ jsx13("div", { className: "blade-chat-render-error rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-2", children: [
3547
- /* @__PURE__ */ jsx13(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
3548
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
3549
- /* @__PURE__ */ jsxs11("div", { className: "font-medium", children: [
3684
+ return /* @__PURE__ */ jsx14("div", { className: "blade-chat-render-error rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2", children: [
3685
+ /* @__PURE__ */ jsx14(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
3686
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
3687
+ /* @__PURE__ */ jsxs12("div", { className: "font-medium", children: [
3550
3688
  label,
3551
3689
  "\u6E32\u67D3\u5931\u8D25"
3552
3690
  ] }),
3553
- /* @__PURE__ */ jsxs11("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
3691
+ /* @__PURE__ */ jsxs12("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
3554
3692
  componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
3555
3693
  error.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
3556
3694
  ] }),
3557
- details ? /* @__PURE__ */ jsx13("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
3695
+ details ? /* @__PURE__ */ jsx14("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
3558
3696
  ] })
3559
3697
  ] }) });
3560
3698
  }
3561
3699
  };
3562
3700
 
3563
3701
  // src/components/PostChatFollowupBlock.tsx
3564
- import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef11, useState as useState13 } from "react";
3565
- import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3702
+ import { useCallback as useCallback6, useEffect as useEffect11, useRef as useRef12, useState as useState14 } from "react";
3703
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3566
3704
  function emitInteraction(callback, event) {
3567
3705
  try {
3568
3706
  callback?.(event);
@@ -3581,10 +3719,10 @@ function ArtifactCard({
3581
3719
  onArtifactOpened
3582
3720
  }) {
3583
3721
  const client = useBladeClient();
3584
- const [downloading, setDownloading] = useState13(false);
3722
+ const [downloading, setDownloading] = useState14(false);
3585
3723
  const name = artifact.label || basename(artifact.target);
3586
3724
  if (artifact.kind === "link") {
3587
- return /* @__PURE__ */ jsxs12(
3725
+ return /* @__PURE__ */ jsxs13(
3588
3726
  "a",
3589
3727
  {
3590
3728
  href: artifact.target,
@@ -3595,9 +3733,9 @@ function ArtifactCard({
3595
3733
  ${artifact.target}`,
3596
3734
  className: "group relative flex min-w-0 items-center gap-1.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2 py-1.5 text-xs text-[hsl(var(--card-foreground))] hover:bg-[hsl(var(--accent))]",
3597
3735
  children: [
3598
- /* @__PURE__ */ jsx14(Globe, { size: 15, className: "shrink-0 text-[hsl(var(--primary))]" }),
3599
- /* @__PURE__ */ jsx14("span", { className: "min-w-0 flex-1 truncate font-medium", children: name }),
3600
- /* @__PURE__ */ jsx14(ArrowUpRight, { size: 13, className: "absolute right-2 opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" })
3736
+ /* @__PURE__ */ jsx15(Globe, { size: 15, className: "shrink-0 text-[hsl(var(--primary))]" }),
3737
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate font-medium", children: name }),
3738
+ /* @__PURE__ */ jsx15(ArrowUpRight, { size: 13, className: "absolute right-2 opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" })
3601
3739
  ]
3602
3740
  }
3603
3741
  );
@@ -3632,7 +3770,7 @@ ${artifact.target}`,
3632
3770
  setDownloading(false);
3633
3771
  }
3634
3772
  };
3635
- return /* @__PURE__ */ jsx14(
3773
+ return /* @__PURE__ */ jsx15(
3636
3774
  "a",
3637
3775
  {
3638
3776
  href: downloadUrl,
@@ -3660,17 +3798,17 @@ function feedbackReasonLabel(reason) {
3660
3798
  }
3661
3799
  function HistoricalResultFeedback({ feedback }) {
3662
3800
  const label = feedbackReasonLabel(feedback.reason);
3663
- return /* @__PURE__ */ jsxs12(
3801
+ return /* @__PURE__ */ jsxs13(
3664
3802
  "section",
3665
3803
  {
3666
3804
  "aria-label": "\u5386\u53F2\u7ED3\u679C\u53CD\u9988",
3667
3805
  className: "mt-3 w-fit max-w-full rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.2)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]",
3668
3806
  children: [
3669
- /* @__PURE__ */ jsxs12("span", { children: [
3807
+ /* @__PURE__ */ jsxs13("span", { children: [
3670
3808
  "\u4F60\u5BF9\u6B64\u8F6E\u7ED3\u679C\u7684\u8BC4\u4EF7\uFF1A",
3671
3809
  feedback.helpful ? "\u6709\u5E2E\u52A9" : "\u6CA1\u5E2E\u52A9"
3672
3810
  ] }),
3673
- label ? /* @__PURE__ */ jsxs12("span", { children: [
3811
+ label ? /* @__PURE__ */ jsxs13("span", { children: [
3674
3812
  " \xB7 ",
3675
3813
  label
3676
3814
  ] }) : null
@@ -3687,15 +3825,15 @@ function ResultFeedback({
3687
3825
  onFeedbackSaved
3688
3826
  }) {
3689
3827
  const client = useBladeClient();
3690
- const [saved, setSaved] = useState13(savedFeedback ?? null);
3691
- const [helpful, setHelpful] = useState13(savedFeedback?.helpful ?? null);
3692
- const [reason, setReason] = useState13(savedFeedback?.reason ?? null);
3693
- const [saving, setSaving] = useState13(false);
3694
- const [saveError, setSaveError] = useState13(false);
3695
- const reportedShown = useRef11(false);
3696
- const latestChoice = useRef11(null);
3828
+ const [saved, setSaved] = useState14(savedFeedback ?? null);
3829
+ const [helpful, setHelpful] = useState14(savedFeedback?.helpful ?? null);
3830
+ const [reason, setReason] = useState14(savedFeedback?.reason ?? null);
3831
+ const [saving, setSaving] = useState14(false);
3832
+ const [saveError, setSaveError] = useState14(false);
3833
+ const reportedShown = useRef12(false);
3834
+ const latestChoice = useRef12(null);
3697
3835
  const eligible = followup.feedback_eligible === true && Boolean(sessionId) && !isViewer;
3698
- useEffect10(() => {
3836
+ useEffect11(() => {
3699
3837
  if (!eligible || reportedShown.current) return;
3700
3838
  reportedShown.current = true;
3701
3839
  emitInteraction(onInteraction, {
@@ -3704,7 +3842,7 @@ function ResultFeedback({
3704
3842
  assistantEntryId: followup.assistant_entry_id
3705
3843
  });
3706
3844
  }, [eligible, followup.assistant_entry_id, onInteraction, sessionId]);
3707
- useEffect10(() => {
3845
+ useEffect11(() => {
3708
3846
  if (!savedFeedback || latestChoice.current) return;
3709
3847
  setSaved(savedFeedback);
3710
3848
  setHelpful(savedFeedback.helpful);
@@ -3745,15 +3883,15 @@ function ResultFeedback({
3745
3883
  [client, followup.assistant_entry_id, onFeedbackSaved, onInteraction, sessionId]
3746
3884
  );
3747
3885
  if (!eligible) return null;
3748
- return /* @__PURE__ */ jsxs12(
3886
+ return /* @__PURE__ */ jsxs13(
3749
3887
  "section",
3750
3888
  {
3751
3889
  "aria-label": "\u7ED3\u679C\u53CD\u9988",
3752
3890
  className: "flex flex-col gap-2 border-t border-[hsl(var(--border))] pt-3",
3753
3891
  children: [
3754
- /* @__PURE__ */ jsx14("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u76EE\u524D\u7684\u6574\u4F53\u7ED3\u679C\u6709\u5E2E\u52A9\u5417\uFF1F" }),
3755
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap gap-1.5", children: [
3756
- /* @__PURE__ */ jsx14(
3892
+ /* @__PURE__ */ jsx15("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u76EE\u524D\u7684\u6574\u4F53\u7ED3\u679C\u6709\u5E2E\u52A9\u5417\uFF1F" }),
3893
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap gap-1.5", children: [
3894
+ /* @__PURE__ */ jsx15(
3757
3895
  "button",
3758
3896
  {
3759
3897
  type: "button",
@@ -3764,7 +3902,7 @@ function ResultFeedback({
3764
3902
  children: "\u6709\u5E2E\u52A9"
3765
3903
  }
3766
3904
  ),
3767
- /* @__PURE__ */ jsx14(
3905
+ /* @__PURE__ */ jsx15(
3768
3906
  "button",
3769
3907
  {
3770
3908
  type: "button",
@@ -3776,7 +3914,7 @@ function ResultFeedback({
3776
3914
  }
3777
3915
  )
3778
3916
  ] }),
3779
- helpful === false ? /* @__PURE__ */ jsx14("div", { className: "flex flex-wrap gap-1.5", "aria-label": "\u6CA1\u5E2E\u52A9\u7684\u4E3B\u8981\u539F\u56E0", children: FEEDBACK_REASONS.map((item) => /* @__PURE__ */ jsx14(
3917
+ helpful === false ? /* @__PURE__ */ jsx15("div", { className: "flex flex-wrap gap-1.5", "aria-label": "\u6CA1\u5E2E\u52A9\u7684\u4E3B\u8981\u539F\u56E0", children: FEEDBACK_REASONS.map((item) => /* @__PURE__ */ jsx15(
3780
3918
  "button",
3781
3919
  {
3782
3920
  type: "button",
@@ -3788,9 +3926,9 @@ function ResultFeedback({
3788
3926
  },
3789
3927
  item.value
3790
3928
  )) }) : null,
3791
- saveError ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--destructive))]", children: [
3792
- /* @__PURE__ */ jsx14("span", { children: "\u53CD\u9988\u6682\u672A\u4FDD\u5B58\uFF0C\u53EF\u91CD\u8BD5" }),
3793
- /* @__PURE__ */ jsx14(
3929
+ saveError ? /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--destructive))]", children: [
3930
+ /* @__PURE__ */ jsx15("span", { children: "\u53CD\u9988\u6682\u672A\u4FDD\u5B58\uFF0C\u53EF\u91CD\u8BD5" }),
3931
+ /* @__PURE__ */ jsx15(
3794
3932
  "button",
3795
3933
  {
3796
3934
  type: "button",
@@ -3802,7 +3940,7 @@ function ResultFeedback({
3802
3940
  children: "\u91CD\u8BD5"
3803
3941
  }
3804
3942
  )
3805
- ] }) : saved ? /* @__PURE__ */ jsx14("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539" }) : null
3943
+ ] }) : saved ? /* @__PURE__ */ jsx15("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539" }) : null
3806
3944
  ]
3807
3945
  }
3808
3946
  );
@@ -3816,14 +3954,14 @@ function PostChatFollowupBlock({
3816
3954
  savedFeedback,
3817
3955
  onFeedbackSaved
3818
3956
  }) {
3819
- const [expanded, setExpanded] = useState13(false);
3820
- const adopted = useRef11(/* @__PURE__ */ new Set());
3821
- const reportedSuggestions = useRef11(false);
3822
- const reportedArtifacts = useRef11(/* @__PURE__ */ new Set());
3823
- const openedArtifacts = useRef11(/* @__PURE__ */ new Set());
3957
+ const [expanded, setExpanded] = useState14(false);
3958
+ const adopted = useRef12(/* @__PURE__ */ new Set());
3959
+ const reportedSuggestions = useRef12(false);
3960
+ const reportedArtifacts = useRef12(/* @__PURE__ */ new Set());
3961
+ const openedArtifacts = useRef12(/* @__PURE__ */ new Set());
3824
3962
  const artifacts = followup.final_artifacts ?? [];
3825
3963
  const visibleArtifacts = expanded ? artifacts : artifacts.slice(0, 3);
3826
- useEffect10(() => {
3964
+ useEffect11(() => {
3827
3965
  if (!reportedSuggestions.current && followup.suggestions.length > 0) {
3828
3966
  reportedSuggestions.current = true;
3829
3967
  emitInteraction(onInteraction, {
@@ -3869,15 +4007,15 @@ function PostChatFollowupBlock({
3869
4007
  );
3870
4008
  if (!followup.recaption && artifacts.length === 0 && followup.suggestions.length === 0 && !followup.feedback_eligible)
3871
4009
  return null;
3872
- return /* @__PURE__ */ jsxs12("div", { className: "mt-3 flex w-fit max-w-full flex-col gap-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.28)] p-3 sm:max-w-[680px]", children: [
3873
- followup.recaption || artifacts.length > 0 ? /* @__PURE__ */ jsxs12("section", { "aria-label": "\u672C\u8F6E\u5C0F\u7ED3", className: "flex flex-col gap-2", children: [
3874
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 text-xs font-medium text-[hsl(var(--muted-foreground))]", children: [
3875
- /* @__PURE__ */ jsx14(Sparkles, { size: 14 }),
4010
+ return /* @__PURE__ */ jsxs13("div", { className: "mt-3 flex w-fit max-w-full flex-col gap-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.28)] p-3 sm:max-w-[680px]", children: [
4011
+ followup.recaption || artifacts.length > 0 ? /* @__PURE__ */ jsxs13("section", { "aria-label": "\u672C\u8F6E\u5C0F\u7ED3", className: "flex flex-col gap-2", children: [
4012
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 text-xs font-medium text-[hsl(var(--muted-foreground))]", children: [
4013
+ /* @__PURE__ */ jsx15(Sparkles, { size: 14 }),
3876
4014
  "\u672C\u8F6E\u5C0F\u7ED3"
3877
4015
  ] }),
3878
- followup.recaption ? /* @__PURE__ */ jsx14("p", { className: "text-[13px] leading-5", children: followup.recaption }) : null,
3879
- artifacts.length > 0 ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
3880
- /* @__PURE__ */ jsx14("div", { className: "grid max-w-full grid-cols-3 gap-1.5", children: visibleArtifacts.map((artifact, artifactIndex) => /* @__PURE__ */ jsx14(
4016
+ followup.recaption ? /* @__PURE__ */ jsx15("p", { className: "text-[13px] leading-5", children: followup.recaption }) : null,
4017
+ artifacts.length > 0 ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
4018
+ /* @__PURE__ */ jsx15("div", { className: "grid max-w-full grid-cols-3 gap-1.5", children: visibleArtifacts.map((artifact, artifactIndex) => /* @__PURE__ */ jsx15(
3881
4019
  ArtifactCard,
3882
4020
  {
3883
4021
  artifact,
@@ -3889,7 +4027,7 @@ function PostChatFollowupBlock({
3889
4027
  },
3890
4028
  `${artifact.kind}:${artifactIndex}`
3891
4029
  )) }),
3892
- artifacts.length > 3 ? /* @__PURE__ */ jsxs12(
4030
+ artifacts.length > 3 ? /* @__PURE__ */ jsxs13(
3893
4031
  "button",
3894
4032
  {
3895
4033
  type: "button",
@@ -3898,15 +4036,15 @@ function PostChatFollowupBlock({
3898
4036
  className: "flex w-fit items-center gap-0.5 text-[11px] text-[hsl(var(--muted-foreground))]",
3899
4037
  children: [
3900
4038
  expanded ? "\u6536\u8D77" : `\u5C55\u5F00 ${artifacts.length - 3} \u4E2A`,
3901
- /* @__PURE__ */ jsx14(ChevronDown, { size: 13, className: expanded ? "rotate-180" : void 0 })
4039
+ /* @__PURE__ */ jsx15(ChevronDown, { size: 13, className: expanded ? "rotate-180" : void 0 })
3902
4040
  ]
3903
4041
  }
3904
4042
  ) : null
3905
4043
  ] }) : null
3906
4044
  ] }) : null,
3907
- followup.suggestions.length > 0 ? /* @__PURE__ */ jsxs12("section", { "aria-label": "\u4E0B\u4E00\u6B65\u5EFA\u8BAE", className: "flex flex-col gap-1.5", children: [
3908
- /* @__PURE__ */ jsx14("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u4E0B\u4E00\u6B65\u53EF\u4EE5" }),
3909
- followup.suggestions.map((suggestion, suggestionIndex) => /* @__PURE__ */ jsxs12(
4045
+ followup.suggestions.length > 0 ? /* @__PURE__ */ jsxs13("section", { "aria-label": "\u4E0B\u4E00\u6B65\u5EFA\u8BAE", className: "flex flex-col gap-1.5", children: [
4046
+ /* @__PURE__ */ jsx15("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u4E0B\u4E00\u6B65\u53EF\u4EE5" }),
4047
+ followup.suggestions.map((suggestion, suggestionIndex) => /* @__PURE__ */ jsxs13(
3910
4048
  "button",
3911
4049
  {
3912
4050
  type: "button",
@@ -3925,14 +4063,14 @@ function PostChatFollowupBlock({
3925
4063
  },
3926
4064
  className: "group flex items-center gap-2 rounded-xl bg-[hsl(var(--muted)/0.62)] px-3 py-2 text-left text-[13px] disabled:cursor-default disabled:opacity-60",
3927
4065
  children: [
3928
- /* @__PURE__ */ jsx14("span", { children: suggestion }),
3929
- /* @__PURE__ */ jsx14(ArrowRight, { size: 14, className: "ml-auto shrink-0" })
4066
+ /* @__PURE__ */ jsx15("span", { children: suggestion }),
4067
+ /* @__PURE__ */ jsx15(ArrowRight, { size: 14, className: "ml-auto shrink-0" })
3930
4068
  ]
3931
4069
  },
3932
4070
  suggestion
3933
4071
  ))
3934
4072
  ] }) : null,
3935
- /* @__PURE__ */ jsx14(
4073
+ /* @__PURE__ */ jsx15(
3936
4074
  ResultFeedback,
3937
4075
  {
3938
4076
  followup,
@@ -4007,31 +4145,31 @@ function parseWhatIfPrompt(text) {
4007
4145
  }
4008
4146
 
4009
4147
  // src/components/WhatIfUserBubble.tsx
4010
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
4148
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
4011
4149
  function WhatIfUserBubble({ parsed, onQuoteClick }) {
4012
4150
  const { fromStep, quotes, userText } = parsed;
4013
- return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-end gap-2", children: [
4014
- /* @__PURE__ */ jsxs13("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: [
4015
- /* @__PURE__ */ jsx15(RefreshCcw, { size: 10 }),
4016
- /* @__PURE__ */ jsx15("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
4151
+ return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-end gap-2", children: [
4152
+ /* @__PURE__ */ jsxs14("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: [
4153
+ /* @__PURE__ */ jsx16(RefreshCcw, { size: 10 }),
4154
+ /* @__PURE__ */ jsx16("span", { children: fromStep != null ? `\u91CD\u8DD1\u81EA step ${fromStep}` : "\u91CD\u8DD1" })
4017
4155
  ] }),
4018
- quotes.length > 0 && /* @__PURE__ */ jsx15("div", { className: "flex max-w-[min(72vw,42rem)] flex-col items-stretch gap-2", children: quotes.map((quote, index) => {
4156
+ quotes.length > 0 && /* @__PURE__ */ jsx16("div", { className: "flex max-w-[min(72vw,42rem)] flex-col items-stretch gap-2", children: quotes.map((quote, index) => {
4019
4157
  const clickable = quote.stepNumber != null && !!onQuoteClick;
4020
4158
  const label = quote.stepNumber != null ? `\u6B65\u9AA4${quote.stepNumber} \xB7 ${quote.label}` : quote.label;
4021
- return /* @__PURE__ */ jsxs13("div", { className: "rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.8)] px-3 py-2 text-left", children: [
4022
- /* @__PURE__ */ jsxs13("button", { type: "button", disabled: !clickable, onClick: () => clickable && onQuoteClick(quote.stepNumber), className: "inline-flex max-w-full items-center gap-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] disabled:cursor-default", title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0, children: [
4023
- /* @__PURE__ */ jsx15("span", { children: "\u21B3" }),
4024
- /* @__PURE__ */ jsx15("span", { className: "truncate", children: label })
4159
+ return /* @__PURE__ */ jsxs14("div", { className: "rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.8)] px-3 py-2 text-left", children: [
4160
+ /* @__PURE__ */ jsxs14("button", { type: "button", disabled: !clickable, onClick: () => clickable && onQuoteClick(quote.stepNumber), className: "inline-flex max-w-full items-center gap-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] disabled:cursor-default", title: clickable ? "\u8DF3\u8F6C\u5230\u5BF9\u5E94\u6B65\u9AA4\u5361\u7247" : void 0, children: [
4161
+ /* @__PURE__ */ jsx16("span", { children: "\u21B3" }),
4162
+ /* @__PURE__ */ jsx16("span", { className: "truncate", children: label })
4025
4163
  ] }),
4026
- quote.snapshot ? /* @__PURE__ */ jsx15("div", { className: "mt-1 border-l-2 border-[hsl(var(--accent-foreground)/0.35)] pl-2 text-xs leading-relaxed text-[hsl(var(--foreground)/0.8)]", children: /* @__PURE__ */ jsx15(MarkdownContent, { className: "blade-chat-prose", children: quote.snapshot }) }) : null
4164
+ quote.snapshot ? /* @__PURE__ */ jsx16("div", { className: "mt-1 border-l-2 border-[hsl(var(--accent-foreground)/0.35)] pl-2 text-xs leading-relaxed text-[hsl(var(--foreground)/0.8)]", children: /* @__PURE__ */ jsx16(MarkdownContent, { className: "blade-chat-prose", children: quote.snapshot }) }) : null
4027
4165
  ] }, `${quote.stepNumber ?? "x"}-${index}`);
4028
4166
  }) }),
4029
- userText && /* @__PURE__ */ jsx15("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))]", children: /* @__PURE__ */ jsx15(MarkdownContent, { className: "blade-chat-prose", children: userText }) })
4167
+ userText && /* @__PURE__ */ jsx16("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))]", children: /* @__PURE__ */ jsx16(MarkdownContent, { className: "blade-chat-prose", children: userText }) })
4030
4168
  ] });
4031
4169
  }
4032
4170
 
4033
4171
  // src/components/UserMessageBubble.tsx
4034
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
4172
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4035
4173
  function isUserMessage(message) {
4036
4174
  return message.role === "user";
4037
4175
  }
@@ -4045,10 +4183,10 @@ function UserMessageBubble({ message, className }) {
4045
4183
  const imageParts = getImageParts2(message.content);
4046
4184
  const whatifParsed = text && imageParts.length === 0 && fileParts.length === 0 ? parseWhatIfPrompt(text) : null;
4047
4185
  if (whatifParsed) {
4048
- return /* @__PURE__ */ jsx16("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsx16("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: /* @__PURE__ */ jsx16(WhatIfUserBubble, { parsed: whatifParsed }) }) });
4186
+ return /* @__PURE__ */ jsx17("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsx17("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: /* @__PURE__ */ jsx17(WhatIfUserBubble, { parsed: whatifParsed }) }) });
4049
4187
  }
4050
- return /* @__PURE__ */ jsx16("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsxs14("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: [
4051
- imageParts.length > 0 && /* @__PURE__ */ jsx16("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx16(
4188
+ return /* @__PURE__ */ jsx17("div", { className: cn("blade-chat-user-row flex justify-end", className), children: /* @__PURE__ */ jsxs15("div", { className: "blade-chat-user-col flex max-w-[72%] flex-col items-end gap-3", children: [
4189
+ imageParts.length > 0 && /* @__PURE__ */ jsx17("div", { className: "grid gap-2", children: imageParts.map((part) => /* @__PURE__ */ jsx17(
4052
4190
  "img",
4053
4191
  {
4054
4192
  src: part.image_url.url,
@@ -4057,21 +4195,21 @@ function UserMessageBubble({ message, className }) {
4057
4195
  },
4058
4196
  part.image_url.url
4059
4197
  )) }),
4060
- fileParts.length > 0 && /* @__PURE__ */ jsx16("div", { className: "flex flex-col items-end gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs14(
4198
+ fileParts.length > 0 && /* @__PURE__ */ jsx17("div", { className: "flex flex-col items-end gap-1.5", children: fileParts.map((part) => /* @__PURE__ */ jsxs15(
4061
4199
  "div",
4062
4200
  {
4063
4201
  className: "flex items-center gap-1.5 rounded-lg border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--muted)/0.3)] px-2.5 py-1.5 text-xs text-[hsl(var(--muted-foreground))]",
4064
4202
  children: [
4065
- /* @__PURE__ */ jsx16(FileText, { size: 12, className: "shrink-0" }),
4066
- /* @__PURE__ */ jsx16("span", { className: "max-w-56 truncate", title: part.name, children: part.name })
4203
+ /* @__PURE__ */ jsx17(FileText, { size: 12, className: "shrink-0" }),
4204
+ /* @__PURE__ */ jsx17("span", { className: "max-w-56 truncate", title: part.name, children: part.name })
4067
4205
  ]
4068
4206
  },
4069
4207
  `${part.name}-${part.data.length}`
4070
4208
  )) }),
4071
- text && /* @__PURE__ */ jsx16("div", { className: "blade-chat-user-bubble max-w-full rounded-[20px] rounded-br-[6px] border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-[18px] py-[13px] text-sm leading-[1.65] text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx16(MarkdownContent, { className: "blade-chat-prose", children: text }) }),
4072
- text && isSending(message) && /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
4073
- /* @__PURE__ */ jsx16(LoaderCircle, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
4074
- /* @__PURE__ */ jsx16("span", { children: "\u53D1\u9001\u4E2D" })
4209
+ text && /* @__PURE__ */ jsx17("div", { className: "blade-chat-user-bubble max-w-full rounded-[20px] rounded-br-[6px] border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-[18px] py-[13px] text-sm leading-[1.65] text-[hsl(var(--user-msg-fg))]", children: /* @__PURE__ */ jsx17(MarkdownContent, { className: "blade-chat-prose", children: text }) }),
4210
+ text && isSending(message) && /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
4211
+ /* @__PURE__ */ jsx17(LoaderCircle, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
4212
+ /* @__PURE__ */ jsx17("span", { children: "\u53D1\u9001\u4E2D" })
4075
4213
  ] })
4076
4214
  ] }) });
4077
4215
  }
@@ -4080,11 +4218,11 @@ function ErrorMessageBlock({
4080
4218
  className
4081
4219
  }) {
4082
4220
  const text = chatErrorForDisplay(getTextContent2(message.content));
4083
- return /* @__PURE__ */ jsx16("div", { className: cn("blade-chat-error-row flex min-w-0 justify-start", className), children: /* @__PURE__ */ jsx16("div", { className: "blade-chat-error-block min-w-0 max-w-full whitespace-pre-wrap break-words border-l-[3px] border-[hsl(var(--border))] px-3 py-1 text-left text-sm leading-7 text-[hsl(var(--muted-foreground))] [overflow-wrap:anywhere]", children: text }) });
4221
+ return /* @__PURE__ */ jsx17("div", { className: cn("blade-chat-error-row flex min-w-0 justify-start", className), children: /* @__PURE__ */ jsx17("div", { className: "blade-chat-error-block min-w-0 max-w-full whitespace-pre-wrap break-words border-l-[3px] border-[hsl(var(--border))] px-3 py-1 text-left text-sm leading-7 text-[hsl(var(--muted-foreground))] [overflow-wrap:anywhere]", children: text }) });
4084
4222
  }
4085
4223
 
4086
4224
  // src/components/MessageList.tsx
4087
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4225
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4088
4226
  function parseModeChange(message) {
4089
4227
  if (message.kind !== "mode_change" || typeof message.content !== "string") {
4090
4228
  return null;
@@ -4218,25 +4356,25 @@ function MessageList({
4218
4356
  }
4219
4357
  return blocks;
4220
4358
  }, [messages, isStreaming]);
4221
- return /* @__PURE__ */ jsxs15("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: [
4222
- isStreaming ? /* @__PURE__ */ jsx17("output", { className: "sr-only", children: "\u6B63\u5728\u751F\u6210\u56DE\u590D" }) : null,
4223
- /* @__PURE__ */ jsxs15(
4359
+ return /* @__PURE__ */ jsxs16("div", { className: cn("blade-chat-messages relative min-h-0 flex-1", className), children: [
4360
+ isStreaming ? /* @__PURE__ */ jsx18("output", { className: "sr-only", children: "\u6B63\u5728\u751F\u6210\u56DE\u590D" }) : null,
4361
+ /* @__PURE__ */ jsxs16(
4224
4362
  StickToBottom,
4225
4363
  {
4226
4364
  className: "h-full overflow-y-hidden",
4227
4365
  initial: "instant",
4228
4366
  resize: "instant",
4229
4367
  children: [
4230
- /* @__PURE__ */ jsx17(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsxs15("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: [
4231
- historyPaging && (historyPaging.hasOlder || historyPaging.loading) ? /* @__PURE__ */ jsx17(LoadOlderSentinel, { ...historyPaging }) : null,
4232
- /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-col", children: [
4233
- renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs15("div", { className: "blade-chat-empty", children: [
4234
- /* @__PURE__ */ jsx17(MessageSquare, { size: 40, strokeWidth: 1.5 }),
4235
- /* @__PURE__ */ jsx17("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
4236
- /* @__PURE__ */ jsx17("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
4368
+ /* @__PURE__ */ jsx18(StickToBottom.Content, { className: "blade-chat-messages-scroll", children: /* @__PURE__ */ jsxs16("div", { className: "blade-chat-messages-content mx-auto max-w-[748px]", children: [
4369
+ historyPaging && (historyPaging.hasOlder || historyPaging.loading) ? /* @__PURE__ */ jsx18(LoadOlderSentinel, { ...historyPaging }) : null,
4370
+ /* @__PURE__ */ jsxs16("div", { className: "flex min-w-0 flex-col", children: [
4371
+ renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */ jsxs16("div", { className: "blade-chat-empty", children: [
4372
+ /* @__PURE__ */ jsx18(MessageSquare, { size: 40, strokeWidth: 1.5 }),
4373
+ /* @__PURE__ */ jsx18("span", { className: "text-base font-medium", children: "\u5F00\u59CB\u5BF9\u8BDD" }),
4374
+ /* @__PURE__ */ jsx18("span", { className: "text-sm opacity-60", children: "\u5728\u4E0B\u65B9\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u804A\u5929" })
4237
4375
  ] }) : renderBlocks.map((block) => {
4238
4376
  if (block.type === "message") {
4239
- return /* @__PURE__ */ jsx17("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx17(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx17(ErrorMessageBlock, { message: block.message }) : null }, block.key);
4377
+ return /* @__PURE__ */ jsx18("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx18(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx18(ErrorMessageBlock, { message: block.message }) : null }, block.key);
4240
4378
  }
4241
4379
  if (block.type === "assistant_turn") {
4242
4380
  const blockFeedback = block.messages.map(
@@ -4247,14 +4385,14 @@ function MessageList({
4247
4385
  (message) => message.entry_id === postChatFollowup.assistant_entry_id
4248
4386
  )
4249
4387
  );
4250
- return /* @__PURE__ */ jsx17("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs15(
4388
+ return /* @__PURE__ */ jsx18("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs16(
4251
4389
  RenderErrorBoundary,
4252
4390
  {
4253
4391
  label: "\u52A9\u624B\u6D88\u606F",
4254
4392
  details: block.key,
4255
4393
  resetKey: getMessageResetSignature(block.messages),
4256
4394
  children: [
4257
- /* @__PURE__ */ jsx17(
4395
+ /* @__PURE__ */ jsx18(
4258
4396
  AssistantTurnBlock,
4259
4397
  {
4260
4398
  messages: block.messages,
@@ -4267,8 +4405,8 @@ function MessageList({
4267
4405
  sessionId
4268
4406
  }
4269
4407
  ),
4270
- blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx17(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
4271
- hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx17(
4408
+ blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx18(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
4409
+ hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx18(
4272
4410
  PostChatFollowupBlock,
4273
4411
  {
4274
4412
  followup: postChatFollowup,
@@ -4285,24 +4423,24 @@ function MessageList({
4285
4423
  ) }, block.key);
4286
4424
  }
4287
4425
  if (block.type === "compaction") {
4288
- return /* @__PURE__ */ jsxs15(
4426
+ return /* @__PURE__ */ jsxs16(
4289
4427
  "div",
4290
4428
  {
4291
4429
  className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]",
4292
4430
  children: [
4293
- /* @__PURE__ */ jsx17(Layers, { size: 12 }),
4294
- /* @__PURE__ */ jsx17("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
4431
+ /* @__PURE__ */ jsx18(Layers, { size: 12 }),
4432
+ /* @__PURE__ */ jsx18("span", { children: "\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29" })
4295
4433
  ]
4296
4434
  },
4297
4435
  block.key
4298
4436
  );
4299
4437
  }
4300
- return /* @__PURE__ */ jsx17(PlanningDivider, { kind: block.kind }, block.key);
4438
+ return /* @__PURE__ */ jsx18(PlanningDivider, { kind: block.kind }, block.key);
4301
4439
  }),
4302
- sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx17("div", { className: "flex", children: /* @__PURE__ */ jsx17("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
4440
+ sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */ jsx18("div", { className: "flex", children: /* @__PURE__ */ jsx18("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
4303
4441
  ] })
4304
4442
  ] }) }),
4305
- /* @__PURE__ */ jsx17(
4443
+ /* @__PURE__ */ jsx18(
4306
4444
  PinLatestUserMessage,
4307
4445
  {
4308
4446
  userMessageCount: userMessages.length,
@@ -4312,7 +4450,7 @@ function MessageList({
4312
4450
  },
4313
4451
  sessionId ?? "no-session"
4314
4452
  ),
4315
- /* @__PURE__ */ jsx17(ScrollToBottomButton, {})
4453
+ /* @__PURE__ */ jsx18(ScrollToBottomButton, {})
4316
4454
  ]
4317
4455
  },
4318
4456
  sessionId ?? "no-session"
@@ -4325,10 +4463,10 @@ function LoadOlderSentinel({
4325
4463
  loadOlder
4326
4464
  }) {
4327
4465
  const { contentRef, scrollRef } = useStickToBottomContext();
4328
- const sentinelRef = useRef12(null);
4329
- const stateRef = useRef12({ hasOlder, loading, loadOlder });
4466
+ const sentinelRef = useRef13(null);
4467
+ const stateRef = useRef13({ hasOlder, loading, loadOlder });
4330
4468
  stateRef.current = { hasOlder, loading, loadOlder };
4331
- useEffect11(() => {
4469
+ useEffect12(() => {
4332
4470
  const sentinel = sentinelRef.current;
4333
4471
  const scroller = scrollRef.current;
4334
4472
  if (!sentinel || !scroller || typeof IntersectionObserver === "undefined") return;
@@ -4387,7 +4525,7 @@ function LoadOlderSentinel({
4387
4525
  observer.disconnect();
4388
4526
  };
4389
4527
  }, [contentRef, scrollRef]);
4390
- return /* @__PURE__ */ jsx17("div", { ref: sentinelRef, "data-history-sentinel": true, className: "flex h-6 items-center justify-center", children: loading ? /* @__PURE__ */ jsx17("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u52A0\u8F7D\u66F4\u65E9\u6D88\u606F\u2026" }) : null });
4528
+ return /* @__PURE__ */ jsx18("div", { ref: sentinelRef, "data-history-sentinel": true, className: "flex h-6 items-center justify-center", children: loading ? /* @__PURE__ */ jsx18("span", { className: "text-xs text-[hsl(var(--muted-foreground))]", children: "\u6B63\u5728\u52A0\u8F7D\u66F4\u65E9\u6D88\u606F\u2026" }) : null });
4391
4529
  }
4392
4530
  function PinLatestUserMessage({
4393
4531
  userMessageCount,
@@ -4396,8 +4534,8 @@ function PinLatestUserMessage({
4396
4534
  targetKey
4397
4535
  }) {
4398
4536
  const { contentRef, scrollRef, scrollToBottom, stopScroll } = useStickToBottomContext();
4399
- const previousCountRef = useRef12(userMessageCount);
4400
- const spacerHeightRef = useRef12(0);
4537
+ const previousCountRef = useRef13(userMessageCount);
4538
+ const spacerHeightRef = useRef13(0);
4401
4539
  const getScrollElement = useCallback7(() => scrollRef.current, [scrollRef]);
4402
4540
  const getContentElement = useCallback7(() => contentRef.current, [contentRef]);
4403
4541
  const getTargetElement = useCallback7(() => {
@@ -4427,7 +4565,7 @@ function PinLatestUserMessage({
4427
4565
  stopAutoScroll: stopScroll,
4428
4566
  scrollToBottom
4429
4567
  });
4430
- useEffect11(() => {
4568
+ useEffect12(() => {
4431
4569
  if (userMessageCount > previousCountRef.current && !shouldPinLatestUser) {
4432
4570
  scrollToBottom("instant");
4433
4571
  }
@@ -4437,9 +4575,9 @@ function PinLatestUserMessage({
4437
4575
  }
4438
4576
  function ScrollToBottomButton() {
4439
4577
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
4440
- const [visible, setVisible] = useState14(false);
4441
- const hideTimerRef = useRef12(null);
4442
- useEffect11(() => {
4578
+ const [visible, setVisible] = useState15(false);
4579
+ const hideTimerRef = useRef13(null);
4580
+ useEffect12(() => {
4443
4581
  if (isAtBottom) {
4444
4582
  if (!hideTimerRef.current) {
4445
4583
  hideTimerRef.current = setTimeout(() => {
@@ -4470,7 +4608,7 @@ function ScrollToBottomButton() {
4470
4608
  scrollToBottom();
4471
4609
  }, [scrollToBottom]);
4472
4610
  if (!visible) return null;
4473
- return /* @__PURE__ */ jsxs15(
4611
+ return /* @__PURE__ */ jsxs16(
4474
4612
  "button",
4475
4613
  {
4476
4614
  type: "button",
@@ -4478,25 +4616,25 @@ function ScrollToBottomButton() {
4478
4616
  "aria-label": "\u6EDA\u52A8\u5230\u5E95\u90E8",
4479
4617
  className: "blade-chat-scroll-bottom absolute bottom-4 right-4 flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-1.5 text-xs text-[hsl(var(--muted-foreground))] shadow-lg transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
4480
4618
  children: [
4481
- /* @__PURE__ */ jsx17(ChevronDown, { size: 14 }),
4482
- /* @__PURE__ */ jsx17("span", { className: "blade-chat-scroll-bottom-label", children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
4619
+ /* @__PURE__ */ jsx18(ChevronDown, { size: 14 }),
4620
+ /* @__PURE__ */ jsx18("span", { className: "blade-chat-scroll-bottom-label", children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
4483
4621
  ]
4484
4622
  }
4485
4623
  );
4486
4624
  }
4487
4625
  function PlanningDivider({ kind }) {
4488
- return /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-3 py-1", children: [
4489
- /* @__PURE__ */ jsx17("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
4490
- /* @__PURE__ */ jsxs15("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: [
4491
- /* @__PURE__ */ jsx17(Lightbulb, { size: 12 }),
4492
- /* @__PURE__ */ jsx17("span", { children: kind === "enter" ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
4626
+ return /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-3 py-1", children: [
4627
+ /* @__PURE__ */ jsx18("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" }),
4628
+ /* @__PURE__ */ jsxs16("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: [
4629
+ /* @__PURE__ */ jsx18(Lightbulb, { size: 12 }),
4630
+ /* @__PURE__ */ jsx18("span", { children: kind === "enter" ? "\u8FDB\u5165\u89C4\u5212\u6A21\u5F0F" : "\u89C4\u5212\u5B8C\u6210" })
4493
4631
  ] }),
4494
- /* @__PURE__ */ jsx17("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
4632
+ /* @__PURE__ */ jsx18("div", { className: "h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent" })
4495
4633
  ] });
4496
4634
  }
4497
4635
 
4498
4636
  // src/components/ChatSurface.tsx
4499
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4637
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
4500
4638
  function themeAttr(theme) {
4501
4639
  return theme === "dark" ? "dark" : void 0;
4502
4640
  }
@@ -4532,7 +4670,7 @@ function ChatSurface({
4532
4670
  historyPaging,
4533
4671
  banner
4534
4672
  }) {
4535
- return /* @__PURE__ */ jsxs16(
4673
+ return /* @__PURE__ */ jsxs17(
4536
4674
  "div",
4537
4675
  {
4538
4676
  "data-theme": themeAttr(theme),
@@ -4541,14 +4679,14 @@ function ChatSurface({
4541
4679
  classNames?.root
4542
4680
  ),
4543
4681
  children: [
4544
- /* @__PURE__ */ jsx18(ConnectionBanner, { connection, className: classNames?.banner }),
4682
+ /* @__PURE__ */ jsx19(ConnectionBanner, { connection, className: classNames?.banner }),
4545
4683
  banner,
4546
- errorMessage && /* @__PURE__ */ jsxs16("div", { className: "blade-chat-error-bar flex items-start gap-2 border-b px-4 py-3 text-sm", children: [
4547
- /* @__PURE__ */ jsx18(CircleAlert, { size: 16, className: "mt-0.5 shrink-0" }),
4548
- /* @__PURE__ */ jsx18("span", { className: "min-w-0 whitespace-pre-wrap break-words [overflow-wrap:anywhere]", children: chatErrorForDisplay2(errorMessage) })
4684
+ errorMessage && /* @__PURE__ */ jsxs17("div", { className: "blade-chat-error-bar flex items-start gap-2 border-b px-4 py-3 text-sm", children: [
4685
+ /* @__PURE__ */ jsx19(CircleAlert, { size: 16, className: "mt-0.5 shrink-0" }),
4686
+ /* @__PURE__ */ jsx19("span", { className: "min-w-0 whitespace-pre-wrap break-words [overflow-wrap:anywhere]", children: chatErrorForDisplay2(errorMessage) })
4549
4687
  ] }),
4550
4688
  slots?.header,
4551
- /* @__PURE__ */ jsx18(
4689
+ /* @__PURE__ */ jsx19(
4552
4690
  MessageList,
4553
4691
  {
4554
4692
  messages,
@@ -4570,7 +4708,7 @@ function ChatSurface({
4570
4708
  historyPaging
4571
4709
  }
4572
4710
  ),
4573
- showPlanUpdates ? /* @__PURE__ */ jsx18(
4711
+ showPlanUpdates ? /* @__PURE__ */ jsx19(
4574
4712
  CurrentPlanPanel,
4575
4713
  {
4576
4714
  messages,
@@ -4581,7 +4719,7 @@ function ChatSurface({
4581
4719
  }
4582
4720
  ) : null,
4583
4721
  beforeInput,
4584
- /* @__PURE__ */ jsx18(
4722
+ /* @__PURE__ */ jsx19(
4585
4723
  ChatInput,
4586
4724
  {
4587
4725
  value: inputText,
@@ -4603,13 +4741,13 @@ function ChatSurface({
4603
4741
  }
4604
4742
 
4605
4743
  // src/components/AgentChat.tsx
4606
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
4744
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4607
4745
  function isUnauthorizedError(error) {
4608
4746
  return error instanceof BladeApiError && error.status === 401;
4609
4747
  }
4610
4748
  function LoginCard({ client, onLoggedIn }) {
4611
- const [loggingIn, setLoggingIn] = useState15(false);
4612
- const [loginError, setLoginError] = useState15(null);
4749
+ const [loggingIn, setLoggingIn] = useState16(false);
4750
+ const [loginError, setLoginError] = useState16(null);
4613
4751
  const handleLogin = async () => {
4614
4752
  setLoggingIn(true);
4615
4753
  setLoginError(null);
@@ -4622,11 +4760,11 @@ function LoginCard({ client, onLoggedIn }) {
4622
4760
  setLoggingIn(false);
4623
4761
  }
4624
4762
  };
4625
- return /* @__PURE__ */ jsx19("div", { className: "blade-chat-login flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs17("div", { className: "flex w-full max-w-sm flex-col items-center gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-6 py-8 text-center", children: [
4626
- /* @__PURE__ */ jsx19(LockKeyhole, { size: 28, className: "text-[hsl(var(--muted-foreground))]" }),
4627
- /* @__PURE__ */ jsx19("div", { className: "text-base font-medium text-[hsl(var(--foreground))]", children: "\u9700\u8981\u767B\u5F55\u540E\u4F7F\u7528" }),
4628
- /* @__PURE__ */ jsx19("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u767B\u5F55\u540E\u5373\u53EF\u4E0E\u667A\u80FD\u4F53\u5BF9\u8BDD\uFF0C\u4F60\u7684\u4F1A\u8BDD\u5185\u5BB9\u4EC5\u81EA\u5DF1\u53EF\u89C1\u3002" }),
4629
- /* @__PURE__ */ jsx19(
4763
+ return /* @__PURE__ */ jsx20("div", { className: "blade-chat-login flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs18("div", { className: "flex w-full max-w-sm flex-col items-center gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-6 py-8 text-center", children: [
4764
+ /* @__PURE__ */ jsx20(LockKeyhole, { size: 28, className: "text-[hsl(var(--muted-foreground))]" }),
4765
+ /* @__PURE__ */ jsx20("div", { className: "text-base font-medium text-[hsl(var(--foreground))]", children: "\u9700\u8981\u767B\u5F55\u540E\u4F7F\u7528" }),
4766
+ /* @__PURE__ */ jsx20("div", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u767B\u5F55\u540E\u5373\u53EF\u4E0E\u667A\u80FD\u4F53\u5BF9\u8BDD\uFF0C\u4F60\u7684\u4F1A\u8BDD\u5185\u5BB9\u4EC5\u81EA\u5DF1\u53EF\u89C1\u3002" }),
4767
+ /* @__PURE__ */ jsx20(
4630
4768
  "button",
4631
4769
  {
4632
4770
  type: "button",
@@ -4636,20 +4774,20 @@ function LoginCard({ client, onLoggedIn }) {
4636
4774
  children: loggingIn ? "\u767B\u5F55\u4E2D\u2026" : "\u767B\u5F55"
4637
4775
  }
4638
4776
  ),
4639
- loginError && /* @__PURE__ */ jsx19("div", { className: "text-xs text-[hsl(var(--destructive))]", children: loginError })
4777
+ loginError && /* @__PURE__ */ jsx20("div", { className: "text-xs text-[hsl(var(--destructive))]", children: loginError })
4640
4778
  ] }) });
4641
4779
  }
4642
4780
  function AgentChat(props) {
4643
4781
  const client = useBladeClient();
4644
- const [attempt, setAttempt] = useState15(0);
4645
- const [needLogin, setNeedLogin] = useState15(() => !client.hasToken());
4782
+ const [attempt, setAttempt] = useState16(0);
4783
+ const [needLogin, setNeedLogin] = useState16(() => !client.hasToken());
4646
4784
  if (needLogin) {
4647
- return /* @__PURE__ */ jsx19(
4785
+ return /* @__PURE__ */ jsx20(
4648
4786
  "div",
4649
4787
  {
4650
4788
  "data-theme": themeAttr(props.theme),
4651
4789
  className: cn("blade-chat flex min-h-0 flex-1 flex-col", props.classNames?.root),
4652
- children: /* @__PURE__ */ jsx19(
4790
+ children: /* @__PURE__ */ jsx20(
4653
4791
  LoginCard,
4654
4792
  {
4655
4793
  client,
@@ -4662,7 +4800,7 @@ function AgentChat(props) {
4662
4800
  }
4663
4801
  );
4664
4802
  }
4665
- return /* @__PURE__ */ jsx19(ChatSessionView, { ...props, onUnauthorized: () => setNeedLogin(true) }, attempt);
4803
+ return /* @__PURE__ */ jsx20(ChatSessionView, { ...props, onUnauthorized: () => setNeedLogin(true) }, attempt);
4666
4804
  }
4667
4805
  function ChatSessionView({
4668
4806
  sessionId,
@@ -4680,7 +4818,7 @@ function ChatSessionView({
4680
4818
  onUnauthorized
4681
4819
  }) {
4682
4820
  const client = useBladeClient();
4683
- const [planRevealRevisions, setPlanRevealRevisions] = useState15(
4821
+ const [planRevealRevisions, setPlanRevealRevisions] = useState16(
4684
4822
  () => /* @__PURE__ */ new Map()
4685
4823
  );
4686
4824
  const handleSessionConnected = useCallback8((connectedSession) => {
@@ -4701,12 +4839,12 @@ function ChatSessionView({
4701
4839
  onSessionConnected: handleSessionConnected
4702
4840
  });
4703
4841
  const replay = useReplay(session);
4704
- const [stopRequested, setStopRequested] = useState15(false);
4705
- const [inputText, setInputText] = useState15("");
4706
- const [resultFeedback, setResultFeedback] = useState15([]);
4842
+ const [stopRequested, setStopRequested] = useState16(false);
4843
+ const [inputText, setInputText] = useState16("");
4844
+ const [resultFeedback, setResultFeedback] = useState16([]);
4707
4845
  const resolvedSessionId = session?.sessionId;
4708
4846
  const isViewer = state?.viewerRole === "viewer";
4709
- useEffect12(() => {
4847
+ useEffect13(() => {
4710
4848
  setResultFeedback([]);
4711
4849
  if (!resolvedSessionId || isViewer) return;
4712
4850
  let cancelled = false;
@@ -4741,12 +4879,12 @@ function ChatSessionView({
4741
4879
  saved
4742
4880
  ]);
4743
4881
  }, []);
4744
- useEffect12(() => {
4882
+ useEffect13(() => {
4745
4883
  if (session) {
4746
4884
  onSessionReady?.(session);
4747
4885
  }
4748
4886
  }, [session, onSessionReady]);
4749
- useEffect12(() => {
4887
+ useEffect13(() => {
4750
4888
  if (!session) return;
4751
4889
  const offAttach = session.on("attachRequested", ({ label, content }) => {
4752
4890
  setInputText((prev) => `${prev ? `${prev}
@@ -4762,12 +4900,12 @@ ${content}`);
4762
4900
  offInsert();
4763
4901
  };
4764
4902
  }, [session]);
4765
- useEffect12(() => {
4903
+ useEffect13(() => {
4766
4904
  if (isUnauthorizedError(error)) {
4767
4905
  onUnauthorized();
4768
4906
  }
4769
4907
  }, [error, onUnauthorized]);
4770
- useEffect12(() => {
4908
+ useEffect13(() => {
4771
4909
  if (!session || !commands) return;
4772
4910
  const unsubscribes = Object.entries(commands).map(
4773
4911
  ([action, handler]) => session.onCommand(action, (payload) => handler(payload))
@@ -4789,7 +4927,7 @@ ${content}`);
4789
4927
  setStopRequested(true);
4790
4928
  void session?.stop();
4791
4929
  };
4792
- return /* @__PURE__ */ jsx19(
4930
+ return /* @__PURE__ */ jsx20(
4793
4931
  ChatSurface,
4794
4932
  {
4795
4933
  theme,
@@ -4799,9 +4937,9 @@ ${content}`);
4799
4937
  slots,
4800
4938
  placeholder,
4801
4939
  connection: state?.connection ?? "connecting",
4802
- banner: /* @__PURE__ */ jsxs17(Fragment4, { children: [
4803
- resolvedSessionId && !isViewer && sessionPluginControls?.(resolvedSessionId),
4804
- /* @__PURE__ */ jsx19(
4940
+ banner: /* @__PURE__ */ jsxs18(Fragment4, { children: [
4941
+ resolvedSessionId && !isViewer && (sessionPluginControls ? sessionPluginControls(resolvedSessionId) : /* @__PURE__ */ jsx20(SessionPluginSelector, { client, sessionId: resolvedSessionId })),
4942
+ /* @__PURE__ */ jsx20(
4805
4943
  ReplayBar,
4806
4944
  {
4807
4945
  isReplay: replay.isReplay,
@@ -4811,7 +4949,7 @@ ${content}`);
4811
4949
  onExit: () => void replay.exitToAutonomous()
4812
4950
  }
4813
4951
  ),
4814
- /* @__PURE__ */ jsx19(ReplayMismatchPrompt, { mismatch: replay.mismatch })
4952
+ /* @__PURE__ */ jsx20(ReplayMismatchPrompt, { mismatch: replay.mismatch })
4815
4953
  ] }),
4816
4954
  errorMessage,
4817
4955
  messages: state?.messages ?? [],
@@ -4854,11 +4992,11 @@ ${content}`);
4854
4992
  }
4855
4993
 
4856
4994
  // src/components/LlmChat.tsx
4857
- import { useEffect as useEffect13, useMemo as useMemo9, useState as useState17 } from "react";
4995
+ import { useEffect as useEffect14, useMemo as useMemo9, useState as useState18 } from "react";
4858
4996
 
4859
4997
  // src/components/LlmAdvancedSettings.tsx
4860
- import { useState as useState16 } from "react";
4861
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4998
+ import { useState as useState17 } from "react";
4999
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4862
5000
  var FIELDS = [
4863
5001
  { id: "baseURL", label: "\u6A21\u578B\u670D\u52A1\u5730\u5740", placeholder: "http://\u5185\u7F51\u5730\u5740/v1" },
4864
5002
  { id: "model", label: "\u6A21\u578B", placeholder: "\u6A21\u578B\u540D\u79F0" },
@@ -4904,13 +5042,13 @@ function writeOverride(settings, baseURL, override) {
4904
5042
  }
4905
5043
  function LlmAdvancedSettingsBar({ settings, defaults, override, onChange }) {
4906
5044
  const normalized = normalizeAdvanced(settings);
4907
- const [open, setOpen] = useState16(false);
4908
- const [draft, setDraft] = useState16(override);
5045
+ const [open, setOpen] = useState17(false);
5046
+ const [draft, setDraft] = useState17(override);
4909
5047
  if (!normalized) return null;
4910
5048
  const fields = FIELDS.filter((field) => normalized[field.id]);
4911
5049
  const dirty = Object.keys(override).length > 0;
4912
- return /* @__PURE__ */ jsxs18("div", { className: "blade-chat-advanced border-t border-[hsl(var(--border))] px-4 py-2 text-xs", children: [
4913
- /* @__PURE__ */ jsxs18(
5050
+ return /* @__PURE__ */ jsxs19("div", { className: "blade-chat-advanced border-t border-[hsl(var(--border))] px-4 py-2 text-xs", children: [
5051
+ /* @__PURE__ */ jsxs19(
4914
5052
  "button",
4915
5053
  {
4916
5054
  type: "button",
@@ -4920,16 +5058,16 @@ function LlmAdvancedSettingsBar({ settings, defaults, override, onChange }) {
4920
5058
  },
4921
5059
  className: "flex items-center gap-1.5 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
4922
5060
  children: [
4923
- /* @__PURE__ */ jsx20(Settings2, { size: 13 }),
5061
+ /* @__PURE__ */ jsx21(Settings2, { size: 13 }),
4924
5062
  "\u9AD8\u7EA7\u8BBE\u7F6E",
4925
- dirty && /* @__PURE__ */ jsx20("span", { className: "text-[hsl(var(--primary))]", children: "\uFF08\u5DF2\u81EA\u5B9A\u4E49\uFF09" })
5063
+ dirty && /* @__PURE__ */ jsx21("span", { className: "text-[hsl(var(--primary))]", children: "\uFF08\u5DF2\u81EA\u5B9A\u4E49\uFF09" })
4926
5064
  ]
4927
5065
  }
4928
5066
  ),
4929
- open && /* @__PURE__ */ jsxs18("div", { className: "mt-2 flex flex-col gap-2", children: [
4930
- fields.map((field) => /* @__PURE__ */ jsxs18("label", { className: "flex flex-col gap-1", children: [
4931
- /* @__PURE__ */ jsx20("span", { className: "text-[hsl(var(--muted-foreground))]", children: field.label }),
4932
- /* @__PURE__ */ jsx20(
5067
+ open && /* @__PURE__ */ jsxs19("div", { className: "mt-2 flex flex-col gap-2", children: [
5068
+ fields.map((field) => /* @__PURE__ */ jsxs19("label", { className: "flex flex-col gap-1", children: [
5069
+ /* @__PURE__ */ jsx21("span", { className: "text-[hsl(var(--muted-foreground))]", children: field.label }),
5070
+ /* @__PURE__ */ jsx21(
4933
5071
  "input",
4934
5072
  {
4935
5073
  type: field.secret ? "password" : "text",
@@ -4940,9 +5078,9 @@ function LlmAdvancedSettingsBar({ settings, defaults, override, onChange }) {
4940
5078
  }
4941
5079
  )
4942
5080
  ] }, field.id)),
4943
- normalized.apiKey && /* @__PURE__ */ jsx20("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u5BC6\u94A5\u4F1A\u5B58\u5728\u8FD9\u53F0\u6D4F\u89C8\u5668\u91CC\u3002\u53EA\u5728\u4F60\u4FE1\u5F97\u8FC7\u8FD9\u53F0\u673A\u5668\u65F6\u586B\u3002" }),
4944
- /* @__PURE__ */ jsxs18("div", { className: "flex gap-2", children: [
4945
- /* @__PURE__ */ jsx20(
5081
+ normalized.apiKey && /* @__PURE__ */ jsx21("p", { className: "text-[hsl(var(--muted-foreground))]", children: "\u5BC6\u94A5\u4F1A\u5B58\u5728\u8FD9\u53F0\u6D4F\u89C8\u5668\u91CC\u3002\u53EA\u5728\u4F60\u4FE1\u5F97\u8FC7\u8FD9\u53F0\u673A\u5668\u65F6\u586B\u3002" }),
5082
+ /* @__PURE__ */ jsxs19("div", { className: "flex gap-2", children: [
5083
+ /* @__PURE__ */ jsx21(
4946
5084
  "button",
4947
5085
  {
4948
5086
  type: "button",
@@ -4957,7 +5095,7 @@ function LlmAdvancedSettingsBar({ settings, defaults, override, onChange }) {
4957
5095
  children: "\u4FDD\u5B58"
4958
5096
  }
4959
5097
  ),
4960
- /* @__PURE__ */ jsx20(
5098
+ /* @__PURE__ */ jsx21(
4961
5099
  "button",
4962
5100
  {
4963
5101
  type: "button",
@@ -4976,7 +5114,7 @@ function LlmAdvancedSettingsBar({ settings, defaults, override, onChange }) {
4976
5114
  }
4977
5115
 
4978
5116
  // src/components/LlmChat.tsx
4979
- import { jsx as jsx21 } from "react/jsx-runtime";
5117
+ import { jsx as jsx22 } from "react/jsx-runtime";
4980
5118
  function LlmChat({
4981
5119
  classNames,
4982
5120
  renderers,
@@ -4988,11 +5126,11 @@ function LlmChat({
4988
5126
  onOverrideChange,
4989
5127
  ...options
4990
5128
  }) {
4991
- const [override, setOverride] = useState17(() => readOverride(advanced, options.baseURL));
5129
+ const [override, setOverride] = useState18(() => readOverride(advanced, options.baseURL));
4992
5130
  const effective = { ...options, ...override };
4993
5131
  const { messages, isStreaming, error, send, stop, reset } = useLlmChat(effective);
4994
- const [inputText, setInputText] = useState17("");
4995
- const [stopRequested, setStopRequested] = useState17(false);
5132
+ const [inputText, setInputText] = useState18("");
5133
+ const [stopRequested, setStopRequested] = useState18(false);
4996
5134
  const handle = useMemo9(
4997
5135
  () => ({
4998
5136
  insertText: (text) => setInputText((prev) => prev ? `${prev}
@@ -5002,10 +5140,10 @@ ${text}` : text),
5002
5140
  }),
5003
5141
  [send, reset]
5004
5142
  );
5005
- useEffect13(() => {
5143
+ useEffect14(() => {
5006
5144
  onReady?.(handle);
5007
5145
  }, [handle, onReady]);
5008
- return /* @__PURE__ */ jsx21(
5146
+ return /* @__PURE__ */ jsx22(
5009
5147
  ChatSurface,
5010
5148
  {
5011
5149
  theme,
@@ -5030,7 +5168,7 @@ ${text}` : text),
5030
5168
  setStopRequested(true);
5031
5169
  stop();
5032
5170
  },
5033
- beforeInput: advanced ? /* @__PURE__ */ jsx21(
5171
+ beforeInput: advanced ? /* @__PURE__ */ jsx22(
5034
5172
  LlmAdvancedSettingsBar,
5035
5173
  {
5036
5174
  settings: advanced,
@@ -5048,14 +5186,14 @@ ${text}` : text),
5048
5186
  }
5049
5187
 
5050
5188
  // src/components/ChatView.tsx
5051
- import { jsx as jsx22 } from "react/jsx-runtime";
5189
+ import { jsx as jsx23 } from "react/jsx-runtime";
5052
5190
  function ChatView(props) {
5053
5191
  const { mode, llm, onLlmReady, ...rest } = props;
5054
5192
  if (mode === "llm") {
5055
5193
  if (!llm) {
5056
5194
  throw new Error('ChatView: mode="llm" \u9700\u8981\u540C\u65F6\u4F20 llm={{ baseURL, model }}');
5057
5195
  }
5058
- return /* @__PURE__ */ jsx22(
5196
+ return /* @__PURE__ */ jsx23(
5059
5197
  LlmChat,
5060
5198
  {
5061
5199
  ...llm,
@@ -5068,7 +5206,7 @@ function ChatView(props) {
5068
5206
  }
5069
5207
  );
5070
5208
  }
5071
- return /* @__PURE__ */ jsx22(AgentChat, { ...rest });
5209
+ return /* @__PURE__ */ jsx23(AgentChat, { ...rest });
5072
5210
  }
5073
5211
 
5074
5212
  // src/components/ContextCard.tsx
@@ -5076,16 +5214,16 @@ import {
5076
5214
  getContextDisplayState,
5077
5215
  getContextGroupDisplayState
5078
5216
  } from "@blade-hq/agent-client";
5079
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
5217
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5080
5218
  function ContextCard({ context, className }) {
5081
5219
  const display = getContextDisplayState(context);
5082
- return /* @__PURE__ */ jsxs19(
5220
+ return /* @__PURE__ */ jsxs20(
5083
5221
  "details",
5084
5222
  {
5085
5223
  className: `blade-chat-context-card group/context-card rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-sm ${className ?? ""}`,
5086
5224
  children: [
5087
- /* @__PURE__ */ jsxs19("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
5088
- /* @__PURE__ */ jsx23(
5225
+ /* @__PURE__ */ jsxs20("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
5226
+ /* @__PURE__ */ jsx24(
5089
5227
  Layers,
5090
5228
  {
5091
5229
  size: 15,
@@ -5093,11 +5231,11 @@ function ContextCard({ context, className }) {
5093
5231
  "aria-hidden": "true"
5094
5232
  }
5095
5233
  ),
5096
- /* @__PURE__ */ jsxs19("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
5097
- /* @__PURE__ */ jsx23("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: display.title }),
5098
- /* @__PURE__ */ jsx23("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: display.summary })
5234
+ /* @__PURE__ */ jsxs20("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
5235
+ /* @__PURE__ */ jsx24("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: display.title }),
5236
+ /* @__PURE__ */ jsx24("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: display.summary })
5099
5237
  ] }),
5100
- /* @__PURE__ */ jsx23(
5238
+ /* @__PURE__ */ jsx24(
5101
5239
  ChevronDown,
5102
5240
  {
5103
5241
  size: 14,
@@ -5106,7 +5244,7 @@ function ContextCard({ context, className }) {
5106
5244
  }
5107
5245
  )
5108
5246
  ] }),
5109
- /* @__PURE__ */ jsx23("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: display.detail })
5247
+ /* @__PURE__ */ jsx24("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: display.detail })
5110
5248
  ]
5111
5249
  }
5112
5250
  );
@@ -5115,9 +5253,9 @@ function ContextGroupCard({ contexts, className }) {
5115
5253
  if (contexts.length === 0) return null;
5116
5254
  const single = contexts.length === 1 ? getContextDisplayState(contexts[0]) : null;
5117
5255
  const group = single ? null : getContextGroupDisplayState(contexts);
5118
- return /* @__PURE__ */ jsxs19("details", { className: `blade-chat-context-card group/context-group rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-sm ${className ?? ""}`, children: [
5119
- /* @__PURE__ */ jsxs19("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
5120
- /* @__PURE__ */ jsx23(
5256
+ return /* @__PURE__ */ jsxs20("details", { className: `blade-chat-context-card group/context-group rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-sm ${className ?? ""}`, children: [
5257
+ /* @__PURE__ */ jsxs20("summary", { className: "blade-chat-context-summary flex cursor-pointer list-none items-center gap-2 px-3 py-2.5 [&::-webkit-details-marker]:hidden", children: [
5258
+ /* @__PURE__ */ jsx24(
5121
5259
  Layers,
5122
5260
  {
5123
5261
  size: 15,
@@ -5125,11 +5263,11 @@ function ContextGroupCard({ contexts, className }) {
5125
5263
  "aria-hidden": "true"
5126
5264
  }
5127
5265
  ),
5128
- /* @__PURE__ */ jsxs19("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
5129
- /* @__PURE__ */ jsx23("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: single ? single.title : `${group?.title} \xB7 ${group?.count} \u9879` }),
5130
- /* @__PURE__ */ jsx23("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: single ? single.summary : group?.summary })
5266
+ /* @__PURE__ */ jsxs20("span", { className: "blade-chat-context-copy min-w-0 flex-1", children: [
5267
+ /* @__PURE__ */ jsx24("span", { className: "blade-chat-context-title block font-medium text-[hsl(var(--foreground))]", children: single ? single.title : `${group?.title} \xB7 ${group?.count} \u9879` }),
5268
+ /* @__PURE__ */ jsx24("span", { className: "blade-chat-context-status block truncate text-xs text-[hsl(var(--muted-foreground))]", children: single ? single.summary : group?.summary })
5131
5269
  ] }),
5132
- /* @__PURE__ */ jsx23(
5270
+ /* @__PURE__ */ jsx24(
5133
5271
  ChevronDown,
5134
5272
  {
5135
5273
  size: 14,
@@ -5138,7 +5276,7 @@ function ContextGroupCard({ contexts, className }) {
5138
5276
  }
5139
5277
  )
5140
5278
  ] }),
5141
- single ? /* @__PURE__ */ jsx23("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: single.detail }) : /* @__PURE__ */ jsx23("div", { className: "blade-chat-context-group-items flex flex-col gap-1.5 border-t border-[hsl(var(--border))] p-2", children: contexts.map((context) => /* @__PURE__ */ jsx23(
5279
+ single ? /* @__PURE__ */ jsx24("div", { className: "blade-chat-context-detail border-t border-[hsl(var(--border))] px-3 py-2.5 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: single.detail }) : /* @__PURE__ */ jsx24("div", { className: "blade-chat-context-group-items flex flex-col gap-1.5 border-t border-[hsl(var(--border))] p-2", children: contexts.map((context) => /* @__PURE__ */ jsx24(
5142
5280
  ContextCard,
5143
5281
  {
5144
5282
  context
@@ -5149,8 +5287,8 @@ function ContextGroupCard({ contexts, className }) {
5149
5287
  }
5150
5288
 
5151
5289
  // src/components/SessionMemoryToggle.tsx
5152
- import { useCallback as useCallback9, useEffect as useEffect14, useRef as useRef13, useState as useState18, useSyncExternalStore as useSyncExternalStore2 } from "react";
5153
- import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5290
+ import { useCallback as useCallback9, useEffect as useEffect15, useRef as useRef14, useState as useState19, useSyncExternalStore as useSyncExternalStore2 } from "react";
5291
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
5154
5292
  var saveStates = /* @__PURE__ */ new WeakMap();
5155
5293
  function getSaveState(client, sessionId) {
5156
5294
  let clientStates = saveStates.get(client);
@@ -5207,10 +5345,10 @@ function SessionMemoryToggle({
5207
5345
  getSaving,
5208
5346
  getSaving
5209
5347
  );
5210
- const [draftEnabled, setDraftEnabled] = useState18(enabled);
5211
- const activeSessionIdRef = useRef13(sessionId);
5348
+ const [draftEnabled, setDraftEnabled] = useState19(enabled);
5349
+ const activeSessionIdRef = useRef14(sessionId);
5212
5350
  activeSessionIdRef.current = sessionId;
5213
- useEffect14(() => {
5351
+ useEffect15(() => {
5214
5352
  setDraftEnabled(enabled);
5215
5353
  }, [enabled, sessionId]);
5216
5354
  const update = useCallback9(
@@ -5239,9 +5377,9 @@ function SessionMemoryToggle({
5239
5377
  },
5240
5378
  [client, enabled, onError, onSaved, sessionId]
5241
5379
  );
5242
- return /* @__PURE__ */ jsxs20("label", { className: cn("flex items-center justify-between", className), children: [
5243
- /* @__PURE__ */ jsx24("span", { className: labelClassName, children: label }),
5244
- /* @__PURE__ */ jsx24(
5380
+ return /* @__PURE__ */ jsxs21("label", { className: cn("flex items-center justify-between", className), children: [
5381
+ /* @__PURE__ */ jsx25("span", { className: labelClassName, children: label }),
5382
+ /* @__PURE__ */ jsx25(
5245
5383
  "input",
5246
5384
  {
5247
5385
  type: "checkbox",
@@ -5313,6 +5451,7 @@ export {
5313
5451
  ReplayBar,
5314
5452
  ReplayMismatchPrompt,
5315
5453
  SessionMemoryToggle,
5454
+ SessionPluginSelector,
5316
5455
  WhatIfUserBubble,
5317
5456
  classifyAgentComputerLaunchOutcome,
5318
5457
  collectMemoryRefs,