@opengeni/react 3.1.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
|
@@ -105,7 +105,12 @@ const REALTIME_MODEL_CATALOG_CACHE_MAX_WORKSPACES = 64;
|
|
|
105
105
|
type RealtimeControllerClient = EmbeddedRealtimeSessionClientLike & SessionRealtimeClientLike;
|
|
106
106
|
|
|
107
107
|
type RealtimeModelCatalogCacheEntry =
|
|
108
|
-
| {
|
|
108
|
+
| {
|
|
109
|
+
state: "loading";
|
|
110
|
+
promise: Promise<RealtimeModelOption[]>;
|
|
111
|
+
controller: AbortController;
|
|
112
|
+
consumers: number;
|
|
113
|
+
}
|
|
109
114
|
| { state: "ready"; models: RealtimeModelOption[]; expiresAt: number };
|
|
110
115
|
|
|
111
116
|
// Scope advisory availability to the exact client object and workspace. The
|
|
@@ -166,19 +171,26 @@ function pruneRealtimeModelCatalogCache(
|
|
|
166
171
|
function loadRealtimeModelCatalog(
|
|
167
172
|
client: RealtimeControllerClient,
|
|
168
173
|
workspaceId: string,
|
|
174
|
+
signal?: AbortSignal,
|
|
169
175
|
): Promise<RealtimeModelOption[]> | null {
|
|
170
176
|
const load = client.getWorkspaceRealtimeModelCatalog;
|
|
171
177
|
if (!load) return null;
|
|
178
|
+
if (signal?.aborted) {
|
|
179
|
+
return Promise.reject(signal.reason ?? new DOMException("Request aborted", "AbortError"));
|
|
180
|
+
}
|
|
172
181
|
const now = Date.now();
|
|
173
182
|
const cache = realtimeModelCatalogCacheFor(client);
|
|
174
183
|
const entry = cache.get(workspaceId);
|
|
175
|
-
if (entry?.state === "loading"
|
|
184
|
+
if (entry?.state === "loading" && !entry.controller.signal.aborted) {
|
|
185
|
+
return consumeRealtimeModelCatalog(entry, signal);
|
|
186
|
+
}
|
|
176
187
|
if (entry?.state === "ready" && entry.expiresAt > now) return Promise.resolve(entry.models);
|
|
177
188
|
if (entry) cache.delete(workspaceId);
|
|
178
189
|
pruneRealtimeModelCatalogCache(cache, now);
|
|
179
190
|
|
|
191
|
+
const controller = new AbortController();
|
|
180
192
|
const promise = load
|
|
181
|
-
.call(client, workspaceId)
|
|
193
|
+
.call(client, workspaceId, { signal: controller.signal })
|
|
182
194
|
.then((response) => response.models.map(toRealtimeModelOption))
|
|
183
195
|
.then((models) => {
|
|
184
196
|
const current = cache.get(workspaceId);
|
|
@@ -197,8 +209,43 @@ function loadRealtimeModelCatalog(
|
|
|
197
209
|
if (current?.state === "loading" && current.promise === promise) cache.delete(workspaceId);
|
|
198
210
|
throw error;
|
|
199
211
|
});
|
|
200
|
-
|
|
201
|
-
|
|
212
|
+
const loading: RealtimeModelCatalogCacheEntry & { state: "loading" } = {
|
|
213
|
+
state: "loading",
|
|
214
|
+
promise,
|
|
215
|
+
controller,
|
|
216
|
+
consumers: 0,
|
|
217
|
+
};
|
|
218
|
+
cache.set(workspaceId, loading);
|
|
219
|
+
return consumeRealtimeModelCatalog(loading, signal);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function consumeRealtimeModelCatalog(
|
|
223
|
+
entry: RealtimeModelCatalogCacheEntry & { state: "loading" },
|
|
224
|
+
signal?: AbortSignal,
|
|
225
|
+
): Promise<RealtimeModelOption[]> {
|
|
226
|
+
entry.consumers += 1;
|
|
227
|
+
return new Promise((resolve, reject) => {
|
|
228
|
+
let released = false;
|
|
229
|
+
const release = (abandoned: boolean) => {
|
|
230
|
+
if (released) return;
|
|
231
|
+
released = true;
|
|
232
|
+
entry.consumers = Math.max(0, entry.consumers - 1);
|
|
233
|
+
if (abandoned && entry.consumers === 0) {
|
|
234
|
+
entry.controller.abort(
|
|
235
|
+
signal?.reason ?? new DOMException("Request abandoned", "AbortError"),
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const onAbort = () => {
|
|
240
|
+
release(true);
|
|
241
|
+
reject(signal?.reason ?? new DOMException("Request aborted", "AbortError"));
|
|
242
|
+
};
|
|
243
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
244
|
+
void entry.promise.then(resolve, reject).finally(() => {
|
|
245
|
+
signal?.removeEventListener("abort", onAbort);
|
|
246
|
+
release(false);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
202
249
|
}
|
|
203
250
|
|
|
204
251
|
export type SessionRealtimeControllerFactory = (
|
|
@@ -550,6 +597,7 @@ export function useRealtimeModelSelection(options: {
|
|
|
550
597
|
|
|
551
598
|
useEffect(() => {
|
|
552
599
|
let disposed = false;
|
|
600
|
+
const requestAbort = new AbortController();
|
|
553
601
|
const applyCatalog = (models: RealtimeModelOption[]) => {
|
|
554
602
|
catalogScopeRef.current = { client, workspaceId, source: "cache" };
|
|
555
603
|
setCatalog(models);
|
|
@@ -570,7 +618,7 @@ export function useRealtimeModelSelection(options: {
|
|
|
570
618
|
}
|
|
571
619
|
return;
|
|
572
620
|
}
|
|
573
|
-
const loading = loadRealtimeModelCatalog(client, workspaceId);
|
|
621
|
+
const loading = loadRealtimeModelCatalog(client, workspaceId, requestAbort.signal);
|
|
574
622
|
if (!loading) return;
|
|
575
623
|
void loading
|
|
576
624
|
.then((models) => {
|
|
@@ -580,6 +628,7 @@ export function useRealtimeModelSelection(options: {
|
|
|
580
628
|
.catch(() => undefined);
|
|
581
629
|
return () => {
|
|
582
630
|
disposed = true;
|
|
631
|
+
requestAbort.abort();
|
|
583
632
|
};
|
|
584
633
|
}, [client, workspaceId]);
|
|
585
634
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, useRef } from "react";
|
|
1
|
+
import { createContext, useContext, useRef, type ReactNode } from "react";
|
|
2
2
|
|
|
3
3
|
/* ----------------------------------------------------------------------------
|
|
4
4
|
Entrance animation gating
|
|
@@ -15,8 +15,33 @@ import { createContext, useContext, useRef } from "react";
|
|
|
15
15
|
-------------------------------------------------------------------------- */
|
|
16
16
|
|
|
17
17
|
const EntranceAnimationContext = createContext(true);
|
|
18
|
+
const EntranceAnimationLiveContext = createContext(true);
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Freeze the mount-time gate for this subtree while publishing a separate live
|
|
22
|
+
* gate to activity rails that need later appends to animate after a bulk paint.
|
|
23
|
+
* MessageTimeline mounts one provider per durable group, so existing groups do
|
|
24
|
+
* not receive a context invalidation when a prepend toggles bulk mode and new
|
|
25
|
+
* groups still capture the value from the commit that created them.
|
|
26
|
+
*/
|
|
27
|
+
export function EntranceAnimationProvider({
|
|
28
|
+
value,
|
|
29
|
+
liveValue = value,
|
|
30
|
+
children,
|
|
31
|
+
}: {
|
|
32
|
+
value: boolean;
|
|
33
|
+
liveValue?: boolean | undefined;
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
}) {
|
|
36
|
+
const mountedValue = useRef(value).current;
|
|
37
|
+
return (
|
|
38
|
+
<EntranceAnimationContext.Provider value={mountedValue}>
|
|
39
|
+
<EntranceAnimationLiveContext.Provider value={liveValue}>
|
|
40
|
+
{children}
|
|
41
|
+
</EntranceAnimationLiveContext.Provider>
|
|
42
|
+
</EntranceAnimationContext.Provider>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
20
45
|
|
|
21
46
|
/**
|
|
22
47
|
* Live entrance gate from the nearest provider. Prefer
|
|
@@ -25,7 +50,7 @@ export const EntranceAnimationProvider = EntranceAnimationContext.Provider;
|
|
|
25
50
|
* later appends after a bulk window clears.
|
|
26
51
|
*/
|
|
27
52
|
export function useEntranceAnimationLive(): boolean {
|
|
28
|
-
return useContext(
|
|
53
|
+
return useContext(EntranceAnimationLiveContext);
|
|
29
54
|
}
|
|
30
55
|
|
|
31
56
|
/**
|
|
@@ -2091,6 +2091,10 @@ function findOpenCall(
|
|
|
2091
2091
|
if (byId) {
|
|
2092
2092
|
return byId as ToolCallItem | WorkerItem;
|
|
2093
2093
|
}
|
|
2094
|
+
// An explicit provider correlation id is authoritative. Falling back to
|
|
2095
|
+
// an unrelated running call corrupts its status/output when compact pages
|
|
2096
|
+
// or interleaved providers deliver an unmatched historical result.
|
|
2097
|
+
return undefined;
|
|
2094
2098
|
}
|
|
2095
2099
|
return reversed.find(
|
|
2096
2100
|
(item): item is ToolCallItem | WorkerItem => isCall(item) && item.status === "running",
|