Metadata-Version: 2.5
Name: hitl-cdp-browser-provider
Version: 0.1.1
Summary: Bridge any CDP-capable browser session (agent-browser, Playwright, Puppeteer, plain Chrome) into an HTTP+WebSocket endpoint for human-in-the-loop remote viewing/control, e.g. HITL Broker's Browser Gateway.
Project-URL: Homepage, https://github.com/aqiu9/HITL-Broker
Project-URL: Repository, https://github.com/aqiu9/HITL-Broker
License: MIT
Keywords: agent-browser,browser-automation,cdp,chrome-devtools-protocol,hitl,human-in-the-loop,playwright,puppeteer
Requires-Python: >=3.9
Requires-Dist: websockets<14,>=13
Description-Content-Type: text/markdown

# hitl-cdp-browser-provider

Bridges **any** Chrome DevTools Protocol (CDP) browser session into a plain
HTTP page + WebSocket endpoint — the shape [HITL Broker](https://github.com/aqiu9/HITL-Broker)'s
Browser Gateway (and similar systems) expect a task's `internal_url` to
serve.

Works with anything that exposes a CDP remote-debugging endpoint:
[agent-browser](https://github.com/keithamus/agent-browser), Playwright,
Puppeteer, or a plain `chrome --remote-debugging-port=...`. It talks CDP's
own standard primitives (`Page.startScreencast`, `Input.dispatchMouseEvent`,
`Input.dispatchKeyEvent`) — not any tool-specific protocol — so one bridge
covers all of them. Functionally identical to the
[Node package of the same name](https://github.com/aqiu9/HITL-Broker/tree/main/packages/node/hitl-cdp-browser-provider);
pick whichever fits your automation stack (e.g. Playwright-Python/Selenium-Python
users won't need Node at all).

## Install

```bash
pip install hitl-cdp-browser-provider
```

## Use

```bash
# Point it at a CDP HTTP base -- it auto-picks the first "page" target
hitl-cdp-browser-provider --cdp-http http://127.0.0.1:9222 --bind 0.0.0.0:18234 --token "$(openssl rand -hex 16)"

# Or an exact page WebSocket URL if you already have one
hitl-cdp-browser-provider --cdp-url ws://127.0.0.1:9222/devtools/page/ABC123 --bind 0.0.0.0:18234 --token "$(openssl rand -hex 16)"
```

Then point your HITL Source's `browser_endpoint` (or any equivalent
"internal_url for browser tasks" field) at `<bind-host>:<bind-port>?token=<same-secret>`.

**⚠️ This bridge has no authentication of its own beyond `--token`.**
Without it, anyone who can reach `--bind`'s address and port can view and
remotely control the browser session -- no HITL token, no login, nothing.
`127.0.0.1` (the default) is safe on its own since only local processes
can reach it; the moment you bind wider (`0.0.0.0`, a LAN IP -- which the
typical deployment needs, since the bridge and HITL Broker usually run on
different hosts), **always pass `--token`**. The viewer page forwards its
own query string (including `?token=...`) into the WebSocket URL it opens,
so setting it once on the page's URL covers both the HTTP GET and the WS
connection.

### Finding a CDP endpoint

- **agent-browser**: `agent-browser get cdp-url --session <name>` gives a
  `ws://127.0.0.1:<port>/devtools/browser/<id>` browser-level URL — pass its
  `http://127.0.0.1:<port>` base as `--cdp-http` (screencast needs a page
  target, which `--cdp-http` auto-discovers via `/json/list`).
- **Chrome/Chromium directly**: launch with `--remote-debugging-port=9222`,
  use `--cdp-http http://127.0.0.1:9222`.
- **Playwright (Python)**: launch Chromium with
  `args=["--remote-debugging-port=9222"]`, then point `--cdp-http` at that
  port. (`browser.new_cdp_session(page)` also works if you'd rather wire
  the CDP session up yourself instead of using this CLI.)
- **Selenium (Python)**: Chrome launched with `--remote-debugging-port`
  works the same way; Selenium 4's own `driver.execute_cdp_cmd` isn't
  needed here since this bridge connects directly.

## Library use

```python
import asyncio
from hitl_cdp_browser_provider import serve

asyncio.run(serve({
    "cdp_http": "http://127.0.0.1:9222",
    "cdp_url": None,
    "bind": "0.0.0.0:18234",
    "quality": 60,
    "max_width": 1280,
    "max_height": 800,
    "token": "replace-with-a-real-secret",
}))
```

## Protocol

The viewer page renders `{"t":"frame","data":"<base64 jpeg>"}` messages onto
a `<canvas>` and sends back `{"t":"mouse",...}` / `{"t":"key",...}` messages,
which this bridge translates 1:1 into `Input.dispatchMouseEvent` /
`Input.dispatchKeyEvent` CDP calls.

## Not CDP? Use noVNC instead

If your browser session isn't driven by anything CDP-capable (or you want a
screen-level rather than browser-API-level handoff — e.g. an arbitrary GUI
app in a container, not just a browser), see the
[noVNC recipe](https://github.com/aqiu9/HITL-Broker/blob/main/docs/browser-provider-novnc.md)
in the HITL-Broker repo instead — noVNC + websockify already implements the
same "HTTP page + WS" contract with zero custom *code*, at the cost of
needing an X server (Xvfb) + VNC server in the container (see that doc for
path-prefix caveats).

## License

MIT
