Files
fn_registry/functions/browser/cdp_click_xy_human.go
T
egutierrez 216cad4c12 perf(browser): acelera CDP — enable cacheado, wait_load por evento, timeout en sendCDP, escritura insertText
Optimiza el dominio browser para que el manejo del navegador via CDP sea mucho más rápido en automatización propia, manteniendo el camino sigiloso disponible.

- CDPConn cachea los enable de Accessibility/Network/Page por conexión (ensureAX/ensureNetwork/ensurePage): elimina un round-trip redundante en cada percepción y espera, que son las operaciones más frecuentes del bucle percibir->actuar del agente.
- sendCDP adquiere timeout (cdpCmdTimeout 30s): antes una respuesta que Chrome nunca enviaba colgaba la goroutine del tool indefinidamente; ahora falla limpio y el retry puede reconectar.
- CdpWaitLoad pasa de polling de document.readyState cada 200ms a esperar el evento Page.loadEventFired, con fast path inicial de readyState y re-chequeo anti-carrera tras suscribir. Si la página ya está cargada retorna en microsegundos.
- cdp_wait_idle usa ensureNetwork y deja de hacer Network.disable al salir (borraba el estado y forzaba el enable de nuevo).
- Nuevas funciones de escritura rápida: CdpInsertText (todo el texto en un solo Input.insertText) y CdpTypeRefFast (focus + insertText). El chequeo de foco se extrajo a assertEditableFocus, compartido con CdpTypeText.
- CdpTypeText pasa su pausa entre caracteres de 10ms fija a aleatoria 15-65ms (ritmo humano irregular).
- El modo 'auto' se añade al perfil de ratón (MouseProfileForMode, mouseHumanDefaults, clickPauseMs) como alias rápido de 'fast'.

No se tocan las firmas públicas existentes; CdpTypeRef y CdpTypeText conservan su comportamiento (camino human).
2026-06-13 14:27:10 +02:00

65 lines
2.1 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)
}
// Pausa entre press y release según el modo de velocidad.
if pms := clickPauseMs(opts.Mode); pms > 0 {
time.Sleep(time.Duration(pms) * 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
}
// clickPauseMs devuelve la pausa (ms) entre press y release según el modo de
// velocidad: human 30-90, auto/fast 5-15, instant 0.
func clickPauseMs(mode string) int {
switch mode {
case "instant":
return 0
case "fast", "auto":
return 5 + rand.Intn(11) // 5..15
default: // "human" o ""
return 30 + rand.Intn(61) // 30..90
}
}