From 093103bdd7cd02e10f2339e7beeb71375fb16256 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Tue, 3 Mar 2026 10:53:04 +0300 Subject: [PATCH] Feat (pw_tools): click_at --- tools.go | 3 +++ tools_playwright.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tools.go b/tools.go index 76ba34e..3974a34 100644 --- a/tools.go +++ b/tools.go @@ -1391,6 +1391,7 @@ func removePlaywrightToolsFromBaseTools() { "pw_is_running": true, "pw_navigate": true, "pw_click": true, + "pw_click_at": true, "pw_fill": true, "pw_extract_text": true, "pw_screenshot": true, @@ -1410,6 +1411,7 @@ func removePlaywrightToolsFromBaseTools() { delete(fnMap, "pw_is_running") delete(fnMap, "pw_navigate") delete(fnMap, "pw_click") + delete(fnMap, "pw_click_at") delete(fnMap, "pw_fill") delete(fnMap, "pw_extract_text") delete(fnMap, "pw_screenshot") @@ -1487,6 +1489,7 @@ func registerPlaywrightTools() { fnMap["pw_is_running"] = pwIsRunning fnMap["pw_navigate"] = pwNavigate fnMap["pw_click"] = pwClick + fnMap["pw_click_at"] = pwClickAt fnMap["pw_fill"] = pwFill fnMap["pw_extract_text"] = pwExtractText fnMap["pw_screenshot"] = pwScreenshot diff --git a/tools_playwright.go b/tools_playwright.go index 9f19a4b..7920230 100644 --- a/tools_playwright.go +++ b/tools_playwright.go @@ -70,6 +70,11 @@ Additional browser automation tools (Playwright): "args": ["x1", "y1", "x2", "y2"], "when_to_use": "drag the mouse from point (x1,y1) to (x2,y2)." }, +{ + "name": "pw_click_at", + "args": ["x", "y"], + "when_to_use": "click at specific X,Y coordinates on the page. Use when you know the exact position." +}, { "name": "pw_get_html", "args": ["selector"], @@ -442,6 +447,34 @@ func pwDrag(args map[string]string) []byte { return []byte(fmt.Sprintf(`{"success": true, "message": "Dragged from (%s,%s) to (%s,%s)"}`, x1, y1, x2, y2)) } +func pwClickAt(args map[string]string) []byte { + x, ok := args["x"] + if !ok { + return []byte(`{"error": "x not provided"}`) + } + y, ok := args["y"] + if !ok { + return []byte(`{"error": "y not provided"}`) + } + if !browserStarted || page == nil { + return []byte(`{"error": "Browser not started. Call pw_start first."}`) + } + fx, err := strconv.ParseFloat(x, 64) + if err != nil { + return []byte(fmt.Sprintf(`{"error": "failed to parse x: %s"}`, err.Error())) + } + fy, err := strconv.ParseFloat(y, 64) + if err != nil { + return []byte(fmt.Sprintf(`{"error": "failed to parse y: %s"}`, err.Error())) + } + mouse := page.Mouse() + err = mouse.Click(fx, fy) + if err != nil { + return []byte(fmt.Sprintf(`{"error": "failed to click: %s"}`, err.Error())) + } + return []byte(fmt.Sprintf(`{"success": true, "message": "Clicked at (%s,%s)"}`, x, y)) +} + func pwGetHTML(args map[string]string) []byte { selector := args["selector"] if selector == "" {