bots-garden/mini-mepublic Fork
⑂ aa53c8e
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

Merge fix/too-long-completion into main

rickub committed 2026-09-25T15:31:20Z Browse files
aa53c8e parents: 4b0b7b4 eba422a
added .tickets/issues/0043-solve-the-too-long-sessions-errors.yaml +29 -0
new file mode 100644
@@ -0,0 +1,29 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 43
3+title: Solve the too long sessions errors
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-25T04:06:50.781Z
9+updatedAt: 2026-09-25T07:50:41.268Z
10+labels:
11+ - priority::urgent
12+ - kind::bug
13+body: |
14+ [error: stream error: unexpected end of JSON input]
15+
16+ - check the automatic compression first (how it works)
17+ - a slash command that create a raw/txt summary of a specific session (removing the errors)
18+ - or a slash command that loads the only last 3 turns/messages of a session
19+tasks: []
20+comments:
21+ - id: 1
22+ author:
23+ name: k33g
24+ email: ph.charriere@gmail.com
25+ createdAt: 2026-09-25T07:50:41.266Z
26+ body: |
27+ - it's a context windows size problem
28+ - make an audit -> how is it handled?
29+ - when there is an error -> log the sizes
new file mode 100644
@@ -0,0 +1,29 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 43
3+title: Solve the too long sessions errors
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-25T04:06:50.781Z
9+updatedAt: 2026-09-25T07:50:41.268Z
10+labels:
11+ - priority::urgent
12+ - kind::bug
13+body: |
14+ [error: stream error: unexpected end of JSON input]
15+
16+ - check the automatic compression first (how it works)
17+ - a slash command that create a raw/txt summary of a specific session (removing the errors)
18+ - or a slash command that loads the only last 3 turns/messages of a session
19+tasks: []
20+comments:
21+ - id: 1
22+ author:
23+ name: k33g
24+ email: ph.charriere@gmail.com
25+ createdAt: 2026-09-25T07:50:41.266Z
26+ body: |
27+ - it's a context windows size problem
28+ - make an audit -> how is it handled?
29+ - when there is an error -> log the sizes
added .tickets/issues/0044-can-mini-me-use-the-multi-model-mode-of-llamacpp.yaml +15 -0
new file mode 100644
@@ -0,0 +1,15 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 44
3+title: Can mini me use the multi model mode of llamacpp?
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-25T04:44:02.972Z
9+updatedAt: 2026-09-25T04:44:12.561Z
10+labels:
11+ - question
12+ - llama.cpp
13+body: ""
14+tasks: []
15+comments: []
new file mode 100644
@@ -0,0 +1,15 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 44
3+title: Can mini me use the multi model mode of llamacpp?
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-25T04:44:02.972Z
9+updatedAt: 2026-09-25T04:44:12.561Z
10+labels:
11+ - question
12+ - llama.cpp
13+body: ""
14+tasks: []
15+comments: []
added .tickets/issues/0045-sampling-parameters.yaml +14 -0
new file mode 100644
@@ -0,0 +1,14 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 45
3+title: Sampling parameters
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-25T07:14:21.206Z
9+updatedAt: 2026-09-25T07:14:51.120Z
10+labels: []
11+body: |
12+ Create a document to explain how to use the sampling parameters
13+tasks: []
14+comments: []
new file mode 100644
@@ -0,0 +1,14 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 45
3+title: Sampling parameters
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-09-25T07:14:21.206Z
9+updatedAt: 2026-09-25T07:14:51.120Z
10+labels: []
11+body: |
12+ Create a document to explain how to use the sampling parameters
13+tasks: []
14+comments: []
added docker-agent.yaml +65 -0
new file mode 100644
@@ -0,0 +1,65 @@
1+agents:
2+
3+ root:
4+ model: coder
5+ description: A local code agent, powered by a small LLM served by Docker Model Runner.
6+ instruction: |
7+ Your name is Bob. You are a developer and a Golang + HTMX expert.
8+ You act as a mentor and coding partner.
9+ You help users write, run, test, debug, and *understand* high-quality, idiomatic Golang.
10+ You can also brainstorm features and iterate on small Golang projects.
11+
12+ # Tool discipline
13+
14+ Built-in tools:
15+ - shell: use the `shell` tool to explore the project, read files, or run commands.
16+ Chain commands as long as it is useful, then give a clear final answer.
17+
18+ # Style
19+
20+ Be concise. Prefer a small, correct, compilable example over prose.
21+
22+ max_tool_result_tokens: 1500
23+ max_old_tool_call_tokens: 4000
24+ compaction_threshold: 0.8
25+ max_iterations: 40
26+
27+ toolsets:
28+ - type: shell
29+ - type: filesystem
30+ - type: background_jobs
31+
32+ - type: lsp
33+ command: gopls
34+ args: []
35+ file_types: [".go", ".mod"]
36+ working_dir: "."
37+ lifecycle:
38+ profile: resilient
39+ startup_timeout: 10s
40+
41+
42+permissions:
43+ deny:
44+ # filesystem toolset
45+ # - write_file:path=*spec.yaml
46+ # - edit_file:path=*spec.yaml
47+ # - write_file:path=*agent.yaml
48+ # - edit_file:path=*agent.yaml
49+
50+ # shell toolset
51+ # The shell completely bypasses the filesystem toolset:
52+ - shell:cmd=*spec.yaml*
53+ - shell:cmd=*agent.yaml*
54+ - shell:cmd=*start.sh*
55+
56+
57+models:
58+ # A local model served by Docker Model Runner (OpenAI-compatible API).
59+ coder:
60+ provider: dmr
61+ #model: huggingface.co/unsloth/gemma-4-26b-a4b-it-gguf:UD-Q4_K_M
62+ model: huggingface.co/ornith-ai/ornith-1.5-35b-a3b-gguf:Q4_K_M
63+
64+ base_url: http://localhost:12434/engines/v1
65+ #base_url: http://host.docker.internal:12434/engines/v1
new file mode 100644
@@ -0,0 +1,65 @@
1+agents:
2+
3+ root:
4+ model: coder
5+ description: A local code agent, powered by a small LLM served by Docker Model Runner.
6+ instruction: |
7+ Your name is Bob. You are a developer and a Golang + HTMX expert.
8+ You act as a mentor and coding partner.
9+ You help users write, run, test, debug, and *understand* high-quality, idiomatic Golang.
10+ You can also brainstorm features and iterate on small Golang projects.
11+
12+ # Tool discipline
13+
14+ Built-in tools:
15+ - shell: use the `shell` tool to explore the project, read files, or run commands.
16+ Chain commands as long as it is useful, then give a clear final answer.
17+
18+ # Style
19+
20+ Be concise. Prefer a small, correct, compilable example over prose.
21+
22+ max_tool_result_tokens: 1500
23+ max_old_tool_call_tokens: 4000
24+ compaction_threshold: 0.8
25+ max_iterations: 40
26+
27+ toolsets:
28+ - type: shell
29+ - type: filesystem
30+ - type: background_jobs
31+
32+ - type: lsp
33+ command: gopls
34+ args: []
35+ file_types: [".go", ".mod"]
36+ working_dir: "."
37+ lifecycle:
38+ profile: resilient
39+ startup_timeout: 10s
40+
41+
42+permissions:
43+ deny:
44+ # filesystem toolset
45+ # - write_file:path=*spec.yaml
46+ # - edit_file:path=*spec.yaml
47+ # - write_file:path=*agent.yaml
48+ # - edit_file:path=*agent.yaml
49+
50+ # shell toolset
51+ # The shell completely bypasses the filesystem toolset:
52+ - shell:cmd=*spec.yaml*
53+ - shell:cmd=*agent.yaml*
54+ - shell:cmd=*start.sh*
55+
56+
57+models:
58+ # A local model served by Docker Model Runner (OpenAI-compatible API).
59+ coder:
60+ provider: dmr
61+ #model: huggingface.co/unsloth/gemma-4-26b-a4b-it-gguf:UD-Q4_K_M
62+ model: huggingface.co/ornith-ai/ornith-1.5-35b-a3b-gguf:Q4_K_M
63+
64+ base_url: http://localhost:12434/engines/v1
65+ #base_url: http://host.docker.internal:12434/engines/v1
modified docs/en/how-to/use-from-an-editor.md +16 -1
@@ -32,7 +32,22 @@ This guide shows how to host `mm` inside an editor that speaks the Agent Client
3232 - **Compress or restart the conversation.** Send `/compact` or `/new`; editors that list the agent's commands offer both in the slash-command menu. See the [slash commands reference](../reference/slash-commands.md#acp-mode).
3333 - **Attach a file with `@`.** The editor's picker sends a `resource_link`, passed to the model as `[attached file: <path>]`; a path typed by hand as `@path` is understood the same way (see [`@path`](attach-a-file.md)). The model reads the file with its tools.
3434 - **Reload the agent without losing the thread.** With `sessions.enabled: true` in the config file, the editor's Reload Agent (Zed) calls `session/load` and the whole conversation, tool calls included, is replayed into the thread. See [Keep sessions and resume them](keep-sessions.md).
35-- **Run from a terminal to debug the protocol.** `mm -acp` reads JSON-RPC on stdin and writes it on stdout, one message per line.
35+- **Change the name the editor sees.** Add an `acp:` block to the config file; `name` is the identifier the editor logs, `title` the name it may display (leave `title` empty to not send one). The version sent is always the binary's, the one `mm --version` prints — check it with the `initialize` request below. See the [`acp` keys](../reference/configuration.md#acp-keys).
36+
37+ ```yaml
38+ acp:
39+ name: mini-me
40+ title: Mini Me
41+ ```
42+
43+- **Run from a terminal to debug the protocol.** `mm -acp` reads JSON-RPC on stdin and writes it on stdout, one message per line. For instance, to see how the agent introduces itself:
44+
45+ ```bash
46+ (echo '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1}}'; sleep 2) \
47+ | mm -acp -config /absolute/path/to/agent.yaml 2>/dev/null | head -1
48+ ```
49+
50+ The answer carries `"agentInfo":{"name":"bob","title":"Bob (bash-first agent)","version":"v0.1.6"}` with the default settings.
3651
3752 ## See also
3853
@@ -32,7 +32,22 @@ This guide shows how to host `mm` inside an editor that speaks the Agent Client
32 - **Compress or restart the conversation.** Send `/compact` or `/new`; editors that list the agent's commands offer both in the slash-command menu. See the [slash commands reference](../reference/slash-commands.md#acp-mode).32 - **Compress or restart the conversation.** Send `/compact` or `/new`; editors that list the agent's commands offer both in the slash-command menu. See the [slash commands reference](../reference/slash-commands.md#acp-mode).
33 - **Attach a file with `@`.** The editor's picker sends a `resource_link`, passed to the model as `[attached file: <path>]`; a path typed by hand as `@path` is understood the same way (see [`@path`](attach-a-file.md)). The model reads the file with its tools.33 - **Attach a file with `@`.** The editor's picker sends a `resource_link`, passed to the model as `[attached file: <path>]`; a path typed by hand as `@path` is understood the same way (see [`@path`](attach-a-file.md)). The model reads the file with its tools.
34 - **Reload the agent without losing the thread.** With `sessions.enabled: true` in the config file, the editor's Reload Agent (Zed) calls `session/load` and the whole conversation, tool calls included, is replayed into the thread. See [Keep sessions and resume them](keep-sessions.md).34 - **Reload the agent without losing the thread.** With `sessions.enabled: true` in the config file, the editor's Reload Agent (Zed) calls `session/load` and the whole conversation, tool calls included, is replayed into the thread. See [Keep sessions and resume them](keep-sessions.md).
35-- **Run from a terminal to debug the protocol.** `mm -acp` reads JSON-RPC on stdin and writes it on stdout, one message per line.35+- **Change the name the editor sees.** Add an `acp:` block to the config file; `name` is the identifier the editor logs, `title` the name it may display (leave `title` empty to not send one). The version sent is always the binary's, the one `mm --version` prints — check it with the `initialize` request below. See the [`acp` keys](../reference/configuration.md#acp-keys).
36+
37+ ```yaml
38+ acp:
39+ name: mini-me
40+ title: Mini Me
41+ ```
42+
43+- **Run from a terminal to debug the protocol.** `mm -acp` reads JSON-RPC on stdin and writes it on stdout, one message per line. For instance, to see how the agent introduces itself:
44+
45+ ```bash
46+ (echo '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1}}'; sleep 2) \
47+ | mm -acp -config /absolute/path/to/agent.yaml 2>/dev/null | head -1
48+ ```
49+
50+ The answer carries `"agentInfo":{"name":"bob","title":"Bob (bash-first agent)","version":"v0.1.6"}` with the default settings.
36 51
37 ## See also52 ## See also
38 53
modified docs/en/reference/acp.md +3 -3
@@ -17,9 +17,9 @@
1717 |-------|-------|
1818 | `protocolVersion` | `1` |
1919 | `agentCapabilities` | `loadSession: true` when `sessions.enabled` is set, absent (false) otherwise. Everything else absent (false): no image or audio prompts, no HTTP MCP. |
20-| `agentInfo.name` | `bob` |
21-| `agentInfo.title` | `Bob (bash-first agent)` |
22-| `agentInfo.version` | `0.11.0` |
20+| `agentInfo.name` | `acp.name` of the configuration, `bob` by default. |
21+| `agentInfo.title` | `acp.title` of the configuration, `Bob (bash-first agent)` by default; absent when empty. |
22+| `agentInfo.version` | The binary's version, the same string as `mm --version` (for example `v0.1.6`). |
2323 | `authMethods` | `[]` |
2424
2525 ## Methods
@@ -17,9 +17,9 @@
17 |-------|-------|17 |-------|-------|
18 | `protocolVersion` | `1` |18 | `protocolVersion` | `1` |
19 | `agentCapabilities` | `loadSession: true` when `sessions.enabled` is set, absent (false) otherwise. Everything else absent (false): no image or audio prompts, no HTTP MCP. |19 | `agentCapabilities` | `loadSession: true` when `sessions.enabled` is set, absent (false) otherwise. Everything else absent (false): no image or audio prompts, no HTTP MCP. |
20-| `agentInfo.name` | `bob` |20+| `agentInfo.name` | `acp.name` of the configuration, `bob` by default. |
21-| `agentInfo.title` | `Bob (bash-first agent)` |21+| `agentInfo.title` | `acp.title` of the configuration, `Bob (bash-first agent)` by default; absent when empty. |
22-| `agentInfo.version` | `0.11.0` |22+| `agentInfo.version` | The binary's version, the same string as `mm --version` (for example `v0.1.6`). |
23 | `authMethods` | `[]` |23 | `authMethods` | `[]` |
24 24
25 ## Methods25 ## Methods
modified docs/en/reference/configuration.md +11 -0
@@ -25,6 +25,7 @@
2525 | `watchdogTimeout` | duration | `20s` | Silence tolerated between two streamed tokens before the connection is declared hung. Doubled for summary requests. |
2626 | `context` | map | see below | Automatic history compression. |
2727 | `sessions` | map | see below | Persistent, per-project sessions. |
28+| `acp` | map | see below | How `mm -acp` introduces itself to the editor. |
2829 | `lsp` | map | see below | Language servers behind the `lsp` tool. No server listed = no tool. |
2930 | `tui` | bool | `false` | Start in the single-window mode without the `-tui` flag. Falls back to the line mode when stdin or stdout is not a terminal; ignored with `-acp`. |
3031 | `permissions` | string | `auto` | `ask`: in the window mode, `bash`, `write_file` and `edit_file` wait for the user's answer (`a`/`s`/`r`) before running. `auto`: tools run at once. The line mode and the ACP façade do not read it (ACP has its own dialog). Must be `auto` or `ask`. |
@@ -48,6 +49,15 @@
4849 | `sessions.enabled` | bool | `false` | Save every conversation to a file, rewritten after each turn, `/compact` and `/new`. The file also records, outside the history, every error shown (`errors` array: failed generation, failed compaction, failed `/resume`). Enables `/sessions` and `/resume` in the terminal and `session/load` over ACP. |
4950 | `sessions.dir` | string | `.mm/sessions` | Directory of the session files, one `<id>.json` each. Relative to the directory `mm` is started from (terminal) or to the session's `cwd` (ACP); an absolute path is used as-is. Must not be empty. |
5051
52+## `acp` keys
53+
54+| Key | Type | Default | Description |
55+|-----|------|---------|-------------|
56+| `acp.name` | string | `bob` | `agentInfo.name` in the `initialize` response. Must not be empty. |
57+| `acp.title` | string | `Bob (bash-first agent)` | `agentInfo.title`, the name the editor may display. Empty: not sent. |
58+
59+The version is not configurable: `agentInfo.version` is always the binary's, as printed by `mm --version`.
60+
5161 ## `lsp` keys
5262
5363 | Key | Type | Default | Description |
@@ -96,6 +106,7 @@ Reported as `[config error: <path>: <message>]`, exit code 1.
96106 | `context.summaryMaxTokens must be > 0` | zero or negative |
97107 | `context.maxMessages must be >= 0` | negative value |
98108 | `sessions.dir must not be empty` | empty string |
109+| `acp.name must not be empty` | empty or blank string |
99110 | `lsp.servers[N].name must not be empty` | a server without `name` |
100111 | `lsp.servers[N].command must not be empty` | a server without `command` |
101112 | `lsp.servers[N].extensions must list at least one extension` | a server without `extensions` |
@@ -25,6 +25,7 @@
25 | `watchdogTimeout` | duration | `20s` | Silence tolerated between two streamed tokens before the connection is declared hung. Doubled for summary requests. |25 | `watchdogTimeout` | duration | `20s` | Silence tolerated between two streamed tokens before the connection is declared hung. Doubled for summary requests. |
26 | `context` | map | see below | Automatic history compression. |26 | `context` | map | see below | Automatic history compression. |
27 | `sessions` | map | see below | Persistent, per-project sessions. |27 | `sessions` | map | see below | Persistent, per-project sessions. |
28+| `acp` | map | see below | How `mm -acp` introduces itself to the editor. |
28 | `lsp` | map | see below | Language servers behind the `lsp` tool. No server listed = no tool. |29 | `lsp` | map | see below | Language servers behind the `lsp` tool. No server listed = no tool. |
29 | `tui` | bool | `false` | Start in the single-window mode without the `-tui` flag. Falls back to the line mode when stdin or stdout is not a terminal; ignored with `-acp`. |30 | `tui` | bool | `false` | Start in the single-window mode without the `-tui` flag. Falls back to the line mode when stdin or stdout is not a terminal; ignored with `-acp`. |
30 | `permissions` | string | `auto` | `ask`: in the window mode, `bash`, `write_file` and `edit_file` wait for the user's answer (`a`/`s`/`r`) before running. `auto`: tools run at once. The line mode and the ACP façade do not read it (ACP has its own dialog). Must be `auto` or `ask`. |31 | `permissions` | string | `auto` | `ask`: in the window mode, `bash`, `write_file` and `edit_file` wait for the user's answer (`a`/`s`/`r`) before running. `auto`: tools run at once. The line mode and the ACP façade do not read it (ACP has its own dialog). Must be `auto` or `ask`. |
@@ -48,6 +49,15 @@
48 | `sessions.enabled` | bool | `false` | Save every conversation to a file, rewritten after each turn, `/compact` and `/new`. The file also records, outside the history, every error shown (`errors` array: failed generation, failed compaction, failed `/resume`). Enables `/sessions` and `/resume` in the terminal and `session/load` over ACP. |49 | `sessions.enabled` | bool | `false` | Save every conversation to a file, rewritten after each turn, `/compact` and `/new`. The file also records, outside the history, every error shown (`errors` array: failed generation, failed compaction, failed `/resume`). Enables `/sessions` and `/resume` in the terminal and `session/load` over ACP. |
49 | `sessions.dir` | string | `.mm/sessions` | Directory of the session files, one `<id>.json` each. Relative to the directory `mm` is started from (terminal) or to the session's `cwd` (ACP); an absolute path is used as-is. Must not be empty. |50 | `sessions.dir` | string | `.mm/sessions` | Directory of the session files, one `<id>.json` each. Relative to the directory `mm` is started from (terminal) or to the session's `cwd` (ACP); an absolute path is used as-is. Must not be empty. |
50 51
52+## `acp` keys
53+
54+| Key | Type | Default | Description |
55+|-----|------|---------|-------------|
56+| `acp.name` | string | `bob` | `agentInfo.name` in the `initialize` response. Must not be empty. |
57+| `acp.title` | string | `Bob (bash-first agent)` | `agentInfo.title`, the name the editor may display. Empty: not sent. |
58+
59+The version is not configurable: `agentInfo.version` is always the binary's, as printed by `mm --version`.
60+
51 ## `lsp` keys61 ## `lsp` keys
52 62
53 | Key | Type | Default | Description |63 | Key | Type | Default | Description |
@@ -96,6 +106,7 @@ Reported as `[config error: <path>: <message>]`, exit code 1.
96 | `context.summaryMaxTokens must be > 0` | zero or negative |106 | `context.summaryMaxTokens must be > 0` | zero or negative |
97 | `context.maxMessages must be >= 0` | negative value |107 | `context.maxMessages must be >= 0` | negative value |
98 | `sessions.dir must not be empty` | empty string |108 | `sessions.dir must not be empty` | empty string |
109+| `acp.name must not be empty` | empty or blank string |
99 | `lsp.servers[N].name must not be empty` | a server without `name` |110 | `lsp.servers[N].name must not be empty` | a server without `name` |
100 | `lsp.servers[N].command must not be empty` | a server without `command` |111 | `lsp.servers[N].command must not be empty` | a server without `command` |
101 | `lsp.servers[N].extensions must list at least one extension` | a server without `extensions` |112 | `lsp.servers[N].extensions must list at least one extension` | a server without `extensions` |
modified docs/fr/how-to/use-from-an-editor.md +16 -1
@@ -32,7 +32,22 @@ Ce guide montre comment héberger `mm` dans un éditeur qui parle l'Agent Client
3232 - **Compresser ou recommencer la conversation.** Envoyez `/compact` ou `/new` ; les éditeurs qui listent les commandes de l'agent proposent les deux dans le menu des commandes slash. Voir la [référence des commandes slash](../reference/slash-commands.md#mode-acp).
3333 - **Attacher un fichier avec `@`.** Le sélecteur de l'éditeur envoie un `resource_link`, transmis au modèle sous la forme `[attached file: <chemin>]` ; un chemin tapé à la main comme `@chemin` est compris de la même façon (voir [`@chemin`](attach-a-file.md)). Le modèle lit le fichier avec ses outils.
3434 - **Recharger l'agent sans perdre le fil.** Avec `sessions.enabled: true` dans le fichier de configuration, le Reload Agent de l'éditeur (Zed) appelle `session/load` et toute la conversation, appels d'outils compris, est rejouée dans le fil. Voir [Conserver les sessions et les reprendre](keep-sessions.md).
35-- **Lancer depuis un terminal pour déboguer le protocole.** `mm -acp` lit du JSON-RPC sur stdin et l'écrit sur stdout, un message par ligne.
35+- **Changer le nom que voit l'éditeur.** Ajoutez un bloc `acp:` au fichier de configuration ; `name` est l'identifiant que l'éditeur journalise, `title` le nom qu'il peut afficher (laissez `title` vide pour n'en envoyer aucun). La version envoyée est toujours celle du binaire, celle qu'affiche `mm --version` — vérifiez-la avec la requête `initialize` ci-dessous. Voir les [clés de `acp`](../reference/configuration.md#clés-de-acp).
36+
37+ ```yaml
38+ acp:
39+ name: mini-me
40+ title: Mini Me
41+ ```
42+
43+- **Lancer depuis un terminal pour déboguer le protocole.** `mm -acp` lit du JSON-RPC sur stdin et l'écrit sur stdout, un message par ligne. Par exemple, pour voir comment l'agent se présente :
44+
45+ ```bash
46+ (echo '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1}}'; sleep 2) \
47+ | mm -acp -config /chemin/absolu/vers/agent.yaml 2>/dev/null | head -1
48+ ```
49+
50+ Avec les réglages par défaut, la réponse contient `"agentInfo":{"name":"bob","title":"Bob (bash-first agent)","version":"v0.1.6"}`.
3651
3752 ## Voir aussi
3853
@@ -32,7 +32,22 @@ Ce guide montre comment héberger `mm` dans un éditeur qui parle l'Agent Client
32 - **Compresser ou recommencer la conversation.** Envoyez `/compact` ou `/new` ; les éditeurs qui listent les commandes de l'agent proposent les deux dans le menu des commandes slash. Voir la [référence des commandes slash](../reference/slash-commands.md#mode-acp).32 - **Compresser ou recommencer la conversation.** Envoyez `/compact` ou `/new` ; les éditeurs qui listent les commandes de l'agent proposent les deux dans le menu des commandes slash. Voir la [référence des commandes slash](../reference/slash-commands.md#mode-acp).
33 - **Attacher un fichier avec `@`.** Le sélecteur de l'éditeur envoie un `resource_link`, transmis au modèle sous la forme `[attached file: <chemin>]` ; un chemin tapé à la main comme `@chemin` est compris de la même façon (voir [`@chemin`](attach-a-file.md)). Le modèle lit le fichier avec ses outils.33 - **Attacher un fichier avec `@`.** Le sélecteur de l'éditeur envoie un `resource_link`, transmis au modèle sous la forme `[attached file: <chemin>]` ; un chemin tapé à la main comme `@chemin` est compris de la même façon (voir [`@chemin`](attach-a-file.md)). Le modèle lit le fichier avec ses outils.
34 - **Recharger l'agent sans perdre le fil.** Avec `sessions.enabled: true` dans le fichier de configuration, le Reload Agent de l'éditeur (Zed) appelle `session/load` et toute la conversation, appels d'outils compris, est rejouée dans le fil. Voir [Conserver les sessions et les reprendre](keep-sessions.md).34 - **Recharger l'agent sans perdre le fil.** Avec `sessions.enabled: true` dans le fichier de configuration, le Reload Agent de l'éditeur (Zed) appelle `session/load` et toute la conversation, appels d'outils compris, est rejouée dans le fil. Voir [Conserver les sessions et les reprendre](keep-sessions.md).
35-- **Lancer depuis un terminal pour déboguer le protocole.** `mm -acp` lit du JSON-RPC sur stdin et l'écrit sur stdout, un message par ligne.35+- **Changer le nom que voit l'éditeur.** Ajoutez un bloc `acp:` au fichier de configuration ; `name` est l'identifiant que l'éditeur journalise, `title` le nom qu'il peut afficher (laissez `title` vide pour n'en envoyer aucun). La version envoyée est toujours celle du binaire, celle qu'affiche `mm --version` — vérifiez-la avec la requête `initialize` ci-dessous. Voir les [clés de `acp`](../reference/configuration.md#clés-de-acp).
36+
37+ ```yaml
38+ acp:
39+ name: mini-me
40+ title: Mini Me
41+ ```
42+
43+- **Lancer depuis un terminal pour déboguer le protocole.** `mm -acp` lit du JSON-RPC sur stdin et l'écrit sur stdout, un message par ligne. Par exemple, pour voir comment l'agent se présente :
44+
45+ ```bash
46+ (echo '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1}}'; sleep 2) \
47+ | mm -acp -config /chemin/absolu/vers/agent.yaml 2>/dev/null | head -1
48+ ```
49+
50+ Avec les réglages par défaut, la réponse contient `"agentInfo":{"name":"bob","title":"Bob (bash-first agent)","version":"v0.1.6"}`.
36 51
37 ## Voir aussi52 ## Voir aussi
38 53
modified docs/fr/reference/acp.md +3 -3
@@ -17,9 +17,9 @@
1717 |-------|--------|
1818 | `protocolVersion` | `1` |
1919 | `agentCapabilities` | `loadSession: true` quand `sessions.enabled` est activé, absente (false) sinon. Tout le reste absent (false) : pas de prompts image ou audio, pas de MCP HTTP. |
20-| `agentInfo.name` | `bob` |
21-| `agentInfo.title` | `Bob (bash-first agent)` |
22-| `agentInfo.version` | `0.11.0` |
20+| `agentInfo.name` | `acp.name` de la configuration, `bob` par défaut. |
21+| `agentInfo.title` | `acp.title` de la configuration, `Bob (bash-first agent)` par défaut ; absent quand vide. |
22+| `agentInfo.version` | La version du binaire, la même chaîne que `mm --version` (par exemple `v0.1.6`). |
2323 | `authMethods` | `[]` |
2424
2525 ## Méthodes
@@ -17,9 +17,9 @@
17 |-------|--------|17 |-------|--------|
18 | `protocolVersion` | `1` |18 | `protocolVersion` | `1` |
19 | `agentCapabilities` | `loadSession: true` quand `sessions.enabled` est activé, absente (false) sinon. Tout le reste absent (false) : pas de prompts image ou audio, pas de MCP HTTP. |19 | `agentCapabilities` | `loadSession: true` quand `sessions.enabled` est activé, absente (false) sinon. Tout le reste absent (false) : pas de prompts image ou audio, pas de MCP HTTP. |
20-| `agentInfo.name` | `bob` |20+| `agentInfo.name` | `acp.name` de la configuration, `bob` par défaut. |
21-| `agentInfo.title` | `Bob (bash-first agent)` |21+| `agentInfo.title` | `acp.title` de la configuration, `Bob (bash-first agent)` par défaut ; absent quand vide. |
22-| `agentInfo.version` | `0.11.0` |22+| `agentInfo.version` | La version du binaire, la même chaîne que `mm --version` (par exemple `v0.1.6`). |
23 | `authMethods` | `[]` |23 | `authMethods` | `[]` |
24 24
25 ## Méthodes25 ## Méthodes
modified docs/fr/reference/configuration.md +11 -0
@@ -25,6 +25,7 @@
2525 | `watchdogTimeout` | durée | `20s` | Silence toléré entre deux tokens diffusés avant de déclarer la connexion bloquée. Doublé pour les requêtes de résumé. |
2626 | `context` | dictionnaire | voir ci-dessous | Compression automatique de l'historique. |
2727 | `sessions` | dictionnaire | voir ci-dessous | Sessions persistantes, par projet. |
28+| `acp` | dictionnaire | voir ci-dessous | La façon dont `mm -acp` se présente à l'éditeur. |
2829 | `lsp` | dictionnaire | voir ci-dessous | Serveurs de langage derrière l'outil `lsp`. Aucun serveur listé = pas d'outil. |
2930 | `tui` | bool | `false` | Démarre dans le mode fenêtre unique sans l'option `-tui`. Retombe sur le mode ligne quand stdin ou stdout n'est pas un terminal ; ignoré avec `-acp`. |
3031 | `permissions` | chaîne | `auto` | `ask` : en mode fenêtre, `bash`, `write_file` et `edit_file` attendent la réponse de l'utilisateur (`a`/`s`/`r`) avant de s'exécuter. `auto` : les outils s'exécutent aussitôt. Le mode ligne et la façade ACP ne la lisent pas (ACP a son propre dialogue). Doit valoir `auto` ou `ask`. |
@@ -48,6 +49,15 @@
4849 | `sessions.enabled` | bool | `false` | Enregistre chaque conversation dans un fichier, réécrit après chaque tour, `/compact` et `/new`. Le fichier enregistre aussi, hors de l'historique, chaque erreur affichée (tableau `errors` : génération échouée, compression échouée, `/resume` échoué). Active `/sessions` et `/resume` dans le terminal et `session/load` en ACP. |
4950 | `sessions.dir` | chaîne | `.mm/sessions` | Répertoire des fichiers de session, un `<id>.json` chacun. Relatif au répertoire de lancement de `mm` (terminal) ou au `cwd` de la session (ACP) ; un chemin absolu est utilisé tel quel. Ne doit pas être vide. |
5051
52+## Clés de `acp`
53+
54+| Clé | Type | Défaut | Description |
55+|-----|------|--------|-------------|
56+| `acp.name` | chaîne | `bob` | `agentInfo.name` dans la réponse à `initialize`. Ne doit pas être vide. |
57+| `acp.title` | chaîne | `Bob (bash-first agent)` | `agentInfo.title`, le nom que l'éditeur peut afficher. Vide : non envoyé. |
58+
59+La version n'est pas paramétrable : `agentInfo.version` est toujours celle du binaire, telle qu'affichée par `mm --version`.
60+
5161 ## Clés de `lsp`
5262
5363 | Clé | Type | Défaut | Description |
@@ -96,6 +106,7 @@ Signalées sous la forme `[config error: <chemin>: <message>]`, code de sortie 1
96106 | `context.summaryMaxTokens must be > 0` | zéro ou négatif |
97107 | `context.maxMessages must be >= 0` | valeur négative |
98108 | `sessions.dir must not be empty` | chaîne vide |
109+| `acp.name must not be empty` | chaîne vide ou blanche |
99110 | `lsp.servers[N].name must not be empty` | un serveur sans `name` |
100111 | `lsp.servers[N].command must not be empty` | un serveur sans `command` |
101112 | `lsp.servers[N].extensions must list at least one extension` | un serveur sans `extensions` |
@@ -25,6 +25,7 @@
25 | `watchdogTimeout` | durée | `20s` | Silence toléré entre deux tokens diffusés avant de déclarer la connexion bloquée. Doublé pour les requêtes de résumé. |25 | `watchdogTimeout` | durée | `20s` | Silence toléré entre deux tokens diffusés avant de déclarer la connexion bloquée. Doublé pour les requêtes de résumé. |
26 | `context` | dictionnaire | voir ci-dessous | Compression automatique de l'historique. |26 | `context` | dictionnaire | voir ci-dessous | Compression automatique de l'historique. |
27 | `sessions` | dictionnaire | voir ci-dessous | Sessions persistantes, par projet. |27 | `sessions` | dictionnaire | voir ci-dessous | Sessions persistantes, par projet. |
28+| `acp` | dictionnaire | voir ci-dessous | La façon dont `mm -acp` se présente à l'éditeur. |
28 | `lsp` | dictionnaire | voir ci-dessous | Serveurs de langage derrière l'outil `lsp`. Aucun serveur listé = pas d'outil. |29 | `lsp` | dictionnaire | voir ci-dessous | Serveurs de langage derrière l'outil `lsp`. Aucun serveur listé = pas d'outil. |
29 | `tui` | bool | `false` | Démarre dans le mode fenêtre unique sans l'option `-tui`. Retombe sur le mode ligne quand stdin ou stdout n'est pas un terminal ; ignoré avec `-acp`. |30 | `tui` | bool | `false` | Démarre dans le mode fenêtre unique sans l'option `-tui`. Retombe sur le mode ligne quand stdin ou stdout n'est pas un terminal ; ignoré avec `-acp`. |
30 | `permissions` | chaîne | `auto` | `ask` : en mode fenêtre, `bash`, `write_file` et `edit_file` attendent la réponse de l'utilisateur (`a`/`s`/`r`) avant de s'exécuter. `auto` : les outils s'exécutent aussitôt. Le mode ligne et la façade ACP ne la lisent pas (ACP a son propre dialogue). Doit valoir `auto` ou `ask`. |31 | `permissions` | chaîne | `auto` | `ask` : en mode fenêtre, `bash`, `write_file` et `edit_file` attendent la réponse de l'utilisateur (`a`/`s`/`r`) avant de s'exécuter. `auto` : les outils s'exécutent aussitôt. Le mode ligne et la façade ACP ne la lisent pas (ACP a son propre dialogue). Doit valoir `auto` ou `ask`. |
@@ -48,6 +49,15 @@
48 | `sessions.enabled` | bool | `false` | Enregistre chaque conversation dans un fichier, réécrit après chaque tour, `/compact` et `/new`. Le fichier enregistre aussi, hors de l'historique, chaque erreur affichée (tableau `errors` : génération échouée, compression échouée, `/resume` échoué). Active `/sessions` et `/resume` dans le terminal et `session/load` en ACP. |49 | `sessions.enabled` | bool | `false` | Enregistre chaque conversation dans un fichier, réécrit après chaque tour, `/compact` et `/new`. Le fichier enregistre aussi, hors de l'historique, chaque erreur affichée (tableau `errors` : génération échouée, compression échouée, `/resume` échoué). Active `/sessions` et `/resume` dans le terminal et `session/load` en ACP. |
49 | `sessions.dir` | chaîne | `.mm/sessions` | Répertoire des fichiers de session, un `<id>.json` chacun. Relatif au répertoire de lancement de `mm` (terminal) ou au `cwd` de la session (ACP) ; un chemin absolu est utilisé tel quel. Ne doit pas être vide. |50 | `sessions.dir` | chaîne | `.mm/sessions` | Répertoire des fichiers de session, un `<id>.json` chacun. Relatif au répertoire de lancement de `mm` (terminal) ou au `cwd` de la session (ACP) ; un chemin absolu est utilisé tel quel. Ne doit pas être vide. |
50 51
52+## Clés de `acp`
53+
54+| Clé | Type | Défaut | Description |
55+|-----|------|--------|-------------|
56+| `acp.name` | chaîne | `bob` | `agentInfo.name` dans la réponse à `initialize`. Ne doit pas être vide. |
57+| `acp.title` | chaîne | `Bob (bash-first agent)` | `agentInfo.title`, le nom que l'éditeur peut afficher. Vide : non envoyé. |
58+
59+La version n'est pas paramétrable : `agentInfo.version` est toujours celle du binaire, telle qu'affichée par `mm --version`.
60+
51 ## Clés de `lsp`61 ## Clés de `lsp`
52 62
53 | Clé | Type | Défaut | Description |63 | Clé | Type | Défaut | Description |
@@ -96,6 +106,7 @@ Signalées sous la forme `[config error: <chemin>: <message>]`, code de sortie 1
96 | `context.summaryMaxTokens must be > 0` | zéro ou négatif |106 | `context.summaryMaxTokens must be > 0` | zéro ou négatif |
97 | `context.maxMessages must be >= 0` | valeur négative |107 | `context.maxMessages must be >= 0` | valeur négative |
98 | `sessions.dir must not be empty` | chaîne vide |108 | `sessions.dir must not be empty` | chaîne vide |
109+| `acp.name must not be empty` | chaîne vide ou blanche |
99 | `lsp.servers[N].name must not be empty` | un serveur sans `name` |110 | `lsp.servers[N].name must not be empty` | un serveur sans `name` |
100 | `lsp.servers[N].command must not be empty` | un serveur sans `command` |111 | `lsp.servers[N].command must not be empty` | un serveur sans `command` |
101 | `lsp.servers[N].extensions must list at least one extension` | un serveur sans `extensions` |112 | `lsp.servers[N].extensions must list at least one extension` | un serveur sans `extensions` |
modified internal/acp/acp.go +13 -5
@@ -38,15 +38,12 @@ import (
3838 "mm/internal/skills"
3939 "mm/internal/store"
4040 "mm/internal/ui"
41+ "mm/internal/version"
4142
4243 sdk "github.com/coder/acp-go-sdk"
4344 "github.com/firebase/genkit/go/ai"
4445 )
4546
46-// version is what initialize reports in agentInfo — the part number, so a
47-// trace says which chapter of the talk produced it.
48-const version = "0.11.0"
49-
5047 // session is one conversation with the client. Like the REPL, the history is
5148 // plain []*ai.Message with the system prompt first; unlike the REPL there can
5249 // be several of them, one per session/new.
@@ -192,11 +189,22 @@ func (f *front) Initialize(_ context.Context, p sdk.InitializeRequest) (sdk.Init
192189 // editor's "reload" needs a file to reload. Honest capabilities are
193190 // what lets a client adapt.
194191 AgentCapabilities: sdk.AgentCapabilities{LoadSession: f.sessionsDir != ""},
195- AgentInfo: &sdk.Implementation{Name: "bob", Title: sdk.Ptr("Bob (bash-first agent)"), Version: version},
192+ AgentInfo: agentInfo(),
196193 AuthMethods: []sdk.AuthMethod{}, // the engine is local: nothing to log into
197194 }, nil
198195 }
199196
197+// agentInfo is how the agent introduces itself: name and title from the
198+// `acp:` block of the config, version from the binary — the same string as
199+// `mm --version`, so an ACP trace and a bug report name the same build.
200+func agentInfo() *sdk.Implementation {
201+ info := &sdk.Implementation{Name: config.Cfg.ACP.Name, Version: version.Short()}
202+ if config.Cfg.ACP.Title != "" {
203+ info.Title = sdk.Ptr(config.Cfg.ACP.Title)
204+ }
205+ return info
206+}
207+
200208 func clientName(impl *sdk.Implementation) string {
201209 if impl == nil {
202210 return "unknown"
@@ -38,15 +38,12 @@ import (
38 "mm/internal/skills"38 "mm/internal/skills"
39 "mm/internal/store"39 "mm/internal/store"
40 "mm/internal/ui"40 "mm/internal/ui"
41+ "mm/internal/version"
41 42
42 sdk "github.com/coder/acp-go-sdk"43 sdk "github.com/coder/acp-go-sdk"
43 "github.com/firebase/genkit/go/ai"44 "github.com/firebase/genkit/go/ai"
44 )45 )
45 46
46-// version is what initialize reports in agentInfo — the part number, so a
47-// trace says which chapter of the talk produced it.
48-const version = "0.11.0"
49-
50 // session is one conversation with the client. Like the REPL, the history is47 // session is one conversation with the client. Like the REPL, the history is
51 // plain []*ai.Message with the system prompt first; unlike the REPL there can48 // plain []*ai.Message with the system prompt first; unlike the REPL there can
52 // be several of them, one per session/new.49 // be several of them, one per session/new.
@@ -192,11 +189,22 @@ func (f *front) Initialize(_ context.Context, p sdk.InitializeRequest) (sdk.Init
192 // editor's "reload" needs a file to reload. Honest capabilities are189 // editor's "reload" needs a file to reload. Honest capabilities are
193 // what lets a client adapt.190 // what lets a client adapt.
194 AgentCapabilities: sdk.AgentCapabilities{LoadSession: f.sessionsDir != ""},191 AgentCapabilities: sdk.AgentCapabilities{LoadSession: f.sessionsDir != ""},
195- AgentInfo: &sdk.Implementation{Name: "bob", Title: sdk.Ptr("Bob (bash-first agent)"), Version: version},192+ AgentInfo: agentInfo(),
196 AuthMethods: []sdk.AuthMethod{}, // the engine is local: nothing to log into193 AuthMethods: []sdk.AuthMethod{}, // the engine is local: nothing to log into
197 }, nil194 }, nil
198 }195 }
199 196
197+// agentInfo is how the agent introduces itself: name and title from the
198+// `acp:` block of the config, version from the binary — the same string as
199+// `mm --version`, so an ACP trace and a bug report name the same build.
200+func agentInfo() *sdk.Implementation {
201+ info := &sdk.Implementation{Name: config.Cfg.ACP.Name, Version: version.Short()}
202+ if config.Cfg.ACP.Title != "" {
203+ info.Title = sdk.Ptr(config.Cfg.ACP.Title)
204+ }
205+ return info
206+}
207+
200 func clientName(impl *sdk.Implementation) string {208 func clientName(impl *sdk.Implementation) string {
201 if impl == nil {209 if impl == nil {
202 return "unknown"210 return "unknown"
modified internal/acp/acp_test.go +27 -0
@@ -14,6 +14,7 @@ import (
1414 "mm/internal/compact"
1515 "mm/internal/config"
1616 history "mm/internal/session"
17+ "mm/internal/version"
1718
1819 sdk "github.com/coder/acp-go-sdk"
1920 "github.com/firebase/genkit/go/ai"
@@ -299,3 +300,29 @@ func TestCompactHistoryOutcomes(t *testing.T) {
299300 }
300301 })
301302 }
303+
304+// initialize introduces the agent with the name and title of the `acp:`
305+// config block and the binary's own version — the string `mm --version`
306+// prints, not a number of its own. An empty title is left out.
307+func TestAgentInfo(t *testing.T) {
308+ saved := config.Cfg.ACP
309+ t.Cleanup(func() { config.Cfg.ACP = saved })
310+
311+ config.Cfg.ACP = config.ACPConfig{Name: "mini-me", Title: "Mini Me"}
312+ resp, err := (&front{}).Initialize(context.Background(), sdk.InitializeRequest{})
313+ if err != nil {
314+ t.Fatal(err)
315+ }
316+ info := resp.AgentInfo
317+ if info.Name != "mini-me" || info.Title == nil || *info.Title != "Mini Me" {
318+ t.Errorf("agentInfo = %+v, want mini-me / Mini Me", info)
319+ }
320+ if info.Version != version.Short() {
321+ t.Errorf("agentInfo.version = %q, want version.Short() = %q", info.Version, version.Short())
322+ }
323+
324+ config.Cfg.ACP.Title = ""
325+ if got := agentInfo(); got.Title != nil {
326+ t.Errorf("empty title sent as %q", *got.Title)
327+ }
328+}
@@ -14,6 +14,7 @@ import (
14 "mm/internal/compact"14 "mm/internal/compact"
15 "mm/internal/config"15 "mm/internal/config"
16 history "mm/internal/session"16 history "mm/internal/session"
17+ "mm/internal/version"
17 18
18 sdk "github.com/coder/acp-go-sdk"19 sdk "github.com/coder/acp-go-sdk"
19 "github.com/firebase/genkit/go/ai"20 "github.com/firebase/genkit/go/ai"
@@ -299,3 +300,29 @@ func TestCompactHistoryOutcomes(t *testing.T) {
299 }300 }
300 })301 })
301 }302 }
303+
304+// initialize introduces the agent with the name and title of the `acp:`
305+// config block and the binary's own version — the string `mm --version`
306+// prints, not a number of its own. An empty title is left out.
307+func TestAgentInfo(t *testing.T) {
308+ saved := config.Cfg.ACP
309+ t.Cleanup(func() { config.Cfg.ACP = saved })
310+
311+ config.Cfg.ACP = config.ACPConfig{Name: "mini-me", Title: "Mini Me"}
312+ resp, err := (&front{}).Initialize(context.Background(), sdk.InitializeRequest{})
313+ if err != nil {
314+ t.Fatal(err)
315+ }
316+ info := resp.AgentInfo
317+ if info.Name != "mini-me" || info.Title == nil || *info.Title != "Mini Me" {
318+ t.Errorf("agentInfo = %+v, want mini-me / Mini Me", info)
319+ }
320+ if info.Version != version.Short() {
321+ t.Errorf("agentInfo.version = %q, want version.Short() = %q", info.Version, version.Short())
322+ }
323+
324+ config.Cfg.ACP.Title = ""
325+ if got := agentInfo(); got.Title != nil {
326+ t.Errorf("empty title sent as %q", *got.Title)
327+ }
328+}
modified internal/config/config.go +19 -0
@@ -118,6 +118,11 @@ type Config struct {
118118 // editor can reload one over ACP (session/load).
119119 Sessions SessionsConfig `yaml:"sessions"`
120120
121+ // ACP: how the agent introduces itself to an editor in the `initialize`
122+ // response (`mm -acp`). The version is not configurable: it is the
123+ // binary's own, the one `mm --version` prints.
124+ ACP ACPConfig `yaml:"acp"`
125+
121126 // TUI: start in the single-window mode (`mm -tui`) without the flag.
122127 // Falls back to the line mode when stdout is not a terminal.
123128 TUI bool `yaml:"tui"`
@@ -147,6 +152,14 @@ const (
147152 PermissionsAsk = "ask"
148153 )
149154
155+// ACPConfig is the `acp:` block of the YAML.
156+type ACPConfig struct {
157+ // Name: agentInfo.name, the identifier the client logs. Must not be empty.
158+ Name string `yaml:"name"`
159+ // Title: agentInfo.title, the name an editor shows. Empty = not sent.
160+ Title string `yaml:"title"`
161+}
162+
150163 // SessionsConfig is the `sessions:` block of the YAML.
151164 // LSPConfig is the `lsp` key.
152165 type LSPConfig struct {
@@ -426,6 +439,10 @@ which ones you left running.`,
426439 Enabled: false,
427440 Dir: ".mm/sessions",
428441 },
442+ ACP: ACPConfig{
443+ Name: "bob",
444+ Title: "Bob (bash-first agent)",
445+ },
429446 Permissions: PermissionsAuto,
430447 Context: ContextConfig{
431448 Enabled: false,
@@ -574,6 +591,8 @@ func (c Config) validate() error {
574591 return errors.New("context.maxMessages must be >= 0")
575592 case c.Sessions.Dir == "":
576593 return errors.New("sessions.dir must not be empty")
594+ case strings.TrimSpace(c.ACP.Name) == "":
595+ return errors.New("acp.name must not be empty")
577596 case c.Permissions != PermissionsAuto && c.Permissions != PermissionsAsk:
578597 return errors.New(`permissions must be "auto" or "ask"`)
579598 }
@@ -118,6 +118,11 @@ type Config struct {
118 // editor can reload one over ACP (session/load).118 // editor can reload one over ACP (session/load).
119 Sessions SessionsConfig `yaml:"sessions"`119 Sessions SessionsConfig `yaml:"sessions"`
120 120
121+ // ACP: how the agent introduces itself to an editor in the `initialize`
122+ // response (`mm -acp`). The version is not configurable: it is the
123+ // binary's own, the one `mm --version` prints.
124+ ACP ACPConfig `yaml:"acp"`
125+
121 // TUI: start in the single-window mode (`mm -tui`) without the flag.126 // TUI: start in the single-window mode (`mm -tui`) without the flag.
122 // Falls back to the line mode when stdout is not a terminal.127 // Falls back to the line mode when stdout is not a terminal.
123 TUI bool `yaml:"tui"`128 TUI bool `yaml:"tui"`
@@ -147,6 +152,14 @@ const (
147 PermissionsAsk = "ask"152 PermissionsAsk = "ask"
148 )153 )
149 154
155+// ACPConfig is the `acp:` block of the YAML.
156+type ACPConfig struct {
157+ // Name: agentInfo.name, the identifier the client logs. Must not be empty.
158+ Name string `yaml:"name"`
159+ // Title: agentInfo.title, the name an editor shows. Empty = not sent.
160+ Title string `yaml:"title"`
161+}
162+
150 // SessionsConfig is the `sessions:` block of the YAML.163 // SessionsConfig is the `sessions:` block of the YAML.
151 // LSPConfig is the `lsp` key.164 // LSPConfig is the `lsp` key.
152 type LSPConfig struct {165 type LSPConfig struct {
@@ -426,6 +439,10 @@ which ones you left running.`,
426 Enabled: false,439 Enabled: false,
427 Dir: ".mm/sessions",440 Dir: ".mm/sessions",
428 },441 },
442+ ACP: ACPConfig{
443+ Name: "bob",
444+ Title: "Bob (bash-first agent)",
445+ },
429 Permissions: PermissionsAuto,446 Permissions: PermissionsAuto,
430 Context: ContextConfig{447 Context: ContextConfig{
431 Enabled: false,448 Enabled: false,
@@ -574,6 +591,8 @@ func (c Config) validate() error {
574 return errors.New("context.maxMessages must be >= 0")591 return errors.New("context.maxMessages must be >= 0")
575 case c.Sessions.Dir == "":592 case c.Sessions.Dir == "":
576 return errors.New("sessions.dir must not be empty")593 return errors.New("sessions.dir must not be empty")
594+ case strings.TrimSpace(c.ACP.Name) == "":
595+ return errors.New("acp.name must not be empty")
577 case c.Permissions != PermissionsAuto && c.Permissions != PermissionsAsk:596 case c.Permissions != PermissionsAuto && c.Permissions != PermissionsAsk:
578 return errors.New(`permissions must be "auto" or "ask"`)597 return errors.New(`permissions must be "auto" or "ask"`)
579 }598 }
modified internal/config/config_test.go +33 -0
@@ -163,3 +163,36 @@ func TestLSPConfig(t *testing.T) {
163163 }
164164 }
165165 }
166+
167+// The acp block keeps the historical identity by default, reads a new one
168+// from the YAML, and refuses an empty name: agentInfo.name is required by the
169+// protocol.
170+func TestACPConfig(t *testing.T) {
171+ defaults := Cfg
172+ t.Cleanup(func() { Cfg = defaults })
173+
174+ if Cfg.ACP.Name != "bob" || Cfg.ACP.Title != "Bob (bash-first agent)" {
175+ t.Fatalf("defaults: %+v", Cfg.ACP)
176+ }
177+
178+ dir := t.TempDir()
179+ on := filepath.Join(dir, "acp.yaml")
180+ if err := os.WriteFile(on, []byte("acp:\n name: mini-me\n title: Mini Me\n"), 0o644); err != nil {
181+ t.Fatal(err)
182+ }
183+ if _, err := Load(on); err != nil {
184+ t.Fatal(err)
185+ }
186+ if Cfg.ACP.Name != "mini-me" || Cfg.ACP.Title != "Mini Me" {
187+ t.Errorf("after acp.yaml: %+v", Cfg.ACP)
188+ }
189+
190+ Cfg = defaults
191+ bad := filepath.Join(dir, "bad.yaml")
192+ if err := os.WriteFile(bad, []byte("acp:\n name: \" \"\n"), 0o644); err != nil {
193+ t.Fatal(err)
194+ }
195+ if _, err := Load(bad); err == nil || !strings.Contains(err.Error(), "acp.name") {
196+ t.Errorf("Load(bad.yaml) = %v, want an acp.name validation error", err)
197+ }
198+}
@@ -163,3 +163,36 @@ func TestLSPConfig(t *testing.T) {
163 }163 }
164 }164 }
165 }165 }
166+
167+// The acp block keeps the historical identity by default, reads a new one
168+// from the YAML, and refuses an empty name: agentInfo.name is required by the
169+// protocol.
170+func TestACPConfig(t *testing.T) {
171+ defaults := Cfg
172+ t.Cleanup(func() { Cfg = defaults })
173+
174+ if Cfg.ACP.Name != "bob" || Cfg.ACP.Title != "Bob (bash-first agent)" {
175+ t.Fatalf("defaults: %+v", Cfg.ACP)
176+ }
177+
178+ dir := t.TempDir()
179+ on := filepath.Join(dir, "acp.yaml")
180+ if err := os.WriteFile(on, []byte("acp:\n name: mini-me\n title: Mini Me\n"), 0o644); err != nil {
181+ t.Fatal(err)
182+ }
183+ if _, err := Load(on); err != nil {
184+ t.Fatal(err)
185+ }
186+ if Cfg.ACP.Name != "mini-me" || Cfg.ACP.Title != "Mini Me" {
187+ t.Errorf("after acp.yaml: %+v", Cfg.ACP)
188+ }
189+
190+ Cfg = defaults
191+ bad := filepath.Join(dir, "bad.yaml")
192+ if err := os.WriteFile(bad, []byte("acp:\n name: \" \"\n"), 0o644); err != nil {
193+ t.Fatal(err)
194+ }
195+ if _, err := Load(bad); err == nil || !strings.Contains(err.Error(), "acp.name") {
196+ t.Errorf("Load(bad.yaml) = %v, want an acp.name validation error", err)
197+ }
198+}