Skip to content

WebFetchTool / WebSearchTool : outils réseau du compte Cline

源码版本v4.0.10

Responsabilités

Ces deux handlers sont les outils réseau de sortie de Cline ; tous deux implémentent IFullyManagedTool et exigent, avant exécution, que le provider soit cline, que l'utilisateur ait activé clineWebToolsEnabled et que le feature flag correspondant soit levé (WebFetch class:20-21, WebSearch class:21-22). La différence essentielle avec BrowserToolHandler est la suivante : l'outil navigateur saisit la page directement via Chrome local ou distant, alors que ces deux outils envoient une requête HTTP à l'API officielle de Cline ; le serveur Cline effectue l'extraction ou la recherche, puis renvoie le résultat au modèle.

  • WebFetchToolHandler (ClineDefaultTool.WEB_FETCH) : le modèle fournit une URL et un prompt ; l'outil POST les deux à ${apiBaseUrl}/api/v1/search/webfetch, le serveur extrait le contenu de l'URL selon le prompt et renvoie un texte (webfetch axios:150).
  • WebSearchToolHandler (ClineDefaultTool.WEB_SEARCH) : le modèle fournit une requête et, optionnellement, une liste blanche allowed_domains ou une liste noire blocked_domains (mutuellement exclusives) ; l'outil POST vers /api/v1/search/websearch et récupère un ensemble de résultats {title, url} (websearch axios:174).

Les sorties de ces deux outils ne sont pas présentées directement à l'utilisateur : elles ne sont qu'un tool result injecté dans userMessageContent pour le prochain tour LLM. Ils ne consomment aucune ressource locale (système de fichiers, terminal, navigateur), c'est une sortie purement réseau, donc operationIsLocatedInWorkspace: false.

Motivation de conception

  • Proxy serveur plutôt que fetch local : dans beaucoup de scénarios, Cline tourne en environnement restreint sans accès direct à Internet ; le proxy serveur unifie authentification, rate limiting et logique d'extraction (rendu JavaScript, contournement d'anti-scraping), le client ne fait qu'envoyer la requête (webfetch request:150-166).
  • Trois portes de contrôle : provider doit être cline, paramètre utilisateur clineWebToolsEnabled activé, feature flag levé — si l'un manque, on renvoie toolError("Cline web tools are currently disabled.") sans laisser le modèle continuer (feature flag gate:55-59).
  • Timeout de 15 s : les deux outils appliquent un timeout axios de 15 s pour éviter qu'une requête à longue traîne ne tue la manche (timeout:163).
  • Listes blanche/noire de domaines mutuellement exclusives : web_search valide que allowed_domains et blocked_domains ne sont pas fournis ensemble ; en cas de violation, mistake++ + toolError (mutual exclusivity:75-78).
  • Parsing de tableau partiel en streaming : parsePartialArrayString sait extraire les éléments déjà complets d'un flux ["a", "b" incomplet, de sorte que la liste de domaines peut s'afficher dès la phase partial block (parsePartialArrayString:71-72).
  • Erreur d'auth explicite : si le token d'auth ne peut être récupéré, on lève CLINE_ACCOUNT_AUTH_ERROR_MESSAGE invitant l'utilisateur à se connecter à son compte Cline, plutôt que de renvoyer un 401 au modèle (auth check:146-148).

Fichiers clés

Flux de données

Les deux handlers ont un flux quasi identique ; prenons WebFetchToolHandler en exemple. Le cœur est le POST vers l'API Cline après approbation :

typescript
// apps/vscode/src/core/task/tools/handlers/WebFetchToolHandler.ts
const baseUrl = ClineEnv.config().apiBaseUrl
const authToken = await AuthService.getInstance().getAuthToken()
if (!authToken) {
    throw new Error(CLINE_ACCOUNT_AUTH_ERROR_MESSAGE)
}

const response = await axios.post(
    `${baseUrl}/api/v1/search/webfetch`,
    { Url: url, Prompt: prompt },
    {
        headers: {
            Authorization: `Bearer ${authToken}`,
            "Content-Type": "application/json",
            "X-Task-ID": config.ulid || "",
            ...(await buildClineExtraHeaders()),
        },
        timeout: 15000,
        ...getAxiosSettings(),
    },
)
const result = response.data.data.result
return formatResponse.toolResult(result)

buildClineExtraHeaders() ajoute des headers de traçabilité ; getAxiosSettings() injecte la configuration utilisateur (proxy/CA, etc.) dans axios. La structure de réponse est { data: { result: "..." } } (notez qu'axios a automatiquement ajouté une couche data), qu'on extrait et qu'on emballe via formatResponse.toolResult pour le renvoyer au LLM.

WebSearchToolHandler ajoute une étape de formatage des résultats :

typescript
// apps/vscode/src/core/task/tools/handlers/WebSearchToolHandler.ts
const data = response.data.data
const results = data.results || []
let resultText = `Search completed (${resultCount} results found)`
if (results.length > 0) {
    resultText += ":\n\n"
    results.forEach((result, index) => {
        resultText += `${index + 1}. ${result.title}\n   ${result.url}\n\n`
    })
}
return formatResponse.toolResult(resultText)

allowed_domains / blocked_domains ne sont inclus dans le body que s'ils sont non vides ; la validation de mutex déclenche mistake++ puis toolError, sans envoyer la requête.

Limites et échecs

  • portes non satisfaites : provider non cline, web tools désactivé par l'utilisateur, feature flag coupé — n'importe lequel manquant renvoie un toolError disabled sans incrémenter mistake (feature flag gate:55-59).
  • non connecté : si AuthService.getInstance().getAuthToken() renvoie vide, on lève CLINE_ACCOUNT_AUTH_ERROR_MESSAGE, transformé dans le catch en Error fetching web content: ... (auth check:146-148).
  • listes blanche et noire fournies ensemble : si web_search reçoit à la fois allowed_domains et blocked_domains, mistake++ + toolError, on bloque (mutual exclusivity:75-78).
  • hook PreToolUse annule : s'il lève PreToolUseHookCancellationError, on renvoie toolDenied sans envoyer de requête (PreToolUse hook:131-140).
  • repli sur erreur de requête : si axios lève ou si le serveur n'est pas 200, le catch emballe en Error fetching web content: ... / Error performing web search: ... sans remonter à Task, pour que le modèle voie l'erreur (error catch:173-175).
  • timeout : 15 s axios ; les requêtes à longue traîne sont coupées et passent dans le catch d'erreur (timeout:163).
  • résultat vide : si web_search renvoie 0 résultat, on retourne Search completed (0 results found) sans ligne de suite (empty results:193-199).

Résumé

WebFetch et WebSearch sont les deux handlers par lesquels Cline fait du fetch/recherche réseau via son proxy serveur. Ils partagent la même gate (provider=cline + setting + flag), le même flux approbation/hook et le même timeout de 15 s. WebFetch renvoie le texte extrait par le serveur selon le prompt ; WebSearch renvoie une liste structurée {title, url} mise en forme en 1./2./3.. Aucun des deux n'écrit sur disque ni n'ouvre de navigateur : pure sortie réseau.

Pour aller plus loin :

  • Outil navigateur (fetch local) : /cap-tools/browser
  • Outils fichier et commande : /cap-tools/file-ops
  • Chaîne de distribution des outils : /agent-loop/task-class

Voir la documentation officielle : documentation Cline · README.