Skip to content

Commit e7ca7d3

Browse files
committed
Add ability to stream results after useTaskTrigger
1 parent 6b24e01 commit e7ca7d3

File tree

9 files changed

+366
-30
lines changed

9 files changed

+366
-30
lines changed

packages/react-hooks/src/hooks/useRealtime.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useApiClient, UseApiClientOptions } from "./useApiClient.js";
99
export type UseRealtimeRunOptions = UseApiClientOptions & {
1010
id?: string;
1111
enabled?: boolean;
12-
throttleInMs?: number;
12+
experimental_throttleInMs?: number;
1313
};
1414

1515
export type UseRealtimeRunInstance<TTask extends AnyTask = AnyTask> = {
@@ -37,7 +37,7 @@ export type UseRealtimeRunInstance<TTask extends AnyTask = AnyTask> = {
3737
* ```
3838
*/
3939
export function useRealtimeRun<TTask extends AnyTask>(
40-
runId: string,
40+
runId?: string,
4141
options?: UseRealtimeRunOptions
4242
): UseRealtimeRunInstance<TTask> {
4343
const hookId = useId();
@@ -71,13 +71,17 @@ export function useRealtimeRun<TTask extends AnyTask>(
7171

7272
const triggerRequest = useCallback(async () => {
7373
try {
74+
if (!runId) {
75+
return;
76+
}
77+
7478
const abortController = new AbortController();
7579
abortControllerRef.current = abortController;
7680

7781
await processRealtimeRun(
7882
runId,
7983
apiClient,
80-
throttle(mutateRun, options?.throttleInMs),
84+
throttle(mutateRun, options?.experimental_throttleInMs),
8185
abortControllerRef
8286
);
8387
} catch (err) {
@@ -96,6 +100,10 @@ export function useRealtimeRun<TTask extends AnyTask>(
96100
return;
97101
}
98102

103+
if (!runId) {
104+
return;
105+
}
106+
99107
triggerRequest().finally(() => {});
100108

101109
return () => {
@@ -130,7 +138,7 @@ export function useRealtimeRunWithStreams<
130138
TTask extends AnyTask = AnyTask,
131139
TStreams extends Record<string, any> = Record<string, any>,
132140
>(
133-
runId: string,
141+
runId?: string,
134142
options?: UseRealtimeRunOptions
135143
): UseRealtimeRunWithStreamsInstance<TTask, TStreams> {
136144
const hookId = useId();
@@ -181,14 +189,18 @@ export function useRealtimeRunWithStreams<
181189

182190
const triggerRequest = useCallback(async () => {
183191
try {
192+
if (!runId) {
193+
return;
194+
}
195+
184196
const abortController = new AbortController();
185197
abortControllerRef.current = abortController;
186198

187199
await processRealtimeRunWithStreams(
188200
runId,
189201
apiClient,
190-
throttle(mutateRun, options?.throttleInMs),
191-
throttle(mutateStreams, options?.throttleInMs),
202+
throttle(mutateRun, options?.experimental_throttleInMs),
203+
throttle(mutateStreams, options?.experimental_throttleInMs),
192204
streamsRef,
193205
abortControllerRef
194206
);
@@ -208,6 +220,10 @@ export function useRealtimeRunWithStreams<
208220
return;
209221
}
210222

223+
if (!runId) {
224+
return;
225+
}
226+
211227
triggerRequest().finally(() => {});
212228

213229
return () => {
@@ -272,7 +288,7 @@ export function useRealtimeRunsWithTag<TTask extends AnyTask>(
272288
await processRealtimeRunsWithTag(
273289
tag,
274290
apiClient,
275-
throttle(mutateRuns, options?.throttleInMs),
291+
throttle(mutateRuns, options?.experimental_throttleInMs),
276292
runsRef,
277293
abortControllerRef
278294
);
@@ -359,7 +375,7 @@ export function useRealtimeBatch<TTask extends AnyTask>(
359375
await processRealtimeBatch(
360376
batchId,
361377
apiClient,
362-
throttle(mutateRuns, options?.throttleInMs),
378+
throttle(mutateRuns, options?.experimental_throttleInMs),
363379
runsRef,
364380
abortControllerRef
365381
);

packages/react-hooks/src/hooks/useTaskTrigger.ts

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,27 @@ import {
1111
TaskRunOptions,
1212
} from "@trigger.dev/core/v3";
1313
import useSWRMutation from "swr/mutation";
14-
import { useApiClient } from "./useApiClient.js";
14+
import { useApiClient, UseApiClientOptions } from "./useApiClient.js";
15+
import {
16+
useRealtimeRun,
17+
UseRealtimeRunInstance,
18+
useRealtimeRunWithStreams,
19+
UseRealtimeRunWithStreamsInstance,
20+
} from "./useRealtime.js";
1521

1622
export interface TriggerInstance<TTask extends AnyTask> {
1723
submit: (payload: TaskPayload<TTask>) => void;
1824
isLoading: boolean;
1925
handle?: RunHandleFromTypes<InferRunTypes<TTask>>;
2026
}
2127

28+
export type UseTaskTriggerOptions = UseApiClientOptions;
29+
2230
export function useTaskTrigger<TTask extends AnyTask>(
23-
id: TaskIdentifier<TTask>
31+
id: TaskIdentifier<TTask>,
32+
options?: UseTaskTriggerOptions
2433
): TriggerInstance<TTask> {
25-
const apiClient = useApiClient();
34+
const apiClient = useApiClient(options);
2635

2736
async function triggerTask(
2837
id: string,
@@ -62,3 +71,58 @@ export function useTaskTrigger<TTask extends AnyTask>(
6271
handle: mutation.data as RunHandleFromTypes<InferRunTypes<TTask>>,
6372
};
6473
}
74+
75+
export type UseRealtimeTaskTriggerOptions = UseTaskTriggerOptions & {
76+
enabled?: boolean;
77+
experimental_throttleInMs?: number;
78+
};
79+
80+
export type RealtimeTriggerInstanceWithStreams<
81+
TTask extends AnyTask,
82+
TStreams extends Record<string, any> = Record<string, any>,
83+
> = UseRealtimeRunWithStreamsInstance<TTask, TStreams> & {
84+
submit: (payload: TaskPayload<TTask>) => void;
85+
isLoading: boolean;
86+
handle?: RunHandleFromTypes<InferRunTypes<TTask>>;
87+
};
88+
89+
export function useRealtimeTaskTriggerWithStreams<
90+
TTask extends AnyTask,
91+
TStreams extends Record<string, any> = Record<string, any>,
92+
>(
93+
id: TaskIdentifier<TTask>,
94+
options?: UseRealtimeTaskTriggerOptions
95+
): RealtimeTriggerInstanceWithStreams<TTask, TStreams> {
96+
const triggerInstance = useTaskTrigger<TTask>(id, options);
97+
const realtimeInstance = useRealtimeRunWithStreams<TTask, TStreams>(triggerInstance.handle?.id, {
98+
...options,
99+
accessToken: triggerInstance.handle?.publicAccessToken ?? options?.accessToken,
100+
});
101+
102+
return {
103+
...realtimeInstance,
104+
...triggerInstance,
105+
};
106+
}
107+
108+
export type RealtimeTriggerInstance<TTask extends AnyTask> = UseRealtimeRunInstance<TTask> & {
109+
submit: (payload: TaskPayload<TTask>) => void;
110+
isLoading: boolean;
111+
handle?: RunHandleFromTypes<InferRunTypes<TTask>>;
112+
};
113+
114+
export function useRealtimeTaskTrigger<TTask extends AnyTask>(
115+
id: TaskIdentifier<TTask>,
116+
options?: UseRealtimeTaskTriggerOptions
117+
): RealtimeTriggerInstance<TTask> {
118+
const triggerInstance = useTaskTrigger<TTask>(id, options);
119+
const realtimeInstance = useRealtimeRun<TTask>(triggerInstance.handle?.id, {
120+
...options,
121+
accessToken: triggerInstance.handle?.publicAccessToken ?? options?.accessToken,
122+
});
123+
124+
return {
125+
...realtimeInstance,
126+
...triggerInstance,
127+
};
128+
}

pnpm-lock.yaml

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

references/nextjs-realtime/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"dependencies": {
1313
"@ai-sdk/openai": "^0.0.72",
1414
"@fal-ai/serverless-client": "^0.15.0",
15+
"@radix-ui/react-dialog": "^1.0.3",
1516
"@radix-ui/react-icons": "^1.3.0",
1617
"@radix-ui/react-scroll-area": "^1.2.0",
1718
"@radix-ui/react-slot": "^1.1.0",

references/nextjs-realtime/src/app/ai/[id]/ClientAiDetails.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ function AiRunDetailsWrapper({ runId, accessToken }: { runId: string; accessToke
88
const { run, streams, error } = useRealtimeRunWithStreams<typeof openaiStreaming, STREAMS>(
99
runId,
1010
{
11-
throttleInMs: 500,
1211
accessToken,
1312
baseURL: process.env.NEXT_PUBLIC_TRIGGER_API_URL,
1413
}

references/nextjs-realtime/src/app/page.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import RunButton from "@/components/RunButton";
22
import BatchRunButton from "@/components/BatchRunButton";
33
import TriggerButton from "@/components/TriggerButton";
4+
import TriggerButtonWithStreaming from "@/components/TriggerButtonWithStreaming";
45
import { ImageUploadDropzone } from "@/components/ImageUploadButton";
56
import { auth } from "@trigger.dev/sdk/v3";
67

@@ -24,7 +25,8 @@ export default async function Home() {
2425
<div className="flex items-center space-x-4 justify-center w-full">
2526
<RunButton />
2627
<BatchRunButton />
27-
<TriggerButton publicAccessToken={publicAccessToken} />
28+
<TriggerButton accessToken={publicAccessToken} />
29+
<TriggerButtonWithStreaming accessToken={publicAccessToken} />
2830
</div>
2931
</main>
3032
);

references/nextjs-realtime/src/components/TriggerButton.tsx

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
import { Button } from "@/components/ui/button";
44
import { type openaiStreaming } from "@/trigger/ai";
5-
import { TriggerAuthContext, useTaskTrigger } from "@trigger.dev/react-hooks";
5+
import { useTaskTrigger } from "@trigger.dev/react-hooks";
66
import { useRouter } from "next/navigation";
77
import { useEffect } from "react";
88

9-
function TriggerButton() {
10-
const { submit, handle, isLoading } = useTaskTrigger<typeof openaiStreaming>("openai-streaming");
9+
export default function TriggerButton({ accessToken }: { accessToken: string }) {
10+
const { submit, handle, isLoading } = useTaskTrigger<typeof openaiStreaming>("openai-streaming", {
11+
accessToken,
12+
baseURL: process.env.NEXT_PUBLIC_TRIGGER_API_URL,
13+
});
1114
const router = useRouter();
1215

1316
useEffect(() => {
@@ -33,17 +36,3 @@ function TriggerButton() {
3336
</Button>
3437
);
3538
}
36-
37-
export default function TriggerButtonClientWrapper({
38-
publicAccessToken,
39-
}: {
40-
publicAccessToken: string;
41-
}) {
42-
return (
43-
<TriggerAuthContext.Provider
44-
value={{ accessToken: publicAccessToken, baseURL: process.env.NEXT_PUBLIC_TRIGGER_API_URL }}
45-
>
46-
<TriggerButton />
47-
</TriggerAuthContext.Provider>
48-
);
49-
}

0 commit comments

Comments
 (0)