refactor: reorganize client transport and extension internals
- Split client, native, remote, serve, markdown, and SDK internals into focused packages with direct imports. - Move local and remote transport framing/protocol helpers behind clearer module boundaries. - Break up the extension injected DOM logic into a separate content dispatch bundle and dedicated content modules. - Add explicit client handling for passive remote discovery without noisy PQ warnings. - Keep behavior covered with updated unit, integration, and extension tests.
This commit is contained in:
@@ -67,7 +67,7 @@ The `install` command will:
|
||||
|
||||
After install, **fully restart your browser** (Quit and reopen — not just close the window). The extension will connect to the native host automatically on startup.
|
||||
|
||||
Only the `browser-cli` command needs to be on your `PATH`. The browser launches the native host wrapper directly from its absolute path in the native messaging manifest, and that wrapper points to the internally installed `native_host.py` copy. On Windows the install command also registers the host in the current user's Registry for the selected browser.
|
||||
Only the `browser-cli` command needs to be on your `PATH`. The browser launches the native host wrapper directly from its absolute path in the native messaging manifest, and that wrapper imports the installed `browser_cli.native.host` entry point. On Windows the install command also registers the host in the current user's Registry for the selected browser.
|
||||
|
||||
---
|
||||
|
||||
@@ -78,9 +78,19 @@ browser-cli/
|
||||
├── browser_cli/
|
||||
│ ├── __init__.py # Python SDK — BrowserCLI class and SDK entry point
|
||||
│ ├── cli.py # Click CLI entry point
|
||||
│ ├── client.py # Local IPC client used by CLI and SDK
|
||||
│ ├── client/ # Client-side command routing used by CLI and SDK
|
||||
│ │ ├── core.py # send_command and remote command routing
|
||||
│ │ ├── targets.py # Browser target discovery and socket resolution
|
||||
│ │ ├── auth.py # Remote auth fields and key lookup
|
||||
│ │ └── messages.py # Request/response helpers
|
||||
│ ├── models.py # Tab and Group helper models
|
||||
│ ├── native_host.py # Native messaging host launched by the browser
|
||||
│ ├── native/ # Native messaging host internals
|
||||
│ │ ├── host.py # Browser-launched native host entry point
|
||||
│ │ ├── local_server.py # Local CLI IPC server
|
||||
│ │ └── protocol.py # Chrome Native Messaging framing
|
||||
│ ├── remote/ # Client-side remote browser support
|
||||
│ │ ├── transport.py # TCP/TLS remote transport
|
||||
│ │ └── registry.py # Saved remote endpoints/keys
|
||||
│ └── commands/
|
||||
│ ├── navigate.py # nav open/reload/back/forward/focus
|
||||
│ ├── search.py # search engine shortcuts
|
||||
@@ -94,7 +104,8 @@ browser-cli/
|
||||
│ ├── manifest.json # MV3 extension manifest
|
||||
│ ├── content.js # Content-script helpers
|
||||
│ └── src/ # TypeScript source split by command area
|
||||
│ └── index.ts # Builds generated extension/background.js
|
||||
│ ├── index.ts # Builds generated extension/background.js
|
||||
│ └── content/ # Builds generated extension/content-dispatch.js
|
||||
├── examples/
|
||||
│ ├── demo.py # Python SDK walkthrough
|
||||
│ └── demo.sh # Bash CLI walkthrough
|
||||
@@ -285,12 +296,12 @@ browser-cli completion zsh --script # output raw completion script
|
||||
## Python SDK
|
||||
|
||||
```python
|
||||
from browser_cli import BrowserCLI
|
||||
from browser_cli import AsyncBrowserCLI, BrowserCLI
|
||||
|
||||
b = BrowserCLI()
|
||||
```
|
||||
|
||||
Commands are grouped into namespaces on the client (`b.tabs`, `b.dom`, `b.session`, ...). Each call blocks until the browser responds and returns the data directly as a Python object.
|
||||
Commands are grouped into namespaces on the client (`b.tabs`, `b.dom`, `b.session`, ...). Each sync call blocks until the browser responds and returns the data directly as a Python object. For asyncio programs, `AsyncBrowserCLI` exposes the same namespaces as native awaitable methods over async Unix/TCP transport.
|
||||
|
||||
```python
|
||||
# Navigation ── b.nav
|
||||
@@ -385,6 +396,35 @@ b.perf.status()
|
||||
b.perf.set_profile("gentle")
|
||||
b.extension.reload()
|
||||
|
||||
# Workflow decorators ── b.decorators
|
||||
@b.decorators.new_tab("https://example.com", wait=True, close=True)
|
||||
def scrape(*, tab):
|
||||
return b.extract.markdown("article")
|
||||
|
||||
@b.decorators.wait_for_selector("#ready", visible=True)
|
||||
def run_after_page_ready():
|
||||
return b.dom.text("#ready")
|
||||
|
||||
@b.decorators.performance_profile("ultra")
|
||||
def restore_big_session():
|
||||
return b.session.load("work", lazy=True)
|
||||
|
||||
@b.decorators.retry(times=3, delay=1)
|
||||
@b.decorators.save_session_before("before-risky-step")
|
||||
def risky_workflow():
|
||||
b.tabs.close_duplicates()
|
||||
|
||||
# Async SDK: same namespaces, native awaitable methods
|
||||
async def async_example():
|
||||
ab = AsyncBrowserCLI()
|
||||
tabs = await ab.tabs.list()
|
||||
|
||||
@ab.decorators.new_tab("https://example.com", wait=True, close=True)
|
||||
async def scrape(*, tab):
|
||||
return await ab.extract.markdown("article")
|
||||
|
||||
return tabs, await scrape()
|
||||
|
||||
# Misc
|
||||
clients = b.clients()
|
||||
raw = b.command("tabs.count", {"pattern": "github"}) # escape hatch for raw commands
|
||||
@@ -436,7 +476,7 @@ bash examples/demo.sh
|
||||
|
||||
```sh
|
||||
npm ci
|
||||
npm run check:extension # type-check, build extension/background.js, syntax-check bundle
|
||||
npm run check:extension # type-check, build extension bundles, syntax-check bundle
|
||||
uv run pytest -q
|
||||
```
|
||||
|
||||
@@ -447,7 +487,7 @@ nix-shell # automatically runs npm ci when node_modules is missing/outdated
|
||||
npm run check:extension
|
||||
```
|
||||
|
||||
The extension source lives in `extension/src/`. `extension/background.js` is generated and ignored by git. Run `npm run build:extension` before using `Load unpacked` with `extension/`. On NixOS, use `nix-shell` first if npm is not installed globally.
|
||||
The extension source lives in `extension/src/`. `extension/background.js` and `extension/content-dispatch.js` are generated and ignored by git. Run `npm run build:extension` before using `Load unpacked` with `extension/`. On NixOS, use `nix-shell` first if npm is not installed globally.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user