Skip to content

Commit 32be0d4

Browse files
committed
feat(sdk): allow a ttl on session-triggered runs
1 parent 5c65e5f commit 32be0d4

6 files changed

Lines changed: 29 additions & 2 deletions

File tree

.changeset/chat-session-run-ttl.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@trigger.dev/core": patch
3+
"@trigger.dev/sdk": patch
4+
---
5+
6+
Chat server sessions can now set a `ttl` on the runs they trigger, so a run that is never picked up expires instead of waiting indefinitely.

packages/core/src/v3/schemas/api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,11 @@ export const SessionTriggerConfig = z.object({
18241824
lockToVersion: z.string().optional(),
18251825
/** Region to schedule runs in. Forwarded to `TaskRunOptions.region`. */
18261826
region: z.string().optional(),
1827+
/**
1828+
* How long a run may sit undequeued before it expires (duration string
1829+
* like `"2m"`, or seconds). Forwarded to `TaskRunOptions.ttl`.
1830+
*/
1831+
ttl: z.string().or(z.number().nonnegative().int()).optional(),
18271832
/** Convenience field surfaced to chat.agent via the wire payload. */
18281833
idleTimeoutInSeconds: z.number().int().positive().max(3600).optional(),
18291834
});

packages/trigger-sdk/src/v3/ai.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10448,6 +10448,7 @@ function createChatStartSessionAction<TChat extends AnyTask = AnyTask>(
1044810448
const maxDuration = params.triggerConfig?.maxDuration ?? options?.triggerConfig?.maxDuration;
1044910449
const idleTimeoutInSeconds =
1045010450
params.triggerConfig?.idleTimeoutInSeconds ?? options?.triggerConfig?.idleTimeoutInSeconds;
10451+
const ttl = params.triggerConfig?.ttl ?? options?.triggerConfig?.ttl;
1045110452

1045210453
const triggerConfig: SessionTriggerConfig = {
1045310454
basePayload: {
@@ -10470,6 +10471,7 @@ function createChatStartSessionAction<TChat extends AnyTask = AnyTask>(
1047010471
...(options?.triggerConfig?.region || params.triggerConfig?.region
1047110472
? { region: params.triggerConfig?.region ?? options?.triggerConfig?.region }
1047210473
: {}),
10474+
...(ttl !== undefined ? { ttl } : {}),
1047310475
...(options?.triggerConfig?.lockToVersion || params.triggerConfig?.lockToVersion
1047410476
? {
1047510477
lockToVersion:

packages/trigger-sdk/src/v3/chat-server.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ describe("chat.headStart (route handler)", () => {
216216
expect(body.triggerConfig.basePayload.idleTimeoutInSeconds).toBe(60);
217217
});
218218

219-
it("merges triggerConfig tags and queue into createSession", async () => {
219+
it("merges triggerConfig tags, queue and ttl into createSession", async () => {
220220
const requests: CapturedRequest[] = [];
221221
global.fetch = vi.fn().mockImplementation(async (url: string | URL, init?: RequestInit) => {
222222
const urlStr = typeof url === "string" ? url : url.toString();
@@ -248,6 +248,7 @@ describe("chat.headStart (route handler)", () => {
248248
triggerConfig: {
249249
tags: ["org:acme", "agentic-run:xyz"],
250250
queue: "my-queue",
251+
ttl: "2m",
251252
},
252253
run: async ({ chat: chatHelper }) => {
253254
return streamText({
@@ -276,6 +277,7 @@ describe("chat.headStart (route handler)", () => {
276277
const body = JSON.parse(sessionCreate!.init!.body as string);
277278
expect(body.triggerConfig.tags).toEqual(["chat:chat-1", "org:acme", "agentic-run:xyz"]);
278279
expect(body.triggerConfig.queue).toBe("my-queue");
280+
expect(body.triggerConfig.ttl).toBe("2m");
279281
expect(body.triggerConfig.basePayload.trigger).toBe("handover-prepare");
280282
expect(body.triggerConfig.basePayload.chatId).toBe("chat-1");
281283
});

packages/trigger-sdk/src/v3/chat-server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ async function openHandoverSession(opts: {
550550
? { maxDuration: opts.triggerConfig.maxDuration }
551551
: {}),
552552
...(opts.triggerConfig?.region ? { region: opts.triggerConfig.region } : {}),
553+
...(opts.triggerConfig?.ttl !== undefined ? { ttl: opts.triggerConfig.ttl } : {}),
553554
...(opts.triggerConfig?.lockToVersion
554555
? { lockToVersion: opts.triggerConfig.lockToVersion }
555556
: {}),

packages/trigger-sdk/src/v3/createStartSessionAction.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,32 @@ describe("chat.createStartSessionAction — runtime", () => {
115115
]);
116116
});
117117

118-
it("forwards maxDuration, region, and lockToVersion from triggerConfig", async () => {
118+
it("forwards maxDuration, region, lockToVersion, and ttl from triggerConfig", async () => {
119119
installStartFixture();
120120

121121
const start = chat.createStartSessionAction("fake-chat", {
122122
triggerConfig: {
123123
maxDuration: 120,
124124
region: "us-east-1",
125125
lockToVersion: "20260101.1",
126+
ttl: "2m",
126127
},
127128
});
128129
await start({ chatId: "chat-parity" });
129130

130131
expect(lastStartBody?.triggerConfig.maxDuration).toBe(120);
131132
expect(lastStartBody?.triggerConfig.region).toBe("us-east-1");
132133
expect(lastStartBody?.triggerConfig.lockToVersion).toBe("20260101.1");
134+
expect(lastStartBody?.triggerConfig.ttl).toBe("2m");
135+
});
136+
137+
it("omits ttl when triggerConfig does not set it", async () => {
138+
installStartFixture();
139+
140+
const start = chat.createStartSessionAction("fake-chat");
141+
await start({ chatId: "chat-no-ttl" });
142+
143+
expect(lastStartBody?.triggerConfig).not.toHaveProperty("ttl");
133144
});
134145

135146
it("server-mints override tokens for additional API keys", async () => {

0 commit comments

Comments
 (0)