turbo-editors/turbo-pythonpublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-python.git
git clone ssh://git@rickub.com/turbo-editors/turbo-python.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

acp.md · 239 lines · 16.0 KBmarkdown Blame HistoryRaw
📦 Turbo Python 6fc62ea k33g 12h ago1# Agents et ACP
2
3Turbo Python est un client de l'[Agent Client Protocol](https://agentclientprotocol.com). Il lance chaque agent comme processus fils et échange avec lui des messages JSON-RPC 2.0 sur son entrée et sa sortie standard, à raison d'un message par ligne.
4
5## Où se trouve le fichier
6
7| Chemin | Lu | Rôle |
8| --- | --- | --- |
9| `~/.config/turbo-python/acp.toml` | en premier | Les agents que vous voulez dans tous les projets |
10| `<projet>/.turbo-python/acp.toml` | en second | Les agents propres à ce projet |
11
12Les deux sont facultatifs. Quand un `name` d'agent apparaît dans les deux, celui du projet remplace celui de l'utilisateur, étant l'énoncé le plus spécifique — la règle que suivent déjà les [snippets](snippets.md). Un fichier absent n'est pas une erreur ; un fichier présent mais illisible en est une, signalée sous **Agent ▸ Agent status** plutôt que de laisser silencieusement le menu vide.
13
14`TURBO_PYTHON_DIR` remplace le dossier où le fichier utilisateur est cherché. Le fichier du projet est toujours `.turbo-python/acp.toml` sous le dossier depuis lequel l'éditeur a été lancé — il n'y a pas de remontée dans l'arborescence, pour la même raison que les [réglages de projet](project-settings.md) ne remontent pas.
15
16## Format du fichier
17
18Un bloc `[[agent]]` par agent, dans l'ordre souhaité dans le menu.
19
20```toml
21[[agent]]
22name = "Bob (llama.cpp)"
23command = "docker"
24args = ["agent", "serve", "acp", ".turbo-python/agent.yaml"]
25env = { TELEMETRY_ENABLED = "false" }
26cwd = "."
27```
28
29| Clé | Type | Requise | Signification |
30| --- | --- | --- | --- |
31| `name` | chaîne | **oui** | Ce qu'affiche le menu Agent et le titre de la fenêtre. Doit être unique dans l'ensemble fusionné. |
32| `command` | chaîne | **oui** | L'exécutable à lancer. Cherché dans `PATH` sauf s'il contient un séparateur. |
33| `args` | liste de chaînes | non | Ses arguments, passés tels quels — pas de shell, donc ni guillemets, ni jokers, ni `&&`. |
34| `env` | table de chaînes | non | Variables d'environnement ajoutées à celles de l'éditeur. Un nom donné ici l'emporte. |
35| `cwd` | chaîne | non | Où le processus démarre, et le `cwd` annoncé à l'agent. Relatif à la racine du projet. Par défaut, la racine du projet. |
36
37`env` peut aussi s'écrire en sous-table, ce qui est la même chose :
38
39```toml
40[[agent]]
41name = "Bob (llama.cpp)"
42command = "docker"
43args = ["agent", "serve", "acp", ".turbo-python/agent.yaml"]
44
45[agent.env]
46TELEMETRY_ENABLED = "false"
47```
48
49### Ce qui est refusé
50
51Le fichier est refusé dans son ensemble, plutôt que chargé à moitié, dès que l'un de ces cas se présente. Un menu à moitié chargé proposant trois de vos cinq agents est pire qu'une erreur qui dit pourquoi.
52
53| Problème | Message |
54| --- | --- |
55| un agent sans `name` | `reading …/acp.toml: agent 1 has no name` |
56| un agent sans `command` | `reading …/acp.toml: agent "Bob" has no command` |
57| deux agents portant le même `name` | `reading …/acp.toml: two agents are called "Bob"` |
58| une clé que le format ne définit pas | `reading …/acp.toml: agent.comand is not a key this file has` |
59
60Le dernier cas est voulu : une clé mal orthographiée silencieusement ignorée ressemblerait exactement à une clé sans effet.
61
62## Le menu Agent
63
64`Alt-A` l'ouvre. Il est sur la barre qu'un agent soit configuré ou non, parce que c'est de là que **Create agents file** doit être atteignable.
65
66| Entrée | Active quand | Effet |
67| --- | --- | --- |
68| *une entrée par agent, par son nom* | toujours | Démarrer cet agent et ouvrir une fenêtre dessus |
69| **Create agents file** | pas d'`acp.toml` dans le projet | Écrire le fichier de départ et l'ouvrir |
70| **Cancel turn** | un tour est en cours dans la fenêtre de devant | `session/cancel` |
71| **Agent status** | toujours | Ce qui a été chargé, la ligne de commande de chacun, et ce qui a échoué |
72
73## Touches dans une fenêtre agent
74
75Une fenêtre agent est une fenêtre ordinaire : `F6`, `Alt-1``Alt-9`, Tile, Maximise, `[x]` et `[■]` y fonctionnent tous. À l'intérieur :
76
77| Touche | Effet |
78| --- | --- |
79| `Entrée` | Envoyer la zone de saisie comme invite |
80| `Alt-Entrée` | Insérer un saut de ligne dans la zone de saisie |
81| `Tab` | Déplacer le focus entre la conversation et la zone de saisie |
82| `Ctrl-C`, `Ctrl-Ins` | Copier la sélection, ou le bloc sur lequel est le curseur |
83| `Échap` | Abandonner la sélection ; s'il n'y en a pas, annuler le tour en cours |
84| `Ctrl-W` | Fermer la fenêtre et arrêter l'agent |
85
86Avec la **zone de saisie** au premier plan :
87
88| Touche | Effet |
89| --- | --- |
90| `↑` `↓` `←` `→` `Début` `Fin` | Déplacer le curseur dans ce que vous tapez |
91| `Retour arrière` `Suppr` | L'éditer ; le retour arrière en début de ligne la joint à celle du dessus |
92| `/` en premier caractère | Ouvrir la liste des commandes de l'agent — voir [Commandes et mentions](#commandes-et-mentions) |
93| `@` | Ouvrir la liste des fichiers du projet, réduite par ce que vous tapez ensuite |
94| `↑` `↓` `PgUp` `PgDn`, liste ouverte | Se déplacer dans la liste |
95| `Tab`, liste ouverte | Prendre l'entrée en surbrillance |
96| `Entrée`, liste ouverte | Prendre l'entrée en surbrillance ; sur un mot déjà complet, envoyer |
97| `Échap`, liste ouverte | Fermer la liste jusqu'à ce que le texte change |
98
99Avec la **conversation** au premier plan :
100
101| Touche | Effet |
102| --- | --- |
103| `↑` `↓` | Déplacer le curseur d'une ligne |
104| `PgUp` `PgDn` | Le déplacer d'un écran |
105| `Début` `Fin` | Le début de la conversation, et la fin |
106| `Shift-` l'une d'elles | Étendre la sélection à la place |
107| Glisser avec le bouton 1 | Sélectionner à la main |
108| Molette | Défiler de trois lignes sans bouger le curseur |
109
110Contrairement à une fenêtre terminal, une fenêtre agent ne **prend pas** les raccourcis de l'éditeur : il n'y a pas de shell qui ait besoin de `Ctrl-F`, donc cette touche garde son sens habituel. `Ctrl-C` fait exception, et seulement parce que rien d'autre n'en veut dans une fenêtre agent.
111
112## Commandes et mentions
113
114Deux caractères ouvrent une liste par-dessus le bas de la conversation pendant que vous tapez. Ce sont les deux mêmes que Zed, si bien que la documentation d'un agent — « tapez `/web` pour chercher » — reste vraie ici.
115
116### `/` — les commandes de l'agent
117
118Un agent peut annoncer des commandes par `available_commands_update`, au début de la session ou à tout moment pendant celle-ci. Taper `/` comme **premier caractère** de la zone de saisie les liste : le nom, la description donnée par l'agent et, entre chevrons, ce qu'il attend après le nom quand il attend quelque chose. Continuez à taper pour réduire la liste ; la correspondance porte sur le début du nom et ignore la casse.
119
120`Tab` complète la commande en surbrillance. Une commande qui prend une entrée est complétée avec une espace à la fin, pour que la suite de votre frappe soit son argument ; une qui n'en prend pas est complétée au nom seul. `Entrée` complète aussi, sauf sur un mot qui se lit déjà exactement comme une commande, où elle envoie.
121
122Sur le fil, une commande est du **texte** : `/web agent client protocol` part comme un seul bloc texte, et l'agent la reconnaît à son premier mot. C'est tout le protocole des commandes, et c'est pourquoi un `/` ailleurs qu'au début de la zone n'est qu'un caractère.
123
124Sans commande annoncée, `/` est un caractère et `Tab` garde son sens habituel. **Agent ▸ Agent status** liste les commandes avec leur description.
125
126### `@` — un fichier du projet
127
128Taper `@` n'importe où dans la zone liste les fichiers du projet, relatifs à sa racine, avec des barres obliques. Ce que vous tapez après le `@` réduit la liste : les fichiers dont le nom propre commence par cela viennent d'abord, puis ceux dont le chemin le contient seulement. `Tab` ou `Entrée` complète celui en surbrillance et ajoute une espace.
129
130À l'envoi de l'invite, chaque `@nom` qui désigne un fichier connu de la liste devient un bloc de contenu **à la place du nom** :
131
132| L'agent a déclaré | Le bloc envoyé |
133| --- | --- |
134| `promptCapabilities.embeddedContext: true` | `resource` — l'`uri` du fichier, son `mimeType` et son `text` entier, lu comme `fs/read_text_file` le lit : depuis le tampon ouvert quand le fichier est ouvert et modifié |
135| autre chose, ou le fichier n'a pas pu être lu | `resource_link` — l'`uri`, le `name` et le `mimeType`, pour que l'agent aille le chercher lui-même |
136
137Les mots de part et d'autre partent en blocs texte, si bien que `explique @docs/README.md s'il te plaît` fait trois blocs : `explique `, le fichier, ` s'il te plaît`. La conversation garde la ligne telle que vous l'avez tapée.
138
139Un mot qui commence par `@` et ne désigne aucun fichier reste du texte — une adresse électronique dans une invite n'est pas un fichier — et `@main.go` ne désigne pas `main.gopher` : le nom doit terminer le mot.
140
141La liste est le projet parcouru depuis sa racine, `.git` exclu, au plus 5 000 fichiers, et au plus 200 d'entre eux affichés à la fois. Au-delà de l'une ou l'autre limite, tapez une lettre de plus. Le parcours est refait à chaque ouverture de la liste par `@`, si bien qu'un fichier que l'agent vient de créer y figure.
142
143## La copie
144
145La sélection porte sur des **lignes entières**. Rien ne s'édite dans une conversation, donc une demi-ligne n'est jamais ce qu'on veut dire, et des lignes entières préservent l'indentation d'un bloc de code copié.
146
147Sans rien de sélectionné, la copie prend la **région sur laquelle est le curseur** : un bloc de code délimité, un passage de prose, la sortie d'un appel d'outil. Le libellé d'un interlocuteur et l'en-tête d'un appel d'outil sont du mobilier et forment des régions à part : ni l'un ni l'autre n'est jamais copié avec ce qu'il surmonte.
148
149L'indentation d'affichage de la conversation est retirée, donc le code collé arrive collé à la marge.
150
151Le texte part à deux endroits à la fois :
152
153| Presse-papiers | Comment | Collé avec |
154| --- | --- | --- |
155| Celui de l'éditeur | directement | `Shift-Ins`, dans un fichier ouvert ici |
156| Celui du système | OSC 52, à travers le terminal | `Ctrl-V`, n'importe où ailleurs |
157
158Rien ne vérifie que le terminal a accepté le second : il n'y a pas de réponse à vérifier, et un terminal peut refuser OSC 52 par sécurité ou demander qu'on l'active. Le presse-papiers de l'éditeur contient le texte dans tous les cas, et la barre d'état dit combien de lignes ont été copiées.
159
160## Quelle part du protocole est implémentée
161
162Version de protocole **1**. Turbo Python annonce sa version dans `initialize` et accepte la version que l'agent répond, pourvu qu'il la connaisse.
163
164### Ce que l'éditeur appelle sur l'agent
165
166| Méthode | Implémentée | Remarques |
167| --- | --- | --- |
168| `initialize` | oui | Annonce la capacité `fs` ci-dessous ; `terminal` n'est pas annoncée |
169| `session/new` | oui | `cwd` vient de la clé `cwd` de l'agent ; `mcpServers` est toujours vide — les serveurs MCP sont l'affaire de l'agent |
170| `session/prompt` | oui | Des blocs texte, et un bloc `resource` ou `resource_link` par fichier désigné par `@` — voir [Commandes et mentions](#commandes-et-mentions) |
171| `session/cancel` | oui | `Échap`, et **Agent ▸ Cancel turn** |
172| `session/load` | **non** | Les conversations ne survivent pas à la fermeture de la fenêtre |
173| `authenticate` | **non** | Un agent qui liste des `authMethods` est signalé comme exigeant une connexion que l'éditeur ne sait pas faire |
174
175### Ce que l'agent peut appeler sur l'éditeur
176
177| Méthode | Implémentée | Remarques |
178| --- | --- | --- |
179| `session/update` | oui | Voir la table ci-dessous |
180| `session/request_permission` | oui | Une boîte modale portant les options de l'agent lui-même |
181| `fs/read_text_file` | oui | Depuis le tampon quand le fichier est ouvert et modifié, sinon depuis le disque |
182| `fs/write_text_file` | oui | Dans le tampon quand le fichier est ouvert, sinon sur le disque |
183| `terminal/*` | **non** | Non annoncée, donc un agent conforme ne la demandera pas |
184
185### Mises à jour de session
186
187| `sessionUpdate` | Affiché comme |
188| --- | --- |
189| `agent_message_chunk` | La réponse de l'agent, ajoutée au fil de son arrivée |
190| `agent_thought_chunk` | La même chose, dans la couleur des commentaires, sous une étiquette *réflexion* |
191| `user_message_chunk` | Votre propre message, tel que l'agent le renvoie |
192| `tool_call` | Une ligne nommant l'outil et son titre, avec son état |
193| `tool_call_update` | Repliée sur la ligne dont le `toolCallId` correspond, avec sa sortie |
194| `plan` | Les entrées en liste, chacune avec son état |
195| `available_commands_update` | La liste que `/` ouvre dans la zone de saisie ; aussi listée, avec les descriptions, par **Agent ▸ Agent status** |
196| `usage_update` | Le compte de jetons dans la barre d'état quand la fenêtre est devant |
197| tout le reste | Ignoré, et compté ; le compte figure dans **Agent status** |
198
199Pendant qu'un tour est en cours, la règle entre les deux zones fait tourner un indicateur. Il est dessiné à partir de l'horloge et non d'un compteur, donc deux fenêtres qui réfléchissent en même temps tournent en phase et rien n'a besoin d'être remis à zéro au début d'un tour. Le *titre* de la fenêtre, lui, n'est délibérément pas animé : c'est aussi ce qu'affichent la liste des fenêtres et le menu `Alt`-chiffre, et un nom qui change huit fois par seconde les fait scintiller tous les deux.
200
201Une mise à jour inconnue est ignorée plutôt que refusée : le protocole grandit, et un éditeur qui cesserait de parler à un agent parce que celui-ci a appris un nouveau type de message aurait tort plus souvent que raison.
202
203## Coloration
204
205La conversation est dessinée avec des clés que tous les thèmes définissent déjà, donc aucun n'a eu besoin d'être touché :
206
207| Élément | Classe |
208| --- | --- |
209| Le nom d'un interlocuteur | `syntax.keyword` |
210| Une réflexion | `syntax.comment` |
211| Un appel d'outil et son état | `syntax.type` |
212| Un appel d'outil en échec, et les avis de l'éditeur | `diagnostic.error` |
213| Une ligne sélectionnée, et la barre du curseur | `editor.selection` |
214| Le code dans un bloc délimité | l'analyseur du langage annoncé |
215| Tout le reste | le texte ordinaire de la fenêtre |
216
217Un bloc délimité annonçant un langage que l'éditeur colore — `python`, `toml`, `yaml`, `markdown`, `javascript`, `html`, `xml`, `dockerfile`, `bash` — est coloré par cet analyseur. Un bloc annonçant autre chose, ou rien, est laissé brut.
218
219## Tracer la conversation avec un agent
220
221| Variable | Effet |
222| --- | --- |
223| `TURBO_ACP_TRACE=<fichier>` | Ajouter à ce fichier chaque message vers et depuis chaque agent, un par ligne, horodaté et marqué `->` (envoyé) ou `<-` (reçu) |
224
225C'est pour la seule question à laquelle l'écran ne peut pas répondre — *qu'a réellement envoyé l'agent ?* Une mise à jour que cet éditeur ne sait pas décoder est comptée dans **Agent ▸ Agent status**, qui nomme aussi la dernière et son erreur ; la trace montre le message lui-même. Un fichier qui ne peut pas être ouvert veut dire pas de trace, et rien d'autre : la trace n'a jamais le droit de casser l'éditeur.
226
227## Limites
228
229- **Une session par fenêtre.** Fermer la fenêtre termine la session ; il n'y a pas de reprise.
230- **Texte et fichiers seulement.** L'éditeur envoie du texte, et les fichiers que vous désignez par `@` ; ni images ni audio, quoi que disent les `promptCapabilities` de l'agent.
231- **Pas d'authentification.** Un agent exigeant une connexion doit être connecté par sa propre CLI avant que l'éditeur ne le lance.
232- **`args` n'est pas une commande shell.** `command = "sh"`, `args = ["-c", "…"]` est la façon délibérée d'en obtenir une.
233- **Une entrée est plafonnée** à un mégaoctet de texte. Un agent qui déverse tout un journal de compilation ne peut pas rendre la fenêtre inutilisable ; ce qui a été perdu est signalé dans l'entrée elle-même.
234
235## Voir aussi
236
237- La tâche : [Dialoguer avec un agent de code depuis l'éditeur](../how-to/talk-to-an-agent.md)
238- Le raisonnement : [Fenêtres agent](../explanation/agent-windows.md)
239- Le protocole : [agentclientprotocol.com](https://agentclientprotocol.com)