Skip to content

ToolValidator und autoApprove: Zwei Tore vor der Ausführung

源码版本v4.0.10

Verantwortung

Bevor ein Werkzeug tatsächlich läuft, durchläuft es zwei unabhängige Prüfungen: ToolValidator kümmert sich um die Legitimität von Parametern und Pfaden, AutoApprove entscheidet, ob ein Genehmigungsdialog angezeigt wird. Keiner von beiden führt das Werkzeug aus; sie entscheiden nur «darf es laufen» und «muss der Benutzer gefragt werden».

Der ToolValidator ist eine sehr dünne Hilfsklasse für Handler. Er bietet zwei Methoden: assertRequiredParams prüft, ob erforderliche Parameter vorhanden sind, und checkClineIgnorePath prüft, ob ein Pfad durch .clineignore blockiert wird (assertRequiredParams:17). Er hat selbst keine Seiteneffekte und liefert nur ein ValidationResult, damit der Handler entscheidet, wie damit umgegangen wird.

AutoApprove ist etwas komplexer: ein privates Feld des ToolExecutor, das über asToolConfig in die TaskConfig injiziert wird (autoApprover init:126). Ein Handler greift indirekt über config.callbacks.shouldAutoApproveTool oder config.callbacks.shouldAutoApproveToolWithPath darauf zu (callback wiring:181). Gelesen werden drei globale Schalter – yoloModeToggled, autoApproveAllToggled, autoApprovalSettings – sowie ob der Pfad innerhalb des Workspace liegt; daraus entsteht ein dreistufiges Resultat: «lokale Auto-Genehmigung», «externe Auto-Genehmigung», «keine Genehmigung».

Entwurfsmotivation

  • Validator und AutoApprove getrennt: Legitimitätsprüfung und Genehmigung sind zwei orthogonale Belange – gültige Parameter ohne Genehmigung oder ungültige Parameter trotz Genehmigung können beide auftreten. Zwei getrennte Objekte erlauben es dem Handler, auf Fehlerpfaden die Genehmigung nicht zu umgehen und auch nach einer erteilten Genehmigung illegitime Parameter abzublocken.
  • Validator liest nur, ändert nicht: Er gibt ein ValidationResult zurück, anstatt zu werfen; der Handler entscheidet selbst, ob er einen Fehler pushen oder einen abgemilderten Pfad wählen will (ValidationResult:4). So können verschiedene Handler dieselbe Fehlerdarstellung teilen.
  • Drei Stufen bei AutoApprove: yolo gibt alles frei, autoApproveAll ist die zweite Stufe, autoApprovalSettings ist die feinste Granularität (Unterscheidung lokal/extern, sichere Befehle/alle Befehle) (shouldAutoApproveTool:42). Die weiter oben genannten Schalter haben Vorrang.
  • Pfadklassifikation entscheidet über externen Zugriff: Das Auto-Approve-Resultat von Lese-/Schreibwerkzeugen ist ein Tupel [local, external] (tuple result:96). local steuert Dateien innerhalb des Arbeitsbereichs, external Dateien ausserhalb. Standardmässig ist extern strenger, um versehentliche Änderungen an Systemdateien zu vermeiden.
  • Workspace-Info im Task-Rahmen cachen: getWorkspaceInfo speichert beim ersten Abruf in workspacePathsCache und isMultiRootScenarioCache (getWorkspaceInfo:23). Da sich die Workspace-Wurzeln während des Task-Lebenszyklus kaum ändern, spart der Cache wiederholte IPC-Aufrufe.

Schlüsseldateien

Datenfluss

Nachdem ein Handler den Block erhalten hat, lautet der typische Ablauf: zunächst per Validator Parameter prüfen, dann per AutoApprove über den UI-Pfad entscheiden. Der tatsächliche Aufruf von WriteToFileToolHandler in der Partial-Block-Phase:

typescript
// apps/vscode/src/core/task/tools/handlers/WriteToFileToolHandler.ts
// Handle auto-approval vs manual approval for partial
if (await uiHelpers.shouldAutoApproveToolWithPath(block.name, relPath)) {
    await uiHelpers.removeLastPartialMessageIfExistsWithType("ask", "tool") // in case the user changes auto-approval settings mid stream
    await uiHelpers.say("tool", partialMessage, undefined, undefined, block.partial)
} else {
    await uiHelpers.removeLastPartialMessageIfExistsWithType("say", "tool")
    await uiHelpers.ask("tool", partialMessage, block.partial).catch(() => {})
}

shouldAutoApproveToolWithPath prüft intern zuerst die beiden Hauptschalter YOLO und autoApproveAll; ist einer von ihnen wahr, wird sofort true zurückgegeben (yolo short circuit:126). Danach wird berechnet, ob der Pfad innerhalb des Workspace liegt, und mit dem Tupel aus shouldAutoApproveTool zur endgültigen Entscheidung kombiniert:

typescript
// apps/vscode/src/core/task/tools/autoApprove.ts
const autoApproveResult = this.shouldAutoApproveTool(blockname)
const [autoApproveLocal, autoApproveExternal] = Array.isArray(autoApproveResult)
    ? autoApproveResult
    : [autoApproveResult, false]

if ((isLocalRead && autoApproveLocal) || (!isLocalRead && autoApproveLocal && autoApproveExternal)) {
    return true
}
return false

Hier wird autoApproveExternal nur dann geprüft, wenn auch autoApproveLocal wahr ist – das bedeutet, dass «externe Auto-Genehmigung» implizit auch «lokale Auto-Genehmigung» voraussetzt. Das ist die Standard-Sicherheitshaltung von Cline: Externe Operationen sind stets eine Stufe strikter als lokale.

Grenzen und Fehler

  • Leere Zeichenketten zählen als fehlend: assertRequiredParams prüft mit String(val).trim() === ""; leere Strings oder reiner Whitespace gelten als fehlend (empty check:21). Das Feld content darf jedoch leer sein (neue leere Datei); der Handler prüft es darum selbst mit == null und geht nicht über den Validator (content null check:42).
  • Ohne Pfad keine Genehmigung: Erhält shouldAutoApproveToolWithPath den Pfad undefined, setzt es isLocalRead = false (no path default:153). Als Sicherheits-Standard gilt: Ein Werkzeug ohne Pfad wird als externe Operation behandelt.
  • Cache nimmt unveränderlichen Workspace an: Der Kommentar hält fest: «assumes that the task has a fixed set of workspace roots» (cache assumption:11). Fügt der Benutzer mitten in der Task eine neue Wurzel hinzu, sieht diese Task weiterhin den alten Cache; erst die nächste Task bekommt die neuen Wurzeln.
  • YOLO deckt nicht alle Werkzeuge ab: Im YOLO-Switch sind nur read / write / bash / browser / web / MCP aufgeführt; ASK, ATTEMPT, NEW_TASK fehlen (yolo switch list:44). Solche Werkzeuge fallen auf return false zurück und benötigen die reguläre Genehmigung.
  • Das YOLO-Tupel gilt nur für file/bash-artige Werkzeuge: Das Tupel [true, true] wird nur für read/write/bash/subagents geliefert (yolo tuple:55). browser/web/MCP erhalten den einfachen Wert true; unter YOLO wird bei ihnen also nicht zwischen lokal und extern unterschieden.
  • Validator wird nicht vom alten ToolExecutor genutzt: Der Klassenkommentar sagt ausdrücklich: «The legacy ToolExecutor switch remains unchanged and does not depend on this» (legacy note:8). Im alten Pfad sind die Parameterprüfungen über die einzelnen cases verstreut; der Validator bedient nur die neuen Handler.

Zusammenfassung

Der Validator ist die harte Prüfung von Parametern und Pfaden; bei Misserfolg meldet er einen Fehler und veranlasst das Modell zum Wiederholen. AutoApprove ist ein weicher, durch Benutzerpräferenzen gesteuerter Schalter, der über Auto-Approval oder Dialog entscheidet. Beide zusammen wirken als Torwache vor der Werkzeugausführung; der Handler ruft sie auf, bevor er über den nächsten Schritt entscheidet. Wie die Handler-Liste registriert wird, steht in /tools/handlers-overview; wie das Routing arbeitet, in /tools/coordinator.

Siehe offizielle Dokumentation: Cline-Dokumentation · README