Member Junction
    Preparing search index...

    Class BaseRealtimeChannelServerAbstract

    Base class for SERVER-SIDE interactive-channel plugins (per plans/ai-agent-sessions.md → "Pluggable Interfaces (IAgentChannelServer & IAgentChannelClient)").

    The plan's interface anticipates server-bridged media — a channel that owns sockets, receives demultiplexed OnClientMessage payloads from a unified ISessionTransport, and streams data back. That transport plane is an independent, not-yet-built track. What exists TODAY is the client-direct topology: channel plugins execute in the browser (BaseRealtimeChannelClient), and the server's per-channel touchpoints are the durable lifecycle events — session minted, channel state-of-record saved, session closed. This base class is the pragmatic adaptation to that reality:

    • Initialize(ctx) / Dispose() keep the plan's lifecycle bracket (and mirror the client half).
    • OnClientMessage / SendToClient / socket ownership are deferred with the transport track — when ISessionTransport lands, this class grows an injected-transport overload rather than the plan's raw-socket form (the plan itself refines them away; see its "Unified Session Transport").
    • The lifecycle hooks below (OnSessionStarted / OnChannelStateSave / OnSessionClosed) are the events the shipping session machinery actually emits.

    Concrete plugins are @RegisterClass(BaseRealtimeChannelServer, '<ServerPluginClass>') and are resolved at session start from the ACTIVE MJ: AI Agent Channels rows: each row's ServerPluginClass is the ClassFactory key. Rows whose key has no registration are skipped with a log — never fatal; a session always proceeds with whatever server plugins resolve. Ship a Load<YourChannel>Server() no-op beside the class and call it from a static code path so bundlers cannot tree-shake the registration away.

    ClassFactory.CreateInstanceInitialize(ctx) → OnSessionStarted → zero or more OnChannelStateSave calls (one per debounced client state-save landing on the server) → OnSessionClosed(reason) → Dispose. Disposal is deliberately deferred briefly after close by the host so the client's final post-close state flush (a legitimate, contract- sanctioned late save) still routes through the plugin.

    Every hook is invoked inside a host-side try/catch: a throwing plugin is logged and the session proceeds untouched — a channel plugin can never break a live call or block persistence. Implementations should still prefer returning benign results over throwing.

    A server-side channel may contribute a dynamic, runtime-computed tool vocabulary the agent can invoke server-side (a bot has no browser, so these execute on the server rather than client-side like the import('../..').BaseRealtimeChannelClient half). The two hooks:

    • GetServerToolDefinitions — returns the channel's server-executed tool declarations. May be runtime-computed (per session / per platform state), not only constants — this is what lets a bridge-contributed channel (e.g. Meeting Controls, a Zoom native whiteboard) declare a tool set that only exists because of the live connection. Default: [] (a state-only channel like the whiteboard contributes no server tools).
    • ExecuteServerTool — executes ONE of this channel's tools and returns the result. Default: a structured "not implemented" error (never throws), so a channel that declares tools but forgets to implement execution fails loudly-but-safely rather than crashing the session.

    The per-session host (RealtimeChannelServerHost) aggregates every live plugin's GetServerToolDefinitions into the session's tool set (feeding RealtimeSessionRunner.ServerChannelTools) and routes each {@link ToolNamePrefix}* tool call back to the owning plugin's ExecuteServerTool. Tool-name collisions across channels are avoided by each channel's ToolNamePrefix (mirroring the client half's ToolNamePrefix).

    Socket/media members (OnClientMessage, SendToClient) remain deferred with the unified-transport track — when ISessionTransport lands, this class grows an injected-transport overload rather than the plan's raw-socket form.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

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

    Accessors

    • get ToolNamePrefix(): string

      The shared name prefix of every server-executed tool this channel contributes (e.g. 'MeetingControls_'). The host routes any tool call whose name starts with this prefix to THIS plugin's ExecuteServerTool, which is what prevents tool-name collisions when multiple channels are active in one session. A channel that contributes no server tools may leave the default empty string (the host then never routes any call to it).

      Mirrors the client half's ToolNamePrefix. Default: '' (no server tools).

      Returns string

    Methods

    • Tears the plugin down: release any per-session resources, then drop the context. Subclasses overriding this MUST call super.Dispose(). Invoked by the host after the post-close linger window elapses (or immediately when the host is configured with no linger).

      Returns void

    • Executes ONE of this channel's server-side tools (a tool whose name starts with ToolNamePrefix) and returns the result fed back to the model as the tool_response.

      Implementations should NOT throw — return a { Success: false, Output } result so the model can narrate the failure. The host additionally wraps anything thrown into a structured error, so a throwing implementation can never break the live session. The default implementation returns a structured "not implemented" error, so a channel that declares tools via GetServerToolDefinitions but forgets to implement execution fails safely and visibly.

      Parameters

      • toolName: string

        The full tool name the model invoked (begins with ToolNamePrefix).

      • argsJson: string

        The raw arguments JSON string the model emitted for the call.

      Returns ServerChannelToolResult | Promise<ServerChannelToolResult>

      The execution result (or a structured error), synchronously or as a promise.

    • Returns this channel's server-executed tool declarations — the tools the agent can invoke on this channel that run server-side (a bot has no browser). May be runtime-computed: the returned set can depend on the live session, the connected platform, or current channel state, so a bridge-contributed channel can declare a vocabulary that only exists because of the live connection. Every tool's Name SHOULD start with ToolNamePrefix so the host can route its execution back here unambiguously.

      Invoked by RealtimeChannelServerHost when assembling the session's tool set (after the plugin's OnSessionStarted). Default: [] (a state-only channel contributes none).

      Returns RealtimeToolDefinition[]

      The channel's server-executed tool definitions (possibly empty).

    • Invoked when the client's debounced channel-state save for THIS channel lands on the server, BEFORE the state is persisted onto the session's MJ: AI Agent Session Channels row.

      The plugin may validate/normalize the payload: return a replacement JSON string to persist instead of stateJson, or null to persist the original unchanged (the default). The host treats a thrown error, a non-string, or an empty string as "keep the original" — a plugin can therefore never lose a state save, only improve it.

      Parameters

      • stateJson: string

        The raw state-of-record payload the client submitted (already size-capped host-side).

      Returns Promise<string>

      The normalized payload to persist, or null to keep stateJson as-is.

    • Invoked when the session is closed — from ANY close path: the user's explicit hang-up, the janitor's orphan/staleness sweeps, the graceful shutdown drain, or an error-path teardown (the reason says which). Fired once per session; Dispose follows after the host's brief post-close linger window (during which late state saves still route here first). Default: no-op.

      Parameters

      Returns Promise<void>