@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
@@ -5,7 +5,7 @@ import {
5
5
  type EffectiveControlResumeOption,
6
6
  type EffectiveSessionControl,
7
7
  type LatencyMode,
8
- OpenGeniApiError,
8
+ type OpenGeniApiError,
9
9
  type ReasoningEffort,
10
10
  type ResourceRef,
11
11
  type SaveComposerDraftRequest,
@@ -15,15 +15,7 @@ import {
15
15
  } from "@opengeni/sdk";
16
16
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
17
17
  import { useEmbeddedSession, type EmbeddedSessionClientOverride } from "../session-context";
18
- import {
19
- COMPOSER_MODEL_UNAVAILABLE_MESSAGE,
20
- ComposerReconciliationRequiredError,
21
- ComposerStateError,
22
- ComposerWorkspaceControlUnavailableError,
23
- composerSubmissionCanRetry,
24
- composerSubmissionErrorMessage,
25
- } from "../lib/format";
26
- import { normalizeError, useErrorMessage } from "../lib/error-message";
18
+ import { composerSubmissionCanRetry, composerSubmissionErrorMessage } from "../lib/format";
27
19
  import { useSessionEventTrigger, type SessionEventFeedOptions } from "./internal";
28
20
 
29
21
  export type ComposerPolicy = {
@@ -106,8 +98,6 @@ export type ComposerOptimisticMessage = {
106
98
  triggerEventId?: string | null | undefined;
107
99
  appliedQueueVersion?: number | null | undefined;
108
100
  error?: string | undefined;
109
- /** Bounded support reference retained independently of display copy across remounts. */
110
- correlationId?: string | undefined;
111
101
  /** False for a definitive refusal that requires changing payment or allowance settings. */
112
102
  retryable?: boolean | undefined;
113
103
  outcomeUnknown?: boolean | undefined;
@@ -195,19 +185,12 @@ function restoreOptimisticSendOperations(key: string | null): OptimisticSendOper
195
185
  operation.state === "sending" || operation.state === "queued"
196
186
  ? true
197
187
  : operation.outcomeUnknown,
198
- correlationId: restoredCorrelationId(operation.correlationId),
199
- error: restoredErrorReference(
200
- operation.correlationId,
201
- hasMcpCredentialUpdates && (operation.state === "sending" || operation.outcomeUnknown)
202
- ? composerSubmissionErrorMessage(new ComposerReconciliationRequiredError())
203
- : operation.state === "sending"
204
- ? "Delivery was interrupted; retry to reconcile this message."
205
- : operation.outcomeUnknown
206
- ? "The request could not be confirmed. Check its status before retrying."
207
- : operation.error
208
- ? composerSubmissionErrorMessage(new Error(operation.error))
209
- : undefined,
210
- ),
188
+ error:
189
+ operation.state === "sending"
190
+ ? "Delivery was interrupted; retry to reconcile this message."
191
+ : operation.error
192
+ ? composerSubmissionErrorMessage(new Error(operation.error))
193
+ : undefined,
211
194
  retryable:
212
195
  operation.state === "sending" || operation.outcomeUnknown
213
196
  ? true
@@ -218,20 +201,6 @@ function restoreOptimisticSendOperations(key: string | null): OptimisticSendOper
218
201
  }));
219
202
  }
220
203
 
221
- function restoredCorrelationId(value: unknown): string | undefined {
222
- return typeof value === "string" && /^[\w.:-]{1,128}$/u.test(value) ? value : undefined;
223
- }
224
-
225
- function restoredErrorReference(
226
- reference: unknown,
227
- message: string | undefined,
228
- ): string | undefined {
229
- const correlationId = restoredCorrelationId(reference);
230
- return message && correlationId && message !== COMPOSER_MODEL_UNAVAILABLE_MESSAGE
231
- ? `${message} Reference: ${correlationId}.`
232
- : message;
233
- }
234
-
235
204
  function rememberOptimisticSendOperations(
236
205
  key: string | null,
237
206
  operations: OptimisticSendOperation[],
@@ -682,7 +651,6 @@ export function useComposer(
682
651
  options: UseComposerOptions = {},
683
652
  ): ComposerControllerState {
684
653
  const { client, workspaceId, registerSessionReconciler } = useEmbeddedSession(options);
685
- const formatError = useErrorMessage();
686
654
  const durableDrafts = options.draftPersistence !== "disabled";
687
655
  if (!durableDrafts && !options.initialPolicy) {
688
656
  throw new Error("useComposer requires initialPolicy when draft persistence is disabled");
@@ -1103,9 +1071,7 @@ export function useComposer(
1103
1071
  const problem = asError(cause);
1104
1072
  const timedOut = problem.name === "TimeoutError";
1105
1073
  setDraftReadError(
1106
- timedOut
1107
- ? new ComposerStateError("Draft sync timed out. Retrying…", { cause })
1108
- : problem,
1074
+ timedOut ? new Error("Draft sync timed out. Retrying…", { cause }) : problem,
1109
1075
  );
1110
1076
  if (
1111
1077
  timedOut ||
@@ -1412,34 +1378,22 @@ export function useComposer(
1412
1378
  optimisticProcessorBusyRef.current = true;
1413
1379
  void (async () => {
1414
1380
  let mutationFailureObserved = false;
1415
- const markFailed = (cause: unknown, outcomeUnknown: boolean): void => {
1381
+ const markFailed = (problem: Error, outcomeUnknown: boolean): void => {
1416
1382
  if (
1417
1383
  targetKeyRef.current !== ownedTargetKey ||
1418
1384
  targetGeneration.current !== ownedGeneration
1419
1385
  ) {
1420
1386
  return;
1421
1387
  }
1422
- const problem = asError(cause);
1423
1388
  replaceOptimisticSends((current) =>
1424
1389
  current.map((candidate) =>
1425
1390
  candidate.clientEventId === operation.clientEventId
1426
1391
  ? {
1427
1392
  ...candidate,
1428
1393
  state: "failed",
1429
- error: formatError(
1430
- cause,
1431
- outcomeUnknown &&
1432
- !isOutcomeUnknownError(problem) &&
1433
- !(problem instanceof ComposerReconciliationRequiredError)
1434
- ? `The request could not be confirmed. Check its status before retrying.${problem instanceof OpenGeniApiError && problem.correlationId ? ` Reference: ${problem.correlationId}.` : ""}`
1435
- : composerSubmissionErrorMessage(problem),
1436
- ),
1394
+ error: outcomeUnknown ? problem.message : composerSubmissionErrorMessage(problem),
1437
1395
  retryable: outcomeUnknown || composerSubmissionCanRetry(problem),
1438
1396
  outcomeUnknown,
1439
- correlationId:
1440
- problem instanceof OpenGeniApiError
1441
- ? problem.correlationId
1442
- : candidate.correlationId,
1443
1397
  }
1444
1398
  : candidate,
1445
1399
  ),
@@ -1466,7 +1420,7 @@ export function useComposer(
1466
1420
  // This read cannot settle the prior mutation in either direction.
1467
1421
  // Preserve its exact key and uncertain status until reconciliation
1468
1422
  // succeeds or that same mutation is actually replayed.
1469
- markFailed(cause, true);
1423
+ markFailed(asError(cause), true);
1470
1424
  return;
1471
1425
  }
1472
1426
  const reconciled = reconcileOptimisticSendFromEvents(operation, events);
@@ -1490,13 +1444,15 @@ export function useComposer(
1490
1444
  return;
1491
1445
  }
1492
1446
  if (!operation.canRetry) {
1493
- throw new ComposerReconciliationRequiredError();
1447
+ throw new Error(
1448
+ "Opengeni cannot safely retry this uncertain request after remount; reconcile the session before sending again.",
1449
+ );
1494
1450
  }
1495
1451
  }
1496
1452
  let expectedDraftRevision: number | undefined;
1497
1453
  if (durableDrafts && operation.draftPayload) {
1498
1454
  if (!(await persistPayload(operation.draftPayload))) {
1499
- throw new ComposerStateError("The message draft could not be saved before delivery.");
1455
+ throw new Error("The message draft could not be saved before delivery.");
1500
1456
  }
1501
1457
  expectedDraftRevision = draftRef.current?.revision;
1502
1458
  }
@@ -1514,7 +1470,7 @@ export function useComposer(
1514
1470
  let acceptedEvent: SessionEvent | null = null;
1515
1471
  if (durableDrafts) {
1516
1472
  if (!operation.draftPayload || expectedDraftRevision === undefined) {
1517
- throw new ComposerStateError("The durable composer draft is not ready for delivery.");
1473
+ throw new Error("The durable composer draft is not ready for delivery.");
1518
1474
  }
1519
1475
  const result = await client
1520
1476
  .submitComposerDraft(workspaceId, sessionId, {
@@ -1612,7 +1568,7 @@ export function useComposer(
1612
1568
  operation.outcomeUnknown && !mutationFailureObserved
1613
1569
  ? true
1614
1570
  : isOutcomeUnknownError(cause);
1615
- markFailed(cause, outcomeUnknown);
1571
+ markFailed(problem, outcomeUnknown);
1616
1572
  } finally {
1617
1573
  optimisticProcessorBusyRef.current = false;
1618
1574
  if (targetKeyRef.current === ownedTargetKey) {
@@ -1624,7 +1580,6 @@ export function useComposer(
1624
1580
  adoptDraftBase,
1625
1581
  client,
1626
1582
  durableDrafts,
1627
- formatError,
1628
1583
  markOptimisticAccepted,
1629
1584
  loadDraft,
1630
1585
  onSent,
@@ -1793,7 +1748,7 @@ export function useComposer(
1793
1748
  input.reasoningEffort === undefined ||
1794
1749
  input.latencyMode === undefined
1795
1750
  ) {
1796
- throw new ComposerStateError("The durable composer draft is not ready for delivery.");
1751
+ throw new Error("The durable composer draft is not ready for delivery.");
1797
1752
  }
1798
1753
  const result = await client.submitComposerDraft(workspaceId, sessionId, {
1799
1754
  text: input.text,
@@ -1898,7 +1853,11 @@ export function useComposer(
1898
1853
  return true;
1899
1854
  }
1900
1855
  if (!pending.canRetry) {
1901
- setError(new ComposerReconciliationRequiredError());
1856
+ setError(
1857
+ new Error(
1858
+ "Opengeni cannot safely retry this uncertain request after remount; reconcile the session before sending again.",
1859
+ ),
1860
+ );
1902
1861
  return false;
1903
1862
  }
1904
1863
  try {
@@ -2293,7 +2252,7 @@ export function useComposer(
2293
2252
  targetKeyRef.current === ownedTargetKey &&
2294
2253
  targetGeneration.current === ownedGeneration
2295
2254
  ) {
2296
- setError(normalizeError(cause));
2255
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
2297
2256
  }
2298
2257
  } finally {
2299
2258
  if (
@@ -2337,7 +2296,7 @@ export function useComposer(
2337
2296
  targetKeyRef.current === ownedTargetKey &&
2338
2297
  targetGeneration.current === ownedGeneration
2339
2298
  ) {
2340
- setError(normalizeError(cause));
2299
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
2341
2300
  }
2342
2301
  } finally {
2343
2302
  if (
@@ -2364,7 +2323,9 @@ export function useComposer(
2364
2323
  (blocker) => blocker.kind === "workspace",
2365
2324
  );
2366
2325
  if (!client.setWorkspaceInferenceState) {
2367
- throw new ComposerWorkspaceControlUnavailableError();
2326
+ throw new Error(
2327
+ "@opengeni/react: workspace-scoped resume requires setWorkspaceInferenceState.",
2328
+ );
2368
2329
  }
2369
2330
  const clientEventId = generateClientEventId();
2370
2331
  await replayOutcomeUnknown(() =>
@@ -2494,7 +2455,7 @@ export function useComposer(
2494
2455
  const addAnnotation = useCallback(
2495
2456
  (annotation: DraftTimelineAnnotation) => {
2496
2457
  if (annotationsRef.current.length >= 12) {
2497
- setError(new ComposerStateError("A message can include at most 12 timeline annotations."));
2458
+ setError(new Error("A message can include at most 12 timeline annotations."));
2498
2459
  return;
2499
2460
  }
2500
2461
  const next = [...annotationsRef.current, annotation];
@@ -2891,7 +2852,7 @@ async function replayOutcomeUnknown<T>(command: () => Promise<T>): Promise<T> {
2891
2852
  }
2892
2853
 
2893
2854
  function asError(cause: unknown): Error {
2894
- return normalizeError(cause);
2855
+ return cause instanceof Error ? cause : new Error(String(cause));
2895
2856
  }
2896
2857
 
2897
2858
  function promptRoutingFromAcceptedEvent(
@@ -8,10 +8,7 @@ import type {
8
8
  ComputerTarget,
9
9
  } from "@opengeni/sdk/interaction";
10
10
  import { useCallback, useEffect, useRef, useState } from "react";
11
- import {
12
- isInteractionControlUnavailable,
13
- isNonRetryableInteractionError,
14
- } from "../lib/interaction-errors";
11
+ import { isNonRetryableInteractionError } from "../lib/interaction-errors";
15
12
  import {
16
13
  type EmbeddedComputerInteractionClientOverride,
17
14
  useEmbeddedComputerInteraction,
@@ -32,8 +29,6 @@ export type UseComputerSessionResult = {
32
29
  loading: boolean;
33
30
  mutating: boolean;
34
31
  error: Error | null;
35
- /** Control service loss, independent of target accessibility inspection and media. */
36
- controlError: Error | null;
37
32
  refresh: () => Promise<void>;
38
33
  readClipboard: () => Promise<ComputerClipboard>;
39
34
  /** Changes only this viewer's target cursor; it never takes ownership or
@@ -110,7 +105,6 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
110
105
  requestRef.current.controller?.abort();
111
106
  const controller = new AbortController();
112
107
  requestRef.current = { id, controller };
113
- let discoveryCompleted = false;
114
108
  try {
115
109
  const [session, targetResponse] = await Promise.all([
116
110
  client.getComputerSession(workspaceId, computerSessionId, {
@@ -120,7 +114,6 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
120
114
  signal: controller.signal,
121
115
  }),
122
116
  ]);
123
- discoveryCompleted = true;
124
117
  if (!mountedRef.current || requestRef.current.id !== id) return;
125
118
  const targets = sortComputerTargets(targetResponse.targets);
126
119
  const selected = chooseTarget(targets, selectedTargetIdRef.current, session.platform);
@@ -148,7 +141,6 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
148
141
  observation: retainedObservation,
149
142
  loading: false,
150
143
  error: null,
151
- controlError: null,
152
144
  }
153
145
  : current,
154
146
  );
@@ -176,19 +168,12 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
176
168
  );
177
169
  } catch (cause) {
178
170
  if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id) return;
179
- const error = cause instanceof Error ? cause : new Error(String(cause));
180
171
  setState((current) =>
181
172
  current.computerSessionId === computerSessionId
182
173
  ? {
183
174
  ...current,
184
175
  loading: false,
185
- error,
186
- controlError: isInteractionControlUnavailable(
187
- error,
188
- discoveryCompleted ? "observation" : "control",
189
- )
190
- ? error
191
- : current.controlError,
176
+ error: cause instanceof Error ? cause : new Error(String(cause)),
192
177
  }
193
178
  : current,
194
179
  );
@@ -254,23 +239,11 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
254
239
  : current,
255
240
  );
256
241
  try {
257
- const result = await operation();
258
- setState((current) =>
259
- current.computerSessionId === scopeComputerSessionId
260
- ? { ...current, controlError: null }
261
- : current,
262
- );
263
- return result;
242
+ return await operation();
264
243
  } catch (cause) {
265
244
  const error = cause instanceof Error ? cause : new Error(String(cause));
266
245
  setState((current) =>
267
- current.computerSessionId === scopeComputerSessionId
268
- ? {
269
- ...current,
270
- error,
271
- controlError: isInteractionControlUnavailable(error) ? error : current.controlError,
272
- }
273
- : current,
246
+ current.computerSessionId === scopeComputerSessionId ? { ...current, error } : current,
274
247
  );
275
248
  throw error;
276
249
  } finally {
@@ -325,14 +298,7 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
325
298
  const error = cause instanceof Error ? cause : new Error(String(cause));
326
299
  setState((current) =>
327
300
  current.computerSessionId === computerSessionId && current.selectedTargetId === target.id
328
- ? {
329
- ...current,
330
- loading: false,
331
- error,
332
- controlError: isInteractionControlUnavailable(error, "observation")
333
- ? error
334
- : current.controlError,
335
- }
301
+ ? { ...current, loading: false, error }
336
302
  : current,
337
303
  );
338
304
  throw error;
@@ -439,21 +405,7 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
439
405
 
440
406
  const readClipboard = useCallback(async (): Promise<ComputerClipboard> => {
441
407
  if (!computerSessionId) throw new Error("No desktop is selected.");
442
- try {
443
- return await client.readComputerClipboard(workspaceId, computerSessionId);
444
- } catch (cause) {
445
- const error = cause instanceof Error ? cause : new Error(String(cause));
446
- setState((current) =>
447
- current.computerSessionId === computerSessionId
448
- ? {
449
- ...current,
450
- error,
451
- controlError: isInteractionControlUnavailable(error) ? error : current.controlError,
452
- }
453
- : current,
454
- );
455
- throw error;
456
- }
408
+ return await client.readComputerClipboard(workspaceId, computerSessionId);
457
409
  }, [client, computerSessionId, workspaceId]);
458
410
 
459
411
  return {
@@ -465,7 +417,6 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
465
417
  loading: visible.loading,
466
418
  mutating: visible.mutating,
467
419
  error: visible.error,
468
- controlError: visible.controlError,
469
420
  refresh,
470
421
  readClipboard,
471
422
  selectTarget,
@@ -483,7 +434,6 @@ type ComputerControlState = {
483
434
  loading: boolean;
484
435
  mutating: boolean;
485
436
  error: Error | null;
486
- controlError: Error | null;
487
437
  };
488
438
 
489
439
  function emptyState(computerSessionId: string | null, loading: boolean): ComputerControlState {
@@ -496,7 +446,6 @@ function emptyState(computerSessionId: string | null, loading: boolean): Compute
496
446
  loading,
497
447
  mutating: false,
498
448
  error: null,
499
- controlError: null,
500
449
  };
501
450
  }
502
451
 
@@ -4,7 +4,6 @@ import {
4
4
  useEmbeddedFileAttachments,
5
5
  type EmbeddedFileAttachmentClientOverride,
6
6
  } from "../session-context";
7
- import { useErrorMessage } from "../lib/error-message";
8
7
 
9
8
  export type UseFileAttachmentsOptions = EmbeddedFileAttachmentClientOverride & {
10
9
  /**
@@ -32,8 +31,6 @@ export type FileAttachment = {
32
31
  /** Stable SDK failure code for UI behavior that must not parse error copy. */
33
32
  errorCode?: "secure_context_required" | undefined;
34
33
  error?: string | undefined;
35
- /** Original diagnostic failure; presentation copy is kept separately in `error`. */
36
- errorCause?: unknown;
37
34
  };
38
35
 
39
36
  export type UseFileAttachmentsResult = {
@@ -123,7 +120,6 @@ export function useFileAttachments(
123
120
  options: UseFileAttachmentsOptions = {},
124
121
  ): UseFileAttachmentsResult {
125
122
  const { client, workspaceId } = useEmbeddedFileAttachments(options);
126
- const formatError = useErrorMessage();
127
123
  const pasteFilter = options.pasteFilter ?? isImage;
128
124
  const [attachments, setAttachments] = useState<FileAttachment[]>([]);
129
125
  const attachmentsRef = useRef(attachments);
@@ -238,7 +234,6 @@ export function useFileAttachments(
238
234
  sizeBytes: asset.sizeBytes,
239
235
  errorCode: undefined,
240
236
  error: undefined,
241
- errorCause: undefined,
242
237
  }
243
238
  : attachment,
244
239
  ),
@@ -253,15 +248,14 @@ export function useFileAttachments(
253
248
  ...attachment,
254
249
  status: "failed",
255
250
  errorCode: secureContextRequiredErrorCode(error),
256
- error: formatError(error),
257
- errorCause: error,
251
+ error: error instanceof Error ? error.message : String(error),
258
252
  }
259
253
  : attachment,
260
254
  ),
261
255
  );
262
256
  });
263
257
  },
264
- [client, workspaceId, options.scope, formatError],
258
+ [client, workspaceId, options.scope],
265
259
  );
266
260
 
267
261
  const addFiles = useCallback(
@@ -297,13 +291,7 @@ export function useFileAttachments(
297
291
  setAttachments((current) =>
298
292
  current.map((attachment) =>
299
293
  attachment.id === id
300
- ? {
301
- ...attachment,
302
- status: "uploading",
303
- errorCode: undefined,
304
- error: undefined,
305
- errorCause: undefined,
306
- }
294
+ ? { ...attachment, status: "uploading", errorCode: undefined, error: undefined }
307
295
  : attachment,
308
296
  ),
309
297
  );
@@ -355,7 +343,6 @@ export function useFileAttachments(
355
343
  file,
356
344
  errorCode: undefined,
357
345
  error: undefined,
358
- errorCause: undefined,
359
346
  }
360
347
  : {
361
348
  id: `restored:${file.id}`,
@@ -1,7 +1,6 @@
1
1
  import { OpenGeniApiError, type SessionEvent, type SessionGoal } from "@opengeni/sdk";
2
2
  import { useCallback, useEffect, useRef, useState } from "react";
3
3
  import { useEmbeddedGoal, type EmbeddedGoalClientOverride } from "../session-context";
4
- import { normalizeError } from "../lib/error-message";
5
4
  import {
6
5
  useDebouncedCallback,
7
6
  useMutationRunner,
@@ -118,7 +117,7 @@ export function useGoal(
118
117
  setGoal(null);
119
118
  setError(null);
120
119
  } else {
121
- setError(normalizeError(cause));
120
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
122
121
  }
123
122
  setLoading(false);
124
123
  } finally {
@@ -9,7 +9,6 @@ import { useCallback, useEffect, useRef, useState } from "react";
9
9
  import { useOpenGeni, type ClientOverride } from "../provider";
10
10
  import { sandboxAcceptsLiveIo } from "../lib/sandbox-liveness";
11
11
  import { terminalCanAcquirePty } from "../lib/terminal-capability";
12
- import { normalizeError } from "../lib/error-message";
13
12
  import { usePageLiveActivity } from "./internal";
14
13
 
15
14
  // "on-demand" is the boxless-benign resting state: the lease is not currently
@@ -290,7 +289,7 @@ export function useSessionCapabilities(
290
289
  return;
291
290
  }
292
291
  setState("error");
293
- setError(normalizeError(cause));
292
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
294
293
  }
295
294
  });
296
295
  }, warmingPollMs);
@@ -470,7 +469,7 @@ export function useSessionCapabilities(
470
469
  return;
471
470
  }
472
471
  setState("error");
473
- setError(normalizeError(cause));
472
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
474
473
  }
475
474
  })();
476
475
 
@@ -10,7 +10,6 @@ import { createOlderHistoryLoadReceipt, type OlderHistoryLoadReceipt } from "../
10
10
  import { buildTimeline, groupTimeline, sessionStatusFromEvents } from "../timeline/projection";
11
11
  import type { TimelineItem } from "../timeline/types";
12
12
  import type { EmbeddedSessionClientLike } from "../client";
13
- import { normalizeError } from "../lib/error-message";
14
13
  import { usePageLiveActivity } from "./internal";
15
14
  import type { LatestQuestionOptions } from "./latest-question";
16
15
 
@@ -115,11 +114,8 @@ const FOREGROUND_COMPACT_CATCHUP_MAX_GROUPS = 16;
115
114
  const FOREGROUND_COMPACT_CATCHUP_MAX_BYTES = 512 * 1024;
116
115
  const EMPTY_EVENTS: SessionEvent[] = [];
117
116
  const encoder = new TextEncoder();
118
- // Durable history remains on the server and is available through bounded
119
- // navigation. Keep the live browser working set small across multiple tabs;
120
- // serialized payloads also expand into objects and timeline projections.
121
- export const SESSION_EVENT_BROWSER_MAX_BYTES = 16 * 1024 * 1024;
122
- export const SESSION_EVENT_BROWSER_MAX_COUNT = 20_000;
117
+ export const SESSION_EVENT_BROWSER_MAX_BYTES = 160 * 1024 * 1024;
118
+ export const SESSION_EVENT_BROWSER_MAX_COUNT = 200_000;
123
119
  export const SESSION_EVENT_BROWSER_PENDING_MAX_BYTES = 1024 * 1024;
124
120
  export const SESSION_EVENT_BROWSER_PENDING_MAX_COUNT = 256;
125
121
 
@@ -499,7 +495,7 @@ export function useSessionEvents(
499
495
  .then(() => reconcileSession(sessionId))
500
496
  .catch((cause) => {
501
497
  if (isCurrent()) {
502
- setError(normalizeError(cause));
498
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
503
499
  }
504
500
  });
505
501
  },
@@ -540,7 +536,7 @@ export function useSessionEvents(
540
536
  } catch (cause) {
541
537
  if (isCurrent()) {
542
538
  flush();
543
- setError(normalizeError(cause));
539
+ setError(cause instanceof Error ? cause : new Error(String(cause)));
544
540
  setConnectionState("error");
545
541
  // A failed first compact-tail request has no later success path in
546
542
  // this effect instance. End the loading gate so hosts can render the
@@ -882,7 +878,7 @@ export function useSessionEvents(
882
878
  if (!isCurrent()) {
883
879
  return false;
884
880
  }
885
- setNewerError(normalizeError(reason));
881
+ setNewerError(reason instanceof Error ? reason : new Error(String(reason)));
886
882
  // Keep authorization and integrity failures actionable for callers;
887
883
  // timeline-owned invocations attach their own explicit recovery UI.
888
884
  throw reason;
@@ -1082,13 +1078,10 @@ export function useSessionEvents(
1082
1078
  visibleEvents.some((event) => event.sequence === questionEvidence.anchor)
1083
1079
  ? questionEvidence.events
1084
1080
  : EMPTY_EVENTS;
1085
- const timelineOptions = { partialStart: hasOlder || eventWindow.truncated || after > 0 };
1086
- if (witness.length === 0) return buildTimeline(visibleEvents, timelineOptions);
1087
1081
  const ids = new Set(visibleEvents.map((event) => event.id));
1088
- return buildTimeline(
1089
- [...visibleEvents, ...witness.filter((event) => !ids.has(event.id))],
1090
- timelineOptions,
1091
- );
1082
+ return buildTimeline([...visibleEvents, ...witness.filter((event) => !ids.has(event.id))], {
1083
+ partialStart: hasOlder || eventWindow.truncated || after > 0,
1084
+ });
1092
1085
  }, [visibleEvents, hasOlder, eventWindow.truncated, after, questionEvidence, client, streamKey]);
1093
1086
 
1094
1087
  return {
@@ -1,6 +1,5 @@
1
1
  import type { KeyboardEvent } from "react";
2
2
  import { useCallback, useMemo, useRef, useState } from "react";
3
- import { useErrorMessage } from "../lib/error-message";
4
3
  import {
5
4
  argHint,
6
5
  filterCommands,
@@ -82,7 +81,6 @@ export type UseSlashCommandsResult = {
82
81
  };
83
82
 
84
83
  export function useSlashCommands(options: UseSlashCommandsOptions): UseSlashCommandsResult {
85
- const formatError = useErrorMessage();
86
84
  const { commands, context, handlers, value, setValue } = options;
87
85
  const [highlight, setHighlight] = useState(0);
88
86
  // Escape closes the palette but keeps the draft. We remember the dismissed
@@ -155,9 +153,9 @@ export function useSlashCommands(options: UseSlashCommandsOptions): UseSlashComm
155
153
  if (!context) {
156
154
  return null;
157
155
  }
158
- return { ...context, ...handlers, formatError, confirm: () => handlers.confirm(command) };
156
+ return { ...context, ...handlers, confirm: () => handlers.confirm(command) };
159
157
  },
160
- [context, handlers, formatError],
158
+ [context, handlers],
161
159
  );
162
160
 
163
161
  const execute = useCallback(
@@ -175,10 +173,10 @@ export function useSlashCommands(options: UseSlashCommandsOptions): UseSlashComm
175
173
  setValue("");
176
174
  }
177
175
  } catch (cause) {
178
- ctx.notice({ tone: "error", message: formatError(cause) });
176
+ ctx.notice({ tone: "error", message: errorMessage(cause) });
179
177
  }
180
178
  },
181
- [buildContext, setValue, formatError],
179
+ [buildContext, setValue],
182
180
  );
183
181
 
184
182
  const autocomplete = useCallback(
@@ -361,3 +359,10 @@ export function useSlashCommands(options: UseSlashCommandsOptions): UseSlashComm
361
359
  autocompleteHighlighted,
362
360
  };
363
361
  }
362
+
363
+ function errorMessage(cause: unknown): string {
364
+ if (cause instanceof Error) {
365
+ return cause.message;
366
+ }
367
+ return String(cause);
368
+ }
@@ -10,7 +10,6 @@ import type {
10
10
  } from "@opengeni/sdk";
11
11
  import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
12
12
  import { useEmbeddedSession, type EmbeddedSessionClientOverride } from "../session-context";
13
- import { normalizeError } from "../lib/error-message";
14
13
  import {
15
14
  useDebouncedCallback,
16
15
  usePageLiveActivity,
@@ -464,7 +463,7 @@ function operationKey(): string {
464
463
  }
465
464
 
466
465
  function asError(cause: unknown): Error {
467
- return normalizeError(cause);
466
+ return cause instanceof Error ? cause : new Error(String(cause));
468
467
  }
469
468
 
470
469
  function isOutcomeUnknownError(cause: unknown): boolean {