ToolValidator und autoApprove: Zwei Tore vor der Ausführung
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
ValidationResultzurü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:
yologibt alles frei,autoApproveAllist die zweite Stufe,autoApprovalSettingsist 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).localsteuert Dateien innerhalb des Arbeitsbereichs,externalDateien ausserhalb. Standardmässig ist extern strenger, um versehentliche Änderungen an Systemdateien zu vermeiden. - Workspace-Info im Task-Rahmen cachen:
getWorkspaceInfospeichert beim ersten Abruf inworkspacePathsCacheundisMultiRootScenarioCache(getWorkspaceInfo:23). Da sich die Workspace-Wurzeln während des Task-Lebenszyklus kaum ändern, spart der Cache wiederholte IPC-Aufrufe.
Schlüsseldateien
ToolValidator:10— Klassendefinition; Konstruktor nimmtClineIgnoreControllerentgegen.assertRequiredParams:17— Durchläuft Parameternamen; bei Leerwerten oder reinem Whitespace wird ein Fehler geliefert.checkClineIgnorePath:32— RuftclineIgnoreController.validateAccessauf; bei Blockade Fehler.AutoApprove:8— Klassendefinition; hältstateManagerund zwei Cache-Felder.getWorkspaceInfo:23— Gecachte Workspace-Pfade und Multiroot-Erkennung.shouldAutoApproveTool:42— Drei Stufen: YOLO, autoApproveAll, feingranulares autoApprovalSettings.yolo branch:43— Im YOLO-Modus liefern Lese-/Dateioperationen[true, true], browser/web/MCP lieferntrue.autoApproveAll branch:66— Dieselbe Reichweite wie YOLO, aber als nachrangiger Schalter.autoApprovalSettings:88— Feingranularer Zweig; unterteilt nach actions.readFiles / editFiles / executeSafeCommands usw.shouldAutoApproveToolWithPath:122— Version mit Pfad; prüft lokal/extern und kombiniert mit dem Auto-Approve-Tupel.multi-root workspace check:138— Im Multiroot-Fall wird mitisLocatedInWorkspacegegen jede Wurzel geprüft.final decision:163— Freigabe nur beilocal && autoApproveLocalbeziehungsweiseexternal && autoApproveLocal && autoApproveExternal.ToolExecutor delegations:48— ToolExecutor bindet sich selbst als Callback und leitet anautoApproverweiter.complete block approval:205— Vollständiger Block: pershouldAutoApproveToolWithPathzwischen Auto-Approval und manuellemask("tool", ...)entscheiden.partial block approval:74— Auch gestreamte Partial-Blöcke durchlaufen dieselbe Auto-Approve-Prüfung und entscheiden während des Streamings, ob ein Dialog erscheint.
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:
// 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:
// 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 falseHier 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:
assertRequiredParamsprüft mitString(val).trim() === ""; leere Strings oder reiner Whitespace gelten als fehlend (empty check:21). Das Feldcontentdarf jedoch leer sein (neue leere Datei); der Handler prüft es darum selbst mit== nullund geht nicht über den Validator (content null check:42). - Ohne Pfad keine Genehmigung: Erhält
shouldAutoApproveToolWithPathden Pfadundefined, setzt esisLocalRead = 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_TASKfehlen (yolo switch list:44). Solche Werkzeuge fallen aufreturn falsezurü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 Werttrue; 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