From 86a41b28510bde5e221aede0ab40a7114dd53e11 Mon Sep 17 00:00:00 2001 From: Ljy-0827 Date: Fri, 31 Jul 2026 11:43:13 +0800 Subject: [PATCH] fix: agent self-recovery when 0 browsers connected (issue #40) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add 0-browser recovery protocol in SKILL.md: agent should self-detect and self-launch browsers before falling back to user interaction - Update NoBrowserConnected error hint in render_error.rs with detailed ACTION and FALLBACK branches for different agent capabilities - Update NO_BROWSER_HINT in status.rs and doctor.rs with consistent two-case FALLBACK (can detect vs cannot detect) - Clarify that BrowserSkill never launches browsers itself — browser launch is always the agent's responsibility via shell commands --- crates/bsk-cli/skill/SKILL.md | 32 +++++++++++++++++++++++ crates/bsk-cli/src/cli/doctor.rs | 28 ++++++++++++++++---- crates/bsk-cli/src/cli/render_error.rs | 2 +- crates/bsk-cli/src/cli/status.rs | 36 ++++++++++++++++++++++++++ skill/SKILL.md | 32 +++++++++++++++++++++++ 5 files changed, 124 insertions(+), 6 deletions(-) diff --git a/crates/bsk-cli/skill/SKILL.md b/crates/bsk-cli/skill/SKILL.md index 43d2417..fe9c5ee 100644 --- a/crates/bsk-cli/skill/SKILL.md +++ b/crates/bsk-cli/skill/SKILL.md @@ -32,6 +32,27 @@ Drive the user's **real Chromium browser** (with their logins and cookies) throu 2. browser-skill **extension** loaded in Chromium and connected (popup shows green) 3. Any `bsk` command auto-starts background services as needed; use `bsk doctor` if anything fails +### 0-browser recovery protocol (mandatory) + +When you observe `browsers connected: 0` (from `bsk status`) or a `NoBrowserConnected` failure (from `bsk session start` / `bsk doctor`), **do not ask the user to check anything yet**. The default behaviour — every time — is to recover on the agent's own, in this exact order: + +1. **Self-detect.** Run `pgrep -lf 'Google Chrome|Chromium|brave-browser|microsoft-edge'` (or the platform equivalent). If any of those processes are running, the browser is up but its extension is not connected — go straight to step 3. +2. **Self-launch (if nothing was running).** You almost certainly have a shell that can spawn GUI apps. Launch the user's default supported browser yourself: + - macOS: `open -a "Google Chrome"` (or `Chromium` / `"Microsoft Edge"` / `"Brave Browser"`) + - Linux: `google-chrome &` (or `chromium` / `microsoft-edge` / `brave-browser &`) + - Windows: `start chrome` (or `start chromium` / `start msedge` / `start brave`) +3. **Wait + verify.** Sleep a few seconds (`bsk wait-ms 3s` or `sleep 3`), then re-run `bsk status` (or `bsk browsers`). If `browsers connected` is still 0, retry once (an extension service worker may need a moment to wake). +4. **Now retry the original task** (`bsk session start`, etc.) — do not pre-emptively message the user. + +Only fall back to involving the user if you hit one of these blockers and **only at the matching step**: + +- **Step 1 detected a browser, but step 3 still shows 0 after retry** → the extension is likely not installed or the popup is not green. Ask the user to confirm the browser-skill extension is loaded in that browser and the popup is green, then retry step 3. +- **Step 2 cannot launch** (sandboxed shell, no GUI spawn) → detect which browsers are present, report state, ask the user to open a supported browser themselves, then retry from step 3 after they confirm. +- **Step 1 cannot detect processes at all** (no `pgrep` / no OS access) → ask the user to confirm a supported Chromium browser is started with the extension connected, then retry. +- **No supported Chromium browser is installed on this host** → tell the user to install one (Chrome, Chromium, Edge, or Brave) and the browser-skill extension; retry after they confirm. + +The `hint:` line that `bsk status` and `bsk doctor` print in this state is the same tree condensed into one line — follow it. + ## Mandatory workflow Every automation task **must** follow this lifecycle. Do **not** rely on idle timeouts (default session idle is 5 minutes). @@ -260,6 +281,17 @@ Human errors print `error:` + `hint:` on stderr; `--json` includes `code`, `mess | Any failure you cannot fix in one retry | `bsk doctor` | | Multiple browsers / wrong target | `bsk browsers` then `bsk session start --browser ` | +### NoBrowserConnected (exit 1) + +No browser with the browser-skill extension installed and connected was found. +BrowserSkill never launches a browser — the agent or user must. Get one connected: + +| Capability | Action | +|------------|--------| +| Can detect + launch (default) | Launch the browser yourself (relaunch if a stale one is open but not green); confirm connected via `bsk status`; retry. | +| Can detect, no launch | Report detected state; ask user to open the browser and confirm extension installed and connected; retry after confirm. | +| No OS access / human | Ask user to confirm a supported browser is started and the extension is installed and connected; retry. | + Always **`bsk session stop `** in a `finally`-style path so the Agent Window closes and borrowed tabs return. ## Red lines diff --git a/crates/bsk-cli/src/cli/doctor.rs b/crates/bsk-cli/src/cli/doctor.rs index fa33718..1fa16ee 100644 --- a/crates/bsk-cli/src/cli/doctor.rs +++ b/crates/bsk-cli/src/cli/doctor.rs @@ -404,6 +404,27 @@ fn display_protocol(value: &str) -> &str { if value.is_empty() { "unknown" } else { value } } +/// Repair hint emitted by [`check_extension_connected`] when zero +/// browsers are online. Mirrors the ACTION/FALLBACK decision tree of +/// `ErrorCode::NoBrowserConnected` in `cli::render_error` (issue #40) +/// so an LLM driving `bsk doctor` is steered to launch a browser +/// itself (the default), fall back to asking the user only when it +/// genuinely cannot spawn GUI apps, and reach for the Web Store URL +/// only as a last-resort "no Chromium installed on this host" path. +/// Kept as a single line because [`render_human`] concatenates it +/// after `— hint: ` without wrapping. +const NO_BROWSER_HINT: &str = "BrowserSkill does not launch browsers itself. \ +Launch a supported Chromium browser (Chrome / Chromium / Edge / Brave) so the extension can connect — \ +quit and relaunch any stale one whose extension popup is not green. \ +macOS: `open -a \"Google Chrome\"` (or Chromium / \"Microsoft Edge\" / \"Brave Browser\"); \ +Linux: `google-chrome &` (or chromium / microsoft-edge / brave-browser &); \ +Windows: `start chrome` (or start chromium / start msedge / start brave). \ +Then `bsk status` / `bsk browsers` and retry. \ +FALLBACK — only if you genuinely CANNOT launch applications (sandboxed, no GUI spawn, or no shell/OS access): \ +- Can detect processes but cannot launch: detect which browsers are running and report state; ask user to open a supported browser and confirm extension is connected (popup green); retry after they confirm. \ +- Cannot detect processes at all: ask user to confirm a supported Chromium browser is started and the extension is connected (popup green); retry. \ +If no supported Chromium browser is installed on this host at all, install one and the browser-skill extension from {URL}."; + fn check_extension_connected(status: Option<&StatusResult>) -> CheckResult { let name = "extension connected"; let Some(status) = status else { @@ -417,11 +438,8 @@ fn check_extension_connected(status: Option<&StatusResult>) -> CheckResult { if browsers > 0 { CheckResult::ok(name, format!("{} browser(s) connected", browsers)) } else { - CheckResult::fail( - name, - "0 browsers connected", - format!("install the extension from {EXTENSION_STORE_URL} and load it in Chromium"), - ) + let hint = NO_BROWSER_HINT.replace("{URL}", EXTENSION_STORE_URL); + CheckResult::fail(name, "0 browsers connected", hint) } } diff --git a/crates/bsk-cli/src/cli/render_error.rs b/crates/bsk-cli/src/cli/render_error.rs index 30cd5bb..a568ddd 100644 --- a/crates/bsk-cli/src/cli/render_error.rs +++ b/crates/bsk-cli/src/cli/render_error.rs @@ -156,7 +156,7 @@ pub fn info_for(code: ErrorCode) -> RenderInfo { ErrorCode::NoBrowserConnected => RenderInfo { summary: "no browser is connected to the daemon", hint: Some( - "open the browser-skill extension in your browser and wait for the popup to show \"connected\"", + "a supported Chromium browser (Chrome, Chromium, Edge, or Brave) with the browser-skill extension installed and connected (popup shows green) is required before a session can start. BrowserSkill does not launch browsers itself — so the agent (or user) must connect one.\n\nACTION — do this first. If you run in a normal shell (the usual case for an AI agent, and you can spawn GUI apps), launch the browser yourself:\n1. If a supported browser is already running but its popup is NOT green, quit it and relaunch so the extension makes a fresh connection.\n2. If no supported browser is running, launch one:\n - macOS: open -a \"Google Chrome\" (or Chromium / \"Microsoft Edge\" / \"Brave Browser\")\n - Linux: google-chrome & (or chromium / microsoft-edge / brave-browser &)\n - Windows: start chrome (or start chromium / start msedge / start brave)\n3. Wait a few seconds for the extension to connect; verify with `bsk status` or `bsk browsers`.\n4. Retry `bsk session start`.\n\nFALLBACK — only if you genuinely CANNOT launch applications in your environment (sandboxed shell with no GUI spawn, or no shell/OS access at all):\n- Can detect processes but cannot launch: detect which supported browsers are running and report the state; ask the user to open the missing browser and confirm the browser-skill extension is installed and connected (popup green); retry after they confirm.\n- Cannot detect processes at all: ask the user to confirm a supported Chromium browser is started and the browser-skill extension is installed and connected (popup green); retry.\n\nIf you are a human user: open a supported Chromium browser, ensure the browser-skill extension is installed and its popup shows connected (green), then run `bsk session start` again.", ), exit_code: 1, }, diff --git a/crates/bsk-cli/src/cli/status.rs b/crates/bsk-cli/src/cli/status.rs index 77855f0..87e69c5 100644 --- a/crates/bsk-cli/src/cli/status.rs +++ b/crates/bsk-cli/src/cli/status.rs @@ -11,6 +11,32 @@ use crate::cli::browser_wait::{ use crate::cli::ensure_daemon::ensure_daemon; use crate::cli::error::CliError; +/// Chrome Web Store listing for the browser-skill extension. Mirrors the +/// same constant in `cli::doctor` — they must stay in sync so a single +/// `bsk status` / `bsk doctor` run steers an LLM to the same place. +const EXTENSION_STORE_URL: &str = + "https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi"; + +/// Repair hint appended after the `browsers connected` row when zero +/// browsers are online. Mirrors the ACTION/FALLBACK decision tree of +/// `ErrorCode::NoBrowserConnected` in `cli::render_error` and the +/// `extension connected` check in `cli::doctor` (issue #40) so an LLM +/// driving `bsk status` is steered to launch a browser itself, fall +/// back to asking the user only when it genuinely cannot spawn GUI +/// apps, and reach for the Web Store URL only as a last-resort +/// "no Chromium installed on this host" path. +const NO_BROWSER_HINT: &str = "BrowserSkill does not launch browsers itself. \ +Launch a supported Chromium browser (Chrome / Chromium / Edge / Brave) so the extension can connect — \ +quit and relaunch any stale one whose extension popup is not green. \ +macOS: `open -a \"Google Chrome\"` (or Chromium / \"Microsoft Edge\" / \"Brave Browser\"); \ +Linux: `google-chrome &` (or chromium / microsoft-edge / brave-browser &); \ +Windows: `start chrome` (or start chromium / start msedge / start brave). \ +Then `bsk status` / `bsk browsers` and retry. \ +FALLBACK — only if you genuinely CANNOT launch applications (sandboxed, no GUI spawn, or no shell/OS access): \ +- Can detect processes but cannot launch: detect which browsers are running and report state; ask user to open a supported browser and confirm extension is connected (popup green); retry after they confirm. \ +- Cannot detect processes at all: ask user to confirm a supported Chromium browser is started and the extension is connected (popup green); retry. \ +If no supported Chromium browser is installed on this host at all, install one and the browser-skill extension from {URL}."; + /// Output format selector. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Output { @@ -99,6 +125,16 @@ fn render_human(s: &StatusResult) { for (key, value) in &rows { println!("{key: anyhow::Result<()> { diff --git a/skill/SKILL.md b/skill/SKILL.md index 43d2417..fe9c5ee 100644 --- a/skill/SKILL.md +++ b/skill/SKILL.md @@ -32,6 +32,27 @@ Drive the user's **real Chromium browser** (with their logins and cookies) throu 2. browser-skill **extension** loaded in Chromium and connected (popup shows green) 3. Any `bsk` command auto-starts background services as needed; use `bsk doctor` if anything fails +### 0-browser recovery protocol (mandatory) + +When you observe `browsers connected: 0` (from `bsk status`) or a `NoBrowserConnected` failure (from `bsk session start` / `bsk doctor`), **do not ask the user to check anything yet**. The default behaviour — every time — is to recover on the agent's own, in this exact order: + +1. **Self-detect.** Run `pgrep -lf 'Google Chrome|Chromium|brave-browser|microsoft-edge'` (or the platform equivalent). If any of those processes are running, the browser is up but its extension is not connected — go straight to step 3. +2. **Self-launch (if nothing was running).** You almost certainly have a shell that can spawn GUI apps. Launch the user's default supported browser yourself: + - macOS: `open -a "Google Chrome"` (or `Chromium` / `"Microsoft Edge"` / `"Brave Browser"`) + - Linux: `google-chrome &` (or `chromium` / `microsoft-edge` / `brave-browser &`) + - Windows: `start chrome` (or `start chromium` / `start msedge` / `start brave`) +3. **Wait + verify.** Sleep a few seconds (`bsk wait-ms 3s` or `sleep 3`), then re-run `bsk status` (or `bsk browsers`). If `browsers connected` is still 0, retry once (an extension service worker may need a moment to wake). +4. **Now retry the original task** (`bsk session start`, etc.) — do not pre-emptively message the user. + +Only fall back to involving the user if you hit one of these blockers and **only at the matching step**: + +- **Step 1 detected a browser, but step 3 still shows 0 after retry** → the extension is likely not installed or the popup is not green. Ask the user to confirm the browser-skill extension is loaded in that browser and the popup is green, then retry step 3. +- **Step 2 cannot launch** (sandboxed shell, no GUI spawn) → detect which browsers are present, report state, ask the user to open a supported browser themselves, then retry from step 3 after they confirm. +- **Step 1 cannot detect processes at all** (no `pgrep` / no OS access) → ask the user to confirm a supported Chromium browser is started with the extension connected, then retry. +- **No supported Chromium browser is installed on this host** → tell the user to install one (Chrome, Chromium, Edge, or Brave) and the browser-skill extension; retry after they confirm. + +The `hint:` line that `bsk status` and `bsk doctor` print in this state is the same tree condensed into one line — follow it. + ## Mandatory workflow Every automation task **must** follow this lifecycle. Do **not** rely on idle timeouts (default session idle is 5 minutes). @@ -260,6 +281,17 @@ Human errors print `error:` + `hint:` on stderr; `--json` includes `code`, `mess | Any failure you cannot fix in one retry | `bsk doctor` | | Multiple browsers / wrong target | `bsk browsers` then `bsk session start --browser ` | +### NoBrowserConnected (exit 1) + +No browser with the browser-skill extension installed and connected was found. +BrowserSkill never launches a browser — the agent or user must. Get one connected: + +| Capability | Action | +|------------|--------| +| Can detect + launch (default) | Launch the browser yourself (relaunch if a stale one is open but not green); confirm connected via `bsk status`; retry. | +| Can detect, no launch | Report detected state; ask user to open the browser and confirm extension installed and connected; retry after confirm. | +| No OS access / human | Ask user to confirm a supported browser is started and the extension is installed and connected; retry. | + Always **`bsk session stop `** in a `finally`-style path so the Agent Window closes and borrowed tabs return. ## Red lines