Merge PR #7007: feat(tools): add a browser.cdpUrl setting for the default automation target (@terrxo)

This commit is contained in:
can1357
2026-07-30 01:48:50 +02:00
4 changed files with 21 additions and 2 deletions
+3 -2
View File
@@ -55,7 +55,7 @@
| `viewport` | `{ width: number; height: number; scale?: number }` | No | Requested viewport. For headless launch this becomes the initial viewport; for a page it is applied with `page.setViewport()`. `scale` maps to Puppeteer `deviceScaleFactor`. |
| `wait_until` | `"load" \| "domcontentloaded" \| "networkidle0" \| "networkidle2"` | No | Navigation wait condition. Defaults to `"load"` where omitted, including `open` navigation and later `tab.goto(...)`. |
| `dialogs` | `"accept" \| "dismiss"` | No | Installs a page `dialog` handler that auto-accepts or auto-dismisses dialogs. Omitted means no handler. |
| `app` | `{ path?: string; cdp_url?: string; args?: string[]; target?: string }` | No | Selects browser kind. With no `app`, the cmux backend is used when a cmux socket is available (`CMUX_SOCKET_PATH`, gated by the `browser.cmux` setting / `PI_BROWSER_CMUX` override); otherwise the session `browser.headless` setting applies. `app.path` is resolved against the session cwd and used as the executable path for spawn/attach reuse. `app.cdp_url` connects to an existing CDP endpoint. `args` are appended only when spawning `app.path`. `target` is only used for attached/spawned-app page selection. |
| `app` | `{ path?: string; cdp_url?: string; args?: string[]; target?: string }` | No | Selects browser kind. With no `app`, a configured `browser.cdpUrl` setting attaches to that endpoint; otherwise the cmux backend is used when a cmux socket is available (`CMUX_SOCKET_PATH`, gated by the `browser.cmux` setting / `PI_BROWSER_CMUX` override); otherwise the session `browser.headless` setting applies. `app.path` is resolved against the session cwd and used as the executable path for spawn/attach reuse. `app.cdp_url` connects to an existing CDP endpoint. `args` are appended only when spawning `app.path`. `target` is only used for attached/spawned-app page selection. |
### `action: "close"`
@@ -92,6 +92,7 @@ The tool returns one result per call; no streaming partial output is emitted fro
2. `open` resolves browser kind with `resolveBrowserKind()`:
- `app.cdp_url` → `{ kind: "connected" }` after trimming trailing slashes.
- `app.path` → `{ kind: "spawned" }` after resolving against session cwd.
- otherwise, a non-empty `browser.cdpUrl` setting → `{ kind: "connected" }` after trimming whitespace and trailing slashes.
- otherwise, `resolveCmuxKind()` → `{ kind: "cmux", socketPath, password?, surface? }` when `CMUX_SOCKET_PATH` is set and cmux is enabled (`browser.cmux` setting, overridable by `PI_BROWSER_CMUX`).
- otherwise → `{ kind: "headless", headless: session.settings.get("browser.headless") }`.
3. `open` rejects reusing the same tab name across different browser kinds (`sameBrowserKind()`); callers must close first.
@@ -163,7 +164,7 @@ The tool returns one result per call; no streaming partial output is emitted fro
- **Browser kind**
- **Headless**: launches local Chromium with Puppeteer, applies stealth patches, and creates a fresh page per tab.
- **Spawned app (`app.path`)**: reuses an existing CDP-enabled process for that executable when possible; otherwise kills same-path processes, spawns the executable with remote debugging enabled, then attaches. No stealth patches are injected.
- **Connected browser (`app.cdp_url`)**: attaches to an already-running CDP endpoint. No process ownership; close only disconnects.
- **Connected browser (`app.cdp_url`, or the `browser.cdpUrl` setting when the call carries no `app`)**: attaches to an already-running CDP endpoint. No process ownership; close only disconnects.
- **Cmux surface (`browser.cmux`)**: with no `app` and a cmux socket available (`CMUX_SOCKET_PATH`, enabled by the `browser.cmux` setting / `PI_BROWSER_CMUX` override), drives a cmux WKWebView surface over a unix-socket JSON-RPC client instead of Puppeteer. No Bun worker and no stealth patches; `open` opens a split (owning that surface), `run` executes via `runCmuxCode()`, and `close` issues `surface.close` for surfaces it owns (leaving the workspace's last surface open).
- **Target selection for attached/spawned browsers**
- With `app.target`, `pickElectronTarget()` returns the first page whose URL or title contains the case-insensitive substring.
+1
View File
@@ -42,6 +42,7 @@
- Added `fastModeEnabled` and `fastModeActive` to RPC `get_state` responses.
- Fixed RPC fast-mode state reporting after direct Anthropic rejects `speed: "fast"`, while allowing explicit re-enable requests to retry priority service.
- Added opt-in subagent access to `checkpoint`, `rewind`, `learn`, and `manage_skill` when explicitly listed in an agent definition's `tools:` frontmatter. Listing one of `checkpoint`/`rewind` auto-includes the other. Settings (`checkpoint.enabled`, `autolearn.enabled`) remain master toggles.
- Added a `browser.cdpUrl` setting that points browser automation at an already-running CDP endpoint by default, so `app.cdp_url` no longer has to be repeated on every call. Explicit `app` options still take precedence.
## [17.1.8] - 2026-07-28
@@ -4054,6 +4054,18 @@ export const SETTINGS_SCHEMA = {
},
},
"browser.cdpUrl": {
type: "string",
default: undefined,
ui: {
tab: "tools",
group: "Grep & Browser",
label: "Browser CDP URL",
description:
"Default HTTP CDP discovery endpoint (for example http://127.0.0.1:9222) to attach to instead of launching a browser. Explicit app.cdp_url or app.path on the tool call take precedence.",
},
},
"browser.headless": {
type: "boolean",
default: true,
@@ -95,6 +95,11 @@ function resolveBrowserKind(params: BrowserParams, session: ToolSession): Browse
const exe = resolveToCwd(app.path, session.cwd);
return { kind: "spawned", path: exe };
}
// A configured endpoint is a default, not an override: explicit app options win.
const configuredCdpUrl = (session.settings.get("browser.cdpUrl") as string | undefined)?.trim();
if (configuredCdpUrl) {
return { kind: "connected", cdpUrl: configuredCdpUrl.replace(/\/+$/, "") };
}
const cmuxKind = resolveCmuxKind({
settingEnabled: session.settings.get("browser.cmux") as boolean | undefined,
});