bots-garden/mini-mepublic Fork
⑂ feature/lsp-builtin
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bots-garden/mini-me.git
git clone ssh://git@rickub.com/bots-garden/mini-me.git

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

Download ZIP
🛟 Updated. d511266 · on feature/lsp-builtin · k33g · Sep 18, 2026
tools.md · 147 lines · 12.0 KBmarkdown
Blame HistoryOpen raw

Référence : outils intégrés

Description neutre des outils déclarés au modèle. Un outil ne renvoie jamais d'erreur Go pour un échec ordinaire : le texte de l'échec est renvoyé au modèle comme sortie de l'outil. Chaque outil enregistre son appel dans le détecteur de boucle ; le même outil, la même entrée et la même sortie trois fois de suite ajoutent [LOOP_DETECTED: …] à la sortie.

bash

Déclaré quand bashTool: true (la valeur par défaut).

Champ Type Description
command chaîne La commande shell à exécuter.
Aspect Comportement
Shell bash -c <command>, un nouveau shell par appel, pas de stdin.
Répertoire de travail Le répertoire du processus en mode terminal ; le cwd de la session en mode ACP.
Délai 30 s ; la sortie se termine alors par [error: 30s timeout exceeded].
Sortie stdout et stderr fusionnés, tronqués à maxOutput caractères.
Code de sortie non nul La sortie se termine par [exit code: exit status N].
Affichage terminal 🛠️ bash: <command> avant exécution, puis jusqu'à previewLines lignes grisées et indentées, ou (no output).
ACP Appel d'outil de genre execute ; permission demandée avant exécution ; un refus renvoie [command rejected by the user] avec le statut failed.
Mode fenêtre Une ligne ‣ bash <commande> avec statut, durée et sortie repliée. Avec permissions: ask, attend a/s/r ; un refus renvoie le même texte qu'en ACP.

read_skill

Déclaré seulement quand skillsDir contient au moins un skill (<nom>.md ou <nom>/SKILL.md).

Champ Type Description
name chaîne Nom du skill, exactement tel que listé dans la description de l'outil.
Aspect Comportement
Description Phrase fixe suivie du catalogue : une ligne <name> — <description> par skill, triées par nom.
Sortie Le markdown complet de <skillsDir>/<name>.md, ou de <skillsDir>/<name>/SKILL.md s'il n'y a pas de fichier à plat, tronqué à maxOutput.
Nom inconnu No skill named "x". Available skills: a, b, c
Sécurité des chemins Seul le nom de base de name est utilisé ; pas de traversée de répertoire.
Affichage terminal 📖 read_skill: <name> ; le contenu n'est pas affiché.
ACP Appel d'outil de genre read ; pas de dialogue de permission.

read_file

Déclaré quand editTools: true.

Champ Type Défaut Description
path chaîne — Chemin du fichier, relatif au répertoire de travail.
start entier 0 Première ligne (base 1) ; 0 = depuis le début.
end entier 0 Dernière ligne (base 1, incluse) ; 0 = jusqu'à la fin.
numbered booléen false Préfixe chaque ligne de son numéro.
Aspect Comportement
Fichier absent <path> does not exist. Create it with write_file
Sortie Les lignes, tronquées à maxOutput ; le saut de ligne final n'est conservé que si la fin du fichier est affichée.
ACP Genre read, avec le chemin absolu comme emplacement.

write_file

Déclaré quand editTools: true.

Champ Type Description
path chaîne Chemin du fichier, relatif au répertoire de travail ; les répertoires parents sont créés.
content chaîne Le contenu entier du fichier.
Aspect Comportement
Fichier existant Entièrement remplacé.
Contenu identique Rien n'est écrit ; le résultat le dit.
Sortie Un en-tête d'une ligne et le diff par rapport au contenu précédent.
ACP Genre edit ; permission demandée ; le changement voyage comme un diff (diff de nouveau fichier à la création).

edit_file

Déclaré quand editTools: true.

Champ Type Défaut Description
path chaîne — Chemin d'un fichier existant.
edits tableau de {old, new} — Remplacements, tous résolus par rapport au fichier original.
edits[].old chaîne — Texte exact à trouver, présent exactement une fois.
edits[].new chaîne — Remplacement ; vide supprime le texte trouvé.
dry_run booléen false Rapporte ce qui changerait, n'écrit rien.
Règle Conséquence si violée
old apparaît exactement une fois Refusé : introuvable, ou ambigu — old text appears N times (lines 11, 20) — to change ONE of them, include its surrounding lines in old until the text is unique; to change several, send one edit per place….
Deux éditions ne doivent ni se chevaucher, ni s'imbriquer, ni se répéter Refus.
Les éditions sont résolues sur le texte original, jamais en cascade —
Toute édition refusée Rien n'est écrit.
Aspect Comportement
Sortie Un en-tête d'une ligne (éditions appliquées, lignes ajoutées et supprimées, première ligne modifiée) et le diff avec numéros de ligne.
ACP Genre edit ; permission demandée ; le changement voyage comme un diff avec ancien et nouveau texte.

lsp

Déclaré quand lsp.servers liste au moins un serveur dont la commande est sur le PATH au démarrage. Un serveur listé mais introuvable est ignoré avec un [warning: lsp server <nom> (<commande>) not found on the PATH — skipped] ; quand aucun n'est trouvé, l'outil n'est pas déclaré et la bannière le dit.

Champ Type Défaut Description
action chaîne — definition, references, hover, symbols, diagnostics ou rename.
path chaîne — Chemin du fichier, relatif au répertoire de travail. Son extension choisit le serveur.
symbol chaîne "" L'identifiant, tel qu'écrit dans le code. Guillemets et ponctuation parasites sont coupés, un préfixe receveur. ou pkg. est retiré (Greet', et person.Greet désignent tous deux Greet). Ses occurrences dans le fichier sont essayées dans l'ordre — lignes de code d'abord, lignes de commentaire en dernier — jusqu'à ce que le serveur réponde. Pour definition, references, hover, rename.
line entier 0 Ligne en base 1. Avec symbol : restreint la recherche à cette ligne. Avec column : la position exacte.
column entier 0 Colonne en base 1, en caractères, à l'intérieur de l'identifiant. Nécessaire seulement sans symbol.
new_name chaîne "" Le nouvel identifiant, pour rename. Nettoyé comme symbol. Quand il est vide et que symbol contient plusieurs mots (Greet 1 12 Hello — un petit modèle qui écrit symbole, ligne, colonne et nouveau nom dans une seule chaîne), le premier identifiant est le symbole et le dernier le nouveau nom.
Aspect Comportement
Description Nomme les serveurs et leurs extensions (Servers available: gopls (.go), …) et les six actions.
definition, references Une ligne chemin:ligne:colonne <ligne source> par emplacement, triée par chemin puis position, doublons retirés ; les chemins du projet sont relatifs, les autres absolus. references est préfixé de N reference(s): et inclut la déclaration.
hover Le texte du serveur tel qu'envoyé (signature, type, documentation ; Markdown pour la plupart des serveurs).
symbols Une ligne <sorte> <nom> [<détail>] line N par symbole, enfants indentés de deux espaces.
diagnostics Le fichier est synchronisé, puis l'appel attend jusqu'à 3 s la publication du serveur. N diagnostic(s) in <chemin>: puis une ligne <sévérité> chemin:ligne:colonne <message> [<source>] par constat ; no diagnostics: <chemin> is clean ; (as last published) quand le fichier n'a pas changé depuis la dernière publication ; no diagnostics received for <chemin> within 3s (…) quand le serveur n'a jamais publié.
rename Applique les modifications du serveur aux fichiers sur disque (positions UTF-16 converties), informe le serveur du nouveau contenu, et répond renamed to <nouveau>: N edit(s) in M file(s) suivi d'une ligne chemin: N edit(s) par fichier. Sans new_name : [lsp: rename needs new_name — call lsp again with {"action": "rename", "path": …, "symbol": …, "new_name": "<the new identifier>"}; do not use edit_file for a rename].
Positions Lignes et colonnes en base 1 à la frontière de l'outil, UTF-16 en base 0 sur le fil. Une position au-delà de la fin d'une ligne ou du fichier est refusée, avec le compte.
Synchronisation Avant chaque requête, le fichier est relu sur disque et envoyé en didOpen (première fois) ou en didChange complet (quand son contenu a bougé) : les modifications faites avec edit_file sont vues sans étape supplémentaire.
Cycle de vie du serveur Démarré au premier appel pour l'une de ses extensions, dans la racine du projet (le répertoire où mm tourne), gardé pour la session, arrêté (shutdown, exit, puis le processus) à la sortie de mm. Un serveur mort est relancé à l'appel suivant.
Échecs Toujours du texte, jamais une erreur Go : [lsp: no language server for "x.md" — configured: gopls (.go)], [lsp: "foo" not found in main.go], [lsp: column 40 is past the end of line 3 (15 characters)], [lsp: gopls: hover failed: …], [lsp: no definition found for the symbol at main.go:5:4].
Affichage terminal 🔎 lsp: definition main.go greet (ou …:9:14 avec une position, rename main.go greet → hello), puis la réponse affichée comme la sortie d'une commande.
ACP / fenêtre Sorte read pour la navigation, sans permission ; rename est de sorte edit et demande la permission comme edit_file ([rename rejected by the user] en cas de refus).
Compteur 🔎 N lsp call(s) dans la ligne de récapitulatif (voir plus bas).

Détection de boucle

Chaque outil enregistre (outil, entrée, sortie) dans le détecteur de boucle après chaque appel.

Situation Comportement
Le même triplet 3 fois de suite La sortie de l'outil reçoit [LOOP_DETECTED: You have attempted the same action multiple times with the same result. Please try a different approach or provide more information.] en annexe. Rien ne s'arrête.
3 appels identiques de plus (6 de suite) L'outil renvoie une erreur au lieu de texte et le tour se termine : [error: the model repeated the same edit_file call 6 times in a row with the same failing result — turn stopped by the loop detector; rephrase the request, or fix what the tool kept reporting]. L'historique garde tout ce qui a tourné ; l'erreur est enregistrée dans le tableau errors du fichier de session (where: generation).
Un appel différent Le compte repart. /new réinitialise le détecteur ; /compact non.
Un appel d'outil dont les arguments diffusés répètent un motif (les 256 derniers caractères sont un motif de 4 à 64 caractères répété) ou dépassent 256 Ko La génération est arrêtée aussitôt : [error: the model's tool call ran away: its arguments repeat the same pattern (N characters so far: …) — generation stopped; rephrase the request, or try another model]. Sans cela, un modèle qui déraille compose du charabia pendant des minutes pendant que l'écran affiche « Thinking » (le chien de garde est nourri par chaque fragment). Pendant qu'un appel d'outil est diffusé, le spinner dit Composing a tool call.

Les seuils (3, puis 3 de plus) sont fixés dans main.go ; maxTurns reste la borne extérieure d'un tour.

Compteurs affichés après un tour

Compteur Compte
⚙ N command(s) Réponses de l'outil bash dans le tour.
📝 N file op(s) Réponses de read_file, write_file, edit_file.
📖 N skill(s) Réponses de read_skill.
🔎 N lsp call(s) Réponses de lsp.
  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
# Référence : outils intégrés

> Description neutre des outils déclarés au modèle. Un outil ne renvoie jamais d'erreur Go pour un échec ordinaire : le texte de l'échec est renvoyé au modèle comme sortie de l'outil. Chaque outil enregistre son appel dans le détecteur de boucle ; le même outil, la même entrée et la même sortie trois fois de suite ajoutent `[LOOP_DETECTED: …]` à la sortie.

## `bash`

Déclaré quand `bashTool: true` (la valeur par défaut).

| Champ | Type | Description |
|-------|------|-------------|
| `command` | chaîne | La commande shell à exécuter. |

| Aspect | Comportement |
|--------|--------------|
| Shell | `bash -c <command>`, un nouveau shell par appel, pas de stdin. |
| Répertoire de travail | Le répertoire du processus en mode terminal ; le `cwd` de la session en mode ACP. |
| Délai | 30 s ; la sortie se termine alors par `[error: 30s timeout exceeded]`. |
| Sortie | stdout et stderr fusionnés, tronqués à `maxOutput` caractères. |
| Code de sortie non nul | La sortie se termine par `[exit code: exit status N]`. |
| Affichage terminal | `🛠️  bash: <command>` avant exécution, puis jusqu'à `previewLines` lignes grisées et indentées, ou `(no output)`. |
| ACP | Appel d'outil de genre `execute` ; permission demandée avant exécution ; un refus renvoie `[command rejected by the user]` avec le statut `failed`. |
| Mode fenêtre | Une ligne `‣ bash  <commande>` avec statut, durée et sortie repliée. Avec `permissions: ask`, attend `a`/`s`/`r` ; un refus renvoie le même texte qu'en ACP. |

## `read_skill`

Déclaré seulement quand `skillsDir` contient au moins un skill (`<nom>.md` ou `<nom>/SKILL.md`).

| Champ | Type | Description |
|-------|------|-------------|
| `name` | chaîne | Nom du skill, exactement tel que listé dans la description de l'outil. |

| Aspect | Comportement |
|--------|--------------|
| Description | Phrase fixe suivie du catalogue : une ligne `  <name> — <description>` par skill, triées par nom. |
| Sortie | Le markdown complet de `<skillsDir>/<name>.md`, ou de `<skillsDir>/<name>/SKILL.md` s'il n'y a pas de fichier à plat, tronqué à `maxOutput`. |
| Nom inconnu | `No skill named "x". Available skills: a, b, c` |
| Sécurité des chemins | Seul le nom de base de `name` est utilisé ; pas de traversée de répertoire. |
| Affichage terminal | `📖 read_skill: <name>` ; le contenu n'est pas affiché. |
| ACP | Appel d'outil de genre `read` ; pas de dialogue de permission. |

## `read_file`

Déclaré quand `editTools: true`.

| Champ | Type | Défaut | Description |
|-------|------|--------|-------------|
| `path` | chaîne | — | Chemin du fichier, relatif au répertoire de travail. |
| `start` | entier | `0` | Première ligne (base 1) ; `0` = depuis le début. |
| `end` | entier | `0` | Dernière ligne (base 1, incluse) ; `0` = jusqu'à la fin. |
| `numbered` | booléen | `false` | Préfixe chaque ligne de son numéro. |

| Aspect | Comportement |
|--------|--------------|
| Fichier absent | `<path> does not exist. Create it with write_file` |
| Sortie | Les lignes, tronquées à `maxOutput` ; le saut de ligne final n'est conservé que si la fin du fichier est affichée. |
| ACP | Genre `read`, avec le chemin absolu comme emplacement. |

## `write_file`

Déclaré quand `editTools: true`.

| Champ | Type | Description |
|-------|------|-------------|
| `path` | chaîne | Chemin du fichier, relatif au répertoire de travail ; les répertoires parents sont créés. |
| `content` | chaîne | Le contenu entier du fichier. |

| Aspect | Comportement |
|--------|--------------|
| Fichier existant | Entièrement remplacé. |
| Contenu identique | Rien n'est écrit ; le résultat le dit. |
| Sortie | Un en-tête d'une ligne et le diff par rapport au contenu précédent. |
| ACP | Genre `edit` ; permission demandée ; le changement voyage comme un diff (diff de nouveau fichier à la création). |

## `edit_file`

Déclaré quand `editTools: true`.

| Champ | Type | Défaut | Description |
|-------|------|--------|-------------|
| `path` | chaîne | — | Chemin d'un fichier existant. |
| `edits` | tableau de `{old, new}` | — | Remplacements, tous résolus par rapport au fichier original. |
| `edits[].old` | chaîne | — | Texte exact à trouver, présent exactement une fois. |
| `edits[].new` | chaîne | — | Remplacement ; vide supprime le texte trouvé. |
| `dry_run` | booléen | `false` | Rapporte ce qui changerait, n'écrit rien. |

| Règle | Conséquence si violée |
|-------|-----------------------|
| `old` apparaît exactement une fois | Refusé : introuvable, ou ambigu — `old text appears N times (lines 11, 20) — to change ONE of them, include its surrounding lines in old until the text is unique; to change several, send one edit per place…`. |
| Deux éditions ne doivent ni se chevaucher, ni s'imbriquer, ni se répéter | Refus. |
| Les éditions sont résolues sur le texte original, jamais en cascade | — |
| Toute édition refusée | Rien n'est écrit. |

| Aspect | Comportement |
|--------|--------------|
| Sortie | Un en-tête d'une ligne (éditions appliquées, lignes ajoutées et supprimées, première ligne modifiée) et le diff avec numéros de ligne. |
| ACP | Genre `edit` ; permission demandée ; le changement voyage comme un diff avec ancien et nouveau texte. |

## `lsp`

Déclaré quand `lsp.servers` liste au moins un serveur dont la commande est sur le `PATH` au démarrage. Un serveur listé mais introuvable est ignoré avec un `[warning: lsp server <nom> (<commande>) not found on the PATH — skipped]` ; quand aucun n'est trouvé, l'outil n'est pas déclaré et la bannière le dit.

| Champ | Type | Défaut | Description |
|-------|------|--------|-------------|
| `action` | chaîne | — | `definition`, `references`, `hover`, `symbols`, `diagnostics` ou `rename`. |
| `path` | chaîne | — | Chemin du fichier, relatif au répertoire de travail. Son extension choisit le serveur. |
| `symbol` | chaîne | `""` | L'identifiant, tel qu'écrit dans le code. Guillemets et ponctuation parasites sont coupés, un préfixe `receveur.` ou `pkg.` est retiré (`Greet', ` et `person.Greet` désignent tous deux `Greet`). Ses occurrences dans le fichier sont essayées dans l'ordre — lignes de code d'abord, lignes de commentaire en dernier — jusqu'à ce que le serveur réponde. Pour `definition`, `references`, `hover`, `rename`. |
| `line` | entier | `0` | Ligne en base 1. Avec `symbol` : restreint la recherche à cette ligne. Avec `column` : la position exacte. |
| `column` | entier | `0` | Colonne en base 1, en caractères, à l'intérieur de l'identifiant. Nécessaire seulement sans `symbol`. |
| `new_name` | chaîne | `""` | Le nouvel identifiant, pour `rename`. Nettoyé comme `symbol`. Quand il est vide et que `symbol` contient plusieurs mots (`Greet 1 12 Hello` — un petit modèle qui écrit symbole, ligne, colonne et nouveau nom dans une seule chaîne), le premier identifiant est le symbole et le dernier le nouveau nom. |

| Aspect | Comportement |
|--------|--------------|
| Description | Nomme les serveurs et leurs extensions (`Servers available: gopls (.go), …`) et les six actions. |
| `definition`, `references` | Une ligne `chemin:ligne:colonne  <ligne source>` par emplacement, triée par chemin puis position, doublons retirés ; les chemins du projet sont relatifs, les autres absolus. `references` est préfixé de `N reference(s):` et inclut la déclaration. |
| `hover` | Le texte du serveur tel qu'envoyé (signature, type, documentation ; Markdown pour la plupart des serveurs). |
| `symbols` | Une ligne `<sorte> <nom>  [<détail>]  line N` par symbole, enfants indentés de deux espaces. |
| `diagnostics` | Le fichier est synchronisé, puis l'appel attend jusqu'à 3 s la publication du serveur. `N diagnostic(s) in <chemin>:` puis une ligne `<sévérité> chemin:ligne:colonne <message> [<source>]` par constat ; `no diagnostics: <chemin> is clean` ; ` (as last published)` quand le fichier n'a pas changé depuis la dernière publication ; `no diagnostics received for <chemin> within 3s (…)` quand le serveur n'a jamais publié. |
| `rename` | Applique les modifications du serveur aux fichiers sur disque (positions UTF-16 converties), informe le serveur du nouveau contenu, et répond `renamed to <nouveau>: N edit(s) in M file(s)` suivi d'une ligne `chemin: N edit(s)` par fichier. Sans `new_name` : `[lsp: rename needs new_name — call lsp again with {"action": "rename", "path": …, "symbol": …, "new_name": "<the new identifier>"}; do not use edit_file for a rename]`. |
| Positions | Lignes et colonnes en base 1 à la frontière de l'outil, UTF-16 en base 0 sur le fil. Une position au-delà de la fin d'une ligne ou du fichier est refusée, avec le compte. |
| Synchronisation | Avant chaque requête, le fichier est relu sur disque et envoyé en `didOpen` (première fois) ou en `didChange` complet (quand son contenu a bougé) : les modifications faites avec `edit_file` sont vues sans étape supplémentaire. |
| Cycle de vie du serveur | Démarré au premier appel pour l'une de ses extensions, dans la racine du projet (le répertoire où `mm` tourne), gardé pour la session, arrêté (`shutdown`, `exit`, puis le processus) à la sortie de `mm`. Un serveur mort est relancé à l'appel suivant. |
| Échecs | Toujours du texte, jamais une erreur Go : `[lsp: no language server for "x.md" — configured: gopls (.go)]`, `[lsp: "foo" not found in main.go]`, `[lsp: column 40 is past the end of line 3 (15 characters)]`, `[lsp: gopls: hover failed: …]`, `[lsp: no definition found for the symbol at main.go:5:4]`. |
| Affichage terminal | `🔎 lsp: definition main.go greet` (ou `…:9:14` avec une position, `rename main.go greet → hello`), puis la réponse affichée comme la sortie d'une commande. |
| ACP / fenêtre | Sorte `read` pour la navigation, sans permission ; `rename` est de sorte `edit` et demande la permission comme `edit_file` (`[rename rejected by the user]` en cas de refus). |
| Compteur | `🔎 N lsp call(s)` dans la ligne de récapitulatif (voir plus bas). |

## Détection de boucle

Chaque outil enregistre `(outil, entrée, sortie)` dans le détecteur de boucle après chaque appel.

| Situation | Comportement |
|-----------|--------------|
| Le même triplet 3 fois de suite | La sortie de l'outil reçoit `[LOOP_DETECTED: You have attempted the same action multiple times with the same result. Please try a different approach or provide more information.]` en annexe. Rien ne s'arrête. |
| 3 appels identiques de plus (6 de suite) | L'outil renvoie une erreur au lieu de texte et le tour se termine : `[error: the model repeated the same edit_file call 6 times in a row with the same failing result — turn stopped by the loop detector; rephrase the request, or fix what the tool kept reporting]`. L'historique garde tout ce qui a tourné ; l'erreur est enregistrée dans le tableau `errors` du fichier de session (`where: generation`). |
| Un appel différent | Le compte repart. `/new` réinitialise le détecteur ; `/compact` non. |
| Un appel d'outil dont les arguments diffusés répètent un motif (les 256 derniers caractères sont un motif de 4 à 64 caractères répété) ou dépassent 256 Ko | La génération est arrêtée aussitôt : `[error: the model's tool call ran away: its arguments repeat the same pattern (N characters so far: …) — generation stopped; rephrase the request, or try another model]`. Sans cela, un modèle qui déraille compose du charabia pendant des minutes pendant que l'écran affiche « Thinking » (le chien de garde est nourri par chaque fragment). Pendant qu'un appel d'outil est diffusé, le spinner dit `Composing a tool call`. |

Les seuils (3, puis 3 de plus) sont fixés dans `main.go` ; `maxTurns` reste la borne extérieure d'un tour.

## Compteurs affichés après un tour

| Compteur | Compte |
|----------|--------|
| `⚙ N command(s)` | Réponses de l'outil `bash` dans le tour. |
| `📝 N file op(s)` | Réponses de `read_file`, `write_file`, `edit_file`. |
| `📖 N skill(s)` | Réponses de `read_skill`. |
| `🔎 N lsp call(s)` | Réponses de `lsp`. |