mm ini #40
Merged@k33g wants to merge
feature/mm-init into mainMerged as
a38f300bae7d.45 files changed
modified
.tickets/issues/0061-llmman-provider-download-the-model-automatically.yaml +2 -2 | @@ -6,9 +6,9 @@ author: | ||
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-01T05:48:44.919Z |
| 9 | -updatedAt: 2026-10-20T07:39:23.051Z | |
| 9 | +updatedAt: 2026-10-21T11:45:30.797Z | |
| 10 | 10 | labels: [] |
| 11 | -milestone: v0.9.0 | |
| 11 | +milestone: v1.0.0 | |
| 12 | 12 | epic: Providers (LLM Engine) |
| 13 | 13 | body: "" |
| 14 | 14 | tasks: [] |
| @@ -6,9 +6,9 @@ author: | |||
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-10-01T05:48:44.919Z | 8 | createdAt: 2026-10-01T05:48:44.919Z |
| 9 | -updatedAt: 2026-10-20T07:39:23.051Z | 9 | +updatedAt: 2026-10-21T11:45:30.797Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | -milestone: v0.9.0 | 11 | +milestone: v1.0.0 |
| 12 | epic: Providers (LLM Engine) | 12 | epic: Providers (LLM Engine) |
| 13 | body: "" | 13 | body: "" |
| 14 | tasks: [] | 14 | tasks: [] |
modified
.tickets/issues/0075-add-gronk-provider.yaml +2 -2 | @@ -6,9 +6,9 @@ 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-20T07:48:28.395Z | |
| 9 | +updatedAt: 2026-10-21T11:49:01.282Z | |
| 10 | 10 | labels: [] |
| 11 | -milestone: v0.9.0 | |
| 11 | +milestone: v1.0.0 | |
| 12 | 12 | epic: Providers (LLM Engine) |
| 13 | 13 | body: "" |
| 14 | 14 | tasks: [] |
| @@ -6,9 +6,9 @@ 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-20T07:48:28.395Z | 9 | +updatedAt: 2026-10-21T11:49:01.282Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | -milestone: v0.9.0 | 11 | +milestone: v1.0.0 |
| 12 | epic: Providers (LLM Engine) | 12 | epic: Providers (LLM Engine) |
| 13 | body: "" | 13 | body: "" |
| 14 | tasks: [] | 14 | tasks: [] |
added
.tickets/issues/0097-generate-an-agent-yaml-file-with-the-cli.yaml +275 -0 | new file mode 100644 | ||
| @@ -0,0 +1,275 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 97 | |
| 3 | +title: Generate an agent.yaml file with the CLI | |
| 4 | +state: closed | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-18T12:31:14.544Z | |
| 9 | +updatedAt: 2026-10-21T23:00:00.000Z | |
| 10 | +labels: [] | |
| 11 | +milestone: v0.9.0 | |
| 12 | +related: | |
| 13 | + - 98 | |
| 14 | +body: | | |
| 15 | + generate an agent configuration file from de CLI (`mm`) | |
| 16 | + | |
| 17 | + - with a wizard using options with kind of model: qwen, gemma, mellum, llama, mistral and ask for the type of usage (developer, translateur, ...) and then generate the appropriate settings | |
| 18 | +tasks: | |
| 19 | + - id: 1 | |
| 20 | + title: "Agree on the open questions (command name, families, usages, sources of the family table, server probing, prompt language)" | |
| 21 | + state: closed | |
| 22 | + priority: none | |
| 23 | + author: | |
| 24 | + name: k33g | |
| 25 | + email: ph.charriere@gmail.com | |
| 26 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 27 | + updatedAt: 2026-10-21T16:00:00.000Z | |
| 28 | + - id: 2 | |
| 29 | + title: "Port model_facts.py's rules to Go: read a model's facts from llmman/Ollama (/api/show) and llama.cpp (/props) — with tests on recorded answers" | |
| 30 | + state: closed | |
| 31 | + priority: none | |
| 32 | + author: | |
| 33 | + name: k33g | |
| 34 | + email: ph.charriere@gmail.com | |
| 35 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 36 | + updatedAt: 2026-10-21T16:00:00.000Z | |
| 37 | + - id: 3 | |
| 38 | + title: "Family table (sourced values) + usage profiles + machine rows (from the settings guide) — with tests" | |
| 39 | + state: closed | |
| 40 | + priority: none | |
| 41 | + author: | |
| 42 | + name: k33g | |
| 43 | + email: ph.charriere@gmail.com | |
| 44 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 45 | + updatedAt: 2026-10-21T16:00:00.000Z | |
| 46 | + - id: 4 | |
| 47 | + title: "The wizard: questions through internal/elicit in the terminal, flags for every question, never overwrite — with tests" | |
| 48 | + state: closed | |
| 49 | + priority: none | |
| 50 | + author: | |
| 51 | + name: k33g | |
| 52 | + email: ph.charriere@gmail.com | |
| 53 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 54 | + updatedAt: 2026-10-21T16:00:00.000Z | |
| 55 | + - id: 5 | |
| 56 | + title: "Generate the commented agent.yaml, load it with config.Load, --check sends one question — with tests and a live check per provider available" | |
| 57 | + state: closed | |
| 58 | + priority: none | |
| 59 | + author: | |
| 60 | + name: k33g | |
| 61 | + email: ph.charriere@gmail.com | |
| 62 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 63 | + updatedAt: 2026-10-21T16:00:00.000Z | |
| 64 | + - id: 6 | |
| 65 | + title: "Docs EN+FR (how-to: create an agent with mm init; reference: the flags), README, release notes" | |
| 66 | + state: closed | |
| 67 | + priority: none | |
| 68 | + author: | |
| 69 | + name: k33g | |
| 70 | + email: ph.charriere@gmail.com | |
| 71 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 72 | + updatedAt: 2026-10-21T16:00:00.000Z | |
| 73 | +comments: | |
| 74 | + - id: 1 | |
| 75 | + author: | |
| 76 | + name: k33g | |
| 77 | + email: ph.charriere@gmail.com | |
| 78 | + createdAt: 2026-10-21T16:00:00.000Z | |
| 79 | + body: | | |
| 80 | + Proposal (2026-10-21) — to confirm before coding. | |
| 81 | + | |
| 82 | + ## What exists already (checked in the repo) | |
| 83 | + - agent.creator.yaml + skills/create-agent: an LLM agent (Qwen3.8 27B) | |
| 84 | + that creates an agent.yaml. Powerful, but needs a 27B model loaded and | |
| 85 | + minutes per agent. | |
| 86 | + - skills/create-agent/model_facts.py: reads a model from llmman | |
| 87 | + (/api/show, /api/tags) — context window, the sampling recommended in the | |
| 88 | + GGUF, the chat template's reasoning switch and its default, the tool-call | |
| 89 | + format — and turns them into settings rules. | |
| 90 | + - guides/agent-settings-for-small-models.md (ticket 98): the "typical | |
| 91 | + profiles" table (timeouts, maxTurns, maxOutput, context) and the sampling | |
| 92 | + advice. | |
| 93 | + - config.samples/ (dmr gemma, gpt-oss, qwen3.6; llamacpp ornith, qwen3.8) | |
| 94 | + and the demos: tested settings per model. | |
| 95 | + - internal/elicit: the questions (choice, multi, text, confirm) and their | |
| 96 | + line-mode answers, used by ask_user in the REPL. | |
| 97 | + | |
| 98 | + ## Proposal: `mm init` — a wizard with no model to run | |
| 99 | + A deterministic generator, in Go, in mm itself: questions in the terminal, | |
| 100 | + then a commented agent.yaml. No LLM involved, so it is instant and works | |
| 101 | + before any agent exists. agent.creator.yaml stays for the unusual cases. | |
| 102 | + | |
| 103 | + ### Questions (in this order, each with a default) | |
| 104 | + 1. Model server: dmr / llmman / ollama / llamacpp — and its URL (the | |
| 105 | + provider's default; the wizard checks it answers). | |
| 106 | + 2. Model: picked from the server's list (/v1/models, or llmman's | |
| 107 | + /api/tags) — or typed. | |
| 108 | + 3. Model family: detected from the name (qwen, gemma, mellum, llama, | |
| 109 | + mistral, gpt-oss, granite, minicpm… — "other" when unknown), shown for | |
| 110 | + confirmation. | |
| 111 | + 4. Usage: developer (code), translator, writer / documentation, assistant | |
| 112 | + (questions & answers), reviewer, JSON extractor (structuredOutput), | |
| 113 | + coordinator (asks other agents) — each a profile, see below. | |
| 114 | + 5. Machine: small (laptop, ≤ 8B models) / medium / large — picks the row of | |
| 115 | + the settings guide's profiles table. | |
| 116 | + 6. Ask before each change (yolo: false)? — default from the usage. | |
| 117 | + 7. Agent name and file name (default agent.yaml; never overwrite an | |
| 118 | + existing file, as /save). | |
| 119 | + | |
| 120 | + ### Where each setting comes from (most reliable first) | |
| 121 | + 1. The server's facts about THAT model, when it can tell (llmman, Ollama: | |
| 122 | + /api/show; llama.cpp: /props): the context window, the GGUF's sampling, | |
| 123 | + the reasoning switch (enable_thinking or reasoning_effort) and its | |
| 124 | + default — the rules of model_facts.py, ported to Go. | |
| 125 | + 2. The family table, when the server cannot tell (DMR, or no GGUF | |
| 126 | + sampling): the authors' published sampling and reasoning switches per | |
| 127 | + family — each value sourced from a model card or a measured demo, the | |
| 128 | + source written in a comment of the generated file. | |
| 129 | + 3. The usage profile: which tools (developer: bash + files + plan; | |
| 130 | + translator / writer: none, or files only; JSON extractor: none — | |
| 131 | + structuredOutput forbids tools; coordinator: ask_agent), reasoning on or | |
| 132 | + off (on for code and multi-step work, off for short tasks — the | |
| 133 | + create-agent rule), a starting system prompt, maxTurns. | |
| 134 | + 4. The machine row of the settings guide: firstTokenTimeout, | |
| 135 | + watchdogTimeout, bashTimeout, maxOutput, context compression. | |
| 136 | + | |
| 137 | + ### The generated file | |
| 138 | + Every key commented with WHY it has that value ("from the GGUF", "Qwen's | |
| 139 | + model card", "settings guide, small machine row"), the way the demos' | |
| 140 | + agent.yaml are written — so the file teaches as it configures. Then the | |
| 141 | + wizard loads it with config.Load and, with `--check`, sends one question | |
| 142 | + ("Say hello in one line.") to prove the model answers. | |
| 143 | + | |
| 144 | + ### Non-interactive, for scripts and tests | |
| 145 | + `mm init --provider llmman --model hf.co/… --usage translator --machine | |
| 146 | + small --name lucy -o agent.yaml`: every question has a flag; with all of | |
| 147 | + them, no prompt at all. | |
| 148 | + | |
| 149 | + ### Not in scope of a first version | |
| 150 | + Skills scaffolding, MCP servers, hooks, mmConfigs agents — the wizard says | |
| 151 | + where to add them (links to the how-tos) in the file's closing comment. | |
| 152 | + | |
| 153 | + ## Open questions | |
| 154 | + - Command name: `mm init`, `mm new`, or a flag `--init`? | |
| 155 | + - The families and usages above: keep, add, remove? | |
| 156 | + - Source of the family table: model cards only, or the measured demos too | |
| 157 | + (which also give tested maxTurns / timeouts)? | |
| 158 | + - Probe the server for its model list, or only ask for a name? | |
| 159 | + - The generated system prompts: English only, or in the language the user | |
| 160 | + picks? | |
| 161 | + - Ticket 111 (a Claude skill from the settings guide): same knowledge — one | |
| 162 | + shared table in Go that both use, or separate? | |
| 163 | + - id: 2 | |
| 164 | + author: | |
| 165 | + name: k33g | |
| 166 | + email: ph.charriere@gmail.com | |
| 167 | + createdAt: 2026-10-21T16:30:00.000Z | |
| 168 | + body: | | |
| 169 | + Decided by the user (2026-10-21): | |
| 170 | + 1. both spellings: `mm init` and `mm --init`; | |
| 171 | + 2. families and usages: the proposed ones, completed as needed; | |
| 172 | + 3. the family table draws on both the model cards and the measured | |
| 173 | + demos (each value with its source); | |
| 174 | + 4. the wizard queries the server (model list, model facts); | |
| 175 | + 5. generated system prompts in English only; | |
| 176 | + 6. one shared table, used by mm init and by the Claude skill of | |
| 177 | + ticket 111. | |
| 178 | + - id: 3 | |
| 179 | + author: | |
| 180 | + name: k33g | |
| 181 | + email: ph.charriere@gmail.com | |
| 182 | + createdAt: 2026-10-21T18:00:00.000Z | |
| 183 | + body: | | |
| 184 | + Implemented on feature/mm-init (branch created at the user's request). | |
| 185 | + - internal/agentinit (new): presets.yaml (embedded; THE shared table for | |
| 186 | + ticket 111: 13 families — qwen-coder, qwen, gemma, mellum-thinking, | |
| 187 | + mellum, gpt-oss, minicpm, ornith, granite-guardian, menlo, llama, | |
| 188 | + mistral, other — each with its source: model cards (Qwen, Gemma 4 | |
| 189 | + GGUF, Llama 3.1 generation_config, Mistral Small 3.1 card) and the | |
| 190 | + measured demos; 9 usages — developer, reviewer, translator, writer, | |
| 191 | + assistant, researcher, docs, json, coordinator — with tools, | |
| 192 | + reasoning, precise, maxTurns, yolo and an English system prompt; 3 | |
| 193 | + machine rows from the settings guide); facts.go (model_facts.py | |
| 194 | + ported: /api/tags, /api/show — native window, general.sampling.*, | |
| 195 | + Ollama parameters, template reasoning switch and default — llama.cpp | |
| 196 | + /props, OpenAI /models); decide.go (each value with its reason: server | |
| 197 | + facts > family > usage > machine); render.go (commented YAML, | |
| 198 | + consecutive settings sharing one comment); wizard.go (questions through | |
| 199 | + internal/elicit, legends, Enter = default, every question a flag, | |
| 200 | + --yes, -o -, never overwrite — checked before any question —, | |
| 201 | + config.Load after writing, --check runs this mm -p). | |
| 202 | + - main.go: `mm init`, `mm --init`, `-init` answered before flag.Parse; | |
| 203 | + `--init` listed in -h. | |
| 204 | + - Changed from the proposal: context.threshold stays mm's 75 — a | |
| 205 | + threshold computed from the NATIVE window (the create-agent rule) | |
| 206 | + would compress almost at once on a server that serves less (Ollama | |
| 207 | + often 4k–8k), since mm applies it to the served window. | |
| 208 | + - Tests: presets (every entry sourced; family matching), facts (fake | |
| 209 | + servers per provider, template switches), decide/render (every usage | |
| 210 | + × 4 families × 3 machines loads with config.Load; sampling cases; | |
| 211 | + tools / docs / json / guard note), wizard (flags only, piped answers, | |
| 212 | + never overwrite, stdout, bad answers), main (isInit; the generated | |
| 213 | + JSON agent declares no tool — StructuredOutputConflict). | |
| 214 | + - Live (llmman, Qwen3.5 4B): developer, translator, docs and json | |
| 215 | + written with --yes --check — each loads and the model answers (the | |
| 216 | + json agent answered JSON of the example's shape); interactive run with | |
| 217 | + piped answers on gemma-4-E4B. Ollama, DMR and llama-server were not | |
| 218 | + running here: their paths are covered by the fake-server tests only. | |
| 219 | + - Docs EN+FR: how-to create-an-agent, reference/cli (mm init section, | |
| 220 | + invocation line), both indexes, root README, packages.drawio. | |
| 221 | + Not done: release notes (v0.9.0 has none yet); ticket 111's skill | |
| 222 | + itself (it can now read internal/agentinit/presets.yaml). | |
| 223 | + - id: 4 | |
| 224 | + author: | |
| 225 | + name: k33g | |
| 226 | + email: ph.charriere@gmail.com | |
| 227 | + createdAt: 2026-10-21T20:00:00.000Z | |
| 228 | + body: | | |
| 229 | + Updated for ticket 118 (the generic openai provider): | |
| 230 | + - `openai` is offered as a fifth server, but never probed for the first | |
| 231 | + question's default (its default address is the OpenAI API: mm init | |
| 232 | + must not call a remote service nobody asked for); | |
| 233 | + - its model list is read with OPENAI_API_KEY (Authorization header); | |
| 234 | + - the file says where the key comes from, that no baseUrl means the | |
| 235 | + OpenAI API, and that this provider cannot ask for the window | |
| 236 | + (contextWindow: 0 = unknown → compression counts messages); | |
| 237 | + - presets.yaml: a new family `openai` (match `gpt-`, after gpt-oss): | |
| 238 | + temperature 1.0 and max_completion_tokens instead of max_tokens (new | |
| 239 | + field maxTokensKey), with a note — source: the OpenAI API reference, | |
| 240 | + not measured here. | |
| 241 | + - Tests: openai lists models with the key (and other providers do not | |
| 242 | + send one), the openai family and provider render and load, openai is | |
| 243 | + not in the probed list. Live: mm init --provider openai on llmman's | |
| 244 | + OpenAI address with --check — written, loaded, the model answered. | |
| 245 | + - Docs EN+FR: reference/cli (provider row, facts row), how-to | |
| 246 | + create-an-agent (server list, prerequisites). | |
| 247 | + - id: 5 | |
| 248 | + author: | |
| 249 | + name: k33g | |
| 250 | + email: ph.charriere@gmail.com | |
| 251 | + createdAt: 2026-10-21T22:00:00.000Z | |
| 252 | + body: | | |
| 253 | + A window "in the style of the TUI" (user's layout choice: steps + | |
| 254 | + choices + preview): | |
| 255 | + - internal/agentinit/flow.go: the questions as a UI-agnostic Flow | |
| 256 | + (Steps, Set/Unset, Preview of the file with a candidate answer, | |
| 257 | + Result); the line wizard and the window both drive it. | |
| 258 | + - internal/tui/initwin.go (tui.RunInit): steps on the left (✓ ▸ ·, each | |
| 259 | + answer beside it), the question with the highlighted choice's | |
| 260 | + description, and the agent.yaml as it would be written with that | |
| 261 | + choice, live; a confirmation screen before writing. Keys: ↑↓ Home | |
| 262 | + End, Enter, y/n, Esc back (skips flag answers), PgUp/PgDn preview, | |
| 263 | + Tab = preview in place of the question below 100 columns, Ctrl-U, | |
| 264 | + Ctrl-C = nothing written. | |
| 265 | + - The window opens when stdin and stdout are terminals; `--line` (new) | |
| 266 | + or a pipe keeps the line-by-line questions; --yes asks nothing. | |
| 267 | + The step "Yolo" is labelled "Ask first" (Yolo no read as yes). | |
| 268 | + - Tests: flow (steps, preview candidate), window on a tcell | |
| 269 | + SimulationScreen (defaults all the way, preview follows the | |
| 270 | + selection, back/text/quit, narrow Tab). Live in a pty (130×34, | |
| 271 | + pyte) against llmman: written and loaded. | |
| 272 | + - Docs EN+FR: how-to create-an-agent (real capture, keys, line mode), | |
| 273 | + reference/cli (Window and Line mode rows, --line), the TUI keyboard | |
| 274 | + shortcuts guide (an mm init section), packages.drawio (tui → | |
| 275 | + agentinit). | |
| new file mode 100644 | |||
| @@ -0,0 +1,275 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 97 | ||
| 3 | +title: Generate an agent.yaml file with the CLI | ||
| 4 | +state: closed | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-18T12:31:14.544Z | ||
| 9 | +updatedAt: 2026-10-21T23:00:00.000Z | ||
| 10 | +labels: [] | ||
| 11 | +milestone: v0.9.0 | ||
| 12 | +related: | ||
| 13 | + - 98 | ||
| 14 | +body: | | ||
| 15 | + generate an agent configuration file from de CLI (`mm`) | ||
| 16 | + | ||
| 17 | + - with a wizard using options with kind of model: qwen, gemma, mellum, llama, mistral and ask for the type of usage (developer, translateur, ...) and then generate the appropriate settings | ||
| 18 | +tasks: | ||
| 19 | + - id: 1 | ||
| 20 | + title: "Agree on the open questions (command name, families, usages, sources of the family table, server probing, prompt language)" | ||
| 21 | + state: closed | ||
| 22 | + priority: none | ||
| 23 | + author: | ||
| 24 | + name: k33g | ||
| 25 | + email: ph.charriere@gmail.com | ||
| 26 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 27 | + updatedAt: 2026-10-21T16:00:00.000Z | ||
| 28 | + - id: 2 | ||
| 29 | + title: "Port model_facts.py's rules to Go: read a model's facts from llmman/Ollama (/api/show) and llama.cpp (/props) — with tests on recorded answers" | ||
| 30 | + state: closed | ||
| 31 | + priority: none | ||
| 32 | + author: | ||
| 33 | + name: k33g | ||
| 34 | + email: ph.charriere@gmail.com | ||
| 35 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 36 | + updatedAt: 2026-10-21T16:00:00.000Z | ||
| 37 | + - id: 3 | ||
| 38 | + title: "Family table (sourced values) + usage profiles + machine rows (from the settings guide) — with tests" | ||
| 39 | + state: closed | ||
| 40 | + priority: none | ||
| 41 | + author: | ||
| 42 | + name: k33g | ||
| 43 | + email: ph.charriere@gmail.com | ||
| 44 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 45 | + updatedAt: 2026-10-21T16:00:00.000Z | ||
| 46 | + - id: 4 | ||
| 47 | + title: "The wizard: questions through internal/elicit in the terminal, flags for every question, never overwrite — with tests" | ||
| 48 | + state: closed | ||
| 49 | + priority: none | ||
| 50 | + author: | ||
| 51 | + name: k33g | ||
| 52 | + email: ph.charriere@gmail.com | ||
| 53 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 54 | + updatedAt: 2026-10-21T16:00:00.000Z | ||
| 55 | + - id: 5 | ||
| 56 | + title: "Generate the commented agent.yaml, load it with config.Load, --check sends one question — with tests and a live check per provider available" | ||
| 57 | + state: closed | ||
| 58 | + priority: none | ||
| 59 | + author: | ||
| 60 | + name: k33g | ||
| 61 | + email: ph.charriere@gmail.com | ||
| 62 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 63 | + updatedAt: 2026-10-21T16:00:00.000Z | ||
| 64 | + - id: 6 | ||
| 65 | + title: "Docs EN+FR (how-to: create an agent with mm init; reference: the flags), README, release notes" | ||
| 66 | + state: closed | ||
| 67 | + priority: none | ||
| 68 | + author: | ||
| 69 | + name: k33g | ||
| 70 | + email: ph.charriere@gmail.com | ||
| 71 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 72 | + updatedAt: 2026-10-21T16:00:00.000Z | ||
| 73 | +comments: | ||
| 74 | + - id: 1 | ||
| 75 | + author: | ||
| 76 | + name: k33g | ||
| 77 | + email: ph.charriere@gmail.com | ||
| 78 | + createdAt: 2026-10-21T16:00:00.000Z | ||
| 79 | + body: | | ||
| 80 | + Proposal (2026-10-21) — to confirm before coding. | ||
| 81 | + | ||
| 82 | + ## What exists already (checked in the repo) | ||
| 83 | + - agent.creator.yaml + skills/create-agent: an LLM agent (Qwen3.8 27B) | ||
| 84 | + that creates an agent.yaml. Powerful, but needs a 27B model loaded and | ||
| 85 | + minutes per agent. | ||
| 86 | + - skills/create-agent/model_facts.py: reads a model from llmman | ||
| 87 | + (/api/show, /api/tags) — context window, the sampling recommended in the | ||
| 88 | + GGUF, the chat template's reasoning switch and its default, the tool-call | ||
| 89 | + format — and turns them into settings rules. | ||
| 90 | + - guides/agent-settings-for-small-models.md (ticket 98): the "typical | ||
| 91 | + profiles" table (timeouts, maxTurns, maxOutput, context) and the sampling | ||
| 92 | + advice. | ||
| 93 | + - config.samples/ (dmr gemma, gpt-oss, qwen3.6; llamacpp ornith, qwen3.8) | ||
| 94 | + and the demos: tested settings per model. | ||
| 95 | + - internal/elicit: the questions (choice, multi, text, confirm) and their | ||
| 96 | + line-mode answers, used by ask_user in the REPL. | ||
| 97 | + | ||
| 98 | + ## Proposal: `mm init` — a wizard with no model to run | ||
| 99 | + A deterministic generator, in Go, in mm itself: questions in the terminal, | ||
| 100 | + then a commented agent.yaml. No LLM involved, so it is instant and works | ||
| 101 | + before any agent exists. agent.creator.yaml stays for the unusual cases. | ||
| 102 | + | ||
| 103 | + ### Questions (in this order, each with a default) | ||
| 104 | + 1. Model server: dmr / llmman / ollama / llamacpp — and its URL (the | ||
| 105 | + provider's default; the wizard checks it answers). | ||
| 106 | + 2. Model: picked from the server's list (/v1/models, or llmman's | ||
| 107 | + /api/tags) — or typed. | ||
| 108 | + 3. Model family: detected from the name (qwen, gemma, mellum, llama, | ||
| 109 | + mistral, gpt-oss, granite, minicpm… — "other" when unknown), shown for | ||
| 110 | + confirmation. | ||
| 111 | + 4. Usage: developer (code), translator, writer / documentation, assistant | ||
| 112 | + (questions & answers), reviewer, JSON extractor (structuredOutput), | ||
| 113 | + coordinator (asks other agents) — each a profile, see below. | ||
| 114 | + 5. Machine: small (laptop, ≤ 8B models) / medium / large — picks the row of | ||
| 115 | + the settings guide's profiles table. | ||
| 116 | + 6. Ask before each change (yolo: false)? — default from the usage. | ||
| 117 | + 7. Agent name and file name (default agent.yaml; never overwrite an | ||
| 118 | + existing file, as /save). | ||
| 119 | + | ||
| 120 | + ### Where each setting comes from (most reliable first) | ||
| 121 | + 1. The server's facts about THAT model, when it can tell (llmman, Ollama: | ||
| 122 | + /api/show; llama.cpp: /props): the context window, the GGUF's sampling, | ||
| 123 | + the reasoning switch (enable_thinking or reasoning_effort) and its | ||
| 124 | + default — the rules of model_facts.py, ported to Go. | ||
| 125 | + 2. The family table, when the server cannot tell (DMR, or no GGUF | ||
| 126 | + sampling): the authors' published sampling and reasoning switches per | ||
| 127 | + family — each value sourced from a model card or a measured demo, the | ||
| 128 | + source written in a comment of the generated file. | ||
| 129 | + 3. The usage profile: which tools (developer: bash + files + plan; | ||
| 130 | + translator / writer: none, or files only; JSON extractor: none — | ||
| 131 | + structuredOutput forbids tools; coordinator: ask_agent), reasoning on or | ||
| 132 | + off (on for code and multi-step work, off for short tasks — the | ||
| 133 | + create-agent rule), a starting system prompt, maxTurns. | ||
| 134 | + 4. The machine row of the settings guide: firstTokenTimeout, | ||
| 135 | + watchdogTimeout, bashTimeout, maxOutput, context compression. | ||
| 136 | + | ||
| 137 | + ### The generated file | ||
| 138 | + Every key commented with WHY it has that value ("from the GGUF", "Qwen's | ||
| 139 | + model card", "settings guide, small machine row"), the way the demos' | ||
| 140 | + agent.yaml are written — so the file teaches as it configures. Then the | ||
| 141 | + wizard loads it with config.Load and, with `--check`, sends one question | ||
| 142 | + ("Say hello in one line.") to prove the model answers. | ||
| 143 | + | ||
| 144 | + ### Non-interactive, for scripts and tests | ||
| 145 | + `mm init --provider llmman --model hf.co/… --usage translator --machine | ||
| 146 | + small --name lucy -o agent.yaml`: every question has a flag; with all of | ||
| 147 | + them, no prompt at all. | ||
| 148 | + | ||
| 149 | + ### Not in scope of a first version | ||
| 150 | + Skills scaffolding, MCP servers, hooks, mmConfigs agents — the wizard says | ||
| 151 | + where to add them (links to the how-tos) in the file's closing comment. | ||
| 152 | + | ||
| 153 | + ## Open questions | ||
| 154 | + - Command name: `mm init`, `mm new`, or a flag `--init`? | ||
| 155 | + - The families and usages above: keep, add, remove? | ||
| 156 | + - Source of the family table: model cards only, or the measured demos too | ||
| 157 | + (which also give tested maxTurns / timeouts)? | ||
| 158 | + - Probe the server for its model list, or only ask for a name? | ||
| 159 | + - The generated system prompts: English only, or in the language the user | ||
| 160 | + picks? | ||
| 161 | + - Ticket 111 (a Claude skill from the settings guide): same knowledge — one | ||
| 162 | + shared table in Go that both use, or separate? | ||
| 163 | + - id: 2 | ||
| 164 | + author: | ||
| 165 | + name: k33g | ||
| 166 | + email: ph.charriere@gmail.com | ||
| 167 | + createdAt: 2026-10-21T16:30:00.000Z | ||
| 168 | + body: | | ||
| 169 | + Decided by the user (2026-10-21): | ||
| 170 | + 1. both spellings: `mm init` and `mm --init`; | ||
| 171 | + 2. families and usages: the proposed ones, completed as needed; | ||
| 172 | + 3. the family table draws on both the model cards and the measured | ||
| 173 | + demos (each value with its source); | ||
| 174 | + 4. the wizard queries the server (model list, model facts); | ||
| 175 | + 5. generated system prompts in English only; | ||
| 176 | + 6. one shared table, used by mm init and by the Claude skill of | ||
| 177 | + ticket 111. | ||
| 178 | + - id: 3 | ||
| 179 | + author: | ||
| 180 | + name: k33g | ||
| 181 | + email: ph.charriere@gmail.com | ||
| 182 | + createdAt: 2026-10-21T18:00:00.000Z | ||
| 183 | + body: | | ||
| 184 | + Implemented on feature/mm-init (branch created at the user's request). | ||
| 185 | + - internal/agentinit (new): presets.yaml (embedded; THE shared table for | ||
| 186 | + ticket 111: 13 families — qwen-coder, qwen, gemma, mellum-thinking, | ||
| 187 | + mellum, gpt-oss, minicpm, ornith, granite-guardian, menlo, llama, | ||
| 188 | + mistral, other — each with its source: model cards (Qwen, Gemma 4 | ||
| 189 | + GGUF, Llama 3.1 generation_config, Mistral Small 3.1 card) and the | ||
| 190 | + measured demos; 9 usages — developer, reviewer, translator, writer, | ||
| 191 | + assistant, researcher, docs, json, coordinator — with tools, | ||
| 192 | + reasoning, precise, maxTurns, yolo and an English system prompt; 3 | ||
| 193 | + machine rows from the settings guide); facts.go (model_facts.py | ||
| 194 | + ported: /api/tags, /api/show — native window, general.sampling.*, | ||
| 195 | + Ollama parameters, template reasoning switch and default — llama.cpp | ||
| 196 | + /props, OpenAI /models); decide.go (each value with its reason: server | ||
| 197 | + facts > family > usage > machine); render.go (commented YAML, | ||
| 198 | + consecutive settings sharing one comment); wizard.go (questions through | ||
| 199 | + internal/elicit, legends, Enter = default, every question a flag, | ||
| 200 | + --yes, -o -, never overwrite — checked before any question —, | ||
| 201 | + config.Load after writing, --check runs this mm -p). | ||
| 202 | + - main.go: `mm init`, `mm --init`, `-init` answered before flag.Parse; | ||
| 203 | + `--init` listed in -h. | ||
| 204 | + - Changed from the proposal: context.threshold stays mm's 75 — a | ||
| 205 | + threshold computed from the NATIVE window (the create-agent rule) | ||
| 206 | + would compress almost at once on a server that serves less (Ollama | ||
| 207 | + often 4k–8k), since mm applies it to the served window. | ||
| 208 | + - Tests: presets (every entry sourced; family matching), facts (fake | ||
| 209 | + servers per provider, template switches), decide/render (every usage | ||
| 210 | + × 4 families × 3 machines loads with config.Load; sampling cases; | ||
| 211 | + tools / docs / json / guard note), wizard (flags only, piped answers, | ||
| 212 | + never overwrite, stdout, bad answers), main (isInit; the generated | ||
| 213 | + JSON agent declares no tool — StructuredOutputConflict). | ||
| 214 | + - Live (llmman, Qwen3.5 4B): developer, translator, docs and json | ||
| 215 | + written with --yes --check — each loads and the model answers (the | ||
| 216 | + json agent answered JSON of the example's shape); interactive run with | ||
| 217 | + piped answers on gemma-4-E4B. Ollama, DMR and llama-server were not | ||
| 218 | + running here: their paths are covered by the fake-server tests only. | ||
| 219 | + - Docs EN+FR: how-to create-an-agent, reference/cli (mm init section, | ||
| 220 | + invocation line), both indexes, root README, packages.drawio. | ||
| 221 | + Not done: release notes (v0.9.0 has none yet); ticket 111's skill | ||
| 222 | + itself (it can now read internal/agentinit/presets.yaml). | ||
| 223 | + - id: 4 | ||
| 224 | + author: | ||
| 225 | + name: k33g | ||
| 226 | + email: ph.charriere@gmail.com | ||
| 227 | + createdAt: 2026-10-21T20:00:00.000Z | ||
| 228 | + body: | | ||
| 229 | + Updated for ticket 118 (the generic openai provider): | ||
| 230 | + - `openai` is offered as a fifth server, but never probed for the first | ||
| 231 | + question's default (its default address is the OpenAI API: mm init | ||
| 232 | + must not call a remote service nobody asked for); | ||
| 233 | + - its model list is read with OPENAI_API_KEY (Authorization header); | ||
| 234 | + - the file says where the key comes from, that no baseUrl means the | ||
| 235 | + OpenAI API, and that this provider cannot ask for the window | ||
| 236 | + (contextWindow: 0 = unknown → compression counts messages); | ||
| 237 | + - presets.yaml: a new family `openai` (match `gpt-`, after gpt-oss): | ||
| 238 | + temperature 1.0 and max_completion_tokens instead of max_tokens (new | ||
| 239 | + field maxTokensKey), with a note — source: the OpenAI API reference, | ||
| 240 | + not measured here. | ||
| 241 | + - Tests: openai lists models with the key (and other providers do not | ||
| 242 | + send one), the openai family and provider render and load, openai is | ||
| 243 | + not in the probed list. Live: mm init --provider openai on llmman's | ||
| 244 | + OpenAI address with --check — written, loaded, the model answered. | ||
| 245 | + - Docs EN+FR: reference/cli (provider row, facts row), how-to | ||
| 246 | + create-an-agent (server list, prerequisites). | ||
| 247 | + - id: 5 | ||
| 248 | + author: | ||
| 249 | + name: k33g | ||
| 250 | + email: ph.charriere@gmail.com | ||
| 251 | + createdAt: 2026-10-21T22:00:00.000Z | ||
| 252 | + body: | | ||
| 253 | + A window "in the style of the TUI" (user's layout choice: steps + | ||
| 254 | + choices + preview): | ||
| 255 | + - internal/agentinit/flow.go: the questions as a UI-agnostic Flow | ||
| 256 | + (Steps, Set/Unset, Preview of the file with a candidate answer, | ||
| 257 | + Result); the line wizard and the window both drive it. | ||
| 258 | + - internal/tui/initwin.go (tui.RunInit): steps on the left (✓ ▸ ·, each | ||
| 259 | + answer beside it), the question with the highlighted choice's | ||
| 260 | + description, and the agent.yaml as it would be written with that | ||
| 261 | + choice, live; a confirmation screen before writing. Keys: ↑↓ Home | ||
| 262 | + End, Enter, y/n, Esc back (skips flag answers), PgUp/PgDn preview, | ||
| 263 | + Tab = preview in place of the question below 100 columns, Ctrl-U, | ||
| 264 | + Ctrl-C = nothing written. | ||
| 265 | + - The window opens when stdin and stdout are terminals; `--line` (new) | ||
| 266 | + or a pipe keeps the line-by-line questions; --yes asks nothing. | ||
| 267 | + The step "Yolo" is labelled "Ask first" (Yolo no read as yes). | ||
| 268 | + - Tests: flow (steps, preview candidate), window on a tcell | ||
| 269 | + SimulationScreen (defaults all the way, preview follows the | ||
| 270 | + selection, back/text/quit, narrow Tab). Live in a pty (130×34, | ||
| 271 | + pyte) against llmman: written and loaded. | ||
| 272 | + - Docs EN+FR: how-to create-an-agent (real capture, keys, line mode), | ||
| 273 | + reference/cli (Window and Line mode rows, --line), the TUI keyboard | ||
| 274 | + shortcuts guide (an mm init section), packages.drawio (tui → | ||
| 275 | + agentinit). | ||
modified
.tickets/issues/0111-using-the-settings-guide-create-a-claude-skill.yaml +12 -1 | @@ -12,4 +12,15 @@ milestone: v1.0.0 | ||
| 12 | 12 | body: | |
| 13 | 13 | the Claude skill will produce a descriptive doc about the model and a config file (`agent.yaml`) |
| 14 | 14 | tasks: [] |
| 15 | -comments: [] | |
| 15 | +comments: | |
| 16 | + - id: 1 | |
| 17 | + author: | |
| 18 | + name: k33g | |
| 19 | + email: ph.charriere@gmail.com | |
| 20 | + createdAt: 2026-10-21T18:00:00.000Z | |
| 21 | + body: | | |
| 22 | + User's decision in ticket 97: ONE shared table. It now exists: | |
| 23 | + internal/agentinit/presets.yaml (families with sourced sampling and | |
| 24 | + reasoning switches, usages, machine rows from the settings guide), | |
| 25 | + embedded by `mm init`. The skill of this ticket should read that file | |
| 26 | + rather than carry its own values. | |
| @@ -12,4 +12,15 @@ milestone: v1.0.0 | |||
| 12 | body: | | 12 | body: | |
| 13 | the Claude skill will produce a descriptive doc about the model and a config file (`agent.yaml`) | 13 | the Claude skill will produce a descriptive doc about the model and a config file (`agent.yaml`) |
| 14 | tasks: [] | 14 | tasks: [] |
| 15 | -comments: [] | 15 | +comments: |
| 16 | + - id: 1 | ||
| 17 | + author: | ||
| 18 | + name: k33g | ||
| 19 | + email: ph.charriere@gmail.com | ||
| 20 | + createdAt: 2026-10-21T18:00:00.000Z | ||
| 21 | + body: | | ||
| 22 | + User's decision in ticket 97: ONE shared table. It now exists: | ||
| 23 | + internal/agentinit/presets.yaml (families with sourced sampling and | ||
| 24 | + reasoning switches, usages, machine rows from the settings guide), | ||
| 25 | + embedded by `mm init`. The skill of this ticket should read that file | ||
| 26 | + rather than carry its own values. | ||
modified
.tickets/issues/0112-add-a-help-window-in-tui-mode-for-the-ui-shortcu.yaml +8 -3 | @@ -1,16 +1,21 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 112 |
| 3 | 3 | title: Add a help window in TUI mode for the UI shortcuts |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-21T04:43:03.511Z |
| 9 | -updatedAt: 2026-10-21T04:43:13.927Z | |
| 9 | +updatedAt: 2026-10-21T11:26:26.119Z | |
| 10 | 10 | labels: |
| 11 | 11 | - kind::feature |
| 12 | + - wontfix | |
| 12 | 13 | milestone: v0.9.0 |
| 13 | -body: "" | |
| 14 | +body: | | |
| 15 | + Already displayed in the TUI | |
| 16 | + ``` | |
| 17 | + ── Enter sends · Ctrl-J new line · / commands · @ files · $ skills · Tab scroll ─────────────────────────────── | |
| 18 | + ``` | |
| 14 | 19 | tasks: [] |
| 15 | 20 | comments: |
| 16 | 21 | - id: 1 |
| @@ -1,16 +1,21 @@ | |||
| 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: 112 | 2 | id: 112 |
| 3 | title: Add a help window in TUI mode for the UI shortcuts | 3 | title: Add a help window in TUI mode for the UI shortcuts |
| 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-10-21T04:43:03.511Z | 8 | createdAt: 2026-10-21T04:43:03.511Z |
| 9 | -updatedAt: 2026-10-21T04:43:13.927Z | 9 | +updatedAt: 2026-10-21T11:26:26.119Z |
| 10 | labels: | 10 | labels: |
| 11 | - kind::feature | 11 | - kind::feature |
| 12 | + - wontfix | ||
| 12 | milestone: v0.9.0 | 13 | milestone: v0.9.0 |
| 13 | -body: "" | 14 | +body: | |
| 15 | + Already displayed in the TUI | ||
| 16 | + ``` | ||
| 17 | + ── Enter sends · Ctrl-J new line · / commands · @ files · $ skills · Tab scroll ─────────────────────────────── | ||
| 18 | + ``` | ||
| 14 | tasks: [] | 19 | tasks: [] |
| 15 | comments: | 20 | comments: |
| 16 | - id: 1 | 21 | - id: 1 |
modified
.tickets/issues/0115-uograde-go-version.yaml +2 -2 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 115 |
| 3 | 3 | title: Uograde go version |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-10-21T11:03:46.198Z |
| 9 | -updatedAt: 2026-10-21T15:00:00.000Z | |
| 9 | +updatedAt: 2026-10-21T11:23:25.320Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | milestone: v0.9.0 |
| 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: 115 | 2 | id: 115 |
| 3 | title: Uograde go version | 3 | title: Uograde go version |
| 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-10-21T11:03:46.198Z | 8 | createdAt: 2026-10-21T11:03:46.198Z |
| 9 | -updatedAt: 2026-10-21T15:00:00.000Z | 9 | +updatedAt: 2026-10-21T11:23:25.320Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | milestone: v0.9.0 | 11 | milestone: v0.9.0 |
| 12 | body: | | 12 | body: | |
renamed
.tickets/issues/0116-how-to-use-mm-for-completion.yaml +4 -6 | similarity index 57% | ||
| rename from .tickets/issues/0097-generate-an-agent-yaml-file-with-rhe-cli.yaml | ||
| rename to .tickets/issues/0116-how-to-use-mm-for-completion.yaml | ||
| @@ -1,16 +1,14 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | -id: 97 | |
| 3 | -title: Generate an agent.yaml file with rhe CLI | |
| 2 | +id: 116 | |
| 3 | +title: How to use mm for completion? | |
| 4 | 4 | state: open |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | -createdAt: 2026-10-18T12:31:14.544Z | |
| 9 | -updatedAt: 2026-10-20T05:38:52.918Z | |
| 8 | +createdAt: 2026-10-21T11:38:42.420Z | |
| 9 | +updatedAt: 2026-10-21T11:44:57.748Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | milestone: v0.9.0 |
| 12 | -related: | |
| 13 | - - 98 | |
| 14 | 12 | body: "" |
| 15 | 13 | tasks: [] |
| 16 | 14 | comments: [] |
| similarity index 57% | |||
| rename from .tickets/issues/0097-generate-an-agent-yaml-file-with-rhe-cli.yaml | |||
| rename to .tickets/issues/0116-how-to-use-mm-for-completion.yaml | |||
| @@ -1,16 +1,14 @@ | |||
| 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: 97 | 2 | +id: 116 |
| 3 | -title: Generate an agent.yaml file with rhe CLI | 3 | +title: How to use mm for completion? |
| 4 | state: open | 4 | state: open |
| 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-10-18T12:31:14.544Z | 8 | +createdAt: 2026-10-21T11:38:42.420Z |
| 9 | -updatedAt: 2026-10-20T05:38:52.918Z | 9 | +updatedAt: 2026-10-21T11:44:57.748Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | milestone: v0.9.0 | 11 | milestone: v0.9.0 |
| 12 | -related: | ||
| 13 | - - 98 | ||
| 14 | body: "" | 12 | body: "" |
| 15 | tasks: [] | 13 | tasks: [] |
| 16 | comments: [] | 14 | comments: [] |
added
.tickets/issues/0117-make-possible-the-usage-of-mm-tui-like-mm-tui-an.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: 117 | |
| 3 | +title: make possible the usage of mm tui like mm --tui and mm acp like mm --acp | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-21T11:39:39.289Z | |
| 9 | +updatedAt: 2026-10-21T11:44:38.778Z | |
| 10 | +labels: [] | |
| 11 | +milestone: v0.9.0 | |
| 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: 117 | ||
| 3 | +title: make possible the usage of mm tui like mm --tui and mm acp like mm --acp | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-21T11:39:39.289Z | ||
| 9 | +updatedAt: 2026-10-21T11:44:38.778Z | ||
| 10 | +labels: [] | ||
| 11 | +milestone: v0.9.0 | ||
| 12 | +body: "" | ||
| 13 | +tasks: [] | ||
| 14 | +comments: [] | ||
added
.tickets/issues/0118-add-a-generic-openai-provider.yaml +53 -0 | new file mode 100644 | ||
| @@ -0,0 +1,53 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 118 | |
| 3 | +title: Add a generic OpenAI provider | |
| 4 | +state: closed | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-10-21T11:50:07.819Z | |
| 9 | +updatedAt: 2026-10-21T23:00:00.000Z | |
| 10 | +labels: [] | |
| 11 | +milestone: v0.9.0 | |
| 12 | +related: | |
| 13 | + - 97 | |
| 14 | +body: | | |
| 15 | + A generic `openai` provider: any server that speaks the OpenAI | |
| 16 | + chat-completions protocol and has no dedicated provider in mm — the OpenAI | |
| 17 | + API itself (default address), vLLM, LM Studio, OpenRouter, a gateway. | |
| 18 | +tasks: [] | |
| 19 | +comments: | |
| 20 | + - id: 1 | |
| 21 | + author: | |
| 22 | + name: k33g | |
| 23 | + email: ph.charriere@gmail.com | |
| 24 | + createdAt: 2026-10-21T20:00:00.000Z | |
| 25 | + body: | | |
| 26 | + Implemented on feature/mm-init (with ticket 97, which it is related to). | |
| 27 | + - internal/engine/openai.go: a sixth registry entry, name `openai`, | |
| 28 | + baseURL https://api.openai.com/v1, no fallback, apiKeyEnv | |
| 29 | + OPENAI_API_KEY, key NOT required (dummy key, like the local | |
| 30 | + providers: a local server checks none, a remote one answers 401). Every | |
| 31 | + server-specific field left empty: no return_progress (a llama.cpp | |
| 32 | + field a strict API may refuse), no thinkingOff for summaries, no | |
| 33 | + unload. probeOpenAI sends the key to GET /models: 401/403 → "refused | |
| 34 | + the key — export OPENAI_API_KEY" (reachable), 200 → model looked up in | |
| 35 | + the list, anything else → unreachable (the plain reachable() sends no | |
| 36 | + key and would call a remote API "down"). | |
| 37 | + - Tests (engine/openai_test.go): the entry assumes no server feature; | |
| 38 | + Resolve default address and key variable; only standard fields sent | |
| 39 | + (stream_options, never return_progress); probe with a fake server | |
| 40 | + (good key, unknown model, refused key, nothing listening). The | |
| 41 | + registry test lists openai. | |
| 42 | + - Live: provider openai pointed at llmman's OpenAI address (a real | |
| 43 | + generic server): mm -p ran a bash tool call and answered; with a wrong | |
| 44 | + baseUrl the start-up warning gives the openai hint. The OpenAI API | |
| 45 | + itself was NOT tried (no key here). | |
| 46 | + - mm --about: "…, and any other OpenAI-compatible one (provider openai)". | |
| 47 | + - Docs EN+FR: how-to run-with-an-openai-compatible-server (new), | |
| 48 | + reference/configuration (provider row, defaults table + what openai | |
| 49 | + sends and does not), explanation/providers, both indexes, README. | |
| 50 | + Known limits, documented: no prompt-reading progress, no reasoning switch | |
| 51 | + on summaries, no /unload, no window from the server (set contextWindow); | |
| 52 | + the OpenAI API's reasoning models need max_completion_tokens and the | |
| 53 | + default temperature (from the API reference, not measured). | |
| new file mode 100644 | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 118 | ||
| 3 | +title: Add a generic OpenAI provider | ||
| 4 | +state: closed | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-10-21T11:50:07.819Z | ||
| 9 | +updatedAt: 2026-10-21T23:00:00.000Z | ||
| 10 | +labels: [] | ||
| 11 | +milestone: v0.9.0 | ||
| 12 | +related: | ||
| 13 | + - 97 | ||
| 14 | +body: | | ||
| 15 | + A generic `openai` provider: any server that speaks the OpenAI | ||
| 16 | + chat-completions protocol and has no dedicated provider in mm — the OpenAI | ||
| 17 | + API itself (default address), vLLM, LM Studio, OpenRouter, a gateway. | ||
| 18 | +tasks: [] | ||
| 19 | +comments: | ||
| 20 | + - id: 1 | ||
| 21 | + author: | ||
| 22 | + name: k33g | ||
| 23 | + email: ph.charriere@gmail.com | ||
| 24 | + createdAt: 2026-10-21T20:00:00.000Z | ||
| 25 | + body: | | ||
| 26 | + Implemented on feature/mm-init (with ticket 97, which it is related to). | ||
| 27 | + - internal/engine/openai.go: a sixth registry entry, name `openai`, | ||
| 28 | + baseURL https://api.openai.com/v1, no fallback, apiKeyEnv | ||
| 29 | + OPENAI_API_KEY, key NOT required (dummy key, like the local | ||
| 30 | + providers: a local server checks none, a remote one answers 401). Every | ||
| 31 | + server-specific field left empty: no return_progress (a llama.cpp | ||
| 32 | + field a strict API may refuse), no thinkingOff for summaries, no | ||
| 33 | + unload. probeOpenAI sends the key to GET /models: 401/403 → "refused | ||
| 34 | + the key — export OPENAI_API_KEY" (reachable), 200 → model looked up in | ||
| 35 | + the list, anything else → unreachable (the plain reachable() sends no | ||
| 36 | + key and would call a remote API "down"). | ||
| 37 | + - Tests (engine/openai_test.go): the entry assumes no server feature; | ||
| 38 | + Resolve default address and key variable; only standard fields sent | ||
| 39 | + (stream_options, never return_progress); probe with a fake server | ||
| 40 | + (good key, unknown model, refused key, nothing listening). The | ||
| 41 | + registry test lists openai. | ||
| 42 | + - Live: provider openai pointed at llmman's OpenAI address (a real | ||
| 43 | + generic server): mm -p ran a bash tool call and answered; with a wrong | ||
| 44 | + baseUrl the start-up warning gives the openai hint. The OpenAI API | ||
| 45 | + itself was NOT tried (no key here). | ||
| 46 | + - mm --about: "…, and any other OpenAI-compatible one (provider openai)". | ||
| 47 | + - Docs EN+FR: how-to run-with-an-openai-compatible-server (new), | ||
| 48 | + reference/configuration (provider row, defaults table + what openai | ||
| 49 | + sends and does not), explanation/providers, both indexes, README. | ||
| 50 | + Known limits, documented: no prompt-reading progress, no reasoning switch | ||
| 51 | + on summaries, no /unload, no window from the server (set contextWindow); | ||
| 52 | + the OpenAI API's reasoning models need max_completion_tokens and the | ||
| 53 | + default temperature (from the API reference, not measured). | ||
modified
README.md +2 -1 | @@ -20,7 +20,7 @@ What makes Mini Me a bit special is that it was designed from the start to be us | ||
| 20 | 20 | |
| 21 | 21 | ## Install |
| 22 | 22 | |
| 23 | -You need Go 1.27+ and a model server that can emit tool calls, through its OpenAI-compatible API: Docker Model Runner (`provider: dmr`, the default), llama.cpp's `llama-server` (`llamacpp`), [llmman](https://github.com/llmmanorg/llmman) (`llmman`) or Ollama (`ollama`). | |
| 23 | +You need Go 1.27+ and a model server that can emit tool calls, through its OpenAI-compatible API: Docker Model Runner (`provider: dmr`, the default), llama.cpp's `llama-server` (`llamacpp`), [llmman](https://github.com/llmmanorg/llmman) (`llmman`) or Ollama (`ollama`) — or any other OpenAI-compatible server with `provider: openai` (the OpenAI API by default, vLLM, LM Studio…). | |
| 24 | 24 | |
| 25 | 25 | ```bash |
| 26 | 26 | git clone https://git.rickub.com/bots-garden/mini-me.git |
| @@ -107,6 +107,7 @@ Anything that speaks ACP can host `mm -acp` the same way: **JetBrains IDEs** (In | ||
| 107 | 107 | |
| 108 | 108 | ## More features |
| 109 | 109 | |
| 110 | +- **Create an agent**: `mm init` (or `mm --init`) asks which server, which model (from the server's list), what the agent is for and which machine runs it, then writes a commented agent.yaml — the model's facts read from the server (window, the GGUF's sampling, the reasoning switch), a family table sourced from model cards and the measured demos, every value with its reason; `--check` proves the model answers, flags make it scriptable. See [Create an agent with `mm init`](docs/en/how-to/create-an-agent.md). | |
| 110 | 111 | - **One prompt and exit**: `mm -p "…"` — for scripts. See [Run a single prompt](docs/en/how-to/run-a-single-prompt.md). |
| 111 | 112 | - **Other agents**: list other mm agents under `mmConfigs`; you ask them with `/ask-<name>`, your agent calls them itself with its `ask_agent` tool, a script with `mm --ask <name>`. See [Let your agent call other agents](docs/en/how-to/let-the-agent-call-other-agents.md). |
| 112 | 113 | - **Questions to you**: the agent asks with its `ask_user` tool — pick one, pick several, type a text, yes or no — as numbered choices in the terminal, an arrow-key box in the window, a form or a dialog in an editor; a called agent's questions come up to you too. `askUserTool: false` turns it off. See [Let the agent ask you questions](docs/en/how-to/let-the-agent-ask-you.md). |
| @@ -20,7 +20,7 @@ What makes Mini Me a bit special is that it was designed from the start to be us | |||
| 20 | 20 | ||
| 21 | ## Install | 21 | ## Install |
| 22 | 22 | ||
| 23 | -You need Go 1.27+ and a model server that can emit tool calls, through its OpenAI-compatible API: Docker Model Runner (`provider: dmr`, the default), llama.cpp's `llama-server` (`llamacpp`), [llmman](https://github.com/llmmanorg/llmman) (`llmman`) or Ollama (`ollama`). | 23 | +You need Go 1.27+ and a model server that can emit tool calls, through its OpenAI-compatible API: Docker Model Runner (`provider: dmr`, the default), llama.cpp's `llama-server` (`llamacpp`), [llmman](https://github.com/llmmanorg/llmman) (`llmman`) or Ollama (`ollama`) — or any other OpenAI-compatible server with `provider: openai` (the OpenAI API by default, vLLM, LM Studio…). |
| 24 | 24 | ||
| 25 | ```bash | 25 | ```bash |
| 26 | git clone https://git.rickub.com/bots-garden/mini-me.git | 26 | git clone https://git.rickub.com/bots-garden/mini-me.git |
| @@ -107,6 +107,7 @@ Anything that speaks ACP can host `mm -acp` the same way: **JetBrains IDEs** (In | |||
| 107 | 107 | ||
| 108 | ## More features | 108 | ## More features |
| 109 | 109 | ||
| 110 | +- **Create an agent**: `mm init` (or `mm --init`) asks which server, which model (from the server's list), what the agent is for and which machine runs it, then writes a commented agent.yaml — the model's facts read from the server (window, the GGUF's sampling, the reasoning switch), a family table sourced from model cards and the measured demos, every value with its reason; `--check` proves the model answers, flags make it scriptable. See [Create an agent with `mm init`](docs/en/how-to/create-an-agent.md). | ||
| 110 | - **One prompt and exit**: `mm -p "…"` — for scripts. See [Run a single prompt](docs/en/how-to/run-a-single-prompt.md). | 111 | - **One prompt and exit**: `mm -p "…"` — for scripts. See [Run a single prompt](docs/en/how-to/run-a-single-prompt.md). |
| 111 | - **Other agents**: list other mm agents under `mmConfigs`; you ask them with `/ask-<name>`, your agent calls them itself with its `ask_agent` tool, a script with `mm --ask <name>`. See [Let your agent call other agents](docs/en/how-to/let-the-agent-call-other-agents.md). | 112 | - **Other agents**: list other mm agents under `mmConfigs`; you ask them with `/ask-<name>`, your agent calls them itself with its `ask_agent` tool, a script with `mm --ask <name>`. See [Let your agent call other agents](docs/en/how-to/let-the-agent-call-other-agents.md). |
| 112 | - **Questions to you**: the agent asks with its `ask_user` tool — pick one, pick several, type a text, yes or no — as numbered choices in the terminal, an arrow-key box in the window, a form or a dialog in an editor; a called agent's questions come up to you too. `askUserTool: false` turns it off. See [Let the agent ask you questions](docs/en/how-to/let-the-agent-ask-you.md). | 113 | - **Questions to you**: the agent asks with its `ask_user` tool — pick one, pick several, type a text, yes or no — as numbered choices in the terminal, an arrow-key box in the window, a form or a dialog in an editor; a called agent's questions come up to you too. `askUserTool: false` turns it off. See [Let the agent ask you questions](docs/en/how-to/let-the-agent-ask-you.md). |
modified
docs/diagrams/packages.drawio +1 -1 | @@ -1,3 +1,3 @@ | ||
| 1 | 1 | <mxfile host="app.diagrams.net" modified="2026-10-06T00:00:00.000Z" agent="mm docs" version="24.0.0" type="device"><diagram id="packages" name="packages"><mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1400" pageHeight="1060"><root><mxCell id="0" /><mxCell id="1" parent="0" /><mxCell id="main" value="<b>main (mm)</b><br/><font style="font-size:10px">wiring: config, engine, tools, then one front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1"><mxGeometry x="420" y="40" width="200" height="60" as="geometry" /></mxCell><mxCell id="agent" value="<b>internal/agent</b><br/><font style="font-size:10px">terminal REPL: /quit /abort /compact /new</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="160" y="180" width="200" height="60" as="geometry" /></mxCell><mxCell id="acp" value="<b>internal/acp</b><br/><font style="font-size:10px">editor front end: Agent Client Protocol on stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="700" y="180" width="200" height="60" as="geometry" /></mxCell><mxCell id="session" value="<b>internal/session</b><br/><font style="font-size:10px">what a conversation starts from; the /new reset</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="compact" value="<b>internal/compact</b><br/><font style="font-size:10px">history compression into a model-written summary</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="40" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="engine" value="<b>internal/engine</b><br/><font style="font-size:10px">LLM connection + generation, one Provider per server</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="700" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="tools" value="<b>internal/tools</b><br/><font style="font-size:10px">built-in tools: bash, read_skill, file tools, lsp, fetch_content; declared toolsbuilt-in tools: bash, read_skill, file tools, lsp, fetch_content</font>lt;/fontbuilt-in tools: bash, read_skill, file tools, lsp, fetch_content</font>gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="detector" value="<b>internal/detector</b><br/><font style="font-size:10px">repeated-action (loop) detection</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="40" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="config" value="<b>internal/config</b><br/><font style="font-size:10px">settings with YAML overrides (agent.yaml)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="spinner" value="<b>internal/spinner</b><br/><font style="font-size:10px">terminal spinner and styling</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="480" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="ui" value="<b>internal/ui</b><br/><font style="font-size:10px">human output destination + shared event sink</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="fileedit" value="<b>internal/fileedit</b><br/><font style="font-size:10px">exact-replacement file editing</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="skills" value="<b>internal/skills</b><br/><font style="font-size:10px">markdown skills catalogue (./skills)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="genkit" value="<b>github.com/firebase/genkit</b><br/><font style="font-size:10px">ai.Message, tools, model calls</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="160" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="acpsdk" value="<b>github.com/coder/acp-go-sdk</b><br/><font style="font-size:10px">JSON-RPC transport for ACP</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="700" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="openai" value="<b>github.com/openai/openai-go</b><br/><font style="font-size:10px">OpenAI-compatible HTTP client</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="yaml" value="<b>gopkg.in/yaml.v3</b><br/><font style="font-size:10px">YAML parsing</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="400" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="e0" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="version" value="<b>internal/version</b><br/><font style="font-size:10px">which mm this is: build stamp, else the commit</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1380" y="600" width="200" height="60" as="geometry" /></mxCell> |
| 2 | 2 | <mxCell id="e61" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="version"><mxGeometry relative="1" as="geometry" /></mxCell> |
| 3 | - <mxCell id="e1" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="acp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e2" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e3" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e4" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e5" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e6" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e7" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e8" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e9" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e10" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e11" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e12" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e13" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e14" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e15" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e16" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e17" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e18" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e19" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e20" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="agent" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e21" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="compact" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e22" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="compact" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e23" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="config" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e24" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e25" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e26" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e27" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e28" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="openai"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e29" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e30" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e31" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="fileedit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e32" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e33" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e34" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e35" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="tools" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e36" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="session" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="mention" value="<b>internal/mention</b><br/><font style="font-size:10px">the @path notation of a question</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e37" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e38" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="store" value="<b>internal/store</b><br/><font style="font-size:10px">per-project session files (.mm/sessions/<id>.json), the questions ↑ recalls, /memory and search_memory</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="480" width="200" height="60" as="geometry" /></mxCell><mxCell id="e39" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e40" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="tui" value="<b>internal/tui</b><br/><font style="font-size:10px">window front end: one screen on tcell (mm -tui)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="430" y="160" width="200" height="60" as="geometry" /></mxCell><mxCell id="command" value="<b>internal/command</b><br/><font style="font-size:10px">the one slash-command table, per front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="tcell" value="<b>github.com/gdamore/tcell/v2</b><br/><font style="font-size:10px">terminal screen, keys, mouse</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="840" width="200" height="60" as="geometry" /></mxCell><mxCell id="e41" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e42" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e43" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e44" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e45" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e46" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e47" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e48" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e49" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e50" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e51" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tcell"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e52" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e53" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e54" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="command" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="saved" value="<b>internal/saved</b><br/><font style="font-size:10px">an answer to a new file: /save, save_answer</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e87" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e88" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e89" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="clipboard" value="<b>internal/clipboard</b><br/><font style="font-size:10px">system clipboard: native tool, then OSC 52</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e55" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e56" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="lsp" value="<b>internal/lsp</b><br/><font style="font-size:10px">language-server client: definition, references, hover, symbols, diagnostics, rename</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1160" y="600" width="220" height="60" as="geometry" /></mxCell><mxCell id="lspdev" value="<b>go.lsp.dev/protocol + jsonrpc2</b><br/><font style="font-size:10px">LSP types and JSON-RPC 2.0 over stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="1160" y="700" width="220" height="60" as="geometry" /></mxCell><mxCell id="e57" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e58" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e59" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="lsp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e60" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="lsp" target="lspdev"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="legend" value="<b>mm — package dependencies</b><br/>Arrow: "imports". Yellow: entry point. Blue: front ends. Green: shared logic. Grey: leaf packages. Dashed purple: third-party modules.<br/>Regenerate the edge list from: go list -f '{{.ImportPath}}: {{join .Imports " "}}' ./..." style="text;html=1;whiteSpace=wrap;align=left;verticalAlign=top;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="900" y="40" width="440" height="90" as="geometry" /></mxCell><mxCell id="webmd" value="<b>internal/webmd</b><br/><font style="font-size:10px">web page → Markdown: fetch (robots.txt, charset → UTF-8), clean, convert</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="460" width="220" height="60" as="geometry" /></mxCell><mxCell id="xnet" value="<b>golang.org/x/net/html (+ x/text)</b><br/><font style="font-size:10px">HTML5 parser, charset lookup</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="1400" y="760" width="220" height="60" as="geometry" /></mxCell><mxCell id="e_main_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_webmd_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="webmd" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="ask" value="<b>internal/ask</b><br/><font style="font-size:10px">/ask another mm agent: child mm -acp, ACP client side</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="640" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_main_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_command" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_ui" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_acpsdk" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_genkit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_yaml" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="consent" value="<b>internal/consent</b><br/><font style="font-size:10px">yolo switch, the four answers, per-session memory, the line mode prompt hook</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="500" width="200" height="60" as="geometry" /></mxCell><mxCell id="mcp" value="<b>internal/mcp</b><br/><font style="font-size:10px">MCP clients (stdio, HTTP), their tools wrapped as mm tools</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e62" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e63" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e64" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e65" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e66" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e67" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e68" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e69" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e70" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e71" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e72" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e73" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e74" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="structured" value="<b>internal/structured</b><br/><font style="font-size:10px">structuredOutput: Go declarations → JSON Schema (go/parser)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e75" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="config" target="structured"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="agentsmd" value="<b>internal/agentsmd</b><br/><font style="font-size:10px">the project's AGENTS.md, appended to the system prompt per conversation</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="520.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e76" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e77" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e78" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e79" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e80" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentsmd" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="elicit" value="<b>internal/elicit</b><br/><font style="font-size:10px">ask_user's questions and answers: normalize, line answers, elicitation form schema</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="780.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e81" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e82" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e83" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e84" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e85" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e86" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="hooks" value="<b>internal/hooks</b><br/><font style="font-size:10px">the hooks: block — runs each hook (sh -c, JSON on stdin/stdout), chain, onError</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="940" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_engine_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_main_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_hooks_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="hooks" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_session" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_engine" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_store" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="docsearch" value="<b>internal/docsearch</b><br/><font style="font-size:10px">BM25 over the text files of folders: /docs, search_docs</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="1640" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="textfold" value="<b>internal/textfold</b><br/><font style="font-size:10px">case and accents folded, rune for rune</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1640" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_docsearch_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_docsearch_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_textfold_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="textfold" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell></root></mxGraphModel></diagram></mxfile> | |
| \ No newline at end of file | ||
| 3 | + <mxCell id="e1" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="acp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e2" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e3" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e4" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e5" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e6" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e7" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e8" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e9" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e10" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e11" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e12" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e13" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e14" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e15" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e16" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e17" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e18" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e19" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e20" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="agent" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e21" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="compact" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e22" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="compact" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e23" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="config" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e24" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e25" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e26" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e27" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e28" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="openai"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e29" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e30" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e31" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="fileedit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e32" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e33" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e34" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e35" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="tools" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e36" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="session" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="mention" value="<b>internal/mention</b><br/><font style="font-size:10px">the @path notation of a question</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e37" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e38" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="store" value="<b>internal/store</b><br/><font style="font-size:10px">per-project session files (.mm/sessions/<id>.json), the questions ↑ recalls, /memory and search_memory</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="480" width="200" height="60" as="geometry" /></mxCell><mxCell id="e39" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e40" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="tui" value="<b>internal/tui</b><br/><font style="font-size:10px">window front end: one screen on tcell (mm -tui)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="430" y="160" width="200" height="60" as="geometry" /></mxCell><mxCell id="command" value="<b>internal/command</b><br/><font style="font-size:10px">the one slash-command table, per front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="tcell" value="<b>github.com/gdamore/tcell/v2</b><br/><font style="font-size:10px">terminal screen, keys, mouse</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="840" width="200" height="60" as="geometry" /></mxCell><mxCell id="e41" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e42" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e43" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e44" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e45" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e46" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e47" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e48" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e49" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e50" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e51" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tcell"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e52" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e53" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e54" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="command" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="saved" value="<b>internal/saved</b><br/><font style="font-size:10px">an answer to a new file: /save, save_answer</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e87" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e88" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e89" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="clipboard" value="<b>internal/clipboard</b><br/><font style="font-size:10px">system clipboard: native tool, then OSC 52</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e55" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e56" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="lsp" value="<b>internal/lsp</b><br/><font style="font-size:10px">language-server client: definition, references, hover, symbols, diagnostics, rename</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1160" y="600" width="220" height="60" as="geometry" /></mxCell><mxCell id="lspdev" value="<b>go.lsp.dev/protocol + jsonrpc2</b><br/><font style="font-size:10px">LSP types and JSON-RPC 2.0 over stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="1160" y="700" width="220" height="60" as="geometry" /></mxCell><mxCell id="e57" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e58" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e59" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="lsp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e60" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="lsp" target="lspdev"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="legend" value="<b>mm — package dependencies</b><br/>Arrow: "imports". Yellow: entry point. Blue: front ends. Green: shared logic. Grey: leaf packages. Dashed purple: third-party modules.<br/>Regenerate the edge list from: go list -f '{{.ImportPath}}: {{join .Imports " "}}' ./..." style="text;html=1;whiteSpace=wrap;align=left;verticalAlign=top;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="900" y="40" width="440" height="90" as="geometry" /></mxCell><mxCell id="webmd" value="<b>internal/webmd</b><br/><font style="font-size:10px">web page → Markdown: fetch (robots.txt, charset → UTF-8), clean, convert</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="460" width="220" height="60" as="geometry" /></mxCell><mxCell id="xnet" value="<b>golang.org/x/net/html (+ x/text)</b><br/><font style="font-size:10px">HTML5 parser, charset lookup</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="1400" y="760" width="220" height="60" as="geometry" /></mxCell><mxCell id="e_main_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_webmd_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="webmd" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="ask" value="<b>internal/ask</b><br/><font style="font-size:10px">/ask another mm agent: child mm -acp, ACP client side</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="640" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_main_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_command" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_ui" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_acpsdk" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_genkit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_yaml" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="consent" value="<b>internal/consent</b><br/><font style="font-size:10px">yolo switch, the four answers, per-session memory, the line mode prompt hook</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="500" width="200" height="60" as="geometry" /></mxCell><mxCell id="mcp" value="<b>internal/mcp</b><br/><font style="font-size:10px">MCP clients (stdio, HTTP), their tools wrapped as mm tools</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e62" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e63" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e64" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e65" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e66" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e67" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e68" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e69" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e70" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e71" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e72" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e73" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e74" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="structured" value="<b>internal/structured</b><br/><font style="font-size:10px">structuredOutput: Go declarations → JSON Schema (go/parser)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e75" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="config" target="structured"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="agentsmd" value="<b>internal/agentsmd</b><br/><font style="font-size:10px">the project's AGENTS.md, appended to the system prompt per conversation</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="520.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e76" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e77" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e78" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e79" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e80" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentsmd" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="elicit" value="<b>internal/elicit</b><br/><font style="font-size:10px">ask_user's questions and answers: normalize, line answers, elicitation form schema</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="780.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e81" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e82" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e83" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e84" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e85" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e86" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="hooks" value="<b>internal/hooks</b><br/><font style="font-size:10px">the hooks: block — runs each hook (sh -c, JSON on stdin/stdout), chain, onError</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="940" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_engine_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_main_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_hooks_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="hooks" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_session" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_engine" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_store" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="docsearch" value="<b>internal/docsearch</b><br/><font style="font-size:10px">BM25 over the text files of folders: /docs, search_docs</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="1640" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="textfold" value="<b>internal/textfold</b><br/><font style="font-size:10px">case and accents folded, rune for rune</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1640" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_docsearch_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_docsearch_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_textfold_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="textfold" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="agentinit" value="<b>internal/agentinit</b><br/><font style="font-size:10px">mm init: the agent.yaml wizard, presets.yaml, the server's model facts</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="1640" y="660" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_main_agentinit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agentinit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agentinit_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentinit" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agentinit_elicit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentinit" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agentinit_engine" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentinit" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_agentinit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="agentinit"><mxGeometry relative="1" as="geometry" /></mxCell></root></mxGraphModel></diagram></mxfile> | |
| \ No newline at end of file | ||
| @@ -1,3 +1,3 @@ | |||
| 1 | <mxfile host="app.diagrams.net" modified="2026-10-06T00:00:00.000Z" agent="mm docs" version="24.0.0" type="device"><diagram id="packages" name="packages"><mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1400" pageHeight="1060"><root><mxCell id="0" /><mxCell id="1" parent="0" /><mxCell id="main" value="<b>main (mm)</b><br/><font style="font-size:10px">wiring: config, engine, tools, then one front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1"><mxGeometry x="420" y="40" width="200" height="60" as="geometry" /></mxCell><mxCell id="agent" value="<b>internal/agent</b><br/><font style="font-size:10px">terminal REPL: /quit /abort /compact /new</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="160" y="180" width="200" height="60" as="geometry" /></mxCell><mxCell id="acp" value="<b>internal/acp</b><br/><font style="font-size:10px">editor front end: Agent Client Protocol on stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="700" y="180" width="200" height="60" as="geometry" /></mxCell><mxCell id="session" value="<b>internal/session</b><br/><font style="font-size:10px">what a conversation starts from; the /new reset</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="compact" value="<b>internal/compact</b><br/><font style="font-size:10px">history compression into a model-written summary</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="40" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="engine" value="<b>internal/engine</b><br/><font style="font-size:10px">LLM connection + generation, one Provider per server</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="700" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="tools" value="<b>internal/tools</b><br/><font style="font-size:10px">built-in tools: bash, read_skill, file tools, lsp, fetch_content; declared toolsbuilt-in tools: bash, read_skill, file tools, lsp, fetch_content</font>lt;/fontbuilt-in tools: bash, read_skill, file tools, lsp, fetch_content</font>gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="detector" value="<b>internal/detector</b><br/><font style="font-size:10px">repeated-action (loop) detection</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="40" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="config" value="<b>internal/config</b><br/><font style="font-size:10px">settings with YAML overrides (agent.yaml)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="spinner" value="<b>internal/spinner</b><br/><font style="font-size:10px">terminal spinner and styling</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="480" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="ui" value="<b>internal/ui</b><br/><font style="font-size:10px">human output destination + shared event sink</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="fileedit" value="<b>internal/fileedit</b><br/><font style="font-size:10px">exact-replacement file editing</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="skills" value="<b>internal/skills</b><br/><font style="font-size:10px">markdown skills catalogue (./skills)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="genkit" value="<b>github.com/firebase/genkit</b><br/><font style="font-size:10px">ai.Message, tools, model calls</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="160" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="acpsdk" value="<b>github.com/coder/acp-go-sdk</b><br/><font style="font-size:10px">JSON-RPC transport for ACP</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="700" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="openai" value="<b>github.com/openai/openai-go</b><br/><font style="font-size:10px">OpenAI-compatible HTTP client</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="yaml" value="<b>gopkg.in/yaml.v3</b><br/><font style="font-size:10px">YAML parsing</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="400" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="e0" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="version" value="<b>internal/version</b><br/><font style="font-size:10px">which mm this is: build stamp, else the commit</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1380" y="600" width="200" height="60" as="geometry" /></mxCell> | 1 | <mxfile host="app.diagrams.net" modified="2026-10-06T00:00:00.000Z" agent="mm docs" version="24.0.0" type="device"><diagram id="packages" name="packages"><mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1400" pageHeight="1060"><root><mxCell id="0" /><mxCell id="1" parent="0" /><mxCell id="main" value="<b>main (mm)</b><br/><font style="font-size:10px">wiring: config, engine, tools, then one front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1"><mxGeometry x="420" y="40" width="200" height="60" as="geometry" /></mxCell><mxCell id="agent" value="<b>internal/agent</b><br/><font style="font-size:10px">terminal REPL: /quit /abort /compact /new</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="160" y="180" width="200" height="60" as="geometry" /></mxCell><mxCell id="acp" value="<b>internal/acp</b><br/><font style="font-size:10px">editor front end: Agent Client Protocol on stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="700" y="180" width="200" height="60" as="geometry" /></mxCell><mxCell id="session" value="<b>internal/session</b><br/><font style="font-size:10px">what a conversation starts from; the /new reset</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="compact" value="<b>internal/compact</b><br/><font style="font-size:10px">history compression into a model-written summary</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="40" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="engine" value="<b>internal/engine</b><br/><font style="font-size:10px">LLM connection + generation, one Provider per server</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="700" y="320" width="200" height="60" as="geometry" /></mxCell><mxCell id="tools" value="<b>internal/tools</b><br/><font style="font-size:10px">built-in tools: bash, read_skill, file tools, lsp, fetch_content; declared toolsbuilt-in tools: bash, read_skill, file tools, lsp, fetch_content</font>lt;/fontbuilt-in tools: bash, read_skill, file tools, lsp, fetch_content</font>gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="detector" value="<b>internal/detector</b><br/><font style="font-size:10px">repeated-action (loop) detection</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="40" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="config" value="<b>internal/config</b><br/><font style="font-size:10px">settings with YAML overrides (agent.yaml)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="spinner" value="<b>internal/spinner</b><br/><font style="font-size:10px">terminal spinner and styling</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="480" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="ui" value="<b>internal/ui</b><br/><font style="font-size:10px">human output destination + shared event sink</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="fileedit" value="<b>internal/fileedit</b><br/><font style="font-size:10px">exact-replacement file editing</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="skills" value="<b>internal/skills</b><br/><font style="font-size:10px">markdown skills catalogue (./skills)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="600" width="200" height="60" as="geometry" /></mxCell><mxCell id="genkit" value="<b>github.com/firebase/genkit</b><br/><font style="font-size:10px">ai.Message, tools, model calls</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="160" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="acpsdk" value="<b>github.com/coder/acp-go-sdk</b><br/><font style="font-size:10px">JSON-RPC transport for ACP</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="700" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="openai" value="<b>github.com/openai/openai-go</b><br/><font style="font-size:10px">OpenAI-compatible HTTP client</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="yaml" value="<b>gopkg.in/yaml.v3</b><br/><font style="font-size:10px">YAML parsing</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="400" y="760" width="200" height="60" as="geometry" /></mxCell><mxCell id="e0" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="version" value="<b>internal/version</b><br/><font style="font-size:10px">which mm this is: build stamp, else the commit</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1380" y="600" width="200" height="60" as="geometry" /></mxCell> |
| 2 | <mxCell id="e61" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="version"><mxGeometry relative="1" as="geometry" /></mxCell> | 2 | <mxCell id="e61" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="version"><mxGeometry relative="1" as="geometry" /></mxCell> |
| 3 | - <mxCell id="e1" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="acp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e2" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e3" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e4" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e5" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e6" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e7" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e8" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e9" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e10" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e11" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e12" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e13" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e14" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e15" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e16" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e17" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e18" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e19" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e20" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="agent" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e21" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="compact" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e22" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="compact" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e23" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="config" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e24" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e25" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e26" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e27" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e28" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="openai"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e29" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e30" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e31" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="fileedit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e32" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e33" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e34" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e35" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="tools" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e36" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="session" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="mention" value="<b>internal/mention</b><br/><font style="font-size:10px">the @path notation of a question</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e37" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e38" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="store" value="<b>internal/store</b><br/><font style="font-size:10px">per-project session files (.mm/sessions/<id>.json), the questions ↑ recalls, /memory and search_memory</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="480" width="200" height="60" as="geometry" /></mxCell><mxCell id="e39" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e40" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="tui" value="<b>internal/tui</b><br/><font style="font-size:10px">window front end: one screen on tcell (mm -tui)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="430" y="160" width="200" height="60" as="geometry" /></mxCell><mxCell id="command" value="<b>internal/command</b><br/><font style="font-size:10px">the one slash-command table, per front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="tcell" value="<b>github.com/gdamore/tcell/v2</b><br/><font style="font-size:10px">terminal screen, keys, mouse</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="840" width="200" height="60" as="geometry" /></mxCell><mxCell id="e41" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e42" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e43" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e44" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e45" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e46" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e47" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e48" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e49" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e50" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e51" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tcell"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e52" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e53" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e54" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="command" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="saved" value="<b>internal/saved</b><br/><font style="font-size:10px">an answer to a new file: /save, save_answer</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e87" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e88" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e89" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="clipboard" value="<b>internal/clipboard</b><br/><font style="font-size:10px">system clipboard: native tool, then OSC 52</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e55" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e56" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="lsp" value="<b>internal/lsp</b><br/><font style="font-size:10px">language-server client: definition, references, hover, symbols, diagnostics, rename</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1160" y="600" width="220" height="60" as="geometry" /></mxCell><mxCell id="lspdev" value="<b>go.lsp.dev/protocol + jsonrpc2</b><br/><font style="font-size:10px">LSP types and JSON-RPC 2.0 over stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="1160" y="700" width="220" height="60" as="geometry" /></mxCell><mxCell id="e57" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e58" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e59" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="lsp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e60" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="lsp" target="lspdev"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="legend" value="<b>mm — package dependencies</b><br/>Arrow: "imports". Yellow: entry point. Blue: front ends. Green: shared logic. Grey: leaf packages. Dashed purple: third-party modules.<br/>Regenerate the edge list from: go list -f '{{.ImportPath}}: {{join .Imports " "}}' ./..." style="text;html=1;whiteSpace=wrap;align=left;verticalAlign=top;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="900" y="40" width="440" height="90" as="geometry" /></mxCell><mxCell id="webmd" value="<b>internal/webmd</b><br/><font style="font-size:10px">web page → Markdown: fetch (robots.txt, charset → UTF-8), clean, convert</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="460" width="220" height="60" as="geometry" /></mxCell><mxCell id="xnet" value="<b>golang.org/x/net/html (+ x/text)</b><br/><font style="font-size:10px">HTML5 parser, charset lookup</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="1400" y="760" width="220" height="60" as="geometry" /></mxCell><mxCell id="e_main_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_webmd_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="webmd" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="ask" value="<b>internal/ask</b><br/><font style="font-size:10px">/ask another mm agent: child mm -acp, ACP client side</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="640" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_main_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_command" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_ui" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_acpsdk" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_genkit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_yaml" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="consent" value="<b>internal/consent</b><br/><font style="font-size:10px">yolo switch, the four answers, per-session memory, the line mode prompt hook</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="500" width="200" height="60" as="geometry" /></mxCell><mxCell id="mcp" value="<b>internal/mcp</b><br/><font style="font-size:10px">MCP clients (stdio, HTTP), their tools wrapped as mm tools</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e62" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e63" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e64" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e65" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e66" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e67" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e68" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e69" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e70" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e71" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e72" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e73" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e74" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="structured" value="<b>internal/structured</b><br/><font style="font-size:10px">structuredOutput: Go declarations → JSON Schema (go/parser)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e75" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="config" target="structured"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="agentsmd" value="<b>internal/agentsmd</b><br/><font style="font-size:10px">the project's AGENTS.md, appended to the system prompt per conversation</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="520.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e76" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e77" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e78" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e79" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e80" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentsmd" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="elicit" value="<b>internal/elicit</b><br/><font style="font-size:10px">ask_user's questions and answers: normalize, line answers, elicitation form schema</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="780.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e81" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e82" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e83" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e84" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e85" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e86" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="hooks" value="<b>internal/hooks</b><br/><font style="font-size:10px">the hooks: block — runs each hook (sh -c, JSON on stdin/stdout), chain, onError</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="940" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_engine_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_main_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_hooks_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="hooks" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_session" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_engine" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_store" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="docsearch" value="<b>internal/docsearch</b><br/><font style="font-size:10px">BM25 over the text files of folders: /docs, search_docs</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="1640" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="textfold" value="<b>internal/textfold</b><br/><font style="font-size:10px">case and accents folded, rune for rune</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1640" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_docsearch_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_docsearch_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_textfold_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="textfold" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell></root></mxGraphModel></diagram></mxfile> | ||
| \ No newline at end of file | \ No newline at end of file | ||
| 3 | + <mxCell id="e1" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="acp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e2" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e3" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e4" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e5" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e6" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e7" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e8" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e9" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e10" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e11" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e12" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e13" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="acp" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e14" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e15" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e16" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e17" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e18" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e19" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e20" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="agent" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e21" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="compact" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e22" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="compact" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e23" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="config" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e24" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e25" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e26" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e27" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e28" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="engine" target="openai"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e29" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e30" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e31" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="fileedit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e32" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="skills"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e33" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="spinner"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e34" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e35" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="tools" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e36" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="session" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="mention" value="<b>internal/mention</b><br/><font style="font-size:10px">the @path notation of a question</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e37" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e38" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="store" value="<b>internal/store</b><br/><font style="font-size:10px">per-project session files (.mm/sessions/<id>.json), the questions ↑ recalls, /memory and search_memory</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="480" width="200" height="60" as="geometry" /></mxCell><mxCell id="e39" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e40" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="tui" value="<b>internal/tui</b><br/><font style="font-size:10px">window front end: one screen on tcell (mm -tui)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1"><mxGeometry x="430" y="160" width="200" height="60" as="geometry" /></mxCell><mxCell id="command" value="<b>internal/command</b><br/><font style="font-size:10px">the one slash-command table, per front end</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="tcell" value="<b>github.com/gdamore/tcell/v2</b><br/><font style="font-size:10px">terminal screen, keys, mouse</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="920" y="840" width="200" height="60" as="geometry" /></mxCell><mxCell id="e41" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="tui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e42" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e43" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e44" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e45" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e46" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="mention"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e47" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e48" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e49" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e50" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e51" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tcell"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e52" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e53" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e54" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="command" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="saved" value="<b>internal/saved</b><br/><font style="font-size:10px">an answer to a new file: /save, save_answer</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="920" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e87" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e88" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e89" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="saved"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="clipboard" value="<b>internal/clipboard</b><br/><font style="font-size:10px">system clipboard: native tool, then OSC 52</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1140" y="680" width="200" height="60" as="geometry" /></mxCell><mxCell id="e55" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e56" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="clipboard"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="lsp" value="<b>internal/lsp</b><br/><font style="font-size:10px">language-server client: definition, references, hover, symbols, diagnostics, rename</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1160" y="600" width="220" height="60" as="geometry" /></mxCell><mxCell id="lspdev" value="<b>go.lsp.dev/protocol + jsonrpc2</b><br/><font style="font-size:10px">LSP types and JSON-RPC 2.0 over stdio</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="1160" y="700" width="220" height="60" as="geometry" /></mxCell><mxCell id="e57" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e58" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="lsp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e59" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="lsp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e60" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="lsp" target="lspdev"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="legend" value="<b>mm — package dependencies</b><br/>Arrow: "imports". Yellow: entry point. Blue: front ends. Green: shared logic. Grey: leaf packages. Dashed purple: third-party modules.<br/>Regenerate the edge list from: go list -f '{{.ImportPath}}: {{join .Imports " "}}' ./..." style="text;html=1;whiteSpace=wrap;align=left;verticalAlign=top;fillColor=#ffffff;strokeColor=#999999;" vertex="1" parent="1"><mxGeometry x="900" y="40" width="440" height="90" as="geometry" /></mxCell><mxCell id="webmd" value="<b>internal/webmd</b><br/><font style="font-size:10px">web page → Markdown: fetch (robots.txt, charset → UTF-8), clean, convert</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="460" width="220" height="60" as="geometry" /></mxCell><mxCell id="xnet" value="<b>golang.org/x/net/html (+ x/text)</b><br/><font style="font-size:10px">HTML5 parser, charset lookup</font>" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1"><mxGeometry x="1400" y="760" width="220" height="60" as="geometry" /></mxCell><mxCell id="e_main_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_webmd" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="webmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_webmd_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="webmd" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="ask" value="<b>internal/ask</b><br/><font style="font-size:10px">/ask another mm agent: child mm -acp, ACP client side</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="430" y="640" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_main_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_ask" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="ask"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_command" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="command"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_ui" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_acpsdk" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="acpsdk"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_genkit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="genkit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_yaml" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="ask" target="yaml"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="consent" value="<b>internal/consent</b><br/><font style="font-size:10px">yolo switch, the four answers, per-session memory, the line mode prompt hook</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="700" y="500" width="200" height="60" as="geometry" /></mxCell><mxCell id="mcp" value="<b>internal/mcp</b><br/><font style="font-size:10px">MCP clients (stdio, HTTP), their tools wrapped as mm tools</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1400" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e62" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e63" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="consent" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e64" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e65" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e66" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e67" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e68" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e69" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="consent"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e70" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e71" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="ui"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e72" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="mcp" target="detector"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e73" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e74" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="mcp"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="structured" value="<b>internal/structured</b><br/><font style="font-size:10px">structuredOutput: Go declarations → JSON Schema (go/parser)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="260" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e75" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="config" target="structured"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="agentsmd" value="<b>internal/agentsmd</b><br/><font style="font-size:10px">the project's AGENTS.md, appended to the system prompt per conversation</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="520.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e76" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e77" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e78" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e79" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agentsmd"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e80" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentsmd" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="elicit" value="<b>internal/elicit</b><br/><font style="font-size:10px">ask_user's questions and answers: normalize, line answers, elicitation form schema</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="780.0" y="940.0" width="200" height="60" as="geometry" /></mxCell><mxCell id="e81" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e82" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e83" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e84" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e85" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e86" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="hooks" value="<b>internal/hooks</b><br/><font style="font-size:10px">the hooks: block — runs each hook (sh -c, JSON on stdin/stdout), chain, onError</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="940" y="400" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_engine_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="engine" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_ask_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="ask" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_main_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_hooks_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="hooks" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_session" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="session"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_compact" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="compact"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_engine" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_hooks" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="hooks"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_store" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="store"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="docsearch" value="<b>internal/docsearch</b><br/><font style="font-size:10px">BM25 over the text files of folders: /docs, search_docs</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="1640" y="460" width="200" height="60" as="geometry" /></mxCell><mxCell id="textfold" value="<b>internal/textfold</b><br/><font style="font-size:10px">case and accents folded, rune for rune</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1"><mxGeometry x="1640" y="560" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_docsearch_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_docsearch_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="docsearch" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_store_textfold" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="store" target="textfold"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_textfold_xnet" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;" edge="1" parent="1" source="textfold" target="xnet"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tools_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tools" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agent_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agent" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_docsearch" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="docsearch"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_acp_tools" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="acp" target="tools"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="agentinit" value="<b>internal/agentinit</b><br/><font style="font-size:10px">mm init: the agent.yaml wizard, presets.yaml, the server's model facts</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1"><mxGeometry x="1640" y="660" width="200" height="60" as="geometry" /></mxCell><mxCell id="e_main_agentinit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="main" target="agentinit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agentinit_config" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentinit" target="config"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agentinit_elicit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentinit" target="elicit"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_agentinit_engine" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="agentinit" target="engine"><mxGeometry relative="1" as="geometry" /></mxCell><mxCell id="e_tui_agentinit" style="endArrow=block;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;" edge="1" parent="1" source="tui" target="agentinit"><mxGeometry relative="1" as="geometry" /></mxCell></root></mxGraphModel></diagram></mxfile> | ||
| \ No newline at end of file | \ No newline at end of file | ||
modified
docs/en/README.md +2 -0 | @@ -10,9 +10,11 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr) | ||
| 10 | 10 | |
| 11 | 11 | ## How-to guides — get a task done |
| 12 | 12 | |
| 13 | +- [Create an agent with `mm init`](how-to/create-an-agent.md) — a wizard that writes a commented agent.yaml from the model server's facts, a family table, the usage and the machine | |
| 13 | 14 | - [Run mini-me on llama.cpp instead of Docker Model Runner](how-to/run-with-llama-cpp.md) |
| 14 | 15 | - [Run mini-me on llmman](how-to/run-with-llmman.md) — `provider: llmman`, the demo config in `demos/llmman/` |
| 15 | 16 | - [Run mini-me on Ollama](how-to/run-with-ollama.md) — `provider: ollama`, the demo config in `demos/ollama/` |
| 17 | +- [Use any OpenAI-compatible server](how-to/run-with-an-openai-compatible-server.md) — `provider: openai`: the OpenAI API, vLLM, LM Studio, a gateway | |
| 16 | 18 | - [Ask another mm agent from your session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<name>`, `/ask-with-context-<name>` |
| 17 | 19 | - [See the JSON sent to the model and its answer](how-to/inspect-model-traffic.md) — `trace`, `AGENT_TRACE`, reading the files with jq |
| 18 | 20 | - [Give the agent your project's instructions](how-to/give-project-instructions.md) — `AGENTS.md`, read per conversation, `agentsMd` settings |
| @@ -10,9 +10,11 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr) | |||
| 10 | 10 | ||
| 11 | ## How-to guides — get a task done | 11 | ## How-to guides — get a task done |
| 12 | 12 | ||
| 13 | +- [Create an agent with `mm init`](how-to/create-an-agent.md) — a wizard that writes a commented agent.yaml from the model server's facts, a family table, the usage and the machine | ||
| 13 | - [Run mini-me on llama.cpp instead of Docker Model Runner](how-to/run-with-llama-cpp.md) | 14 | - [Run mini-me on llama.cpp instead of Docker Model Runner](how-to/run-with-llama-cpp.md) |
| 14 | - [Run mini-me on llmman](how-to/run-with-llmman.md) — `provider: llmman`, the demo config in `demos/llmman/` | 15 | - [Run mini-me on llmman](how-to/run-with-llmman.md) — `provider: llmman`, the demo config in `demos/llmman/` |
| 15 | - [Run mini-me on Ollama](how-to/run-with-ollama.md) — `provider: ollama`, the demo config in `demos/ollama/` | 16 | - [Run mini-me on Ollama](how-to/run-with-ollama.md) — `provider: ollama`, the demo config in `demos/ollama/` |
| 17 | +- [Use any OpenAI-compatible server](how-to/run-with-an-openai-compatible-server.md) — `provider: openai`: the OpenAI API, vLLM, LM Studio, a gateway | ||
| 16 | - [Ask another mm agent from your session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<name>`, `/ask-with-context-<name>` | 18 | - [Ask another mm agent from your session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<name>`, `/ask-with-context-<name>` |
| 17 | - [See the JSON sent to the model and its answer](how-to/inspect-model-traffic.md) — `trace`, `AGENT_TRACE`, reading the files with jq | 19 | - [See the JSON sent to the model and its answer](how-to/inspect-model-traffic.md) — `trace`, `AGENT_TRACE`, reading the files with jq |
| 18 | - [Give the agent your project's instructions](how-to/give-project-instructions.md) — `AGENTS.md`, read per conversation, `agentsMd` settings | 20 | - [Give the agent your project's instructions](how-to/give-project-instructions.md) — `AGENTS.md`, read per conversation, `agentsMd` settings |
modified
docs/en/explanation/providers.md +1 -1 | @@ -2,7 +2,7 @@ | ||
| 2 | 2 | |
| 3 | 3 | ## What is this about? |
| 4 | 4 | |
| 5 | -`mm` talks to a local model server through the OpenAI chat-completions API. Four servers are supported out of the box: Docker Model Runner, llama.cpp's `llama-server`, llmman and Ollama, under the names `dmr`, `llamacpp`, `llmman` and `ollama`. The engine package used to be tied to Docker Model Runner; the provider abstraction is what generalised it. | |
| 5 | +`mm` talks to a local model server through the OpenAI chat-completions API. Four servers are supported out of the box: Docker Model Runner, llama.cpp's `llama-server`, llmman and Ollama, under the names `dmr`, `llamacpp`, `llmman` and `ollama`. A fifth entry, `openai` (ticket 118), takes any other server that speaks the protocol — the OpenAI API by default, vLLM, LM Studio, a gateway — and assumes nothing beyond it: it is the same data-only entry with every server-specific field left empty, and a probe that sends the key. The engine package used to be tied to Docker Model Runner; the provider abstraction is what generalised it. | |
| 6 | 6 | |
| 7 | 7 | ## Why it is designed this way |
| 8 | 8 | |
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | ## What is this about? | 3 | ## What is this about? |
| 4 | 4 | ||
| 5 | -`mm` talks to a local model server through the OpenAI chat-completions API. Four servers are supported out of the box: Docker Model Runner, llama.cpp's `llama-server`, llmman and Ollama, under the names `dmr`, `llamacpp`, `llmman` and `ollama`. The engine package used to be tied to Docker Model Runner; the provider abstraction is what generalised it. | 5 | +`mm` talks to a local model server through the OpenAI chat-completions API. Four servers are supported out of the box: Docker Model Runner, llama.cpp's `llama-server`, llmman and Ollama, under the names `dmr`, `llamacpp`, `llmman` and `ollama`. A fifth entry, `openai` (ticket 118), takes any other server that speaks the protocol — the OpenAI API by default, vLLM, LM Studio, a gateway — and assumes nothing beyond it: it is the same data-only entry with every server-specific field left empty, and a probe that sends the key. The engine package used to be tied to Docker Model Runner; the provider abstraction is what generalised it. |
| 6 | 6 | ||
| 7 | ## Why it is designed this way | 7 | ## Why it is designed this way |
| 8 | 8 | ||
added
docs/en/how-to/create-an-agent.md +91 -0 | new file mode 100644 | ||
| @@ -0,0 +1,91 @@ | ||
| 1 | +# How to create an agent with `mm init` | |
| 2 | + | |
| 3 | +This guide shows how to write a new agent.yaml for a model and a job, with mm's wizard: it asks a few questions, reads what the model server says about the model, and writes a commented file — every value with the reason it has that value. No model runs while it does. It assumes a model server is running (llmman, Ollama, Docker Model Runner, llama-server, or any OpenAI-compatible one). | |
| 4 | + | |
| 5 | +## Steps | |
| 6 | + | |
| 7 | +1. In the directory where the agent will work, run: | |
| 8 | + | |
| 9 | + ```bash | |
| 10 | + mm init | |
| 11 | + ``` | |
| 12 | + | |
| 13 | + (`mm --init` is the same.) | |
| 14 | + | |
| 15 | +2. In a terminal, a window opens, in the style of `mm -tui`: the steps on the left, the current question in the middle — with what the highlighted choice means —, and on the right the agent.yaml as it would be written, updated as you move the selection. A real capture (130 × 34, llmman, usage step, `docs` highlighted): | |
| 16 | + | |
| 17 | + ```text | |
| 18 | + mm init — new agent · llmman · Qwen3.5-4B:Q4_K_M | |
| 19 | + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── | |
| 20 | + ✓ Server llmman │ What is the agent for? │ # docs — answers from a documentation folder (docs/), with lin… | |
| 21 | + ✓ Model Qwen3.5-…│ │ # | |
| 22 | + ✓ Family qwen │ developer (default) │ # Written by `mm init`. Every value says why it has that value… | |
| 23 | + ▸ Usage │ reviewer │ # them as you watch the agent work (guides/agent-settings-for-… | |
| 24 | + · Machine │ translator │ # | |
| 25 | + · Ask first │ writer │ # model family: qwen | |
| 26 | + · Name │ assistant │ # usage: docs | |
| 27 | + · File │ researcher │ # machine: small — a laptop, models up to about 8B | |
| 28 | + │ ▸ docs │ # | |
| 29 | + │ json │ # mm -config <this file> or mm -tui <this file> | |
| 30 | + │ coordinator │ | |
| 31 | + │ │ provider: llmman | |
| 32 | + │ answers from a documentation folder │ model: "hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M" | |
| 33 | + │ (docs/), with links to the passages │ | |
| 34 | + │ │ # 0 = mm asks the server for the window it serves (the model's… | |
| 35 | + │ │ # is 262144 tokens; the server may serve less) | |
| 36 | + │ │ contextWindow: 0 | |
| 37 | + │ │ # usage docs's default: tools run without asking | |
| 38 | + │ │ yolo: true | |
| 39 | + │ │ # usage docs | |
| 40 | + │ │ bashTool: false | |
| 41 | + │ │ editTools: true | |
| 42 | + │ │ planTool: false | |
| 43 | + │ │ askUserTool: false | |
| 44 | + │ │ # no skills: add a skills/ folder and set skillsDir to use som… | |
| 45 | + │ │ # docs/en/how-to/add-a-skill.md) | |
| 46 | + │ │ skillsDir: no-skills | |
| 47 | + │ │ # usage docs | |
| 48 | + │ │ maxTurns: 8 | |
| 49 | + │ │ # settings guide, row "Small model (≤ 8B), short tasks" | |
| 50 | + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── | |
| 51 | + ↑↓ choose · Enter next · Esc back · PgUp/PgDn preview · Ctrl-C quit | |
| 52 | + ``` | |
| 53 | + | |
| 54 | + `↑` `↓` choose, `Enter` answers and goes to the next question, `Esc` goes back one question, `PgUp` `PgDn` scroll the preview, `Ctrl-C` quits without writing. A text question (the name, the file) is typed; `Ctrl-U` clears it. On a screen narrower than 100 columns, `Tab` shows the preview in place of the question. When every question is answered, `Enter` writes the file. | |
| 55 | + | |
| 56 | + The questions: the model server, the model (from the server's list), its family (detected from the name), what the agent is for (developer, reviewer, translator, writer, assistant, researcher, docs, json, coordinator), which machine runs the model (small, medium, large), whether to ask before each command or file change, the agent's name and the file. | |
| 57 | + | |
| 58 | +3. mm writes the file and checks that it loads: | |
| 59 | + | |
| 60 | + ```text | |
| 61 | + ✅ wrote agent.yaml | |
| 62 | + ✅ mm loads it | |
| 63 | + Next: mm -config agent.yaml (or mm -tui agent.yaml) | |
| 64 | + ``` | |
| 65 | + | |
| 66 | +4. Read the file: each value is preceded by its reason — the GGUF's own sampling, a model card, a measured demo of this repository, the settings guide's row for your machine. Change what does not fit as you watch the agent work. | |
| 67 | + | |
| 68 | +## Variants | |
| 69 | + | |
| 70 | +- **Prove the model answers.** Add `--check`: after writing, mm asks the model "Say hello in one line." with the new file and says whether it answered. The first answer loads the model, which can take a while. | |
| 71 | +- **Line by line.** `--line`, or a run whose input or output is not a terminal (`mm init < answers.txt`), asks the same questions one per line: numbered choices, Enter takes the default. | |
| 72 | +- **No questions, for a script.** Give every answer as a flag, and `--yes` for the rest: | |
| 73 | + | |
| 74 | + ```bash | |
| 75 | + mm init --provider llmman --model hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M \ | |
| 76 | + --usage docs --machine small --name rata -o agent.yaml --yes --check | |
| 77 | + ``` | |
| 78 | + | |
| 79 | +- **See the file without writing it.** `-o -` prints it on stdout. | |
| 80 | +- **A server elsewhere.** `--base-url http://192.168.1.20:17434/v1`; it is written into the file as `baseUrl`. | |
| 81 | +- **A server that does not answer.** mm says so and asks for the model's name: the settings then come from the family table only. | |
| 82 | +- **An existing file.** mm never overwrites it, and says so before asking anything: choose another name with `-o`. | |
| 83 | +- **A JSON agent.** `--usage json` writes a `structuredOutput` example (Go types) to replace with yours, and turns every tool off, since a structured answer forbids tools. | |
| 84 | +- **A model mm does not know.** The family `other` gives a generic starting point and a note in the file: check the model card. | |
| 85 | + | |
| 86 | +## See also | |
| 87 | + | |
| 88 | +- [Command line reference — `mm init`](../reference/cli.md#mm-init--the-agentyaml-wizard): every flag, the sources, the exit codes | |
| 89 | +- [Configuration reference](../reference/configuration.md): every key the file holds | |
| 90 | +- [Agent settings for small models](../../../guides/agent-settings-for-small-models.md): what each setting does, the machine rows | |
| 91 | +- `agent.creator.yaml`: an agent that creates agents with a model, for the unusual cases | |
| new file mode 100644 | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | +# How to create an agent with `mm init` | ||
| 2 | + | ||
| 3 | +This guide shows how to write a new agent.yaml for a model and a job, with mm's wizard: it asks a few questions, reads what the model server says about the model, and writes a commented file — every value with the reason it has that value. No model runs while it does. It assumes a model server is running (llmman, Ollama, Docker Model Runner, llama-server, or any OpenAI-compatible one). | ||
| 4 | + | ||
| 5 | +## Steps | ||
| 6 | + | ||
| 7 | +1. In the directory where the agent will work, run: | ||
| 8 | + | ||
| 9 | + ```bash | ||
| 10 | + mm init | ||
| 11 | + ``` | ||
| 12 | + | ||
| 13 | + (`mm --init` is the same.) | ||
| 14 | + | ||
| 15 | +2. In a terminal, a window opens, in the style of `mm -tui`: the steps on the left, the current question in the middle — with what the highlighted choice means —, and on the right the agent.yaml as it would be written, updated as you move the selection. A real capture (130 × 34, llmman, usage step, `docs` highlighted): | ||
| 16 | + | ||
| 17 | + ```text | ||
| 18 | + mm init — new agent · llmman · Qwen3.5-4B:Q4_K_M | ||
| 19 | + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── | ||
| 20 | + ✓ Server llmman │ What is the agent for? │ # docs — answers from a documentation folder (docs/), with lin… | ||
| 21 | + ✓ Model Qwen3.5-…│ │ # | ||
| 22 | + ✓ Family qwen │ developer (default) │ # Written by `mm init`. Every value says why it has that value… | ||
| 23 | + ▸ Usage │ reviewer │ # them as you watch the agent work (guides/agent-settings-for-… | ||
| 24 | + · Machine │ translator │ # | ||
| 25 | + · Ask first │ writer │ # model family: qwen | ||
| 26 | + · Name │ assistant │ # usage: docs | ||
| 27 | + · File │ researcher │ # machine: small — a laptop, models up to about 8B | ||
| 28 | + │ ▸ docs │ # | ||
| 29 | + │ json │ # mm -config <this file> or mm -tui <this file> | ||
| 30 | + │ coordinator │ | ||
| 31 | + │ │ provider: llmman | ||
| 32 | + │ answers from a documentation folder │ model: "hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M" | ||
| 33 | + │ (docs/), with links to the passages │ | ||
| 34 | + │ │ # 0 = mm asks the server for the window it serves (the model's… | ||
| 35 | + │ │ # is 262144 tokens; the server may serve less) | ||
| 36 | + │ │ contextWindow: 0 | ||
| 37 | + │ │ # usage docs's default: tools run without asking | ||
| 38 | + │ │ yolo: true | ||
| 39 | + │ │ # usage docs | ||
| 40 | + │ │ bashTool: false | ||
| 41 | + │ │ editTools: true | ||
| 42 | + │ │ planTool: false | ||
| 43 | + │ │ askUserTool: false | ||
| 44 | + │ │ # no skills: add a skills/ folder and set skillsDir to use som… | ||
| 45 | + │ │ # docs/en/how-to/add-a-skill.md) | ||
| 46 | + │ │ skillsDir: no-skills | ||
| 47 | + │ │ # usage docs | ||
| 48 | + │ │ maxTurns: 8 | ||
| 49 | + │ │ # settings guide, row "Small model (≤ 8B), short tasks" | ||
| 50 | + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── | ||
| 51 | + ↑↓ choose · Enter next · Esc back · PgUp/PgDn preview · Ctrl-C quit | ||
| 52 | + ``` | ||
| 53 | + | ||
| 54 | + `↑` `↓` choose, `Enter` answers and goes to the next question, `Esc` goes back one question, `PgUp` `PgDn` scroll the preview, `Ctrl-C` quits without writing. A text question (the name, the file) is typed; `Ctrl-U` clears it. On a screen narrower than 100 columns, `Tab` shows the preview in place of the question. When every question is answered, `Enter` writes the file. | ||
| 55 | + | ||
| 56 | + The questions: the model server, the model (from the server's list), its family (detected from the name), what the agent is for (developer, reviewer, translator, writer, assistant, researcher, docs, json, coordinator), which machine runs the model (small, medium, large), whether to ask before each command or file change, the agent's name and the file. | ||
| 57 | + | ||
| 58 | +3. mm writes the file and checks that it loads: | ||
| 59 | + | ||
| 60 | + ```text | ||
| 61 | + ✅ wrote agent.yaml | ||
| 62 | + ✅ mm loads it | ||
| 63 | + Next: mm -config agent.yaml (or mm -tui agent.yaml) | ||
| 64 | + ``` | ||
| 65 | + | ||
| 66 | +4. Read the file: each value is preceded by its reason — the GGUF's own sampling, a model card, a measured demo of this repository, the settings guide's row for your machine. Change what does not fit as you watch the agent work. | ||
| 67 | + | ||
| 68 | +## Variants | ||
| 69 | + | ||
| 70 | +- **Prove the model answers.** Add `--check`: after writing, mm asks the model "Say hello in one line." with the new file and says whether it answered. The first answer loads the model, which can take a while. | ||
| 71 | +- **Line by line.** `--line`, or a run whose input or output is not a terminal (`mm init < answers.txt`), asks the same questions one per line: numbered choices, Enter takes the default. | ||
| 72 | +- **No questions, for a script.** Give every answer as a flag, and `--yes` for the rest: | ||
| 73 | + | ||
| 74 | + ```bash | ||
| 75 | + mm init --provider llmman --model hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M \ | ||
| 76 | + --usage docs --machine small --name rata -o agent.yaml --yes --check | ||
| 77 | + ``` | ||
| 78 | + | ||
| 79 | +- **See the file without writing it.** `-o -` prints it on stdout. | ||
| 80 | +- **A server elsewhere.** `--base-url http://192.168.1.20:17434/v1`; it is written into the file as `baseUrl`. | ||
| 81 | +- **A server that does not answer.** mm says so and asks for the model's name: the settings then come from the family table only. | ||
| 82 | +- **An existing file.** mm never overwrites it, and says so before asking anything: choose another name with `-o`. | ||
| 83 | +- **A JSON agent.** `--usage json` writes a `structuredOutput` example (Go types) to replace with yours, and turns every tool off, since a structured answer forbids tools. | ||
| 84 | +- **A model mm does not know.** The family `other` gives a generic starting point and a note in the file: check the model card. | ||
| 85 | + | ||
| 86 | +## See also | ||
| 87 | + | ||
| 88 | +- [Command line reference — `mm init`](../reference/cli.md#mm-init--the-agentyaml-wizard): every flag, the sources, the exit codes | ||
| 89 | +- [Configuration reference](../reference/configuration.md): every key the file holds | ||
| 90 | +- [Agent settings for small models](../../../guides/agent-settings-for-small-models.md): what each setting does, the machine rows | ||
| 91 | +- `agent.creator.yaml`: an agent that creates agents with a model, for the unusual cases | ||
added
docs/en/how-to/run-with-an-openai-compatible-server.md +44 -0 | new file mode 100644 | ||
| @@ -0,0 +1,44 @@ | ||
| 1 | +# How to use any OpenAI-compatible server | |
| 2 | + | |
| 3 | +This guide shows how to run mini-me on a model server that has no dedicated provider — the OpenAI API itself, vLLM, LM Studio, OpenRouter, a company gateway — with the generic `openai` provider. It assumes the server speaks the OpenAI chat-completions protocol and supports tool calls. | |
| 4 | + | |
| 5 | +## Steps | |
| 6 | + | |
| 7 | +1. Point the agent at the server, in its YAML: | |
| 8 | + | |
| 9 | + ```yaml | |
| 10 | + provider: openai | |
| 11 | + model: my-model # as the server names it: GET <baseUrl>/models | |
| 12 | + baseUrl: http://localhost:8000/v1 # omit it for the OpenAI API | |
| 13 | + contextWindow: 32768 # the window the server serves: this provider cannot ask for it | |
| 14 | + ``` | |
| 15 | + | |
| 16 | +2. If the server needs a key, export it — it never goes in the YAML: | |
| 17 | + | |
| 18 | + ```bash | |
| 19 | + export OPENAI_API_KEY=sk-… | |
| 20 | + ``` | |
| 21 | + | |
| 22 | + Another variable name: `apiKeyEnv: MY_GATEWAY_KEY`. | |
| 23 | + | |
| 24 | +3. Start mm as usual (`mm agent.yaml`, `mm -tui agent.yaml`, `mm -acp`). Checked with llmman's OpenAI address used as a generic server: the start-up probe lists the models, and a `bash` tool call runs: | |
| 25 | + | |
| 26 | + ```text | |
| 27 | + 🛠️ bash: echo hello-from-openai-provider | |
| 28 | + │ hello-from-openai-provider | |
| 29 | + 🤖 The command printed: `hello-from-openai-provider` | |
| 30 | + ``` | |
| 31 | + | |
| 32 | +`mm init --provider openai --base-url <address>` writes such a file for you (see [Create an agent with `mm init`](create-an-agent.md)). | |
| 33 | + | |
| 34 | +## Variants | |
| 35 | + | |
| 36 | +- **The OpenAI API.** No `baseUrl`, `OPENAI_API_KEY` exported, a model such as `gpt-5-mini`. Its reasoning models accept only the default temperature and take `max_completion_tokens` instead of `max_tokens`: write those in `sampling`, and remove a key the API refuses. (Not measured in this repository.) | |
| 37 | +- **The key is refused.** The start-up warning says `openai: <baseUrl> refused the key (HTTP 401) — export OPENAI_API_KEY`. | |
| 38 | +- **Nothing answers.** The warning says `openai: nothing answers at <baseUrl> — check baseUrl: …`: the address must be the OpenAI-compatible one, usually ending in `/v1`. | |
| 39 | +- **A server mm has a provider for.** Prefer it (`dmr`, `llamacpp`, `llmman`, `ollama`): those know how the server reads a long prompt, turns reasoning off for a summary, unloads a model, and tell the window size. The generic provider does none of that. | |
| 40 | + | |
| 41 | +## See also | |
| 42 | + | |
| 43 | +- [Configuration reference — provider defaults](../reference/configuration.md#provider-defaults): what `openai` sends and does not | |
| 44 | +- [Providers — explanation](../explanation/providers.md) | |
| new file mode 100644 | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | +# How to use any OpenAI-compatible server | ||
| 2 | + | ||
| 3 | +This guide shows how to run mini-me on a model server that has no dedicated provider — the OpenAI API itself, vLLM, LM Studio, OpenRouter, a company gateway — with the generic `openai` provider. It assumes the server speaks the OpenAI chat-completions protocol and supports tool calls. | ||
| 4 | + | ||
| 5 | +## Steps | ||
| 6 | + | ||
| 7 | +1. Point the agent at the server, in its YAML: | ||
| 8 | + | ||
| 9 | + ```yaml | ||
| 10 | + provider: openai | ||
| 11 | + model: my-model # as the server names it: GET <baseUrl>/models | ||
| 12 | + baseUrl: http://localhost:8000/v1 # omit it for the OpenAI API | ||
| 13 | + contextWindow: 32768 # the window the server serves: this provider cannot ask for it | ||
| 14 | + ``` | ||
| 15 | + | ||
| 16 | +2. If the server needs a key, export it — it never goes in the YAML: | ||
| 17 | + | ||
| 18 | + ```bash | ||
| 19 | + export OPENAI_API_KEY=sk-… | ||
| 20 | + ``` | ||
| 21 | + | ||
| 22 | + Another variable name: `apiKeyEnv: MY_GATEWAY_KEY`. | ||
| 23 | + | ||
| 24 | +3. Start mm as usual (`mm agent.yaml`, `mm -tui agent.yaml`, `mm -acp`). Checked with llmman's OpenAI address used as a generic server: the start-up probe lists the models, and a `bash` tool call runs: | ||
| 25 | + | ||
| 26 | + ```text | ||
| 27 | + 🛠️ bash: echo hello-from-openai-provider | ||
| 28 | + │ hello-from-openai-provider | ||
| 29 | + 🤖 The command printed: `hello-from-openai-provider` | ||
| 30 | + ``` | ||
| 31 | + | ||
| 32 | +`mm init --provider openai --base-url <address>` writes such a file for you (see [Create an agent with `mm init`](create-an-agent.md)). | ||
| 33 | + | ||
| 34 | +## Variants | ||
| 35 | + | ||
| 36 | +- **The OpenAI API.** No `baseUrl`, `OPENAI_API_KEY` exported, a model such as `gpt-5-mini`. Its reasoning models accept only the default temperature and take `max_completion_tokens` instead of `max_tokens`: write those in `sampling`, and remove a key the API refuses. (Not measured in this repository.) | ||
| 37 | +- **The key is refused.** The start-up warning says `openai: <baseUrl> refused the key (HTTP 401) — export OPENAI_API_KEY`. | ||
| 38 | +- **Nothing answers.** The warning says `openai: nothing answers at <baseUrl> — check baseUrl: …`: the address must be the OpenAI-compatible one, usually ending in `/v1`. | ||
| 39 | +- **A server mm has a provider for.** Prefer it (`dmr`, `llamacpp`, `llmman`, `ollama`): those know how the server reads a long prompt, turns reasoning off for a summary, unloads a model, and tell the window size. The generic provider does none of that. | ||
| 40 | + | ||
| 41 | +## See also | ||
| 42 | + | ||
| 43 | +- [Configuration reference — provider defaults](../reference/configuration.md#provider-defaults): what `openai` sends and does not | ||
| 44 | +- [Providers — explanation](../explanation/providers.md) | ||
modified
docs/en/reference/cli.md +32 -0 | @@ -8,6 +8,7 @@ | ||
| 8 | 8 | mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--about] [<path>] |
| 9 | 9 | mm [-config <path>] --ask <agent> [-p <question>] (question on stdin when -p is absent) |
| 10 | 10 | mm [-config <path>] --ask-with-context <agent> [-p <question>] (context on stdin) |
| 11 | +mm init [flags] (write a new agent.yaml; also mm --init) | |
| 11 | 12 | ``` |
| 12 | 13 | |
| 13 | 14 | | Element | Type | Default | Description | |
| @@ -148,6 +149,37 @@ mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/ | ||
| 148 | 149 | | Parent process | Watched every 500 ms: when it is gone, the ask is cancelled and the agent stopped. | |
| 149 | 150 | | Session | None: neither this process nor the agent writes session files. | |
| 150 | 151 | |
| 152 | +## `mm init` — the agent.yaml wizard | |
| 153 | + | |
| 154 | +`mm init` and `mm --init` (also `-init`) write a new, commented agent.yaml. They are answered before any configuration is read. Each question below has a flag; a question whose flag is given is not asked. See [How to create an agent with `mm init`](../how-to/create-an-agent.md). | |
| 155 | + | |
| 156 | +| Flag | Question when absent | Default | | |
| 157 | +|------|----------------------|---------| | |
| 158 | +| `--provider` | Model server: `llmman`, `ollama`, `dmr`, `llamacpp`, `openai` | the first local one whose server answers, else `llmman` (`openai` is never probed: its default address is the OpenAI API) | | |
| 159 | +| `--base-url` | — (not asked) | the provider's address, or its fallback when it does not answer | | |
| 160 | +| `--model` | Model: a list of the server's models (`/api/tags` for llmman and Ollama, `/models` for the others), or a name to type when the server does not answer | the first of the list | | |
| 161 | +| `--family` | Model family | detected from the model's name, then from the server's family name | | |
| 162 | +| `--usage` | What the agent is for: `developer`, `reviewer`, `translator`, `writer`, `assistant`, `researcher`, `docs`, `json`, `coordinator` | `developer` | | |
| 163 | +| `--machine` | Which machine runs the model: `small`, `medium`, `large` | `small` | | |
| 164 | +| `--yolo yes\|no` | Ask before each command or file change? — only for usages with `bash`, file tools or `fetch_content` | the usage's | | |
| 165 | +| `--name` | Agent name (`acp.name`) | the usage's name | | |
| 166 | +| `-o`, `--output` | File to write (`-` = stdout) | `agent.yaml` | | |
| 167 | +| `--check` | — | off; on: after writing, runs this mm with `-config <file> -p "Say hello in one line."` and reports whether the model answered (5 min at most) | | |
| 168 | +| `--yes` | — | off; on: nothing is asked, every missing answer takes its default | | |
| 169 | +| `--line` | — | off; on: the questions are asked line by line even in a terminal | | |
| 170 | + | |
| 171 | +| Aspect | Behaviour | | |
| 172 | +|--------|-----------| | |
| 173 | +| Window | When stdin and stdout are terminals (and neither `--yes` nor `--line`): a full-screen window — steps (✓ answered, ▸ current, · to come, each answer beside its step), the question with the highlighted choice's description, and the file as it would be written with that choice (preview beside the question from 100 columns, in its place with `Tab` below). Keys: `↑` `↓` `Home` `End` choose, `Enter` answers, `y` / `n` answer the yes-or-no question, `Esc` takes the previous answer back (answers given by flags are skipped), `PgUp` `PgDn` scroll the preview, `Ctrl-U` clears a text answer, `Ctrl-C` quits without writing (`nothing written`, exit 1). A refused answer shows on the bottom rule. Once every question is answered, `Enter` writes the file. | | |
| 174 | +| Line mode | Otherwise: one question per screen line, numbered choices; a number, an option's text or another text answers; an empty line or `/skip` takes the default. Usages and machines are listed with a one-line description first. | | |
| 175 | +| Model facts | llmman and Ollama: `POST /api/show` — the native window, the GGUF's sampling (`general.sampling.*`, Ollama's Modelfile parameters), the chat template's reasoning switch (`enable_thinking`, `reasoning_effort`) and its default. llama-server: `GET /props` — `n_ctx` and the chat template. Docker Model Runner and `openai`: none — the family table decides; `openai` lists its models with `OPENAI_API_KEY`. | | |
| 176 | +| Where each value comes from | The server's facts, then the family table, then the usage, then the machine row; the table is `internal/agentinit/presets.yaml`, each entry with its source. | | |
| 177 | +| Sampling | Reasoning on (the usage asks for it and the model has a switch): the family's thinking sampling, never a temperature under 0.6, `max_tokens: 16384`. Reasoning off: the family's general sampling, or its precise temperature for tool-heavy usages, `max_tokens: 4096`. The GGUF's own sampling replaces the family's. `parallel_tool_calls: false` when any tool is on. | | |
| 178 | +| Written file | Every value preceded by a comment saying why it has that value; `contextWindow: 0` (mm asks the server), with the native window in its comment; `context.threshold: 75`; the usage's English system prompt; for `docs` a `docSearch` block, for `json` a `structuredOutput` example and every tool off, for `coordinator` a commented `mmConfigs` example. | | |
| 179 | +| Existing file | Never overwritten: `⚠️ <file> already exists — nothing was written; choose another name with -o`, exit 1, before any question. | | |
| 180 | +| After writing | The file is loaded as mm loads a configuration; an error is printed and the exit code is 1. | | |
| 181 | +| Exit codes | 0 written (and checked); 1 an unknown provider, usage or machine, no model, an existing file, a file mm does not load, a failed check; 2 a bad flag. | | |
| 182 | + | |
| 151 | 183 | ## Exit codes |
| 152 | 184 | |
| 153 | 185 | | Code | Cause | |
| @@ -8,6 +8,7 @@ | |||
| 8 | mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--about] [<path>] | 8 | mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--about] [<path>] |
| 9 | mm [-config <path>] --ask <agent> [-p <question>] (question on stdin when -p is absent) | 9 | mm [-config <path>] --ask <agent> [-p <question>] (question on stdin when -p is absent) |
| 10 | mm [-config <path>] --ask-with-context <agent> [-p <question>] (context on stdin) | 10 | mm [-config <path>] --ask-with-context <agent> [-p <question>] (context on stdin) |
| 11 | +mm init [flags] (write a new agent.yaml; also mm --init) | ||
| 11 | ``` | 12 | ``` |
| 12 | 13 | ||
| 13 | | Element | Type | Default | Description | | 14 | | Element | Type | Default | Description | |
| @@ -148,6 +149,37 @@ mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/ | |||
| 148 | | Parent process | Watched every 500 ms: when it is gone, the ask is cancelled and the agent stopped. | | 149 | | Parent process | Watched every 500 ms: when it is gone, the ask is cancelled and the agent stopped. | |
| 149 | | Session | None: neither this process nor the agent writes session files. | | 150 | | Session | None: neither this process nor the agent writes session files. | |
| 150 | 151 | ||
| 152 | +## `mm init` — the agent.yaml wizard | ||
| 153 | + | ||
| 154 | +`mm init` and `mm --init` (also `-init`) write a new, commented agent.yaml. They are answered before any configuration is read. Each question below has a flag; a question whose flag is given is not asked. See [How to create an agent with `mm init`](../how-to/create-an-agent.md). | ||
| 155 | + | ||
| 156 | +| Flag | Question when absent | Default | | ||
| 157 | +|------|----------------------|---------| | ||
| 158 | +| `--provider` | Model server: `llmman`, `ollama`, `dmr`, `llamacpp`, `openai` | the first local one whose server answers, else `llmman` (`openai` is never probed: its default address is the OpenAI API) | | ||
| 159 | +| `--base-url` | — (not asked) | the provider's address, or its fallback when it does not answer | | ||
| 160 | +| `--model` | Model: a list of the server's models (`/api/tags` for llmman and Ollama, `/models` for the others), or a name to type when the server does not answer | the first of the list | | ||
| 161 | +| `--family` | Model family | detected from the model's name, then from the server's family name | | ||
| 162 | +| `--usage` | What the agent is for: `developer`, `reviewer`, `translator`, `writer`, `assistant`, `researcher`, `docs`, `json`, `coordinator` | `developer` | | ||
| 163 | +| `--machine` | Which machine runs the model: `small`, `medium`, `large` | `small` | | ||
| 164 | +| `--yolo yes\|no` | Ask before each command or file change? — only for usages with `bash`, file tools or `fetch_content` | the usage's | | ||
| 165 | +| `--name` | Agent name (`acp.name`) | the usage's name | | ||
| 166 | +| `-o`, `--output` | File to write (`-` = stdout) | `agent.yaml` | | ||
| 167 | +| `--check` | — | off; on: after writing, runs this mm with `-config <file> -p "Say hello in one line."` and reports whether the model answered (5 min at most) | | ||
| 168 | +| `--yes` | — | off; on: nothing is asked, every missing answer takes its default | | ||
| 169 | +| `--line` | — | off; on: the questions are asked line by line even in a terminal | | ||
| 170 | + | ||
| 171 | +| Aspect | Behaviour | | ||
| 172 | +|--------|-----------| | ||
| 173 | +| Window | When stdin and stdout are terminals (and neither `--yes` nor `--line`): a full-screen window — steps (✓ answered, ▸ current, · to come, each answer beside its step), the question with the highlighted choice's description, and the file as it would be written with that choice (preview beside the question from 100 columns, in its place with `Tab` below). Keys: `↑` `↓` `Home` `End` choose, `Enter` answers, `y` / `n` answer the yes-or-no question, `Esc` takes the previous answer back (answers given by flags are skipped), `PgUp` `PgDn` scroll the preview, `Ctrl-U` clears a text answer, `Ctrl-C` quits without writing (`nothing written`, exit 1). A refused answer shows on the bottom rule. Once every question is answered, `Enter` writes the file. | | ||
| 174 | +| Line mode | Otherwise: one question per screen line, numbered choices; a number, an option's text or another text answers; an empty line or `/skip` takes the default. Usages and machines are listed with a one-line description first. | | ||
| 175 | +| Model facts | llmman and Ollama: `POST /api/show` — the native window, the GGUF's sampling (`general.sampling.*`, Ollama's Modelfile parameters), the chat template's reasoning switch (`enable_thinking`, `reasoning_effort`) and its default. llama-server: `GET /props` — `n_ctx` and the chat template. Docker Model Runner and `openai`: none — the family table decides; `openai` lists its models with `OPENAI_API_KEY`. | | ||
| 176 | +| Where each value comes from | The server's facts, then the family table, then the usage, then the machine row; the table is `internal/agentinit/presets.yaml`, each entry with its source. | | ||
| 177 | +| Sampling | Reasoning on (the usage asks for it and the model has a switch): the family's thinking sampling, never a temperature under 0.6, `max_tokens: 16384`. Reasoning off: the family's general sampling, or its precise temperature for tool-heavy usages, `max_tokens: 4096`. The GGUF's own sampling replaces the family's. `parallel_tool_calls: false` when any tool is on. | | ||
| 178 | +| Written file | Every value preceded by a comment saying why it has that value; `contextWindow: 0` (mm asks the server), with the native window in its comment; `context.threshold: 75`; the usage's English system prompt; for `docs` a `docSearch` block, for `json` a `structuredOutput` example and every tool off, for `coordinator` a commented `mmConfigs` example. | | ||
| 179 | +| Existing file | Never overwritten: `⚠️ <file> already exists — nothing was written; choose another name with -o`, exit 1, before any question. | | ||
| 180 | +| After writing | The file is loaded as mm loads a configuration; an error is printed and the exit code is 1. | | ||
| 181 | +| Exit codes | 0 written (and checked); 1 an unknown provider, usage or machine, no model, an existing file, a file mm does not load, a failed check; 2 a bad flag. | | ||
| 182 | + | ||
| 151 | ## Exit codes | 183 | ## Exit codes |
| 152 | 184 | ||
| 153 | | Code | Cause | | 185 | | Code | Cause | |
modified
docs/en/reference/configuration.md +4 -1 | @@ -6,7 +6,7 @@ | ||
| 6 | 6 | |
| 7 | 7 | | Key | Type | Default | Description | |
| 8 | 8 | |-----|------|---------|-------------| |
| 9 | -| `provider` | string | `dmr` | Registry key of the LLM server: `dmr`, `llamacpp`, `llmman` or `ollama`. Overridden by `AGENT_PROVIDER`. | | |
| 9 | +| `provider` | string | `dmr` | Registry key of the LLM server: `dmr`, `llamacpp`, `llmman`, `ollama`, or `openai` for any other OpenAI-compatible server (see [How to use any OpenAI-compatible server](../how-to/run-with-an-openai-compatible-server.md)). Overridden by `AGENT_PROVIDER`. | | |
| 10 | 10 | | `model` | string | `huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M` | Model identifier in the provider's naming. Overridden by `AGENT_MODEL`. | |
| 11 | 11 | | `baseUrl` | string | `""` (provider default) | OpenAI-compatible endpoint tried first. Overridden by `AGENT_BASE_URL`. | |
| 12 | 12 | | `fallback` | string or absent | absent (provider default) | Endpoint used when `baseUrl` does not answer `/models` within 2 s. Absent = provider default; `""` = no fallback. | |
| @@ -177,6 +177,9 @@ tools: | ||
| 177 | 177 | | `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no | |
| 178 | 178 | | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no | |
| 179 | 179 | | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no | |
| 180 | +| `openai` | `https://api.openai.com/v1` | none | `OPENAI_API_KEY` | no — a server that needs one answers 401, and the start-up warning names the variable | | |
| 181 | + | |
| 182 | +The `openai` provider sends only standard fields: no `return_progress` (so no prompt-reading progress while a long prompt is read), no reasoning switch on a summary request, no `/unload`. It cannot ask the server for its window: set `contextWindow`, or compression counts messages (`context.maxMessages`). Its start-up probe sends the key to `GET /models`; a 401 or 403 is reported as a refused key, not as a server that does not answer. | |
| 180 | 183 | |
| 181 | 184 | ## `structuredOutput` |
| 182 | 185 | |
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | | Key | Type | Default | Description | | 7 | | Key | Type | Default | Description | |
| 8 | |-----|------|---------|-------------| | 8 | |-----|------|---------|-------------| |
| 9 | -| `provider` | string | `dmr` | Registry key of the LLM server: `dmr`, `llamacpp`, `llmman` or `ollama`. Overridden by `AGENT_PROVIDER`. | | 9 | +| `provider` | string | `dmr` | Registry key of the LLM server: `dmr`, `llamacpp`, `llmman`, `ollama`, or `openai` for any other OpenAI-compatible server (see [How to use any OpenAI-compatible server](../how-to/run-with-an-openai-compatible-server.md)). Overridden by `AGENT_PROVIDER`. | |
| 10 | | `model` | string | `huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M` | Model identifier in the provider's naming. Overridden by `AGENT_MODEL`. | | 10 | | `model` | string | `huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M` | Model identifier in the provider's naming. Overridden by `AGENT_MODEL`. | |
| 11 | | `baseUrl` | string | `""` (provider default) | OpenAI-compatible endpoint tried first. Overridden by `AGENT_BASE_URL`. | | 11 | | `baseUrl` | string | `""` (provider default) | OpenAI-compatible endpoint tried first. Overridden by `AGENT_BASE_URL`. | |
| 12 | | `fallback` | string or absent | absent (provider default) | Endpoint used when `baseUrl` does not answer `/models` within 2 s. Absent = provider default; `""` = no fallback. | | 12 | | `fallback` | string or absent | absent (provider default) | Endpoint used when `baseUrl` does not answer `/models` within 2 s. Absent = provider default; `""` = no fallback. | |
| @@ -177,6 +177,9 @@ tools: | |||
| 177 | | `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no | | 177 | | `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no | |
| 178 | | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no | | 178 | | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no | |
| 179 | | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no | | 179 | | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no | |
| 180 | +| `openai` | `https://api.openai.com/v1` | none | `OPENAI_API_KEY` | no — a server that needs one answers 401, and the start-up warning names the variable | | ||
| 181 | + | ||
| 182 | +The `openai` provider sends only standard fields: no `return_progress` (so no prompt-reading progress while a long prompt is read), no reasoning switch on a summary request, no `/unload`. It cannot ask the server for its window: set `contextWindow`, or compression counts messages (`context.maxMessages`). Its start-up probe sends the key to `GET /models`; a 401 or 403 is reported as a refused key, not as a server that does not answer. | ||
| 180 | 183 | ||
| 181 | ## `structuredOutput` | 184 | ## `structuredOutput` |
| 182 | 185 | ||
modified
docs/fr/README.md +2 -0 | @@ -10,9 +10,11 @@ Cette documentation est organisée selon les quatre quadrants [Diátaxis](https: | ||
| 10 | 10 | |
| 11 | 11 | ## Guides pratiques — accomplir une tâche |
| 12 | 12 | |
| 13 | +- [Créer un agent avec `mm init`](how-to/create-an-agent.md) — un assistant qui écrit un agent.yaml commenté à partir des faits du serveur, d'une table de familles, de l'usage et de la machine | |
| 13 | 14 | - [Faire tourner mini-me sur llama.cpp plutôt que Docker Model Runner](how-to/run-with-llama-cpp.md) |
| 14 | 15 | - [Faire tourner mini-me sur llmman](how-to/run-with-llmman.md) — `provider: llmman`, la config de démo dans `demos/llmman/` |
| 15 | 16 | - [Faire tourner mini-me sur Ollama](how-to/run-with-ollama.md) — `provider: ollama`, la config de démo dans `demos/ollama/` |
| 17 | +- [Utiliser n'importe quel serveur compatible OpenAI](how-to/run-with-an-openai-compatible-server.md) — `provider: openai` : l'API d'OpenAI, vLLM, LM Studio, une passerelle | |
| 16 | 18 | - [Interroger un autre agent mm depuis votre session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<nom>`, `/ask-with-context-<nom>` |
| 17 | 19 | - [Voir le JSON envoyé au modèle et sa réponse](how-to/inspect-model-traffic.md) — `trace`, `AGENT_TRACE`, lire les fichiers avec jq |
| 18 | 20 | - [Donner à l'agent les consignes de votre projet](how-to/give-project-instructions.md) — `AGENTS.md`, lu à chaque conversation, réglages `agentsMd` |
| @@ -10,9 +10,11 @@ Cette documentation est organisée selon les quatre quadrants [Diátaxis](https: | |||
| 10 | 10 | ||
| 11 | ## Guides pratiques — accomplir une tâche | 11 | ## Guides pratiques — accomplir une tâche |
| 12 | 12 | ||
| 13 | +- [Créer un agent avec `mm init`](how-to/create-an-agent.md) — un assistant qui écrit un agent.yaml commenté à partir des faits du serveur, d'une table de familles, de l'usage et de la machine | ||
| 13 | - [Faire tourner mini-me sur llama.cpp plutôt que Docker Model Runner](how-to/run-with-llama-cpp.md) | 14 | - [Faire tourner mini-me sur llama.cpp plutôt que Docker Model Runner](how-to/run-with-llama-cpp.md) |
| 14 | - [Faire tourner mini-me sur llmman](how-to/run-with-llmman.md) — `provider: llmman`, la config de démo dans `demos/llmman/` | 15 | - [Faire tourner mini-me sur llmman](how-to/run-with-llmman.md) — `provider: llmman`, la config de démo dans `demos/llmman/` |
| 15 | - [Faire tourner mini-me sur Ollama](how-to/run-with-ollama.md) — `provider: ollama`, la config de démo dans `demos/ollama/` | 16 | - [Faire tourner mini-me sur Ollama](how-to/run-with-ollama.md) — `provider: ollama`, la config de démo dans `demos/ollama/` |
| 17 | +- [Utiliser n'importe quel serveur compatible OpenAI](how-to/run-with-an-openai-compatible-server.md) — `provider: openai` : l'API d'OpenAI, vLLM, LM Studio, une passerelle | ||
| 16 | - [Interroger un autre agent mm depuis votre session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<nom>`, `/ask-with-context-<nom>` | 18 | - [Interroger un autre agent mm depuis votre session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<nom>`, `/ask-with-context-<nom>` |
| 17 | - [Voir le JSON envoyé au modèle et sa réponse](how-to/inspect-model-traffic.md) — `trace`, `AGENT_TRACE`, lire les fichiers avec jq | 19 | - [Voir le JSON envoyé au modèle et sa réponse](how-to/inspect-model-traffic.md) — `trace`, `AGENT_TRACE`, lire les fichiers avec jq |
| 18 | - [Donner à l'agent les consignes de votre projet](how-to/give-project-instructions.md) — `AGENTS.md`, lu à chaque conversation, réglages `agentsMd` | 20 | - [Donner à l'agent les consignes de votre projet](how-to/give-project-instructions.md) — `AGENTS.md`, lu à chaque conversation, réglages `agentsMd` |
modified
docs/fr/explanation/providers.md +1 -1 | @@ -2,7 +2,7 @@ | ||
| 2 | 2 | |
| 3 | 3 | ## De quoi s'agit-il ? |
| 4 | 4 | |
| 5 | -`mm` dialogue avec un serveur de modèle local via l'API chat-completions d'OpenAI. Quatre serveurs sont pris en charge d'origine : Docker Model Runner, `llama-server` de llama.cpp, llmman et Ollama, sous les noms `dmr`, `llamacpp`, `llmman` et `ollama`. Le paquet moteur était autrefois lié à Docker Model Runner ; l'abstraction de fournisseur est ce qui l'a généralisé. | |
| 5 | +`mm` dialogue avec un serveur de modèle local via l'API chat-completions d'OpenAI. Quatre serveurs sont pris en charge d'origine : Docker Model Runner, `llama-server` de llama.cpp, llmman et Ollama, sous les noms `dmr`, `llamacpp`, `llmman` et `ollama`. Une cinquième entrée, `openai` (ticket 118), prend tout autre serveur qui parle le protocole — l'API d'OpenAI par défaut, vLLM, LM Studio, une passerelle — et ne suppose rien au-delà : c'est la même entrée faite de données, avec tous les champs propres à un serveur laissés vides, et une sonde qui envoie la clé. Le paquet moteur était autrefois lié à Docker Model Runner ; l'abstraction de fournisseur est ce qui l'a généralisé. | |
| 6 | 6 | |
| 7 | 7 | ## Pourquoi c'est conçu ainsi |
| 8 | 8 | |
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | ## De quoi s'agit-il ? | 3 | ## De quoi s'agit-il ? |
| 4 | 4 | ||
| 5 | -`mm` dialogue avec un serveur de modèle local via l'API chat-completions d'OpenAI. Quatre serveurs sont pris en charge d'origine : Docker Model Runner, `llama-server` de llama.cpp, llmman et Ollama, sous les noms `dmr`, `llamacpp`, `llmman` et `ollama`. Le paquet moteur était autrefois lié à Docker Model Runner ; l'abstraction de fournisseur est ce qui l'a généralisé. | 5 | +`mm` dialogue avec un serveur de modèle local via l'API chat-completions d'OpenAI. Quatre serveurs sont pris en charge d'origine : Docker Model Runner, `llama-server` de llama.cpp, llmman et Ollama, sous les noms `dmr`, `llamacpp`, `llmman` et `ollama`. Une cinquième entrée, `openai` (ticket 118), prend tout autre serveur qui parle le protocole — l'API d'OpenAI par défaut, vLLM, LM Studio, une passerelle — et ne suppose rien au-delà : c'est la même entrée faite de données, avec tous les champs propres à un serveur laissés vides, et une sonde qui envoie la clé. Le paquet moteur était autrefois lié à Docker Model Runner ; l'abstraction de fournisseur est ce qui l'a généralisé. |
| 6 | 6 | ||
| 7 | ## Pourquoi c'est conçu ainsi | 7 | ## Pourquoi c'est conçu ainsi |
| 8 | 8 | ||
added
docs/fr/how-to/create-an-agent.md +91 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
docs/fr/how-to/run-with-an-openai-compatible-server.md +44 -0 | new file mode 100644 | ||
| @@ -0,0 +1,44 @@ | ||
| 1 | +# Utiliser n'importe quel serveur compatible OpenAI | |
| 2 | + | |
| 3 | +Ce guide montre comment faire tourner mini-me sur un serveur de modèles qui n'a pas de fournisseur dédié — l'API d'OpenAI elle-même, vLLM, LM Studio, OpenRouter, une passerelle d'entreprise — avec le fournisseur générique `openai`. Il suppose que le serveur parle le protocole chat-completions d'OpenAI et gère les appels d'outils. | |
| 4 | + | |
| 5 | +## Étapes | |
| 6 | + | |
| 7 | +1. Pointez l'agent vers le serveur, dans son YAML : | |
| 8 | + | |
| 9 | + ```yaml | |
| 10 | + provider: openai | |
| 11 | + model: mon-modele # tel que le serveur le nomme : GET <baseUrl>/models | |
| 12 | + baseUrl: http://localhost:8000/v1 # à omettre pour l'API d'OpenAI | |
| 13 | + contextWindow: 32768 # la fenêtre servie : ce fournisseur ne peut pas la demander | |
| 14 | + ``` | |
| 15 | + | |
| 16 | +2. Si le serveur exige une clé, exportez-la — elle ne va jamais dans le YAML : | |
| 17 | + | |
| 18 | + ```bash | |
| 19 | + export OPENAI_API_KEY=sk-… | |
| 20 | + ``` | |
| 21 | + | |
| 22 | + Un autre nom de variable : `apiKeyEnv: MA_CLE_PASSERELLE`. | |
| 23 | + | |
| 24 | +3. Lancez mm comme d'habitude (`mm agent.yaml`, `mm -tui agent.yaml`, `mm -acp`). Vérifié avec l'adresse OpenAI de llmman utilisée comme serveur générique : la sonde de démarrage liste les modèles, et un appel à l'outil `bash` s'exécute : | |
| 25 | + | |
| 26 | + ```text | |
| 27 | + 🛠️ bash: echo hello-from-openai-provider | |
| 28 | + │ hello-from-openai-provider | |
| 29 | + 🤖 The command printed: `hello-from-openai-provider` | |
| 30 | + ``` | |
| 31 | + | |
| 32 | +`mm init --provider openai --base-url <adresse>` écrit ce fichier pour vous (voir [Créer un agent avec `mm init`](create-an-agent.md)). | |
| 33 | + | |
| 34 | +## Variantes | |
| 35 | + | |
| 36 | +- **L'API d'OpenAI.** Pas de `baseUrl`, `OPENAI_API_KEY` exportée, un modèle comme `gpt-5-mini`. Ses modèles à raisonnement n'acceptent que la température par défaut et prennent `max_completion_tokens` au lieu de `max_tokens` : écrivez-les dans `sampling`, et retirez une clé que l'API refuse. (Non mesuré dans ce dépôt.) | |
| 37 | +- **La clé est refusée.** L'avertissement de démarrage indique `openai: <baseUrl> refused the key (HTTP 401) — export OPENAI_API_KEY`. | |
| 38 | +- **Rien ne répond.** L'avertissement indique `openai: nothing answers at <baseUrl> — check baseUrl: …` : l'adresse doit être celle compatible OpenAI, qui finit généralement par `/v1`. | |
| 39 | +- **Un serveur pour lequel mm a un fournisseur.** Préférez-le (`dmr`, `llamacpp`, `llmman`, `ollama`) : ceux-là savent comment le serveur lit un long prompt, coupent le raisonnement pour un résumé, déchargent un modèle et donnent la taille de la fenêtre. Le fournisseur générique ne fait rien de tout cela. | |
| 40 | + | |
| 41 | +## Voir aussi | |
| 42 | + | |
| 43 | +- [Référence de la configuration — valeurs par défaut des fournisseurs](../reference/configuration.md#valeurs-par-défaut-des-fournisseurs) : ce que `openai` envoie et n'envoie pas | |
| 44 | +- [Les fournisseurs — explication](../explanation/providers.md) | |
| new file mode 100644 | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | +# Utiliser n'importe quel serveur compatible OpenAI | ||
| 2 | + | ||
| 3 | +Ce guide montre comment faire tourner mini-me sur un serveur de modèles qui n'a pas de fournisseur dédié — l'API d'OpenAI elle-même, vLLM, LM Studio, OpenRouter, une passerelle d'entreprise — avec le fournisseur générique `openai`. Il suppose que le serveur parle le protocole chat-completions d'OpenAI et gère les appels d'outils. | ||
| 4 | + | ||
| 5 | +## Étapes | ||
| 6 | + | ||
| 7 | +1. Pointez l'agent vers le serveur, dans son YAML : | ||
| 8 | + | ||
| 9 | + ```yaml | ||
| 10 | + provider: openai | ||
| 11 | + model: mon-modele # tel que le serveur le nomme : GET <baseUrl>/models | ||
| 12 | + baseUrl: http://localhost:8000/v1 # à omettre pour l'API d'OpenAI | ||
| 13 | + contextWindow: 32768 # la fenêtre servie : ce fournisseur ne peut pas la demander | ||
| 14 | + ``` | ||
| 15 | + | ||
| 16 | +2. Si le serveur exige une clé, exportez-la — elle ne va jamais dans le YAML : | ||
| 17 | + | ||
| 18 | + ```bash | ||
| 19 | + export OPENAI_API_KEY=sk-… | ||
| 20 | + ``` | ||
| 21 | + | ||
| 22 | + Un autre nom de variable : `apiKeyEnv: MA_CLE_PASSERELLE`. | ||
| 23 | + | ||
| 24 | +3. Lancez mm comme d'habitude (`mm agent.yaml`, `mm -tui agent.yaml`, `mm -acp`). Vérifié avec l'adresse OpenAI de llmman utilisée comme serveur générique : la sonde de démarrage liste les modèles, et un appel à l'outil `bash` s'exécute : | ||
| 25 | + | ||
| 26 | + ```text | ||
| 27 | + 🛠️ bash: echo hello-from-openai-provider | ||
| 28 | + │ hello-from-openai-provider | ||
| 29 | + 🤖 The command printed: `hello-from-openai-provider` | ||
| 30 | + ``` | ||
| 31 | + | ||
| 32 | +`mm init --provider openai --base-url <adresse>` écrit ce fichier pour vous (voir [Créer un agent avec `mm init`](create-an-agent.md)). | ||
| 33 | + | ||
| 34 | +## Variantes | ||
| 35 | + | ||
| 36 | +- **L'API d'OpenAI.** Pas de `baseUrl`, `OPENAI_API_KEY` exportée, un modèle comme `gpt-5-mini`. Ses modèles à raisonnement n'acceptent que la température par défaut et prennent `max_completion_tokens` au lieu de `max_tokens` : écrivez-les dans `sampling`, et retirez une clé que l'API refuse. (Non mesuré dans ce dépôt.) | ||
| 37 | +- **La clé est refusée.** L'avertissement de démarrage indique `openai: <baseUrl> refused the key (HTTP 401) — export OPENAI_API_KEY`. | ||
| 38 | +- **Rien ne répond.** L'avertissement indique `openai: nothing answers at <baseUrl> — check baseUrl: …` : l'adresse doit être celle compatible OpenAI, qui finit généralement par `/v1`. | ||
| 39 | +- **Un serveur pour lequel mm a un fournisseur.** Préférez-le (`dmr`, `llamacpp`, `llmman`, `ollama`) : ceux-là savent comment le serveur lit un long prompt, coupent le raisonnement pour un résumé, déchargent un modèle et donnent la taille de la fenêtre. Le fournisseur générique ne fait rien de tout cela. | ||
| 40 | + | ||
| 41 | +## Voir aussi | ||
| 42 | + | ||
| 43 | +- [Référence de la configuration — valeurs par défaut des fournisseurs](../reference/configuration.md#valeurs-par-défaut-des-fournisseurs) : ce que `openai` envoie et n'envoie pas | ||
| 44 | +- [Les fournisseurs — explication](../explanation/providers.md) | ||
modified
docs/fr/reference/cli.md +32 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
docs/fr/reference/configuration.md +4 -1 | @@ -6,7 +6,7 @@ | ||
| 6 | 6 | |
| 7 | 7 | | Clé | Type | Défaut | Description | |
| 8 | 8 | |-----|------|--------|-------------| |
| 9 | -| `provider` | chaîne | `dmr` | Clé du registre du serveur LLM : `dmr`, `llamacpp`, `llmman` ou `ollama`. Surchargée par `AGENT_PROVIDER`. | | |
| 9 | +| `provider` | chaîne | `dmr` | Clé du registre du serveur LLM : `dmr`, `llamacpp`, `llmman`, `ollama`, ou `openai` pour tout autre serveur compatible OpenAI (voir [Utiliser n'importe quel serveur compatible OpenAI](../how-to/run-with-an-openai-compatible-server.md)). Surchargée par `AGENT_PROVIDER`. | | |
| 10 | 10 | | `model` | chaîne | `huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M` | Identifiant du modèle dans la nomenclature du fournisseur. Surchargé par `AGENT_MODEL`. | |
| 11 | 11 | | `baseUrl` | chaîne | `""` (défaut du fournisseur) | Point d'accès compatible OpenAI essayé en premier. Surchargé par `AGENT_BASE_URL`. | |
| 12 | 12 | | `fallback` | chaîne ou absente | absente (défaut du fournisseur) | Point d'accès utilisé quand `baseUrl` ne répond pas sur `/models` en 2 s. Absente = défaut du fournisseur ; `""` = pas de repli. | |
| @@ -177,6 +177,9 @@ tools: | ||
| 177 | 177 | | `llamacpp` | `http://127.0.0.1:8080/v1` | aucun | `LLAMA_API_KEY` | non | |
| 178 | 178 | | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | non | |
| 179 | 179 | | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | non | |
| 180 | +| `openai` | `https://api.openai.com/v1` | aucun | `OPENAI_API_KEY` | non — un serveur qui en exige une répond 401, et l'avertissement de démarrage nomme la variable | | |
| 181 | + | |
| 182 | +Le fournisseur `openai` n'envoie que des champs standard : pas de `return_progress` (donc pas de progression pendant la lecture d'un long prompt), pas d'interrupteur de raisonnement sur une requête de résumé, pas de `/unload`. Il ne peut pas demander sa fenêtre au serveur : renseignez `contextWindow`, sinon la compression compte les messages (`context.maxMessages`). Sa sonde de démarrage envoie la clé à `GET /models` ; un 401 ou un 403 est signalé comme une clé refusée, pas comme un serveur qui ne répond pas. | |
| 180 | 183 | |
| 181 | 184 | ## `structuredOutput` |
| 182 | 185 | |
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | | Clé | Type | Défaut | Description | | 7 | | Clé | Type | Défaut | Description | |
| 8 | |-----|------|--------|-------------| | 8 | |-----|------|--------|-------------| |
| 9 | -| `provider` | chaîne | `dmr` | Clé du registre du serveur LLM : `dmr`, `llamacpp`, `llmman` ou `ollama`. Surchargée par `AGENT_PROVIDER`. | | 9 | +| `provider` | chaîne | `dmr` | Clé du registre du serveur LLM : `dmr`, `llamacpp`, `llmman`, `ollama`, ou `openai` pour tout autre serveur compatible OpenAI (voir [Utiliser n'importe quel serveur compatible OpenAI](../how-to/run-with-an-openai-compatible-server.md)). Surchargée par `AGENT_PROVIDER`. | |
| 10 | | `model` | chaîne | `huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M` | Identifiant du modèle dans la nomenclature du fournisseur. Surchargé par `AGENT_MODEL`. | | 10 | | `model` | chaîne | `huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M` | Identifiant du modèle dans la nomenclature du fournisseur. Surchargé par `AGENT_MODEL`. | |
| 11 | | `baseUrl` | chaîne | `""` (défaut du fournisseur) | Point d'accès compatible OpenAI essayé en premier. Surchargé par `AGENT_BASE_URL`. | | 11 | | `baseUrl` | chaîne | `""` (défaut du fournisseur) | Point d'accès compatible OpenAI essayé en premier. Surchargé par `AGENT_BASE_URL`. | |
| 12 | | `fallback` | chaîne ou absente | absente (défaut du fournisseur) | Point d'accès utilisé quand `baseUrl` ne répond pas sur `/models` en 2 s. Absente = défaut du fournisseur ; `""` = pas de repli. | | 12 | | `fallback` | chaîne ou absente | absente (défaut du fournisseur) | Point d'accès utilisé quand `baseUrl` ne répond pas sur `/models` en 2 s. Absente = défaut du fournisseur ; `""` = pas de repli. | |
| @@ -177,6 +177,9 @@ tools: | |||
| 177 | | `llamacpp` | `http://127.0.0.1:8080/v1` | aucun | `LLAMA_API_KEY` | non | | 177 | | `llamacpp` | `http://127.0.0.1:8080/v1` | aucun | `LLAMA_API_KEY` | non | |
| 178 | | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | non | | 178 | | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | non | |
| 179 | | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | non | | 179 | | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | non | |
| 180 | +| `openai` | `https://api.openai.com/v1` | aucun | `OPENAI_API_KEY` | non — un serveur qui en exige une répond 401, et l'avertissement de démarrage nomme la variable | | ||
| 181 | + | ||
| 182 | +Le fournisseur `openai` n'envoie que des champs standard : pas de `return_progress` (donc pas de progression pendant la lecture d'un long prompt), pas d'interrupteur de raisonnement sur une requête de résumé, pas de `/unload`. Il ne peut pas demander sa fenêtre au serveur : renseignez `contextWindow`, sinon la compression compte les messages (`context.maxMessages`). Sa sonde de démarrage envoie la clé à `GET /models` ; un 401 ou un 403 est signalé comme une clé refusée, pas comme un serveur qui ne répond pas. | ||
| 180 | 183 | ||
| 181 | ## `structuredOutput` | 184 | ## `structuredOutput` |
| 182 | 185 | ||
modified
guides/raccourcis-clavier-tui.md +15 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
guides/tui-keyboard-shortcuts.md +15 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
init_assemble_test.go +50 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/decide.go +264 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/decide_test.go +155 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/facts.go +242 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/facts_test.go +114 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/flow.go +365 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/flow_test.go +70 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/presets.go +165 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/presets.yaml +284 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/presets_test.go +59 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/render.go +147 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/wizard.go +299 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/agentinit/wizard_test.go +114 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/engine/openai.go +76 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/engine/openai_test.go +85 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
internal/engine/provider_test.go +2 -2 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/tui/initwin.go +384 -0 Large diff collapsed to keep the page fast — load it when you need it.
added
internal/tui/initwin_test.go +164 -0 Large diff collapsed to keep the page fast — load it when you need it.
modified
internal/version/about.go +1 -1 | @@ -29,7 +29,7 @@ func About() string { | ||
| 29 | 29 | b.WriteString("Built-in tools: bash, read_file, write_file, edit_file, read_skill, plan, ask_user, unload_model;\n") |
| 30 | 30 | b.WriteString(" when the config turns them on: lsp, fetch_content, ask_agent, save_answer, search_memory, search_docs.\n") |
| 31 | 31 | b.WriteString(" Plus the agent file's own tools (tools:) and MCP servers' tools.\n") |
| 32 | - b.WriteString("Model servers: Docker Model Runner, llmman, Ollama, llama.cpp — anything speaking the OpenAI API.\n\n") | |
| 32 | + b.WriteString("Model servers: Docker Model Runner, llmman, Ollama, llama.cpp, and any other OpenAI-compatible one (provider openai).\n\n") | |
| 33 | 33 | fmt.Fprintf(&b, "%s\n", Home) |
| 34 | 34 | b.WriteString("Docs: docs/en (English), docs/fr (français) · mm -h for the flags") |
| 35 | 35 | return b.String() |
| @@ -29,7 +29,7 @@ func About() string { | |||
| 29 | b.WriteString("Built-in tools: bash, read_file, write_file, edit_file, read_skill, plan, ask_user, unload_model;\n") | 29 | b.WriteString("Built-in tools: bash, read_file, write_file, edit_file, read_skill, plan, ask_user, unload_model;\n") |
| 30 | b.WriteString(" when the config turns them on: lsp, fetch_content, ask_agent, save_answer, search_memory, search_docs.\n") | 30 | b.WriteString(" when the config turns them on: lsp, fetch_content, ask_agent, save_answer, search_memory, search_docs.\n") |
| 31 | b.WriteString(" Plus the agent file's own tools (tools:) and MCP servers' tools.\n") | 31 | b.WriteString(" Plus the agent file's own tools (tools:) and MCP servers' tools.\n") |
| 32 | - b.WriteString("Model servers: Docker Model Runner, llmman, Ollama, llama.cpp — anything speaking the OpenAI API.\n\n") | 32 | + b.WriteString("Model servers: Docker Model Runner, llmman, Ollama, llama.cpp, and any other OpenAI-compatible one (provider openai).\n\n") |
| 33 | fmt.Fprintf(&b, "%s\n", Home) | 33 | fmt.Fprintf(&b, "%s\n", Home) |
| 34 | b.WriteString("Docs: docs/en (English), docs/fr (français) · mm -h for the flags") | 34 | b.WriteString("Docs: docs/en (English), docs/fr (français) · mm -h for the flags") |
| 35 | return b.String() | 35 | return b.String() |
modified
main.go +15 -0 Large diff collapsed to keep the page fast — load it when you need it.