@opengeni/react 0.28.2 → 0.32.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.
- package/dist/approvals.d.ts +14 -0
- package/dist/{chunk-M7X4JZOD.js → chunk-4QOQ2DSR.js} +8 -1
- package/dist/chunk-4QOQ2DSR.js.map +1 -0
- package/dist/{chunk-HQFPO7VX.js → chunk-7CJOAW3V.js} +24 -3
- package/dist/{chunk-HQFPO7VX.js.map → chunk-7CJOAW3V.js.map} +1 -1
- package/dist/{chunk-PMSGE233.js → chunk-A2WITZTI.js} +377 -113
- package/dist/chunk-A2WITZTI.js.map +1 -0
- package/dist/{chunk-BC6RKIHS.js → chunk-GZ4KR67U.js} +11 -11
- package/dist/{chunk-4F2YLLHP.js → chunk-KZRUYCL4.js} +14 -17
- package/dist/chunk-KZRUYCL4.js.map +1 -0
- package/dist/{chunk-OCHBZ2X7.js → chunk-TCCE5ZU5.js} +192 -28
- package/dist/chunk-TCCE5ZU5.js.map +1 -0
- package/dist/chunk-U255M5EZ.js +178 -0
- package/dist/chunk-U255M5EZ.js.map +1 -0
- package/dist/{chunk-XVVQP7A4.js → chunk-WY2QN2CX.js} +2539 -2174
- package/dist/chunk-WY2QN2CX.js.map +1 -0
- package/dist/chunk-ZNNE2VES.js +6413 -0
- package/dist/chunk-ZNNE2VES.js.map +1 -0
- package/dist/client.d.ts +33 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/registry.d.ts +41 -0
- package/dist/commands/types.d.ts +85 -0
- package/dist/components/approval-surface.d.ts +28 -0
- package/dist/components/chat-composer.d.ts +51 -0
- package/dist/components/code-editor.d.ts +43 -0
- package/dist/components/command-palette.d.ts +25 -0
- package/dist/components/composer-transcription-control.d.ts +36 -0
- package/dist/components/composer.d.ts +277 -0
- package/dist/components/copy-button.d.ts +26 -0
- package/dist/components/desktop-viewer.d.ts +85 -0
- package/dist/components/diff-view.d.ts +38 -0
- package/dist/components/enrollment-consent.d.ts +33 -0
- package/dist/components/enrollment-device-flow.d.ts +27 -0
- package/dist/components/file-browser.d.ts +47 -0
- package/dist/components/fleet-tile.d.ts +18 -0
- package/dist/components/human-input-form.d.ts +47 -0
- package/dist/components/machine-card.d.ts +21 -0
- package/dist/components/machine-dock-bar.d.ts +31 -0
- package/dist/components/machine-health-pill.d.ts +9 -0
- package/dist/components/machine-metrics.d.ts +15 -0
- package/dist/components/machine-status-pill.d.ts +54 -0
- package/dist/components/machines/health.d.ts +25 -0
- package/dist/components/machines/machine-detail.d.ts +14 -0
- package/dist/components/machines/metric-history-chart.d.ts +24 -0
- package/dist/components/machines/metric-sparkline.d.ts +9 -0
- package/dist/components/machines/series.d.ts +24 -0
- package/dist/components/machines-dashboard.d.ts +30 -0
- package/dist/components/markdown.d.ts +31 -0
- package/dist/components/message-timeline.d.ts +98 -0
- package/dist/components/model-picker.d.ts +19 -0
- package/dist/components/pierre-diff.d.ts +34 -0
- package/dist/components/pierre-file.d.ts +27 -0
- package/dist/components/queue-draft-policy.d.ts +7 -0
- package/dist/components/queue-surface-implementation.d.ts +20 -0
- package/dist/components/queue-surface-state.d.ts +12 -0
- package/dist/components/queue-surface.d.ts +12 -0
- package/dist/components/sandbox-files.d.ts +49 -0
- package/dist/components/sandbox-terminal.d.ts +123 -0
- package/dist/components/sandbox-workspace.d.ts +128 -0
- package/dist/components/session-chrome.d.ts +70 -0
- package/dist/components/session-status.d.ts +25 -0
- package/dist/components/soften-streaming-markdown.d.ts +13 -0
- package/dist/components/stream-reveal.d.ts +37 -0
- package/dist/components/tip-follow.d.ts +139 -0
- package/dist/components/tooltip.d.ts +16 -0
- package/dist/components/workbench-changes.d.ts +34 -0
- package/dist/components/workspace-dock.d.ts +35 -0
- package/dist/composer.d.ts +11 -7
- package/dist/composer.js +9 -6
- package/dist/hooks/internal.d.ts +46 -0
- package/dist/hooks/use-available-models.d.ts +37 -0
- package/dist/hooks/use-billing-usage.d.ts +26 -0
- package/dist/hooks/use-codex-accounts.d.ts +69 -0
- package/dist/{use-composer-ClHy1rkL.d.ts → hooks/use-composer.d.ts} +16 -24
- package/dist/hooks/use-desktop-stream.d.ts +43 -0
- package/dist/hooks/use-environments.d.ts +35 -0
- package/dist/{use-file-attachments-BmT8WtqO.d.ts → hooks/use-file-attachments.d.ts} +6 -9
- package/dist/hooks/use-goal.d.ts +46 -0
- package/dist/hooks/use-human-input.d.ts +26 -0
- package/dist/hooks/use-last-started-turn-policy.d.ts +27 -0
- package/dist/hooks/use-machine-chip.d.ts +54 -0
- package/dist/hooks/use-machines.d.ts +81 -0
- package/dist/hooks/use-packs.d.ts +27 -0
- package/dist/hooks/use-relay-frame-stream.d.ts +53 -0
- package/dist/hooks/use-rigs.d.ts +87 -0
- package/dist/hooks/use-sandbox-files.d.ts +108 -0
- package/dist/hooks/use-sandbox-git.d.ts +58 -0
- package/dist/hooks/use-sandbox-terminal.d.ts +62 -0
- package/dist/hooks/use-scheduled-tasks.d.ts +15 -0
- package/dist/hooks/use-session-capabilities.d.ts +83 -0
- package/dist/hooks/use-session-control.d.ts +22 -0
- package/dist/hooks/use-session-events.d.ts +92 -0
- package/dist/hooks/use-session-lineage.d.ts +17 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +23 -0
- package/dist/hooks/use-session.d.ts +23 -0
- package/dist/hooks/use-slash-commands.d.ts +66 -0
- package/dist/hooks/use-terminal-stream.d.ts +46 -0
- package/dist/hooks/use-transcription.d.ts +73 -0
- package/dist/hooks/use-turn-queue.d.ts +44 -0
- package/dist/hooks/use-voice-input.d.ts +25 -0
- package/dist/hooks/use-windowed-sections.d.ts +42 -0
- package/dist/hooks/use-workspace-capture.d.ts +49 -0
- package/dist/hooks/use-workspace-edit.d.ts +73 -0
- package/dist/hooks/use-workspace-sessions.d.ts +30 -0
- package/dist/hooks/use-workspaces.d.ts +22 -0
- package/dist/human-input.d.ts +18 -0
- package/dist/index.d.ts +144 -2119
- package/dist/index.js +421 -324
- package/dist/index.js.map +1 -1
- package/dist/lib/clipboard.d.ts +7 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/format.d.ts +48 -0
- package/dist/lib/git-patch.d.ts +8 -0
- package/dist/lib/motion-inspect.d.ts +5 -0
- package/dist/lib/motion.d.ts +14 -0
- package/dist/lib/noto-sans-arabic-loader.d.ts +1 -0
- package/dist/lib/noto-sans-jp-loader.generated.d.ts +1 -0
- package/dist/lib/relay-wire.d.ts +30 -0
- package/dist/lib/use-portal-token-style.d.ts +9 -0
- package/dist/lib/use-theme-type.d.ts +5 -0
- package/dist/lib/use-unicode-fonts.d.ts +12 -0
- package/dist/lib/xterm-renderer.d.ts +19 -0
- package/dist/lib/xterm-theme.d.ts +75 -0
- package/dist/machines.d.ts +30 -413
- package/dist/machines.js +3 -3
- package/dist/model-policy.d.ts +32 -0
- package/dist/model-policy.js +33 -0
- package/dist/model-policy.js.map +1 -0
- package/dist/provider.d.ts +16 -0
- package/dist/{queue-surface-implementation-UQ535OKQ.js → queue-surface-implementation-THPAKGMD.js} +2 -2
- package/dist/{queue-surface-implementation-UQ535OKQ.js.map → queue-surface-implementation-THPAKGMD.js.map} +1 -1
- package/dist/session-context.d.ts +82 -0
- package/dist/session-ui.d.ts +10 -7
- package/dist/session-ui.js +9 -5
- package/dist/session.d.ts +28 -6
- package/dist/session.js +11 -11
- package/dist/timeline/activity-rail.d.ts +19 -0
- package/dist/timeline/disclosure-context.d.ts +14 -0
- package/dist/timeline/entrance.d.ts +14 -0
- package/dist/timeline/fleet-decision-projection.d.ts +9 -0
- package/dist/timeline/fleet-decision-row.d.ts +11 -0
- package/dist/timeline/fold-memory.d.ts +15 -0
- package/dist/timeline/index.d.ts +18 -0
- package/dist/timeline/parsers.d.ts +96 -0
- package/dist/timeline/projection.d.ts +38 -0
- package/dist/timeline/registry.d.ts +40 -0
- package/dist/timeline/screenshot-lightbox.d.ts +26 -0
- package/dist/timeline/seen-activity-ids.d.ts +2 -0
- package/dist/timeline/shared.d.ts +125 -0
- package/dist/timeline/tool-diff.d.ts +8 -0
- package/dist/timeline/tool-display-name.d.ts +10 -0
- package/dist/timeline/tool-renderers.d.ts +5 -0
- package/dist/timeline/turn-summary.d.ts +116 -0
- package/dist/{use-turn-queue-Drm_ypue.d.ts → timeline/types.d.ts} +57 -67
- package/dist/types/machines.d.ts +11 -0
- package/package.json +8 -4
- package/src/client.ts +1 -0
- package/src/components/composer-transcription-control.tsx +278 -130
- package/src/components/composer.tsx +20 -15
- package/src/components/copy-button.tsx +127 -0
- package/src/components/markdown.tsx +231 -32
- package/src/components/message-timeline.tsx +1382 -378
- package/src/components/model-picker.tsx +83 -43
- package/src/components/queue-surface-implementation.tsx +1 -1
- package/src/components/session-chrome.tsx +942 -0
- package/src/components/soften-streaming-markdown.ts +205 -0
- package/src/components/stream-reveal.ts +195 -0
- package/src/components/tip-follow.ts +459 -0
- package/src/components/tooltip.tsx +103 -0
- package/src/composer.ts +6 -0
- package/src/hooks/internal.ts +30 -4
- package/src/hooks/use-available-models.ts +51 -4
- package/src/hooks/use-composer.ts +24 -18
- package/src/hooks/use-last-started-turn-policy.ts +95 -0
- package/src/hooks/use-session-events.ts +359 -5
- package/src/hooks/use-voice-input.ts +232 -0
- package/src/index.ts +49 -1
- package/src/lib/clipboard.ts +58 -0
- package/src/lib/format.ts +18 -0
- package/src/lib/motion-inspect.ts +5 -0
- package/src/lib/motion.ts +80 -0
- package/src/model-policy.ts +210 -0
- package/src/session-ui.ts +7 -0
- package/src/session.ts +2 -0
- package/src/timeline/activity-rail.tsx +46 -7
- package/src/timeline/entrance.tsx +10 -0
- package/src/timeline/fold-memory.ts +52 -0
- package/src/timeline/index.ts +11 -1
- package/src/timeline/projection.ts +252 -47
- package/src/timeline/seen-activity-ids.ts +19 -0
- package/src/timeline/shared.tsx +1 -1
- package/src/timeline/tool-renderers.tsx +75 -6
- package/src/timeline/turn-summary.tsx +387 -97
- package/src/timeline/types.ts +47 -0
- package/styles/index.css +99 -7
- package/styles/tokens.css +44 -3
- package/dist/chunk-4F2YLLHP.js.map +0 -1
- package/dist/chunk-M7X4JZOD.js.map +0 -1
- package/dist/chunk-OCHBZ2X7.js.map +0 -1
- package/dist/chunk-PMSGE233.js.map +0 -1
- package/dist/chunk-WAA247AB.js +0 -3858
- package/dist/chunk-WAA247AB.js.map +0 -1
- package/dist/chunk-XVVQP7A4.js.map +0 -1
- package/dist/composer-BMzimGTO.d.ts +0 -528
- package/dist/session-C3tIXLim.d.ts +0 -264
- package/dist/session-context-CAjlaeZb.d.ts +0 -84
- package/dist/session-ui-B_7cfN5u.d.ts +0 -259
- /package/dist/{chunk-BC6RKIHS.js.map → chunk-GZ4KR67U.js.map} +0 -0
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildTimeline,
|
|
3
|
+
groupTimeline,
|
|
4
|
+
sessionStatusFromEvents
|
|
5
|
+
} from "./chunk-TCCE5ZU5.js";
|
|
1
6
|
import {
|
|
2
7
|
useDebouncedCallback,
|
|
3
8
|
useEmbeddedFileAttachments,
|
|
@@ -10,12 +15,7 @@ import {
|
|
|
10
15
|
useMutationRunner,
|
|
11
16
|
usePolledValue,
|
|
12
17
|
useSessionEventTrigger
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import {
|
|
15
|
-
buildTimeline,
|
|
16
|
-
groupTimeline,
|
|
17
|
-
sessionStatusFromEvents
|
|
18
|
-
} from "./chunk-OCHBZ2X7.js";
|
|
18
|
+
} from "./chunk-7CJOAW3V.js";
|
|
19
19
|
|
|
20
20
|
// src/hooks/use-session.ts
|
|
21
21
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
@@ -102,9 +102,15 @@ function useSession(sessionId, options = {}) {
|
|
|
102
102
|
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
103
103
|
var INITIAL_TAIL_PAGE_SIZE = 1e3;
|
|
104
104
|
var OLDER_PAGE_SIZE = 5e3;
|
|
105
|
+
var NEWER_PAGE_SIZE = 5e3;
|
|
106
|
+
var OLDEST_PAGE_SIZE = 1e3;
|
|
105
107
|
var INITIAL_FETCH_CAP = 1;
|
|
106
108
|
var OLDER_GROUP_TARGET = 32;
|
|
107
109
|
var OLDER_FETCH_CAP = 2;
|
|
110
|
+
var NEWER_GROUP_TARGET = 32;
|
|
111
|
+
var NEWER_FETCH_CAP = 2;
|
|
112
|
+
var OLDEST_GROUP_TARGET = 32;
|
|
113
|
+
var OLDEST_FETCH_CAP = 2;
|
|
108
114
|
var BOUNDARY_PAGE_CAP = 4;
|
|
109
115
|
var EMPTY_EVENTS = [];
|
|
110
116
|
var encoder = new TextEncoder();
|
|
@@ -152,17 +158,28 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
152
158
|
const [connectionState, setConnectionState] = useState2("idle");
|
|
153
159
|
const [error, setError] = useState2(null);
|
|
154
160
|
const [hasOlder, setHasOlder] = useState2(false);
|
|
161
|
+
const [hasNewer, setHasNewer] = useState2(false);
|
|
155
162
|
const [sessionStatusProjection, setSessionStatusProjection] = useState2(
|
|
156
163
|
null
|
|
157
164
|
);
|
|
158
165
|
const [initialLoading, setInitialLoading] = useState2(true);
|
|
159
166
|
const [loadingOlder, setLoadingOlder] = useState2(false);
|
|
167
|
+
const [loadingNewer, setLoadingNewer] = useState2(false);
|
|
168
|
+
const [loadingOldest, setLoadingOldest] = useState2(false);
|
|
169
|
+
const [loadingLatest, setLoadingLatest] = useState2(false);
|
|
160
170
|
const [streamEpoch, setStreamEpoch] = useState2(0);
|
|
171
|
+
const [viewMode, setViewMode] = useState2("live");
|
|
161
172
|
const lastSequenceRef = useRef(after);
|
|
162
173
|
const streamResumeSequenceRef = useRef(after);
|
|
163
174
|
const oldestSequenceRef = useRef(null);
|
|
175
|
+
const newestSequenceRef = useRef(null);
|
|
164
176
|
const hasOlderRef = useRef(false);
|
|
177
|
+
const hasNewerRef = useRef(false);
|
|
165
178
|
const loadingOlderRef = useRef(false);
|
|
179
|
+
const loadingNewerRef = useRef(false);
|
|
180
|
+
const loadingOldestRef = useRef(false);
|
|
181
|
+
const loadingLatestRef = useRef(false);
|
|
182
|
+
const viewModeRef = useRef("live");
|
|
166
183
|
const initialWindowLoadedRef = useRef(false);
|
|
167
184
|
const streamAbortRef = useRef(null);
|
|
168
185
|
const streamKeyRef = useRef(null);
|
|
@@ -181,15 +198,26 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
181
198
|
setEventWindow(EMPTY_EVENT_WINDOW);
|
|
182
199
|
setError(null);
|
|
183
200
|
setHasOlder(false);
|
|
201
|
+
setHasNewer(false);
|
|
184
202
|
sessionStatusRef.current = { sequence: after, status: null };
|
|
185
203
|
setSessionStatusProjection(null);
|
|
186
204
|
setLoadingOlder(false);
|
|
205
|
+
setLoadingNewer(false);
|
|
206
|
+
setLoadingOldest(false);
|
|
207
|
+
setLoadingLatest(false);
|
|
187
208
|
setInitialLoading(true);
|
|
188
209
|
lastSequenceRef.current = after;
|
|
189
210
|
streamResumeSequenceRef.current = after;
|
|
190
211
|
oldestSequenceRef.current = null;
|
|
212
|
+
newestSequenceRef.current = null;
|
|
191
213
|
hasOlderRef.current = false;
|
|
214
|
+
hasNewerRef.current = false;
|
|
192
215
|
loadingOlderRef.current = false;
|
|
216
|
+
loadingNewerRef.current = false;
|
|
217
|
+
loadingOldestRef.current = false;
|
|
218
|
+
loadingLatestRef.current = false;
|
|
219
|
+
viewModeRef.current = "live";
|
|
220
|
+
setViewMode("live");
|
|
193
221
|
initialWindowLoadedRef.current = false;
|
|
194
222
|
}
|
|
195
223
|
const generation = generationRef.current + 1;
|
|
@@ -202,6 +230,11 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
202
230
|
setConnectionState("idle");
|
|
203
231
|
return;
|
|
204
232
|
}
|
|
233
|
+
if (viewMode === "history") {
|
|
234
|
+
setConnectionState("idle");
|
|
235
|
+
setInitialLoading(false);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
205
238
|
const controller = new AbortController();
|
|
206
239
|
const isCurrent = () => generationRef.current === generation && !controller.signal.aborted;
|
|
207
240
|
streamAbortRef.current = controller;
|
|
@@ -243,6 +276,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
243
276
|
eventWindowRef.current = retained;
|
|
244
277
|
setEventWindow(retained);
|
|
245
278
|
oldestSequenceRef.current = retained.events[0]?.sequence ?? null;
|
|
279
|
+
newestSequenceRef.current = retained.events.at(-1)?.sequence ?? null;
|
|
246
280
|
if (retained.truncated) {
|
|
247
281
|
hasOlderRef.current = true;
|
|
248
282
|
setHasOlder(true);
|
|
@@ -271,11 +305,14 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
271
305
|
eventWindowRef.current = retained;
|
|
272
306
|
setEventWindow(retained);
|
|
273
307
|
oldestSequenceRef.current = retained.events[0]?.sequence ?? window.oldestSequence;
|
|
308
|
+
newestSequenceRef.current = retained.events.at(-1)?.sequence ?? window.newestSequence;
|
|
274
309
|
hasOlderRef.current = window.hasOlder || retained.truncated;
|
|
310
|
+
hasNewerRef.current = false;
|
|
275
311
|
lastSequenceRef.current = window.newestSequence;
|
|
276
312
|
streamResumeSequenceRef.current = window.newestSequence;
|
|
277
313
|
initialWindowLoadedRef.current = true;
|
|
278
314
|
setHasOlder(window.hasOlder || retained.truncated);
|
|
315
|
+
setHasNewer(false);
|
|
279
316
|
setInitialLoading(false);
|
|
280
317
|
}
|
|
281
318
|
if (fullReplay) {
|
|
@@ -340,10 +377,12 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
340
377
|
fullReplay,
|
|
341
378
|
streamKey,
|
|
342
379
|
streamEpoch,
|
|
380
|
+
viewMode,
|
|
343
381
|
reconcileSession
|
|
344
382
|
]);
|
|
383
|
+
const navigationBusy = () => loadingOlderRef.current || loadingNewerRef.current || loadingOldestRef.current || loadingLatestRef.current;
|
|
345
384
|
const loadOlder = useCallback2(async () => {
|
|
346
|
-
if (!sessionId ||
|
|
385
|
+
if (!sessionId || navigationBusy() || !hasOlderRef.current) {
|
|
347
386
|
return false;
|
|
348
387
|
}
|
|
349
388
|
const before = oldestSequenceRef.current;
|
|
@@ -386,22 +425,177 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
386
425
|
if (retainedOldest === null || retainedOldest >= before) {
|
|
387
426
|
throw new Error("@opengeni/react: loadOlder made no durable sequence progress");
|
|
388
427
|
}
|
|
428
|
+
const retainedNewest = retained.events.at(-1)?.sequence ?? null;
|
|
389
429
|
eventWindowRef.current = retained;
|
|
390
430
|
setEventWindow(retained);
|
|
391
431
|
oldestSequenceRef.current = retainedOldest;
|
|
432
|
+
newestSequenceRef.current = retainedNewest;
|
|
392
433
|
streamResumeSequenceRef.current = maxResumeSequence(retained.events);
|
|
393
434
|
const olderStillAvailable = window.hasOlder;
|
|
394
435
|
hasOlderRef.current = olderStillAvailable;
|
|
395
436
|
setHasOlder(olderStillAvailable);
|
|
396
|
-
|
|
437
|
+
if (viewModeRef.current === "history") {
|
|
438
|
+
const highWater = lastSequenceRef.current;
|
|
439
|
+
const newer = retainedNewest !== null && (retainedNewest < highWater || retained.truncated);
|
|
440
|
+
hasNewerRef.current = newer;
|
|
441
|
+
setHasNewer(newer);
|
|
442
|
+
} else {
|
|
443
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
444
|
+
}
|
|
397
445
|
return olderStillAvailable;
|
|
398
446
|
} finally {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
447
|
+
loadingOlderRef.current = false;
|
|
448
|
+
setLoadingOlder(false);
|
|
449
|
+
}
|
|
450
|
+
}, [client, workspaceId, sessionId]);
|
|
451
|
+
const loadOldest = useCallback2(async () => {
|
|
452
|
+
if (!sessionId || navigationBusy() || !hasOlderRef.current) {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
const generation = generationRef.current;
|
|
456
|
+
loadingOldestRef.current = true;
|
|
457
|
+
setLoadingOldest(true);
|
|
458
|
+
try {
|
|
459
|
+
const window = await loadForwardEventWindow(client, workspaceId, sessionId, {
|
|
460
|
+
after: 0,
|
|
461
|
+
pageSize: OLDEST_PAGE_SIZE,
|
|
462
|
+
targetGroups: OLDEST_GROUP_TARGET,
|
|
463
|
+
maxFetches: OLDEST_FETCH_CAP
|
|
464
|
+
});
|
|
465
|
+
if (generationRef.current !== generation) {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
if (window.events.length === 0) {
|
|
469
|
+
hasOlderRef.current = false;
|
|
470
|
+
setHasOlder(false);
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
streamAbortRef.current?.abort();
|
|
474
|
+
observeSessionStatus(window.events, sessionStatusRef, setSessionStatusProjection);
|
|
475
|
+
const retained = boundBrowserSessionEventWindow(window.events, { direction: "oldest" });
|
|
476
|
+
const retainedOldest = retained.events[0]?.sequence ?? null;
|
|
477
|
+
const retainedNewest = retained.events.at(-1)?.sequence ?? null;
|
|
478
|
+
eventWindowRef.current = retained;
|
|
479
|
+
setEventWindow(retained);
|
|
480
|
+
oldestSequenceRef.current = retainedOldest;
|
|
481
|
+
newestSequenceRef.current = retainedNewest;
|
|
482
|
+
hasOlderRef.current = false;
|
|
483
|
+
setHasOlder(false);
|
|
484
|
+
const highWater = Math.max(lastSequenceRef.current, retainedNewest ?? 0);
|
|
485
|
+
lastSequenceRef.current = highWater;
|
|
486
|
+
const newer = window.hasNewer || retained.truncated || retainedNewest !== null && retainedNewest < highWater;
|
|
487
|
+
hasNewerRef.current = newer;
|
|
488
|
+
setHasNewer(newer);
|
|
489
|
+
initialWindowLoadedRef.current = true;
|
|
490
|
+
viewModeRef.current = "history";
|
|
491
|
+
setViewMode("history");
|
|
492
|
+
return newer;
|
|
493
|
+
} finally {
|
|
494
|
+
loadingOldestRef.current = false;
|
|
495
|
+
setLoadingOldest(false);
|
|
496
|
+
}
|
|
497
|
+
}, [client, workspaceId, sessionId]);
|
|
498
|
+
const loadNewer = useCallback2(async () => {
|
|
499
|
+
if (!sessionId || navigationBusy() || !hasNewerRef.current) {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
const afterSequence = newestSequenceRef.current;
|
|
503
|
+
if (afterSequence === null) {
|
|
504
|
+
hasNewerRef.current = false;
|
|
505
|
+
setHasNewer(false);
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
const generation = generationRef.current;
|
|
509
|
+
loadingNewerRef.current = true;
|
|
510
|
+
setLoadingNewer(true);
|
|
511
|
+
try {
|
|
512
|
+
const window = await loadForwardEventWindow(client, workspaceId, sessionId, {
|
|
513
|
+
after: afterSequence,
|
|
514
|
+
pageSize: NEWER_PAGE_SIZE,
|
|
515
|
+
targetGroups: NEWER_GROUP_TARGET,
|
|
516
|
+
maxFetches: NEWER_FETCH_CAP
|
|
517
|
+
});
|
|
518
|
+
if (generationRef.current !== generation) {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
if (window.events.length === 0) {
|
|
522
|
+
hasNewerRef.current = false;
|
|
523
|
+
setHasNewer(false);
|
|
524
|
+
streamResumeSequenceRef.current = afterSequence;
|
|
525
|
+
viewModeRef.current = "live";
|
|
526
|
+
setViewMode("live");
|
|
527
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
const current = eventWindowRef.current;
|
|
531
|
+
assertAppendOrder(current.events, window.events);
|
|
532
|
+
observeSessionStatus(window.events, sessionStatusRef, setSessionStatusProjection);
|
|
533
|
+
const previousOldest = current.events[0]?.sequence ?? null;
|
|
534
|
+
const next = boundBrowserSessionEventWindow([...current.events, ...window.events], {
|
|
535
|
+
direction: "newest"
|
|
536
|
+
});
|
|
537
|
+
const retained = {
|
|
538
|
+
...next,
|
|
539
|
+
truncated: current.truncated || next.truncated || window.hasNewer
|
|
540
|
+
};
|
|
541
|
+
const retainedOldest = retained.events[0]?.sequence ?? null;
|
|
542
|
+
const retainedNewest = retained.events.at(-1)?.sequence ?? null;
|
|
543
|
+
if (retainedNewest === null || retainedNewest <= afterSequence) {
|
|
544
|
+
throw new Error("@opengeni/react: loadNewer made no durable sequence progress");
|
|
402
545
|
}
|
|
546
|
+
eventWindowRef.current = retained;
|
|
547
|
+
setEventWindow(retained);
|
|
548
|
+
oldestSequenceRef.current = retainedOldest;
|
|
549
|
+
newestSequenceRef.current = retainedNewest;
|
|
550
|
+
if (retainedOldest !== null && (previousOldest === null || retainedOldest > previousOldest || retained.truncated && retained.events[0]?.type !== "session.created" && retainedOldest > 1)) {
|
|
551
|
+
hasOlderRef.current = true;
|
|
552
|
+
setHasOlder(true);
|
|
553
|
+
}
|
|
554
|
+
const highWater = Math.max(lastSequenceRef.current, retainedNewest);
|
|
555
|
+
lastSequenceRef.current = highWater;
|
|
556
|
+
const newer = window.hasNewer || retainedNewest < highWater;
|
|
557
|
+
hasNewerRef.current = newer;
|
|
558
|
+
setHasNewer(newer);
|
|
559
|
+
if (!newer) {
|
|
560
|
+
streamResumeSequenceRef.current = retainedNewest;
|
|
561
|
+
viewModeRef.current = "live";
|
|
562
|
+
setViewMode("live");
|
|
563
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
564
|
+
}
|
|
565
|
+
return newer;
|
|
566
|
+
} finally {
|
|
567
|
+
loadingNewerRef.current = false;
|
|
568
|
+
setLoadingNewer(false);
|
|
403
569
|
}
|
|
404
570
|
}, [client, workspaceId, sessionId]);
|
|
571
|
+
const jumpToLatest = useCallback2(async () => {
|
|
572
|
+
if (!sessionId || navigationBusy()) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
loadingLatestRef.current = true;
|
|
576
|
+
setLoadingLatest(true);
|
|
577
|
+
try {
|
|
578
|
+
streamAbortRef.current?.abort();
|
|
579
|
+
hasNewerRef.current = false;
|
|
580
|
+
setHasNewer(false);
|
|
581
|
+
hasOlderRef.current = false;
|
|
582
|
+
setHasOlder(false);
|
|
583
|
+
newestSequenceRef.current = null;
|
|
584
|
+
oldestSequenceRef.current = null;
|
|
585
|
+
eventWindowRef.current = EMPTY_EVENT_WINDOW;
|
|
586
|
+
setEventWindow(EMPTY_EVENT_WINDOW);
|
|
587
|
+
initialWindowLoadedRef.current = false;
|
|
588
|
+
streamResumeSequenceRef.current = after;
|
|
589
|
+
setInitialLoading(true);
|
|
590
|
+
viewModeRef.current = "live";
|
|
591
|
+
setViewMode("live");
|
|
592
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
593
|
+
await Promise.resolve();
|
|
594
|
+
} finally {
|
|
595
|
+
loadingLatestRef.current = false;
|
|
596
|
+
setLoadingLatest(false);
|
|
597
|
+
}
|
|
598
|
+
}, [after, sessionId]);
|
|
405
599
|
const identityMatches = stateStreamKey === streamKey;
|
|
406
600
|
const visibleEvents = identityMatches ? eventWindow.events : EMPTY_EVENTS;
|
|
407
601
|
const timeline = useMemo2(() => buildTimeline(visibleEvents), [visibleEvents]);
|
|
@@ -417,6 +611,13 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
417
611
|
hasOlder: !identityMatches ? false : hasOlder,
|
|
418
612
|
loadingOlder: !identityMatches ? false : loadingOlder,
|
|
419
613
|
loadOlder,
|
|
614
|
+
hasNewer: !identityMatches ? false : hasNewer,
|
|
615
|
+
loadingNewer: !identityMatches ? false : loadingNewer,
|
|
616
|
+
loadNewer,
|
|
617
|
+
loadingOldest: !identityMatches ? false : loadingOldest,
|
|
618
|
+
loadOldest,
|
|
619
|
+
loadingLatest: !identityMatches ? false : loadingLatest,
|
|
620
|
+
jumpToLatest,
|
|
420
621
|
error: identityMatches ? error : null
|
|
421
622
|
};
|
|
422
623
|
}
|
|
@@ -704,6 +905,41 @@ function findBoundaryIndex(events) {
|
|
|
704
905
|
}
|
|
705
906
|
return -1;
|
|
706
907
|
}
|
|
908
|
+
async function loadForwardEventWindow(client, workspaceId, sessionId, options) {
|
|
909
|
+
let cursor = options.after;
|
|
910
|
+
let buffer = [];
|
|
911
|
+
let fetches = 0;
|
|
912
|
+
let reachedEnd = false;
|
|
913
|
+
while (fetches < options.maxFetches) {
|
|
914
|
+
if (buffer.length > 0 && groupCount(buffer) >= options.targetGroups) {
|
|
915
|
+
break;
|
|
916
|
+
}
|
|
917
|
+
const page = await loadNextPage(client, workspaceId, sessionId, cursor, {
|
|
918
|
+
pageSize: options.pageSize,
|
|
919
|
+
...options.signal ? { signal: options.signal } : {}
|
|
920
|
+
});
|
|
921
|
+
fetches += 1;
|
|
922
|
+
if (page.length === 0) {
|
|
923
|
+
reachedEnd = true;
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
assertAscending(page);
|
|
927
|
+
buffer = [...buffer, ...page];
|
|
928
|
+
cursor = page[page.length - 1].sequence;
|
|
929
|
+
if (page.length < options.pageSize) {
|
|
930
|
+
reachedEnd = true;
|
|
931
|
+
break;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
const oldest = buffer[0] ?? null;
|
|
935
|
+
const newest = buffer[buffer.length - 1] ?? null;
|
|
936
|
+
return {
|
|
937
|
+
events: buffer,
|
|
938
|
+
oldestSequence: oldest?.sequence ?? null,
|
|
939
|
+
newestSequence: newest ? maxResumeSequence(buffer) : 0,
|
|
940
|
+
hasNewer: buffer.length > 0 && !reachedEnd
|
|
941
|
+
};
|
|
942
|
+
}
|
|
707
943
|
async function loadPreviousPage(client, workspaceId, sessionId, before, options) {
|
|
708
944
|
if (options.signal?.aborted) {
|
|
709
945
|
throw abortError();
|
|
@@ -727,6 +963,26 @@ async function loadPreviousPage(client, workspaceId, sessionId, before, options)
|
|
|
727
963
|
}
|
|
728
964
|
return Object.assign(page, { requested });
|
|
729
965
|
}
|
|
966
|
+
async function loadNextPage(client, workspaceId, sessionId, after, options) {
|
|
967
|
+
if (options.signal?.aborted) {
|
|
968
|
+
throw abortError();
|
|
969
|
+
}
|
|
970
|
+
const requested = options.pageSize;
|
|
971
|
+
if (requested === 0) {
|
|
972
|
+
return Object.assign([], { requested });
|
|
973
|
+
}
|
|
974
|
+
const page = await client.listEvents(workspaceId, sessionId, {
|
|
975
|
+
after,
|
|
976
|
+
limit: requested,
|
|
977
|
+
compact: true,
|
|
978
|
+
direction: "after",
|
|
979
|
+
payloadMode: "full"
|
|
980
|
+
});
|
|
981
|
+
if (options.signal?.aborted) {
|
|
982
|
+
throw abortError();
|
|
983
|
+
}
|
|
984
|
+
return Object.assign(page, { requested });
|
|
985
|
+
}
|
|
730
986
|
function groupCount(events) {
|
|
731
987
|
if (events.length === 0) {
|
|
732
988
|
return 0;
|
|
@@ -762,6 +1018,14 @@ function assertPrependOrder(existing, older) {
|
|
|
762
1018
|
throw new Error("@opengeni/react: loadOlder returned overlapping session events");
|
|
763
1019
|
}
|
|
764
1020
|
}
|
|
1021
|
+
function assertAppendOrder(existing, newer) {
|
|
1022
|
+
if (!shouldAssertDevelopment() || existing.length === 0 || newer.length === 0) {
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
if (newer[0].sequence <= existing[existing.length - 1].sequence) {
|
|
1026
|
+
throw new Error("@opengeni/react: loadNewer returned overlapping session events");
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
765
1029
|
function shouldAssertDevelopment() {
|
|
766
1030
|
const processEnv = globalThis.process?.env;
|
|
767
1031
|
return processEnv !== void 0 && processEnv.NODE_ENV !== "production";
|
|
@@ -1364,12 +1628,97 @@ function useGoal(sessionId, options = {}) {
|
|
|
1364
1628
|
};
|
|
1365
1629
|
}
|
|
1366
1630
|
|
|
1631
|
+
// src/hooks/use-session-lineage.ts
|
|
1632
|
+
import { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
1633
|
+
function isLineageRefreshEvent(event) {
|
|
1634
|
+
if (event.type === "session.status.changed" || event.type === "session.created") {
|
|
1635
|
+
return true;
|
|
1636
|
+
}
|
|
1637
|
+
if (event.type === "agent.toolCall.output") {
|
|
1638
|
+
const payload = event.payload;
|
|
1639
|
+
const name = typeof payload?.name === "string" ? payload.name : typeof payload?.toolName === "string" ? payload.toolName : "";
|
|
1640
|
+
return name === "session_create" || name.endsWith("__session_create");
|
|
1641
|
+
}
|
|
1642
|
+
return false;
|
|
1643
|
+
}
|
|
1644
|
+
function isSessionCreateToolCallCreated(event) {
|
|
1645
|
+
if (event.type !== "agent.toolCall.created") {
|
|
1646
|
+
return false;
|
|
1647
|
+
}
|
|
1648
|
+
const payload = event.payload;
|
|
1649
|
+
const name = typeof payload?.name === "string" ? payload.name : typeof payload?.toolName === "string" ? payload.toolName : "";
|
|
1650
|
+
return name === "session_create" || name.endsWith("__session_create");
|
|
1651
|
+
}
|
|
1652
|
+
function useSessionLineage(sessionId, options = {}) {
|
|
1653
|
+
const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } = useEmbeddedSessionLineage(options);
|
|
1654
|
+
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
1655
|
+
const load = useCallback6(
|
|
1656
|
+
async () => sessionId ? await client.getSessionLineage(workspaceId, sessionId) : { ancestors: [], children: [], truncated: false },
|
|
1657
|
+
[client, workspaceId, sessionId]
|
|
1658
|
+
);
|
|
1659
|
+
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });
|
|
1660
|
+
const refresh = state.refresh;
|
|
1661
|
+
useEffect5(() => {
|
|
1662
|
+
if (enabled && workspaceControlEvent) void refresh();
|
|
1663
|
+
}, [enabled, refresh, workspaceControlEvent]);
|
|
1664
|
+
useEffect5(() => {
|
|
1665
|
+
if (!sessionId || !enabled) return;
|
|
1666
|
+
return registerSessionReconciler(sessionId, "lineage", refresh);
|
|
1667
|
+
}, [enabled, refresh, registerSessionReconciler, sessionId]);
|
|
1668
|
+
const refreshSoon = useDebouncedCallback(() => void refresh(), 150);
|
|
1669
|
+
const delayedChildRefreshRef = useRef5(null);
|
|
1670
|
+
useEffect5(() => {
|
|
1671
|
+
return () => {
|
|
1672
|
+
if (delayedChildRefreshRef.current !== null) {
|
|
1673
|
+
clearTimeout(delayedChildRefreshRef.current);
|
|
1674
|
+
delayedChildRefreshRef.current = null;
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
}, [sessionId, workspaceId]);
|
|
1678
|
+
const refreshAfterChildCreate = useCallback6(() => {
|
|
1679
|
+
void refresh();
|
|
1680
|
+
if (delayedChildRefreshRef.current !== null) {
|
|
1681
|
+
clearTimeout(delayedChildRefreshRef.current);
|
|
1682
|
+
}
|
|
1683
|
+
delayedChildRefreshRef.current = setTimeout(() => {
|
|
1684
|
+
delayedChildRefreshRef.current = null;
|
|
1685
|
+
void refresh();
|
|
1686
|
+
}, 2500);
|
|
1687
|
+
}, [refresh]);
|
|
1688
|
+
useSessionEventTrigger(
|
|
1689
|
+
client,
|
|
1690
|
+
workspaceId,
|
|
1691
|
+
sessionId,
|
|
1692
|
+
isLineageRefreshEvent,
|
|
1693
|
+
refreshSoon,
|
|
1694
|
+
// SHARED-FEED ONLY: without a caller-provided events log the trigger would
|
|
1695
|
+
// open its OWN streamEvents tail — a second live SSE connection next to the
|
|
1696
|
+
// session route's useSessionEvents. A caller with no feed opts into polling
|
|
1697
|
+
// (pollIntervalMs), never a duplicate stream.
|
|
1698
|
+
{ events: options.events, enabled: enabled && options.events !== void 0 }
|
|
1699
|
+
);
|
|
1700
|
+
useSessionEventTrigger(
|
|
1701
|
+
client,
|
|
1702
|
+
workspaceId,
|
|
1703
|
+
sessionId,
|
|
1704
|
+
isSessionCreateToolCallCreated,
|
|
1705
|
+
refreshAfterChildCreate,
|
|
1706
|
+
{ events: options.events, enabled: enabled && options.events !== void 0 }
|
|
1707
|
+
);
|
|
1708
|
+
return {
|
|
1709
|
+
lineage: state.data,
|
|
1710
|
+
loading: state.loading,
|
|
1711
|
+
error: state.error,
|
|
1712
|
+
refresh
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1367
1716
|
// src/hooks/use-session-control.ts
|
|
1368
|
-
import { useCallback as
|
|
1717
|
+
import { useCallback as useCallback7, useLayoutEffect as useLayoutEffect2, useRef as useRef6 } from "react";
|
|
1369
1718
|
function useSessionControl(sessionId, options = {}) {
|
|
1370
1719
|
const { client, workspaceId } = useEmbeddedSession(options);
|
|
1371
1720
|
const approvalTargetKey = `${workspaceId}\0${sessionId ?? ""}`;
|
|
1372
|
-
const pendingApproval =
|
|
1721
|
+
const pendingApproval = useRef6(null);
|
|
1373
1722
|
useLayoutEffect2(() => {
|
|
1374
1723
|
if (pendingApproval.current?.targetKey !== approvalTargetKey) {
|
|
1375
1724
|
pendingApproval.current = null;
|
|
@@ -1387,7 +1736,7 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
1387
1736
|
mutationError: approvalError,
|
|
1388
1737
|
clearMutationError: clearApprovalError
|
|
1389
1738
|
} = useMutationRunner(approvalTargetKey);
|
|
1390
|
-
const pause =
|
|
1739
|
+
const pause = useCallback7(
|
|
1391
1740
|
async (reason) => {
|
|
1392
1741
|
if (!sessionId) {
|
|
1393
1742
|
return null;
|
|
@@ -1398,7 +1747,7 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
1398
1747
|
},
|
|
1399
1748
|
[client, workspaceId, sessionId, runControl]
|
|
1400
1749
|
);
|
|
1401
|
-
const resume =
|
|
1750
|
+
const resume = useCallback7(
|
|
1402
1751
|
async (reason) => {
|
|
1403
1752
|
if (!sessionId) return null;
|
|
1404
1753
|
return await runControl(
|
|
@@ -1407,7 +1756,7 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
1407
1756
|
},
|
|
1408
1757
|
[client, workspaceId, sessionId, runControl]
|
|
1409
1758
|
);
|
|
1410
|
-
const decide =
|
|
1759
|
+
const decide = useCallback7(
|
|
1411
1760
|
async (approvalId, decision, message) => {
|
|
1412
1761
|
if (!sessionId) {
|
|
1413
1762
|
return null;
|
|
@@ -1436,16 +1785,16 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
1436
1785
|
},
|
|
1437
1786
|
[approvalTargetKey, client, workspaceId, sessionId, runApproval]
|
|
1438
1787
|
);
|
|
1439
|
-
const approve =
|
|
1788
|
+
const approve = useCallback7(
|
|
1440
1789
|
async (approvalId, message) => await decide(approvalId, "approve", message),
|
|
1441
1790
|
[decide]
|
|
1442
1791
|
);
|
|
1443
|
-
const reject =
|
|
1792
|
+
const reject = useCallback7(
|
|
1444
1793
|
async (approvalId, message) => await decide(approvalId, "reject", message),
|
|
1445
1794
|
[decide]
|
|
1446
1795
|
);
|
|
1447
1796
|
const error = approvalError ?? controlError;
|
|
1448
|
-
const clearError =
|
|
1797
|
+
const clearError = useCallback7(() => {
|
|
1449
1798
|
clearControlError();
|
|
1450
1799
|
clearApprovalError();
|
|
1451
1800
|
}, [clearControlError, clearApprovalError]);
|
|
@@ -1462,7 +1811,7 @@ function useSessionControl(sessionId, options = {}) {
|
|
|
1462
1811
|
}
|
|
1463
1812
|
|
|
1464
1813
|
// src/hooks/use-session-mcp-approval-policy.ts
|
|
1465
|
-
import { useCallback as
|
|
1814
|
+
import { useCallback as useCallback8, useEffect as useEffect6, useLayoutEffect as useLayoutEffect3, useMemo as useMemo4, useRef as useRef7, useState as useState6 } from "react";
|
|
1466
1815
|
function isSessionMcpApprovalPolicyEvent(event, serverId) {
|
|
1467
1816
|
if (event.type !== "session.mcp.approval_policy.updated") {
|
|
1468
1817
|
return false;
|
|
@@ -1478,14 +1827,14 @@ function useSessionMcpApprovalPolicy(sessionId, serverId, options = {}) {
|
|
|
1478
1827
|
const enabled = (options.enabled ?? true) && Boolean(sessionId && serverId);
|
|
1479
1828
|
const [override, setOverride] = useState6(null);
|
|
1480
1829
|
const targetKey = `${workspaceId}\0${sessionId ?? ""}\0${serverId ?? ""}`;
|
|
1481
|
-
const authoritativeGeneration =
|
|
1830
|
+
const authoritativeGeneration = useRef7(0);
|
|
1482
1831
|
const mutationIdentity = useMemo4(() => ({ client, targetKey }), [client, targetKey]);
|
|
1483
1832
|
const { run, mutating, mutationError, clearMutationError } = useMutationRunner(mutationIdentity);
|
|
1484
1833
|
useLayoutEffect3(() => {
|
|
1485
1834
|
authoritativeGeneration.current += 1;
|
|
1486
1835
|
setOverride(null);
|
|
1487
1836
|
}, [client, targetKey]);
|
|
1488
|
-
const load =
|
|
1837
|
+
const load = useCallback8(async () => {
|
|
1489
1838
|
const generation = authoritativeGeneration.current;
|
|
1490
1839
|
if (!sessionId || !serverId) {
|
|
1491
1840
|
return { targetKey, generation, server: null };
|
|
@@ -1506,13 +1855,13 @@ function useSessionMcpApprovalPolicy(sessionId, serverId, options = {}) {
|
|
|
1506
1855
|
enabled,
|
|
1507
1856
|
pollIntervalMs: options.pollIntervalMs
|
|
1508
1857
|
});
|
|
1509
|
-
|
|
1858
|
+
useEffect6(() => {
|
|
1510
1859
|
if (data?.targetKey === targetKey && data.generation === authoritativeGeneration.current) {
|
|
1511
1860
|
setOverride(null);
|
|
1512
1861
|
}
|
|
1513
1862
|
}, [data, targetKey]);
|
|
1514
1863
|
const scheduleRefresh = useDebouncedCallback(() => void refresh());
|
|
1515
|
-
const matchesPolicyEvent =
|
|
1864
|
+
const matchesPolicyEvent = useCallback8(
|
|
1516
1865
|
(event) => isSessionMcpApprovalPolicyEvent(event, serverId ?? void 0),
|
|
1517
1866
|
[serverId]
|
|
1518
1867
|
);
|
|
@@ -1528,7 +1877,7 @@ function useSessionMcpApprovalPolicy(sessionId, serverId, options = {}) {
|
|
|
1528
1877
|
},
|
|
1529
1878
|
async () => await refresh()
|
|
1530
1879
|
);
|
|
1531
|
-
const update =
|
|
1880
|
+
const update = useCallback8(
|
|
1532
1881
|
async (policy) => {
|
|
1533
1882
|
if (!sessionId || !serverId) {
|
|
1534
1883
|
return null;
|
|
@@ -1562,91 +1911,6 @@ function useSessionMcpApprovalPolicy(sessionId, serverId, options = {}) {
|
|
|
1562
1911
|
};
|
|
1563
1912
|
}
|
|
1564
1913
|
|
|
1565
|
-
// src/hooks/use-session-lineage.ts
|
|
1566
|
-
import { useCallback as useCallback8, useEffect as useEffect6, useRef as useRef7 } from "react";
|
|
1567
|
-
function isLineageRefreshEvent(event) {
|
|
1568
|
-
if (event.type === "session.status.changed" || event.type === "session.created") {
|
|
1569
|
-
return true;
|
|
1570
|
-
}
|
|
1571
|
-
if (event.type === "agent.toolCall.output") {
|
|
1572
|
-
const payload = event.payload;
|
|
1573
|
-
const name = typeof payload?.name === "string" ? payload.name : typeof payload?.toolName === "string" ? payload.toolName : "";
|
|
1574
|
-
return name === "session_create" || name.endsWith("__session_create");
|
|
1575
|
-
}
|
|
1576
|
-
return false;
|
|
1577
|
-
}
|
|
1578
|
-
function isSessionCreateToolCallCreated(event) {
|
|
1579
|
-
if (event.type !== "agent.toolCall.created") {
|
|
1580
|
-
return false;
|
|
1581
|
-
}
|
|
1582
|
-
const payload = event.payload;
|
|
1583
|
-
const name = typeof payload?.name === "string" ? payload.name : typeof payload?.toolName === "string" ? payload.toolName : "";
|
|
1584
|
-
return name === "session_create" || name.endsWith("__session_create");
|
|
1585
|
-
}
|
|
1586
|
-
function useSessionLineage(sessionId, options = {}) {
|
|
1587
|
-
const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } = useEmbeddedSessionLineage(options);
|
|
1588
|
-
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
1589
|
-
const load = useCallback8(
|
|
1590
|
-
async () => sessionId ? await client.getSessionLineage(workspaceId, sessionId) : { ancestors: [], children: [], truncated: false },
|
|
1591
|
-
[client, workspaceId, sessionId]
|
|
1592
|
-
);
|
|
1593
|
-
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });
|
|
1594
|
-
const refresh = state.refresh;
|
|
1595
|
-
useEffect6(() => {
|
|
1596
|
-
if (enabled && workspaceControlEvent) void refresh();
|
|
1597
|
-
}, [enabled, refresh, workspaceControlEvent]);
|
|
1598
|
-
useEffect6(() => {
|
|
1599
|
-
if (!sessionId || !enabled) return;
|
|
1600
|
-
return registerSessionReconciler(sessionId, "lineage", refresh);
|
|
1601
|
-
}, [enabled, refresh, registerSessionReconciler, sessionId]);
|
|
1602
|
-
const refreshSoon = useDebouncedCallback(() => void refresh(), 150);
|
|
1603
|
-
const delayedChildRefreshRef = useRef7(null);
|
|
1604
|
-
useEffect6(() => {
|
|
1605
|
-
return () => {
|
|
1606
|
-
if (delayedChildRefreshRef.current !== null) {
|
|
1607
|
-
clearTimeout(delayedChildRefreshRef.current);
|
|
1608
|
-
delayedChildRefreshRef.current = null;
|
|
1609
|
-
}
|
|
1610
|
-
};
|
|
1611
|
-
}, [sessionId, workspaceId]);
|
|
1612
|
-
const refreshAfterChildCreate = useCallback8(() => {
|
|
1613
|
-
void refresh();
|
|
1614
|
-
if (delayedChildRefreshRef.current !== null) {
|
|
1615
|
-
clearTimeout(delayedChildRefreshRef.current);
|
|
1616
|
-
}
|
|
1617
|
-
delayedChildRefreshRef.current = setTimeout(() => {
|
|
1618
|
-
delayedChildRefreshRef.current = null;
|
|
1619
|
-
void refresh();
|
|
1620
|
-
}, 2500);
|
|
1621
|
-
}, [refresh]);
|
|
1622
|
-
useSessionEventTrigger(
|
|
1623
|
-
client,
|
|
1624
|
-
workspaceId,
|
|
1625
|
-
sessionId,
|
|
1626
|
-
isLineageRefreshEvent,
|
|
1627
|
-
refreshSoon,
|
|
1628
|
-
// SHARED-FEED ONLY: without a caller-provided events log the trigger would
|
|
1629
|
-
// open its OWN streamEvents tail — a second live SSE connection next to the
|
|
1630
|
-
// session route's useSessionEvents. A caller with no feed opts into polling
|
|
1631
|
-
// (pollIntervalMs), never a duplicate stream.
|
|
1632
|
-
{ events: options.events, enabled: enabled && options.events !== void 0 }
|
|
1633
|
-
);
|
|
1634
|
-
useSessionEventTrigger(
|
|
1635
|
-
client,
|
|
1636
|
-
workspaceId,
|
|
1637
|
-
sessionId,
|
|
1638
|
-
isSessionCreateToolCallCreated,
|
|
1639
|
-
refreshAfterChildCreate,
|
|
1640
|
-
{ events: options.events, enabled: enabled && options.events !== void 0 }
|
|
1641
|
-
);
|
|
1642
|
-
return {
|
|
1643
|
-
lineage: state.data,
|
|
1644
|
-
loading: state.loading,
|
|
1645
|
-
error: state.error,
|
|
1646
|
-
refresh
|
|
1647
|
-
};
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
1914
|
// src/approvals.ts
|
|
1651
1915
|
function approvalsFromRequiresAction(payload) {
|
|
1652
1916
|
const approvals = payload && typeof payload === "object" ? payload.approvals : void 0;
|
|
@@ -1823,11 +2087,11 @@ export {
|
|
|
1823
2087
|
useTurnQueue,
|
|
1824
2088
|
isGoalEvent,
|
|
1825
2089
|
useGoal,
|
|
2090
|
+
isLineageRefreshEvent,
|
|
2091
|
+
useSessionLineage,
|
|
1826
2092
|
useSessionControl,
|
|
1827
2093
|
isSessionMcpApprovalPolicyEvent,
|
|
1828
2094
|
useSessionMcpApprovalPolicy,
|
|
1829
|
-
isLineageRefreshEvent,
|
|
1830
|
-
useSessionLineage,
|
|
1831
2095
|
approvalsFromRequiresAction,
|
|
1832
2096
|
projectPendingApprovals,
|
|
1833
2097
|
humanInputRequestFromEvent,
|
|
@@ -1835,4 +2099,4 @@ export {
|
|
|
1835
2099
|
isHumanInputEvent,
|
|
1836
2100
|
useHumanInputRequests
|
|
1837
2101
|
};
|
|
1838
|
-
//# sourceMappingURL=chunk-
|
|
2102
|
+
//# sourceMappingURL=chunk-A2WITZTI.js.map
|