import type { ControlEvent, SSEStreamPart } from "@trigger.dev/core/v3"; import type { UseApiClientOptions } from "./useApiClient.js"; export type UseSessionStreamInstance = { /** * The records received so far on the channel, in arrival order. Control records are * never included here, they are delivered to `onControl` instead. */ records: Array; /** * The cursor of the last record seen. Persist this and pass it back as the `lastEventId` * option to resume the channel where you left off. */ lastEventId: string | undefined; /** * The last control record seen on the channel (e.g. `turn-complete`). */ lastControl: ControlEvent | undefined; error: Error | undefined; /** * Abort the current request immediately, keep the records received so far. */ stop: () => void; }; export type UseSessionStreamOptions = UseApiClientOptions & { id?: string; enabled?: boolean; /** * Which channel of the session to read. * * @default "out" */ io?: "out" | "in"; /** * The number of milliseconds to throttle the record updates. * * @default 16 */ throttleInMs?: number; /** * The number of seconds to wait for new data to be available, * If no data arrives within the timeout, the stream will be closed. * * @default 60 seconds */ timeoutInSeconds?: number; /** * The cursor to resume from. If not provided, the channel is read from the beginning. */ lastEventId?: string | number; /** * Where a fresh subscription (no `lastEventId`) starts reading. * * - `"beginning"` (default): replay the full channel history, then live-tail. * - `"latest"`: start at the current tail (the latest record, then live * updates) instead of replaying history, for a last-value / live view. * * Ignored when `lastEventId` is set. */ from?: "beginning" | "latest"; /** * Cap the number of records kept in the accumulated `records` array. When more * than `maxRecords` have been received, only the most recent `maxRecords` are * retained. Use `maxRecords: 1` with `from: "latest"` for a last-value view * with bounded memory. When unset, `records` accumulates without bound. */ maxRecords?: number; /** * Callback invoked once per throttled flush with the batch of records in that * flush, each carrying its event `id`, `chunk` and `timestamp`. Fires at the * `throttleInMs` cadence (not per record) and includes control records, so it * can track the resume cursor for everything on the channel. */ onRecords?: (records: Array>) => void; /** * Callback this is called when a control record is received (e.g. `turn-complete`). */ onControl?: (event: ControlEvent) => void; }; /** * Hook to read one channel of a Session's realtime stream. * * This hook subscribes to one of the session's channels (`out` by default, or `in`) and * updates the `records` array as new records arrive. It is read-only: use `useSession` for * two-way (read and write) communication. The subscription is automatically managed: it * starts when the component mounts (or when `enabled` becomes `true`) and stops when the * component unmounts or when `stop()` is called. * * Requires a Public Access Token with the `read:sessions:{id}` scope. * * @template TRecord - The type of each record on the channel * @param sessionIdOrExternalId - The id or external id of the session to subscribe to * @param options - Optional configuration for the subscription * @returns An object containing: * - `records`: An array of all the records received so far (accumulates over time) * - `lastEventId`: The cursor of the last record seen, for resuming later * - `lastControl`: The last control record seen * - `error`: Any error that occurred during subscription * - `stop`: A function to manually stop the subscription * * @example * ```tsx * "use client"; * import { useSessionStream } from "@trigger.dev/react-hooks"; * * function SessionViewer({ sessionId }: { sessionId: string }) { * const { records, error } = useSessionStream(sessionId, { * accessToken: publicAccessToken, * }); * * if (error) return
Error: {error.message}
; * * return
{records.join("")}
; * } * ``` * * @example * ```tsx * // Read the input channel, resuming from a persisted cursor * const { records, lastEventId, stop } = useSessionStream(sessionId, { * accessToken: publicAccessToken, * io: "in", * lastEventId: persistedCursor, * onControl: (event) => { * if (event.subtype === "turn-complete") { * console.log("The turn is complete"); * } * }, * }); * ``` */ export declare function useSessionStream(sessionIdOrExternalId?: string, options?: UseSessionStreamOptions): UseSessionStreamInstance;