browser-pilot-cli 0.3.0-rc.3 → 0.3.0-rc.5
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 +1 -1
- package/dist/cli.js +13 -8
- package/dist/daemon.js +45 -10
- package/docs/plans/v0.3.0-stabilization.md +8 -4
- package/docs/releases/v0.3.0-rc.4.md +28 -0
- package/docs/releases/v0.3.0-rc.5.md +26 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -182,7 +182,7 @@ A project can pin Browser Pilot locally and run the same CLI without a global
|
|
|
182
182
|
installation:
|
|
183
183
|
|
|
184
184
|
```bash
|
|
185
|
-
npm install --save-exact browser-pilot-cli@0.3.0-rc.
|
|
185
|
+
npm install --save-exact browser-pilot-cli@0.3.0-rc.5
|
|
186
186
|
npx --no-install browser-pilot tabs
|
|
187
187
|
```
|
|
188
188
|
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import { writeFileSync as writeFileSync2, readFileSync as readFileSync4, existsS
|
|
|
6
6
|
import { resolve as resolvePath } from "path";
|
|
7
7
|
|
|
8
8
|
// src/version.ts
|
|
9
|
-
var BROWSER_PILOT_VERSION = "0.3.0-rc.
|
|
9
|
+
var BROWSER_PILOT_VERSION = "0.3.0-rc.5";
|
|
10
10
|
|
|
11
11
|
// src/protocol/errors.ts
|
|
12
12
|
var ERROR_CODES = [
|
|
@@ -1804,7 +1804,7 @@ var scrollEvidenceSchema = objectSchema({
|
|
|
1804
1804
|
afterX: numberSchema({ minimum: 0 }),
|
|
1805
1805
|
afterY: numberSchema({ minimum: 0 }),
|
|
1806
1806
|
matchedText: sensitive(stringSchema({ maxLength: 4096 }), "browser_data"),
|
|
1807
|
-
reason: stringSchema({ enum: ["at_boundary", "text_not_found"] })
|
|
1807
|
+
reason: stringSchema({ enum: ["at_boundary", "text_not_found", "text_not_revealed"] })
|
|
1808
1808
|
}, [
|
|
1809
1809
|
"action",
|
|
1810
1810
|
"status",
|
|
@@ -3283,6 +3283,13 @@ var CompatibilityBrokerClient = class _CompatibilityBrokerClient {
|
|
|
3283
3283
|
}
|
|
3284
3284
|
await this.callTool("browser.connect", { browserId: selected.id });
|
|
3285
3285
|
}
|
|
3286
|
+
async listBrowsers(browser) {
|
|
3287
|
+
const result = await this.callTool("browser.discover", browser ? { browser } : {});
|
|
3288
|
+
if (!Array.isArray(result.browsers)) {
|
|
3289
|
+
throw new BrowserPilotError("internal_error", "browser.discover returned invalid browsers");
|
|
3290
|
+
}
|
|
3291
|
+
return result.browsers;
|
|
3292
|
+
}
|
|
3286
3293
|
async listTabs(scope = "all") {
|
|
3287
3294
|
const result = await this.callTool("browser.tabs.list", { scope });
|
|
3288
3295
|
if (!Array.isArray(result.targets)) {
|
|
@@ -3709,7 +3716,8 @@ function readStdin() {
|
|
|
3709
3716
|
}
|
|
3710
3717
|
program.command("browsers").description("List supported local browsers and their setup state").option("-b, --browser <name>", "filter by browser ID, product, or channel").action(action(async (opts) => {
|
|
3711
3718
|
const filter = typeof opts.browser === "string" ? opts.browser.toLowerCase() : void 0;
|
|
3712
|
-
const
|
|
3719
|
+
const client = await resumeCompatibility(BROWSER_PILOT_VERSION);
|
|
3720
|
+
const browsers = client ? await client.listBrowsers(filter) : (await discoverBrowserCandidates()).map((discovered) => discovered.candidate).filter((candidate) => !filter || [candidate.id, candidate.product, candidate.channel].some((value) => value?.toLowerCase().includes(filter)));
|
|
3713
3721
|
if (useJson()) {
|
|
3714
3722
|
console.log(JSON.stringify({ ok: true, browsers }));
|
|
3715
3723
|
return;
|
|
@@ -4360,9 +4368,6 @@ program.command("close").description("Close current browser tab").option("-a, --
|
|
|
4360
4368
|
context: { failedTargetIds: failed }
|
|
4361
4369
|
});
|
|
4362
4370
|
}
|
|
4363
|
-
if (remainingTabs.length > 0 && !remainingTabs.some((tab) => tab.active)) {
|
|
4364
|
-
await client.callTool("browser.tabs.switch", { targetId: remainingTabs[0].targetId });
|
|
4365
|
-
}
|
|
4366
4371
|
emit(
|
|
4367
4372
|
{ ok: true, closed, remaining: remainingTabs.length },
|
|
4368
4373
|
`\u2713 Closed ${closed} Pilot tab(s)`
|
|
@@ -4373,8 +4378,8 @@ program.command("close").description("Close current browser tab").option("-a, --
|
|
|
4373
4378
|
const remainingTabs = await client.listTabs("all");
|
|
4374
4379
|
if (remainingTabs.length > 0) {
|
|
4375
4380
|
if (!remainingTabs.some((tab) => tab.active)) {
|
|
4376
|
-
const fallback = remainingTabs.find((tab) => tab.origin !== "user_tab")
|
|
4377
|
-
await client.callTool("browser.tabs.switch", { targetId: fallback.targetId });
|
|
4381
|
+
const fallback = remainingTabs.find((tab) => tab.origin !== "user_tab");
|
|
4382
|
+
if (fallback) await client.callTool("browser.tabs.switch", { targetId: fallback.targetId });
|
|
4378
4383
|
}
|
|
4379
4384
|
emit({ ok: true, remaining: remainingTabs.length }, "\u2713 Tab closed");
|
|
4380
4385
|
} else {
|
package/dist/daemon.js
CHANGED
|
@@ -747,7 +747,7 @@ var scrollEvidenceSchema = objectSchema({
|
|
|
747
747
|
afterX: numberSchema({ minimum: 0 }),
|
|
748
748
|
afterY: numberSchema({ minimum: 0 }),
|
|
749
749
|
matchedText: sensitive(stringSchema({ maxLength: 4096 }), "browser_data"),
|
|
750
|
-
reason: stringSchema({ enum: ["at_boundary", "text_not_found"] })
|
|
750
|
+
reason: stringSchema({ enum: ["at_boundary", "text_not_found", "text_not_revealed"] })
|
|
751
751
|
}, [
|
|
752
752
|
"action",
|
|
753
753
|
"status",
|
|
@@ -9012,6 +9012,10 @@ var ScrollService = class {
|
|
|
9012
9012
|
const exact=${exact};
|
|
9013
9013
|
const normalize=value=>String(value||'').replace(/\\s+/g,' ').trim();
|
|
9014
9014
|
const needle=normalize(query).toLocaleLowerCase();
|
|
9015
|
+
const slash=String.fromCharCode(92);
|
|
9016
|
+
const regexSpecials='^$.*+?()[]{}|'+slash;
|
|
9017
|
+
const escapeRegex=value=>Array.from(value,char=>regexSpecials.includes(char)?slash+char:char).join('');
|
|
9018
|
+
const queryPattern=exact?null:new RegExp(normalize(query).split(' ').map(escapeRegex).join(slash+'s+'),'iu');
|
|
9015
9019
|
const roots=[document];
|
|
9016
9020
|
let visited=0;
|
|
9017
9021
|
while(roots.length&&visited<20000){
|
|
@@ -9029,21 +9033,50 @@ var ScrollService = class {
|
|
|
9029
9033
|
if(!element)continue;
|
|
9030
9034
|
const tag=String(element.tagName||'').toLowerCase();
|
|
9031
9035
|
if(['script','style','noscript','template'].includes(tag))continue;
|
|
9032
|
-
const
|
|
9036
|
+
const raw=String(node.nodeValue||'');
|
|
9037
|
+
const content=normalize(raw);
|
|
9033
9038
|
const normalized=content.toLocaleLowerCase();
|
|
9034
9039
|
if(!(exact?normalized===needle:normalized.includes(needle)))continue;
|
|
9040
|
+
let matchStart=0;
|
|
9041
|
+
let matchEnd=raw.length;
|
|
9042
|
+
if(exact){
|
|
9043
|
+
matchStart=Math.max(0,raw.search(/\\S/u));
|
|
9044
|
+
matchEnd=Math.max(matchStart,raw.length-((raw.match(/\\s*$/u)||[''])[0].length));
|
|
9045
|
+
}else{
|
|
9046
|
+
const match=queryPattern.exec(raw);
|
|
9047
|
+
if(!match)continue;
|
|
9048
|
+
matchStart=match.index;
|
|
9049
|
+
matchEnd=match.index+match[0].length;
|
|
9050
|
+
}
|
|
9035
9051
|
const style=getComputedStyle(element);
|
|
9036
9052
|
if(style.display==='none'||style.visibility==='hidden'||style.visibility==='collapse'||element.getClientRects().length===0)continue;
|
|
9053
|
+
const viewportWidth=Math.max(0,window.innerWidth||document.documentElement.clientWidth||0);
|
|
9054
|
+
const viewportHeight=Math.max(0,window.innerHeight||document.documentElement.clientHeight||0);
|
|
9055
|
+
const range=document.createRange();
|
|
9056
|
+
range.setStart(node,matchStart);
|
|
9057
|
+
range.setEnd(node,matchEnd);
|
|
9058
|
+
const rangeRect=()=>range.getBoundingClientRect();
|
|
9059
|
+
const intersectsViewport=rect=>rect.width>0&&rect.height>0&&rect.bottom>0&&rect.right>0&&rect.top<viewportHeight&&rect.left<viewportWidth;
|
|
9037
9060
|
const beforeX=Math.max(0,window.scrollX||document.documentElement.scrollLeft||0);
|
|
9038
9061
|
const beforeY=Math.max(0,window.scrollY||document.documentElement.scrollTop||0);
|
|
9039
9062
|
element.scrollIntoView({block:'center',inline:'nearest',behavior:'instant'});
|
|
9040
|
-
|
|
9041
|
-
|
|
9063
|
+
let afterX=Math.max(0,window.scrollX||document.documentElement.scrollLeft||0);
|
|
9064
|
+
let afterY=Math.max(0,window.scrollY||document.documentElement.scrollTop||0);
|
|
9065
|
+
let rect=rangeRect();
|
|
9066
|
+
if(!intersectsViewport(rect)){
|
|
9067
|
+
const left=Math.max(0,afterX+rect.left-Math.max(0,(viewportWidth-rect.width)/2));
|
|
9068
|
+
const top=Math.max(0,afterY+rect.top-Math.max(0,(viewportHeight-rect.height)/2));
|
|
9069
|
+
window.scrollTo({left,top,behavior:'instant'});
|
|
9070
|
+
afterX=Math.max(0,window.scrollX||document.documentElement.scrollLeft||0);
|
|
9071
|
+
afterY=Math.max(0,window.scrollY||document.documentElement.scrollTop||0);
|
|
9072
|
+
rect=rangeRect();
|
|
9073
|
+
}
|
|
9042
9074
|
const round=value=>Math.round(Number(value)||0);
|
|
9043
9075
|
const moved=Math.abs(afterX-beforeX)>=1||Math.abs(afterY-beforeY)>=1;
|
|
9044
|
-
|
|
9076
|
+
const revealed=intersectsViewport(rect);
|
|
9077
|
+
return{ok:true,action:'scroll',status:revealed?'verified':'mismatch',mode:'text',target:'text',moved,
|
|
9045
9078
|
deltaX:round(afterX-beforeX),deltaY:round(afterY-beforeY),beforeX:round(beforeX),beforeY:round(beforeY),
|
|
9046
|
-
afterX:round(afterX),afterY:round(afterY),matchedText:content.slice(0,4096)};
|
|
9079
|
+
afterX:round(afterX),afterY:round(afterY),matchedText:content.slice(0,4096),...(revealed?{}:{reason:'text_not_revealed'})};
|
|
9047
9080
|
}
|
|
9048
9081
|
}
|
|
9049
9082
|
return{ok:true,action:'scroll',status:'mismatch',mode:'text',target:'text',moved:false,
|
|
@@ -9066,11 +9099,13 @@ var ScrollService = class {
|
|
|
9066
9099
|
var MAX_ANNOTATIONS = 200;
|
|
9067
9100
|
function annotationScript(data, annotations, viewport) {
|
|
9068
9101
|
return `(async() => {
|
|
9069
|
-
const
|
|
9102
|
+
const base64=${JSON.stringify(data)};
|
|
9070
9103
|
const annotations=${JSON.stringify(annotations)};
|
|
9071
9104
|
const viewport=${JSON.stringify(viewport)};
|
|
9072
|
-
const
|
|
9073
|
-
const
|
|
9105
|
+
const binary=atob(base64);
|
|
9106
|
+
const bytes=new Uint8Array(binary.length);
|
|
9107
|
+
for(let index=0;index<binary.length;index+=1)bytes[index]=binary.charCodeAt(index);
|
|
9108
|
+
const bitmap=await createImageBitmap(new Blob([bytes],{type:'image/png'}));
|
|
9074
9109
|
const canvas=document.createElement('canvas');
|
|
9075
9110
|
canvas.width=bitmap.width;canvas.height=bitmap.height;
|
|
9076
9111
|
const context=canvas.getContext('2d');
|
|
@@ -13979,7 +14014,7 @@ var ManagedTargetJanitorClient = class {
|
|
|
13979
14014
|
};
|
|
13980
14015
|
|
|
13981
14016
|
// src/version.ts
|
|
13982
|
-
var BROWSER_PILOT_VERSION = "0.3.0-rc.
|
|
14017
|
+
var BROWSER_PILOT_VERSION = "0.3.0-rc.5";
|
|
13983
14018
|
|
|
13984
14019
|
// src/daemon.ts
|
|
13985
14020
|
var CLI_EXECUTABLE_PATH = publicExecutablePath(import.meta.url);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Browser Pilot v0.3.0 Stabilization Plan
|
|
2
2
|
|
|
3
3
|
Status: **In progress**
|
|
4
|
-
Candidate baseline: `v0.3.0-rc.
|
|
4
|
+
Candidate baseline: `v0.3.0-rc.4`; correction target: `v0.3.0-rc.5`, protocol `1.2`
|
|
5
5
|
|
|
6
6
|
## Goal
|
|
7
7
|
|
|
@@ -31,10 +31,14 @@ products depend on. No Agent-specific behavior enters Browser Pilot.
|
|
|
31
31
|
files survive Artifact and Workspace cleanup.
|
|
32
32
|
- [x] Pass TypeScript, 276 Node, 109 Playwright, 13 stdio conformance, three
|
|
33
33
|
distribution-mode, and 13 host integration checks on the candidate source.
|
|
34
|
-
- [
|
|
35
|
-
|
|
36
|
-
- [
|
|
34
|
+
- [x] Publish `v0.3.0-rc.3` through trusted publishing and pass all 13 host
|
|
35
|
+
integration checks against the installed standalone release executable.
|
|
36
|
+
- [x] Run one controlled user-Chrome host acceptance with explicit Profile
|
|
37
37
|
choices and a single authorization attempt.
|
|
38
|
+
- [x] Publish `v0.3.0-rc.4` with Broker-backed CLI browser status and verify
|
|
39
|
+
that passive discovery reports the live authorized connection.
|
|
40
|
+
- [ ] Publish `v0.3.0-rc.5` with the real-site soak corrections and rerun the
|
|
41
|
+
same public information, form, capture, and managed-cleanup tasks.
|
|
38
42
|
- [ ] Soak several real Agent tasks through the installed candidate.
|
|
39
43
|
- [ ] Tag `v0.3.0`, publish npm `latest`, and verify upgrade/rollback metadata.
|
|
40
44
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Browser Pilot 0.3.0-rc.4
|
|
2
|
+
|
|
3
|
+
This release candidate fixes a connection-status inconsistency found during
|
|
4
|
+
controlled user-Chrome acceptance of RC.3.
|
|
5
|
+
|
|
6
|
+
When a Broker already held an authorized Chrome connection, `bp profiles` and
|
|
7
|
+
browser operations worked, but `bp browsers` performed a separate local endpoint
|
|
8
|
+
scan and could report the same browser as `disconnected`. An Agent following
|
|
9
|
+
that result could unnecessarily call `bp connect` and cause another Chrome
|
|
10
|
+
authorization prompt.
|
|
11
|
+
|
|
12
|
+
RC.4 makes `bp browsers` use the Broker-owned `browser.discover` operation when
|
|
13
|
+
a compatible Broker is running. Local discovery remains the passive fallback
|
|
14
|
+
when no Broker exists. The command still never starts a Broker or requests
|
|
15
|
+
Chrome authorization.
|
|
16
|
+
|
|
17
|
+
The RC.3 controlled user-Chrome acceptance passed with two independent Agent
|
|
18
|
+
hosts routed to two live Profiles. It verified user-tab handoff, concurrent CLI
|
|
19
|
+
use, native screenshot content, PDF and download export, event replay, managed
|
|
20
|
+
cleanup, and preservation of all existing user tabs. Chrome's original
|
|
21
|
+
download was also confirmed in its default download directory.
|
|
22
|
+
|
|
23
|
+
RC.4 keeps protocol 1.2, browser control behavior, Profile routing, and the
|
|
24
|
+
Agent-neutral stdio integration contract unchanged.
|
|
25
|
+
|
|
26
|
+
Automated candidate gates passed with 276 Node tests, 109 isolated Playwright
|
|
27
|
+
tests, all 13 stdio conformance checks, all 13 host integration checks, and npm
|
|
28
|
+
distribution verification in global, local-project, and product-bundled modes.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Browser Pilot 0.3.0-rc.5
|
|
2
|
+
|
|
3
|
+
This release candidate fixes three edge cases found by running RC.4 through
|
|
4
|
+
real Agent tasks in two live Chrome Profiles.
|
|
5
|
+
|
|
6
|
+
- Text-targeted scrolling now verifies that the matched text actually entered
|
|
7
|
+
the viewport. If a site's `scrollIntoView` path is ineffective, Browser Pilot
|
|
8
|
+
falls back to the matched text Range's page coordinates; an unrevealed match
|
|
9
|
+
returns an explicit mismatch instead of a false success.
|
|
10
|
+
- Screenshot annotations no longer decode captured PNGs through
|
|
11
|
+
`fetch(data:)`. They use in-memory base64, Blob, and ImageBitmap conversion in
|
|
12
|
+
the isolated world, so restrictive site `connect-src` policies such as
|
|
13
|
+
GitHub's cannot break annotation.
|
|
14
|
+
- Tab cleanup no longer switches control to a user tab when Chrome has not yet
|
|
15
|
+
reported its next active target. `bp close --all` still closes only managed
|
|
16
|
+
tabs.
|
|
17
|
+
|
|
18
|
+
The soak otherwise completed public GitHub reading and targeted search, a
|
|
19
|
+
disposable HTTP form with verified input and control state, submission result
|
|
20
|
+
verification, multi-Profile routing, ordinary screenshots, annotated form
|
|
21
|
+
screenshots, PDF export, connection-status checks, and preservation of every
|
|
22
|
+
user tab and exported file.
|
|
23
|
+
|
|
24
|
+
RC.5 keeps protocol 1.2 and the Agent-neutral stdio contract unchanged.
|
|
25
|
+
Candidate gates passed with 276 Node tests, 109 isolated Playwright tests, and
|
|
26
|
+
TypeScript type checking.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-pilot-cli",
|
|
3
|
-
"version": "0.3.0-rc.
|
|
3
|
+
"version": "0.3.0-rc.5",
|
|
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",
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
"docs/releases/v0.3.0-rc.1.md",
|
|
48
48
|
"docs/releases/v0.3.0-rc.2.md",
|
|
49
49
|
"docs/releases/v0.3.0-rc.3.md",
|
|
50
|
+
"docs/releases/v0.3.0-rc.4.md",
|
|
51
|
+
"docs/releases/v0.3.0-rc.5.md",
|
|
50
52
|
"README.md",
|
|
51
53
|
"LICENSE"
|
|
52
54
|
],
|