Skip to content

Commit ffb91a1

Browse files
Support async payload and trigger option resolvers
Co-authored-by: Eric Allam <eric@trigger.dev>
1 parent 390e53c commit ffb91a1

File tree

5 files changed

+42
-8
lines changed

5 files changed

+42
-8
lines changed

packages/ai/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ type Payload = TriggerChatTransportPayload<UIMessage>;
6161

6262
## Custom payload mapping
6363

64-
If your task expects a custom payload shape, provide `payloadMapper`:
64+
If your task expects a custom payload shape, provide `payloadMapper` (sync or async):
6565

6666
```ts
6767
import { TriggerChatTransport } from "@trigger.dev/ai";
@@ -73,7 +73,9 @@ const transport = new TriggerChatTransport<
7373
>({
7474
task: "ai-chat-custom",
7575
accessToken: "pk_...",
76-
payloadMapper: function payloadMapper(request) {
76+
payloadMapper: async function payloadMapper(request) {
77+
await Promise.resolve();
78+
7779
const firstPart = request.messages[0]?.parts[0];
7880

7981
return {
@@ -87,6 +89,9 @@ const transport = new TriggerChatTransport<
8789
});
8890
```
8991

92+
`triggerOptions` can also be a function (sync or async), which gives you access to
93+
`chatId`, messages, and request context to compute queueing/idempotency options.
94+
9095
## Optional persistent run state
9196

9297
`TriggerChatTransport` supports custom run stores (including async implementations) to persist reconnect state:

packages/ai/src/chatTransport.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,9 @@ describe("TriggerChatTransport", function () {
323323
stream: "chat-stream",
324324
accessToken: "pk_trigger",
325325
baseURL: server.url,
326-
payloadMapper: function payloadMapper(request) {
326+
payloadMapper: async function payloadMapper(request) {
327+
await sleep(1);
328+
327329
const firstMessage = request.messages[0];
328330
const firstPart = firstMessage?.parts[0];
329331
const prompt =
@@ -337,7 +339,9 @@ describe("TriggerChatTransport", function () {
337339
sourceHeader: request.request.headers?.["x-source"],
338340
};
339341
},
340-
triggerOptions: function triggerOptions(request) {
342+
triggerOptions: async function triggerOptions(request) {
343+
await sleep(1);
344+
341345
receivedResolverChatId = request.chatId;
342346
receivedResolverHeader = request.request.headers?.["x-source"];
343347

packages/ai/src/chatTransport.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export class TriggerChatTransport<
160160
} & ChatRequestOptions
161161
): Promise<ReadableStream<UIMessageChunk>> {
162162
const transportRequest = createTransportRequest<UI_MESSAGE>(options);
163-
const payload = this.payloadMapper(transportRequest);
163+
const payload = await this.payloadMapper(transportRequest);
164164
const triggerOptions = await resolveTriggerOptions<UI_MESSAGE>(
165165
this.triggerOptions,
166166
transportRequest
@@ -430,7 +430,7 @@ async function resolveTriggerOptions<UI_MESSAGE extends UIMessage>(
430430
}
431431

432432
if (typeof options === "function") {
433-
return options(request);
433+
return await options(request);
434434
}
435435

436436
return options;

packages/ai/src/chatTransport.types.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,29 @@ it("types mapper input with rich request context", function () {
6363
expectTypeOf(options.payloadMapper).toBeFunction();
6464
});
6565

66+
it("accepts async payload mappers and trigger option resolvers", function () {
67+
const options: TriggerChatTransportOptions<
68+
UIMessage,
69+
{ prompt: string; chatId: string }
70+
> = {
71+
task: "ai-chat",
72+
accessToken: "pk_test",
73+
payloadMapper: async function payloadMapper(request) {
74+
return {
75+
prompt: request.chatId,
76+
chatId: request.chatId,
77+
};
78+
},
79+
triggerOptions: async function triggerOptions(request) {
80+
return {
81+
queue: `queue-${request.chatId}`,
82+
};
83+
},
84+
};
85+
86+
expectTypeOf(options).toBeObject();
87+
});
88+
6689
it("accepts typed stream definition objects", function () {
6790
const typedStream = {
6891
id: "chat-stream",

packages/ai/src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,18 @@ export type TriggerChatTaskContext<
4848
streamKey: string;
4949
};
5050

51+
type MaybePromise<T> = T | Promise<T>;
52+
5153
export type TriggerChatPayloadMapper<
5254
UI_MESSAGE extends UIMessage = UIMessage,
5355
PAYLOAD = TriggerChatTransportPayload<UI_MESSAGE>,
54-
> = (request: TriggerChatTransportRequest<UI_MESSAGE>) => PAYLOAD;
56+
> = (request: TriggerChatTransportRequest<UI_MESSAGE>) => MaybePromise<PAYLOAD>;
5557

5658
export type TriggerChatTriggerOptionsResolver<
5759
UI_MESSAGE extends UIMessage = UIMessage,
5860
> = (
5961
request: TriggerChatTransportRequest<UI_MESSAGE>
60-
) => TriggerOptions | undefined;
62+
) => MaybePromise<TriggerOptions | undefined>;
6163

6264
export type TriggerChatStream<
6365
UI_MESSAGE extends UIMessage = UIMessage,

0 commit comments

Comments
 (0)