From cf1b5c7ffe2978ea3eee2103e54f1328954bb35d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 14 Feb 2026 23:35:34 +0000 Subject: [PATCH] Add compile-time DX tests for chat transport types Co-authored-by: Eric Allam --- packages/ai/src/chatTransport.types.test.ts | 81 +++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 packages/ai/src/chatTransport.types.test.ts diff --git a/packages/ai/src/chatTransport.types.test.ts b/packages/ai/src/chatTransport.types.test.ts new file mode 100644 index 000000000..0926cddd0 --- /dev/null +++ b/packages/ai/src/chatTransport.types.test.ts @@ -0,0 +1,81 @@ +import { expectTypeOf, it } from "vitest"; +import type { InferUIMessageChunk, UIMessage } from "ai"; +import { + TriggerChatTransport, + TriggerChatTransportOptions, + type TriggerChatTransportPayload, + type TriggerChatTransportRequest, + type TriggerChatRunState, +} from "./index.js"; +import type { RealtimeDefinedStream } from "@trigger.dev/core/v3"; + +it("infers rich default payload contract", function () { + const transport = new TriggerChatTransport({ + task: "ai-chat", + accessToken: "pk_test", + stream: "chat-stream", + }); + + expectTypeOf(transport).toEqualTypeOf< + TriggerChatTransport> + >(); +}); + +it("requires payload mapper for custom payload types", function () { + // @ts-expect-error Custom payload generic requires payloadMapper + const invalidOptions: TriggerChatTransportOptions = { + task: "ai-chat", + accessToken: "pk_test", + stream: "chat-stream", + }; + + expectTypeOf(invalidOptions).toBeObject(); +}); + +it("types mapper input with rich request context", function () { + const options: TriggerChatTransportOptions< + UIMessage, + { prompt: string; chatId: string; source: string | undefined } + > = { + task: "ai-chat", + accessToken: "pk_test", + stream: "chat-stream", + payloadMapper: function payloadMapper(request: TriggerChatTransportRequest) { + const firstMessage = request.messages[0]; + const firstPart = firstMessage?.parts[0]; + const prompt = + firstPart && firstPart.type === "text" + ? firstPart.text + : ""; + + return { + prompt, + chatId: request.chatId, + source: request.request.headers?.["x-source"], + }; + }, + onTriggeredRun: function onTriggeredRun(state: TriggerChatRunState) { + expectTypeOf(state.chatId).toEqualTypeOf(); + expectTypeOf(state.publicAccessToken).toEqualTypeOf(); + }, + }; + + expectTypeOf(options.payloadMapper).toBeFunction(); +}); + +it("accepts typed stream definition objects", function () { + const typedStream = { + id: "chat-stream", + pipe: async function pipe() { + throw new Error("not used in type test"); + }, + } as unknown as RealtimeDefinedStream>; + + const transport = new TriggerChatTransport({ + task: "ai-chat", + accessToken: "pk_test", + stream: typedStream, + }); + + expectTypeOf(transport).toBeObject(); +});