029dbf57bd
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
50 lines
1.7 KiB
Go
50 lines
1.7 KiB
Go
package browser
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"time"
|
|
)
|
|
|
|
// CdpClickXYHuman hace click en las coordenadas absolutas (x, y) de la página con
|
|
// comportamiento humano: mueve el ratón hasta el punto por una trayectoria de
|
|
// Bézier cúbica (CdpMoveMouseHuman) y despacha mousePressed/mouseReleased con una
|
|
// micro-pausa variable (30-90 ms) entre ambos.
|
|
//
|
|
// Es el PRIMITIVO de click compartido por las tres vías de acción del agente:
|
|
// - por selector CSS → CdpClickHuman (obtiene el bbox y llama aquí).
|
|
// - por #ref del AX tree → CdpClickRef (resuelve backendDOMNodeId → bbox → aquí).
|
|
// - por visión → click sobre el bounding box que devuelve OCR/YOLO.
|
|
// Construir un único primitivo evita tener tres caminos de click divergentes.
|
|
func CdpClickXYHuman(c *CDPConn, x, y float64, opts MouseHumanOpts) error {
|
|
if c == nil {
|
|
return fmt.Errorf("cdp click xy human: conexion nula")
|
|
}
|
|
|
|
// Mover el ratón hasta el destino con trayectoria humana.
|
|
if err := CdpMoveMouseHuman(c, x, y, opts); err != nil {
|
|
return fmt.Errorf("cdp click xy human: mover raton: %w", err)
|
|
}
|
|
|
|
clickParams := map[string]any{
|
|
"type": "mousePressed",
|
|
"x": x,
|
|
"y": y,
|
|
"button": "left",
|
|
"clickCount": 1,
|
|
}
|
|
if _, err := c.sendCDP("Input.dispatchMouseEvent", clickParams); err != nil {
|
|
return fmt.Errorf("cdp click xy human: mousePressed: %w", err)
|
|
}
|
|
|
|
// Micro-pausa humana entre press y release (30-90 ms).
|
|
time.Sleep(time.Duration(30+rand.Intn(61)) * time.Millisecond)
|
|
|
|
clickParams["type"] = "mouseReleased"
|
|
if _, err := c.sendCDP("Input.dispatchMouseEvent", clickParams); err != nil {
|
|
return fmt.Errorf("cdp click xy human: mouseReleased: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|