@opengeni/react 1.2.1-canary.37222965366001 → 1.4.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 (75) hide show
  1. package/README.md +52 -1
  2. package/dist/artifacts.js +2 -2
  3. package/dist/artifacts.js.map +1 -1
  4. package/dist/{chunk-ERGYJIBB.js → chunk-AWZLIMKX.js} +2 -2
  5. package/dist/{chunk-ERGYJIBB.js.map → chunk-AWZLIMKX.js.map} +1 -1
  6. package/dist/{chunk-FZCP527Y.js → chunk-CJUO7J5Z.js} +2 -2
  7. package/dist/{chunk-742CZ3L3.js → chunk-H5X55XH7.js} +16 -200
  8. package/dist/chunk-H5X55XH7.js.map +1 -0
  9. package/dist/{chunk-4OTO7KBK.js → chunk-LJ2UTJJE.js} +2737 -1580
  10. package/dist/chunk-LJ2UTJJE.js.map +1 -0
  11. package/dist/{chunk-CY7WK5FD.js → chunk-LN6TCXD3.js} +22 -1
  12. package/dist/chunk-LN6TCXD3.js.map +1 -0
  13. package/dist/{chunk-TMYGL6X5.js → chunk-MBMPHOMA.js} +71 -6
  14. package/dist/chunk-MBMPHOMA.js.map +1 -0
  15. package/dist/{chunk-RC6BZ44Q.js → chunk-OA6HFRQP.js} +2 -2
  16. package/dist/{chunk-X34BSY2R.js → chunk-WZMYFJD3.js} +242 -63
  17. package/dist/chunk-WZMYFJD3.js.map +1 -0
  18. package/dist/components/approval-surface.d.ts +11 -13
  19. package/dist/components/composer-transcription-control.d.ts +3 -0
  20. package/dist/components/open-geni-chat.d.ts +26 -7
  21. package/dist/components/session-conversation.d.ts +26 -3
  22. package/dist/components/session-list.d.ts +4 -1
  23. package/dist/components/session-proxy-scope.d.ts +16 -2
  24. package/dist/components/tool-action-review.d.ts +47 -0
  25. package/dist/components/tool-review-history.d.ts +25 -0
  26. package/dist/composer.js +1 -1
  27. package/dist/connect.js +1 -1
  28. package/dist/hooks/use-client-config-flags.d.ts +37 -0
  29. package/dist/index.d.ts +7 -4
  30. package/dist/index.js +27 -11
  31. package/dist/index.js.map +1 -1
  32. package/dist/{latest-question-YTOBHCWR.js → latest-question-GPYM2JNU.js} +3 -3
  33. package/dist/realtime/realtime-control.d.ts +2 -0
  34. package/dist/realtime.js +25 -4
  35. package/dist/realtime.js.map +1 -1
  36. package/dist/session-capability-policy.d.ts +20 -1
  37. package/dist/session-ui.d.ts +4 -1
  38. package/dist/session-ui.js +12 -6
  39. package/dist/session-ui.js.map +1 -1
  40. package/dist/session.js +6 -6
  41. package/dist/timeline/index.d.ts +2 -0
  42. package/dist/timeline/retained-loaders.d.ts +27 -0
  43. package/package.json +3 -3
  44. package/src/components/approval-surface.tsx +368 -239
  45. package/src/components/artifacts/session-artifact-viewer.tsx +4 -2
  46. package/src/components/composer-transcription-control.tsx +14 -0
  47. package/src/components/composer.tsx +1 -0
  48. package/src/components/open-geni-chat.tsx +245 -72
  49. package/src/components/session-conversation.tsx +243 -58
  50. package/src/components/session-list.tsx +9 -2
  51. package/src/components/session-proxy-scope.tsx +47 -7
  52. package/src/components/tool-action-review.tsx +649 -0
  53. package/src/components/tool-review-history.tsx +88 -0
  54. package/src/hooks/use-client-config-flags.ts +102 -0
  55. package/src/hooks/use-session-events.ts +19 -16
  56. package/src/hooks/use-transcription.ts +6 -0
  57. package/src/hooks/use-voice-input.ts +6 -0
  58. package/src/index.ts +18 -1
  59. package/src/realtime/realtime-control.tsx +28 -1
  60. package/src/session-capability-policy.ts +119 -6
  61. package/src/session-ui.ts +9 -1
  62. package/src/timeline/index.ts +10 -0
  63. package/src/timeline/retained-loaders.ts +86 -0
  64. package/src/timeline/tool-display-name.ts +5 -1
  65. package/src/timeline/tool-renderers.tsx +148 -8
  66. package/styles/compiled.css +79 -15
  67. package/styles/tokens.css +1 -1
  68. package/dist/chunk-4OTO7KBK.js.map +0 -1
  69. package/dist/chunk-742CZ3L3.js.map +0 -1
  70. package/dist/chunk-CY7WK5FD.js.map +0 -1
  71. package/dist/chunk-TMYGL6X5.js.map +0 -1
  72. package/dist/chunk-X34BSY2R.js.map +0 -1
  73. /package/dist/{chunk-FZCP527Y.js.map → chunk-CJUO7J5Z.js.map} +0 -0
  74. /package/dist/{chunk-RC6BZ44Q.js.map → chunk-OA6HFRQP.js.map} +0 -0
  75. /package/dist/{latest-question-YTOBHCWR.js.map → latest-question-GPYM2JNU.js.map} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  buildTimeline,
3
3
  groupTimeline,
4
4
  sessionStatusFromEvents
5
- } from "./chunk-RC6BZ44Q.js";
5
+ } from "./chunk-OA6HFRQP.js";
6
6
  import {
7
7
  useDebouncedCallback,
8
8
  useMutationRunner,
@@ -16,6 +16,7 @@ import {
16
16
  } from "./chunk-UGLEYEMP.js";
17
17
  import {
18
18
  useEmbeddedFileAttachments,
19
+ useEmbeddedGoal,
19
20
  useEmbeddedHumanInputSession,
20
21
  useEmbeddedSession,
21
22
  useEmbeddedSessionRead
@@ -68,6 +69,63 @@ function isRecord(value) {
68
69
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
69
70
  }
70
71
 
72
+ // src/approvals.ts
73
+ import {
74
+ parseToolDisplayMetadata
75
+ } from "@opengeni/sdk";
76
+ function approvalsFromRequiresAction(payload) {
77
+ const approvals = payload && typeof payload === "object" ? payload.approvals : void 0;
78
+ if (!Array.isArray(approvals)) {
79
+ return [];
80
+ }
81
+ return approvals.map((approval, index) => {
82
+ const raw = approval && typeof approval === "object" ? approval : {};
83
+ const rawItem = raw.rawItem && typeof raw.rawItem === "object" ? raw.rawItem : {};
84
+ const display = parseToolDisplayMetadata(raw.display);
85
+ return {
86
+ // Mirror the runtime's canonical interruption identity before retaining
87
+ // the legacy top-level callId fallback for already-normalized payloads.
88
+ id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),
89
+ name: String(raw.name ?? raw.toolName ?? rawItem.name ?? "approval"),
90
+ ...display ? { display } : {},
91
+ arguments: raw.arguments ?? rawItem.arguments,
92
+ raw: approval
93
+ };
94
+ });
95
+ }
96
+ function projectPendingApprovals(events) {
97
+ let pending = [];
98
+ let owningTurnId = null;
99
+ for (const event of events) {
100
+ switch (event.type) {
101
+ case "session.requiresAction": {
102
+ pending = approvalsFromRequiresAction(event.payload);
103
+ owningTurnId = event.turnId ?? null;
104
+ break;
105
+ }
106
+ case "user.approvalDecision": {
107
+ const payload = event.payload && typeof event.payload === "object" ? event.payload : {};
108
+ if (typeof payload.approvalId === "string") {
109
+ pending = pending.filter((approval) => approval.id !== payload.approvalId);
110
+ }
111
+ break;
112
+ }
113
+ case "turn.completed":
114
+ case "turn.failed":
115
+ case "turn.cancelled": {
116
+ if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {
117
+ pending = [];
118
+ owningTurnId = null;
119
+ }
120
+ break;
121
+ }
122
+ default:
123
+ break;
124
+ }
125
+ }
126
+ return pending;
127
+ }
128
+
71
129
  // src/older-history.ts
72
130
  var activeReceiptCapture;
73
131
  var preserveTailForAutomaticLoad = false;
@@ -523,7 +581,6 @@ function useSessionEvents(sessionId, options = {}) {
523
581
  markTailPreserved();
524
582
  return false;
525
583
  }
526
- streamAbortRef.current?.abort();
527
584
  const status = observeSessionStatus(window.events, sessionStatusRef);
528
585
  const retained = {
529
586
  ...next,
@@ -535,17 +592,21 @@ function useSessionEvents(sessionId, options = {}) {
535
592
  }
536
593
  const retainedNewest = maxResumeSequenceOrNull(retained.events);
537
594
  const previousNewest = maxResumeSequenceOrNull(current.events);
595
+ const evictedLiveTail = previousNewest !== null && retainedNewest !== null && retainedNewest < previousNewest;
596
+ if (evictedLiveTail && viewModeRef.current === "live") {
597
+ streamAbortRef.current?.abort();
598
+ }
538
599
  eventWindowRef.current = retained;
539
600
  markCommitted();
540
601
  oldestSequenceRef.current = retainedOldest;
541
602
  newestSequenceRef.current = retainedNewest;
542
- streamResumeSequenceRef.current = maxResumeSequence(retained.events);
603
+ if (evictedLiveTail) {
604
+ streamResumeSequenceRef.current = maxResumeSequence(retained.events);
605
+ }
543
606
  const olderStillAvailable = window.hasOlder;
544
607
  hasOlderRef.current = olderStillAvailable;
545
- const evictedLiveTail = previousNewest !== null && retainedNewest !== null && retainedNewest < previousNewest;
546
608
  let newer = null;
547
609
  let enterHistory = false;
548
- let reconnectLive = false;
549
610
  if (viewModeRef.current === "history" || evictedLiveTail) {
550
611
  const highWater = lastSequenceRef.current;
551
612
  newer = retainedNewest !== null && (retainedNewest < highWater || retained.truncated);
@@ -554,8 +615,6 @@ function useSessionEvents(sessionId, options = {}) {
554
615
  viewModeRef.current = "history";
555
616
  enterHistory = true;
556
617
  }
557
- } else {
558
- reconnectLive = true;
559
618
  }
560
619
  loadingOlderRef.current = false;
561
620
  startTransition(() => {
@@ -569,8 +628,6 @@ function useSessionEvents(sessionId, options = {}) {
569
628
  }
570
629
  if (enterHistory) {
571
630
  setViewMode("history");
572
- } else if (reconnectLive) {
573
- setStreamEpoch((epoch) => epoch + 1);
574
631
  }
575
632
  setLoadingOlder(false);
576
633
  });
@@ -834,7 +891,7 @@ function useSessionEvents(sessionId, options = {}) {
834
891
  let generation = navigationGenerationRef.current;
835
892
  const current = () => ownsNavigation() && generation === navigationGenerationRef.current;
836
893
  try {
837
- const { resolveLatestQuestion } = await import("./latest-question-YTOBHCWR.js");
894
+ const { resolveLatestQuestion } = await import("./latest-question-GPYM2JNU.js");
838
895
  if (!current()) return null;
839
896
  const destination = await resolveLatestQuestion({
840
897
  client,
@@ -2193,61 +2250,181 @@ function useSessionControl(sessionId, options = {}) {
2193
2250
  };
2194
2251
  }
2195
2252
 
2196
- // src/approvals.ts
2197
- import {
2198
- parseToolDisplayMetadata
2199
- } from "@opengeni/sdk";
2200
- function approvalsFromRequiresAction(payload) {
2201
- const approvals = payload && typeof payload === "object" ? payload.approvals : void 0;
2202
- if (!Array.isArray(approvals)) {
2203
- return [];
2204
- }
2205
- return approvals.map((approval, index) => {
2206
- const raw = approval && typeof approval === "object" ? approval : {};
2207
- const rawItem = raw.rawItem && typeof raw.rawItem === "object" ? raw.rawItem : {};
2208
- const display = parseToolDisplayMetadata(raw.display);
2209
- return {
2210
- // Mirror the runtime's canonical interruption identity before retaining
2211
- // the legacy top-level callId fallback for already-normalized payloads.
2212
- id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),
2213
- name: String(raw.name ?? raw.toolName ?? rawItem.name ?? "approval"),
2214
- ...display ? { display } : {},
2215
- arguments: raw.arguments ?? rawItem.arguments,
2216
- raw: approval
2217
- };
2218
- });
2253
+ // src/hooks/use-goal.ts
2254
+ import { OpenGeniApiError } from "@opengeni/sdk";
2255
+ import { useCallback as useCallback7, useEffect as useEffect6, useRef as useRef7, useState as useState6 } from "react";
2256
+ function isGoalEvent(event) {
2257
+ return event.type.startsWith("goal.");
2219
2258
  }
2220
- function projectPendingApprovals(events) {
2221
- let pending = [];
2222
- let owningTurnId = null;
2223
- for (const event of events) {
2224
- switch (event.type) {
2225
- case "session.requiresAction": {
2226
- pending = approvalsFromRequiresAction(event.payload);
2227
- owningTurnId = event.turnId ?? null;
2228
- break;
2259
+ function isGoalRefreshEvent(event) {
2260
+ const type = event.type;
2261
+ return isGoalEvent(event) || type.startsWith("turn.") || type.startsWith("session.") || type.startsWith("system.update.") || type.startsWith("workspace.inference.") || type.startsWith("user.");
2262
+ }
2263
+ function useGoal(sessionId, options = {}) {
2264
+ const { client, workspaceId } = useEmbeddedGoal(options);
2265
+ const enabled = (options.enabled ?? true) && Boolean(sessionId);
2266
+ const sharedEvents = options.events;
2267
+ const sharedFeed = sharedEvents !== void 0;
2268
+ const pageLive = usePageLiveActivity();
2269
+ const [goal, setGoal] = useState6(null);
2270
+ const [loading, setLoading] = useState6(enabled);
2271
+ const [error, setError] = useState6(null);
2272
+ const { run, mutating, mutationError, clearMutationError } = useMutationRunner();
2273
+ const generation = useRef7(0);
2274
+ const targetKeyRef = useRef7(null);
2275
+ const loadAbort = useRef7(null);
2276
+ const retireLoads = useCallback7(() => {
2277
+ generation.current += 1;
2278
+ loadAbort.current?.abort();
2279
+ loadAbort.current = null;
2280
+ }, []);
2281
+ const load = useCallback7(async () => {
2282
+ if (!sessionId) {
2283
+ return;
2284
+ }
2285
+ const ticket = ++generation.current;
2286
+ loadAbort.current?.abort();
2287
+ const controller = new AbortController();
2288
+ loadAbort.current = controller;
2289
+ try {
2290
+ const fetched = await client.getGoal(workspaceId, sessionId, {
2291
+ signal: controller.signal
2292
+ });
2293
+ if (ticket === generation.current) {
2294
+ setGoal(fetched);
2295
+ setError(null);
2296
+ setLoading(false);
2229
2297
  }
2230
- case "user.approvalDecision": {
2231
- const payload = event.payload && typeof event.payload === "object" ? event.payload : {};
2232
- if (typeof payload.approvalId === "string") {
2233
- pending = pending.filter((approval) => approval.id !== payload.approvalId);
2234
- }
2235
- break;
2298
+ } catch (cause) {
2299
+ if (ticket !== generation.current) {
2300
+ return;
2236
2301
  }
2237
- case "turn.completed":
2238
- case "turn.failed":
2239
- case "turn.cancelled": {
2240
- if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {
2241
- pending = [];
2242
- owningTurnId = null;
2243
- }
2244
- break;
2302
+ if (cause instanceof OpenGeniApiError && cause.status === 404) {
2303
+ setGoal(null);
2304
+ setError(null);
2305
+ } else {
2306
+ setError(normalizeError(cause));
2245
2307
  }
2246
- default:
2247
- break;
2308
+ setLoading(false);
2309
+ } finally {
2310
+ if (loadAbort.current === controller) loadAbort.current = null;
2248
2311
  }
2249
- }
2250
- return pending;
2312
+ }, [client, workspaceId, sessionId]);
2313
+ useEffect6(() => {
2314
+ const targetKey = `${workspaceId} ${sessionId ?? ""}`;
2315
+ if (targetKeyRef.current !== targetKey) {
2316
+ targetKeyRef.current = targetKey;
2317
+ setGoal(null);
2318
+ setError(null);
2319
+ }
2320
+ if (!enabled || !pageLive) {
2321
+ retireLoads();
2322
+ setLoading(false);
2323
+ return;
2324
+ }
2325
+ if (sharedFeed) {
2326
+ setLoading(true);
2327
+ void load();
2328
+ return () => {
2329
+ retireLoads();
2330
+ };
2331
+ }
2332
+ setLoading(true);
2333
+ const pollIntervalMs = options.pollIntervalMs;
2334
+ if (pollIntervalMs === void 0 || pollIntervalMs <= 0) {
2335
+ void load();
2336
+ return () => {
2337
+ retireLoads();
2338
+ };
2339
+ }
2340
+ let cancelled = false;
2341
+ let timer = null;
2342
+ const schedule = () => {
2343
+ if (cancelled) return;
2344
+ timer = setTimeout(() => {
2345
+ timer = null;
2346
+ void load().finally(schedule);
2347
+ }, pollIntervalMs);
2348
+ };
2349
+ void load().finally(schedule);
2350
+ return () => {
2351
+ cancelled = true;
2352
+ if (timer !== null) clearTimeout(timer);
2353
+ retireLoads();
2354
+ };
2355
+ }, [
2356
+ load,
2357
+ enabled,
2358
+ pageLive,
2359
+ workspaceId,
2360
+ sessionId,
2361
+ options.pollIntervalMs,
2362
+ retireLoads,
2363
+ sharedFeed
2364
+ ]);
2365
+ const scheduleRefresh = useDebouncedCallback(() => void load());
2366
+ useSessionEventTrigger(client, workspaceId, sessionId, isGoalRefreshEvent, scheduleRefresh, {
2367
+ enabled,
2368
+ ...sharedEvents !== void 0 ? { events: sharedEvents } : {}
2369
+ });
2370
+ const pause = useCallback7(
2371
+ async (rationale) => {
2372
+ if (!sessionId) {
2373
+ return null;
2374
+ }
2375
+ const result = await run(
2376
+ () => client.updateGoal(workspaceId, sessionId, {
2377
+ status: "paused",
2378
+ ...rationale !== void 0 ? { rationale } : {}
2379
+ })
2380
+ );
2381
+ if (result) {
2382
+ setGoal(result);
2383
+ }
2384
+ return result;
2385
+ },
2386
+ [client, workspaceId, sessionId, run]
2387
+ );
2388
+ const resume = useCallback7(async () => {
2389
+ if (!sessionId) {
2390
+ return null;
2391
+ }
2392
+ const result = await run(() => client.updateGoal(workspaceId, sessionId, { status: "active" }));
2393
+ if (result) {
2394
+ setGoal(result);
2395
+ }
2396
+ return result;
2397
+ }, [client, workspaceId, sessionId, run]);
2398
+ const clearGoal = useCallback7(async () => {
2399
+ if (!sessionId) {
2400
+ return;
2401
+ }
2402
+ const ok = await run(async () => {
2403
+ await client.deleteGoal(workspaceId, sessionId);
2404
+ return true;
2405
+ });
2406
+ if (ok) {
2407
+ retireLoads();
2408
+ setGoal(null);
2409
+ setError(null);
2410
+ }
2411
+ }, [client, workspaceId, sessionId, run, retireLoads]);
2412
+ return {
2413
+ goal,
2414
+ isActive: goal?.status === "active",
2415
+ isPaused: goal?.status === "paused",
2416
+ isCompleted: goal?.status === "completed",
2417
+ loading,
2418
+ error,
2419
+ refresh: load,
2420
+ pause,
2421
+ resume,
2422
+ clearGoal,
2423
+ deleteGoal: clearGoal,
2424
+ updating: mutating,
2425
+ mutationError,
2426
+ clearMutationError
2427
+ };
2251
2428
  }
2252
2429
 
2253
2430
  // src/conversation-timeline.ts
@@ -2306,6 +2483,8 @@ export {
2306
2483
  isActionableHumanInputRequest,
2307
2484
  humanInputRequestFromEvent,
2308
2485
  projectPendingHumanInputRequests,
2486
+ approvalsFromRequiresAction,
2487
+ projectPendingApprovals,
2309
2488
  invokeOlderHistoryLoaderWithReceiptCapture,
2310
2489
  createOlderHistoryLoadReceipt,
2311
2490
  SESSION_EVENT_BROWSER_MAX_BYTES,
@@ -2322,8 +2501,8 @@ export {
2322
2501
  useHumanInputRequests,
2323
2502
  useFileAttachments,
2324
2503
  useSessionControl,
2325
- approvalsFromRequiresAction,
2326
- projectPendingApprovals,
2504
+ isGoalEvent,
2505
+ useGoal,
2327
2506
  conversationTimeline
2328
2507
  };
2329
- //# sourceMappingURL=chunk-X34BSY2R.js.map
2508
+ //# sourceMappingURL=chunk-WZMYFJD3.js.map