From 9afa035574bb2246effed481e3b7c48f92123a3d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 15 Feb 2026 04:22:40 +0000 Subject: [PATCH] Require http(s) protocol for chat transport baseURL Co-authored-by: Eric Allam --- docs/tasks/streams.mdx | 3 ++- packages/ai/CHANGELOG.md | 1 + packages/ai/README.md | 1 + packages/ai/src/chatTransport.test.ts | 22 ++++++++++++++++++++++ packages/ai/src/chatTransport.ts | 10 +++++++++- 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/tasks/streams.mdx b/docs/tasks/streams.mdx index 26c7c906b..49798ca75 100644 --- a/docs/tasks/streams.mdx +++ b/docs/tasks/streams.mdx @@ -655,7 +655,8 @@ If `onError` is omitted, reconnect still returns `null` and continues without ca `baseURL` supports optional path prefixes and trailing slashes; both trigger and stream URLs are normalized consistently, surrounding whitespace is trimmed before normalization, and -the resulting value must not be empty. The value must also be a valid absolute URL. +the resulting value must not be empty. The value must also be a valid absolute URL using +the `http` or `https` protocol. For richer TypeScript ergonomics in app code, `@trigger.dev/ai` also exports: diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 34b4d6ac6..085ab4be4 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -23,3 +23,4 @@ - Added surrounding-whitespace trimming for `baseURL` before endpoint normalization. - Added explicit validation that `baseURL` is non-empty after normalization. - Added explicit validation that `baseURL` is a valid absolute URL. +- Added explicit validation that `baseURL` uses `http` or `https`. diff --git a/packages/ai/README.md b/packages/ai/README.md index 3fa5acc46..f20d57663 100644 --- a/packages/ai/README.md +++ b/packages/ai/README.md @@ -162,6 +162,7 @@ both cleanup steps (`set` inactive state and `delete`) even if one of them fails - Surrounding whitespace is trimmed before normalization. - `baseURL` must not be empty after trimming/normalization. - `baseURL` must be a valid absolute URL. +- `baseURL` must use the `http` or `https` protocol. ## `ai.tool(...)` example diff --git a/packages/ai/src/chatTransport.test.ts b/packages/ai/src/chatTransport.test.ts index 36722f492..69ab5e031 100644 --- a/packages/ai/src/chatTransport.test.ts +++ b/packages/ai/src/chatTransport.test.ts @@ -642,6 +642,17 @@ describe("TriggerChatTransport", function () { }).toThrowError("baseURL must be a valid absolute URL"); }); + it("throws when baseURL protocol is not http or https", function () { + expect(function () { + new TriggerChatTransport({ + task: "chat-task", + accessToken: "pk_trigger", + baseURL: "ftp://example.com", + stream: "chat-stream", + }); + }).toThrowError("baseURL must use http or https protocol"); + }); + it("combines path prefixes with run and stream URL encoding", async function () { let observedTriggerPath: string | undefined; let observedStreamPath: string | undefined; @@ -2778,6 +2789,17 @@ describe("TriggerChatTransport", function () { }).toThrowError("baseURL must be a valid absolute URL"); }); + it("throws from factory when baseURL protocol is not http or https", function () { + expect(function () { + createTriggerChatTransport({ + task: "chat-task", + accessToken: "pk_trigger", + baseURL: "ftp://example.com", + stream: "chat-stream", + }); + }).toThrowError("baseURL must use http or https protocol"); + }); + it("continues streaming when onTriggeredRun callback throws", async function () { let callbackCalled = false; const errors: TriggerChatTransportError[] = []; diff --git a/packages/ai/src/chatTransport.ts b/packages/ai/src/chatTransport.ts index f86c5a12f..ebc263b6c 100644 --- a/packages/ai/src/chatTransport.ts +++ b/packages/ai/src/chatTransport.ts @@ -466,12 +466,20 @@ function normalizeBaseUrl(baseURL: string) { throw new Error("baseURL must not be empty"); } + let parsedBaseUrl: URL; try { - new URL(normalizedBaseUrl); + parsedBaseUrl = new URL(normalizedBaseUrl); } catch { throw new Error("baseURL must be a valid absolute URL"); } + if ( + parsedBaseUrl.protocol !== "http:" && + parsedBaseUrl.protocol !== "https:" + ) { + throw new Error("baseURL must use http or https protocol"); + } + return normalizedBaseUrl; }