Files
triggerdotdev--trigger.dev/packages
Eric Allam 6ac545a095 feat(sdk): chat.agent → Sessions migration (phases B + C + min E)
Rewires chat.agent's internal I/O and TriggerChatTransport's send +
subscribe paths onto the Session primitive. Minimum token-scope work
included so the transport's session endpoints actually authenticate.

Phase B — chat.agent internals (ai.ts)

- New ChatInputChunk tagged union (`kind: "message" | "stop"`) —
  replaces the two-stream split (chat-messages + chat-stop) with a
  single Session `.in` channel.
- New chatSessionHandleKey locals slot populated at run start from
  `payload.sessionId ?? payload.chatId`. Every module-level helper
  now resolves to the per-run session handle.
- Module-level `chatStream`, `messagesInput`, `stopInput` become thin
  facades over the session. `chatStream` mirrors
  `RealtimeDefinedStream<UIMessageChunk>` and delegates to
  `handle.out`. `messagesInput` / `stopInput` mirror
  `RealtimeDefinedInputStream<…>` and filter `.in` by kind — the two
  internal `.on()`/`.waitWithIdleTimeout()` callers and the
  `chat.messages` / `chat.createStopSignal` public exposures keep
  their existing shapes.
- Every `streams.writer(CHAT_STREAM_KEY, …)` callsite swaps to
  `chatStream.writer(…)` so all chat output flows through
  `session.out` → `SessionStreamInstance` → direct-to-S2.
- Threaded `sessionId` through `ChatTaskWirePayload` /
  `ChatTaskPayload` / `ChatTaskRunPayload` so advanced users can
  `sessions.open(sessionId)` directly from `run()`.

Phase C — TriggerChatTransport (chat.ts)

- `ChatSessionState` keys durable identity on `sessionId` (friendlyId);
  `runId` becomes an optional hint about whether a run is live.
- `ensureSession(chatId)` lazily upserts the Session via
  `apiClient.createSession({type: "chat.agent", externalId: chatId})`
  on the direct `accessToken` path. Idempotent — two tabs on the
  same chat converge.
- `sendMessages`, `sendPendingMessage`, `stopGeneration`,
  `sendAction` all go through `appendToSessionStream(sessionId, "in",
  serializeInputChunk({kind: …}))` — one endpoint, one tag per
  record.
- SSE subscribe URL moves from `/realtime/v1/streams/{runId}/chat` to
  `/realtime/v1/sessions/{sessionId}/out`. The old run-scoped
  `subscribeToStream` is replaced by `subscribeToSessionStream`.
  Incoming chunks come back as JSON strings on the session channel
  (server wraps records as `{data, id}` on S2), so the subscribe
  loop parses them back into objects to keep the rest of the control
  flow (turn-complete / upgrade-required / skipToTurnComplete)
  unchanged.
- Upgrade-required re-trigger keeps the same Session and swaps only
  the runId + token.
- `getSession` / `setSession` / `setOnSessionChange` / persistence
  shape all grow a `sessionId` field (runId now optional).

Phase E — minimum token scopes

- `chat.createTriggerAction` (server side) now creates the Session
  before triggering so it can (a) thread `sessionId` into the run
  payload and (b) mint a token with both run and session scopes.
  Returns `sessionId` in its result so the transport can skip its
  own `sessions.create` call on the server-side-trigger path.
- `TriggerChatTaskResult` gains optional `sessionId`.
- The two in-run PAT refresh sites (preloadAccessToken,
  turnAccessToken) add `read:sessions:{sessionId}` +
  `write:sessions:{sessionId}` alongside the existing run scopes.

Known follow-ups (deferred to later passes)

- Phase D: `AgentChat` / `ChatStream` in chat-client.ts still uses
  the old `/realtime/v1/streams/{runId}/chat` path. Used by server-
  side task-to-task compositions, not the browser transport.
- Phase F: delete CHAT_STREAM_KEY, CHAT_MESSAGES_STREAM_ID,
  CHAT_STOP_STREAM_ID from chat-constants.ts + ai-chat smoke verify.
2026-05-10 22:11:20 +01:00
..
2026-05-01 15:13:11 +01:00
2026-05-01 15:13:11 +01:00
2026-05-01 15:13:11 +01:00