@blade-hq/agent-react 2610.0.0-beta.47 → 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/README.md +6 -0
- package/dist/components/AgentChat.d.ts +1 -1
- package/dist/components/SessionPluginSelector.d.ts +10 -0
- package/dist/embed/entry.d.ts +3 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +601 -462
- package/dist/index.js.map +1 -1
- package/dist/style.full.css +1 -1
- package/package.json +2 -2
- package/public-api.md +48 -3
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
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1202
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1258
|
-
/* @__PURE__ */
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
/* @__PURE__ */
|
|
1261
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
1508
|
-
const collapseTimerRef =
|
|
1645
|
+
const [collapsed, setCollapsed] = useState5(!autoReveal);
|
|
1646
|
+
const collapseTimerRef = useRef5(null);
|
|
1509
1647
|
const data = parsePlanUpdate(toolCall.arguments);
|
|
1510
|
-
|
|
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
|
-
|
|
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__ */
|
|
1530
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1550
|
-
pausedAtCurrentStep ? /* @__PURE__ */
|
|
1551
|
-
] }) : /* @__PURE__ */
|
|
1552
|
-
/* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
1554
|
-
pausedAtCurrentStep ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
1584
|
-
/* @__PURE__ */
|
|
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 =
|
|
1745
|
+
const revealBaselinesRef = useRef5(/* @__PURE__ */ new Map([[sessionId, revealRevision]]));
|
|
1608
1746
|
const autoReveal = (revealBaselinesRef.current.get(sessionId) ?? 0) !== revealRevision;
|
|
1609
|
-
|
|
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__ */
|
|
1615
|
-
updating ? /* @__PURE__ */
|
|
1616
|
-
/* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
1636
|
-
import { Fragment, jsx as
|
|
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] =
|
|
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__ */
|
|
1688
|
-
/* @__PURE__ */
|
|
1689
|
-
/* @__PURE__ */
|
|
1690
|
-
/* @__PURE__ */
|
|
1691
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1694
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1712
|
-
sendMode === "queue" ? /* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
] }) : /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
1732
|
-
import { jsx as
|
|
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] =
|
|
1737
|
-
const connectedRef =
|
|
1738
|
-
const timersRef =
|
|
1874
|
+
const [phase, setPhase] = useState7("hidden");
|
|
1875
|
+
const connectedRef = useRef6(connected);
|
|
1876
|
+
const timersRef = useRef6([]);
|
|
1739
1877
|
connectedRef.current = connected;
|
|
1740
|
-
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
1797
|
-
/* @__PURE__ */
|
|
1798
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
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] =
|
|
1848
|
-
const [isAtBottom, updateIsAtBottom] =
|
|
1849
|
-
const [isNearBottom, setIsNearBottom] =
|
|
1850
|
-
const optionsRef =
|
|
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
|
|
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 :
|
|
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 =
|
|
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
|
|
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
|
|
2244
|
-
import { jsx as
|
|
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] =
|
|
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__ */
|
|
2264
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2280
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2443
|
+
useEffect as useEffect8,
|
|
2306
2444
|
useMemo as useMemo5,
|
|
2307
|
-
useRef as
|
|
2308
|
-
useState as
|
|
2445
|
+
useRef as useRef9,
|
|
2446
|
+
useState as useState10
|
|
2309
2447
|
} from "react";
|
|
2310
|
-
import { jsx as
|
|
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 =
|
|
2326
|
-
const [copied, setCopied] =
|
|
2327
|
-
const [language, setLanguage] =
|
|
2328
|
-
|
|
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__ */
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
/* @__PURE__ */
|
|
2342
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2353
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2531
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2394
2532
|
function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
|
|
2395
|
-
return /* @__PURE__ */
|
|
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
|
|
2537
|
+
import { useState as useState12 } from "react";
|
|
2400
2538
|
|
|
2401
2539
|
// src/components/AskUserQuestionBlock.tsx
|
|
2402
|
-
import { useEffect as
|
|
2403
|
-
import { jsx as
|
|
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 =
|
|
2412
|
-
|
|
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
|
-
|
|
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] =
|
|
2442
|
-
const [customTexts, setCustomTexts] =
|
|
2443
|
-
const [usingCustom, setUsingCustom] =
|
|
2444
|
-
const [note, setNote] =
|
|
2445
|
-
const [submitted, setSubmitted] =
|
|
2446
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2621
|
-
/* @__PURE__ */
|
|
2622
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2774
|
+
children: /* @__PURE__ */ jsx11(MarkdownContent, { className: "blade-chat-prose", children: question.question })
|
|
2637
2775
|
}
|
|
2638
2776
|
)
|
|
2639
2777
|
] }),
|
|
2640
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2674
|
-
/* @__PURE__ */
|
|
2675
|
-
opt.description && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2746
|
-
/* @__PURE__ */
|
|
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
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2889
|
-
/* @__PURE__ */
|
|
2890
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2897
|
-
/* @__PURE__ */
|
|
2898
|
-
/* @__PURE__ */
|
|
2899
|
-
errorDetail?.detail ? /* @__PURE__ */
|
|
2900
|
-
/* @__PURE__ */
|
|
2901
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2911
|
-
/* @__PURE__ */
|
|
2912
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3068
|
+
/* @__PURE__ */ jsxs10("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
|
|
2931
3069
|
statusIcon,
|
|
2932
|
-
/* @__PURE__ */
|
|
3070
|
+
/* @__PURE__ */ jsx12("span", { children: getToolStatusLabel(toolCall.status) })
|
|
2933
3071
|
] }),
|
|
2934
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2941
|
-
/* @__PURE__ */
|
|
2942
|
-
/* @__PURE__ */
|
|
2943
|
-
/* @__PURE__ */
|
|
2944
|
-
/* @__PURE__ */
|
|
2945
|
-
toolCall.result != null && /* @__PURE__ */
|
|
2946
|
-
/* @__PURE__ */
|
|
2947
|
-
/* @__PURE__ */
|
|
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
|
|
3103
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2966
3104
|
function ThinkingBlock({ reasoning, isStreaming }) {
|
|
2967
|
-
const [open, setOpen] =
|
|
3105
|
+
const [open, setOpen] = useState13(false);
|
|
2968
3106
|
if (!isStreaming) return null;
|
|
2969
|
-
return /* @__PURE__ */
|
|
2970
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3327
|
+
return /* @__PURE__ */ jsxs11("div", { "data-testid": "execution-tool-intent", className: rowClassName, title: label, children: [
|
|
3190
3328
|
icon,
|
|
3191
|
-
/* @__PURE__ */
|
|
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] =
|
|
3375
|
+
const [displayMode, setDisplayMode] = useState13(
|
|
3238
3376
|
() => isStreaming || hasActionableToolCall ? "detail" : "compact"
|
|
3239
3377
|
);
|
|
3240
|
-
const userSelectedDisplayModeRef =
|
|
3241
|
-
const wasStreamingRef =
|
|
3242
|
-
|
|
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] =
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
3269
|
-
hasInterrupted && /* @__PURE__ */
|
|
3270
|
-
hasFailedWithoutContent && /* @__PURE__ */
|
|
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__ */
|
|
3410
|
+
return hasRenderableMessageContent(message) ? /* @__PURE__ */ jsx13(
|
|
3273
3411
|
"div",
|
|
3274
3412
|
{
|
|
3275
3413
|
className: "flex flex-col gap-3",
|
|
3276
|
-
children: /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3299
|
-
hasInterrupted && /* @__PURE__ */
|
|
3300
|
-
hasFailedWithoutContent && /* @__PURE__ */
|
|
3301
|
-
/* @__PURE__ */
|
|
3302
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3445
|
+
children: /* @__PURE__ */ jsx13(Bot, { size: 16 })
|
|
3308
3446
|
}
|
|
3309
3447
|
),
|
|
3310
|
-
/* @__PURE__ */
|
|
3311
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
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__ */
|
|
3432
|
-
/* @__PURE__ */
|
|
3433
|
-
/* @__PURE__ */
|
|
3434
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3578
|
+
/* @__PURE__ */ jsx13(ChevronRight, { size: 10, className: cn("transition-transform", expanded && "rotate-90") })
|
|
3441
3579
|
] }),
|
|
3442
|
-
expanded ? /* @__PURE__ */
|
|
3443
|
-
/* @__PURE__ */
|
|
3444
|
-
ref.skill_name ? /* @__PURE__ */
|
|
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__ */
|
|
3459
|
-
const textContent = text ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3622
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3", children: [
|
|
3485
3623
|
failedBadge,
|
|
3486
|
-
imageParts.length > 0 ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3502
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
3547
|
-
/* @__PURE__ */
|
|
3548
|
-
/* @__PURE__ */
|
|
3549
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
3565
|
-
import { Fragment as Fragment3, jsx as
|
|
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] =
|
|
3722
|
+
const [downloading, setDownloading] = useState14(false);
|
|
3585
3723
|
const name = artifact.label || basename(artifact.target);
|
|
3586
3724
|
if (artifact.kind === "link") {
|
|
3587
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
3599
|
-
/* @__PURE__ */
|
|
3600
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
3691
|
-
const [helpful, setHelpful] =
|
|
3692
|
-
const [reason, setReason] =
|
|
3693
|
-
const [saving, setSaving] =
|
|
3694
|
-
const [saveError, setSaveError] =
|
|
3695
|
-
const reportedShown =
|
|
3696
|
-
const latestChoice =
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
3755
|
-
/* @__PURE__ */
|
|
3756
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3792
|
-
/* @__PURE__ */
|
|
3793
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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] =
|
|
3820
|
-
const adopted =
|
|
3821
|
-
const reportedSuggestions =
|
|
3822
|
-
const reportedArtifacts =
|
|
3823
|
-
const openedArtifacts =
|
|
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
|
-
|
|
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__ */
|
|
3873
|
-
followup.recaption || artifacts.length > 0 ? /* @__PURE__ */
|
|
3874
|
-
/* @__PURE__ */
|
|
3875
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3879
|
-
artifacts.length > 0 ? /* @__PURE__ */
|
|
3880
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3908
|
-
/* @__PURE__ */
|
|
3909
|
-
followup.suggestions.map((suggestion, suggestionIndex) => /* @__PURE__ */
|
|
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__ */
|
|
3929
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
4014
|
-
/* @__PURE__ */
|
|
4015
|
-
/* @__PURE__ */
|
|
4016
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4022
|
-
/* @__PURE__ */
|
|
4023
|
-
/* @__PURE__ */
|
|
4024
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
4051
|
-
imageParts.length > 0 && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4066
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4072
|
-
text && isSending(message) && /* @__PURE__ */
|
|
4073
|
-
/* @__PURE__ */
|
|
4074
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
4222
|
-
isStreaming ? /* @__PURE__ */
|
|
4223
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4231
|
-
historyPaging && (historyPaging.hasOlder || historyPaging.loading) ? /* @__PURE__ */
|
|
4232
|
-
/* @__PURE__ */
|
|
4233
|
-
renderBlocks.length === 0 ? emptyState ?? /* @__PURE__ */
|
|
4234
|
-
/* @__PURE__ */
|
|
4235
|
-
/* @__PURE__ */
|
|
4236
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4271
|
-
hasActiveFollowup && postChatFollowup ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4294
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4438
|
+
return /* @__PURE__ */ jsx18(PlanningDivider, { kind: block.kind }, block.key);
|
|
4301
4439
|
}),
|
|
4302
|
-
sessionStatus === "interrupted" && !isStreaming ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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 =
|
|
4329
|
-
const stateRef =
|
|
4466
|
+
const sentinelRef = useRef13(null);
|
|
4467
|
+
const stateRef = useRef13({ hasOlder, loading, loadOlder });
|
|
4330
4468
|
stateRef.current = { hasOlder, loading, loadOlder };
|
|
4331
|
-
|
|
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__ */
|
|
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 =
|
|
4400
|
-
const spacerHeightRef =
|
|
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
|
-
|
|
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] =
|
|
4441
|
-
const hideTimerRef =
|
|
4442
|
-
|
|
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__ */
|
|
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__ */
|
|
4482
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4489
|
-
/* @__PURE__ */
|
|
4490
|
-
/* @__PURE__ */
|
|
4491
|
-
/* @__PURE__ */
|
|
4492
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
4682
|
+
/* @__PURE__ */ jsx19(ConnectionBanner, { connection, className: classNames?.banner }),
|
|
4545
4683
|
banner,
|
|
4546
|
-
errorMessage && /* @__PURE__ */
|
|
4547
|
-
/* @__PURE__ */
|
|
4548
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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] =
|
|
4612
|
-
const [loginError, setLoginError] =
|
|
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__ */
|
|
4626
|
-
/* @__PURE__ */
|
|
4627
|
-
/* @__PURE__ */
|
|
4628
|
-
/* @__PURE__ */
|
|
4629
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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] =
|
|
4645
|
-
const [needLogin, setNeedLogin] =
|
|
4782
|
+
const [attempt, setAttempt] = useState16(0);
|
|
4783
|
+
const [needLogin, setNeedLogin] = useState16(() => !client.hasToken());
|
|
4646
4784
|
if (needLogin) {
|
|
4647
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
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] =
|
|
4705
|
-
const [inputText, setInputText] =
|
|
4706
|
-
const [resultFeedback, setResultFeedback] =
|
|
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
|
-
|
|
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
|
-
|
|
4882
|
+
useEffect13(() => {
|
|
4745
4883
|
if (session) {
|
|
4746
4884
|
onSessionReady?.(session);
|
|
4747
4885
|
}
|
|
4748
4886
|
}, [session, onSessionReady]);
|
|
4749
|
-
|
|
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
|
-
|
|
4903
|
+
useEffect13(() => {
|
|
4766
4904
|
if (isUnauthorizedError(error)) {
|
|
4767
4905
|
onUnauthorized();
|
|
4768
4906
|
}
|
|
4769
4907
|
}, [error, onUnauthorized]);
|
|
4770
|
-
|
|
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__ */
|
|
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__ */
|
|
4803
|
-
resolvedSessionId && !isViewer && sessionPluginControls
|
|
4804
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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
|
|
4861
|
-
import { jsx as
|
|
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] =
|
|
4908
|
-
const [draft, setDraft] =
|
|
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__ */
|
|
4913
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5061
|
+
/* @__PURE__ */ jsx21(Settings2, { size: 13 }),
|
|
4924
5062
|
"\u9AD8\u7EA7\u8BBE\u7F6E",
|
|
4925
|
-
dirty && /* @__PURE__ */
|
|
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__ */
|
|
4930
|
-
fields.map((field) => /* @__PURE__ */
|
|
4931
|
-
/* @__PURE__ */
|
|
4932
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4944
|
-
/* @__PURE__ */
|
|
4945
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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] =
|
|
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] =
|
|
4995
|
-
const [stopRequested, setStopRequested] =
|
|
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
|
-
|
|
5143
|
+
useEffect14(() => {
|
|
5006
5144
|
onReady?.(handle);
|
|
5007
5145
|
}, [handle, onReady]);
|
|
5008
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
5088
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5097
|
-
/* @__PURE__ */
|
|
5098
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
5119
|
-
/* @__PURE__ */
|
|
5120
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5129
|
-
/* @__PURE__ */
|
|
5130
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
5153
|
-
import { jsx as
|
|
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] =
|
|
5211
|
-
const activeSessionIdRef =
|
|
5348
|
+
const [draftEnabled, setDraftEnabled] = useState19(enabled);
|
|
5349
|
+
const activeSessionIdRef = useRef14(sessionId);
|
|
5212
5350
|
activeSessionIdRef.current = sessionId;
|
|
5213
|
-
|
|
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__ */
|
|
5243
|
-
/* @__PURE__ */
|
|
5244
|
-
/* @__PURE__ */
|
|
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,
|