@@ -35,6 +35,7 @@ import {
3535 type TaskWithSchema ,
3636 SESSION_IN_EVENT_ID_HEADER ,
3737 TRIGGER_CONTROL_SUBTYPE ,
38+ generateJWT ,
3839 type WriterStreamOptions ,
3940} from "@trigger.dev/core/v3" ;
4041import type {
@@ -8411,6 +8412,32 @@ export type { InferChatClientData, InferChatUIMessage } from "./ai-shared.js";
84118412/**
84128413 * Options for {@link createChatStartSessionAction}.
84138414 */
8415+ /**
8416+ * Discriminator for per-endpoint `baseURL` / `fetch` callbacks on
8417+ * `createChatStartSessionAction`.
8418+ *
8419+ * - `"sessions"` — `POST /api/v1/sessions` (session create + first run trigger).
8420+ * - `"auth"` — `POST /api/v1/auth/jwt/claims` (only fired when
8421+ * `tokenTTL` is set; otherwise the publicAccessToken from session create
8422+ * is reused as-is).
8423+ */
8424+ export type ChatStartSessionEndpoint = "sessions" | "auth" ;
8425+
8426+ export type ChatStartSessionEndpointContext = {
8427+ endpoint : ChatStartSessionEndpoint ;
8428+ chatId : string ;
8429+ } ;
8430+
8431+ export type ChatStartSessionBaseURLResolver = (
8432+ ctx : ChatStartSessionEndpointContext
8433+ ) => string ;
8434+
8435+ export type ChatStartSessionFetchOverride = (
8436+ url : string ,
8437+ init : RequestInit ,
8438+ ctx : ChatStartSessionEndpointContext
8439+ ) => Promise < Response > ;
8440+
84148441export type CreateChatStartSessionActionOptions = {
84158442 /** TTL for the session-scoped public access token. @default "1h" */
84168443 tokenTTL ?: string | number | Date ;
@@ -8419,6 +8446,21 @@ export type CreateChatStartSessionActionOptions = {
84198446 * Per-call `params.triggerConfig` shallow-merges on top.
84208447 */
84218448 triggerConfig ?: Partial < SessionTriggerConfig > ;
8449+ /**
8450+ * Override the Trigger.dev API base URL. String applies to both
8451+ * `/api/v1/sessions` and `/api/v1/auth/jwt/claims`; function picks per
8452+ * endpoint. When unset, falls back to `apiClientManager.baseURL`
8453+ * (typically the `TRIGGER_API_URL` env var). Set this to route session
8454+ * create through a trusted edge proxy that injects server-side signal
8455+ * into `basePayload.metadata` before forwarding upstream.
8456+ */
8457+ baseURL ?: string | ChatStartSessionBaseURLResolver ;
8458+ /**
8459+ * Per-request fetch override. Receives the resolved URL, RequestInit,
8460+ * and endpoint context. Use for header injection, proxy routing, or
8461+ * custom retry. Applies to both session-create and JWT-claims POSTs.
8462+ */
8463+ fetch ?: ChatStartSessionFetchOverride ;
84228464} ;
84238465
84248466/**
@@ -8542,27 +8584,47 @@ function createChatStartSessionAction(
85428584 : { } ) ,
85438585 } ;
85448586
8545- const created = await sessions . start ( {
8546- type : "chat.agent" ,
8587+ const startBody = {
8588+ type : "chat.agent" as const ,
85478589 externalId : params . chatId ,
85488590 taskIdentifier : taskId ,
85498591 triggerConfig,
85508592 metadata : params . metadata ,
8551- } ) ;
8593+ } ;
8594+
8595+ const baseURLOption = options ?. baseURL ;
8596+ const fetchOverride = options ?. fetch ;
8597+ const hasOverride = baseURLOption !== undefined || fetchOverride !== undefined ;
8598+
8599+ const created : { id : string ; runId : string ; publicAccessToken : string } = hasOverride
8600+ ? await callSessionsCreateWithOverride ( {
8601+ chatId : params . chatId ,
8602+ body : startBody ,
8603+ baseURLOption,
8604+ fetchOverride,
8605+ } )
8606+ : await sessions . start ( startBody ) ;
85528607
85538608 // Session create returns a session PAT directly when called with a
85548609 // start token, but when the SDK call goes via the secret key we still
85558610 // need to mint our own (the server returns a PAT regardless, but
85568611 // re-minting here lets the customer override `tokenTTL`).
85578612 const publicAccessToken =
85588613 options ?. tokenTTL !== undefined
8559- ? await auth . createPublicToken ( {
8560- scopes : {
8561- read : { sessions : params . chatId } ,
8562- write : { sessions : params . chatId } ,
8563- } ,
8564- expirationTime : options . tokenTTL ,
8565- } )
8614+ ? hasOverride
8615+ ? await mintPublicTokenWithOverride ( {
8616+ chatId : params . chatId ,
8617+ expirationTime : options . tokenTTL ,
8618+ baseURLOption,
8619+ fetchOverride,
8620+ } )
8621+ : await auth . createPublicToken ( {
8622+ scopes : {
8623+ read : { sessions : params . chatId } ,
8624+ write : { sessions : params . chatId } ,
8625+ } ,
8626+ expirationTime : options . tokenTTL ,
8627+ } )
85668628 : created . publicAccessToken ;
85678629
85688630 return {
@@ -8573,6 +8635,93 @@ function createChatStartSessionAction(
85738635 } ;
85748636}
85758637
8638+ function resolveChatStartBaseURL (
8639+ endpoint : ChatStartSessionEndpoint ,
8640+ chatId : string ,
8641+ option : string | ChatStartSessionBaseURLResolver | undefined
8642+ ) : string {
8643+ const fallback = apiClientManager . baseURL ?? "https://api.trigger.dev" ;
8644+ const raw =
8645+ typeof option === "function"
8646+ ? option ( { endpoint, chatId } )
8647+ : option ?? fallback ;
8648+ return raw . replace ( / \/ $ / , "" ) ;
8649+ }
8650+
8651+ async function callSessionsCreateWithOverride ( args : {
8652+ chatId : string ;
8653+ body : { type : "chat.agent" ; externalId : string ; taskIdentifier : string ; triggerConfig : SessionTriggerConfig ; metadata ?: Record < string , unknown > } ;
8654+ baseURLOption : string | ChatStartSessionBaseURLResolver | undefined ;
8655+ fetchOverride : ChatStartSessionFetchOverride | undefined ;
8656+ } ) : Promise < { id : string ; runId : string ; publicAccessToken : string } > {
8657+ const accessToken = apiClientManager . accessToken ;
8658+ if ( ! accessToken ) {
8659+ throw new Error (
8660+ "chat.createStartSessionAction: no API access token configured. Set TRIGGER_SECRET_KEY or call apiClientManager.setGlobalAPIClientConfiguration before invoking the action."
8661+ ) ;
8662+ }
8663+ const ctx : ChatStartSessionEndpointContext = { endpoint : "sessions" , chatId : args . chatId } ;
8664+ const url = `${ resolveChatStartBaseURL ( "sessions" , args . chatId , args . baseURLOption ) } /api/v1/sessions` ;
8665+ const init : RequestInit = {
8666+ method : "POST" ,
8667+ headers : {
8668+ "Content-Type" : "application/json" ,
8669+ Authorization : `Bearer ${ accessToken } ` ,
8670+ "x-trigger-source" : "sdk" ,
8671+ } ,
8672+ body : JSON . stringify ( args . body ) ,
8673+ } ;
8674+ const response = args . fetchOverride
8675+ ? await args . fetchOverride ( url , init , ctx )
8676+ : await fetch ( url , init ) ;
8677+ if ( ! response . ok ) {
8678+ const text = await response . text ( ) . catch ( ( ) => "" ) ;
8679+ throw new Error ( `sessions.start failed: ${ response . status } ${ text } ` ) ;
8680+ }
8681+ const json = ( await response . json ( ) ) as { id : string ; runId : string ; publicAccessToken : string } ;
8682+ return json ;
8683+ }
8684+
8685+ async function mintPublicTokenWithOverride ( args : {
8686+ chatId : string ;
8687+ expirationTime : string | number | Date ;
8688+ baseURLOption : string | ChatStartSessionBaseURLResolver | undefined ;
8689+ fetchOverride : ChatStartSessionFetchOverride | undefined ;
8690+ } ) : Promise < string > {
8691+ const accessToken = apiClientManager . accessToken ;
8692+ if ( ! accessToken ) {
8693+ throw new Error (
8694+ "chat.createStartSessionAction: no API access token configured for JWT mint."
8695+ ) ;
8696+ }
8697+ const ctx : ChatStartSessionEndpointContext = { endpoint : "auth" , chatId : args . chatId } ;
8698+ const url = `${ resolveChatStartBaseURL ( "auth" , args . chatId , args . baseURLOption ) } /api/v1/auth/jwt/claims` ;
8699+ const init : RequestInit = {
8700+ method : "POST" ,
8701+ headers : {
8702+ "Content-Type" : "application/json" ,
8703+ Authorization : `Bearer ${ accessToken } ` ,
8704+ "x-trigger-source" : "sdk" ,
8705+ } ,
8706+ } ;
8707+ const response = args . fetchOverride
8708+ ? await args . fetchOverride ( url , init , ctx )
8709+ : await fetch ( url , init ) ;
8710+ if ( ! response . ok ) {
8711+ const text = await response . text ( ) . catch ( ( ) => "" ) ;
8712+ throw new Error ( `auth.createPublicToken failed: ${ response . status } ${ text } ` ) ;
8713+ }
8714+ const claims = ( await response . json ( ) ) as Record < string , unknown > ;
8715+ return generateJWT ( {
8716+ secretKey : accessToken ,
8717+ payload : {
8718+ ...claims ,
8719+ scopes : [ `read:sessions:${ args . chatId } ` , `write:sessions:${ args . chatId } ` ] ,
8720+ } ,
8721+ expirationTime : args . expirationTime ,
8722+ } ) ;
8723+ }
8724+
85768725export const chat = {
85778726 /** Create a chat agent. See {@link chatAgent}. */
85788727 agent : chatAgent ,
0 commit comments