@blade-hq/agent-react 2610.0.3 → 2610.0.4

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
@@ -1659,6 +1659,43 @@ var require_react_is = __commonJS({
1659
1659
  }
1660
1660
  });
1661
1661
 
1662
+ // src/hooks/use-live-execution-duration.ts
1663
+ import { useEffect, useRef, useState } from "react";
1664
+ function useLiveExecutionDuration({
1665
+ turnKey,
1666
+ isStreaming,
1667
+ initialDurationMs,
1668
+ isInitialDurationReady
1669
+ }) {
1670
+ const initialDurationRef = useRef(initialDurationMs);
1671
+ initialDurationRef.current = initialDurationMs;
1672
+ const [durationMs, setDurationMs] = useState(initialDurationMs);
1673
+ useEffect(() => {
1674
+ if (!isStreaming || !isInitialDurationReady) return;
1675
+ const baseDurationMs = initialDurationRef.current;
1676
+ const startedAt = performance.now();
1677
+ setDurationMs(baseDurationMs);
1678
+ const timer = window.setInterval(() => {
1679
+ setDurationMs(baseDurationMs + Math.max(0, performance.now() - startedAt));
1680
+ }, 1e3);
1681
+ return () => window.clearInterval(timer);
1682
+ }, [isStreaming, turnKey, isInitialDurationReady]);
1683
+ return durationMs;
1684
+ }
1685
+ function getChatRun(messages) {
1686
+ const runs = messages.flatMap((message) => message.chat_run ? [message.chat_run] : []);
1687
+ const latestId = runs.at(-1)?.run_id;
1688
+ const settled = [...runs].reverse().find((run) => run.run_id === latestId && run.status !== "incomplete");
1689
+ return settled ?? runs.at(-1) ?? null;
1690
+ }
1691
+ function getChatRunDuration(messages, now) {
1692
+ const running = getChatRun(messages);
1693
+ if (!running) return null;
1694
+ if (running.status !== "incomplete") return running.duration_ms ?? 0;
1695
+ const start = running.started_at ? Date.parse(running.started_at) : Number.NaN;
1696
+ return now !== null && Number.isFinite(start) ? Math.max(0, now - start) : 0;
1697
+ }
1698
+
1662
1699
  // src/context.tsx
1663
1700
  import { createContext, useContext } from "react";
1664
1701
  import { jsx } from "react/jsx-runtime";
@@ -1678,28 +1715,28 @@ function useOptionalBladeClient() {
1678
1715
  }
1679
1716
 
1680
1717
  // src/hooks/use-agent-session.ts
1681
- import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
1718
+ import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
1682
1719
  var EMPTY_SUBSCRIBE = () => () => {
1683
1720
  };
1684
1721
  var DISPOSE_DELAY_MS = 1e3;
1685
1722
  function useAgentSession(sessionId, options = {}) {
1686
1723
  const client = useBladeClient();
1687
- const [session, setSession] = useState(null);
1688
- const [error61, setError] = useState(null);
1689
- const connRef = useRef({
1724
+ const [session, setSession] = useState2(null);
1725
+ const [error61, setError] = useState2(null);
1726
+ const connRef = useRef2({
1690
1727
  id: null,
1691
1728
  session: null,
1692
1729
  cleanup: null,
1693
1730
  gen: 0
1694
1731
  });
1695
- const createdIdPromiseRef = useRef(null);
1696
- const onCreatedRef = useRef(options.onSessionCreated);
1732
+ const createdIdPromiseRef = useRef2(null);
1733
+ const onCreatedRef = useRef2(options.onSessionCreated);
1697
1734
  onCreatedRef.current = options.onSessionCreated;
1698
- const onConnectedRef = useRef(options.onSessionConnected);
1735
+ const onConnectedRef = useRef2(options.onSessionConnected);
1699
1736
  onConnectedRef.current = options.onSessionConnected;
1700
- const createOptionsRef = useRef(options.createOptions);
1737
+ const createOptionsRef = useRef2(options.createOptions);
1701
1738
  createOptionsRef.current = options.createOptions;
1702
- const sessionIdRef = useRef(sessionId);
1739
+ const sessionIdRef = useRef2(sessionId);
1703
1740
  sessionIdRef.current = sessionId;
1704
1741
  const connect = useMemo(() => {
1705
1742
  return (targetId) => {
@@ -1739,7 +1776,7 @@ function useAgentSession(sessionId, options = {}) {
1739
1776
  });
1740
1777
  };
1741
1778
  }, [client]);
1742
- useEffect(() => {
1779
+ useEffect2(() => {
1743
1780
  connect(sessionIdRef.current);
1744
1781
  return () => {
1745
1782
  connRef.current.gen++;
@@ -1753,7 +1790,7 @@ function useAgentSession(sessionId, options = {}) {
1753
1790
  if (toRelease) setTimeout(() => toRelease.dispose(), DISPOSE_DELAY_MS);
1754
1791
  };
1755
1792
  }, [connect]);
1756
- useEffect(() => {
1793
+ useEffect2(() => {
1757
1794
  if (!sessionId) return;
1758
1795
  if (connRef.current.id === null) return;
1759
1796
  if (sessionId === connRef.current.id) return;
@@ -1779,20 +1816,20 @@ function useAgentSession(sessionId, options = {}) {
1779
1816
 
1780
1817
  // src/hooks/use-replay.ts
1781
1818
  import { DEFAULT_REPLAY_SPEED } from "@blade-hq/agent-client";
1782
- import { useCallback, useEffect as useEffect2, useState as useState2 } from "react";
1819
+ import { useCallback, useEffect as useEffect3, useState as useState3 } from "react";
1783
1820
  var replayCreating = /* @__PURE__ */ new Set();
1784
1821
  function useReplay(session) {
1785
1822
  const client = useBladeClient();
1786
1823
  const sessionId = session?.sessionId ?? null;
1787
- const [replay, setReplay] = useState2(null);
1788
- const [viewerRole, setViewerRole] = useState2(null);
1789
- const [sourceRunning, setSourceRunning] = useState2(false);
1790
- const [mismatch, setMismatch] = useState2(null);
1791
- const [preview, setPreview] = useState2({ status: "loading" });
1792
- const [isStarting, setIsStarting] = useState2(false);
1793
- const [error61, setError] = useState2(null);
1794
- const [draftSpeed, setDraftSpeed] = useState2(DEFAULT_REPLAY_SPEED);
1795
- useEffect2(() => {
1824
+ const [replay, setReplay] = useState3(null);
1825
+ const [viewerRole, setViewerRole] = useState3(null);
1826
+ const [sourceRunning, setSourceRunning] = useState3(false);
1827
+ const [mismatch, setMismatch] = useState3(null);
1828
+ const [preview, setPreview] = useState3({ status: "loading" });
1829
+ const [isStarting, setIsStarting] = useState3(false);
1830
+ const [error61, setError] = useState3(null);
1831
+ const [draftSpeed, setDraftSpeed] = useState3(DEFAULT_REPLAY_SPEED);
1832
+ useEffect3(() => {
1796
1833
  if (!session) {
1797
1834
  setReplay(null);
1798
1835
  setViewerRole(null);
@@ -1808,14 +1845,14 @@ function useReplay(session) {
1808
1845
  pull();
1809
1846
  return session.subscribe(pull);
1810
1847
  }, [session]);
1811
- const [lastSessionId, setLastSessionId] = useState2(sessionId);
1848
+ const [lastSessionId, setLastSessionId] = useState3(sessionId);
1812
1849
  if (sessionId !== lastSessionId) {
1813
1850
  setLastSessionId(sessionId);
1814
1851
  setMismatch(null);
1815
1852
  setError(null);
1816
1853
  setDraftSpeed(DEFAULT_REPLAY_SPEED);
1817
1854
  }
1818
- useEffect2(() => {
1855
+ useEffect3(() => {
1819
1856
  setPreview({ status: "loading" });
1820
1857
  if (!sessionId) return;
1821
1858
  let alive = true;
@@ -1833,7 +1870,7 @@ function useReplay(session) {
1833
1870
  alive = false;
1834
1871
  };
1835
1872
  }, [client, sessionId, sourceRunning]);
1836
- useEffect2(() => {
1873
+ useEffect3(() => {
1837
1874
  if (!session) return;
1838
1875
  return session.on("replayMismatch", ({ actualMessage, expectedMessage, respond }) => {
1839
1876
  setMismatch({
@@ -1911,23 +1948,23 @@ function useReplay(session) {
1911
1948
  }
1912
1949
 
1913
1950
  // src/hooks/use-llm-chat.ts
1914
- import { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
1951
+ import { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef3, useState as useState4 } from "react";
1915
1952
  var DEFAULT_HISTORY_TURNS = 12;
1916
1953
  var DEFAULT_MAX_TOOL_ROUNDS = 4;
1917
1954
  var syntheticIdSeq = 0;
1918
1955
  function useLlmChat(options) {
1919
- const [history, setHistory] = useState3([]);
1920
- const [streamingText, setStreamingText] = useState3(null);
1921
- const [streamingCalls, setStreamingCalls] = useState3([]);
1922
- const [failedToolIds, setFailedToolIds] = useState3([]);
1923
- const [error61, setError] = useState3(null);
1924
- const [isStreaming, setIsStreaming] = useState3(false);
1925
- const abortRef = useRef2(null);
1926
- const activeStartedAtRef = useRef2(null);
1927
- const assistantTimingsRef = useRef2(/* @__PURE__ */ new WeakMap());
1928
- const generationRef = useRef2(0);
1929
- const historyRef = useRef2([]);
1930
- const optionsRef = useRef2(options);
1956
+ const [history, setHistory] = useState4([]);
1957
+ const [streamingText, setStreamingText] = useState4(null);
1958
+ const [streamingCalls, setStreamingCalls] = useState4([]);
1959
+ const [failedToolIds, setFailedToolIds] = useState4([]);
1960
+ const [error61, setError] = useState4(null);
1961
+ const [isStreaming, setIsStreaming] = useState4(false);
1962
+ const abortRef = useRef3(null);
1963
+ const activeStartedAtRef = useRef3(null);
1964
+ const assistantTimingsRef = useRef3(/* @__PURE__ */ new WeakMap());
1965
+ const generationRef = useRef3(0);
1966
+ const historyRef = useRef3([]);
1967
+ const optionsRef = useRef3(options);
1931
1968
  optionsRef.current = options;
1932
1969
  historyRef.current = history;
1933
1970
  const stop = useCallback2(() => {
@@ -2267,7 +2304,7 @@ function toToolCallInfo(call, results, failedToolIds) {
2267
2304
  }
2268
2305
 
2269
2306
  // src/hooks/use-message-pin.ts
2270
- import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3 } from "react";
2307
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4 } from "react";
2271
2308
  var DEFAULT_MARGIN_PX = 24;
2272
2309
  var MANUAL_SCROLL_TOLERANCE_PX = 2;
2273
2310
  function useMessagePin({
@@ -2289,16 +2326,16 @@ function useMessagePin({
2289
2326
  scrollToBottom,
2290
2327
  margin = DEFAULT_MARGIN_PX
2291
2328
  }) {
2292
- const pinActiveRef = useRef3(false);
2293
- const frameRef = useRef3(null);
2294
- const retryTimeoutRef = useRef3(null);
2295
- const manualScrollCheckTimeoutRef = useRef3(null);
2296
- const repositionPendingRef = useRef3(false);
2297
- const pinnedTargetScrollTopRef = useRef3(null);
2298
- const appliedTargetKeyRef = useRef3(null);
2299
- const initialObservedTargetKeyRef = useRef3(pinTarget ? null : targetKey);
2300
- const observedTargetKeyRef = useRef3(initialObservedTargetKeyRef.current);
2301
- const setSpacerHeightRef = useRef3(setSpacerHeight);
2329
+ const pinActiveRef = useRef4(false);
2330
+ const frameRef = useRef4(null);
2331
+ const retryTimeoutRef = useRef4(null);
2332
+ const manualScrollCheckTimeoutRef = useRef4(null);
2333
+ const repositionPendingRef = useRef4(false);
2334
+ const pinnedTargetScrollTopRef = useRef4(null);
2335
+ const appliedTargetKeyRef = useRef4(null);
2336
+ const initialObservedTargetKeyRef = useRef4(pinTarget ? null : targetKey);
2337
+ const observedTargetKeyRef = useRef4(initialObservedTargetKeyRef.current);
2338
+ const setSpacerHeightRef = useRef4(setSpacerHeight);
2302
2339
  setSpacerHeightRef.current = setSpacerHeight;
2303
2340
  const release = useCallback3(() => {
2304
2341
  if (!pinActiveRef.current) return;
@@ -2360,7 +2397,7 @@ function useMessagePin({
2360
2397
  },
2361
2398
  [reposition]
2362
2399
  );
2363
- useEffect3(() => {
2400
+ useEffect4(() => {
2364
2401
  if (!targetKey) {
2365
2402
  release();
2366
2403
  appliedTargetKeyRef.current = null;
@@ -2390,10 +2427,10 @@ function useMessagePin({
2390
2427
  scheduleReposition();
2391
2428
  }, 80);
2392
2429
  }, [isStreaming, pinTarget, release, scheduleReposition, stopAutoScroll, targetKey]);
2393
- useEffect3(() => {
2430
+ useEffect4(() => {
2394
2431
  if (layoutKey !== void 0) scheduleReposition();
2395
2432
  }, [layoutKey, scheduleReposition]);
2396
- useEffect3(() => {
2433
+ useEffect4(() => {
2397
2434
  const scroll = getScrollElement();
2398
2435
  if (!scroll) return;
2399
2436
  const content3 = getContentElement?.();
@@ -2424,7 +2461,7 @@ function useMessagePin({
2424
2461
  scroll.removeEventListener("scroll", handleScroll);
2425
2462
  };
2426
2463
  }, [getContentElement, getScrollElement, release, scheduleReposition]);
2427
- useEffect3(
2464
+ useEffect4(
2428
2465
  () => () => {
2429
2466
  if (frameRef.current != null) cancelAnimationFrame(frameRef.current);
2430
2467
  frameRef.current = null;
@@ -2448,7 +2485,7 @@ function useMessagePin({
2448
2485
  }
2449
2486
 
2450
2487
  // src/hooks/use-typewriter-reveal.ts
2451
- import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
2488
+ import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5, useState as useState5 } from "react";
2452
2489
  var REVEAL_INITIAL_CPS = 18;
2453
2490
  var REVEAL_MIN_CPS = 6;
2454
2491
  var REVEAL_MAX_CPS = 240;
@@ -2484,15 +2521,15 @@ function initialRevealState(targetText, isLive, resetKey) {
2484
2521
  };
2485
2522
  }
2486
2523
  function useTypewriterReveal(targetText, isLive, resetKey) {
2487
- const [state, setState] = useState4(() => initialRevealState(targetText, isLive, resetKey));
2488
- const targetTextRef = useRef4(targetText);
2524
+ const [state, setState] = useState5(() => initialRevealState(targetText, isLive, resetKey));
2525
+ const targetTextRef = useRef5(targetText);
2489
2526
  targetTextRef.current = targetText;
2490
- const revealedLenRef = useRef4(state.revealedLen);
2491
- const priorTargetLenRef = useRef4(targetText.length);
2492
- const emaCpsRef = useRef4(REVEAL_INITIAL_CPS);
2493
- const lastTickTsRef = useRef4(null);
2494
- const lastArrivalTsRef = useRef4(null);
2495
- const cancelRef = useRef4(null);
2527
+ const revealedLenRef = useRef5(state.revealedLen);
2528
+ const priorTargetLenRef = useRef5(targetText.length);
2529
+ const emaCpsRef = useRef5(REVEAL_INITIAL_CPS);
2530
+ const lastTickTsRef = useRef5(null);
2531
+ const lastArrivalTsRef = useRef5(null);
2532
+ const cancelRef = useRef5(null);
2496
2533
  const stopTicking = useCallback4(() => {
2497
2534
  cancelRef.current?.();
2498
2535
  cancelRef.current = null;
@@ -2524,7 +2561,7 @@ function useTypewriterReveal(targetText, isLive, resetKey) {
2524
2561
  priorTargetLenRef.current = targetText.length;
2525
2562
  setState((s) => ({ ...s, displayedText: targetText, revealedLen: targetText.length, isRevealing: false }));
2526
2563
  }
2527
- const tickRef = useRef4(null);
2564
+ const tickRef = useRef5(null);
2528
2565
  tickRef.current = (ts) => {
2529
2566
  cancelRef.current = null;
2530
2567
  const currentTargetLen = targetTextRef.current.length;
@@ -2563,7 +2600,7 @@ function useTypewriterReveal(targetText, isLive, resetKey) {
2563
2600
  cancelRef.current = scheduleAnimationFrame((nextTs) => tickRef.current?.(nextTs));
2564
2601
  }
2565
2602
  };
2566
- useEffect4(() => {
2603
+ useEffect5(() => {
2567
2604
  if (!isLive) return;
2568
2605
  if (revealedLenRef.current === 0) return;
2569
2606
  if (revealedLenRef.current >= targetText.length) return;
@@ -2571,10 +2608,10 @@ function useTypewriterReveal(targetText, isLive, resetKey) {
2571
2608
  setState((s) => s.isRevealing ? s : { ...s, isRevealing: true });
2572
2609
  cancelRef.current = scheduleAnimationFrame((ts) => tickRef.current?.(ts));
2573
2610
  }, [targetText, isLive]);
2574
- useEffect4(() => {
2611
+ useEffect5(() => {
2575
2612
  if (!isLive) stopTicking();
2576
2613
  }, [isLive, stopTicking]);
2577
- useEffect4(() => {
2614
+ useEffect5(() => {
2578
2615
  if (typeof document === "undefined") return;
2579
2616
  const handleVisibilityChange = () => {
2580
2617
  if (document.visibilityState === "visible") flushNow();
@@ -2582,7 +2619,7 @@ function useTypewriterReveal(targetText, isLive, resetKey) {
2582
2619
  document.addEventListener("visibilitychange", handleVisibilityChange);
2583
2620
  return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
2584
2621
  }, [flushNow]);
2585
- useEffect4(() => stopTicking, [stopTicking]);
2622
+ useEffect5(() => stopTicking, [stopTicking]);
2586
2623
  return { displayedText: state.displayedText, isRevealing: state.isRevealing, flushNow };
2587
2624
  }
2588
2625
 
@@ -2592,7 +2629,7 @@ import {
2592
2629
  isHiddenInternalMessage,
2593
2630
  normalizeMessageContent
2594
2631
  } from "@blade-hq/agent-client";
2595
- import { useCallback as useCallback5, useEffect as useEffect5, useLayoutEffect, useRef as useRef5, useState as useState5 } from "react";
2632
+ import { useCallback as useCallback5, useEffect as useEffect6, useLayoutEffect, useRef as useRef6, useState as useState6 } from "react";
2596
2633
  var HIGHLIGHT_MS = 1600;
2597
2634
  var TURN_NAV_HIGHLIGHT_CLASS = "blade-turn-nav-flash";
2598
2635
  var MAX_FRAMES_AFTER_LOCATE = 20;
@@ -2647,7 +2684,7 @@ function useTurnNavigation({
2647
2684
  reloadKey,
2648
2685
  rewriteKey
2649
2686
  }) {
2650
- const callbacks = useRef5({
2687
+ const callbacks = useRef6({
2651
2688
  getLoadedEntryElement,
2652
2689
  isEntryLoaded,
2653
2690
  locateEntry,
@@ -2656,27 +2693,27 @@ function useTurnNavigation({
2656
2693
  revealEntry,
2657
2694
  beforeSeek
2658
2695
  });
2659
- const [index3, setIndex] = useState5({ sessionId: null, items: [] });
2660
- const [loadingEntryId, setLoadingEntryId] = useState5(null);
2661
- const [activeEntryId, setActiveEntryId] = useState5(null);
2662
- const [failedEntryId, setFailedEntryId] = useState5(null);
2663
- const [error61, setError] = useState5(null);
2664
- const [indexRefresh, setIndexRefresh] = useState5(0);
2665
- const seekSeq = useRef5(0);
2666
- const indexSeq = useRef5(0);
2667
- const indexRef = useRef5({
2696
+ const [index3, setIndex] = useState6({ sessionId: null, items: [] });
2697
+ const [loadingEntryId, setLoadingEntryId] = useState6(null);
2698
+ const [activeEntryId, setActiveEntryId] = useState6(null);
2699
+ const [failedEntryId, setFailedEntryId] = useState6(null);
2700
+ const [error61, setError] = useState6(null);
2701
+ const [indexRefresh, setIndexRefresh] = useState6(0);
2702
+ const seekSeq = useRef6(0);
2703
+ const indexSeq = useRef6(0);
2704
+ const indexRef = useRef6({
2668
2705
  sessionId: null,
2669
2706
  items: []
2670
2707
  });
2671
- const highlightTimer = useRef5(void 0);
2672
- const highlightedRef = useRef5(null);
2708
+ const highlightTimer = useRef6(void 0);
2709
+ const highlightedRef = useRef6(null);
2673
2710
  const clearHighlight = useCallback5(() => {
2674
2711
  clearTimeout(highlightTimer.current);
2675
2712
  highlightTimer.current = void 0;
2676
2713
  highlightedRef.current?.classList.remove(TURN_NAV_HIGHLIGHT_CLASS);
2677
2714
  highlightedRef.current = null;
2678
2715
  }, []);
2679
- useEffect5(
2716
+ useEffect6(
2680
2717
  () => () => {
2681
2718
  seekSeq.current += 1;
2682
2719
  indexSeq.current += 1;
@@ -2708,7 +2745,7 @@ function useTurnNavigation({
2708
2745
  beforeSeek
2709
2746
  };
2710
2747
  });
2711
- useEffect5(() => {
2748
+ useEffect6(() => {
2712
2749
  const load = callbacks.current.loadTurnIndex;
2713
2750
  indexSeq.current += 1;
2714
2751
  const seq = indexSeq.current;
@@ -2828,7 +2865,7 @@ function useTurnNavigation({
2828
2865
  }
2829
2866
 
2830
2867
  // src/components/TurnNavRail.tsx
2831
- import { useCallback as useCallback6, useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useRef as useRef6, useState as useState6 } from "react";
2868
+ import { useCallback as useCallback6, useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef7, useState as useState7 } from "react";
2832
2869
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
2833
2870
  var PANEL_MAX_HEIGHT = 448;
2834
2871
  var PANEL_MAX_WIDTH = 320;
@@ -2848,11 +2885,11 @@ function TurnNavRail({
2848
2885
  failedTurnId,
2849
2886
  onSelectTurn
2850
2887
  }) {
2851
- const [open2, setOpen] = useState6(false);
2852
- const [hoveredEntryId, setHoveredEntryId] = useState6(null);
2853
- const markersRef = useRef6(null);
2854
- const listRef = useRef6(null);
2855
- useEffect6(() => {
2888
+ const [open2, setOpen] = useState7(false);
2889
+ const [hoveredEntryId, setHoveredEntryId] = useState7(null);
2890
+ const markersRef = useRef7(null);
2891
+ const listRef = useRef7(null);
2892
+ useEffect7(() => {
2856
2893
  if (!activeTurnId) return;
2857
2894
  const marker = Array.from(
2858
2895
  markersRef.current?.querySelectorAll("[data-nav-entry-id]") ?? []
@@ -2878,7 +2915,7 @@ function TurnNavRail({
2878
2915
  if (!open2) return;
2879
2916
  clampPanel();
2880
2917
  }, [open2, items, clampPanel]);
2881
- useEffect6(() => {
2918
+ useEffect7(() => {
2882
2919
  if (!open2) return;
2883
2920
  const container = clippingAncestor(markersRef.current);
2884
2921
  if (!container || typeof ResizeObserver === "undefined") return;
@@ -3412,13 +3449,13 @@ var X = createLucideIcon("X", [
3412
3449
  ]);
3413
3450
 
3414
3451
  // src/components/AgentChat.tsx
3415
- import { useCallback as useCallback30, useEffect as useEffect26, useMemo as useMemo18, useRef as useRef28, useState as useState35 } from "react";
3452
+ import { useCallback as useCallback30, useEffect as useEffect27, useMemo as useMemo18, useRef as useRef29, useState as useState36 } from "react";
3416
3453
 
3417
3454
  // src/components/SessionPluginSelector.tsx
3418
- import { useEffect as useEffect14, useState as useState19 } from "react";
3455
+ import { useEffect as useEffect15, useState as useState20 } from "react";
3419
3456
 
3420
3457
  // src/components/SessionPluginConfigDialog.tsx
3421
- import { useEffect as useEffect12, useRef as useRef12, useState as useState17 } from "react";
3458
+ import { useEffect as useEffect13, useRef as useRef13, useState as useState18 } from "react";
3422
3459
 
3423
3460
  // ../../node_modules/.pnpm/@cfworker+json-schema@4.1.1/node_modules/@cfworker/json-schema/dist/esm/deep-compare-strict.js
3424
3461
  function deepCompareStrict(a, b2) {
@@ -9158,7 +9195,7 @@ function toFieldPathId(fieldPath, globalFormOptions, parentPath, isMultiValue) {
9158
9195
 
9159
9196
  // ../../node_modules/.pnpm/@rjsf+utils@6.10.0_react@19.2.4/node_modules/@rjsf/utils/lib/useAltDateWidgetProps.js
9160
9197
  import { jsx as _jsx3 } from "react/jsx-runtime";
9161
- import { useCallback as useCallback7, useEffect as useEffect7, useMemo as useMemo3, useState as useState7 } from "react";
9198
+ import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo3, useState as useState8 } from "react";
9162
9199
  function readyForChange(state) {
9163
9200
  return Object.values(state).every((value) => value !== -1);
9164
9201
  }
@@ -9171,8 +9208,8 @@ function DateElement(props) {
9171
9208
  }
9172
9209
  function useAltDateWidgetProps(props) {
9173
9210
  const { time: time5 = false, disabled = false, readonly: readonly2 = false, options, onChange, value } = props;
9174
- const [state, setState] = useState7(parseDateString(value, time5));
9175
- useEffect7(() => {
9211
+ const [state, setState] = useState8(parseDateString(value, time5));
9212
+ useEffect8(() => {
9176
9213
  setState(parseDateString(value, time5));
9177
9214
  }, [time5, value]);
9178
9215
  const handleChange = useCallback7((property, newValue) => {
@@ -9206,9 +9243,9 @@ function useAltDateWidgetProps(props) {
9206
9243
  }
9207
9244
 
9208
9245
  // ../../node_modules/.pnpm/@rjsf+utils@6.10.0_react@19.2.4/node_modules/@rjsf/utils/lib/useDeepCompareMemo.js
9209
- import { useRef as useRef7 } from "react";
9246
+ import { useRef as useRef8 } from "react";
9210
9247
  function useDeepCompareMemo(newValue) {
9211
- const valueRef = useRef7(newValue);
9248
+ const valueRef = useRef8(newValue);
9212
9249
  if (!deepEquals_default(newValue, valueRef.current)) {
9213
9250
  valueRef.current = newValue;
9214
9251
  }
@@ -9402,7 +9439,7 @@ var TranslatableString;
9402
9439
 
9403
9440
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/ArrayField.js
9404
9441
  import { jsx as _jsx4 } from "react/jsx-runtime";
9405
- import { memo, useCallback as useCallback9, useMemo as useMemo5, useRef as useRef8, useState as useState8 } from "react";
9442
+ import { memo, useCallback as useCallback9, useMemo as useMemo5, useRef as useRef9, useState as useState9 } from "react";
9406
9443
  var rowIdCounter = 0;
9407
9444
  function generateRowId() {
9408
9445
  rowIdCounter += 1;
@@ -9728,7 +9765,7 @@ function FixedArray(props) {
9728
9765
  }
9729
9766
  function useKeyedFormData(formData = []) {
9730
9767
  const newHash = useMemo5(() => hashObject(formData), [formData]);
9731
- const [state, setState] = useState8(() => ({
9768
+ const [state, setState] = useState9(() => ({
9732
9769
  formDataHash: newHash,
9733
9770
  keyedFormData: generateKeyedFormData(formData)
9734
9771
  }));
@@ -9755,9 +9792,9 @@ function ArrayField(props) {
9755
9792
  const { schema, uiSchema, errorSchema, fieldPathId, registry: registry2, formData, onChange } = props;
9756
9793
  const { globalFormOptions, schemaUtils, translateString } = registry2;
9757
9794
  const { keyedFormData, updateKeyedFormData } = useKeyedFormData(formData);
9758
- const keyedFormDataRef = useRef8(keyedFormData);
9795
+ const keyedFormDataRef = useRef9(keyedFormData);
9759
9796
  keyedFormDataRef.current = keyedFormData;
9760
- const errorSchemaRef = useRef8(errorSchema);
9797
+ const errorSchemaRef = useRef9(errorSchema);
9761
9798
  errorSchemaRef.current = errorSchema;
9762
9799
  const childFieldPathId = props.childFieldPathId ?? fieldPathId;
9763
9800
  const handleAddItem = useCallback9((event, index3) => {
@@ -9975,9 +10012,9 @@ var BooleanField_default = BooleanField;
9975
10012
 
9976
10013
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/CyclicSchemaField.js
9977
10014
  import { jsx as _jsx6 } from "react/jsx-runtime";
9978
- import { useState as useState9 } from "react";
10015
+ import { useState as useState10 } from "react";
9979
10016
  function CyclicSchemaField(props) {
9980
- const [expanded, setExpanded] = useState9(false);
10017
+ const [expanded, setExpanded] = useState10(false);
9981
10018
  const { name, registry: registry2, schema, uiSchema, fieldPathId } = props;
9982
10019
  const { globalUiOptions } = registry2;
9983
10020
  const uiOptions = getUiOptions(uiSchema, globalUiOptions);
@@ -9992,7 +10029,7 @@ function CyclicSchemaField(props) {
9992
10029
 
9993
10030
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/FallbackField.js
9994
10031
  import { jsx as _jsx7 } from "react/jsx-runtime";
9995
- import { useMemo as useMemo6, useState as useState10 } from "react";
10032
+ import { useMemo as useMemo6, useState as useState11 } from "react";
9996
10033
  function getFallbackTypeSelectionSchema(title) {
9997
10034
  return {
9998
10035
  type: "string",
@@ -10028,7 +10065,7 @@ function castToNewType(formData, newType) {
10028
10065
  function FallbackField(props) {
10029
10066
  const { id, formData, displayLabel = true, schema, name, uiSchema, required: required2, disabled = false, readonly: readonly2 = false, onBlur, onFocus, registry: registry2, fieldPathId, onChange, errorSchema } = props;
10030
10067
  const { translateString, fields: fields2, globalFormOptions } = registry2;
10031
- const [type, setType] = useState10(getTypeOfFormData(formData));
10068
+ const [type, setType] = useState11(getTypeOfFormData(formData));
10032
10069
  const uiOptions = getUiOptions(uiSchema);
10033
10070
  const typeSelectorInnerFieldPathId = useDeepCompareMemo(toFieldPathId("__internal_type_selector", globalFormOptions, fieldPathId));
10034
10071
  const schemaTitle = translateString(TranslatableString.Type);
@@ -10371,7 +10408,7 @@ function LayoutHeaderField(props) {
10371
10408
 
10372
10409
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/LayoutMultiSchemaField.js
10373
10410
  import { jsx as _jsx10 } from "react/jsx-runtime";
10374
- import { useState as useState11, useEffect as useEffect8 } from "react";
10411
+ import { useState as useState12, useEffect as useEffect9 } from "react";
10375
10412
  function getSelectedOption(options, selectorField, value) {
10376
10413
  const defaultValue = "!@#!@$@#$!@$#";
10377
10414
  const schemaOptions = options.map(({ schema }) => schema);
@@ -10398,7 +10435,7 @@ function computeEnumOptions(schema, options, schemaUtils, uiSchema, formData) {
10398
10435
  function LayoutMultiSchemaField(props) {
10399
10436
  const { name, baseType, disabled = false, formData, fieldPathId, onBlur, onChange, options, onFocus, registry: registry2, uiSchema, schema, autofocus, readonly: readonly2, required: required2, errorSchema, hideError = false } = props;
10400
10437
  const { widgets: widgets2, schemaUtils, globalUiOptions } = registry2;
10401
- const [enumOptions, setEnumOptions] = useState11(computeEnumOptions(schema, options, schemaUtils, uiSchema, formData));
10438
+ const [enumOptions, setEnumOptions] = useState12(computeEnumOptions(schema, options, schemaUtils, uiSchema, formData));
10402
10439
  const id = fieldPathId[ID_KEY];
10403
10440
  const discriminator = getDiscriminatorFieldFromSchema(schema);
10404
10441
  const FieldErrorTemplate2 = getTemplate("FieldErrorTemplate", registry2, options);
@@ -10407,7 +10444,7 @@ function LayoutMultiSchemaField(props) {
10407
10444
  const optionsHash = hashObject(options);
10408
10445
  const uiSchemaHash = uiSchema ? hashObject(uiSchema) : "";
10409
10446
  const formDataHash = formData ? hashObject(formData) : "";
10410
- useEffect8(() => {
10447
+ useEffect9(() => {
10411
10448
  setEnumOptions(computeEnumOptions(schema, options, schemaUtils, uiSchema, formData));
10412
10449
  }, [schemaHash, optionsHash, schemaUtils, uiSchemaHash, formDataHash]);
10413
10450
  const { widget = discriminator ? "radio" : "select", title = "", placeholder = "", optionsSchemaSelector: selectorField = discriminator, hideError: uiSchemaHideError, ...uiOptions } = getUiOptions(uiSchema);
@@ -10446,7 +10483,7 @@ function LayoutMultiSchemaField(props) {
10446
10483
 
10447
10484
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/MultiSchemaField.js
10448
10485
  import { jsx as _jsx11 } from "react/jsx-runtime";
10449
- import { useCallback as useCallback11, useEffect as useEffect9, useMemo as useMemo7, useRef as useRef9, useState as useState12 } from "react";
10486
+ import { useCallback as useCallback11, useEffect as useEffect10, useMemo as useMemo7, useRef as useRef10, useState as useState13 } from "react";
10450
10487
  function AnyOfField(props) {
10451
10488
  const { name, disabled = false, errorSchema, formData, fieldPathId, onBlur, onChange, onFocus, options, readonly: readonly2, registry: registry2, required: required2 = false, schema, uiSchema } = props;
10452
10489
  const { schemaUtils } = registry2;
@@ -10456,14 +10493,14 @@ function AnyOfField(props) {
10456
10493
  // oxlint-disable-next-line react-hooks/exhaustive-deps -- formDataHash is the value-stable proxy for formData
10457
10494
  [options, schemaUtils, formDataHash]
10458
10495
  );
10459
- const [selectedOption, setSelectedOption] = useState12(() => {
10496
+ const [selectedOption, setSelectedOption] = useState13(() => {
10460
10497
  const discriminator = getDiscriminatorFieldFromSchema(schema);
10461
10498
  return schemaUtils.getClosestMatchingOption(formData, retrievedOptions, 0, discriminator);
10462
10499
  });
10463
- const skipNextOptionRecalculation = useRef9(false);
10464
- const prevFormDataRef = useRef9(formData);
10465
- const prevFieldIdRef = useRef9(fieldPathId.$id);
10466
- useEffect9(() => {
10500
+ const skipNextOptionRecalculation = useRef10(false);
10501
+ const prevFormDataRef = useRef10(formData);
10502
+ const prevFieldIdRef = useRef10(fieldPathId.$id);
10503
+ useEffect10(() => {
10467
10504
  const prevFormData = prevFormDataRef.current;
10468
10505
  const prevFieldId = prevFieldIdRef.current;
10469
10506
  prevFormDataRef.current = formData;
@@ -10561,10 +10598,10 @@ function AnyOfField(props) {
10561
10598
  var MultiSchemaField_default = AnyOfField;
10562
10599
 
10563
10600
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/NullField.js
10564
- import { useEffect as useEffect10 } from "react";
10601
+ import { useEffect as useEffect11 } from "react";
10565
10602
  function NullField(props) {
10566
10603
  const { formData, onChange, fieldPathId } = props;
10567
- useEffect10(() => {
10604
+ useEffect11(() => {
10568
10605
  if (formData === void 0) {
10569
10606
  onChange(null, fieldPathId.path);
10570
10607
  }
@@ -10575,12 +10612,12 @@ var NullField_default = NullField;
10575
10612
 
10576
10613
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/NumberField.js
10577
10614
  import { jsx as _jsx12 } from "react/jsx-runtime";
10578
- import { useState as useState13, useCallback as useCallback12 } from "react";
10615
+ import { useState as useState14, useCallback as useCallback12 } from "react";
10579
10616
  var trailingCharMatcherWithPrefix = /\.([0-9]*0)*$/;
10580
10617
  var trailingCharMatcher = /[0.]0*$/;
10581
10618
  function NumberField(props) {
10582
10619
  const { registry: registry2, onChange, formData, value: initialValue } = props;
10583
- const [lastValue, setLastValue] = useState13(initialValue);
10620
+ const [lastValue, setLastValue] = useState14(initialValue);
10584
10621
  const { StringField: StringField2 } = registry2.fields;
10585
10622
  const separator = getDecimalSeparator();
10586
10623
  const escapedSeparator = separator === "." ? "\\." : separator;
@@ -10615,7 +10652,7 @@ var NumberField_default = NumberField;
10615
10652
 
10616
10653
  // ../../node_modules/.pnpm/@rjsf+core@6.10.0_@rjsf+utils@6.10.0_react@19.2.4__react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/@rjsf/core/lib/components/fields/ObjectField.js
10617
10654
  import { jsx as _jsx13, jsxs as _jsxs } from "react/jsx-runtime";
10618
- import { memo as memo2, useCallback as useCallback13, useMemo as useMemo9, useRef as useRef11, useState as useState14 } from "react";
10655
+ import { memo as memo2, useCallback as useCallback13, useMemo as useMemo9, useRef as useRef12, useState as useState15 } from "react";
10619
10656
 
10620
10657
  // ../../node_modules/.pnpm/markdown-to-jsx@9.10.2_react@19.2.4_vue@3.5.40_typescript@5.9.3_/node_modules/markdown-to-jsx/dist/react.js
10621
10658
  import * as i0 from "react";
@@ -13750,7 +13787,7 @@ function getAdditionalPropertyOrder(schemaProperties) {
13750
13787
  }
13751
13788
  function ObjectFieldPropertyFn(props) {
13752
13789
  const { fieldPathId, schema, registry: registry2, uiSchema, errorSchema, formData, onChange, onBlur, onFocus, disabled, readonly: readonly2, required: required2, hideError, propertyName, handleKeyRename, handleRemoveProperty, addedByAdditionalProperties } = props;
13753
- const [wasPropertyKeyModified, setWasPropertyKeyModified] = useState14(false);
13790
+ const [wasPropertyKeyModified, setWasPropertyKeyModified] = useState15(false);
13754
13791
  const { globalFormOptions, fields: fields2 } = registry2;
13755
13792
  const { SchemaField: SchemaField2 } = fields2;
13756
13793
  const innerFieldIdPathId = useDeepCompareMemo(toFieldPathId(propertyName, globalFormOptions, fieldPathId.path));
@@ -13781,14 +13818,14 @@ function ObjectField(props) {
13781
13818
  const { schema: rawSchema, uiSchema = {}, formData, errorSchema, fieldPathId, name, required: required2 = false, disabled, readonly: readonly2, hideError, onBlur, onFocus, onChange, registry: registry2, title } = props;
13782
13819
  const { fields: fields2, schemaUtils, translateString, globalUiOptions } = registry2;
13783
13820
  const { OptionalDataControlsField: OptionalDataControlsField2 } = fields2;
13784
- const formDataRef = useRef11(formData);
13821
+ const formDataRef = useRef12(formData);
13785
13822
  formDataRef.current = formData;
13786
13823
  const schema = useMemo9(() => schemaUtils.retrieveSchema(rawSchema, formData, true), [schemaUtils, rawSchema, formData]);
13787
13824
  const uiOptions = useMemo9(() => getUiOptions(uiSchema, globalUiOptions), [uiSchema, globalUiOptions]);
13788
13825
  const schemaProperties = useMemo9(() => schema.properties ?? {}, [schema.properties]);
13789
13826
  const childFieldPathId = props.childFieldPathId ?? fieldPathId;
13790
- const lastRenamedProperty = useRef11({ previousKey: "", currentKey: void 0 });
13791
- const [additionalPropertyOrder, setAdditionalPropertyOrder] = useState14(() => getAdditionalPropertyOrder(schemaProperties));
13827
+ const lastRenamedProperty = useRef12({ previousKey: "", currentKey: void 0 });
13828
+ const [additionalPropertyOrder, setAdditionalPropertyOrder] = useState15(() => getAdditionalPropertyOrder(schemaProperties));
13792
13829
  const definedPropertyOrder = useMemo9(() => {
13793
13830
  const additionalPropertySet = new Set(getAdditionalPropertyOrder(schemaProperties));
13794
13831
  return Object.keys(schemaProperties).filter((property) => !additionalPropertySet.has(property));
@@ -15743,7 +15780,7 @@ var Form = class _Form extends Component {
15743
15780
  };
15744
15781
 
15745
15782
  // src/components/SessionPluginConfigForm.tsx
15746
- import { isValidElement, useMemo as useMemo10, useState as useState15 } from "react";
15783
+ import { isValidElement, useMemo as useMemo10, useState as useState16 } from "react";
15747
15784
 
15748
15785
  // src/components/plugin-config-schema.ts
15749
15786
  function asSchema(value) {
@@ -16138,10 +16175,10 @@ function SessionPluginConfigForm({
16138
16175
  onSubmit,
16139
16176
  onCancel
16140
16177
  }) {
16141
- const [initial] = useState15(() => createConfigDraft(config2));
16142
- const [values, setValues] = useState15(initial.values);
16143
- const [removed] = useState15(() => /* @__PURE__ */ new Set());
16144
- const [draftFailure, setDraftFailure] = useState15(null);
16178
+ const [initial] = useState16(() => createConfigDraft(config2));
16179
+ const [values, setValues] = useState16(initial.values);
16180
+ const [removed] = useState16(() => /* @__PURE__ */ new Set());
16181
+ const [draftFailure, setDraftFailure] = useState16(null);
16145
16182
  const support = useMemo10(() => formSupport(config2.schema), [config2.schema]);
16146
16183
  const schema = useMemo10(() => {
16147
16184
  try {
@@ -16251,7 +16288,7 @@ function SessionPluginConfigForm({
16251
16288
  }
16252
16289
 
16253
16290
  // src/components/SessionPluginIcon.tsx
16254
- import { useEffect as useEffect11, useState as useState16 } from "react";
16291
+ import { useEffect as useEffect12, useState as useState17 } from "react";
16255
16292
  import { jsx as jsx4 } from "react/jsx-runtime";
16256
16293
  function sessionPluginLabel(plugin) {
16257
16294
  const display = typeof plugin.display_name === "string" ? plugin.display_name.trim() : "";
@@ -16277,9 +16314,9 @@ function iconBlob(client, sessionId, name, token) {
16277
16314
  return pending;
16278
16315
  }
16279
16316
  function SessionPluginIcon({ client, sessionId, plugin, size: size4 = 20, shape = "rounded", className }) {
16280
- const [url2, setUrl] = useState16(null);
16317
+ const [url2, setUrl] = useState17(null);
16281
16318
  const token = plugin.icon;
16282
- useEffect11(() => {
16319
+ useEffect12(() => {
16283
16320
  setUrl(null);
16284
16321
  if (!token) return;
16285
16322
  let alive = true;
@@ -16348,17 +16385,17 @@ function ConfigDialogState({
16348
16385
  onSaved,
16349
16386
  onClose
16350
16387
  }) {
16351
- const [config2, setConfig] = useState17(null);
16352
- const [loading, setLoading] = useState17(true);
16353
- const [loadFailure, setLoadFailure] = useState17(null);
16354
- const [saving, setSaving] = useState17(false);
16355
- const [failure, setFailure] = useState17(null);
16356
- const [fieldErrors, setFieldErrors] = useState17([]);
16357
- const [formVersion, setFormVersion] = useState17(0);
16358
- const alive = useRef12(true);
16359
- const generation = useRef12(0);
16360
- const dialog = useRef12(null);
16361
- useEffect12(() => {
16388
+ const [config2, setConfig] = useState18(null);
16389
+ const [loading, setLoading] = useState18(true);
16390
+ const [loadFailure, setLoadFailure] = useState18(null);
16391
+ const [saving, setSaving] = useState18(false);
16392
+ const [failure, setFailure] = useState18(null);
16393
+ const [fieldErrors, setFieldErrors] = useState18([]);
16394
+ const [formVersion, setFormVersion] = useState18(0);
16395
+ const alive = useRef13(true);
16396
+ const generation = useRef13(0);
16397
+ const dialog = useRef13(null);
16398
+ useEffect13(() => {
16362
16399
  const element2 = dialog.current;
16363
16400
  if (!element2 || element2.open) return;
16364
16401
  if (typeof element2.showModal === "function") element2.showModal();
@@ -16382,7 +16419,7 @@ function ConfigDialogState({
16382
16419
  if (alive.current && generation.current === current) setLoading(false);
16383
16420
  }
16384
16421
  };
16385
- useEffect12(() => {
16422
+ useEffect13(() => {
16386
16423
  alive.current = true;
16387
16424
  setConfig(null);
16388
16425
  setFailure(null);
@@ -16637,7 +16674,7 @@ function PluginConnectorList({
16637
16674
  }
16638
16675
 
16639
16676
  // src/components/use-session-plugin-activation.ts
16640
- import { useCallback as useCallback25, useEffect as useEffect13, useMemo as useMemo11, useRef as useRef13, useState as useState18 } from "react";
16677
+ import { useCallback as useCallback25, useEffect as useEffect14, useMemo as useMemo11, useRef as useRef14, useState as useState19 } from "react";
16641
16678
 
16642
16679
  // src/components/plugin-connector.ts
16643
16680
  function catalogToConnectorItems(catalog) {
@@ -16698,23 +16735,23 @@ function useSessionPluginActivation({
16698
16735
  sessionId,
16699
16736
  onChange
16700
16737
  }) {
16701
- const [plugins, setPlugins] = useState18([]);
16702
- const [catalog, setCatalog] = useState18(null);
16703
- const [loading, setLoading] = useState18(false);
16704
- const [listError, setListError] = useState18(false);
16705
- const [mutationError, setMutationError] = useState18(false);
16706
- const [inFlight, setInFlight] = useState18({});
16707
- const [configuring, setConfiguring] = useState18(null);
16708
- const alive = useRef13(true);
16709
- const generation = useRef13(0);
16710
- const mutationGenerations = useRef13(/* @__PURE__ */ new Map());
16711
- const desiredActivations = useRef13(/* @__PURE__ */ new Map());
16712
- const pendingMutations = useRef13(/* @__PURE__ */ new Map());
16713
- const submittedActivations = useRef13(/* @__PURE__ */ new Set());
16714
- const serverActive = useRef13(/* @__PURE__ */ new Set());
16715
- const lifetime = useRef13(0);
16716
- const request = useRef13(null);
16717
- const [desiredVersion, setDesiredVersion] = useState18(0);
16738
+ const [plugins, setPlugins] = useState19([]);
16739
+ const [catalog, setCatalog] = useState19(null);
16740
+ const [loading, setLoading] = useState19(false);
16741
+ const [listError, setListError] = useState19(false);
16742
+ const [mutationError, setMutationError] = useState19(false);
16743
+ const [inFlight, setInFlight] = useState19({});
16744
+ const [configuring, setConfiguring] = useState19(null);
16745
+ const alive = useRef14(true);
16746
+ const generation = useRef14(0);
16747
+ const mutationGenerations = useRef14(/* @__PURE__ */ new Map());
16748
+ const desiredActivations = useRef14(/* @__PURE__ */ new Map());
16749
+ const pendingMutations = useRef14(/* @__PURE__ */ new Map());
16750
+ const submittedActivations = useRef14(/* @__PURE__ */ new Set());
16751
+ const serverActive = useRef14(/* @__PURE__ */ new Set());
16752
+ const lifetime = useRef14(0);
16753
+ const request = useRef14(null);
16754
+ const [desiredVersion, setDesiredVersion] = useState19(0);
16718
16755
  const setDesired = useCallback25((name, value) => {
16719
16756
  if (value === null) {
16720
16757
  if (!desiredActivations.current.delete(name)) return;
@@ -16744,7 +16781,7 @@ function useSessionPluginActivation({
16744
16781
  return rest;
16745
16782
  });
16746
16783
  }, []);
16747
- useEffect13(() => {
16784
+ useEffect14(() => {
16748
16785
  alive.current = true;
16749
16786
  setPlugins([]);
16750
16787
  setCatalog(null);
@@ -16973,7 +17010,7 @@ function SessionPluginSelector(props) {
16973
17010
  return /* @__PURE__ */ jsx7(PluginSelectorState, { ...props }, props.sessionId);
16974
17011
  }
16975
17012
  function PluginSelectorState({ client, sessionId, className, side = "bottom", onChange }) {
16976
- const [open2, setOpen] = useState19(false);
17013
+ const [open2, setOpen] = useState20(false);
16977
17014
  return /* @__PURE__ */ jsxs5("div", { className: `relative text-xs ${className ?? ""}`, children: [
16978
17015
  /* @__PURE__ */ jsx7(
16979
17016
  "button",
@@ -16997,7 +17034,7 @@ function PluginSelectorList({
16997
17034
  }) {
16998
17035
  const controller = useSessionPluginActivation({ client, sessionId, onChange });
16999
17036
  const { reload } = controller;
17000
- useEffect14(() => {
17037
+ useEffect15(() => {
17001
17038
  reload();
17002
17039
  }, [reload]);
17003
17040
  return /* @__PURE__ */ jsxs5(
@@ -17037,7 +17074,7 @@ import {
17037
17074
  queuePauseReasonLabel,
17038
17075
  queuedMessageStatusLabel
17039
17076
  } from "@blade-hq/agent-client";
17040
- import { useContext as useContext3, useLayoutEffect as useLayoutEffect3, useRef as useRef14, useState as useState20 } from "react";
17077
+ import { useContext as useContext3, useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState21 } from "react";
17041
17078
 
17042
17079
  // ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
17043
17080
  function r2(e2) {
@@ -20287,19 +20324,19 @@ function SessionQueuePanel({
20287
20324
  onVisibleChange,
20288
20325
  mergesWithInputBelow: mergesWithInputBelowProp
20289
20326
  }) {
20290
- const [collapsed, setCollapsed] = useState20(false);
20291
- const [editing, setEditing] = useState20(null);
20292
- const [draggingId, setDraggingId] = useState20(null);
20293
- const [dropAt, setDropAt] = useState20(null);
20294
- const draggingRef = useRef14(null);
20295
- const dropRef = useRef14(null);
20296
- const requeuePending = useRef14(false);
20297
- const [requeueing, setRequeueing] = useState20(false);
20327
+ const [collapsed, setCollapsed] = useState21(false);
20328
+ const [editing, setEditing] = useState21(null);
20329
+ const [draggingId, setDraggingId] = useState21(null);
20330
+ const [dropAt, setDropAt] = useState21(null);
20331
+ const draggingRef = useRef15(null);
20332
+ const dropRef = useRef15(null);
20333
+ const requeuePending = useRef15(false);
20334
+ const [requeueing, setRequeueing] = useState21(false);
20298
20335
  const adjacency = useContext3(QueuePanelAdjacencyContext);
20299
20336
  const mergesWithInputBelow = mergesWithInputBelowProp ?? adjacency ?? true;
20300
20337
  const items = snapshot.items;
20301
20338
  const visible = isQueuePanelVisible(snapshot, notice, Boolean(editing));
20302
- const onVisibleChangeRef = useRef14(onVisibleChange);
20339
+ const onVisibleChangeRef = useRef15(onVisibleChange);
20303
20340
  onVisibleChangeRef.current = onVisibleChange;
20304
20341
  useLayoutEffect3(() => {
20305
20342
  onVisibleChangeRef.current?.(visible);
@@ -20732,7 +20769,7 @@ function ReplayMismatchPrompt({ mismatch, className }) {
20732
20769
  }
20733
20770
 
20734
20771
  // src/components/PlanUpdateBlock.tsx
20735
- import { useEffect as useEffect15, useRef as useRef15, useState as useState21 } from "react";
20772
+ import { useEffect as useEffect16, useRef as useRef16, useState as useState22 } from "react";
20736
20773
 
20737
20774
  // src/components/display-utils.ts
20738
20775
  var TOOL_NAME_ALIASES = {
@@ -20845,10 +20882,10 @@ function PlanUpdateBlock({
20845
20882
  }) {
20846
20883
  const updateKey = `${toolCall.id}:${toolCall.arguments}`;
20847
20884
  const revealKey = autoReveal ? updateKey : null;
20848
- const [collapsed, setCollapsed] = useState21(!autoReveal);
20849
- const collapseTimerRef = useRef15(null);
20885
+ const [collapsed, setCollapsed] = useState22(!autoReveal);
20886
+ const collapseTimerRef = useRef16(null);
20850
20887
  const data = parsePlanUpdate(toolCall.arguments);
20851
- useEffect15(() => {
20888
+ useEffect16(() => {
20852
20889
  if (!revealKey) return;
20853
20890
  if (collapseTimerRef.current) clearTimeout(collapseTimerRef.current);
20854
20891
  setCollapsed(false);
@@ -20857,7 +20894,7 @@ function PlanUpdateBlock({
20857
20894
  collapseTimerRef.current = null;
20858
20895
  }, PLAN_AUTO_COLLAPSE_MS);
20859
20896
  }, [revealKey]);
20860
- useEffect15(
20897
+ useEffect16(
20861
20898
  () => () => {
20862
20899
  if (collapseTimerRef.current) clearTimeout(collapseTimerRef.current);
20863
20900
  },
@@ -20945,9 +20982,9 @@ function CurrentPlanPanel({
20945
20982
  className
20946
20983
  }) {
20947
20984
  const { current, updating } = getPlanUpdateDisplayState(messages);
20948
- const revealBaselinesRef = useRef15(/* @__PURE__ */ new Map([[sessionId, revealRevision]]));
20985
+ const revealBaselinesRef = useRef16(/* @__PURE__ */ new Map([[sessionId, revealRevision]]));
20949
20986
  const autoReveal = (revealBaselinesRef.current.get(sessionId) ?? 0) !== revealRevision;
20950
- useEffect15(() => {
20987
+ useEffect16(() => {
20951
20988
  if (!current) return;
20952
20989
  revealBaselinesRef.current.set(sessionId, revealRevision);
20953
20990
  }, [current, revealRevision, sessionId]);
@@ -20971,7 +21008,7 @@ function CurrentPlanPanel({
20971
21008
 
20972
21009
  // src/components/ChatSurface.tsx
20973
21010
  import { chatErrorForDisplay as chatErrorForDisplay2 } from "@blade-hq/agent-client";
20974
- import { useMemo as useMemo17, useState as useState34 } from "react";
21011
+ import { useMemo as useMemo17, useState as useState35 } from "react";
20975
21012
 
20976
21013
  // src/lib/random-id.ts
20977
21014
  function randomId() {
@@ -45839,7 +45876,7 @@ function SF(G, Q) {
45839
45876
  }
45840
45877
 
45841
45878
  // src/components/McpAppCard.tsx
45842
- import { createContext as createContext4, useContext as useContext4, useEffect as useEffect16, useLayoutEffect as useLayoutEffect4, useRef as useRef16, useState as useState22 } from "react";
45879
+ import { createContext as createContext4, useContext as useContext4, useEffect as useEffect17, useLayoutEffect as useLayoutEffect4, useRef as useRef17, useState as useState23 } from "react";
45843
45880
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
45844
45881
  var McpAppMessageContext = createContext4(null);
45845
45882
  function securedHtml(archive) {
@@ -45881,17 +45918,17 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
45881
45918
  const contextMessage = useContext4(McpAppMessageContext);
45882
45919
  const client = suppliedClient ?? contextClient;
45883
45920
  const onMessage = suppliedOnMessage ?? contextMessage;
45884
- const onMessageRef = useRef16(onMessage);
45921
+ const onMessageRef = useRef17(onMessage);
45885
45922
  onMessageRef.current = onMessage;
45886
- const frame = useRef16(null);
45887
- const panel = useRef16(null);
45888
- const bridgeRef = useRef16(null);
45889
- const [html, setHtml] = useState22();
45890
- const [title, setTitle] = useState22("\u5DE5\u5177\u754C\u9762");
45891
- const [error61, setError] = useState22(null);
45892
- const [ready, setReady] = useState22(false);
45893
- const [expanded, setExpanded] = useState22(false);
45894
- const [height, setHeight] = useState22(360);
45923
+ const frame = useRef17(null);
45924
+ const panel = useRef17(null);
45925
+ const bridgeRef = useRef17(null);
45926
+ const [html, setHtml] = useState23();
45927
+ const [title, setTitle] = useState23("\u5DE5\u5177\u754C\u9762");
45928
+ const [error61, setError] = useState23(null);
45929
+ const [ready, setReady] = useState23(false);
45930
+ const [expanded, setExpanded] = useState23(false);
45931
+ const [height, setHeight] = useState23(360);
45895
45932
  useLayoutEffect4(() => {
45896
45933
  const dialog = panel.current;
45897
45934
  if (!dialog) return;
@@ -45899,7 +45936,7 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
45899
45936
  if (expanded) dialog.showModal();
45900
45937
  else dialog.show();
45901
45938
  }, [expanded]);
45902
- useEffect16(() => {
45939
+ useEffect17(() => {
45903
45940
  const controller = new AbortController();
45904
45941
  let bridge;
45905
45942
  let disposed = false;
@@ -46107,7 +46144,7 @@ function McpAppCard({ sessionId, sourceId, client: suppliedClient, onMessage: su
46107
46144
  }
46108
46145
 
46109
46146
  // src/components/ChatInput.tsx
46110
- import { useRef as useRef17, useState as useState23 } from "react";
46147
+ import { useRef as useRef18, useState as useState24 } from "react";
46111
46148
  import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
46112
46149
  function isImeCompositionKey(event) {
46113
46150
  return event.isComposing || event.keyCode === 229;
@@ -46133,10 +46170,10 @@ function ChatInput({
46133
46170
  hasAttachments = false
46134
46171
  }) {
46135
46172
  const trimmed = value.trim();
46136
- const latestValue = useRef17(value);
46173
+ const latestValue = useRef18(value);
46137
46174
  latestValue.current = value;
46138
- const sending = useRef17(false);
46139
- const [isSending2, setIsSending] = useState23(false);
46175
+ const sending = useRef18(false);
46176
+ const [isSending2, setIsSending] = useState24(false);
46140
46177
  void queueKey;
46141
46178
  const canSend = !isSending2 && (trimmed.length > 0 || hasAttachments) && (!isStreaming || queueWhileRunning && !hasAttachments && !isStopping);
46142
46179
  const handleSend = async () => {
@@ -46230,16 +46267,16 @@ function ChatInput({
46230
46267
  }
46231
46268
 
46232
46269
  // src/components/ConnectionBanner.tsx
46233
- import { useEffect as useEffect17, useRef as useRef18, useState as useState24 } from "react";
46270
+ import { useEffect as useEffect18, useRef as useRef19, useState as useState25 } from "react";
46234
46271
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
46235
46272
  var CONNECTION_NOTICE_DELAY_MS = 3e3;
46236
46273
  var CONNECTION_ERROR_DELAY_MS = 15e3;
46237
46274
  function useConnectionNoticePhase(connected) {
46238
- const [phase, setPhase] = useState24("hidden");
46239
- const connectedRef = useRef18(connected);
46240
- const timersRef = useRef18([]);
46275
+ const [phase, setPhase] = useState25("hidden");
46276
+ const connectedRef = useRef19(connected);
46277
+ const timersRef = useRef19([]);
46241
46278
  connectedRef.current = connected;
46242
- useEffect17(() => {
46279
+ useEffect18(() => {
46243
46280
  const clearTimers = () => {
46244
46281
  for (const timer of timersRef.current) clearTimeout(timer);
46245
46282
  timersRef.current = [];
@@ -46279,7 +46316,7 @@ function useConnectionNoticePhase(connected) {
46279
46316
  return phase;
46280
46317
  }
46281
46318
  function ConnectionBanner({ connection, className }) {
46282
- const hasConnectedRef = useRef18(connection === "connected" || connection === "reconnecting");
46319
+ const hasConnectedRef = useRef19(connection === "connected" || connection === "reconnecting");
46283
46320
  if (connection === "connected") hasConnectedRef.current = true;
46284
46321
  const connected = connection === "connected";
46285
46322
  const phase = useConnectionNoticePhase(connected);
@@ -46327,14 +46364,14 @@ function BackgroundWakeNotice() {
46327
46364
  import { isBackgroundWakeMessage, isHiddenInternalMessage as isHiddenInternalMessage2 } from "@blade-hq/agent-client";
46328
46365
  import {
46329
46366
  useCallback as useCallback29,
46330
- useEffect as useEffect25,
46367
+ useEffect as useEffect26,
46331
46368
  useMemo as useMemo16,
46332
- useRef as useRef27,
46333
- useState as useState33
46369
+ useRef as useRef28,
46370
+ useState as useState34
46334
46371
  } from "react";
46335
46372
 
46336
46373
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
46337
- import { useCallback as useCallback26, useMemo as useMemo12, useRef as useRef19, useState as useState25 } from "react";
46374
+ import { useCallback as useCallback26, useMemo as useMemo12, useRef as useRef20, useState as useState26 } from "react";
46338
46375
  var DEFAULT_SPRING_ANIMATION = {
46339
46376
  /**
46340
46377
  * A value from 0 to 1, on how much to damp the animation.
@@ -46371,10 +46408,10 @@ globalThis.document?.addEventListener("click", () => {
46371
46408
  mouseDown = false;
46372
46409
  });
46373
46410
  var useStickToBottom = (options = {}) => {
46374
- const [escapedFromLock, updateEscapedFromLock] = useState25(false);
46375
- const [isAtBottom, updateIsAtBottom] = useState25(options.initial !== false);
46376
- const [isNearBottom, setIsNearBottom] = useState25(false);
46377
- const optionsRef = useRef19(null);
46411
+ const [escapedFromLock, updateEscapedFromLock] = useState26(false);
46412
+ const [isAtBottom, updateIsAtBottom] = useState26(options.initial !== false);
46413
+ const [isNearBottom, setIsNearBottom] = useState26(false);
46414
+ const optionsRef = useRef20(null);
46378
46415
  optionsRef.current = options;
46379
46416
  const isSelecting = useCallback26(() => {
46380
46417
  if (!mouseDown) {
@@ -46678,11 +46715,11 @@ function mergeAnimations(...animations) {
46678
46715
 
46679
46716
  // ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/StickToBottom.js
46680
46717
  import * as React from "react";
46681
- import { createContext as createContext5, useContext as useContext5, useEffect as useEffect18, useImperativeHandle, useLayoutEffect as useLayoutEffect5, useMemo as useMemo13, useRef as useRef20 } from "react";
46718
+ import { createContext as createContext5, useContext as useContext5, useEffect as useEffect19, useImperativeHandle, useLayoutEffect as useLayoutEffect5, useMemo as useMemo13, useRef as useRef21 } from "react";
46682
46719
  var StickToBottomContext = createContext5(null);
46683
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect5 : useEffect18;
46720
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect5 : useEffect19;
46684
46721
  function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {
46685
- const customTargetScrollTop = useRef20(null);
46722
+ const customTargetScrollTop = useRef21(null);
46686
46723
  const targetScrollTop = React.useCallback((target, elements) => {
46687
46724
  const get = context?.targetScrollTop ?? currentTargetScrollTop;
46688
46725
  return get?.(target, elements) ?? target;
@@ -46761,23 +46798,23 @@ function useStickToBottomContext() {
46761
46798
  import { getServerTime } from "@blade-hq/agent-client/internal";
46762
46799
 
46763
46800
  // src/components/MessageImage.tsx
46764
- import { forwardRef as forwardRef3, useEffect as useEffect19, useImperativeHandle as useImperativeHandle2, useRef as useRef21, useState as useState26 } from "react";
46801
+ import { forwardRef as forwardRef3, useEffect as useEffect20, useImperativeHandle as useImperativeHandle2, useRef as useRef22, useState as useState27 } from "react";
46765
46802
  import { jsx as jsx16 } from "react/jsx-runtime";
46766
46803
  var assetPattern = /^\/api\/(sessions|share)\/([^/]+)\/media\/([a-f0-9]{64})$/;
46767
46804
  var MessageImage = forwardRef3(function MessageImage2({ client: suppliedClient, src, original = false, alt, style, ...props }, ref) {
46768
46805
  const contextClient = useOptionalBladeClient();
46769
46806
  const client = suppliedClient ?? contextClient;
46770
- const element2 = useRef21(null);
46807
+ const element2 = useRef22(null);
46771
46808
  useImperativeHandle2(ref, () => element2.current);
46772
- const [visible, setVisible] = useState26(false);
46773
- const [result, setResult] = useState26(null);
46809
+ const [visible, setVisible] = useState27(false);
46810
+ const [result, setResult] = useState27(null);
46774
46811
  const match = src?.match(assetPattern);
46775
46812
  const scope = match?.[1];
46776
46813
  const sessionId = match?.[2];
46777
46814
  const assetId = match?.[3];
46778
46815
  const identity2 = assetId && client ? client.buildAuthedUrl(src) : "";
46779
46816
  const source = `${src}:${original}:${identity2}`;
46780
- useEffect19(() => {
46817
+ useEffect20(() => {
46781
46818
  const node3 = element2.current;
46782
46819
  if (!node3 || !assetId) return;
46783
46820
  if (original || typeof IntersectionObserver === "undefined") {
@@ -46793,7 +46830,7 @@ var MessageImage = forwardRef3(function MessageImage2({ client: suppliedClient,
46793
46830
  observer.observe(node3);
46794
46831
  return () => observer.disconnect();
46795
46832
  }, [assetId, original]);
46796
- useEffect19(() => {
46833
+ useEffect20(() => {
46797
46834
  if (!visible || !client || !sessionId || !assetId) return;
46798
46835
  let alive = true;
46799
46836
  let objectUrl = null;
@@ -46833,10 +46870,10 @@ import {
46833
46870
  getTextContent as getTextContent2,
46834
46871
  normalizeMessageContent as normalizeMessageContent2
46835
46872
  } from "@blade-hq/agent-client";
46836
- import { useEffect as useEffect23, useRef as useRef25, useState as useState31 } from "react";
46873
+ import { useEffect as useEffect24, useRef as useRef26, useState as useState32 } from "react";
46837
46874
 
46838
46875
  // src/components/AgentTaskCard.tsx
46839
- import { useEffect as useEffect20, useState as useState27 } from "react";
46876
+ import { useEffect as useEffect21, useState as useState28 } from "react";
46840
46877
  import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
46841
46878
  var STATUS_LABELS = {
46842
46879
  running: "\u8FDB\u884C\u4E2D",
@@ -46847,8 +46884,8 @@ var STATUS_LABELS = {
46847
46884
  };
46848
46885
  function AgentTaskCard({ title, status, activity, children, className, recordId }) {
46849
46886
  const waiting = status === "waiting_input";
46850
- const [open2, setOpen] = useState27(waiting);
46851
- useEffect20(() => {
46887
+ const [open2, setOpen] = useState28(waiting);
46888
+ useEffect21(() => {
46852
46889
  if (waiting) setOpen(true);
46853
46890
  }, [waiting]);
46854
46891
  return /* @__PURE__ */ jsxs14(
@@ -46902,10 +46939,10 @@ function AgentLoopBlock({ toolCall, className }) {
46902
46939
  }
46903
46940
 
46904
46941
  // src/components/MarkdownContent.tsx
46905
- import { isValidElement as isValidElement2, useMemo as useMemo14, useRef as useRef23, useState as useState28 } from "react";
46942
+ import { isValidElement as isValidElement2, useMemo as useMemo14, useRef as useRef24, useState as useState29 } from "react";
46906
46943
 
46907
46944
  // src/components/markdown/index.ts
46908
- import { createElement as createElement7, useRef as useRef22 } from "react";
46945
+ import { createElement as createElement7, useRef as useRef23 } from "react";
46909
46946
 
46910
46947
  // ../../node_modules/.pnpm/mdast-util-to-string@4.0.0/node_modules/mdast-util-to-string/lib/index.js
46911
46948
  var emptyOptions = {};
@@ -55783,10 +55820,10 @@ function MarkdownRenderer({
55783
55820
  codeBlockOverrides
55784
55821
  }) {
55785
55822
  const isStreaming = mode === "streaming";
55786
- const cacheRef = useRef22(createParseCache());
55787
- const blockCacheRef = useRef22(/* @__PURE__ */ new WeakMap());
55788
- const groupIdentityMapRef = useRef22(/* @__PURE__ */ new WeakMap());
55789
- const rendererConfigRef = useRef22(null);
55823
+ const cacheRef = useRef23(createParseCache());
55824
+ const blockCacheRef = useRef23(/* @__PURE__ */ new WeakMap());
55825
+ const groupIdentityMapRef = useRef23(/* @__PURE__ */ new WeakMap());
55826
+ const rendererConfigRef = useRef23(null);
55790
55827
  const previousConfig = rendererConfigRef.current;
55791
55828
  if (!previousConfig || previousConfig.allowedTags !== allowedTags || previousConfig.components !== components || previousConfig.rawHtmlPlugins !== rawHtmlPlugins || previousConfig.codeBlockOverrides !== codeBlockOverrides) {
55792
55829
  blockCacheRef.current = /* @__PURE__ */ new WeakMap();
@@ -55871,8 +55908,8 @@ function normalizeAdjacentUrlFormatting(value) {
55871
55908
  return normalized.replace(/blade-url-protected-(\d+)-marker/g, (_2, index3) => protectedSegments[Number(index3)]);
55872
55909
  }
55873
55910
  function CodeBlockPre({ children, ...props }) {
55874
- const preRef = useRef23(null);
55875
- const [copied, setCopied] = useState28(false);
55911
+ const preRef = useRef24(null);
55912
+ const [copied, setCopied] = useState29(false);
55876
55913
  const codeChild = Array.isArray(children) ? children[0] : children;
55877
55914
  const codeClassName = isValidElement2(codeChild) ? codeChild.props.className : void 0;
55878
55915
  const language = codeClassName?.match(/language-(\S+)/)?.[1] ?? "";
@@ -55947,7 +55984,7 @@ function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
55947
55984
  }
55948
55985
 
55949
55986
  // src/components/AskUserQuestionBlock.tsx
55950
- import { useEffect as useEffect21, useMemo as useMemo15, useRef as useRef24, useState as useState29 } from "react";
55987
+ import { useEffect as useEffect22, useMemo as useMemo15, useRef as useRef25, useState as useState30 } from "react";
55951
55988
  import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
55952
55989
  var CUSTOM_TEXTAREA_MAX_HEIGHT = 160;
55953
55990
  function resizeCustomTextarea(textarea) {
@@ -55956,12 +55993,12 @@ function resizeCustomTextarea(textarea) {
55956
55993
  textarea.style.overflowY = textarea.scrollHeight > CUSTOM_TEXTAREA_MAX_HEIGHT ? "auto" : "hidden";
55957
55994
  }
55958
55995
  function useAutoResizeTextarea(value) {
55959
- const textareaRef = useRef24(null);
55960
- useEffect21(() => {
55996
+ const textareaRef = useRef25(null);
55997
+ useEffect22(() => {
55961
55998
  const textarea = textareaRef.current;
55962
55999
  if (textarea?.value === value) resizeCustomTextarea(textarea);
55963
56000
  }, [value]);
55964
- useEffect21(() => {
56001
+ useEffect22(() => {
55965
56002
  const textarea = textareaRef.current;
55966
56003
  if (!textarea || typeof ResizeObserver === "undefined") return;
55967
56004
  let previousWidth = textarea.clientWidth;
@@ -55988,12 +56025,12 @@ function AskUserQuestionBlock({
55988
56025
  className,
55989
56026
  optionClassName
55990
56027
  }) {
55991
- const [selections, setSelections] = useState29(/* @__PURE__ */ new Map());
55992
- const [customTexts, setCustomTexts] = useState29(/* @__PURE__ */ new Map());
55993
- const [usingCustom, setUsingCustom] = useState29(/* @__PURE__ */ new Set());
55994
- const [note, setNote] = useState29("");
55995
- const [submitted, setSubmitted] = useState29(false);
55996
- useEffect21(() => {
56028
+ const [selections, setSelections] = useState30(/* @__PURE__ */ new Map());
56029
+ const [customTexts, setCustomTexts] = useState30(/* @__PURE__ */ new Map());
56030
+ const [usingCustom, setUsingCustom] = useState30(/* @__PURE__ */ new Set());
56031
+ const [note, setNote] = useState30("");
56032
+ const [submitted, setSubmitted] = useState30(false);
56033
+ useEffect22(() => {
55997
56034
  if (sessionStatus === "failed" || sessionStatus === "interrupted") {
55998
56035
  setSubmitted(false);
55999
56036
  }
@@ -56501,7 +56538,7 @@ function buildAskUserPayload(argumentsJson) {
56501
56538
 
56502
56539
  // src/components/ToolUiCardView.tsx
56503
56540
  import { resolveToolUiCardContent } from "@blade-hq/agent-client";
56504
- import { useEffect as useEffect22, useState as useState30 } from "react";
56541
+ import { useEffect as useEffect23, useState as useState31 } from "react";
56505
56542
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
56506
56543
  function ToolUiCardView({ card, sessionId }) {
56507
56544
  if (card.mcpApp) return sessionId ? /* @__PURE__ */ jsx23(McpAppCard, { sessionId, sourceId: card.mcpApp.sourceId }) : null;
@@ -56528,10 +56565,10 @@ function ToolUiCardView({ card, sessionId }) {
56528
56565
  }
56529
56566
  function FileCard({ card, sessionId, path: path2 }) {
56530
56567
  const client = useBladeClient();
56531
- const [html, setHtml] = useState30(null);
56532
- const [failed, setFailed] = useState30(false);
56533
- const [refreshVersion, setRefreshVersion] = useState30(0);
56534
- useEffect22(() => {
56568
+ const [html, setHtml] = useState31(null);
56569
+ const [failed, setFailed] = useState31(false);
56570
+ const [refreshVersion, setRefreshVersion] = useState31(0);
56571
+ useEffect23(() => {
56535
56572
  const abort = new AbortController();
56536
56573
  setHtml(null);
56537
56574
  setFailed(false);
@@ -56597,7 +56634,7 @@ function ThinkingBlock({
56597
56634
  isStreaming,
56598
56635
  className
56599
56636
  }) {
56600
- const [open2, setOpen] = useState31(false);
56637
+ const [open2, setOpen] = useState32(false);
56601
56638
  if (!isStreaming) return null;
56602
56639
  return /* @__PURE__ */ jsxs19("div", { part: "thinking", className: cn("blade-chat-thinking ml-4 text-xs", className), children: [
56603
56640
  /* @__PURE__ */ jsxs19(
@@ -56686,6 +56723,8 @@ function getExecutionDurationMs({
56686
56723
  isStreaming,
56687
56724
  now = null
56688
56725
  }) {
56726
+ const runDuration = getChatRunDuration(messages, isStreaming ? now : null);
56727
+ if (runDuration !== null) return runDuration;
56689
56728
  const knownDuration = messages.reduce(
56690
56729
  (total, message) => {
56691
56730
  if (typeof message.duration_ms === "number" && message.duration_ms > 0) {
@@ -56877,12 +56916,12 @@ function AssistantTurnBlock({
56877
56916
  )
56878
56917
  );
56879
56918
  const activeQuestionId = questionToolCalls.filter((toolCall) => toolCall.status === "pending").at(-1)?.id;
56880
- const [displayMode, setDisplayMode] = useState31(
56919
+ const [displayMode, setDisplayMode] = useState32(
56881
56920
  () => isStreaming || hasActionableToolCall ? "detail" : "compact"
56882
56921
  );
56883
- const userSelectedDisplayModeRef = useRef25(false);
56884
- const wasStreamingRef = useRef25(isStreaming);
56885
- useEffect23(() => {
56922
+ const userSelectedDisplayModeRef = useRef26(false);
56923
+ const wasStreamingRef = useRef26(isStreaming);
56924
+ useEffect24(() => {
56886
56925
  if (wasStreamingRef.current && !isStreaming && !userSelectedDisplayModeRef.current) {
56887
56926
  setDisplayMode(hasActionableToolCall ? "detail" : "compact");
56888
56927
  }
@@ -56890,22 +56929,23 @@ function AssistantTurnBlock({
56890
56929
  }, [hasActionableToolCall, isStreaming]);
56891
56930
  const effectiveMode = resolveTurnDisplayMode({ isStreaming, displayMode });
56892
56931
  const client = useOptionalBladeClient();
56893
- const executionDurationMs = getExecutionDurationMs({ messages, isStreaming });
56894
- const [clock, setClock] = useState31(() => performance.now());
56895
- const hasLiveStartTime = messages.some(
56896
- (message) => message.timestamp != null && Number.isFinite(Date.parse(message.timestamp))
56897
- );
56898
- useEffect23(() => {
56899
- if (!isStreaming || !hasLiveStartTime) return;
56900
- const timer = window.setInterval(() => setClock(performance.now()), 1e3);
56901
- return () => window.clearInterval(timer);
56902
- }, [hasLiveStartTime, isStreaming]);
56903
- const liveExecutionDurationMs = isStreaming ? getExecutionDurationMs({
56932
+ const clockNow = isStreaming ? sessionId ? getServerTime(client) : Date.now() : null;
56933
+ const executionDurationMs = getExecutionDurationMs({
56904
56934
  messages,
56905
56935
  isStreaming,
56906
- // Direct LLM mode has no Blade session and generates its own local timestamps.
56907
- now: sessionId ? getServerTime(client, clock) : Date.now()
56908
- }) : executionDurationMs;
56936
+ now: clockNow
56937
+ });
56938
+ const chatRun = getChatRun(messages);
56939
+ const isTimerRunning = isStreaming && (!chatRun || chatRun.status === "incomplete");
56940
+ const runningDurationMs = useLiveExecutionDuration({
56941
+ turnKey: `${sessionId ?? ""}:${messages[0]?.entry_id ?? ""}:${chatRun?.run_id ?? ""}`,
56942
+ isStreaming: isTimerRunning,
56943
+ initialDurationMs: executionDurationMs,
56944
+ isInitialDurationReady: clockNow !== null && messages.some(
56945
+ (message) => message.chat_run?.started_at != null && Number.isFinite(Date.parse(message.chat_run.started_at)) || message.chat_run == null && message.timestamp != null && Number.isFinite(Date.parse(message.timestamp))
56946
+ )
56947
+ });
56948
+ const liveExecutionDurationMs = isTimerRunning ? runningDurationMs : executionDurationMs;
56909
56949
  const memoryRefs = collectMemoryRefs(messages);
56910
56950
  const inlineToolUiCards = collectInlineToolUiCards(messages);
56911
56951
  if (!hasExecutionProcess) {
@@ -57112,7 +57152,7 @@ function collectMemoryRefs(messages) {
57112
57152
  return [...refs.values()];
57113
57153
  }
57114
57154
  function MemoryRefsHint({ refs, className }) {
57115
- const [expanded, setExpanded] = useState31(false);
57155
+ const [expanded, setExpanded] = useState32(false);
57116
57156
  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";
57117
57157
  return /* @__PURE__ */ jsxs19("div", { part: "memory-refs", className: cn("blade-chat-memory-refs ml-1 w-full max-w-[680px]", className), children: [
57118
57158
  /* @__PURE__ */ jsxs19("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: [
@@ -57258,7 +57298,7 @@ var RenderErrorBoundary = class extends Component2 {
57258
57298
  };
57259
57299
 
57260
57300
  // src/components/PostChatFollowupBlock.tsx
57261
- import { useCallback as useCallback28, useEffect as useEffect24, useRef as useRef26, useState as useState32 } from "react";
57301
+ import { useCallback as useCallback28, useEffect as useEffect25, useRef as useRef27, useState as useState33 } from "react";
57262
57302
  import { Fragment as Fragment8, jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
57263
57303
  function emitInteraction(callback, event) {
57264
57304
  try {
@@ -57278,7 +57318,7 @@ function ArtifactCard({
57278
57318
  onArtifactOpened
57279
57319
  }) {
57280
57320
  const client = useBladeClient();
57281
- const [downloading, setDownloading] = useState32(false);
57321
+ const [downloading, setDownloading] = useState33(false);
57282
57322
  const name = artifact.label || basename(artifact.target);
57283
57323
  if (artifact.kind === "link") {
57284
57324
  return /* @__PURE__ */ jsxs21(
@@ -57384,15 +57424,15 @@ function ResultFeedback({
57384
57424
  onFeedbackSaved
57385
57425
  }) {
57386
57426
  const client = useBladeClient();
57387
- const [saved, setSaved] = useState32(savedFeedback ?? null);
57388
- const [helpful, setHelpful] = useState32(savedFeedback?.helpful ?? null);
57389
- const [reason, setReason] = useState32(savedFeedback?.reason ?? null);
57390
- const [saving, setSaving] = useState32(false);
57391
- const [saveError, setSaveError] = useState32(false);
57392
- const reportedShown = useRef26(false);
57393
- const latestChoice = useRef26(null);
57427
+ const [saved, setSaved] = useState33(savedFeedback ?? null);
57428
+ const [helpful, setHelpful] = useState33(savedFeedback?.helpful ?? null);
57429
+ const [reason, setReason] = useState33(savedFeedback?.reason ?? null);
57430
+ const [saving, setSaving] = useState33(false);
57431
+ const [saveError, setSaveError] = useState33(false);
57432
+ const reportedShown = useRef27(false);
57433
+ const latestChoice = useRef27(null);
57394
57434
  const eligible = followup.feedback_eligible === true && Boolean(sessionId) && !isViewer;
57395
- useEffect24(() => {
57435
+ useEffect25(() => {
57396
57436
  if (!eligible || reportedShown.current) return;
57397
57437
  reportedShown.current = true;
57398
57438
  emitInteraction(onInteraction, {
@@ -57401,7 +57441,7 @@ function ResultFeedback({
57401
57441
  assistantEntryId: followup.assistant_entry_id
57402
57442
  });
57403
57443
  }, [eligible, followup.assistant_entry_id, onInteraction, sessionId]);
57404
- useEffect24(() => {
57444
+ useEffect25(() => {
57405
57445
  if (!savedFeedback || latestChoice.current) return;
57406
57446
  setSaved(savedFeedback);
57407
57447
  setHelpful(savedFeedback.helpful);
@@ -57515,14 +57555,14 @@ function PostChatFollowupBlock({
57515
57555
  className,
57516
57556
  suggestionClassName
57517
57557
  }) {
57518
- const [expanded, setExpanded] = useState32(false);
57519
- const adopted = useRef26(/* @__PURE__ */ new Set());
57520
- const reportedSuggestions = useRef26(false);
57521
- const reportedArtifacts = useRef26(/* @__PURE__ */ new Set());
57522
- const openedArtifacts = useRef26(/* @__PURE__ */ new Set());
57558
+ const [expanded, setExpanded] = useState33(false);
57559
+ const adopted = useRef27(/* @__PURE__ */ new Set());
57560
+ const reportedSuggestions = useRef27(false);
57561
+ const reportedArtifacts = useRef27(/* @__PURE__ */ new Set());
57562
+ const openedArtifacts = useRef27(/* @__PURE__ */ new Set());
57523
57563
  const artifacts = followup.final_artifacts ?? [];
57524
57564
  const visibleArtifacts = expanded ? artifacts : artifacts.slice(0, 3);
57525
- useEffect24(() => {
57565
+ useEffect25(() => {
57526
57566
  if (!reportedSuggestions.current && followup.suggestions.length > 0) {
57527
57567
  reportedSuggestions.current = true;
57528
57568
  emitInteraction(onInteraction, {
@@ -57899,10 +57939,10 @@ function MessageList({
57899
57939
  const contentReveal = useTypewriterReveal(revealContentText, isRevealLive, revealTargetKey);
57900
57940
  const reasoningReveal = useTypewriterReveal(revealReasoningText, isRevealLive, revealTargetKey);
57901
57941
  const isRevealingAny = contentReveal.isRevealing || reasoningReveal.isRevealing;
57902
- useEffect25(() => {
57942
+ useEffect26(() => {
57903
57943
  onRevealingChange?.(isRevealingAny);
57904
57944
  }, [isRevealingAny, onRevealingChange]);
57905
- useEffect25(() => {
57945
+ useEffect26(() => {
57906
57946
  if (isStopping) {
57907
57947
  contentReveal.flushNow();
57908
57948
  reasoningReveal.flushNow();
@@ -57989,8 +58029,8 @@ function MessageList({
57989
58029
  }
57990
58030
  return blocks;
57991
58031
  }, [visibleRootMessages, isStreaming, isRevealingAny]);
57992
- const rootRef = useRef27(null);
57993
- const stopAutoScrollRef = useRef27(null);
58032
+ const rootRef = useRef28(null);
58033
+ const stopAutoScrollRef = useRef28(null);
57994
58034
  const {
57995
58035
  items: turnNavItems,
57996
58036
  activeEntryId: activeNavTurnId,
@@ -58010,7 +58050,7 @@ function MessageList({
58010
58050
  isEntryLoaded: (entryId) => findEntryRow(rootRef.current, entryId) !== null,
58011
58051
  beforeSeek: () => stopAutoScrollRef.current?.()
58012
58052
  });
58013
- const [viewportNavTurnId, setViewportNavTurnId] = useState33(null);
58053
+ const [viewportNavTurnId, setViewportNavTurnId] = useState34(null);
58014
58054
  const latestNavTurnId = turnNavItems.at(-1)?.id ?? null;
58015
58055
  return /* @__PURE__ */ jsxs24(
58016
58056
  "div",
@@ -58164,10 +58204,10 @@ function LoadOlderSentinel({
58164
58204
  loadOlder
58165
58205
  }) {
58166
58206
  const { contentRef, scrollRef } = useStickToBottomContext();
58167
- const sentinelRef = useRef27(null);
58168
- const stateRef = useRef27({ hasOlder, loading, loadOlder });
58207
+ const sentinelRef = useRef28(null);
58208
+ const stateRef = useRef28({ hasOlder, loading, loadOlder });
58169
58209
  stateRef.current = { hasOlder, loading, loadOlder };
58170
- useEffect25(() => {
58210
+ useEffect26(() => {
58171
58211
  const sentinel = sentinelRef.current;
58172
58212
  const scroller = scrollRef.current;
58173
58213
  if (!sentinel || !scroller || typeof IntersectionObserver === "undefined") return;
@@ -58235,8 +58275,8 @@ function PinLatestUserMessage({
58235
58275
  targetKey
58236
58276
  }) {
58237
58277
  const { contentRef, scrollRef, scrollToBottom, stopScroll } = useStickToBottomContext();
58238
- const previousCountRef = useRef27(userMessageCount);
58239
- const spacerHeightRef = useRef27(0);
58278
+ const previousCountRef = useRef28(userMessageCount);
58279
+ const spacerHeightRef = useRef28(0);
58240
58280
  const getScrollElement = useCallback29(() => scrollRef.current, [scrollRef]);
58241
58281
  const getContentElement = useCallback29(() => contentRef.current, [contentRef]);
58242
58282
  const getTargetElement = useCallback29(() => {
@@ -58278,7 +58318,7 @@ function PinLatestUserMessage({
58278
58318
  stopAutoScroll: stopScroll,
58279
58319
  scrollToBottom
58280
58320
  });
58281
- useEffect25(() => {
58321
+ useEffect26(() => {
58282
58322
  if (userMessageCount > previousCountRef.current && !shouldPinLatestUser) {
58283
58323
  scrollToBottom("instant");
58284
58324
  }
@@ -58288,9 +58328,9 @@ function PinLatestUserMessage({
58288
58328
  }
58289
58329
  function ScrollToBottomButton({ className }) {
58290
58330
  const { isAtBottom, scrollToBottom } = useStickToBottomContext();
58291
- const [visible, setVisible] = useState33(false);
58292
- const hideTimerRef = useRef27(null);
58293
- useEffect25(() => {
58331
+ const [visible, setVisible] = useState34(false);
58332
+ const hideTimerRef = useRef28(null);
58333
+ useEffect26(() => {
58294
58334
  if (isAtBottom) {
58295
58335
  if (!hideTimerRef.current) {
58296
58336
  hideTimerRef.current = setTimeout(() => {
@@ -58362,13 +58402,13 @@ function ViewportTurnBridge({
58362
58402
  onActiveChange
58363
58403
  }) {
58364
58404
  const { scrollRef } = useStickToBottomContext();
58365
- const itemsRef = useRef27(items);
58366
- const updateRef = useRef27(null);
58367
- useEffect25(() => {
58405
+ const itemsRef = useRef28(items);
58406
+ const updateRef = useRef28(null);
58407
+ useEffect26(() => {
58368
58408
  itemsRef.current = items;
58369
58409
  updateRef.current?.();
58370
58410
  }, [items]);
58371
- useEffect25(() => {
58411
+ useEffect26(() => {
58372
58412
  const scroller = scrollRef.current;
58373
58413
  const root = rootRef.current;
58374
58414
  if (!scroller || !root) return;
@@ -58412,7 +58452,7 @@ function ViewportTurnBridge({
58412
58452
  var VIEWPORT_ACTIVE_OFFSET = 8;
58413
58453
  function StopAutoScrollBridge({ stopRef }) {
58414
58454
  const { stopScroll } = useStickToBottomContext();
58415
- useEffect25(() => {
58455
+ useEffect26(() => {
58416
58456
  stopRef.current = stopScroll;
58417
58457
  return () => {
58418
58458
  stopRef.current = null;
@@ -58462,7 +58502,7 @@ function ChatSurface({
58462
58502
  onRevealingChange,
58463
58503
  isReplay
58464
58504
  }) {
58465
- const [pending, setPending] = useState34([]);
58505
+ const [pending, setPending] = useState35([]);
58466
58506
  const currentPending = pending.filter((item) => item.sessionId === sessionId);
58467
58507
  const sendWithApps = async (text4) => {
58468
58508
  const content3 = [...currentPending.map((item) => `[${item.label}]
@@ -58584,8 +58624,8 @@ function isUnauthorizedError(error61) {
58584
58624
  return error61 instanceof BladeApiError2 && error61.status === 401;
58585
58625
  }
58586
58626
  function LoginCard({ client, onLoggedIn }) {
58587
- const [loggingIn, setLoggingIn] = useState35(false);
58588
- const [loginError, setLoginError] = useState35(null);
58627
+ const [loggingIn, setLoggingIn] = useState36(false);
58628
+ const [loginError, setLoginError] = useState36(null);
58589
58629
  const handleLogin = async () => {
58590
58630
  setLoggingIn(true);
58591
58631
  setLoginError(null);
@@ -58617,8 +58657,8 @@ function LoginCard({ client, onLoggedIn }) {
58617
58657
  }
58618
58658
  function AgentChat(props) {
58619
58659
  const client = useBladeClient();
58620
- const [attempt, setAttempt] = useState35(0);
58621
- const [needLogin, setNeedLogin] = useState35(() => !client.hasToken());
58660
+ const [attempt, setAttempt] = useState36(0);
58661
+ const [needLogin, setNeedLogin] = useState36(() => !client.hasToken());
58622
58662
  if (needLogin) {
58623
58663
  return /* @__PURE__ */ jsx31(
58624
58664
  "div",
@@ -58657,7 +58697,7 @@ function ChatSessionView({
58657
58697
  onUnauthorized
58658
58698
  }) {
58659
58699
  const client = useBladeClient();
58660
- const [planRevealRevisions, setPlanRevealRevisions] = useState35(
58700
+ const [planRevealRevisions, setPlanRevealRevisions] = useState36(
58661
58701
  () => /* @__PURE__ */ new Map()
58662
58702
  );
58663
58703
  const handleSessionConnected = useCallback30((connectedSession) => {
@@ -58678,24 +58718,24 @@ function ChatSessionView({
58678
58718
  onSessionConnected: handleSessionConnected
58679
58719
  });
58680
58720
  const replay = useReplay(session);
58681
- const [stopRequested, setStopRequested] = useState35(false);
58682
- const [isRevealing, setIsRevealing] = useState35(false);
58683
- const [inputText, setInputText] = useState35("");
58684
- const [queueNotice, setQueueNotice] = useState35(null);
58685
- const [queuePendingItemId, setQueuePendingItemId] = useState35(null);
58686
- const [queuePanelVisible, setQueuePanelVisible] = useState35(false);
58687
- const [resultFeedback, setResultFeedback] = useState35([]);
58688
- const [timelineRewrite, setTimelineRewrite] = useState35(0);
58721
+ const [stopRequested, setStopRequested] = useState36(false);
58722
+ const [isRevealing, setIsRevealing] = useState36(false);
58723
+ const [inputText, setInputText] = useState36("");
58724
+ const [queueNotice, setQueueNotice] = useState36(null);
58725
+ const [queuePendingItemId, setQueuePendingItemId] = useState36(null);
58726
+ const [queuePanelVisible, setQueuePanelVisible] = useState36(false);
58727
+ const [resultFeedback, setResultFeedback] = useState36([]);
58728
+ const [timelineRewrite, setTimelineRewrite] = useState36(0);
58689
58729
  const resolvedSessionId = session?.sessionId;
58690
58730
  const isViewer = state?.viewerRole === "viewer";
58691
58731
  const canUseQueue = !isViewer;
58692
- const onSessionReadyRef = useRef28(onSessionReady);
58693
- const readySessionRef = useRef28(null);
58732
+ const onSessionReadyRef = useRef29(onSessionReady);
58733
+ const readySessionRef = useRef29(null);
58694
58734
  const hasOnSessionReady = onSessionReady !== void 0;
58695
- useEffect26(() => {
58735
+ useEffect27(() => {
58696
58736
  onSessionReadyRef.current = onSessionReady;
58697
58737
  }, [onSessionReady]);
58698
- useEffect26(() => {
58738
+ useEffect27(() => {
58699
58739
  setResultFeedback([]);
58700
58740
  if (!resolvedSessionId || isViewer) return;
58701
58741
  let cancelled = false;
@@ -58730,13 +58770,13 @@ function ChatSessionView({
58730
58770
  saved
58731
58771
  ]);
58732
58772
  }, []);
58733
- useEffect26(() => {
58773
+ useEffect27(() => {
58734
58774
  const handler = onSessionReadyRef.current;
58735
58775
  if (!session || !hasOnSessionReady || !handler || readySessionRef.current === session) return;
58736
58776
  readySessionRef.current = session;
58737
58777
  handler(session);
58738
58778
  }, [session, hasOnSessionReady]);
58739
- useEffect26(() => {
58779
+ useEffect27(() => {
58740
58780
  if (!session) return;
58741
58781
  const offAttach = session.on("attachRequested", ({ label, content: content3 }) => {
58742
58782
  setInputText((prev) => `${prev ? `${prev}
@@ -58756,12 +58796,12 @@ ${content3}`);
58756
58796
  offRewind();
58757
58797
  };
58758
58798
  }, [session]);
58759
- useEffect26(() => {
58799
+ useEffect27(() => {
58760
58800
  if (isUnauthorizedError(error61)) {
58761
58801
  onUnauthorized();
58762
58802
  }
58763
58803
  }, [error61, onUnauthorized]);
58764
- useEffect26(() => {
58804
+ useEffect27(() => {
58765
58805
  if (!session || !commands) return;
58766
58806
  const unsubscribes = Object.entries(commands).map(
58767
58807
  ([action, handler]) => session.onCommand(action, (payload) => handler(payload))
@@ -58933,10 +58973,10 @@ ${content3}`);
58933
58973
  }
58934
58974
 
58935
58975
  // src/components/LlmChat.tsx
58936
- import { useEffect as useEffect27, useMemo as useMemo19, useState as useState37 } from "react";
58976
+ import { useEffect as useEffect28, useMemo as useMemo19, useState as useState38 } from "react";
58937
58977
 
58938
58978
  // src/components/LlmAdvancedSettings.tsx
58939
- import { useState as useState36 } from "react";
58979
+ import { useState as useState37 } from "react";
58940
58980
  import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
58941
58981
  var FIELDS = [
58942
58982
  { id: "baseURL", label: "\u6A21\u578B\u670D\u52A1\u5730\u5740", placeholder: "http://\u5185\u7F51\u5730\u5740/v1" },
@@ -58983,8 +59023,8 @@ function writeOverride(settings, baseURL, override) {
58983
59023
  }
58984
59024
  function LlmAdvancedSettingsBar({ settings, defaults: defaults2, override, onChange }) {
58985
59025
  const normalized = normalizeAdvanced(settings);
58986
- const [open2, setOpen] = useState36(false);
58987
- const [draft, setDraft] = useState36(override);
59026
+ const [open2, setOpen] = useState37(false);
59027
+ const [draft, setDraft] = useState37(override);
58988
59028
  if (!normalized) return null;
58989
59029
  const fields2 = FIELDS.filter((field) => normalized[field.id]);
58990
59030
  const dirty = Object.keys(override).length > 0;
@@ -59067,12 +59107,12 @@ function LlmChat({
59067
59107
  onOverrideChange,
59068
59108
  ...options
59069
59109
  }) {
59070
- const [override, setOverride] = useState37(() => readOverride(advanced, options.baseURL));
59110
+ const [override, setOverride] = useState38(() => readOverride(advanced, options.baseURL));
59071
59111
  const effective = { ...options, ...override };
59072
59112
  const { messages, isStreaming, error: error61, send, stop, reset } = useLlmChat(effective);
59073
- const [inputText, setInputText] = useState37("");
59074
- const [stopRequested, setStopRequested] = useState37(false);
59075
- const [isRevealing, setIsRevealing] = useState37(false);
59113
+ const [inputText, setInputText] = useState38("");
59114
+ const [stopRequested, setStopRequested] = useState38(false);
59115
+ const [isRevealing, setIsRevealing] = useState38(false);
59076
59116
  const isStreamingDisplay = isStreaming || isRevealing;
59077
59117
  const handle = useMemo19(
59078
59118
  () => ({
@@ -59083,7 +59123,7 @@ ${text4}` : text4),
59083
59123
  }),
59084
59124
  [send, reset]
59085
59125
  );
59086
- useEffect27(() => {
59126
+ useEffect28(() => {
59087
59127
  onReady?.(handle);
59088
59128
  }, [handle, onReady]);
59089
59129
  return /* @__PURE__ */ jsx33(
@@ -59154,7 +59194,7 @@ function ChatView(props) {
59154
59194
  }
59155
59195
 
59156
59196
  // src/components/ConnectorPanel.tsx
59157
- import { useCallback as useCallback31, useEffect as useEffect28, useMemo as useMemo20, useRef as useRef29, useState as useState38 } from "react";
59197
+ import { useCallback as useCallback31, useEffect as useEffect29, useMemo as useMemo20, useRef as useRef30, useState as useState39 } from "react";
59158
59198
 
59159
59199
  // src/components/connector-panel-types.ts
59160
59200
  function selectionFromItem(item) {
@@ -59194,12 +59234,13 @@ function ConnectorPanel({
59194
59234
  renderComputerSection,
59195
59235
  renderExternalAccounts,
59196
59236
  renderFooterActions,
59237
+ visibleSections = ["plugins", "computers", "accounts"],
59197
59238
  className
59198
59239
  }) {
59199
- const [query, setQuery] = useState38("");
59200
- const [pendingCatalog, setPendingCatalog] = useState38(null);
59201
- const [pendingLoading, setPendingLoading] = useState38(false);
59202
- const [pendingError, setPendingError] = useState38(false);
59240
+ const [query, setQuery] = useState39("");
59241
+ const [pendingCatalog, setPendingCatalog] = useState39(null);
59242
+ const [pendingLoading, setPendingLoading] = useState39(false);
59243
+ const [pendingError, setPendingError] = useState39(false);
59203
59244
  const activation = useSessionPluginActivation({
59204
59245
  client,
59205
59246
  // 首页不会走这个分支:待选在下面自己处理开关,不碰会话接口。
@@ -59207,7 +59248,7 @@ function ConnectorPanel({
59207
59248
  onChange: onPluginsChanged
59208
59249
  });
59209
59250
  const { reload, items: sessionItems } = activation;
59210
- useEffect28(() => {
59251
+ useEffect29(() => {
59211
59252
  if (sessionId) reload();
59212
59253
  }, [reload, sessionId]);
59213
59254
  const loadPendingCatalog = useCallback31(async () => {
@@ -59222,7 +59263,7 @@ function ConnectorPanel({
59222
59263
  setPendingLoading(false);
59223
59264
  }
59224
59265
  }, [client]);
59225
- useEffect28(() => {
59266
+ useEffect29(() => {
59226
59267
  if (sessionId) return;
59227
59268
  void loadPendingCatalog();
59228
59269
  }, [loadPendingCatalog, sessionId]);
@@ -59253,15 +59294,15 @@ function ConnectorPanel({
59253
59294
  () => items.filter((item) => item.active),
59254
59295
  [items]
59255
59296
  );
59256
- const onSelectedChangeRef = useRef29(onSelectedChange);
59297
+ const onSelectedChangeRef = useRef30(onSelectedChange);
59257
59298
  onSelectedChangeRef.current = onSelectedChange;
59258
- const latestSelected = useRef29(selectedItems);
59299
+ const latestSelected = useRef30(selectedItems);
59259
59300
  latestSelected.current = selectedItems;
59260
59301
  const reportSelected = useCallback31(() => {
59261
59302
  onSelectedChangeRef.current?.(latestSelected.current);
59262
59303
  }, []);
59263
59304
  const selectedNames = selectedItems.map((item) => item.name).join("\0");
59264
- useEffect28(reportSelected, [reportSelected, selectedNames]);
59305
+ useEffect29(reportSelected, [reportSelected, selectedNames]);
59265
59306
  const failed = sessionId ? activation.listError : pendingError;
59266
59307
  return /* @__PURE__ */ jsxs28("div", { className, children: [
59267
59308
  /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2 border-[hsl(var(--border))] border-b px-3 py-2", children: [
@@ -59277,52 +59318,54 @@ function ConnectorPanel({
59277
59318
  }
59278
59319
  )
59279
59320
  ] }),
59280
- renderComputerSection ? /* @__PURE__ */ jsxs28(Fragment10, { children: [
59321
+ visibleSections.includes("computers") && renderComputerSection ? /* @__PURE__ */ jsxs28(Fragment10, { children: [
59281
59322
  /* @__PURE__ */ jsx35(PanelTitle, { children: "\u7535\u8111" }),
59282
59323
  renderComputerSection(query)
59283
59324
  ] }) : null,
59284
- /* @__PURE__ */ jsx35(PanelDivider, {}),
59285
- /* @__PURE__ */ jsx35(PanelTitle, { children: "\u63D2\u4EF6" }),
59286
- !sessionId ? (
59287
- // 首页没有会话,开关只记下「这条消息要带上谁」:不说清楚,用户会以为已经
59288
- // 生效(issue 明确要求「明确为待选,不宣称已经激活」)。
59289
- /* @__PURE__ */ jsx35("div", { className: "px-3 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: "\u5148\u9009\u4E2D\uFF0C\u53D1\u9001\u8FD9\u6761\u6D88\u606F\u65F6\u4F1A\u4E00\u5E76\u542F\u7528" })
59290
- ) : null,
59291
- (sessionId ? activation.loading : pendingLoading) && visibleItems.length === 0 ? /* @__PURE__ */ jsxs28("div", { className: "px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
59292
- /* @__PURE__ */ jsx35(LoaderCircle, { size: 12, className: "mr-1 inline animate-spin" }),
59293
- "\u6B63\u5728\u83B7\u53D6\u63D2\u4EF6\u2026"
59325
+ visibleSections.includes("plugins") ? /* @__PURE__ */ jsxs28(Fragment10, { children: [
59326
+ /* @__PURE__ */ jsx35(PanelDivider, {}),
59327
+ /* @__PURE__ */ jsx35(PanelTitle, { children: "\u63D2\u4EF6" }),
59328
+ !sessionId ? (
59329
+ // 首页没有会话,开关只记下「这条消息要带上谁」:不说清楚,用户会以为已经
59330
+ // 生效(issue 明确要求「明确为待选,不宣称已经激活」)。
59331
+ /* @__PURE__ */ jsx35("div", { className: "px-3 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: "\u5148\u9009\u4E2D\uFF0C\u53D1\u9001\u8FD9\u6761\u6D88\u606F\u65F6\u4F1A\u4E00\u5E76\u542F\u7528" })
59332
+ ) : null,
59333
+ (sessionId ? activation.loading : pendingLoading) && visibleItems.length === 0 ? /* @__PURE__ */ jsxs28("div", { className: "px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
59334
+ /* @__PURE__ */ jsx35(LoaderCircle, { size: 12, className: "mr-1 inline animate-spin" }),
59335
+ "\u6B63\u5728\u83B7\u53D6\u63D2\u4EF6\u2026"
59336
+ ] }) : null,
59337
+ failed ? /* @__PURE__ */ jsx35(
59338
+ "button",
59339
+ {
59340
+ type: "button",
59341
+ onClick: () => sessionId ? reload() : void loadPendingCatalog(),
59342
+ className: "px-3 py-1.5 text-left text-[11px] text-[hsl(var(--muted-foreground))] underline",
59343
+ children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5"
59344
+ }
59345
+ ) : null,
59346
+ /* @__PURE__ */ jsx35(
59347
+ PluginConnectorList,
59348
+ {
59349
+ client,
59350
+ sessionId,
59351
+ items: visibleItems,
59352
+ inFlight: activation.inFlight,
59353
+ busy: sessionId ? activation.busy : pendingLoading,
59354
+ mutationError: sessionId ? activation.mutationError : false,
59355
+ onToggle: toggle,
59356
+ onRetry: activation.retry,
59357
+ onEditConfig: activation.editConfig,
59358
+ configuring: sessionId ? activation.configuring : null,
59359
+ onConfigSaved: activation.onConfigSaved,
59360
+ onConfigClose: activation.onConfigClose,
59361
+ disabledReason: sessionId ? null : pendingDisabledReason,
59362
+ unavailableText: failed ? null : query.trim() ? "\u6CA1\u6709\u5339\u914D\u7684\u63D2\u4EF6" : null,
59363
+ emptyText: sessionId ? "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6" : "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6\uFF0C\u53BB\u5E94\u7528\u5E02\u573A\u6DFB\u52A0\u4E00\u4E2A",
59364
+ draft: !sessionId
59365
+ }
59366
+ )
59294
59367
  ] }) : null,
59295
- failed ? /* @__PURE__ */ jsx35(
59296
- "button",
59297
- {
59298
- type: "button",
59299
- onClick: () => sessionId ? reload() : void loadPendingCatalog(),
59300
- className: "px-3 py-1.5 text-left text-[11px] text-[hsl(var(--muted-foreground))] underline",
59301
- children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5"
59302
- }
59303
- ) : null,
59304
- /* @__PURE__ */ jsx35(
59305
- PluginConnectorList,
59306
- {
59307
- client,
59308
- sessionId,
59309
- items: visibleItems,
59310
- inFlight: activation.inFlight,
59311
- busy: sessionId ? activation.busy : pendingLoading,
59312
- mutationError: sessionId ? activation.mutationError : false,
59313
- onToggle: toggle,
59314
- onRetry: activation.retry,
59315
- onEditConfig: activation.editConfig,
59316
- configuring: sessionId ? activation.configuring : null,
59317
- onConfigSaved: activation.onConfigSaved,
59318
- onConfigClose: activation.onConfigClose,
59319
- disabledReason: sessionId ? null : pendingDisabledReason,
59320
- unavailableText: failed ? null : query.trim() ? "\u6CA1\u6709\u5339\u914D\u7684\u63D2\u4EF6" : null,
59321
- emptyText: sessionId ? "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6" : "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6\uFF0C\u53BB\u5E94\u7528\u5E02\u573A\u6DFB\u52A0\u4E00\u4E2A",
59322
- draft: !sessionId
59323
- }
59324
- ),
59325
- renderExternalAccounts ? /* @__PURE__ */ jsxs28(Fragment10, { children: [
59368
+ visibleSections.includes("accounts") && renderExternalAccounts ? /* @__PURE__ */ jsxs28(Fragment10, { children: [
59326
59369
  /* @__PURE__ */ jsx35(PanelDivider, {}),
59327
59370
  /* @__PURE__ */ jsx35(PanelTitle, { children: "\u5916\u90E8\u8D26\u53F7" }),
59328
59371
  renderExternalAccounts(query)
@@ -59473,7 +59516,7 @@ function ContextGroupCard({ contexts, className }) {
59473
59516
  }
59474
59517
 
59475
59518
  // src/components/SessionMemoryToggle.tsx
59476
- import { useCallback as useCallback32, useEffect as useEffect29, useRef as useRef30, useState as useState39, useSyncExternalStore as useSyncExternalStore2 } from "react";
59519
+ import { useCallback as useCallback32, useEffect as useEffect30, useRef as useRef31, useState as useState40, useSyncExternalStore as useSyncExternalStore2 } from "react";
59477
59520
  import { jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
59478
59521
  var saveStates = /* @__PURE__ */ new WeakMap();
59479
59522
  function getSaveState(client, sessionId) {
@@ -59531,10 +59574,10 @@ function SessionMemoryToggle({
59531
59574
  getSaving,
59532
59575
  getSaving
59533
59576
  );
59534
- const [draftEnabled, setDraftEnabled] = useState39(enabled);
59535
- const activeSessionIdRef = useRef30(sessionId);
59577
+ const [draftEnabled, setDraftEnabled] = useState40(enabled);
59578
+ const activeSessionIdRef = useRef31(sessionId);
59536
59579
  activeSessionIdRef.current = sessionId;
59537
- useEffect29(() => {
59580
+ useEffect30(() => {
59538
59581
  setDraftEnabled(enabled);
59539
59582
  }, [enabled, sessionId]);
59540
59583
  const update = useCallback32(
@@ -63103,7 +63146,7 @@ var Portal2 = TooltipPortal;
63103
63146
  var Content2 = TooltipContent;
63104
63147
 
63105
63148
  // src/components/SessionBranchPicker.tsx
63106
- import { useMemo as useMemo26, useState as useState49 } from "react";
63149
+ import { useMemo as useMemo26, useState as useState50 } from "react";
63107
63150
  import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
63108
63151
  var ROW_HEIGHT = 32;
63109
63152
  var SVG_WIDTH = 44;
@@ -63112,8 +63155,8 @@ function SessionBranchPicker({
63112
63155
  disabled = false,
63113
63156
  onCheckout
63114
63157
  }) {
63115
- const [checkoutError, setCheckoutError] = useState49(null);
63116
- const [pendingNodeId, setPendingNodeId] = useState49(null);
63158
+ const [checkoutError, setCheckoutError] = useState50(null);
63159
+ const [pendingNodeId, setPendingNodeId] = useState50(null);
63117
63160
  const hasHistory = tree.nodes.length > 0;
63118
63161
  const layout = useMemo26(() => buildLayoutNodes(tree), [tree]);
63119
63162
  const nodeMap = useMemo26(() => new Map(tree.nodes.map((node3) => [node3.id, node3])), [tree]);
@@ -63435,6 +63478,8 @@ export {
63435
63478
  classifyAgentComputerLaunchOutcome,
63436
63479
  collectMemoryRefs,
63437
63480
  filterConnectorItems,
63481
+ getChatRun,
63482
+ getChatRunDuration,
63438
63483
  getPlanUpdateDisplayState,
63439
63484
  isAgentComputerCommand,
63440
63485
  isAgentComputerToolCall,
@@ -63453,6 +63498,7 @@ export {
63453
63498
  turnNavItemsFromMessages,
63454
63499
  useAgentSession,
63455
63500
  useBladeClient,
63501
+ useLiveExecutionDuration,
63456
63502
  useLlmChat,
63457
63503
  useMessagePin,
63458
63504
  useReplay,