Skip to content

Commit 1659731

Browse files
committed
feat(sdk,webapp,ai-chat): end-to-end browser UI smoke on sessions
Fixes the last set of issues that were blocking TriggerChatTransport from running end-to-end against the ai-chat reference. Smoke now passes: new chat → send → streamed assistant reply in ~4s → second turn reuses the same session + run, lastEventId advances 10 → 21. SDK (@trigger.dev/sdk) - RenewRunAccessTokenParams carries the durable sessionId alongside chatId + runId. Server-side renew handlers MUST mint the renewed PAT with read:sessions:{sessionId} + write:sessions:{sessionId} scopes (in addition to the existing run scopes) — without them, the first append after expiry 401s on session.in/append and sends the transport into a renew loop. transport.renewRunPatForSession looks up the cached sessionId off `this.sessions` so existing renew callers just need to spread the new field through. - transport.preload(chatId) on the triggerTask callback path no longer calls apiClient.createSession from the browser. Matches sendMessages: when triggerTaskFn is configured the server action (chat.createTriggerAction) creates the Session with its secret key and returns sessionId alongside the run PAT. Browser deployments using the callback flow therefore never need write:sessions on any browser-facing token. - chat.test.ts renew-spy assertions updated to match the new {chatId, runId, sessionId} shape — 86/86 tests still green. Webapp - POST /api/v1/sessions gets allowJWT: true + corsStrategy: "all". Pre-fix, the route rejected any CORS-preflighted browser call, which broke the transport's direct accessToken fallback path (sessions.create from the browser). - POST /realtime/v1/sessions/:session/:io/append now exports both { action, loader }. The route builder installs the OPTIONS preflight handler on the loader; without a loader export, the preflight returned 400 ("No loader for route") and Chrome surfaced the follow-up POST as net::ERR_FAILED. Same pattern already in use on /api/v1/tasks/:id/trigger. references/ai-chat - Switch both chat-app.tsx and chat-view.tsx from accessToken: getChatToken to triggerTask: triggerChat. This path has the server action create the Session server-side with the secret key, so the browser never hits POST /api/v1/sessions and the returned PAT already carries the session scopes needed for session.in/out. - renewRunAccessTokenForChat(chatId, runId, sessionId?) now mints tokens that include read:sessions:{sessionId} + write:sessions:{sessionId} alongside the run scopes. Both call sites thread the sessionId from the SDK's renew callback params. - Drop executeJs / runInSecureSandbox / runInPRReviewSandbox to decouple ai-chat trigger dev from the isolated-vm native binary (its darwin-arm64 prebuild is broken against node 20.20.0 on the current toolchain). Deletes src/lib/secure-sandbox.ts and src/lib/pr-review-sandbox.ts, removes the executeJs tool from chatTools, the secure-exec-bridge esbuild plugin from trigger.config.ts (and its companion node-stdlib-browser-stub), and the `secure-exec` dependency from package.json. E2B-backed executeCode stays. If a future session needs the in-process V8 sandbox back, reintroduce through a different module (or pin a prebuilt binary) to avoid this failure mode. Smoke drove via the window.__chat bridge from Chrome DevTools MCP — no click-based interaction needed.
1 parent 0e2463d commit 1659731

16 files changed

Lines changed: 1313 additions & 1227 deletions
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
---
4+
5+
`TriggerChatTransport` fixes for session-scoped auth and end-to-end UI smoke parity:
6+
7+
- `RenewRunAccessTokenParams` now includes the durable `sessionId` alongside `chatId` + `runId`. Server-side renew handlers should mint the renewed PAT with `read:sessions:{sessionId}` + `write:sessions:{sessionId}` scopes (in addition to the existing run scopes) so it keeps authenticating against the session `.in` append + `.out` subscribe endpoints. Renewing without session scopes sends the transport into a 401 loop on the first append after expiry.
8+
- `transport.preload(chatId)` on the `triggerTask` callback path no longer calls `apiClient.createSession` from the browser. The server action (e.g. `chat.createTriggerAction`) creates the session with its secret key and returns the `sessionId` in its result, matching how `sendMessages` already worked. Browser deployments that use the `triggerTask` callback path therefore no longer need `write:sessions` on any browser-side token.

0 commit comments

Comments
 (0)