@opengeni/react 2.5.0-canary.2 → 3.1.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 (69) hide show
  1. package/README.md +15 -0
  2. package/dist/accounts.d.ts +64 -0
  3. package/dist/accounts.js +746 -0
  4. package/dist/accounts.js.map +1 -0
  5. package/dist/{browser-viewer-GXUICIAG.js → browser-viewer-AEFHUYZK.js} +3 -3
  6. package/dist/{chunk-MXJGO7LE.js → chunk-D3UIAJKY.js} +52 -2
  7. package/dist/chunk-D3UIAJKY.js.map +1 -0
  8. package/dist/{chunk-QGBJ6GHG.js → chunk-ELIYWBZR.js} +4 -4
  9. package/dist/{chunk-6H6S5V4Z.js → chunk-HQVCKCLG.js} +758 -871
  10. package/dist/chunk-HQVCKCLG.js.map +1 -0
  11. package/dist/{chunk-T7VAYG2I.js → chunk-MZ2G2XBA.js} +54 -2
  12. package/dist/chunk-MZ2G2XBA.js.map +1 -0
  13. package/dist/{chunk-X4JAFD5R.js → chunk-OAM4WAAM.js} +4 -4
  14. package/dist/{chunk-ZUT5QSQB.js → chunk-RGALCTWO.js} +57 -17
  15. package/dist/{chunk-ZUT5QSQB.js.map → chunk-RGALCTWO.js.map} +1 -1
  16. package/dist/chunk-YFKJ7VZH.js +268 -0
  17. package/dist/chunk-YFKJ7VZH.js.map +1 -0
  18. package/dist/{chunk-ATQJEWCA.js → chunk-YJFGAFBD.js} +124 -50
  19. package/dist/chunk-YJFGAFBD.js.map +1 -0
  20. package/dist/components/composer.d.ts +8 -0
  21. package/dist/components/file-browser.d.ts +4 -1
  22. package/dist/components/sandbox-files.d.ts +4 -1
  23. package/dist/components/sandbox-workspace.d.ts +5 -0
  24. package/dist/composer.js +3 -3
  25. package/dist/{computer-viewer-ZOP4Q7A7.js → computer-viewer-FWEZISW4.js} +3 -3
  26. package/dist/embedded-session-client.d.ts +23 -0
  27. package/dist/file-node-visibility.d.ts +15 -0
  28. package/dist/hooks/use-file-attachments.d.ts +9 -2
  29. package/dist/human-input.d.ts +3 -1
  30. package/dist/index.d.ts +5 -1
  31. package/dist/index.js +139 -53
  32. package/dist/index.js.map +1 -1
  33. package/dist/interaction.js +3 -3
  34. package/dist/session-ui.js +4 -4
  35. package/dist/session.d.ts +2 -0
  36. package/dist/session.js +7 -5
  37. package/dist/timeline/index.d.ts +1 -0
  38. package/dist/timeline/screenshot-lightbox.d.ts +16 -1
  39. package/package.json +6 -2
  40. package/src/accounts.tsx +970 -0
  41. package/src/components/chat-composer.tsx +88 -84
  42. package/src/components/composer.tsx +53 -11
  43. package/src/components/file-browser.tsx +33 -20
  44. package/src/components/human-input-surface.tsx +10 -6
  45. package/src/components/message-timeline.tsx +37 -9
  46. package/src/components/sandbox-files.tsx +42 -2
  47. package/src/components/sandbox-workspace.tsx +10 -0
  48. package/src/embedded-session-client.ts +104 -0
  49. package/src/file-node-visibility.ts +66 -0
  50. package/src/hooks/use-composer.ts +64 -2
  51. package/src/hooks/use-file-attachments.ts +38 -6
  52. package/src/hooks/use-human-input.ts +31 -4
  53. package/src/human-input.ts +12 -1
  54. package/src/index.ts +12 -0
  55. package/src/session.ts +5 -0
  56. package/src/timeline/index.ts +1 -0
  57. package/src/timeline/screenshot-lightbox.tsx +93 -29
  58. package/styles/compiled.css +11 -1
  59. package/styles/tokens.css +3 -1
  60. package/dist/chunk-6H6S5V4Z.js.map +0 -1
  61. package/dist/chunk-ATQJEWCA.js.map +0 -1
  62. package/dist/chunk-FK6VG4LL.js +0 -90
  63. package/dist/chunk-FK6VG4LL.js.map +0 -1
  64. package/dist/chunk-MXJGO7LE.js.map +0 -1
  65. package/dist/chunk-T7VAYG2I.js.map +0 -1
  66. /package/dist/{browser-viewer-GXUICIAG.js.map → browser-viewer-AEFHUYZK.js.map} +0 -0
  67. /package/dist/{chunk-QGBJ6GHG.js.map → chunk-ELIYWBZR.js.map} +0 -0
  68. /package/dist/{chunk-X4JAFD5R.js.map → chunk-OAM4WAAM.js.map} +0 -0
  69. /package/dist/{computer-viewer-ZOP4Q7A7.js.map → computer-viewer-FWEZISW4.js.map} +0 -0
@@ -50,7 +50,14 @@ export type UseFileAttachmentsResult = {
50
50
  * source file). No-op for an id that isn't a known failed upload.
51
51
  */
52
52
  retry: (id: string) => void;
53
- /** Remove one attachment; revokes its object-URL. */
53
+ /**
54
+ * Keep an attachment's object-URL alive for a consumer that outlives its
55
+ * queue entry (for example, an open route-level lightbox). The returned
56
+ * release is idempotent; pending revocation finishes after the last holder
57
+ * releases. Returns `undefined` when the attachment has no local preview.
58
+ */
59
+ retainPreview: (id: string) => (() => void) | undefined;
60
+ /** Remove one attachment; revokes its object-URL after retained users finish. */
54
61
  remove: (id: string) => void;
55
62
  /**
56
63
  * Remove only finalized files whose durable ids were accepted by a send.
@@ -58,7 +65,7 @@ export type UseFileAttachmentsResult = {
58
65
  * next message.
59
66
  */
60
67
  removeReadyFiles: (fileIds: Iterable<string>) => void;
61
- /** Remove all attachments and revoke every object-URL. */
68
+ /** Remove all attachments and revoke every unretained object-URL. */
62
69
  clear: () => void;
63
70
  };
64
71
  /**
@@ -1,4 +1,4 @@
1
- import type { HumanInputQuestion, SessionEvent } from "@opengeni/sdk";
1
+ import type { HumanInputQuestion, SessionEvent, SessionHumanInputRequest } from "@opengeni/sdk";
2
2
  /** Minimal actionable request shape available from the durable event log. */
3
3
  export type PendingHumanInputRequest = {
4
4
  id: string;
@@ -7,6 +7,8 @@ export type PendingHumanInputRequest = {
7
7
  allowSkip: boolean;
8
8
  expiresAt: string | null;
9
9
  };
10
+ /** A pending row stops being actionable at its durable deadline, even before refresh. */
11
+ export declare function isActionableHumanInputRequest(request: Pick<SessionHumanInputRequest, "status" | "expiresAt">, nowMs?: number): boolean;
10
12
  /** Parse one generic `session.humanInput.requested` event defensively. */
11
13
  export declare function humanInputRequestFromEvent(event: Pick<SessionEvent, "type" | "payload" | "turnId">): PendingHumanInputRequest | null;
12
14
  /**
package/dist/index.d.ts CHANGED
@@ -4,7 +4,11 @@ export type { OpenGeniProviderProps } from "./provider.js";
4
4
  export { useOpenGeni, useOpenGeniClient } from "./session-context.js";
5
5
  export { useVideoArtifactPlaybackLoader } from "./hooks/use-video-artifact-playback.js";
6
6
  export type { ClientOverride, OpenGeniContextValue } from "./session-context.js";
7
+ export { createEmbeddedSessionClient } from "./embedded-session-client.js";
8
+ export type { ComposerDraftMapContext, CreateEmbeddedSessionClientOptions, } from "./embedded-session-client.js";
7
9
  export { usePageLiveActivity } from "./hooks/internal.js";
10
+ export { filePathVisibility, visibleFileTree } from "./file-node-visibility.js";
11
+ export type { FileNodeVisibilityContext, FileNodeVisibilityPredicate, FilePathVisibility, } from "./file-node-visibility.js";
8
12
  export { useSession, isTitleEvent } from "./hooks/use-session.js";
9
13
  export type { UseSessionOptions, UseSessionResult } from "./hooks/use-session.js";
10
14
  export { SESSION_EVENT_BROWSER_MAX_BYTES, SESSION_EVENT_BROWSER_MAX_COUNT, SESSION_EVENT_BROWSER_PENDING_MAX_BYTES, SESSION_EVENT_BROWSER_PENDING_MAX_COUNT, SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES, boundBrowserSessionEventWindow, useSessionEvents, } from "./hooks/use-session-events.js";
@@ -97,7 +101,7 @@ export type { ActivityItem, AgentMessageItem, AuthNeededItem, ContextCompactionI
97
101
  export { createDefaultToolRegistry, createToolRegistry, defaultToolRegistry, rawTypeOf, } from "./timeline/index.js";
98
102
  export type { CreateToolRegistryOptions, RetainedArtifactLoader, RetainedScreenshotLoader, VideoArtifactPlaybackLoader, ToolRegistry, ToolRegistryEntry, ToolRenderer, ToolRendererProps, } from "./timeline/index.js";
99
103
  export { ActivityDisclosure, ActivityRail, BodyNote, DisclosureDefaultsProvider, LightboxProvider, MediaEmpty, MediaSkeleton, PayloadBlock, ScreenshotFigure, TermBlock, Thumbnail, TurnSummary, BUILT_IN_TURN_SUMMARY_FACET_IDS, useLightbox, useLightboxOptional, } from "./timeline/index.js";
100
- export type { ActivityDisclosureProps, ActivityRailProps, DisclosureChip, BuiltInTurnSummaryFacetId, TurnOutcome, TurnSummaryContext, TurnSummaryFacet, TurnSummaryFacetConfiguration, TurnSummaryFacetResult, TurnSummaryOptions, TurnSummaryProps, } from "./timeline/index.js";
104
+ export type { ActivityDisclosureProps, ActivityRailProps, DisclosureChip, BuiltInTurnSummaryFacetId, TurnOutcome, TurnSummaryContext, TurnSummaryFacet, TurnSummaryFacetConfiguration, TurnSummaryFacetResult, TurnSummaryOptions, TurnSummaryProps, LightboxControlLabels, } from "./timeline/index.js";
101
105
  export { applyPatchOps, applyPatchOpsFromToolItem, controlCaret, execTruncated, isApplyPatch, isExecSessionLostBanner, looksBinary, parseExecBannerSessionId, parseFreeformApplyPatch, parseToolArgs, sandboxCommandExitCode, stripExecBanner, tailPeek, unwrapMcpOutput, v4aToGitFileDiff, } from "./timeline/index.js";
102
106
  export type { ApplyPatchOperation } from "./timeline/index.js";
103
107
  export { argHint, defaultCommands, filterCommands, firstMissingRequiredArg, hasPermission, matchCommand, parseCommandLine, } from "./commands/registry.js";
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES,
7
7
  approvalsFromRequiresAction,
8
8
  boundBrowserSessionEventWindow,
9
- humanInputRequestFromEvent,
9
+ createEmbeddedSessionClient,
10
10
  isGoalEvent,
11
11
  isHumanInputEvent,
12
12
  isLineageRefreshEvent,
@@ -14,7 +14,6 @@ import {
14
14
  isTitleEvent,
15
15
  isTurnQueueEvent,
16
16
  projectPendingApprovals,
17
- projectPendingHumanInputRequests,
18
17
  useFileAttachments,
19
18
  useGoal,
20
19
  useHumanInputRequests,
@@ -24,7 +23,7 @@ import {
24
23
  useSessionLineage,
25
24
  useSessionMcpApprovalPolicy,
26
25
  useTurnQueue
27
- } from "./chunk-ATQJEWCA.js";
26
+ } from "./chunk-YJFGAFBD.js";
28
27
  import {
29
28
  CONNECTION_STATUS_META,
30
29
  ConnectionDot,
@@ -109,14 +108,14 @@ import {
109
108
  useSlashCommands,
110
109
  useTranscription,
111
110
  useVoiceInput
112
- } from "./chunk-ZUT5QSQB.js";
111
+ } from "./chunk-RGALCTWO.js";
113
112
  import {
114
113
  FILE_ONLY_MESSAGE_TEXT,
115
114
  composeSendInput,
116
115
  shouldSteerOnKey,
117
116
  shouldSubmitOnKey,
118
117
  useComposer
119
- } from "./chunk-T7VAYG2I.js";
118
+ } from "./chunk-MZ2G2XBA.js";
120
119
  import {
121
120
  BillingClassMark,
122
121
  ModelPolicyPicker,
@@ -155,7 +154,6 @@ import {
155
154
  GeneratedVideoPlayer,
156
155
  HumanInputForm,
157
156
  HumanInputSurface,
158
- LightboxProvider,
159
157
  Markdown,
160
158
  MediaEmpty,
161
159
  MediaSkeleton,
@@ -200,30 +198,33 @@ import {
200
198
  stripExecBanner,
201
199
  tailPeek,
202
200
  unwrapMcpOutput,
203
- useLightbox,
204
- useLightboxOptional,
205
201
  useThemeType,
206
202
  userMessageLikelyNeedsDisclosure,
207
203
  v4aToGitFileDiff
208
- } from "./chunk-6H6S5V4Z.js";
204
+ } from "./chunk-HQVCKCLG.js";
209
205
  import {
210
206
  buildTimeline,
211
207
  createOlderHistoryLoadReceipt,
212
208
  creditExhaustedFromEvents,
213
209
  extractSessionRef,
214
210
  groupTimeline,
211
+ humanInputRequestFromEvent,
212
+ projectPendingHumanInputRequests,
215
213
  sessionStatusFromEvents,
216
214
  toolDisplayName
217
- } from "./chunk-MXJGO7LE.js";
215
+ } from "./chunk-D3UIAJKY.js";
218
216
  import {
219
217
  TimelineAnnotationsChip
220
218
  } from "./chunk-WSK7G5LE.js";
221
219
  import {
220
+ LightboxProvider,
222
221
  Tooltip,
223
222
  TooltipContent,
224
223
  TooltipProvider,
225
- TooltipTrigger
226
- } from "./chunk-FK6VG4LL.js";
224
+ TooltipTrigger,
225
+ useLightbox,
226
+ useLightboxOptional
227
+ } from "./chunk-YFKJ7VZH.js";
227
228
  import {
228
229
  usePortalTokenSource,
229
230
  usePortalTokenStyle
@@ -251,6 +252,10 @@ import {
251
252
  useOpenGeni,
252
253
  useOpenGeniClient
253
254
  } from "./chunk-NEXLLTP4.js";
255
+ import {
256
+ copyTextToClipboard,
257
+ tableElementToTsv
258
+ } from "./chunk-JVYQRRC4.js";
254
259
  import {
255
260
  COMPOSER_PAYMENT_REQUIRED_MESSAGE,
256
261
  CREDIT_EXHAUSTION_MESSAGE,
@@ -267,10 +272,6 @@ import {
267
272
  import {
268
273
  cn
269
274
  } from "./chunk-22KP6LR5.js";
270
- import {
271
- copyTextToClipboard,
272
- tableElementToTsv
273
- } from "./chunk-JVYQRRC4.js";
274
275
 
275
276
  // src/hooks/use-video-artifact-playback.ts
276
277
  import { useMemo } from "react";
@@ -291,6 +292,39 @@ function useVideoArtifactPlaybackLoader(options = {}) {
291
292
  );
292
293
  }
293
294
 
295
+ // src/file-node-visibility.ts
296
+ function pathIsInsideDirectory(path, directory) {
297
+ if (!path.startsWith(directory) || path === directory) return false;
298
+ if (directory.endsWith("/") || directory.endsWith("\\")) return true;
299
+ const boundary = path[directory.length];
300
+ return boundary === "/" || boundary === "\\";
301
+ }
302
+ function visibleFileTree(nodes, predicate, parent = null, depth = 0) {
303
+ if (!predicate) return nodes;
304
+ const visible = [];
305
+ for (const node of nodes) {
306
+ if (!predicate(node, { depth, parent })) continue;
307
+ visible.push(
308
+ node.children === void 0 ? node : {
309
+ ...node,
310
+ children: visibleFileTree(node.children, predicate, node, depth + 1)
311
+ }
312
+ );
313
+ }
314
+ return visible;
315
+ }
316
+ function filePathVisibility(nodes, path, predicate, parent = null, depth = 0) {
317
+ if (!predicate) return "visible";
318
+ for (const node of nodes) {
319
+ if (node.path !== path && !pathIsInsideDirectory(path, node.path)) continue;
320
+ if (!predicate(node, { depth, parent })) return "hidden";
321
+ if (node.path === path) return "visible";
322
+ if (node.kind !== "dir" || node.children === void 0) return "unknown";
323
+ return filePathVisibility(node.children, path, predicate, node, depth + 1);
324
+ }
325
+ return "unknown";
326
+ }
327
+
294
328
  // src/hooks/use-last-started-turn-policy.ts
295
329
  import { useCallback, useEffect } from "react";
296
330
  function isLastStartedTurnPolicyEvent(event) {
@@ -3942,7 +3976,7 @@ function ApprovalSurface({
3942
3976
 
3943
3977
  // src/components/chat-composer.tsx
3944
3978
  import { LayoutGroup, motion } from "motion/react";
3945
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3979
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3946
3980
  function ChatComposer({
3947
3981
  composer,
3948
3982
  responsiveBasis,
@@ -3993,7 +4027,7 @@ function ChatComposer({
3993
4027
  attachments || models || controlsLeading || controlsStart || transcription
3994
4028
  );
3995
4029
  const stackActions = hasControls && Boolean(actionsStart);
3996
- return /* @__PURE__ */ jsxs2(Root, { controller, responsiveBasis, className, children: [
4030
+ return /* @__PURE__ */ jsx2(Fragment2, { children: /* @__PURE__ */ jsxs2(Root, { controller, responsiveBasis, className, children: [
3997
4031
  /* @__PURE__ */ jsxs2(Frame, { children: [
3998
4032
  /* @__PURE__ */ jsx2(CommandPalette2, {}),
3999
4033
  /* @__PURE__ */ jsxs2(Surface, { children: [
@@ -4080,7 +4114,7 @@ function ChatComposer({
4080
4114
  ] }),
4081
4115
  /* @__PURE__ */ jsx2(Help, {}),
4082
4116
  /* @__PURE__ */ jsx2(Status, {})
4083
- ] });
4117
+ ] }) });
4084
4118
  }
4085
4119
 
4086
4120
  // src/components/fleet-tile.tsx
@@ -4758,7 +4792,7 @@ function collectUnicodeContent(values) {
4758
4792
  }
4759
4793
 
4760
4794
  // src/components/file-browser.tsx
4761
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4795
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4762
4796
  var STATUS_TINT = {
4763
4797
  added: "text-og-status-idle",
4764
4798
  modified: "text-og-status-running",
@@ -4786,7 +4820,7 @@ function itemKey(item) {
4786
4820
  return `residue:${item.path}`;
4787
4821
  }
4788
4822
  }
4789
- function pathIsInsideDirectory(path, directory) {
4823
+ function pathIsInsideDirectory2(path, directory) {
4790
4824
  if (!path.startsWith(directory) || path === directory) return false;
4791
4825
  if (directory.endsWith("/") || directory.endsWith("\\")) return true;
4792
4826
  const boundary = path[directory.length];
@@ -4795,7 +4829,7 @@ function pathIsInsideDirectory(path, directory) {
4795
4829
  function findNode(nodes, path) {
4796
4830
  for (const node of nodes) {
4797
4831
  if (node.path === path) return node;
4798
- if (node.kind === "dir" && node.children && pathIsInsideDirectory(path, node.path)) {
4832
+ if (node.kind === "dir" && node.children && pathIsInsideDirectory2(path, node.path)) {
4799
4833
  const hit = findNode(node.children, path);
4800
4834
  if (hit) return hit;
4801
4835
  }
@@ -4810,7 +4844,7 @@ function traceRevealPath(nodes, targetPath) {
4810
4844
  frontier: node.kind === "dir" && node.children === void 0 ? node.path : null
4811
4845
  };
4812
4846
  }
4813
- if (node.kind !== "dir" || !pathIsInsideDirectory(targetPath, node.path)) continue;
4847
+ if (node.kind !== "dir" || !pathIsInsideDirectory2(targetPath, node.path)) continue;
4814
4848
  if (node.children === void 0) {
4815
4849
  return { directories: [node.path], frontier: node.path };
4816
4850
  }
@@ -4827,6 +4861,7 @@ function FileBrowser({
4827
4861
  fallback,
4828
4862
  onSelectFile,
4829
4863
  selectedPath,
4864
+ isNodeVisible,
4830
4865
  revealPath,
4831
4866
  revealPathRequestId,
4832
4867
  renderNode,
@@ -4858,6 +4893,10 @@ function FileBrowser({
4858
4893
  () => typeof document === "undefined" ? null : document.getElementById(treeId),
4859
4894
  [treeId]
4860
4895
  );
4896
+ const visibleTree = useMemo10(
4897
+ () => visibleFileTree(result.tree, isNodeVisible),
4898
+ [isNodeVisible, result.tree]
4899
+ );
4861
4900
  useBrowserLayoutEffect(() => {
4862
4901
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
4863
4902
  const query = window.matchMedia("(pointer: coarse)");
@@ -4888,10 +4927,14 @@ function FileBrowser({
4888
4927
  setActive(null);
4889
4928
  setRevealRequest({ path: revealPath, requestId: effectiveRevealRequestId });
4890
4929
  }, [effectiveRevealRequestId, revealPath]);
4891
- const cursor = active ?? selectedPath ?? null;
4930
+ const visibleActive = active && findNode(visibleTree, active) ? active : null;
4931
+ const cursor = visibleActive ?? (selectedPath && findNode(visibleTree, selectedPath) ? selectedPath : null);
4932
+ useEffect13(() => {
4933
+ if (active !== null && visibleActive === null) setActive(null);
4934
+ }, [active, visibleActive]);
4892
4935
  const expand = useCallback19(
4893
4936
  async (path) => {
4894
- const node = findNode(result.tree, path);
4937
+ const node = findNode(visibleTree, path);
4895
4938
  if (node && node.kind === "dir" && node.children === void 0) {
4896
4939
  setLoadingPaths((prev) => new Set(prev).add(path));
4897
4940
  try {
@@ -4905,7 +4948,7 @@ function FileBrowser({
4905
4948
  }
4906
4949
  }
4907
4950
  },
4908
- [result]
4951
+ [result, visibleTree]
4909
4952
  );
4910
4953
  const open = useCallback19(
4911
4954
  (path) => {
@@ -4916,7 +4959,7 @@ function FileBrowser({
4916
4959
  );
4917
4960
  useEffect13(() => {
4918
4961
  if (!revealRequest) return;
4919
- const trace = traceRevealPath(result.tree, revealRequest.path);
4962
+ const trace = traceRevealPath(visibleTree, revealRequest.path);
4920
4963
  if (trace.directories.length > 0) {
4921
4964
  setExpanded((previous) => {
4922
4965
  const next = new Set(previous);
@@ -4935,7 +4978,7 @@ function FileBrowser({
4935
4978
  }
4936
4979
  attemptedRevealPathsRef.current.add(frontier);
4937
4980
  void expand(frontier);
4938
- }, [expand, loadingPaths, result.expandingPaths, result.tree, revealRequest]);
4981
+ }, [expand, loadingPaths, result.expandingPaths, revealRequest, visibleTree]);
4939
4982
  const toggle = useCallback19(
4940
4983
  async (node) => {
4941
4984
  if (node.kind !== "dir") return;
@@ -4979,9 +5022,9 @@ function FileBrowser({
4979
5022
  }
4980
5023
  }
4981
5024
  };
4982
- walk(result.tree, 0);
5025
+ walk(visibleTree, 0);
4983
5026
  return items;
4984
- }, [result.tree, expanded, draftCreate, loadingPaths, result.expandingPaths, cold]);
5027
+ }, [visibleTree, expanded, draftCreate, loadingPaths, result.expandingPaths, cold]);
4985
5028
  const unicodeFontPaths = useMemo10(
4986
5029
  () => renderItems.flatMap((item) => item.type === "node" ? [item.node.path] : []),
4987
5030
  [renderItems]
@@ -5005,9 +5048,9 @@ function FileBrowser({
5005
5048
  if (node.children) visit(node.children);
5006
5049
  });
5007
5050
  };
5008
- visit(result.tree);
5051
+ visit(visibleTree);
5009
5052
  return positions;
5010
- }, [result.tree]);
5053
+ }, [visibleTree]);
5011
5054
  const cursorIndex = cursor ? rowIndexByPath.get(cursor) ?? -1 : -1;
5012
5055
  const activeDescendantId = cursorIndex >= 0 ? `${treeId}-item-${cursorIndex}` : void 0;
5013
5056
  const supportsMutation = editable && result.source === "live" && result.error === null && !result.loading;
@@ -5082,7 +5125,7 @@ function FileBrowser({
5082
5125
  const draft = draftRename;
5083
5126
  setDraftRename(null);
5084
5127
  if (!draft || !supportsMutation) return;
5085
- const node = findNode(result.tree, draft.path);
5128
+ const node = findNode(visibleTree, draft.path);
5086
5129
  const trimmed = name.trim().replace(/\/+$/, "");
5087
5130
  if (!node || !trimmed || trimmed === node.name) return;
5088
5131
  const newPath = joinPath(parentOf2(draft.path), trimmed);
@@ -5098,19 +5141,19 @@ function FileBrowser({
5098
5141
  setBusy(false);
5099
5142
  }
5100
5143
  },
5101
- [draftRename, supportsMutation, result, selectedPath, active, onSelectFile]
5144
+ [draftRename, supportsMutation, result, selectedPath, active, onSelectFile, visibleTree]
5102
5145
  );
5103
5146
  const startCreate = useCallback19(
5104
5147
  (kind) => {
5105
5148
  if (!supportsMutation) return;
5106
- const anchor = cursor ? findNode(result.tree, cursor) : void 0;
5149
+ const anchor = cursor ? findNode(visibleTree, cursor) : void 0;
5107
5150
  const parent = anchor ? anchor.kind === "dir" ? anchor.path : parentOf2(anchor.path) : "";
5108
5151
  if (parent) open(parent);
5109
5152
  setDraftRename(null);
5110
5153
  setMenu(null);
5111
5154
  setDraftCreate({ parent, kind });
5112
5155
  },
5113
- [supportsMutation, cursor, result.tree, open]
5156
+ [supportsMutation, cursor, open, visibleTree]
5114
5157
  );
5115
5158
  const startRename = useCallback19(
5116
5159
  (node) => {
@@ -5125,7 +5168,7 @@ function FileBrowser({
5125
5168
  async (targetDir, sourcePath) => {
5126
5169
  setDragOver(null);
5127
5170
  if (!supportsMutation || !sourcePath) return;
5128
- const src = findNode(result.tree, sourcePath);
5171
+ const src = findNode(visibleTree, sourcePath);
5129
5172
  if (!src) return;
5130
5173
  if (parentOf2(sourcePath) === targetDir) return;
5131
5174
  if (targetDir === sourcePath || targetDir.startsWith(`${sourcePath}/`)) return;
@@ -5143,7 +5186,7 @@ function FileBrowser({
5143
5186
  setBusy(false);
5144
5187
  }
5145
5188
  },
5146
- [supportsMutation, result, selectedPath, active, onSelectFile]
5189
+ [supportsMutation, result, selectedPath, active, onSelectFile, visibleTree]
5147
5190
  );
5148
5191
  const onKeyDown = useCallback19(
5149
5192
  (e) => {
@@ -5276,9 +5319,9 @@ function FileBrowser({
5276
5319
  window.removeEventListener("resize", close);
5277
5320
  };
5278
5321
  }, [menu]);
5279
- const showErrorEmpty = result.error && result.tree.length === 0 && !draftCreate;
5280
- const showDegradedTree = result.error && result.tree.length > 0;
5281
- const showEmpty = !result.loading && result.tree.length === 0 && !draftCreate;
5322
+ const showErrorEmpty = result.error && visibleTree.length === 0 && !draftCreate;
5323
+ const showDegradedTree = result.error && visibleTree.length > 0;
5324
+ const showEmpty = !result.loading && visibleTree.length === 0 && !draftCreate;
5282
5325
  const showToolbar = supportsMutation || result.loading;
5283
5326
  const usesVirtualTree = !showErrorEmpty && !showEmpty && renderItems.length > 500;
5284
5327
  const renderNodeRow = (node, depth) => {
@@ -5473,7 +5516,7 @@ function FileBrowser({
5473
5516
  "aria-label": "File actions",
5474
5517
  className: "flex shrink-0 flex-wrap items-center gap-0.5 border-b border-og-border px-1 py-1",
5475
5518
  children: [
5476
- supportsMutation ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
5519
+ supportsMutation ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
5477
5520
  /* @__PURE__ */ jsx5(ToolbarButton, { label: "New file", onClick: () => startCreate("file"), disabled: busy, children: /* @__PURE__ */ jsx5(FilePlusIcon, { className: "size-3.5" }) }),
5478
5521
  /* @__PURE__ */ jsx5(ToolbarButton, { label: "New folder", onClick: () => startCreate("dir"), disabled: busy, children: /* @__PURE__ */ jsx5(FolderPlusIcon, { className: "size-3.5" }) }),
5479
5522
  /* @__PURE__ */ jsx5(
@@ -5481,7 +5524,7 @@ function FileBrowser({
5481
5524
  {
5482
5525
  label: "Rename",
5483
5526
  onClick: () => {
5484
- const node = cursor ? findNode(result.tree, cursor) : void 0;
5527
+ const node = cursor ? findNode(visibleTree, cursor) : void 0;
5485
5528
  if (node) startRename(node);
5486
5529
  },
5487
5530
  disabled: busy || !cursor,
@@ -5493,7 +5536,7 @@ function FileBrowser({
5493
5536
  {
5494
5537
  label: "Delete",
5495
5538
  onClick: (event) => {
5496
- const node = cursor ? findNode(result.tree, cursor) : void 0;
5539
+ const node = cursor ? findNode(visibleTree, cursor) : void 0;
5497
5540
  if (node) void runDelete(node, event.currentTarget);
5498
5541
  },
5499
5542
  disabled: busy || !cursor,
@@ -5938,7 +5981,7 @@ function ContextMenu({
5938
5981
  "bg-og-surface-1"
5939
5982
  ),
5940
5983
  children: [
5941
- isDir && /* @__PURE__ */ jsxs5(Fragment2, { children: [
5984
+ isDir && /* @__PURE__ */ jsxs5(Fragment3, { children: [
5942
5985
  item("New file", /* @__PURE__ */ jsx5(FilePlusIcon, { className: "size-3.5" }), onNewFile),
5943
5986
  item("New folder", /* @__PURE__ */ jsx5(FolderPlusIcon, { className: "size-3.5" }), onNewFolder),
5944
5987
  /* @__PURE__ */ jsx5("div", { role: "separator", className: "my-1 h-px bg-og-border" })
@@ -7154,7 +7197,7 @@ function EditorSkeleton() {
7154
7197
  import { FileCode2Icon, FileWarningIcon as FileWarningIcon2, LoaderCircleIcon } from "lucide-react";
7155
7198
  import { useCallback as useCallback23, useEffect as useEffect18, useRef as useRef15, useState as useState15 } from "react";
7156
7199
  import { Group, Panel, Separator } from "react-resizable-panels";
7157
- import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
7200
+ import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
7158
7201
  function SandboxFiles({
7159
7202
  files,
7160
7203
  git,
@@ -7164,6 +7207,7 @@ function SandboxFiles({
7164
7207
  onEditIntent,
7165
7208
  initialSelectedPath,
7166
7209
  onSelectedPathChange,
7210
+ isNodeVisible,
7167
7211
  requestedPath,
7168
7212
  requestedLine,
7169
7213
  requestedPathRequestId,
@@ -7200,6 +7244,19 @@ function SandboxFiles({
7200
7244
  setTreeRevealRequest(null);
7201
7245
  return;
7202
7246
  }
7247
+ if (isNodeVisible && files.loading && files.tree.length === 0) return;
7248
+ if (isNodeVisible && !files.loading && files.tree.length === 0) {
7249
+ handledRequestRef.current = requestKey;
7250
+ pendingRequestRef.current = null;
7251
+ setTreeRevealRequest(null);
7252
+ return;
7253
+ }
7254
+ if (filePathVisibility(files.tree, requestedPath, isNodeVisible) === "hidden") {
7255
+ handledRequestRef.current = requestKey;
7256
+ pendingRequestRef.current = null;
7257
+ setTreeRevealRequest(null);
7258
+ return;
7259
+ }
7203
7260
  handledRequestRef.current = requestKey;
7204
7261
  pendingRequestRef.current = null;
7205
7262
  setSelected(requestedPath);
@@ -7208,7 +7265,16 @@ function SandboxFiles({
7208
7265
  setFocusLine(requestedLine != null && requestedLine > 0 ? requestedLine : null);
7209
7266
  setTreeRevealRequest({ path: requestedPath, requestId: requestKey });
7210
7267
  setViewReloadRevision((revision) => revision + 1);
7211
- }, [onSelectedPathChange, requestKey, requestedLine, requestedPath, requestedPathReady]);
7268
+ }, [
7269
+ files.loading,
7270
+ files.tree,
7271
+ isNodeVisible,
7272
+ onSelectedPathChange,
7273
+ requestKey,
7274
+ requestedLine,
7275
+ requestedPath,
7276
+ requestedPathReady
7277
+ ]);
7212
7278
  const rootRef = useRef15(null);
7213
7279
  const [wide, setWide] = useState15(false);
7214
7280
  useEffect18(() => {
@@ -7231,7 +7297,18 @@ function SandboxFiles({
7231
7297
  };
7232
7298
  }, []);
7233
7299
  const resolvedTheme = useThemeType(themeType);
7234
- const viewPath = selected;
7300
+ const selectedVisibility = selected ? filePathVisibility(files.tree, selected, isNodeVisible) : "unknown";
7301
+ const visibilityPending = Boolean(isNodeVisible && files.loading && files.tree.length === 0);
7302
+ const viewPath = selectedVisibility === "hidden" || visibilityPending ? null : selected;
7303
+ useEffect18(() => {
7304
+ if (selected === null || selectedVisibility !== "hidden") return;
7305
+ setSelected(null);
7306
+ onSelectedPathChange?.(null);
7307
+ setEditMode(false);
7308
+ setFocusLine(null);
7309
+ setTreeRevealRequest(null);
7310
+ setLiveRequestedPath(null);
7311
+ }, [onSelectedPathChange, selected, selectedVisibility]);
7235
7312
  const fileView = useFileView(
7236
7313
  viewPath,
7237
7314
  files.readFile,
@@ -7327,6 +7404,7 @@ function SandboxFiles({
7327
7404
  FileBrowser,
7328
7405
  {
7329
7406
  result: files,
7407
+ isNodeVisible,
7330
7408
  selectedPath: selected ?? void 0,
7331
7409
  ...treeRevealRequest ? {
7332
7410
  revealPath: treeRevealRequest.path,
@@ -7444,7 +7522,7 @@ function SandboxFiles({
7444
7522
  " is a binary file (",
7445
7523
  fileView.sizeBytes ?? 0,
7446
7524
  " bytes)."
7447
- ] }) : fileView.content !== null ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
7525
+ ] }) : fileView.content !== null ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
7448
7526
  fileView.truncated && /* @__PURE__ */ jsxs8("div", { className: "border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-xs text-og-status-running", children: [
7449
7527
  "Large file \u2014 showing a truncated preview (",
7450
7528
  fileView.sizeBytes ?? 0,
@@ -7781,7 +7859,7 @@ import {
7781
7859
  useDefaultLayout,
7782
7860
  usePanelRef
7783
7861
  } from "react-resizable-panels";
7784
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
7862
+ import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
7785
7863
  var SERVER_LAYOUT_STORAGE = {
7786
7864
  getItem: () => null,
7787
7865
  setItem: () => {
@@ -8064,7 +8142,7 @@ function WorkspaceDock({
8064
8142
  current,
8065
8143
  onTab: setTab,
8066
8144
  accessory: headerAccessory,
8067
- controls: /* @__PURE__ */ jsxs9(Fragment4, { children: [
8145
+ controls: /* @__PURE__ */ jsxs9(Fragment5, { children: [
8068
8146
  /* @__PURE__ */ jsx11(
8069
8147
  ChromeButton,
8070
8148
  {
@@ -8345,11 +8423,11 @@ import {
8345
8423
  } from "lucide-react";
8346
8424
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
8347
8425
  var LazyBrowserViewer = lazy2(async () => {
8348
- const { BrowserViewer } = await import("./browser-viewer-GXUICIAG.js");
8426
+ const { BrowserViewer } = await import("./browser-viewer-AEFHUYZK.js");
8349
8427
  return { default: BrowserViewer };
8350
8428
  });
8351
8429
  var LazyComputerViewer = lazy2(async () => {
8352
- const { ComputerViewer } = await import("./computer-viewer-ZOP4Q7A7.js");
8430
+ const { ComputerViewer } = await import("./computer-viewer-FWEZISW4.js");
8353
8431
  return { default: ComputerViewer };
8354
8432
  });
8355
8433
  var WORKBENCH_TAB_CHANGES = "changes";
@@ -8482,6 +8560,7 @@ function useSandboxWorkspaceTabs(options) {
8482
8560
  onOpenFile,
8483
8561
  initialFilePath,
8484
8562
  onFilePathChange,
8563
+ isFileNodeVisible,
8485
8564
  initialBrowserSessionId,
8486
8565
  onBrowserSessionIdChange,
8487
8566
  initialComputerSessionId,
@@ -8749,6 +8828,7 @@ function useSandboxWorkspaceTabs(options) {
8749
8828
  {
8750
8829
  files,
8751
8830
  git,
8831
+ isNodeVisible: isFileNodeVisible,
8752
8832
  fileSystemAvailable: fileSystemOn || captureAvailable,
8753
8833
  editable: filesEditable && files.source === "live" && files.error === null && !files.loading,
8754
8834
  workspaceResting: !liveWorkspaceExpected && liveness !== void 0 && !capturePending && !captureAvailable && !workspaceWaking,
@@ -8856,6 +8936,7 @@ function useSandboxWorkspaceTabs(options) {
8856
8936
  onOpenFile,
8857
8937
  initialFilePath,
8858
8938
  onFilePathChange,
8939
+ isFileNodeVisible,
8859
8940
  initialBrowserSessionId,
8860
8941
  onBrowserSessionIdChange,
8861
8942
  initialComputerSessionId,
@@ -8910,6 +8991,7 @@ function SandboxWorkspace(props) {
8910
8991
  onActiveTabChange,
8911
8992
  initialFilePath,
8912
8993
  onFilePathChange,
8994
+ isFileNodeVisible,
8913
8995
  openFileRequest,
8914
8996
  initialBrowserSessionId,
8915
8997
  onBrowserSessionIdChange,
@@ -8991,6 +9073,7 @@ function SandboxWorkspace(props) {
8991
9073
  ...browserExtensionSetupUrl ? { browserExtensionSetupUrl } : {},
8992
9074
  initialFilePath,
8993
9075
  onFilePathChange,
9076
+ isFileNodeVisible,
8994
9077
  initialBrowserSessionId,
8995
9078
  onBrowserSessionIdChange,
8996
9079
  initialComputerSessionId,
@@ -9548,6 +9631,7 @@ export {
9548
9631
  controlCaret,
9549
9632
  copyTextToClipboard,
9550
9633
  createDefaultToolRegistry,
9634
+ createEmbeddedSessionClient,
9551
9635
  createOlderHistoryLoadReceipt,
9552
9636
  createToolRegistry,
9553
9637
  createVoiceRecordingManifest,
@@ -9564,6 +9648,7 @@ export {
9564
9648
  effortOptionsForModel,
9565
9649
  execTruncated,
9566
9650
  extractSessionRef,
9651
+ filePathVisibility,
9567
9652
  filterCommands,
9568
9653
  findPickerRow,
9569
9654
  firstMissingRequiredArg,
@@ -9680,6 +9765,7 @@ export {
9680
9765
  useWorkspaces,
9681
9766
  userMessageLikelyNeedsDisclosure,
9682
9767
  v4aToGitFileDiff,
9768
+ visibleFileTree,
9683
9769
  xtermThemeFromTokens
9684
9770
  };
9685
9771
  //# sourceMappingURL=index.js.map