@memberjunction/remote-browser-selfhost
v5.43.0
Published
MemberJunction: Self-Hosted Chrome backend driver for the Remote Browser channel. Connects the shared CDP control kit to a lightweight MJ-orchestrated headless-Chrome container (raw CDP control, MJ-hosted live view backed by the screencast, human takeover
Maintainers
Keywords
Readme
@memberjunction/remote-browser-selfhost
The Self-Hosted Chrome backend driver for MemberJunction's Remote Browser channel. Instead of a
browser-as-a-service, this backend has MJ orchestrate a lightweight headless-Chrome container (just
Chrome started with a --remote-debugging-port) and connect to it over the Chrome DevTools Protocol.
The shared CDP control kit does all the actual page driving, so this driver answers only one
backend-specific question — how do I obtain a CDP endpoint (and its live-view / release hooks) for a
self-hosted Chrome container? — behind an injectable container-runner seam, so it builds and
unit-tests with no container, no network, and no real browser.
See the Realtime Bridges Guide and
/plans/realtime/realtime-bridges-architecture.md (§4d-i, the Remote Browser channel) for the full
architecture.
Install
npm install @memberjunction/remote-browser-selfhostWhat it provides
SelfHostRemoteBrowser—@RegisterClass(BaseRemoteBrowserProvider, 'SelfHostRemoteBrowser'). AMJ: AI Remote Browser Providersrow withDriverClass = 'SelfHostRemoteBrowser'resolves to this driver via theClassFactory. It extendsBaseCdpRemoteBrowserProviderand implements onlyAcquireSession; everything else (action mapping, capability gating, screencast, human takeover,Connect/Disconnect) is inherited from@memberjunction/remote-browser-cdp.IChromeContainerRunner— the injectable orchestration seam the driver depends on instead of a real container orchestrator:Acquire(opts)→{ CdpEndpoint, ViewerUrl, Release() }.SelfHostSessionBackend— theICdpSessionBackendfor a live session:GetLiveViewUrl()returns the MJ-hosted viewer URL (backed by the inherited screencast),InvokeNativeAIControl()throws (no native harness), andRelease()tears down the container (idempotently).
Capability coverage (the Self-Hosted Chrome seed row)
Seed row name Self-Hosted Chrome, DriverClass = 'SelfHostRemoteBrowser'.
| Capability | Status |
|---|---|
| RawCdpControl | ✅ universal CDP substrate |
| LiveView | ✅ MJ-hosted viewer URL backed by the inherited CDP screencast |
| HumanTakeover | ✅ inherited grab-the-wheel input routing |
| ScreenStreaming | ✅ |
| PersistentContext | ✅ |
| MultiTab | ✅ |
| FileDownloads | ✅ |
| NativeAIControl | ➖ self-host has no first-party AI-control harness — InvokeNativeAIControl throws RemoteBrowserCapabilityNotSupportedError; MJ's own computer-use loop drives the page |
Unlike a browser-as-a-service, Self-Hosted Chrome has no provider-hosted live view of its own.
LiveView is still supported because GetLiveViewUrl() returns an MJ-hosted viewer URL whose page
renders the inherited CDP screencast frames — so it returns a URL rather than throwing.
Binding the real Chrome container runner (production)
This package ships without a real container orchestrator — that is a deployment concern, so no Docker
/ Kubernetes / Chrome-image wiring is hard-coded here. At startup, bind a factory that builds an
IChromeContainerRunner which spins up a headless-Chrome container and returns its CDP endpoint plus an
MJ-hosted viewer URL backed by the screencast:
import { SelfHostRemoteBrowser, IChromeContainerRunner } from '@memberjunction/remote-browser-selfhost';
SelfHostRemoteBrowser.SetContainerRunnerFactory(() => {
// Build a thin adapter over your real container orchestrator (Docker/K8s/…).
// Region/image/proxy arrive already resolved in the acquire options; never inline secrets.
const runner: IChromeContainerRunner = {
async Acquire(opts) {
// …start a headless-Chrome container with --remote-debugging-port,
// stand up the MJ viewer page backed by the screencast,
// and return the handle:
return {
CdpEndpoint, // ws://…/devtools/browser/…
ViewerUrl, // MJ-hosted viewer backed by the inherited screencast
async Release() {
// …stop + tear down the container
},
};
},
};
return runner;
});Until a factory is bound, AcquireSession throws an explicit "bind a real Chrome container runner via
SetContainerRunnerFactory" error.
Testing
Tests inject a FakeChromeContainerRunner via SelfHostRemoteBrowser.SetContainerRunnerFactory(...) —
no container, no network, no real browser. Run them with:
npm run test