🛟 Updated.
9a5c4ec parent: cd2a817 modified
.tickets/epics.yaml +3 -0 | @@ -51,3 +51,6 @@ epics: | ||
| 51 | 51 | - title: Decision models |
| 52 | 52 | state: open |
| 53 | 53 | color: "#c5def5" |
| 54 | + - title: WASM Module | |
| 55 | + state: open | |
| 56 | + color: "#5319e7" | |
| @@ -51,3 +51,6 @@ epics: | |||
| 51 | - title: Decision models | 51 | - title: Decision models |
| 52 | state: open | 52 | state: open |
| 53 | color: "#c5def5" | 53 | color: "#c5def5" |
| 54 | + - title: WASM Module | ||
| 55 | + state: open | ||
| 56 | + color: "#5319e7" | ||
modified
.tickets/issues/0056-blog-post-idea-how-to-query-a-decision-model-fro.yaml +2 -2 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 56 |
| 3 | 3 | title: "Blog post idea: how to query a decision model from a coding agent (skill?)" |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-09-30T06:50:30.091Z |
| 9 | -updatedAt: 2026-10-06T13:12:26.692Z | |
| 9 | +updatedAt: 2026-10-25T04:16:19.984Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | epic: ToDo |
| 12 | 12 | body: "" |
| @@ -1,12 +1,12 @@ | |||
| 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 56 | 2 | id: 56 |
| 3 | title: "Blog post idea: how to query a decision model from a coding agent (skill?)" | 3 | title: "Blog post idea: how to query a decision model from a coding agent (skill?)" |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-09-30T06:50:30.091Z | 8 | createdAt: 2026-09-30T06:50:30.091Z |
| 9 | -updatedAt: 2026-10-06T13:12:26.692Z | 9 | +updatedAt: 2026-10-25T04:16:19.984Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | epic: ToDo | 11 | epic: ToDo |
| 12 | body: "" | 12 | body: "" |
modified
.tickets/issues/0075-add-gronk-provider.yaml +2 -2 | @@ -6,10 +6,10 @@ author: | ||
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-06T03:58:37.611Z |
| 9 | -updatedAt: 2026-10-22T17:11:08.086Z | |
| 9 | +updatedAt: 2026-10-25T04:15:36.796Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | milestone: v1.0.1 |
| 12 | -epic: Providers (LLM Engine) | |
| 12 | +epic: Providers | |
| 13 | 13 | body: "" |
| 14 | 14 | tasks: [] |
| 15 | 15 | comments: [] |
| @@ -6,10 +6,10 @@ author: | |||
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-10-06T03:58:37.611Z | 8 | createdAt: 2026-10-06T03:58:37.611Z |
| 9 | -updatedAt: 2026-10-22T17:11:08.086Z | 9 | +updatedAt: 2026-10-25T04:15:36.796Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | milestone: v1.0.1 | 11 | milestone: v1.0.1 |
| 12 | -epic: Providers (LLM Engine) | 12 | +epic: Providers |
| 13 | body: "" | 13 | body: "" |
| 14 | tasks: [] | 14 | tasks: [] |
| 15 | comments: [] | 15 | comments: [] |
added
.tickets/issues/0142-memory-how-it-works.yaml +76 -0 | new file mode 100644 | ||
| @@ -0,0 +1,76 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 142 | |
| 3 | +title: "Memory: how it works ?" | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-24T11:48:07.733Z | |
| 9 | +updatedAt: 2026-10-24T14:00:00.000Z | |
| 10 | +labels: [] | |
| 11 | +milestone: v1.0.1 | |
| 12 | +body: | | |
| 13 | + How mm keeps things in the conversation history ("memory"), answered from the | |
| 14 | + code on 2026-10-24. Nothing changed yet; candidate for a docs page. | |
| 15 | + | |
| 16 | + ## Skills in the history: does a used skill disappear? | |
| 17 | + | |
| 18 | + No. Three pieces, each kept differently: | |
| 19 | + | |
| 20 | + 1. The catalogue (name, description, up to 8 keywords per skill) is the | |
| 21 | + DESCRIPTION of the `read_skill` tool (`internal/skills/skills.go`, | |
| 22 | + `Catalogue`), not a system-prompt paragraph. It goes out with every | |
| 23 | + request, is never a message, never compressed, and is paid for on every | |
| 24 | + turn (hence `maxKeywords`). | |
| 25 | + 2. `$greetings Bob`, or a skill picked by the decider, appends a line to the | |
| 26 | + USER message (`internal/skills/refs.go`, `internal/decide/route.go`): | |
| 27 | + `[skill: greetings — load it with read_skill and carry out its steps now; parameters: Bob]`. | |
| 28 | + It stays in the history like the rest of the question. | |
| 29 | + 3. The skill's markdown enters the history as the `read_skill` TOOL RESPONSE, | |
| 30 | + truncated at `maxOutput` (16000 by default). The user only sees | |
| 31 | + `📖 read_skill: greetings`. | |
| 32 | + | |
| 33 | + How long it stays: | |
| 34 | + | |
| 35 | + - Next turns, no compression: as is, re-read on every request. The model may | |
| 36 | + still call `read_skill` again, which adds a second copy. | |
| 37 | + - Automatic compression (`context.enabled`, false by default) or `/compact`: | |
| 38 | + the last `keepLastTurns` (3) question turns stay raw; older turns, their | |
| 39 | + `read_skill` calls included, become the summary. The skill text is gone, at | |
| 40 | + best mentioned in the notes; the catalogue is still there, so it can be | |
| 41 | + reloaded. | |
| 42 | + - `/new`, `/quit`: history emptied. `mm -p`: one question, nothing persists. | |
| 43 | + | |
| 44 | + docs/*/explanation/context-compression.md already says that every bash | |
| 45 | + output and every loaded skill stay until `/quit`. Consequence: several skills | |
| 46 | + loaded over a long session fill the window; on a local model, a reason to | |
| 47 | + turn `context.enabled` on. | |
| 48 | + | |
| 49 | + ## Sessions on: does ↑ reload the whole history? | |
| 50 | + | |
| 51 | + No. ↑ (window only, `sessions.enabled: true`) puts the TEXT of a past | |
| 52 | + question in the input box (`internal/tui/recall.go`, | |
| 53 | + `internal/store/questions.go` `Keeper.Questions`): the current session's | |
| 54 | + questions first, then the project's other stored sessions, newest first, 200 | |
| 55 | + at most. Sent, it is a new question in the CURRENT conversation; the model | |
| 56 | + sees none of the old answers, tool outputs or loaded skills. | |
| 57 | + | |
| 58 | + - A recalled question is what the model read: with its `[attached file: …]` | |
| 59 | + lines and pastes in full. Left out: a hook's context, `/compact` summaries, | |
| 60 | + mm's notes, `/` commands. | |
| 61 | + - Without sessions, ↑ scrolls the conversation. | |
| 62 | + | |
| 63 | + What does reload a conversation: | |
| 64 | + | |
| 65 | + | Action | Model history | | |
| 66 | + |---|---| | |
| 67 | + | starting `mm` | a NEW empty session; never resumes the last one by itself | | |
| 68 | + | ↑ | untouched, only the input box changes | | |
| 69 | + | `/resume [id]` | ALL the session's messages (questions, answers, tool calls, loaded skills); today's system prompt and AGENTS.md | | |
| 70 | + | `session/load` (ACP) | the same, replayed to the editor | | |
| 71 | + | `/new` | emptied, new file | | |
| 72 | + | |
| 73 | + So a skill loaded in an old session comes back with `/resume`, as a tool | |
| 74 | + result in the history. | |
| 75 | +tasks: [] | |
| 76 | +comments: [] | |
| new file mode 100644 | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 142 | ||
| 3 | +title: "Memory: how it works ?" | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-24T11:48:07.733Z | ||
| 9 | +updatedAt: 2026-10-24T14:00:00.000Z | ||
| 10 | +labels: [] | ||
| 11 | +milestone: v1.0.1 | ||
| 12 | +body: | | ||
| 13 | + How mm keeps things in the conversation history ("memory"), answered from the | ||
| 14 | + code on 2026-10-24. Nothing changed yet; candidate for a docs page. | ||
| 15 | + | ||
| 16 | + ## Skills in the history: does a used skill disappear? | ||
| 17 | + | ||
| 18 | + No. Three pieces, each kept differently: | ||
| 19 | + | ||
| 20 | + 1. The catalogue (name, description, up to 8 keywords per skill) is the | ||
| 21 | + DESCRIPTION of the `read_skill` tool (`internal/skills/skills.go`, | ||
| 22 | + `Catalogue`), not a system-prompt paragraph. It goes out with every | ||
| 23 | + request, is never a message, never compressed, and is paid for on every | ||
| 24 | + turn (hence `maxKeywords`). | ||
| 25 | + 2. `$greetings Bob`, or a skill picked by the decider, appends a line to the | ||
| 26 | + USER message (`internal/skills/refs.go`, `internal/decide/route.go`): | ||
| 27 | + `[skill: greetings — load it with read_skill and carry out its steps now; parameters: Bob]`. | ||
| 28 | + It stays in the history like the rest of the question. | ||
| 29 | + 3. The skill's markdown enters the history as the `read_skill` TOOL RESPONSE, | ||
| 30 | + truncated at `maxOutput` (16000 by default). The user only sees | ||
| 31 | + `📖 read_skill: greetings`. | ||
| 32 | + | ||
| 33 | + How long it stays: | ||
| 34 | + | ||
| 35 | + - Next turns, no compression: as is, re-read on every request. The model may | ||
| 36 | + still call `read_skill` again, which adds a second copy. | ||
| 37 | + - Automatic compression (`context.enabled`, false by default) or `/compact`: | ||
| 38 | + the last `keepLastTurns` (3) question turns stay raw; older turns, their | ||
| 39 | + `read_skill` calls included, become the summary. The skill text is gone, at | ||
| 40 | + best mentioned in the notes; the catalogue is still there, so it can be | ||
| 41 | + reloaded. | ||
| 42 | + - `/new`, `/quit`: history emptied. `mm -p`: one question, nothing persists. | ||
| 43 | + | ||
| 44 | + docs/*/explanation/context-compression.md already says that every bash | ||
| 45 | + output and every loaded skill stay until `/quit`. Consequence: several skills | ||
| 46 | + loaded over a long session fill the window; on a local model, a reason to | ||
| 47 | + turn `context.enabled` on. | ||
| 48 | + | ||
| 49 | + ## Sessions on: does ↑ reload the whole history? | ||
| 50 | + | ||
| 51 | + No. ↑ (window only, `sessions.enabled: true`) puts the TEXT of a past | ||
| 52 | + question in the input box (`internal/tui/recall.go`, | ||
| 53 | + `internal/store/questions.go` `Keeper.Questions`): the current session's | ||
| 54 | + questions first, then the project's other stored sessions, newest first, 200 | ||
| 55 | + at most. Sent, it is a new question in the CURRENT conversation; the model | ||
| 56 | + sees none of the old answers, tool outputs or loaded skills. | ||
| 57 | + | ||
| 58 | + - A recalled question is what the model read: with its `[attached file: …]` | ||
| 59 | + lines and pastes in full. Left out: a hook's context, `/compact` summaries, | ||
| 60 | + mm's notes, `/` commands. | ||
| 61 | + - Without sessions, ↑ scrolls the conversation. | ||
| 62 | + | ||
| 63 | + What does reload a conversation: | ||
| 64 | + | ||
| 65 | + | Action | Model history | | ||
| 66 | + |---|---| | ||
| 67 | + | starting `mm` | a NEW empty session; never resumes the last one by itself | | ||
| 68 | + | ↑ | untouched, only the input box changes | | ||
| 69 | + | `/resume [id]` | ALL the session's messages (questions, answers, tool calls, loaded skills); today's system prompt and AGENTS.md | | ||
| 70 | + | `session/load` (ACP) | the same, replayed to the editor | | ||
| 71 | + | `/new` | emptied, new file | | ||
| 72 | + | ||
| 73 | + So a skill loaded in an old session comes back with `/resume`, as a tool | ||
| 74 | + result in the history. | ||
| 75 | +tasks: [] | ||
| 76 | +comments: [] | ||
added
.tickets/issues/0143-improve-management-of-the-skills-in-memory.yaml +92 -0 | new file mode 100644 | ||
| @@ -0,0 +1,92 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 143 | |
| 3 | +title: Improve management of the skills in memory | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-24T11:49:03.667Z | |
| 9 | +updatedAt: 2026-10-24T15:00:00.000Z | |
| 10 | +labels: [] | |
| 11 | +milestone: v1.0.1 | |
| 12 | +related: | |
| 13 | + - 142 | |
| 14 | + - 53 | |
| 15 | +body: | | |
| 16 | + Should a loaded skill stay in the history, be removed, or be removed when the | |
| 17 | + context is compressed? Reflection of 2026-10-24, nothing implemented or | |
| 18 | + measured yet. How it works today: see ticket 142. | |
| 19 | + | |
| 20 | + ## Facts it rests on (checked in the code) | |
| 21 | + | |
| 22 | + - A skill's markdown enters the history as the `read_skill` tool response | |
| 23 | + (truncated at `maxOutput`) and stays until `/new`, `/quit` or a | |
| 24 | + compression. The catalogue is the tool description, sent every request, | |
| 25 | + so a skill can ALWAYS be loaded again. | |
| 26 | + - Size: the repo's skills go from 0.4 KB (what-time-is-it) to 12.5 KB | |
| 27 | + (plan-manager), i.e. ~100 to ~3000 tokens each, against 8k–32k windows on | |
| 28 | + the local models mm targets. | |
| 29 | + - Compression (`internal/compact`) already drops the skill text of the old | |
| 30 | + turns, but its summary prompt has no section for skills: after a | |
| 31 | + compression the model is not told which procedure it was following. | |
| 32 | + - llama.cpp reuses the prompt prefix between requests. Rewriting an OLD | |
| 33 | + message makes it re-read everything after it (ticket 53 measured | |
| 34 | + ~3,400–3,900 tokens / 7–9 s per re-read on a 12B). A compression rewrites | |
| 35 | + everything anyway, so it is the free moment to change the history. | |
| 36 | + - The loop detector keeps a sliding list of actions (reset by `/new` and | |
| 37 | + `/resume`); a skill reloaded on a later turn may count as a repeat — to | |
| 38 | + check before relying on reloads. | |
| 39 | + | |
| 40 | + ## The three options | |
| 41 | + | |
| 42 | + 1. Keep it (today). + multi-turn procedures keep working ("do X", "now fix", | |
| 43 | + "and test" all read the same steps); + the prefix cache is never broken; | |
| 44 | + + a resumed session holds it. − every turn pays for it; − loading the | |
| 45 | + same skill twice stores it twice; − several skills in a long session fill | |
| 46 | + the window and trigger compressions sooner. | |
| 47 | + 2. Remove it after the turn (replace the tool response with a stub such as | |
| 48 | + `[skill greetings was loaded here; call read_skill again to follow it]`). | |
| 49 | + + the cheapest history. − breaks the follow-up turns of a multi-step | |
| 50 | + skill: a small model may NOT reload and improvise instead (mm already | |
| 51 | + added `📖 0 skill(s)` and decider skill routing because models skip | |
| 52 | + read_skill); − every reload costs one | |
| 53 | + more tool round trip; − the session file and the ACP replay show a stub, | |
| 54 | + not what the model read. Rewriting just after the turn is cheap for the | |
| 55 | + cache (only the turn's tail is re-read); doing it later is not. | |
| 56 | + 3. Remove it at compression only (today's behaviour) — but then say so. | |
| 57 | + + no cache cost, the only moment the history is rewritten anyway; + the | |
| 58 | + recent turns (`keepLastTurns`) keep their skills, which is where a | |
| 59 | + procedure is usually still running. − without compression on | |
| 60 | + (`context.enabled` is false by default) nothing is ever removed. | |
| 61 | + | |
| 62 | + ## Recommendation | |
| 63 | + | |
| 64 | + Option 3 as the rule, plus two small changes, and no option 2 by default: | |
| 65 | + | |
| 66 | + a. At compression, the summary pair gets a line written BY THE CODE (not by | |
| 67 | + the summarizer, so it cannot be forgotten): the skills loaded in the | |
| 68 | + compressed turns, e.g. `Skills used before this summary: go-rename, | |
| 69 | + bg-jobs — call read_skill again to follow one.` Optionally a `## Skills` | |
| 70 | + section in DefaultPrompt saying which one was in progress and at which | |
| 71 | + step. | |
| 72 | + b. Dedup at load time instead of rewriting the past: when `read_skill` is | |
| 73 | + asked for a skill whose full text is still in the (uncompressed) history, | |
| 74 | + answer `[skill X is already loaded above; follow it]` instead of a second | |
| 75 | + copy. No old message changes, so no cache cost. Risk: a small model may | |
| 76 | + attend poorly to a copy far up — measure before making it the default; | |
| 77 | + a skill edited on disk since the first load must get the new text. | |
| 78 | + c. Option 2 only as an opt-in setting, for very small windows (e.g. | |
| 79 | + `skills.keep: session | turn`, default `session`), and only if a | |
| 80 | + measurement shows a gain. | |
| 81 | + | |
| 82 | + ## To measure before deciding | |
| 83 | + | |
| 84 | + - Multi-turn skill (e.g. a 3-step procedure over 3 questions) with options | |
| 85 | + 1/2/3 on Qwen3.5-4B: does the model finish the steps, does it reload? | |
| 86 | + - Token cost per turn of options 1 and b on a session loading the same skill | |
| 87 | + 3 times (server `input_tokens`). | |
| 88 | + - After a compression, with and without line a: does the model reload the | |
| 89 | + skill it was following? | |
| 90 | + - Whether the loop detector fires on a reload across turns. | |
| 91 | +tasks: [] | |
| 92 | +comments: [] | |
| new file mode 100644 | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 143 | ||
| 3 | +title: Improve management of the skills in memory | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-24T11:49:03.667Z | ||
| 9 | +updatedAt: 2026-10-24T15:00:00.000Z | ||
| 10 | +labels: [] | ||
| 11 | +milestone: v1.0.1 | ||
| 12 | +related: | ||
| 13 | + - 142 | ||
| 14 | + - 53 | ||
| 15 | +body: | | ||
| 16 | + Should a loaded skill stay in the history, be removed, or be removed when the | ||
| 17 | + context is compressed? Reflection of 2026-10-24, nothing implemented or | ||
| 18 | + measured yet. How it works today: see ticket 142. | ||
| 19 | + | ||
| 20 | + ## Facts it rests on (checked in the code) | ||
| 21 | + | ||
| 22 | + - A skill's markdown enters the history as the `read_skill` tool response | ||
| 23 | + (truncated at `maxOutput`) and stays until `/new`, `/quit` or a | ||
| 24 | + compression. The catalogue is the tool description, sent every request, | ||
| 25 | + so a skill can ALWAYS be loaded again. | ||
| 26 | + - Size: the repo's skills go from 0.4 KB (what-time-is-it) to 12.5 KB | ||
| 27 | + (plan-manager), i.e. ~100 to ~3000 tokens each, against 8k–32k windows on | ||
| 28 | + the local models mm targets. | ||
| 29 | + - Compression (`internal/compact`) already drops the skill text of the old | ||
| 30 | + turns, but its summary prompt has no section for skills: after a | ||
| 31 | + compression the model is not told which procedure it was following. | ||
| 32 | + - llama.cpp reuses the prompt prefix between requests. Rewriting an OLD | ||
| 33 | + message makes it re-read everything after it (ticket 53 measured | ||
| 34 | + ~3,400–3,900 tokens / 7–9 s per re-read on a 12B). A compression rewrites | ||
| 35 | + everything anyway, so it is the free moment to change the history. | ||
| 36 | + - The loop detector keeps a sliding list of actions (reset by `/new` and | ||
| 37 | + `/resume`); a skill reloaded on a later turn may count as a repeat — to | ||
| 38 | + check before relying on reloads. | ||
| 39 | + | ||
| 40 | + ## The three options | ||
| 41 | + | ||
| 42 | + 1. Keep it (today). + multi-turn procedures keep working ("do X", "now fix", | ||
| 43 | + "and test" all read the same steps); + the prefix cache is never broken; | ||
| 44 | + + a resumed session holds it. − every turn pays for it; − loading the | ||
| 45 | + same skill twice stores it twice; − several skills in a long session fill | ||
| 46 | + the window and trigger compressions sooner. | ||
| 47 | + 2. Remove it after the turn (replace the tool response with a stub such as | ||
| 48 | + `[skill greetings was loaded here; call read_skill again to follow it]`). | ||
| 49 | + + the cheapest history. − breaks the follow-up turns of a multi-step | ||
| 50 | + skill: a small model may NOT reload and improvise instead (mm already | ||
| 51 | + added `📖 0 skill(s)` and decider skill routing because models skip | ||
| 52 | + read_skill); − every reload costs one | ||
| 53 | + more tool round trip; − the session file and the ACP replay show a stub, | ||
| 54 | + not what the model read. Rewriting just after the turn is cheap for the | ||
| 55 | + cache (only the turn's tail is re-read); doing it later is not. | ||
| 56 | + 3. Remove it at compression only (today's behaviour) — but then say so. | ||
| 57 | + + no cache cost, the only moment the history is rewritten anyway; + the | ||
| 58 | + recent turns (`keepLastTurns`) keep their skills, which is where a | ||
| 59 | + procedure is usually still running. − without compression on | ||
| 60 | + (`context.enabled` is false by default) nothing is ever removed. | ||
| 61 | + | ||
| 62 | + ## Recommendation | ||
| 63 | + | ||
| 64 | + Option 3 as the rule, plus two small changes, and no option 2 by default: | ||
| 65 | + | ||
| 66 | + a. At compression, the summary pair gets a line written BY THE CODE (not by | ||
| 67 | + the summarizer, so it cannot be forgotten): the skills loaded in the | ||
| 68 | + compressed turns, e.g. `Skills used before this summary: go-rename, | ||
| 69 | + bg-jobs — call read_skill again to follow one.` Optionally a `## Skills` | ||
| 70 | + section in DefaultPrompt saying which one was in progress and at which | ||
| 71 | + step. | ||
| 72 | + b. Dedup at load time instead of rewriting the past: when `read_skill` is | ||
| 73 | + asked for a skill whose full text is still in the (uncompressed) history, | ||
| 74 | + answer `[skill X is already loaded above; follow it]` instead of a second | ||
| 75 | + copy. No old message changes, so no cache cost. Risk: a small model may | ||
| 76 | + attend poorly to a copy far up — measure before making it the default; | ||
| 77 | + a skill edited on disk since the first load must get the new text. | ||
| 78 | + c. Option 2 only as an opt-in setting, for very small windows (e.g. | ||
| 79 | + `skills.keep: session | turn`, default `session`), and only if a | ||
| 80 | + measurement shows a gain. | ||
| 81 | + | ||
| 82 | + ## To measure before deciding | ||
| 83 | + | ||
| 84 | + - Multi-turn skill (e.g. a 3-step procedure over 3 questions) with options | ||
| 85 | + 1/2/3 on Qwen3.5-4B: does the model finish the steps, does it reload? | ||
| 86 | + - Token cost per turn of options 1 and b on a session loading the same skill | ||
| 87 | + 3 times (server `input_tokens`). | ||
| 88 | + - After a compression, with and without line a: does the model reload the | ||
| 89 | + skill it was following? | ||
| 90 | + - Whether the loop detector fires on a reload across turns. | ||
| 91 | +tasks: [] | ||
| 92 | +comments: [] | ||
added
.tickets/issues/0144-when-you-use-memory-how-to-use-the-result.yaml +58 -0 | new file mode 100644 | ||
| @@ -0,0 +1,58 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 144 | |
| 3 | +title: When you use /memory how to use the result | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-24T16:59:56.623Z | |
| 9 | +updatedAt: 2026-10-24T17:30:00.000Z | |
| 10 | +labels: [] | |
| 11 | +milestone: v1.0.1 | |
| 12 | +related: | |
| 13 | + - 48 | |
| 14 | + - 142 | |
| 15 | +body: | | |
| 16 | + How to use what `/memory <words>` finds. Answered from the docs on | |
| 17 | + 2026-10-24 (docs/*/how-to/search-earlier-sessions.md, the slash-commands | |
| 18 | + reference); nothing changed yet. | |
| 19 | + | |
| 20 | + `/memory` is display-only: the model is not called and the history is not | |
| 21 | + touched, so the model never sees the hits. Three ways to use one: | |
| 22 | + | |
| 23 | + 1. Resume the conversation it comes from. Each hit starts with its session | |
| 24 | + id: | |
| 25 | + | |
| 26 | + 🔎 2 hit(s) for "port api" in /work/project/.mm/sessions | |
| 27 | + 20261010-090000-aaaaaaaa · 2026-10-10 09:30 · turn 1 · question | |
| 28 | + Which port should the API server listen on? | |
| 29 | + → Let's use port 8417 for the API server: 8080 is already taken by the admin UI. | |
| 30 | + | |
| 31 | + `/resume 20261010-090000-aaaaaaaa` reloads that whole conversation | |
| 32 | + (terminal and window; in an editor, through its session list, | |
| 33 | + `session/load`). | |
| 34 | + 2. Quote the passage in the next question, keeping the current | |
| 35 | + conversation: `We decided "port 8417 for the API server". Write | |
| 36 | + config.go with that port.` Simplest when one decision matters. Not | |
| 37 | + checked: whether `/copy` / Ctrl-Y copy a `/memory` output — they copy the | |
| 38 | + last model ANSWER. | |
| 39 | + 3. Let the model search: `sessions.autoSearchMemory: true` declares | |
| 40 | + `search_memory`; "write config.go with the port agreed last time" makes | |
| 41 | + the model call it, and the hits enter the history as a tool result. | |
| 42 | + `searchMemory` (the command) and `autoSearchMemory` (the tool) are | |
| 43 | + independent. | |
| 44 | + | |
| 45 | + Limits: words, not meanings (use the words actually written, often | |
| 46 | + English); the conversation in progress and tool calls are not searched — | |
| 47 | + questions, answers and `/compact` summaries are. | |
| 48 | + | |
| 49 | + ## Possible improvements (not decided) | |
| 50 | + | |
| 51 | + - A way to hand a hit to the model without retyping it, e.g. `/memory` | |
| 52 | + followed by a pick (`/memory use 2`) that adds the hit, as quoted context, | |
| 53 | + to the next question — like `@path` does for a file. | |
| 54 | + - Make `/copy` able to copy the last `/memory` output (check first what it | |
| 55 | + does today). | |
| 56 | + - Say in the `/memory` output itself how to use it (`/resume <id>` hint). | |
| 57 | +tasks: [] | |
| 58 | +comments: [] | |
| new file mode 100644 | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 144 | ||
| 3 | +title: When you use /memory how to use the result | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-24T16:59:56.623Z | ||
| 9 | +updatedAt: 2026-10-24T17:30:00.000Z | ||
| 10 | +labels: [] | ||
| 11 | +milestone: v1.0.1 | ||
| 12 | +related: | ||
| 13 | + - 48 | ||
| 14 | + - 142 | ||
| 15 | +body: | | ||
| 16 | + How to use what `/memory <words>` finds. Answered from the docs on | ||
| 17 | + 2026-10-24 (docs/*/how-to/search-earlier-sessions.md, the slash-commands | ||
| 18 | + reference); nothing changed yet. | ||
| 19 | + | ||
| 20 | + `/memory` is display-only: the model is not called and the history is not | ||
| 21 | + touched, so the model never sees the hits. Three ways to use one: | ||
| 22 | + | ||
| 23 | + 1. Resume the conversation it comes from. Each hit starts with its session | ||
| 24 | + id: | ||
| 25 | + | ||
| 26 | + 🔎 2 hit(s) for "port api" in /work/project/.mm/sessions | ||
| 27 | + 20261010-090000-aaaaaaaa · 2026-10-10 09:30 · turn 1 · question | ||
| 28 | + Which port should the API server listen on? | ||
| 29 | + → Let's use port 8417 for the API server: 8080 is already taken by the admin UI. | ||
| 30 | + | ||
| 31 | + `/resume 20261010-090000-aaaaaaaa` reloads that whole conversation | ||
| 32 | + (terminal and window; in an editor, through its session list, | ||
| 33 | + `session/load`). | ||
| 34 | + 2. Quote the passage in the next question, keeping the current | ||
| 35 | + conversation: `We decided "port 8417 for the API server". Write | ||
| 36 | + config.go with that port.` Simplest when one decision matters. Not | ||
| 37 | + checked: whether `/copy` / Ctrl-Y copy a `/memory` output — they copy the | ||
| 38 | + last model ANSWER. | ||
| 39 | + 3. Let the model search: `sessions.autoSearchMemory: true` declares | ||
| 40 | + `search_memory`; "write config.go with the port agreed last time" makes | ||
| 41 | + the model call it, and the hits enter the history as a tool result. | ||
| 42 | + `searchMemory` (the command) and `autoSearchMemory` (the tool) are | ||
| 43 | + independent. | ||
| 44 | + | ||
| 45 | + Limits: words, not meanings (use the words actually written, often | ||
| 46 | + English); the conversation in progress and tool calls are not searched — | ||
| 47 | + questions, answers and `/compact` summaries are. | ||
| 48 | + | ||
| 49 | + ## Possible improvements (not decided) | ||
| 50 | + | ||
| 51 | + - A way to hand a hit to the model without retyping it, e.g. `/memory` | ||
| 52 | + followed by a pick (`/memory use 2`) that adds the hit, as quoted context, | ||
| 53 | + to the next question — like `@path` does for a file. | ||
| 54 | + - Make `/copy` able to copy the last `/memory` output (check first what it | ||
| 55 | + does today). | ||
| 56 | + - Say in the `/memory` output itself how to use it (`/resume <id>` hint). | ||
| 57 | +tasks: [] | ||
| 58 | +comments: [] | ||
added
.tickets/issues/0145-oss-closed-source-and-commercial-modules.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: 145 | |
| 3 | +title: OSS, Closed source and commercial modules [???] | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:19:37.267Z | |
| 9 | +updatedAt: 2026-10-25T04:19:49.790Z | |
| 10 | +labels: | |
| 11 | + - question | |
| 12 | +epic: WASM Module | |
| 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: 145 | ||
| 3 | +title: OSS, Closed source and commercial modules [???] | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:19:37.267Z | ||
| 9 | +updatedAt: 2026-10-25T04:19:49.790Z | ||
| 10 | +labels: | ||
| 11 | + - question | ||
| 12 | +epic: WASM Module | ||
| 13 | +body: "" | ||
| 14 | +tasks: [] | ||
| 15 | +comments: [] | ||
added
.tickets/issues/0146-pii-module-in-and-out.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: 146 | |
| 3 | +title: PII module (in and out) | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:20:26.498Z | |
| 9 | +updatedAt: 2026-10-25T04:20:26.498Z | |
| 10 | +labels: [] | |
| 11 | +epic: WASM Module | |
| 12 | +body: "" | |
| 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: 146 | ||
| 3 | +title: PII module (in and out) | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:20:26.498Z | ||
| 9 | +updatedAt: 2026-10-25T04:20:26.498Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: WASM Module | ||
| 12 | +body: "" | ||
| 13 | +tasks: [] | ||
| 14 | +comments: [] | ||
added
.tickets/issues/0147-secrets-modules-i-m-not-sure-it-s-even-possible.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: 147 | |
| 3 | +title: Secrets modules (I'm not sure it's even possible) | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:21:21.430Z | |
| 9 | +updatedAt: 2026-10-25T04:27:06.279Z | |
| 10 | +labels: [] | |
| 11 | +epic: WASM Module | |
| 12 | +body: | | |
| 13 | + Secrets detection | |
| 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: 147 | ||
| 3 | +title: Secrets modules (I'm not sure it's even possible) | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:21:21.430Z | ||
| 9 | +updatedAt: 2026-10-25T04:27:06.279Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: WASM Module | ||
| 12 | +body: | | ||
| 13 | + Secrets detection | ||
| 14 | +tasks: [] | ||
| 15 | +comments: [] | ||
added
.tickets/issues/0148-prompt-injection-module.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: 148 | |
| 3 | +title: Prompt injection module | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:22:10.628Z | |
| 9 | +updatedAt: 2026-10-25T04:22:10.628Z | |
| 10 | +labels: [] | |
| 11 | +epic: WASM Module | |
| 12 | +body: "" | |
| 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: 148 | ||
| 3 | +title: Prompt injection module | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:22:10.628Z | ||
| 9 | +updatedAt: 2026-10-25T04:22:10.628Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: WASM Module | ||
| 12 | +body: "" | ||
| 13 | +tasks: [] | ||
| 14 | +comments: [] | ||
added
.tickets/issues/0149-safety-module.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: 149 | |
| 3 | +title: Safety module | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:22:22.136Z | |
| 9 | +updatedAt: 2026-10-25T04:22:22.136Z | |
| 10 | +labels: [] | |
| 11 | +epic: WASM Module | |
| 12 | +body: "" | |
| 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: 149 | ||
| 3 | +title: Safety module | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:22:22.136Z | ||
| 9 | +updatedAt: 2026-10-25T04:22:22.136Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: WASM Module | ||
| 12 | +body: "" | ||
| 13 | +tasks: [] | ||
| 14 | +comments: [] | ||
added
.tickets/issues/0150-blog-post-to-explain-how-to-create-a-wam-hook.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: 150 | |
| 3 | +title: Blog post to explain how to create a wam hook | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:23:22.576Z | |
| 9 | +updatedAt: 2026-10-25T04:23:22.576Z | |
| 10 | +labels: [] | |
| 11 | +epic: WASM Module | |
| 12 | +body: "" | |
| 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: 150 | ||
| 3 | +title: Blog post to explain how to create a wam hook | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:23:22.576Z | ||
| 9 | +updatedAt: 2026-10-25T04:23:22.576Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: WASM Module | ||
| 12 | +body: "" | ||
| 13 | +tasks: [] | ||
| 14 | +comments: [] | ||
added
.tickets/issues/0151-blog-post-to-explain-how-to-create-a-wasm-declar.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: 151 | |
| 3 | +title: Blog post to explain how to create a wasm declared tool | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:23:41.209Z | |
| 9 | +updatedAt: 2026-10-25T04:23:41.209Z | |
| 10 | +labels: [] | |
| 11 | +epic: WASM Module | |
| 12 | +body: "" | |
| 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: 151 | ||
| 3 | +title: Blog post to explain how to create a wasm declared tool | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:23:41.209Z | ||
| 9 | +updatedAt: 2026-10-25T04:23:41.209Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: WASM Module | ||
| 12 | +body: "" | ||
| 13 | +tasks: [] | ||
| 14 | +comments: [] | ||
added
.tickets/issues/0152-dev-team.yaml +174 -0 | new file mode 100644 | ||
| @@ -0,0 +1,174 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 152 | |
| 3 | +title: Dev team | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-25T04:44:30.351Z | |
| 9 | +updatedAt: 2026-10-25T05:15:11.308Z | |
| 10 | +labels: [] | |
| 11 | +epic: Demos | |
| 12 | +body: |+ | |
| 13 | + ### Objectifs | |
| 14 | + | |
| 15 | + Faire une équipe d'agents (sur le même principe que les projets dans ./demos) qui permettrait d'aider à coder. | |
| 16 | + | |
| 17 | + | |
| 18 | + ### Contraintes | |
| 19 | + | |
| 20 | + - On reste avec des modèles de taille raisonnable (on pense à un MacBook air et 32 GB RAM), il faudra aussi en tenir compte pour les réglages. | |
| 21 | + - lorsque l'on change d'agent (ou revient à l'agent principal), on décharge de la mémoire le modèle en cours (toujours parce qu l'on est sur une machine limitée en mémoire). | |
| 22 | + - Dossier de travail: ./dev.team | |
| 23 | + - Tout ce que tu génères (config, noms, ...) est en anglais | |
| 24 | + - Le nom des agents qui s'affiche dans le header de la TUI doit commencer par un emojii | |
| 25 | + | |
| 26 | + ### Agents | |
| 27 | + | |
| 28 | + - Un coordinateur | |
| 29 | + - Un reformulateur (qui peut aussi poser des question à l'utilisateur) pour améliorer les demande de l'utilisateurs pour le reste de l'équipe | |
| 30 | + - un prof (pour demander des conseils, des lecons, ...) sur le même principe que la configuration mis dans le commentaire "### prof" | |
| 31 | + - un codeur | |
| 32 | + - un reviewer/testeur | |
| 33 | + | |
| 34 | + ### Modèles | |
| 35 | + | |
| 36 | + - unsloth/gemma-4-12b-it-GGUF pour reformmulateur et reviewer/testeur | |
| 37 | + - JetBrains/Mellum2-12B-A2.5B-Instruct-GGUF-Q4_K_M pour prof et codeur | |
| 38 | + - unsloth/Qwen3.5-4B-GGUF pour le coordinateur | |
| 39 | + | |
| 40 | + | |
| 41 | + ### Consignes | |
| 42 | + | |
| 43 | + - pour chaque tu te poseras la question: quels sont les outils appropriés à activer (prompt, ask_user, ...) | |
| 44 | + - tu as le droit de remettre en question mes choix de modèles | |
| 45 | + - tu documenteras cette demo (dans son dossier) (et créeras des fancy diagrams pour expliquer tous les fonctionnements) | |
| 46 | + - tu donneras des exemples d'utilisation pour permettre de tester les agents | |
| 47 | + | |
| 48 | + | |
| 49 | + ### Questions à te poser | |
| 50 | + | |
| 51 | + - a-t-on besoin d'utiliser un modèle de décision ? Si oui dans quels cas et pourquoi ? | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | +tasks: [] | |
| 57 | +comments: | |
| 58 | + - id: 1 | |
| 59 | + author: | |
| 60 | + name: k33g | |
| 61 | + email: ph.charriere@gmail.com | |
| 62 | + createdAt: 2026-10-25T04:56:03.359Z | |
| 63 | + body: | | |
| 64 | + ### prof | |
| 65 | + | |
| 66 | + ```yaml | |
| 67 | + # Tuto — an agent that answers with mini tutorials | |
| 68 | + provider: llmman | |
| 69 | + #model: hf.co/JetBrains/Mellum2.1-12B-A2.5B-Thinking-GGUF:Q4_K_M | |
| 70 | + model: hf.co/JetBrains/Mellum2-12B-A2.5B-Instruct-GGUF-Q8_0:Q8_0 | |
| 71 | + baseUrl: http://127.0.0.1:17434/v1 | |
| 72 | + fallback: http://host.docker.internal:17434/v1 | |
| 73 | + | |
| 74 | + # mm's budget for compression; llmman served 131072 during the measurements. | |
| 75 | + contextWindow: 32768 | |
| 76 | + | |
| 77 | + sampling: | |
| 78 | + # Explanations, not code edits: a little more freedom than a coder's 0.2, | |
| 79 | + # never 0.0 with reasoning on (thinking models loop when greedy). | |
| 80 | + temperature: 0.3 | |
| 81 | + top_p: 0.9 | |
| 82 | + # Measured in wip/: 16384 holds the reasoning plus a long answer; 24576 made | |
| 83 | + # things worse (the model reasons longer). | |
| 84 | + max_tokens: 16384 | |
| 85 | + parallel_tool_calls: false | |
| 86 | + # The template's only reasoning switch (no effort level — see wip/README). | |
| 87 | + chat_template_kwargs: | |
| 88 | + enable_thinking: false | |
| 89 | + | |
| 90 | + showThinking: true | |
| 91 | + firstTokenTimeout: 3m | |
| 92 | + watchdogTimeout: 2m | |
| 93 | + | |
| 94 | + # A mini tutorial is one answer, maybe after one fetch, maybe one save. | |
| 95 | + maxTurns: 8 | |
| 96 | + maxOutput: 8000 | |
| 97 | + previewLines: 10 | |
| 98 | + | |
| 99 | + # ─── Tools: the documentation, and saving on request ───────────────────────── | |
| 100 | + yolo: true | |
| 101 | + bashTool: true # change: 2026 10 21 | |
| 102 | + editTools: true # change: 2026 10 21 | |
| 103 | + planTool: false | |
| 104 | + askUserTool: false | |
| 105 | + fetchContentTool: true | |
| 106 | + saveAnswerTool: true | |
| 107 | + skillsDir: no-skills | |
| 108 | + | |
| 109 | + docSearch: | |
| 110 | + #searchDocs: true | |
| 111 | + autoSearchDocs: true | |
| 112 | + dirs: [docs] | |
| 113 | + extensions: [.md] | |
| 114 | + maxFileSize: 1MB | |
| 115 | + | |
| 116 | + # change: 2026 10 21 | |
| 117 | + lsp: | |
| 118 | + servers: | |
| 119 | + - name: rust | |
| 120 | + command: rust-analyzer | |
| 121 | + extensions: [".rs"] | |
| 122 | + | |
| 123 | + agentsMd: | |
| 124 | + enabled: false | |
| 125 | + | |
| 126 | + sessions: | |
| 127 | + enabled: true | |
| 128 | + dir: .mm/sessions | |
| 129 | + | |
| 130 | + context: | |
| 131 | + enabled: true | |
| 132 | + threshold: 60 | |
| 133 | + keepLastTurns: 2 | |
| 134 | + summaryMaxTokens: 1200 | |
| 135 | + | |
| 136 | + acp: | |
| 137 | + name: tuto | |
| 138 | + title: 📘 Tuto | |
| 139 | + | |
| 140 | + system: | | |
| 141 | + You are Tuto. You answer questions about programming languages, shells and | |
| 142 | + developer tools with a MINI TUTORIAL, in the language of the question. | |
| 143 | + | |
| 144 | + HOW TO ANSWER | |
| 145 | + 1. Decide whether you need the documentation. Fetch ONE page with | |
| 146 | + fetch_content only when the subject is a recent or niche tool (for | |
| 147 | + example Nushell, a young framework), when the user names a version, or | |
| 148 | + when you are not sure a command or an option exists. For well-known | |
| 149 | + topics (Go, Rust, Python, Kotlin, Java basics) answer from what you know. | |
| 150 | + 2. Write the mini tutorial directly in your reply, in Markdown: | |
| 151 | + - a title (#) | |
| 152 | + - one sentence: what the reader will be able to do | |
| 153 | + - Prerequisites: a short list | |
| 154 | + - 3 to 6 numbered steps, each with a code block and, when it prints | |
| 155 | + something, the expected output | |
| 156 | + - Pitfalls: 2 or 3 short points | |
| 157 | + - To go further: one or two lines | |
| 158 | + Between 300 and 600 words. Short snippets; a complete program only when | |
| 159 | + the user asks for one. | |
| 160 | + 3. A follow-up question ("and in Go?") refers to your previous answer: | |
| 161 | + answer the same need for the new language or tool. | |
| 162 | + | |
| 163 | + SAVING TO A FILE | |
| 164 | + - Never save unless the user asks to save, write or export to a file. | |
| 165 | + - When asked, call save_answer with the file name the user gave (or a short | |
| 166 | + name made from the subject, ending in .md). Do NOT write the tutorial | |
| 167 | + again: save_answer saves your previous answer by itself — call it alone, | |
| 168 | + with no text in your reply. | |
| 169 | + - When the request is "explain X and save it", write the tutorial in your | |
| 170 | + reply AND call save_answer in that same reply. | |
| 171 | + - If save_answer says the file exists, tell the user and ask for another | |
| 172 | + name. | |
| 173 | + | |
| 174 | + ``` | |
| new file mode 100644 | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 152 | ||
| 3 | +title: Dev team | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-25T04:44:30.351Z | ||
| 9 | +updatedAt: 2026-10-25T05:15:11.308Z | ||
| 10 | +labels: [] | ||
| 11 | +epic: Demos | ||
| 12 | +body: |+ | ||
| 13 | + ### Objectifs | ||
| 14 | + | ||
| 15 | + Faire une équipe d'agents (sur le même principe que les projets dans ./demos) qui permettrait d'aider à coder. | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + ### Contraintes | ||
| 19 | + | ||
| 20 | + - On reste avec des modèles de taille raisonnable (on pense à un MacBook air et 32 GB RAM), il faudra aussi en tenir compte pour les réglages. | ||
| 21 | + - lorsque l'on change d'agent (ou revient à l'agent principal), on décharge de la mémoire le modèle en cours (toujours parce qu l'on est sur une machine limitée en mémoire). | ||
| 22 | + - Dossier de travail: ./dev.team | ||
| 23 | + - Tout ce que tu génères (config, noms, ...) est en anglais | ||
| 24 | + - Le nom des agents qui s'affiche dans le header de la TUI doit commencer par un emojii | ||
| 25 | + | ||
| 26 | + ### Agents | ||
| 27 | + | ||
| 28 | + - Un coordinateur | ||
| 29 | + - Un reformulateur (qui peut aussi poser des question à l'utilisateur) pour améliorer les demande de l'utilisateurs pour le reste de l'équipe | ||
| 30 | + - un prof (pour demander des conseils, des lecons, ...) sur le même principe que la configuration mis dans le commentaire "### prof" | ||
| 31 | + - un codeur | ||
| 32 | + - un reviewer/testeur | ||
| 33 | + | ||
| 34 | + ### Modèles | ||
| 35 | + | ||
| 36 | + - unsloth/gemma-4-12b-it-GGUF pour reformmulateur et reviewer/testeur | ||
| 37 | + - JetBrains/Mellum2-12B-A2.5B-Instruct-GGUF-Q4_K_M pour prof et codeur | ||
| 38 | + - unsloth/Qwen3.5-4B-GGUF pour le coordinateur | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + ### Consignes | ||
| 42 | + | ||
| 43 | + - pour chaque tu te poseras la question: quels sont les outils appropriés à activer (prompt, ask_user, ...) | ||
| 44 | + - tu as le droit de remettre en question mes choix de modèles | ||
| 45 | + - tu documenteras cette demo (dans son dossier) (et créeras des fancy diagrams pour expliquer tous les fonctionnements) | ||
| 46 | + - tu donneras des exemples d'utilisation pour permettre de tester les agents | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + ### Questions à te poser | ||
| 50 | + | ||
| 51 | + - a-t-on besoin d'utiliser un modèle de décision ? Si oui dans quels cas et pourquoi ? | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + | ||
| 56 | +tasks: [] | ||
| 57 | +comments: | ||
| 58 | + - id: 1 | ||
| 59 | + author: | ||
| 60 | + name: k33g | ||
| 61 | + email: ph.charriere@gmail.com | ||
| 62 | + createdAt: 2026-10-25T04:56:03.359Z | ||
| 63 | + body: | | ||
| 64 | + ### prof | ||
| 65 | + | ||
| 66 | + ```yaml | ||
| 67 | + # Tuto — an agent that answers with mini tutorials | ||
| 68 | + provider: llmman | ||
| 69 | + #model: hf.co/JetBrains/Mellum2.1-12B-A2.5B-Thinking-GGUF:Q4_K_M | ||
| 70 | + model: hf.co/JetBrains/Mellum2-12B-A2.5B-Instruct-GGUF-Q8_0:Q8_0 | ||
| 71 | + baseUrl: http://127.0.0.1:17434/v1 | ||
| 72 | + fallback: http://host.docker.internal:17434/v1 | ||
| 73 | + | ||
| 74 | + # mm's budget for compression; llmman served 131072 during the measurements. | ||
| 75 | + contextWindow: 32768 | ||
| 76 | + | ||
| 77 | + sampling: | ||
| 78 | + # Explanations, not code edits: a little more freedom than a coder's 0.2, | ||
| 79 | + # never 0.0 with reasoning on (thinking models loop when greedy). | ||
| 80 | + temperature: 0.3 | ||
| 81 | + top_p: 0.9 | ||
| 82 | + # Measured in wip/: 16384 holds the reasoning plus a long answer; 24576 made | ||
| 83 | + # things worse (the model reasons longer). | ||
| 84 | + max_tokens: 16384 | ||
| 85 | + parallel_tool_calls: false | ||
| 86 | + # The template's only reasoning switch (no effort level — see wip/README). | ||
| 87 | + chat_template_kwargs: | ||
| 88 | + enable_thinking: false | ||
| 89 | + | ||
| 90 | + showThinking: true | ||
| 91 | + firstTokenTimeout: 3m | ||
| 92 | + watchdogTimeout: 2m | ||
| 93 | + | ||
| 94 | + # A mini tutorial is one answer, maybe after one fetch, maybe one save. | ||
| 95 | + maxTurns: 8 | ||
| 96 | + maxOutput: 8000 | ||
| 97 | + previewLines: 10 | ||
| 98 | + | ||
| 99 | + # ─── Tools: the documentation, and saving on request ───────────────────────── | ||
| 100 | + yolo: true | ||
| 101 | + bashTool: true # change: 2026 10 21 | ||
| 102 | + editTools: true # change: 2026 10 21 | ||
| 103 | + planTool: false | ||
| 104 | + askUserTool: false | ||
| 105 | + fetchContentTool: true | ||
| 106 | + saveAnswerTool: true | ||
| 107 | + skillsDir: no-skills | ||
| 108 | + | ||
| 109 | + docSearch: | ||
| 110 | + #searchDocs: true | ||
| 111 | + autoSearchDocs: true | ||
| 112 | + dirs: [docs] | ||
| 113 | + extensions: [.md] | ||
| 114 | + maxFileSize: 1MB | ||
| 115 | + | ||
| 116 | + # change: 2026 10 21 | ||
| 117 | + lsp: | ||
| 118 | + servers: | ||
| 119 | + - name: rust | ||
| 120 | + command: rust-analyzer | ||
| 121 | + extensions: [".rs"] | ||
| 122 | + | ||
| 123 | + agentsMd: | ||
| 124 | + enabled: false | ||
| 125 | + | ||
| 126 | + sessions: | ||
| 127 | + enabled: true | ||
| 128 | + dir: .mm/sessions | ||
| 129 | + | ||
| 130 | + context: | ||
| 131 | + enabled: true | ||
| 132 | + threshold: 60 | ||
| 133 | + keepLastTurns: 2 | ||
| 134 | + summaryMaxTokens: 1200 | ||
| 135 | + | ||
| 136 | + acp: | ||
| 137 | + name: tuto | ||
| 138 | + title: 📘 Tuto | ||
| 139 | + | ||
| 140 | + system: | | ||
| 141 | + You are Tuto. You answer questions about programming languages, shells and | ||
| 142 | + developer tools with a MINI TUTORIAL, in the language of the question. | ||
| 143 | + | ||
| 144 | + HOW TO ANSWER | ||
| 145 | + 1. Decide whether you need the documentation. Fetch ONE page with | ||
| 146 | + fetch_content only when the subject is a recent or niche tool (for | ||
| 147 | + example Nushell, a young framework), when the user names a version, or | ||
| 148 | + when you are not sure a command or an option exists. For well-known | ||
| 149 | + topics (Go, Rust, Python, Kotlin, Java basics) answer from what you know. | ||
| 150 | + 2. Write the mini tutorial directly in your reply, in Markdown: | ||
| 151 | + - a title (#) | ||
| 152 | + - one sentence: what the reader will be able to do | ||
| 153 | + - Prerequisites: a short list | ||
| 154 | + - 3 to 6 numbered steps, each with a code block and, when it prints | ||
| 155 | + something, the expected output | ||
| 156 | + - Pitfalls: 2 or 3 short points | ||
| 157 | + - To go further: one or two lines | ||
| 158 | + Between 300 and 600 words. Short snippets; a complete program only when | ||
| 159 | + the user asks for one. | ||
| 160 | + 3. A follow-up question ("and in Go?") refers to your previous answer: | ||
| 161 | + answer the same need for the new language or tool. | ||
| 162 | + | ||
| 163 | + SAVING TO A FILE | ||
| 164 | + - Never save unless the user asks to save, write or export to a file. | ||
| 165 | + - When asked, call save_answer with the file name the user gave (or a short | ||
| 166 | + name made from the subject, ending in .md). Do NOT write the tutorial | ||
| 167 | + again: save_answer saves your previous answer by itself — call it alone, | ||
| 168 | + with no text in your reply. | ||
| 169 | + - When the request is "explain X and save it", write the tutorial in your | ||
| 170 | + reply AND call save_answer in that same reply. | ||
| 171 | + - If save_answer says the file exists, tell the user and ask for another | ||
| 172 | + name. | ||
| 173 | + | ||
| 174 | + ``` | ||
modified
docs/en/README.md +1 -0 | @@ -79,6 +79,7 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr) | ||
| 79 | 79 | |
| 80 | 80 | - [Architecture: one loop, three front ends](explanation/architecture.md) |
| 81 | 81 | - [Providers: one implementation per protocol](explanation/providers.md) |
| 82 | +- [`mm init`: where a generated agent's settings come from](explanation/mm-init.md) — the server's facts, the sourced family table, the usage profiles, the settings guide's machine rows; the order of trust, the origin tags, what was rejected | |
| 82 | 83 | - [Context compression](explanation/context-compression.md) |
| 83 | 84 | - [Persistent sessions](explanation/persistent-sessions.md) — files per project, why a start is a new session, `session/load` versus docker agent's `session/resume` |
| 84 | 85 | - [Documentation search](explanation/document-search.md) — `/docs` and `search_docs`: why BM25 and no model, why no index, passages as sections, prefixes instead of stemming |
| @@ -79,6 +79,7 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr) | |||
| 79 | 79 | ||
| 80 | - [Architecture: one loop, three front ends](explanation/architecture.md) | 80 | - [Architecture: one loop, three front ends](explanation/architecture.md) |
| 81 | - [Providers: one implementation per protocol](explanation/providers.md) | 81 | - [Providers: one implementation per protocol](explanation/providers.md) |
| 82 | +- [`mm init`: where a generated agent's settings come from](explanation/mm-init.md) — the server's facts, the sourced family table, the usage profiles, the settings guide's machine rows; the order of trust, the origin tags, what was rejected | ||
| 82 | - [Context compression](explanation/context-compression.md) | 83 | - [Context compression](explanation/context-compression.md) |
| 83 | - [Persistent sessions](explanation/persistent-sessions.md) — files per project, why a start is a new session, `session/load` versus docker agent's `session/resume` | 84 | - [Persistent sessions](explanation/persistent-sessions.md) — files per project, why a start is a new session, `session/load` versus docker agent's `session/resume` |
| 84 | - [Documentation search](explanation/document-search.md) — `/docs` and `search_docs`: why BM25 and no model, why no index, passages as sections, prefixes instead of stemming | 85 | - [Documentation search](explanation/document-search.md) — `/docs` and `search_docs`: why BM25 and no model, why no index, passages as sections, prefixes instead of stemming |
added
docs/en/explanation/mm-init.md +119 -0 | new file mode 100644 | ||
| @@ -0,0 +1,119 @@ | ||
| 1 | +# `mm init`: where a generated agent's settings come from — explanation | |
| 2 | + | |
| 3 | +## What is this about? | |
| 4 | + | |
| 5 | +`mm init` (or `mm --init`) writes a commented `agent.yaml` from a few answers: the model server, the model, the usage (developer, translator, docs…), the machine, and whether to ask before each change. No model runs while the wizard runs. Every value in the file comes from one of four sources, and each value says which one in its comment. This page explains what those sources are, how they were put together, and why the wizard trusts them in that order. The steps are in [Create an agent with `mm init`](../how-to/create-an-agent.md) and the flags in the [command line reference](../reference/cli.md#mm-init--the-agentyaml-wizard). | |
| 6 | + | |
| 7 | +## The four sources, most specific first | |
| 8 | + | |
| 9 | +The code is in `internal/agentinit`. `Decide` (`decide.go`) applies the sources in a fixed order of trust: **the server's facts about this model, then the family table, then the usage profile, then the machine row.** Each source only fills in what the sources before it do not know. | |
| 10 | + | |
| 11 | +### 1. What the model server says about the model (`facts.go`) | |
| 12 | + | |
| 13 | +The server knows the exact model that is loaded, so it is the most specific source there is. The wizard asks it before choosing anything else: | |
| 14 | + | |
| 15 | +| Provider | Asked | What it gives | | |
| 16 | +|---|---|---| | |
| 17 | +| `llmman`, `ollama` | `/api/tags`, then `/api/show` | the model list, the family the server reports (`details.family`), the native context window, the sampling written in the GGUF (`temperature`, `top_p`, `top_k`, `min_p`), the chat template | | |
| 18 | +| `llamacpp` | `/props` | the window and the chat template | | |
| 19 | +| `dmr` | `/models` | the model list only | | |
| 20 | +| `openai` | `/models` (with the key) | the model list only | | |
| 21 | + | |
| 22 | +From the chat template, `templateThinking` reads how the model's reasoning is switched on or off. It finds `enable_thinking` and its default (on or off), or `reasoning_effort` and the values the template accepts. A model whose template knows neither gets no reasoning switch. | |
| 23 | + | |
| 24 | +These rules were not written for `mm init`. They are a Go port of `skills/create-agent/model_facts.py`, the script the agent-creating agent (`agent.creator.yaml`) already used to read a model from llmman: the same endpoints, the same way of reading the template. | |
| 25 | + | |
| 26 | +When the server gives the GGUF's own sampling, those numbers **replace** the family table's. The GGUF is the most specific source, because it was written for that very file. When the server says nothing beyond the model's name (DMR, the generic `openai` provider, an unknown model), the file says so in its closing notes, and the family table decides. | |
| 27 | + | |
| 28 | +### 2. The family table (`presets.yaml`) | |
| 29 | + | |
| 30 | +The family is guessed from the model id: the first family whose `match` words all appear in the lower-cased name wins. `qwen-coder` (`qwen` + `coder`) therefore comes before `qwen`, and `other` matches anything. The server's family is used when the name does not tell. A family gives: | |
| 31 | + | |
| 32 | +- the sampling for normal use (`general`) and with reasoning on (`thinking`); | |
| 33 | +- a `precise` temperature, for agents that use tools without reasoning; | |
| 34 | +- the reasoning switch; | |
| 35 | +- sometimes a note, for example "a guard model, not a general agent". | |
| 36 | + | |
| 37 | +Every number has a `source` line, and the table was filled from two kinds of source only: | |
| 38 | + | |
| 39 | +- **Model cards and published files.** The Qwen cards (thinking 0.6 / 0.95 / 20, non-thinking 0.7 / 0.8 / 20), the Gemma 4 GGUF sampling, Llama 3.1 8B Instruct's `generation_config.json` (0.6 / 0.9, read from a mirror because Meta's repository needs a login), the Mistral Small 3.1 card ("a relatively low temperature, such as temperature=0.15"), and the OpenAI API reference for hosted models. | |
| 40 | +- **This repository's measured demos.** For each family, the demos that run the model were searched for the sampling they use (`demos/*/agent*.yaml`). For example, `demos/qwen-style` (Qwen3-Coder-Next), `demos/coding-helpers` (Mellum2 12B Thinking, MiniCPM5 2B), `demos/team` (Ornith 1.5 9B), `demos/guard` (Granite Guardian), `demos/codex-style` (gpt-oss 20B) and `demos/llmman` (Jan-nano, Lucy). Qwen's `precise` 0.0 comes from runs with Qwen3.5 4B, reasoning off (`demos/docs-search`, `memory-search`, `plans`). | |
| 41 | + | |
| 42 | +When nothing is published, `other` uses the rule of the `skills/create-agent` skill: 0.7 / 0.9, and 0.2 for a code agent that does not reason. | |
| 43 | + | |
| 44 | +### 3. The usage profile (`presets.yaml`, `usages`) | |
| 45 | + | |
| 46 | +The usage says what the agent is for, which the model cannot tell. A profile sets: | |
| 47 | + | |
| 48 | +- which tool switches are on (a translator has no tool at all; a developer has bash, the file tools and the plan tool); | |
| 49 | +- whether to reason when the model can; | |
| 50 | +- whether to use the family's precise temperature; | |
| 51 | +- `maxTurns`; | |
| 52 | +- the default for asking before each change (`yolo`); | |
| 53 | +- a starting system prompt. | |
| 54 | + | |
| 55 | +Some usages switch on one feature each: `docs` turns on the documentation search, `json` writes a `structuredOutput` example (which forbids every tool), and `coordinator` hands the questions to other agents. The prompts are in English, by the user's choice in ticket 97. They repeat rules the demos' prompts share, for example "Never state the output of a command you did not run in this answer". | |
| 56 | + | |
| 57 | +### 4. The machine row (`presets.yaml`, `machines`) | |
| 58 | + | |
| 59 | +The timeouts and the size of tool outputs depend on the machine, not on the model. The three rows `small`, `medium` and `large` (`firstTokenTimeout`, `watchdogTimeout`, `bashTimeout`, `maxOutput`) are copied from the "Summary: typical profiles" table of [the settings guide](../../../guides/agent-settings-for-small-models.md), written for ticket 98. | |
| 60 | + | |
| 61 | +## The rules the code adds | |
| 62 | + | |
| 63 | +A few values follow from the answers rather than from a table. Each rule writes its reason above the value it sets: | |
| 64 | + | |
| 65 | +- **Reasoning on means a temperature of at least 0.6 and `max_tokens: 16384`.** A thinking model loops at a low temperature, and its thoughts need room besides the tool call. With reasoning off, the limit is 4096. | |
| 66 | +- **The precise temperature applies only without reasoning.** It is used when the usage asks for it (developer, reviewer, docs, json…). | |
| 67 | +- **With bash on, `watchdogTimeout` is aligned on `bashTimeout`**, as section 3 of the settings guide says. Otherwise a long command would look like a stalled model. | |
| 68 | +- **`parallel_tool_calls: false` for any agent with tools.** Otherwise small models run a check before the change it checks has landed. | |
| 69 | +- **`contextWindow: 0` and `context.threshold: 75`.** mm asks the server for the window it actually serves. The proposal planned a threshold computed from the model's native window. It was dropped while writing the code: Ollama often serves 4k–8k, so a percentage of the native window would compress almost at once. | |
| 70 | +- **`skillsDir: no-skills`.** A new agent starts without skills, and the comment says how to add some. | |
| 71 | + | |
| 72 | +## Every number says how it was obtained | |
| 73 | + | |
| 74 | +Since ticket 121, each number about the model carries a tag in its comment. The file's header explains the tags it uses: | |
| 75 | + | |
| 76 | +| Tag | Meaning | After a model or quantization change | | |
| 77 | +|---|---|---| | |
| 78 | +| `[server]` | read from the model server when the file was written | run `mm init` again | | |
| 79 | +| `[measured]` | a demo of this repository ran with it | measure again | | |
| 80 | +| `[card]` | copied from the model card, the GGUF or the API reference, not measured here | read the card again | | |
| 81 | +| `[rule]` | a rule of thumb, nothing specific to the model | check it still fits | | |
| 82 | +| `[guide]` | the settings guide's row for the machine | — | | |
| 83 | + | |
| 84 | +A comment above `model:` lists what to redo when the model changes. The comments make the file teach as it configures, the way the demos' `agent.yaml` files are written: a reader sees which numbers were measured on a real run and which were only copied. | |
| 85 | + | |
| 86 | +## The file is checked before the wizard says it is done | |
| 87 | + | |
| 88 | +The wizard never overwrites an existing file. After writing, it loads the file with mm's own `config.Load`, so a file mm would refuse is reported at once. With `--check`, it also runs the same mm on the new file with one question (`Say hello in one line.`), to prove the model answers. | |
| 89 | + | |
| 90 | +## Why it is designed this way | |
| 91 | + | |
| 92 | +**A generator with no model.** Ticket 97 asked for an `agent.yaml` from the command line, by model family and usage. The proposal written for the ticket first listed what already existed: `agent.creator.yaml` with its `create-agent` skill, `model_facts.py`, the settings guide, `config.samples/` and the demos' tested settings. Instead of a new source of knowledge, `mm init` puts those pieces together in deterministic Go code. It is instant and works before any agent exists. | |
| 93 | + | |
| 94 | +**A server first, a table second.** A table can only know a family, while the server knows the very file that is loaded: its window, its GGUF sampling, its template. The table covers the servers that say nothing, such as Docker Model Runner. | |
| 95 | + | |
| 96 | +**Sourced values only.** The user decided that the family table would use model cards **and** measured demos. A number with no source does not go in. A family with neither falls back to `other`, and the file says that its sampling is only a starting point. | |
| 97 | + | |
| 98 | +**One table.** `presets.yaml` is embedded in the binary. Its header says it is meant to be shared with the Claude skill of ticket 111 (a skill built from the settings guide). That ticket is still open, and the `mm-agent-creator` skill does not read the file today. | |
| 99 | + | |
| 100 | +## Rejected alternatives | |
| 101 | + | |
| 102 | +- **Generating the file with a model** (`agent.creator.yaml`). Kept for the unusual cases, but not the default: it needs a 27B model loaded and minutes per agent. | |
| 103 | +- **A threshold computed from the native window.** Rejected, see above: it would compress almost at once on the windows Ollama serves. | |
| 104 | +- **Skills, MCP servers, hooks and `mmConfigs` in the wizard.** Left out of the first version. The file's closing comment points to the how-to guides instead. | |
| 105 | +- **Prompts in the user's language.** Rejected by the user's choice: the generated prompts are in English. | |
| 106 | + | |
| 107 | +## Known limits | |
| 108 | + | |
| 109 | +- Live checks were run against llmman only (Qwen3.5 4B, gemma-4-E4B). Ollama, Docker Model Runner and llama-server were tested against fake servers recorded in the tests. The OpenAI API itself was not tried; its constraints come from its reference. | |
| 110 | +- A `[card]` number was copied, not measured in this repository. | |
| 111 | +- The families are matched on words in the model id: a model renamed by its publisher may land in `other`. | |
| 112 | + | |
| 113 | +## How it relates to the rest | |
| 114 | + | |
| 115 | +- [Providers](providers.md): the five servers the wizard can ask, and why each has its own entry. | |
| 116 | +- [Thinking models](thinking-models.md): what the reasoning switch the wizard sets does at run time. | |
| 117 | +- [Context compression](context-compression.md): what `context.threshold` triggers. | |
| 118 | +- [Structured output](structured-output.md): why the `json` usage has no tools. | |
| 119 | +- [Asking another agent](asking-another-agent.md): what the `coordinator` usage relies on. | |
| new file mode 100644 | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | +# `mm init`: where a generated agent's settings come from — explanation | ||
| 2 | + | ||
| 3 | +## What is this about? | ||
| 4 | + | ||
| 5 | +`mm init` (or `mm --init`) writes a commented `agent.yaml` from a few answers: the model server, the model, the usage (developer, translator, docs…), the machine, and whether to ask before each change. No model runs while the wizard runs. Every value in the file comes from one of four sources, and each value says which one in its comment. This page explains what those sources are, how they were put together, and why the wizard trusts them in that order. The steps are in [Create an agent with `mm init`](../how-to/create-an-agent.md) and the flags in the [command line reference](../reference/cli.md#mm-init--the-agentyaml-wizard). | ||
| 6 | + | ||
| 7 | +## The four sources, most specific first | ||
| 8 | + | ||
| 9 | +The code is in `internal/agentinit`. `Decide` (`decide.go`) applies the sources in a fixed order of trust: **the server's facts about this model, then the family table, then the usage profile, then the machine row.** Each source only fills in what the sources before it do not know. | ||
| 10 | + | ||
| 11 | +### 1. What the model server says about the model (`facts.go`) | ||
| 12 | + | ||
| 13 | +The server knows the exact model that is loaded, so it is the most specific source there is. The wizard asks it before choosing anything else: | ||
| 14 | + | ||
| 15 | +| Provider | Asked | What it gives | | ||
| 16 | +|---|---|---| | ||
| 17 | +| `llmman`, `ollama` | `/api/tags`, then `/api/show` | the model list, the family the server reports (`details.family`), the native context window, the sampling written in the GGUF (`temperature`, `top_p`, `top_k`, `min_p`), the chat template | | ||
| 18 | +| `llamacpp` | `/props` | the window and the chat template | | ||
| 19 | +| `dmr` | `/models` | the model list only | | ||
| 20 | +| `openai` | `/models` (with the key) | the model list only | | ||
| 21 | + | ||
| 22 | +From the chat template, `templateThinking` reads how the model's reasoning is switched on or off. It finds `enable_thinking` and its default (on or off), or `reasoning_effort` and the values the template accepts. A model whose template knows neither gets no reasoning switch. | ||
| 23 | + | ||
| 24 | +These rules were not written for `mm init`. They are a Go port of `skills/create-agent/model_facts.py`, the script the agent-creating agent (`agent.creator.yaml`) already used to read a model from llmman: the same endpoints, the same way of reading the template. | ||
| 25 | + | ||
| 26 | +When the server gives the GGUF's own sampling, those numbers **replace** the family table's. The GGUF is the most specific source, because it was written for that very file. When the server says nothing beyond the model's name (DMR, the generic `openai` provider, an unknown model), the file says so in its closing notes, and the family table decides. | ||
| 27 | + | ||
| 28 | +### 2. The family table (`presets.yaml`) | ||
| 29 | + | ||
| 30 | +The family is guessed from the model id: the first family whose `match` words all appear in the lower-cased name wins. `qwen-coder` (`qwen` + `coder`) therefore comes before `qwen`, and `other` matches anything. The server's family is used when the name does not tell. A family gives: | ||
| 31 | + | ||
| 32 | +- the sampling for normal use (`general`) and with reasoning on (`thinking`); | ||
| 33 | +- a `precise` temperature, for agents that use tools without reasoning; | ||
| 34 | +- the reasoning switch; | ||
| 35 | +- sometimes a note, for example "a guard model, not a general agent". | ||
| 36 | + | ||
| 37 | +Every number has a `source` line, and the table was filled from two kinds of source only: | ||
| 38 | + | ||
| 39 | +- **Model cards and published files.** The Qwen cards (thinking 0.6 / 0.95 / 20, non-thinking 0.7 / 0.8 / 20), the Gemma 4 GGUF sampling, Llama 3.1 8B Instruct's `generation_config.json` (0.6 / 0.9, read from a mirror because Meta's repository needs a login), the Mistral Small 3.1 card ("a relatively low temperature, such as temperature=0.15"), and the OpenAI API reference for hosted models. | ||
| 40 | +- **This repository's measured demos.** For each family, the demos that run the model were searched for the sampling they use (`demos/*/agent*.yaml`). For example, `demos/qwen-style` (Qwen3-Coder-Next), `demos/coding-helpers` (Mellum2 12B Thinking, MiniCPM5 2B), `demos/team` (Ornith 1.5 9B), `demos/guard` (Granite Guardian), `demos/codex-style` (gpt-oss 20B) and `demos/llmman` (Jan-nano, Lucy). Qwen's `precise` 0.0 comes from runs with Qwen3.5 4B, reasoning off (`demos/docs-search`, `memory-search`, `plans`). | ||
| 41 | + | ||
| 42 | +When nothing is published, `other` uses the rule of the `skills/create-agent` skill: 0.7 / 0.9, and 0.2 for a code agent that does not reason. | ||
| 43 | + | ||
| 44 | +### 3. The usage profile (`presets.yaml`, `usages`) | ||
| 45 | + | ||
| 46 | +The usage says what the agent is for, which the model cannot tell. A profile sets: | ||
| 47 | + | ||
| 48 | +- which tool switches are on (a translator has no tool at all; a developer has bash, the file tools and the plan tool); | ||
| 49 | +- whether to reason when the model can; | ||
| 50 | +- whether to use the family's precise temperature; | ||
| 51 | +- `maxTurns`; | ||
| 52 | +- the default for asking before each change (`yolo`); | ||
| 53 | +- a starting system prompt. | ||
| 54 | + | ||
| 55 | +Some usages switch on one feature each: `docs` turns on the documentation search, `json` writes a `structuredOutput` example (which forbids every tool), and `coordinator` hands the questions to other agents. The prompts are in English, by the user's choice in ticket 97. They repeat rules the demos' prompts share, for example "Never state the output of a command you did not run in this answer". | ||
| 56 | + | ||
| 57 | +### 4. The machine row (`presets.yaml`, `machines`) | ||
| 58 | + | ||
| 59 | +The timeouts and the size of tool outputs depend on the machine, not on the model. The three rows `small`, `medium` and `large` (`firstTokenTimeout`, `watchdogTimeout`, `bashTimeout`, `maxOutput`) are copied from the "Summary: typical profiles" table of [the settings guide](../../../guides/agent-settings-for-small-models.md), written for ticket 98. | ||
| 60 | + | ||
| 61 | +## The rules the code adds | ||
| 62 | + | ||
| 63 | +A few values follow from the answers rather than from a table. Each rule writes its reason above the value it sets: | ||
| 64 | + | ||
| 65 | +- **Reasoning on means a temperature of at least 0.6 and `max_tokens: 16384`.** A thinking model loops at a low temperature, and its thoughts need room besides the tool call. With reasoning off, the limit is 4096. | ||
| 66 | +- **The precise temperature applies only without reasoning.** It is used when the usage asks for it (developer, reviewer, docs, json…). | ||
| 67 | +- **With bash on, `watchdogTimeout` is aligned on `bashTimeout`**, as section 3 of the settings guide says. Otherwise a long command would look like a stalled model. | ||
| 68 | +- **`parallel_tool_calls: false` for any agent with tools.** Otherwise small models run a check before the change it checks has landed. | ||
| 69 | +- **`contextWindow: 0` and `context.threshold: 75`.** mm asks the server for the window it actually serves. The proposal planned a threshold computed from the model's native window. It was dropped while writing the code: Ollama often serves 4k–8k, so a percentage of the native window would compress almost at once. | ||
| 70 | +- **`skillsDir: no-skills`.** A new agent starts without skills, and the comment says how to add some. | ||
| 71 | + | ||
| 72 | +## Every number says how it was obtained | ||
| 73 | + | ||
| 74 | +Since ticket 121, each number about the model carries a tag in its comment. The file's header explains the tags it uses: | ||
| 75 | + | ||
| 76 | +| Tag | Meaning | After a model or quantization change | | ||
| 77 | +|---|---|---| | ||
| 78 | +| `[server]` | read from the model server when the file was written | run `mm init` again | | ||
| 79 | +| `[measured]` | a demo of this repository ran with it | measure again | | ||
| 80 | +| `[card]` | copied from the model card, the GGUF or the API reference, not measured here | read the card again | | ||
| 81 | +| `[rule]` | a rule of thumb, nothing specific to the model | check it still fits | | ||
| 82 | +| `[guide]` | the settings guide's row for the machine | — | | ||
| 83 | + | ||
| 84 | +A comment above `model:` lists what to redo when the model changes. The comments make the file teach as it configures, the way the demos' `agent.yaml` files are written: a reader sees which numbers were measured on a real run and which were only copied. | ||
| 85 | + | ||
| 86 | +## The file is checked before the wizard says it is done | ||
| 87 | + | ||
| 88 | +The wizard never overwrites an existing file. After writing, it loads the file with mm's own `config.Load`, so a file mm would refuse is reported at once. With `--check`, it also runs the same mm on the new file with one question (`Say hello in one line.`), to prove the model answers. | ||
| 89 | + | ||
| 90 | +## Why it is designed this way | ||
| 91 | + | ||
| 92 | +**A generator with no model.** Ticket 97 asked for an `agent.yaml` from the command line, by model family and usage. The proposal written for the ticket first listed what already existed: `agent.creator.yaml` with its `create-agent` skill, `model_facts.py`, the settings guide, `config.samples/` and the demos' tested settings. Instead of a new source of knowledge, `mm init` puts those pieces together in deterministic Go code. It is instant and works before any agent exists. | ||
| 93 | + | ||
| 94 | +**A server first, a table second.** A table can only know a family, while the server knows the very file that is loaded: its window, its GGUF sampling, its template. The table covers the servers that say nothing, such as Docker Model Runner. | ||
| 95 | + | ||
| 96 | +**Sourced values only.** The user decided that the family table would use model cards **and** measured demos. A number with no source does not go in. A family with neither falls back to `other`, and the file says that its sampling is only a starting point. | ||
| 97 | + | ||
| 98 | +**One table.** `presets.yaml` is embedded in the binary. Its header says it is meant to be shared with the Claude skill of ticket 111 (a skill built from the settings guide). That ticket is still open, and the `mm-agent-creator` skill does not read the file today. | ||
| 99 | + | ||
| 100 | +## Rejected alternatives | ||
| 101 | + | ||
| 102 | +- **Generating the file with a model** (`agent.creator.yaml`). Kept for the unusual cases, but not the default: it needs a 27B model loaded and minutes per agent. | ||
| 103 | +- **A threshold computed from the native window.** Rejected, see above: it would compress almost at once on the windows Ollama serves. | ||
| 104 | +- **Skills, MCP servers, hooks and `mmConfigs` in the wizard.** Left out of the first version. The file's closing comment points to the how-to guides instead. | ||
| 105 | +- **Prompts in the user's language.** Rejected by the user's choice: the generated prompts are in English. | ||
| 106 | + | ||
| 107 | +## Known limits | ||
| 108 | + | ||
| 109 | +- Live checks were run against llmman only (Qwen3.5 4B, gemma-4-E4B). Ollama, Docker Model Runner and llama-server were tested against fake servers recorded in the tests. The OpenAI API itself was not tried; its constraints come from its reference. | ||
| 110 | +- A `[card]` number was copied, not measured in this repository. | ||
| 111 | +- The families are matched on words in the model id: a model renamed by its publisher may land in `other`. | ||
| 112 | + | ||
| 113 | +## How it relates to the rest | ||
| 114 | + | ||
| 115 | +- [Providers](providers.md): the five servers the wizard can ask, and why each has its own entry. | ||
| 116 | +- [Thinking models](thinking-models.md): what the reasoning switch the wizard sets does at run time. | ||
| 117 | +- [Context compression](context-compression.md): what `context.threshold` triggers. | ||
| 118 | +- [Structured output](structured-output.md): why the `json` usage has no tools. | ||
| 119 | +- [Asking another agent](asking-another-agent.md): what the `coordinator` usage relies on. | ||
modified
docs/en/how-to/create-an-agent.md +1 -0 | @@ -90,4 +90,5 @@ This guide shows how to write a new agent.yaml for a model and a job, with mm's | ||
| 90 | 90 | - [Command line reference — `mm init`](../reference/cli.md#mm-init--the-agentyaml-wizard): every flag, the sources, the exit codes |
| 91 | 91 | - [Configuration reference](../reference/configuration.md): every key the file holds |
| 92 | 92 | - [Agent settings for small models](../../../guides/agent-settings-for-small-models.md): what each setting does, the machine rows |
| 93 | +- [Where the settings come from](../explanation/mm-init.md): the four sources, their order, the origin tags | |
| 93 | 94 | - `agent.creator.yaml`: an agent that creates agents with a model, for the unusual cases |
| @@ -90,4 +90,5 @@ This guide shows how to write a new agent.yaml for a model and a job, with mm's | |||
| 90 | - [Command line reference — `mm init`](../reference/cli.md#mm-init--the-agentyaml-wizard): every flag, the sources, the exit codes | 90 | - [Command line reference — `mm init`](../reference/cli.md#mm-init--the-agentyaml-wizard): every flag, the sources, the exit codes |
| 91 | - [Configuration reference](../reference/configuration.md): every key the file holds | 91 | - [Configuration reference](../reference/configuration.md): every key the file holds |
| 92 | - [Agent settings for small models](../../../guides/agent-settings-for-small-models.md): what each setting does, the machine rows | 92 | - [Agent settings for small models](../../../guides/agent-settings-for-small-models.md): what each setting does, the machine rows |
| 93 | +- [Where the settings come from](../explanation/mm-init.md): the four sources, their order, the origin tags | ||
| 93 | - `agent.creator.yaml`: an agent that creates agents with a model, for the unusual cases | 94 | - `agent.creator.yaml`: an agent that creates agents with a model, for the unusual cases |
modified
docs/fr/README.md +1 -0 | @@ -79,6 +79,7 @@ Cette documentation est organisée selon les quatre quadrants [Diátaxis](https: | ||
| 79 | 79 | |
| 80 | 80 | - [Architecture : une boucle, trois façades](explanation/architecture.md) |
| 81 | 81 | - [Fournisseurs : une implémentation par protocole](explanation/providers.md) |
| 82 | +- [`mm init` : d'où viennent les réglages d'un agent généré](explanation/mm-init.md) — ce que dit le serveur, la table des familles sourcée, les profils d'usage, les lignes machine du guide des réglages ; l'ordre de confiance, les étiquettes d'origine, ce qui a été écarté | |
| 82 | 83 | - [Compression du contexte](explanation/context-compression.md) |
| 83 | 84 | - [Les sessions persistantes](explanation/persistent-sessions.md) — des fichiers par projet, pourquoi un lancement est une nouvelle session, `session/load` face au `session/resume` de docker agent |
| 84 | 85 | - [La recherche dans la documentation](explanation/document-search.md) — `/docs` et `search_docs` : pourquoi BM25 et aucun modèle, pourquoi pas d'index, des passages qui sont des sections, des préfixes plutôt qu'une racinisation |
| @@ -79,6 +79,7 @@ Cette documentation est organisée selon les quatre quadrants [Diátaxis](https: | |||
| 79 | 79 | ||
| 80 | - [Architecture : une boucle, trois façades](explanation/architecture.md) | 80 | - [Architecture : une boucle, trois façades](explanation/architecture.md) |
| 81 | - [Fournisseurs : une implémentation par protocole](explanation/providers.md) | 81 | - [Fournisseurs : une implémentation par protocole](explanation/providers.md) |
| 82 | +- [`mm init` : d'où viennent les réglages d'un agent généré](explanation/mm-init.md) — ce que dit le serveur, la table des familles sourcée, les profils d'usage, les lignes machine du guide des réglages ; l'ordre de confiance, les étiquettes d'origine, ce qui a été écarté | ||
| 82 | - [Compression du contexte](explanation/context-compression.md) | 83 | - [Compression du contexte](explanation/context-compression.md) |
| 83 | - [Les sessions persistantes](explanation/persistent-sessions.md) — des fichiers par projet, pourquoi un lancement est une nouvelle session, `session/load` face au `session/resume` de docker agent | 84 | - [Les sessions persistantes](explanation/persistent-sessions.md) — des fichiers par projet, pourquoi un lancement est une nouvelle session, `session/load` face au `session/resume` de docker agent |
| 84 | - [La recherche dans la documentation](explanation/document-search.md) — `/docs` et `search_docs` : pourquoi BM25 et aucun modèle, pourquoi pas d'index, des passages qui sont des sections, des préfixes plutôt qu'une racinisation | 85 | - [La recherche dans la documentation](explanation/document-search.md) — `/docs` et `search_docs` : pourquoi BM25 et aucun modèle, pourquoi pas d'index, des passages qui sont des sections, des préfixes plutôt qu'une racinisation |
added
docs/fr/explanation/mm-init.md +119 -0 | new file mode 100644 | ||
| @@ -0,0 +1,119 @@ | ||
| 1 | +# `mm init` : d'où viennent les réglages d'un agent généré — explication | |
| 2 | + | |
| 3 | +## De quoi s'agit-il ? | |
| 4 | + | |
| 5 | +`mm init` (ou `mm --init`) écrit un `agent.yaml` commenté à partir de quelques réponses : le serveur de modèles, le modèle, l'usage (développeur, traducteur, docs…), la machine, et s'il faut demander avant chaque modification. Aucun modèle ne tourne pendant l'assistant. Chaque valeur du fichier vient de l'une de quatre sources, et son commentaire dit laquelle. Cette page explique ces sources, comment elles ont été réunies et pourquoi l'assistant leur fait confiance dans cet ordre. Les étapes sont dans [Créer un agent avec `mm init`](../how-to/create-an-agent.md) et les options dans la [référence de la ligne de commande](../reference/cli.md#mm-init--lassistant-agentyaml). | |
| 6 | + | |
| 7 | +## Les quatre sources, de la plus précise à la plus générale | |
| 8 | + | |
| 9 | +Le code est dans `internal/agentinit`. `Decide` (`decide.go`) applique les sources dans un ordre de confiance fixe : **ce que dit le serveur de ce modèle, puis la table des familles, puis le profil d'usage, puis la ligne de la machine.** Chaque source ne complète que ce que les précédentes ne savent pas. | |
| 10 | + | |
| 11 | +### 1. Ce que dit le serveur du modèle (`facts.go`) | |
| 12 | + | |
| 13 | +Le serveur connaît le modèle exact qui est chargé : c'est la source la plus précise qui existe. L'assistant l'interroge avant de choisir quoi que ce soit : | |
| 14 | + | |
| 15 | +| Fournisseur | Interrogé | Ce qu'il donne | | |
| 16 | +|---|---|---| | |
| 17 | +| `llmman`, `ollama` | `/api/tags`, puis `/api/show` | la liste des modèles, la famille annoncée par le serveur (`details.family`), la fenêtre de contexte native, l'échantillonnage écrit dans le GGUF (`temperature`, `top_p`, `top_k`, `min_p`), le template de chat | | |
| 18 | +| `llamacpp` | `/props` | la fenêtre et le template de chat | | |
| 19 | +| `dmr` | `/models` | la liste des modèles seulement | | |
| 20 | +| `openai` | `/models` (avec la clé) | la liste des modèles seulement | | |
| 21 | + | |
| 22 | +Dans le template de chat, `templateThinking` lit comment le raisonnement du modèle s'active et se désactive. Il trouve `enable_thinking` et sa valeur par défaut (activé ou non), ou `reasoning_effort` et les valeurs que le template accepte. Un modèle dont le template ne connaît ni l'un ni l'autre n'a pas d'interrupteur de raisonnement. | |
| 23 | + | |
| 24 | +Ces règles n'ont pas été écrites pour `mm init`. Ce sont celles de `skills/create-agent/model_facts.py`, portées en Go. Ce script servait déjà à l'agent qui crée des agents (`agent.creator.yaml`) pour lire un modèle dans llmman : mêmes points d'accès, même lecture du template. | |
| 25 | + | |
| 26 | +Quand le serveur donne l'échantillonnage propre au GGUF, ces valeurs **remplacent** celles de la table des familles. Le GGUF est la source la plus précise, puisqu'il a été écrit pour ce fichier-là. Quand le serveur ne dit rien de plus que le nom du modèle (DMR, le fournisseur générique `openai`, un modèle inconnu), le fichier le signale dans ses notes de fin, et c'est la table des familles qui décide. | |
| 27 | + | |
| 28 | +### 2. La table des familles (`presets.yaml`) | |
| 29 | + | |
| 30 | +La famille est déduite de l'identifiant du modèle : la première famille dont tous les mots de `match` apparaissent dans le nom en minuscules l'emporte. `qwen-coder` (`qwen` + `coder`) passe donc avant `qwen`, et `other` correspond à tout. La famille annoncée par le serveur sert quand le nom ne dit rien. Une famille donne : | |
| 31 | + | |
| 32 | +- l'échantillonnage pour un usage normal (`general`) et raisonnement activé (`thinking`) ; | |
| 33 | +- une température `precise`, pour les agents qui utilisent des outils sans raisonner ; | |
| 34 | +- l'interrupteur de raisonnement ; | |
| 35 | +- parfois une note, par exemple « un modèle de garde, pas un agent généraliste ». | |
| 36 | + | |
| 37 | +Chaque valeur a une ligne `source`, et la table n'a été remplie qu'à partir de deux sortes de sources : | |
| 38 | + | |
| 39 | +- **Les fiches de modèles et les fichiers publiés.** Les fiches Qwen (avec raisonnement 0.6 / 0.95 / 20, sans raisonnement 0.7 / 0.8 / 20), l'échantillonnage du GGUF de Gemma 4, le `generation_config.json` de Llama 3.1 8B Instruct (0.6 / 0.9, lu sur un miroir parce que le dépôt de Meta demande une connexion), la fiche de Mistral Small 3.1 (« a relatively low temperature, such as temperature=0.15 »), et la référence de l'API OpenAI pour les modèles hébergés. | |
| 40 | +- **Les démos mesurées de ce dépôt.** Pour chaque famille, on a cherché dans les démos qui font tourner le modèle l'échantillonnage qu'elles utilisent (`demos/*/agent*.yaml`). Par exemple `demos/qwen-style` (Qwen3-Coder-Next), `demos/coding-helpers` (Mellum2 12B Thinking, MiniCPM5 2B), `demos/team` (Ornith 1.5 9B), `demos/guard` (Granite Guardian), `demos/codex-style` (gpt-oss 20B) et `demos/llmman` (Jan-nano, Lucy). Le `precise` à 0.0 de Qwen vient d'exécutions avec Qwen3.5 4B sans raisonnement (`demos/docs-search`, `memory-search`, `plans`). | |
| 41 | + | |
| 42 | +Quand rien n'est publié, `other` applique la règle du skill `skills/create-agent` : 0.7 / 0.9, et 0.2 pour un agent de code qui ne raisonne pas. | |
| 43 | + | |
| 44 | +### 3. Le profil d'usage (`presets.yaml`, `usages`) | |
| 45 | + | |
| 46 | +L'usage dit à quoi sert l'agent, ce que le modèle ne peut pas savoir. Un profil fixe : | |
| 47 | + | |
| 48 | +- les outils activés (un traducteur n'a aucun outil, un développeur a bash, les outils de fichiers et l'outil de plan) ; | |
| 49 | +- s'il faut raisonner quand le modèle le peut ; | |
| 50 | +- s'il faut utiliser la température précise de la famille ; | |
| 51 | +- `maxTurns` ; | |
| 52 | +- la valeur par défaut de la demande avant chaque modification (`yolo`) ; | |
| 53 | +- un prompt système de départ. | |
| 54 | + | |
| 55 | +Certains usages activent chacun une fonction : `docs` active la recherche dans la documentation, `json` écrit un exemple de `structuredOutput` (qui interdit tout outil), et `coordinator` confie les questions à d'autres agents. Les prompts sont en anglais, selon le choix de l'utilisateur dans le ticket 97. Ils reprennent des règles communes aux prompts des démos, par exemple « Never state the output of a command you did not run in this answer ». | |
| 56 | + | |
| 57 | +### 4. La ligne de la machine (`presets.yaml`, `machines`) | |
| 58 | + | |
| 59 | +Les délais et la taille des sorties d'outils dépendent de la machine, pas du modèle. Les trois lignes `small`, `medium` et `large` (`firstTokenTimeout`, `watchdogTimeout`, `bashTimeout`, `maxOutput`) sont copiées du tableau « Summary: typical profiles » [du guide des réglages](../../../guides/reglages-agents-petits-modeles.md), écrit pour le ticket 98. | |
| 60 | + | |
| 61 | +## Les règles ajoutées par le code | |
| 62 | + | |
| 63 | +Quelques valeurs découlent des réponses plutôt que d'une table. Chaque règle écrit sa raison au-dessus de la valeur qu'elle fixe : | |
| 64 | + | |
| 65 | +- **Raisonnement activé : une température d'au moins 0.6 et `max_tokens: 16384`.** Un modèle qui raisonne tourne en boucle à basse température, et ses pensées ont besoin de place en plus de l'appel d'outil. Sans raisonnement, la limite est 4096. | |
| 66 | +- **La température précise ne s'applique que sans raisonnement.** Elle sert quand l'usage la demande (developer, reviewer, docs, json…). | |
| 67 | +- **Avec bash, `watchdogTimeout` est aligné sur `bashTimeout`**, comme le dit la section 3 du guide des réglages. Sinon une commande longue passerait pour un modèle bloqué. | |
| 68 | +- **`parallel_tool_calls: false` dès que l'agent a des outils.** Sinon les petits modèles lancent une vérification avant que la modification qu'elle vérifie soit faite. | |
| 69 | +- **`contextWindow: 0` et `context.threshold: 75`.** mm demande au serveur la fenêtre qu'il sert vraiment. La proposition prévoyait un seuil calculé sur la fenêtre native du modèle. Il a été abandonné pendant l'écriture du code : Ollama sert souvent 4k à 8k, donc un pourcentage de la fenêtre native compresserait presque tout de suite. | |
| 70 | +- **`skillsDir: no-skills`.** Un nouvel agent démarre sans skills, et le commentaire dit comment en ajouter. | |
| 71 | + | |
| 72 | +## Chaque valeur dit comment elle a été obtenue | |
| 73 | + | |
| 74 | +Depuis le ticket 121, chaque valeur liée au modèle porte une étiquette dans son commentaire. L'en-tête du fichier explique celles qu'il utilise : | |
| 75 | + | |
| 76 | +| Étiquette | Sens | Après un changement de modèle ou de quantification | | |
| 77 | +|---|---|---| | |
| 78 | +| `[server]` | lue sur le serveur au moment de l'écriture du fichier | relancer `mm init` | | |
| 79 | +| `[measured]` | une démo de ce dépôt a tourné avec | mesurer à nouveau | | |
| 80 | +| `[card]` | copiée de la fiche du modèle, du GGUF ou de la référence de l'API, pas mesurée ici | relire la fiche | | |
| 81 | +| `[rule]` | une règle générale, rien de propre au modèle | vérifier qu'elle convient encore | | |
| 82 | +| `[guide]` | la ligne du guide des réglages pour la machine | — | | |
| 83 | + | |
| 84 | +Un commentaire au-dessus de `model:` liste ce qu'il faut refaire quand on change de modèle. Les commentaires font que le fichier explique en même temps qu'il configure, à la manière des `agent.yaml` des démos : on voit quelles valeurs ont été mesurées sur une vraie exécution et lesquelles ont seulement été recopiées. | |
| 85 | + | |
| 86 | +## Le fichier est vérifié avant que l'assistant ait fini | |
| 87 | + | |
| 88 | +L'assistant n'écrase jamais un fichier existant. Après l'écriture, il charge le fichier avec le `config.Load` de mm, donc un fichier que mm refuserait est signalé tout de suite. Avec `--check`, il lance aussi le même mm sur le nouveau fichier avec une question (`Say hello in one line.`), pour prouver que le modèle répond. | |
| 89 | + | |
| 90 | +## Pourquoi c'est conçu ainsi | |
| 91 | + | |
| 92 | +**Un générateur sans modèle.** Le ticket 97 demandait un `agent.yaml` depuis la ligne de commande, selon la famille du modèle et l'usage. La proposition écrite pour le ticket a d'abord listé ce qui existait déjà : `agent.creator.yaml` et son skill `create-agent`, `model_facts.py`, le guide des réglages, `config.samples/` et les réglages testés des démos. Au lieu d'une nouvelle source de connaissances, `mm init` assemble ces morceaux dans du Go déterministe. C'est instantané et cela marche avant qu'aucun agent n'existe. | |
| 93 | + | |
| 94 | +**Le serveur d'abord, la table ensuite.** Une table ne peut connaître qu'une famille, alors que le serveur connaît le fichier exact qui est chargé : sa fenêtre, l'échantillonnage de son GGUF, son template. La table couvre les serveurs qui ne disent rien, comme Docker Model Runner. | |
| 95 | + | |
| 96 | +**Seulement des valeurs sourcées.** L'utilisateur a décidé que la table des familles utiliserait les fiches de modèles **et** les démos mesurées. Une valeur sans source n'y entre pas. Une famille qui n'a ni l'un ni l'autre retombe sur `other`, et le fichier dit que son échantillonnage n'est qu'un point de départ. | |
| 97 | + | |
| 98 | +**Une seule table.** `presets.yaml` est intégré au binaire. Son en-tête dit qu'il doit être partagé avec le skill Claude du ticket 111 (un skill construit à partir du guide des réglages). Ce ticket est encore ouvert, et le skill `mm-agent-creator` ne lit pas ce fichier aujourd'hui. | |
| 99 | + | |
| 100 | +## Alternatives écartées | |
| 101 | + | |
| 102 | +- **Générer le fichier avec un modèle** (`agent.creator.yaml`). Conservé pour les cas qui sortent de l'ordinaire, mais pas par défaut : il faut un modèle de 27B chargé et plusieurs minutes par agent. | |
| 103 | +- **Un seuil calculé sur la fenêtre native.** Écarté, voir plus haut : il compresserait presque tout de suite avec les fenêtres que sert Ollama. | |
| 104 | +- **Les skills, les serveurs MCP, les hooks et les `mmConfigs` dans l'assistant.** Laissés hors de la première version. Le commentaire de fin du fichier renvoie aux guides pratiques. | |
| 105 | +- **Des prompts dans la langue de l'utilisateur.** Écarté par le choix de l'utilisateur : les prompts générés sont en anglais. | |
| 106 | + | |
| 107 | +## Limites connues | |
| 108 | + | |
| 109 | +- Les vérifications en direct n'ont été faites qu'avec llmman (Qwen3.5 4B, gemma-4-E4B). Ollama, Docker Model Runner et llama-server ont été testés contre de faux serveurs enregistrés dans les tests. L'API OpenAI elle-même n'a pas été essayée ; ses contraintes viennent de sa référence. | |
| 110 | +- Une valeur `[card]` a été recopiée, pas mesurée dans ce dépôt. | |
| 111 | +- Les familles sont reconnues sur des mots de l'identifiant du modèle : un modèle renommé par son éditeur peut tomber dans `other`. | |
| 112 | + | |
| 113 | +## Liens avec le reste | |
| 114 | + | |
| 115 | +- [Fournisseurs](providers.md) : les cinq serveurs que l'assistant peut interroger, et pourquoi chacun a sa propre entrée. | |
| 116 | +- [Modèles à raisonnement](thinking-models.md) : ce que fait à l'exécution l'interrupteur de raisonnement que fixe l'assistant. | |
| 117 | +- [Compression du contexte](context-compression.md) : ce que déclenche `context.threshold`. | |
| 118 | +- [Sortie structurée](structured-output.md) : pourquoi l'usage `json` n'a pas d'outils. | |
| 119 | +- [Interroger un autre agent](asking-another-agent.md) : ce sur quoi s'appuie l'usage `coordinator`. | |
| new file mode 100644 | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | +# `mm init` : d'où viennent les réglages d'un agent généré — explication | ||
| 2 | + | ||
| 3 | +## De quoi s'agit-il ? | ||
| 4 | + | ||
| 5 | +`mm init` (ou `mm --init`) écrit un `agent.yaml` commenté à partir de quelques réponses : le serveur de modèles, le modèle, l'usage (développeur, traducteur, docs…), la machine, et s'il faut demander avant chaque modification. Aucun modèle ne tourne pendant l'assistant. Chaque valeur du fichier vient de l'une de quatre sources, et son commentaire dit laquelle. Cette page explique ces sources, comment elles ont été réunies et pourquoi l'assistant leur fait confiance dans cet ordre. Les étapes sont dans [Créer un agent avec `mm init`](../how-to/create-an-agent.md) et les options dans la [référence de la ligne de commande](../reference/cli.md#mm-init--lassistant-agentyaml). | ||
| 6 | + | ||
| 7 | +## Les quatre sources, de la plus précise à la plus générale | ||
| 8 | + | ||
| 9 | +Le code est dans `internal/agentinit`. `Decide` (`decide.go`) applique les sources dans un ordre de confiance fixe : **ce que dit le serveur de ce modèle, puis la table des familles, puis le profil d'usage, puis la ligne de la machine.** Chaque source ne complète que ce que les précédentes ne savent pas. | ||
| 10 | + | ||
| 11 | +### 1. Ce que dit le serveur du modèle (`facts.go`) | ||
| 12 | + | ||
| 13 | +Le serveur connaît le modèle exact qui est chargé : c'est la source la plus précise qui existe. L'assistant l'interroge avant de choisir quoi que ce soit : | ||
| 14 | + | ||
| 15 | +| Fournisseur | Interrogé | Ce qu'il donne | | ||
| 16 | +|---|---|---| | ||
| 17 | +| `llmman`, `ollama` | `/api/tags`, puis `/api/show` | la liste des modèles, la famille annoncée par le serveur (`details.family`), la fenêtre de contexte native, l'échantillonnage écrit dans le GGUF (`temperature`, `top_p`, `top_k`, `min_p`), le template de chat | | ||
| 18 | +| `llamacpp` | `/props` | la fenêtre et le template de chat | | ||
| 19 | +| `dmr` | `/models` | la liste des modèles seulement | | ||
| 20 | +| `openai` | `/models` (avec la clé) | la liste des modèles seulement | | ||
| 21 | + | ||
| 22 | +Dans le template de chat, `templateThinking` lit comment le raisonnement du modèle s'active et se désactive. Il trouve `enable_thinking` et sa valeur par défaut (activé ou non), ou `reasoning_effort` et les valeurs que le template accepte. Un modèle dont le template ne connaît ni l'un ni l'autre n'a pas d'interrupteur de raisonnement. | ||
| 23 | + | ||
| 24 | +Ces règles n'ont pas été écrites pour `mm init`. Ce sont celles de `skills/create-agent/model_facts.py`, portées en Go. Ce script servait déjà à l'agent qui crée des agents (`agent.creator.yaml`) pour lire un modèle dans llmman : mêmes points d'accès, même lecture du template. | ||
| 25 | + | ||
| 26 | +Quand le serveur donne l'échantillonnage propre au GGUF, ces valeurs **remplacent** celles de la table des familles. Le GGUF est la source la plus précise, puisqu'il a été écrit pour ce fichier-là. Quand le serveur ne dit rien de plus que le nom du modèle (DMR, le fournisseur générique `openai`, un modèle inconnu), le fichier le signale dans ses notes de fin, et c'est la table des familles qui décide. | ||
| 27 | + | ||
| 28 | +### 2. La table des familles (`presets.yaml`) | ||
| 29 | + | ||
| 30 | +La famille est déduite de l'identifiant du modèle : la première famille dont tous les mots de `match` apparaissent dans le nom en minuscules l'emporte. `qwen-coder` (`qwen` + `coder`) passe donc avant `qwen`, et `other` correspond à tout. La famille annoncée par le serveur sert quand le nom ne dit rien. Une famille donne : | ||
| 31 | + | ||
| 32 | +- l'échantillonnage pour un usage normal (`general`) et raisonnement activé (`thinking`) ; | ||
| 33 | +- une température `precise`, pour les agents qui utilisent des outils sans raisonner ; | ||
| 34 | +- l'interrupteur de raisonnement ; | ||
| 35 | +- parfois une note, par exemple « un modèle de garde, pas un agent généraliste ». | ||
| 36 | + | ||
| 37 | +Chaque valeur a une ligne `source`, et la table n'a été remplie qu'à partir de deux sortes de sources : | ||
| 38 | + | ||
| 39 | +- **Les fiches de modèles et les fichiers publiés.** Les fiches Qwen (avec raisonnement 0.6 / 0.95 / 20, sans raisonnement 0.7 / 0.8 / 20), l'échantillonnage du GGUF de Gemma 4, le `generation_config.json` de Llama 3.1 8B Instruct (0.6 / 0.9, lu sur un miroir parce que le dépôt de Meta demande une connexion), la fiche de Mistral Small 3.1 (« a relatively low temperature, such as temperature=0.15 »), et la référence de l'API OpenAI pour les modèles hébergés. | ||
| 40 | +- **Les démos mesurées de ce dépôt.** Pour chaque famille, on a cherché dans les démos qui font tourner le modèle l'échantillonnage qu'elles utilisent (`demos/*/agent*.yaml`). Par exemple `demos/qwen-style` (Qwen3-Coder-Next), `demos/coding-helpers` (Mellum2 12B Thinking, MiniCPM5 2B), `demos/team` (Ornith 1.5 9B), `demos/guard` (Granite Guardian), `demos/codex-style` (gpt-oss 20B) et `demos/llmman` (Jan-nano, Lucy). Le `precise` à 0.0 de Qwen vient d'exécutions avec Qwen3.5 4B sans raisonnement (`demos/docs-search`, `memory-search`, `plans`). | ||
| 41 | + | ||
| 42 | +Quand rien n'est publié, `other` applique la règle du skill `skills/create-agent` : 0.7 / 0.9, et 0.2 pour un agent de code qui ne raisonne pas. | ||
| 43 | + | ||
| 44 | +### 3. Le profil d'usage (`presets.yaml`, `usages`) | ||
| 45 | + | ||
| 46 | +L'usage dit à quoi sert l'agent, ce que le modèle ne peut pas savoir. Un profil fixe : | ||
| 47 | + | ||
| 48 | +- les outils activés (un traducteur n'a aucun outil, un développeur a bash, les outils de fichiers et l'outil de plan) ; | ||
| 49 | +- s'il faut raisonner quand le modèle le peut ; | ||
| 50 | +- s'il faut utiliser la température précise de la famille ; | ||
| 51 | +- `maxTurns` ; | ||
| 52 | +- la valeur par défaut de la demande avant chaque modification (`yolo`) ; | ||
| 53 | +- un prompt système de départ. | ||
| 54 | + | ||
| 55 | +Certains usages activent chacun une fonction : `docs` active la recherche dans la documentation, `json` écrit un exemple de `structuredOutput` (qui interdit tout outil), et `coordinator` confie les questions à d'autres agents. Les prompts sont en anglais, selon le choix de l'utilisateur dans le ticket 97. Ils reprennent des règles communes aux prompts des démos, par exemple « Never state the output of a command you did not run in this answer ». | ||
| 56 | + | ||
| 57 | +### 4. La ligne de la machine (`presets.yaml`, `machines`) | ||
| 58 | + | ||
| 59 | +Les délais et la taille des sorties d'outils dépendent de la machine, pas du modèle. Les trois lignes `small`, `medium` et `large` (`firstTokenTimeout`, `watchdogTimeout`, `bashTimeout`, `maxOutput`) sont copiées du tableau « Summary: typical profiles » [du guide des réglages](../../../guides/reglages-agents-petits-modeles.md), écrit pour le ticket 98. | ||
| 60 | + | ||
| 61 | +## Les règles ajoutées par le code | ||
| 62 | + | ||
| 63 | +Quelques valeurs découlent des réponses plutôt que d'une table. Chaque règle écrit sa raison au-dessus de la valeur qu'elle fixe : | ||
| 64 | + | ||
| 65 | +- **Raisonnement activé : une température d'au moins 0.6 et `max_tokens: 16384`.** Un modèle qui raisonne tourne en boucle à basse température, et ses pensées ont besoin de place en plus de l'appel d'outil. Sans raisonnement, la limite est 4096. | ||
| 66 | +- **La température précise ne s'applique que sans raisonnement.** Elle sert quand l'usage la demande (developer, reviewer, docs, json…). | ||
| 67 | +- **Avec bash, `watchdogTimeout` est aligné sur `bashTimeout`**, comme le dit la section 3 du guide des réglages. Sinon une commande longue passerait pour un modèle bloqué. | ||
| 68 | +- **`parallel_tool_calls: false` dès que l'agent a des outils.** Sinon les petits modèles lancent une vérification avant que la modification qu'elle vérifie soit faite. | ||
| 69 | +- **`contextWindow: 0` et `context.threshold: 75`.** mm demande au serveur la fenêtre qu'il sert vraiment. La proposition prévoyait un seuil calculé sur la fenêtre native du modèle. Il a été abandonné pendant l'écriture du code : Ollama sert souvent 4k à 8k, donc un pourcentage de la fenêtre native compresserait presque tout de suite. | ||
| 70 | +- **`skillsDir: no-skills`.** Un nouvel agent démarre sans skills, et le commentaire dit comment en ajouter. | ||
| 71 | + | ||
| 72 | +## Chaque valeur dit comment elle a été obtenue | ||
| 73 | + | ||
| 74 | +Depuis le ticket 121, chaque valeur liée au modèle porte une étiquette dans son commentaire. L'en-tête du fichier explique celles qu'il utilise : | ||
| 75 | + | ||
| 76 | +| Étiquette | Sens | Après un changement de modèle ou de quantification | | ||
| 77 | +|---|---|---| | ||
| 78 | +| `[server]` | lue sur le serveur au moment de l'écriture du fichier | relancer `mm init` | | ||
| 79 | +| `[measured]` | une démo de ce dépôt a tourné avec | mesurer à nouveau | | ||
| 80 | +| `[card]` | copiée de la fiche du modèle, du GGUF ou de la référence de l'API, pas mesurée ici | relire la fiche | | ||
| 81 | +| `[rule]` | une règle générale, rien de propre au modèle | vérifier qu'elle convient encore | | ||
| 82 | +| `[guide]` | la ligne du guide des réglages pour la machine | — | | ||
| 83 | + | ||
| 84 | +Un commentaire au-dessus de `model:` liste ce qu'il faut refaire quand on change de modèle. Les commentaires font que le fichier explique en même temps qu'il configure, à la manière des `agent.yaml` des démos : on voit quelles valeurs ont été mesurées sur une vraie exécution et lesquelles ont seulement été recopiées. | ||
| 85 | + | ||
| 86 | +## Le fichier est vérifié avant que l'assistant ait fini | ||
| 87 | + | ||
| 88 | +L'assistant n'écrase jamais un fichier existant. Après l'écriture, il charge le fichier avec le `config.Load` de mm, donc un fichier que mm refuserait est signalé tout de suite. Avec `--check`, il lance aussi le même mm sur le nouveau fichier avec une question (`Say hello in one line.`), pour prouver que le modèle répond. | ||
| 89 | + | ||
| 90 | +## Pourquoi c'est conçu ainsi | ||
| 91 | + | ||
| 92 | +**Un générateur sans modèle.** Le ticket 97 demandait un `agent.yaml` depuis la ligne de commande, selon la famille du modèle et l'usage. La proposition écrite pour le ticket a d'abord listé ce qui existait déjà : `agent.creator.yaml` et son skill `create-agent`, `model_facts.py`, le guide des réglages, `config.samples/` et les réglages testés des démos. Au lieu d'une nouvelle source de connaissances, `mm init` assemble ces morceaux dans du Go déterministe. C'est instantané et cela marche avant qu'aucun agent n'existe. | ||
| 93 | + | ||
| 94 | +**Le serveur d'abord, la table ensuite.** Une table ne peut connaître qu'une famille, alors que le serveur connaît le fichier exact qui est chargé : sa fenêtre, l'échantillonnage de son GGUF, son template. La table couvre les serveurs qui ne disent rien, comme Docker Model Runner. | ||
| 95 | + | ||
| 96 | +**Seulement des valeurs sourcées.** L'utilisateur a décidé que la table des familles utiliserait les fiches de modèles **et** les démos mesurées. Une valeur sans source n'y entre pas. Une famille qui n'a ni l'un ni l'autre retombe sur `other`, et le fichier dit que son échantillonnage n'est qu'un point de départ. | ||
| 97 | + | ||
| 98 | +**Une seule table.** `presets.yaml` est intégré au binaire. Son en-tête dit qu'il doit être partagé avec le skill Claude du ticket 111 (un skill construit à partir du guide des réglages). Ce ticket est encore ouvert, et le skill `mm-agent-creator` ne lit pas ce fichier aujourd'hui. | ||
| 99 | + | ||
| 100 | +## Alternatives écartées | ||
| 101 | + | ||
| 102 | +- **Générer le fichier avec un modèle** (`agent.creator.yaml`). Conservé pour les cas qui sortent de l'ordinaire, mais pas par défaut : il faut un modèle de 27B chargé et plusieurs minutes par agent. | ||
| 103 | +- **Un seuil calculé sur la fenêtre native.** Écarté, voir plus haut : il compresserait presque tout de suite avec les fenêtres que sert Ollama. | ||
| 104 | +- **Les skills, les serveurs MCP, les hooks et les `mmConfigs` dans l'assistant.** Laissés hors de la première version. Le commentaire de fin du fichier renvoie aux guides pratiques. | ||
| 105 | +- **Des prompts dans la langue de l'utilisateur.** Écarté par le choix de l'utilisateur : les prompts générés sont en anglais. | ||
| 106 | + | ||
| 107 | +## Limites connues | ||
| 108 | + | ||
| 109 | +- Les vérifications en direct n'ont été faites qu'avec llmman (Qwen3.5 4B, gemma-4-E4B). Ollama, Docker Model Runner et llama-server ont été testés contre de faux serveurs enregistrés dans les tests. L'API OpenAI elle-même n'a pas été essayée ; ses contraintes viennent de sa référence. | ||
| 110 | +- Une valeur `[card]` a été recopiée, pas mesurée dans ce dépôt. | ||
| 111 | +- Les familles sont reconnues sur des mots de l'identifiant du modèle : un modèle renommé par son éditeur peut tomber dans `other`. | ||
| 112 | + | ||
| 113 | +## Liens avec le reste | ||
| 114 | + | ||
| 115 | +- [Fournisseurs](providers.md) : les cinq serveurs que l'assistant peut interroger, et pourquoi chacun a sa propre entrée. | ||
| 116 | +- [Modèles à raisonnement](thinking-models.md) : ce que fait à l'exécution l'interrupteur de raisonnement que fixe l'assistant. | ||
| 117 | +- [Compression du contexte](context-compression.md) : ce que déclenche `context.threshold`. | ||
| 118 | +- [Sortie structurée](structured-output.md) : pourquoi l'usage `json` n'a pas d'outils. | ||
| 119 | +- [Interroger un autre agent](asking-another-agent.md) : ce sur quoi s'appuie l'usage `coordinator`. | ||
modified
docs/fr/how-to/create-an-agent.md +1 -0 | @@ -90,4 +90,5 @@ Ce guide montre comment écrire un nouvel agent.yaml pour un modèle et une tâc | ||
| 90 | 90 | - [Référence de la ligne de commande — `mm init`](../reference/cli.md#mm-init--lassistant-agentyaml) : chaque option, les sources, les codes de sortie |
| 91 | 91 | - [Référence de la configuration](../reference/configuration.md) : chaque clé du fichier |
| 92 | 92 | - [Réglages des agents pour petits modèles](../../../guides/reglages-agents-petits-modeles.md) : ce que fait chaque réglage, les lignes par machine |
| 93 | +- [D'où viennent les réglages](../explanation/mm-init.md) : les quatre sources, leur ordre, les étiquettes d'origine | |
| 93 | 94 | - `agent.creator.yaml` : un agent qui crée des agents avec un modèle, pour les cas qui sortent de l'ordinaire |
| @@ -90,4 +90,5 @@ Ce guide montre comment écrire un nouvel agent.yaml pour un modèle et une tâc | |||
| 90 | - [Référence de la ligne de commande — `mm init`](../reference/cli.md#mm-init--lassistant-agentyaml) : chaque option, les sources, les codes de sortie | 90 | - [Référence de la ligne de commande — `mm init`](../reference/cli.md#mm-init--lassistant-agentyaml) : chaque option, les sources, les codes de sortie |
| 91 | - [Référence de la configuration](../reference/configuration.md) : chaque clé du fichier | 91 | - [Référence de la configuration](../reference/configuration.md) : chaque clé du fichier |
| 92 | - [Réglages des agents pour petits modèles](../../../guides/reglages-agents-petits-modeles.md) : ce que fait chaque réglage, les lignes par machine | 92 | - [Réglages des agents pour petits modèles](../../../guides/reglages-agents-petits-modeles.md) : ce que fait chaque réglage, les lignes par machine |
| 93 | +- [D'où viennent les réglages](../explanation/mm-init.md) : les quatre sources, leur ordre, les étiquettes d'origine | ||
| 93 | - `agent.creator.yaml` : un agent qui crée des agents avec un modèle, pour les cas qui sortent de l'ordinaire | 94 | - `agent.creator.yaml` : un agent qui crée des agents avec un modèle, pour les cas qui sortent de l'ordinaire |
modified
internal/agentinit/wizard.go +6 -0 | @@ -175,6 +175,12 @@ func (f *Flow) takeDefaults() error { | ||
| 175 | 175 | if err := f.Set(st.Key, st.Default); err != nil { |
| 176 | 176 | return err |
| 177 | 177 | } |
| 178 | + // Set records the default as an answer, but nobody answered: leave | |
| 179 | + // yolo to the usage, so the file says "usage X's default", not | |
| 180 | + // "your answer". The value is the same either way. | |
| 181 | + if st.Key == "yolo" { | |
| 182 | + f.c.Yolo = nil | |
| 183 | + } | |
| 178 | 184 | } |
| 179 | 185 | } |
| 180 | 186 | |
| @@ -175,6 +175,12 @@ func (f *Flow) takeDefaults() error { | |||
| 175 | if err := f.Set(st.Key, st.Default); err != nil { | 175 | if err := f.Set(st.Key, st.Default); err != nil { |
| 176 | return err | 176 | return err |
| 177 | } | 177 | } |
| 178 | + // Set records the default as an answer, but nobody answered: leave | ||
| 179 | + // yolo to the usage, so the file says "usage X's default", not | ||
| 180 | + // "your answer". The value is the same either way. | ||
| 181 | + if st.Key == "yolo" { | ||
| 182 | + f.c.Yolo = nil | ||
| 183 | + } | ||
| 178 | } | 184 | } |
| 179 | } | 185 | } |
| 180 | 186 | ||
modified
internal/agentinit/wizard_test.go +20 -0 | @@ -45,6 +45,26 @@ func TestMainWithFlagsOnly(t *testing.T) { | ||
| 45 | 45 | } |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | +// --yes without --yolo: the value is the usage's default, and the comment | |
| 49 | +// says so — not "your answer", which nobody gave. | |
| 50 | +func TestMainYesKeepsTheUsageDefaultForYolo(t *testing.T) { | |
| 51 | + keepConfig(t) | |
| 52 | + out := filepath.Join(t.TempDir(), "agent.yaml") | |
| 53 | + var stdout bytes.Buffer | |
| 54 | + code := Main([]string{"--provider", "llmman", "--base-url", llmmanStub(t), "--usage", "developer", "--machine", "small", "--name", "bob", "-o", out, "--yes"}, strings.NewReader(""), &stdout) | |
| 55 | + if code != 0 { | |
| 56 | + t.Fatalf("exit %d:\n%s", code, stdout.String()) | |
| 57 | + } | |
| 58 | + data, _ := os.ReadFile(out) | |
| 59 | + text := string(data) | |
| 60 | + if !strings.Contains(text, "# usage developer's default: every command") || !strings.Contains(text, "\nyolo: false\n") { | |
| 61 | + t.Errorf("yolo is not the usage's default with its reason:\n%s", text) | |
| 62 | + } | |
| 63 | + if strings.Contains(text, "# your answer") { | |
| 64 | + t.Errorf("--yes answered nothing, yet the file says \"your answer\":\n%s", text) | |
| 65 | + } | |
| 66 | +} | |
| 67 | + | |
| 48 | 68 | // Questions answered on stdin: the model from the server's list, the usage |
| 49 | 69 | // and machine by number, yolo, the name, the file. |
| 50 | 70 | func TestMainAsksTheQuestions(t *testing.T) { |
| @@ -45,6 +45,26 @@ func TestMainWithFlagsOnly(t *testing.T) { | |||
| 45 | } | 45 | } |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | +// --yes without --yolo: the value is the usage's default, and the comment | ||
| 49 | +// says so — not "your answer", which nobody gave. | ||
| 50 | +func TestMainYesKeepsTheUsageDefaultForYolo(t *testing.T) { | ||
| 51 | + keepConfig(t) | ||
| 52 | + out := filepath.Join(t.TempDir(), "agent.yaml") | ||
| 53 | + var stdout bytes.Buffer | ||
| 54 | + code := Main([]string{"--provider", "llmman", "--base-url", llmmanStub(t), "--usage", "developer", "--machine", "small", "--name", "bob", "-o", out, "--yes"}, strings.NewReader(""), &stdout) | ||
| 55 | + if code != 0 { | ||
| 56 | + t.Fatalf("exit %d:\n%s", code, stdout.String()) | ||
| 57 | + } | ||
| 58 | + data, _ := os.ReadFile(out) | ||
| 59 | + text := string(data) | ||
| 60 | + if !strings.Contains(text, "# usage developer's default: every command") || !strings.Contains(text, "\nyolo: false\n") { | ||
| 61 | + t.Errorf("yolo is not the usage's default with its reason:\n%s", text) | ||
| 62 | + } | ||
| 63 | + if strings.Contains(text, "# your answer") { | ||
| 64 | + t.Errorf("--yes answered nothing, yet the file says \"your answer\":\n%s", text) | ||
| 65 | + } | ||
| 66 | +} | ||
| 67 | + | ||
| 48 | // Questions answered on stdin: the model from the server's list, the usage | 68 | // Questions answered on stdin: the model from the server's list, the usage |
| 49 | // and machine by number, yolo, the name, the file. | 69 | // and machine by number, yolo, the name, the file. |
| 50 | func TestMainAsksTheQuestions(t *testing.T) { | 70 | func TestMainAsksTheQuestions(t *testing.T) { |