ProtectedContextThe host context, available from Initialize until Dispose.
null outside that window — guard with ?. in any code that can run early/late.
ProtectedSessionProtectedSessionMax 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).
Matches the seeded MJ: AI Agent Channels row's Name.
OPTIONAL accent color for the channel's tab (a CSS color string, e.g. an hsl() /
token). When a plugin supplies one, the overlay paints the tab's dot + active underline
with it; when omitted (the default null), the overlay derives a stable, deterministic
color from the ChannelName so every channel still reads as a distinct, colored
surface. A channel only overrides this to enforce a specific brand accent.
Font Awesome icon class for the channel's tab (e.g. 'fa-solid fa-chalkboard').
Headless — never rendered, but the abstract contract requires a label/icon.
Routing prefix — the single ContextTool matches ContextTool.startsWith(prefix).
Routes a ContextTool({ action, params }) call to the host's registered surface client tool.
Tolerant: malformed args, a missing host executor, or an unknown/throwing tool all serialize to
a structured { success: false, output } the model narrates (never throws).
Headless — no surface to bind.
Unsubscribes the app-context stream and tears down.
The channel's FIRST-RUN INTRO content, or null when the channel offers no onboarding.
The overlay shows this once per channel per user — the first time the user opens this
channel's surface tab — and remembers "seen" via the user's settings (NOT localStorage),
so it never re-appears on later sessions or other devices.
Default: null (no intro). The base Voice/text channel has no plugin at all, so it never
shows an intro; an interactive channel with a surface worth explaining (whiteboard, remote
browser, …) overrides this to return its ChannelOnboardingDetails. A plugin that
doesn't override it simply shows nothing — onboarding is strictly opt-in.
The Angular component the overlay creates dynamically as this channel's tab pane, or null
for a server-only channel that renders no MJ surface (its surface, if any, lives on the
external platform — e.g. a bridge-contributed native whiteboard or meeting-controls channel).
When this returns null, the overlay renders NO tab for the channel and never calls
BindSurface/UnbindSurface — but the channel's tools (GetToolDefinitions /
ApplyAgentTool) and perception (RealtimeChannelContext.SendContextNote) still run.
A created surface instance is handed straight back via BindSurface; the host treats it as
opaque.
Default: null (server-only). A channel with a rendered surface overrides this to return its
component type.
Declares the single stable proxy tool.
Whether this channel has a rendered MJ surface (GetSurfaceComponent returns non-null).
The overlay uses this to decide whether to register a surface tab; server-only channels are
false. Override only if surface availability must be decided WITHOUT constructing the type
(the default calls GetSurfaceComponent once).
Binds the host context and invokes the OnInitialize hook. Called exactly once per session, right after ClassFactory instantiation and before any tool call or surface bind.
ProtectedOnSubscribes to the host's live app-context stream and streams each change to the model as a
compact context note (the perception half). Null-safe — hosts that supply no AppContext$
(custom apps) simply get no streaming, and the session-start prompt injection still applies.
The focus pill's "exit" affordance, routed by the overlay to the channel that holds
focus. Implementations should leave focus mode through their OWN surface (so surface
toggles stay in sync), ultimately emitting Context.SetFocusMode(false). The overlay
defensively clears its layout flag as well, so a no-op default is safe.
ProtectedResolveResolves 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).
Restores a PRIOR session's saved channel state (the payload a previous session persisted via SerializeState / RealtimeChannelContext.RequestSave). Invoked by the session host AFTER Initialize and BEFORE any surface binding, when a prior session's saved state exists for this channel.
Returns true when the state was applied; false when the channel ignored it —
either because it keeps no persistent state (this default) or because the payload was
malformed/incompatible. Implementations MUST be tolerant: never throw on bad input,
just return false and start fresh.
Serializes the channel's current state of record (the payload persisted on the
session's channel row), or null when the channel keeps no persistent state.
Default: null.
Called by the host when the surface component is being destroyed (tab panel collapsed / overlay torn down). Drop the instance reference and unsubscribe any output subscriptions — after this, ApplyAgentTool runs in its no-surface mode. Default: no-op.
The headless Client Context channel client. One instance per realtime session (created by the session service from the
MJ: AI Agent Channelsregistry — never construct directly).