@blade-hq/agent-react 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,8 @@
1
+ import {
2
+ _r,
3
+ clsx
4
+ } from "./chunk-ZXXLY4RM.js";
5
+
1
6
  // src/context.tsx
2
7
  import { createContext, useContext } from "react";
3
8
  import { jsx } from "react/jsx-runtime";
@@ -95,12 +100,246 @@ function useAgentSession(sessionId, options = {}) {
95
100
  }
96
101
 
97
102
  // src/components/ChatView.tsx
98
- import { BladeApiError, VersionMismatchError } from "@blade-hq/agent-client";
99
- import { CircleAlert, LockKeyhole } from "lucide-react";
100
- import { useEffect as useEffect5, useState as useState7 } from "react";
103
+ import { BladeApiError } from "@blade-hq/agent-client";
104
+
105
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/createLucideIcon.js
106
+ import { forwardRef as forwardRef2, createElement as createElement2 } from "react";
107
+
108
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/shared/src/utils.js
109
+ var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
110
+ var mergeClasses = (...classes) => classes.filter((className, index, array) => {
111
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
112
+ }).join(" ").trim();
113
+
114
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/Icon.js
115
+ import { forwardRef, createElement } from "react";
116
+
117
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/defaultAttributes.js
118
+ var defaultAttributes = {
119
+ xmlns: "http://www.w3.org/2000/svg",
120
+ width: 24,
121
+ height: 24,
122
+ viewBox: "0 0 24 24",
123
+ fill: "none",
124
+ stroke: "currentColor",
125
+ strokeWidth: 2,
126
+ strokeLinecap: "round",
127
+ strokeLinejoin: "round"
128
+ };
129
+
130
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/Icon.js
131
+ var Icon = forwardRef(
132
+ ({
133
+ color = "currentColor",
134
+ size = 24,
135
+ strokeWidth = 2,
136
+ absoluteStrokeWidth,
137
+ className = "",
138
+ children,
139
+ iconNode,
140
+ ...rest
141
+ }, ref) => {
142
+ return createElement(
143
+ "svg",
144
+ {
145
+ ref,
146
+ ...defaultAttributes,
147
+ width: size,
148
+ height: size,
149
+ stroke: color,
150
+ strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
151
+ className: mergeClasses("lucide", className),
152
+ ...rest
153
+ },
154
+ [
155
+ ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
156
+ ...Array.isArray(children) ? children : [children]
157
+ ]
158
+ );
159
+ }
160
+ );
161
+
162
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/createLucideIcon.js
163
+ var createLucideIcon = (iconName, iconNode) => {
164
+ const Component2 = forwardRef2(
165
+ ({ className, ...props }, ref) => createElement2(Icon, {
166
+ ref,
167
+ iconNode,
168
+ className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),
169
+ ...props
170
+ })
171
+ );
172
+ Component2.displayName = `${iconName}`;
173
+ return Component2;
174
+ };
175
+
176
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-up.js
177
+ var ArrowUp = createLucideIcon("ArrowUp", [
178
+ ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
179
+ ["path", { d: "M12 19V5", key: "x0mq9r" }]
180
+ ]);
181
+
182
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/bot.js
183
+ var Bot = createLucideIcon("Bot", [
184
+ ["path", { d: "M12 8V4H8", key: "hb8ula" }],
185
+ ["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
186
+ ["path", { d: "M2 14h2", key: "vft8re" }],
187
+ ["path", { d: "M20 14h2", key: "4cs60a" }],
188
+ ["path", { d: "M15 13v2", key: "1xurst" }],
189
+ ["path", { d: "M9 13v2", key: "rq6x2g" }]
190
+ ]);
191
+
192
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/brain.js
193
+ var Brain = createLucideIcon("Brain", [
194
+ [
195
+ "path",
196
+ {
197
+ d: "M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z",
198
+ key: "l5xja"
199
+ }
200
+ ],
201
+ [
202
+ "path",
203
+ {
204
+ d: "M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z",
205
+ key: "ep3f8r"
206
+ }
207
+ ],
208
+ ["path", { d: "M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4", key: "1p4c4q" }],
209
+ ["path", { d: "M17.599 6.5a3 3 0 0 0 .399-1.375", key: "tmeiqw" }],
210
+ ["path", { d: "M6.003 5.125A3 3 0 0 0 6.401 6.5", key: "105sqy" }],
211
+ ["path", { d: "M3.477 10.896a4 4 0 0 1 .585-.396", key: "ql3yin" }],
212
+ ["path", { d: "M19.938 10.5a4 4 0 0 1 .585.396", key: "1qfode" }],
213
+ ["path", { d: "M6 18a4 4 0 0 1-1.967-.516", key: "2e4loj" }],
214
+ ["path", { d: "M19.967 17.484A4 4 0 0 1 18 18", key: "159ez6" }]
215
+ ]);
216
+
217
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/check.js
218
+ var Check = createLucideIcon("Check", [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]]);
219
+
220
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/chevron-down.js
221
+ var ChevronDown = createLucideIcon("ChevronDown", [
222
+ ["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]
223
+ ]);
224
+
225
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/chevron-right.js
226
+ var ChevronRight = createLucideIcon("ChevronRight", [
227
+ ["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]
228
+ ]);
229
+
230
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/circle-alert.js
231
+ var CircleAlert = createLucideIcon("CircleAlert", [
232
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
233
+ ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
234
+ ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
235
+ ]);
236
+
237
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/copy.js
238
+ var Copy = createLucideIcon("Copy", [
239
+ ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
240
+ ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
241
+ ]);
242
+
243
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-text.js
244
+ var FileText = createLucideIcon("FileText", [
245
+ ["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
246
+ ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
247
+ ["path", { d: "M10 9H8", key: "b1mrlr" }],
248
+ ["path", { d: "M16 13H8", key: "t4e002" }],
249
+ ["path", { d: "M16 17H8", key: "z1uh3a" }]
250
+ ]);
251
+
252
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/layers.js
253
+ var Layers = createLucideIcon("Layers", [
254
+ [
255
+ "path",
256
+ {
257
+ d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",
258
+ key: "zw3jo"
259
+ }
260
+ ],
261
+ [
262
+ "path",
263
+ {
264
+ d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",
265
+ key: "1wduqc"
266
+ }
267
+ ],
268
+ [
269
+ "path",
270
+ {
271
+ d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",
272
+ key: "kqbvx6"
273
+ }
274
+ ]
275
+ ]);
276
+
277
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/lightbulb.js
278
+ var Lightbulb = createLucideIcon("Lightbulb", [
279
+ [
280
+ "path",
281
+ {
282
+ d: "M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5",
283
+ key: "1gvzjb"
284
+ }
285
+ ],
286
+ ["path", { d: "M9 18h6", key: "x1upvd" }],
287
+ ["path", { d: "M10 22h4", key: "ceow96" }]
288
+ ]);
289
+
290
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/loader-circle.js
291
+ var LoaderCircle = createLucideIcon("LoaderCircle", [
292
+ ["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]
293
+ ]);
294
+
295
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/lock-keyhole.js
296
+ var LockKeyhole = createLucideIcon("LockKeyhole", [
297
+ ["circle", { cx: "12", cy: "16", r: "1", key: "1au0dj" }],
298
+ ["rect", { x: "3", y: "10", width: "18", height: "12", rx: "2", key: "6s8ecr" }],
299
+ ["path", { d: "M7 10V7a5 5 0 0 1 10 0v3", key: "1pqi11" }]
300
+ ]);
301
+
302
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/message-square-more.js
303
+ var MessageSquareMore = createLucideIcon("MessageSquareMore", [
304
+ ["path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z", key: "1lielz" }],
305
+ ["path", { d: "M8 10h.01", key: "19clt8" }],
306
+ ["path", { d: "M12 10h.01", key: "1nrarc" }],
307
+ ["path", { d: "M16 10h.01", key: "1m94wz" }]
308
+ ]);
309
+
310
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/message-square.js
311
+ var MessageSquare = createLucideIcon("MessageSquare", [
312
+ ["path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z", key: "1lielz" }]
313
+ ]);
314
+
315
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/square.js
316
+ var Square = createLucideIcon("Square", [
317
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]
318
+ ]);
319
+
320
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/triangle-alert.js
321
+ var TriangleAlert = createLucideIcon("TriangleAlert", [
322
+ [
323
+ "path",
324
+ {
325
+ d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
326
+ key: "wmoenq"
327
+ }
328
+ ],
329
+ ["path", { d: "M12 9v4", key: "juzpu7" }],
330
+ ["path", { d: "M12 17h.01", key: "p32p05" }]
331
+ ]);
332
+
333
+ // ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/x.js
334
+ var X = createLucideIcon("X", [
335
+ ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
336
+ ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
337
+ ]);
338
+
339
+ // src/components/ChatView.tsx
340
+ import { useEffect as useEffect6, useState as useState8 } from "react";
101
341
 
102
342
  // src/lib/utils.ts
103
- import { clsx } from "clsx";
104
343
  function cn(...inputs) {
105
344
  return clsx(inputs);
106
345
  }
@@ -114,7 +353,6 @@ async function copyToClipboard(text) {
114
353
  }
115
354
 
116
355
  // src/components/ChatInput.tsx
117
- import { ArrowUp, Loader2, Square } from "lucide-react";
118
356
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
119
357
  function ChatInput({
120
358
  value,
@@ -166,7 +404,7 @@ function ChatInput({
166
404
  "aria-label": isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D",
167
405
  title: isStopping ? "\u6B63\u5728\u505C\u6B62" : "\u505C\u6B62\u56DE\u590D",
168
406
  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",
169
- children: isStopping ? /* @__PURE__ */ jsx2(Loader2, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Square, { size: 12, fill: "currentColor" })
407
+ children: isStopping ? /* @__PURE__ */ jsx2(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Square, { size: 12, fill: "currentColor" })
170
408
  }
171
409
  ) : /* @__PURE__ */ jsx2(
172
410
  "button",
@@ -184,7 +422,6 @@ function ChatInput({
184
422
  }
185
423
 
186
424
  // src/components/ConnectionBanner.tsx
187
- import { AlertTriangle, LoaderCircle } from "lucide-react";
188
425
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
189
426
  function ConnectionBanner({ connection, className }) {
190
427
  if (connection === "connected" || connection === "connecting") {
@@ -199,7 +436,7 @@ function ConnectionBanner({ connection, className }) {
199
436
  reconnecting ? "border-amber-500/25 bg-amber-500/10 text-amber-100" : "border-rose-500/25 bg-rose-500/10 text-rose-100"
200
437
  ),
201
438
  children: [
202
- /* @__PURE__ */ jsx3("span", { className: "mt-0.5 shrink-0", children: reconnecting ? /* @__PURE__ */ jsx3(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx3(AlertTriangle, { size: 14 }) }),
439
+ /* @__PURE__ */ jsx3("span", { className: "mt-0.5 shrink-0", children: reconnecting ? /* @__PURE__ */ jsx3(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx3(TriangleAlert, { size: 14 }) }),
203
440
  /* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
204
441
  /* @__PURE__ */ jsx3("div", { className: "text-sm font-medium", children: reconnecting ? "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u6B63\u5728\u91CD\u8FDE\u2026" : "\u8FDE\u63A5\u5DF2\u65AD\u5F00" }),
205
442
  /* @__PURE__ */ jsx3("div", { className: "text-xs opacity-80", children: "\u6D88\u606F\u540C\u6B65\u53EF\u80FD\u4F1A\u5EF6\u8FDF\uFF0C\u7CFB\u7EDF\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5" })
@@ -211,18 +448,438 @@ function ConnectionBanner({ connection, className }) {
211
448
 
212
449
  // src/components/MessageList.tsx
213
450
  import { isHiddenInternalMessage } from "@blade-hq/agent-client";
214
- import { ChevronDown as ChevronDown2, Layers, Lightbulb, MessageSquare } from "lucide-react";
215
- import { useEffect as useEffect4, useMemo as useMemo4, useRef as useRef3 } from "react";
216
- import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
451
+ import { useEffect as useEffect5, useMemo as useMemo6, useRef as useRef5 } from "react";
452
+
453
+ // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
454
+ import { useCallback, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
455
+ var DEFAULT_SPRING_ANIMATION = {
456
+ /**
457
+ * A value from 0 to 1, on how much to damp the animation.
458
+ * 0 means no damping, 1 means full damping.
459
+ *
460
+ * @default 0.7
461
+ */
462
+ damping: 0.7,
463
+ /**
464
+ * The stiffness of how fast/slow the animation gets up to speed.
465
+ *
466
+ * @default 0.05
467
+ */
468
+ stiffness: 0.05,
469
+ /**
470
+ * The inertial mass associated with the animation.
471
+ * Higher numbers make the animation slower.
472
+ *
473
+ * @default 1.25
474
+ */
475
+ mass: 1.25
476
+ };
477
+ var STICK_TO_BOTTOM_OFFSET_PX = 70;
478
+ var SIXTY_FPS_INTERVAL_MS = 1e3 / 60;
479
+ var RETAIN_ANIMATION_DURATION_MS = 350;
480
+ var mouseDown = false;
481
+ globalThis.document?.addEventListener("mousedown", () => {
482
+ mouseDown = true;
483
+ });
484
+ globalThis.document?.addEventListener("mouseup", () => {
485
+ mouseDown = false;
486
+ });
487
+ globalThis.document?.addEventListener("click", () => {
488
+ mouseDown = false;
489
+ });
490
+ var useStickToBottom = (options = {}) => {
491
+ const [escapedFromLock, updateEscapedFromLock] = useState2(false);
492
+ const [isAtBottom, updateIsAtBottom] = useState2(options.initial !== false);
493
+ const [isNearBottom, setIsNearBottom] = useState2(false);
494
+ const optionsRef = useRef2(null);
495
+ optionsRef.current = options;
496
+ const isSelecting = useCallback(() => {
497
+ if (!mouseDown) {
498
+ return false;
499
+ }
500
+ const selection = window.getSelection();
501
+ if (!selection || !selection.rangeCount) {
502
+ return false;
503
+ }
504
+ const range = selection.getRangeAt(0);
505
+ return range.commonAncestorContainer.contains(scrollRef.current) || scrollRef.current?.contains(range.commonAncestorContainer);
506
+ }, []);
507
+ const setIsAtBottom = useCallback((isAtBottom2) => {
508
+ state.isAtBottom = isAtBottom2;
509
+ updateIsAtBottom(isAtBottom2);
510
+ }, []);
511
+ const setEscapedFromLock = useCallback((escapedFromLock2) => {
512
+ state.escapedFromLock = escapedFromLock2;
513
+ updateEscapedFromLock(escapedFromLock2);
514
+ }, []);
515
+ const state = useMemo2(() => {
516
+ let lastCalculation;
517
+ return {
518
+ escapedFromLock,
519
+ isAtBottom,
520
+ resizeDifference: 0,
521
+ accumulated: 0,
522
+ velocity: 0,
523
+ listeners: /* @__PURE__ */ new Set(),
524
+ get scrollTop() {
525
+ return scrollRef.current?.scrollTop ?? 0;
526
+ },
527
+ set scrollTop(scrollTop) {
528
+ if (scrollRef.current) {
529
+ scrollRef.current.scrollTop = scrollTop;
530
+ state.ignoreScrollToTop = scrollRef.current.scrollTop;
531
+ }
532
+ },
533
+ get targetScrollTop() {
534
+ if (!scrollRef.current || !contentRef.current) {
535
+ return 0;
536
+ }
537
+ return scrollRef.current.scrollHeight - 1 - scrollRef.current.clientHeight;
538
+ },
539
+ get calculatedTargetScrollTop() {
540
+ if (!scrollRef.current || !contentRef.current) {
541
+ return 0;
542
+ }
543
+ const { targetScrollTop } = this;
544
+ if (!options.targetScrollTop) {
545
+ return targetScrollTop;
546
+ }
547
+ if (lastCalculation?.targetScrollTop === targetScrollTop) {
548
+ return lastCalculation.calculatedScrollTop;
549
+ }
550
+ const calculatedScrollTop = Math.max(Math.min(options.targetScrollTop(targetScrollTop, {
551
+ scrollElement: scrollRef.current,
552
+ contentElement: contentRef.current
553
+ }), targetScrollTop), 0);
554
+ lastCalculation = { targetScrollTop, calculatedScrollTop };
555
+ requestAnimationFrame(() => {
556
+ lastCalculation = void 0;
557
+ });
558
+ return calculatedScrollTop;
559
+ },
560
+ get scrollDifference() {
561
+ return this.calculatedTargetScrollTop - this.scrollTop;
562
+ },
563
+ get isNearBottom() {
564
+ return this.scrollDifference <= STICK_TO_BOTTOM_OFFSET_PX;
565
+ }
566
+ };
567
+ }, []);
568
+ const scrollToBottom = useCallback((scrollOptions = {}) => {
569
+ if (typeof scrollOptions === "string") {
570
+ scrollOptions = { animation: scrollOptions };
571
+ }
572
+ if (!scrollOptions.preserveScrollPosition) {
573
+ setIsAtBottom(true);
574
+ }
575
+ const waitElapsed = Date.now() + (Number(scrollOptions.wait) || 0);
576
+ const behavior = mergeAnimations(optionsRef.current, scrollOptions.animation);
577
+ const { ignoreEscapes = false } = scrollOptions;
578
+ let durationElapsed;
579
+ let startTarget = state.calculatedTargetScrollTop;
580
+ if (scrollOptions.duration instanceof Promise) {
581
+ scrollOptions.duration.finally(() => {
582
+ durationElapsed = Date.now();
583
+ });
584
+ } else {
585
+ durationElapsed = waitElapsed + (scrollOptions.duration ?? 0);
586
+ }
587
+ const next = async () => {
588
+ const promise = new Promise(requestAnimationFrame).then(() => {
589
+ if (!state.isAtBottom) {
590
+ state.animation = void 0;
591
+ return false;
592
+ }
593
+ const { scrollTop } = state;
594
+ const tick = performance.now();
595
+ const tickDelta = (tick - (state.lastTick ?? tick)) / SIXTY_FPS_INTERVAL_MS;
596
+ state.animation || (state.animation = { behavior, promise, ignoreEscapes });
597
+ if (state.animation.behavior === behavior) {
598
+ state.lastTick = tick;
599
+ }
600
+ if (isSelecting()) {
601
+ return next();
602
+ }
603
+ if (waitElapsed > Date.now()) {
604
+ return next();
605
+ }
606
+ if (scrollTop < Math.min(startTarget, state.calculatedTargetScrollTop)) {
607
+ if (state.animation?.behavior === behavior) {
608
+ if (behavior === "instant") {
609
+ state.scrollTop = state.calculatedTargetScrollTop;
610
+ return next();
611
+ }
612
+ state.velocity = (behavior.damping * state.velocity + behavior.stiffness * state.scrollDifference) / behavior.mass;
613
+ state.accumulated += state.velocity * tickDelta;
614
+ state.scrollTop += state.accumulated;
615
+ if (state.scrollTop !== scrollTop) {
616
+ state.accumulated = 0;
617
+ }
618
+ }
619
+ return next();
620
+ }
621
+ if (durationElapsed > Date.now()) {
622
+ startTarget = state.calculatedTargetScrollTop;
623
+ return next();
624
+ }
625
+ state.animation = void 0;
626
+ if (state.scrollTop < state.calculatedTargetScrollTop) {
627
+ return scrollToBottom({
628
+ animation: mergeAnimations(optionsRef.current, optionsRef.current.resize),
629
+ ignoreEscapes,
630
+ duration: Math.max(0, durationElapsed - Date.now()) || void 0
631
+ });
632
+ }
633
+ return state.isAtBottom;
634
+ });
635
+ return promise.then((isAtBottom2) => {
636
+ requestAnimationFrame(() => {
637
+ if (!state.animation) {
638
+ state.lastTick = void 0;
639
+ state.velocity = 0;
640
+ }
641
+ });
642
+ return isAtBottom2;
643
+ });
644
+ };
645
+ if (scrollOptions.wait !== true) {
646
+ state.animation = void 0;
647
+ }
648
+ if (state.animation?.behavior === behavior) {
649
+ return state.animation.promise;
650
+ }
651
+ return next();
652
+ }, [setIsAtBottom, isSelecting, state]);
653
+ const stopScroll = useCallback(() => {
654
+ setEscapedFromLock(true);
655
+ setIsAtBottom(false);
656
+ }, [setEscapedFromLock, setIsAtBottom]);
657
+ const handleScroll = useCallback(({ target }) => {
658
+ if (target !== scrollRef.current) {
659
+ return;
660
+ }
661
+ const { scrollTop, ignoreScrollToTop } = state;
662
+ let { lastScrollTop = scrollTop } = state;
663
+ state.lastScrollTop = scrollTop;
664
+ state.ignoreScrollToTop = void 0;
665
+ if (ignoreScrollToTop && ignoreScrollToTop > scrollTop) {
666
+ lastScrollTop = ignoreScrollToTop;
667
+ }
668
+ setIsNearBottom(state.isNearBottom);
669
+ setTimeout(() => {
670
+ if (state.resizeDifference || scrollTop === ignoreScrollToTop) {
671
+ return;
672
+ }
673
+ if (isSelecting()) {
674
+ setEscapedFromLock(true);
675
+ setIsAtBottom(false);
676
+ return;
677
+ }
678
+ const isScrollingDown = scrollTop > lastScrollTop;
679
+ const isScrollingUp = scrollTop < lastScrollTop;
680
+ if (state.animation?.ignoreEscapes) {
681
+ state.scrollTop = lastScrollTop;
682
+ return;
683
+ }
684
+ if (isScrollingUp) {
685
+ setEscapedFromLock(true);
686
+ setIsAtBottom(false);
687
+ }
688
+ if (isScrollingDown) {
689
+ setEscapedFromLock(false);
690
+ }
691
+ if (!state.escapedFromLock && state.isNearBottom) {
692
+ setIsAtBottom(true);
693
+ }
694
+ }, 1);
695
+ }, [setEscapedFromLock, setIsAtBottom, isSelecting, state]);
696
+ const handleWheel = useCallback(({ target, deltaY }) => {
697
+ let element = target;
698
+ while (!["scroll", "auto"].includes(getComputedStyle(element).overflow)) {
699
+ if (!element.parentElement) {
700
+ return;
701
+ }
702
+ element = element.parentElement;
703
+ }
704
+ if (element === scrollRef.current && deltaY < 0 && scrollRef.current.scrollHeight > scrollRef.current.clientHeight && !state.animation?.ignoreEscapes) {
705
+ setEscapedFromLock(true);
706
+ setIsAtBottom(false);
707
+ }
708
+ }, [setEscapedFromLock, setIsAtBottom, state]);
709
+ const scrollRef = useRefCallback((scroll) => {
710
+ scrollRef.current?.removeEventListener("scroll", handleScroll);
711
+ scrollRef.current?.removeEventListener("wheel", handleWheel);
712
+ scroll?.addEventListener("scroll", handleScroll, { passive: true });
713
+ scroll?.addEventListener("wheel", handleWheel, { passive: true });
714
+ }, []);
715
+ const contentRef = useRefCallback((content) => {
716
+ state.resizeObserver?.disconnect();
717
+ if (!content) {
718
+ return;
719
+ }
720
+ let previousHeight;
721
+ state.resizeObserver = new ResizeObserver(([entry]) => {
722
+ const { height } = entry.contentRect;
723
+ const difference = height - (previousHeight ?? height);
724
+ state.resizeDifference = difference;
725
+ if (state.scrollTop > state.targetScrollTop) {
726
+ state.scrollTop = state.targetScrollTop;
727
+ }
728
+ setIsNearBottom(state.isNearBottom);
729
+ if (difference >= 0) {
730
+ const animation = mergeAnimations(optionsRef.current, previousHeight ? optionsRef.current.resize : optionsRef.current.initial);
731
+ scrollToBottom({
732
+ animation,
733
+ wait: true,
734
+ preserveScrollPosition: true,
735
+ duration: animation === "instant" ? void 0 : RETAIN_ANIMATION_DURATION_MS
736
+ });
737
+ } else {
738
+ if (state.isNearBottom) {
739
+ setEscapedFromLock(false);
740
+ setIsAtBottom(true);
741
+ }
742
+ }
743
+ previousHeight = height;
744
+ requestAnimationFrame(() => {
745
+ setTimeout(() => {
746
+ if (state.resizeDifference === difference) {
747
+ state.resizeDifference = 0;
748
+ }
749
+ }, 1);
750
+ });
751
+ });
752
+ state.resizeObserver?.observe(content);
753
+ }, []);
754
+ return {
755
+ contentRef,
756
+ scrollRef,
757
+ scrollToBottom,
758
+ stopScroll,
759
+ isAtBottom: isAtBottom || isNearBottom,
760
+ isNearBottom,
761
+ escapedFromLock,
762
+ state
763
+ };
764
+ };
765
+ function useRefCallback(callback, deps) {
766
+ const result = useCallback((ref) => {
767
+ result.current = ref;
768
+ return callback(ref);
769
+ }, deps);
770
+ return result;
771
+ }
772
+ var animationCache = /* @__PURE__ */ new Map();
773
+ function mergeAnimations(...animations) {
774
+ const result = { ...DEFAULT_SPRING_ANIMATION };
775
+ let instant = false;
776
+ for (const animation of animations) {
777
+ if (animation === "instant") {
778
+ instant = true;
779
+ continue;
780
+ }
781
+ if (typeof animation !== "object") {
782
+ continue;
783
+ }
784
+ instant = false;
785
+ result.damping = animation.damping ?? result.damping;
786
+ result.stiffness = animation.stiffness ?? result.stiffness;
787
+ result.mass = animation.mass ?? result.mass;
788
+ }
789
+ const key = JSON.stringify(result);
790
+ if (!animationCache.has(key)) {
791
+ animationCache.set(key, Object.freeze(result));
792
+ }
793
+ return instant ? "instant" : animationCache.get(key);
794
+ }
795
+
796
+ // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/StickToBottom.js
797
+ import * as React from "react";
798
+ import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useImperativeHandle, useLayoutEffect, useMemo as useMemo3, useRef as useRef3 } from "react";
799
+ var StickToBottomContext = createContext2(null);
800
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect2;
801
+ function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {
802
+ const customTargetScrollTop = useRef3(null);
803
+ const targetScrollTop = React.useCallback((target, elements) => {
804
+ const get = context?.targetScrollTop ?? currentTargetScrollTop;
805
+ return get?.(target, elements) ?? target;
806
+ }, [currentTargetScrollTop]);
807
+ const defaultInstance = useStickToBottom({
808
+ mass,
809
+ damping,
810
+ stiffness,
811
+ resize,
812
+ initial,
813
+ targetScrollTop
814
+ });
815
+ const { scrollRef, contentRef, scrollToBottom, stopScroll, isAtBottom, escapedFromLock, state } = instance ?? defaultInstance;
816
+ const context = useMemo3(() => ({
817
+ scrollToBottom,
818
+ stopScroll,
819
+ scrollRef,
820
+ isAtBottom,
821
+ escapedFromLock,
822
+ contentRef,
823
+ state,
824
+ get targetScrollTop() {
825
+ return customTargetScrollTop.current;
826
+ },
827
+ set targetScrollTop(targetScrollTop2) {
828
+ customTargetScrollTop.current = targetScrollTop2;
829
+ }
830
+ }), [
831
+ scrollToBottom,
832
+ isAtBottom,
833
+ contentRef,
834
+ scrollRef,
835
+ stopScroll,
836
+ escapedFromLock,
837
+ state
838
+ ]);
839
+ useImperativeHandle(contextRef, () => context, [context]);
840
+ useIsomorphicLayoutEffect(() => {
841
+ if (!scrollRef.current) {
842
+ return;
843
+ }
844
+ if (getComputedStyle(scrollRef.current).overflow === "visible") {
845
+ scrollRef.current.style.overflow = "auto";
846
+ }
847
+ }, []);
848
+ return React.createElement(
849
+ StickToBottomContext.Provider,
850
+ { value: context },
851
+ React.createElement("div", { ...props }, typeof children === "function" ? children(context) : children)
852
+ );
853
+ }
854
+ (function(StickToBottom2) {
855
+ function Content({ children, scrollClassName, ...props }) {
856
+ const context = useStickToBottomContext();
857
+ return React.createElement(
858
+ "div",
859
+ { ref: context.scrollRef, style: {
860
+ height: "100%",
861
+ width: "100%",
862
+ scrollbarGutter: "stable both-edges"
863
+ }, className: scrollClassName },
864
+ React.createElement("div", { ...props, ref: context.contentRef }, typeof children === "function" ? children(context) : children)
865
+ );
866
+ }
867
+ StickToBottom2.Content = Content;
868
+ })(StickToBottom || (StickToBottom = {}));
869
+ function useStickToBottomContext() {
870
+ const context = useContext2(StickToBottomContext);
871
+ if (!context) {
872
+ throw new Error("use-stick-to-bottom component context must be used within a StickToBottom component");
873
+ }
874
+ return context;
875
+ }
217
876
 
218
877
  // src/components/AssistantTurnBlock.tsx
219
878
  import { getTextContent, normalizeMessageContent } from "@blade-hq/agent-client";
220
- import { Brain, ChevronDown } from "lucide-react";
221
- import { useState as useState6 } from "react";
879
+ import { useState as useState7 } from "react";
222
880
 
223
881
  // src/components/AgentLoopBlock.tsx
224
- import { Bot, Check, ChevronRight, Loader2 as Loader22, X } from "lucide-react";
225
- import { useState as useState2 } from "react";
882
+ import { useState as useState3 } from "react";
226
883
 
227
884
  // src/components/display-utils.ts
228
885
  var TOOL_NAME_ALIASES = {
@@ -354,7 +1011,7 @@ function parseAgentDescription(argumentsJson) {
354
1011
  }
355
1012
  }
356
1013
  function AgentLoopBlock({ toolCall }) {
357
- const [expanded, setExpanded] = useState2(false);
1014
+ const [expanded, setExpanded] = useState3(false);
358
1015
  const description = parseAgentDescription(toolCall.arguments);
359
1016
  const running = toolCall.status === "pending" || toolCall.status === "awaiting_answer";
360
1017
  const failed = toolCall.status === "error" || toolCall.status === "cancelled";
@@ -394,7 +1051,7 @@ function AgentLoopBlock({ toolCall }) {
394
1051
  failed ? "text-[hsl(var(--muted-foreground))]" : running ? "text-blue-300" : "text-[hsl(var(--primary))]"
395
1052
  ),
396
1053
  children: [
397
- running ? /* @__PURE__ */ jsx4(Loader22, { size: 11, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx4(X, { size: 11 }) : /* @__PURE__ */ jsx4(Check, { size: 11 }),
1054
+ running ? /* @__PURE__ */ jsx4(LoaderCircle, { size: 11, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx4(X, { size: 11 }) : /* @__PURE__ */ jsx4(Check, { size: 11 }),
398
1055
  /* @__PURE__ */ jsx4("span", { children: running ? "\u6267\u884C\u4E2D" : failed ? "\u5DF2\u7EC8\u6B62" : "\u5B8C\u6210" })
399
1056
  ]
400
1057
  }
@@ -418,21 +1075,19 @@ function AgentLoopBlock({ toolCall }) {
418
1075
  }
419
1076
 
420
1077
  // src/components/MarkdownContent.tsx
421
- import { Check as Check2, Copy } from "lucide-react";
422
1078
  import {
423
- useEffect as useEffect2,
424
- useMemo as useMemo2,
425
- useRef as useRef2,
426
- useState as useState3
1079
+ useEffect as useEffect3,
1080
+ useMemo as useMemo4,
1081
+ useRef as useRef4,
1082
+ useState as useState4
427
1083
  } from "react";
428
- import { Streamdown } from "streamdown";
429
1084
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
430
1085
  var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
431
1086
  function CodeBlockPre({ children, node: _node, ...props }) {
432
- const preRef = useRef2(null);
433
- const [copied, setCopied] = useState3(false);
434
- const [language, setLanguage] = useState3("");
435
- useEffect2(() => {
1087
+ const preRef = useRef4(null);
1088
+ const [copied, setCopied] = useState4(false);
1089
+ const [language, setLanguage] = useState4("");
1090
+ useEffect3(() => {
436
1091
  const codeEl = preRef.current?.querySelector("code");
437
1092
  setLanguage(codeEl?.className.match(/language-(\S+)/)?.[1] ?? "");
438
1093
  }, []);
@@ -456,7 +1111,7 @@ function CodeBlockPre({ children, node: _node, ...props }) {
456
1111
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"
457
1112
  ),
458
1113
  children: [
459
- copied ? /* @__PURE__ */ jsx5(Check2, { size: 12 }) : /* @__PURE__ */ jsx5(Copy, { size: 12 }),
1114
+ copied ? /* @__PURE__ */ jsx5(Check, { size: 12 }) : /* @__PURE__ */ jsx5(Copy, { size: 12 }),
460
1115
  /* @__PURE__ */ jsx5("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
461
1116
  ]
462
1117
  }
@@ -481,9 +1136,9 @@ var MARKDOWN_COMPONENTS = {
481
1136
  a: ExternalAnchor
482
1137
  };
483
1138
  function MarkdownContent({ children, className, mode }) {
484
- const resolvedChildren = useMemo2(() => children.replace(SYSTEM_REMINDER_RE, ""), [children]);
1139
+ const resolvedChildren = useMemo4(() => children.replace(SYSTEM_REMINDER_RE, ""), [children]);
485
1140
  return /* @__PURE__ */ jsx5(
486
- Streamdown,
1141
+ _r,
487
1142
  {
488
1143
  className: cn("blade-chat-markdown break-words", className),
489
1144
  mode: mode ?? "static",
@@ -500,12 +1155,10 @@ function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
500
1155
  }
501
1156
 
502
1157
  // src/components/ToolCallBlock.tsx
503
- import { Check as Check4, ChevronRight as ChevronRight2, Loader2 as Loader24, MessageSquareMore as MessageSquareMore2, X as X2 } from "lucide-react";
504
- import { useState as useState5 } from "react";
1158
+ import { useState as useState6 } from "react";
505
1159
 
506
1160
  // src/components/AskUserQuestionBlock.tsx
507
- import { Check as Check3, Loader2 as Loader23, MessageSquareMore } from "lucide-react";
508
- import { useEffect as useEffect3, useMemo as useMemo3, useState as useState4 } from "react";
1161
+ import { useEffect as useEffect4, useMemo as useMemo5, useState as useState5 } from "react";
509
1162
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
510
1163
  function AskUserQuestionBlock({
511
1164
  data,
@@ -515,16 +1168,16 @@ function AskUserQuestionBlock({
515
1168
  answerData,
516
1169
  onAnswer
517
1170
  }) {
518
- const [selections, setSelections] = useState4(/* @__PURE__ */ new Map());
519
- const [customTexts, setCustomTexts] = useState4(/* @__PURE__ */ new Map());
520
- const [usingCustom, setUsingCustom] = useState4(/* @__PURE__ */ new Set());
521
- const [submitted, setSubmitted] = useState4(false);
522
- useEffect3(() => {
1171
+ const [selections, setSelections] = useState5(/* @__PURE__ */ new Map());
1172
+ const [customTexts, setCustomTexts] = useState5(/* @__PURE__ */ new Map());
1173
+ const [usingCustom, setUsingCustom] = useState5(/* @__PURE__ */ new Set());
1174
+ const [submitted, setSubmitted] = useState5(false);
1175
+ useEffect4(() => {
523
1176
  if (sessionStatus === "failed" || sessionStatus === "interrupted") {
524
1177
  setSubmitted(false);
525
1178
  }
526
1179
  }, [sessionStatus]);
527
- const displayAnswerState = useMemo3(() => {
1180
+ const displayAnswerState = useMemo5(() => {
528
1181
  if (!(answered && answerData)) {
529
1182
  return { selections, customTexts, usingCustom };
530
1183
  }
@@ -654,7 +1307,7 @@ ${parts.join("\n")}`;
654
1307
  disabled: true,
655
1308
  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",
656
1309
  children: [
657
- /* @__PURE__ */ jsx7(Loader23, { size: 14, className: "animate-spin" }),
1310
+ /* @__PURE__ */ jsx7(LoaderCircle, { size: 14, className: "animate-spin" }),
658
1311
  "\u786E\u8BA4\u4E2D"
659
1312
  ]
660
1313
  }
@@ -720,7 +1373,7 @@ function QuestionCard({
720
1373
  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))]"
721
1374
  ),
722
1375
  children: isSel && /* @__PURE__ */ jsx7(
723
- Check3,
1376
+ Check,
724
1377
  {
725
1378
  size: 9,
726
1379
  className: answered ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--primary-foreground))]"
@@ -835,7 +1488,7 @@ function ToolCallBlock({
835
1488
  sessionStatus,
836
1489
  renderer
837
1490
  }) {
838
- const [expanded, setExpanded] = useState5(false);
1491
+ const [expanded, setExpanded] = useState6(false);
839
1492
  const normalizedName = formatToolName(toolCall.name);
840
1493
  if (renderer) {
841
1494
  const custom = renderer(toolCall);
@@ -845,13 +1498,13 @@ function ToolCallBlock({
845
1498
  }
846
1499
  if (normalizedName === "AskUserQuestion") {
847
1500
  const askData = parseAskUserQuestion(typeof toolCall.result === "string" ? toolCall.result : null) ?? parseAskUserQuestion(buildAskUserPayload(toolCall.arguments));
848
- const canAnswer = toolCall.status === "awaiting_answer" && sessionStatus === "waiting_for_input" && Boolean(onAnswer);
1501
+ const canAnswer = toolCall.status === "awaiting_answer" && Boolean(onAnswer);
849
1502
  if (askData) {
850
1503
  return /* @__PURE__ */ jsx8(
851
1504
  AskUserQuestionBlock,
852
1505
  {
853
1506
  data: askData,
854
- answered: Boolean(answered) || toolCall.status === "done",
1507
+ answered: toolCall.status === "awaiting_answer" ? false : Boolean(answered) || toolCall.status === "done",
855
1508
  toolCallId: toolCall.id,
856
1509
  sessionStatus: sessionStatus ?? "",
857
1510
  answerData,
@@ -861,7 +1514,7 @@ function ToolCallBlock({
861
1514
  }
862
1515
  if (toolCall.status === "pending") {
863
1516
  return /* @__PURE__ */ jsxs6("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: [
864
- /* @__PURE__ */ jsx8(Loader24, { size: 14, className: "animate-spin" }),
1517
+ /* @__PURE__ */ jsx8(LoaderCircle, { size: 14, className: "animate-spin" }),
865
1518
  /* @__PURE__ */ jsx8("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
866
1519
  ] });
867
1520
  }
@@ -873,7 +1526,7 @@ function ToolCallBlock({
873
1526
  const tone = getToolTone(toolCall.status);
874
1527
  const displayName = getToolDisplayLabel(toolCall);
875
1528
  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))]";
876
- const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx8(Loader24, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx8(MessageSquareMore2, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx8(X2, { size: 11 }) : /* @__PURE__ */ jsx8(Check4, { size: 11 });
1529
+ const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx8(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx8(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx8(X, { size: 11 }) : /* @__PURE__ */ jsx8(Check, { size: 11 });
877
1530
  const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
878
1531
  return /* @__PURE__ */ jsxs6("div", { className: "blade-chat-tool ml-4 text-xs", children: [
879
1532
  /* @__PURE__ */ jsxs6("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
@@ -886,7 +1539,7 @@ function ToolCallBlock({
886
1539
  "aria-expanded": expanded,
887
1540
  children: [
888
1541
  /* @__PURE__ */ jsx8(
889
- ChevronRight2,
1542
+ ChevronRight,
890
1543
  {
891
1544
  size: 11,
892
1545
  className: cn(
@@ -932,7 +1585,7 @@ function buildAskUserPayload(argumentsJson) {
932
1585
  // src/components/AssistantTurnBlock.tsx
933
1586
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
934
1587
  function ThinkingBlock({ reasoning, isStreaming }) {
935
- const [open, setOpen] = useState6(false);
1588
+ const [open, setOpen] = useState7(false);
936
1589
  return /* @__PURE__ */ jsxs7("div", { className: "blade-chat-thinking ml-4 text-sm", children: [
937
1590
  /* @__PURE__ */ jsxs7(
938
1591
  "button",
@@ -1017,7 +1670,6 @@ function AssistantTurnBlock({
1017
1670
  }
1018
1671
 
1019
1672
  // src/components/RenderErrorBoundary.tsx
1020
- import { AlertTriangle as AlertTriangle2 } from "lucide-react";
1021
1673
  import { Component } from "react";
1022
1674
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1023
1675
  function getFirstComponentName(componentStack) {
@@ -1053,7 +1705,7 @@ var RenderErrorBoundary = class extends Component {
1053
1705
  }
1054
1706
  const componentName = getFirstComponentName(componentStack);
1055
1707
  return /* @__PURE__ */ jsx10("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__ */ jsxs8("div", { className: "flex items-start gap-2", children: [
1056
- /* @__PURE__ */ jsx10(AlertTriangle2, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
1708
+ /* @__PURE__ */ jsx10(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
1057
1709
  /* @__PURE__ */ jsxs8("div", { className: "min-w-0 flex-1", children: [
1058
1710
  /* @__PURE__ */ jsxs8("div", { className: "font-medium", children: [
1059
1711
  label,
@@ -1071,7 +1723,6 @@ var RenderErrorBoundary = class extends Component {
1071
1723
 
1072
1724
  // src/components/UserMessageBubble.tsx
1073
1725
  import { getFileParts, getImageParts, getTextContent as getTextContent2 } from "@blade-hq/agent-client";
1074
- import { FileText, Loader2 as Loader25 } from "lucide-react";
1075
1726
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1076
1727
  function isUserMessage(message) {
1077
1728
  return message.role === "user";
@@ -1107,7 +1758,7 @@ function UserMessageBubble({ message, className }) {
1107
1758
  )) }),
1108
1759
  text && /* @__PURE__ */ jsx11("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__ */ jsx11(MarkdownContent, { className: "blade-chat-prose", children: text }) }),
1109
1760
  text && isSending(message) && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1 pr-1 text-[11px] font-medium text-[hsl(var(--muted-foreground))/0.85]", children: [
1110
- /* @__PURE__ */ jsx11(Loader25, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
1761
+ /* @__PURE__ */ jsx11(LoaderCircle, { size: 11, className: "animate-spin", "aria-hidden": "true" }),
1111
1762
  /* @__PURE__ */ jsx11("span", { children: "\u53D1\u9001\u4E2D" })
1112
1763
  ] })
1113
1764
  ] }) });
@@ -1163,7 +1814,7 @@ function MessageList({
1163
1814
  emptyState,
1164
1815
  className
1165
1816
  }) {
1166
- const renderBlocks = useMemo4(() => {
1817
+ const renderBlocks = useMemo6(() => {
1167
1818
  const visible = messages.filter((message) => {
1168
1819
  if ((message.loop_name ?? "root") !== "root") return false;
1169
1820
  if (isHiddenInternalMessage(message)) return false;
@@ -1290,8 +1941,8 @@ function MessageList({
1290
1941
  }
1291
1942
  function AutoScrollOnUserSend({ userMessageCount }) {
1292
1943
  const { scrollToBottom } = useStickToBottomContext();
1293
- const previousCountRef = useRef3(userMessageCount);
1294
- useEffect4(() => {
1944
+ const previousCountRef = useRef5(userMessageCount);
1945
+ useEffect5(() => {
1295
1946
  if (userMessageCount > previousCountRef.current) {
1296
1947
  scrollToBottom("instant");
1297
1948
  }
@@ -1309,7 +1960,7 @@ function ScrollToBottomButton() {
1309
1960
  onClick: () => scrollToBottom(),
1310
1961
  className: "absolute bottom-4 right-4 flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-1.5 text-xs text-[hsl(var(--muted-foreground))] shadow-lg transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
1311
1962
  children: [
1312
- /* @__PURE__ */ jsx12(ChevronDown2, { size: 14 }),
1963
+ /* @__PURE__ */ jsx12(ChevronDown, { size: 14 }),
1313
1964
  /* @__PURE__ */ jsx12("span", { children: "\u6EDA\u52A8\u5230\u5E95\u90E8" })
1314
1965
  ]
1315
1966
  }
@@ -1332,8 +1983,8 @@ function isUnauthorizedError(error) {
1332
1983
  return error instanceof BladeApiError && error.status === 401;
1333
1984
  }
1334
1985
  function LoginCard({ client, onLoggedIn }) {
1335
- const [loggingIn, setLoggingIn] = useState7(false);
1336
- const [loginError, setLoginError] = useState7(null);
1986
+ const [loggingIn, setLoggingIn] = useState8(false);
1987
+ const [loginError, setLoginError] = useState8(null);
1337
1988
  const handleLogin = async () => {
1338
1989
  setLoggingIn(true);
1339
1990
  setLoginError(null);
@@ -1363,19 +2014,10 @@ function LoginCard({ client, onLoggedIn }) {
1363
2014
  loginError && /* @__PURE__ */ jsx13("div", { className: "text-xs text-[hsl(var(--destructive))]", children: loginError })
1364
2015
  ] }) });
1365
2016
  }
1366
- function VersionMismatchCard({ error }) {
1367
- return /* @__PURE__ */ jsx13("div", { className: "blade-chat-version-mismatch flex flex-1 items-center justify-center p-6", children: /* @__PURE__ */ jsxs11("div", { className: "flex w-full max-w-md flex-col gap-3 rounded-2xl border border-amber-500/30 bg-amber-500/10 px-6 py-6", children: [
1368
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-sm font-medium text-amber-300", children: [
1369
- /* @__PURE__ */ jsx13(CircleAlert, { size: 16 }),
1370
- /* @__PURE__ */ jsx13("span", { children: "\u7248\u672C\u4E0D\u5339\u914D" })
1371
- ] }),
1372
- /* @__PURE__ */ jsx13("div", { className: "break-words text-sm leading-6 text-[hsl(var(--foreground))]", children: error.message })
1373
- ] }) });
1374
- }
1375
2017
  function ChatView(props) {
1376
2018
  const client = useBladeClient();
1377
- const [attempt, setAttempt] = useState7(0);
1378
- const [needLogin, setNeedLogin] = useState7(() => !client.hasToken());
2019
+ const [attempt, setAttempt] = useState8(0);
2020
+ const [needLogin, setNeedLogin] = useState8(() => !client.hasToken());
1379
2021
  if (needLogin) {
1380
2022
  return /* @__PURE__ */ jsx13("div", { className: cn("blade-chat flex min-h-0 flex-1 flex-col", props.classNames?.root), children: /* @__PURE__ */ jsx13(
1381
2023
  LoginCard,
@@ -1406,14 +2048,14 @@ function ChatSessionView({
1406
2048
  createOptions,
1407
2049
  onSessionCreated
1408
2050
  });
1409
- const [stopRequested, setStopRequested] = useState7(false);
1410
- const [inputText, setInputText] = useState7("");
1411
- useEffect5(() => {
2051
+ const [stopRequested, setStopRequested] = useState8(false);
2052
+ const [inputText, setInputText] = useState8("");
2053
+ useEffect6(() => {
1412
2054
  if (session) {
1413
2055
  onSessionReady?.(session);
1414
2056
  }
1415
2057
  }, [session, onSessionReady]);
1416
- useEffect5(() => {
2058
+ useEffect6(() => {
1417
2059
  if (!session) return;
1418
2060
  const offAttach = session.on("attachRequested", ({ label, content }) => {
1419
2061
  setInputText((prev) => `${prev ? `${prev}
@@ -1429,12 +2071,12 @@ ${content}`);
1429
2071
  offInsert();
1430
2072
  };
1431
2073
  }, [session]);
1432
- useEffect5(() => {
2074
+ useEffect6(() => {
1433
2075
  if (isUnauthorizedError(error)) {
1434
2076
  onUnauthorized();
1435
2077
  }
1436
2078
  }, [error, onUnauthorized]);
1437
- useEffect5(() => {
2079
+ useEffect6(() => {
1438
2080
  if (!session || !commands) return;
1439
2081
  const unsubscribes = Object.entries(commands).map(
1440
2082
  ([action, handler]) => session.onCommand(action, (payload) => handler(payload))
@@ -1443,9 +2085,6 @@ ${content}`);
1443
2085
  for (const unsubscribe of unsubscribes) unsubscribe();
1444
2086
  };
1445
2087
  }, [session, commands]);
1446
- if (error instanceof VersionMismatchError) {
1447
- return /* @__PURE__ */ jsx13("div", { className: cn("blade-chat flex min-h-0 flex-1 flex-col", classNames?.root), children: /* @__PURE__ */ jsx13(VersionMismatchCard, { error }) });
1448
- }
1449
2088
  const isStreaming = state?.isStreaming ?? false;
1450
2089
  const isStopping = stopRequested && isStreaming;
1451
2090
  const connectError = error && !isUnauthorizedError(error) ? error.message || "\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5" : null;
@@ -1524,4 +2163,43 @@ export {
1524
2163
  useAgentSession,
1525
2164
  useBladeClient
1526
2165
  };
2166
+ /*! Bundled license information:
2167
+
2168
+ lucide-react/dist/esm/shared/src/utils.js:
2169
+ lucide-react/dist/esm/defaultAttributes.js:
2170
+ lucide-react/dist/esm/Icon.js:
2171
+ lucide-react/dist/esm/createLucideIcon.js:
2172
+ lucide-react/dist/esm/icons/arrow-up.js:
2173
+ lucide-react/dist/esm/icons/bot.js:
2174
+ lucide-react/dist/esm/icons/brain.js:
2175
+ lucide-react/dist/esm/icons/check.js:
2176
+ lucide-react/dist/esm/icons/chevron-down.js:
2177
+ lucide-react/dist/esm/icons/chevron-right.js:
2178
+ lucide-react/dist/esm/icons/circle-alert.js:
2179
+ lucide-react/dist/esm/icons/copy.js:
2180
+ lucide-react/dist/esm/icons/file-text.js:
2181
+ lucide-react/dist/esm/icons/layers.js:
2182
+ lucide-react/dist/esm/icons/lightbulb.js:
2183
+ lucide-react/dist/esm/icons/loader-circle.js:
2184
+ lucide-react/dist/esm/icons/lock-keyhole.js:
2185
+ lucide-react/dist/esm/icons/message-square-more.js:
2186
+ lucide-react/dist/esm/icons/message-square.js:
2187
+ lucide-react/dist/esm/icons/square.js:
2188
+ lucide-react/dist/esm/icons/triangle-alert.js:
2189
+ lucide-react/dist/esm/icons/x.js:
2190
+ lucide-react/dist/esm/lucide-react.js:
2191
+ (**
2192
+ * @license lucide-react v0.468.0 - ISC
2193
+ *
2194
+ * This source code is licensed under the ISC license.
2195
+ * See the LICENSE file in the root directory of this source tree.
2196
+ *)
2197
+
2198
+ use-stick-to-bottom/dist/useStickToBottom.js:
2199
+ use-stick-to-bottom/dist/StickToBottom.js:
2200
+ (*!---------------------------------------------------------------------------------------------
2201
+ * Copyright (c) StackBlitz. All rights reserved.
2202
+ * Licensed under the MIT License. See License.txt in the project root for license information.
2203
+ *--------------------------------------------------------------------------------------------*)
2204
+ */
1527
2205
  //# sourceMappingURL=index.js.map