Adapter SDK

Orchestrators

Bidirectional event routing — Reconciler, BridgeToPlatform, PlatformToBridge.

Orchestrators

The SDK includes four orchestrators that handle the bidirectional flow between bridge and platform. They are created and managed by the Runtime — you typically don't instantiate them directly.

Reconciler

Synchronizes bridge sessions with platform containers. Creates new containers for new sessions, renames existing ones when titles change.

Behavior

  • No orphan deletion — if a bridge session disappears, the container is left in place (data preservation)
  • Title repair — on startup, fixes containers that still have placeholder titles (e.g., claude_abc123...)
  • Guards against empty titles — rejects rename to empty string
  • Configurable title length — truncates to titleMaxLength (default 128)

sync(sessions)

Called automatically when sessions:list arrives from the bridge.

// For each session:
// 1. Does a container exist in the store?
//    No → createContainer() → store.containers.upsert()
//    Yes → has title changed? → renameContainer()
// 2. Update status in store

repairTitles()

Called once during startup. Scans all containers and renames any whose title is still the raw conversationId prefix.

BridgeToPlatform

Routes incoming bridge stream events to the platform. This is the most complex orchestrator, handling streaming, tool cards, deduplication, and message mapping.

Event Flow

stream:message_start     → create TurnStreamer for conversation
stream:text_delta        → streamer.appendDelta(text)
stream:tool_use          → finalize streamer → post tool_card (partial)
stream:tool_result       → edit tool_card with result
stream:message_complete  → finalize streamer with markdown render
stream:result            → post result_card (usage, cost)
stream:stopped           → post stopped indicator
stream:user_message      → dedup check → post user_message_card
session:error            → post error_card
session:status           → post status indicator

Tool Call Chronological Ordering

When toolCallChronologicalOrdering: true (default), the SDK preserves the visual order of events:

  1. Text before tool → finalize streamer (commits placeholder)
  2. Tool card posted after the committed text
  3. New streamer created for post-tool text
  4. Text after tool → streamer edits new placeholder
  5. Message complete → finalize with accumulated text (not full e.content)

This prevents duplication when a turn contains text → tool → text sequences.

Deduplication

Messages are deduplicated using two mechanisms:

  1. Message mapstore.messages.hasBridgeMessage(id) checks if a bridge message was already posted
  2. Pending outbound — tracks messages in-flight (POSTed but not yet confirmed) to catch echoes

PlatformToBridge

Implements PlatformHandlers to receive incoming platform events and route them to the bridge.

onMessage

  1. Resolve containerIdconversationId via store
  2. Download attached files → upload to bridge API
  3. POST message to bridge with sender info
  4. Register pending outbound token for dedup
  5. Store message mapping

onContainerClosed

Configurable behavior:

  • 'delete-session' (default) — calls bridgeApi.deleteSession()
  • 'leave-room' — leaves the WebSocket room
  • 'noop' — ignores the event

onContainerRenamed

  • Checks echo guard (was this rename triggered by the SDK itself?)
  • If not echo → calls bridgeApi.updateSessionTitle()
  • If propagateRenames: false → ignores all renames

Replayer

Replays historical messages from the bridge into platform containers on startup.

Behavior

  1. For each session with a container:
    • Fetch messages from bridge API (getMessages)
    • Skip messages already in message map
    • Render each message → post to container
    • Record in message map

Configuration

interface ReplayerConfig {
  limitPerSession: number    // default: 50
  skipIfNoContainer: boolean // default: true
}
Set skipReplay: true in AdapterConfig during development to speed up startup.