browser-pilot-cli 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,15 +25,23 @@ Inspect installed browsers without requesting authorization:
25
25
  bp browsers
26
26
  ```
27
27
 
28
- Connect when browser work is needed:
28
+ Follow the returned remediation first. Start the selected browser or enable
29
+ remote debugging when requested. Browser Pilot does not connect automatically.
30
+
31
+ When the browser is ready and browser work is needed, tell the user to watch
32
+ for Chrome's Allow dialog, then connect once:
29
33
 
30
34
  ```bash
31
- bp connect
35
+ bp connect --browser <browser-id>
32
36
  ```
33
37
 
34
38
  Chrome may display one Allow dialog for the browser connection. Browser
35
39
  discovery and background-service startup are passive. Concurrent clients share
36
40
  one pending connection request, so they do not create an authorization loop.
41
+ Machine-readable `bp connect` output is emitted after the attempt finishes, so
42
+ an Agent must show the Allow reminder before invoking the command. A timeout or
43
+ `browser_not_authorized` result must be inspected; it is not a reason to loop
44
+ connection attempts.
37
45
 
38
46
  ### 2. Install the Agent skill
39
47
 
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import { writeFileSync as writeFileSync2, readFileSync as readFileSync4, existsS
6
6
  import { basename as basename2, isAbsolute as isAbsolute3, resolve as resolvePath } from "path";
7
7
 
8
8
  // src/version.ts
9
- var BROWSER_PILOT_VERSION = "0.5.0";
9
+ var BROWSER_PILOT_VERSION = "0.5.1";
10
10
 
11
11
  // src/protocol/errors.ts
12
12
  var ERROR_CODES = [
@@ -1435,12 +1435,6 @@ async function resumeCompatibility(executableVersion, clientKey = CLIENT_KEY, in
1435
1435
  return null;
1436
1436
  }
1437
1437
  }
1438
- async function withCompatibilityTarget(executableVersion, operation, clientKey = CLIENT_KEY, invocation = {}) {
1439
- const client = await resumeCompatibility(executableVersion, clientKey, invocation);
1440
- if (!client) throw new Error("Not connected");
1441
- const target = await client.ensureTarget();
1442
- return operation(client, target);
1443
- }
1444
1438
  async function shutdownCompatibility(executableVersion, clientKey = CLIENT_KEY) {
1445
1439
  if (!isDaemonRunning()) return;
1446
1440
  const daemon = new DaemonClient();
@@ -1473,7 +1467,9 @@ var program = new Command();
1473
1467
  program.exitOverride();
1474
1468
  program.name("bp").description("Control your browser from the command line").version(BROWSER_PILOT_VERSION).option("--human", "force human-readable output (default when TTY)").option("--client-key <key>", "stable namespace for Agent browser state").option("--request-id <id>", "stable host request ID for safe retry recovery").option("--timeout <ms>", "browser command deadline in milliseconds", "60000").addHelpText("after", `
1475
1469
  Workflow:
1476
- bp connect # one-time setup (click Allow in Chrome)
1470
+ bp status # inspect connection state without requesting authorization
1471
+ bp browsers # inspect browser setup without requesting authorization
1472
+ bp connect --browser <id> # connect once after setup (click Allow in Chrome if prompted)
1477
1473
  bp profiles # list live Chrome Profile contexts
1478
1474
  bp profile <index> # route new managed tabs to one Profile
1479
1475
  bp open <url> # navigate \u2014 returns snapshot with [ref] numbers
@@ -1560,8 +1556,11 @@ function fail(error, hint, details) {
1560
1556
  ...stable.context ? { context: stable.context } : {},
1561
1557
  ...stable.remediation ? { remediation: stable.remediation } : {}
1562
1558
  }));
1563
- else console.error(`\u2717 ${error}${hint ? `
1564
- hint: ${hint}` : ""}`);
1559
+ else {
1560
+ const guidance = hint ?? stable.remediation?.message;
1561
+ console.error(`\u2717 ${error}${guidance ? `
1562
+ action: ${guidance}` : ""}`);
1563
+ }
1565
1564
  process.exit(receivedSignal === "SIGINT" ? 130 : receivedSignal === "SIGTERM" ? 143 : 1);
1566
1565
  }
1567
1566
  function observationElements(result) {
@@ -1617,7 +1616,11 @@ function action(fn) {
1617
1616
  fail(msg, "Run 'bp snapshot' to refresh element refs.", stable);
1618
1617
  }
1619
1618
  if (stable.code === "browser_disconnected") {
1620
- fail(msg, "Run 'bp connect' first.", stable);
1619
+ fail(
1620
+ msg,
1621
+ stable.remediation ? void 0 : "Run 'bp browsers', follow its setup remediation, then connect once.",
1622
+ stable
1623
+ );
1621
1624
  }
1622
1625
  if (stable.code === "unknown_outcome") {
1623
1626
  fail(msg, "Inspect the current tab state before deciding whether to retry.", stable);
@@ -1770,16 +1773,31 @@ async function cliElementAddress(client, target, raw) {
1770
1773
  if (!raw.trim()) throw invalidArgument("Element target must not be empty", "target");
1771
1774
  return { selector: raw };
1772
1775
  }
1776
+ async function disconnectedBrowserSetup() {
1777
+ const discovered = await discoverBrowserCandidates();
1778
+ const selected = discovered.find((candidate) => candidate.endpoint !== void 0) ?? discovered[0];
1779
+ return {
1780
+ discovered,
1781
+ selected,
1782
+ remediation: selected?.candidate.remediation ?? {
1783
+ code: "connect_browser",
1784
+ message: "Run 'bp browsers', follow its setup remediation, then run one explicit 'bp connect'.",
1785
+ actionRequired: true
1786
+ }
1787
+ };
1788
+ }
1773
1789
  async function requireCompatibility() {
1774
1790
  const client = await resumeCompatibility(BROWSER_PILOT_VERSION, cliClientKey(), cliInvocationOptions());
1775
1791
  if (!client) {
1792
+ const setup = await disconnectedBrowserSetup();
1776
1793
  throw new BrowserPilotError("browser_disconnected", "Browser Pilot is not connected", {
1777
1794
  retryable: true,
1778
- remediation: {
1779
- code: "connect_browser",
1780
- message: "Run 'bp connect', complete Chrome authorization if prompted, then retry.",
1781
- actionRequired: true
1782
- }
1795
+ context: setup.selected ? {
1796
+ browserId: setup.selected.candidate.id,
1797
+ product: setup.selected.candidate.product,
1798
+ browserState: setup.selected.candidate.state
1799
+ } : void 0,
1800
+ remediation: setup.remediation
1783
1801
  });
1784
1802
  }
1785
1803
  return client;
@@ -1824,8 +1842,10 @@ function cliProfile(profile, index) {
1824
1842
  representativeTabs: profile.representativeTabs
1825
1843
  };
1826
1844
  }
1827
- function withCliTarget(operation) {
1828
- return withCompatibilityTarget(BROWSER_PILOT_VERSION, operation, cliClientKey(), cliInvocationOptions());
1845
+ async function withCliTarget(operation) {
1846
+ const client = await requireCompatibility();
1847
+ const target = await client.ensureTarget();
1848
+ return operation(client, target);
1829
1849
  }
1830
1850
  function readStdin() {
1831
1851
  if (process.stdin.isTTY) return Promise.resolve("");
@@ -1841,7 +1861,9 @@ program.command("status").description("Show current Broker, browser, Agent names
1841
1861
  const brokerRunning = isDaemonRunning();
1842
1862
  const client = await resumeCompatibility(BROWSER_PILOT_VERSION, cliClientKey(), cliInvocationOptions());
1843
1863
  if (!client) {
1844
- const browsers = (await discoverBrowserCandidates()).map((discovered) => discovered.candidate);
1864
+ const setup = await disconnectedBrowserSetup();
1865
+ const browsers = setup.discovered.map((candidate) => candidate.candidate);
1866
+ const action2 = setup.remediation.message;
1845
1867
  emit({
1846
1868
  ok: true,
1847
1869
  service: { state: brokerRunning ? "unavailable" : "stopped", version: BROWSER_PILOT_VERSION },
@@ -1851,9 +1873,11 @@ program.command("status").description("Show current Broker, browser, Agent names
1851
1873
  recovery: {
1852
1874
  required: true,
1853
1875
  code: "browser_disconnected",
1854
- action: "bp connect"
1876
+ action: action2
1855
1877
  }
1856
- }, brokerRunning ? "Browser Pilot Broker is running, but the browser session is unavailable." : "Browser Pilot is not connected. Run bp connect.");
1878
+ }, brokerRunning ? `Browser Pilot Broker is running, but the browser session is unavailable.
1879
+ Action: ${action2}` : `Browser Pilot is not connected.
1880
+ Action: ${action2}`);
1857
1881
  return;
1858
1882
  }
1859
1883
  const [activeCommands, uncertainCommands] = await Promise.all([
@@ -2063,7 +2087,16 @@ program.command("browsers").description("List supported local browsers and their
2063
2087
  return details.join("\n");
2064
2088
  }).join("\n\n"));
2065
2089
  }));
2066
- program.command("connect").description("Connect to Chrome and prepare unambiguous managed browsing").option("-b, --browser <name>", "browser to connect to").addHelpText("after", "\nExamples:\n bp connect\n bp connect --browser brave").action(action(async (opts) => {
2090
+ program.command("connect").description("Connect to Chrome and prepare unambiguous managed browsing").option("-b, --browser <name>", "browser to connect to").addHelpText("after", [
2091
+ "",
2092
+ "Preparation:",
2093
+ " Run bp browsers and complete its setup remediation first.",
2094
+ " If an Agent invokes this command, it must tell the user about the possible Allow dialog before the call.",
2095
+ "",
2096
+ "Examples:",
2097
+ " bp connect",
2098
+ " bp connect --browser brave"
2099
+ ].join("\n")).action(action(async (opts) => {
2067
2100
  if (!useJson()) {
2068
2101
  console.log("Connecting to Chrome...");
2069
2102
  console.log(`If prompted, click "Allow" in Chrome's authorization dialog.
package/dist/daemon.js CHANGED
@@ -3680,7 +3680,12 @@ var MemoryBrokerRuntime = class {
3680
3680
  if (!binding || !isBrowserConnectTool && binding.instance.state !== "connected") {
3681
3681
  throw new BrowserPilotError("browser_disconnected", "Workspace browser is disconnected", {
3682
3682
  retryable: true,
3683
- context: workspaceRecord ? { workspaceId: workspaceRecord.value.id } : void 0
3683
+ context: workspaceRecord ? { workspaceId: workspaceRecord.value.id } : void 0,
3684
+ remediation: binding?.candidate.remediation ?? {
3685
+ code: "connect_browser",
3686
+ message: "Run 'bp browsers', follow its setup remediation, then run one explicit 'bp connect'.",
3687
+ actionRequired: true
3688
+ }
3684
3689
  });
3685
3690
  }
3686
3691
  const isBrowserConnectionAttempt = isBrowserConnectTool && binding.instance.state !== "connected";
@@ -14311,7 +14316,7 @@ var ManagedTargetJanitorClient = class {
14311
14316
  };
14312
14317
 
14313
14318
  // src/version.ts
14314
- var BROWSER_PILOT_VERSION = "0.5.0";
14319
+ var BROWSER_PILOT_VERSION = "0.5.1";
14315
14320
 
14316
14321
  // src/daemon.ts
14317
14322
  var CLI_EXECUTABLE_PATH = publicExecutablePath(import.meta.url);
@@ -0,0 +1,30 @@
1
+ # Browser Pilot 0.5.1
2
+
3
+ Browser Pilot 0.5.1 makes disconnected-browser recovery explicit and prevents
4
+ Agents from creating repeated Chrome authorization prompts when remote
5
+ debugging is not ready.
6
+
7
+ ## Deliberate connection flow
8
+
9
+ - `bp status` and `bp browsers` remain passive setup checks and never request
10
+ Chrome authorization.
11
+ - Disconnected browser commands preserve the selected browser candidate's
12
+ structured remediation, including `start_browser`,
13
+ `enable_remote_debugging`, and `restart_remote_debugging`.
14
+ - `bp status` reports the same actionable setup message instead of always
15
+ suggesting another connection attempt.
16
+ - Human CLI output labels structured recovery guidance as an action, while
17
+ JSON output keeps the stable `code`, `retryable`, and `remediation` contract.
18
+ - Target commands now share the same connection requirement and return
19
+ `browser_disconnected` instead of exposing an internal not-connected error.
20
+
21
+ ## Agent guidance
22
+
23
+ - The Browser Pilot skill checks status first, inspects browser candidates only
24
+ when disconnected, and follows the returned remediation before connecting.
25
+ - Agents must warn the user about Chrome's possible Allow dialog before the
26
+ shell call, then issue exactly one explicit `bp connect --browser <id>`.
27
+ - Connection timeouts, interruptions, and authorization failures require state
28
+ inspection; they never authorize a blind or concurrent connect loop.
29
+ - Multiple ready browser candidates are selected explicitly rather than by an
30
+ ambiguous default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-pilot-cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "CLI tool to control your browser via Chrome DevTools Protocol",
5
5
  "repository": "https://github.com/relixiaobo/browser-pilot",
6
6
  "type": "module",