Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brave-browsers-migrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"browse": minor
Comment thread
shrey150 marked this conversation as resolved.
---

migrate the Browse CLI runtime to Stagehand V4 and remove the `--return-xpath` option from coordinate actions
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ browse highlight @0-12 # Highlight an element (--duratio

### Mouse (raw coordinates)

Use these when you need pixel coordinates instead of a ref. Add `--return-xpath` to get the XPath under the cursor.
Use these when you need pixel coordinates instead of a ref.

```bash
browse mouse click 240 320 # Click coordinates (--button, --click-count)
Expand Down
7 changes: 1 addition & 6 deletions packages/cli/src/commands/mouse/click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default class MouseClick extends BrowseCommand {
static override examples = [
"browse mouse click 240 320",
"browse mouse click 240 320 --button right",
"browse mouse click 240 320 --click-count 2 --return-xpath",
"browse mouse click 240 320 --click-count 2",
];

static override args = {
Expand All @@ -31,10 +31,6 @@ export default class MouseClick extends BrowseCommand {
description: "Number of clicks to send.",
helpValue: "<count>",
}),
"return-xpath": Flags.boolean({
description:
"Include the XPath under the coordinate when the driver can return it.",
}),
};

async run(): Promise<void> {
Expand All @@ -44,7 +40,6 @@ export default class MouseClick extends BrowseCommand {
{
button: flags.button,
clickCount: flags["click-count"],
returnXPath: flags["return-xpath"],
x: parseNumber(args.x, "x"),
y: parseNumber(args.y, "y"),
},
Expand Down
6 changes: 0 additions & 6 deletions packages/cli/src/commands/mouse/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export default class MouseDrag extends BrowseCommand {
static override examples = [
"browse mouse drag 100 100 400 400",
"browse mouse drag 100 100 400 400 --steps 20 --delay 10",
"browse mouse drag 100 100 400 400 --return-xpath",
];

static override args = {
Expand Down Expand Up @@ -45,10 +44,6 @@ export default class MouseDrag extends BrowseCommand {
description: "Delay between drag steps in milliseconds.",
helpValue: "<ms>",
}),
"return-xpath": Flags.boolean({
description:
"Include the XPath under the start/end coordinates when the driver can return it.",
}),
steps: Flags.integer({
default: 10,
description: "Number of intermediate drag steps.",
Expand All @@ -65,7 +60,6 @@ export default class MouseDrag extends BrowseCommand {
delay: flags.delay,
fromX: parseNumber(args.fromX, "fromX"),
fromY: parseNumber(args.fromY, "fromY"),
returnXPath: flags["return-xpath"],
steps: flags.steps,
toX: parseNumber(args.toX, "toX"),
toY: parseNumber(args.toY, "toY"),
Expand Down
8 changes: 1 addition & 7 deletions packages/cli/src/commands/mouse/hover.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Args, Flags } from "@oclif/core";
import { Args } from "@oclif/core";

import { BrowseCommand } from "../../base.js";
import {
Expand All @@ -13,7 +13,6 @@ export default class MouseHover extends BrowseCommand {

static override examples = [
"browse mouse hover 240 320",
"browse mouse hover 240 320 --return-xpath",
"browse mouse hover 240 320 --session research",
];

Expand All @@ -24,18 +23,13 @@ export default class MouseHover extends BrowseCommand {

static override flags = {
...driverCommandFlags,
"return-xpath": Flags.boolean({
description:
"Include the XPath under the coordinate when the driver can return it.",
}),
};

async run(): Promise<void> {
const { args, flags } = await this.parse(MouseHover);
await runDriverCommandFromFlags(
"mouse.hover",
{
returnXPath: flags["return-xpath"],
x: parseNumber(args.x, "x"),
y: parseNumber(args.y, "y"),
},
Expand Down
8 changes: 1 addition & 7 deletions packages/cli/src/commands/mouse/scroll.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Args, Flags } from "@oclif/core";
import { Args } from "@oclif/core";

import { BrowseCommand } from "../../base.js";
import {
Expand All @@ -14,7 +14,6 @@ export default class MouseScroll extends BrowseCommand {
static override examples = [
"browse mouse scroll 400 500 0 600",
"browse mouse scroll 400 500 0 -600",
"browse mouse scroll 400 500 0 600 --return-xpath",
];

static override args = {
Expand All @@ -32,10 +31,6 @@ export default class MouseScroll extends BrowseCommand {

static override flags = {
...driverCommandFlags,
"return-xpath": Flags.boolean({
description:
"Include the XPath under the coordinate when the driver can return it.",
}),
};

async run(): Promise<void> {
Expand All @@ -45,7 +40,6 @@ export default class MouseScroll extends BrowseCommand {
{
deltaX: parseNumber(args.deltaX, "deltaX"),
deltaY: parseNumber(args.deltaY, "deltaY"),
returnXPath: flags["return-xpath"],
x: parseNumber(args.x, "x"),
y: parseNumber(args.y, "y"),
},
Expand Down
26 changes: 8 additions & 18 deletions packages/cli/src/lib/driver/commands/mouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ const ButtonSchema = z.enum(["left", "right", "middle"]).optional();

export const mouseHandlers: DriverCommandHandlers = {
async "mouse.click"(manager, params) {
const { button, clickCount, returnXPath, x, y } = z
const { button, clickCount, x, y } = z
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
.object({
button: ButtonSchema,
clickCount: z.number().int().positive().optional(),
returnXPath: z.boolean().optional(),
x: z.number(),
y: z.number(),
})
.strict()
.parse(params);
assertXPathUnavailable(returnXPath);
const page = await manager.activePage();
await positionCursorOverlay(manager, page, x, y);
await page.click(x, y, {
Expand All @@ -28,51 +27,48 @@ export const mouseHandlers: DriverCommandHandlers = {
},

async "mouse.hover"(manager, params) {
const { returnXPath, x, y } = z
const { x, y } = z
.object({
returnXPath: z.boolean().optional(),
x: z.number(),
y: z.number(),
})
.strict()
.parse(params);
assertXPathUnavailable(returnXPath);
const page = await manager.activePage();
await positionCursorOverlay(manager, page, x, y);
await page.hover(x, y);
return { hovered: true };
},

async "mouse.scroll"(manager, params) {
const { deltaX, deltaY, returnXPath, x, y } = z
const { deltaX, deltaY, x, y } = z
.object({
deltaX: z.number(),
deltaY: z.number(),
returnXPath: z.boolean().optional(),
x: z.number(),
y: z.number(),
})
.strict()
.parse(params);
assertXPathUnavailable(returnXPath);
const page = await manager.activePage();
await positionCursorOverlay(manager, page, x, y);
await page.scroll(x, y, deltaX, deltaY);
return { scrolled: true };
},

async "mouse.drag"(manager, params) {
const { button, delay, fromX, fromY, returnXPath, steps, toX, toY } = z
const { button, delay, fromX, fromY, steps, toX, toY } = z
.object({
button: ButtonSchema,
delay: z.number().int().nonnegative().optional(),
fromX: z.number(),
fromY: z.number(),
returnXPath: z.boolean().optional(),
steps: z.number().int().positive().optional(),
toX: z.number(),
toY: z.number(),
})
.strict()
.parse(params);
assertXPathUnavailable(returnXPath);
const page = await manager.activePage();
await positionCursorOverlay(manager, page, fromX, fromY);
await page.dragAndDrop(fromX, fromY, toX, toY, {
Expand Down Expand Up @@ -100,9 +96,3 @@ async function positionCursorOverlay(
// Best-effort parity with V3's cursor updates.
}
}

function assertXPathUnavailable(returnXPath: boolean | undefined): void {
if (returnXPath) {
throw new Error("Coordinate XPath lookup is not exposed by Stagehand V4");
}
}
17 changes: 0 additions & 17 deletions packages/cli/tests/driver-commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,23 +503,6 @@ describe("driver commands", () => {
).rejects.toBe(actionError);
});

it("fails explicitly for the V4 coordinate XPath capability", async () => {
const manager = {} as Parameters<
NonNullable<(typeof mouseHandlers)["mouse.click"]>
>[0];

for (const [command, params] of [
["mouse.click", { returnXPath: true, x: 1, y: 2 }],
["mouse.hover", { returnXPath: true, x: 1, y: 2 }],
["mouse.scroll", { deltaX: 0, deltaY: 1, returnXPath: true, x: 1, y: 2 }],
["mouse.drag", { fromX: 1, fromY: 2, returnXPath: true, toX: 3, toY: 4 }],
] as const) {
await expect(mouseHandlers[command]!(manager, params)).rejects.toThrow(
"Coordinate XPath lookup is not exposed by Stagehand V4",
);
}
});

it("enables sidecar network capture", async () => {
const page = {};
const network = {
Expand Down
Loading