@opengeni/react 0.8.0 → 0.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/react",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views — token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@bufbuild/protobuf": "^2.2.0",
48
- "@opengeni/sdk": "^0.8.0",
48
+ "@opengeni/sdk": "^0.9.0",
49
49
  "clsx": "^2.1.1",
50
50
  "lucide-react": "^1.8.0",
51
51
  "motion": "^12.0.0",
@@ -52,8 +52,9 @@ export type UseSessionCapabilitiesOptions = ClientOverride & {
52
52
  warmingPollMs?: number | undefined;
53
53
  /**
54
54
  * Give up waiting for `warm` after this long while polling (ms) and surface a
55
- * stalled error with a manual `renegotiate`. Default 30000 (must agree with
56
- * the lease warming TTL I15). 0 disables the deadline.
55
+ * stalled error with a manual `renegotiate`. Default 30000. This is a UI
56
+ * patience deadline, independent from the worker's sandbox warming timeout.
57
+ * 0 disables the deadline.
57
58
  */
58
59
  warmingDeadlineMs?: number | undefined;
59
60
  };
@@ -25,6 +25,8 @@ export type UseSessionEventsResult = {
25
25
  connectionState: SessionEventsConnectionState;
26
26
  /** Highest sequence seen so far (0 before the first event). */
27
27
  lastSequence: number;
28
+ /** True until the initial tail window has been applied (windowed mode). */
29
+ initialLoading: boolean;
28
30
  /** Whether older durable events are available before the current window. */
29
31
  hasOlder: boolean;
30
32
  /** True while an older window is being fetched. */
@@ -35,8 +37,7 @@ export type UseSessionEventsResult = {
35
37
  };
36
38
 
37
39
  const TAIL_PAGE_SIZE = 5000;
38
- const INITIAL_GROUP_TARGET = 48;
39
- const INITIAL_FETCH_CAP = 3;
40
+ const INITIAL_FETCH_CAP = 1;
40
41
  const OLDER_GROUP_TARGET = 32;
41
42
  const OLDER_FETCH_CAP = 2;
42
43
  const BOUNDARY_PAGE_CAP = 4;
@@ -57,6 +58,7 @@ export function useSessionEvents(sessionId: string | null | undefined, options:
57
58
  const [connectionState, setConnectionState] = useState<SessionEventsConnectionState>("idle");
58
59
  const [error, setError] = useState<Error | null>(null);
59
60
  const [hasOlder, setHasOlder] = useState(false);
61
+ const [initialLoading, setInitialLoading] = useState(true);
60
62
  const [loadingOlder, setLoadingOlder] = useState(false);
61
63
  const lastSequenceRef = useRef(after);
62
64
  const oldestSequenceRef = useRef<number | null>(null);
@@ -76,6 +78,7 @@ export function useSessionEvents(sessionId: string | null | undefined, options:
76
78
  setError(null);
77
79
  setHasOlder(false);
78
80
  setLoadingOlder(false);
81
+ setInitialLoading(true);
79
82
  lastSequenceRef.current = after;
80
83
  oldestSequenceRef.current = null;
81
84
  hasOlderRef.current = false;
@@ -114,10 +117,13 @@ export function useSessionEvents(sessionId: string | null | undefined, options:
114
117
  try {
115
118
  if (!fullReplay) {
116
119
  setConnectionState("connecting");
120
+ // First paint is ONE compact fetch — the newest window, revealed at
121
+ // the bottom in a few hundred ms. Deeper history loads only when the
122
+ // reader actually scrolls up (the sentinel drives loadOlder).
117
123
  const window = await loadEventWindow(client, workspaceId, sessionId, {
118
124
  before: Number.MAX_SAFE_INTEGER,
119
125
  pageSize: TAIL_PAGE_SIZE,
120
- targetGroups: INITIAL_GROUP_TARGET,
126
+ targetGroups: Number.POSITIVE_INFINITY,
121
127
  maxFetches: INITIAL_FETCH_CAP,
122
128
  signal: controller.signal,
123
129
  });
@@ -129,6 +135,10 @@ export function useSessionEvents(sessionId: string | null | undefined, options:
129
135
  lastSequenceRef.current = window.newestSequence;
130
136
  setHasOlder(window.hasOlder);
131
137
  setEvents(window.events);
138
+ setInitialLoading(false);
139
+ }
140
+ if (fullReplay) {
141
+ setInitialLoading(false);
132
142
  }
133
143
  const stream = client.streamEvents(workspaceId, sessionId, {
134
144
  after: lastSequenceRef.current,
@@ -218,6 +228,7 @@ export function useSessionEvents(sessionId: string | null | undefined, options:
218
228
  sessionStatus,
219
229
  connectionState,
220
230
  lastSequence: lastSequenceRef.current,
231
+ initialLoading: fullReplay ? false : initialLoading,
221
232
  hasOlder: fullReplay ? false : hasOlder,
222
233
  loadingOlder: fullReplay ? false : loadingOlder,
223
234
  loadOlder,