Member Junction
    Preparing search index...

    Class BaseRealtimeChannelClient<TSurface>Abstract

    Base class for CLIENT-SIDE interactive-channel plugins (per plans/ai-agent-sessions.md → "Interactive Channels" / "Pluggable Channel Interfaces").

    An interactive channel is a bidirectional surface the session's single realtime agent both PERCEIVES and ACTS UPON (whiteboard, shared doc, map, …). A concrete plugin contributes everything the channel needs, so the session service / call overlay carry ZERO channel-specific wiring:

    1. a CLIENT-EXECUTED TOOL SET (GetToolDefinitions, declared to the realtime model at session mint) plus the local executor (ApplyAgentTool) the host routes {@link ToolNamePrefix}* calls to — the ACTION direction;
    2. a STATE→CONTEXT SERIALIZER policy — the plugin owns its state engine and pushes coalesced deltas through RealtimeChannelContext.SendContextNote — the PERCEPTION direction;
    3. an OPTIONAL ANGULAR SURFACE (GetSurfaceComponent) the overlay creates dynamically in a channel tab, handed back through BindSurface so the plugin wires its own inputs/outputs (the host never knows the component's API). A channel may be server-only (no rendered surface) — e.g. a bridge-contributed meeting-controls or native-whiteboard channel whose surface lives on the external platform, not in MJ. Such a channel returns null from GetSurfaceComponent (HasSurface is false) and the overlay simply skips its tab while still wiring its tools + perception;
    4. a STATE OF RECORD (SerializeState, persisted via RealtimeChannelContext.RequestSave under ChannelName).

    Concrete plugins are @RegisterClass(BaseRealtimeChannelClient, '<ClientPluginClass>') and are resolved at session start from the MJ: AI Agent Channels registry: each ACTIVE row's ClientPluginClass is the ClassFactory key (exactly how BaseRealtimeClient drivers resolve by provider key). Ship a Load<YourChannel>() no-op alongside the class and call it from a static code path to defeat tree-shaking.

    ClassFactory.CreateInstanceInitialize(ctx) → zero or more BindSurface/UnbindSurface cycles (the surface pane is created/destroyed with the overlay's tab panel, e.g. collapse/expand) → Dispose at teardown. ApplyAgentTool MUST work with NO surface bound (apply to the state engine directly; skip the UI garnish) — tool calls can arrive while the panel is collapsed.

    Type Parameters

    • TSurface extends object = object

      The plugin's Angular surface component type. The host only ever sees the default (object) — the typed parameter exists so concrete plugins get a fully typed BindSurface without casts.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    Context: RealtimeChannelContext | null = null

    The host context, available from Initialize until Dispose. null outside that window — guard with ?. in any code that can run early/late.

    SessionIdWaitIntervalMs: number = 200
    SessionIdWaitTimeoutMs: number = 8000

    Max time ResolveAgentSessionId waits for the session id to bind before giving up, and the poll interval it re-checks on. Protected so tests can shrink the wait; production keeps the defaults (the real mint race is sub-second, 8s is generous headroom).

    Accessors

    Methods

    • Executes ONE agent tool call locally (the ACTION direction) and returns the result JSON string fed back to the model as the tool_response. Called for every tool whose name starts with ToolNamePrefix. Must work both WITH a bound surface (apply + UI garnish) and WITHOUT one (apply to the state engine directly — the tab pane may not exist, e.g. the surface panel is collapsed). Should not throw: return a { success: false, error } payload so the model can narrate the failure (the host additionally wraps anything thrown).

      Parameters

      • toolName: string
      • argsJson: string

      Returns string | Promise<string>

    • Resolves the live RealtimeChannelContext.AgentSessionID, briefly WAITING for it when it isn't bound yet rather than giving up instantly. AgentSessionID is a live getter over the session service's current id: it reads null in the window BEFORE the session mints (the realtime model can fire a tool call the very first beat it connects, before mintSession resolves) and again AFTER teardown. Server-backed tool paths (e.g. the Remote Browser channel's browser_* tools) call this instead of reading Context?.AgentSessionID synchronously, so a tool invoked a beat early WAITS for the session to come live — defense-in-depth against the "session id missing" race — instead of returning a hard failure to the model.

      Returns the id as soon as it's non-null (the common path resolves immediately, no delay), or null if it's still unbound after SessionIdWaitTimeoutMs — or the channel was Disposed in the meantime (Context goes null, so we stop waiting on a torn-down session).

      Returns Promise<string | null>