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

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

Download ZIP

Merge feature/llamacpp-fallback into main

rickub committed 2026-11-14T18:50:47Z Browse files
f81c3b6 parents: 9e1b913 86f68f8
modified .tickets/issues/0210-acp-create-mode-mm-acp-create-mm-init-from-an-acp.yaml +2 -2
@@ -175,6 +175,8 @@ tasks:
175175 name: k33g
176176 email: ph.charriere@gmail.com
177177 createdAt: 2026-11-14T05:41:20.000Z
178+ updatedAt: 2026-11-14T05:56:48.000Z
179+ closedAt: 2026-11-14T05:56:48.000Z
178180 comments:
179181 - id: 1
180182 author:
@@ -194,8 +196,6 @@ comments:
194196 client by hand), the acceptance "tried in two real clients",
195197 permission buttons for choices in conversation mode, and session
196198 config options. qlty not run (not installed in this sandbox).
197- updatedAt: 2026-11-14T05:56:48.000Z
198- closedAt: 2026-11-14T05:56:48.000Z
199199 - id: 2
200200 author:
201201 name: k33g
@@ -175,6 +175,8 @@ tasks:
175 name: k33g175 name: k33g
176 email: ph.charriere@gmail.com176 email: ph.charriere@gmail.com
177 createdAt: 2026-11-14T05:41:20.000Z177 createdAt: 2026-11-14T05:41:20.000Z
178+ updatedAt: 2026-11-14T05:56:48.000Z
179+ closedAt: 2026-11-14T05:56:48.000Z
178 comments:180 comments:
179 - id: 1181 - id: 1
180 author:182 author:
@@ -194,8 +196,6 @@ comments:
194 client by hand), the acceptance "tried in two real clients",196 client by hand), the acceptance "tried in two real clients",
195 permission buttons for choices in conversation mode, and session197 permission buttons for choices in conversation mode, and session
196 config options. qlty not run (not installed in this sandbox).198 config options. qlty not run (not installed in this sandbox).
197- updatedAt: 2026-11-14T05:56:48.000Z
198- closedAt: 2026-11-14T05:56:48.000Z
199 - id: 2199 - id: 2
200 author:200 author:
201 name: k33g201 name: k33g
modified .tickets/issues/0211-check-if-llamacpp-1-0-0-is-working.yaml +2 -2
@@ -6,9 +6,9 @@ author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-11-14T05:56:02.153Z
9-updatedAt: 2026-11-14T06:35:10.000Z
9+updatedAt: 2026-11-14T18:45:26.000Z
1010 labels: []
11-milestone: v1.1.0
11+milestone: v2.0.0
1212 epic: Providers (LLM Engine)
1313 body: ""
1414 tasks: []
@@ -6,9 +6,9 @@ author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-11-14T05:56:02.153Z8 createdAt: 2026-11-14T05:56:02.153Z
9-updatedAt: 2026-11-14T06:35:10.000Z9+updatedAt: 2026-11-14T18:45:26.000Z
10 labels: []10 labels: []
11-milestone: v1.1.011+milestone: v2.0.0
12 epic: Providers (LLM Engine)12 epic: Providers (LLM Engine)
13 body: ""13 body: ""
14 tasks: []14 tasks: []
modified .tickets/issues/0212-mm-dockerinit-know-the-mm-folder-project-layout.yaml +2 -2
@@ -137,6 +137,8 @@ tasks:
137137 name: k33g
138138 email: ph.charriere@gmail.com
139139 createdAt: 2026-11-14T06:29:41.000Z
140+ updatedAt: 2026-11-14T06:37:57.000Z
141+ closedAt: 2026-11-14T06:37:57.000Z
140142 comments:
141143 - id: 1
142144 author:
@@ -159,8 +161,6 @@ comments:
159161 Also asked in the same session: `mm sbxinit` now prints
160162 `Run the sandbox <name>: sbx env run --force` (and the line in the
161163 sbxenv.yaml comments).
162- updatedAt: 2026-11-14T06:37:57.000Z
163- closedAt: 2026-11-14T06:37:57.000Z
164164 - id: 2
165165 author:
166166 name: k33g
@@ -137,6 +137,8 @@ tasks:
137 name: k33g137 name: k33g
138 email: ph.charriere@gmail.com138 email: ph.charriere@gmail.com
139 createdAt: 2026-11-14T06:29:41.000Z139 createdAt: 2026-11-14T06:29:41.000Z
140+ updatedAt: 2026-11-14T06:37:57.000Z
141+ closedAt: 2026-11-14T06:37:57.000Z
140 comments:142 comments:
141 - id: 1143 - id: 1
142 author:144 author:
@@ -159,8 +161,6 @@ comments:
159 Also asked in the same session: `mm sbxinit` now prints161 Also asked in the same session: `mm sbxinit` now prints
160 `Run the sandbox <name>: sbx env run --force` (and the line in the162 `Run the sandbox <name>: sbx env run --force` (and the line in the
161 sbxenv.yaml comments).163 sbxenv.yaml comments).
162- updatedAt: 2026-11-14T06:37:57.000Z
163- closedAt: 2026-11-14T06:37:57.000Z
164 - id: 2164 - id: 2
165 author:165 author:
166 name: k33g166 name: k33g
modified .tickets/issues/0214-mm-acp-create-start-ollama-models-are-listed-fro.yaml +63 -7
@@ -1,12 +1,12 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
22 id: 214
33 title: "mm acp-create (/start): Ollama models are listed from the container address instead of the local one"
4-state: open
4+state: closed
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-11-14T07:40:50.000Z
9-updatedAt: 2026-11-14T07:47:59.000Z
9+updatedAt: 2026-11-14T18:14:17.000Z
1010 labels:
1111 - bug
1212 - kind::bug
@@ -76,44 +76,54 @@ body: |
7676 tasks:
7777 - id: 1
7878 title: Reproduce - mm acp-create from Zed and mm init in a terminal, Ollama on the host, note the address used
79- state: open
79+ state: closed
8080 priority: high
8181 author:
8282 name: k33g
8383 email: ph.charriere@gmail.com
8484 createdAt: 2026-11-14T07:40:50.000Z
85+ updatedAt: 2026-11-14T18:14:17.000Z
86+ closedAt: 2026-11-14T18:14:17.000Z
8587 - id: 2
8688 title: Find why the local address is not taken (probe timeout, localhost vs 127.0.0.1 / IPv6, environment of the editor's process)
87- state: open
89+ state: closed
8890 priority: high
8991 author:
9092 name: k33g
9193 email: ph.charriere@gmail.com
9294 createdAt: 2026-11-14T07:40:50.000Z
95+ updatedAt: 2026-11-14T18:14:17.000Z
96+ closedAt: 2026-11-14T18:14:17.000Z
9397 - id: 3
9498 title: Fix - the wizard lists the models from the local address when mm is not in a container
95- state: open
99+ state: closed
96100 priority: high
97101 author:
98102 name: k33g
99103 email: ph.charriere@gmail.com
100104 createdAt: 2026-11-14T07:40:50.000Z
105+ updatedAt: 2026-11-14T17:54:42.000Z
106+ closedAt: 2026-11-14T17:54:42.000Z
101107 - id: 4
102108 title: Show the address the models were listed from in the model question (both modes)
103- state: open
109+ state: closed
104110 priority: medium
105111 author:
106112 name: k33g
107113 email: ph.charriere@gmail.com
108114 createdAt: 2026-11-14T07:40:50.000Z
115+ updatedAt: 2026-11-14T17:54:42.000Z
116+ closedAt: 2026-11-14T17:54:42.000Z
109117 - id: 5
110118 title: Tests - a local server answering slowly or only on 127.0.0.1 keeps the local address
111- state: open
119+ state: closed
112120 priority: medium
113121 author:
114122 name: k33g
115123 email: ph.charriere@gmail.com
116124 createdAt: 2026-11-14T07:40:50.000Z
125+ updatedAt: 2026-11-14T17:54:42.000Z
126+ closedAt: 2026-11-14T17:54:42.000Z
117127 comments:
118128 - id: 1
119129 author:
@@ -128,3 +138,49 @@ comments:
128138 it: look at what is specific to Ollama — its `/v1/models` answering
129139 later than 2 s or not 200, Ollama listening on IPv4 only while DMR
130140 answers on both, or `OLLAMA_HOST` on the user's machine.
141+ - id: 2
142+ author:
143+ name: k33g
144+ email: ph.charriere@gmail.com
145+ createdAt: 2026-11-14T17:54:42.000Z
146+ body: |
147+ Fixed on `fix/wizard-local-address` (uncommitted), without waiting for
148+ the exact cause on the user's machine: the fix covers hypotheses 1
149+ (slow probe), 2 (IPv4 only) and 4 (Docker Desktop resolving
150+ host.docker.internal on the host, which hid the failed probe).
151+
152+ - The wizard (mm init and mm acp-create) no longer takes the engine's
153+ resolution (2 s probe of `/models`, then a silent switch to the
154+ container fallback). `resolveBase` → `AGENT_BASE_URL` (or the
155+ legacy variable) when set; else the first local address whose model
156+ list answers (the provider's own list endpoint, `/api/tags` for
157+ Ollama, 5 s): the default, then the same with `127.0.0.1` when it
158+ names `localhost`; the fallback only when none answers; a provider
159+ without a fallback is not probed. `engine.EnvBaseURL` added.
160+ - The model question names the address: `Model? (listed from …)`.
161+ - The written file is unchanged (no `baseUrl` for the default).
162+ - Runtime (`mm acp` with the written file) still uses the engine's
163+ resolution — not touched here.
164+
165+ Tests: `TestChooseBasePrefersALocalAddress`, `TestLocalAddresses`,
166+ `TestResolveBaseKeepsASlowLocalServer` (a server whose `/v1/models`
167+ takes 3 s: the engine's probe takes the fallback, the wizard keeps the
168+ local address), `TestResolveBaseHonoursAgentBaseURL`.
169+
170+ End to end, real binary, `mm acp-create --provider ollama`, a fake
171+ Ollama on 127.0.0.1:11434 whose `/v1/models` takes 3 s: before →
172+ `Model ID? (no list from http://host.docker.internal:11434/v1 …)`;
173+ after → `Model? (listed from http://localhost:11434/v1)`.
174+
175+ Not done: tasks 1 and 2 (reproduce on the user's Mac with the real
176+ Ollama, and name the exact cause) — the curl checks given in the
177+ conversation would tell.
178+ - id: 3
179+ author:
180+ name: k33g
181+ email: ph.charriere@gmail.com
182+ createdAt: 2026-11-14T18:14:17.000Z
183+ body: |
184+ Tested by the user with the real Ollama: it works (local models
185+ listed). Closed. The exact cause on the user's machine was not named
186+ (tasks 1–2 closed with the user's test as the reproduction).
@@ -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: 2142 id: 214
3 title: "mm acp-create (/start): Ollama models are listed from the container address instead of the local one"3 title: "mm acp-create (/start): Ollama models are listed from the container address instead of the local one"
4-state: open4+state: closed
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-11-14T07:40:50.000Z8 createdAt: 2026-11-14T07:40:50.000Z
9-updatedAt: 2026-11-14T07:47:59.000Z9+updatedAt: 2026-11-14T18:14:17.000Z
10 labels:10 labels:
11 - bug11 - bug
12 - kind::bug12 - kind::bug
@@ -76,44 +76,54 @@ body: |
76 tasks:76 tasks:
77 - id: 177 - id: 1
78 title: Reproduce - mm acp-create from Zed and mm init in a terminal, Ollama on the host, note the address used78 title: Reproduce - mm acp-create from Zed and mm init in a terminal, Ollama on the host, note the address used
79- state: open79+ state: closed
80 priority: high80 priority: high
81 author:81 author:
82 name: k33g82 name: k33g
83 email: ph.charriere@gmail.com83 email: ph.charriere@gmail.com
84 createdAt: 2026-11-14T07:40:50.000Z84 createdAt: 2026-11-14T07:40:50.000Z
85+ updatedAt: 2026-11-14T18:14:17.000Z
86+ closedAt: 2026-11-14T18:14:17.000Z
85 - id: 287 - id: 2
86 title: Find why the local address is not taken (probe timeout, localhost vs 127.0.0.1 / IPv6, environment of the editor's process)88 title: Find why the local address is not taken (probe timeout, localhost vs 127.0.0.1 / IPv6, environment of the editor's process)
87- state: open89+ state: closed
88 priority: high90 priority: high
89 author:91 author:
90 name: k33g92 name: k33g
91 email: ph.charriere@gmail.com93 email: ph.charriere@gmail.com
92 createdAt: 2026-11-14T07:40:50.000Z94 createdAt: 2026-11-14T07:40:50.000Z
95+ updatedAt: 2026-11-14T18:14:17.000Z
96+ closedAt: 2026-11-14T18:14:17.000Z
93 - id: 397 - id: 3
94 title: Fix - the wizard lists the models from the local address when mm is not in a container98 title: Fix - the wizard lists the models from the local address when mm is not in a container
95- state: open99+ state: closed
96 priority: high100 priority: high
97 author:101 author:
98 name: k33g102 name: k33g
99 email: ph.charriere@gmail.com103 email: ph.charriere@gmail.com
100 createdAt: 2026-11-14T07:40:50.000Z104 createdAt: 2026-11-14T07:40:50.000Z
105+ updatedAt: 2026-11-14T17:54:42.000Z
106+ closedAt: 2026-11-14T17:54:42.000Z
101 - id: 4107 - id: 4
102 title: Show the address the models were listed from in the model question (both modes)108 title: Show the address the models were listed from in the model question (both modes)
103- state: open109+ state: closed
104 priority: medium110 priority: medium
105 author:111 author:
106 name: k33g112 name: k33g
107 email: ph.charriere@gmail.com113 email: ph.charriere@gmail.com
108 createdAt: 2026-11-14T07:40:50.000Z114 createdAt: 2026-11-14T07:40:50.000Z
115+ updatedAt: 2026-11-14T17:54:42.000Z
116+ closedAt: 2026-11-14T17:54:42.000Z
109 - id: 5117 - id: 5
110 title: Tests - a local server answering slowly or only on 127.0.0.1 keeps the local address118 title: Tests - a local server answering slowly or only on 127.0.0.1 keeps the local address
111- state: open119+ state: closed
112 priority: medium120 priority: medium
113 author:121 author:
114 name: k33g122 name: k33g
115 email: ph.charriere@gmail.com123 email: ph.charriere@gmail.com
116 createdAt: 2026-11-14T07:40:50.000Z124 createdAt: 2026-11-14T07:40:50.000Z
125+ updatedAt: 2026-11-14T17:54:42.000Z
126+ closedAt: 2026-11-14T17:54:42.000Z
117 comments:127 comments:
118 - id: 1128 - id: 1
119 author:129 author:
@@ -128,3 +138,49 @@ comments:
128 it: look at what is specific to Ollama — its `/v1/models` answering138 it: look at what is specific to Ollama — its `/v1/models` answering
129 later than 2 s or not 200, Ollama listening on IPv4 only while DMR139 later than 2 s or not 200, Ollama listening on IPv4 only while DMR
130 answers on both, or `OLLAMA_HOST` on the user's machine.140 answers on both, or `OLLAMA_HOST` on the user's machine.
141+ - id: 2
142+ author:
143+ name: k33g
144+ email: ph.charriere@gmail.com
145+ createdAt: 2026-11-14T17:54:42.000Z
146+ body: |
147+ Fixed on `fix/wizard-local-address` (uncommitted), without waiting for
148+ the exact cause on the user's machine: the fix covers hypotheses 1
149+ (slow probe), 2 (IPv4 only) and 4 (Docker Desktop resolving
150+ host.docker.internal on the host, which hid the failed probe).
151+
152+ - The wizard (mm init and mm acp-create) no longer takes the engine's
153+ resolution (2 s probe of `/models`, then a silent switch to the
154+ container fallback). `resolveBase` → `AGENT_BASE_URL` (or the
155+ legacy variable) when set; else the first local address whose model
156+ list answers (the provider's own list endpoint, `/api/tags` for
157+ Ollama, 5 s): the default, then the same with `127.0.0.1` when it
158+ names `localhost`; the fallback only when none answers; a provider
159+ without a fallback is not probed. `engine.EnvBaseURL` added.
160+ - The model question names the address: `Model? (listed from …)`.
161+ - The written file is unchanged (no `baseUrl` for the default).
162+ - Runtime (`mm acp` with the written file) still uses the engine's
163+ resolution — not touched here.
164+
165+ Tests: `TestChooseBasePrefersALocalAddress`, `TestLocalAddresses`,
166+ `TestResolveBaseKeepsASlowLocalServer` (a server whose `/v1/models`
167+ takes 3 s: the engine's probe takes the fallback, the wizard keeps the
168+ local address), `TestResolveBaseHonoursAgentBaseURL`.
169+
170+ End to end, real binary, `mm acp-create --provider ollama`, a fake
171+ Ollama on 127.0.0.1:11434 whose `/v1/models` takes 3 s: before →
172+ `Model ID? (no list from http://host.docker.internal:11434/v1 …)`;
173+ after → `Model? (listed from http://localhost:11434/v1)`.
174+
175+ Not done: tasks 1 and 2 (reproduce on the user's Mac with the real
176+ Ollama, and name the exact cause) — the curl checks given in the
177+ conversation would tell.
178+ - id: 3
179+ author:
180+ name: k33g
181+ email: ph.charriere@gmail.com
182+ createdAt: 2026-11-14T18:14:17.000Z
183+ body: |
184+ Tested by the user with the real Ollama: it works (local models
185+ listed). Closed. The exact cause on the user's machine was not named
186+ (tasks 1–2 closed with the user's test as the reproduction).
modified .tickets/issues/0215-mm-acp-create-start-test-every-provider-address.yaml +34 -5
@@ -1,12 +1,12 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
22 id: 215
33 title: "mm acp-create (/start): test every provider - address used and model list"
4-state: open
4+state: closed
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-11-14T07:41:16.000Z
9-updatedAt: 2026-11-14T08:07:53.000Z
9+updatedAt: 2026-11-14T18:45:13.000Z
1010 labels:
1111 - kind::chore
1212 - To be tested
@@ -79,12 +79,14 @@ tasks:
7979 closedAt: 2026-11-14T07:47:59.000Z
8080 - id: 3
8181 title: llamacpp - llama-server on 127.0.0.1:8080
82- state: open
82+ state: closed
8383 priority: medium
8484 author:
8585 name: k33g
8686 email: ph.charriere@gmail.com
8787 createdAt: 2026-11-14T07:41:16.000Z
88+ updatedAt: 2026-11-14T18:24:44.000Z
89+ closedAt: 2026-11-14T18:24:44.000Z
8890 - id: 4
8991 title: kronk
9092 state: closed
@@ -107,20 +109,24 @@ tasks:
107109 closedAt: 2026-11-14T08:07:53.000Z
108110 - id: 6
109111 title: Same checks with mm in a container or a Docker Sandbox (the fallback must be taken there)
110- state: open
112+ state: closed
111113 priority: medium
112114 author:
113115 name: k33g
114116 email: ph.charriere@gmail.com
115117 createdAt: 2026-11-14T07:41:16.000Z
118+ updatedAt: 2026-11-14T18:45:13.000Z
119+ closedAt: 2026-11-14T18:45:13.000Z
116120 - id: 7
117121 title: Write the results in a comment (version, client, address used, list ok or not); a ticket per bug found
118- state: open
122+ state: closed
119123 priority: low
120124 author:
121125 name: k33g
122126 email: ph.charriere@gmail.com
123127 createdAt: 2026-11-14T07:41:16.000Z
128+ updatedAt: 2026-11-14T18:45:13.000Z
129+ closedAt: 2026-11-14T18:45:13.000Z
124130 comments:
125131 - id: 1
126132 author:
@@ -148,3 +154,26 @@ comments:
148154 body: |
149155 User (2026-11-14): **openai works** too. Still to try: llamacpp, and
150156 inside a container / sandbox.
157+ - id: 4
158+ author:
159+ name: k33g
160+ email: ph.charriere@gmail.com
161+ createdAt: 2026-11-14T18:24:44.000Z
162+ body: |
163+ User (2026-11-14): **llamacpp works** too. Every provider now checked
164+ on the host: dmr, llmman, kronk, openai, llamacpp, and ollama after
165+ the fix of #214. Still to try: inside a container / Docker Sandbox
166+ (task 6).
167+ - id: 5
168+ author:
169+ name: k33g
170+ email: ph.charriere@gmail.com
171+ createdAt: 2026-11-14T18:45:13.000Z
172+ body: |
173+ Closed at the user's request. Summary: on the host, every provider
174+ lists its models in `/start` (dmr, llmman, kronk, openai, llamacpp;
175+ ollama after #214). In a container, the fallback works for ollama and
176+ llmman; llamacpp had none — added by #217 (on a branch, not in a
177+ release yet: a container built by `mm dockerinit` runs the latest
178+ release, v1.0.9, which does not have it). Docker Sandbox not tried.
179+
@@ -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: 2152 id: 215
3 title: "mm acp-create (/start): test every provider - address used and model list"3 title: "mm acp-create (/start): test every provider - address used and model list"
4-state: open4+state: closed
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-11-14T07:41:16.000Z8 createdAt: 2026-11-14T07:41:16.000Z
9-updatedAt: 2026-11-14T08:07:53.000Z9+updatedAt: 2026-11-14T18:45:13.000Z
10 labels:10 labels:
11 - kind::chore11 - kind::chore
12 - To be tested12 - To be tested
@@ -79,12 +79,14 @@ tasks:
79 closedAt: 2026-11-14T07:47:59.000Z79 closedAt: 2026-11-14T07:47:59.000Z
80 - id: 380 - id: 3
81 title: llamacpp - llama-server on 127.0.0.1:808081 title: llamacpp - llama-server on 127.0.0.1:8080
82- state: open82+ state: closed
83 priority: medium83 priority: medium
84 author:84 author:
85 name: k33g85 name: k33g
86 email: ph.charriere@gmail.com86 email: ph.charriere@gmail.com
87 createdAt: 2026-11-14T07:41:16.000Z87 createdAt: 2026-11-14T07:41:16.000Z
88+ updatedAt: 2026-11-14T18:24:44.000Z
89+ closedAt: 2026-11-14T18:24:44.000Z
88 - id: 490 - id: 4
89 title: kronk91 title: kronk
90 state: closed92 state: closed
@@ -107,20 +109,24 @@ tasks:
107 closedAt: 2026-11-14T08:07:53.000Z109 closedAt: 2026-11-14T08:07:53.000Z
108 - id: 6110 - id: 6
109 title: Same checks with mm in a container or a Docker Sandbox (the fallback must be taken there)111 title: Same checks with mm in a container or a Docker Sandbox (the fallback must be taken there)
110- state: open112+ state: closed
111 priority: medium113 priority: medium
112 author:114 author:
113 name: k33g115 name: k33g
114 email: ph.charriere@gmail.com116 email: ph.charriere@gmail.com
115 createdAt: 2026-11-14T07:41:16.000Z117 createdAt: 2026-11-14T07:41:16.000Z
118+ updatedAt: 2026-11-14T18:45:13.000Z
119+ closedAt: 2026-11-14T18:45:13.000Z
116 - id: 7120 - id: 7
117 title: Write the results in a comment (version, client, address used, list ok or not); a ticket per bug found121 title: Write the results in a comment (version, client, address used, list ok or not); a ticket per bug found
118- state: open122+ state: closed
119 priority: low123 priority: low
120 author:124 author:
121 name: k33g125 name: k33g
122 email: ph.charriere@gmail.com126 email: ph.charriere@gmail.com
123 createdAt: 2026-11-14T07:41:16.000Z127 createdAt: 2026-11-14T07:41:16.000Z
128+ updatedAt: 2026-11-14T18:45:13.000Z
129+ closedAt: 2026-11-14T18:45:13.000Z
124 comments:130 comments:
125 - id: 1131 - id: 1
126 author:132 author:
@@ -148,3 +154,26 @@ comments:
148 body: |154 body: |
149 User (2026-11-14): **openai works** too. Still to try: llamacpp, and155 User (2026-11-14): **openai works** too. Still to try: llamacpp, and
150 inside a container / sandbox.156 inside a container / sandbox.
157+ - id: 4
158+ author:
159+ name: k33g
160+ email: ph.charriere@gmail.com
161+ createdAt: 2026-11-14T18:24:44.000Z
162+ body: |
163+ User (2026-11-14): **llamacpp works** too. Every provider now checked
164+ on the host: dmr, llmman, kronk, openai, llamacpp, and ollama after
165+ the fix of #214. Still to try: inside a container / Docker Sandbox
166+ (task 6).
167+ - id: 5
168+ author:
169+ name: k33g
170+ email: ph.charriere@gmail.com
171+ createdAt: 2026-11-14T18:45:13.000Z
172+ body: |
173+ Closed at the user's request. Summary: on the host, every provider
174+ lists its models in `/start` (dmr, llmman, kronk, openai, llamacpp;
175+ ollama after #214). In a container, the fallback works for ollama and
176+ llmman; llamacpp had none — added by #217 (on a branch, not in a
177+ release yet: a container built by `mm dockerinit` runs the latest
178+ release, v1.0.9, which does not have it). Docker Sandbox not tried.
179+
modified .tickets/issues/0216-mm-dockerinit-i-have-no-name-in-the-container-th.yaml +11 -4
@@ -1,12 +1,12 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
22 id: 216
33 title: "mm dockerinit: \"I have no name!\" in the container - the mm account has uid 1000, compose runs as the user's uid"
4-state: open
4+state: closed
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-11-14T17:31:27.000Z
9-updatedAt: 2026-11-14T17:35:14.000Z
9+updatedAt: 2026-11-14T17:50:32.000Z
1010 labels:
1111 - bug
1212 - kind::bug
@@ -143,6 +143,8 @@ tasks:
143143 name: k33g
144144 email: ph.charriere@gmail.com
145145 createdAt: 2026-11-14T17:31:27.000Z
146+ updatedAt: 2026-11-14T17:35:14.000Z
147+ closedAt: 2026-11-14T17:35:14.000Z
146148 comments:
147149 - id: 1
148150 author:
@@ -170,5 +172,10 @@ comments:
170172 identity. Unrelated to the fix — the docs say to set `user.name` /
171173 `user.email` or the `GIT_*` variables. Not tried: `mm tui` in the
172174 container (no terminal here), ssh, Docker Desktop on macOS.
173- updatedAt: 2026-11-14T17:35:14.000Z
174- closedAt: 2026-11-14T17:35:14.000Z
175+ - id: 2
176+ author:
177+ name: k33g
178+ email: ph.charriere@gmail.com
179+ createdAt: 2026-11-14T17:50:32.000Z
180+ body: |
181+ Closed at the user's request.
@@ -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: 2162 id: 216
3 title: "mm dockerinit: \"I have no name!\" in the container - the mm account has uid 1000, compose runs as the user's uid"3 title: "mm dockerinit: \"I have no name!\" in the container - the mm account has uid 1000, compose runs as the user's uid"
4-state: open4+state: closed
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-11-14T17:31:27.000Z8 createdAt: 2026-11-14T17:31:27.000Z
9-updatedAt: 2026-11-14T17:35:14.000Z9+updatedAt: 2026-11-14T17:50:32.000Z
10 labels:10 labels:
11 - bug11 - bug
12 - kind::bug12 - kind::bug
@@ -143,6 +143,8 @@ tasks:
143 name: k33g143 name: k33g
144 email: ph.charriere@gmail.com144 email: ph.charriere@gmail.com
145 createdAt: 2026-11-14T17:31:27.000Z145 createdAt: 2026-11-14T17:31:27.000Z
146+ updatedAt: 2026-11-14T17:35:14.000Z
147+ closedAt: 2026-11-14T17:35:14.000Z
146 comments:148 comments:
147 - id: 1149 - id: 1
148 author:150 author:
@@ -170,5 +172,10 @@ comments:
170 identity. Unrelated to the fix — the docs say to set `user.name` /172 identity. Unrelated to the fix — the docs say to set `user.name` /
171 `user.email` or the `GIT_*` variables. Not tried: `mm tui` in the173 `user.email` or the `GIT_*` variables. Not tried: `mm tui` in the
172 container (no terminal here), ssh, Docker Desktop on macOS.174 container (no terminal here), ssh, Docker Desktop on macOS.
173- updatedAt: 2026-11-14T17:35:14.000Z175+ - id: 2
174- closedAt: 2026-11-14T17:35:14.000Z176+ author:
177+ name: k33g
178+ email: ph.charriere@gmail.com
179+ createdAt: 2026-11-14T17:50:32.000Z
180+ body: |
181+ Closed at the user's request.
added .tickets/issues/0217-llamacpp-fall-back-on-host-docker-internal-8080.yaml +154 -0
new file mode 100644
@@ -0,0 +1,154 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 217
3+title: "llamacpp: fall back on host.docker.internal:8080 like the other local providers"
4+state: closed
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-11-14T18:36:24.000Z
9+updatedAt: 2026-11-14T18:45:13.000Z
10+labels:
11+ - enhancement
12+ - kind::feature
13+milestone: v1.1.0
14+epic: Providers (LLM Engine)
15+related:
16+ - 215
17+body: |
18+ ## Seen (user, 2026-11-14, while testing #215)
19+
20+ With mm in a container, the fallback address works for **ollama** and
21+ **llmman**, not for **llamacpp**.
22+
23+ ## Why (code read)
24+
25+ 1. **llamacpp declares no fallback** ([internal/engine/openai_compat.go](internal/engine/openai_compat.go)):
26+ dmr, ollama, llmman and kronk fall back on
27+ `http://host.docker.internal:<port>/...` when their default does not
28+ answer; llamacpp only has `http://127.0.0.1:8080/v1`. In a container,
29+ that is the container itself, and nothing else is tried. The container
30+ guide says so ("set `baseUrl: http://host.docker.internal:8080/v1`").
31+ The shipped `agent.llamacpp.yaml` even opts out on purpose
32+ (`fallback: ""`, "llama-server is wherever you started it").
33+ 2. **llama-server listens on `127.0.0.1` by default.** On Linux and in a
34+ Docker Sandbox, `host.docker.internal` is the host's gateway, not its
35+ loopback: start it with `--host 0.0.0.0` (as Kronk needs
36+ `--api-host 0.0.0.0:11435`). On Docker Desktop (Mac) the loopback is
37+ reached anyway (Ollama on 127.0.0.1 works there) — not checked for
38+ llama-server.
39+ 3. **Docker Sandbox: port 8080 is not in the mini-me kit's network
40+ policy** (12434, 11434, 17434 only): `sbx policy allow network
41+ host.docker.internal:8080`, or a change in the kit (other repository,
42+ mini-me-kit) — out of scope here.
43+
44+ ## Change (agreed with the user)
45+
46+ - llamacpp's fallback: `http://host.docker.internal:8080/v1`, the same
47+ rule as the others (taken when the default does not answer `/models`
48+ within 2 s; `fallback: ""` in a file still turns it off).
49+ - Its start hint mentions `--host 0.0.0.0` for mm in a container or a
50+ sandbox.
51+ - `agent.llamacpp.yaml` drops `fallback: ""`, so that a copy of it gets
52+ the fallback. Re-litigates that file's explicit choice — the user asked
53+ for llamacpp to behave like the others. `config.samples/` and
54+ `demos/struggle-signals/` (pinned to a fake server) are left alone.
55+ - `mm init` writes the fallback in the file's comment, as for the others
56+ (ticket 121); the wizard's address choice (#214) now also tries it.
57+
58+ ## Acceptance criteria
59+
60+ - mm in a container, no `baseUrl`, llama-server on the host started with
61+ `--host 0.0.0.0` → mm reaches it through `host.docker.internal:8080`.
62+ - On the host, nothing changes when llama-server answers on 127.0.0.1.
63+ - Tests and docs EN+FR.
64+tasks:
65+ - id: 1
66+ title: Engine - llamacpp falls back on http://host.docker.internal:8080/v1, like the other local providers
67+ state: closed
68+ priority: high
69+ author:
70+ name: k33g
71+ email: ph.charriere@gmail.com
72+ createdAt: 2026-11-14T18:36:24.000Z
73+ updatedAt: 2026-11-14T18:39:34.000Z
74+ closedAt: 2026-11-14T18:39:34.000Z
75+ - id: 2
76+ title: startHint - say --host 0.0.0.0 for mm in a container or a sandbox
77+ state: closed
78+ priority: medium
79+ author:
80+ name: k33g
81+ email: ph.charriere@gmail.com
82+ createdAt: 2026-11-14T18:36:24.000Z
83+ updatedAt: 2026-11-14T18:39:34.000Z
84+ closedAt: 2026-11-14T18:39:34.000Z
85+ - id: 3
86+ title: agent.llamacpp.yaml - drop fallback empty (it opted out on purpose)
87+ state: closed
88+ priority: medium
89+ author:
90+ name: k33g
91+ email: ph.charriere@gmail.com
92+ createdAt: 2026-11-14T18:36:24.000Z
93+ updatedAt: 2026-11-14T18:39:34.000Z
94+ closedAt: 2026-11-14T18:39:34.000Z
95+ - id: 4
96+ title: Tests - provider resolution, mm init's comment, the wizard's address choice
97+ state: closed
98+ priority: medium
99+ author:
100+ name: k33g
101+ email: ph.charriere@gmail.com
102+ createdAt: 2026-11-14T18:36:24.000Z
103+ updatedAt: 2026-11-14T18:39:34.000Z
104+ closedAt: 2026-11-14T18:39:34.000Z
105+ - id: 5
106+ title: Docs EN+FR - configuration (providers table), run-in-a-container, run-with-llama-cpp, sandbox (port 8080 policy)
107+ state: closed
108+ priority: medium
109+ author:
110+ name: k33g
111+ email: ph.charriere@gmail.com
112+ createdAt: 2026-11-14T18:36:24.000Z
113+ updatedAt: 2026-11-14T18:39:34.000Z
114+ closedAt: 2026-11-14T18:39:34.000Z
115+comments:
116+ - id: 1
117+ author:
118+ name: k33g
119+ email: ph.charriere@gmail.com
120+ createdAt: 2026-11-14T18:39:34.000Z
121+ body: |
122+ Implemented on `feature/llamacpp-fallback` (uncommitted).
123+
124+ - Engine: llamacpp's fallback `http://host.docker.internal:8080/v1`;
125+ start hint `… --port 8080 (add --host 0.0.0.0 when mm runs in a
126+ container or a sandbox)`.
127+ - `agent.llamacpp.yaml`: `fallback: ""` removed, the comment says what
128+ the fallback is and how to turn it off. `config.samples/` and
129+ `demos/struggle-signals/` keep their `fallback: ""`.
130+ - Tests updated where they asserted "no fallback"
131+ (`TestResolveURLPrecedence`: falls back when baseUrl is down, keeps
132+ it when up; `TestConfigCompat` pins `fallback: ""`;
133+ `TestDefaultURLs`; `TestRenderRecordsTheDefaultURLs`: mm init now
134+ writes the fallback comment for llamacpp). Whole suite green.
135+ - Docs EN+FR: configuration (providers table, agent.llamacpp.yaml),
136+ mcp-configuration (EN), cli (warning example), run-in-a-container,
137+ run-with-llama-cpp (container / sandbox variant), sandbox guide.
138+
139+ Side effect, same as dmr/ollama/llmman already: on the host with
140+ llama-server down, the start-up warning names the fallback address
141+ (`nothing answers at http://host.docker.internal:8080/v1`).
142+
143+ Not tried with a real llama-server in a container or a sandbox.
144+ - id: 2
145+ author:
146+ name: k33g
147+ email: ph.charriere@gmail.com
148+ createdAt: 2026-11-14T18:45:13.000Z
149+ body: |
150+ Closed at the user's request. mm init writes the fallback comment for
151+ llamacpp (checked by the user). In a container, checked only with
152+ v1.0.9 (the released binary the image downloads), which does not have
153+ the fallback yet: the fix reaches containers with the next release.
154+
new file mode 100644
@@ -0,0 +1,154 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 217
3+title: "llamacpp: fall back on host.docker.internal:8080 like the other local providers"
4+state: closed
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-11-14T18:36:24.000Z
9+updatedAt: 2026-11-14T18:45:13.000Z
10+labels:
11+ - enhancement
12+ - kind::feature
13+milestone: v1.1.0
14+epic: Providers (LLM Engine)
15+related:
16+ - 215
17+body: |
18+ ## Seen (user, 2026-11-14, while testing #215)
19+
20+ With mm in a container, the fallback address works for **ollama** and
21+ **llmman**, not for **llamacpp**.
22+
23+ ## Why (code read)
24+
25+ 1. **llamacpp declares no fallback** ([internal/engine/openai_compat.go](internal/engine/openai_compat.go)):
26+ dmr, ollama, llmman and kronk fall back on
27+ `http://host.docker.internal:<port>/...` when their default does not
28+ answer; llamacpp only has `http://127.0.0.1:8080/v1`. In a container,
29+ that is the container itself, and nothing else is tried. The container
30+ guide says so ("set `baseUrl: http://host.docker.internal:8080/v1`").
31+ The shipped `agent.llamacpp.yaml` even opts out on purpose
32+ (`fallback: ""`, "llama-server is wherever you started it").
33+ 2. **llama-server listens on `127.0.0.1` by default.** On Linux and in a
34+ Docker Sandbox, `host.docker.internal` is the host's gateway, not its
35+ loopback: start it with `--host 0.0.0.0` (as Kronk needs
36+ `--api-host 0.0.0.0:11435`). On Docker Desktop (Mac) the loopback is
37+ reached anyway (Ollama on 127.0.0.1 works there) — not checked for
38+ llama-server.
39+ 3. **Docker Sandbox: port 8080 is not in the mini-me kit's network
40+ policy** (12434, 11434, 17434 only): `sbx policy allow network
41+ host.docker.internal:8080`, or a change in the kit (other repository,
42+ mini-me-kit) — out of scope here.
43+
44+ ## Change (agreed with the user)
45+
46+ - llamacpp's fallback: `http://host.docker.internal:8080/v1`, the same
47+ rule as the others (taken when the default does not answer `/models`
48+ within 2 s; `fallback: ""` in a file still turns it off).
49+ - Its start hint mentions `--host 0.0.0.0` for mm in a container or a
50+ sandbox.
51+ - `agent.llamacpp.yaml` drops `fallback: ""`, so that a copy of it gets
52+ the fallback. Re-litigates that file's explicit choice — the user asked
53+ for llamacpp to behave like the others. `config.samples/` and
54+ `demos/struggle-signals/` (pinned to a fake server) are left alone.
55+ - `mm init` writes the fallback in the file's comment, as for the others
56+ (ticket 121); the wizard's address choice (#214) now also tries it.
57+
58+ ## Acceptance criteria
59+
60+ - mm in a container, no `baseUrl`, llama-server on the host started with
61+ `--host 0.0.0.0` → mm reaches it through `host.docker.internal:8080`.
62+ - On the host, nothing changes when llama-server answers on 127.0.0.1.
63+ - Tests and docs EN+FR.
64+tasks:
65+ - id: 1
66+ title: Engine - llamacpp falls back on http://host.docker.internal:8080/v1, like the other local providers
67+ state: closed
68+ priority: high
69+ author:
70+ name: k33g
71+ email: ph.charriere@gmail.com
72+ createdAt: 2026-11-14T18:36:24.000Z
73+ updatedAt: 2026-11-14T18:39:34.000Z
74+ closedAt: 2026-11-14T18:39:34.000Z
75+ - id: 2
76+ title: startHint - say --host 0.0.0.0 for mm in a container or a sandbox
77+ state: closed
78+ priority: medium
79+ author:
80+ name: k33g
81+ email: ph.charriere@gmail.com
82+ createdAt: 2026-11-14T18:36:24.000Z
83+ updatedAt: 2026-11-14T18:39:34.000Z
84+ closedAt: 2026-11-14T18:39:34.000Z
85+ - id: 3
86+ title: agent.llamacpp.yaml - drop fallback empty (it opted out on purpose)
87+ state: closed
88+ priority: medium
89+ author:
90+ name: k33g
91+ email: ph.charriere@gmail.com
92+ createdAt: 2026-11-14T18:36:24.000Z
93+ updatedAt: 2026-11-14T18:39:34.000Z
94+ closedAt: 2026-11-14T18:39:34.000Z
95+ - id: 4
96+ title: Tests - provider resolution, mm init's comment, the wizard's address choice
97+ state: closed
98+ priority: medium
99+ author:
100+ name: k33g
101+ email: ph.charriere@gmail.com
102+ createdAt: 2026-11-14T18:36:24.000Z
103+ updatedAt: 2026-11-14T18:39:34.000Z
104+ closedAt: 2026-11-14T18:39:34.000Z
105+ - id: 5
106+ title: Docs EN+FR - configuration (providers table), run-in-a-container, run-with-llama-cpp, sandbox (port 8080 policy)
107+ state: closed
108+ priority: medium
109+ author:
110+ name: k33g
111+ email: ph.charriere@gmail.com
112+ createdAt: 2026-11-14T18:36:24.000Z
113+ updatedAt: 2026-11-14T18:39:34.000Z
114+ closedAt: 2026-11-14T18:39:34.000Z
115+comments:
116+ - id: 1
117+ author:
118+ name: k33g
119+ email: ph.charriere@gmail.com
120+ createdAt: 2026-11-14T18:39:34.000Z
121+ body: |
122+ Implemented on `feature/llamacpp-fallback` (uncommitted).
123+
124+ - Engine: llamacpp's fallback `http://host.docker.internal:8080/v1`;
125+ start hint `… --port 8080 (add --host 0.0.0.0 when mm runs in a
126+ container or a sandbox)`.
127+ - `agent.llamacpp.yaml`: `fallback: ""` removed, the comment says what
128+ the fallback is and how to turn it off. `config.samples/` and
129+ `demos/struggle-signals/` keep their `fallback: ""`.
130+ - Tests updated where they asserted "no fallback"
131+ (`TestResolveURLPrecedence`: falls back when baseUrl is down, keeps
132+ it when up; `TestConfigCompat` pins `fallback: ""`;
133+ `TestDefaultURLs`; `TestRenderRecordsTheDefaultURLs`: mm init now
134+ writes the fallback comment for llamacpp). Whole suite green.
135+ - Docs EN+FR: configuration (providers table, agent.llamacpp.yaml),
136+ mcp-configuration (EN), cli (warning example), run-in-a-container,
137+ run-with-llama-cpp (container / sandbox variant), sandbox guide.
138+
139+ Side effect, same as dmr/ollama/llmman already: on the host with
140+ llama-server down, the start-up warning names the fallback address
141+ (`nothing answers at http://host.docker.internal:8080/v1`).
142+
143+ Not tried with a real llama-server in a container or a sandbox.
144+ - id: 2
145+ author:
146+ name: k33g
147+ email: ph.charriere@gmail.com
148+ createdAt: 2026-11-14T18:45:13.000Z
149+ body: |
150+ Closed at the user's request. mm init writes the fallback comment for
151+ llamacpp (checked by the user). In a container, checked only with
152+ v1.0.9 (the released binary the image downloads), which does not have
153+ the fallback yet: the fix reaches containers with the next release.
154+
added .tickets/issues/0218-llamacpp-llama-server-s-default-port-will-change.yaml +114 -0
new file mode 100644
@@ -0,0 +1,114 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 218
3+title: "llamacpp: llama-server's default port will change from 8080 to 9931"
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-11-14T18:37:23.000Z
9+updatedAt: 2026-11-14T18:37:23.000Z
10+labels:
11+ - kind::chore
12+milestone: v2.0.0
13+epic: Providers (LLM Engine)
14+related:
15+ - 217
16+body: |
17+ ## Notice (seen by the user, 2026-11-14)
18+
19+ llama-server prints at start-up:
20+
21+ ```text
22+ llama_server: NOTICE: server default port will be changed to :9931 in a future release
23+ ```
24+
25+ The llama.cpp version that printed it, and the release that will make
26+ the change, are not recorded yet.
27+
28+ ## What depends on 8080 in mini-me (read 2026-11-14)
29+
30+ - **The engine** ([internal/engine/openai_compat.go](internal/engine/openai_compat.go)):
31+ llamacpp's default address `http://127.0.0.1:8080/v1`, its fallback
32+ `http://host.docker.internal:8080/v1` (ticket #217) and its start hint
33+ (`llama-server -m <model.gguf> --jinja --port 8080`).
34+ - **Shipped files**: `agent.llamacpp.yaml` (`baseUrl:
35+ http://127.0.0.1:8080/v1`), `config.samples/agent.llamacpp.*.yaml`,
36+ and the demos run on llama-server (e.g. `demos/qwen-style/`,
37+ `demos/decision-skills/`) — to check one by one: most `8080` in
38+ `demos/` are web apps the agents build, unrelated.
39+ - **Docs EN+FR**: `how-to/run-with-llama-cpp.md`,
40+ `reference/configuration.md` (providers table, `agent.llamacpp.yaml`),
41+ `reference/cli.md` (the warning example), `how-to/run-in-a-container.md`,
42+ `how-to/run-in-a-docker-sandbox.md` (`sbx policy allow network
43+ host.docker.internal:8080`), `how-to/verify-tool-order.md`.
44+
45+ ## Who is affected
46+
47+ Only someone who starts llama-server **without** `--port`: the docs and
48+ the start hint always pass `--port 8080`, and a file with an explicit
49+ `baseUrl` keeps working. With the new default, an agent with no
50+ `baseUrl` would find nothing at 8080.
51+
52+ ## To decide
53+
54+ - Follow the new default (`9931`) once the release is out — and say so
55+ in the release notes, since files without `baseUrl` change server.
56+ - Keep `8080` and keep passing `--port 8080` everywhere.
57+ - Or, during a transition, try both on the host: the wizard already
58+ tries several local addresses in order (`localAddresses`, #214); the
59+ engine's own resolution tries one default and one fallback.
60+
61+ ## Done when
62+
63+ The release is identified, the choice is made and written here, and the
64+ engine, the shipped files and the docs agree on it.
65+tasks:
66+ - id: 1
67+ title: Find the llama.cpp release that changes the default port, and whether it is already out
68+ state: open
69+ priority: high
70+ author:
71+ name: k33g
72+ email: ph.charriere@gmail.com
73+ createdAt: 2026-11-14T18:37:23.000Z
74+ - id: 2
75+ title: Decide - follow the new default (9931), keep 8080, or try both during a transition
76+ state: open
77+ priority: high
78+ author:
79+ name: k33g
80+ email: ph.charriere@gmail.com
81+ createdAt: 2026-11-14T18:37:23.000Z
82+ - id: 3
83+ title: Engine - default address, fallback and start hint of llamacpp
84+ state: open
85+ priority: medium
86+ author:
87+ name: k33g
88+ email: ph.charriere@gmail.com
89+ createdAt: 2026-11-14T18:37:23.000Z
90+ - id: 4
91+ title: Shipped files - agent.llamacpp.yaml, config.samples/agent.llamacpp.*, demos using llamacpp
92+ state: open
93+ priority: medium
94+ author:
95+ name: k33g
96+ email: ph.charriere@gmail.com
97+ createdAt: 2026-11-14T18:37:23.000Z
98+ - id: 5
99+ title: Docs EN+FR - run-with-llama-cpp, configuration (providers table), cli (warning example), container and sandbox guides
100+ state: open
101+ priority: medium
102+ author:
103+ name: k33g
104+ email: ph.charriere@gmail.com
105+ createdAt: 2026-11-14T18:37:23.000Z
106+ - id: 6
107+ title: Docker Sandbox - the port in the mini-me kit's network policy, if 8080 is ever added there (mini-me-kit repository)
108+ state: open
109+ priority: low
110+ author:
111+ name: k33g
112+ email: ph.charriere@gmail.com
113+ createdAt: 2026-11-14T18:37:23.000Z
114+comments: []
new file mode 100644
@@ -0,0 +1,114 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 218
3+title: "llamacpp: llama-server's default port will change from 8080 to 9931"
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-11-14T18:37:23.000Z
9+updatedAt: 2026-11-14T18:37:23.000Z
10+labels:
11+ - kind::chore
12+milestone: v2.0.0
13+epic: Providers (LLM Engine)
14+related:
15+ - 217
16+body: |
17+ ## Notice (seen by the user, 2026-11-14)
18+
19+ llama-server prints at start-up:
20+
21+ ```text
22+ llama_server: NOTICE: server default port will be changed to :9931 in a future release
23+ ```
24+
25+ The llama.cpp version that printed it, and the release that will make
26+ the change, are not recorded yet.
27+
28+ ## What depends on 8080 in mini-me (read 2026-11-14)
29+
30+ - **The engine** ([internal/engine/openai_compat.go](internal/engine/openai_compat.go)):
31+ llamacpp's default address `http://127.0.0.1:8080/v1`, its fallback
32+ `http://host.docker.internal:8080/v1` (ticket #217) and its start hint
33+ (`llama-server -m <model.gguf> --jinja --port 8080`).
34+ - **Shipped files**: `agent.llamacpp.yaml` (`baseUrl:
35+ http://127.0.0.1:8080/v1`), `config.samples/agent.llamacpp.*.yaml`,
36+ and the demos run on llama-server (e.g. `demos/qwen-style/`,
37+ `demos/decision-skills/`) — to check one by one: most `8080` in
38+ `demos/` are web apps the agents build, unrelated.
39+ - **Docs EN+FR**: `how-to/run-with-llama-cpp.md`,
40+ `reference/configuration.md` (providers table, `agent.llamacpp.yaml`),
41+ `reference/cli.md` (the warning example), `how-to/run-in-a-container.md`,
42+ `how-to/run-in-a-docker-sandbox.md` (`sbx policy allow network
43+ host.docker.internal:8080`), `how-to/verify-tool-order.md`.
44+
45+ ## Who is affected
46+
47+ Only someone who starts llama-server **without** `--port`: the docs and
48+ the start hint always pass `--port 8080`, and a file with an explicit
49+ `baseUrl` keeps working. With the new default, an agent with no
50+ `baseUrl` would find nothing at 8080.
51+
52+ ## To decide
53+
54+ - Follow the new default (`9931`) once the release is out — and say so
55+ in the release notes, since files without `baseUrl` change server.
56+ - Keep `8080` and keep passing `--port 8080` everywhere.
57+ - Or, during a transition, try both on the host: the wizard already
58+ tries several local addresses in order (`localAddresses`, #214); the
59+ engine's own resolution tries one default and one fallback.
60+
61+ ## Done when
62+
63+ The release is identified, the choice is made and written here, and the
64+ engine, the shipped files and the docs agree on it.
65+tasks:
66+ - id: 1
67+ title: Find the llama.cpp release that changes the default port, and whether it is already out
68+ state: open
69+ priority: high
70+ author:
71+ name: k33g
72+ email: ph.charriere@gmail.com
73+ createdAt: 2026-11-14T18:37:23.000Z
74+ - id: 2
75+ title: Decide - follow the new default (9931), keep 8080, or try both during a transition
76+ state: open
77+ priority: high
78+ author:
79+ name: k33g
80+ email: ph.charriere@gmail.com
81+ createdAt: 2026-11-14T18:37:23.000Z
82+ - id: 3
83+ title: Engine - default address, fallback and start hint of llamacpp
84+ state: open
85+ priority: medium
86+ author:
87+ name: k33g
88+ email: ph.charriere@gmail.com
89+ createdAt: 2026-11-14T18:37:23.000Z
90+ - id: 4
91+ title: Shipped files - agent.llamacpp.yaml, config.samples/agent.llamacpp.*, demos using llamacpp
92+ state: open
93+ priority: medium
94+ author:
95+ name: k33g
96+ email: ph.charriere@gmail.com
97+ createdAt: 2026-11-14T18:37:23.000Z
98+ - id: 5
99+ title: Docs EN+FR - run-with-llama-cpp, configuration (providers table), cli (warning example), container and sandbox guides
100+ state: open
101+ priority: medium
102+ author:
103+ name: k33g
104+ email: ph.charriere@gmail.com
105+ createdAt: 2026-11-14T18:37:23.000Z
106+ - id: 6
107+ title: Docker Sandbox - the port in the mini-me kit's network policy, if 8080 is ever added there (mini-me-kit repository)
108+ state: open
109+ priority: low
110+ author:
111+ name: k33g
112+ email: ph.charriere@gmail.com
113+ createdAt: 2026-11-14T18:37:23.000Z
114+comments: []
modified agent.llamacpp.yaml +4 -2
@@ -9,8 +9,10 @@ model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M
99 # llama-server's default is 127.0.0.1:8080; the OpenAI routes sit under /v1.
1010 baseUrl: http://127.0.0.1:8080/v1
1111
12-# No fallback: llama-server is wherever you started it.
13-fallback: ""
12+# No fallback line: when baseUrl does not answer, mm tries llama-server on the
13+# host, http://host.docker.internal:8080/v1 — what mm in a container or a
14+# sandbox needs (start llama-server with --host 0.0.0.0 there). fallback: ""
15+# turns that off.
1416
1517 # Only when llama-server was started with --api-key; unset otherwise.
1618 # apiKeyEnv: LLAMA_API_KEY
@@ -9,8 +9,10 @@ model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M
9 # llama-server's default is 127.0.0.1:8080; the OpenAI routes sit under /v1.9 # llama-server's default is 127.0.0.1:8080; the OpenAI routes sit under /v1.
10 baseUrl: http://127.0.0.1:8080/v110 baseUrl: http://127.0.0.1:8080/v1
11 11
12-# No fallback: llama-server is wherever you started it.12+# No fallback line: when baseUrl does not answer, mm tries llama-server on the
13-fallback: ""13+# host, http://host.docker.internal:8080/v1 — what mm in a container or a
14+# sandbox needs (start llama-server with --host 0.0.0.0 there). fallback: ""
15+# turns that off.
14 16
15 # Only when llama-server was started with --api-key; unset otherwise.17 # Only when llama-server was started with --api-key; unset otherwise.
16 # apiKeyEnv: LLAMA_API_KEY18 # apiKeyEnv: LLAMA_API_KEY
modified docs/en/how-to/run-in-a-container.md +2 -2
@@ -68,9 +68,9 @@ The project is mounted at the same path as on your machine, so the paths the edi
6868
6969 ## Reach the model
7070
71-From the container, `localhost` is the container. `dmr`, `llmman` and `ollama` fall back on `host.docker.internal` by themselves when their default address does not answer, as long as the agent file sets no `baseUrl`. The compose file makes that name known on Linux too.
71+From the container, `localhost` is the container. `dmr`, `llmman`, `ollama`, `kronk` and `llamacpp` fall back on `host.docker.internal` by themselves when their default address does not answer, as long as the agent file sets no `baseUrl`. The compose file makes that name known on Linux too.
7272
73-- **`llamacpp`** has no such fallback: set `baseUrl: http://host.docker.internal:8080/v1`.
73+- **`llamacpp`**: on Linux, start llama-server with `--host 0.0.0.0`, as it listens on the loopback only by default (see the last point). Files written before v1.1.0 may say `fallback: ""`: remove that line.
7474 - **An agent file with a `baseUrl` on `localhost` or `127.0.0.1`:** replace the host with `host.docker.internal`, or add a `fallback`.
7575 - **A server on Linux that only listens on `127.0.0.1`:** make it listen on an address the container can reach. `host.docker.internal` is then the host's gateway, not its loopback.
7676
@@ -68,9 +68,9 @@ The project is mounted at the same path as on your machine, so the paths the edi
68 68
69 ## Reach the model69 ## Reach the model
70 70
71-From the container, `localhost` is the container. `dmr`, `llmman` and `ollama` fall back on `host.docker.internal` by themselves when their default address does not answer, as long as the agent file sets no `baseUrl`. The compose file makes that name known on Linux too.71+From the container, `localhost` is the container. `dmr`, `llmman`, `ollama`, `kronk` and `llamacpp` fall back on `host.docker.internal` by themselves when their default address does not answer, as long as the agent file sets no `baseUrl`. The compose file makes that name known on Linux too.
72 72
73-- **`llamacpp`** has no such fallback: set `baseUrl: http://host.docker.internal:8080/v1`.73+- **`llamacpp`**: on Linux, start llama-server with `--host 0.0.0.0`, as it listens on the loopback only by default (see the last point). Files written before v1.1.0 may say `fallback: ""`: remove that line.
74 - **An agent file with a `baseUrl` on `localhost` or `127.0.0.1`:** replace the host with `host.docker.internal`, or add a `fallback`.74 - **An agent file with a `baseUrl` on `localhost` or `127.0.0.1`:** replace the host with `host.docker.internal`, or add a `fallback`.
75 - **A server on Linux that only listens on `127.0.0.1`:** make it listen on an address the container can reach. `host.docker.internal` is then the host's gateway, not its loopback.75 - **A server on Linux that only listens on `127.0.0.1`:** make it listen on an address the container can reach. `host.docker.internal` is then the host's gateway, not its loopback.
76 76
modified docs/en/how-to/run-in-a-docker-sandbox.md +1 -1
@@ -203,7 +203,7 @@ Inside a sandbox `localhost` is the sandbox itself. Your model server keeps runn
203203
204204 - The `mini-me` kit's network policy allows **`host.docker.internal:12434`** (Docker Model Runner), **`:11434`** (Ollama) and **`:17434`** (llmman). `agent.dmr.yaml` already falls back to `http://host.docker.internal:12434/engines/v1`; the configurations shipped in `demos/use-with-sbx/` use llmman (`fallback: http://host.docker.internal:17434/v1`).
205205 - Kronk (`:11435`) is not in that list: allow `localhost:11435` in the policy, and start Kronk on the host with `--api-host 0.0.0.0:11435` — it listens on the loopback only otherwise. See [How to run mini-me on Kronk](run-with-kronk.md).
206-- For another port — llama-server's `8080`, for instance — add it to the kit's `network-policy` capability, or allow it for one sandbox:
206+- For another port — llama-server's `8080`, for instance, which mm tries on its own (`http://host.docker.internal:8080/v1`) when started on the host with `--host 0.0.0.0` — add it to the kit's `network-policy` capability, or allow it for one sandbox:
207207
208208 ```bash
209209 sbx policy allow network host.docker.internal:8080
@@ -203,7 +203,7 @@ Inside a sandbox `localhost` is the sandbox itself. Your model server keeps runn
203 203
204 - The `mini-me` kit's network policy allows **`host.docker.internal:12434`** (Docker Model Runner), **`:11434`** (Ollama) and **`:17434`** (llmman). `agent.dmr.yaml` already falls back to `http://host.docker.internal:12434/engines/v1`; the configurations shipped in `demos/use-with-sbx/` use llmman (`fallback: http://host.docker.internal:17434/v1`).204 - The `mini-me` kit's network policy allows **`host.docker.internal:12434`** (Docker Model Runner), **`:11434`** (Ollama) and **`:17434`** (llmman). `agent.dmr.yaml` already falls back to `http://host.docker.internal:12434/engines/v1`; the configurations shipped in `demos/use-with-sbx/` use llmman (`fallback: http://host.docker.internal:17434/v1`).
205 - Kronk (`:11435`) is not in that list: allow `localhost:11435` in the policy, and start Kronk on the host with `--api-host 0.0.0.0:11435` — it listens on the loopback only otherwise. See [How to run mini-me on Kronk](run-with-kronk.md).205 - Kronk (`:11435`) is not in that list: allow `localhost:11435` in the policy, and start Kronk on the host with `--api-host 0.0.0.0:11435` — it listens on the loopback only otherwise. See [How to run mini-me on Kronk](run-with-kronk.md).
206-- For another port — llama-server's `8080`, for instance — add it to the kit's `network-policy` capability, or allow it for one sandbox:206+- For another port — llama-server's `8080`, for instance, which mm tries on its own (`http://host.docker.internal:8080/v1`) when started on the host with `--host 0.0.0.0` — add it to the kit's `network-policy` capability, or allow it for one sandbox:
207 207
208 ```bash208 ```bash
209 sbx policy allow network host.docker.internal:8080209 sbx policy allow network host.docker.internal:8080
modified docs/en/how-to/run-with-llama-cpp.md +1 -0
@@ -23,6 +23,7 @@ This guide shows how to point `mm` at a `llama-server` you start yourself. It as
2323 ## Variants
2424
2525 - **Different port or host.** Set `baseUrl` in the YAML to `http://<host>:<port>/v1`, or override it for one run with `AGENT_BASE_URL=http://<host>:<port>/v1 ./mm agent.llamacpp.yaml`. An environment override is taken as-is, without the fallback probe.
26+- **From a container or a Docker Sandbox.** When `baseUrl` does not answer, mm tries `http://host.docker.internal:8080/v1`, llama-server on the host. Start it there with `--host 0.0.0.0`: by default it listens on the loopback only, which a container on Linux or a sandbox cannot reach. In a sandbox, also allow the port: `sbx policy allow network host.docker.internal:8080`. `fallback: ""` turns the fallback off. See [run mini-me in a container](run-in-a-container.md) and [run mini-me in a Docker Sandbox](run-in-a-docker-sandbox.md).
2627 - **`autoPull: true`.** llama-server cannot download a model over its API: it serves the one it was started with. `-hf <repo>:<quant>` (step 1) is what downloads it. With `autoPull` on and a `model:` the server does not list, mm says so at start-up and goes on. See [`autoPull`](../reference/configuration.md).
2728 - **Server started with `--api-key`.** Export the key in `LLAMA_API_KEY` (the provider's default variable) or name another variable under `apiKeyEnv`. The key itself never goes in the YAML.
2829 - **Keep `agent.yaml` and switch provider for one run.** `AGENT_PROVIDER=llamacpp ./mm` works as long as `agent.yaml` leaves `baseUrl` empty; an explicit DMR URL in the file would still be honoured and point at port 12434.
@@ -23,6 +23,7 @@ This guide shows how to point `mm` at a `llama-server` you start yourself. It as
23 ## Variants23 ## Variants
24 24
25 - **Different port or host.** Set `baseUrl` in the YAML to `http://<host>:<port>/v1`, or override it for one run with `AGENT_BASE_URL=http://<host>:<port>/v1 ./mm agent.llamacpp.yaml`. An environment override is taken as-is, without the fallback probe.25 - **Different port or host.** Set `baseUrl` in the YAML to `http://<host>:<port>/v1`, or override it for one run with `AGENT_BASE_URL=http://<host>:<port>/v1 ./mm agent.llamacpp.yaml`. An environment override is taken as-is, without the fallback probe.
26+- **From a container or a Docker Sandbox.** When `baseUrl` does not answer, mm tries `http://host.docker.internal:8080/v1`, llama-server on the host. Start it there with `--host 0.0.0.0`: by default it listens on the loopback only, which a container on Linux or a sandbox cannot reach. In a sandbox, also allow the port: `sbx policy allow network host.docker.internal:8080`. `fallback: ""` turns the fallback off. See [run mini-me in a container](run-in-a-container.md) and [run mini-me in a Docker Sandbox](run-in-a-docker-sandbox.md).
26 - **`autoPull: true`.** llama-server cannot download a model over its API: it serves the one it was started with. `-hf <repo>:<quant>` (step 1) is what downloads it. With `autoPull` on and a `model:` the server does not list, mm says so at start-up and goes on. See [`autoPull`](../reference/configuration.md).27 - **`autoPull: true`.** llama-server cannot download a model over its API: it serves the one it was started with. `-hf <repo>:<quant>` (step 1) is what downloads it. With `autoPull` on and a `model:` the server does not list, mm says so at start-up and goes on. See [`autoPull`](../reference/configuration.md).
27 - **Server started with `--api-key`.** Export the key in `LLAMA_API_KEY` (the provider's default variable) or name another variable under `apiKeyEnv`. The key itself never goes in the YAML.28 - **Server started with `--api-key`.** Export the key in `LLAMA_API_KEY` (the provider's default variable) or name another variable under `apiKeyEnv`. The key itself never goes in the YAML.
28 - **Keep `agent.yaml` and switch provider for one run.** `AGENT_PROVIDER=llamacpp ./mm` works as long as `agent.yaml` leaves `baseUrl` empty; an explicit DMR URL in the file would still be honoured and point at port 12434.29 - **Keep `agent.yaml` and switch provider for one run.** `AGENT_PROVIDER=llamacpp ./mm` works as long as `agent.yaml` leaves `baseUrl` empty; an explicit DMR URL in the file would still be honoured and point at port 12434.
modified docs/en/reference/cli.md +2 -2
@@ -104,7 +104,7 @@ Printed on stdout in terminal mode, on stderr in ACP mode. Dimmed when stdout is
104104 ### Example
105105
106106 ```
107-[warning: llamacpp: nothing answers at http://127.0.0.1:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080]
107+[warning: llamacpp: nothing answers at http://host.docker.internal:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080 (add --host 0.0.0.0 when mm runs in a container or a sandbox)]
108108 mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M | ctx: unknown | tools: bash, read_file, write_file, edit_file | skills: 0 | yolo: on
109109 ```
110110
@@ -240,7 +240,7 @@ An agent file outside the workspace only gives a warning: see [when the agent fi
240240 |------|----------------------|---------|
241241 | `--project yes\|no` | Keep everything in a `.mm` folder? — asked first. `yes`: the file is `.mm/agent.yaml` (the folder is created), its paths are written from the project root (`skillsDir: .mm/skills`), and `mm` / `mm tui` started there find it with no argument | `no` |
242242 | `--provider` | Model server: `llmman`, `ollama`, `dmr`, `llamacpp`, `kronk`, `openai` | the first local one whose server answers, else `llmman` (`openai` is never probed: its default address is the OpenAI API) |
243-| `--base-url` | `openai` only: Endpoint — the service's OpenAI-compatible address (OpenAI, Cerebras, Hugging Face…); for the other providers, not asked | `https://api.openai.com/v1` for `openai`; otherwise the provider's address, or its fallback when it does not answer. Written as `baseUrl` unless it is the default |
243+| `--base-url` | `openai` only: Endpoint — the service's OpenAI-compatible address (OpenAI, Cerebras, Hugging Face…); for the other providers, not asked | `https://api.openai.com/v1` for `openai`; otherwise `AGENT_BASE_URL` when set, else the first of the provider's local addresses whose model list answers — its default, then the same with `127.0.0.1` when the default names `localhost` — and its container fallback (`host.docker.internal`) only when none does. The model question names the address its list comes from (`Model? (listed from …)`). Written as `baseUrl` unless it is the default |
244244 | `--api-key-env` | `openai` only: Environment variable that holds the API key | `OPENAI_API_KEY`. Written as `apiKeyEnv` unless it is the default |
245245 | `--model` | Model: a list of the server's models (`/api/tags` for llmman and Ollama, `/models` for the others; 5 s for a local server, 20 s for `openai`), or a name to type when there is no list — the question says why (`<VARIABLE> is not set: no list`, or the server's error). For `openai` the list is asked with the key read from the variable named above, and not asked at all when that variable is empty | the first of the list |
246246 | `--family` | Model family | detected from the model's name, then from the server's family name |
@@ -104,7 +104,7 @@ Printed on stdout in terminal mode, on stderr in ACP mode. Dimmed when stdout is
104 ### Example104 ### Example
105 105
106 ```106 ```
107-[warning: llamacpp: nothing answers at http://127.0.0.1:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080]107+[warning: llamacpp: nothing answers at http://host.docker.internal:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080 (add --host 0.0.0.0 when mm runs in a container or a sandbox)]
108 mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M | ctx: unknown | tools: bash, read_file, write_file, edit_file | skills: 0 | yolo: on108 mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M | ctx: unknown | tools: bash, read_file, write_file, edit_file | skills: 0 | yolo: on
109 ```109 ```
110 110
@@ -240,7 +240,7 @@ An agent file outside the workspace only gives a warning: see [when the agent fi
240 |------|----------------------|---------|240 |------|----------------------|---------|
241 | `--project yes\|no` | Keep everything in a `.mm` folder? — asked first. `yes`: the file is `.mm/agent.yaml` (the folder is created), its paths are written from the project root (`skillsDir: .mm/skills`), and `mm` / `mm tui` started there find it with no argument | `no` |241 | `--project yes\|no` | Keep everything in a `.mm` folder? — asked first. `yes`: the file is `.mm/agent.yaml` (the folder is created), its paths are written from the project root (`skillsDir: .mm/skills`), and `mm` / `mm tui` started there find it with no argument | `no` |
242 | `--provider` | Model server: `llmman`, `ollama`, `dmr`, `llamacpp`, `kronk`, `openai` | the first local one whose server answers, else `llmman` (`openai` is never probed: its default address is the OpenAI API) |242 | `--provider` | Model server: `llmman`, `ollama`, `dmr`, `llamacpp`, `kronk`, `openai` | the first local one whose server answers, else `llmman` (`openai` is never probed: its default address is the OpenAI API) |
243-| `--base-url` | `openai` only: Endpoint — the service's OpenAI-compatible address (OpenAI, Cerebras, Hugging Face…); for the other providers, not asked | `https://api.openai.com/v1` for `openai`; otherwise the provider's address, or its fallback when it does not answer. Written as `baseUrl` unless it is the default |243+| `--base-url` | `openai` only: Endpoint — the service's OpenAI-compatible address (OpenAI, Cerebras, Hugging Face…); for the other providers, not asked | `https://api.openai.com/v1` for `openai`; otherwise `AGENT_BASE_URL` when set, else the first of the provider's local addresses whose model list answers — its default, then the same with `127.0.0.1` when the default names `localhost` — and its container fallback (`host.docker.internal`) only when none does. The model question names the address its list comes from (`Model? (listed from …)`). Written as `baseUrl` unless it is the default |
244 | `--api-key-env` | `openai` only: Environment variable that holds the API key | `OPENAI_API_KEY`. Written as `apiKeyEnv` unless it is the default |244 | `--api-key-env` | `openai` only: Environment variable that holds the API key | `OPENAI_API_KEY`. Written as `apiKeyEnv` unless it is the default |
245 | `--model` | Model: a list of the server's models (`/api/tags` for llmman and Ollama, `/models` for the others; 5 s for a local server, 20 s for `openai`), or a name to type when there is no list — the question says why (`<VARIABLE> is not set: no list`, or the server's error). For `openai` the list is asked with the key read from the variable named above, and not asked at all when that variable is empty | the first of the list |245 | `--model` | Model: a list of the server's models (`/api/tags` for llmman and Ollama, `/models` for the others; 5 s for a local server, 20 s for `openai`), or a name to type when there is no list — the question says why (`<VARIABLE> is not set: no list`, or the server's error). For `openai` the list is asked with the key read from the variable named above, and not asked at all when that variable is empty | the first of the list |
246 | `--family` | Model family | detected from the model's name, then from the server's family name |246 | `--family` | Model family | detected from the model's name, then from the server's family name |
modified docs/en/reference/configuration.md +2 -2
@@ -197,7 +197,7 @@ tools:
197197 | Provider | `baseUrl` | `fallback` | `apiKeyEnv` | Key required |
198198 |----------|-----------|------------|-------------|--------------|
199199 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | none | no |
200-| `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no |
200+| `llamacpp` | `http://127.0.0.1:8080/v1` | `http://host.docker.internal:8080/v1` | `LLAMA_API_KEY` | no |
201201 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no |
202202 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no |
203203 | `kronk` | `http://127.0.0.1:11435/v1` | `http://host.docker.internal:11435/v1` | `KRONK_TOKEN` | no — only Kronk's `authenticated` and `full-protected` modes check it |
@@ -477,7 +477,7 @@ A start-up warning, not an error, is printed when `context.enabled` is `true`, t
477477 | File | Purpose |
478478 |------|---------|
479479 | `agent.yaml` | Docker Model Runner set-up: `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression off, a system prompt named "Bob" that describes the skills and file-editing rules. |
480-| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, `fallback: ""`, compression on. |
480+| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, compression on. |
481481
482482 ### Example
483483
@@ -197,7 +197,7 @@ tools:
197 | Provider | `baseUrl` | `fallback` | `apiKeyEnv` | Key required |197 | Provider | `baseUrl` | `fallback` | `apiKeyEnv` | Key required |
198 |----------|-----------|------------|-------------|--------------|198 |----------|-----------|------------|-------------|--------------|
199 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | none | no |199 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | none | no |
200-| `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no |200+| `llamacpp` | `http://127.0.0.1:8080/v1` | `http://host.docker.internal:8080/v1` | `LLAMA_API_KEY` | no |
201 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no |201 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no |
202 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no |202 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no |
203 | `kronk` | `http://127.0.0.1:11435/v1` | `http://host.docker.internal:11435/v1` | `KRONK_TOKEN` | no — only Kronk's `authenticated` and `full-protected` modes check it |203 | `kronk` | `http://127.0.0.1:11435/v1` | `http://host.docker.internal:11435/v1` | `KRONK_TOKEN` | no — only Kronk's `authenticated` and `full-protected` modes check it |
@@ -477,7 +477,7 @@ A start-up warning, not an error, is printed when `context.enabled` is `true`, t
477 | File | Purpose |477 | File | Purpose |
478 |------|---------|478 |------|---------|
479 | `agent.yaml` | Docker Model Runner set-up: `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression off, a system prompt named "Bob" that describes the skills and file-editing rules. |479 | `agent.yaml` | Docker Model Runner set-up: `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression off, a system prompt named "Bob" that describes the skills and file-editing rules. |
480-| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, `fallback: ""`, compression on. |480+| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, compression on. |
481 481
482 ### Example482 ### Example
483 483
modified docs/en/reference/mcp-configuration.md +2 -2
@@ -78,7 +78,7 @@ The shipped `agent.lsp.yaml` is `agent.dmr.yaml` with this block on (gopls activ
7878 | Provider | `baseUrl` | `fallback` | `apiKeyEnv` | Key required |
7979 |----------|-----------|------------|-------------|--------------|
8080 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | none | no |
81-| `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no |
81+| `llamacpp` | `http://127.0.0.1:8080/v1` | `http://host.docker.internal:8080/v1` | `LLAMA_API_KEY` | no |
8282 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no |
8383 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no |
8484
@@ -114,7 +114,7 @@ A start-up warning, not an error, is printed when `context.enabled` is `true`, t
114114 | File | Purpose |
115115 |------|---------|
116116 | `agent.yaml` | Docker Model Runner set-up: `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression off, a system prompt named "Bob" that describes the skills and file-editing rules. |
117-| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, `fallback: ""`, compression on. |
117+| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, compression on. |
118118
119119 ### Example
120120
@@ -78,7 +78,7 @@ The shipped `agent.lsp.yaml` is `agent.dmr.yaml` with this block on (gopls activ
78 | Provider | `baseUrl` | `fallback` | `apiKeyEnv` | Key required |78 | Provider | `baseUrl` | `fallback` | `apiKeyEnv` | Key required |
79 |----------|-----------|------------|-------------|--------------|79 |----------|-----------|------------|-------------|--------------|
80 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | none | no |80 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | none | no |
81-| `llamacpp` | `http://127.0.0.1:8080/v1` | none | `LLAMA_API_KEY` | no |81+| `llamacpp` | `http://127.0.0.1:8080/v1` | `http://host.docker.internal:8080/v1` | `LLAMA_API_KEY` | no |
82 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no |82 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | no |
83 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no |83 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | no |
84 84
@@ -114,7 +114,7 @@ A start-up warning, not an error, is printed when `context.enabled` is `true`, t
114 | File | Purpose |114 | File | Purpose |
115 |------|---------|115 |------|---------|
116 | `agent.yaml` | Docker Model Runner set-up: `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression off, a system prompt named "Bob" that describes the skills and file-editing rules. |116 | `agent.yaml` | Docker Model Runner set-up: `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression off, a system prompt named "Bob" that describes the skills and file-editing rules. |
117-| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, `fallback: ""`, compression on. |117+| `agent.llamacpp.yaml` | llama.cpp set-up: `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, compression on. |
118 118
119 ### Example119 ### Example
120 120
modified docs/fr/how-to/run-in-a-container.md +2 -2
@@ -68,9 +68,9 @@ Le projet est monté au même chemin que sur votre machine : les chemins envoyé
6868
6969 ## Joindre le modèle
7070
71-Depuis le conteneur, `localhost` désigne le conteneur. `dmr`, `llmman` et `ollama` se rabattent d'eux-mêmes sur `host.docker.internal` quand leur adresse par défaut ne répond pas, tant que le fichier d'agent ne définit pas de `baseUrl`. Le fichier compose fait aussi connaître ce nom sous Linux.
71+Depuis le conteneur, `localhost` désigne le conteneur. `dmr`, `llmman`, `ollama`, `kronk` et `llamacpp` se rabattent d'eux-mêmes sur `host.docker.internal` quand leur adresse par défaut ne répond pas, tant que le fichier d'agent ne définit pas de `baseUrl`. Le fichier compose fait aussi connaître ce nom sous Linux.
7272
73-- **`llamacpp`** n'a pas ce repli : définissez `baseUrl: http://host.docker.internal:8080/v1`.
73+- **`llamacpp`** : sous Linux, lancez llama-server avec `--host 0.0.0.0`, car par défaut il n'écoute que sur la boucle locale (voir le dernier point). Les fichiers écrits avant la v1.1.0 peuvent contenir `fallback: ""` : retirez cette ligne.
7474 - **Un fichier d'agent avec un `baseUrl` sur `localhost` ou `127.0.0.1` :** remplacez l'hôte par `host.docker.internal`, ou ajoutez un `fallback`.
7575 - **Un serveur sous Linux qui n'écoute que sur `127.0.0.1` :** faites-le écouter sur une adresse joignable par le conteneur. `host.docker.internal` y désigne la passerelle de l'hôte, pas sa boucle locale.
7676
@@ -68,9 +68,9 @@ Le projet est monté au même chemin que sur votre machine : les chemins envoyé
68 68
69 ## Joindre le modèle69 ## Joindre le modèle
70 70
71-Depuis le conteneur, `localhost` désigne le conteneur. `dmr`, `llmman` et `ollama` se rabattent d'eux-mêmes sur `host.docker.internal` quand leur adresse par défaut ne répond pas, tant que le fichier d'agent ne définit pas de `baseUrl`. Le fichier compose fait aussi connaître ce nom sous Linux.71+Depuis le conteneur, `localhost` désigne le conteneur. `dmr`, `llmman`, `ollama`, `kronk` et `llamacpp` se rabattent d'eux-mêmes sur `host.docker.internal` quand leur adresse par défaut ne répond pas, tant que le fichier d'agent ne définit pas de `baseUrl`. Le fichier compose fait aussi connaître ce nom sous Linux.
72 72
73-- **`llamacpp`** n'a pas ce repli : définissez `baseUrl: http://host.docker.internal:8080/v1`.73+- **`llamacpp`** : sous Linux, lancez llama-server avec `--host 0.0.0.0`, car par défaut il n'écoute que sur la boucle locale (voir le dernier point). Les fichiers écrits avant la v1.1.0 peuvent contenir `fallback: ""` : retirez cette ligne.
74 - **Un fichier d'agent avec un `baseUrl` sur `localhost` ou `127.0.0.1` :** remplacez l'hôte par `host.docker.internal`, ou ajoutez un `fallback`.74 - **Un fichier d'agent avec un `baseUrl` sur `localhost` ou `127.0.0.1` :** remplacez l'hôte par `host.docker.internal`, ou ajoutez un `fallback`.
75 - **Un serveur sous Linux qui n'écoute que sur `127.0.0.1` :** faites-le écouter sur une adresse joignable par le conteneur. `host.docker.internal` y désigne la passerelle de l'hôte, pas sa boucle locale.75 - **Un serveur sous Linux qui n'écoute que sur `127.0.0.1` :** faites-le écouter sur une adresse joignable par le conteneur. `host.docker.internal` y désigne la passerelle de l'hôte, pas sa boucle locale.
76 76
modified docs/fr/how-to/run-in-a-docker-sandbox.md +1 -1
@@ -203,7 +203,7 @@ Dans un sandbox, `localhost` est le sandbox lui-même. Votre serveur de modèles
203203
204204 - La politique réseau du kit `mini-me` autorise **`host.docker.internal:12434`** (Docker Model Runner), **`:11434`** (Ollama) et **`:17434`** (llmman). `agent.dmr.yaml` se replie déjà sur `http://host.docker.internal:12434/engines/v1` ; les configurations livrées dans `demos/use-with-sbx/` utilisent llmman (`fallback: http://host.docker.internal:17434/v1`).
205205 - Kronk (`:11435`) n'est pas dans cette liste : autorisez `localhost:11435` dans la politique, et lancez Kronk sur l'hôte avec `--api-host 0.0.0.0:11435` — sinon il n'écoute que sur la boucle locale. Voir [Faire tourner mini-me sur Kronk](run-with-kronk.md).
206-- Pour un autre port — le `8080` de llama-server, par exemple — ajoutez-le à la capacité `network-policy` du kit, ou autorisez-le pour un seul sandbox :
206+- Pour un autre port — le `8080` de llama-server, par exemple, que mm essaie de lui-même (`http://host.docker.internal:8080/v1`) quand il est lancé sur l'hôte avec `--host 0.0.0.0` — ajoutez-le à la capacité `network-policy` du kit, ou autorisez-le pour un seul sandbox :
207207
208208 ```bash
209209 sbx policy allow network host.docker.internal:8080
@@ -203,7 +203,7 @@ Dans un sandbox, `localhost` est le sandbox lui-même. Votre serveur de modèles
203 203
204 - La politique réseau du kit `mini-me` autorise **`host.docker.internal:12434`** (Docker Model Runner), **`:11434`** (Ollama) et **`:17434`** (llmman). `agent.dmr.yaml` se replie déjà sur `http://host.docker.internal:12434/engines/v1` ; les configurations livrées dans `demos/use-with-sbx/` utilisent llmman (`fallback: http://host.docker.internal:17434/v1`).204 - La politique réseau du kit `mini-me` autorise **`host.docker.internal:12434`** (Docker Model Runner), **`:11434`** (Ollama) et **`:17434`** (llmman). `agent.dmr.yaml` se replie déjà sur `http://host.docker.internal:12434/engines/v1` ; les configurations livrées dans `demos/use-with-sbx/` utilisent llmman (`fallback: http://host.docker.internal:17434/v1`).
205 - Kronk (`:11435`) n'est pas dans cette liste : autorisez `localhost:11435` dans la politique, et lancez Kronk sur l'hôte avec `--api-host 0.0.0.0:11435` — sinon il n'écoute que sur la boucle locale. Voir [Faire tourner mini-me sur Kronk](run-with-kronk.md).205 - Kronk (`:11435`) n'est pas dans cette liste : autorisez `localhost:11435` dans la politique, et lancez Kronk sur l'hôte avec `--api-host 0.0.0.0:11435` — sinon il n'écoute que sur la boucle locale. Voir [Faire tourner mini-me sur Kronk](run-with-kronk.md).
206-- Pour un autre port — le `8080` de llama-server, par exemple — ajoutez-le à la capacité `network-policy` du kit, ou autorisez-le pour un seul sandbox :206+- Pour un autre port — le `8080` de llama-server, par exemple, que mm essaie de lui-même (`http://host.docker.internal:8080/v1`) quand il est lancé sur l'hôte avec `--host 0.0.0.0` — ajoutez-le à la capacité `network-policy` du kit, ou autorisez-le pour un seul sandbox :
207 207
208 ```bash208 ```bash
209 sbx policy allow network host.docker.internal:8080209 sbx policy allow network host.docker.internal:8080
modified docs/fr/how-to/run-with-llama-cpp.md +1 -0
@@ -23,6 +23,7 @@ Ce guide montre comment pointer `mm` vers un `llama-server` que vous démarrez v
2323 ## Variantes
2424
2525 - **Autre port ou autre hôte.** Mettez `baseUrl` à `http://<hôte>:<port>/v1` dans le YAML, ou surchargez pour une seule exécution avec `AGENT_BASE_URL=http://<hôte>:<port>/v1 ./mm agent.llamacpp.yaml`. Une surcharge par l'environnement est prise telle quelle, sans sonde de repli.
26+- **Depuis un conteneur ou un Docker Sandbox.** Quand `baseUrl` ne répond pas, mm essaie `http://host.docker.internal:8080/v1`, llama-server sur l'hôte. Lancez-le avec `--host 0.0.0.0` : par défaut il n'écoute que sur la boucle locale, qu'un conteneur sous Linux ou un sandbox ne peuvent pas joindre. Dans un sandbox, autorisez aussi le port : `sbx policy allow network host.docker.internal:8080`. `fallback: ""` coupe le repli. Voir [faire tourner mini-me dans un conteneur](run-in-a-container.md) et [faire tourner mini-me dans un Docker Sandbox](run-in-a-docker-sandbox.md).
2627 - **`autoPull: true`.** llama-server ne sait pas télécharger un modèle par son API : il sert celui avec lequel il a été lancé. C'est `-hf <dépôt>:<quant>` (étape 1) qui le télécharge. Avec `autoPull` actif et un `model:` que le serveur ne liste pas, mm le dit au démarrage et continue. Voir [`autoPull`](../reference/configuration.md).
2728 - **Serveur démarré avec `--api-key`.** Exportez la clé dans `LLAMA_API_KEY` (la variable par défaut du fournisseur) ou nommez une autre variable dans `apiKeyEnv`. La clé elle-même ne va jamais dans le YAML.
2829 - **Garder `agent.yaml` et changer de fournisseur pour une exécution.** `AGENT_PROVIDER=llamacpp ./mm` fonctionne tant qu'`agent.yaml` laisse `baseUrl` vide ; une URL DMR explicite dans le fichier serait respectée et pointerait toujours sur le port 12434.
@@ -23,6 +23,7 @@ Ce guide montre comment pointer `mm` vers un `llama-server` que vous démarrez v
23 ## Variantes23 ## Variantes
24 24
25 - **Autre port ou autre hôte.** Mettez `baseUrl` à `http://<hôte>:<port>/v1` dans le YAML, ou surchargez pour une seule exécution avec `AGENT_BASE_URL=http://<hôte>:<port>/v1 ./mm agent.llamacpp.yaml`. Une surcharge par l'environnement est prise telle quelle, sans sonde de repli.25 - **Autre port ou autre hôte.** Mettez `baseUrl` à `http://<hôte>:<port>/v1` dans le YAML, ou surchargez pour une seule exécution avec `AGENT_BASE_URL=http://<hôte>:<port>/v1 ./mm agent.llamacpp.yaml`. Une surcharge par l'environnement est prise telle quelle, sans sonde de repli.
26+- **Depuis un conteneur ou un Docker Sandbox.** Quand `baseUrl` ne répond pas, mm essaie `http://host.docker.internal:8080/v1`, llama-server sur l'hôte. Lancez-le avec `--host 0.0.0.0` : par défaut il n'écoute que sur la boucle locale, qu'un conteneur sous Linux ou un sandbox ne peuvent pas joindre. Dans un sandbox, autorisez aussi le port : `sbx policy allow network host.docker.internal:8080`. `fallback: ""` coupe le repli. Voir [faire tourner mini-me dans un conteneur](run-in-a-container.md) et [faire tourner mini-me dans un Docker Sandbox](run-in-a-docker-sandbox.md).
26 - **`autoPull: true`.** llama-server ne sait pas télécharger un modèle par son API : il sert celui avec lequel il a été lancé. C'est `-hf <dépôt>:<quant>` (étape 1) qui le télécharge. Avec `autoPull` actif et un `model:` que le serveur ne liste pas, mm le dit au démarrage et continue. Voir [`autoPull`](../reference/configuration.md).27 - **`autoPull: true`.** llama-server ne sait pas télécharger un modèle par son API : il sert celui avec lequel il a été lancé. C'est `-hf <dépôt>:<quant>` (étape 1) qui le télécharge. Avec `autoPull` actif et un `model:` que le serveur ne liste pas, mm le dit au démarrage et continue. Voir [`autoPull`](../reference/configuration.md).
27 - **Serveur démarré avec `--api-key`.** Exportez la clé dans `LLAMA_API_KEY` (la variable par défaut du fournisseur) ou nommez une autre variable dans `apiKeyEnv`. La clé elle-même ne va jamais dans le YAML.28 - **Serveur démarré avec `--api-key`.** Exportez la clé dans `LLAMA_API_KEY` (la variable par défaut du fournisseur) ou nommez une autre variable dans `apiKeyEnv`. La clé elle-même ne va jamais dans le YAML.
28 - **Garder `agent.yaml` et changer de fournisseur pour une exécution.** `AGENT_PROVIDER=llamacpp ./mm` fonctionne tant qu'`agent.yaml` laisse `baseUrl` vide ; une URL DMR explicite dans le fichier serait respectée et pointerait toujours sur le port 12434.29 - **Garder `agent.yaml` et changer de fournisseur pour une exécution.** `AGENT_PROVIDER=llamacpp ./mm` fonctionne tant qu'`agent.yaml` laisse `baseUrl` vide ; une URL DMR explicite dans le fichier serait respectée et pointerait toujours sur le port 12434.
modified docs/fr/reference/cli.md +2 -2
@@ -104,7 +104,7 @@ Affichée sur stdout en mode terminal, sur stderr en mode ACP. Grisée quand std
104104 ### Exemple
105105
106106 ```
107-[warning: llamacpp: nothing answers at http://127.0.0.1:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080]
107+[warning: llamacpp: nothing answers at http://host.docker.internal:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080 (add --host 0.0.0.0 when mm runs in a container or a sandbox)]
108108 mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M | ctx: unknown | tools: bash, read_file, write_file, edit_file | skills: 0 | yolo: on
109109 ```
110110
@@ -240,7 +240,7 @@ Un fichier d'agent hors du workspace ne donne qu'un avertissement : voir [quand
240240 |--------|---------------------------------|--------|
241241 | `--project yes\|no` | Tout ranger dans un dossier `.mm` ? — posée en premier. `yes` : le fichier est `.mm/agent.yaml` (le dossier est créé), ses chemins sont écrits depuis la racine du projet (`skillsDir: .mm/skills`), et `mm` / `mm tui` lancés là le trouvent sans argument | `no` |
242242 | `--provider` | Serveur de modèles : `llmman`, `ollama`, `dmr`, `llamacpp`, `kronk`, `openai` | le premier serveur local qui répond, sinon `llmman` (`openai` n'est jamais sondé : son adresse par défaut est l'API d'OpenAI) |
243-| `--base-url` | `openai` seulement : Endpoint — l'adresse compatible OpenAI du service (OpenAI, Cerebras, Hugging Face…) ; pour les autres fournisseurs, pas posée | `https://api.openai.com/v1` pour `openai` ; sinon l'adresse du fournisseur, ou son adresse de secours quand elle ne répond pas. Écrite comme `baseUrl` sauf si c'est la valeur par défaut |
243+| `--base-url` | `openai` seulement : Endpoint — l'adresse compatible OpenAI du service (OpenAI, Cerebras, Hugging Face…) ; pour les autres fournisseurs, pas posée | `https://api.openai.com/v1` pour `openai` ; sinon `AGENT_BASE_URL` s'il est défini, sinon la première des adresses locales du fournisseur dont la liste de modèles répond — son adresse par défaut, puis la même avec `127.0.0.1` quand elle nomme `localhost` — et son adresse de secours pour conteneur (`host.docker.internal`) seulement quand aucune ne répond. La question du modèle nomme l'adresse d'où vient sa liste (`Model? (listed from …)`). Écrite comme `baseUrl` sauf si c'est la valeur par défaut |
244244 | `--api-key-env` | `openai` seulement : variable d'environnement qui contient la clé d'API | `OPENAI_API_KEY`. Écrite comme `apiKeyEnv` sauf si c'est la valeur par défaut |
245245 | `--model` | Modèle : la liste des modèles du serveur (`/api/tags` pour llmman et Ollama, `/models` pour les autres ; 5 s pour un serveur local, 20 s pour `openai`), ou un nom à taper quand il n'y a pas de liste — la question dit pourquoi (`<VARIABLE> is not set: no list`, ou l'erreur du serveur). Pour `openai`, la liste est demandée avec la clé lue dans la variable nommée plus haut, et pas demandée du tout quand cette variable est vide | le premier de la liste |
246246 | `--family` | Famille du modèle | détectée d'après le nom du modèle, puis d'après le nom de famille donné par le serveur |
@@ -104,7 +104,7 @@ Affichée sur stdout en mode terminal, sur stderr en mode ACP. Grisée quand std
104 ### Exemple104 ### Exemple
105 105
106 ```106 ```
107-[warning: llamacpp: nothing answers at http://127.0.0.1:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080]107+[warning: llamacpp: nothing answers at http://host.docker.internal:8080/v1 — start it: llama-server -m <model.gguf> --jinja --port 8080 (add --host 0.0.0.0 when mm runs in a container or a sandbox)]
108 mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M | ctx: unknown | tools: bash, read_file, write_file, edit_file | skills: 0 | yolo: on108 mm v0.1.7 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M | ctx: unknown | tools: bash, read_file, write_file, edit_file | skills: 0 | yolo: on
109 ```109 ```
110 110
@@ -240,7 +240,7 @@ Un fichier d'agent hors du workspace ne donne qu'un avertissement : voir [quand
240 |--------|---------------------------------|--------|240 |--------|---------------------------------|--------|
241 | `--project yes\|no` | Tout ranger dans un dossier `.mm` ? — posée en premier. `yes` : le fichier est `.mm/agent.yaml` (le dossier est créé), ses chemins sont écrits depuis la racine du projet (`skillsDir: .mm/skills`), et `mm` / `mm tui` lancés là le trouvent sans argument | `no` |241 | `--project yes\|no` | Tout ranger dans un dossier `.mm` ? — posée en premier. `yes` : le fichier est `.mm/agent.yaml` (le dossier est créé), ses chemins sont écrits depuis la racine du projet (`skillsDir: .mm/skills`), et `mm` / `mm tui` lancés là le trouvent sans argument | `no` |
242 | `--provider` | Serveur de modèles : `llmman`, `ollama`, `dmr`, `llamacpp`, `kronk`, `openai` | le premier serveur local qui répond, sinon `llmman` (`openai` n'est jamais sondé : son adresse par défaut est l'API d'OpenAI) |242 | `--provider` | Serveur de modèles : `llmman`, `ollama`, `dmr`, `llamacpp`, `kronk`, `openai` | le premier serveur local qui répond, sinon `llmman` (`openai` n'est jamais sondé : son adresse par défaut est l'API d'OpenAI) |
243-| `--base-url` | `openai` seulement : Endpoint — l'adresse compatible OpenAI du service (OpenAI, Cerebras, Hugging Face…) ; pour les autres fournisseurs, pas posée | `https://api.openai.com/v1` pour `openai` ; sinon l'adresse du fournisseur, ou son adresse de secours quand elle ne répond pas. Écrite comme `baseUrl` sauf si c'est la valeur par défaut |243+| `--base-url` | `openai` seulement : Endpoint — l'adresse compatible OpenAI du service (OpenAI, Cerebras, Hugging Face…) ; pour les autres fournisseurs, pas posée | `https://api.openai.com/v1` pour `openai` ; sinon `AGENT_BASE_URL` s'il est défini, sinon la première des adresses locales du fournisseur dont la liste de modèles répond — son adresse par défaut, puis la même avec `127.0.0.1` quand elle nomme `localhost` — et son adresse de secours pour conteneur (`host.docker.internal`) seulement quand aucune ne répond. La question du modèle nomme l'adresse d'où vient sa liste (`Model? (listed from …)`). Écrite comme `baseUrl` sauf si c'est la valeur par défaut |
244 | `--api-key-env` | `openai` seulement : variable d'environnement qui contient la clé d'API | `OPENAI_API_KEY`. Écrite comme `apiKeyEnv` sauf si c'est la valeur par défaut |244 | `--api-key-env` | `openai` seulement : variable d'environnement qui contient la clé d'API | `OPENAI_API_KEY`. Écrite comme `apiKeyEnv` sauf si c'est la valeur par défaut |
245 | `--model` | Modèle : la liste des modèles du serveur (`/api/tags` pour llmman et Ollama, `/models` pour les autres ; 5 s pour un serveur local, 20 s pour `openai`), ou un nom à taper quand il n'y a pas de liste — la question dit pourquoi (`<VARIABLE> is not set: no list`, ou l'erreur du serveur). Pour `openai`, la liste est demandée avec la clé lue dans la variable nommée plus haut, et pas demandée du tout quand cette variable est vide | le premier de la liste |245 | `--model` | Modèle : la liste des modèles du serveur (`/api/tags` pour llmman et Ollama, `/models` pour les autres ; 5 s pour un serveur local, 20 s pour `openai`), ou un nom à taper quand il n'y a pas de liste — la question dit pourquoi (`<VARIABLE> is not set: no list`, ou l'erreur du serveur). Pour `openai`, la liste est demandée avec la clé lue dans la variable nommée plus haut, et pas demandée du tout quand cette variable est vide | le premier de la liste |
246 | `--family` | Famille du modèle | détectée d'après le nom du modèle, puis d'après le nom de famille donné par le serveur |246 | `--family` | Famille du modèle | détectée d'après le nom du modèle, puis d'après le nom de famille donné par le serveur |
modified docs/fr/reference/configuration.md +2 -2
@@ -197,7 +197,7 @@ tools:
197197 | Fournisseur | `baseUrl` | `fallback` | `apiKeyEnv` | Clé requise |
198198 |-------------|-----------|------------|-------------|-------------|
199199 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | aucune | non |
200-| `llamacpp` | `http://127.0.0.1:8080/v1` | aucun | `LLAMA_API_KEY` | non |
200+| `llamacpp` | `http://127.0.0.1:8080/v1` | `http://host.docker.internal:8080/v1` | `LLAMA_API_KEY` | non |
201201 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | non |
202202 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | non |
203203 | `kronk` | `http://127.0.0.1:11435/v1` | `http://host.docker.internal:11435/v1` | `KRONK_TOKEN` | non — seuls les modes `authenticated` et `full-protected` de Kronk la vérifient |
@@ -477,7 +477,7 @@ Un avertissement au démarrage, et non une erreur, est affiché quand `context.e
477477 | Fichier | Rôle |
478478 |---------|------|
479479 | `agent.yaml` | Configuration Docker Model Runner : `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression désactivée, un prompt système nommé « Bob » qui décrit les skills et les règles d'édition de fichiers. |
480-| `agent.llamacpp.yaml` | Configuration llama.cpp : `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, `fallback: ""`, compression activée. |
480+| `agent.llamacpp.yaml` | Configuration llama.cpp : `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, compression activée. |
481481
482482 ### Exemple
483483
@@ -197,7 +197,7 @@ tools:
197 | Fournisseur | `baseUrl` | `fallback` | `apiKeyEnv` | Clé requise |197 | Fournisseur | `baseUrl` | `fallback` | `apiKeyEnv` | Clé requise |
198 |-------------|-----------|------------|-------------|-------------|198 |-------------|-----------|------------|-------------|-------------|
199 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | aucune | non |199 | `dmr` | `http://localhost:12434/engines/v1` | `http://host.docker.internal:12434/engines/v1` | aucune | non |
200-| `llamacpp` | `http://127.0.0.1:8080/v1` | aucun | `LLAMA_API_KEY` | non |200+| `llamacpp` | `http://127.0.0.1:8080/v1` | `http://host.docker.internal:8080/v1` | `LLAMA_API_KEY` | non |
201 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | non |201 | `llmman` | `http://127.0.0.1:17434/v1` | `http://host.docker.internal:17434/v1` | `LLMMAN_API_KEY` | non |
202 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | non |202 | `ollama` | `http://localhost:11434/v1` | `http://host.docker.internal:11434/v1` | `OLLAMA_API_KEY` | non |
203 | `kronk` | `http://127.0.0.1:11435/v1` | `http://host.docker.internal:11435/v1` | `KRONK_TOKEN` | non — seuls les modes `authenticated` et `full-protected` de Kronk la vérifient |203 | `kronk` | `http://127.0.0.1:11435/v1` | `http://host.docker.internal:11435/v1` | `KRONK_TOKEN` | non — seuls les modes `authenticated` et `full-protected` de Kronk la vérifient |
@@ -477,7 +477,7 @@ Un avertissement au démarrage, et non une erreur, est affiché quand `context.e
477 | Fichier | Rôle |477 | Fichier | Rôle |
478 |---------|------|478 |---------|------|
479 | `agent.yaml` | Configuration Docker Model Runner : `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression désactivée, un prompt système nommé « Bob » qui décrit les skills et les règles d'édition de fichiers. |479 | `agent.yaml` | Configuration Docker Model Runner : `provider: dmr`, `maxTurns: 40`, `displayCommands: true`, compression désactivée, un prompt système nommé « Bob » qui décrit les skills et les règles d'édition de fichiers. |
480-| `agent.llamacpp.yaml` | Configuration llama.cpp : `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, `fallback: ""`, compression activée. |480+| `agent.llamacpp.yaml` | Configuration llama.cpp : `provider: llamacpp`, `baseUrl: http://127.0.0.1:8080/v1`, compression activée. |
481 481
482 ### Exemple482 ### Exemple
483 483
modified internal/agentinit/decide_test.go +1 -1
@@ -170,7 +170,7 @@ func TestRenderRecordsTheDefaultURLs(t *testing.T) {
170170 t.Errorf("llmman's default URLs missing:\n%s", llmman)
171171 }
172172 llamacpp := Render(Decide(p, Choices{Provider: "llamacpp", Model: "qwen3", Usage: "assistant", Machine: "small"}, Facts{}))
173- if !strings.Contains(llamacpp, "# baseUrl: \"http://127.0.0.1:8080/v1\"\n# (llamacpp has no fallback address)\n") {
173+ if !strings.Contains(llamacpp, "# baseUrl: \"http://127.0.0.1:8080/v1\"\n# fallback: \"http://host.docker.internal:8080/v1\" # tried when baseUrl does not answer\n") {
174174 t.Errorf("llamacpp's default URL missing:\n%s", llamacpp)
175175 }
176176 own := Render(Decide(p, Choices{Provider: "llmman", BaseURL: "http://box:17434/v1", Model: "qwen3", Usage: "assistant", Machine: "small"}, Facts{}))
@@ -170,7 +170,7 @@ func TestRenderRecordsTheDefaultURLs(t *testing.T) {
170 t.Errorf("llmman's default URLs missing:\n%s", llmman)170 t.Errorf("llmman's default URLs missing:\n%s", llmman)
171 }171 }
172 llamacpp := Render(Decide(p, Choices{Provider: "llamacpp", Model: "qwen3", Usage: "assistant", Machine: "small"}, Facts{}))172 llamacpp := Render(Decide(p, Choices{Provider: "llamacpp", Model: "qwen3", Usage: "assistant", Machine: "small"}, Facts{}))
173- if !strings.Contains(llamacpp, "# baseUrl: \"http://127.0.0.1:8080/v1\"\n# (llamacpp has no fallback address)\n") {173+ if !strings.Contains(llamacpp, "# baseUrl: \"http://127.0.0.1:8080/v1\"\n# fallback: \"http://host.docker.internal:8080/v1\" # tried when baseUrl does not answer\n") {
174 t.Errorf("llamacpp's default URL missing:\n%s", llamacpp)174 t.Errorf("llamacpp's default URL missing:\n%s", llamacpp)
175 }175 }
176 own := Render(Decide(p, Choices{Provider: "llmman", BaseURL: "http://box:17434/v1", Model: "qwen3", Usage: "assistant", Machine: "small"}, Facts{}))176 own := Render(Decide(p, Choices{Provider: "llmman", BaseURL: "http://box:17434/v1", Model: "qwen3", Usage: "assistant", Machine: "small"}, Facts{}))
modified internal/agentinit/flow.go +5 -2
@@ -222,6 +222,9 @@ func (f *Flow) Step(key string) Step {
222222 st.Kind, st.Prompt = elicit.Text, f.typeModelPrompt()
223223 break
224224 }
225+ // Where the list comes from (ticket 214): a wrong address — the
226+ // container one on the host — shows at once.
227+ st.Prompt = fmt.Sprintf("Model? (listed from %s)", f.Base())
225228 for _, m := range models {
226229 st.Options = append(st.Options, Option{Value: m, Label: m, Detail: modelDetail(f.c.Provider, m)})
227230 }
@@ -578,7 +581,7 @@ func (f *Flow) Result() (Choices, Facts, string) {
578581 // Base is the resolved server address ("" before a provider is chosen).
579582 func (f *Flow) Base() string {
580583 if f.base == "" && f.c.Provider != "" {
581- f.base = resolveBase(f.c)
584+ f.base = resolveBase(f.ctx, f.c)
582585 }
583586 return f.base
584587 }
@@ -628,7 +631,7 @@ func (f *Flow) answers(name string) bool {
628631 if f.reachable == nil {
629632 f.reachable = map[string]bool{}
630633 for _, p := range local {
631- _, err := Models(f.ctx, p, resolveBase(Choices{Provider: p}))
634+ _, err := Models(f.ctx, p, resolveBase(f.ctx, Choices{Provider: p}))
632635 f.reachable[p] = err == nil
633636 }
634637 }
@@ -222,6 +222,9 @@ func (f *Flow) Step(key string) Step {
222 st.Kind, st.Prompt = elicit.Text, f.typeModelPrompt()222 st.Kind, st.Prompt = elicit.Text, f.typeModelPrompt()
223 break223 break
224 }224 }
225+ // Where the list comes from (ticket 214): a wrong address — the
226+ // container one on the host — shows at once.
227+ st.Prompt = fmt.Sprintf("Model? (listed from %s)", f.Base())
225 for _, m := range models {228 for _, m := range models {
226 st.Options = append(st.Options, Option{Value: m, Label: m, Detail: modelDetail(f.c.Provider, m)})229 st.Options = append(st.Options, Option{Value: m, Label: m, Detail: modelDetail(f.c.Provider, m)})
227 }230 }
@@ -578,7 +581,7 @@ func (f *Flow) Result() (Choices, Facts, string) {
578 // Base is the resolved server address ("" before a provider is chosen).581 // Base is the resolved server address ("" before a provider is chosen).
579 func (f *Flow) Base() string {582 func (f *Flow) Base() string {
580 if f.base == "" && f.c.Provider != "" {583 if f.base == "" && f.c.Provider != "" {
581- f.base = resolveBase(f.c)584+ f.base = resolveBase(f.ctx, f.c)
582 }585 }
583 return f.base586 return f.base
584 }587 }
@@ -628,7 +631,7 @@ func (f *Flow) answers(name string) bool {
628 if f.reachable == nil {631 if f.reachable == nil {
629 f.reachable = map[string]bool{}632 f.reachable = map[string]bool{}
630 for _, p := range local {633 for _, p := range local {
631- _, err := Models(f.ctx, p, resolveBase(Choices{Provider: p}))634+ _, err := Models(f.ctx, p, resolveBase(f.ctx, Choices{Provider: p}))
632 f.reachable[p] = err == nil635 f.reachable[p] = err == nil
633 }636 }
634 }637 }
modified internal/agentinit/wizard.go +61 -3
@@ -367,12 +367,70 @@ func (w *lineWizard) ask(st Step) string {
367367 }
368368 }
369369
370-// resolveBase is the server's address: the flag's, else the provider's
371-// default (or its fallback, when the default does not answer).
372-func resolveBase(c Choices) string {
370+// resolveBase is the server's address the wizard lists models from: the
371+// flag's, else the one the environment imposes (AGENT_BASE_URL…), else the
372+// first that answers of the provider's local addresses, then its fallback
373+// (chooseBase).
374+//
375+// Ticket 214: it used to take the engine's own resolution, whose probe gives
376+// the default address 2 s on /models and switches to the container fallback
377+// (host.docker.internal) without a word. mm on a Mac with Docker Desktop —
378+// where that name resolves on the host too — then listed Ollama's models
379+// from the container address. The written file is not concerned: it carries
380+// no baseUrl for the default address.
381+func resolveBase(ctx context.Context, c Choices) string {
373382 if c.BaseURL != "" {
374383 return c.BaseURL
375384 }
385+ if env := engine.EnvBaseURL(c.Provider); env != "" {
386+ return env
387+ }
388+ if base, fallback, ok := engine.DefaultURLs(c.Provider); ok {
389+ return chooseBase(base, fallback, func(url string) bool {
390+ _, err := Models(ctx, c.Provider, url)
391+ return err == nil
392+ })
393+ }
394+ return engineBase(c)
395+}
396+
397+// chooseBase picks the address to list models from: the first that lists
398+// them among the local ones (localAddresses), else the fallback when it
399+// does, else the default — whose error the model question then shows. A
400+// provider without a fallback (llamacpp, openai) is not probed at all: there
401+// is nothing to choose, and openai's default is a remote service nobody
402+// asked mm to call yet.
403+func chooseBase(base, fallback string, lists func(string) bool) string {
404+ if fallback == "" {
405+ return base
406+ }
407+ for _, url := range localAddresses(base) {
408+ if lists(url) {
409+ return url
410+ }
411+ }
412+ if lists(fallback) {
413+ return fallback
414+ }
415+ return base
416+}
417+
418+// localAddresses is the default address, then — when it names localhost —
419+// the same with 127.0.0.1: a server listening on IPv4 only does not answer
420+// a localhost that resolves to ::1 first.
421+//
422+// localAddresses("http://localhost:11434/v1") // [http://localhost:11434/v1 http://127.0.0.1:11434/v1]
423+func localAddresses(base string) []string {
424+ out := []string{base}
425+ if strings.Contains(base, "://localhost:") || strings.HasSuffix(base, "://localhost") {
426+ out = append(out, strings.Replace(base, "://localhost", "://127.0.0.1", 1))
427+ }
428+ return out
429+}
430+
431+// engineBase is the engine's own resolution, for a provider the wizard has
432+// no addresses for.
433+func engineBase(c Choices) string {
376434 p, err := engine.Lookup(c.Provider)
377435 if err != nil {
378436 return ""
@@ -367,12 +367,70 @@ func (w *lineWizard) ask(st Step) string {
367 }367 }
368 }368 }
369 369
370-// resolveBase is the server's address: the flag's, else the provider's370+// resolveBase is the server's address the wizard lists models from: the
371-// default (or its fallback, when the default does not answer).371+// flag's, else the one the environment imposes (AGENT_BASE_URL…), else the
372-func resolveBase(c Choices) string {372+// first that answers of the provider's local addresses, then its fallback
373+// (chooseBase).
374+//
375+// Ticket 214: it used to take the engine's own resolution, whose probe gives
376+// the default address 2 s on /models and switches to the container fallback
377+// (host.docker.internal) without a word. mm on a Mac with Docker Desktop —
378+// where that name resolves on the host too — then listed Ollama's models
379+// from the container address. The written file is not concerned: it carries
380+// no baseUrl for the default address.
381+func resolveBase(ctx context.Context, c Choices) string {
373 if c.BaseURL != "" {382 if c.BaseURL != "" {
374 return c.BaseURL383 return c.BaseURL
375 }384 }
385+ if env := engine.EnvBaseURL(c.Provider); env != "" {
386+ return env
387+ }
388+ if base, fallback, ok := engine.DefaultURLs(c.Provider); ok {
389+ return chooseBase(base, fallback, func(url string) bool {
390+ _, err := Models(ctx, c.Provider, url)
391+ return err == nil
392+ })
393+ }
394+ return engineBase(c)
395+}
396+
397+// chooseBase picks the address to list models from: the first that lists
398+// them among the local ones (localAddresses), else the fallback when it
399+// does, else the default — whose error the model question then shows. A
400+// provider without a fallback (llamacpp, openai) is not probed at all: there
401+// is nothing to choose, and openai's default is a remote service nobody
402+// asked mm to call yet.
403+func chooseBase(base, fallback string, lists func(string) bool) string {
404+ if fallback == "" {
405+ return base
406+ }
407+ for _, url := range localAddresses(base) {
408+ if lists(url) {
409+ return url
410+ }
411+ }
412+ if lists(fallback) {
413+ return fallback
414+ }
415+ return base
416+}
417+
418+// localAddresses is the default address, then — when it names localhost —
419+// the same with 127.0.0.1: a server listening on IPv4 only does not answer
420+// a localhost that resolves to ::1 first.
421+//
422+// localAddresses("http://localhost:11434/v1") // [http://localhost:11434/v1 http://127.0.0.1:11434/v1]
423+func localAddresses(base string) []string {
424+ out := []string{base}
425+ if strings.Contains(base, "://localhost:") || strings.HasSuffix(base, "://localhost") {
426+ out = append(out, strings.Replace(base, "://localhost", "://127.0.0.1", 1))
427+ }
428+ return out
429+}
430+
431+// engineBase is the engine's own resolution, for a provider the wizard has
432+// no addresses for.
433+func engineBase(c Choices) string {
376 p, err := engine.Lookup(c.Provider)434 p, err := engine.Lookup(c.Provider)
377 if err != nil {435 if err != nil {
378 return ""436 return ""
modified internal/agentinit/wizard_test.go +102 -0
@@ -3,13 +3,18 @@ package agentinit
33 import (
44 "bytes"
55 "context"
6+ "encoding/json"
7+ "net/http"
8+ "net/http/httptest"
69 "os"
710 "path/filepath"
811 "strings"
912 "testing"
13+ "time"
1014
1115 "mm/internal/config"
1216 "mm/internal/elicit"
17+ "mm/internal/engine"
1318 )
1419
1520 func llmmanStub(t *testing.T) string {
@@ -247,3 +252,100 @@ func TestMainToStdoutAndBadAnswers(t *testing.T) {
247252 t.Errorf("bad usage: exit %d:\n%s", code, stdout.String())
248253 }
249254 }
255+
256+// Ticket 214: the wizard lists the models from a local address whenever one
257+// answers — the default, then the same with 127.0.0.1 — and takes the
258+// container fallback only when none does. A provider without a fallback is
259+// not probed.
260+func TestChooseBasePrefersALocalAddress(t *testing.T) {
261+ const base, ipv4, fallback = "http://localhost:11434/v1", "http://127.0.0.1:11434/v1", "http://host.docker.internal:11434/v1"
262+ answering := func(urls ...string) (func(string) bool, *[]string) {
263+ var asked []string
264+ return func(url string) bool {
265+ asked = append(asked, url)
266+ for _, u := range urls {
267+ if u == url {
268+ return true
269+ }
270+ }
271+ return false
272+ }, &asked
273+ }
274+ cases := []struct {
275+ name string
276+ answer []string
277+ want string
278+ wantAsked int
279+ }{
280+ {"the default answers, the fallback too (Docker Desktop on a Mac)", []string{base, fallback}, base, 1},
281+ {"only 127.0.0.1 answers (a server on IPv4 only)", []string{ipv4, fallback}, ipv4, 2},
282+ {"only the fallback answers (mm in a container)", []string{fallback}, fallback, 3},
283+ {"nothing answers: the default, whose error the question shows", nil, base, 3},
284+ }
285+ for _, c := range cases {
286+ lists, asked := answering(c.answer...)
287+ if got := chooseBase(base, fallback, lists); got != c.want || len(*asked) != c.wantAsked {
288+ t.Errorf("%s: got %s after asking %v, want %s after %d", c.name, got, *asked, c.want, c.wantAsked)
289+ }
290+ }
291+ lists, asked := answering()
292+ if got := chooseBase("https://api.openai.com/v1", "", lists); got != "https://api.openai.com/v1" || len(*asked) != 0 {
293+ t.Errorf("no fallback: got %s, asked %v — want the default, nothing asked", got, *asked)
294+ }
295+}
296+
297+func TestLocalAddresses(t *testing.T) {
298+ for in, want := range map[string]string{
299+ "http://localhost:11434/v1": "http://localhost:11434/v1 http://127.0.0.1:11434/v1",
300+ "http://localhost:12434/engines/v1": "http://localhost:12434/engines/v1 http://127.0.0.1:12434/engines/v1",
301+ "http://127.0.0.1:17434/v1": "http://127.0.0.1:17434/v1",
302+ } {
303+ if got := strings.Join(localAddresses(in), " "); got != want {
304+ t.Errorf("localAddresses(%s) = %s, want %s", in, got, want)
305+ }
306+ }
307+}
308+
309+// The address comes from the model list, not the engine's 2 s probe of
310+// /models: a server whose /v1/models is slow but whose list answers is kept
311+// — before ticket 214, the probe gave up and the fallback was taken.
312+func TestResolveBaseKeepsASlowLocalServer(t *testing.T) {
313+ slow := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
314+ switch r.URL.Path {
315+ case "/api/tags":
316+ _ = json.NewEncoder(w).Encode(map[string]any{"models": []any{map[string]any{"name": "qwen3.5:4b"}}})
317+ case "/v1/models":
318+ time.Sleep(3 * time.Second) // longer than the engine's probe
319+ _ = json.NewEncoder(w).Encode(map[string]any{"data": []any{}})
320+ default:
321+ http.NotFound(w, r)
322+ }
323+ }))
324+ t.Cleanup(slow.Close)
325+ base := slow.URL + "/v1"
326+ // The engine's own resolution — what the wizard used before — gives up
327+ // on this server and takes the fallback.
328+ fallback := "http://host.docker.internal:1/v1"
329+ p, err := engine.Lookup("ollama")
330+ if err != nil {
331+ t.Fatal(err)
332+ }
333+ if b, err := p.Resolve(config.Config{Provider: "ollama", Model: "probe", BaseURL: base, Fallback: &fallback}); err != nil || b.BaseURL != fallback {
334+ t.Fatalf("the engine's probe kept %s (%v): the test server is not slow enough to show ticket 214", b.BaseURL, err)
335+ }
336+ got := chooseBase(base, fallback, func(url string) bool {
337+ _, err := Models(context.Background(), "ollama", url)
338+ return err == nil
339+ })
340+ if got != base {
341+ t.Errorf("got %s, want the local server %s", got, base)
342+ }
343+}
344+
345+// An address imposed by the environment is taken as is, like the engine does.
346+func TestResolveBaseHonoursAgentBaseURL(t *testing.T) {
347+ t.Setenv("AGENT_BASE_URL", "http://example.invalid:9/v1")
348+ if got := resolveBase(context.Background(), Choices{Provider: "ollama"}); got != "http://example.invalid:9/v1" {
349+ t.Errorf("got %s", got)
350+ }
351+}
@@ -3,13 +3,18 @@ package agentinit
3 import (3 import (
4 "bytes"4 "bytes"
5 "context"5 "context"
6+ "encoding/json"
7+ "net/http"
8+ "net/http/httptest"
6 "os"9 "os"
7 "path/filepath"10 "path/filepath"
8 "strings"11 "strings"
9 "testing"12 "testing"
13+ "time"
10 14
11 "mm/internal/config"15 "mm/internal/config"
12 "mm/internal/elicit"16 "mm/internal/elicit"
17+ "mm/internal/engine"
13 )18 )
14 19
15 func llmmanStub(t *testing.T) string {20 func llmmanStub(t *testing.T) string {
@@ -247,3 +252,100 @@ func TestMainToStdoutAndBadAnswers(t *testing.T) {
247 t.Errorf("bad usage: exit %d:\n%s", code, stdout.String())252 t.Errorf("bad usage: exit %d:\n%s", code, stdout.String())
248 }253 }
249 }254 }
255+
256+// Ticket 214: the wizard lists the models from a local address whenever one
257+// answers — the default, then the same with 127.0.0.1 — and takes the
258+// container fallback only when none does. A provider without a fallback is
259+// not probed.
260+func TestChooseBasePrefersALocalAddress(t *testing.T) {
261+ const base, ipv4, fallback = "http://localhost:11434/v1", "http://127.0.0.1:11434/v1", "http://host.docker.internal:11434/v1"
262+ answering := func(urls ...string) (func(string) bool, *[]string) {
263+ var asked []string
264+ return func(url string) bool {
265+ asked = append(asked, url)
266+ for _, u := range urls {
267+ if u == url {
268+ return true
269+ }
270+ }
271+ return false
272+ }, &asked
273+ }
274+ cases := []struct {
275+ name string
276+ answer []string
277+ want string
278+ wantAsked int
279+ }{
280+ {"the default answers, the fallback too (Docker Desktop on a Mac)", []string{base, fallback}, base, 1},
281+ {"only 127.0.0.1 answers (a server on IPv4 only)", []string{ipv4, fallback}, ipv4, 2},
282+ {"only the fallback answers (mm in a container)", []string{fallback}, fallback, 3},
283+ {"nothing answers: the default, whose error the question shows", nil, base, 3},
284+ }
285+ for _, c := range cases {
286+ lists, asked := answering(c.answer...)
287+ if got := chooseBase(base, fallback, lists); got != c.want || len(*asked) != c.wantAsked {
288+ t.Errorf("%s: got %s after asking %v, want %s after %d", c.name, got, *asked, c.want, c.wantAsked)
289+ }
290+ }
291+ lists, asked := answering()
292+ if got := chooseBase("https://api.openai.com/v1", "", lists); got != "https://api.openai.com/v1" || len(*asked) != 0 {
293+ t.Errorf("no fallback: got %s, asked %v — want the default, nothing asked", got, *asked)
294+ }
295+}
296+
297+func TestLocalAddresses(t *testing.T) {
298+ for in, want := range map[string]string{
299+ "http://localhost:11434/v1": "http://localhost:11434/v1 http://127.0.0.1:11434/v1",
300+ "http://localhost:12434/engines/v1": "http://localhost:12434/engines/v1 http://127.0.0.1:12434/engines/v1",
301+ "http://127.0.0.1:17434/v1": "http://127.0.0.1:17434/v1",
302+ } {
303+ if got := strings.Join(localAddresses(in), " "); got != want {
304+ t.Errorf("localAddresses(%s) = %s, want %s", in, got, want)
305+ }
306+ }
307+}
308+
309+// The address comes from the model list, not the engine's 2 s probe of
310+// /models: a server whose /v1/models is slow but whose list answers is kept
311+// — before ticket 214, the probe gave up and the fallback was taken.
312+func TestResolveBaseKeepsASlowLocalServer(t *testing.T) {
313+ slow := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
314+ switch r.URL.Path {
315+ case "/api/tags":
316+ _ = json.NewEncoder(w).Encode(map[string]any{"models": []any{map[string]any{"name": "qwen3.5:4b"}}})
317+ case "/v1/models":
318+ time.Sleep(3 * time.Second) // longer than the engine's probe
319+ _ = json.NewEncoder(w).Encode(map[string]any{"data": []any{}})
320+ default:
321+ http.NotFound(w, r)
322+ }
323+ }))
324+ t.Cleanup(slow.Close)
325+ base := slow.URL + "/v1"
326+ // The engine's own resolution — what the wizard used before — gives up
327+ // on this server and takes the fallback.
328+ fallback := "http://host.docker.internal:1/v1"
329+ p, err := engine.Lookup("ollama")
330+ if err != nil {
331+ t.Fatal(err)
332+ }
333+ if b, err := p.Resolve(config.Config{Provider: "ollama", Model: "probe", BaseURL: base, Fallback: &fallback}); err != nil || b.BaseURL != fallback {
334+ t.Fatalf("the engine's probe kept %s (%v): the test server is not slow enough to show ticket 214", b.BaseURL, err)
335+ }
336+ got := chooseBase(base, fallback, func(url string) bool {
337+ _, err := Models(context.Background(), "ollama", url)
338+ return err == nil
339+ })
340+ if got != base {
341+ t.Errorf("got %s, want the local server %s", got, base)
342+ }
343+}
344+
345+// An address imposed by the environment is taken as is, like the engine does.
346+func TestResolveBaseHonoursAgentBaseURL(t *testing.T) {
347+ t.Setenv("AGENT_BASE_URL", "http://example.invalid:9/v1")
348+ if got := resolveBase(context.Background(), Choices{Provider: "ollama"}); got != "http://example.invalid:9/v1" {
349+ t.Errorf("got %s", got)
350+ }
351+}
modified internal/engine/openai_compat.go +20 -1
@@ -87,6 +87,20 @@ func DefaultURLs(provider string) (baseURL, fallback string, ok bool) {
8787 return p.baseURL, p.fallback, true
8888 }
8989
90+// EnvBaseURL is the address the environment imposes on a provider —
91+// AGENT_BASE_URL, else the provider's legacy variable (DMR_BASE_URL) — or
92+// "" when none is set. Resolve takes it as is, without probing; so does
93+// `mm init` (ticket 214).
94+func EnvBaseURL(provider string) string {
95+ if env := os.Getenv("AGENT_BASE_URL"); env != "" {
96+ return env
97+ }
98+ if p, found := registry[provider].(*openaiCompat); found && p.legacyBaseURLEnv != "" {
99+ return os.Getenv(p.legacyBaseURLEnv)
100+ }
101+ return ""
102+}
103+
90104 func init() {
91105 register(&openaiCompat{
92106 name: "dmr",
@@ -104,11 +118,16 @@ func init() {
104118 register(&openaiCompat{
105119 name: "llamacpp",
106120 baseURL: "http://127.0.0.1:8080/v1", // llama-server's default host:port, plus the OpenAI prefix
121+ // From a container or a sandbox, like the other local servers
122+ // (ticket 217). llama-server listens on the loopback only unless
123+ // started with --host 0.0.0.0, which Linux and a Docker Sandbox need
124+ // for this name to reach it (Docker Desktop reaches the loopback).
125+ fallback: "http://host.docker.internal:8080/v1",
107126 // llama-server only checks a key when started with --api-key; most
108127 // local set-ups are not, so an unset LLAMA_API_KEY is normal.
109128 apiKeyEnv: "LLAMA_API_KEY",
110129 dummyKey: "not-needed",
111- startHint: "start it: llama-server -m <model.gguf> --jinja --port 8080",
130+ startHint: "start it: llama-server -m <model.gguf> --jinja --port 8080 (add --host 0.0.0.0 when mm runs in a container or a sandbox)",
112131 notFoundHint: "llama-server serves one model; check baseUrl ends with /v1 (model: %s)",
113132 probe: probeLlamaCpp,
114133 progress: true,
@@ -87,6 +87,20 @@ func DefaultURLs(provider string) (baseURL, fallback string, ok bool) {
87 return p.baseURL, p.fallback, true87 return p.baseURL, p.fallback, true
88 }88 }
89 89
90+// EnvBaseURL is the address the environment imposes on a provider —
91+// AGENT_BASE_URL, else the provider's legacy variable (DMR_BASE_URL) — or
92+// "" when none is set. Resolve takes it as is, without probing; so does
93+// `mm init` (ticket 214).
94+func EnvBaseURL(provider string) string {
95+ if env := os.Getenv("AGENT_BASE_URL"); env != "" {
96+ return env
97+ }
98+ if p, found := registry[provider].(*openaiCompat); found && p.legacyBaseURLEnv != "" {
99+ return os.Getenv(p.legacyBaseURLEnv)
100+ }
101+ return ""
102+}
103+
90 func init() {104 func init() {
91 register(&openaiCompat{105 register(&openaiCompat{
92 name: "dmr",106 name: "dmr",
@@ -104,11 +118,16 @@ func init() {
104 register(&openaiCompat{118 register(&openaiCompat{
105 name: "llamacpp",119 name: "llamacpp",
106 baseURL: "http://127.0.0.1:8080/v1", // llama-server's default host:port, plus the OpenAI prefix120 baseURL: "http://127.0.0.1:8080/v1", // llama-server's default host:port, plus the OpenAI prefix
121+ // From a container or a sandbox, like the other local servers
122+ // (ticket 217). llama-server listens on the loopback only unless
123+ // started with --host 0.0.0.0, which Linux and a Docker Sandbox need
124+ // for this name to reach it (Docker Desktop reaches the loopback).
125+ fallback: "http://host.docker.internal:8080/v1",
107 // llama-server only checks a key when started with --api-key; most126 // llama-server only checks a key when started with --api-key; most
108 // local set-ups are not, so an unset LLAMA_API_KEY is normal.127 // local set-ups are not, so an unset LLAMA_API_KEY is normal.
109 apiKeyEnv: "LLAMA_API_KEY",128 apiKeyEnv: "LLAMA_API_KEY",
110 dummyKey: "not-needed",129 dummyKey: "not-needed",
111- startHint: "start it: llama-server -m <model.gguf> --jinja --port 8080",130+ startHint: "start it: llama-server -m <model.gguf> --jinja --port 8080 (add --host 0.0.0.0 when mm runs in a container or a sandbox)",
112 notFoundHint: "llama-server serves one model; check baseUrl ends with /v1 (model: %s)",131 notFoundHint: "llama-server serves one model; check baseUrl ends with /v1 (model: %s)",
113 probe: probeLlamaCpp,132 probe: probeLlamaCpp,
114 progress: true,133 progress: true,
modified internal/engine/provider_test.go +11 -6
@@ -108,10 +108,13 @@ func TestResolveURLPrecedence(t *testing.T) {
108108 {"an explicit empty fallback disables it", "dmr", config.Config{BaseURL: down, Fallback: ptr("")}, nil, down, "not-needed"},
109109 {"AGENT_BASE_URL wins without probing", "dmr", config.Config{BaseURL: up.URL, Fallback: ptr("")}, map[string]string{"AGENT_BASE_URL": down}, down, "not-needed"},
110110 {"DMR_BASE_URL still works for dmr", "dmr", config.Config{BaseURL: up.URL, Fallback: ptr("")}, map[string]string{"DMR_BASE_URL": down}, down, "not-needed"},
111- {"llamacpp default is llama-server's port", "llamacpp", config.Config{}, nil, "http://127.0.0.1:8080/v1", "not-needed"},
112- {"llamacpp ignores DMR_BASE_URL", "llamacpp", config.Config{}, map[string]string{"DMR_BASE_URL": down}, "http://127.0.0.1:8080/v1", "not-needed"},
113- {"llamacpp reads LLAMA_API_KEY when set", "llamacpp", config.Config{}, map[string]string{"LLAMA_API_KEY": "secret"}, "http://127.0.0.1:8080/v1", "secret"},
114- {"apiKeyEnv names another variable", "llamacpp", config.Config{APIKeyEnv: "MY_KEY"}, map[string]string{"MY_KEY": "k2"}, "http://127.0.0.1:8080/v1", "k2"},
111+ // llamacpp falls back on the host like the other local servers
112+ // since ticket 217 (its default address: TestDefaultURLs).
113+ {"llamacpp falls back to the host's llama-server", "llamacpp", config.Config{BaseURL: down}, nil, "http://host.docker.internal:8080/v1", "not-needed"},
114+ {"llamacpp keeps a reachable baseUrl", "llamacpp", config.Config{BaseURL: up.URL}, nil, up.URL, "not-needed"},
115+ {"llamacpp ignores DMR_BASE_URL", "llamacpp", config.Config{BaseURL: up.URL}, map[string]string{"DMR_BASE_URL": down}, up.URL, "not-needed"},
116+ {"llamacpp reads LLAMA_API_KEY when set", "llamacpp", config.Config{BaseURL: up.URL}, map[string]string{"LLAMA_API_KEY": "secret"}, up.URL, "secret"},
117+ {"apiKeyEnv names another variable", "llamacpp", config.Config{BaseURL: up.URL, APIKeyEnv: "MY_KEY"}, map[string]string{"MY_KEY": "k2"}, up.URL, "k2"},
115118 {"llmman falls back to the host's daemon", "llmman", config.Config{BaseURL: down}, nil, "http://host.docker.internal:17434/v1", "not-needed"},
116119 {"llmman keeps a reachable baseUrl", "llmman", config.Config{BaseURL: up.URL}, nil, up.URL, "not-needed"},
117120 {"llmman reads LLMMAN_API_KEY when set", "llmman", config.Config{BaseURL: up.URL}, map[string]string{"LLMMAN_API_KEY": "k3", "LLAMA_API_KEY": "secret"}, up.URL, "k3"},
@@ -445,7 +448,9 @@ func TestConfigCompat(t *testing.T) {
445448 }
446449
447450 config.Cfg = saved
448- llama := write("llama.yaml", "provider: llamacpp\nmodel: qwen2.5-coder\ncontextWindow: 16384\n")
451+ // fallback: "" keeps the default address whether llama-server runs or
452+ // not (it has a fallback since ticket 217).
453+ llama := write("llama.yaml", "provider: llamacpp\nmodel: qwen2.5-coder\ncontextWindow: 16384\nfallback: \"\"\n")
449454 if _, err := config.Load(llama); err != nil {
450455 t.Fatalf("Load(llamacpp config): %v", err)
451456 }
@@ -559,7 +564,7 @@ func TestDefaultURLs(t *testing.T) {
559564 {"ollama", "http://localhost:11434/v1", "http://host.docker.internal:11434/v1"},
560565 {"kronk", "http://127.0.0.1:11435/v1", "http://host.docker.internal:11435/v1"},
561566 {"dmr", "http://localhost:12434/engines/v1", "http://host.docker.internal:12434/engines/v1"},
562- {"llamacpp", "http://127.0.0.1:8080/v1", ""},
567+ {"llamacpp", "http://127.0.0.1:8080/v1", "http://host.docker.internal:8080/v1"},
563568 {"openai", "https://api.openai.com/v1", ""},
564569 }
565570 for _, c := range cases {
@@ -108,10 +108,13 @@ func TestResolveURLPrecedence(t *testing.T) {
108 {"an explicit empty fallback disables it", "dmr", config.Config{BaseURL: down, Fallback: ptr("")}, nil, down, "not-needed"},108 {"an explicit empty fallback disables it", "dmr", config.Config{BaseURL: down, Fallback: ptr("")}, nil, down, "not-needed"},
109 {"AGENT_BASE_URL wins without probing", "dmr", config.Config{BaseURL: up.URL, Fallback: ptr("")}, map[string]string{"AGENT_BASE_URL": down}, down, "not-needed"},109 {"AGENT_BASE_URL wins without probing", "dmr", config.Config{BaseURL: up.URL, Fallback: ptr("")}, map[string]string{"AGENT_BASE_URL": down}, down, "not-needed"},
110 {"DMR_BASE_URL still works for dmr", "dmr", config.Config{BaseURL: up.URL, Fallback: ptr("")}, map[string]string{"DMR_BASE_URL": down}, down, "not-needed"},110 {"DMR_BASE_URL still works for dmr", "dmr", config.Config{BaseURL: up.URL, Fallback: ptr("")}, map[string]string{"DMR_BASE_URL": down}, down, "not-needed"},
111- {"llamacpp default is llama-server's port", "llamacpp", config.Config{}, nil, "http://127.0.0.1:8080/v1", "not-needed"},111+ // llamacpp falls back on the host like the other local servers
112- {"llamacpp ignores DMR_BASE_URL", "llamacpp", config.Config{}, map[string]string{"DMR_BASE_URL": down}, "http://127.0.0.1:8080/v1", "not-needed"},112+ // since ticket 217 (its default address: TestDefaultURLs).
113- {"llamacpp reads LLAMA_API_KEY when set", "llamacpp", config.Config{}, map[string]string{"LLAMA_API_KEY": "secret"}, "http://127.0.0.1:8080/v1", "secret"},113+ {"llamacpp falls back to the host's llama-server", "llamacpp", config.Config{BaseURL: down}, nil, "http://host.docker.internal:8080/v1", "not-needed"},
114- {"apiKeyEnv names another variable", "llamacpp", config.Config{APIKeyEnv: "MY_KEY"}, map[string]string{"MY_KEY": "k2"}, "http://127.0.0.1:8080/v1", "k2"},114+ {"llamacpp keeps a reachable baseUrl", "llamacpp", config.Config{BaseURL: up.URL}, nil, up.URL, "not-needed"},
115+ {"llamacpp ignores DMR_BASE_URL", "llamacpp", config.Config{BaseURL: up.URL}, map[string]string{"DMR_BASE_URL": down}, up.URL, "not-needed"},
116+ {"llamacpp reads LLAMA_API_KEY when set", "llamacpp", config.Config{BaseURL: up.URL}, map[string]string{"LLAMA_API_KEY": "secret"}, up.URL, "secret"},
117+ {"apiKeyEnv names another variable", "llamacpp", config.Config{BaseURL: up.URL, APIKeyEnv: "MY_KEY"}, map[string]string{"MY_KEY": "k2"}, up.URL, "k2"},
115 {"llmman falls back to the host's daemon", "llmman", config.Config{BaseURL: down}, nil, "http://host.docker.internal:17434/v1", "not-needed"},118 {"llmman falls back to the host's daemon", "llmman", config.Config{BaseURL: down}, nil, "http://host.docker.internal:17434/v1", "not-needed"},
116 {"llmman keeps a reachable baseUrl", "llmman", config.Config{BaseURL: up.URL}, nil, up.URL, "not-needed"},119 {"llmman keeps a reachable baseUrl", "llmman", config.Config{BaseURL: up.URL}, nil, up.URL, "not-needed"},
117 {"llmman reads LLMMAN_API_KEY when set", "llmman", config.Config{BaseURL: up.URL}, map[string]string{"LLMMAN_API_KEY": "k3", "LLAMA_API_KEY": "secret"}, up.URL, "k3"},120 {"llmman reads LLMMAN_API_KEY when set", "llmman", config.Config{BaseURL: up.URL}, map[string]string{"LLMMAN_API_KEY": "k3", "LLAMA_API_KEY": "secret"}, up.URL, "k3"},
@@ -445,7 +448,9 @@ func TestConfigCompat(t *testing.T) {
445 }448 }
446 449
447 config.Cfg = saved450 config.Cfg = saved
448- llama := write("llama.yaml", "provider: llamacpp\nmodel: qwen2.5-coder\ncontextWindow: 16384\n")451+ // fallback: "" keeps the default address whether llama-server runs or
452+ // not (it has a fallback since ticket 217).
453+ llama := write("llama.yaml", "provider: llamacpp\nmodel: qwen2.5-coder\ncontextWindow: 16384\nfallback: \"\"\n")
449 if _, err := config.Load(llama); err != nil {454 if _, err := config.Load(llama); err != nil {
450 t.Fatalf("Load(llamacpp config): %v", err)455 t.Fatalf("Load(llamacpp config): %v", err)
451 }456 }
@@ -559,7 +564,7 @@ func TestDefaultURLs(t *testing.T) {
559 {"ollama", "http://localhost:11434/v1", "http://host.docker.internal:11434/v1"},564 {"ollama", "http://localhost:11434/v1", "http://host.docker.internal:11434/v1"},
560 {"kronk", "http://127.0.0.1:11435/v1", "http://host.docker.internal:11435/v1"},565 {"kronk", "http://127.0.0.1:11435/v1", "http://host.docker.internal:11435/v1"},
561 {"dmr", "http://localhost:12434/engines/v1", "http://host.docker.internal:12434/engines/v1"},566 {"dmr", "http://localhost:12434/engines/v1", "http://host.docker.internal:12434/engines/v1"},
562- {"llamacpp", "http://127.0.0.1:8080/v1", ""},567+ {"llamacpp", "http://127.0.0.1:8080/v1", "http://host.docker.internal:8080/v1"},
563 {"openai", "https://api.openai.com/v1", ""},568 {"openai", "https://api.openai.com/v1", ""},
564 }569 }
565 for _, c := range cases {570 for _, c := range cases {