mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 19:59:56 +02:00
La façade tient la session Chrome des outils browser_* (src/browser/, port de computer_cdp.go, computer_use.go, browser_grid.go et cu_autoshot.go) : lancement (profil temporaire, mêmes arguments, tué avec la façade), client CDP multiplexé sur websocket, attente du chargement et du calme réseau, scripts injectés copiés à l'octet près, les neuf outils aux textes du Go (snapshot dédoublonné, recherche, clics, saisie et listes déroulantes, touches, défilement, navigation et ses erreurs), capture rangée propre et quadrillée pour le modèle (mêmes pixels), aperçus JPEG en anneau servis par /api/chat/cushot. Un seul navigateur : quand la façade tient la conversation, le Go lui passe les outils de ses sous-agents et tâches IA, ses aperçus et la fermeture (POST /internal/facade/v1/browser) ; façade injoignable, le navigateur du Go prend le relais. Couper l'interrupteur ferme les deux. Parité : journal de 42 étapes tiré du Go contre un faux Chrome (script + faux serveur CDP qui note chaque commande, scripts résumés par leur empreinte, pixels de la grille), rejoué par tests/browser.rs ; un vrai Chromium de bout en bout avec LOKI_CU_SMOKE=1 ; un tour de la façade qui ouvre une page (tests/lot6.rs) ; TestFacadeNavigateur côté Go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
87 lines
2.7 KiB
Go
87 lines
2.7 KiB
Go
package loki
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// facade_browser.go — le navigateur piloté tenu par la façade (lot 44 de la
|
|
// migration Rust). Quand elle tient la conversation, la session Chrome est
|
|
// la sienne : ses tours exécutent les outils browser_* chez elle, et ceux du
|
|
// Go (sous-agents, tâches IA) passent par /internal/facade/v1/browser — un
|
|
// seul navigateur. L'aperçu après une action et la fermeture aussi.
|
|
// Façade injoignable : le navigateur du Go prend le relais.
|
|
|
|
// facadeBrowserClient : une action du navigateur peut attendre le
|
|
// lancement de Chrome, puis le chargement et le calme réseau de la page.
|
|
var facadeBrowserClient = &http.Client{Timeout: 3 * time.Minute}
|
|
|
|
// facadeBrowserCall appelle l'API du navigateur de la façade.
|
|
func facadeBrowserCall(body map[string]any, out any) error {
|
|
b, err := json.Marshal(body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req, err := http.NewRequest(http.MethodPost, "http://"+facadeAddr()+"/internal/facade/v1/browser", bytes.NewReader(b))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set(internalTokenHeader, internalToken())
|
|
resp, err := facadeBrowserClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
return fmt.Errorf("façade : %s", resp.Status)
|
|
}
|
|
return json.NewDecoder(resp.Body).Decode(out)
|
|
}
|
|
|
|
// facadeBrowserTool exécute un outil browser_* à la façade ; ok faux : elle
|
|
// ne tient pas la conversation, ou ne répond pas (le Go le fait lui-même).
|
|
func facadeBrowserTool(name string, args map[string]any) (result string, image map[string]any, ok bool) {
|
|
if !facadeChat() {
|
|
return "", nil, false
|
|
}
|
|
var out struct {
|
|
Result string `json:"result"`
|
|
Image map[string]any `json:"image"`
|
|
}
|
|
if err := facadeBrowserCall(map[string]any{"op": "tool", "name": name, "args": args}, &out); err != nil {
|
|
fmt.Fprintf(os.Stderr, "[cu] navigateur de la façade injoignable, repli local : %v\n", err)
|
|
return "", nil, false
|
|
}
|
|
return out.Result, out.Image, true
|
|
}
|
|
|
|
// facadeBrowserShot : l'aperçu pris par la façade.
|
|
func facadeBrowserShot() (string, bool) {
|
|
if !facadeChat() {
|
|
return "", false
|
|
}
|
|
var out struct {
|
|
ID string `json:"id"`
|
|
}
|
|
if err := facadeBrowserCall(map[string]any{"op": "shot"}, &out); err != nil {
|
|
return "", false
|
|
}
|
|
return out.ID, true
|
|
}
|
|
|
|
// facadeBrowserShutdown ferme le navigateur de la façade.
|
|
func facadeBrowserShutdown() {
|
|
if !facadeChat() {
|
|
return
|
|
}
|
|
var out struct{}
|
|
if err := facadeBrowserCall(map[string]any{"op": "shutdown"}, &out); err != nil {
|
|
fmt.Fprintf(os.Stderr, "[cu] fermeture du navigateur de la façade : %v\n", err)
|
|
}
|
|
}
|