Aller au contenu

Rechercher du code avec le graphe de code

Ce guide vous montre comment faire entrer un dépôt dans le graphe de code, puis comment l’utiliser pour répondre à la question qui vous préoccupe réellement avant une refactorisation : qu’est-ce qui dépend de ceci ?

Le graphe de code est une base de données de symboles et d’arêtes construite en analysant vos copies de dépôts enregistrées avec tree-sitter. Ses outils sont destinés aux agents : vous y accédez en demandant à un agent.

Le graphe indexe Dart, JavaScript, TypeScript, TSX, PHP, Python, Rust, Zig, C, C++, Go, Java, Ruby, C#, Swift, Kotlin, R, Assembly, MATLAB et Ada. Les fichiers dans toute autre langue ne sont pas analysés : ils n’apparaissent donc pas dans search_code, code_symbol, code_callers, code_callees ni code_impact.

Deux autres éléments déterminent ce qui est indexé :

  • Dans un arbre de travail git, l’énumération s’en remet à git ls-files --cached --others --exclude-standard : tous les .gitignore, les fichiers d’exclusion imbriqués, .git/info/exclude et le fichier d’exclusions global sont donc respectés. C’est ce qui tient node_modules et les artefacts de compilation hors du graphe.
  • Le Dart généré est écarté dans tous les cas. Les fichiers générés sont habituellement validés dans le dépôt, de sorte que git seul ne les exclurait pas, et ils changent constamment à chaque exécution de génération de code.

L’enregistrement d’une copie de dépôt déclenche RepoAdded, qui démarre automatiquement le pipeline index_code pour celle-ci. Voir Ajouter des dépôts à un espace de travail.

Pour réindexer manuellement :

  1. Ouvrez Paramètres → Espace de travail → Dépôts.
  2. Cliquez sur le bouton Indexer le code dans la ligne du dépôt.
  3. Pendant l’exécution, le bouton affiche le nombre de fichiers traités sur le total, avec une commande d’annulation. Une fois terminé, il se stabilise en une coche accompagnée du nombre de symboles.

Le graphe est partitionné par espace de travail, par dépôt et par copie de dépôt : la copie de dépôt liée constitue une partition, et chaque arbre de travail d’espace obtient la sienne (indexée par son identifiant de dépôt isolé).

Deux mécanismes de régulation valent la peine d’être connus, car ils expliquent une attente qui ressemble à un blocage :

  • L’observateur de fichiers n’admet qu’une seule exécution d’indexation à la fois sur l’hôte : une deuxième copie de dépôt attend. Le pipeline index_code est par ailleurs plafonné à une exécution par espace de travail, de sorte que deux dépôts du même espace de travail font la queue ; des espaces de travail différents peuvent s’indexer en parallèle. L’indexeur lui-même sérialise deux exécutions de la même copie de dépôt, afin qu’un démarrage de pipeline et un balayage de l’observateur ne puissent pas l’analyser deux fois.
  • Les arbres de travail appartenant à des espaces dormants (aucun message depuis une semaine) ne sont ni observés ni indexés. Les copies de dépôts liées restent observées. Une décision de saut est revérifiée après cinq minutes, de sorte qu’un espace redevenu actif est pris en charge.

Demandez à un agent de faire la recherche. L’outil est search_code et il exige à la fois un espace de travail et un dépôt :

search_code(workspace_id: "...", repo_id: "...", query: "authentication middleware")

Les identifiants de dépôt proviennent de list_repos. L’argument facultatif mode prend la valeur keyword, semantic ou hybrid et vaut hybrid par défaut : BM25 sur les noms, les signatures et les commentaires de documentation, fusionné avec la similarité vectorielle.

Chaque résultat porte l’identifiant, le nom, le nom qualifié, le type, le chemin de fichier, la ligne de début et de fin du symbole, ainsi que sa signature lorsqu’il en a une. L’id est la référence que vous transmettez à tous les autres outils de cette page.

Lorsque vous connaissez le nom exact, consultez-le directement à la place :

code_symbol(workspace_id: "...", repo_id: "...", name: "MyClass")

Les deux prennent un symbol_id issu d’un résultat de recherche, ainsi qu’un limit facultatif (50 par défaut) :

code_callers(workspace_id: "...", symbol_id: "...")
code_callees(workspace_id: "...", symbol_id: "...")

code_callers renvoie les symboles ayant une arête entrante vers celui-ci ; code_callees renvoie ceux dont il dépend.

Voici l’outil pour lequel toute cette page existe :

code_impact(workspace_id: "...", symbol_id: "...", depth: 3)

Il calcule le rayon de dépendance inverse : tout ce qui dépend directement ou transitivement du symbole le long des arêtes calls, extends et implements (les imports, les mixes-in et les références génériques sont stockés dans le graphe, mais ne sont pas parcourus ici). depth est le nombre maximal de sauts, entre 1 et 6, avec une valeur par défaut de 2.

Le résultat comporte trois champs :

  • root — le symbole sur lequel portait votre question
  • impacted — l’ensemble atteignable, y compris la racine à la profondeur 0, chacun portant sa depth depuis la racine
  • edgeCount — le nombre d’arêtes franchies par la traversée, sous forme de compte plutôt que des arêtes elles-mêmes

Exécutez-le avant de renommer quoi que ce soit ou de modifier une signature, et donnez à l’agent la liste des éléments touchés comme périmètre.

Les résultats sont vérifiés par rapport à la copie de travail de l’appelant

Section intitulée “Les résultats sont vérifiés par rapport à la copie de travail de l’appelant”

Pour un appelant agent, l’identifiant d’espace est injecté automatiquement et les résultats sont vérifiés par rapport à la copie de travail de cet espace. Un symbole dont le fichier n’existe plus dans l’arbre de l’appelant est omis, et la réponse porte un compte staleOmitted ainsi qu’une note indiquant que l’index est périmé pour ces symboles.

C’est pourquoi vous et un agent pouvez obtenir des réponses différentes à la même requête, et pourquoi un agent d’un espace peut obtenir une réponse différente de celle d’un agent d’un autre espace. Toutes les conversations d’un espace partagent ce même arbre de travail. La vérification échoue en mode ouvert : une réponse périmée est préférée à une réponse vide.

Demandez à un agent d’exécuter code_impact (ou review_studio.blastRadius) lorsque vous voulez le rayon d’impact d’un changement. Voir Calcul de révision.

La recherche sémantique exige le modèle d’embedding

Section intitulée “La recherche sémantique exige le modèle d’embedding”

Les symboles et les faits sont vectorisés au moment de l’écriture, et seulement lorsque le modèle d’embedding local est installé. D’ici là, mode: "semantic" et la moitié sémantique du mode hybride n’ont rien à quoi se comparer, et la recherche est de fait limitée aux mots-clés.

Installez le modèle dans Paramètres → Serveur → Diagnostics et confidentialité → Recherche sémantique avant d’indexer. Les symboles obtiennent un vecteur lorsque leur fichier est ingéré.

Notez aussi que toute recompilation du binaire du serveur réinstalle les dylibs de grammaires et modifie leur mtime, ce qui invalide chaque point de contrôle d’index et force un nouveau balayage complet de chaque copie de dépôt à l’exécution suivante. Il recalcule les empreintes, mais il n’extrait pas de nouveau les fichiers inchangés.

Types de symboles : function, method, class, field, enum, constructor, getter, setter, typedef, extension, mixin, variable.

Types d’arêtes : calls, imports, extends, implements, mixes in, references.

Les signatures de référence de ces outils se trouvent dans Outils MCP.