@opengeni/react 0.23.0 → 0.25.0

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.
Files changed (38) hide show
  1. package/dist/{chunk-UQS7OQDE.js → chunk-AVPU5PMC.js} +6 -4
  2. package/dist/chunk-AVPU5PMC.js.map +1 -0
  3. package/dist/{chunk-CATATY77.js → chunk-RDPDU4TA.js} +7 -6
  4. package/dist/chunk-RDPDU4TA.js.map +1 -0
  5. package/dist/{chunk-UAHPKLB6.js → chunk-SHOFILHJ.js} +18 -8
  6. package/dist/chunk-SHOFILHJ.js.map +1 -0
  7. package/dist/{composer-CVm5uoUI.d.ts → composer-BXb0Q1HF.d.ts} +18 -4
  8. package/dist/composer.d.ts +2 -2
  9. package/dist/composer.js +2 -2
  10. package/dist/fleet-decision-projection-SLNZMS42.js +241 -0
  11. package/dist/fleet-decision-projection-SLNZMS42.js.map +1 -0
  12. package/dist/fleet-decision-row-GGCAT4E4.js +351 -0
  13. package/dist/fleet-decision-row-GGCAT4E4.js.map +1 -0
  14. package/dist/index.d.ts +12 -9
  15. package/dist/index.js +332 -224
  16. package/dist/index.js.map +1 -1
  17. package/dist/{session-Db00TRwl.d.ts → session-BEvtFWhe.d.ts} +40 -14
  18. package/dist/session.d.ts +2 -2
  19. package/dist/session.js +2 -2
  20. package/dist/{use-composer-By1wn3MM.d.ts → use-composer-BnEzheSk.d.ts} +8 -2
  21. package/package.json +2 -2
  22. package/src/components/composer.tsx +7 -6
  23. package/src/components/message-timeline.tsx +2 -2
  24. package/src/hooks/use-composer.ts +15 -5
  25. package/src/hooks/use-file-attachments.ts +95 -2
  26. package/src/hooks/use-goal.ts +22 -4
  27. package/src/hooks/use-workspace-sessions.ts +30 -5
  28. package/src/timeline/activity-rail.tsx +17 -1
  29. package/src/timeline/fleet-decision-projection.ts +366 -0
  30. package/src/timeline/fleet-decision-row.tsx +412 -0
  31. package/src/timeline/index.ts +2 -0
  32. package/src/timeline/projection.ts +19 -8
  33. package/src/timeline/tool-display-name.ts +16 -0
  34. package/src/timeline/tool-renderers.tsx +1 -1
  35. package/src/timeline/types.ts +68 -1
  36. package/dist/chunk-CATATY77.js.map +0 -1
  37. package/dist/chunk-UAHPKLB6.js.map +0 -1
  38. package/dist/chunk-UQS7OQDE.js.map +0 -1
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  useChatComposerController,
37
37
  useSlashCommands,
38
38
  useTranscription
39
- } from "./chunk-CATATY77.js";
39
+ } from "./chunk-RDPDU4TA.js";
40
40
  import {
41
41
  CONNECTION_STATUS_META,
42
42
  ConnectionDot,
@@ -93,14 +93,14 @@ import {
93
93
  useSessionEvents,
94
94
  useSessionMcpApprovalPolicy,
95
95
  useTurnQueue
96
- } from "./chunk-UAHPKLB6.js";
96
+ } from "./chunk-SHOFILHJ.js";
97
97
  import {
98
98
  FILE_ONLY_MESSAGE_TEXT,
99
99
  composeSendInput,
100
100
  shouldSteerOnKey,
101
101
  shouldSubmitOnKey,
102
102
  useComposer
103
- } from "./chunk-UQS7OQDE.js";
103
+ } from "./chunk-AVPU5PMC.js";
104
104
  import {
105
105
  CREDIT_EXHAUSTION_MESSAGE,
106
106
  formatBytes,
@@ -214,6 +214,7 @@ function useFileAttachments(options = {}) {
214
214
  contentType: file.type || "application/octet-stream",
215
215
  data: file
216
216
  }).then((asset) => {
217
+ sources.current.delete(id);
217
218
  setAttachments(
218
219
  (current) => current.map(
219
220
  (attachment) => attachment.id === id ? {
@@ -291,6 +292,52 @@ function useFileAttachments(options = {}) {
291
292
  },
292
293
  [addFiles, pasteFilter]
293
294
  );
295
+ const restoreReadyFiles = useCallback2(
296
+ (files) => {
297
+ const incoming = /* @__PURE__ */ new Map();
298
+ for (const file of files) {
299
+ if (file.status === "ready" && file.workspaceId === workspaceId) {
300
+ incoming.set(file.id, file);
301
+ }
302
+ }
303
+ setAttachments((current) => {
304
+ const unresolved = current.filter((attachment) => attachment.status !== "ready");
305
+ const existingReady = new Map(
306
+ current.flatMap(
307
+ (attachment) => attachment.status === "ready" && attachment.file ? [[attachment.file.id, attachment]] : []
308
+ )
309
+ );
310
+ const restored = [...incoming.values()].map((file) => {
311
+ const existing = existingReady.get(file.id);
312
+ return existing ? {
313
+ ...existing,
314
+ name: file.filename,
315
+ contentType: file.contentType,
316
+ sizeBytes: file.sizeBytes,
317
+ status: "ready",
318
+ file,
319
+ error: void 0
320
+ } : {
321
+ id: `restored:${file.id}`,
322
+ name: file.filename,
323
+ contentType: file.contentType,
324
+ sizeBytes: file.sizeBytes,
325
+ status: "ready",
326
+ file
327
+ // No source File and no object URL: server metadata is the
328
+ // only authority restored across page/device boundaries.
329
+ };
330
+ });
331
+ for (const [fileId, attachment] of existingReady) {
332
+ if (!incoming.has(fileId) && attachment.previewUrl) {
333
+ URL.revokeObjectURL(attachment.previewUrl);
334
+ }
335
+ }
336
+ return [...unresolved, ...restored];
337
+ });
338
+ },
339
+ [workspaceId]
340
+ );
294
341
  const remove = useCallback2((id) => {
295
342
  sources.current.delete(id);
296
343
  setAttachments((current) => {
@@ -301,6 +348,20 @@ function useFileAttachments(options = {}) {
301
348
  return current.filter((attachment) => attachment.id !== id);
302
349
  });
303
350
  }, []);
351
+ const removeReadyFiles = useCallback2((fileIds) => {
352
+ const accepted = new Set(fileIds);
353
+ if (accepted.size === 0) return;
354
+ setAttachments(
355
+ (current) => current.filter((attachment) => {
356
+ const removeAccepted = attachment.status === "ready" && attachment.file !== void 0 && accepted.has(attachment.file.id);
357
+ if (removeAccepted) {
358
+ sources.current.delete(attachment.id);
359
+ if (attachment.previewUrl) URL.revokeObjectURL(attachment.previewUrl);
360
+ }
361
+ return !removeAccepted;
362
+ })
363
+ );
364
+ }, []);
304
365
  const clear = useCallback2(() => {
305
366
  sources.current.clear();
306
367
  setAttachments((current) => {
@@ -318,10 +379,13 @@ function useFileAttachments(options = {}) {
318
379
  (attachment) => attachment.status === "ready" && attachment.file ? [{ kind: "file", fileId: attachment.file.id }] : []
319
380
  ),
320
381
  uploading: attachments.some((attachment) => attachment.status === "uploading"),
382
+ hasUnresolved: attachments.some((attachment) => attachment.status !== "ready"),
321
383
  addFiles,
322
384
  addFromPaste,
385
+ restoreReadyFiles,
323
386
  retry,
324
387
  remove,
388
+ removeReadyFiles,
325
389
  clear
326
390
  };
327
391
  }
@@ -448,6 +512,10 @@ import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2
448
512
  function isGoalEvent(event) {
449
513
  return event.type.startsWith("goal.");
450
514
  }
515
+ function isGoalRefreshEvent(event) {
516
+ const type = event.type;
517
+ return isGoalEvent(event) || type.startsWith("turn.") || type.startsWith("session.") || type.startsWith("system.update.") || type.startsWith("workspace.inference.") || type.startsWith("user.");
518
+ }
451
519
  function useGoal(sessionId, options = {}) {
452
520
  const { client, workspaceId } = useOpenGeni(options);
453
521
  const enabled = (options.enabled ?? true) && Boolean(sessionId);
@@ -516,7 +584,7 @@ function useGoal(sessionId, options = {}) {
516
584
  };
517
585
  }, [load, enabled, workspaceId, sessionId, options.pollIntervalMs, sharedFeed]);
518
586
  const scheduleRefresh = useDebouncedCallback(() => void load());
519
- useSessionEventTrigger(client, workspaceId, sessionId, isGoalEvent, scheduleRefresh, {
587
+ useSessionEventTrigger(client, workspaceId, sessionId, isGoalRefreshEvent, scheduleRefresh, {
520
588
  enabled,
521
589
  ...sharedEvents !== void 0 ? { events: sharedEvents } : {}
522
590
  });
@@ -602,14 +670,28 @@ function useScheduledTasks(options = {}) {
602
670
  }
603
671
 
604
672
  // src/hooks/use-workspace-sessions.ts
605
- import { useCallback as useCallback5 } from "react";
673
+ import { useCallback as useCallback5, useEffect as useEffect3, useRef as useRef3 } from "react";
606
674
  function useWorkspaceSessions(options = {}) {
607
675
  const { client, workspaceId } = useOpenGeni(options);
608
676
  const limit = options.limit;
609
677
  const parentSessionId = options.parentSessionId;
610
678
  const cursor = options.cursor;
611
679
  const search = options.search;
612
- const queryKey = JSON.stringify({ workspaceId, limit, parentSessionId, cursor, search });
680
+ const pinsOnly = options.pinsOnly;
681
+ const enabled = options.enabled ?? true;
682
+ const queryKey = [
683
+ workspaceId,
684
+ limit ?? "",
685
+ parentSessionId === null ? "null" : parentSessionId ?? "",
686
+ cursor ?? "",
687
+ search ?? "",
688
+ pinsOnly ? "1" : ""
689
+ ].join("\0");
690
+ const previousQueryKey = useRef3(queryKey);
691
+ const queryKeyTransition = previousQueryKey.current !== queryKey;
692
+ useEffect3(() => {
693
+ previousQueryKey.current = queryKey;
694
+ }, [queryKey]);
613
695
  const load = useCallback5(
614
696
  async () => ({
615
697
  queryKey,
@@ -617,14 +699,15 @@ function useWorkspaceSessions(options = {}) {
617
699
  ...limit !== void 0 ? { limit } : {},
618
700
  ...parentSessionId !== void 0 ? { parentSessionId } : {},
619
701
  ...cursor !== void 0 ? { cursor } : {},
620
- ...search !== void 0 ? { search } : {}
702
+ ...search !== void 0 ? { search } : {},
703
+ ...pinsOnly ? { pinsOnly: true } : {}
621
704
  })
622
705
  }),
623
- [client, workspaceId, limit, parentSessionId, cursor, search, queryKey]
706
+ [client, workspaceId, limit, parentSessionId, cursor, search, pinsOnly, queryKey]
624
707
  );
625
708
  const state = usePolledValue(load, {
626
709
  pollIntervalMs: options.pollIntervalMs,
627
- enabled: options.enabled
710
+ enabled
628
711
  });
629
712
  const page = state.data?.queryKey === queryKey ? state.data.page : null;
630
713
  const pinned = page?.pinned ?? [];
@@ -637,14 +720,18 @@ function useWorkspaceSessions(options = {}) {
637
720
  pinned,
638
721
  pinnedTruncated: page?.pinnedTruncated ?? false,
639
722
  nextCursor: page?.nextCursor ?? null,
640
- loading: state.loading,
723
+ // `usePolledValue` clears the old data and starts the new request in an
724
+ // effect. During that query-key transition render, its old loading flag
725
+ // can still be false; expose loading immediately so consumers do not
726
+ // announce a transient false zero-match result.
727
+ loading: enabled && (state.loading || queryKeyTransition || state.data !== null && state.data.queryKey !== queryKey),
641
728
  error: state.error,
642
729
  refresh: state.refresh
643
730
  };
644
731
  }
645
732
 
646
733
  // src/hooks/use-session-lineage.ts
647
- import { useCallback as useCallback6, useEffect as useEffect3, useRef as useRef3 } from "react";
734
+ import { useCallback as useCallback6, useEffect as useEffect4, useRef as useRef4 } from "react";
648
735
  function isLineageRefreshEvent(event) {
649
736
  if (event.type === "session.status.changed" || event.type === "session.created") {
650
737
  return true;
@@ -673,16 +760,16 @@ function useSessionLineage(sessionId, options = {}) {
673
760
  );
674
761
  const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });
675
762
  const refresh = state.refresh;
676
- useEffect3(() => {
763
+ useEffect4(() => {
677
764
  if (enabled && workspaceControlEvent) void refresh();
678
765
  }, [enabled, refresh, workspaceControlEvent]);
679
- useEffect3(() => {
766
+ useEffect4(() => {
680
767
  if (!sessionId || !enabled) return;
681
768
  return registerSessionReconciler(sessionId, "lineage", refresh);
682
769
  }, [enabled, refresh, registerSessionReconciler, sessionId]);
683
770
  const refreshSoon = useDebouncedCallback(() => void refresh(), 150);
684
- const delayedChildRefreshRef = useRef3(null);
685
- useEffect3(() => {
771
+ const delayedChildRefreshRef = useRef4(null);
772
+ useEffect4(() => {
686
773
  return () => {
687
774
  if (delayedChildRefreshRef.current !== null) {
688
775
  clearTimeout(delayedChildRefreshRef.current);
@@ -1205,7 +1292,7 @@ import {
1205
1292
  OpenGeniApiError as OpenGeniApiError2,
1206
1293
  applyUrlRotation
1207
1294
  } from "@opengeni/sdk";
1208
- import { useCallback as useCallback13, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1295
+ import { useCallback as useCallback13, useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
1209
1296
  function desktopAttachable(cell) {
1210
1297
  if (cell.transport !== null) return true;
1211
1298
  return cell.reason === "lease_cold" || cell.reason === "not_provisioned" || cell.reason === null;
@@ -1242,13 +1329,13 @@ function useSessionCapabilities(sessionId, options = {}) {
1242
1329
  const [viewerId, setViewerId] = useState4(null);
1243
1330
  const [stateIdentity, setStateIdentity] = useState4(identityKey);
1244
1331
  const [nonce, setNonce] = useState4(0);
1245
- const epochRef = useRef4(0);
1246
- const viewerIdRef = useRef4(null);
1247
- const previousIdentityRef = useRef4(identityKey);
1332
+ const epochRef = useRef5(0);
1333
+ const viewerIdRef = useRef5(null);
1334
+ const previousIdentityRef = useRef5(identityKey);
1248
1335
  const renegotiate = useCallback13(() => {
1249
1336
  setNonce((n) => n + 1);
1250
1337
  }, []);
1251
- useEffect4(() => {
1338
+ useEffect5(() => {
1252
1339
  const identityChanged = previousIdentityRef.current !== identityKey;
1253
1340
  previousIdentityRef.current = identityKey;
1254
1341
  if (identityChanged) {
@@ -1445,7 +1532,7 @@ function useSessionCapabilities(sessionId, options = {}) {
1445
1532
  identityKey
1446
1533
  ]);
1447
1534
  const events = options.events;
1448
- useEffect4(() => {
1535
+ useEffect5(() => {
1449
1536
  if (!events || events.length === 0) return;
1450
1537
  setCapabilities((prev) => {
1451
1538
  if (!prev || !prev.DesktopStream.url) return prev;
@@ -1482,7 +1569,7 @@ import {
1482
1569
  desktopSocketUrl,
1483
1570
  nextDesktopState
1484
1571
  } from "@opengeni/sdk";
1485
- import { useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
1572
+ import { useEffect as useEffect7, useRef as useRef7, useState as useState6 } from "react";
1486
1573
 
1487
1574
  // src/lib/relay-wire.ts
1488
1575
  import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
@@ -1555,7 +1642,7 @@ function decodeStreamFrame(bytes) {
1555
1642
  }
1556
1643
 
1557
1644
  // src/hooks/use-relay-frame-stream.ts
1558
- import { useEffect as useEffect5, useRef as useRef5, useState as useState5 } from "react";
1645
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
1559
1646
  var TAG_OPEN = 1;
1560
1647
  var TAG_OPENACK = 2;
1561
1648
  var TAG_FRAME = 3;
@@ -1573,7 +1660,7 @@ function useRelayFrameStream(options) {
1573
1660
  const [state, setState] = useState5("idle");
1574
1661
  const [error, setError] = useState5(null);
1575
1662
  const [nonce, setNonce] = useState5(0);
1576
- const stateRef = useRef5("idle");
1663
+ const stateRef = useRef6("idle");
1577
1664
  const setBoth = (next) => {
1578
1665
  stateRef.current = next;
1579
1666
  setState(next);
@@ -1582,9 +1669,9 @@ function useRelayFrameStream(options) {
1582
1669
  const transport = capability?.transport ?? null;
1583
1670
  const url = capability?.url ?? null;
1584
1671
  const token = capability?.token ?? null;
1585
- const factoryRef = useRef5(webSocketFactory);
1672
+ const factoryRef = useRef6(webSocketFactory);
1586
1673
  factoryRef.current = webSocketFactory;
1587
- useEffect5(() => {
1674
+ useEffect6(() => {
1588
1675
  if (typeof window === "undefined") return;
1589
1676
  if (transport !== "relay-frames" || !url) {
1590
1677
  setBoth("idle");
@@ -1777,7 +1864,7 @@ function useDesktopStream(options) {
1777
1864
  const [state, setState] = useState6("idle");
1778
1865
  const [error, setError] = useState6(null);
1779
1866
  const [nonce, setNonce] = useState6(0);
1780
- const stateRef = useRef6("idle");
1867
+ const stateRef = useRef7("idle");
1781
1868
  const setBoth = (next) => {
1782
1869
  stateRef.current = next;
1783
1870
  setState(next);
@@ -1787,17 +1874,17 @@ function useDesktopStream(options) {
1787
1874
  const token = capability?.token ?? null;
1788
1875
  const transport = capability?.transport ?? null;
1789
1876
  const mode = capability?.mode ?? "read-only";
1790
- const rfbRef = useRef6(null);
1791
- const interactiveRef = useRef6(interactive);
1792
- const scaleViewportRef = useRef6(scaleViewport);
1793
- const modeRef = useRef6(mode);
1794
- const rfbFactoryRef = useRef6(rfbFactory);
1877
+ const rfbRef = useRef7(null);
1878
+ const interactiveRef = useRef7(interactive);
1879
+ const scaleViewportRef = useRef7(scaleViewport);
1880
+ const modeRef = useRef7(mode);
1881
+ const rfbFactoryRef = useRef7(rfbFactory);
1795
1882
  interactiveRef.current = interactive;
1796
1883
  scaleViewportRef.current = scaleViewport;
1797
1884
  modeRef.current = mode;
1798
1885
  rfbFactoryRef.current = rfbFactory;
1799
1886
  const viewOnlyFor = (m, want) => m === "read-only" || !want;
1800
- useEffect6(() => {
1887
+ useEffect7(() => {
1801
1888
  if (typeof window === "undefined") return;
1802
1889
  if (transport !== "vnc-ws" || !url) {
1803
1890
  setBoth("idle");
@@ -1860,11 +1947,11 @@ function useDesktopStream(options) {
1860
1947
  }
1861
1948
  };
1862
1949
  }, [url, token, transport, nonce]);
1863
- useEffect6(() => {
1950
+ useEffect7(() => {
1864
1951
  const rfb = rfbRef.current;
1865
1952
  if (rfb) rfb.viewOnly = viewOnlyFor(mode, interactive);
1866
1953
  }, [interactive, mode, state]);
1867
- useEffect6(() => {
1954
+ useEffect7(() => {
1868
1955
  const rfb = rfbRef.current;
1869
1956
  if (rfb) {
1870
1957
  rfb.clipViewport = false;
@@ -1884,7 +1971,7 @@ import {
1884
1971
  ttydResizeFrame,
1885
1972
  TtydServerCommand
1886
1973
  } from "@opengeni/sdk";
1887
- import { useEffect as useEffect7, useMemo as useMemo2, useRef as useRef7, useState as useState7 } from "react";
1974
+ import { useEffect as useEffect8, useMemo as useMemo2, useRef as useRef8, useState as useState7 } from "react";
1888
1975
  function decodeFrame(data) {
1889
1976
  if (typeof data === "string") {
1890
1977
  return { command: data.charAt(0), payload: data.slice(1) };
@@ -1897,19 +1984,19 @@ function decodeFrame(data) {
1897
1984
  function useTerminalStream(options) {
1898
1985
  const { capability, onOutput, onTitle, initialCols, initialRows } = options;
1899
1986
  const [status, setStatus] = useState7("closed");
1900
- const wsRef = useRef7(null);
1901
- const sizeRef = useRef7({
1987
+ const wsRef = useRef8(null);
1988
+ const sizeRef = useRef8({
1902
1989
  cols: initialCols ?? 80,
1903
1990
  rows: initialRows ?? 24
1904
1991
  });
1905
- const onOutputRef = useRef7(onOutput);
1906
- const onTitleRef = useRef7(onTitle);
1992
+ const onOutputRef = useRef8(onOutput);
1993
+ const onTitleRef = useRef8(onTitle);
1907
1994
  onOutputRef.current = onOutput;
1908
1995
  onTitleRef.current = onTitle;
1909
1996
  const transport = capability?.transport ?? null;
1910
1997
  const url = capability?.url ?? null;
1911
1998
  const token = capability?.token ?? null;
1912
- useEffect7(() => {
1999
+ useEffect8(() => {
1913
2000
  if (typeof window === "undefined" || typeof WebSocket === "undefined") return;
1914
2001
  if (transport !== "pty-ws" || !url) {
1915
2002
  setStatus("closed");
@@ -2006,7 +2093,7 @@ function useTerminalStream(options) {
2006
2093
 
2007
2094
  // src/hooks/use-sandbox-terminal.ts
2008
2095
  import { OpenGeniApiError as OpenGeniApiError3 } from "@opengeni/sdk";
2009
- import { useCallback as useCallback14, useEffect as useEffect8, useMemo as useMemo3, useRef as useRef8, useState as useState8 } from "react";
2096
+ import { useCallback as useCallback14, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef9, useState as useState8 } from "react";
2010
2097
  function useSandboxTerminal(sessionId, options) {
2011
2098
  const { client, workspaceId } = useOpenGeni(options);
2012
2099
  const includeAgentFirehose = options.includeAgentFirehose ?? true;
@@ -2018,16 +2105,16 @@ function useSandboxTerminal(sessionId, options) {
2018
2105
  const [openError, setOpenError] = useState8(null);
2019
2106
  const [stateIdentity, setStateIdentity] = useState8(identityKey);
2020
2107
  const [reopenNonce, setReopenNonce] = useState8(0);
2021
- const currentIdentityRef = useRef8(identityKey);
2108
+ const currentIdentityRef = useRef9(identityKey);
2022
2109
  currentIdentityRef.current = identityKey;
2023
- useEffect8(() => {
2110
+ useEffect9(() => {
2024
2111
  setStateIdentity(identityKey);
2025
2112
  setOpenedPtyId(null);
2026
2113
  setOpenError(null);
2027
2114
  }, [identityKey]);
2028
- const openInFlight = useRef8(false);
2115
+ const openInFlight = useRef9(false);
2029
2116
  const boxWarm = liveness === void 0 || liveness === "warm" || liveness === "draining";
2030
- useEffect8(() => {
2117
+ useEffect9(() => {
2031
2118
  if (!interactive || !sessionId || ptyFilter || !boxWarm) {
2032
2119
  setOpenError(null);
2033
2120
  return;
@@ -2138,7 +2225,7 @@ function useSandboxTerminal(sessionId, options) {
2138
2225
  }
2139
2226
 
2140
2227
  // src/hooks/use-sandbox-files.ts
2141
- import { useCallback as useCallback15, useEffect as useEffect9, useRef as useRef9, useState as useState9 } from "react";
2228
+ import { useCallback as useCallback15, useEffect as useEffect10, useRef as useRef10, useState as useState9 } from "react";
2142
2229
  var CapturedFileUnavailableError = class extends Error {
2143
2230
  constructor(path, reason) {
2144
2231
  super(
@@ -2323,23 +2410,23 @@ function useSandboxFiles(sessionId, options = {}) {
2323
2410
  const isLive2 = options.liveness === "warm" || options.liveness === "draining";
2324
2411
  const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${rootPath}`;
2325
2412
  const [tree, setTree] = useState9([]);
2326
- const treeRef = useRef9([]);
2413
+ const treeRef = useRef10([]);
2327
2414
  const [loading, setLoading] = useState9(false);
2328
2415
  const [expandingPaths, setExpandingPaths] = useState9(/* @__PURE__ */ new Set());
2329
2416
  const [error, setError] = useState9(null);
2330
2417
  const [stateIdentity, setStateIdentity] = useState9(identityKey);
2331
2418
  const [source, setSource] = useState9(null);
2332
- const sourceRef = useRef9(null);
2333
- const statusRef = useRef9(/* @__PURE__ */ new Map());
2334
- const refreshGenerationRef = useRef9(0);
2335
- const refreshAbortRef = useRef9(null);
2336
- const identityAbortRef = useRef9(new AbortController());
2337
- const identityGenerationRef = useRef9(0);
2338
- const lastSeqRef = useRef9(0);
2339
- const pendingParentsRef = useRef9(/* @__PURE__ */ new Set());
2340
- const pendingGitRef = useRef9(false);
2341
- const debounceRef = useRef9(null);
2342
- const ownRevisionsRef = useRef9(/* @__PURE__ */ new Set());
2419
+ const sourceRef = useRef10(null);
2420
+ const statusRef = useRef10(/* @__PURE__ */ new Map());
2421
+ const refreshGenerationRef = useRef10(0);
2422
+ const refreshAbortRef = useRef10(null);
2423
+ const identityAbortRef = useRef10(new AbortController());
2424
+ const identityGenerationRef = useRef10(0);
2425
+ const lastSeqRef = useRef10(0);
2426
+ const pendingParentsRef = useRef10(/* @__PURE__ */ new Set());
2427
+ const pendingGitRef = useRef10(false);
2428
+ const debounceRef = useRef10(null);
2429
+ const ownRevisionsRef = useRef10(/* @__PURE__ */ new Set());
2343
2430
  const onMutationError = options.onMutationError;
2344
2431
  treeRef.current = tree;
2345
2432
  const applyStatus = useCallback15((nodes) => {
@@ -2706,11 +2793,11 @@ function useSandboxFiles(sessionId, options = {}) {
2706
2793
  },
2707
2794
  [client, workspaceId, sessionId, runOptimistic]
2708
2795
  );
2709
- const captureRef = useRef9(capture);
2796
+ const captureRef = useRef10(capture);
2710
2797
  captureRef.current = capture;
2711
2798
  const captureRevision = capture?.revision ?? null;
2712
- const previousIdentityRef = useRef9(identityKey);
2713
- useEffect9(() => {
2799
+ const previousIdentityRef = useRef10(identityKey);
2800
+ useEffect10(() => {
2714
2801
  refreshAbortRef.current?.abort();
2715
2802
  refreshAbortRef.current = null;
2716
2803
  refreshGenerationRef.current += 1;
@@ -2778,7 +2865,7 @@ function useSandboxFiles(sessionId, options = {}) {
2778
2865
  }
2779
2866
  }, [client, workspaceId, sessionId, rootPath, applyStatus]);
2780
2867
  const events = options.events;
2781
- useEffect9(() => {
2868
+ useEffect10(() => {
2782
2869
  if (!enabled || !events) return;
2783
2870
  let sawNew = false;
2784
2871
  for (const event of events) {
@@ -2824,7 +2911,7 @@ function useSandboxFiles(sessionId, options = {}) {
2824
2911
  })();
2825
2912
  }, 150);
2826
2913
  }, [enabled, events, reconcilePath, refreshGitOverlay]);
2827
- useEffect9(
2914
+ useEffect10(
2828
2915
  () => () => {
2829
2916
  refreshAbortRef.current?.abort();
2830
2917
  identityAbortRef.current.abort();
@@ -2853,7 +2940,7 @@ function useSandboxFiles(sessionId, options = {}) {
2853
2940
  }
2854
2941
 
2855
2942
  // src/hooks/use-sandbox-git.ts
2856
- import { useCallback as useCallback16, useEffect as useEffect10, useMemo as useMemo4, useRef as useRef10, useState as useState10 } from "react";
2943
+ import { useCallback as useCallback16, useEffect as useEffect11, useMemo as useMemo4, useRef as useRef11, useState as useState10 } from "react";
2857
2944
  function normalizeRoot(root) {
2858
2945
  const normalized = root.replaceAll("\\", "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
2859
2946
  return normalized === "." ? "" : normalized;
@@ -2929,13 +3016,13 @@ function useSandboxGit(sessionId, options = {}) {
2929
3016
  const [behind, setBehind] = useState10(0);
2930
3017
  const [repoRoots, setRepoRoots] = useState10([]);
2931
3018
  const [source, setSource] = useState10(null);
2932
- const sourceRef = useRef10(null);
3019
+ const sourceRef = useRef11(null);
2933
3020
  const [loading, setLoading] = useState10(false);
2934
3021
  const [error, setError] = useState10(null);
2935
3022
  const [stateIdentity, setStateIdentity] = useState10(identityKey);
2936
- const refreshGenerationRef = useRef10(0);
2937
- const refreshAbortRef = useRef10(null);
2938
- const lastChangeRef = useRef10(0);
3023
+ const refreshGenerationRef = useRef11(0);
3024
+ const refreshAbortRef = useRef11(null);
3025
+ const lastChangeRef = useRef11(0);
2939
3026
  const refresh = useCallback16(async () => {
2940
3027
  if (!sessionId) return;
2941
3028
  refreshAbortRef.current?.abort();
@@ -3037,11 +3124,11 @@ function useSandboxGit(sessionId, options = {}) {
3037
3124
  },
3038
3125
  [repoPath, workspaceWide]
3039
3126
  );
3040
- const captureRef = useRef10(capture);
3127
+ const captureRef = useRef11(capture);
3041
3128
  captureRef.current = capture;
3042
3129
  const captureRevision = capture?.revision ?? null;
3043
- const previousIdentityRef = useRef10(identityKey);
3044
- useEffect10(() => {
3130
+ const previousIdentityRef = useRef11(identityKey);
3131
+ useEffect11(() => {
3045
3132
  refreshAbortRef.current?.abort();
3046
3133
  refreshAbortRef.current = null;
3047
3134
  refreshGenerationRef.current += 1;
@@ -3078,7 +3165,7 @@ function useSandboxGit(sessionId, options = {}) {
3078
3165
  };
3079
3166
  }, [enabled, isLive2, captureRevision, identityKey, refresh, seedFromCapture]);
3080
3167
  const events = options.events;
3081
- useEffect10(() => {
3168
+ useEffect11(() => {
3082
3169
  if (!enabled || !events) return;
3083
3170
  let latest = lastChangeRef.current;
3084
3171
  for (const event of events) {
@@ -3110,7 +3197,7 @@ function useSandboxGit(sessionId, options = {}) {
3110
3197
  }
3111
3198
 
3112
3199
  // src/hooks/use-workspace-capture.ts
3113
- import { useCallback as useCallback17, useEffect as useEffect11, useRef as useRef11, useState as useState11 } from "react";
3200
+ import { useCallback as useCallback17, useEffect as useEffect12, useRef as useRef12, useState as useState11 } from "react";
3114
3201
  var REVISION_CAPTURED = "workspace.revision.captured";
3115
3202
  var REVISION_DEGRADED = "workspace.revision.degraded";
3116
3203
  var MANIFEST_FETCH_TIMEOUT_MS = 15e3;
@@ -3157,9 +3244,9 @@ function useWorkspaceCapture(sessionId, options = {}) {
3157
3244
  const [error, setError] = useState11(null);
3158
3245
  const [announcedRevision, setAnnouncedRevision] = useState11(null);
3159
3246
  const [stateIdentity, setStateIdentity] = useState11(identityKey);
3160
- const generationRef = useRef11(0);
3161
- const requestAbortRef = useRef11(null);
3162
- const lastSeqRef = useRef11(0);
3247
+ const generationRef = useRef12(0);
3248
+ const requestAbortRef = useRef12(null);
3249
+ const lastSeqRef = useRef12(0);
3163
3250
  const refresh = useCallback17(async () => {
3164
3251
  if (!sessionId) return;
3165
3252
  requestAbortRef.current?.abort();
@@ -3233,7 +3320,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3233
3320
  if (requestAbortRef.current === requestAbort) requestAbortRef.current = null;
3234
3321
  }
3235
3322
  }, [client, workspaceId, sessionId, identityKey]);
3236
- useEffect11(() => {
3323
+ useEffect12(() => {
3237
3324
  requestAbortRef.current?.abort();
3238
3325
  requestAbortRef.current = null;
3239
3326
  generationRef.current += 1;
@@ -3256,7 +3343,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3256
3343
  };
3257
3344
  }, [enabled, refresh]);
3258
3345
  const events = options.events;
3259
- useEffect11(() => {
3346
+ useEffect12(() => {
3260
3347
  if (!enabled || !events) return;
3261
3348
  let newest = null;
3262
3349
  for (const event of events) {
@@ -3282,7 +3369,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3282
3369
  const visibleCapture = identityMatches ? capture : null;
3283
3370
  const visibleAnnouncedRevision = identityMatches ? announcedRevision : null;
3284
3371
  const loadedRevision = visibleCapture?.revision ?? null;
3285
- useEffect11(() => {
3372
+ useEffect12(() => {
3286
3373
  if (!enabled) return;
3287
3374
  if (visibleAnnouncedRevision === null) return;
3288
3375
  if (loadedRevision !== null && visibleAnnouncedRevision <= loadedRevision) return;
@@ -3304,7 +3391,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3304
3391
  }
3305
3392
 
3306
3393
  // src/hooks/use-workspace-edit.ts
3307
- import { useCallback as useCallback18, useEffect as useEffect12, useRef as useRef12, useState as useState12 } from "react";
3394
+ import { useCallback as useCallback18, useEffect as useEffect13, useRef as useRef13, useState as useState12 } from "react";
3308
3395
  function isLive(liveness) {
3309
3396
  return liveness === "warm" || liveness === "draining";
3310
3397
  }
@@ -3322,13 +3409,13 @@ function useWorkspaceEdit(sessionId, options = {}) {
3322
3409
  const [error, setError] = useState12(null);
3323
3410
  const [stateIdentity, setStateIdentity] = useState12(identityKey);
3324
3411
  const onWarmRequested = options.onWarmRequested;
3325
- const bufferRef = useRef12(null);
3412
+ const bufferRef = useRef13(null);
3326
3413
  bufferRef.current = buffer;
3327
- const flushingRef = useRef12(false);
3328
- const identityGenerationRef = useRef12(0);
3329
- const flushAttemptRef = useRef12(0);
3330
- const readAbortRef = useRef12(null);
3331
- useEffect12(() => {
3414
+ const flushingRef = useRef13(false);
3415
+ const identityGenerationRef = useRef13(0);
3416
+ const flushAttemptRef = useRef13(0);
3417
+ const readAbortRef = useRef13(null);
3418
+ useEffect13(() => {
3332
3419
  identityGenerationRef.current += 1;
3333
3420
  flushAttemptRef.current += 1;
3334
3421
  readAbortRef.current?.abort();
@@ -3413,7 +3500,7 @@ function useWorkspaceEdit(sessionId, options = {}) {
3413
3500
  },
3414
3501
  [client, workspaceId, sessionId, path, baseContent, stateIdentity, identityKey]
3415
3502
  );
3416
- useEffect12(() => {
3503
+ useEffect13(() => {
3417
3504
  if (offline) return;
3418
3505
  if (!live) return;
3419
3506
  if (buffer === null) return;
@@ -3526,7 +3613,7 @@ function useMachineChip(input) {
3526
3613
 
3527
3614
  // src/components/approval-surface.tsx
3528
3615
  import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
3529
- import { useEffect as useEffect13, useId, useRef as useRef13, useState as useState13 } from "react";
3616
+ import { useEffect as useEffect14, useId, useRef as useRef14, useState as useState13 } from "react";
3530
3617
  import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3531
3618
  var defaultApprovalSurfaceMessages = {
3532
3619
  title: "Approval required",
@@ -3567,9 +3654,9 @@ function ApprovalSurface({
3567
3654
  const titleId = useId();
3568
3655
  const messages = { ...defaultApprovalSurfaceMessages, ...overrides };
3569
3656
  const [pending, setPending] = useState13(null);
3570
- const pendingRef = useRef13(null);
3657
+ const pendingRef = useRef14(null);
3571
3658
  const [decisionError, setDecisionError] = useState13(null);
3572
- useEffect13(() => {
3659
+ useEffect14(() => {
3573
3660
  if (pending && !approvals.some((approval) => approvalOwnershipKey(approval) === pending.approvalKey)) {
3574
3661
  if (pendingRef.current?.token === pending.token) {
3575
3662
  pendingRef.current = null;
@@ -3667,7 +3754,7 @@ function ApprovalSurface({
3667
3754
  }
3668
3755
 
3669
3756
  // src/components/human-input-form.tsx
3670
- import { useEffect as useEffect14, useId as useId2, useRef as useRef14, useState as useState14 } from "react";
3757
+ import { useEffect as useEffect15, useId as useId2, useRef as useRef15, useState as useState14 } from "react";
3671
3758
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3672
3759
  var defaultHumanInputFormMessages = {
3673
3760
  title: "Your input is needed",
@@ -3710,10 +3797,10 @@ function HumanInputForm({
3710
3797
  const [validationErrors, setValidationErrors] = useState14({});
3711
3798
  const [submissionError, setSubmissionError] = useState14(null);
3712
3799
  const [submittingInternally, setSubmittingInternally] = useState14(false);
3713
- const submissionInFlight = useRef14(false);
3714
- const submissionGeneration = useRef14(0);
3800
+ const submissionInFlight = useRef15(false);
3801
+ const submissionGeneration = useRef15(0);
3715
3802
  const busy = submitting || submittingInternally;
3716
- useEffect14(() => {
3803
+ useEffect15(() => {
3717
3804
  submissionGeneration.current += 1;
3718
3805
  submissionInFlight.current = false;
3719
3806
  setDrafts(initialDrafts(request.questions));
@@ -4731,10 +4818,10 @@ function ScreenshotFigure({
4731
4818
  import { useState as useState19 } from "react";
4732
4819
 
4733
4820
  // src/lib/use-theme-type.ts
4734
- import { useEffect as useEffect15, useState as useState17 } from "react";
4821
+ import { useEffect as useEffect16, useState as useState17 } from "react";
4735
4822
  function useThemeType(forced) {
4736
4823
  const [detected, setDetected] = useState17("dark");
4737
- useEffect15(() => {
4824
+ useEffect16(() => {
4738
4825
  if (forced || typeof document === "undefined") return;
4739
4826
  const read = () => {
4740
4827
  const el = document.querySelector("[data-og-theme]");
@@ -4757,7 +4844,7 @@ function useThemeType(forced) {
4757
4844
  import {
4758
4845
  lazy as lazy2,
4759
4846
  Suspense as Suspense2,
4760
- useEffect as useEffect16,
4847
+ useEffect as useEffect17,
4761
4848
  useState as useState18
4762
4849
  } from "react";
4763
4850
 
@@ -4810,7 +4897,7 @@ function PierreDiff({
4810
4897
  }) {
4811
4898
  const [failed, setFailed] = useState18(false);
4812
4899
  const [forcedColors, setForcedColors] = useState18(false);
4813
- useEffect16(() => {
4900
+ useEffect17(() => {
4814
4901
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
4815
4902
  const query = window.matchMedia("(forced-colors: active)");
4816
4903
  const update = () => setForcedColors(query.matches);
@@ -4818,7 +4905,7 @@ function PierreDiff({
4818
4905
  query.addEventListener?.("change", update);
4819
4906
  return () => query.removeEventListener?.("change", update);
4820
4907
  }, []);
4821
- useEffect16(() => {
4908
+ useEffect17(() => {
4822
4909
  if (plain) return;
4823
4910
  let cancelled = false;
4824
4911
  void import("@pierre/diffs/react").catch(() => {
@@ -4958,6 +5045,13 @@ function RawPatch({ diff }) {
4958
5045
  ] });
4959
5046
  }
4960
5047
 
5048
+ // src/timeline/tool-display-name.ts
5049
+ function toolDisplayName2(name) {
5050
+ const boundary = name.indexOf("__");
5051
+ const toolPart = boundary >= 0 ? name.slice(boundary + 2) : name;
5052
+ return toolPart.replace(/[_-]+/g, " ").trim();
5053
+ }
5054
+
4961
5055
  // src/timeline/tool-renderers.tsx
4962
5056
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
4963
5057
  var ICON_SIZE = "size-3.5";
@@ -5654,7 +5748,7 @@ function SecretSetRenderer({ item }) {
5654
5748
  function GenericRenderer({ item }) {
5655
5749
  const running = item.status === "running";
5656
5750
  const args = redactSecrets(parseToolArgs(item.arguments));
5657
- const display = toolDisplayName(item.name);
5751
+ const display = toolDisplayName2(item.name);
5658
5752
  if (running) {
5659
5753
  return /* @__PURE__ */ jsx10(
5660
5754
  ActivityDisclosure,
@@ -5744,19 +5838,22 @@ import {
5744
5838
  BrainIcon,
5745
5839
  SquareTerminalIcon
5746
5840
  } from "lucide-react";
5841
+ import { lazy as lazy3, Suspense as Suspense3 } from "react";
5842
+ import { jsx as rowJsx, jsxs as rowJsxs } from "react/jsx-runtime";
5747
5843
 
5748
5844
  // src/timeline/entrance.tsx
5749
- import { createContext as createContext3, useContext as useContext3, useRef as useRef15 } from "react";
5845
+ import { createContext as createContext3, useContext as useContext3, useRef as useRef16 } from "react";
5750
5846
  var EntranceAnimationContext = createContext3(true);
5751
5847
  var EntranceAnimationProvider = EntranceAnimationContext.Provider;
5752
5848
  function useEntranceAnimation() {
5753
5849
  const enabled = useContext3(EntranceAnimationContext);
5754
- const captured = useRef15(enabled);
5850
+ const captured = useRef16(enabled);
5755
5851
  return captured.current;
5756
5852
  }
5757
5853
 
5758
5854
  // src/timeline/activity-rail.tsx
5759
5855
  import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
5856
+ var LazyFleetDecisionRow = lazy3(() => import("./fleet-decision-row-GGCAT4E4.js"));
5760
5857
  function familyOf(item) {
5761
5858
  if (item.kind === "tool-call") {
5762
5859
  return item.name === "exec_command" || item.name === "write_stdin" ? "terminal" : item.name;
@@ -5809,6 +5906,17 @@ function renderActivity(item, toolRegistry, onOpenSession, onMemoryClick) {
5809
5906
  return /* @__PURE__ */ jsx11(SandboxRow, { item });
5810
5907
  case "memory":
5811
5908
  return /* @__PURE__ */ jsx11(MemoryRow, { item, onMemoryClick });
5909
+ case "fleet-decision":
5910
+ return /* @__PURE__ */ jsx11(Suspense3, { fallback: null, children: /* @__PURE__ */ jsx11(
5911
+ LazyFleetDecisionRow,
5912
+ {
5913
+ item,
5914
+ d: ActivityDisclosure,
5915
+ b: BodyNote,
5916
+ j: rowJsx,
5917
+ s: rowJsxs
5918
+ }
5919
+ ) });
5812
5920
  default:
5813
5921
  return assertNever(item);
5814
5922
  }
@@ -5900,7 +6008,7 @@ function sandboxRowTitle(item) {
5900
6008
  if (item.origin === "created") return "Sandbox created";
5901
6009
  return "Sandbox ready";
5902
6010
  }
5903
- return toolDisplayName(item.name);
6011
+ return toolDisplayName2(item.name);
5904
6012
  }
5905
6013
  function SandboxRow({ item }) {
5906
6014
  return /* @__PURE__ */ jsxs9(
@@ -6151,10 +6259,10 @@ import { Collapsible as Collapsible3 } from "radix-ui";
6151
6259
  import {
6152
6260
  memo as memo2,
6153
6261
  useCallback as useCallback20,
6154
- useEffect as useEffect17,
6262
+ useEffect as useEffect18,
6155
6263
  useLayoutEffect,
6156
6264
  useMemo as useMemo7,
6157
- useRef as useRef16,
6265
+ useRef as useRef17,
6158
6266
  useState as useState21
6159
6267
  } from "react";
6160
6268
 
@@ -6415,13 +6523,13 @@ function MessageTimeline({
6415
6523
  const keyedGroups = useStableTimelineGroupKeys(allGroups);
6416
6524
  const { mountedGroups: groups, mountingOlderGroups } = useProgressivelyMountedGroups(keyedGroups);
6417
6525
  const firstGroupKey = allGroups[0] ? timelineGroupKey(allGroups[0]) : null;
6418
- const scrollRef = useRef16(null);
6419
- const topSentinelRef = useRef16(null);
6420
- const previousBulkFirstKeyRef = useRef16(void 0);
6526
+ const scrollRef = useRef17(null);
6527
+ const topSentinelRef = useRef17(null);
6528
+ const previousBulkFirstKeyRef = useRef17(void 0);
6421
6529
  const [pinned, setPinned] = useState21(true);
6422
6530
  const [bulkActive, setBulkActive] = useState21(true);
6423
6531
  const [revealed, setRevealed] = useState21(false);
6424
- const programmaticScrollRef = useRef16(false);
6532
+ const programmaticScrollRef = useRef17(false);
6425
6533
  const assignScrollTop = useCallback20((node, value) => {
6426
6534
  const previous = node.scrollTop;
6427
6535
  programmaticScrollRef.current = true;
@@ -6430,8 +6538,8 @@ function MessageTimeline({
6430
6538
  programmaticScrollRef.current = false;
6431
6539
  }
6432
6540
  }, []);
6433
- const pinnedRef = useRef16(true);
6434
- const anchorRef = useRef16(null);
6541
+ const pinnedRef = useRef17(true);
6542
+ const anchorRef = useRef17(null);
6435
6543
  const lastItem = resolvedItems[resolvedItems.length - 1];
6436
6544
  const streaming = lastItem !== void 0 && (lastItem.kind === "agent-message" || lastItem.kind === "reasoning") && lastItem.streaming;
6437
6545
  const working = status === "running" && !streaming;
@@ -6483,7 +6591,7 @@ function MessageTimeline({
6483
6591
  const frame = requestFrame(() => setBulkActive(false));
6484
6592
  return () => cancelFrame(frame);
6485
6593
  }, [bulkRender, firstGroupKey, mountingOlderGroups]);
6486
- useEffect17(() => {
6594
+ useEffect18(() => {
6487
6595
  const root = scrollRef.current;
6488
6596
  const target = topSentinelRef.current;
6489
6597
  if (!root || !target || mountingOlderGroups || !hasOlder || loadingOlder || !onLoadOlder || typeof IntersectionObserver === "undefined") {
@@ -6500,7 +6608,7 @@ function MessageTimeline({
6500
6608
  observer.observe(target);
6501
6609
  return () => observer.disconnect();
6502
6610
  }, [hasOlder, loadingOlder, onLoadOlder, firstGroupKey, mountingOlderGroups]);
6503
- useEffect17(() => {
6611
+ useEffect18(() => {
6504
6612
  const node = scrollRef.current;
6505
6613
  const inner = node?.firstElementChild;
6506
6614
  if (!node || !inner || typeof ResizeObserver === "undefined") {
@@ -6613,7 +6721,7 @@ function MessageTimeline({
6613
6721
  ] }) }) });
6614
6722
  }
6615
6723
  function useStableTimelineGroupKeys(allGroups) {
6616
- const previousRef = useRef16([]);
6724
+ const previousRef = useRef17([]);
6617
6725
  const keyedGroups = useMemo7(() => {
6618
6726
  const previousByItemId = /* @__PURE__ */ new Map();
6619
6727
  for (const previous of previousRef.current) {
@@ -6649,7 +6757,7 @@ function useStableTimelineGroupKeys(allGroups) {
6649
6757
  return keyedGroups;
6650
6758
  }
6651
6759
  function useProgressivelyMountedGroups(allGroups) {
6652
- const previousGroupKeysRef = useRef16([]);
6760
+ const previousGroupKeysRef = useRef17([]);
6653
6761
  const groupKeys = useMemo7(() => {
6654
6762
  const nextKeys = allGroups.map((group) => group.key);
6655
6763
  const previousKeys = previousGroupKeysRef.current;
@@ -6676,7 +6784,7 @@ function useProgressivelyMountedGroups(allGroups) {
6676
6784
  }
6677
6785
  visibleStart = retainedStart === void 0 ? lastPossibleStart : Math.min(retainedStart, lastPossibleStart);
6678
6786
  }
6679
- useEffect17(() => {
6787
+ useEffect18(() => {
6680
6788
  if (window2.groupKeys !== groupKeys || window2.visibleStart !== visibleStart) {
6681
6789
  setWindow({ groupKeys, visibleStart });
6682
6790
  return;
@@ -6836,7 +6944,7 @@ function clusterIsSettled(group) {
6836
6944
  if (item.kind === "reasoning") {
6837
6945
  return !item.streaming;
6838
6946
  }
6839
- if (item.kind === "memory") {
6947
+ if (item.kind === "memory" || item.kind === "fleet-decision") {
6840
6948
  return true;
6841
6949
  }
6842
6950
  return item.status !== "running";
@@ -7226,7 +7334,7 @@ function AuthNeededRow({
7226
7334
  }
7227
7335
  function AuthProviderLogo({ src, label }) {
7228
7336
  const [failed, setFailed] = useState21(false);
7229
- useEffect17(() => setFailed(false), [src]);
7337
+ useEffect18(() => setFailed(false), [src]);
7230
7338
  const showImage = src && !failed;
7231
7339
  return /* @__PURE__ */ jsx15(
7232
7340
  "span",
@@ -7343,7 +7451,7 @@ function FleetTile({ session, title, subtitle, onOpen, className }) {
7343
7451
  }
7344
7452
 
7345
7453
  // src/components/sandbox-terminal.tsx
7346
- import { useEffect as useEffect18, useRef as useRef17, useState as useState22 } from "react";
7454
+ import { useEffect as useEffect19, useRef as useRef18, useState as useState22 } from "react";
7347
7455
 
7348
7456
  // src/lib/xterm-theme.ts
7349
7457
  var DARK_ANSI = {
@@ -7521,17 +7629,17 @@ function SandboxTerminal({
7521
7629
  onActivate,
7522
7630
  className
7523
7631
  }) {
7524
- const containerRef = useRef17(null);
7525
- const termRef = useRef17(null);
7526
- const fitRef = useRef17(null);
7527
- const rendererRef = useRef17(null);
7528
- const writtenRef = useRef17(/* @__PURE__ */ new Set());
7529
- const wroteFirehoseRef = useRef17(false);
7530
- const bootActiveRef = useRef17(false);
7632
+ const containerRef = useRef18(null);
7633
+ const termRef = useRef18(null);
7634
+ const fitRef = useRef18(null);
7635
+ const rendererRef = useRef18(null);
7636
+ const writtenRef = useRef18(/* @__PURE__ */ new Set());
7637
+ const wroteFirehoseRef = useRef18(false);
7638
+ const bootActiveRef = useRef18(false);
7531
7639
  const [ready, setReady] = useState22(false);
7532
7640
  const [activated, setActivated] = useState22(false);
7533
7641
  const ptyWs = terminalCapability?.transport === "pty-ws" && Boolean(terminalCapability?.url);
7534
- const ptyOutputQueueRef = useRef17([]);
7642
+ const ptyOutputQueueRef = useRef18([]);
7535
7643
  const {
7536
7644
  status: ptyStatus,
7537
7645
  write: ptyWrite,
@@ -7557,7 +7665,7 @@ function SandboxTerminal({
7557
7665
  if (!activated) setActivated(true);
7558
7666
  onActivate?.();
7559
7667
  }
7560
- useEffect18(() => {
7668
+ useEffect19(() => {
7561
7669
  if (typeof window === "undefined") return;
7562
7670
  const el = containerRef.current;
7563
7671
  if (!el) return;
@@ -7669,19 +7777,19 @@ function SandboxTerminal({
7669
7777
  setReady(false);
7670
7778
  };
7671
7779
  }, []);
7672
- useEffect18(() => {
7780
+ useEffect19(() => {
7673
7781
  const term = termRef.current;
7674
7782
  if (!ready || !term) return;
7675
7783
  term.options.disableStdin = !interactive;
7676
7784
  term.options.cursorBlink = interactive;
7677
7785
  }, [ready, interactive]);
7678
- useEffect18(() => {
7786
+ useEffect19(() => {
7679
7787
  const term = termRef.current;
7680
7788
  if (!ready || !term) return;
7681
7789
  const next = theme ?? xtermThemeFromTokens(containerRef.current);
7682
7790
  if (next) term.options.theme = next;
7683
7791
  }, [ready, theme]);
7684
- useEffect18(() => {
7792
+ useEffect19(() => {
7685
7793
  const term = termRef.current;
7686
7794
  if (!ready || !term) return;
7687
7795
  if (!booting) {
@@ -7702,7 +7810,7 @@ function SandboxTerminal({
7702
7810
  const id = setInterval(paint, 1e3);
7703
7811
  return () => clearInterval(id);
7704
7812
  }, [ready, booting]);
7705
- useEffect18(() => {
7813
+ useEffect19(() => {
7706
7814
  const term = termRef.current;
7707
7815
  if (!ready || !term || ptyMode) return;
7708
7816
  for (const chunk of result.chunks) {
@@ -7712,7 +7820,7 @@ function SandboxTerminal({
7712
7820
  term.write(chunk.text);
7713
7821
  }
7714
7822
  }, [ready, result.chunks, ptyMode]);
7715
- useEffect18(() => {
7823
+ useEffect19(() => {
7716
7824
  const term = termRef.current;
7717
7825
  if (!ready || !term || !interactive) return;
7718
7826
  const sink = ptyMode ? ptyWrite : result.write;
@@ -7720,14 +7828,14 @@ function SandboxTerminal({
7720
7828
  const sub = term.onData((data) => sink(data));
7721
7829
  return () => sub.dispose();
7722
7830
  }, [ready, interactive, ptyMode, ptyWrite, result.write]);
7723
- useEffect18(() => {
7831
+ useEffect19(() => {
7724
7832
  const term = termRef.current;
7725
7833
  if (!ready || !term || !ptyMode) return;
7726
7834
  resizePty(term.cols, term.rows);
7727
7835
  const sub = term.onResize(({ cols, rows }) => resizePty(cols, rows));
7728
7836
  return () => sub.dispose();
7729
7837
  }, [ready, ptyMode, ptyConnected, resizePty]);
7730
- useEffect18(() => {
7838
+ useEffect19(() => {
7731
7839
  if (typeof window === "undefined") return;
7732
7840
  const refit = () => {
7733
7841
  try {
@@ -7862,21 +7970,21 @@ import {
7862
7970
  } from "lucide-react";
7863
7971
  import {
7864
7972
  useCallback as useCallback21,
7865
- useEffect as useEffect21,
7973
+ useEffect as useEffect22,
7866
7974
  useId as useId3,
7867
7975
  useLayoutEffect as useLayoutEffect2,
7868
7976
  useMemo as useMemo9,
7869
- useRef as useRef18,
7977
+ useRef as useRef19,
7870
7978
  useState as useState24
7871
7979
  } from "react";
7872
7980
  import { AlertDialog } from "radix-ui";
7873
7981
  import { VList } from "virtua";
7874
7982
 
7875
7983
  // src/lib/use-portal-token-style.ts
7876
- import { useEffect as useEffect19, useState as useState23 } from "react";
7984
+ import { useEffect as useEffect20, useState as useState23 } from "react";
7877
7985
  function usePortalTokenStyle(sourceRef) {
7878
7986
  const [style, setStyle] = useState23({});
7879
- useEffect19(() => {
7987
+ useEffect20(() => {
7880
7988
  const source = sourceRef.current;
7881
7989
  if (!source || typeof MutationObserver === "undefined") return;
7882
7990
  let signature = "";
@@ -7917,12 +8025,12 @@ function usePortalTokenStyle(sourceRef) {
7917
8025
  }
7918
8026
 
7919
8027
  // src/lib/use-unicode-fonts.ts
7920
- import { useEffect as useEffect20, useMemo as useMemo8 } from "react";
8028
+ import { useEffect as useEffect21, useMemo as useMemo8 } from "react";
7921
8029
  var japaneseScript = /[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u;
7922
8030
  var arabicScript = /[\u0600-\u06ff\u0750-\u077f\u0870-\u08ff\ufb50-\ufdff\ufe70-\ufefc]/u;
7923
8031
  function useUnicodeFallbackFonts(values) {
7924
8032
  const content = useMemo8(() => collectUnicodeContent(values), [values]);
7925
- useEffect20(() => {
8033
+ useEffect21(() => {
7926
8034
  if (content.japanese) {
7927
8035
  void import("./noto-sans-jp-loader.generated-HFGLYBR3.js").then(({ loadNotoSansJp }) => loadNotoSansJp(content.japanese)).catch(() => void 0);
7928
8036
  }
@@ -7952,7 +8060,7 @@ var STATUS_TINT = {
7952
8060
  renamed: "text-og-accent",
7953
8061
  untracked: "text-og-fg-subtle"
7954
8062
  };
7955
- var useBrowserLayoutEffect = typeof window === "undefined" ? useEffect21 : useLayoutEffect2;
8063
+ var useBrowserLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect2;
7956
8064
  function parentOf2(path) {
7957
8065
  const i = path.lastIndexOf("/");
7958
8066
  return i <= 0 ? "" : path.slice(0, i);
@@ -8004,9 +8112,9 @@ function FileBrowser({
8004
8112
  const [busy, setBusy] = useState24(false);
8005
8113
  const [coarsePointer, setCoarsePointer] = useState24(false);
8006
8114
  const treeId = useId3();
8007
- const containerRef = useRef18(null);
8008
- const deleteReturnFocusRef = useRef18(null);
8009
- const vlistRef = useRef18(null);
8115
+ const containerRef = useRef19(null);
8116
+ const deleteReturnFocusRef = useRef19(null);
8117
+ const vlistRef = useRef19(null);
8010
8118
  const portalTokenStyle = usePortalTokenStyle(containerRef);
8011
8119
  const getTreeElement = useCallback21(
8012
8120
  () => typeof document === "undefined" ? null : document.getElementById(treeId),
@@ -8379,7 +8487,7 @@ function FileBrowser({
8379
8487
  treeId
8380
8488
  ]
8381
8489
  );
8382
- useEffect21(() => {
8490
+ useEffect22(() => {
8383
8491
  if (!menu) return;
8384
8492
  const close = () => setMenu(null);
8385
8493
  window.addEventListener("click", close);
@@ -8560,7 +8668,7 @@ function FileBrowser({
8560
8668
  );
8561
8669
  }
8562
8670
  };
8563
- useEffect21(() => {
8671
+ useEffect22(() => {
8564
8672
  if (!cursor) return;
8565
8673
  const index = renderItems.findIndex((it) => it.type === "node" && it.node.path === cursor);
8566
8674
  if (index >= 0) vlistRef.current?.scrollToIndex(index);
@@ -8761,11 +8869,11 @@ function DeleteDialog({
8761
8869
  onCancel,
8762
8870
  onConfirm
8763
8871
  }) {
8764
- const cancelRef = useRef18(null);
8872
+ const cancelRef = useRef19(null);
8765
8873
  const [open, setOpen] = useState24(true);
8766
- const closeIntentRef = useRef18("cancel");
8767
- const settledRef = useRef18(false);
8768
- const settleTimerRef = useRef18(null);
8874
+ const closeIntentRef = useRef19("cancel");
8875
+ const settledRef = useRef19(false);
8876
+ const settleTimerRef = useRef19(null);
8769
8877
  const settle = () => {
8770
8878
  if (settledRef.current) return;
8771
8879
  settledRef.current = true;
@@ -8782,7 +8890,7 @@ function DeleteDialog({
8782
8890
  settle();
8783
8891
  }, 0);
8784
8892
  };
8785
- useEffect21(
8893
+ useEffect22(
8786
8894
  () => () => {
8787
8895
  if (settleTimerRef.current !== null) clearTimeout(settleTimerRef.current);
8788
8896
  },
@@ -8901,9 +9009,9 @@ function InlineInput({
8901
9009
  onCancel
8902
9010
  }) {
8903
9011
  const [value, setValue] = useState24(initialValue);
8904
- const ref = useRef18(null);
8905
- const doneRef = useRef18(false);
8906
- useEffect21(() => {
9012
+ const ref = useRef19(null);
9013
+ const doneRef = useRef19(false);
9014
+ useEffect22(() => {
8907
9015
  const el = ref.current;
8908
9016
  if (!el) return;
8909
9017
  el.focus();
@@ -8967,12 +9075,12 @@ function ContextMenu({
8967
9075
  onClose
8968
9076
  }) {
8969
9077
  const isDir = node.kind === "dir";
8970
- const menuRef = useRef18(null);
9078
+ const menuRef = useRef19(null);
8971
9079
  const vw = typeof window !== "undefined" ? window.innerWidth : 9999;
8972
9080
  const vh = typeof window !== "undefined" ? window.innerHeight : 9999;
8973
9081
  const left = Math.max(4, Math.min(x, vw - 180));
8974
9082
  const top = Math.max(4, Math.min(y, vh - 160));
8975
- useEffect21(() => {
9083
+ useEffect22(() => {
8976
9084
  menuRef.current?.querySelector('[role="menuitem"]')?.focus();
8977
9085
  }, []);
8978
9086
  const onKeyDown = (event) => {
@@ -9072,13 +9180,13 @@ function DiffView({
9072
9180
 
9073
9181
  // src/components/pierre-file.tsx
9074
9182
  import {
9075
- lazy as lazy3,
9076
- Suspense as Suspense3,
9077
- useEffect as useEffect22,
9183
+ lazy as lazy4,
9184
+ Suspense as Suspense4,
9185
+ useEffect as useEffect23,
9078
9186
  useState as useState25
9079
9187
  } from "react";
9080
9188
  import { jsx as jsx20 } from "react/jsx-runtime";
9081
- var LazyFile = lazy3(async () => {
9189
+ var LazyFile = lazy4(async () => {
9082
9190
  const mod = await import("@pierre/diffs/react");
9083
9191
  return { default: mod.File };
9084
9192
  });
@@ -9093,7 +9201,7 @@ function PierreFile({
9093
9201
  className
9094
9202
  }) {
9095
9203
  const [failed, setFailed] = useState25(false);
9096
- useEffect22(() => {
9204
+ useEffect23(() => {
9097
9205
  let cancelled = false;
9098
9206
  void import("@pierre/diffs/react").catch(() => {
9099
9207
  if (!cancelled) setFailed(true);
@@ -9126,7 +9234,7 @@ function PierreFile({
9126
9234
  "--diffs-font-size": "var(--og-code-font-size)",
9127
9235
  "--diffs-line-height": "var(--og-code-line-height)"
9128
9236
  };
9129
- return /* @__PURE__ */ jsx20("div", { className: cn("min-w-0", className), "data-opengeni-pierre-file": true, style: pierreVars, children: /* @__PURE__ */ jsx20(Suspense3, { fallback: loading ?? /* @__PURE__ */ jsx20(FileSkeleton, {}), children: /* @__PURE__ */ jsx20(
9237
+ return /* @__PURE__ */ jsx20("div", { className: cn("min-w-0", className), "data-opengeni-pierre-file": true, style: pierreVars, children: /* @__PURE__ */ jsx20(Suspense4, { fallback: loading ?? /* @__PURE__ */ jsx20(FileSkeleton, {}), children: /* @__PURE__ */ jsx20(
9130
9238
  LazyFile,
9131
9239
  {
9132
9240
  file: { name, contents },
@@ -9153,9 +9261,9 @@ function FileSkeleton() {
9153
9261
  import { Loader2Icon as Loader2Icon2, SaveIcon } from "lucide-react";
9154
9262
  import {
9155
9263
  useCallback as useCallback22,
9156
- useEffect as useEffect23,
9264
+ useEffect as useEffect24,
9157
9265
  useMemo as useMemo10,
9158
- useRef as useRef19,
9266
+ useRef as useRef20,
9159
9267
  useState as useState26
9160
9268
  } from "react";
9161
9269
  import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
@@ -9224,9 +9332,9 @@ function CodeEditor({
9224
9332
  const [savedTick, setSavedTick] = useState26(false);
9225
9333
  const dirty = value !== baseline;
9226
9334
  const saveConflict = saveError !== null && saveError.code === "file_write_conflict";
9227
- const editIntentFiredRef = useRef19(false);
9228
- const lastSeed = useRef19({ path, contents: initialContents });
9229
- useEffect23(() => {
9335
+ const editIntentFiredRef = useRef20(false);
9336
+ const lastSeed = useRef20({ path, contents: initialContents });
9337
+ useEffect24(() => {
9230
9338
  const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
9231
9339
  if (!seedChanged) return;
9232
9340
  lastSeed.current = { path, contents: initialContents };
@@ -9248,7 +9356,7 @@ function CodeEditor({
9248
9356
  [baseline, onEditIntent]
9249
9357
  );
9250
9358
  const langKey = useMemo10(() => languageForPath(path), [path]);
9251
- useEffect23(() => {
9359
+ useEffect24(() => {
9252
9360
  let cancelled = false;
9253
9361
  void (async () => {
9254
9362
  try {
@@ -9288,7 +9396,7 @@ function CodeEditor({
9288
9396
  cancelled = true;
9289
9397
  };
9290
9398
  }, [langKey]);
9291
- const saveRef = useRef19(() => {
9399
+ const saveRef = useRef20(() => {
9292
9400
  });
9293
9401
  const save = useCallback22(async () => {
9294
9402
  if (readOnly) return;
@@ -9329,7 +9437,7 @@ function CodeEditor({
9329
9437
  saveRef.current = () => {
9330
9438
  void save();
9331
9439
  };
9332
- useEffect23(() => {
9440
+ useEffect24(() => {
9333
9441
  if (!savedTick) return;
9334
9442
  const t = setTimeout(() => setSavedTick(false), 1800);
9335
9443
  return () => clearTimeout(t);
@@ -9491,7 +9599,7 @@ function EditorSkeleton() {
9491
9599
 
9492
9600
  // src/components/sandbox-files.tsx
9493
9601
  import { FileCode2Icon, FileWarningIcon, LoaderCircleIcon } from "lucide-react";
9494
- import { useCallback as useCallback23, useEffect as useEffect24, useRef as useRef20, useState as useState27 } from "react";
9602
+ import { useCallback as useCallback23, useEffect as useEffect25, useRef as useRef21, useState as useState27 } from "react";
9495
9603
  import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
9496
9604
  function SandboxFiles({
9497
9605
  files,
@@ -9514,10 +9622,10 @@ function SandboxFiles({
9514
9622
  const [editMode, setEditMode] = useState27(false);
9515
9623
  const [liveRequestedPath, setLiveRequestedPath] = useState27(null);
9516
9624
  const [viewReloadRevision, setViewReloadRevision] = useState27(0);
9517
- const pendingRequestRef = useRef20(null);
9518
- const handledRequestRef = useRef20(null);
9625
+ const pendingRequestRef = useRef21(null);
9626
+ const handledRequestRef = useRef21(null);
9519
9627
  const requestKey = requestedPath ? requestedPathRequestId ?? requestedPath : null;
9520
- useEffect24(() => {
9628
+ useEffect25(() => {
9521
9629
  if (!requestedPath || requestKey === null) {
9522
9630
  pendingRequestRef.current = null;
9523
9631
  handledRequestRef.current = null;
@@ -9535,9 +9643,9 @@ function SandboxFiles({
9535
9643
  setSelected(requestedPath);
9536
9644
  setEditMode(false);
9537
9645
  }, [requestKey, requestedPath, requestedPathReady]);
9538
- const rootRef = useRef20(null);
9646
+ const rootRef = useRef21(null);
9539
9647
  const [wide, setWide] = useState27(false);
9540
- useEffect24(() => {
9648
+ useEffect25(() => {
9541
9649
  const el = rootRef.current;
9542
9650
  if (!el || typeof ResizeObserver === "undefined") return;
9543
9651
  const observer = new ResizeObserver((entries) => {
@@ -9832,7 +9940,7 @@ function useFileView(path, readFile, reloadRevision = 0) {
9832
9940
  loading: false,
9833
9941
  error: null
9834
9942
  });
9835
- useEffect24(() => {
9943
+ useEffect25(() => {
9836
9944
  if (!path) {
9837
9945
  setState({
9838
9946
  content: null,
@@ -9923,7 +10031,7 @@ function Notice({
9923
10031
 
9924
10032
  // src/components/desktop-viewer.tsx
9925
10033
  import { LoaderCircleIcon as LoaderCircleIcon2, MonitorIcon, MousePointerClickIcon, WifiOffIcon } from "lucide-react";
9926
- import { useEffect as useEffect25, useRef as useRef21, useState as useState28 } from "react";
10034
+ import { useEffect as useEffect26, useRef as useRef22, useState as useState28 } from "react";
9927
10035
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
9928
10036
  var DESKTOP_MEDIA_BACKGROUND = "#000";
9929
10037
  function isHardUnavailable(reason) {
@@ -9956,7 +10064,7 @@ function DesktopViewer({
9956
10064
  connectTimeoutMs = 13e3,
9957
10065
  className
9958
10066
  }) {
9959
- const containerRef = useRef21(null);
10067
+ const containerRef = useRef22(null);
9960
10068
  const [consented, setConsented] = useState28(false);
9961
10069
  const [takeControl, setTakeControl] = useState28(interactive ?? false);
9962
10070
  const externallyControlled = interactive !== void 0;
@@ -9974,7 +10082,7 @@ function DesktopViewer({
9974
10082
  setConsented(true);
9975
10083
  onAcknowledge?.();
9976
10084
  };
9977
- useEffect25(() => {
10085
+ useEffect26(() => {
9978
10086
  if (!inControl || externallyControlled) return;
9979
10087
  const onKey = (event) => {
9980
10088
  if (event.ctrlKey && event.altKey && event.shiftKey && (event.key === "Control" || event.key === "Alt" || event.key === "Shift")) {
@@ -9998,10 +10106,10 @@ function DesktopViewer({
9998
10106
  });
9999
10107
  const connected = stream.state === "connected";
10000
10108
  const hasLiveUrl = Boolean(connectCapability?.url);
10001
- const streamStateRef = useRef21(stream.state);
10109
+ const streamStateRef = useRef22(stream.state);
10002
10110
  streamStateRef.current = stream.state;
10003
- const warmKeyRef = useRef21(null);
10004
- useEffect25(() => {
10111
+ const warmKeyRef = useRef22(null);
10112
+ useEffect26(() => {
10005
10113
  if (!isWatching || !coldWarmable || needsAck || viewerCapReached) {
10006
10114
  if (!coldWarmable) warmKeyRef.current = null;
10007
10115
  return;
@@ -10013,7 +10121,7 @@ function DesktopViewer({
10013
10121
  warmKeyRef.current = key;
10014
10122
  warm();
10015
10123
  }, [isWatching, coldWarmable, needsAck, viewerCapReached, capability, onWarm, onAcknowledge]);
10016
- useEffect25(() => {
10124
+ useEffect26(() => {
10017
10125
  if (!hasLiveUrl || typeof document === "undefined") return;
10018
10126
  const maybeReattach = () => {
10019
10127
  if (document.visibilityState !== "visible") return;
@@ -10024,7 +10132,7 @@ function DesktopViewer({
10024
10132
  }, [hasLiveUrl, connectCapability?.url]);
10025
10133
  const [connectTimedOut, setConnectTimedOut] = useState28(false);
10026
10134
  const [reconnectNonce, setReconnectNonce] = useState28(0);
10027
- useEffect25(() => {
10135
+ useEffect26(() => {
10028
10136
  setConnectTimedOut(false);
10029
10137
  if (!hasLiveUrl || connected || stream.error || connectTimeoutMs <= 0) return;
10030
10138
  const timer = setTimeout(() => setConnectTimedOut(true), connectTimeoutMs);
@@ -10303,10 +10411,10 @@ function defaultNotice(title, body, onRetry) {
10303
10411
  // src/components/workspace-dock.tsx
10304
10412
  import {
10305
10413
  useCallback as useCallback24,
10306
- useEffect as useEffect26,
10414
+ useEffect as useEffect27,
10307
10415
  useId as useId4,
10308
10416
  useLayoutEffect as useLayoutEffect3,
10309
- useRef as useRef22,
10417
+ useRef as useRef23,
10310
10418
  useState as useState29
10311
10419
  } from "react";
10312
10420
  import {
@@ -10337,7 +10445,7 @@ function getLayoutStorage() {
10337
10445
  return SERVER_LAYOUT_STORAGE;
10338
10446
  }
10339
10447
  }
10340
- var useDockLayoutEffect = typeof window === "undefined" ? useEffect26 : useLayoutEffect3;
10448
+ var useDockLayoutEffect = typeof window === "undefined" ? useEffect27 : useLayoutEffect3;
10341
10449
  var DOCK_OVERLAY_BREAKPOINT = 1024;
10342
10450
  function useIsNarrow(maxWidth) {
10343
10451
  const [narrow, setNarrow] = useState29(false);
@@ -10373,17 +10481,17 @@ function WorkspaceDock({
10373
10481
  className
10374
10482
  }) {
10375
10483
  const narrow = useIsNarrow(DOCK_OVERLAY_BREAKPOINT);
10376
- const rootRef = useRef22(null);
10377
- const reopenRef = useRef22(null);
10378
- const returnFocusRef = useRef22(null);
10379
- const initialNarrowFocusRef = useRef22(false);
10484
+ const rootRef = useRef23(null);
10485
+ const reopenRef = useRef23(null);
10486
+ const returnFocusRef = useRef23(null);
10487
+ const initialNarrowFocusRef = useRef23(false);
10380
10488
  const dockPanelRef = usePanelRef();
10381
10489
  const [internalCollapsed, setInternalCollapsed] = useState29(false);
10382
10490
  const [maximized, setMaximized] = useState29(false);
10383
10491
  const [internalTab, setInternalTab] = useState29(tabs[0]?.id ?? "");
10384
10492
  const collapsed = collapsedProp ?? internalCollapsed;
10385
10493
  const hostControlled = collapsedProp !== void 0;
10386
- const previousCollapsedRef = useRef22(collapsed);
10494
+ const previousCollapsedRef = useRef23(collapsed);
10387
10495
  const { defaultLayout, onLayoutChanged } = useDefaultLayout({
10388
10496
  panelIds: ["primary", "dock"],
10389
10497
  storage: getLayoutStorage(),
@@ -10419,7 +10527,7 @@ function WorkspaceDock({
10419
10527
  dockPanelRef.current?.expand();
10420
10528
  }
10421
10529
  }, [collapsedProp, dockPanelRef]);
10422
- useEffect26(() => {
10530
+ useEffect27(() => {
10423
10531
  const previous = previousCollapsedRef.current;
10424
10532
  previousCollapsedRef.current = collapsed;
10425
10533
  if (previous === collapsed) return;
@@ -10449,7 +10557,7 @@ function WorkspaceDock({
10449
10557
  });
10450
10558
  return () => cancelAnimationFrame(frame);
10451
10559
  }, [collapsed, hostControlled, narrow]);
10452
- useEffect26(() => {
10560
+ useEffect27(() => {
10453
10561
  if (!narrow || collapsed || initialNarrowFocusRef.current) return;
10454
10562
  initialNarrowFocusRef.current = true;
10455
10563
  const active = document.activeElement;
@@ -10462,7 +10570,7 @@ function WorkspaceDock({
10462
10570
  });
10463
10571
  return () => cancelAnimationFrame(frame);
10464
10572
  }, [collapsed, narrow]);
10465
- useEffect26(() => {
10573
+ useEffect27(() => {
10466
10574
  if (firstTabId && !requestedTabIsValid) {
10467
10575
  setTab(firstTabId);
10468
10576
  }
@@ -10475,7 +10583,7 @@ function WorkspaceDock({
10475
10583
  dockPanelRef.current?.expand();
10476
10584
  setCollapsed(false);
10477
10585
  }, [dockPanelRef, setCollapsed]);
10478
- useEffect26(() => {
10586
+ useEffect27(() => {
10479
10587
  const overlayOpen = maximized || narrow && !collapsed;
10480
10588
  if (!overlayOpen) return;
10481
10589
  const onKey = (event) => {
@@ -10692,8 +10800,8 @@ function DockChrome({
10692
10800
  }) {
10693
10801
  const active = tabs.find((t) => t.id === current) ?? tabs[0];
10694
10802
  const tabsetId = useId4();
10695
- const tabRefs = useRef22([]);
10696
- const tabListRef = useRef22(null);
10803
+ const tabRefs = useRef23([]);
10804
+ const tabListRef = useRef23(null);
10697
10805
  const [visitedTabs, setVisitedTabs] = useState29(() => /* @__PURE__ */ new Set());
10698
10806
  const [tabOverflow, setTabOverflow] = useState29({ start: false, end: false });
10699
10807
  const activeId = active?.id ?? "";
@@ -10702,7 +10810,7 @@ function DockChrome({
10702
10810
  const selected = activeTabIndex >= 0 ? tabRefs.current[activeTabIndex] : null;
10703
10811
  selected?.scrollIntoView({ block: "nearest", inline: "nearest" });
10704
10812
  }, [activeTabIndex]);
10705
- useEffect26(() => {
10813
+ useEffect27(() => {
10706
10814
  if (!activeId) return;
10707
10815
  setVisitedTabs((previous) => {
10708
10816
  if (previous.has(activeId)) return previous;
@@ -10824,7 +10932,7 @@ function DockChrome({
10824
10932
  }
10825
10933
 
10826
10934
  // src/components/sandbox-workspace.tsx
10827
- import { useCallback as useCallback27, useEffect as useEffect29, useMemo as useMemo13, useRef as useRef25, useState as useState32 } from "react";
10935
+ import { useCallback as useCallback27, useEffect as useEffect30, useMemo as useMemo13, useRef as useRef26, useState as useState32 } from "react";
10828
10936
  import { Popover } from "radix-ui";
10829
10937
  import {
10830
10938
  CircleCheckIcon,
@@ -10839,17 +10947,17 @@ import {
10839
10947
  import { ArrowUpRightIcon, FileWarningIcon as FileWarningIcon2, HistoryIcon } from "lucide-react";
10840
10948
  import {
10841
10949
  useCallback as useCallback26,
10842
- useEffect as useEffect28,
10950
+ useEffect as useEffect29,
10843
10951
  useId as useId5,
10844
10952
  useLayoutEffect as useLayoutEffect4,
10845
10953
  useMemo as useMemo12,
10846
- useRef as useRef24,
10954
+ useRef as useRef25,
10847
10955
  useState as useState31
10848
10956
  } from "react";
10849
10957
  import { VList as VList2 } from "virtua";
10850
10958
 
10851
10959
  // src/hooks/use-windowed-sections.ts
10852
- import { useCallback as useCallback25, useEffect as useEffect27, useMemo as useMemo11, useRef as useRef23, useState as useState30 } from "react";
10960
+ import { useCallback as useCallback25, useEffect as useEffect28, useMemo as useMemo11, useRef as useRef24, useState as useState30 } from "react";
10853
10961
  function computeWindowRange(heights, scrollTop, viewport, overscan) {
10854
10962
  const n = heights.length;
10855
10963
  if (n === 0) return { start: 0, end: 0 };
@@ -10880,17 +10988,17 @@ function computeWindowRange(heights, scrollTop, viewport, overscan) {
10880
10988
  }
10881
10989
  function useWindowedSections(opts) {
10882
10990
  const { count, estimateHeight, overscan = 3 } = opts;
10883
- const scrollRef = useRef23(null);
10991
+ const scrollRef = useRef24(null);
10884
10992
  const [heights, setHeights] = useState30(
10885
10993
  () => Array.from({ length: count }, (_, i) => estimateHeight(i))
10886
10994
  );
10887
- useEffect27(() => {
10995
+ useEffect28(() => {
10888
10996
  setHeights((prev) => {
10889
10997
  if (prev.length === count) return prev;
10890
10998
  return Array.from({ length: count }, (_, i) => prev[i] ?? estimateHeight(i));
10891
10999
  });
10892
11000
  }, [count]);
10893
- const heightsRef = useRef23(heights);
11001
+ const heightsRef = useRef24(heights);
10894
11002
  heightsRef.current = heights;
10895
11003
  const [range, setRange] = useState30(() => ({
10896
11004
  start: 0,
@@ -10902,7 +11010,7 @@ function useWindowedSections(opts) {
10902
11010
  const next = computeWindowRange(heightsRef.current, el.scrollTop, el.clientHeight, overscan);
10903
11011
  setRange((prev) => prev.start === next.start && prev.end === next.end ? prev : next);
10904
11012
  }, [overscan]);
10905
- useEffect27(() => {
11013
+ useEffect28(() => {
10906
11014
  const el = scrollRef.current;
10907
11015
  if (!el) return;
10908
11016
  let raf = 0;
@@ -10938,7 +11046,7 @@ function useWindowedSections(opts) {
10938
11046
  for (let i = 0; i < count; i++) out[i + 1] = (out[i] ?? 0) + Math.max(heights[i] ?? 0, 0);
10939
11047
  return out;
10940
11048
  }, [heights, count]);
10941
- useEffect27(() => {
11049
+ useEffect28(() => {
10942
11050
  recompute();
10943
11051
  }, [offsets, recompute]);
10944
11052
  const scrollToIndex = useCallback25(
@@ -10968,7 +11076,7 @@ var HEADER_PX = 30;
10968
11076
  var LINE_PX = 18;
10969
11077
  var GUARD_BODY_PX = 52;
10970
11078
  var COMPACT_SURFACE_PX = 560;
10971
- var useChangesLayoutEffect = typeof window === "undefined" ? useEffect28 : useLayoutEffect4;
11079
+ var useChangesLayoutEffect = typeof window === "undefined" ? useEffect29 : useLayoutEffect4;
10972
11080
  var STATUS_TINT2 = {
10973
11081
  added: "text-og-status-idle",
10974
11082
  modified: "text-og-status-running",
@@ -11048,7 +11156,7 @@ function WorkbenchChanges({
11048
11156
  onOpenFile,
11049
11157
  className
11050
11158
  }) {
11051
- const rootRef = useRef24(null);
11159
+ const rootRef = useRef25(null);
11052
11160
  const [compact, setCompact] = useState31(false);
11053
11161
  const [coarsePointer, setCoarsePointer] = useState31(false);
11054
11162
  const resolvedTheme = useThemeType(themeType);
@@ -11126,7 +11234,7 @@ function WorkbenchChanges({
11126
11234
  const nextPath = orderedFiles[idx]?.path ?? null;
11127
11235
  setActivePath((previous) => previous === nextPath ? previous : nextPath);
11128
11236
  }, [windowed, orderedFiles]);
11129
- useEffect28(() => {
11237
+ useEffect29(() => {
11130
11238
  const el = windowed.scrollRef.current;
11131
11239
  if (!el) return;
11132
11240
  el.addEventListener("scroll", onPaneScroll, { passive: true });
@@ -11359,8 +11467,8 @@ function MeasuredSection({
11359
11467
  onMeasure,
11360
11468
  children
11361
11469
  }) {
11362
- const ref = useRef24(null);
11363
- useEffect28(() => {
11470
+ const ref = useRef25(null);
11471
+ useEffect29(() => {
11364
11472
  const el = ref.current;
11365
11473
  if (!el) return;
11366
11474
  const report = () => onMeasure(index, el.offsetHeight);
@@ -11580,8 +11688,8 @@ function useSandboxWorkspaceTabs(options) {
11580
11688
  const desktopAdvertised = desktopEnabled && ((capabilities?.DesktopStream.transport ?? null) !== null || capabilities?.DesktopStream.reason === "lease_cold");
11581
11689
  const provisioning = sandboxProvisionInFlight(events);
11582
11690
  const renegotiate = caps.renegotiate;
11583
- const provisioningRef = useRef25({ sessionId, provisioning });
11584
- useEffect29(() => {
11691
+ const provisioningRef = useRef26({ sessionId, provisioning });
11692
+ useEffect30(() => {
11585
11693
  const previous = provisioningRef.current;
11586
11694
  if (previous.sessionId === sessionId && previous.provisioning && !provisioning) {
11587
11695
  renegotiate();
@@ -11600,14 +11708,14 @@ function useSandboxWorkspaceTabs(options) {
11600
11708
  if (advertised.length > 0) return advertised;
11601
11709
  return captureState.capture?.repos.map((repo) => repo.root) ?? [];
11602
11710
  }, [capabilities?.Git.repos, captureState.capture]);
11603
- const notifiedCaptureDegradedReason = useRef25({
11711
+ const notifiedCaptureDegradedReason = useRef26({
11604
11712
  sessionId,
11605
11713
  reason: null
11606
11714
  });
11607
11715
  if (notifiedCaptureDegradedReason.current.sessionId !== sessionId) {
11608
11716
  notifiedCaptureDegradedReason.current = { sessionId, reason: null };
11609
11717
  }
11610
- useEffect29(() => {
11718
+ useEffect30(() => {
11611
11719
  const reason = captureState.degradedReason;
11612
11720
  if (!reason || notifiedCaptureDegradedReason.current.reason === reason) return;
11613
11721
  notifiedCaptureDegradedReason.current = { sessionId, reason };
@@ -11645,7 +11753,7 @@ function useSandboxWorkspaceTabs(options) {
11645
11753
  capture: captureState.capture
11646
11754
  });
11647
11755
  const [xtermTheme, setXtermTheme] = useState32(void 0);
11648
- useEffect29(() => {
11756
+ useEffect30(() => {
11649
11757
  if (!terminalEnabled || typeof document === "undefined") return;
11650
11758
  const derive = () => setXtermTheme(xtermThemeFromTokens());
11651
11759
  derive();
@@ -11687,7 +11795,7 @@ function useSandboxWorkspaceTabs(options) {
11687
11795
  });
11688
11796
  const workspaceWaking = chip.state === "waking";
11689
11797
  const defaultIdentity = `${sessionId}\0${surfaceIdentity}`;
11690
- const defaultTabRef = useRef25({
11798
+ const defaultTabRef = useRef26({
11691
11799
  identity: defaultIdentity,
11692
11800
  value: null
11693
11801
  });
@@ -11882,7 +11990,7 @@ function SandboxWorkspace(props) {
11882
11990
  } = props;
11883
11991
  const [storedSelection, setStoredSelection] = useState32(null);
11884
11992
  const [requestedFile, setRequestedFile] = useState32(null);
11885
- const nextFileRequestId = useRef25(0);
11993
+ const nextFileRequestId = useRef26(0);
11886
11994
  const openFile = useCallback27(
11887
11995
  (path) => {
11888
11996
  nextFileRequestId.current += 1;
@@ -11965,7 +12073,7 @@ function MachineStateChip({
11965
12073
  error,
11966
12074
  onRetry
11967
12075
  }) {
11968
- const triggerRef = useRef25(null);
12076
+ const triggerRef = useRef26(null);
11969
12077
  const portalStyle = usePortalTokenStyle(triggerRef);
11970
12078
  return /* @__PURE__ */ jsxs21(Popover.Root, { children: [
11971
12079
  /* @__PURE__ */ jsx26(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs21(