@opengeni/react 3.0.0-canary.0 → 3.3.2-canary.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.
- package/dist/accounts.js +87 -11
- package/dist/accounts.js.map +1 -1
- package/dist/{browser-viewer-AEFHUYZK.js → browser-viewer-MKKFRRRV.js} +3 -3
- package/dist/{chunk-W6NFJXSA.js → chunk-2DZVYHVO.js} +20 -4
- package/dist/chunk-2DZVYHVO.js.map +1 -0
- package/dist/{chunk-YJFGAFBD.js → chunk-3AGBGTRT.js} +226 -95
- package/dist/chunk-3AGBGTRT.js.map +1 -0
- package/dist/{chunk-YFKJ7VZH.js → chunk-7EAFGICR.js} +45 -11
- package/dist/chunk-7EAFGICR.js.map +1 -0
- package/dist/{chunk-MZ2G2XBA.js → chunk-IOLVN74D.js} +31 -4
- package/dist/chunk-IOLVN74D.js.map +1 -0
- package/dist/{chunk-D3UIAJKY.js → chunk-JAQ5K7W6.js} +3 -2
- package/dist/{chunk-D3UIAJKY.js.map → chunk-JAQ5K7W6.js.map} +1 -1
- package/dist/{chunk-LAKLF4PA.js → chunk-VTOREEXF.js} +8 -7
- package/dist/chunk-VTOREEXF.js.map +1 -0
- package/dist/{chunk-RGALCTWO.js → chunk-XYRDDSXF.js} +4 -4
- package/dist/{chunk-HQVCKCLG.js → chunk-YG4QEQF5.js} +354 -255
- package/dist/chunk-YG4QEQF5.js.map +1 -0
- package/dist/{chunk-XXWH2JLC.js → chunk-YVCHAQZY.js} +2 -2
- package/dist/{chunk-OAM4WAAM.js → chunk-ZPBTI3TE.js} +2 -2
- package/dist/components/fleet-tile.d.ts +2 -2
- package/dist/components/model-policy-picker.d.ts +9 -0
- package/dist/components/tip-follow.d.ts +16 -0
- package/dist/composer.js +5 -5
- package/dist/hooks/use-session-events.d.ts +3 -3
- package/dist/index.js +76 -68
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +2 -2
- package/dist/machines.js +2 -2
- package/dist/realtime.js +46 -7
- package/dist/realtime.js.map +1 -1
- package/dist/session-ui.js +4 -4
- package/dist/session.js +4 -4
- package/dist/timeline/entrance.d.ts +13 -1
- package/package.json +3 -2
- package/src/accounts.tsx +116 -14
- package/src/components/fleet-tile.tsx +4 -15
- package/src/components/message-timeline.tsx +237 -101
- package/src/components/model-policy-picker.tsx +24 -3
- package/src/components/tip-follow.ts +52 -0
- package/src/components/tooltip.tsx +38 -5
- package/src/hooks/use-available-models.ts +20 -14
- package/src/hooks/use-composer.ts +49 -3
- package/src/hooks/use-goal.ts +31 -7
- package/src/hooks/use-last-started-turn-policy.ts +11 -5
- package/src/hooks/use-session-events.ts +186 -61
- package/src/hooks/use-session-lineage.ts +20 -16
- package/src/hooks/use-session.ts +23 -19
- package/src/hooks/use-workspace-sessions.ts +31 -27
- package/src/lib/format.ts +8 -6
- package/src/realtime/realtime-control.tsx +55 -6
- package/src/timeline/entrance.tsx +28 -3
- package/src/timeline/projection.ts +4 -0
- package/dist/chunk-HQVCKCLG.js.map +0 -1
- package/dist/chunk-LAKLF4PA.js.map +0 -1
- package/dist/chunk-MZ2G2XBA.js.map +0 -1
- package/dist/chunk-W6NFJXSA.js.map +0 -1
- package/dist/chunk-YFKJ7VZH.js.map +0 -1
- package/dist/chunk-YJFGAFBD.js.map +0 -1
- /package/dist/{browser-viewer-AEFHUYZK.js.map → browser-viewer-MKKFRRRV.js.map} +0 -0
- /package/dist/{chunk-RGALCTWO.js.map → chunk-XYRDDSXF.js.map} +0 -0
- /package/dist/{chunk-XXWH2JLC.js.map → chunk-YVCHAQZY.js.map} +0 -0
- /package/dist/{chunk-OAM4WAAM.js.map → chunk-ZPBTI3TE.js.map} +0 -0
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
groupTimeline,
|
|
5
5
|
isActionableHumanInputRequest,
|
|
6
6
|
sessionStatusFromEvents
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JAQ5K7W6.js";
|
|
8
8
|
import {
|
|
9
9
|
useDebouncedCallback,
|
|
10
10
|
useMutationRunner,
|
|
@@ -102,24 +102,28 @@ function useSession(sessionId, options = {}) {
|
|
|
102
102
|
const nextReadGeneration = useRef(0);
|
|
103
103
|
const beginRead = options.beginRead;
|
|
104
104
|
const { run, mutating, mutationError, clearMutationError } = useMutationRunner();
|
|
105
|
-
const load = useCallback(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
let readGeneration2 = 0;
|
|
110
|
-
const fetched = await client.getSession(workspaceId, sessionId, {
|
|
111
|
-
fresh: true,
|
|
112
|
-
onRequestStart: () => {
|
|
113
|
-
readGeneration2 = beginRead?.() ?? ++nextReadGeneration.current;
|
|
105
|
+
const load = useCallback(
|
|
106
|
+
async (signal) => {
|
|
107
|
+
if (!sessionId) {
|
|
108
|
+
return null;
|
|
114
109
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
110
|
+
let readGeneration2 = 0;
|
|
111
|
+
const fetched = await client.getSession(workspaceId, sessionId, {
|
|
112
|
+
fresh: true,
|
|
113
|
+
signal,
|
|
114
|
+
onRequestStart: () => {
|
|
115
|
+
readGeneration2 = beginRead?.() ?? ++nextReadGeneration.current;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
setOverride(null);
|
|
119
|
+
return {
|
|
120
|
+
session: fetched,
|
|
121
|
+
revision: ++nextReadRevision.current,
|
|
122
|
+
readGeneration: readGeneration2
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
[beginRead, client, workspaceId, sessionId]
|
|
126
|
+
);
|
|
123
127
|
const { data, loading, error, refresh } = usePolledValue(load, {
|
|
124
128
|
pollIntervalMs: options.pollIntervalMs,
|
|
125
129
|
enabled
|
|
@@ -188,7 +192,7 @@ function useSession(sessionId, options = {}) {
|
|
|
188
192
|
}
|
|
189
193
|
|
|
190
194
|
// src/hooks/use-session-events.ts
|
|
191
|
-
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
195
|
+
import { startTransition, useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
192
196
|
var INITIAL_TAIL_PAGE_SIZE = 1e3;
|
|
193
197
|
var OLDER_PAGE_SIZE = 5e3;
|
|
194
198
|
var NEWER_PAGE_SIZE = 5e3;
|
|
@@ -357,7 +361,10 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
357
361
|
batchResumeSequence
|
|
358
362
|
);
|
|
359
363
|
}
|
|
360
|
-
observeSessionStatus(batch, sessionStatusRef
|
|
364
|
+
const status = observeSessionStatus(batch, sessionStatusRef);
|
|
365
|
+
if (status !== void 0) {
|
|
366
|
+
setSessionStatusProjection(status);
|
|
367
|
+
}
|
|
361
368
|
const current = eventWindowRef.current;
|
|
362
369
|
const next = boundBrowserSessionEventWindow([...current.events, ...batch]);
|
|
363
370
|
const retained = {
|
|
@@ -367,7 +374,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
367
374
|
eventWindowRef.current = retained;
|
|
368
375
|
setEventWindow(retained);
|
|
369
376
|
oldestSequenceRef.current = retained.events[0]?.sequence ?? null;
|
|
370
|
-
newestSequenceRef.current = retained.events
|
|
377
|
+
newestSequenceRef.current = maxResumeSequenceOrNull(retained.events);
|
|
371
378
|
if (retained.truncated) {
|
|
372
379
|
hasOlderRef.current = true;
|
|
373
380
|
setHasOlder(true);
|
|
@@ -391,17 +398,20 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
391
398
|
if (!isCurrent()) {
|
|
392
399
|
return;
|
|
393
400
|
}
|
|
394
|
-
observeSessionStatus(window.events, sessionStatusRef
|
|
401
|
+
const status = observeSessionStatus(window.events, sessionStatusRef);
|
|
395
402
|
const retained = boundBrowserSessionEventWindow(window.events);
|
|
396
403
|
eventWindowRef.current = retained;
|
|
397
|
-
setEventWindow(retained);
|
|
398
404
|
oldestSequenceRef.current = retained.events[0]?.sequence ?? window.oldestSequence;
|
|
399
|
-
newestSequenceRef.current = retained.events
|
|
405
|
+
newestSequenceRef.current = maxResumeSequenceOrNull(retained.events) ?? window.newestSequence;
|
|
400
406
|
hasOlderRef.current = window.hasOlder || retained.truncated;
|
|
401
407
|
hasNewerRef.current = false;
|
|
402
408
|
lastSequenceRef.current = window.newestSequence;
|
|
403
409
|
streamResumeSequenceRef.current = window.newestSequence;
|
|
404
410
|
initialWindowLoadedRef.current = true;
|
|
411
|
+
if (status !== void 0) {
|
|
412
|
+
setSessionStatusProjection(status);
|
|
413
|
+
}
|
|
414
|
+
setEventWindow(retained);
|
|
405
415
|
setHasOlder(window.hasOlder || retained.truncated);
|
|
406
416
|
setHasNewer(false);
|
|
407
417
|
setInitialLoading(false);
|
|
@@ -450,6 +460,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
450
460
|
flush();
|
|
451
461
|
setError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
452
462
|
setConnectionState("error");
|
|
463
|
+
setInitialLoading(false);
|
|
453
464
|
}
|
|
454
465
|
}
|
|
455
466
|
})();
|
|
@@ -493,6 +504,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
493
504
|
const generation = generationRef.current;
|
|
494
505
|
loadingOlderRef.current = true;
|
|
495
506
|
setLoadingOlder(true);
|
|
507
|
+
let published = false;
|
|
496
508
|
try {
|
|
497
509
|
const window = await loadEventWindow(client, workspaceId, sessionId, {
|
|
498
510
|
before,
|
|
@@ -512,7 +524,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
512
524
|
const current = eventWindowRef.current;
|
|
513
525
|
assertPrependOrder(current.events, window.events);
|
|
514
526
|
streamAbortRef.current?.abort();
|
|
515
|
-
observeSessionStatus(window.events, sessionStatusRef
|
|
527
|
+
const status = observeSessionStatus(window.events, sessionStatusRef);
|
|
516
528
|
const next = boundBrowserSessionEventWindow([...window.events, ...current.events], {
|
|
517
529
|
direction: "oldest"
|
|
518
530
|
});
|
|
@@ -524,28 +536,54 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
524
536
|
if (retainedOldest === null || retainedOldest >= before) {
|
|
525
537
|
throw new Error("@opengeni/react: loadOlder made no durable sequence progress");
|
|
526
538
|
}
|
|
527
|
-
const retainedNewest = retained.events
|
|
539
|
+
const retainedNewest = maxResumeSequenceOrNull(retained.events);
|
|
540
|
+
const previousNewest = maxResumeSequenceOrNull(current.events);
|
|
528
541
|
eventWindowRef.current = retained;
|
|
529
542
|
markCommitted();
|
|
530
|
-
setEventWindow(retained);
|
|
531
543
|
oldestSequenceRef.current = retainedOldest;
|
|
532
544
|
newestSequenceRef.current = retainedNewest;
|
|
533
545
|
streamResumeSequenceRef.current = maxResumeSequence(retained.events);
|
|
534
546
|
const olderStillAvailable = window.hasOlder;
|
|
535
547
|
hasOlderRef.current = olderStillAvailable;
|
|
536
|
-
|
|
537
|
-
|
|
548
|
+
const evictedLiveTail = previousNewest !== null && retainedNewest !== null && retainedNewest < previousNewest;
|
|
549
|
+
let newer = null;
|
|
550
|
+
let enterHistory = false;
|
|
551
|
+
let reconnectLive = false;
|
|
552
|
+
if (viewModeRef.current === "history" || evictedLiveTail) {
|
|
538
553
|
const highWater = lastSequenceRef.current;
|
|
539
|
-
|
|
554
|
+
newer = retainedNewest !== null && (retainedNewest < highWater || retained.truncated);
|
|
540
555
|
hasNewerRef.current = newer;
|
|
541
|
-
|
|
556
|
+
if (evictedLiveTail) {
|
|
557
|
+
viewModeRef.current = "history";
|
|
558
|
+
enterHistory = true;
|
|
559
|
+
}
|
|
542
560
|
} else {
|
|
543
|
-
|
|
561
|
+
reconnectLive = true;
|
|
544
562
|
}
|
|
563
|
+
loadingOlderRef.current = false;
|
|
564
|
+
startTransition(() => {
|
|
565
|
+
if (status !== void 0) {
|
|
566
|
+
setSessionStatusProjection(status);
|
|
567
|
+
}
|
|
568
|
+
setEventWindow(retained);
|
|
569
|
+
setHasOlder(olderStillAvailable);
|
|
570
|
+
if (newer !== null) {
|
|
571
|
+
setHasNewer(newer);
|
|
572
|
+
}
|
|
573
|
+
if (enterHistory) {
|
|
574
|
+
setViewMode("history");
|
|
575
|
+
} else if (reconnectLive) {
|
|
576
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
577
|
+
}
|
|
578
|
+
setLoadingOlder(false);
|
|
579
|
+
});
|
|
580
|
+
published = true;
|
|
545
581
|
return olderStillAvailable;
|
|
546
582
|
} finally {
|
|
547
|
-
|
|
548
|
-
|
|
583
|
+
if (!published) {
|
|
584
|
+
loadingOlderRef.current = false;
|
|
585
|
+
setLoadingOlder(false);
|
|
586
|
+
}
|
|
549
587
|
}
|
|
550
588
|
}),
|
|
551
589
|
[client, workspaceId, sessionId]
|
|
@@ -557,6 +595,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
557
595
|
const generation = generationRef.current;
|
|
558
596
|
loadingOldestRef.current = true;
|
|
559
597
|
setLoadingOldest(true);
|
|
598
|
+
let published = false;
|
|
560
599
|
try {
|
|
561
600
|
const window = await loadForwardEventWindow(client, workspaceId, sessionId, {
|
|
562
601
|
after: 0,
|
|
@@ -573,28 +612,38 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
573
612
|
return false;
|
|
574
613
|
}
|
|
575
614
|
streamAbortRef.current?.abort();
|
|
576
|
-
observeSessionStatus(window.events, sessionStatusRef
|
|
615
|
+
const status = observeSessionStatus(window.events, sessionStatusRef);
|
|
577
616
|
const retained = boundBrowserSessionEventWindow(window.events, { direction: "oldest" });
|
|
578
617
|
const retainedOldest = retained.events[0]?.sequence ?? null;
|
|
579
|
-
const retainedNewest = retained.events
|
|
618
|
+
const retainedNewest = maxResumeSequenceOrNull(retained.events);
|
|
580
619
|
eventWindowRef.current = retained;
|
|
581
|
-
setEventWindow(retained);
|
|
582
620
|
oldestSequenceRef.current = retainedOldest;
|
|
583
621
|
newestSequenceRef.current = retainedNewest;
|
|
584
622
|
hasOlderRef.current = false;
|
|
585
|
-
setHasOlder(false);
|
|
586
623
|
const highWater = Math.max(lastSequenceRef.current, retainedNewest ?? 0);
|
|
587
624
|
lastSequenceRef.current = highWater;
|
|
588
625
|
const newer = window.hasNewer || retained.truncated || retainedNewest !== null && retainedNewest < highWater;
|
|
589
626
|
hasNewerRef.current = newer;
|
|
590
|
-
setHasNewer(newer);
|
|
591
627
|
initialWindowLoadedRef.current = true;
|
|
592
628
|
viewModeRef.current = "history";
|
|
593
|
-
|
|
629
|
+
loadingOldestRef.current = false;
|
|
630
|
+
startTransition(() => {
|
|
631
|
+
if (status !== void 0) {
|
|
632
|
+
setSessionStatusProjection(status);
|
|
633
|
+
}
|
|
634
|
+
setEventWindow(retained);
|
|
635
|
+
setHasOlder(false);
|
|
636
|
+
setHasNewer(newer);
|
|
637
|
+
setViewMode("history");
|
|
638
|
+
setLoadingOldest(false);
|
|
639
|
+
});
|
|
640
|
+
published = true;
|
|
594
641
|
return newer;
|
|
595
642
|
} finally {
|
|
596
|
-
|
|
597
|
-
|
|
643
|
+
if (!published) {
|
|
644
|
+
loadingOldestRef.current = false;
|
|
645
|
+
setLoadingOldest(false);
|
|
646
|
+
}
|
|
598
647
|
}
|
|
599
648
|
}, [client, workspaceId, sessionId]);
|
|
600
649
|
const loadNewer = useCallback2(async () => {
|
|
@@ -610,6 +659,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
610
659
|
const generation = generationRef.current;
|
|
611
660
|
loadingNewerRef.current = true;
|
|
612
661
|
setLoadingNewer(true);
|
|
662
|
+
let published = false;
|
|
613
663
|
try {
|
|
614
664
|
const window = await loadForwardEventWindow(client, workspaceId, sessionId, {
|
|
615
665
|
after: afterSequence,
|
|
@@ -631,7 +681,7 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
631
681
|
}
|
|
632
682
|
const current = eventWindowRef.current;
|
|
633
683
|
assertAppendOrder(current.events, window.events);
|
|
634
|
-
observeSessionStatus(window.events, sessionStatusRef
|
|
684
|
+
const status = observeSessionStatus(window.events, sessionStatusRef);
|
|
635
685
|
const previousOldest = current.events[0]?.sequence ?? null;
|
|
636
686
|
const next = boundBrowserSessionEventWindow([...current.events, ...window.events], {
|
|
637
687
|
direction: "newest"
|
|
@@ -641,33 +691,48 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
641
691
|
truncated: current.truncated || next.truncated || window.hasNewer
|
|
642
692
|
};
|
|
643
693
|
const retainedOldest = retained.events[0]?.sequence ?? null;
|
|
644
|
-
const retainedNewest = retained.events
|
|
694
|
+
const retainedNewest = maxResumeSequenceOrNull(retained.events);
|
|
645
695
|
if (retainedNewest === null || retainedNewest <= afterSequence) {
|
|
646
696
|
throw new Error("@opengeni/react: loadNewer made no durable sequence progress");
|
|
647
697
|
}
|
|
648
698
|
eventWindowRef.current = retained;
|
|
649
|
-
setEventWindow(retained);
|
|
650
699
|
oldestSequenceRef.current = retainedOldest;
|
|
651
700
|
newestSequenceRef.current = retainedNewest;
|
|
652
701
|
if (retainedOldest !== null && (previousOldest === null || retainedOldest > previousOldest || retained.truncated && retained.events[0]?.type !== "session.created" && retainedOldest > 1)) {
|
|
653
702
|
hasOlderRef.current = true;
|
|
654
|
-
setHasOlder(true);
|
|
655
703
|
}
|
|
704
|
+
const rearmedOlder = hasOlderRef.current;
|
|
656
705
|
const highWater = Math.max(lastSequenceRef.current, retainedNewest);
|
|
657
706
|
lastSequenceRef.current = highWater;
|
|
658
707
|
const newer = window.hasNewer || retainedNewest < highWater;
|
|
659
708
|
hasNewerRef.current = newer;
|
|
660
|
-
|
|
709
|
+
let resumeLive = false;
|
|
661
710
|
if (!newer) {
|
|
662
711
|
streamResumeSequenceRef.current = retainedNewest;
|
|
663
712
|
viewModeRef.current = "live";
|
|
664
|
-
|
|
665
|
-
setStreamEpoch((epoch) => epoch + 1);
|
|
713
|
+
resumeLive = true;
|
|
666
714
|
}
|
|
715
|
+
loadingNewerRef.current = false;
|
|
716
|
+
startTransition(() => {
|
|
717
|
+
if (status !== void 0) {
|
|
718
|
+
setSessionStatusProjection(status);
|
|
719
|
+
}
|
|
720
|
+
setEventWindow(retained);
|
|
721
|
+
setHasOlder(rearmedOlder);
|
|
722
|
+
setHasNewer(newer);
|
|
723
|
+
if (resumeLive) {
|
|
724
|
+
setViewMode("live");
|
|
725
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
726
|
+
}
|
|
727
|
+
setLoadingNewer(false);
|
|
728
|
+
});
|
|
729
|
+
published = true;
|
|
667
730
|
return newer;
|
|
668
731
|
} finally {
|
|
669
|
-
|
|
670
|
-
|
|
732
|
+
if (!published) {
|
|
733
|
+
loadingNewerRef.current = false;
|
|
734
|
+
setLoadingNewer(false);
|
|
735
|
+
}
|
|
671
736
|
}
|
|
672
737
|
}, [client, workspaceId, sessionId]);
|
|
673
738
|
const jumpToLatest = useCallback2(async () => {
|
|
@@ -676,26 +741,34 @@ function useSessionEvents(sessionId, options = {}) {
|
|
|
676
741
|
}
|
|
677
742
|
loadingLatestRef.current = true;
|
|
678
743
|
setLoadingLatest(true);
|
|
744
|
+
let published = false;
|
|
679
745
|
try {
|
|
680
746
|
streamAbortRef.current?.abort();
|
|
681
747
|
hasNewerRef.current = false;
|
|
682
|
-
setHasNewer(false);
|
|
683
748
|
hasOlderRef.current = false;
|
|
684
|
-
setHasOlder(false);
|
|
685
749
|
newestSequenceRef.current = null;
|
|
686
750
|
oldestSequenceRef.current = null;
|
|
687
751
|
eventWindowRef.current = EMPTY_EVENT_WINDOW;
|
|
688
|
-
setEventWindow(EMPTY_EVENT_WINDOW);
|
|
689
752
|
initialWindowLoadedRef.current = false;
|
|
690
753
|
streamResumeSequenceRef.current = after;
|
|
691
|
-
setInitialLoading(true);
|
|
692
754
|
viewModeRef.current = "live";
|
|
693
|
-
|
|
694
|
-
|
|
755
|
+
loadingLatestRef.current = false;
|
|
756
|
+
startTransition(() => {
|
|
757
|
+
setHasNewer(false);
|
|
758
|
+
setHasOlder(false);
|
|
759
|
+
setEventWindow(EMPTY_EVENT_WINDOW);
|
|
760
|
+
setInitialLoading(true);
|
|
761
|
+
setViewMode("live");
|
|
762
|
+
setStreamEpoch((epoch) => epoch + 1);
|
|
763
|
+
setLoadingLatest(false);
|
|
764
|
+
});
|
|
765
|
+
published = true;
|
|
695
766
|
await Promise.resolve();
|
|
696
767
|
} finally {
|
|
697
|
-
|
|
698
|
-
|
|
768
|
+
if (!published) {
|
|
769
|
+
loadingLatestRef.current = false;
|
|
770
|
+
setLoadingLatest(false);
|
|
771
|
+
}
|
|
699
772
|
}
|
|
700
773
|
}, [after, sessionId]);
|
|
701
774
|
const identityMatches = stateStreamKey === streamKey;
|
|
@@ -925,7 +998,7 @@ function browserUtf8Bytes(value) {
|
|
|
925
998
|
function isBrowserUtf8Continuation(value) {
|
|
926
999
|
return (value & 192) === 128;
|
|
927
1000
|
}
|
|
928
|
-
function observeSessionStatus(events, ref
|
|
1001
|
+
function observeSessionStatus(events, ref) {
|
|
929
1002
|
let latest = null;
|
|
930
1003
|
for (const event of events) {
|
|
931
1004
|
const status = sessionStatusFromEvents([event]);
|
|
@@ -933,9 +1006,9 @@ function observeSessionStatus(events, ref, setStatus) {
|
|
|
933
1006
|
latest = { sequence: event.sequence, status };
|
|
934
1007
|
}
|
|
935
1008
|
}
|
|
936
|
-
if (!latest || latest.sequence < ref.current.sequence) return;
|
|
1009
|
+
if (!latest || latest.sequence < ref.current.sequence) return void 0;
|
|
937
1010
|
ref.current = latest;
|
|
938
|
-
|
|
1011
|
+
return latest.status;
|
|
939
1012
|
}
|
|
940
1013
|
async function loadEventWindow(client, workspaceId, sessionId, options) {
|
|
941
1014
|
let cursor = options.before;
|
|
@@ -989,24 +1062,28 @@ async function loadEventWindow(client, workspaceId, sessionId, options) {
|
|
|
989
1062
|
buffer = buffer.slice(boundary);
|
|
990
1063
|
}
|
|
991
1064
|
}
|
|
1065
|
+
const densityWindow = trimBackwardToGroupTarget(buffer, options.targetGroups);
|
|
1066
|
+
buffer = densityWindow.events;
|
|
992
1067
|
const oldest = buffer[0] ?? null;
|
|
993
1068
|
const newest = buffer[buffer.length - 1] ?? null;
|
|
994
1069
|
return {
|
|
995
1070
|
events: buffer,
|
|
996
1071
|
oldestSequence: oldest?.sequence ?? null,
|
|
997
1072
|
newestSequence: newest ? maxResumeSequence(buffer) : 0,
|
|
998
|
-
hasOlder: buffer.length > 0 && !reachedStart && oldest?.type !== "session.created"
|
|
1073
|
+
hasOlder: buffer.length > 0 && (densityWindow.trimmed || !reachedStart && oldest?.type !== "session.created")
|
|
999
1074
|
};
|
|
1000
1075
|
}
|
|
1001
1076
|
function findBoundaryIndex(events) {
|
|
1002
1077
|
for (let index = 0; index < events.length; index += 1) {
|
|
1003
|
-
|
|
1004
|
-
if (type === "session.created" || type === "user.message") {
|
|
1078
|
+
if (isTurnBoundary(events[index])) {
|
|
1005
1079
|
return index;
|
|
1006
1080
|
}
|
|
1007
1081
|
}
|
|
1008
1082
|
return -1;
|
|
1009
1083
|
}
|
|
1084
|
+
function isTurnBoundary(event) {
|
|
1085
|
+
return event.type === "session.created" || event.type === "user.message";
|
|
1086
|
+
}
|
|
1010
1087
|
async function loadForwardEventWindow(client, workspaceId, sessionId, options) {
|
|
1011
1088
|
let cursor = options.after;
|
|
1012
1089
|
let buffer = [];
|
|
@@ -1027,21 +1104,45 @@ async function loadForwardEventWindow(client, workspaceId, sessionId, options) {
|
|
|
1027
1104
|
}
|
|
1028
1105
|
assertAscending(page);
|
|
1029
1106
|
buffer = [...buffer, ...page];
|
|
1030
|
-
cursor = page
|
|
1031
|
-
if (page.length < options.pageSize) {
|
|
1032
|
-
reachedEnd = true;
|
|
1033
|
-
break;
|
|
1034
|
-
}
|
|
1107
|
+
cursor = maxResumeSequence(page);
|
|
1035
1108
|
}
|
|
1109
|
+
const densityWindow = trimForwardToGroupTarget(buffer, options.targetGroups);
|
|
1110
|
+
buffer = densityWindow.events;
|
|
1036
1111
|
const oldest = buffer[0] ?? null;
|
|
1037
1112
|
const newest = buffer[buffer.length - 1] ?? null;
|
|
1038
1113
|
return {
|
|
1039
1114
|
events: buffer,
|
|
1040
1115
|
oldestSequence: oldest?.sequence ?? null,
|
|
1041
1116
|
newestSequence: newest ? maxResumeSequence(buffer) : 0,
|
|
1042
|
-
hasNewer: buffer.length > 0 && !reachedEnd
|
|
1117
|
+
hasNewer: buffer.length > 0 && (densityWindow.trimmed || !reachedEnd)
|
|
1043
1118
|
};
|
|
1044
1119
|
}
|
|
1120
|
+
function trimBackwardToGroupTarget(events, targetGroups) {
|
|
1121
|
+
if (!Number.isFinite(targetGroups) || targetGroups <= 0 || events.length === 0) {
|
|
1122
|
+
return { events, trimmed: false };
|
|
1123
|
+
}
|
|
1124
|
+
for (let index = events.length - 1; index > 0; index -= 1) {
|
|
1125
|
+
if (!isTurnBoundary(events[index])) continue;
|
|
1126
|
+
const candidate = events.slice(index);
|
|
1127
|
+
if (groupCount(candidate) >= targetGroups) {
|
|
1128
|
+
return { events: candidate, trimmed: true };
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return { events, trimmed: false };
|
|
1132
|
+
}
|
|
1133
|
+
function trimForwardToGroupTarget(events, targetGroups) {
|
|
1134
|
+
if (!Number.isFinite(targetGroups) || targetGroups <= 0 || events.length === 0) {
|
|
1135
|
+
return { events, trimmed: false };
|
|
1136
|
+
}
|
|
1137
|
+
for (let index = 1; index < events.length; index += 1) {
|
|
1138
|
+
if (!isTurnBoundary(events[index])) continue;
|
|
1139
|
+
const candidate = events.slice(0, index);
|
|
1140
|
+
if (groupCount(candidate) >= targetGroups) {
|
|
1141
|
+
return { events: candidate, trimmed: true };
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return { events, trimmed: false };
|
|
1145
|
+
}
|
|
1045
1146
|
async function loadPreviousPage(client, workspaceId, sessionId, before, options) {
|
|
1046
1147
|
if (options.signal?.aborted) {
|
|
1047
1148
|
throw abortError();
|
|
@@ -1097,6 +1198,9 @@ function isLogStart(event) {
|
|
|
1097
1198
|
function maxResumeSequence(events) {
|
|
1098
1199
|
return events.reduce((max, event) => Math.max(max, eventResumeSequence(event)), 0);
|
|
1099
1200
|
}
|
|
1201
|
+
function maxResumeSequenceOrNull(events) {
|
|
1202
|
+
return events.length > 0 ? maxResumeSequence(events) : null;
|
|
1203
|
+
}
|
|
1100
1204
|
function eventResumeSequence(event) {
|
|
1101
1205
|
const payload = asRecord(event.payload);
|
|
1102
1206
|
const coalescedUntil = Number(payload.coalescedUntil);
|
|
@@ -1734,13 +1838,24 @@ function useGoal(sessionId, options = {}) {
|
|
|
1734
1838
|
const { run, mutating, mutationError, clearMutationError } = useMutationRunner();
|
|
1735
1839
|
const generation = useRef5(0);
|
|
1736
1840
|
const targetKeyRef = useRef5(null);
|
|
1841
|
+
const loadAbort = useRef5(null);
|
|
1842
|
+
const retireLoads = useCallback5(() => {
|
|
1843
|
+
generation.current += 1;
|
|
1844
|
+
loadAbort.current?.abort();
|
|
1845
|
+
loadAbort.current = null;
|
|
1846
|
+
}, []);
|
|
1737
1847
|
const load = useCallback5(async () => {
|
|
1738
1848
|
if (!sessionId) {
|
|
1739
1849
|
return;
|
|
1740
1850
|
}
|
|
1741
1851
|
const ticket = ++generation.current;
|
|
1852
|
+
loadAbort.current?.abort();
|
|
1853
|
+
const controller = new AbortController();
|
|
1854
|
+
loadAbort.current = controller;
|
|
1742
1855
|
try {
|
|
1743
|
-
const fetched = await client.getGoal(workspaceId, sessionId
|
|
1856
|
+
const fetched = await client.getGoal(workspaceId, sessionId, {
|
|
1857
|
+
signal: controller.signal
|
|
1858
|
+
});
|
|
1744
1859
|
if (ticket === generation.current) {
|
|
1745
1860
|
setGoal(fetched);
|
|
1746
1861
|
setError(null);
|
|
@@ -1757,6 +1872,8 @@ function useGoal(sessionId, options = {}) {
|
|
|
1757
1872
|
setError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
1758
1873
|
}
|
|
1759
1874
|
setLoading(false);
|
|
1875
|
+
} finally {
|
|
1876
|
+
if (loadAbort.current === controller) loadAbort.current = null;
|
|
1760
1877
|
}
|
|
1761
1878
|
}, [client, workspaceId, sessionId]);
|
|
1762
1879
|
useEffect5(() => {
|
|
@@ -1767,13 +1884,14 @@ function useGoal(sessionId, options = {}) {
|
|
|
1767
1884
|
setError(null);
|
|
1768
1885
|
}
|
|
1769
1886
|
if (!enabled || !pageLive) {
|
|
1887
|
+
retireLoads();
|
|
1770
1888
|
setLoading(false);
|
|
1771
1889
|
return;
|
|
1772
1890
|
}
|
|
1773
1891
|
if (sharedFeed) {
|
|
1774
1892
|
setLoading(false);
|
|
1775
1893
|
return () => {
|
|
1776
|
-
|
|
1894
|
+
retireLoads();
|
|
1777
1895
|
};
|
|
1778
1896
|
}
|
|
1779
1897
|
setLoading(true);
|
|
@@ -1781,7 +1899,7 @@ function useGoal(sessionId, options = {}) {
|
|
|
1781
1899
|
if (pollIntervalMs === void 0 || pollIntervalMs <= 0) {
|
|
1782
1900
|
void load();
|
|
1783
1901
|
return () => {
|
|
1784
|
-
|
|
1902
|
+
retireLoads();
|
|
1785
1903
|
};
|
|
1786
1904
|
}
|
|
1787
1905
|
let cancelled = false;
|
|
@@ -1797,9 +1915,18 @@ function useGoal(sessionId, options = {}) {
|
|
|
1797
1915
|
return () => {
|
|
1798
1916
|
cancelled = true;
|
|
1799
1917
|
if (timer !== null) clearTimeout(timer);
|
|
1800
|
-
|
|
1918
|
+
retireLoads();
|
|
1801
1919
|
};
|
|
1802
|
-
}, [
|
|
1920
|
+
}, [
|
|
1921
|
+
load,
|
|
1922
|
+
enabled,
|
|
1923
|
+
pageLive,
|
|
1924
|
+
workspaceId,
|
|
1925
|
+
sessionId,
|
|
1926
|
+
options.pollIntervalMs,
|
|
1927
|
+
retireLoads,
|
|
1928
|
+
sharedFeed
|
|
1929
|
+
]);
|
|
1803
1930
|
const scheduleRefresh = useDebouncedCallback(() => void load());
|
|
1804
1931
|
useSessionEventTrigger(client, workspaceId, sessionId, isGoalRefreshEvent, scheduleRefresh, {
|
|
1805
1932
|
enabled,
|
|
@@ -1842,11 +1969,11 @@ function useGoal(sessionId, options = {}) {
|
|
|
1842
1969
|
return true;
|
|
1843
1970
|
});
|
|
1844
1971
|
if (ok) {
|
|
1845
|
-
|
|
1972
|
+
retireLoads();
|
|
1846
1973
|
setGoal(null);
|
|
1847
1974
|
setError(null);
|
|
1848
1975
|
}
|
|
1849
|
-
}, [client, workspaceId, sessionId, run]);
|
|
1976
|
+
}, [client, workspaceId, sessionId, run, retireLoads]);
|
|
1850
1977
|
return {
|
|
1851
1978
|
goal,
|
|
1852
1979
|
isActive: goal?.status === "active",
|
|
@@ -2089,24 +2216,28 @@ function useSessionLineage(sessionId, options = {}) {
|
|
|
2089
2216
|
const enabled = (options.enabled ?? true) && Boolean(sessionId);
|
|
2090
2217
|
const nextReadGeneration = useRef8(0);
|
|
2091
2218
|
const beginRead = options.beginRead;
|
|
2092
|
-
const load = useCallback8(
|
|
2093
|
-
|
|
2219
|
+
const load = useCallback8(
|
|
2220
|
+
async (signal) => {
|
|
2221
|
+
if (!sessionId) {
|
|
2222
|
+
return {
|
|
2223
|
+
lineage: { ancestors: [], children: [], truncated: false },
|
|
2224
|
+
readGeneration: 0
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
let readGeneration = 0;
|
|
2228
|
+
const lineage = await client.getSessionLineage(workspaceId, sessionId, {
|
|
2229
|
+
signal,
|
|
2230
|
+
onRequestStart: (sharedReadGeneration) => {
|
|
2231
|
+
readGeneration = sharedReadGeneration ?? beginRead?.() ?? ++nextReadGeneration.current;
|
|
2232
|
+
}
|
|
2233
|
+
});
|
|
2094
2234
|
return {
|
|
2095
|
-
lineage
|
|
2096
|
-
readGeneration
|
|
2235
|
+
lineage,
|
|
2236
|
+
readGeneration
|
|
2097
2237
|
};
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
onRequestStart: (sharedReadGeneration) => {
|
|
2102
|
-
readGeneration = sharedReadGeneration ?? beginRead?.() ?? ++nextReadGeneration.current;
|
|
2103
|
-
}
|
|
2104
|
-
});
|
|
2105
|
-
return {
|
|
2106
|
-
lineage,
|
|
2107
|
-
readGeneration
|
|
2108
|
-
};
|
|
2109
|
-
}, [beginRead, client, workspaceId, sessionId]);
|
|
2238
|
+
},
|
|
2239
|
+
[beginRead, client, workspaceId, sessionId]
|
|
2240
|
+
);
|
|
2110
2241
|
const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });
|
|
2111
2242
|
const refresh = state.refresh;
|
|
2112
2243
|
useEffect7(() => {
|
|
@@ -2334,4 +2465,4 @@ export {
|
|
|
2334
2465
|
isHumanInputEvent,
|
|
2335
2466
|
useHumanInputRequests
|
|
2336
2467
|
};
|
|
2337
|
-
//# sourceMappingURL=chunk-
|
|
2468
|
+
//# sourceMappingURL=chunk-3AGBGTRT.js.map
|