Skip to content

BrowserToolHandler: Puppeteer-Browserautomatisierung

源码版本v4.0.10

Verantwortung

BrowserToolHandler ist der Einstiegspunkt, über den Cline den Browser bedient, und entspricht dem Werkzeugnamen ClineDefaultTool.BROWSER. Das Modell wählt über den Parameter action die konkrete Operation: launch (URL öffnen), click (Koordinatenklick), type (Text in den aktuellen Fokus eingeben), scroll_up/scroll_down (Seite scrollen), close (Browser schließen) (class declaration:12-13). Nach jeder Aktion wird ein Screenshot sowie die in diesem Fenster angefallenen console logs zurückgegeben, damit das Modell den Seitenzustand visuell erfasst.

Der Handler selbst ist nur eine „Fassade": Er übernimmt nach einem tool_use die Parametervalidierung, Approval und den Hook und reicht die Aktion dann an die BrowserSession-Instanz config.services.browserSession weiter. Der echte Browser-Prozess, die Puppeteer-API, die Screenshot-Codierung und die Remote-Browser-Verbindung liegen alle in der BrowserSession (class BrowserSession:38). Die BrowserSession nutzt puppeteer-core, um sich mit einem lokalen Chrome oder einem Remote-Browser zu verbinden, und erhält über connect/launch die Browser/Page-Objekte.

Die Positionierung dieses Werkzeugs in Cline ist die einer „Capability Tool" (Fähigkeits-Werkzeug) auf gleicher Ebene wie file ops und web fetch: eine vom ToolExecutor angestoßene einmalige Ausführungseinheit. Die Besonderheit ist, dass es zustandsbehaftet ist: Innerhalb einer Task gibt es nur eine Browsersitzung, nach launch verwenden alle nachfolgenden click/type/scroll-Aktionen dieselbe Page, bis close oder ein Fehler auftritt. Deshalb ruft der Handler in jedem Fehlerzweig closeBrowser() auf — ein Browser-Prozess darf nicht zurückbleiben.

Entwurfsmotivation

  • Sitzungs-Wiederverwendung: Nach launch wird die Page bis close weiterverwendet, damit nicht bei jedem click neu geöffnet wird; außerdem kann das Modell über mehrere Aktionen hinweg Login-Status und Scroll-Position halten (launchBrowser:155).
  • Screenshot + Console-Logs dual: Nach jeder Aktion wartet doAction 500 ms auf Console-Stille und liefert dann Screenshot + Logs zusammen an das Modell zurück, um die Lücke rein visueller Erfassung (keine JS-Fehler sichtbar) zu schließen (doAction:378).
  • Launch mit eigenem Approval: Einen Browser zu öffnen ist eine hochriskante Aktion; launch läuft über den eigenen ask-Typ browser_action_launch, während andere Aktionen (click/type/scroll) nach erfolgter launch-Freigabe standardmäßig durchgehen (launch flow:81).
  • Remote-Browser-Fallback: Schlägt die Remote-Browser-Verbindung fehl, wird auf den lokalen Modus herabgestuft, damit das Werkzeug als Ganzes nicht abstürzt (remote fallback:181-198).
  • Nach click auf Navigation warten: Ein Klick kann eine Seitennavigation auslösen; doAction lauscht bei click auf request-Ereignisse, um Netzwerkaktivität zu erkennen, und ruft ggf. waitForNavigation auf (click:528-561).
  • Browser zwingend schließen vor Werkzeugwechsel: Im Ergebnis wird der Hinweis „REMEMBER ... non-browser_action tools erst nach close des Browsers verwenden" angefügt, damit das Modell nicht bei offenem Browser zu Dateiänderungen wechselt (result reminder:190-194).

Schlüsseldateien

  • class declaration:12export class BrowserToolHandler implements IFullyManagedTool,name = ClineDefaultTool.BROWSER.
  • handlePartialBlock:19 — Streaming-Zweig: launch geht über den ask-Typ browser_action_launch, andere Aktionen sagen direkt die aktuelle Koordinate/den Text.
  • execute:62 — Hauptfluss: action validieren → launch-Zweig oder click/type/scroll/close-Zweig → Screenshot + Logs zurückgeben.
  • launch flow:81-127 — Vollständiger launch-Ablauf: url validieren, approval, PreToolUse hook, applyLatestBrowserSettings aktualisiert die Session, launchBrowser + navigateToUrl.
  • click/type param check:130-145 — Bei click fehlt coordinate oder bei type fehlt text: jeweils Fehlermeldung und closeBrowser.
  • action dispatch:163-179 — switch verteilt auf browserSession.click/type/scrollDown/scrollUp/closeBrowser.
  • result format:184-203 — launch/click/type/scroll liefern Screenshot + Logs, close liefert reinen Text-Hinweis.
  • error close:205-208 — Jede Ausnahme führt closeBrowser aus, kein Browser-Prozess bleibt zurück.
  • launchBrowser:155 — Remote-Vorrang, bei Misserfolg Fallback auf lokal, dann browser.newPage() für neuen Tab.
  • doAction:378 — console/pageerror-Listener anhängen, Aktion ausführen, 500 ms auf Stille warten, Screenshot, Listener aufräumen.
  • navigateToUrl:481page.goto mit domcontentloaded + networkidle2, danach waitTillHTMLStable pollt die HTML-Größe.
  • click:528 — Koordinaten zerlegen, page.mouse.click, auf request lauschen und entscheiden, ob auf Navigation gewartet wird.
  • screenshot:441 — webp bevorzugt, bei Misserfolg Fallback auf png; schlagen beide fehl, wird geworfen und screenshot_error-Telemetrie gesendet.

Datenfluss

Der launch-Zweig ist der vollständigste Ablauf des BrowserToolHandler: url validieren → approval → hook → browserSession aktualisieren → Browser öffnen → navigieren → Screenshot und Logs zurückgeben. Der Schlüsselcode:

typescript
// apps/vscode/src/core/task/tools/handlers/BrowserToolHandler.ts
if (action === "launch") {
    if (!url) {
        config.taskState.consecutiveMistakeCount++
        const errorResult = await config.callbacks.sayAndCreateMissingParamError(this.name, "url")
        await config.services.browserSession.closeBrowser()
        return errorResult
    }
    config.taskState.consecutiveMistakeCount = 0
    // ... approval + PreToolUse hook ...
    await config.callbacks.say("browser_action_result", "")
    config.services.browserSession = await config.callbacks.applyLatestBrowserSettings()
    await config.services.browserSession.launchBrowser()
    browserActionResult = await config.services.browserSession.navigateToUrl(url)
}

Beachten Sie die Zeile config.services.browserSession = await config.callbacks.applyLatestBrowserSettings(): Sie aktualisiert nicht nur die Einstellungen, sondern ersetzt auch die von ToolExecutor gehaltene browserSession-Referenz, sodass nachfolgende Browser-Tool-Aufrufe dieselbe neue Session erhalten (applyLatestBrowserSettings:125).

navigateToUrl läuft intern über doAction, und alle Nicht-launch-Aktionen gehen ebenfalls über doAction. doAction setzt Screenshot + console-Logs zu einem BrowserActionResult zusammen:

typescript
// apps/vscode/src/services/browser/BrowserSession.ts
const screenshotType = this.useWebp ? "webp" : "png"
let screenshotBase64 = await this.page.screenshot({ ...options, type: screenshotType })
let screenshot = `data:image/${screenshotType};base64,${screenshotBase64}`
if (!screenshotBase64) {
    screenshotBase64 = await this.page.screenshot({ ...options, type: "png" })
    screenshot = `data:image/png;base64,${screenshotBase64}`
}
return {
    screenshot,
    logs: logs.join("\n"),
    currentUrl: this.page.url(),
    currentMousePosition: this.currentMousePosition,
}

Der Handler verpackt dieses Resultat als formatResponse.toolResult und fügt die starke Erinnerung „Browser erst schließen, dann zu anderen Werkzeugen wechseln" an.

Grenzen und Fehler

  • Ungültige action: Beim Abschluss des Blocks ist die action nicht in der Liste browserActions, consecutiveMistakeCount++ + sayAndCreateMissingParamError + closeBrowser (invalid action:69-75).
  • launch ohne url: launch muss url mitbringen; fehlt sie, erfolgt ebenfalls mistake++ und closeBrowser (missing url:82-87).
  • click ohne coordinate / type ohne text: Bei fehlendem Parameter wird ein Fehler gemeldet und closeBrowser aufgerufen, damit keine Session zurückbleibt (param checks:131-145).
  • Remote-Browser-Verbindung fehlgeschlagen: Wenn launchRemoteBrowser wirft, wird nach catch auf launchLocalBrowser herabgestuft und remote_browser_launch_error per Telemetrie aufgezeichnet (remote fallback:181-198).
  • Screenshot fehlgeschlagen: Schlägt webp fehl, wird auf png retry gewechselt; schlagen beide fehl, wird "Failed to take screenshot." geworfen und screenshot_error-Telemetrie gesendet (screenshot retry:448-466).
  • page nicht gestartet: doAction prüft this.page und wirft, falls nicht vorhanden, mit dem Hinweis „Browser is not launched"; das passiert typischerweise bei Nicht-browser_action-Werkzeugen (die eigentlich keine Berechtigung haben) oder nach einem vorherigen close (page check:379-383).
  • Jede Ausnahme schließt den Browser: Der try/catch-Fallback des Handlers ist browserSession.closeBrowser(), um sicherzustellen, dass kein Chrome-Prozess Ressourcen blockiert (error close:205-208).

Zusammenfassung

BrowserToolHandler ist eine dünne Hülle; die eigentliche Arbeit macht die BrowserSession. Das Modell wählt über den action-Parameter launch/click/type/scroll/close; der Handler übernimmt Parameter-Validierung und Approval und reicht die Aktion an die Puppeteer-Aufrufe der BrowserSession weiter, um dann Screenshot und console-Logs an das Modell zurückzugeben. launch hat ein eigenes Approval, die anderen Aktionen verwenden die bereits geöffnete Sitzung; bei jedem Fehler wird der Browser zwangsgeschlossen.

Wer tiefer einsteigen will, kann weiterlesen bei:

  • Datei- und Befehls-Werkzeuge: /cap-tools/file-ops
  • Web fetch/search: /cap-tools/web
  • Werkzeug-Dispatch-Pfad: /agent-loop/task-class

Siehe offizielle Dokumentation: Cline-Dokumentation · README