@opengeni/react 7.6.1-canary.37073905159001 → 7.6.1

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 (136) hide show
  1. package/README.md +2 -19
  2. package/dist/{browser-viewer-63TXMINB.js → browser-viewer-5X47I6T2.js} +5 -6
  3. package/dist/{chunk-TKB4SB44.js → chunk-45GE35O7.js} +2 -10
  4. package/dist/chunk-45GE35O7.js.map +1 -0
  5. package/dist/{chunk-DOJWJQ3F.js → chunk-5EXGU7UF.js} +3 -3
  6. package/dist/{chunk-YN7I3STW.js → chunk-6NEZPF53.js} +32 -153
  7. package/dist/chunk-6NEZPF53.js.map +1 -0
  8. package/dist/{chunk-I7IWRQLN.js → chunk-BI57CQUV.js} +2 -2
  9. package/dist/{chunk-6ZSWSH4I.js → chunk-CHPKSLPN.js} +1 -3
  10. package/dist/chunk-CHPKSLPN.js.map +1 -0
  11. package/dist/{chunk-Q5QBEZIQ.js → chunk-DV2DBNPQ.js} +29 -48
  12. package/dist/chunk-DV2DBNPQ.js.map +1 -0
  13. package/dist/{chunk-RDKBXMWX.js → chunk-FGBCYQOT.js} +74 -120
  14. package/dist/chunk-FGBCYQOT.js.map +1 -0
  15. package/dist/{chunk-AAG4R3QN.js → chunk-KGENSZKS.js} +3 -4
  16. package/dist/chunk-KGENSZKS.js.map +1 -0
  17. package/dist/{chunk-YQEAA6LT.js → chunk-KZ73RL76.js} +3 -7
  18. package/dist/chunk-KZ73RL76.js.map +1 -0
  19. package/dist/{chunk-LFXYGZWK.js → chunk-LZ3KHA55.js} +60 -169
  20. package/dist/chunk-LZ3KHA55.js.map +1 -0
  21. package/dist/{chunk-2QUSQVF2.js → chunk-UINDK6C3.js} +3 -3
  22. package/dist/{chunk-UTRTG6LH.js → chunk-UJRYEWZI.js} +8 -48
  23. package/dist/chunk-UJRYEWZI.js.map +1 -0
  24. package/dist/{chunk-XOAMRDDK.js → chunk-VGIKFIO2.js} +3 -6
  25. package/dist/chunk-VGIKFIO2.js.map +1 -0
  26. package/dist/{chunk-ELCE5SXV.js → chunk-WZ55DVGK.js} +4 -8
  27. package/dist/chunk-WZ55DVGK.js.map +1 -0
  28. package/dist/{chunk-IQUCRAT7.js → chunk-XA6R7DJQ.js} +3 -3
  29. package/dist/{chunk-TOAH2BKA.js → chunk-YCGBREUV.js} +2 -6
  30. package/dist/{chunk-TOAH2BKA.js.map → chunk-YCGBREUV.js.map} +1 -1
  31. package/dist/{chunk-HNFCAQ5R.js → chunk-YRYF2GLG.js} +31 -39
  32. package/dist/chunk-YRYF2GLG.js.map +1 -0
  33. package/dist/{chunk-GISEVGS6.js → chunk-YSMMDOOE.js} +2 -10
  34. package/dist/chunk-YSMMDOOE.js.map +1 -0
  35. package/dist/{chunk-CWWKTNKK.js → chunk-Z3DISEQN.js} +18 -35
  36. package/dist/chunk-Z3DISEQN.js.map +1 -0
  37. package/dist/client.d.ts +1 -4
  38. package/dist/commands/types.d.ts +0 -2
  39. package/dist/components/approval-surface.d.ts +0 -15
  40. package/dist/composer.js +7 -8
  41. package/dist/{computer-viewer-X2MBRZY4.js → computer-viewer-7GF35SNY.js} +4 -5
  42. package/dist/connect.js +3 -3
  43. package/dist/hooks/use-browser-session.d.ts +0 -4
  44. package/dist/hooks/use-composer.d.ts +0 -2
  45. package/dist/hooks/use-computer-session.d.ts +0 -2
  46. package/dist/hooks/use-file-attachments.d.ts +0 -2
  47. package/dist/hooks/use-session-events.d.ts +1 -1
  48. package/dist/hooks/use-workspace-sessions.d.ts +5 -15
  49. package/dist/index.d.ts +2 -2
  50. package/dist/index.js +21 -28
  51. package/dist/index.js.map +1 -1
  52. package/dist/interaction.d.ts +1 -1
  53. package/dist/interaction.js +5 -6
  54. package/dist/interaction.js.map +1 -1
  55. package/dist/{latest-question-CNEZ5KAN.js → latest-question-3BJGKQQ6.js} +3 -3
  56. package/dist/lib/format.d.ts +3 -27
  57. package/dist/lib/interaction-errors.d.ts +0 -3
  58. package/dist/machines.js +4 -5
  59. package/dist/{model-policy-picker-menu-JSA64TNN.js → model-policy-picker-menu-PUTA5JOB.js} +4 -4
  60. package/dist/model-policy.js +1 -1
  61. package/dist/provider.d.ts +1 -5
  62. package/dist/{queue-surface-implementation-HENWYFWA.js → queue-surface-implementation-2CAQAIHM.js} +2 -3
  63. package/dist/{queue-surface-implementation-HENWYFWA.js.map → queue-surface-implementation-2CAQAIHM.js.map} +1 -1
  64. package/dist/realtime.js +2 -2
  65. package/dist/{sandbox-files-BBC47SLD.js → sandbox-files-AEJTWGT4.js} +3 -4
  66. package/dist/session-ui.d.ts +1 -1
  67. package/dist/session-ui.js +12 -13
  68. package/dist/session-ui.js.map +1 -1
  69. package/dist/session.js +6 -7
  70. package/dist/usage.js +1 -2
  71. package/dist/usage.js.map +1 -1
  72. package/package.json +3 -3
  73. package/src/client.ts +1 -5
  74. package/src/commands/registry.ts +15 -18
  75. package/src/commands/types.ts +0 -2
  76. package/src/components/approval-surface.tsx +42 -166
  77. package/src/components/browser-viewer.tsx +9 -38
  78. package/src/components/composer.tsx +2 -9
  79. package/src/components/computer-viewer.tsx +30 -160
  80. package/src/components/generated-video-player.tsx +2 -4
  81. package/src/components/human-input-form.tsx +5 -18
  82. package/src/components/message-timeline.tsx +2 -4
  83. package/src/components/open-geni-chat.tsx +4 -11
  84. package/src/components/queue-surface-state.tsx +1 -3
  85. package/src/components/session-chrome.tsx +2 -5
  86. package/src/components/session-commands-panel.tsx +1 -3
  87. package/src/components/session-conversation.tsx +2 -4
  88. package/src/components/session-list.tsx +5 -7
  89. package/src/components/session-mcp-capability-card.tsx +1 -11
  90. package/src/hooks/internal.ts +2 -3
  91. package/src/hooks/use-browser-session.ts +79 -115
  92. package/src/hooks/use-composer.ts +31 -70
  93. package/src/hooks/use-computer-session.ts +6 -57
  94. package/src/hooks/use-file-attachments.ts +3 -16
  95. package/src/hooks/use-goal.ts +1 -2
  96. package/src/hooks/use-session-capabilities.ts +2 -3
  97. package/src/hooks/use-session-events.ts +8 -15
  98. package/src/hooks/use-slash-commands.ts +11 -6
  99. package/src/hooks/use-turn-queue.ts +1 -2
  100. package/src/hooks/use-workspace-sessions.ts +7 -40
  101. package/src/index.ts +2 -7
  102. package/src/interaction.ts +0 -1
  103. package/src/lib/format.ts +9 -73
  104. package/src/lib/interaction-errors.ts +0 -15
  105. package/src/model-policy.ts +0 -5
  106. package/src/provider.tsx +4 -12
  107. package/src/session-ui.ts +1 -1
  108. package/src/timeline/projection.ts +1 -12
  109. package/styles/compiled.css +0 -14
  110. package/dist/chunk-6ZSWSH4I.js.map +0 -1
  111. package/dist/chunk-AAG4R3QN.js.map +0 -1
  112. package/dist/chunk-CWWKTNKK.js.map +0 -1
  113. package/dist/chunk-ELCE5SXV.js.map +0 -1
  114. package/dist/chunk-GISEVGS6.js.map +0 -1
  115. package/dist/chunk-HNFCAQ5R.js.map +0 -1
  116. package/dist/chunk-LFXYGZWK.js.map +0 -1
  117. package/dist/chunk-Q5QBEZIQ.js.map +0 -1
  118. package/dist/chunk-RDKBXMWX.js.map +0 -1
  119. package/dist/chunk-TKB4SB44.js.map +0 -1
  120. package/dist/chunk-UGLEYEMP.js +0 -33
  121. package/dist/chunk-UGLEYEMP.js.map +0 -1
  122. package/dist/chunk-UTRTG6LH.js.map +0 -1
  123. package/dist/chunk-XOAMRDDK.js.map +0 -1
  124. package/dist/chunk-YN7I3STW.js.map +0 -1
  125. package/dist/chunk-YQEAA6LT.js.map +0 -1
  126. package/dist/lib/error-message.d.ts +0 -7
  127. package/src/lib/error-message.ts +0 -37
  128. /package/dist/{browser-viewer-63TXMINB.js.map → browser-viewer-5X47I6T2.js.map} +0 -0
  129. /package/dist/{chunk-DOJWJQ3F.js.map → chunk-5EXGU7UF.js.map} +0 -0
  130. /package/dist/{chunk-I7IWRQLN.js.map → chunk-BI57CQUV.js.map} +0 -0
  131. /package/dist/{chunk-2QUSQVF2.js.map → chunk-UINDK6C3.js.map} +0 -0
  132. /package/dist/{chunk-IQUCRAT7.js.map → chunk-XA6R7DJQ.js.map} +0 -0
  133. /package/dist/{computer-viewer-X2MBRZY4.js.map → computer-viewer-7GF35SNY.js.map} +0 -0
  134. /package/dist/{latest-question-CNEZ5KAN.js.map → latest-question-3BJGKQQ6.js.map} +0 -0
  135. /package/dist/{model-policy-picker-menu-JSA64TNN.js.map → model-policy-picker-menu-PUTA5JOB.js.map} +0 -0
  136. /package/dist/{sandbox-files-BBC47SLD.js.map → sandbox-files-AEJTWGT4.js.map} +0 -0
@@ -2,7 +2,6 @@ import { ChevronRightIcon, Loader2Icon, SquareIcon } from "lucide-react";
2
2
  import { useState } from "react";
3
3
  import type { UseSessionBackgroundCommandsResult } from "../hooks/use-session-background-commands";
4
4
  import { formatClockTime } from "../lib/format";
5
- import { useErrorMessage } from "../lib/error-message";
6
5
 
7
6
  /** The current session's live commands. Settled commands belong to the timeline. */
8
7
  export function SessionCommandsPanel({
@@ -12,7 +11,6 @@ export function SessionCommandsPanel({
12
11
  commands: UseSessionBackgroundCommandsResult;
13
12
  readOnly?: boolean;
14
13
  }) {
15
- const formatError = useErrorMessage();
16
14
  const [pending, setPending] = useState<string | null>(null);
17
15
  const [error, setError] = useState<string | null>(null);
18
16
  const active = state.commands.filter(
@@ -24,7 +22,7 @@ export function SessionCommandsPanel({
24
22
  try {
25
23
  await state.cancel(id);
26
24
  } catch (cause) {
27
- setError(formatError(cause));
25
+ setError(cause instanceof Error ? cause.message : "Stop was not confirmed. Try again.");
28
26
  } finally {
29
27
  setPending(null);
30
28
  }
@@ -37,7 +37,6 @@ import {
37
37
  import type { UserMessageDisclosureLabels } from "./user-message-body";
38
38
  import { conversationTimeline } from "../conversation-timeline";
39
39
  import { cn } from "../lib/cn";
40
- import { useErrorMessage } from "../lib/error-message";
41
40
 
42
41
  export type SessionConversationProps = ClientOverride & {
43
42
  sessionId: string;
@@ -121,7 +120,6 @@ function Conversation({
121
120
  }: SessionConversationProps) {
122
121
  const scope = { client, workspaceId };
123
122
  const context = useOpenGeni(scope);
124
- const formatError = useErrorMessage();
125
123
  const config = useClientConfigFlags(context.client);
126
124
  const showModelPicker = modelPicker ?? config.modelSelection;
127
125
  const catalog = useWorkspaceModelCatalog({
@@ -205,7 +203,7 @@ function Conversation({
205
203
  style={{ height }}
206
204
  data-og-conversation=""
207
205
  >
208
- {error && <p role="alert">{formatError(error)}</p>}
206
+ {error && <p role="alert">{error.message}</p>}
209
207
  <MessageTimeline
210
208
  renderMessageText={renderMessageText}
211
209
  resolveLink={links}
@@ -267,7 +265,7 @@ function Conversation({
267
265
  await human.respond(id, response);
268
266
  }}
269
267
  respondingRequestId={human.respondingRequestId}
270
- error={human.mutationError ? formatError(human.mutationError) : null}
268
+ error={human.mutationError?.message}
271
269
  autoFocus={false}
272
270
  />
273
271
  {terminal ? (
@@ -4,7 +4,6 @@ import { useEffect, useRef, useState, type FormEvent } from "react";
4
4
  import { useWorkspaceSessions } from "../hooks/use-workspace-sessions";
5
5
  import { cn } from "../lib/cn";
6
6
  import { formatRelativeTime } from "../lib/format";
7
- import { useErrorMessage } from "../lib/error-message";
8
7
  import { useOpenGeni, type ClientOverride } from "../session-context";
9
8
 
10
9
  export type SessionListLabels = {
@@ -91,8 +90,7 @@ export function SessionList({
91
90
  }, [refresh, refreshKey]);
92
91
  const [editing, setEditing] = useState<{ id: string; title: string } | null>(null);
93
92
  const [busy, setBusy] = useState<string | null>(null);
94
- const [error, setError] = useState<{ cause: unknown } | null>(null);
95
- const formatError = useErrorMessage();
93
+ const [error, setError] = useState<string | null>(null);
96
94
  const archiveClient = context.client as unknown as ArchiveClient;
97
95
  const canArchive = archive && typeof archiveClient.updateSessionArchive === "function";
98
96
 
@@ -103,7 +101,7 @@ export function SessionList({
103
101
  await action();
104
102
  await list.refresh();
105
103
  } catch (cause) {
106
- setError({ cause });
104
+ setError(cause instanceof Error ? cause.message : String(cause));
107
105
  } finally {
108
106
  setBusy(null);
109
107
  }
@@ -150,16 +148,16 @@ export function SessionList({
150
148
  </button>
151
149
  ) : null}
152
150
  </div>
153
- {error || list.error ? (
151
+ {error ? (
154
152
  <p role="alert" className="px-2 text-og-xs text-og-status-failed">
155
- {formatError(error ? error.cause : list.error)}
153
+ {error}
156
154
  </p>
157
155
  ) : null}
158
156
  <ul className="flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-1 pb-2">
159
157
  {list.loading && sessions.length === 0 ? (
160
158
  <li className="px-2 py-2 text-og-xs text-og-fg-subtle">{labels.loading}</li>
161
159
  ) : null}
162
- {!list.loading && !list.error && sessions.length === 0 ? (
160
+ {!list.loading && sessions.length === 0 ? (
163
161
  <li className="px-2 py-2 text-og-xs text-og-fg-subtle">{labels.empty}</li>
164
162
  ) : null}
165
163
  {sessions.map((session) => {
@@ -127,17 +127,7 @@ function ScopedCard({
127
127
  ]);
128
128
  if (!invocation || invocation.signal.aborted || lifetime.current !== invocation || !active())
129
129
  return null;
130
- let resolved = catalog.items.find((entry) => entry.id === capabilityId);
131
- // Custom catalog entries may not declare authentication. Discover it from
132
- // the live catalog's endpoint, never from recommendation/host copy.
133
- if (resolved?.kind === "mcp" && !resolved.enabled && !resolved.authKind) {
134
- const endpoint = resolved.mcpUrl ?? resolved.endpointUrl;
135
- if (endpoint) {
136
- const inspected = await client.inspectMcpAuthentication(workspaceId, endpoint);
137
- if (invocation.signal.aborted || lifetime.current !== invocation || !active()) return null;
138
- if (inspected.kind === "oauth2") resolved = { ...resolved, authKind: "oauth2" };
139
- }
140
- }
130
+ const resolved = catalog.items.find((entry) => entry.id === capabilityId);
141
131
  if (!resolved || resolved.kind !== "mcp" || resolved.authKind !== "oauth2")
142
132
  throw new Error(
143
133
  "This recommendation is not an available OAuth MCP integration. Review the current connection catalog.",
@@ -1,7 +1,6 @@
1
1
  import type { SessionEvent } from "@opengeni/sdk";
2
2
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
3
  import type { EmbeddedSessionEventClientLike } from "../client";
4
- import { normalizeError } from "../lib/error-message";
5
4
 
6
5
  const HIDDEN_STREAM_GRACE_MS = 2_000;
7
6
 
@@ -117,7 +116,7 @@ export function usePolledValue<T>(
117
116
  activeLoadRef.current === load &&
118
117
  !requestAbort.signal.aborted
119
118
  ) {
120
- setError(normalizeError(cause));
119
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
121
120
  setLoading(false);
122
121
  }
123
122
  } finally {
@@ -259,7 +258,7 @@ export function useMutationRunner(identity: unknown = undefined): MutationState
259
258
  generation.current === ownedGeneration &&
260
259
  Object.is(identityRef.current, ownedIdentity)
261
260
  ) {
262
- setMutationError(normalizeError(cause));
261
+ setMutationError(cause instanceof Error ? cause : new Error(String(cause)));
263
262
  }
264
263
  return null;
265
264
  } finally {
@@ -30,10 +30,6 @@ export type BrowserFrameInputFence = Pick<
30
30
  | "frameId"
31
31
  >;
32
32
 
33
- export type BrowserInputFailure = Pick<BrowserActionReceipt, "operationId" | "error"> & {
34
- state: Exclude<BrowserActionReceipt["state"], "completed">;
35
- };
36
-
37
33
  export type UseBrowserSessionOptions = EmbeddedBrowserInteractionClientOverride & {
38
34
  browserSessionId: string | null;
39
35
  enabled?: boolean | undefined;
@@ -51,7 +47,6 @@ export type UseBrowserSessionResult = {
51
47
  loading: boolean;
52
48
  mutating: boolean;
53
49
  error: Error | null;
54
- inputFailure: BrowserInputFailure | null;
55
50
  refresh: () => Promise<void>;
56
51
  observeForInput: () => Promise<BrowserObservation>;
57
52
  actFromObservation: (
@@ -101,13 +96,10 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
101
96
  loading: boolean;
102
97
  mutating: boolean;
103
98
  error: Error | null;
104
- inputFailure: BrowserInputFailure | null;
105
99
  }>(() => emptyState(browserSessionId, enabled));
106
100
  const visible =
107
101
  state.browserSessionId === browserSessionId ? state : emptyState(browserSessionId, enabled);
108
102
  const refreshBlocked = isNonRetryableInteractionError(visible.error);
109
- const inputFailureRef = useRef(visible.inputFailure);
110
- inputFailureRef.current = visible.inputFailure;
111
103
  const selectedTargetIdRef = useRef<string | null>(visible.selectedTargetId);
112
104
  selectedTargetIdRef.current = visible.selectedTargetId;
113
105
  const selectedTargetRef = useRef<BrowserTarget | null>(
@@ -147,104 +139,88 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
147
139
  requestRef.current = { id, controller: null };
148
140
  }, []);
149
141
 
150
- const refreshInventory = useCallback(
151
- async (checkInput = false) => {
152
- if (!enabled || !browserSessionId) return;
153
- const checkedInputFailure = inputFailureRef.current;
154
- const id = requestRef.current.id + 1;
155
- requestRef.current.controller?.abort();
156
- const controller = new AbortController();
157
- requestRef.current = { id, controller };
142
+ const refresh = useCallback(async (): Promise<void> => {
143
+ if (!enabled || !browserSessionId) return;
144
+ const id = requestRef.current.id + 1;
145
+ requestRef.current.controller?.abort();
146
+ const controller = new AbortController();
147
+ requestRef.current = { id, controller };
148
+ try {
149
+ const [session, targetResponse] = await Promise.all([
150
+ client.getBrowserSession(workspaceId, browserSessionId, {
151
+ signal: controller.signal,
152
+ }),
153
+ client.listBrowserTargets(workspaceId, browserSessionId, {
154
+ signal: controller.signal,
155
+ }),
156
+ ]);
157
+ if (!mountedRef.current || requestRef.current.id !== id) return;
158
+ const selected = chooseTarget(targetResponse.targets, selectedTargetIdRef.current);
159
+ selectedTargetIdRef.current = selected?.id ?? null;
160
+ const previousObservation =
161
+ observationRef.current.browserSessionId === browserSessionId
162
+ ? observationRef.current.observation
163
+ : null;
164
+ const retainedObservation =
165
+ selected && previousObservation && sameObservationTarget(previousObservation, selected)
166
+ ? previousObservation
167
+ : null;
168
+ observationRef.current = { browserSessionId, observation: retainedObservation };
169
+ setState((current) =>
170
+ current.browserSessionId === browserSessionId
171
+ ? {
172
+ ...current,
173
+ session,
174
+ targets: targetResponse.targets,
175
+ selectedTargetId: selected?.id ?? null,
176
+ observation: retainedObservation,
177
+ loading: false,
178
+ error: null,
179
+ }
180
+ : current,
181
+ );
182
+ if (!selected || !semanticObservationEnabledRef.current) return;
158
183
  try {
159
- const [session, targetResponse] = await Promise.all([
160
- client.getBrowserSession(workspaceId, browserSessionId, {
161
- signal: controller.signal,
162
- }),
163
- client.listBrowserTargets(workspaceId, browserSessionId, {
164
- signal: controller.signal,
165
- }),
166
- ]);
184
+ const observation = await client.observeBrowserTarget(
185
+ workspaceId,
186
+ browserSessionId,
187
+ selected.id,
188
+ { signal: controller.signal },
189
+ );
167
190
  if (!mountedRef.current || requestRef.current.id !== id) return;
168
- const selected = chooseTarget(targetResponse.targets, selectedTargetIdRef.current);
169
- selectedTargetIdRef.current = selected?.id ?? null;
170
- const previousObservation =
171
- observationRef.current.browserSessionId === browserSessionId
172
- ? observationRef.current.observation
173
- : null;
174
- const retainedObservation =
175
- selected && previousObservation && sameObservationTarget(previousObservation, selected)
176
- ? previousObservation
177
- : null;
178
- observationRef.current = { browserSessionId, observation: retainedObservation };
191
+ observationRef.current = { browserSessionId, observation };
192
+ lastObservationAtRef.current = Date.now();
179
193
  setState((current) =>
180
- current.browserSessionId === browserSessionId
181
- ? {
182
- ...current,
183
- session,
184
- targets: targetResponse.targets,
185
- selectedTargetId: selected?.id ?? null,
186
- observation: retainedObservation,
187
- loading: false,
188
- error: null,
189
- // Media and background polling cannot confirm an input outcome.
190
- // Only an explicit fresh check clears the notice it began with.
191
- inputFailure:
192
- checkInput &&
193
- session.id === browserSessionId &&
194
- targetResponse.browserSessionId === browserSessionId &&
195
- current.inputFailure === checkedInputFailure
196
- ? null
197
- : current.inputFailure,
198
- }
194
+ current.browserSessionId === browserSessionId &&
195
+ current.selectedTargetId === observation.target.id
196
+ ? { ...current, observation }
199
197
  : current,
200
198
  );
201
- if (!selected || !semanticObservationEnabledRef.current) return;
202
- try {
203
- const observation = await client.observeBrowserTarget(
204
- workspaceId,
205
- browserSessionId,
206
- selected.id,
207
- { signal: controller.signal },
208
- );
209
- if (!mountedRef.current || requestRef.current.id !== id) return;
210
- observationRef.current = { browserSessionId, observation };
211
- lastObservationAtRef.current = Date.now();
212
- setState((current) =>
213
- current.browserSessionId === browserSessionId &&
214
- current.selectedTargetId === observation.target.id
215
- ? { ...current, observation }
216
- : current,
217
- );
218
- } catch (cause) {
219
- if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id)
220
- return;
221
- // Target inventory and the media plane remain authoritative for the
222
- // human-facing browser. A failed semantic snapshot must not blank or
223
- // disable an otherwise live visual browser.
224
- void cause;
225
- }
226
199
  } catch (cause) {
227
200
  if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id)
228
201
  return;
229
- setState((current) =>
230
- current.browserSessionId === browserSessionId
231
- ? {
232
- ...current,
233
- loading: false,
234
- error: cause instanceof Error ? cause : new Error(String(cause)),
235
- }
236
- : current,
237
- );
238
- } finally {
239
- if (requestRef.current.id === id) {
240
- requestRef.current = { id, controller: null };
241
- }
202
+ // Target inventory and the media plane remain authoritative for the
203
+ // human-facing browser. A failed semantic snapshot must not blank or
204
+ // disable an otherwise live visual browser.
205
+ void cause;
242
206
  }
243
- },
244
- [browserSessionId, client, enabled, workspaceId],
245
- );
246
-
247
- const refresh = useCallback(async () => await refreshInventory(true), [refreshInventory]);
207
+ } catch (cause) {
208
+ if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id) return;
209
+ setState((current) =>
210
+ current.browserSessionId === browserSessionId
211
+ ? {
212
+ ...current,
213
+ loading: false,
214
+ error: cause instanceof Error ? cause : new Error(String(cause)),
215
+ }
216
+ : current,
217
+ );
218
+ } finally {
219
+ if (requestRef.current.id === id) {
220
+ requestRef.current = { id, controller: null };
221
+ }
222
+ }
223
+ }, [browserSessionId, client, enabled, workspaceId]);
248
224
 
249
225
  const refreshSemantic = useCallback(async (): Promise<void> => {
250
226
  if (!enabled || !browserSessionId) return;
@@ -289,12 +265,12 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
289
265
  ? { ...current, loading: true }
290
266
  : emptyState(browserSessionId, true),
291
267
  );
292
- void refreshInventory();
268
+ void refresh();
293
269
  return () => {
294
270
  mountedRef.current = false;
295
271
  invalidateRefresh();
296
272
  };
297
- }, [browserSessionId, enabled, invalidateRefresh, refreshInventory]);
273
+ }, [browserSessionId, enabled, invalidateRefresh, refresh]);
298
274
 
299
275
  useEffect(() => {
300
276
  const previous = previousSemanticObservationRef.current;
@@ -330,17 +306,17 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
330
306
  useEffect(() => {
331
307
  if (!enabled || !pageLive || visible.mutating || refreshBlocked) return;
332
308
  const timer = setInterval(() => {
333
- if (!requestRef.current.controller) void refreshInventory();
309
+ if (!requestRef.current.controller) void refresh();
334
310
  }, pollIntervalMs);
335
311
  return () => clearInterval(timer);
336
- }, [enabled, pageLive, pollIntervalMs, refreshInventory, refreshBlocked, visible.mutating]);
312
+ }, [enabled, pageLive, pollIntervalMs, refresh, refreshBlocked, visible.mutating]);
337
313
 
338
314
  useEffect(() => {
339
315
  if (!enabled || !browserSessionId || !pageLive || refreshBlocked) return;
340
316
  let disposed = false;
341
317
  const heartbeat = () => {
342
318
  void client.heartbeatBrowserSession(workspaceId, browserSessionId).catch(() => {
343
- if (!disposed) void refreshInventory();
319
+ if (!disposed) void refresh();
344
320
  });
345
321
  };
346
322
  const timer = setInterval(heartbeat, 30_000);
@@ -348,7 +324,7 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
348
324
  disposed = true;
349
325
  clearInterval(timer);
350
326
  };
351
- }, [browserSessionId, client, enabled, pageLive, refreshInventory, refreshBlocked, workspaceId]);
327
+ }, [browserSessionId, client, enabled, pageLive, refresh, refreshBlocked, workspaceId]);
352
328
 
353
329
  const runMutation = useCallback(
354
330
  async <T>(scopeBrowserSessionId: string, operation: () => Promise<T>): Promise<T> => {
@@ -556,16 +532,6 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
556
532
  observationMode,
557
533
  action,
558
534
  });
559
- if (receipt.state !== "completed") {
560
- const inputFailure: BrowserInputFailure = {
561
- operationId: receipt.operationId,
562
- state: receipt.state,
563
- error: receipt.error,
564
- };
565
- setState((current) =>
566
- current.browserSessionId === browserSessionId ? { ...current, inputFailure } : current,
567
- );
568
- }
569
535
  if (receipt.observation) {
570
536
  observationRef.current = {
571
537
  browserSessionId,
@@ -677,7 +643,6 @@ export function useBrowserSession(options: UseBrowserSessionOptions): UseBrowser
677
643
  loading: visible.loading,
678
644
  mutating: visible.mutating,
679
645
  error: visible.error,
680
- inputFailure: visible.inputFailure,
681
646
  refresh,
682
647
  observeForInput,
683
648
  actFromObservation,
@@ -701,7 +666,6 @@ function emptyState(browserSessionId: string | null, loading: boolean) {
701
666
  loading,
702
667
  mutating: false,
703
668
  error: null as Error | null,
704
- inputFailure: null as BrowserInputFailure | null,
705
669
  };
706
670
  }
707
671