browser-pilot-cli 0.1.2 → 0.1.4

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.
Files changed (2) hide show
  1. package/dist/cli.js +59 -19
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -548,8 +548,10 @@ Workflow:
548
548
  bp connect # one-time setup (click Allow in Chrome)
549
549
  bp open <url> # navigate \u2014 returns snapshot with [ref] numbers
550
550
  bp click <ref> # interact \u2014 returns updated snapshot
551
+ bp click 0 --xy 400,300 # click at coordinates (canvas/maps)
551
552
  bp type <ref> <text> # input text \u2014 returns updated snapshot
552
- bp press <key> # keyboard \u2014 returns updated snapshot
553
+ bp keyboard <text> # type via keyboard events (Google Docs etc.)
554
+ bp press <key> # press key \u2014 returns updated snapshot
553
555
  bp eval <js> # run JavaScript (escape hatch for anything)
554
556
 
555
557
  Refs:
@@ -563,12 +565,17 @@ Output:
563
565
  Actions return: {"ok":true, "title":"...", "url":"...", "elements":[...]}
564
566
  Errors return: {"ok":false, "error":"...", "hint":"..."}
565
567
 
568
+ Canvas editors (Google Docs, Sheets, Figma):
569
+ bp keyboard "text" --click ".editor" # click to focus, then type
570
+ bp keyboard "text" --clear # select all + delete, then type
571
+ bp press Meta+b # toggle bold (works in Docs)
572
+
566
573
  Edge cases:
567
- bp upload <ref> <filepath> # file input upload
568
- bp auth <user> <pass> # HTTP Basic Auth
569
- bp frame # list iframes
570
- bp frame 1 # eval in iframe context
571
- bp frame 0 # back to top frame
574
+ bp upload <filepath> # file input upload (auto-detect)
575
+ bp auth <user> <pass> # HTTP Basic Auth
576
+ bp frame # list iframes
577
+ bp frame 1 # eval in iframe context
578
+ bp frame 0 # back to top frame
572
579
  Dialogs (alert/confirm) are auto-handled by the daemon.
573
580
 
574
581
  Eval (replaces scroll, back, forward, extract, etc.):
@@ -746,21 +753,54 @@ program.command("snapshot").description("Get interactive elements on the page").
746
753
  emitSnapshot(await takeSnapshot(transport, sessionId, state.activeTargetId, limit));
747
754
  });
748
755
  }));
749
- program.command("click <ref>").description("Click element by ref number and return page snapshot").option("-l, --limit <n>", "max elements in snapshot", "50").addHelpText("after", "\nRef is a number from the snapshot output.\n\nExamples:\n bp click 3\n bp click 3 --limit 10").action(action(async (ref, opts) => {
756
+ program.command("click <ref>").description("Click element by ref number and return page snapshot").option("--xy <coords>", "click at x,y coordinates instead of ref (e.g. --xy 400,300)").option("--double", "double-click").option("--right", "right-click (context menu)").option("-l, --limit <n>", "max elements in snapshot", "50").addHelpText("after", `
757
+ Ref is a number from the snapshot output, or use --xy for coordinate clicks.
758
+
759
+ Examples:
760
+ bp click 3 # click element [3]
761
+ bp click 0 --xy 400,300 # click at coordinates (ref ignored)
762
+ bp click 0 --xy 400,300 --double # double-click at coordinates
763
+ bp click 0 --xy 400,300 --right # right-click at coordinates`).action(action(async (ref, opts) => {
750
764
  const limit = parseLimit(opts.limit);
751
765
  await withPilot(async ({ transport, sessionId, state }) => {
752
- const objectId = await resolveTarget(transport, sessionId, ref, state.activeTargetId);
753
- try {
754
- const { result } = await transport.send("Runtime.callFunctionOn", {
755
- objectId,
756
- functionDeclaration: GET_CLICK_COORDS,
757
- returnByValue: true
758
- }, sessionId);
759
- const { x, y } = JSON.parse(result.value);
760
- await dispatchClick(transport, sessionId, x, y);
761
- } finally {
762
- await transport.send("Runtime.releaseObject", { objectId }, sessionId).catch(() => {
763
- });
766
+ if (opts.xy) {
767
+ const [xStr, yStr] = opts.xy.split(",");
768
+ const x = parseFloat(xStr), y = parseFloat(yStr);
769
+ if (isNaN(x) || isNaN(y)) throw new Error("--xy must be x,y (e.g. --xy 400,300)");
770
+ if (opts.right) {
771
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseMoved", x, y, button: "none" }, sessionId);
772
+ await transport.send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "right", clickCount: 1 }, sessionId);
773
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "right", clickCount: 1 }, sessionId);
774
+ } else {
775
+ const clickCount = opts.double ? 2 : 1;
776
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseMoved", x, y, button: "none" }, sessionId);
777
+ await transport.send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "left", clickCount }, sessionId);
778
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "left", clickCount }, sessionId);
779
+ }
780
+ } else {
781
+ const objectId = await resolveTarget(transport, sessionId, ref, state.activeTargetId);
782
+ try {
783
+ const { result } = await transport.send("Runtime.callFunctionOn", {
784
+ objectId,
785
+ functionDeclaration: GET_CLICK_COORDS,
786
+ returnByValue: true
787
+ }, sessionId);
788
+ const { x, y } = JSON.parse(result.value);
789
+ if (opts.double) {
790
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseMoved", x, y, button: "none" }, sessionId);
791
+ await transport.send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "left", clickCount: 2 }, sessionId);
792
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "left", clickCount: 2 }, sessionId);
793
+ } else if (opts.right) {
794
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseMoved", x, y, button: "none" }, sessionId);
795
+ await transport.send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "right", clickCount: 1 }, sessionId);
796
+ await transport.send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "right", clickCount: 1 }, sessionId);
797
+ } else {
798
+ await dispatchClick(transport, sessionId, x, y);
799
+ }
800
+ } finally {
801
+ await transport.send("Runtime.releaseObject", { objectId }, sessionId).catch(() => {
802
+ });
803
+ }
764
804
  }
765
805
  emitSnapshot(await snap(transport, sessionId, state.activeTargetId, limit));
766
806
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-pilot-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "CLI tool to control your browser via Chrome DevTools Protocol",
5
5
  "type": "module",
6
6
  "bin": {