aboutsummaryrefslogtreecommitdiff
path: root/src/domains
diff options
context:
space:
mode:
authoramankumarsingh77 <amankumarsingh7702@gmal.com>2026-05-04 22:44:55 +0530
committeramankumarsingh77 <amankumarsingh7702@gmal.com>2026-05-04 22:44:55 +0530
commit71da8e0719c50d9b11c918b032b9ed4d77aabf5b (patch)
tree16794f5884f95abe9fff79d7eec7e08f24286aed /src/domains
parent2a98be01d28044beabe6a1363f01a5a3acde9fd5 (diff)
feat: parallel tool execution with automatic mutation serialization
- Add lightweight async mutex (src/util/mutex.ts) for FIFO serialization - Add serialized?: boolean to BrowserToolDefinition - Wire mutex acquisition into registerBrowserTool execute wrapper - Expose mutationMutex() on BrowserClient - Mark all mutation tools (click, type, scroll, navigate, switch_tab, etc.) as serialized - Leave observation tools (screenshot, page_info, execute_js, http_get, etc.) unguarded - Update prompt and skill docs to reflect parallel-safe behavior - Fix scroll tool: add Page.bringToFront, explicit button:none/buttons:0/pointerType:mouse - Update .gitignore to ignore scripts/ and data/ folders
Diffstat (limited to 'src/domains')
-rw-r--r--src/domains/scroll.ts25
1 files changed, 16 insertions, 9 deletions
diff --git a/src/domains/scroll.ts b/src/domains/scroll.ts
index db80af7..2bd2ed1 100644
--- a/src/domains/scroll.ts
+++ b/src/domains/scroll.ts
@@ -7,8 +7,8 @@ const ScrollArgs = Type.Object({
y: Type.Optional(Type.Number({ description: "Y coordinate where to scroll. Default: viewport center" })),
deltaX: Type.Optional(Type.Number({ default: 0, description: "Horizontal scroll delta (CSS pixels). Positive = right." })),
deltaY: Type.Optional(Type.Number({
- default: -300,
- description: "Vertical scroll delta (CSS pixels). Positive = up (matches W3C wheel events). Default: -300 (scroll down).",
+ default: 300,
+ description: "Vertical scroll delta (CSS pixels). Positive = down, negative = up (W3C wheel-event convention). Default: 300 (scroll down).",
})),
});
@@ -16,10 +16,10 @@ export const scrollTool = defineBrowserTool({
name: "browser_scroll",
label: "Browser Scroll",
description:
- "Scroll the page at given coordinates. deltaY follows W3C wheel-event convention: positive = scroll up, negative = scroll down. Default scrolls down (deltaY = -300).",
- promptSnippet: "Scroll the page (deltaY positive=up, negative=down)",
+ "Scroll the page at given coordinates. deltaY follows W3C wheel-event convention: positive = scroll down, negative = scroll up. Default scrolls down (deltaY = 300).",
+ promptSnippet: "Scroll the page (deltaY positive=down, negative=up)",
promptGuidelines: [
- "Default behavior scrolls down 300px (deltaY=-300). Pass a positive deltaY to scroll up.",
+ "Default behavior scrolls down 300px (deltaY=300). Pass a negative deltaY to scroll up.",
"Pass x/y to target a specific scrollable region (e.g., a div with overflow); otherwise scrolls the page at viewport center.",
],
parameters: ScrollArgs,
@@ -35,14 +35,21 @@ export const scrollTool = defineBrowserTool({
const cx = args.x ?? Math.round(info.data.width / 2);
const cy = args.y ?? Math.round(info.data.height / 2);
const dx = args.deltaX ?? 0;
- const dy = args.deltaY ?? -300;
+ const dy = args.deltaY ?? 300;
+ // The page target must be focused or Input events are dropped silently
+ // (mouseWheel hangs; synthesizeScrollGesture returns ok but no scroll).
+ // Page.bringToFront makes the target the active one in the browser.
+ const front = await client.session().call("Page.bringToFront", {});
+ if (!front.success) return err({ kind: "cdp_error", message: front.error.message });
// Establish compositor mouse position before mouseWheel; without this,
- // CDP sometimes drops the wheel event with a timeout. Fix preserved
- // from v0.2.0.
- const moved = await client.session().call("Input.dispatchMouseEvent", { type: "mouseMoved", x: cx, y: cy });
+ // CDP sometimes drops the wheel event with a timeout.
+ const moved = await client.session().call("Input.dispatchMouseEvent", {
+ type: "mouseMoved", x: cx, y: cy, button: "none", buttons: 0,
+ });
if (!moved.success) return err({ kind: "cdp_error", message: moved.error.message });
const wheel = await client.session().call("Input.dispatchMouseEvent", {
type: "mouseWheel", x: cx, y: cy, deltaX: dx, deltaY: dy,
+ button: "none", buttons: 0, pointerType: "mouse",
});
if (!wheel.success) return err({ kind: "cdp_error", message: wheel.error.message });
return ok({