Member Junction
    Preparing search index...

    The REMOTE BROWSER as a pluggable interactive channel — a BaseRealtimeChannelClient resolved from the MJ: AI Agent Channels registry row whose ClientPluginClass is 'RealtimeRemoteBrowserChannel'. One instance per session (ClassFactory-created at session start).

    Topology (CLIENT-DIRECT, like the whiteboard — the browser just happens to live on the server):

    • Action: the browser_* client-executed tool set (REMOTE_BROWSER_TOOL_DEFINITIONS). ApplyAgentTool maps a tool call → a normalized RemoteBrowserAction (MapToolToAction) and awaits the ExecuteRemoteBrowserAction GraphQL mutation (via RealtimeChannelContext.ExecuteServerAction) to drive the server browser, returning a concise JSON result for the model. Never throws — argument and transport failures map to a { success: false, error } payload.
    • Perception: after a successful action, a [browser] context note carries the new page URL so the agent perceives where the page went; the surface independently polls a live screenshot.
    • Surface: RemoteBrowserSurfaceComponent, created dynamically in the channel tab; the plugin hands it the session's provider + id in BindSurface so it can poll RemoteBrowserSnapshot. HUMAN TAKEOVER is enabled by default (Collaborative): the user can click/type into the live canvas and those events relay to the server browser via RELAY_HUMAN_INPUT_MUTATION (server-gated on the backend's HumanTakeover capability).

    The channel keeps NO client-side state of record — the browser's state lives entirely on the server — so SerializeState / RestoreState use the base no-op behavior.

    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.

    GoalPollIntervalMs: number = 2500

    Poll cadence + deadline for pollGoalResult (the async browser_AchieveGoal result poll). Protected so tests can shrink them; production polls every 2.5s for up to 5 minutes (a goal loop past 5 min keeps running server-side, the model just gets a "still running" note).

    GoalPollTimeoutMs: number = ...
    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

    • get TabColor(): string | null

      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.

      Returns string | null

    Methods

    • Wires the dynamically-created surface: hands it a snapshot fetcher closing over the channel context (session id + provider live there), so the surface stays transport- agnostic. Set BEFORE the surface's first change detection (the pane binds synchronously), so its ngOnInit poll has the fetcher.

      Also asks the server to start a live screencast. When the backend supports ScreenStreaming the server starts PUSHING frames and reports Streaming: true; we flip the surface to canvas mode (its poll is then skipped) and OnScreencastFrame paints each pushed frame. When the backend lacks the capability (Streaming: false) the surface keeps the snapshot poll already running — graceful fallback, no further action.

      HUMAN TAKEOVER is enabled BY DEFAULT (Collaborative): the surface is flipped Interactive = true and its HumanInput output subscribed, forwarding each pointer/keyboard event to the server via RELAY_HUMAN_INPUT_MUTATION. Takeover only takes effect on the canvas (screencast) path; the <img> poll fallback stays view-only. The server gates the actual routing on the backend's HumanTakeover capability, so this is safe to enable unconditionally.

      Parameters

      Returns void

    • 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>