Skip to main content
Turn a raw gateway event stream into a correct, resumable session view — no per-client de-dup, gap-healing or bounded retention to re-implement.

Quick Start

1

Simplest usage

Iterate the projected state and render it — the reducer folds every event for you.
2

With a resume snapshot

Seed the projection with a snapshot on reconnect so the view converges instead of drifting.
3

Bound retention on a long-lived session

Cap how many finished runs stay tracked; active streams are never evicted.
4

Pure-core usage without the wrapper

Drive the reducer directly for third-party clients or tests — no transport required.

How It Works

The reducer folds a snapshot plus live events into an immutable state, reconciling every duplicate along the way.

De-duplication Behaviours

Three distinct reconciliations keep the view correct, each keyed on a different identifier.
A final assistant message that arrives both as a STREAM_END and as a persisted transcript row renders once, keyed by message_id.

Configuration Options

The reducer constructor takes a single option. SessionProjectionState — the immutable value returned by every apply call: RunView — the immutable per-run streaming view:

GatewayClient.project()

Yields a SessionProjectionState after the initial snapshot (if any) and after every subsequent event.

TypeScript Parity

The praisonai-ts SDK ships the same reducer, importing from the package root. It accepts both camelCase (SDK) and snake_case (wire) keys — messageId/message_id, requestId/request_id, senderId/sender_id, runId/run_id — so wire frames from the Python gateway drop straight in with identical de-dup, reconciliation, gap and retention semantics.

Common Patterns


Choose Your Entry Point

Pick the wrapper when you use the bundled client; drive the pure core everywhere else.

Best Practices

Pass a snapshot so the view converges instead of drifting — apply_snapshot() resets gap tracking and rebuilds the transcript from persisted rows.
Pair state.has_transport_gap with client.resync() on the transport side to heal a sequence hole after a reconnect.
Lower max_tracked_runs for dashboards that run for days; leave the default 200 for a chat UI.
Never mutate state.entries or state.runs — they are immutable snapshots. A previous state is never mutated in place by a later apply().
client.project() is the SDK primitive that removes double-rendered answers, reconnect flicker and unbounded memory growth.

Gateway Client

Reconnecting transport and raw event stream

Stream Events

Live progress events forwarded over WebSocket

Frame Codec

The request_id reconciliation key

Session Persistence

Where durable transcript rows come from