Optionaldeps: MeetingControlsChannelDepsOptional per-session dependencies. Omitted only for a registry-resolved discovery instance (the host's ClassFactory path) — such an instance maintains no live state and contributes its tool vocabulary but cannot actuate platform mutes.
ProtectedContextThe bound session context, available from Initialize until Dispose.
null outside that window — guard with ?. in any code that can run early/late.
The channel definition name — MUST match the MJ: AI Agent Channels row's Name
(e.g. 'Whiteboard'). The host routes OnChannelStateSave by the registry row's
name and warns when a resolved plugin's ChannelName disagrees with its row.
Read-only access to the live facilitator state (for the channel's own perception + tests).
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).
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).
Executes one facilitator tool and returns the result (the model narrates it). Tool dispatch is by the bare tool name (after the MEETING_CONTROLS_TOOL_PREFIX). Never throws — bad args or an unknown tool resolve to a structured failure result.
The full tool name (prefixed).
The raw arguments JSON.
The execution result.
The facilitator tool vocabulary. MuteParticipant is included only when the platform advertises
the 'Mute' capability — so the contributed tool set is runtime-computed from the connected
platform's abilities (the §4b dynamic-tool point), not a fixed constant.
The contributed server-executed tool definitions.
Binds the session context and invokes the OnInitialize hook. Called exactly once per session by the host, right after ClassFactory instantiation and before any lifecycle hook.
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.
The raw state-of-record payload the client submitted (already size-capped host-side).
The normalized payload to persist, or null to keep stateJson as-is.
ProtectedOnSubclass hook invoked from Initialize once Context is bound — allocate any per-session state here. Default: no-op.
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.
The persisted close provenance, or null for legacy/unstamped rows.
Subscribes the injected event source's perception streams into MeetingControlsState and emits an initial perception snapshot. A discovery instance (no event source) is inert.
Server-only Meeting Controls channel — the facilitator surface. ONE instance per session.
Unlike the whiteboard (resolved from the registry by the host via a parameterless ClassFactory construction), this channel needs a per-session IMeetingControlsEventSource from the bridge, so a bridge driver constructs it directly with MeetingControlsChannelDeps and hands it to the host's per-session plugin set. It has no client surface — the contract's
GetServerToolDefinitions/ExecuteServerToolare the entire interface; there is noGetSurfaceComponenton the server half at all.Registered under MEETING_CONTROLS_CHANNEL_NAME so a seeded registry row can resolve a default (event-source-less) instance for discovery; a real session always injects the driver's event source.