@trigger.dev/react-hooks 4.5.13 → 4.5.15

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 (37) hide show
  1. package/dist/commonjs/hooks/useApiClient.d.ts +5 -0
  2. package/dist/commonjs/hooks/useApiClient.js +14 -1
  3. package/dist/commonjs/hooks/useApiClient.js.map +1 -1
  4. package/dist/commonjs/hooks/useRealtime.d.ts +43 -1
  5. package/dist/commonjs/hooks/useRealtime.js +65 -22
  6. package/dist/commonjs/hooks/useRealtime.js.map +1 -1
  7. package/dist/commonjs/hooks/useSessionStream.d.ts +131 -0
  8. package/dist/commonjs/hooks/useSessionStream.js +236 -0
  9. package/dist/commonjs/hooks/useSessionStream.js.map +1 -0
  10. package/dist/commonjs/hooks/useSessionStreamChannel.d.ts +86 -0
  11. package/dist/commonjs/hooks/useSessionStreamChannel.js +209 -0
  12. package/dist/commonjs/hooks/useSessionStreamChannel.js.map +1 -0
  13. package/dist/commonjs/index.d.ts +2 -0
  14. package/dist/commonjs/index.js +2 -0
  15. package/dist/commonjs/index.js.map +1 -1
  16. package/dist/commonjs/utils/useStableRequestCallback.d.ts +5 -0
  17. package/dist/commonjs/utils/useStableRequestCallback.js +17 -0
  18. package/dist/commonjs/utils/useStableRequestCallback.js.map +1 -0
  19. package/dist/esm/hooks/useApiClient.d.ts +5 -0
  20. package/dist/esm/hooks/useApiClient.js +15 -2
  21. package/dist/esm/hooks/useApiClient.js.map +1 -1
  22. package/dist/esm/hooks/useRealtime.d.ts +43 -1
  23. package/dist/esm/hooks/useRealtime.js +60 -17
  24. package/dist/esm/hooks/useRealtime.js.map +1 -1
  25. package/dist/esm/hooks/useSessionStream.d.ts +131 -0
  26. package/dist/esm/hooks/useSessionStream.js +233 -0
  27. package/dist/esm/hooks/useSessionStream.js.map +1 -0
  28. package/dist/esm/hooks/useSessionStreamChannel.d.ts +86 -0
  29. package/dist/esm/hooks/useSessionStreamChannel.js +206 -0
  30. package/dist/esm/hooks/useSessionStreamChannel.js.map +1 -0
  31. package/dist/esm/index.d.ts +2 -0
  32. package/dist/esm/index.js +2 -0
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/utils/useStableRequestCallback.d.ts +5 -0
  35. package/dist/esm/utils/useStableRequestCallback.js +14 -0
  36. package/dist/esm/utils/useStableRequestCallback.js.map +1 -0
  37. package/package.json +2 -2
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ "use client";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useSessionStream = useSessionStream;
5
+ const react_1 = require("react");
6
+ const throttle_js_1 = require("../utils/throttle.js");
7
+ const trigger_swr_js_1 = require("../utils/trigger-swr.js");
8
+ const useStableRequestCallback_js_1 = require("../utils/useStableRequestCallback.js");
9
+ const useApiClient_js_1 = require("./useApiClient.js");
10
+ /**
11
+ * Hook to read one channel of a Session's realtime stream.
12
+ *
13
+ * This hook subscribes to one of the session's channels (`out` by default, or `in`) and
14
+ * updates the `records` array as new records arrive. It is read-only: use `useSession` for
15
+ * two-way (read and write) communication. The subscription is automatically managed: it
16
+ * starts when the component mounts (or when `enabled` becomes `true`) and stops when the
17
+ * component unmounts or when `stop()` is called.
18
+ *
19
+ * Requires a Public Access Token with the `read:sessions:{id}` scope.
20
+ *
21
+ * @template TRecord - The type of each record on the channel
22
+ * @param sessionIdOrExternalId - The id or external id of the session to subscribe to
23
+ * @param options - Optional configuration for the subscription
24
+ * @returns An object containing:
25
+ * - `records`: An array of all the records received so far (accumulates over time)
26
+ * - `lastEventId`: The cursor of the last record seen, for resuming later
27
+ * - `lastControl`: The last control record seen
28
+ * - `error`: Any error that occurred during subscription
29
+ * - `stop`: A function to manually stop the subscription
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * "use client";
34
+ * import { useSessionStream } from "@trigger.dev/react-hooks";
35
+ *
36
+ * function SessionViewer({ sessionId }: { sessionId: string }) {
37
+ * const { records, error } = useSessionStream<string>(sessionId, {
38
+ * accessToken: publicAccessToken,
39
+ * });
40
+ *
41
+ * if (error) return <div>Error: {error.message}</div>;
42
+ *
43
+ * return <div>{records.join("")}</div>;
44
+ * }
45
+ * ```
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * // Read the input channel, resuming from a persisted cursor
50
+ * const { records, lastEventId, stop } = useSessionStream<MyRecord>(sessionId, {
51
+ * accessToken: publicAccessToken,
52
+ * io: "in",
53
+ * lastEventId: persistedCursor,
54
+ * onControl: (event) => {
55
+ * if (event.subtype === "turn-complete") {
56
+ * console.log("The turn is complete");
57
+ * }
58
+ * },
59
+ * });
60
+ * ```
61
+ */
62
+ function useSessionStream(sessionIdOrExternalId, options) {
63
+ const hookId = (0, react_1.useId)();
64
+ const idKey = options?.id ?? hookId;
65
+ const io = options?.io ?? "out";
66
+ const [initialRecordsFallback] = (0, react_1.useState)([]);
67
+ const { data: records, mutate: mutateRecords } = (0, trigger_swr_js_1.useSWR)([idKey, sessionIdOrExternalId, io, "records"], null, {
68
+ fallbackData: initialRecordsFallback,
69
+ });
70
+ const recordsRef = (0, react_1.useRef)(records ?? []);
71
+ (0, react_1.useEffect)(() => {
72
+ recordsRef.current = records || [];
73
+ }, [records]);
74
+ const { data: lastEventId = undefined, mutate: setLastEventId } = (0, trigger_swr_js_1.useSWR)([idKey, sessionIdOrExternalId, io, "lastEventId"], null);
75
+ const lastEventIdRef = (0, react_1.useRef)(lastEventId);
76
+ const channelIdentityRef = (0, react_1.useRef)(`${idKey}:${sessionIdOrExternalId}:${io}`);
77
+ (0, react_1.useEffect)(() => {
78
+ const identity = `${idKey}:${sessionIdOrExternalId}:${io}`;
79
+ if (channelIdentityRef.current !== identity) {
80
+ channelIdentityRef.current = identity;
81
+ lastEventIdRef.current = lastEventId;
82
+ }
83
+ }, [idKey, sessionIdOrExternalId, io, lastEventId]);
84
+ const { data: lastControl = undefined, mutate: setLastControl } = (0, trigger_swr_js_1.useSWR)([idKey, sessionIdOrExternalId, io, "lastControl"], null);
85
+ const { data: _isComplete = false, mutate: setIsComplete } = (0, trigger_swr_js_1.useSWR)([idKey, sessionIdOrExternalId, io, "complete"], null);
86
+ const { data: error = undefined, mutate: setError } = (0, trigger_swr_js_1.useSWR)([idKey, sessionIdOrExternalId, io, "error"], null);
87
+ const abortControllerRef = (0, react_1.useRef)(null);
88
+ const stop = (0, react_1.useCallback)(() => {
89
+ if (abortControllerRef.current) {
90
+ abortControllerRef.current.abort();
91
+ abortControllerRef.current = null;
92
+ }
93
+ }, []);
94
+ const onRecordsCallback = options?.onRecords;
95
+ const onRecords = (0, react_1.useCallback)((recordsBatch) => {
96
+ if (onRecordsCallback) {
97
+ onRecordsCallback(recordsBatch);
98
+ }
99
+ }, [onRecordsCallback]);
100
+ const onControlCallback = options?.onControl;
101
+ const onControl = (0, react_1.useCallback)((event) => {
102
+ if (onControlCallback) {
103
+ onControlCallback(event);
104
+ }
105
+ }, [onControlCallback]);
106
+ const apiClient = (0, useApiClient_js_1.useApiClient)(options);
107
+ const timeoutInSeconds = options?.timeoutInSeconds;
108
+ const startEventId = options?.lastEventId;
109
+ const throttleInMs = options?.throttleInMs;
110
+ const from = options?.from;
111
+ const maxRecords = options?.maxRecords;
112
+ (0, react_1.useEffect)(() => {
113
+ if (maxRecords != null && maxRecords >= 0) {
114
+ const current = recordsRef.current;
115
+ if (current.length > maxRecords) {
116
+ mutateRecords(current.slice(current.length - maxRecords));
117
+ }
118
+ }
119
+ }, [maxRecords, mutateRecords]);
120
+ const triggerRequest = (0, react_1.useCallback)(async () => {
121
+ try {
122
+ if (!sessionIdOrExternalId || !apiClient) {
123
+ return;
124
+ }
125
+ const abortController = new AbortController();
126
+ abortControllerRef.current = abortController;
127
+ await processSessionStream(sessionIdOrExternalId, io, apiClient, mutateRecords, recordsRef, setLastEventId, setLastControl, setError, onRecords, onControl, abortControllerRef, timeoutInSeconds, startEventId !== undefined ? String(startEventId) : lastEventIdRef.current, throttleInMs ?? 16, from, maxRecords);
128
+ }
129
+ catch (err) {
130
+ if (err.name === "AbortError") {
131
+ abortControllerRef.current = null;
132
+ return;
133
+ }
134
+ setError(err);
135
+ }
136
+ finally {
137
+ if (abortControllerRef.current) {
138
+ abortControllerRef.current = null;
139
+ }
140
+ setIsComplete(true);
141
+ }
142
+ }, [
143
+ sessionIdOrExternalId,
144
+ io,
145
+ apiClient,
146
+ mutateRecords,
147
+ setLastEventId,
148
+ setLastControl,
149
+ setError,
150
+ setIsComplete,
151
+ onRecords,
152
+ onControl,
153
+ timeoutInSeconds,
154
+ startEventId,
155
+ throttleInMs,
156
+ from,
157
+ maxRecords,
158
+ ]);
159
+ const requestSubscription = (0, useStableRequestCallback_js_1.useStableRequestCallback)(triggerRequest);
160
+ (0, react_1.useEffect)(() => {
161
+ if (typeof options?.enabled === "boolean" && !options.enabled) {
162
+ return;
163
+ }
164
+ if (!sessionIdOrExternalId) {
165
+ return;
166
+ }
167
+ requestSubscription().finally(() => { });
168
+ return () => {
169
+ stop();
170
+ };
171
+ }, [sessionIdOrExternalId, io, stop, options?.enabled, requestSubscription]);
172
+ return { records: records ?? initialRecordsFallback, lastEventId, lastControl, error, stop };
173
+ }
174
+ async function processSessionStream(sessionIdOrExternalId, io, apiClient, mutateRecordsData, existingRecordsRef, setLastEventId, setLastControl, onError, onRecords, onControl, abortControllerRef, timeoutInSeconds, lastEventId, throttleInMs, from, maxRecords) {
175
+ let lastSeenEventId;
176
+ let publishedEventId;
177
+ let partsBatch = [];
178
+ const publishLastEventId = () => {
179
+ if (lastSeenEventId !== publishedEventId) {
180
+ publishedEventId = lastSeenEventId;
181
+ setLastEventId(lastSeenEventId);
182
+ }
183
+ };
184
+ const flushParts = () => {
185
+ if (partsBatch.length === 0)
186
+ return;
187
+ const batch = partsBatch;
188
+ partsBatch = [];
189
+ onRecords(batch);
190
+ };
191
+ try {
192
+ const stream = await apiClient.subscribeToSessionStream(sessionIdOrExternalId, io, {
193
+ signal: abortControllerRef.current?.signal,
194
+ timeoutInSeconds,
195
+ lastEventId,
196
+ from,
197
+ onPart: (part) => {
198
+ lastSeenEventId = part.id;
199
+ partsBatch.push(part);
200
+ },
201
+ onControl: (event) => {
202
+ setLastControl(event);
203
+ onControl(event);
204
+ },
205
+ });
206
+ const recordsQueue = (0, throttle_js_1.createThrottledQueue)(async (newRecords) => {
207
+ const combined = [...existingRecordsRef.current, ...newRecords];
208
+ const bounded = maxRecords != null && maxRecords >= 0 && combined.length > maxRecords
209
+ ? combined.slice(combined.length - maxRecords)
210
+ : combined;
211
+ existingRecordsRef.current = bounded;
212
+ mutateRecordsData(bounded);
213
+ publishLastEventId();
214
+ flushParts();
215
+ }, throttleInMs);
216
+ for await (const record of stream) {
217
+ recordsQueue.add(record);
218
+ }
219
+ await recordsQueue.flush();
220
+ publishLastEventId();
221
+ flushParts();
222
+ }
223
+ catch (err) {
224
+ if (err.name === "AbortError") {
225
+ return;
226
+ }
227
+ if (err instanceof Error) {
228
+ onError(err);
229
+ }
230
+ else {
231
+ onError(new Error(String(err)));
232
+ }
233
+ throw err;
234
+ }
235
+ }
236
+ //# sourceMappingURL=useSessionStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSessionStream.js","sourceRoot":"","sources":["../../../src/hooks/useSessionStream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type { AnySessionChannel, ControlEvent, SessionChannelIn, SessionChannelName, SessionChannelOut, SSEStreamPart } from "@trigger.dev/core/v3";
2
+ import type { UseApiClientOptions } from "./useApiClient.js";
3
+ type ChannelRecord<TChannel extends AnySessionChannel, S extends "in" | "out"> = S extends "out" ? SessionChannelOut<TChannel> : SessionChannelIn<TChannel>;
4
+ export type UseSessionStreamChannelInstance<TRecord> = {
5
+ /** The records received so far on the channel, in arrival order. */
6
+ records: Array<TRecord>;
7
+ /** The cursor of the last record seen; pass back as `lastEventId` to resume. */
8
+ lastEventId: string | undefined;
9
+ /** The last control record seen on the channel. */
10
+ lastControl: ControlEvent | undefined;
11
+ error: Error | undefined;
12
+ /** Abort the current request immediately, keep the records received so far. */
13
+ stop: () => void;
14
+ };
15
+ export type UseSessionStreamChannelOptions<TChannel extends AnySessionChannel, S extends "in" | "out"> = UseApiClientOptions & {
16
+ /**
17
+ * The id or external id of the session that owns the channel. May be
18
+ * undefined while it resolves; the subscription starts once it is set.
19
+ */
20
+ sessionId?: string;
21
+ id?: string;
22
+ enabled?: boolean;
23
+ /**
24
+ * Which side of the channel to read.
25
+ *
26
+ * @default "out"
27
+ */
28
+ io?: S;
29
+ /**
30
+ * The number of milliseconds to throttle the record updates.
31
+ *
32
+ * @default 16
33
+ */
34
+ throttleInMs?: number;
35
+ /**
36
+ * The number of seconds to wait for new data before the stream closes.
37
+ *
38
+ * @default 60 seconds
39
+ */
40
+ timeoutInSeconds?: number;
41
+ /** The cursor to resume from. If not provided, reads per `from`. */
42
+ lastEventId?: string | number;
43
+ /**
44
+ * Where a fresh subscription (no `lastEventId`) starts reading.
45
+ *
46
+ * - `"beginning"` (default): replay the full channel history, then live-tail.
47
+ * - `"latest"`: start at the current tail, for a last-value / live view.
48
+ *
49
+ * Ignored when `lastEventId` is set.
50
+ */
51
+ from?: "beginning" | "latest";
52
+ /**
53
+ * Cap the number of records kept in `records`. Use `maxRecords: 1` with
54
+ * `from: "latest"` for a bounded last-value view.
55
+ */
56
+ maxRecords?: number;
57
+ /** Invoked once per throttled flush with the batch of records (control records included). */
58
+ onRecords?: (records: Array<SSEStreamPart<ChannelRecord<TChannel, S>>>) => void;
59
+ /** Called when a control record is received on the channel. */
60
+ onControl?: (event: ControlEvent) => void;
61
+ };
62
+ /**
63
+ * Read one side of a named Session side channel, with record types inferred
64
+ * from a `defineSessionChannel` declaration passed as the type argument.
65
+ *
66
+ * The channel name is typesafe (`SessionChannelName<TChannel>`) and `records`
67
+ * is typed from the channel's `.out` / `.in` record type. Called without the
68
+ * type argument, the channel name is any string and `records` is `unknown`.
69
+ *
70
+ * Requires a Public Access Token scoped to the session (or to the channel).
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * import type { screenshotsChannel } from "./shared/channels";
75
+ *
76
+ * const { records } = useSessionStreamChannel<typeof screenshotsChannel>("screenshots", {
77
+ * sessionId,
78
+ * accessToken,
79
+ * io: "out",
80
+ * from: "latest",
81
+ * maxRecords: 1,
82
+ * });
83
+ * ```
84
+ */
85
+ export declare function useSessionStreamChannel<TChannel extends AnySessionChannel = AnySessionChannel, S extends "in" | "out" = "out">(channel: SessionChannelName<TChannel>, options: UseSessionStreamChannelOptions<TChannel, S>): UseSessionStreamChannelInstance<ChannelRecord<TChannel, S>>;
86
+ export {};
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ "use client";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useSessionStreamChannel = useSessionStreamChannel;
5
+ const react_1 = require("react");
6
+ const throttle_js_1 = require("../utils/throttle.js");
7
+ const trigger_swr_js_1 = require("../utils/trigger-swr.js");
8
+ const useStableRequestCallback_js_1 = require("../utils/useStableRequestCallback.js");
9
+ const useApiClient_js_1 = require("./useApiClient.js");
10
+ /**
11
+ * Read one side of a named Session side channel, with record types inferred
12
+ * from a `defineSessionChannel` declaration passed as the type argument.
13
+ *
14
+ * The channel name is typesafe (`SessionChannelName<TChannel>`) and `records`
15
+ * is typed from the channel's `.out` / `.in` record type. Called without the
16
+ * type argument, the channel name is any string and `records` is `unknown`.
17
+ *
18
+ * Requires a Public Access Token scoped to the session (or to the channel).
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * import type { screenshotsChannel } from "./shared/channels";
23
+ *
24
+ * const { records } = useSessionStreamChannel<typeof screenshotsChannel>("screenshots", {
25
+ * sessionId,
26
+ * accessToken,
27
+ * io: "out",
28
+ * from: "latest",
29
+ * maxRecords: 1,
30
+ * });
31
+ * ```
32
+ */
33
+ function useSessionStreamChannel(channel, options) {
34
+ const hookId = (0, react_1.useId)();
35
+ const idKey = options.id ?? hookId;
36
+ const io = (options.io ?? "out");
37
+ const sessionId = options.sessionId;
38
+ const channelName = channel;
39
+ const [initialRecordsFallback] = (0, react_1.useState)([]);
40
+ const { data: records, mutate: mutateRecords } = (0, trigger_swr_js_1.useSWR)([idKey, sessionId, channelName, io, "records"], null, { fallbackData: initialRecordsFallback });
41
+ const recordsRef = (0, react_1.useRef)(records ?? []);
42
+ (0, react_1.useEffect)(() => {
43
+ recordsRef.current = records || [];
44
+ }, [records]);
45
+ const { data: lastEventId = undefined, mutate: setLastEventId } = (0, trigger_swr_js_1.useSWR)([idKey, sessionId, channelName, io, "lastEventId"], null);
46
+ const lastEventIdRef = (0, react_1.useRef)(lastEventId);
47
+ const channelIdentityRef = (0, react_1.useRef)(`${idKey}:${sessionId}:${channelName}:${io}`);
48
+ (0, react_1.useEffect)(() => {
49
+ const identity = `${idKey}:${sessionId}:${channelName}:${io}`;
50
+ if (channelIdentityRef.current !== identity) {
51
+ channelIdentityRef.current = identity;
52
+ lastEventIdRef.current = lastEventId;
53
+ }
54
+ }, [idKey, sessionId, channelName, io, lastEventId]);
55
+ const { data: lastControl = undefined, mutate: setLastControl } = (0, trigger_swr_js_1.useSWR)([idKey, sessionId, channelName, io, "lastControl"], null);
56
+ const { data: _isComplete = false, mutate: setIsComplete } = (0, trigger_swr_js_1.useSWR)([idKey, sessionId, channelName, io, "complete"], null);
57
+ const { data: error = undefined, mutate: setError } = (0, trigger_swr_js_1.useSWR)([idKey, sessionId, channelName, io, "error"], null);
58
+ const abortControllerRef = (0, react_1.useRef)(null);
59
+ const stop = (0, react_1.useCallback)(() => {
60
+ if (abortControllerRef.current) {
61
+ abortControllerRef.current.abort();
62
+ abortControllerRef.current = null;
63
+ }
64
+ }, []);
65
+ const onRecordsCallback = options.onRecords;
66
+ const onRecords = (0, react_1.useCallback)((recordsBatch) => {
67
+ if (onRecordsCallback) {
68
+ onRecordsCallback(recordsBatch);
69
+ }
70
+ }, [onRecordsCallback]);
71
+ const onControlCallback = options.onControl;
72
+ const onControl = (0, react_1.useCallback)((event) => {
73
+ if (onControlCallback) {
74
+ onControlCallback(event);
75
+ }
76
+ }, [onControlCallback]);
77
+ const apiClient = (0, useApiClient_js_1.useApiClient)(options);
78
+ const timeoutInSeconds = options.timeoutInSeconds;
79
+ const startEventId = options.lastEventId;
80
+ const throttleInMs = options.throttleInMs;
81
+ const from = options.from;
82
+ const maxRecords = options.maxRecords;
83
+ (0, react_1.useEffect)(() => {
84
+ if (maxRecords != null && maxRecords >= 0) {
85
+ const current = recordsRef.current;
86
+ if (current.length > maxRecords) {
87
+ mutateRecords(current.slice(current.length - maxRecords));
88
+ }
89
+ }
90
+ }, [maxRecords, mutateRecords]);
91
+ const triggerRequest = (0, react_1.useCallback)(async () => {
92
+ let abortController = null;
93
+ try {
94
+ if (!sessionId || !apiClient) {
95
+ return;
96
+ }
97
+ abortController = new AbortController();
98
+ abortControllerRef.current = abortController;
99
+ await processSessionChannelStream(sessionId, io, channelName, apiClient, mutateRecords, recordsRef, setLastEventId, setLastControl, setError, onRecords, onControl, abortControllerRef, timeoutInSeconds, startEventId !== undefined ? String(startEventId) : lastEventIdRef.current, throttleInMs ?? 16, from, maxRecords);
100
+ }
101
+ catch (err) {
102
+ if (err.name === "AbortError") {
103
+ return;
104
+ }
105
+ setError(err);
106
+ }
107
+ finally {
108
+ if (abortControllerRef.current === abortController) {
109
+ abortControllerRef.current = null;
110
+ }
111
+ setIsComplete(true);
112
+ }
113
+ }, [
114
+ sessionId,
115
+ io,
116
+ channelName,
117
+ apiClient,
118
+ mutateRecords,
119
+ setLastEventId,
120
+ setLastControl,
121
+ setError,
122
+ setIsComplete,
123
+ onRecords,
124
+ onControl,
125
+ timeoutInSeconds,
126
+ startEventId,
127
+ throttleInMs,
128
+ from,
129
+ maxRecords,
130
+ ]);
131
+ const requestSubscription = (0, useStableRequestCallback_js_1.useStableRequestCallback)(triggerRequest);
132
+ (0, react_1.useEffect)(() => {
133
+ if (typeof options.enabled === "boolean" && !options.enabled) {
134
+ return;
135
+ }
136
+ if (!sessionId) {
137
+ return;
138
+ }
139
+ requestSubscription().finally(() => { });
140
+ return () => {
141
+ stop();
142
+ };
143
+ }, [sessionId, channelName, io, stop, options.enabled, requestSubscription]);
144
+ return { records: records ?? initialRecordsFallback, lastEventId, lastControl, error, stop };
145
+ }
146
+ async function processSessionChannelStream(sessionIdOrExternalId, io, channel, apiClient, mutateRecordsData, existingRecordsRef, setLastEventId, setLastControl, onError, onRecords, onControl, abortControllerRef, timeoutInSeconds, lastEventId, throttleInMs, from, maxRecords) {
147
+ let lastSeenEventId;
148
+ let publishedEventId;
149
+ let partsBatch = [];
150
+ const publishLastEventId = () => {
151
+ if (lastSeenEventId !== publishedEventId) {
152
+ publishedEventId = lastSeenEventId;
153
+ setLastEventId(lastSeenEventId);
154
+ }
155
+ };
156
+ const flushParts = () => {
157
+ if (partsBatch.length === 0)
158
+ return;
159
+ const batch = partsBatch;
160
+ partsBatch = [];
161
+ onRecords(batch);
162
+ };
163
+ try {
164
+ const stream = await apiClient.subscribeToSessionStream(sessionIdOrExternalId, io, {
165
+ signal: abortControllerRef.current?.signal,
166
+ channel,
167
+ timeoutInSeconds,
168
+ lastEventId,
169
+ from,
170
+ onPart: (part) => {
171
+ lastSeenEventId = part.id;
172
+ partsBatch.push(part);
173
+ },
174
+ onControl: (event) => {
175
+ setLastControl(event);
176
+ onControl(event);
177
+ },
178
+ });
179
+ const recordsQueue = (0, throttle_js_1.createThrottledQueue)(async (newRecords) => {
180
+ const combined = [...existingRecordsRef.current, ...newRecords];
181
+ const bounded = maxRecords != null && maxRecords >= 0 && combined.length > maxRecords
182
+ ? combined.slice(combined.length - maxRecords)
183
+ : combined;
184
+ existingRecordsRef.current = bounded;
185
+ mutateRecordsData(bounded);
186
+ publishLastEventId();
187
+ flushParts();
188
+ }, throttleInMs);
189
+ for await (const record of stream) {
190
+ recordsQueue.add(record);
191
+ }
192
+ await recordsQueue.flush();
193
+ publishLastEventId();
194
+ flushParts();
195
+ }
196
+ catch (err) {
197
+ if (err.name === "AbortError") {
198
+ return;
199
+ }
200
+ if (err instanceof Error) {
201
+ onError(err);
202
+ }
203
+ else {
204
+ onError(new Error(String(err)));
205
+ }
206
+ throw err;
207
+ }
208
+ }
209
+ //# sourceMappingURL=useSessionStreamChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSessionStreamChannel.js","sourceRoot":"","sources":["../../../src/hooks/useSessionStreamChannel.ts"],"names":[],"mappings":"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"}
@@ -5,3 +5,5 @@ export * from "./hooks/useRealtime.js";
5
5
  export * from "./hooks/useTaskTrigger.js";
6
6
  export * from "./hooks/useWaitToken.js";
7
7
  export * from "./hooks/useInputStreamSend.js";
8
+ export * from "./hooks/useSessionStream.js";
9
+ export * from "./hooks/useSessionStreamChannel.js";
@@ -21,4 +21,6 @@ __exportStar(require("./hooks/useRealtime.js"), exports);
21
21
  __exportStar(require("./hooks/useTaskTrigger.js"), exports);
22
22
  __exportStar(require("./hooks/useWaitToken.js"), exports);
23
23
  __exportStar(require("./hooks/useInputStreamSend.js"), exports);
24
+ __exportStar(require("./hooks/useSessionStream.js"), exports);
25
+ __exportStar(require("./hooks/useSessionStreamChannel.js"), exports);
24
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0DAAwC;AACxC,oDAAkC;AAClC,yDAAuC;AACvC,4DAA0C;AAC1C,0DAAwC;AACxC,gEAA8C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0DAAwC;AACxC,oDAAkC;AAClC,yDAAuC;AACvC,4DAA0C;AAC1C,0DAAwC;AACxC,gEAA8C;AAC9C,8DAA4C;AAC5C,qEAAmD"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Keep subscription lifecycles controlled by their effects while using the
3
+ * latest request inputs.
4
+ */
5
+ export declare function useStableRequestCallback(callback: () => Promise<void>): () => Promise<void>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ "use client";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useStableRequestCallback = useStableRequestCallback;
5
+ const react_1 = require("react");
6
+ /**
7
+ * Keep subscription lifecycles controlled by their effects while using the
8
+ * latest request inputs.
9
+ */
10
+ function useStableRequestCallback(callback) {
11
+ const callbackRef = (0, react_1.useRef)(callback);
12
+ (0, react_1.useEffect)(() => {
13
+ callbackRef.current = callback;
14
+ }, [callback]);
15
+ return (0, react_1.useCallback)(() => callbackRef.current(), []);
16
+ }
17
+ //# sourceMappingURL=useStableRequestCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStableRequestCallback.js","sourceRoot":"","sources":["../../../src/utils/useStableRequestCallback.ts"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;AAEb,iCAAuD;AAEvD;;;GAGG;AACH,kCAAyC,QAA6B;IACpE,MAAM,WAAW,GAAG,IAAA,cAAM,EAAC,QAAQ,CAAC,CAAC;IAErC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,OAAO,IAAA,mBAAW,EAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC"}
@@ -12,6 +12,11 @@ export type UseApiClientOptions = {
12
12
  previewBranch?: string;
13
13
  /** Optional additional request configuration */
14
14
  requestOptions?: ApiRequestOptions;
15
+ /**
16
+ * Optional callback that mints a fresh access token. Used to reconnect a
17
+ * realtime stream that the server rejected because its token expired.
18
+ */
19
+ refreshAccessToken?: () => Promise<string>;
15
20
  /**
16
21
  * Enable or disable the API client instance.
17
22
  *
@@ -1,5 +1,6 @@
1
1
  "use client";
2
- import { ApiClient } from "@trigger.dev/core/v3";
2
+ import { ApiClient, refreshAccessTokenOnce } from "@trigger.dev/core/v3";
3
+ import { useCallback, useEffect, useRef } from "react";
3
4
  import { useTriggerAuthContextOptional } from "../contexts.js";
4
5
  /**
5
6
  * Hook to create an API client instance using authentication context or provided options.
@@ -26,6 +27,18 @@ export function useApiClient(options) {
26
27
  const baseUrl = options?.baseURL ?? auth?.baseURL ?? "https://api.trigger.dev";
27
28
  const accessToken = options?.accessToken ?? auth?.accessToken;
28
29
  const previewBranch = options?.previewBranch ?? auth?.previewBranch;
30
+ const refreshAccessToken = options?.refreshAccessToken ?? auth?.refreshAccessToken;
31
+ const refreshAccessTokenRef = useRef(refreshAccessToken);
32
+ useEffect(() => {
33
+ refreshAccessTokenRef.current = refreshAccessToken;
34
+ }, [refreshAccessToken]);
35
+ const stableRefreshAccessToken = useCallback(async () => {
36
+ const refresh = refreshAccessTokenRef.current;
37
+ if (!refresh) {
38
+ throw new Error("Missing refreshAccessToken in TriggerAuthContext or useApiClient options");
39
+ }
40
+ return refreshAccessTokenOnce(refresh);
41
+ }, []);
29
42
  if (!accessToken) {
30
43
  if (options?.enabled === false) {
31
44
  return undefined;
@@ -36,6 +49,6 @@ export function useApiClient(options) {
36
49
  ...auth?.requestOptions,
37
50
  ...options?.requestOptions,
38
51
  };
39
- return new ApiClient(baseUrl, accessToken, previewBranch, requestOptions);
52
+ return new ApiClient(baseUrl, accessToken, previewBranch, requestOptions, undefined, refreshAccessToken ? stableRefreshAccessToken : undefined);
40
53
  }
41
54
  //# sourceMappingURL=useApiClient.js.map