@trigger.dev/react-hooks 0.0.0-langsmith-ai-20250111212321 → 0.0.0-next-20260414123825
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/commonjs/hooks/useApiClient.d.ts +2 -0
- package/dist/commonjs/hooks/useApiClient.js +2 -1
- package/dist/commonjs/hooks/useApiClient.js.map +1 -1
- package/dist/commonjs/hooks/useInputStreamSend.d.ts +26 -0
- package/dist/commonjs/hooks/useInputStreamSend.js +45 -0
- package/dist/commonjs/hooks/useInputStreamSend.js.map +1 -0
- package/dist/commonjs/hooks/useRealtime.d.ts +180 -3
- package/dist/commonjs/hooks/useRealtime.js +140 -14
- package/dist/commonjs/hooks/useRealtime.js.map +1 -1
- package/dist/commonjs/hooks/useTaskTrigger.d.ts +7 -1
- package/dist/commonjs/hooks/useTaskTrigger.js +2 -1
- package/dist/commonjs/hooks/useTaskTrigger.js.map +1 -1
- package/dist/commonjs/hooks/useWaitToken.d.ts +35 -0
- package/dist/commonjs/hooks/useWaitToken.js +52 -0
- package/dist/commonjs/hooks/useWaitToken.js.map +1 -0
- package/dist/commonjs/index.d.ts +2 -0
- package/dist/commonjs/index.js +2 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/hooks/useApiClient.d.ts +2 -0
- package/dist/esm/hooks/useApiClient.js +2 -1
- package/dist/esm/hooks/useApiClient.js.map +1 -1
- package/dist/esm/hooks/useInputStreamSend.d.ts +26 -0
- package/dist/esm/hooks/useInputStreamSend.js +39 -0
- package/dist/esm/hooks/useInputStreamSend.js.map +1 -0
- package/dist/esm/hooks/useRealtime.d.ts +180 -3
- package/dist/esm/hooks/useRealtime.js +139 -14
- package/dist/esm/hooks/useRealtime.js.map +1 -1
- package/dist/esm/hooks/useTaskTrigger.d.ts +7 -1
- package/dist/esm/hooks/useTaskTrigger.js +2 -1
- package/dist/esm/hooks/useTaskTrigger.js.map +1 -1
- package/dist/esm/hooks/useWaitToken.d.ts +35 -0
- package/dist/esm/hooks/useWaitToken.js +46 -0
- package/dist/esm/hooks/useWaitToken.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +4 -6
|
@@ -7,6 +7,8 @@ export type UseApiClientOptions = {
|
|
|
7
7
|
accessToken?: string;
|
|
8
8
|
/** Optional base URL for the API endpoints */
|
|
9
9
|
baseURL?: string;
|
|
10
|
+
/** Optional preview branch name for preview environments */
|
|
11
|
+
previewBranch?: string;
|
|
10
12
|
/** Optional additional request configuration */
|
|
11
13
|
requestOptions?: ApiRequestOptions;
|
|
12
14
|
/**
|
|
@@ -28,6 +28,7 @@ function useApiClient(options) {
|
|
|
28
28
|
const auth = (0, contexts_js_1.useTriggerAuthContextOptional)();
|
|
29
29
|
const baseUrl = options?.baseURL ?? auth?.baseURL ?? "https://api.trigger.dev";
|
|
30
30
|
const accessToken = options?.accessToken ?? auth?.accessToken;
|
|
31
|
+
const previewBranch = options?.previewBranch ?? auth?.previewBranch;
|
|
31
32
|
if (!accessToken) {
|
|
32
33
|
if (options?.enabled === false) {
|
|
33
34
|
return undefined;
|
|
@@ -38,6 +39,6 @@ function useApiClient(options) {
|
|
|
38
39
|
...auth?.requestOptions,
|
|
39
40
|
...options?.requestOptions,
|
|
40
41
|
};
|
|
41
|
-
return new v3_1.ApiClient(baseUrl, accessToken, requestOptions);
|
|
42
|
+
return new v3_1.ApiClient(baseUrl, accessToken, previewBranch, requestOptions);
|
|
42
43
|
}
|
|
43
44
|
//# sourceMappingURL=useApiClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useApiClient.js","sourceRoot":"","sources":["../../../src/hooks/useApiClient.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;
|
|
1
|
+
{"version":3,"file":"useApiClient.js","sourceRoot":"","sources":["../../../src/hooks/useApiClient.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;AA8Cb,oCAoBC;AAhED,6CAAoE;AACpE,gDAA+D;AAuB/D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,YAAY,CAAC,OAA6B;IACxD,MAAM,IAAI,GAAG,IAAA,2CAA6B,GAAE,CAAC;IAE7C,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,OAAO,IAAI,yBAAyB,CAAC;IAC/E,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,IAAI,EAAE,WAAW,CAAC;IAC9D,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,IAAI,EAAE,aAAa,CAAC;IACpE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,OAAO,EAAE,OAAO,KAAK,KAAK,EAAE,CAAC;YAC/B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,cAAc,GAAsB;QACxC,GAAG,IAAI,EAAE,cAAc;QACvB,GAAG,OAAO,EAAE,cAAc;KAC3B,CAAC;IAEF,OAAO,IAAI,cAAS,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { UseApiClientOptions } from "./useApiClient.js";
|
|
2
|
+
export interface InputStreamSendInstance<TData> {
|
|
3
|
+
/** Send data to the input stream */
|
|
4
|
+
send: (data: TData) => void;
|
|
5
|
+
/** Whether a send is currently in progress */
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
/** Any error that occurred during the last send */
|
|
8
|
+
error?: Error;
|
|
9
|
+
/** Whether the hook is ready to send (has runId and access token) */
|
|
10
|
+
isReady: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Hook to send data to an input stream on a running task.
|
|
14
|
+
*
|
|
15
|
+
* @template TData - The type of data to send
|
|
16
|
+
* @param streamId - The input stream identifier
|
|
17
|
+
* @param runId - The run to send input stream data to
|
|
18
|
+
* @param options - API client options (e.g. accessToken)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { send, isLoading } = useInputStreamSend("my-stream", runId, { accessToken });
|
|
23
|
+
* send({ message: "hello" });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function useInputStreamSend<TData>(streamId: string, runId?: string, options?: UseApiClientOptions): InputStreamSendInstance<TData>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.useInputStreamSend = useInputStreamSend;
|
|
8
|
+
const mutation_1 = __importDefault(require("swr/mutation"));
|
|
9
|
+
const useApiClient_js_1 = require("./useApiClient.js");
|
|
10
|
+
/**
|
|
11
|
+
* Hook to send data to an input stream on a running task.
|
|
12
|
+
*
|
|
13
|
+
* @template TData - The type of data to send
|
|
14
|
+
* @param streamId - The input stream identifier
|
|
15
|
+
* @param runId - The run to send input stream data to
|
|
16
|
+
* @param options - API client options (e.g. accessToken)
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { send, isLoading } = useInputStreamSend("my-stream", runId, { accessToken });
|
|
21
|
+
* send({ message: "hello" });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function useInputStreamSend(streamId, runId, options) {
|
|
25
|
+
const apiClient = (0, useApiClient_js_1.useApiClient)(options);
|
|
26
|
+
async function sendToStream(key, { arg }) {
|
|
27
|
+
if (!apiClient) {
|
|
28
|
+
throw new Error("Could not send to input stream: Missing access token");
|
|
29
|
+
}
|
|
30
|
+
if (!runId) {
|
|
31
|
+
throw new Error("Could not send to input stream: Missing run ID");
|
|
32
|
+
}
|
|
33
|
+
return await apiClient.sendInputStream(runId, streamId, arg.data);
|
|
34
|
+
}
|
|
35
|
+
const mutation = (0, mutation_1.default)(runId ? `input-stream:${runId}:${streamId}` : null, sendToStream);
|
|
36
|
+
return {
|
|
37
|
+
send: (data) => {
|
|
38
|
+
mutation.trigger({ data });
|
|
39
|
+
},
|
|
40
|
+
isLoading: mutation.isMutating,
|
|
41
|
+
isReady: !!runId && !!apiClient,
|
|
42
|
+
error: mutation.error,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=useInputStreamSend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInputStreamSend.js","sourceRoot":"","sources":["../../../src/hooks/useInputStreamSend.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;AA8Bb,gDA6BC;AAzDD,4DAA0C;AAC1C,uDAAsE;AAatE;;;;;;;;;;;;;GAaG;AACH,SAAgB,kBAAkB,CAChC,QAAgB,EAChB,KAAc,EACd,OAA6B;IAE7B,MAAM,SAAS,GAAG,IAAA,8BAAY,EAAC,OAAO,CAAC,CAAC;IAExC,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,EAAE,GAAG,EAA4B;QACxE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,MAAM,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,kBAAc,EAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAElG,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;YACb,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7B,CAAC;QACD,SAAS,EAAE,QAAQ,CAAC,UAAU;QAC9B,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS;QAC/B,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;AACJ,CAAC"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { AnyTask, RealtimeRun } from "@trigger.dev/core/v3";
|
|
1
|
+
import { AnyTask, InferStreamType, RealtimeDefinedStream, RealtimeRun, RealtimeRunSkipColumns } from "@trigger.dev/core/v3";
|
|
2
2
|
import { UseApiClientOptions } from "./useApiClient.js";
|
|
3
3
|
export type UseRealtimeRunOptions = UseApiClientOptions & {
|
|
4
4
|
id?: string;
|
|
5
5
|
enabled?: boolean;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The number of milliseconds to throttle the stream updates.
|
|
8
|
+
*
|
|
9
|
+
* @default 16
|
|
10
|
+
*/
|
|
11
|
+
throttleInMs?: number;
|
|
7
12
|
};
|
|
8
13
|
export type UseRealtimeSingleRunOptions<TTask extends AnyTask = AnyTask> = UseRealtimeRunOptions & {
|
|
9
14
|
/**
|
|
@@ -21,6 +26,12 @@ export type UseRealtimeSingleRunOptions<TTask extends AnyTask = AnyTask> = UseRe
|
|
|
21
26
|
* Set this to false if you are making updates to the run metadata after completion through child runs
|
|
22
27
|
*/
|
|
23
28
|
stopOnCompletion?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Skip columns from the subscription.
|
|
31
|
+
*
|
|
32
|
+
* @default []
|
|
33
|
+
*/
|
|
34
|
+
skipColumns?: RealtimeRunSkipColumns;
|
|
24
35
|
};
|
|
25
36
|
export type UseRealtimeRunInstance<TTask extends AnyTask = AnyTask> = {
|
|
26
37
|
run: RealtimeRun<TTask> | undefined;
|
|
@@ -83,6 +94,30 @@ export type UseRealtimeRunsInstance<TTask extends AnyTask = AnyTask> = {
|
|
|
83
94
|
*/
|
|
84
95
|
stop: () => void;
|
|
85
96
|
};
|
|
97
|
+
export type UseRealtimeRunsWithTagOptions = UseRealtimeRunOptions & {
|
|
98
|
+
/**
|
|
99
|
+
* Filter runs by the time they were created. You must specify the duration string like "1h", "10s", "30m", etc.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* "1h" - 1 hour ago
|
|
103
|
+
* "10s" - 10 seconds ago
|
|
104
|
+
* "30m" - 30 minutes ago
|
|
105
|
+
* "1d" - 1 day ago
|
|
106
|
+
* "1w" - 1 week ago
|
|
107
|
+
*
|
|
108
|
+
* The maximum duration is 1 week
|
|
109
|
+
*
|
|
110
|
+
* @note The timestamp will be calculated on the server side when you first subscribe to the runs.
|
|
111
|
+
*
|
|
112
|
+
*/
|
|
113
|
+
createdAt?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Skip columns from the subscription.
|
|
116
|
+
*
|
|
117
|
+
* @default []
|
|
118
|
+
*/
|
|
119
|
+
skipColumns?: RealtimeRunSkipColumns;
|
|
120
|
+
};
|
|
86
121
|
/**
|
|
87
122
|
* Hook to subscribe to realtime updates of task runs filtered by tag(s).
|
|
88
123
|
*
|
|
@@ -97,9 +132,11 @@ export type UseRealtimeRunsInstance<TTask extends AnyTask = AnyTask> = {
|
|
|
97
132
|
* const { runs, error } = useRealtimeRunsWithTag<typeof myTask>('my-tag');
|
|
98
133
|
* // Or with multiple tags
|
|
99
134
|
* const { runs, error } = useRealtimeRunsWithTag<typeof myTask>(['tag1', 'tag2']);
|
|
135
|
+
* // Or with a createdAt filter
|
|
136
|
+
* const { runs, error } = useRealtimeRunsWithTag<typeof myTask>('my-tag', { createdAt: '1h' });
|
|
100
137
|
* ```
|
|
101
138
|
*/
|
|
102
|
-
export declare function useRealtimeRunsWithTag<TTask extends AnyTask>(tag: string | string[], options?:
|
|
139
|
+
export declare function useRealtimeRunsWithTag<TTask extends AnyTask>(tag: string | string[], options?: UseRealtimeRunsWithTagOptions): UseRealtimeRunsInstance<TTask>;
|
|
103
140
|
/**
|
|
104
141
|
* Hook to subscribe to realtime updates of a batch of task runs.
|
|
105
142
|
*
|
|
@@ -115,3 +152,143 @@ export declare function useRealtimeRunsWithTag<TTask extends AnyTask>(tag: strin
|
|
|
115
152
|
* ```
|
|
116
153
|
*/
|
|
117
154
|
export declare function useRealtimeBatch<TTask extends AnyTask>(batchId: string, options?: UseRealtimeRunOptions): UseRealtimeRunsInstance<TTask>;
|
|
155
|
+
export type UseRealtimeStreamInstance<TPart> = {
|
|
156
|
+
parts: Array<TPart>;
|
|
157
|
+
error: Error | undefined;
|
|
158
|
+
/**
|
|
159
|
+
* Abort the current request immediately, keep the generated tokens if any.
|
|
160
|
+
*/
|
|
161
|
+
stop: () => void;
|
|
162
|
+
};
|
|
163
|
+
export type UseRealtimeStreamOptions<TPart> = UseApiClientOptions & {
|
|
164
|
+
id?: string;
|
|
165
|
+
enabled?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* The number of milliseconds to throttle the stream updates.
|
|
168
|
+
*
|
|
169
|
+
* @default 16
|
|
170
|
+
*/
|
|
171
|
+
throttleInMs?: number;
|
|
172
|
+
/**
|
|
173
|
+
* The number of seconds to wait for new data to be available,
|
|
174
|
+
* If no data arrives within the timeout, the stream will be closed.
|
|
175
|
+
*
|
|
176
|
+
* @default 60 seconds
|
|
177
|
+
*/
|
|
178
|
+
timeoutInSeconds?: number;
|
|
179
|
+
/**
|
|
180
|
+
* The index to start reading from.
|
|
181
|
+
* If not provided, the stream will start from the beginning.
|
|
182
|
+
* @default 0
|
|
183
|
+
*/
|
|
184
|
+
startIndex?: number;
|
|
185
|
+
/**
|
|
186
|
+
* Callback this is called when new data is received.
|
|
187
|
+
*/
|
|
188
|
+
onData?: (data: TPart) => void;
|
|
189
|
+
};
|
|
190
|
+
export declare function useRealtimeStream<TDefinedStream extends RealtimeDefinedStream<any>>(stream: TDefinedStream, runId: string, options?: UseRealtimeStreamOptions<InferStreamType<TDefinedStream>>): UseRealtimeStreamInstance<InferStreamType<TDefinedStream>>;
|
|
191
|
+
/**
|
|
192
|
+
* Hook to subscribe to realtime updates of a stream with a specific stream key.
|
|
193
|
+
*
|
|
194
|
+
* This hook automatically subscribes to a stream and updates the `parts` array as new data arrives.
|
|
195
|
+
* The stream subscription is automatically managed: it starts when the component mounts (or when
|
|
196
|
+
* `enabled` becomes `true`) and stops when the component unmounts or when `stop()` is called.
|
|
197
|
+
*
|
|
198
|
+
* @template TPart - The type of each chunk/part in the stream
|
|
199
|
+
* @param runId - The unique identifier of the run to subscribe to
|
|
200
|
+
* @param streamKey - The unique identifier of the stream to subscribe to. Use this overload
|
|
201
|
+
* when you want to read from a specific stream key.
|
|
202
|
+
* @param options - Optional configuration for the stream subscription
|
|
203
|
+
* @returns An object containing:
|
|
204
|
+
* - `parts`: An array of all stream chunks received so far (accumulates over time)
|
|
205
|
+
* - `error`: Any error that occurred during subscription
|
|
206
|
+
* - `stop`: A function to manually stop the subscription
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```tsx
|
|
210
|
+
* "use client";
|
|
211
|
+
* import { useRealtimeStream } from "@trigger.dev/react-hooks";
|
|
212
|
+
*
|
|
213
|
+
* function StreamViewer({ runId }: { runId: string }) {
|
|
214
|
+
* const { parts, error } = useRealtimeStream<string>(
|
|
215
|
+
* runId,
|
|
216
|
+
* "my-stream",
|
|
217
|
+
* {
|
|
218
|
+
* accessToken: process.env.NEXT_PUBLIC_TRIGGER_PUBLIC_KEY,
|
|
219
|
+
* }
|
|
220
|
+
* );
|
|
221
|
+
*
|
|
222
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
223
|
+
*
|
|
224
|
+
* // Parts array accumulates all chunks
|
|
225
|
+
* const fullText = parts.join("");
|
|
226
|
+
*
|
|
227
|
+
* return <div>{fullText}</div>;
|
|
228
|
+
* }
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```tsx
|
|
233
|
+
* // With custom options
|
|
234
|
+
* const { parts, error, stop } = useRealtimeStream<ChatChunk>(
|
|
235
|
+
* runId,
|
|
236
|
+
* "chat-stream",
|
|
237
|
+
* {
|
|
238
|
+
* accessToken: publicKey,
|
|
239
|
+
* timeoutInSeconds: 120,
|
|
240
|
+
* startIndex: 10, // Start from the 10th chunk
|
|
241
|
+
* throttleInMs: 50, // Throttle updates to every 50ms
|
|
242
|
+
* onData: (chunk) => {
|
|
243
|
+
* console.log("New chunk received:", chunk);
|
|
244
|
+
* },
|
|
245
|
+
* }
|
|
246
|
+
* );
|
|
247
|
+
*
|
|
248
|
+
* // Manually stop the subscription
|
|
249
|
+
* <button onClick={stop}>Stop Stream</button>
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
export declare function useRealtimeStream<TPart>(runId: string, streamKey: string, options?: UseRealtimeStreamOptions<TPart>): UseRealtimeStreamInstance<TPart>;
|
|
253
|
+
/**
|
|
254
|
+
* Hook to subscribe to realtime updates of a stream using the default stream key (`"default"`).
|
|
255
|
+
*
|
|
256
|
+
* This is a convenience overload that allows you to subscribe to the default stream without
|
|
257
|
+
* specifying a stream key. The stream will be accessed with the key `"default"`.
|
|
258
|
+
*
|
|
259
|
+
* @template TPart - The type of each chunk/part in the stream
|
|
260
|
+
* @param runId - The unique identifier of the run to subscribe to
|
|
261
|
+
* @param options - Optional configuration for the stream subscription
|
|
262
|
+
* @returns An object containing:
|
|
263
|
+
* - `parts`: An array of all stream chunks received so far (accumulates over time)
|
|
264
|
+
* - `error`: Any error that occurred during subscription
|
|
265
|
+
* - `stop`: A function to manually stop the subscription
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```tsx
|
|
269
|
+
* "use client";
|
|
270
|
+
* import { useRealtimeStream } from "@trigger.dev/react-hooks";
|
|
271
|
+
*
|
|
272
|
+
* function DefaultStreamViewer({ runId }: { runId: string }) {
|
|
273
|
+
* // Subscribe to the default stream
|
|
274
|
+
* const { parts, error } = useRealtimeStream<string>(runId, {
|
|
275
|
+
* accessToken: process.env.NEXT_PUBLIC_TRIGGER_PUBLIC_KEY,
|
|
276
|
+
* });
|
|
277
|
+
*
|
|
278
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
279
|
+
*
|
|
280
|
+
* const fullText = parts.join("");
|
|
281
|
+
* return <div>{fullText}</div>;
|
|
282
|
+
* }
|
|
283
|
+
* ```
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```tsx
|
|
287
|
+
* // Conditionally enable the stream
|
|
288
|
+
* const { parts } = useRealtimeStream<string>(runId, {
|
|
289
|
+
* accessToken: publicKey,
|
|
290
|
+
* enabled: !!runId && isStreaming, // Only subscribe when runId exists and isStreaming is true
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
export declare function useRealtimeStream<TPart>(runId: string, options?: UseRealtimeStreamOptions<TPart>): UseRealtimeStreamInstance<TPart>;
|
|
@@ -5,6 +5,7 @@ exports.useRealtimeRun = useRealtimeRun;
|
|
|
5
5
|
exports.useRealtimeRunWithStreams = useRealtimeRunWithStreams;
|
|
6
6
|
exports.useRealtimeRunsWithTag = useRealtimeRunsWithTag;
|
|
7
7
|
exports.useRealtimeBatch = useRealtimeBatch;
|
|
8
|
+
exports.useRealtimeStream = useRealtimeStream;
|
|
8
9
|
const react_1 = require("react");
|
|
9
10
|
const trigger_swr_js_1 = require("../utils/trigger-swr.js");
|
|
10
11
|
const useApiClient_js_1 = require("./useApiClient.js");
|
|
@@ -47,7 +48,7 @@ function useRealtimeRun(runId, options) {
|
|
|
47
48
|
}
|
|
48
49
|
const abortController = new AbortController();
|
|
49
50
|
abortControllerRef.current = abortController;
|
|
50
|
-
await processRealtimeRun(runId, apiClient, mutateRun, setError, abortControllerRef, typeof options?.stopOnCompletion === "boolean" ? options.stopOnCompletion : true);
|
|
51
|
+
await processRealtimeRun(runId, { skipColumns: options?.skipColumns }, apiClient, mutateRun, setError, abortControllerRef, typeof options?.stopOnCompletion === "boolean" ? options.stopOnCompletion : true);
|
|
51
52
|
}
|
|
52
53
|
catch (err) {
|
|
53
54
|
// Ignore abort errors as they are expected.
|
|
@@ -67,8 +68,10 @@ function useRealtimeRun(runId, options) {
|
|
|
67
68
|
}, [runId, mutateRun, abortControllerRef, apiClient, setError]);
|
|
68
69
|
const hasCalledOnCompleteRef = (0, react_1.useRef)(false);
|
|
69
70
|
// Effect to handle onComplete callback
|
|
71
|
+
// Only call onComplete when the run has actually finished (has finishedAt),
|
|
72
|
+
// not just when the subscription stream ends (which can happen due to network issues)
|
|
70
73
|
(0, react_1.useEffect)(() => {
|
|
71
|
-
if (isComplete && run && options?.onComplete && !hasCalledOnCompleteRef.current) {
|
|
74
|
+
if (isComplete && run?.finishedAt && options?.onComplete && !hasCalledOnCompleteRef.current) {
|
|
72
75
|
options.onComplete(run, error);
|
|
73
76
|
hasCalledOnCompleteRef.current = true;
|
|
74
77
|
}
|
|
@@ -143,7 +146,7 @@ function useRealtimeRunWithStreams(runId, options) {
|
|
|
143
146
|
}
|
|
144
147
|
const abortController = new AbortController();
|
|
145
148
|
abortControllerRef.current = abortController;
|
|
146
|
-
await processRealtimeRunWithStreams(runId, apiClient, mutateRun, mutateStreams, streamsRef, setError, abortControllerRef, typeof options?.stopOnCompletion === "boolean" ? options.stopOnCompletion : true, options?.
|
|
149
|
+
await processRealtimeRunWithStreams(runId, { skipColumns: options?.skipColumns }, apiClient, mutateRun, mutateStreams, streamsRef, setError, abortControllerRef, typeof options?.stopOnCompletion === "boolean" ? options.stopOnCompletion : true, options?.throttleInMs ?? 16);
|
|
147
150
|
}
|
|
148
151
|
catch (err) {
|
|
149
152
|
// Ignore abort errors as they are expected.
|
|
@@ -163,8 +166,10 @@ function useRealtimeRunWithStreams(runId, options) {
|
|
|
163
166
|
}, [runId, mutateRun, mutateStreams, streamsRef, abortControllerRef, apiClient, setError]);
|
|
164
167
|
const hasCalledOnCompleteRef = (0, react_1.useRef)(false);
|
|
165
168
|
// Effect to handle onComplete callback
|
|
169
|
+
// Only call onComplete when the run has actually finished (has finishedAt),
|
|
170
|
+
// not just when the subscription stream ends (which can happen due to network issues)
|
|
166
171
|
(0, react_1.useEffect)(() => {
|
|
167
|
-
if (isComplete && run && options?.onComplete && !hasCalledOnCompleteRef.current) {
|
|
172
|
+
if (isComplete && run?.finishedAt && options?.onComplete && !hasCalledOnCompleteRef.current) {
|
|
168
173
|
options.onComplete(run, error);
|
|
169
174
|
hasCalledOnCompleteRef.current = true;
|
|
170
175
|
}
|
|
@@ -202,9 +207,12 @@ function useRealtimeRunWithStreams(runId, options) {
|
|
|
202
207
|
* const { runs, error } = useRealtimeRunsWithTag<typeof myTask>('my-tag');
|
|
203
208
|
* // Or with multiple tags
|
|
204
209
|
* const { runs, error } = useRealtimeRunsWithTag<typeof myTask>(['tag1', 'tag2']);
|
|
210
|
+
* // Or with a createdAt filter
|
|
211
|
+
* const { runs, error } = useRealtimeRunsWithTag<typeof myTask>('my-tag', { createdAt: '1h' });
|
|
205
212
|
* ```
|
|
206
213
|
*/
|
|
207
214
|
function useRealtimeRunsWithTag(tag, options) {
|
|
215
|
+
const normalizedTag = (Array.isArray(tag) ? tag : [tag]).join("-");
|
|
208
216
|
const hookId = (0, react_1.useId)();
|
|
209
217
|
const idKey = options?.id ?? hookId;
|
|
210
218
|
// Store the streams state in SWR, using the idKey as the key to share states.
|
|
@@ -233,7 +241,7 @@ function useRealtimeRunsWithTag(tag, options) {
|
|
|
233
241
|
}
|
|
234
242
|
const abortController = new AbortController();
|
|
235
243
|
abortControllerRef.current = abortController;
|
|
236
|
-
await processRealtimeRunsWithTag(tag, apiClient, mutateRuns, runsRef, setError, abortControllerRef);
|
|
244
|
+
await processRealtimeRunsWithTag(tag, { createdAt: options?.createdAt, skipColumns: options?.skipColumns }, apiClient, mutateRuns, runsRef, setError, abortControllerRef);
|
|
237
245
|
}
|
|
238
246
|
catch (err) {
|
|
239
247
|
// Ignore abort errors as they are expected.
|
|
@@ -248,7 +256,7 @@ function useRealtimeRunsWithTag(tag, options) {
|
|
|
248
256
|
abortControllerRef.current = null;
|
|
249
257
|
}
|
|
250
258
|
}
|
|
251
|
-
}, [
|
|
259
|
+
}, [normalizedTag, mutateRuns, runsRef, abortControllerRef, apiClient, setError]);
|
|
252
260
|
(0, react_1.useEffect)(() => {
|
|
253
261
|
if (typeof options?.enabled === "boolean" && !options.enabled) {
|
|
254
262
|
return;
|
|
@@ -257,7 +265,7 @@ function useRealtimeRunsWithTag(tag, options) {
|
|
|
257
265
|
return () => {
|
|
258
266
|
stop();
|
|
259
267
|
};
|
|
260
|
-
}, [
|
|
268
|
+
}, [normalizedTag, stop, options?.enabled]);
|
|
261
269
|
return { runs: runs ?? [], error, stop };
|
|
262
270
|
}
|
|
263
271
|
/**
|
|
@@ -330,6 +338,93 @@ function useRealtimeBatch(batchId, options) {
|
|
|
330
338
|
}, [batchId, stop, options?.enabled]);
|
|
331
339
|
return { runs: runs ?? [], error, stop };
|
|
332
340
|
}
|
|
341
|
+
function useRealtimeStream(runIdOrDefinedStream, streamKeyOrOptionsOrRunId, options) {
|
|
342
|
+
if (typeof runIdOrDefinedStream === "string") {
|
|
343
|
+
if (typeof streamKeyOrOptionsOrRunId === "string") {
|
|
344
|
+
return useRealtimeStreamImplementation(runIdOrDefinedStream, streamKeyOrOptionsOrRunId, options);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
return useRealtimeStreamImplementation(runIdOrDefinedStream, "default", streamKeyOrOptionsOrRunId);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
if (typeof streamKeyOrOptionsOrRunId === "string") {
|
|
352
|
+
return useRealtimeStreamImplementation(streamKeyOrOptionsOrRunId, runIdOrDefinedStream.id, options);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
throw new Error("Invalid second argument to useRealtimeStream. When using a defined stream instance, the second argument to useRealtimeStream must be a run ID.");
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function useRealtimeStreamImplementation(runId, streamKey, options) {
|
|
360
|
+
const hookId = (0, react_1.useId)();
|
|
361
|
+
const idKey = options?.id ?? hookId;
|
|
362
|
+
const [initialPartsFallback] = (0, react_1.useState)([]);
|
|
363
|
+
// Store the streams state in SWR, using the idKey as the key to share states.
|
|
364
|
+
const { data: parts, mutate: mutateParts } = (0, trigger_swr_js_1.useSWR)([idKey, runId, streamKey, "parts"], null, {
|
|
365
|
+
fallbackData: initialPartsFallback,
|
|
366
|
+
});
|
|
367
|
+
// Keep the latest streams in a ref.
|
|
368
|
+
const partsRef = (0, react_1.useRef)(parts ?? []);
|
|
369
|
+
(0, react_1.useEffect)(() => {
|
|
370
|
+
partsRef.current = parts || [];
|
|
371
|
+
}, [parts]);
|
|
372
|
+
// Add state to track when the subscription is complete
|
|
373
|
+
const { data: isComplete = false, mutate: setIsComplete } = (0, trigger_swr_js_1.useSWR)([idKey, runId, streamKey, "complete"], null);
|
|
374
|
+
const { data: error = undefined, mutate: setError } = (0, trigger_swr_js_1.useSWR)([idKey, runId, streamKey, "error"], null);
|
|
375
|
+
// Abort controller to cancel the current API call.
|
|
376
|
+
const abortControllerRef = (0, react_1.useRef)(null);
|
|
377
|
+
const stop = (0, react_1.useCallback)(() => {
|
|
378
|
+
if (abortControllerRef.current) {
|
|
379
|
+
abortControllerRef.current.abort();
|
|
380
|
+
abortControllerRef.current = null;
|
|
381
|
+
}
|
|
382
|
+
}, []);
|
|
383
|
+
const onData = (0, react_1.useCallback)((data) => {
|
|
384
|
+
if (options?.onData) {
|
|
385
|
+
options.onData(data);
|
|
386
|
+
}
|
|
387
|
+
}, [options?.onData]);
|
|
388
|
+
const apiClient = (0, useApiClient_js_1.useApiClient)(options);
|
|
389
|
+
const triggerRequest = (0, react_1.useCallback)(async () => {
|
|
390
|
+
try {
|
|
391
|
+
if (!runId || !apiClient) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const abortController = new AbortController();
|
|
395
|
+
abortControllerRef.current = abortController;
|
|
396
|
+
await processRealtimeStream(runId, streamKey, apiClient, mutateParts, partsRef, setError, onData, abortControllerRef, options?.timeoutInSeconds, options?.startIndex, options?.throttleInMs ?? 16);
|
|
397
|
+
}
|
|
398
|
+
catch (err) {
|
|
399
|
+
// Ignore abort errors as they are expected.
|
|
400
|
+
if (err.name === "AbortError") {
|
|
401
|
+
abortControllerRef.current = null;
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
setError(err);
|
|
405
|
+
}
|
|
406
|
+
finally {
|
|
407
|
+
if (abortControllerRef.current) {
|
|
408
|
+
abortControllerRef.current = null;
|
|
409
|
+
}
|
|
410
|
+
// Mark the subscription as complete
|
|
411
|
+
setIsComplete(true);
|
|
412
|
+
}
|
|
413
|
+
}, [runId, streamKey, mutateParts, partsRef, abortControllerRef, apiClient, setError]);
|
|
414
|
+
(0, react_1.useEffect)(() => {
|
|
415
|
+
if (typeof options?.enabled === "boolean" && !options.enabled) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!runId) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
triggerRequest().finally(() => { });
|
|
422
|
+
return () => {
|
|
423
|
+
stop();
|
|
424
|
+
};
|
|
425
|
+
}, [runId, stop, options?.enabled]);
|
|
426
|
+
return { parts: parts ?? initialPartsFallback, error, stop };
|
|
427
|
+
}
|
|
333
428
|
async function processRealtimeBatch(batchId, apiClient, mutateRunsData, existingRunsRef, onError, abortControllerRef) {
|
|
334
429
|
const subscription = apiClient.subscribeToBatch(batchId, {
|
|
335
430
|
signal: abortControllerRef.current?.signal,
|
|
@@ -339,21 +434,21 @@ async function processRealtimeBatch(batchId, apiClient, mutateRunsData, existing
|
|
|
339
434
|
mutateRunsData(insertRunShapeInOrder(existingRunsRef.current, part));
|
|
340
435
|
}
|
|
341
436
|
}
|
|
342
|
-
// Inserts and then orders by the run
|
|
437
|
+
// Inserts and then orders by the run createdAt timestamp, and ensures that the run is not duplicated
|
|
343
438
|
function insertRunShapeInOrder(previousRuns, run) {
|
|
344
439
|
const existingRun = previousRuns.find((r) => r.id === run.id);
|
|
345
440
|
if (existingRun) {
|
|
346
441
|
return previousRuns.map((r) => (r.id === run.id ? run : r));
|
|
347
442
|
}
|
|
348
|
-
const
|
|
349
|
-
const index = previousRuns.findIndex((r) => r.
|
|
443
|
+
const runCreatedAt = run.createdAt;
|
|
444
|
+
const index = previousRuns.findIndex((r) => r.createdAt > runCreatedAt);
|
|
350
445
|
if (index === -1) {
|
|
351
446
|
return [...previousRuns, run];
|
|
352
447
|
}
|
|
353
448
|
return [...previousRuns.slice(0, index), run, ...previousRuns.slice(index)];
|
|
354
449
|
}
|
|
355
|
-
async function processRealtimeRunsWithTag(tag, apiClient, mutateRunsData, existingRunsRef, onError, abortControllerRef) {
|
|
356
|
-
const subscription = apiClient.subscribeToRunsWithTag(tag, {
|
|
450
|
+
async function processRealtimeRunsWithTag(tag, filters, apiClient, mutateRunsData, existingRunsRef, onError, abortControllerRef) {
|
|
451
|
+
const subscription = apiClient.subscribeToRunsWithTag(tag, filters, {
|
|
357
452
|
signal: abortControllerRef.current?.signal,
|
|
358
453
|
onFetchError: onError,
|
|
359
454
|
});
|
|
@@ -374,11 +469,12 @@ function insertRunShape(previousRuns, run) {
|
|
|
374
469
|
}
|
|
375
470
|
return [...previousRuns.slice(0, index), run, ...previousRuns.slice(index)];
|
|
376
471
|
}
|
|
377
|
-
async function processRealtimeRunWithStreams(runId, apiClient, mutateRunData, mutateStreamData, existingDataRef, onError, abortControllerRef, stopOnCompletion = true, throttleInMs) {
|
|
472
|
+
async function processRealtimeRunWithStreams(runId, filters, apiClient, mutateRunData, mutateStreamData, existingDataRef, onError, abortControllerRef, stopOnCompletion = true, throttleInMs) {
|
|
378
473
|
const subscription = apiClient.subscribeToRun(runId, {
|
|
379
474
|
signal: abortControllerRef.current?.signal,
|
|
380
475
|
closeOnComplete: stopOnCompletion,
|
|
381
476
|
onFetchError: onError,
|
|
477
|
+
skipColumns: filters.skipColumns,
|
|
382
478
|
});
|
|
383
479
|
const streamQueue = (0, throttle_js_1.createThrottledQueue)(async (updates) => {
|
|
384
480
|
const nextStreamData = { ...existingDataRef.current };
|
|
@@ -410,14 +506,44 @@ async function processRealtimeRunWithStreams(runId, apiClient, mutateRunData, mu
|
|
|
410
506
|
}
|
|
411
507
|
}
|
|
412
508
|
}
|
|
413
|
-
async function processRealtimeRun(runId, apiClient, mutateRunData, onError, abortControllerRef, stopOnCompletion = true) {
|
|
509
|
+
async function processRealtimeRun(runId, filters, apiClient, mutateRunData, onError, abortControllerRef, stopOnCompletion = true) {
|
|
414
510
|
const subscription = apiClient.subscribeToRun(runId, {
|
|
415
511
|
signal: abortControllerRef.current?.signal,
|
|
416
512
|
closeOnComplete: stopOnCompletion,
|
|
417
513
|
onFetchError: onError,
|
|
514
|
+
skipColumns: filters.skipColumns,
|
|
418
515
|
});
|
|
419
516
|
for await (const part of subscription) {
|
|
420
517
|
mutateRunData(part);
|
|
421
518
|
}
|
|
422
519
|
}
|
|
520
|
+
async function processRealtimeStream(runId, streamKey, apiClient, mutatePartsData, existingPartsRef, onError, onData, abortControllerRef, timeoutInSeconds, startIndex, throttleInMs) {
|
|
521
|
+
try {
|
|
522
|
+
const stream = await apiClient.fetchStream(runId, streamKey, {
|
|
523
|
+
signal: abortControllerRef.current?.signal,
|
|
524
|
+
timeoutInSeconds,
|
|
525
|
+
lastEventId: startIndex ? (startIndex - 1).toString() : undefined,
|
|
526
|
+
});
|
|
527
|
+
// Throttle the stream
|
|
528
|
+
const streamQueue = (0, throttle_js_1.createThrottledQueue)(async (parts) => {
|
|
529
|
+
mutatePartsData([...existingPartsRef.current, ...parts]);
|
|
530
|
+
}, throttleInMs);
|
|
531
|
+
for await (const part of stream) {
|
|
532
|
+
onData(part);
|
|
533
|
+
streamQueue.add(part);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch (err) {
|
|
537
|
+
if (err.name === "AbortError") {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (err instanceof Error) {
|
|
541
|
+
onError(err);
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
onError(new Error(String(err)));
|
|
545
|
+
}
|
|
546
|
+
throw err;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
423
549
|
//# sourceMappingURL=useRealtime.js.map
|