@opengeni/react 0.20.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 (60) hide show
  1. package/dist/{chunk-6BXBGJ3B.js → chunk-6XUS5VFM.js} +2 -2
  2. package/dist/{chunk-MRSECXRP.js → chunk-AVPU5PMC.js} +87 -57
  3. package/dist/chunk-AVPU5PMC.js.map +1 -0
  4. package/dist/{chunk-HHFA4AFX.js → chunk-I3BJZIG5.js} +15 -1
  5. package/dist/chunk-I3BJZIG5.js.map +1 -0
  6. package/dist/{chunk-LAZ2A743.js → chunk-RDPDU4TA.js} +8 -7
  7. package/dist/chunk-RDPDU4TA.js.map +1 -0
  8. package/dist/{chunk-6UT5OC3P.js → chunk-SHOFILHJ.js} +130 -16
  9. package/dist/chunk-SHOFILHJ.js.map +1 -0
  10. package/dist/{chunk-EBTT3MYN.js → chunk-YDNWMKXO.js} +11 -1
  11. package/dist/chunk-YDNWMKXO.js.map +1 -0
  12. package/dist/{composer-DvUaa5ki.d.ts → composer-BXb0Q1HF.d.ts} +19 -5
  13. package/dist/composer.d.ts +3 -3
  14. package/dist/composer.js +3 -3
  15. package/dist/fleet-decision-projection-SLNZMS42.js +241 -0
  16. package/dist/fleet-decision-projection-SLNZMS42.js.map +1 -0
  17. package/dist/fleet-decision-row-GGCAT4E4.js +351 -0
  18. package/dist/fleet-decision-row-GGCAT4E4.js.map +1 -0
  19. package/dist/index.d.ts +14 -11
  20. package/dist/index.js +466 -244
  21. package/dist/index.js.map +1 -1
  22. package/dist/machines.d.ts +1 -1
  23. package/dist/machines.js +2 -2
  24. package/dist/{queue-surface-implementation-NQMV2ML3.js → queue-surface-implementation-3UW3MIIR.js} +9 -9
  25. package/dist/queue-surface-implementation-3UW3MIIR.js.map +1 -0
  26. package/dist/{session-Gd4iVPYw.d.ts → session-BEvtFWhe.d.ts} +71 -24
  27. package/dist/{session-context-DIFFlXKc.d.ts → session-context-rgrfElMl.d.ts} +7 -1
  28. package/dist/session.d.ts +3 -3
  29. package/dist/session.js +7 -3
  30. package/dist/{use-composer-BCfm4mzX.d.ts → use-composer-BnEzheSk.d.ts} +13 -20
  31. package/package.json +2 -2
  32. package/src/client.ts +4 -0
  33. package/src/components/composer.tsx +7 -6
  34. package/src/components/message-timeline.tsx +197 -25
  35. package/src/components/queue-draft-policy.ts +18 -0
  36. package/src/components/queue-surface-implementation.tsx +6 -10
  37. package/src/components/queue-surface.tsx +1 -0
  38. package/src/hooks/use-composer.ts +143 -83
  39. package/src/hooks/use-file-attachments.ts +95 -2
  40. package/src/hooks/use-goal.ts +22 -4
  41. package/src/hooks/use-session-mcp-approval-policy.ts +161 -0
  42. package/src/hooks/use-workspace-sessions.ts +30 -5
  43. package/src/index.ts +9 -0
  44. package/src/session-context.ts +25 -0
  45. package/src/session.ts +10 -0
  46. package/src/timeline/activity-rail.tsx +17 -1
  47. package/src/timeline/fleet-decision-projection.ts +366 -0
  48. package/src/timeline/fleet-decision-row.tsx +412 -0
  49. package/src/timeline/index.ts +2 -0
  50. package/src/timeline/projection.ts +19 -8
  51. package/src/timeline/tool-display-name.ts +16 -0
  52. package/src/timeline/tool-renderers.tsx +1 -1
  53. package/src/timeline/types.ts +76 -16
  54. package/dist/chunk-6UT5OC3P.js.map +0 -1
  55. package/dist/chunk-EBTT3MYN.js.map +0 -1
  56. package/dist/chunk-HHFA4AFX.js.map +0 -1
  57. package/dist/chunk-LAZ2A743.js.map +0 -1
  58. package/dist/chunk-MRSECXRP.js.map +0 -1
  59. package/dist/queue-surface-implementation-NQMV2ML3.js.map +0 -1
  60. /package/dist/{chunk-6BXBGJ3B.js.map → chunk-6XUS5VFM.js.map} +0 -0
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  useChatComposerController,
37
37
  useSlashCommands,
38
38
  useTranscription
39
- } from "./chunk-LAZ2A743.js";
39
+ } from "./chunk-RDPDU4TA.js";
40
40
  import {
41
41
  CONNECTION_STATUS_META,
42
42
  ConnectionDot,
@@ -64,7 +64,7 @@ import {
64
64
  healthPulses,
65
65
  pointsFor,
66
66
  useMachines
67
- } from "./chunk-6BXBGJ3B.js";
67
+ } from "./chunk-6XUS5VFM.js";
68
68
  import {
69
69
  cn
70
70
  } from "./chunk-TK7G6XLT.js";
@@ -82,6 +82,7 @@ import {
82
82
  groupTimeline,
83
83
  humanInputRequestFromEvent,
84
84
  isHumanInputEvent,
85
+ isSessionMcpApprovalPolicyEvent,
85
86
  isTurnQueueEvent,
86
87
  projectPendingApprovals,
87
88
  projectPendingHumanInputRequests,
@@ -90,15 +91,16 @@ import {
90
91
  useHumanInputRequests,
91
92
  useSessionControl,
92
93
  useSessionEvents,
94
+ useSessionMcpApprovalPolicy,
93
95
  useTurnQueue
94
- } from "./chunk-6UT5OC3P.js";
96
+ } from "./chunk-SHOFILHJ.js";
95
97
  import {
96
98
  FILE_ONLY_MESSAGE_TEXT,
97
99
  composeSendInput,
98
100
  shouldSteerOnKey,
99
101
  shouldSubmitOnKey,
100
102
  useComposer
101
- } from "./chunk-MRSECXRP.js";
103
+ } from "./chunk-AVPU5PMC.js";
102
104
  import {
103
105
  CREDIT_EXHAUSTION_MESSAGE,
104
106
  formatBytes,
@@ -114,10 +116,10 @@ import {
114
116
  useOpenGeniClient,
115
117
  usePolledValue,
116
118
  useSessionEventTrigger
117
- } from "./chunk-HHFA4AFX.js";
119
+ } from "./chunk-I3BJZIG5.js";
118
120
  import {
119
121
  EmptyQueueStateSurface
120
- } from "./chunk-EBTT3MYN.js";
122
+ } from "./chunk-YDNWMKXO.js";
121
123
 
122
124
  // src/hooks/use-session.ts
123
125
  import { useCallback, useEffect, useState } from "react";
@@ -212,6 +214,7 @@ function useFileAttachments(options = {}) {
212
214
  contentType: file.type || "application/octet-stream",
213
215
  data: file
214
216
  }).then((asset) => {
217
+ sources.current.delete(id);
215
218
  setAttachments(
216
219
  (current) => current.map(
217
220
  (attachment) => attachment.id === id ? {
@@ -289,6 +292,52 @@ function useFileAttachments(options = {}) {
289
292
  },
290
293
  [addFiles, pasteFilter]
291
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
+ );
292
341
  const remove = useCallback2((id) => {
293
342
  sources.current.delete(id);
294
343
  setAttachments((current) => {
@@ -299,6 +348,20 @@ function useFileAttachments(options = {}) {
299
348
  return current.filter((attachment) => attachment.id !== id);
300
349
  });
301
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
+ }, []);
302
365
  const clear = useCallback2(() => {
303
366
  sources.current.clear();
304
367
  setAttachments((current) => {
@@ -316,10 +379,13 @@ function useFileAttachments(options = {}) {
316
379
  (attachment) => attachment.status === "ready" && attachment.file ? [{ kind: "file", fileId: attachment.file.id }] : []
317
380
  ),
318
381
  uploading: attachments.some((attachment) => attachment.status === "uploading"),
382
+ hasUnresolved: attachments.some((attachment) => attachment.status !== "ready"),
319
383
  addFiles,
320
384
  addFromPaste,
385
+ restoreReadyFiles,
321
386
  retry,
322
387
  remove,
388
+ removeReadyFiles,
323
389
  clear
324
390
  };
325
391
  }
@@ -328,7 +394,7 @@ function useFileAttachments(options = {}) {
328
394
  import { Loader2Icon } from "lucide-react";
329
395
  import { lazy, Suspense } from "react";
330
396
  import { jsx, jsxs } from "react/jsx-runtime";
331
- var loadQueueSurface = () => import("./queue-surface-implementation-NQMV2ML3.js");
397
+ var loadQueueSurface = () => import("./queue-surface-implementation-3UW3MIIR.js");
332
398
  var QueueSurface = createQueueSurface(loadQueueSurface);
333
399
  function createQueueSurface(loadImplementation) {
334
400
  const LazyQueueSurface = lazy(async () => ({
@@ -446,6 +512,10 @@ import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2
446
512
  function isGoalEvent(event) {
447
513
  return event.type.startsWith("goal.");
448
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
+ }
449
519
  function useGoal(sessionId, options = {}) {
450
520
  const { client, workspaceId } = useOpenGeni(options);
451
521
  const enabled = (options.enabled ?? true) && Boolean(sessionId);
@@ -514,7 +584,7 @@ function useGoal(sessionId, options = {}) {
514
584
  };
515
585
  }, [load, enabled, workspaceId, sessionId, options.pollIntervalMs, sharedFeed]);
516
586
  const scheduleRefresh = useDebouncedCallback(() => void load());
517
- useSessionEventTrigger(client, workspaceId, sessionId, isGoalEvent, scheduleRefresh, {
587
+ useSessionEventTrigger(client, workspaceId, sessionId, isGoalRefreshEvent, scheduleRefresh, {
518
588
  enabled,
519
589
  ...sharedEvents !== void 0 ? { events: sharedEvents } : {}
520
590
  });
@@ -600,14 +670,28 @@ function useScheduledTasks(options = {}) {
600
670
  }
601
671
 
602
672
  // src/hooks/use-workspace-sessions.ts
603
- import { useCallback as useCallback5 } from "react";
673
+ import { useCallback as useCallback5, useEffect as useEffect3, useRef as useRef3 } from "react";
604
674
  function useWorkspaceSessions(options = {}) {
605
675
  const { client, workspaceId } = useOpenGeni(options);
606
676
  const limit = options.limit;
607
677
  const parentSessionId = options.parentSessionId;
608
678
  const cursor = options.cursor;
609
679
  const search = options.search;
610
- 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]);
611
695
  const load = useCallback5(
612
696
  async () => ({
613
697
  queryKey,
@@ -615,14 +699,15 @@ function useWorkspaceSessions(options = {}) {
615
699
  ...limit !== void 0 ? { limit } : {},
616
700
  ...parentSessionId !== void 0 ? { parentSessionId } : {},
617
701
  ...cursor !== void 0 ? { cursor } : {},
618
- ...search !== void 0 ? { search } : {}
702
+ ...search !== void 0 ? { search } : {},
703
+ ...pinsOnly ? { pinsOnly: true } : {}
619
704
  })
620
705
  }),
621
- [client, workspaceId, limit, parentSessionId, cursor, search, queryKey]
706
+ [client, workspaceId, limit, parentSessionId, cursor, search, pinsOnly, queryKey]
622
707
  );
623
708
  const state = usePolledValue(load, {
624
709
  pollIntervalMs: options.pollIntervalMs,
625
- enabled: options.enabled
710
+ enabled
626
711
  });
627
712
  const page = state.data?.queryKey === queryKey ? state.data.page : null;
628
713
  const pinned = page?.pinned ?? [];
@@ -635,14 +720,18 @@ function useWorkspaceSessions(options = {}) {
635
720
  pinned,
636
721
  pinnedTruncated: page?.pinnedTruncated ?? false,
637
722
  nextCursor: page?.nextCursor ?? null,
638
- 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),
639
728
  error: state.error,
640
729
  refresh: state.refresh
641
730
  };
642
731
  }
643
732
 
644
733
  // src/hooks/use-session-lineage.ts
645
- 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";
646
735
  function isLineageRefreshEvent(event) {
647
736
  if (event.type === "session.status.changed" || event.type === "session.created") {
648
737
  return true;
@@ -671,16 +760,16 @@ function useSessionLineage(sessionId, options = {}) {
671
760
  );
672
761
  const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });
673
762
  const refresh = state.refresh;
674
- useEffect3(() => {
763
+ useEffect4(() => {
675
764
  if (enabled && workspaceControlEvent) void refresh();
676
765
  }, [enabled, refresh, workspaceControlEvent]);
677
- useEffect3(() => {
766
+ useEffect4(() => {
678
767
  if (!sessionId || !enabled) return;
679
768
  return registerSessionReconciler(sessionId, "lineage", refresh);
680
769
  }, [enabled, refresh, registerSessionReconciler, sessionId]);
681
770
  const refreshSoon = useDebouncedCallback(() => void refresh(), 150);
682
- const delayedChildRefreshRef = useRef3(null);
683
- useEffect3(() => {
771
+ const delayedChildRefreshRef = useRef4(null);
772
+ useEffect4(() => {
684
773
  return () => {
685
774
  if (delayedChildRefreshRef.current !== null) {
686
775
  clearTimeout(delayedChildRefreshRef.current);
@@ -1203,7 +1292,7 @@ import {
1203
1292
  OpenGeniApiError as OpenGeniApiError2,
1204
1293
  applyUrlRotation
1205
1294
  } from "@opengeni/sdk";
1206
- 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";
1207
1296
  function desktopAttachable(cell) {
1208
1297
  if (cell.transport !== null) return true;
1209
1298
  return cell.reason === "lease_cold" || cell.reason === "not_provisioned" || cell.reason === null;
@@ -1240,13 +1329,13 @@ function useSessionCapabilities(sessionId, options = {}) {
1240
1329
  const [viewerId, setViewerId] = useState4(null);
1241
1330
  const [stateIdentity, setStateIdentity] = useState4(identityKey);
1242
1331
  const [nonce, setNonce] = useState4(0);
1243
- const epochRef = useRef4(0);
1244
- const viewerIdRef = useRef4(null);
1245
- const previousIdentityRef = useRef4(identityKey);
1332
+ const epochRef = useRef5(0);
1333
+ const viewerIdRef = useRef5(null);
1334
+ const previousIdentityRef = useRef5(identityKey);
1246
1335
  const renegotiate = useCallback13(() => {
1247
1336
  setNonce((n) => n + 1);
1248
1337
  }, []);
1249
- useEffect4(() => {
1338
+ useEffect5(() => {
1250
1339
  const identityChanged = previousIdentityRef.current !== identityKey;
1251
1340
  previousIdentityRef.current = identityKey;
1252
1341
  if (identityChanged) {
@@ -1443,7 +1532,7 @@ function useSessionCapabilities(sessionId, options = {}) {
1443
1532
  identityKey
1444
1533
  ]);
1445
1534
  const events = options.events;
1446
- useEffect4(() => {
1535
+ useEffect5(() => {
1447
1536
  if (!events || events.length === 0) return;
1448
1537
  setCapabilities((prev) => {
1449
1538
  if (!prev || !prev.DesktopStream.url) return prev;
@@ -1480,7 +1569,7 @@ import {
1480
1569
  desktopSocketUrl,
1481
1570
  nextDesktopState
1482
1571
  } from "@opengeni/sdk";
1483
- 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";
1484
1573
 
1485
1574
  // src/lib/relay-wire.ts
1486
1575
  import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
@@ -1553,7 +1642,7 @@ function decodeStreamFrame(bytes) {
1553
1642
  }
1554
1643
 
1555
1644
  // src/hooks/use-relay-frame-stream.ts
1556
- 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";
1557
1646
  var TAG_OPEN = 1;
1558
1647
  var TAG_OPENACK = 2;
1559
1648
  var TAG_FRAME = 3;
@@ -1571,7 +1660,7 @@ function useRelayFrameStream(options) {
1571
1660
  const [state, setState] = useState5("idle");
1572
1661
  const [error, setError] = useState5(null);
1573
1662
  const [nonce, setNonce] = useState5(0);
1574
- const stateRef = useRef5("idle");
1663
+ const stateRef = useRef6("idle");
1575
1664
  const setBoth = (next) => {
1576
1665
  stateRef.current = next;
1577
1666
  setState(next);
@@ -1580,9 +1669,9 @@ function useRelayFrameStream(options) {
1580
1669
  const transport = capability?.transport ?? null;
1581
1670
  const url = capability?.url ?? null;
1582
1671
  const token = capability?.token ?? null;
1583
- const factoryRef = useRef5(webSocketFactory);
1672
+ const factoryRef = useRef6(webSocketFactory);
1584
1673
  factoryRef.current = webSocketFactory;
1585
- useEffect5(() => {
1674
+ useEffect6(() => {
1586
1675
  if (typeof window === "undefined") return;
1587
1676
  if (transport !== "relay-frames" || !url) {
1588
1677
  setBoth("idle");
@@ -1775,7 +1864,7 @@ function useDesktopStream(options) {
1775
1864
  const [state, setState] = useState6("idle");
1776
1865
  const [error, setError] = useState6(null);
1777
1866
  const [nonce, setNonce] = useState6(0);
1778
- const stateRef = useRef6("idle");
1867
+ const stateRef = useRef7("idle");
1779
1868
  const setBoth = (next) => {
1780
1869
  stateRef.current = next;
1781
1870
  setState(next);
@@ -1785,17 +1874,17 @@ function useDesktopStream(options) {
1785
1874
  const token = capability?.token ?? null;
1786
1875
  const transport = capability?.transport ?? null;
1787
1876
  const mode = capability?.mode ?? "read-only";
1788
- const rfbRef = useRef6(null);
1789
- const interactiveRef = useRef6(interactive);
1790
- const scaleViewportRef = useRef6(scaleViewport);
1791
- const modeRef = useRef6(mode);
1792
- 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);
1793
1882
  interactiveRef.current = interactive;
1794
1883
  scaleViewportRef.current = scaleViewport;
1795
1884
  modeRef.current = mode;
1796
1885
  rfbFactoryRef.current = rfbFactory;
1797
1886
  const viewOnlyFor = (m, want) => m === "read-only" || !want;
1798
- useEffect6(() => {
1887
+ useEffect7(() => {
1799
1888
  if (typeof window === "undefined") return;
1800
1889
  if (transport !== "vnc-ws" || !url) {
1801
1890
  setBoth("idle");
@@ -1858,11 +1947,11 @@ function useDesktopStream(options) {
1858
1947
  }
1859
1948
  };
1860
1949
  }, [url, token, transport, nonce]);
1861
- useEffect6(() => {
1950
+ useEffect7(() => {
1862
1951
  const rfb = rfbRef.current;
1863
1952
  if (rfb) rfb.viewOnly = viewOnlyFor(mode, interactive);
1864
1953
  }, [interactive, mode, state]);
1865
- useEffect6(() => {
1954
+ useEffect7(() => {
1866
1955
  const rfb = rfbRef.current;
1867
1956
  if (rfb) {
1868
1957
  rfb.clipViewport = false;
@@ -1882,7 +1971,7 @@ import {
1882
1971
  ttydResizeFrame,
1883
1972
  TtydServerCommand
1884
1973
  } from "@opengeni/sdk";
1885
- 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";
1886
1975
  function decodeFrame(data) {
1887
1976
  if (typeof data === "string") {
1888
1977
  return { command: data.charAt(0), payload: data.slice(1) };
@@ -1895,19 +1984,19 @@ function decodeFrame(data) {
1895
1984
  function useTerminalStream(options) {
1896
1985
  const { capability, onOutput, onTitle, initialCols, initialRows } = options;
1897
1986
  const [status, setStatus] = useState7("closed");
1898
- const wsRef = useRef7(null);
1899
- const sizeRef = useRef7({
1987
+ const wsRef = useRef8(null);
1988
+ const sizeRef = useRef8({
1900
1989
  cols: initialCols ?? 80,
1901
1990
  rows: initialRows ?? 24
1902
1991
  });
1903
- const onOutputRef = useRef7(onOutput);
1904
- const onTitleRef = useRef7(onTitle);
1992
+ const onOutputRef = useRef8(onOutput);
1993
+ const onTitleRef = useRef8(onTitle);
1905
1994
  onOutputRef.current = onOutput;
1906
1995
  onTitleRef.current = onTitle;
1907
1996
  const transport = capability?.transport ?? null;
1908
1997
  const url = capability?.url ?? null;
1909
1998
  const token = capability?.token ?? null;
1910
- useEffect7(() => {
1999
+ useEffect8(() => {
1911
2000
  if (typeof window === "undefined" || typeof WebSocket === "undefined") return;
1912
2001
  if (transport !== "pty-ws" || !url) {
1913
2002
  setStatus("closed");
@@ -2004,7 +2093,7 @@ function useTerminalStream(options) {
2004
2093
 
2005
2094
  // src/hooks/use-sandbox-terminal.ts
2006
2095
  import { OpenGeniApiError as OpenGeniApiError3 } from "@opengeni/sdk";
2007
- 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";
2008
2097
  function useSandboxTerminal(sessionId, options) {
2009
2098
  const { client, workspaceId } = useOpenGeni(options);
2010
2099
  const includeAgentFirehose = options.includeAgentFirehose ?? true;
@@ -2016,16 +2105,16 @@ function useSandboxTerminal(sessionId, options) {
2016
2105
  const [openError, setOpenError] = useState8(null);
2017
2106
  const [stateIdentity, setStateIdentity] = useState8(identityKey);
2018
2107
  const [reopenNonce, setReopenNonce] = useState8(0);
2019
- const currentIdentityRef = useRef8(identityKey);
2108
+ const currentIdentityRef = useRef9(identityKey);
2020
2109
  currentIdentityRef.current = identityKey;
2021
- useEffect8(() => {
2110
+ useEffect9(() => {
2022
2111
  setStateIdentity(identityKey);
2023
2112
  setOpenedPtyId(null);
2024
2113
  setOpenError(null);
2025
2114
  }, [identityKey]);
2026
- const openInFlight = useRef8(false);
2115
+ const openInFlight = useRef9(false);
2027
2116
  const boxWarm = liveness === void 0 || liveness === "warm" || liveness === "draining";
2028
- useEffect8(() => {
2117
+ useEffect9(() => {
2029
2118
  if (!interactive || !sessionId || ptyFilter || !boxWarm) {
2030
2119
  setOpenError(null);
2031
2120
  return;
@@ -2136,7 +2225,7 @@ function useSandboxTerminal(sessionId, options) {
2136
2225
  }
2137
2226
 
2138
2227
  // src/hooks/use-sandbox-files.ts
2139
- 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";
2140
2229
  var CapturedFileUnavailableError = class extends Error {
2141
2230
  constructor(path, reason) {
2142
2231
  super(
@@ -2321,23 +2410,23 @@ function useSandboxFiles(sessionId, options = {}) {
2321
2410
  const isLive2 = options.liveness === "warm" || options.liveness === "draining";
2322
2411
  const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${rootPath}`;
2323
2412
  const [tree, setTree] = useState9([]);
2324
- const treeRef = useRef9([]);
2413
+ const treeRef = useRef10([]);
2325
2414
  const [loading, setLoading] = useState9(false);
2326
2415
  const [expandingPaths, setExpandingPaths] = useState9(/* @__PURE__ */ new Set());
2327
2416
  const [error, setError] = useState9(null);
2328
2417
  const [stateIdentity, setStateIdentity] = useState9(identityKey);
2329
2418
  const [source, setSource] = useState9(null);
2330
- const sourceRef = useRef9(null);
2331
- const statusRef = useRef9(/* @__PURE__ */ new Map());
2332
- const refreshGenerationRef = useRef9(0);
2333
- const refreshAbortRef = useRef9(null);
2334
- const identityAbortRef = useRef9(new AbortController());
2335
- const identityGenerationRef = useRef9(0);
2336
- const lastSeqRef = useRef9(0);
2337
- const pendingParentsRef = useRef9(/* @__PURE__ */ new Set());
2338
- const pendingGitRef = useRef9(false);
2339
- const debounceRef = useRef9(null);
2340
- 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());
2341
2430
  const onMutationError = options.onMutationError;
2342
2431
  treeRef.current = tree;
2343
2432
  const applyStatus = useCallback15((nodes) => {
@@ -2704,11 +2793,11 @@ function useSandboxFiles(sessionId, options = {}) {
2704
2793
  },
2705
2794
  [client, workspaceId, sessionId, runOptimistic]
2706
2795
  );
2707
- const captureRef = useRef9(capture);
2796
+ const captureRef = useRef10(capture);
2708
2797
  captureRef.current = capture;
2709
2798
  const captureRevision = capture?.revision ?? null;
2710
- const previousIdentityRef = useRef9(identityKey);
2711
- useEffect9(() => {
2799
+ const previousIdentityRef = useRef10(identityKey);
2800
+ useEffect10(() => {
2712
2801
  refreshAbortRef.current?.abort();
2713
2802
  refreshAbortRef.current = null;
2714
2803
  refreshGenerationRef.current += 1;
@@ -2776,7 +2865,7 @@ function useSandboxFiles(sessionId, options = {}) {
2776
2865
  }
2777
2866
  }, [client, workspaceId, sessionId, rootPath, applyStatus]);
2778
2867
  const events = options.events;
2779
- useEffect9(() => {
2868
+ useEffect10(() => {
2780
2869
  if (!enabled || !events) return;
2781
2870
  let sawNew = false;
2782
2871
  for (const event of events) {
@@ -2822,7 +2911,7 @@ function useSandboxFiles(sessionId, options = {}) {
2822
2911
  })();
2823
2912
  }, 150);
2824
2913
  }, [enabled, events, reconcilePath, refreshGitOverlay]);
2825
- useEffect9(
2914
+ useEffect10(
2826
2915
  () => () => {
2827
2916
  refreshAbortRef.current?.abort();
2828
2917
  identityAbortRef.current.abort();
@@ -2851,7 +2940,7 @@ function useSandboxFiles(sessionId, options = {}) {
2851
2940
  }
2852
2941
 
2853
2942
  // src/hooks/use-sandbox-git.ts
2854
- 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";
2855
2944
  function normalizeRoot(root) {
2856
2945
  const normalized = root.replaceAll("\\", "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
2857
2946
  return normalized === "." ? "" : normalized;
@@ -2927,13 +3016,13 @@ function useSandboxGit(sessionId, options = {}) {
2927
3016
  const [behind, setBehind] = useState10(0);
2928
3017
  const [repoRoots, setRepoRoots] = useState10([]);
2929
3018
  const [source, setSource] = useState10(null);
2930
- const sourceRef = useRef10(null);
3019
+ const sourceRef = useRef11(null);
2931
3020
  const [loading, setLoading] = useState10(false);
2932
3021
  const [error, setError] = useState10(null);
2933
3022
  const [stateIdentity, setStateIdentity] = useState10(identityKey);
2934
- const refreshGenerationRef = useRef10(0);
2935
- const refreshAbortRef = useRef10(null);
2936
- const lastChangeRef = useRef10(0);
3023
+ const refreshGenerationRef = useRef11(0);
3024
+ const refreshAbortRef = useRef11(null);
3025
+ const lastChangeRef = useRef11(0);
2937
3026
  const refresh = useCallback16(async () => {
2938
3027
  if (!sessionId) return;
2939
3028
  refreshAbortRef.current?.abort();
@@ -3035,11 +3124,11 @@ function useSandboxGit(sessionId, options = {}) {
3035
3124
  },
3036
3125
  [repoPath, workspaceWide]
3037
3126
  );
3038
- const captureRef = useRef10(capture);
3127
+ const captureRef = useRef11(capture);
3039
3128
  captureRef.current = capture;
3040
3129
  const captureRevision = capture?.revision ?? null;
3041
- const previousIdentityRef = useRef10(identityKey);
3042
- useEffect10(() => {
3130
+ const previousIdentityRef = useRef11(identityKey);
3131
+ useEffect11(() => {
3043
3132
  refreshAbortRef.current?.abort();
3044
3133
  refreshAbortRef.current = null;
3045
3134
  refreshGenerationRef.current += 1;
@@ -3076,7 +3165,7 @@ function useSandboxGit(sessionId, options = {}) {
3076
3165
  };
3077
3166
  }, [enabled, isLive2, captureRevision, identityKey, refresh, seedFromCapture]);
3078
3167
  const events = options.events;
3079
- useEffect10(() => {
3168
+ useEffect11(() => {
3080
3169
  if (!enabled || !events) return;
3081
3170
  let latest = lastChangeRef.current;
3082
3171
  for (const event of events) {
@@ -3108,7 +3197,7 @@ function useSandboxGit(sessionId, options = {}) {
3108
3197
  }
3109
3198
 
3110
3199
  // src/hooks/use-workspace-capture.ts
3111
- 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";
3112
3201
  var REVISION_CAPTURED = "workspace.revision.captured";
3113
3202
  var REVISION_DEGRADED = "workspace.revision.degraded";
3114
3203
  var MANIFEST_FETCH_TIMEOUT_MS = 15e3;
@@ -3155,9 +3244,9 @@ function useWorkspaceCapture(sessionId, options = {}) {
3155
3244
  const [error, setError] = useState11(null);
3156
3245
  const [announcedRevision, setAnnouncedRevision] = useState11(null);
3157
3246
  const [stateIdentity, setStateIdentity] = useState11(identityKey);
3158
- const generationRef = useRef11(0);
3159
- const requestAbortRef = useRef11(null);
3160
- const lastSeqRef = useRef11(0);
3247
+ const generationRef = useRef12(0);
3248
+ const requestAbortRef = useRef12(null);
3249
+ const lastSeqRef = useRef12(0);
3161
3250
  const refresh = useCallback17(async () => {
3162
3251
  if (!sessionId) return;
3163
3252
  requestAbortRef.current?.abort();
@@ -3231,7 +3320,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3231
3320
  if (requestAbortRef.current === requestAbort) requestAbortRef.current = null;
3232
3321
  }
3233
3322
  }, [client, workspaceId, sessionId, identityKey]);
3234
- useEffect11(() => {
3323
+ useEffect12(() => {
3235
3324
  requestAbortRef.current?.abort();
3236
3325
  requestAbortRef.current = null;
3237
3326
  generationRef.current += 1;
@@ -3254,7 +3343,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3254
3343
  };
3255
3344
  }, [enabled, refresh]);
3256
3345
  const events = options.events;
3257
- useEffect11(() => {
3346
+ useEffect12(() => {
3258
3347
  if (!enabled || !events) return;
3259
3348
  let newest = null;
3260
3349
  for (const event of events) {
@@ -3280,7 +3369,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3280
3369
  const visibleCapture = identityMatches ? capture : null;
3281
3370
  const visibleAnnouncedRevision = identityMatches ? announcedRevision : null;
3282
3371
  const loadedRevision = visibleCapture?.revision ?? null;
3283
- useEffect11(() => {
3372
+ useEffect12(() => {
3284
3373
  if (!enabled) return;
3285
3374
  if (visibleAnnouncedRevision === null) return;
3286
3375
  if (loadedRevision !== null && visibleAnnouncedRevision <= loadedRevision) return;
@@ -3302,7 +3391,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
3302
3391
  }
3303
3392
 
3304
3393
  // src/hooks/use-workspace-edit.ts
3305
- 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";
3306
3395
  function isLive(liveness) {
3307
3396
  return liveness === "warm" || liveness === "draining";
3308
3397
  }
@@ -3320,13 +3409,13 @@ function useWorkspaceEdit(sessionId, options = {}) {
3320
3409
  const [error, setError] = useState12(null);
3321
3410
  const [stateIdentity, setStateIdentity] = useState12(identityKey);
3322
3411
  const onWarmRequested = options.onWarmRequested;
3323
- const bufferRef = useRef12(null);
3412
+ const bufferRef = useRef13(null);
3324
3413
  bufferRef.current = buffer;
3325
- const flushingRef = useRef12(false);
3326
- const identityGenerationRef = useRef12(0);
3327
- const flushAttemptRef = useRef12(0);
3328
- const readAbortRef = useRef12(null);
3329
- useEffect12(() => {
3414
+ const flushingRef = useRef13(false);
3415
+ const identityGenerationRef = useRef13(0);
3416
+ const flushAttemptRef = useRef13(0);
3417
+ const readAbortRef = useRef13(null);
3418
+ useEffect13(() => {
3330
3419
  identityGenerationRef.current += 1;
3331
3420
  flushAttemptRef.current += 1;
3332
3421
  readAbortRef.current?.abort();
@@ -3411,7 +3500,7 @@ function useWorkspaceEdit(sessionId, options = {}) {
3411
3500
  },
3412
3501
  [client, workspaceId, sessionId, path, baseContent, stateIdentity, identityKey]
3413
3502
  );
3414
- useEffect12(() => {
3503
+ useEffect13(() => {
3415
3504
  if (offline) return;
3416
3505
  if (!live) return;
3417
3506
  if (buffer === null) return;
@@ -3524,7 +3613,7 @@ function useMachineChip(input) {
3524
3613
 
3525
3614
  // src/components/approval-surface.tsx
3526
3615
  import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
3527
- 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";
3528
3617
  import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3529
3618
  var defaultApprovalSurfaceMessages = {
3530
3619
  title: "Approval required",
@@ -3565,9 +3654,9 @@ function ApprovalSurface({
3565
3654
  const titleId = useId();
3566
3655
  const messages = { ...defaultApprovalSurfaceMessages, ...overrides };
3567
3656
  const [pending, setPending] = useState13(null);
3568
- const pendingRef = useRef13(null);
3657
+ const pendingRef = useRef14(null);
3569
3658
  const [decisionError, setDecisionError] = useState13(null);
3570
- useEffect13(() => {
3659
+ useEffect14(() => {
3571
3660
  if (pending && !approvals.some((approval) => approvalOwnershipKey(approval) === pending.approvalKey)) {
3572
3661
  if (pendingRef.current?.token === pending.token) {
3573
3662
  pendingRef.current = null;
@@ -3665,7 +3754,7 @@ function ApprovalSurface({
3665
3754
  }
3666
3755
 
3667
3756
  // src/components/human-input-form.tsx
3668
- 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";
3669
3758
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3670
3759
  var defaultHumanInputFormMessages = {
3671
3760
  title: "Your input is needed",
@@ -3708,10 +3797,10 @@ function HumanInputForm({
3708
3797
  const [validationErrors, setValidationErrors] = useState14({});
3709
3798
  const [submissionError, setSubmissionError] = useState14(null);
3710
3799
  const [submittingInternally, setSubmittingInternally] = useState14(false);
3711
- const submissionInFlight = useRef14(false);
3712
- const submissionGeneration = useRef14(0);
3800
+ const submissionInFlight = useRef15(false);
3801
+ const submissionGeneration = useRef15(0);
3713
3802
  const busy = submitting || submittingInternally;
3714
- useEffect14(() => {
3803
+ useEffect15(() => {
3715
3804
  submissionGeneration.current += 1;
3716
3805
  submissionInFlight.current = false;
3717
3806
  setDrafts(initialDrafts(request.questions));
@@ -4729,10 +4818,10 @@ function ScreenshotFigure({
4729
4818
  import { useState as useState19 } from "react";
4730
4819
 
4731
4820
  // src/lib/use-theme-type.ts
4732
- import { useEffect as useEffect15, useState as useState17 } from "react";
4821
+ import { useEffect as useEffect16, useState as useState17 } from "react";
4733
4822
  function useThemeType(forced) {
4734
4823
  const [detected, setDetected] = useState17("dark");
4735
- useEffect15(() => {
4824
+ useEffect16(() => {
4736
4825
  if (forced || typeof document === "undefined") return;
4737
4826
  const read = () => {
4738
4827
  const el = document.querySelector("[data-og-theme]");
@@ -4755,7 +4844,7 @@ function useThemeType(forced) {
4755
4844
  import {
4756
4845
  lazy as lazy2,
4757
4846
  Suspense as Suspense2,
4758
- useEffect as useEffect16,
4847
+ useEffect as useEffect17,
4759
4848
  useState as useState18
4760
4849
  } from "react";
4761
4850
 
@@ -4808,7 +4897,7 @@ function PierreDiff({
4808
4897
  }) {
4809
4898
  const [failed, setFailed] = useState18(false);
4810
4899
  const [forcedColors, setForcedColors] = useState18(false);
4811
- useEffect16(() => {
4900
+ useEffect17(() => {
4812
4901
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
4813
4902
  const query = window.matchMedia("(forced-colors: active)");
4814
4903
  const update = () => setForcedColors(query.matches);
@@ -4816,7 +4905,7 @@ function PierreDiff({
4816
4905
  query.addEventListener?.("change", update);
4817
4906
  return () => query.removeEventListener?.("change", update);
4818
4907
  }, []);
4819
- useEffect16(() => {
4908
+ useEffect17(() => {
4820
4909
  if (plain) return;
4821
4910
  let cancelled = false;
4822
4911
  void import("@pierre/diffs/react").catch(() => {
@@ -4956,6 +5045,13 @@ function RawPatch({ diff }) {
4956
5045
  ] });
4957
5046
  }
4958
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
+
4959
5055
  // src/timeline/tool-renderers.tsx
4960
5056
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
4961
5057
  var ICON_SIZE = "size-3.5";
@@ -5652,7 +5748,7 @@ function SecretSetRenderer({ item }) {
5652
5748
  function GenericRenderer({ item }) {
5653
5749
  const running = item.status === "running";
5654
5750
  const args = redactSecrets(parseToolArgs(item.arguments));
5655
- const display = toolDisplayName(item.name);
5751
+ const display = toolDisplayName2(item.name);
5656
5752
  if (running) {
5657
5753
  return /* @__PURE__ */ jsx10(
5658
5754
  ActivityDisclosure,
@@ -5742,19 +5838,22 @@ import {
5742
5838
  BrainIcon,
5743
5839
  SquareTerminalIcon
5744
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";
5745
5843
 
5746
5844
  // src/timeline/entrance.tsx
5747
- 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";
5748
5846
  var EntranceAnimationContext = createContext3(true);
5749
5847
  var EntranceAnimationProvider = EntranceAnimationContext.Provider;
5750
5848
  function useEntranceAnimation() {
5751
5849
  const enabled = useContext3(EntranceAnimationContext);
5752
- const captured = useRef15(enabled);
5850
+ const captured = useRef16(enabled);
5753
5851
  return captured.current;
5754
5852
  }
5755
5853
 
5756
5854
  // src/timeline/activity-rail.tsx
5757
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"));
5758
5857
  function familyOf(item) {
5759
5858
  if (item.kind === "tool-call") {
5760
5859
  return item.name === "exec_command" || item.name === "write_stdin" ? "terminal" : item.name;
@@ -5807,6 +5906,17 @@ function renderActivity(item, toolRegistry, onOpenSession, onMemoryClick) {
5807
5906
  return /* @__PURE__ */ jsx11(SandboxRow, { item });
5808
5907
  case "memory":
5809
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
+ ) });
5810
5920
  default:
5811
5921
  return assertNever(item);
5812
5922
  }
@@ -5898,7 +6008,7 @@ function sandboxRowTitle(item) {
5898
6008
  if (item.origin === "created") return "Sandbox created";
5899
6009
  return "Sandbox ready";
5900
6010
  }
5901
- return toolDisplayName(item.name);
6011
+ return toolDisplayName2(item.name);
5902
6012
  }
5903
6013
  function SandboxRow({ item }) {
5904
6014
  return /* @__PURE__ */ jsxs9(
@@ -6147,11 +6257,12 @@ import {
6147
6257
  import { AnimatePresence as AnimatePresence2, motion as motion2 } from "motion/react";
6148
6258
  import { Collapsible as Collapsible3 } from "radix-ui";
6149
6259
  import {
6260
+ memo as memo2,
6150
6261
  useCallback as useCallback20,
6151
- useEffect as useEffect17,
6262
+ useEffect as useEffect18,
6152
6263
  useLayoutEffect,
6153
6264
  useMemo as useMemo7,
6154
- useRef as useRef16,
6265
+ useRef as useRef17,
6155
6266
  useState as useState21
6156
6267
  } from "react";
6157
6268
 
@@ -6389,6 +6500,7 @@ function StatusDot({ status, className }) {
6389
6500
 
6390
6501
  // src/components/message-timeline.tsx
6391
6502
  import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
6503
+ var INITIAL_MOUNTED_GROUPS = 1;
6392
6504
  function MessageTimeline({
6393
6505
  events,
6394
6506
  items,
@@ -6407,15 +6519,17 @@ function MessageTimeline({
6407
6519
  className
6408
6520
  }) {
6409
6521
  const resolvedItems = useMemo7(() => items ?? buildTimeline(events ?? []), [items, events]);
6410
- const groups = useMemo7(() => groupTimeline(resolvedItems), [resolvedItems]);
6411
- const firstGroupKey = groups[0] ? timelineGroupKey(groups[0]) : null;
6412
- const scrollRef = useRef16(null);
6413
- const topSentinelRef = useRef16(null);
6414
- const previousBulkFirstKeyRef = useRef16(void 0);
6522
+ const allGroups = useMemo7(() => groupTimeline(resolvedItems), [resolvedItems]);
6523
+ const keyedGroups = useStableTimelineGroupKeys(allGroups);
6524
+ const { mountedGroups: groups, mountingOlderGroups } = useProgressivelyMountedGroups(keyedGroups);
6525
+ const firstGroupKey = allGroups[0] ? timelineGroupKey(allGroups[0]) : null;
6526
+ const scrollRef = useRef17(null);
6527
+ const topSentinelRef = useRef17(null);
6528
+ const previousBulkFirstKeyRef = useRef17(void 0);
6415
6529
  const [pinned, setPinned] = useState21(true);
6416
6530
  const [bulkActive, setBulkActive] = useState21(true);
6417
6531
  const [revealed, setRevealed] = useState21(false);
6418
- const programmaticScrollRef = useRef16(false);
6532
+ const programmaticScrollRef = useRef17(false);
6419
6533
  const assignScrollTop = useCallback20((node, value) => {
6420
6534
  const previous = node.scrollTop;
6421
6535
  programmaticScrollRef.current = true;
@@ -6424,13 +6538,13 @@ function MessageTimeline({
6424
6538
  programmaticScrollRef.current = false;
6425
6539
  }
6426
6540
  }, []);
6427
- const pinnedRef = useRef16(true);
6428
- const anchorRef = useRef16(null);
6541
+ const pinnedRef = useRef17(true);
6542
+ const anchorRef = useRef17(null);
6429
6543
  const lastItem = resolvedItems[resolvedItems.length - 1];
6430
6544
  const streaming = lastItem !== void 0 && (lastItem.kind === "agent-message" || lastItem.kind === "reasoning") && lastItem.streaming;
6431
6545
  const working = status === "running" && !streaming;
6432
6546
  const firstKeyChangedForBulk = previousBulkFirstKeyRef.current !== void 0 && previousBulkFirstKeyRef.current !== firstGroupKey;
6433
- const bulkRender = groups.length > 0 && (bulkActive || firstKeyChangedForBulk);
6547
+ const bulkRender = allGroups.length > 0 && (bulkActive || firstKeyChangedForBulk || mountingOlderGroups);
6434
6548
  const captureAnchor = useCallback20(() => {
6435
6549
  const node = scrollRef.current;
6436
6550
  const inner = node?.firstElementChild;
@@ -6461,23 +6575,26 @@ function MessageTimeline({
6461
6575
  }
6462
6576
  }, [resolvedItems, working, autoFollow, pinned, revealed, groups.length, assignScrollTop]);
6463
6577
  useLayoutEffect(() => {
6464
- if (groups.length === 0 && revealed) {
6578
+ if (allGroups.length === 0 && revealed) {
6465
6579
  setRevealed(false);
6466
6580
  }
6467
- }, [groups.length, revealed]);
6581
+ }, [allGroups.length, revealed]);
6468
6582
  useLayoutEffect(() => {
6469
6583
  previousBulkFirstKeyRef.current = firstGroupKey;
6470
6584
  if (!bulkRender) {
6471
6585
  return;
6472
6586
  }
6473
6587
  setBulkActive(true);
6588
+ if (mountingOlderGroups) {
6589
+ return;
6590
+ }
6474
6591
  const frame = requestFrame(() => setBulkActive(false));
6475
6592
  return () => cancelFrame(frame);
6476
- }, [bulkRender, firstGroupKey]);
6477
- useEffect17(() => {
6593
+ }, [bulkRender, firstGroupKey, mountingOlderGroups]);
6594
+ useEffect18(() => {
6478
6595
  const root = scrollRef.current;
6479
6596
  const target = topSentinelRef.current;
6480
- if (!root || !target || !hasOlder || loadingOlder || !onLoadOlder || typeof IntersectionObserver === "undefined") {
6597
+ if (!root || !target || mountingOlderGroups || !hasOlder || loadingOlder || !onLoadOlder || typeof IntersectionObserver === "undefined") {
6481
6598
  return;
6482
6599
  }
6483
6600
  const observer = new IntersectionObserver(
@@ -6490,8 +6607,8 @@ function MessageTimeline({
6490
6607
  );
6491
6608
  observer.observe(target);
6492
6609
  return () => observer.disconnect();
6493
- }, [hasOlder, loadingOlder, onLoadOlder, firstGroupKey]);
6494
- useEffect17(() => {
6610
+ }, [hasOlder, loadingOlder, onLoadOlder, firstGroupKey, mountingOlderGroups]);
6611
+ useEffect18(() => {
6495
6612
  const node = scrollRef.current;
6496
6613
  const inner = node?.firstElementChild;
6497
6614
  if (!node || !inner || typeof ResizeObserver === "undefined") {
@@ -6544,7 +6661,7 @@ function MessageTimeline({
6544
6661
  className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 [overflow-anchor:none] sm:px-6",
6545
6662
  children: /* @__PURE__ */ jsxs12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: [
6546
6663
  groups.length === 0 && !working ? emptyState ?? /* @__PURE__ */ jsx15("p", { className: "py-10 text-center text-sm text-og-fg-subtle", children: "No activity yet." }) : null,
6547
- hasOlder ? /* @__PURE__ */ jsx15(
6664
+ hasOlder && !mountingOlderGroups ? /* @__PURE__ */ jsx15(
6548
6665
  "div",
6549
6666
  {
6550
6667
  ref: topSentinelRef,
@@ -6555,7 +6672,7 @@ function MessageTimeline({
6555
6672
  }
6556
6673
  ) : null,
6557
6674
  loadingOlder ? /* @__PURE__ */ jsx15("div", { "data-og-timeline-chrome": "", className: "flex items-center gap-2 text-sm", children: /* @__PURE__ */ jsx15("span", { className: "og-shimmer-text font-medium", children: "Loading earlier activity\u2026" }) }) : null,
6558
- groups.map((group, index) => /* @__PURE__ */ jsx15(
6675
+ groups.map(({ group, key }, index) => /* @__PURE__ */ jsx15(
6559
6676
  TimelineGroupView,
6560
6677
  {
6561
6678
  group,
@@ -6565,9 +6682,9 @@ function MessageTimeline({
6565
6682
  onReconnect,
6566
6683
  resolveProviderLogo,
6567
6684
  toolRegistry,
6568
- foldLiveCluster: isAgentProgress(groups[index + 1])
6685
+ foldLiveCluster: isAgentProgress(groups[index + 1]?.group)
6569
6686
  },
6570
- timelineGroupKey(group)
6687
+ key
6571
6688
  )),
6572
6689
  working ? /* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2 text-sm", children: /* @__PURE__ */ jsx15("span", { className: "og-shimmer-text font-medium", children: "Working\u2026" }) }) : null
6573
6690
  ] })
@@ -6603,6 +6720,90 @@ function MessageTimeline({
6603
6720
  ) : null })
6604
6721
  ] }) }) });
6605
6722
  }
6723
+ function useStableTimelineGroupKeys(allGroups) {
6724
+ const previousRef = useRef17([]);
6725
+ const keyedGroups = useMemo7(() => {
6726
+ const previousByItemId = /* @__PURE__ */ new Map();
6727
+ for (const previous of previousRef.current) {
6728
+ for (const itemId of timelineGroupItemIds(previous.group)) {
6729
+ previousByItemId.set(itemId, previous);
6730
+ }
6731
+ }
6732
+ const usedKeys = /* @__PURE__ */ new Set();
6733
+ return allGroups.map((group, index) => {
6734
+ const itemIds = timelineGroupItemIds(group);
6735
+ let retainedKey;
6736
+ for (const itemId of itemIds) {
6737
+ const previous = previousByItemId.get(itemId);
6738
+ if (previous && !usedKeys.has(previous.key)) {
6739
+ retainedKey = previous.key;
6740
+ break;
6741
+ }
6742
+ }
6743
+ const canonicalKey = timelineGroupKey(group);
6744
+ let key = retainedKey ?? canonicalKey;
6745
+ let collision = 0;
6746
+ while (usedKeys.has(key)) {
6747
+ key = `${canonicalKey}:${index}:${collision}`;
6748
+ collision += 1;
6749
+ }
6750
+ usedKeys.add(key);
6751
+ return { group, key };
6752
+ });
6753
+ }, [allGroups]);
6754
+ useLayoutEffect(() => {
6755
+ previousRef.current = keyedGroups;
6756
+ }, [keyedGroups]);
6757
+ return keyedGroups;
6758
+ }
6759
+ function useProgressivelyMountedGroups(allGroups) {
6760
+ const previousGroupKeysRef = useRef17([]);
6761
+ const groupKeys = useMemo7(() => {
6762
+ const nextKeys = allGroups.map((group) => group.key);
6763
+ const previousKeys = previousGroupKeysRef.current;
6764
+ return nextKeys.length === previousKeys.length && nextKeys.every((key, index) => key === previousKeys[index]) ? previousKeys : nextKeys;
6765
+ }, [allGroups]);
6766
+ useLayoutEffect(() => {
6767
+ previousGroupKeysRef.current = groupKeys;
6768
+ }, [groupKeys]);
6769
+ const [window2, setWindow] = useState21(() => ({
6770
+ groupKeys,
6771
+ visibleStart: Math.max(0, allGroups.length - INITIAL_MOUNTED_GROUPS)
6772
+ }));
6773
+ const lastPossibleStart = Math.max(0, allGroups.length - INITIAL_MOUNTED_GROUPS);
6774
+ let visibleStart = 0;
6775
+ if (allGroups.length > 0) {
6776
+ const currentIndexByKey = new Map(groupKeys.map((key, index) => [key, index]));
6777
+ let retainedStart;
6778
+ for (const key of window2.groupKeys.slice(window2.visibleStart)) {
6779
+ const index = currentIndexByKey.get(key);
6780
+ if (index !== void 0) {
6781
+ retainedStart = index;
6782
+ break;
6783
+ }
6784
+ }
6785
+ visibleStart = retainedStart === void 0 ? lastPossibleStart : Math.min(retainedStart, lastPossibleStart);
6786
+ }
6787
+ useEffect18(() => {
6788
+ if (window2.groupKeys !== groupKeys || window2.visibleStart !== visibleStart) {
6789
+ setWindow({ groupKeys, visibleStart });
6790
+ return;
6791
+ }
6792
+ if (visibleStart === 0) {
6793
+ return;
6794
+ }
6795
+ const frame = requestFrame(() => {
6796
+ setWindow(
6797
+ (current) => current.groupKeys === groupKeys && current.visibleStart > 0 ? { ...current, visibleStart: current.visibleStart - 1 } : current
6798
+ );
6799
+ });
6800
+ return () => cancelFrame(frame);
6801
+ }, [groupKeys, visibleStart, window2.groupKeys, window2.visibleStart]);
6802
+ return {
6803
+ mountedGroups: allGroups.slice(visibleStart),
6804
+ mountingOlderGroups: visibleStart > 0
6805
+ };
6806
+ }
6606
6807
  function requestFrame(callback) {
6607
6808
  if (typeof requestAnimationFrame === "function") {
6608
6809
  return requestAnimationFrame(callback);
@@ -6616,7 +6817,7 @@ function cancelFrame(id) {
6616
6817
  }
6617
6818
  window.clearTimeout(id);
6618
6819
  }
6619
- function TimelineGroupView({
6820
+ var TimelineGroupView = memo2(function TimelineGroupView2({
6620
6821
  group,
6621
6822
  renderMessageText,
6622
6823
  onOpenSession,
@@ -6665,7 +6866,7 @@ function TimelineGroupView({
6665
6866
  case "turn": {
6666
6867
  const activityItems = flattenActivityItems(group.groups);
6667
6868
  const body = group.groups.map((child) => /* @__PURE__ */ jsx15(
6668
- TimelineGroupView,
6869
+ TimelineGroupView2,
6669
6870
  {
6670
6871
  group: child,
6671
6872
  renderMessageText,
@@ -6711,7 +6912,7 @@ function TimelineGroupView({
6711
6912
  }
6712
6913
  );
6713
6914
  }
6714
- }
6915
+ });
6715
6916
  function timelineGroupKey(group) {
6716
6917
  switch (group.kind) {
6717
6918
  case "item":
@@ -6722,6 +6923,16 @@ function timelineGroupKey(group) {
6722
6923
  return group.id;
6723
6924
  }
6724
6925
  }
6926
+ function timelineGroupItemIds(group) {
6927
+ switch (group.kind) {
6928
+ case "item":
6929
+ return [group.item.id];
6930
+ case "activity":
6931
+ return group.items.map((item) => item.id);
6932
+ case "turn":
6933
+ return group.groups.flatMap(timelineGroupItemIds);
6934
+ }
6935
+ }
6725
6936
  function isAgentProgress(next) {
6726
6937
  if (!next) {
6727
6938
  return false;
@@ -6733,7 +6944,7 @@ function clusterIsSettled(group) {
6733
6944
  if (item.kind === "reasoning") {
6734
6945
  return !item.streaming;
6735
6946
  }
6736
- if (item.kind === "memory") {
6947
+ if (item.kind === "memory" || item.kind === "fleet-decision") {
6737
6948
  return true;
6738
6949
  }
6739
6950
  return item.status !== "running";
@@ -7044,6 +7255,8 @@ function AuthNeededRow({
7044
7255
  const [failed, setFailed] = useState21(false);
7045
7256
  const provider = providerLabel(item.providerDomain);
7046
7257
  const unavailable = item.reason === "unsupported_auth" || item.reason === "resource_scope_unavailable";
7258
+ const missing = item.reason === "missing_connection";
7259
+ const actionLabel = missing ? "Connect" : "Reconnect";
7047
7260
  const start = async () => {
7048
7261
  if (!onReconnect || busy) {
7049
7262
  return;
@@ -7069,7 +7282,7 @@ function AuthNeededRow({
7069
7282
  }
7070
7283
  ),
7071
7284
  /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
7072
- /* @__PURE__ */ jsx15("p", { className: "truncate text-og-md font-medium text-og-fg", children: unavailable ? `${provider} tools unavailable` : `Reconnect ${provider}` }),
7285
+ /* @__PURE__ */ jsx15("p", { className: "truncate text-og-md font-medium text-og-fg", children: unavailable ? `${provider} tools unavailable` : `${actionLabel} ${provider}` }),
7073
7286
  /* @__PURE__ */ jsx15("p", { className: "truncate text-og-sm text-og-fg-subtle", children: authReasonLine(item.reason) })
7074
7287
  ] })
7075
7288
  ] }),
@@ -7085,7 +7298,7 @@ function AuthNeededRow({
7085
7298
  ),
7086
7299
  children: [
7087
7300
  /* @__PURE__ */ jsx15(RefreshCwIcon, { className: cn("size-3.5", busy && "animate-og-spin"), "aria-hidden": true }),
7088
- busy ? "Reconnecting\u2026" : "Reconnect"
7301
+ busy ? "Opening\u2026" : actionLabel
7089
7302
  ]
7090
7303
  }
7091
7304
  ) : !unavailable && item.authorizationUrl ? /* @__PURE__ */ jsxs12(
@@ -7100,13 +7313,20 @@ function AuthNeededRow({
7100
7313
  ),
7101
7314
  children: [
7102
7315
  /* @__PURE__ */ jsx15(RefreshCwIcon, { className: "size-3.5", "aria-hidden": true }),
7103
- "Reconnect"
7316
+ actionLabel
7104
7317
  ]
7105
7318
  }
7106
7319
  ) : null
7107
7320
  ] }),
7321
+ !unavailable ? /* @__PURE__ */ jsxs12("p", { className: "px-1 text-og-xs text-og-fg-subtle", children: [
7322
+ "This tool call wasn't replayed. After ",
7323
+ missing ? "connecting" : "reconnecting",
7324
+ ", send a new message to try again."
7325
+ ] }) : null,
7108
7326
  failed ? /* @__PURE__ */ jsxs12("p", { className: "px-1 text-og-xs text-og-status-failed", children: [
7109
- "Couldn't start reconnecting ",
7327
+ "Couldn't start ",
7328
+ missing ? "connecting" : "reconnecting",
7329
+ " ",
7110
7330
  provider,
7111
7331
  ". Try again."
7112
7332
  ] }) : null
@@ -7114,7 +7334,7 @@ function AuthNeededRow({
7114
7334
  }
7115
7335
  function AuthProviderLogo({ src, label }) {
7116
7336
  const [failed, setFailed] = useState21(false);
7117
- useEffect17(() => setFailed(false), [src]);
7337
+ useEffect18(() => setFailed(false), [src]);
7118
7338
  const showImage = src && !failed;
7119
7339
  return /* @__PURE__ */ jsx15(
7120
7340
  "span",
@@ -7231,7 +7451,7 @@ function FleetTile({ session, title, subtitle, onOpen, className }) {
7231
7451
  }
7232
7452
 
7233
7453
  // src/components/sandbox-terminal.tsx
7234
- 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";
7235
7455
 
7236
7456
  // src/lib/xterm-theme.ts
7237
7457
  var DARK_ANSI = {
@@ -7409,17 +7629,17 @@ function SandboxTerminal({
7409
7629
  onActivate,
7410
7630
  className
7411
7631
  }) {
7412
- const containerRef = useRef17(null);
7413
- const termRef = useRef17(null);
7414
- const fitRef = useRef17(null);
7415
- const rendererRef = useRef17(null);
7416
- const writtenRef = useRef17(/* @__PURE__ */ new Set());
7417
- const wroteFirehoseRef = useRef17(false);
7418
- 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);
7419
7639
  const [ready, setReady] = useState22(false);
7420
7640
  const [activated, setActivated] = useState22(false);
7421
7641
  const ptyWs = terminalCapability?.transport === "pty-ws" && Boolean(terminalCapability?.url);
7422
- const ptyOutputQueueRef = useRef17([]);
7642
+ const ptyOutputQueueRef = useRef18([]);
7423
7643
  const {
7424
7644
  status: ptyStatus,
7425
7645
  write: ptyWrite,
@@ -7445,7 +7665,7 @@ function SandboxTerminal({
7445
7665
  if (!activated) setActivated(true);
7446
7666
  onActivate?.();
7447
7667
  }
7448
- useEffect18(() => {
7668
+ useEffect19(() => {
7449
7669
  if (typeof window === "undefined") return;
7450
7670
  const el = containerRef.current;
7451
7671
  if (!el) return;
@@ -7557,19 +7777,19 @@ function SandboxTerminal({
7557
7777
  setReady(false);
7558
7778
  };
7559
7779
  }, []);
7560
- useEffect18(() => {
7780
+ useEffect19(() => {
7561
7781
  const term = termRef.current;
7562
7782
  if (!ready || !term) return;
7563
7783
  term.options.disableStdin = !interactive;
7564
7784
  term.options.cursorBlink = interactive;
7565
7785
  }, [ready, interactive]);
7566
- useEffect18(() => {
7786
+ useEffect19(() => {
7567
7787
  const term = termRef.current;
7568
7788
  if (!ready || !term) return;
7569
7789
  const next = theme ?? xtermThemeFromTokens(containerRef.current);
7570
7790
  if (next) term.options.theme = next;
7571
7791
  }, [ready, theme]);
7572
- useEffect18(() => {
7792
+ useEffect19(() => {
7573
7793
  const term = termRef.current;
7574
7794
  if (!ready || !term) return;
7575
7795
  if (!booting) {
@@ -7590,7 +7810,7 @@ function SandboxTerminal({
7590
7810
  const id = setInterval(paint, 1e3);
7591
7811
  return () => clearInterval(id);
7592
7812
  }, [ready, booting]);
7593
- useEffect18(() => {
7813
+ useEffect19(() => {
7594
7814
  const term = termRef.current;
7595
7815
  if (!ready || !term || ptyMode) return;
7596
7816
  for (const chunk of result.chunks) {
@@ -7600,7 +7820,7 @@ function SandboxTerminal({
7600
7820
  term.write(chunk.text);
7601
7821
  }
7602
7822
  }, [ready, result.chunks, ptyMode]);
7603
- useEffect18(() => {
7823
+ useEffect19(() => {
7604
7824
  const term = termRef.current;
7605
7825
  if (!ready || !term || !interactive) return;
7606
7826
  const sink = ptyMode ? ptyWrite : result.write;
@@ -7608,14 +7828,14 @@ function SandboxTerminal({
7608
7828
  const sub = term.onData((data) => sink(data));
7609
7829
  return () => sub.dispose();
7610
7830
  }, [ready, interactive, ptyMode, ptyWrite, result.write]);
7611
- useEffect18(() => {
7831
+ useEffect19(() => {
7612
7832
  const term = termRef.current;
7613
7833
  if (!ready || !term || !ptyMode) return;
7614
7834
  resizePty(term.cols, term.rows);
7615
7835
  const sub = term.onResize(({ cols, rows }) => resizePty(cols, rows));
7616
7836
  return () => sub.dispose();
7617
7837
  }, [ready, ptyMode, ptyConnected, resizePty]);
7618
- useEffect18(() => {
7838
+ useEffect19(() => {
7619
7839
  if (typeof window === "undefined") return;
7620
7840
  const refit = () => {
7621
7841
  try {
@@ -7750,21 +7970,21 @@ import {
7750
7970
  } from "lucide-react";
7751
7971
  import {
7752
7972
  useCallback as useCallback21,
7753
- useEffect as useEffect21,
7973
+ useEffect as useEffect22,
7754
7974
  useId as useId3,
7755
7975
  useLayoutEffect as useLayoutEffect2,
7756
7976
  useMemo as useMemo9,
7757
- useRef as useRef18,
7977
+ useRef as useRef19,
7758
7978
  useState as useState24
7759
7979
  } from "react";
7760
7980
  import { AlertDialog } from "radix-ui";
7761
7981
  import { VList } from "virtua";
7762
7982
 
7763
7983
  // src/lib/use-portal-token-style.ts
7764
- import { useEffect as useEffect19, useState as useState23 } from "react";
7984
+ import { useEffect as useEffect20, useState as useState23 } from "react";
7765
7985
  function usePortalTokenStyle(sourceRef) {
7766
7986
  const [style, setStyle] = useState23({});
7767
- useEffect19(() => {
7987
+ useEffect20(() => {
7768
7988
  const source = sourceRef.current;
7769
7989
  if (!source || typeof MutationObserver === "undefined") return;
7770
7990
  let signature = "";
@@ -7805,12 +8025,12 @@ function usePortalTokenStyle(sourceRef) {
7805
8025
  }
7806
8026
 
7807
8027
  // src/lib/use-unicode-fonts.ts
7808
- import { useEffect as useEffect20, useMemo as useMemo8 } from "react";
8028
+ import { useEffect as useEffect21, useMemo as useMemo8 } from "react";
7809
8029
  var japaneseScript = /[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u;
7810
8030
  var arabicScript = /[\u0600-\u06ff\u0750-\u077f\u0870-\u08ff\ufb50-\ufdff\ufe70-\ufefc]/u;
7811
8031
  function useUnicodeFallbackFonts(values) {
7812
8032
  const content = useMemo8(() => collectUnicodeContent(values), [values]);
7813
- useEffect20(() => {
8033
+ useEffect21(() => {
7814
8034
  if (content.japanese) {
7815
8035
  void import("./noto-sans-jp-loader.generated-HFGLYBR3.js").then(({ loadNotoSansJp }) => loadNotoSansJp(content.japanese)).catch(() => void 0);
7816
8036
  }
@@ -7840,7 +8060,7 @@ var STATUS_TINT = {
7840
8060
  renamed: "text-og-accent",
7841
8061
  untracked: "text-og-fg-subtle"
7842
8062
  };
7843
- var useBrowserLayoutEffect = typeof window === "undefined" ? useEffect21 : useLayoutEffect2;
8063
+ var useBrowserLayoutEffect = typeof window === "undefined" ? useEffect22 : useLayoutEffect2;
7844
8064
  function parentOf2(path) {
7845
8065
  const i = path.lastIndexOf("/");
7846
8066
  return i <= 0 ? "" : path.slice(0, i);
@@ -7892,9 +8112,9 @@ function FileBrowser({
7892
8112
  const [busy, setBusy] = useState24(false);
7893
8113
  const [coarsePointer, setCoarsePointer] = useState24(false);
7894
8114
  const treeId = useId3();
7895
- const containerRef = useRef18(null);
7896
- const deleteReturnFocusRef = useRef18(null);
7897
- const vlistRef = useRef18(null);
8115
+ const containerRef = useRef19(null);
8116
+ const deleteReturnFocusRef = useRef19(null);
8117
+ const vlistRef = useRef19(null);
7898
8118
  const portalTokenStyle = usePortalTokenStyle(containerRef);
7899
8119
  const getTreeElement = useCallback21(
7900
8120
  () => typeof document === "undefined" ? null : document.getElementById(treeId),
@@ -8267,7 +8487,7 @@ function FileBrowser({
8267
8487
  treeId
8268
8488
  ]
8269
8489
  );
8270
- useEffect21(() => {
8490
+ useEffect22(() => {
8271
8491
  if (!menu) return;
8272
8492
  const close = () => setMenu(null);
8273
8493
  window.addEventListener("click", close);
@@ -8448,7 +8668,7 @@ function FileBrowser({
8448
8668
  );
8449
8669
  }
8450
8670
  };
8451
- useEffect21(() => {
8671
+ useEffect22(() => {
8452
8672
  if (!cursor) return;
8453
8673
  const index = renderItems.findIndex((it) => it.type === "node" && it.node.path === cursor);
8454
8674
  if (index >= 0) vlistRef.current?.scrollToIndex(index);
@@ -8649,11 +8869,11 @@ function DeleteDialog({
8649
8869
  onCancel,
8650
8870
  onConfirm
8651
8871
  }) {
8652
- const cancelRef = useRef18(null);
8872
+ const cancelRef = useRef19(null);
8653
8873
  const [open, setOpen] = useState24(true);
8654
- const closeIntentRef = useRef18("cancel");
8655
- const settledRef = useRef18(false);
8656
- const settleTimerRef = useRef18(null);
8874
+ const closeIntentRef = useRef19("cancel");
8875
+ const settledRef = useRef19(false);
8876
+ const settleTimerRef = useRef19(null);
8657
8877
  const settle = () => {
8658
8878
  if (settledRef.current) return;
8659
8879
  settledRef.current = true;
@@ -8670,7 +8890,7 @@ function DeleteDialog({
8670
8890
  settle();
8671
8891
  }, 0);
8672
8892
  };
8673
- useEffect21(
8893
+ useEffect22(
8674
8894
  () => () => {
8675
8895
  if (settleTimerRef.current !== null) clearTimeout(settleTimerRef.current);
8676
8896
  },
@@ -8789,9 +9009,9 @@ function InlineInput({
8789
9009
  onCancel
8790
9010
  }) {
8791
9011
  const [value, setValue] = useState24(initialValue);
8792
- const ref = useRef18(null);
8793
- const doneRef = useRef18(false);
8794
- useEffect21(() => {
9012
+ const ref = useRef19(null);
9013
+ const doneRef = useRef19(false);
9014
+ useEffect22(() => {
8795
9015
  const el = ref.current;
8796
9016
  if (!el) return;
8797
9017
  el.focus();
@@ -8855,12 +9075,12 @@ function ContextMenu({
8855
9075
  onClose
8856
9076
  }) {
8857
9077
  const isDir = node.kind === "dir";
8858
- const menuRef = useRef18(null);
9078
+ const menuRef = useRef19(null);
8859
9079
  const vw = typeof window !== "undefined" ? window.innerWidth : 9999;
8860
9080
  const vh = typeof window !== "undefined" ? window.innerHeight : 9999;
8861
9081
  const left = Math.max(4, Math.min(x, vw - 180));
8862
9082
  const top = Math.max(4, Math.min(y, vh - 160));
8863
- useEffect21(() => {
9083
+ useEffect22(() => {
8864
9084
  menuRef.current?.querySelector('[role="menuitem"]')?.focus();
8865
9085
  }, []);
8866
9086
  const onKeyDown = (event) => {
@@ -8960,13 +9180,13 @@ function DiffView({
8960
9180
 
8961
9181
  // src/components/pierre-file.tsx
8962
9182
  import {
8963
- lazy as lazy3,
8964
- Suspense as Suspense3,
8965
- useEffect as useEffect22,
9183
+ lazy as lazy4,
9184
+ Suspense as Suspense4,
9185
+ useEffect as useEffect23,
8966
9186
  useState as useState25
8967
9187
  } from "react";
8968
9188
  import { jsx as jsx20 } from "react/jsx-runtime";
8969
- var LazyFile = lazy3(async () => {
9189
+ var LazyFile = lazy4(async () => {
8970
9190
  const mod = await import("@pierre/diffs/react");
8971
9191
  return { default: mod.File };
8972
9192
  });
@@ -8981,7 +9201,7 @@ function PierreFile({
8981
9201
  className
8982
9202
  }) {
8983
9203
  const [failed, setFailed] = useState25(false);
8984
- useEffect22(() => {
9204
+ useEffect23(() => {
8985
9205
  let cancelled = false;
8986
9206
  void import("@pierre/diffs/react").catch(() => {
8987
9207
  if (!cancelled) setFailed(true);
@@ -9014,7 +9234,7 @@ function PierreFile({
9014
9234
  "--diffs-font-size": "var(--og-code-font-size)",
9015
9235
  "--diffs-line-height": "var(--og-code-line-height)"
9016
9236
  };
9017
- 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(
9018
9238
  LazyFile,
9019
9239
  {
9020
9240
  file: { name, contents },
@@ -9041,9 +9261,9 @@ function FileSkeleton() {
9041
9261
  import { Loader2Icon as Loader2Icon2, SaveIcon } from "lucide-react";
9042
9262
  import {
9043
9263
  useCallback as useCallback22,
9044
- useEffect as useEffect23,
9264
+ useEffect as useEffect24,
9045
9265
  useMemo as useMemo10,
9046
- useRef as useRef19,
9266
+ useRef as useRef20,
9047
9267
  useState as useState26
9048
9268
  } from "react";
9049
9269
  import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
@@ -9112,9 +9332,9 @@ function CodeEditor({
9112
9332
  const [savedTick, setSavedTick] = useState26(false);
9113
9333
  const dirty = value !== baseline;
9114
9334
  const saveConflict = saveError !== null && saveError.code === "file_write_conflict";
9115
- const editIntentFiredRef = useRef19(false);
9116
- const lastSeed = useRef19({ path, contents: initialContents });
9117
- useEffect23(() => {
9335
+ const editIntentFiredRef = useRef20(false);
9336
+ const lastSeed = useRef20({ path, contents: initialContents });
9337
+ useEffect24(() => {
9118
9338
  const seedChanged = lastSeed.current.path !== path || lastSeed.current.contents !== initialContents;
9119
9339
  if (!seedChanged) return;
9120
9340
  lastSeed.current = { path, contents: initialContents };
@@ -9136,7 +9356,7 @@ function CodeEditor({
9136
9356
  [baseline, onEditIntent]
9137
9357
  );
9138
9358
  const langKey = useMemo10(() => languageForPath(path), [path]);
9139
- useEffect23(() => {
9359
+ useEffect24(() => {
9140
9360
  let cancelled = false;
9141
9361
  void (async () => {
9142
9362
  try {
@@ -9176,7 +9396,7 @@ function CodeEditor({
9176
9396
  cancelled = true;
9177
9397
  };
9178
9398
  }, [langKey]);
9179
- const saveRef = useRef19(() => {
9399
+ const saveRef = useRef20(() => {
9180
9400
  });
9181
9401
  const save = useCallback22(async () => {
9182
9402
  if (readOnly) return;
@@ -9217,7 +9437,7 @@ function CodeEditor({
9217
9437
  saveRef.current = () => {
9218
9438
  void save();
9219
9439
  };
9220
- useEffect23(() => {
9440
+ useEffect24(() => {
9221
9441
  if (!savedTick) return;
9222
9442
  const t = setTimeout(() => setSavedTick(false), 1800);
9223
9443
  return () => clearTimeout(t);
@@ -9379,7 +9599,7 @@ function EditorSkeleton() {
9379
9599
 
9380
9600
  // src/components/sandbox-files.tsx
9381
9601
  import { FileCode2Icon, FileWarningIcon, LoaderCircleIcon } from "lucide-react";
9382
- 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";
9383
9603
  import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
9384
9604
  function SandboxFiles({
9385
9605
  files,
@@ -9402,10 +9622,10 @@ function SandboxFiles({
9402
9622
  const [editMode, setEditMode] = useState27(false);
9403
9623
  const [liveRequestedPath, setLiveRequestedPath] = useState27(null);
9404
9624
  const [viewReloadRevision, setViewReloadRevision] = useState27(0);
9405
- const pendingRequestRef = useRef20(null);
9406
- const handledRequestRef = useRef20(null);
9625
+ const pendingRequestRef = useRef21(null);
9626
+ const handledRequestRef = useRef21(null);
9407
9627
  const requestKey = requestedPath ? requestedPathRequestId ?? requestedPath : null;
9408
- useEffect24(() => {
9628
+ useEffect25(() => {
9409
9629
  if (!requestedPath || requestKey === null) {
9410
9630
  pendingRequestRef.current = null;
9411
9631
  handledRequestRef.current = null;
@@ -9423,9 +9643,9 @@ function SandboxFiles({
9423
9643
  setSelected(requestedPath);
9424
9644
  setEditMode(false);
9425
9645
  }, [requestKey, requestedPath, requestedPathReady]);
9426
- const rootRef = useRef20(null);
9646
+ const rootRef = useRef21(null);
9427
9647
  const [wide, setWide] = useState27(false);
9428
- useEffect24(() => {
9648
+ useEffect25(() => {
9429
9649
  const el = rootRef.current;
9430
9650
  if (!el || typeof ResizeObserver === "undefined") return;
9431
9651
  const observer = new ResizeObserver((entries) => {
@@ -9720,7 +9940,7 @@ function useFileView(path, readFile, reloadRevision = 0) {
9720
9940
  loading: false,
9721
9941
  error: null
9722
9942
  });
9723
- useEffect24(() => {
9943
+ useEffect25(() => {
9724
9944
  if (!path) {
9725
9945
  setState({
9726
9946
  content: null,
@@ -9811,7 +10031,7 @@ function Notice({
9811
10031
 
9812
10032
  // src/components/desktop-viewer.tsx
9813
10033
  import { LoaderCircleIcon as LoaderCircleIcon2, MonitorIcon, MousePointerClickIcon, WifiOffIcon } from "lucide-react";
9814
- 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";
9815
10035
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
9816
10036
  var DESKTOP_MEDIA_BACKGROUND = "#000";
9817
10037
  function isHardUnavailable(reason) {
@@ -9844,7 +10064,7 @@ function DesktopViewer({
9844
10064
  connectTimeoutMs = 13e3,
9845
10065
  className
9846
10066
  }) {
9847
- const containerRef = useRef21(null);
10067
+ const containerRef = useRef22(null);
9848
10068
  const [consented, setConsented] = useState28(false);
9849
10069
  const [takeControl, setTakeControl] = useState28(interactive ?? false);
9850
10070
  const externallyControlled = interactive !== void 0;
@@ -9862,7 +10082,7 @@ function DesktopViewer({
9862
10082
  setConsented(true);
9863
10083
  onAcknowledge?.();
9864
10084
  };
9865
- useEffect25(() => {
10085
+ useEffect26(() => {
9866
10086
  if (!inControl || externallyControlled) return;
9867
10087
  const onKey = (event) => {
9868
10088
  if (event.ctrlKey && event.altKey && event.shiftKey && (event.key === "Control" || event.key === "Alt" || event.key === "Shift")) {
@@ -9886,10 +10106,10 @@ function DesktopViewer({
9886
10106
  });
9887
10107
  const connected = stream.state === "connected";
9888
10108
  const hasLiveUrl = Boolean(connectCapability?.url);
9889
- const streamStateRef = useRef21(stream.state);
10109
+ const streamStateRef = useRef22(stream.state);
9890
10110
  streamStateRef.current = stream.state;
9891
- const warmKeyRef = useRef21(null);
9892
- useEffect25(() => {
10111
+ const warmKeyRef = useRef22(null);
10112
+ useEffect26(() => {
9893
10113
  if (!isWatching || !coldWarmable || needsAck || viewerCapReached) {
9894
10114
  if (!coldWarmable) warmKeyRef.current = null;
9895
10115
  return;
@@ -9901,7 +10121,7 @@ function DesktopViewer({
9901
10121
  warmKeyRef.current = key;
9902
10122
  warm();
9903
10123
  }, [isWatching, coldWarmable, needsAck, viewerCapReached, capability, onWarm, onAcknowledge]);
9904
- useEffect25(() => {
10124
+ useEffect26(() => {
9905
10125
  if (!hasLiveUrl || typeof document === "undefined") return;
9906
10126
  const maybeReattach = () => {
9907
10127
  if (document.visibilityState !== "visible") return;
@@ -9912,7 +10132,7 @@ function DesktopViewer({
9912
10132
  }, [hasLiveUrl, connectCapability?.url]);
9913
10133
  const [connectTimedOut, setConnectTimedOut] = useState28(false);
9914
10134
  const [reconnectNonce, setReconnectNonce] = useState28(0);
9915
- useEffect25(() => {
10135
+ useEffect26(() => {
9916
10136
  setConnectTimedOut(false);
9917
10137
  if (!hasLiveUrl || connected || stream.error || connectTimeoutMs <= 0) return;
9918
10138
  const timer = setTimeout(() => setConnectTimedOut(true), connectTimeoutMs);
@@ -10191,10 +10411,10 @@ function defaultNotice(title, body, onRetry) {
10191
10411
  // src/components/workspace-dock.tsx
10192
10412
  import {
10193
10413
  useCallback as useCallback24,
10194
- useEffect as useEffect26,
10414
+ useEffect as useEffect27,
10195
10415
  useId as useId4,
10196
10416
  useLayoutEffect as useLayoutEffect3,
10197
- useRef as useRef22,
10417
+ useRef as useRef23,
10198
10418
  useState as useState29
10199
10419
  } from "react";
10200
10420
  import {
@@ -10225,7 +10445,7 @@ function getLayoutStorage() {
10225
10445
  return SERVER_LAYOUT_STORAGE;
10226
10446
  }
10227
10447
  }
10228
- var useDockLayoutEffect = typeof window === "undefined" ? useEffect26 : useLayoutEffect3;
10448
+ var useDockLayoutEffect = typeof window === "undefined" ? useEffect27 : useLayoutEffect3;
10229
10449
  var DOCK_OVERLAY_BREAKPOINT = 1024;
10230
10450
  function useIsNarrow(maxWidth) {
10231
10451
  const [narrow, setNarrow] = useState29(false);
@@ -10261,17 +10481,17 @@ function WorkspaceDock({
10261
10481
  className
10262
10482
  }) {
10263
10483
  const narrow = useIsNarrow(DOCK_OVERLAY_BREAKPOINT);
10264
- const rootRef = useRef22(null);
10265
- const reopenRef = useRef22(null);
10266
- const returnFocusRef = useRef22(null);
10267
- const initialNarrowFocusRef = useRef22(false);
10484
+ const rootRef = useRef23(null);
10485
+ const reopenRef = useRef23(null);
10486
+ const returnFocusRef = useRef23(null);
10487
+ const initialNarrowFocusRef = useRef23(false);
10268
10488
  const dockPanelRef = usePanelRef();
10269
10489
  const [internalCollapsed, setInternalCollapsed] = useState29(false);
10270
10490
  const [maximized, setMaximized] = useState29(false);
10271
10491
  const [internalTab, setInternalTab] = useState29(tabs[0]?.id ?? "");
10272
10492
  const collapsed = collapsedProp ?? internalCollapsed;
10273
10493
  const hostControlled = collapsedProp !== void 0;
10274
- const previousCollapsedRef = useRef22(collapsed);
10494
+ const previousCollapsedRef = useRef23(collapsed);
10275
10495
  const { defaultLayout, onLayoutChanged } = useDefaultLayout({
10276
10496
  panelIds: ["primary", "dock"],
10277
10497
  storage: getLayoutStorage(),
@@ -10307,7 +10527,7 @@ function WorkspaceDock({
10307
10527
  dockPanelRef.current?.expand();
10308
10528
  }
10309
10529
  }, [collapsedProp, dockPanelRef]);
10310
- useEffect26(() => {
10530
+ useEffect27(() => {
10311
10531
  const previous = previousCollapsedRef.current;
10312
10532
  previousCollapsedRef.current = collapsed;
10313
10533
  if (previous === collapsed) return;
@@ -10337,7 +10557,7 @@ function WorkspaceDock({
10337
10557
  });
10338
10558
  return () => cancelAnimationFrame(frame);
10339
10559
  }, [collapsed, hostControlled, narrow]);
10340
- useEffect26(() => {
10560
+ useEffect27(() => {
10341
10561
  if (!narrow || collapsed || initialNarrowFocusRef.current) return;
10342
10562
  initialNarrowFocusRef.current = true;
10343
10563
  const active = document.activeElement;
@@ -10350,7 +10570,7 @@ function WorkspaceDock({
10350
10570
  });
10351
10571
  return () => cancelAnimationFrame(frame);
10352
10572
  }, [collapsed, narrow]);
10353
- useEffect26(() => {
10573
+ useEffect27(() => {
10354
10574
  if (firstTabId && !requestedTabIsValid) {
10355
10575
  setTab(firstTabId);
10356
10576
  }
@@ -10363,7 +10583,7 @@ function WorkspaceDock({
10363
10583
  dockPanelRef.current?.expand();
10364
10584
  setCollapsed(false);
10365
10585
  }, [dockPanelRef, setCollapsed]);
10366
- useEffect26(() => {
10586
+ useEffect27(() => {
10367
10587
  const overlayOpen = maximized || narrow && !collapsed;
10368
10588
  if (!overlayOpen) return;
10369
10589
  const onKey = (event) => {
@@ -10580,8 +10800,8 @@ function DockChrome({
10580
10800
  }) {
10581
10801
  const active = tabs.find((t) => t.id === current) ?? tabs[0];
10582
10802
  const tabsetId = useId4();
10583
- const tabRefs = useRef22([]);
10584
- const tabListRef = useRef22(null);
10803
+ const tabRefs = useRef23([]);
10804
+ const tabListRef = useRef23(null);
10585
10805
  const [visitedTabs, setVisitedTabs] = useState29(() => /* @__PURE__ */ new Set());
10586
10806
  const [tabOverflow, setTabOverflow] = useState29({ start: false, end: false });
10587
10807
  const activeId = active?.id ?? "";
@@ -10590,7 +10810,7 @@ function DockChrome({
10590
10810
  const selected = activeTabIndex >= 0 ? tabRefs.current[activeTabIndex] : null;
10591
10811
  selected?.scrollIntoView({ block: "nearest", inline: "nearest" });
10592
10812
  }, [activeTabIndex]);
10593
- useEffect26(() => {
10813
+ useEffect27(() => {
10594
10814
  if (!activeId) return;
10595
10815
  setVisitedTabs((previous) => {
10596
10816
  if (previous.has(activeId)) return previous;
@@ -10712,7 +10932,7 @@ function DockChrome({
10712
10932
  }
10713
10933
 
10714
10934
  // src/components/sandbox-workspace.tsx
10715
- 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";
10716
10936
  import { Popover } from "radix-ui";
10717
10937
  import {
10718
10938
  CircleCheckIcon,
@@ -10727,17 +10947,17 @@ import {
10727
10947
  import { ArrowUpRightIcon, FileWarningIcon as FileWarningIcon2, HistoryIcon } from "lucide-react";
10728
10948
  import {
10729
10949
  useCallback as useCallback26,
10730
- useEffect as useEffect28,
10950
+ useEffect as useEffect29,
10731
10951
  useId as useId5,
10732
10952
  useLayoutEffect as useLayoutEffect4,
10733
10953
  useMemo as useMemo12,
10734
- useRef as useRef24,
10954
+ useRef as useRef25,
10735
10955
  useState as useState31
10736
10956
  } from "react";
10737
10957
  import { VList as VList2 } from "virtua";
10738
10958
 
10739
10959
  // src/hooks/use-windowed-sections.ts
10740
- 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";
10741
10961
  function computeWindowRange(heights, scrollTop, viewport, overscan) {
10742
10962
  const n = heights.length;
10743
10963
  if (n === 0) return { start: 0, end: 0 };
@@ -10768,17 +10988,17 @@ function computeWindowRange(heights, scrollTop, viewport, overscan) {
10768
10988
  }
10769
10989
  function useWindowedSections(opts) {
10770
10990
  const { count, estimateHeight, overscan = 3 } = opts;
10771
- const scrollRef = useRef23(null);
10991
+ const scrollRef = useRef24(null);
10772
10992
  const [heights, setHeights] = useState30(
10773
10993
  () => Array.from({ length: count }, (_, i) => estimateHeight(i))
10774
10994
  );
10775
- useEffect27(() => {
10995
+ useEffect28(() => {
10776
10996
  setHeights((prev) => {
10777
10997
  if (prev.length === count) return prev;
10778
10998
  return Array.from({ length: count }, (_, i) => prev[i] ?? estimateHeight(i));
10779
10999
  });
10780
11000
  }, [count]);
10781
- const heightsRef = useRef23(heights);
11001
+ const heightsRef = useRef24(heights);
10782
11002
  heightsRef.current = heights;
10783
11003
  const [range, setRange] = useState30(() => ({
10784
11004
  start: 0,
@@ -10790,7 +11010,7 @@ function useWindowedSections(opts) {
10790
11010
  const next = computeWindowRange(heightsRef.current, el.scrollTop, el.clientHeight, overscan);
10791
11011
  setRange((prev) => prev.start === next.start && prev.end === next.end ? prev : next);
10792
11012
  }, [overscan]);
10793
- useEffect27(() => {
11013
+ useEffect28(() => {
10794
11014
  const el = scrollRef.current;
10795
11015
  if (!el) return;
10796
11016
  let raf = 0;
@@ -10826,7 +11046,7 @@ function useWindowedSections(opts) {
10826
11046
  for (let i = 0; i < count; i++) out[i + 1] = (out[i] ?? 0) + Math.max(heights[i] ?? 0, 0);
10827
11047
  return out;
10828
11048
  }, [heights, count]);
10829
- useEffect27(() => {
11049
+ useEffect28(() => {
10830
11050
  recompute();
10831
11051
  }, [offsets, recompute]);
10832
11052
  const scrollToIndex = useCallback25(
@@ -10856,7 +11076,7 @@ var HEADER_PX = 30;
10856
11076
  var LINE_PX = 18;
10857
11077
  var GUARD_BODY_PX = 52;
10858
11078
  var COMPACT_SURFACE_PX = 560;
10859
- var useChangesLayoutEffect = typeof window === "undefined" ? useEffect28 : useLayoutEffect4;
11079
+ var useChangesLayoutEffect = typeof window === "undefined" ? useEffect29 : useLayoutEffect4;
10860
11080
  var STATUS_TINT2 = {
10861
11081
  added: "text-og-status-idle",
10862
11082
  modified: "text-og-status-running",
@@ -10936,7 +11156,7 @@ function WorkbenchChanges({
10936
11156
  onOpenFile,
10937
11157
  className
10938
11158
  }) {
10939
- const rootRef = useRef24(null);
11159
+ const rootRef = useRef25(null);
10940
11160
  const [compact, setCompact] = useState31(false);
10941
11161
  const [coarsePointer, setCoarsePointer] = useState31(false);
10942
11162
  const resolvedTheme = useThemeType(themeType);
@@ -11014,7 +11234,7 @@ function WorkbenchChanges({
11014
11234
  const nextPath = orderedFiles[idx]?.path ?? null;
11015
11235
  setActivePath((previous) => previous === nextPath ? previous : nextPath);
11016
11236
  }, [windowed, orderedFiles]);
11017
- useEffect28(() => {
11237
+ useEffect29(() => {
11018
11238
  const el = windowed.scrollRef.current;
11019
11239
  if (!el) return;
11020
11240
  el.addEventListener("scroll", onPaneScroll, { passive: true });
@@ -11247,8 +11467,8 @@ function MeasuredSection({
11247
11467
  onMeasure,
11248
11468
  children
11249
11469
  }) {
11250
- const ref = useRef24(null);
11251
- useEffect28(() => {
11470
+ const ref = useRef25(null);
11471
+ useEffect29(() => {
11252
11472
  const el = ref.current;
11253
11473
  if (!el) return;
11254
11474
  const report = () => onMeasure(index, el.offsetHeight);
@@ -11468,8 +11688,8 @@ function useSandboxWorkspaceTabs(options) {
11468
11688
  const desktopAdvertised = desktopEnabled && ((capabilities?.DesktopStream.transport ?? null) !== null || capabilities?.DesktopStream.reason === "lease_cold");
11469
11689
  const provisioning = sandboxProvisionInFlight(events);
11470
11690
  const renegotiate = caps.renegotiate;
11471
- const provisioningRef = useRef25({ sessionId, provisioning });
11472
- useEffect29(() => {
11691
+ const provisioningRef = useRef26({ sessionId, provisioning });
11692
+ useEffect30(() => {
11473
11693
  const previous = provisioningRef.current;
11474
11694
  if (previous.sessionId === sessionId && previous.provisioning && !provisioning) {
11475
11695
  renegotiate();
@@ -11488,14 +11708,14 @@ function useSandboxWorkspaceTabs(options) {
11488
11708
  if (advertised.length > 0) return advertised;
11489
11709
  return captureState.capture?.repos.map((repo) => repo.root) ?? [];
11490
11710
  }, [capabilities?.Git.repos, captureState.capture]);
11491
- const notifiedCaptureDegradedReason = useRef25({
11711
+ const notifiedCaptureDegradedReason = useRef26({
11492
11712
  sessionId,
11493
11713
  reason: null
11494
11714
  });
11495
11715
  if (notifiedCaptureDegradedReason.current.sessionId !== sessionId) {
11496
11716
  notifiedCaptureDegradedReason.current = { sessionId, reason: null };
11497
11717
  }
11498
- useEffect29(() => {
11718
+ useEffect30(() => {
11499
11719
  const reason = captureState.degradedReason;
11500
11720
  if (!reason || notifiedCaptureDegradedReason.current.reason === reason) return;
11501
11721
  notifiedCaptureDegradedReason.current = { sessionId, reason };
@@ -11533,7 +11753,7 @@ function useSandboxWorkspaceTabs(options) {
11533
11753
  capture: captureState.capture
11534
11754
  });
11535
11755
  const [xtermTheme, setXtermTheme] = useState32(void 0);
11536
- useEffect29(() => {
11756
+ useEffect30(() => {
11537
11757
  if (!terminalEnabled || typeof document === "undefined") return;
11538
11758
  const derive = () => setXtermTheme(xtermThemeFromTokens());
11539
11759
  derive();
@@ -11575,7 +11795,7 @@ function useSandboxWorkspaceTabs(options) {
11575
11795
  });
11576
11796
  const workspaceWaking = chip.state === "waking";
11577
11797
  const defaultIdentity = `${sessionId}\0${surfaceIdentity}`;
11578
- const defaultTabRef = useRef25({
11798
+ const defaultTabRef = useRef26({
11579
11799
  identity: defaultIdentity,
11580
11800
  value: null
11581
11801
  });
@@ -11770,7 +11990,7 @@ function SandboxWorkspace(props) {
11770
11990
  } = props;
11771
11991
  const [storedSelection, setStoredSelection] = useState32(null);
11772
11992
  const [requestedFile, setRequestedFile] = useState32(null);
11773
- const nextFileRequestId = useRef25(0);
11993
+ const nextFileRequestId = useRef26(0);
11774
11994
  const openFile = useCallback27(
11775
11995
  (path) => {
11776
11996
  nextFileRequestId.current += 1;
@@ -11853,7 +12073,7 @@ function MachineStateChip({
11853
12073
  error,
11854
12074
  onRetry
11855
12075
  }) {
11856
- const triggerRef = useRef25(null);
12076
+ const triggerRef = useRef26(null);
11857
12077
  const portalStyle = usePortalTokenStyle(triggerRef);
11858
12078
  return /* @__PURE__ */ jsxs21(Popover.Root, { children: [
11859
12079
  /* @__PURE__ */ jsx26(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs21(
@@ -12317,6 +12537,7 @@ export {
12317
12537
  isGoalEvent,
12318
12538
  isHumanInputEvent,
12319
12539
  isLineageRefreshEvent,
12540
+ isSessionMcpApprovalPolicyEvent,
12320
12541
  isTitleEvent,
12321
12542
  isTurnQueueEvent,
12322
12543
  languageForPath,
@@ -12374,6 +12595,7 @@ export {
12374
12595
  useSessionControl,
12375
12596
  useSessionEvents,
12376
12597
  useSessionLineage,
12598
+ useSessionMcpApprovalPolicy,
12377
12599
  useSlashCommands,
12378
12600
  useTerminalStream,
12379
12601
  useTranscription,