Skip to content

feat(realtime): add generating lifecycle state and event buffering#79

Merged
AdirAmsalem merged 2 commits intomainfrom
feat/generation-started-event-buffering
Feb 10, 2026
Merged

feat(realtime): add generating lifecycle state and event buffering#79
AdirAmsalem merged 2 commits intomainfrom
feat/generation-started-event-buffering

Conversation

@AdirAmsalem
Copy link
Contributor

@AdirAmsalem AdirAmsalem commented Feb 10, 2026

Summary

Adds "generating" ConnectionState and event buffering to the realtime client.

  • "generating" state: Emitted when the server sends a generation_started signaling message, letting consumers know the session is live and frames are incoming. connect() now resolves on either "connected" or "generating" (whichever arrives first).
  • Event buffering: Events fired during connect() are buffered and replayed after the client is returned, so listeners registered on the returned client never miss early state transitions.

What Changed

New: "generating" ConnectionState

  • ConnectionState type now includes "generating" (type moved from webrtc-connection.ts to types.ts for shared use)
  • WebRTCConnection handles generation_started signaling messages → sets state to "generating"
  • "generating" is sticky in onconnectionstatechange — only "disconnected" can override it
  • isConnected() and assertConnected() accept "generating" as a writable state
  • connect() resolves on "connected" or "generating"

Usage

// Subscribe to connection state changes
realtimeClient.on("connectionChange", (state) => {
  switch (state) {
    case "connecting":
      console.log("Connecting to server...");
      break;
    case "connected":
      console.log("Connected! Streaming active.");
      break;
    case "generating":
      console.log("Generation started! Frames incoming.");
      break;
    case "reconnecting":
      console.log("Connection lost, reconnecting...");
      break;
    case "disconnected":
      console.log("Disconnected from server.");
      break;
  }
});

New: Event Buffering

  • connectionChange and error events emitted during connect() are buffered
  • After connect() resolves and returns the client, buffered events replay via a macrotask (setTimeout(0))
  • buffering = false is set inside the macrotask to prevent ordering issues
  • disconnect() clears the event buffer to prevent re-entrant replay

Public API Changes

  • ConnectionState type: added "generating"additive, non-breaking for most consumers
    • ⚠️ Consumers with exhaustive switch on ConnectionState will get a compile error (intentional)
  • Events["connectionChange"]: now typed as ConnectionState instead of a hardcoded string union
  • No new methods, no removed methods, no changed method signatures

Tests

4 new unit tests:

  • connect() resolves when state reaches "generating"
  • "generating""disconnected" transition works correctly
  • "generating" triggers reconnect flow
  • Event replay delivers buffered events after connect() returns

All 80 tests pass. Typecheck and build clean.


Note

Medium Risk
Changes core realtime connection state handling and reconnect decisions; while additive, consumers with exhaustive ConnectionState handling or reliance on event timing could see behavior changes.

Overview
Adds a new realtime lifecycle state, generating, surfaced via the exported ConnectionState type and emitted when the server sends a generation_started signaling message; connect() now treats generating as an established state (handshake completion, isConnected(), reconnect gating, and method send preconditions).

Updates the realtime client to buffer connectionChange/error events during connect() and replay them asynchronously after the client is returned, preventing missed early state transitions; includes new unit tests covering generating transitions/reconnect behavior and event replay ordering.

Written by Cursor Bugbot for commit 6c2565b. This will update automatically on new commits. Configure here.

…ering

Add 'generating' ConnectionState emitted when the server sends a
generation_started signaling message, letting consumers know the
session is live and frames are on their way.

Event buffering defers connectionChange/error events that fire during
connect() so listeners registered on the returned client never miss
early state transitions. Events replay via a macrotask after connect()
resolves.

Changes:
- ConnectionState type now includes 'generating' (moved to types.ts)
- WebRTCConnection handles generation_started message, makes
  'generating' sticky (only 'disconnected' can override)
- connect() resolves on 'connected' OR 'generating'
- isConnected()/assertConnected() accept 'generating' as a writable
  state
- Events emitted during connect() are buffered and replayed after
  the client is returned to the caller
- disconnect() clears the event buffer to prevent re-entrant replay
- 4 new unit tests covering generating state and event replay
@AdirAmsalem AdirAmsalem force-pushed the feat/generation-started-event-buffering branch from c91dc78 to 17a46d6 Compare February 10, 2026 05:55
@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 10, 2026

Open in StackBlitz

npm i https://pkg.pr.new/DecartAI/sdk/@decartai/sdk@79

commit: 87b6fe3

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

@AdirAmsalem AdirAmsalem force-pushed the feat/generation-started-event-buffering branch from 0f97f80 to 6c2565b Compare February 10, 2026 06:11
@AdirAmsalem AdirAmsalem force-pushed the feat/generation-started-event-buffering branch from 6c2565b to 87b6fe3 Compare February 10, 2026 06:15
@AdirAmsalem AdirAmsalem changed the title feat(realtime): add generation_started lifecycle state and event buffering feat(realtime): add generating lifecycle state and event buffering Feb 10, 2026
Copy link
Contributor

@tomershlasky tomershlasky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, letf 1 comment

Comment on lines +347 to +351
const nextState =
s === "connected" ? "connected" : ["connecting", "new"].includes(s) ? "connecting" : "disconnected";
// Keep "generating" sticky unless the connection is actually lost.
if (this.state === "generating" && nextState !== "disconnected") return;
this.setState(nextState);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe some better if else for more readbility

@AdirAmsalem AdirAmsalem merged commit a5c60a5 into main Feb 10, 2026
5 checks passed
@AdirAmsalem AdirAmsalem deleted the feat/generation-started-event-buffering branch February 10, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants