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 +10 -2
- package/dist/cli.js +55 -22
- package/dist/daemon.js +7 -2
- package/docs/releases/v0.5.1.md +30 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,15 +25,23 @@ Inspect installed browsers without requesting authorization:
|
|
|
25
25
|
bp browsers
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
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.
|
|
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
|
|
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
|
|
1564
|
-
|
|
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(
|
|
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
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
1876
|
+
action: action2
|
|
1855
1877
|
}
|
|
1856
|
-
}, brokerRunning ?
|
|
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",
|
|
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.
|
|
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