turbo-editors/turbo-rustpublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-rust.git
git clone ssh://git@rickub.com/turbo-editors/turbo-rust.git

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

📦 Turbo Rust 713ea5c · on main · k33g · 11h ago
acp.md · 239 lines · 16.0 KBmarkdown
Blame HistoryOpen raw

Agents et ACP

Turbo Rust est un client de l'Agent Client Protocol. 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.

Où se trouve le fichier

Chemin Lu Rôle
~/.config/turbo-rust/acp.toml en premier Les agents que vous voulez dans tous les projets
<projet>/.turbo-rust/acp.toml en second Les agents propres à ce projet

Les 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. 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.

TURBO_RUST_DIR remplace le dossier où le fichier utilisateur est cherché. Le fichier du projet est toujours .turbo-rust/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 ne remontent pas.

Format du fichier

Un bloc [[agent]] par agent, dans l'ordre souhaité dans le menu.

[[agent]]
name    = "Bob (llama.cpp)"
command = "docker"
args    = ["agent", "serve", "acp", ".turbo-rust/agent.yaml"]
env     = { TELEMETRY_ENABLED = "false" }
cwd     = "."
Clé Type Requise Signification
name chaîne oui Ce qu'affiche le menu Agent et le titre de la fenêtre. Doit être unique dans l'ensemble fusionné.
command chaîne oui L'exécutable à lancer. Cherché dans PATH sauf s'il contient un séparateur.
args liste de chaînes non Ses arguments, passés tels quels — pas de shell, donc ni guillemets, ni jokers, ni &&.
env table de chaînes non Variables d'environnement ajoutées à celles de l'éditeur. Un nom donné ici l'emporte.
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.

env peut aussi s'écrire en sous-table, ce qui est la même chose :

[[agent]]
name    = "Bob (llama.cpp)"
command = "docker"
args    = ["agent", "serve", "acp", ".turbo-rust/agent.yaml"]

[agent.env]
TELEMETRY_ENABLED = "false"

Ce qui est refusé

Le 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.

Problème Message
un agent sans name reading …/acp.toml: agent 1 has no name
un agent sans command reading …/acp.toml: agent "Bob" has no command
deux agents portant le même name reading …/acp.toml: two agents are called "Bob"
une clé que le format ne définit pas reading …/acp.toml: agent.comand is not a key this file has

Le dernier cas est voulu : une clé mal orthographiée silencieusement ignorée ressemblerait exactement à une clé sans effet.

Le menu Agent

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.

Entrée Active quand Effet
une entrée par agent, par son nom toujours Démarrer cet agent et ouvrir une fenêtre dessus
Create agents file pas d'acp.toml dans le projet Écrire le fichier de départ et l'ouvrir
Cancel turn un tour est en cours dans la fenêtre de devant session/cancel
Agent status toujours Ce qui a été chargé, la ligne de commande de chacun, et ce qui a échoué

Touches dans une fenêtre agent

Une fenêtre agent est une fenêtre ordinaire : F6, Alt-1Alt-9, Tile, Maximise, [x] et [■] y fonctionnent tous. À l'intérieur :

Touche Effet
Entrée Envoyer la zone de saisie comme invite
Alt-Entrée Insérer un saut de ligne dans la zone de saisie
Tab Déplacer le focus entre la conversation et la zone de saisie
Ctrl-C, Ctrl-Ins Copier la sélection, ou le bloc sur lequel est le curseur
Échap Abandonner la sélection ; s'il n'y en a pas, annuler le tour en cours
Ctrl-W Fermer la fenêtre et arrêter l'agent

Avec la zone de saisie au premier plan :

Touche Effet
Début Fin Déplacer le curseur dans ce que vous tapez
Retour arrière Suppr L'éditer ; le retour arrière en début de ligne la joint à celle du dessus
/ en premier caractère Ouvrir la liste des commandes de l'agent — voir Commandes et mentions
@ Ouvrir la liste des fichiers du projet, réduite par ce que vous tapez ensuite
PgUp PgDn, liste ouverte Se déplacer dans la liste
Tab, liste ouverte Prendre l'entrée en surbrillance
Entrée, liste ouverte Prendre l'entrée en surbrillance ; sur un mot déjà complet, envoyer
Échap, liste ouverte Fermer la liste jusqu'à ce que le texte change

Avec la conversation au premier plan :

Touche Effet
Déplacer le curseur d'une ligne
PgUp PgDn Le déplacer d'un écran
Début Fin Le début de la conversation, et la fin
Shift- l'une d'elles Étendre la sélection à la place
Glisser avec le bouton 1 Sélectionner à la main
Molette Défiler de trois lignes sans bouger le curseur

Contrairement à 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.

Commandes et mentions

Deux 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.

/ — les commandes de l'agent

Un 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.

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.

Sur 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.

Sans commande annoncée, / est un caractère et Tab garde son sens habituel. Agent ▸ Agent status liste les commandes avec leur description.

@ — un fichier du projet

Taper @ 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.

À 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 :

L'agent a déclaré Le bloc envoyé
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é
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

Les 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.

Un 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.

La 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.

La copie

La 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é.

Sans 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.

L'indentation d'affichage de la conversation est retirée, donc le code collé arrive collé à la marge.

Le texte part à deux endroits à la fois :

Presse-papiers Comment Collé avec
Celui de l'éditeur directement Shift-Ins, dans un fichier ouvert ici
Celui du système OSC 52, à travers le terminal Ctrl-V, n'importe où ailleurs

Rien 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.

Quelle part du protocole est implémentée

Version de protocole 1. Turbo Rust annonce sa version dans initialize et accepte la version que l'agent répond, pourvu qu'il la connaisse.

Ce que l'éditeur appelle sur l'agent

Méthode Implémentée Remarques
initialize oui Annonce la capacité fs ci-dessous ; terminal n'est pas annoncée
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
session/prompt oui Des blocs texte, et un bloc resource ou resource_link par fichier désigné par @ — voir Commandes et mentions
session/cancel oui Échap, et Agent ▸ Cancel turn
session/load non Les conversations ne survivent pas à la fermeture de la fenêtre
authenticate non Un agent qui liste des authMethods est signalé comme exigeant une connexion que l'éditeur ne sait pas faire

Ce que l'agent peut appeler sur l'éditeur

Méthode Implémentée Remarques
session/update oui Voir la table ci-dessous
session/request_permission oui Une boîte modale portant les options de l'agent lui-même
fs/read_text_file oui Depuis le tampon quand le fichier est ouvert et modifié, sinon depuis le disque
fs/write_text_file oui Dans le tampon quand le fichier est ouvert, sinon sur le disque
terminal/* non Non annoncée, donc un agent conforme ne la demandera pas

Mises à jour de session

sessionUpdate Affiché comme
agent_message_chunk La réponse de l'agent, ajoutée au fil de son arrivée
agent_thought_chunk La même chose, dans la couleur des commentaires, sous une étiquette réflexion
user_message_chunk Votre propre message, tel que l'agent le renvoie
tool_call Une ligne nommant l'outil et son titre, avec son état
tool_call_update Repliée sur la ligne dont le toolCallId correspond, avec sa sortie
plan Les entrées en liste, chacune avec son état
available_commands_update La liste que / ouvre dans la zone de saisie ; aussi listée, avec les descriptions, par Agent ▸ Agent status
usage_update Le compte de jetons dans la barre d'état quand la fenêtre est devant
tout le reste Ignoré, et compté ; le compte figure dans Agent status

Pendant 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.

Une 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.

Coloration

La 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é :

Élément Classe
Le nom d'un interlocuteur syntax.keyword
Une réflexion syntax.comment
Un appel d'outil et son état syntax.type
Un appel d'outil en échec, et les avis de l'éditeur diagnostic.error
Une ligne sélectionnée, et la barre du curseur editor.selection
Le code dans un bloc délimité l'analyseur du langage annoncé
Tout le reste le texte ordinaire de la fenêtre

Un bloc délimité annonçant un langage que l'éditeur colore — rust, toml, yaml, markdown, javascript, html, xml, dockerfile, bash — est coloré par cet analyseur. Un bloc annonçant autre chose, ou rien, est laissé brut.

Tracer la conversation avec un agent

Variable Effet
TURBO_ACP_TRACE=<fichier> Ajouter à ce fichier chaque message vers et depuis chaque agent, un par ligne, horodaté et marqué -> (envoyé) ou <- (reçu)

C'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.

Limites

  • Une session par fenêtre. Fermer la fenêtre termine la session ; il n'y a pas de reprise.
  • 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.
  • Pas d'authentification. Un agent exigeant une connexion doit être connecté par sa propre CLI avant que l'éditeur ne le lance.
  • args n'est pas une commande shell. command = "sh", args = ["-c", "…"] est la façon délibérée d'en obtenir une.
  • 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.

Voir aussi

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# Agents et ACP

Turbo Rust 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.

## Où se trouve le fichier

| Chemin | Lu | Rôle |
| --- | --- | --- |
| `~/.config/turbo-rust/acp.toml` | en premier | Les agents que vous voulez dans tous les projets |
| `<projet>/.turbo-rust/acp.toml` | en second | Les agents propres à ce projet |

Les 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.

`TURBO_RUST_DIR` remplace le dossier où le fichier utilisateur est cherché. Le fichier du projet est toujours `.turbo-rust/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.

## Format du fichier

Un bloc `[[agent]]` par agent, dans l'ordre souhaité dans le menu.

```toml
[[agent]]
name    = "Bob (llama.cpp)"
command = "docker"
args    = ["agent", "serve", "acp", ".turbo-rust/agent.yaml"]
env     = { TELEMETRY_ENABLED = "false" }
cwd     = "."
```

| Clé | Type | Requise | Signification |
| --- | --- | --- | --- |
| `name` | chaîne | **oui** | Ce qu'affiche le menu Agent et le titre de la fenêtre. Doit être unique dans l'ensemble fusionné. |
| `command` | chaîne | **oui** | L'exécutable à lancer. Cherché dans `PATH` sauf s'il contient un séparateur. |
| `args` | liste de chaînes | non | Ses arguments, passés tels quels — pas de shell, donc ni guillemets, ni jokers, ni `&&`. |
| `env` | table de chaînes | non | Variables d'environnement ajoutées à celles de l'éditeur. Un nom donné ici l'emporte. |
| `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. |

`env` peut aussi s'écrire en sous-table, ce qui est la même chose :

```toml
[[agent]]
name    = "Bob (llama.cpp)"
command = "docker"
args    = ["agent", "serve", "acp", ".turbo-rust/agent.yaml"]

[agent.env]
TELEMETRY_ENABLED = "false"
```

### Ce qui est refusé

Le 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.

| Problème | Message |
| --- | --- |
| un agent sans `name` | `reading …/acp.toml: agent 1 has no name` |
| un agent sans `command` | `reading …/acp.toml: agent "Bob" has no command` |
| deux agents portant le même `name` | `reading …/acp.toml: two agents are called "Bob"` |
| une clé que le format ne définit pas | `reading …/acp.toml: agent.comand is not a key this file has` |

Le dernier cas est voulu : une clé mal orthographiée silencieusement ignorée ressemblerait exactement à une clé sans effet.

## Le menu Agent

`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.

| Entrée | Active quand | Effet |
| --- | --- | --- |
| *une entrée par agent, par son nom* | toujours | Démarrer cet agent et ouvrir une fenêtre dessus |
| **Create agents file** | pas d'`acp.toml` dans le projet | Écrire le fichier de départ et l'ouvrir |
| **Cancel turn** | un tour est en cours dans la fenêtre de devant | `session/cancel` |
| **Agent status** | toujours | Ce qui a été chargé, la ligne de commande de chacun, et ce qui a échoué |

## Touches dans une fenêtre agent

Une fenêtre agent est une fenêtre ordinaire : `F6`, `Alt-1``Alt-9`, Tile, Maximise, `[x]` et `[■]` y fonctionnent tous. À l'intérieur :

| Touche | Effet |
| --- | --- |
| `Entrée` | Envoyer la zone de saisie comme invite |
| `Alt-Entrée` | Insérer un saut de ligne dans la zone de saisie |
| `Tab` | Déplacer le focus entre la conversation et la zone de saisie |
| `Ctrl-C`, `Ctrl-Ins` | Copier la sélection, ou le bloc sur lequel est le curseur |
| `Échap` | Abandonner la sélection ; s'il n'y en a pas, annuler le tour en cours |
| `Ctrl-W` | Fermer la fenêtre et arrêter l'agent |

Avec la **zone de saisie** au premier plan :

| Touche | Effet |
| --- | --- |
| `↑` `↓` `←` `→` `Début` `Fin` | Déplacer le curseur dans ce que vous tapez |
| `Retour arrière` `Suppr` | L'éditer ; le retour arrière en début de ligne la joint à celle du dessus |
| `/` en premier caractère | Ouvrir la liste des commandes de l'agent — voir [Commandes et mentions](#commandes-et-mentions) |
| `@` | Ouvrir la liste des fichiers du projet, réduite par ce que vous tapez ensuite |
| `↑` `↓` `PgUp` `PgDn`, liste ouverte | Se déplacer dans la liste |
| `Tab`, liste ouverte | Prendre l'entrée en surbrillance |
| `Entrée`, liste ouverte | Prendre l'entrée en surbrillance ; sur un mot déjà complet, envoyer |
| `Échap`, liste ouverte | Fermer la liste jusqu'à ce que le texte change |

Avec la **conversation** au premier plan :

| Touche | Effet |
| --- | --- |
| `↑` `↓` | Déplacer le curseur d'une ligne |
| `PgUp` `PgDn` | Le déplacer d'un écran |
| `Début` `Fin` | Le début de la conversation, et la fin |
| `Shift-` l'une d'elles | Étendre la sélection à la place |
| Glisser avec le bouton 1 | Sélectionner à la main |
| Molette | Défiler de trois lignes sans bouger le curseur |

Contrairement à 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.

## Commandes et mentions

Deux 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.

### `/` — les commandes de l'agent

Un 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.

`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.

Sur 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.

Sans commande annoncée, `/` est un caractère et `Tab` garde son sens habituel. **Agent ▸ Agent status** liste les commandes avec leur description.

### `@` — un fichier du projet

Taper `@` 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.

À 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** :

| L'agent a déclaré | Le bloc envoyé |
| --- | --- |
| `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é |
| 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 |

Les 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.

Un 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.

La 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.

## La copie

La 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é.

Sans 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.

L'indentation d'affichage de la conversation est retirée, donc le code collé arrive collé à la marge.

Le texte part à deux endroits à la fois :

| Presse-papiers | Comment | Collé avec |
| --- | --- | --- |
| Celui de l'éditeur | directement | `Shift-Ins`, dans un fichier ouvert ici |
| Celui du système | OSC 52, à travers le terminal | `Ctrl-V`, n'importe où ailleurs |

Rien 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.

## Quelle part du protocole est implémentée

Version de protocole **1**. Turbo Rust annonce sa version dans `initialize` et accepte la version que l'agent répond, pourvu qu'il la connaisse.

### Ce que l'éditeur appelle sur l'agent

| Méthode | Implémentée | Remarques |
| --- | --- | --- |
| `initialize` | oui | Annonce la capacité `fs` ci-dessous ; `terminal` n'est pas annoncée |
| `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 |
| `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) |
| `session/cancel` | oui | `Échap`, et **Agent ▸ Cancel turn** |
| `session/load` | **non** | Les conversations ne survivent pas à la fermeture de la fenêtre |
| `authenticate` | **non** | Un agent qui liste des `authMethods` est signalé comme exigeant une connexion que l'éditeur ne sait pas faire |

### Ce que l'agent peut appeler sur l'éditeur

| Méthode | Implémentée | Remarques |
| --- | --- | --- |
| `session/update` | oui | Voir la table ci-dessous |
| `session/request_permission` | oui | Une boîte modale portant les options de l'agent lui-même |
| `fs/read_text_file` | oui | Depuis le tampon quand le fichier est ouvert et modifié, sinon depuis le disque |
| `fs/write_text_file` | oui | Dans le tampon quand le fichier est ouvert, sinon sur le disque |
| `terminal/*` | **non** | Non annoncée, donc un agent conforme ne la demandera pas |

### Mises à jour de session

| `sessionUpdate` | Affiché comme |
| --- | --- |
| `agent_message_chunk` | La réponse de l'agent, ajoutée au fil de son arrivée |
| `agent_thought_chunk` | La même chose, dans la couleur des commentaires, sous une étiquette *réflexion* |
| `user_message_chunk` | Votre propre message, tel que l'agent le renvoie |
| `tool_call` | Une ligne nommant l'outil et son titre, avec son état |
| `tool_call_update` | Repliée sur la ligne dont le `toolCallId` correspond, avec sa sortie |
| `plan` | Les entrées en liste, chacune avec son état |
| `available_commands_update` | La liste que `/` ouvre dans la zone de saisie ; aussi listée, avec les descriptions, par **Agent ▸ Agent status** |
| `usage_update` | Le compte de jetons dans la barre d'état quand la fenêtre est devant |
| tout le reste | Ignoré, et compté ; le compte figure dans **Agent status** |

Pendant 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.

Une 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.

## Coloration

La 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é :

| Élément | Classe |
| --- | --- |
| Le nom d'un interlocuteur | `syntax.keyword` |
| Une réflexion | `syntax.comment` |
| Un appel d'outil et son état | `syntax.type` |
| Un appel d'outil en échec, et les avis de l'éditeur | `diagnostic.error` |
| Une ligne sélectionnée, et la barre du curseur | `editor.selection` |
| Le code dans un bloc délimité | l'analyseur du langage annoncé |
| Tout le reste | le texte ordinaire de la fenêtre |

Un bloc délimité annonçant un langage que l'éditeur colore — `rust`, `toml`, `yaml`, `markdown`, `javascript`, `html`, `xml`, `dockerfile`, `bash` — est coloré par cet analyseur. Un bloc annonçant autre chose, ou rien, est laissé brut.

## Tracer la conversation avec un agent

| Variable | Effet |
| --- | --- |
| `TURBO_ACP_TRACE=<fichier>` | Ajouter à ce fichier chaque message vers et depuis chaque agent, un par ligne, horodaté et marqué `->` (envoyé) ou `<-` (reçu) |

C'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.

## Limites

- **Une session par fenêtre.** Fermer la fenêtre termine la session ; il n'y a pas de reprise.
- **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.
- **Pas d'authentification.** Un agent exigeant une connexion doit être connecté par sa propre CLI avant que l'éditeur ne le lance.
- **`args` n'est pas une commande shell.** `command = "sh"`, `args = ["-c", "…"]` est la façon délibérée d'en obtenir une.
- **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.

## Voir aussi

- La tâche : [Dialoguer avec un agent de code depuis l'éditeur](../how-to/talk-to-an-agent.md)
- Le raisonnement : [Fenêtres agent](../explanation/agent-windows.md)
- Le protocole : [agentclientprotocol.com](https://agentclientprotocol.com)