overmind-mcp 2.8.50 → 2.8.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/bin/cli.js +30 -4
  2. package/dist/bin/cli.js.map +1 -1
  3. package/dist/lib/orchestration/swarm.js +2 -2
  4. package/dist/lib/orchestration/swarm.js.map +1 -1
  5. package/dist/lib/processRegistry.js +2 -2
  6. package/dist/lib/processRegistry.js.map +1 -1
  7. package/dist/lib/sessions.js +2 -2
  8. package/dist/lib/sessions.js.map +1 -1
  9. package/dist/memory/MemoryFactory.js +2 -2
  10. package/dist/memory/MemoryFactory.js.map +1 -1
  11. package/dist/memory/PostgresMemoryProvider.d.ts.map +1 -1
  12. package/dist/memory/PostgresMemoryProvider.js +2 -2
  13. package/dist/memory/PostgresMemoryProvider.js.map +1 -1
  14. package/dist/services/ClineRunner.js +2 -2
  15. package/dist/services/ClineRunner.js.map +1 -1
  16. package/dist/services/GeminiRunner.js +2 -2
  17. package/dist/services/GeminiRunner.js.map +1 -1
  18. package/dist/services/NousHermesRunner.js +2 -2
  19. package/dist/services/NousHermesRunner.js.map +1 -1
  20. package/dist/services/OpenClawRunner.js +2 -2
  21. package/dist/services/OpenClawRunner.js.map +1 -1
  22. package/dist/services/OpenCodeRunner.js +2 -2
  23. package/dist/services/OpenCodeRunner.js.map +1 -1
  24. package/dist/services/QwenCliRunner.js +2 -2
  25. package/dist/services/QwenCliRunner.js.map +1 -1
  26. package/dist/services/hermes/binaryFinder.js +2 -2
  27. package/dist/services/hermes/binaryFinder.js.map +1 -1
  28. package/dist/services/hermes/configYamlFilter.js +2 -2
  29. package/dist/services/hermes/configYamlFilter.js.map +1 -1
  30. package/dist/services/hermes/processUtils.js +2 -2
  31. package/dist/services/hermes/processUtils.js.map +1 -1
  32. package/docs/OVERMIND_HERMES_SNIPERBOT_FLOW.md +1 -1
  33. package/docs/SETUP_HERMES_AGENT_FROM_SCRATCH.md +18 -18
  34. package/docs/SUBTILISATION_EXPLAINED.md +2 -2
  35. package/docs/agent-http-tutorial.md +524 -524
  36. package/docs/doc_guide_agent_hermes_permanent.md +1 -1
  37. package/docs/doc_hermes_gateway.md +2 -2
  38. package/docs/guide_agent_hermes_overmind.md +1 -1
  39. package/docs/provider-config-map.md +556 -556
  40. package/package.json +1 -1
  41. package/docs/PLAN_REFACTORING_OVERMIND_V2.md +0 -414
  42. package/docs/PLAN_REFACTOR_OVERMIND_AGI.md +0 -606
@@ -1,557 +1,557 @@
1
- # Hermes x Overmind — Config Provider Map
2
-
3
- ## Ordre de resolution (qui gagne, qui perd)
4
-
5
- Chaque variable suit cette priorite (la premiere gagne):
6
-
7
- ```
8
- process.env (env du parent, herite par le spawn)
9
-
10
- Workflow/.env (C:\Users\Deamon\Desktop\Backup\Serveur MCP\Workflow\.env)
11
-
12
- settings_[agent].json → env (apres interpolation $VAR par process.env)
13
-
14
- HERMES_HOME/.env (C:\Users\Deamon\AppData\Local\hermes\.env) ← DERNIER MOT
15
- ```
16
-
17
- **Detail du code** (`NousHermesRunner.ts` l.268-456):
18
- 1. `agentCustomEnv = { ...process.env, ...settings.env }` (line 268 puis 384)
19
- 2. Puis lit `overmindHermesSubPath/.env` (le `.hermes/.env` de l'agent) et fait `agentCustomEnv[key] = value` (line 437-456) — ce qui OVERRIDE tout ce qui precede.
20
- 3. Finalement ecrit ce `agentCustomEnv` dans le `.env` final de l'agent (line 722-732) avec dedup sur les cles `*api_key` / `*auth_token`.
21
-
22
- Donc le `.hermes/.env` de l'agent a **toujours le dernier mot**. Si tu mets `MINIMAX_API_KEY=*** dans le .hermes/.env, il ecrase `MINIMAX_API_KEY` du process.env et du settings.
23
-
24
- **MAIS** pour `OPENROUTER_API_KEY` uniquement:
25
- - Hermes lit d'abord `HERMES_HOME/.env` puis `os.environ`
26
- - Si present dans `auth.json` avec status `exhausted` → skip
27
- - Si present dans `HERMES_HOME/.env` (meme vide `""`) → **PREND LA PRIORITE sur process.env**
28
-
29
- **MAIS** pour tous les autres providers (zai, minimax-cn, etc.):
30
- - Hermes lit `HERMES_HOME/.env` → si vide/null → lit `os.environ`
31
- - `os.environ` contient tout ce que le parent a passe (donc le `.env` du Workflow)
32
-
33
- ---
34
-
35
- ## Les 5 fichiers cles
36
-
37
- | Fichier | Role |
38
- |---|---|
39
- | `HERMES_HOME/.env` | API keys globales Hermes (fallback) |
40
- | `Workflow/.env` | Variables du workflow (DB, tokens, etc.) |
41
- | `settings_[agent].json` | Config par agent (model, provider, tokens, MCP) |
42
- | `HERMES_HOME/.hermes/config.yaml` | Config systeme Hermes (model.default, provider, etc.) |
43
- | `HERMES_HOME/auth.json` | Credential pool — status des tokens (ok/exhausted), URLs par provider |
44
-
45
- ---
46
-
47
- ## Les 2 endpoints Z.AI (DECOUVERTE CRITIQUE)
48
-
49
- Z.AI a **deux endpoints distincts** — confusion entre les deux causait des erreurs 402:
50
-
51
- | Endpoint | URL | Usage |
52
- |---|---|---|
53
- | **Coding** (celui qu'il faut) | `https://api.z.ai/api/coding/paas/v4` | Inference LLM (Hermes, Overmind) |
54
- | **Non-coding** (ancien, different billing) | `https://api.z.ai/api/paas/v4` | Autre chose (pas le meme systeme de facturation) |
55
-
56
- **Comment le credential pool est seed:**
57
-
58
- | Source dans .env | Cle dans auth.json | base_url assignee |
59
- |---|---|---|
60
- | `ZAI_ANTHROPIC_FALLBACK_KEY` | `zai[0].access_token` | `https://api.z.ai/api/coding/paas/v4` ✅ |
61
- | `Z_AI_API_KEY` | `zai[1].access_token` | `https://api.z.ai/api/paas/v4` ❌ (ancien) |
62
-
63
- Le premier entry (priority 0) est utilise en premier. C'est celui qui est seed par `writeAuthJson()` dans `NousHermesRunner.ts` → `ZAI_ANTHROPIC_FALLBACK_KEY`.
64
-
65
- ---
66
-
67
- ## Provider → Ce qu'Hermes attend
68
-
69
- ### Z.AI (id: `zai`)
70
-
71
- | Param | Valeur attendue | Source dans Hermes |
72
- |---|---|---|
73
- | Provider ID | `zai` | config.yaml ou settings |
74
- | API Key | `ZAI_ANTHROPIC_FALLBACK_KEY` (cle primaire) ou `Z_AI_API_KEY` (fallback ancien) | `HERMES_HOME/.env` → `os.environ` |
75
- | Base URL | `https://api.z.ai/api/coding/paas/v4` | credential pool (seed par writeAuthJson) |
76
- | Model | `glm-5.1` | settings `env.ANTHROPIC_MODEL` |
77
-
78
- ```json
79
- // settings_[agent].json — Z.AI correct
80
- {
81
- "env": {
82
- "ANTHROPIC_AUTH_TOKEN": "$ZAI_ANTHROPIC_FALLBACK_KEY",
83
- "ANTHROPIC_BASE_URL": "https://api.z.ai/api/coding/paas/v4",
84
- "ANTHROPIC_MODEL": "glm-5.1"
85
- }
86
- }
87
- ```
88
-
89
- ```bash
90
- # .env minimal pour Z.AI
91
- ZAI_ANTHROPIC_FALLBACK_KEY=5f650035e5a845549e4765184d8179b1.GdehlMpHT0dKq3m3
92
- ```
93
-
94
- Le credential pool `auth.json` est ecrit par `writeAuthJson()` dans `NousHermesRunner.ts`. La cle `ZAI_ANTHROPIC_FALLBACK_KEY` est envoyee par `agentCustomEnv` → Hermes seed le credential pool avec le bon endpoint.
95
-
96
- ---
97
-
98
- ### Z.AI Multi-Token (E/Y)
99
-
100
- Deamon a 2 tokens Z.AI (E=primary, Y=secondary). Le credential pool peut contenir les deux:
101
-
102
- | Token | Label dans auth.json | Cle dans .env |
103
- |---|---|---|
104
- | Primary | `ANTHROPIC_AUTH_TOKEN_E` | `ANTHROPIC_AUTH_TOKEN_E` = `5f65...q3m3` |
105
- | Secondary | `ANTHROPIC_AUTH_TOKEN_Y` | `ANTHROPIC_AUTH_TOKEN_Y` = `c78a...1ISt` |
106
-
107
- Pour qu'un agent utilise le token Y (secondary) au lieu de E (primary), le settings doit utiliser `$ANTHROPIC_AUTH_TOKEN_Y` au lieu de `$ANTHROPIC_AUTH_TOKEN_E`.
108
-
109
- ---
110
-
111
- ### MiniMax CN (id: `minimax-cn`)
112
-
113
- | Param | Valeur attendue | Source dans Hermes |
114
- |---|---|---|
115
- | Provider ID | `minimax-cn` | config.yaml ou settings |
116
- | API Key | `MINIMAX_CN_API_KEY` **uniquement** | `HERMES_HOME/.env` → `os.environ` |
117
- | Base URL | `https://api.minimaxi.com/anthropic` | hardcoded dans ProviderConfig |
118
- | Model | `MiniMax-M3` | settings `env.ANTHROPIC_MODEL` |
119
-
120
- ```json
121
- // settings_[agent].json — MiniMax correct
122
- {
123
- "env": {
124
- "ANTHROPIC_AUTH_TOKEN": "$MINIMAX_CN_API_KEY",
125
- "ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic",
126
- "ANTHROPIC_MODEL": "MiniMax-M3"
127
- }
128
- }
129
- ```
130
-
131
- ```bash
132
- # .env minimal pour MiniMax CN
133
- MINIMAX_CN_API_KEY=ton_token_minimax_ici
134
- ```
135
-
136
- **auth.json** stocke sous `MINIMAX_CN_API_KEY`.
137
-
138
- #### MiniMax CN par défaut (convention)
139
-
140
- Le préfixe `sk-cp-` est partagé entre MiniMax GLOBAL (`api.minimax.com`) et
141
- MiniMax CN (`api.minimaxi.com`). L'URL est le seul signal qui disambiguïse.
142
- Pour les setups où TOUS les tokens MiniMax sont CN (cas le plus commun),
143
- le runner a un fallback par défaut : quand un token `sk-cp-*` est détecté
144
- sans URL explicite, on bascule sur CN.
145
-
146
- Controlable via env var :
147
-
148
- ```bash
149
- # Défaut (recommandé pour les setups CN-only)
150
- OVERMIND_MINIMAX_DEFAULT=cn # sk-cp-* sans URL → minimax-cn
151
-
152
- # Pour les setups GLOBAL-only
153
- OVERMIND_MINIMAX_DEFAULT=global # sk-cp-* sans URL → minimax
154
-
155
- # Strict mode (jamais d'inference, URL obligatoire)
156
- OVERMIND_MINIMAX_DEFAULT=auto # sk-cp-* sans URL → minimax (no override)
157
- ```
158
-
159
- Si une URL explicite est présente dans `ANTHROPIC_BASE_URL`, elle gagne
160
- toujours sur `OVERMIND_MINIMAX_DEFAULT`.
161
-
162
- ---
163
-
164
- ### OpenRouter — BANNIR pour LLM
165
-
166
- | Param | Valeur attendue | Source |
167
- |---|---|---|
168
- | Provider ID | — | **Ne PAS utiliser** |
169
- | API Key | `OPENROUTER_API_KEY` | `HERMES_HOME/.env` → `os.environ` |
170
- | Base URL | `https://openrouter.ai/api/v1` | hardcoded |
171
- | Guardrail | — | Force 404 si active |
172
-
173
- **PROBLEME:** Si `OPENROUTER_API_KEY` est present (meme dans `OVERMIND_EMBEDDING_KEY` route via NousHermesRunner), Hermes le detecte et tente OpenRouter pour l'inference.
174
-
175
- **auth.json** a une entree OpenRouter — si le status est `exhausted`, Hermes ne retry plus mais peut quand meme picker le provider "openrouter" dans le credential pool.
176
-
177
- ---
178
-
179
- ## Ne PAS passer --provider au CLI Hermes (NOUVEAU en 2.8.28)
180
-
181
- Le runner Overmind **ne passe plus** le flag `--provider` au CLI Hermes.
182
- Découverte empirique (le `Hermes-MiniMax-2.bat` du bureau marche mais
183
- le sniperbot échoue) :
184
-
185
- | Commande | Résultat |
186
- |---|---|
187
- | `hermes chat -q --provider minimax-cn ...` | **401** (bug plugin upstream) |
188
- | `hermes chat --yolo` (sans --provider) | **200 OK** |
189
-
190
- **Cause** : le flag `--provider` explicite active un code path buggé
191
- dans le plugin Hermes upstream (`hermes-agent/plugins/model-providers/minimax/`)
192
- qui envoie un format d'auth header rejeté par `api.minimaxi.com`.
193
-
194
- **Fix appliqué** : le runner retire `--provider` de `cleanArgs` mais
195
- loggue le `resolvedProvider` à INFO pour debug. Hermes auto-détecte
196
- le bon provider depuis l'env var :
197
- - `MINIMAX_CN_API_KEY` → plugin `minimax-cn`
198
- - `MINIMAX_API_KEY` → plugin `minimax` (GLOBAL)
199
- - `ZAI_ANTHROPIC_FALLBACK_KEY` ou `GLM_API_KEY` → plugin `zai`
200
- - `ANTHROPIC_AUTH_TOKEN` avec préfixe `sk-ant-` → plugin `anthropic`
201
-
202
- `ANTHROPIC_BASE_URL` et `ANTHROPIC_MODEL` sont toujours passés, donc
203
- Hermes a assez d'info pour ne pas se tromper.
204
-
205
-
206
- ## HERMES_HOME resolution (multi-OS, multi-install)
207
-
208
- Chaque agent Hermes a son propre HERMES_HOME. Le path est resolu de maniere
209
- deterministe par `getAgentHermesHome(agentName)` dans `src/lib/config.ts`.
210
-
211
- Ordre de resolution (la premiere gagne):
212
-
213
- ```
214
- OVERMIND_AGENT_HOME (env var, set par l'install ou systemd)
215
-
216
- <workspace>/.overmind/hermes/agent_<name>/.hermes (legacy, si deja existant)
217
-
218
- $HOME/.overmind/hermes/agent_<name>/.hermes (Linux/Mac sudo npm -g)
219
- %LOCALAPPDATA%\overmind\hermes\agent_<name>\.hermes (Windows npm -g)
220
- %USERPROFILE%\overmind\hermes\agent_<name>\.hermes (Windows fallback)
221
- ```
222
-
223
- Pour un agent nomme `sniperbot_analyst`:
224
- - Dev local (workspace = `C:\Users\Deamon\Desktop\Backup\Serveur MCP\Workflow`):
225
- `Workflow\.overmind\hermes\agent_sniperbot_analyst\.hermes` (si deja cree)
226
- - Prod Linux: `~/.overmind/hermes/agent_sniperbot_analyst/.hermes`
227
- - Prod Windows: `%LOCALAPPDATA%\overmind\hermes\agent_sniperbot_analyst\.hermes`
228
-
229
- **Pourquoi c'est important**: avant, le runner Overmind calculait HERMES_HOME
230
- depuis `process.cwd()`. Si le sniper etait lance depuis `C:\Users\Deamon\Desktop\Backup\Serveur MCP\`
231
- et le runner depuis `Workflow\`, ils lisaient des `.hermes/.env` differents
232
- et ecrivaient dans des `auth.json` differents. Maintenant, c'est cwd-independent.
233
-
234
- Pour forcer un chemin explicite (ex: deploy Docker), set:
235
- ```bash
236
- export OVERMIND_AGENT_HOME=/var/lib/overmind/hermes
237
- ```
238
-
239
-
240
- ## Comment Hermes decide quel provider utiliser
241
-
242
- Il y a DEUX niveaux de decision:
243
-
244
- ### Niveau 1: Overmind runner (avant spawn)
245
-
246
- `NousHermesRunner.writeAuthJson()` (l.782-918) vote entre 3 signaux pour determiner le `effectiveProvider` qui sera seed dans `auth.json` et le `.env` de l'agent:
247
-
248
- 1. **Token prefix** (le plus fiable) — `detectTokenProvider()` reconnait:
249
- - `sk-cp-...` ou `sk-mm-...` → `minimax`
250
- - `32hex.32hex` ou 32-char hex → `zai`
251
- - `sk-ant-...` → `anthropic`
252
- - `sk-or-...` → `openrouter` (mais BLOQUE pour LLM par la suite)
253
- - `sk-...` (autre) → `openai`
254
- 2. **BASE_URL** (tres fiable, plus specifique que le token pour CN vs GLOBAL) — `api.minimaxi.com` → `minimax-cn`, `api.minimax.com` → `minimax`, `api.z.ai/api/coding/paas/v4` → `zai`, `anthropic.com` → `anthropic`, `openai.com` → `openai`.
255
- 3. **ANTHROPIC_PROVIDER** hint du settings (le moins fiable).
256
-
257
- **Cas special CN vs GLOBAL**: `sk-cp-` est ambigu entre `minimax` et `minimax-cn` (meme prefix). Si l'URL dit `minimaxi` (avec le `i`), c'est CN. Si `minimax` (sans le `i`), c'est GLOBAL. **L'URL gagne dans ce cas precis** parce qu'elle est la seule a desambiguïser.
258
-
259
- ### Niveau 2: Hermes upstream (apres spawn)
260
-
261
- Hermes relit son `auth.json` + `HERMES_HOME/.env` + `os.environ` avec sa propre logique (dans `hermes_cli/auth.py`):
262
-
263
- ```
264
- 1. Si `provider` explicite dans config.yaml → utilise ce provider
265
- 2. Sinon si `ANTHROPIC_BASE_URL` contient openrouter → "openrouter"
266
- 3. Sinon lit model name → compare avec model_defaults par provider
267
- - "glm-*" → "zai"
268
- - "MiniMax-*" → "minimax-cn"
269
- 4. Sinon fallback: model.default dans config.yaml
270
- ```
271
-
272
- **Le runner a deja vote au Niveau 1** — donc ce que tu mets dans `auth.json` (via `writeAuthJson()`) determine ce qu'Hermes verra au Niveau 2. Si le runner a seed `minimax-cn` mais que `config.yaml` dit `provider: minimax`, Hermes va probablement se plaindre. **Garde les deux alignes** ou laisse le runner ecrire le `config.yaml` (ce qu'il fait deja a chaque run).
273
-
274
- ---
275
-
276
- ## Comment NousHermesRunner passe les vars a Hermes
277
-
278
- Le runner lit `settings_[agent].json` → applique `interpolateEnvVars()` qui remplace `$VAR` par `process.env[VAR]` → envoie le tout dans `agentCustomEnv` au processus Hermes.
279
-
280
- ```typescript
281
- // Ce que NousHermesRunner.ts passe a Hermes (agentCustomEnv)
282
- const agentCustomEnv = {
283
- ...process.env, // HERMES_HOME/.env + Workflow/.env fusionnes
284
- PYTHONIOENCODING: 'utf-8',
285
- OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '', // VIDE (fixe)
286
- NVIDIA_API_KEY: process.env.NVIDIA_API_KEY || process.env.NVAPI_KEY,
287
- ANTHROPIC_AUTH_TOKEN: s.env.ANTHROPIC_AUTH_TOKEN, // interpolate
288
- ANTHROPIC_BASE_URL: s.env.ANTHROPIC_BASE_URL, // interpolate
289
- ANTHROPIC_MODEL: s.env.ANTHROPIC_MODEL, // interpolate
290
- };
291
- ```
292
-
293
- Puis lance Hermes avec `--env-file` pour discord_llm + Workflow `.env` (via startpipeline.js).
294
-
295
- ---
296
-
297
- ## Le probleme de OPENROUTER_API_KEY
298
-
299
- **AVANT le fix:**
300
- ```typescript
301
- OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || process.env.OVERMIND_EMBEDDING_KEY,
302
- ```
303
- → Si `OPENROUTER_API_KEY` vide mais `OVERMIND_EMBEDDING_KEY` present → passe quand meme une cle OpenRouter a Hermes → Hermes detecte `OPENROUTER_API_KEY` → tente OpenRouter → 404 guardrail.
304
-
305
- **APRES le fix:**
306
- ```typescript
307
- OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '',
308
- ```
309
- → `OVERMIND_EMBEDDING_KEY` n'est plus redirige. Si `OPENROUTER_API_KEY` absent du `.env`, Hermes recoit string vide et ne pick pas OpenRouter.
310
-
311
- ---
312
-
313
- ## Comment Hermes obtient la API Key (le vrai flux)
314
-
315
- Le `ANTHROPIC_AUTH_TOKEN` dans `settings.json` **ne passe pas directement** dans le body de la requete API. Hermes utilise son propre credential pool:
316
-
317
- ```
318
- settings_[agent].json
319
- "env": {
320
- "ANTHROPIC_AUTH_TOKEN": "$ZAI_ANTHROPIC_FALLBACK_KEY", ← Runner remplace $VAR → "token_reel"
321
- "ANTHROPIC_BASE_URL": "https://api.z.ai/api/coding/paas/v4",
322
- "ANTHROPIC_MODEL": "glm-5.1"
323
- }
324
- ↓ (interpolateEnvVars par NousHermesRunner)
325
- agentCustomEnv envoye a Hermes:
326
- ANTHROPIC_AUTH_TOKEN=token_reel
327
- ANTHROPIC_BASE_URL=https://api.z.ai/api/coding/paas/v4
328
- ANTHROPIC_MODEL=glm-5.1
329
-
330
- MAIS Hermes ne lit PAS ANTHROPIC_AUTH_TOKEN directement.
331
- Hermes lit le CREDENTIAL POOL (auth.json) + les .env vars listees dans api_key_env_vars.
332
-
333
- Credential pool est seed par:
334
- ZAI_ANTHROPIC_FALLBACK_KEY → "zai" avec base_url coding ✅
335
- Z_AI_API_KEY → "zai" avec base_url non-coding (ancien)
336
- MINIMAX_CN_API_KEY → "minimax-cn"
337
- ```
338
-
339
- Le `$VAR` dans `ANTHROPIC_AUTH_TOKEN` est juste une convenience pour que le token traverse le runner et arrive dans `process.env` du subprocess Hermes. C'est `process.env.ZAI_ANTHROPIC_FALLBACK_KEY` qui seed le credential pool.
340
-
341
- ---
342
-
343
- ## Le flow complet (Z.AI par exemple)
344
-
345
- 1. `Workflow/.env` contient `ZAI_ANTHROPIC_FALLBACK_KEY=<TOKEN>`
346
- 2. `startpipeline.js` charge `.env` → `process.env.ZAI_ANTHROPIC_FALLBACK_KEY`
347
- 3. ` NousHermesRunner` lit `settings_zai.json` → `interpolateEnvVars()`
348
- - `$ZAI_ANTHROPIC_FALLBACK_KEY` → `process.env["ZAI_ANTHROPIC_FALLBACK_KEY"]` → `"<TOKEN>"`
349
- - `ANTHROPIC_AUTH_TOKEN="<TOKEN>"` (valeur concrete maintenant)
350
- 4. `agentCustomEnv` envoye a Hermes:
351
- - `ANTHROPIC_AUTH_TOKEN=<TOKEN>`
352
- - `ANTHROPIC_BASE_URL=https://api.z.ai/api/coding/paas/v4`
353
- - `ANTHROPIC_MODEL=glm-5.1`
354
- 5. Hermes fait son propre lookup:
355
- - `load_pool("zai")` → `_resolve_api_key_provider_secret("zai")`
356
- - Cherche `ZAI_ANTHROPIC_FALLBACK_KEY` via `_get_env_prefer_dotenv()` dans `HERMES_HOME/.env` puis `os.environ`
357
- - Trouve dans `os.environ` (herite du parent)
358
- - `writeAuthJson()` ecrit dans `auth.json` avec base_url `https://api.z.ai/api/coding/paas/v4`
359
- 6. API call → utilise le credential pool entry pour `zai` avec le bon endpoint
360
-
361
- ---
362
-
363
- ## OPENROUTER et Les Embeddings
364
-
365
- **`OVERMIND_EMBEDDING_KEY`** = clef OpenRouter pour les **embeddings uniquement** (PostgresMemoryProvider du Workflow). Elle est dans le `.env` Overmind. Hermes n'a pas besoin de la voir pour l'LLM inference.
366
-
367
- **NousHermesRunner ne doit jamais forwarder de clef OpenRouter a Hermes.** OpenRouter n'est pas un provider LLM dans ce setup. Si `OPENROUTER_API_KEY` arrive jusqu'a Hermes, il detecte la clef et tente OpenRouter pour l'inference → 404 guardrail.
368
-
369
- **Fix applique:**
370
- ```typescript
371
- OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '',
372
- ```
373
-
374
- ---
375
-
376
- ## Le config.yaml ecrit par NousHermesRunner (exemple sniperbot_analyst)
377
-
378
- ```yaml
379
- mcp_servers:
380
- memory-server:
381
- url: "http://localhost:3099/mcp"
382
- discord-server:
383
- url: "http://localhost:3141/mcp"
384
- x-mcp-server:
385
- url: "http://localhost:3142/mcp"
386
- postgresql-server:
387
- url: "http://localhost:5433/mcp"
388
-
389
- model:
390
- default: glm-5.1
391
- provider: z-ai
392
-
393
- tts:
394
- provider: elevenlabs
395
- voice: charlie
396
- voice_id: IKne3meq5aSn9XLyUdCD
397
- model: eleven_multilingual_v2
398
- ```
399
-
400
- Ce config est ecrit dans `.overmind/hermes/agent_<name>/.hermes/config.yaml` a chaque run. Les valeurs viennent de `settings_<agent>.json` + defaults.
401
-
402
- ---
403
-
404
- ## Checklist pour ajouter un nouveau provider
405
-
406
- 1. **Verifier le ProviderConfig** dans `hermes-agent/hermes_cli/auth.py`
407
- - Verifier `api_key_env_vars` (les vars que Hermes cherche)
408
- - Verifier `inference_base_url` (URL par defaut)
409
- - Verifier `base_url_env_var` (optionnel, surcharge URL)
410
-
411
- 2. **Ajouter dans Workflow/.env**
412
- ```bash
413
- MAISON_API_KEY=cle_api_du_fournisseur
414
- ```
415
-
416
- 3. **Ajouter dans settings_[agent].json**
417
- ```json
418
- {
419
- "env": {
420
- "ANTHROPIC_AUTH_TOKEN": "$MAISON_API_KEY",
421
- "ANTHROPIC_BASE_URL": "https://api.fournisseur.com/v1",
422
- "ANTHROPIC_MODEL": "model-name"
423
- }
424
- }
425
- ```
426
-
427
- 4. **Verifier auth.json** — apres premiere utilisation, Hermes stocke le token avec status.
428
- - Si `exhausted` → Hermes skip ce provider automatiquement
429
- - Si `ok` → utilise le token
430
-
431
- 5. **NE JAMAIS** faire de mapping `AUTRE_CHOSE_API_KEY → OPENROUTER_API_KEY` — ca force OpenRouter.
432
-
433
- 6. **Pour eviter OpenRouter:** pas de `OPENROUTER_API_KEY` dans `HERMES_HOME/.env`
434
-
435
- ---
436
-
437
- ## Resume
438
-
439
- | Tu veux... | Utilise ces vars |
440
- |---|---|
441
- | Z.AI (glm-5.1) | `ZAI_ANTHROPIC_FALLBACK_KEY` dans `.env` + settings `$ZAI_ANTHROPIC_FALLBACK_KEY` |
442
- | Z.AI secondary (token Y) | `ANTHROPIC_AUTH_TOKEN_Y` dans `.env` + settings `$ANTHROPIC_AUTH_TOKEN_Y` |
443
- | MiniMax CN | `MINIMAX_CN_API_KEY` dans `.env` + settings `$MINIMAX_CN_API_KEY` |
444
- | Embeddings OpenRouter | `OVERMIND_EMBEDDING_KEY` (pour embeddings, PAS LLM) |
445
- | Eviter OpenRouter LLM | Pas de `OPENROUTER_API_KEY` dans `HERMES_HOME/.env` |
446
-
447
- ---
448
-
449
- ## Gemini / @google/gemini-cli (id: `gemini`)
450
-
451
- Le runner `gemini` utilise **`@google/gemini-cli`** (npm, v0.43.0) en headless mode.
452
- Le CLI est installé via `npm install -g @google/gemini-cli` et disponible dans le PATH.
453
-
454
- ### Installation
455
-
456
- ```bash
457
- npm install -g @google/gemini-cli
458
- gemini --version # → 0.43.0
459
- ```
460
-
461
- ### Flags CLI utilisés
462
-
463
- | Flag | Valeur | Rôle |
464
- |---|---|---|
465
- | `-p` / `--prompt` | prompt text | Mode headless (non-interactif) |
466
- | `--approval-mode` | `yolo` | Auto-approve tous les outils |
467
- | `--session-id` | UUID | Session persistante entre appels |
468
- | `--acp` | (flag) | Active le protocol agent (ACP) |
469
- | `--model` | `antigravity/<MODE>` | Passe le mode Antigravity comme contexte |
470
- | `--output-format` | `json` | Output structuré pour parser session_id |
471
-
472
- ### Commandes equivalents (CLI direct)
473
-
474
- ```bash
475
- # Test quick
476
- gemini -p "Dis-moi bonjour" --approval-mode yolo
477
-
478
- # Avec session
479
- gemini -p "Analyse ce code" --approval-mode yolo --session-id <uuid> --acp
480
-
481
- # Mode PLAN
482
- gemini -p "Planifie cette tache" --model antigravity/PLAN --approval-mode yolo --acp
483
-
484
- # List sessions
485
- gemini --list-sessions
486
- ```
487
-
488
- ### Modes Antigravity (parametre `mode`)
489
-
490
- Le mode est passe via `--model antigravity/<MODE>` pour donner du contexte au modele.
491
-
492
- || Mode | Usage |
493
- |---|---|
494
- | `GENERAL` | Mode par defaut, taches polyvalentes |
495
- | `CONTEXT_CHECK` | Verification de contexte code |
496
- | `PLAN` | Planification de taches complexes |
497
- | `COMMAND` | Execution de commandes shell |
498
- | `CASCADE` | Execution en cascade multi-agents |
499
- | `EVAL` | Evaluation et revue de code |
500
- | `ANTIGRAVITY_REVIEW` | Revue automatique Antigravity |
501
- | `MQUERY` | Recherche multi-source |
502
- | `COMMIT_MESSAGE` | Generation de messages de commit |
503
- | `CHECKPOINT` | Sauvegarde de checkpoint |
504
- | `FAST_APPLY` | Application rapide de patches |
505
-
506
- ### Utilisation Overmind (run_agent)
507
-
508
- ```typescript
509
- // run_agent avec runner: 'gemini'
510
- const result = await runAgent({
511
- runner: 'gemini', // GeminiRunner → gemini CLI npm
512
- prompt: 'Analyse ce code',
513
- agentName: 'expert_python',
514
- mode: 'GENERAL', // GENERAL, PLAN, COMMAND, CASCADE, EVAL, etc.
515
- autoResume: false,
516
- configPath: './Workflow',
517
- });
518
-
519
- // ou directement via run_gemini.ts
520
- const result = await runGeminiAgent({
521
- prompt: '...',
522
- mode: 'PLAN',
523
- });
524
- ```
525
-
526
- ### Configuration agent
527
-
528
- Chaque agent stocke sa config dans `.antigravity/agent_<nom>/`:
529
- - `mcp.json` — serveurs MCP actifs (copies depuis settings_<agent>.json)
530
- - Session store — sessions persistees
531
-
532
- ### Verification installation
533
-
534
- ```bash
535
- gemini --version
536
- # → 0.43.0
537
-
538
- gemini mcp list
539
- # → liste les MCP servers configures
540
- ```
541
-
542
- ### Erreurs connues
543
-
544
- | Erreur | Cause | Fix |
545
- |---|---|---|
546
- | `GEMINI_CLI_NOT_INSTALLED` | `@google/gemini-cli` pas dans le PATH | `npm install -g @google/gemini-cli` |
547
- | `EXIT_CODE_1` | Session invalide ou prompt rejete | Retry sans sessionId |
548
- | `TIMEOUT` | Reponse > 15min | Augmente `CONFIG.TIMEOUT_MS` |
549
-
550
- ### Ce qui a change (historique)
551
-
552
- || Avant (session 2025) | Maintenant |
553
- |---|---|---|
554
- | Spawn `language_server_windows_x64.exe` avec flags inexistants | Spawn `gemini` (npm bin) avec flags reels |
555
- | `--mode --prompt-file --session --output-format` (flags Go inexistants) | `-p --approval-mode yolo --session-id --acp --model --output-format json` |
556
- | Auth via OAuth interne Antigravity IDE | Auth via Google account du CLI npm |
1
+ # Hermes x Overmind — Config Provider Map
2
+
3
+ ## Ordre de resolution (qui gagne, qui perd)
4
+
5
+ Chaque variable suit cette priorite (la premiere gagne):
6
+
7
+ ```
8
+ process.env (env du parent, herite par le spawn)
9
+
10
+ Workflow/.env (~/.env)
11
+
12
+ settings_[agent].json → env (apres interpolation $VAR par process.env)
13
+
14
+ HERMES_HOME/.env (~/.hermes/.env) ← DERNIER MOT
15
+ ```
16
+
17
+ **Detail du code** (`NousHermesRunner.ts` l.268-456):
18
+ 1. `agentCustomEnv = { ...process.env, ...settings.env }` (line 268 puis 384)
19
+ 2. Puis lit `overmindHermesSubPath/.env` (le `.hermes/.env` de l'agent) et fait `agentCustomEnv[key] = value` (line 437-456) — ce qui OVERRIDE tout ce qui precede.
20
+ 3. Finalement ecrit ce `agentCustomEnv` dans le `.env` final de l'agent (line 722-732) avec dedup sur les cles `*api_key` / `*auth_token`.
21
+
22
+ Donc le `.hermes/.env` de l'agent a **toujours le dernier mot**. Si tu mets `MINIMAX_API_KEY=*** dans le .hermes/.env, il ecrase `MINIMAX_API_KEY` du process.env et du settings.
23
+
24
+ **MAIS** pour `OPENROUTER_API_KEY` uniquement:
25
+ - Hermes lit d'abord `HERMES_HOME/.env` puis `os.environ`
26
+ - Si present dans `auth.json` avec status `exhausted` → skip
27
+ - Si present dans `HERMES_HOME/.env` (meme vide `""`) → **PREND LA PRIORITE sur process.env**
28
+
29
+ **MAIS** pour tous les autres providers (zai, minimax-cn, etc.):
30
+ - Hermes lit `HERMES_HOME/.env` → si vide/null → lit `os.environ`
31
+ - `os.environ` contient tout ce que le parent a passe (donc le `.env` du Workflow)
32
+
33
+ ---
34
+
35
+ ## Les 5 fichiers cles
36
+
37
+ | Fichier | Role |
38
+ |---|---|
39
+ | `HERMES_HOME/.env` | API keys globales Hermes (fallback) |
40
+ | `Workflow/.env` | Variables du workflow (DB, tokens, etc.) |
41
+ | `settings_[agent].json` | Config par agent (model, provider, tokens, MCP) |
42
+ | `HERMES_HOME/.hermes/config.yaml` | Config systeme Hermes (model.default, provider, etc.) |
43
+ | `HERMES_HOME/auth.json` | Credential pool — status des tokens (ok/exhausted), URLs par provider |
44
+
45
+ ---
46
+
47
+ ## Les 2 endpoints Z.AI (DECOUVERTE CRITIQUE)
48
+
49
+ Z.AI a **deux endpoints distincts** — confusion entre les deux causait des erreurs 402:
50
+
51
+ | Endpoint | URL | Usage |
52
+ |---|---|---|
53
+ | **Coding** (celui qu'il faut) | `https://api.z.ai/api/coding/paas/v4` | Inference LLM (Hermes, Overmind) |
54
+ | **Non-coding** (ancien, different billing) | `https://api.z.ai/api/paas/v4` | Autre chose (pas le meme systeme de facturation) |
55
+
56
+ **Comment le credential pool est seed:**
57
+
58
+ | Source dans .env | Cle dans auth.json | base_url assignee |
59
+ |---|---|---|
60
+ | `ZAI_ANTHROPIC_FALLBACK_KEY` | `zai[0].access_token` | `https://api.z.ai/api/coding/paas/v4` ✅ |
61
+ | `Z_AI_API_KEY` | `zai[1].access_token` | `https://api.z.ai/api/paas/v4` ❌ (ancien) |
62
+
63
+ Le premier entry (priority 0) est utilise en premier. C'est celui qui est seed par `writeAuthJson()` dans `NousHermesRunner.ts` → `ZAI_ANTHROPIC_FALLBACK_KEY`.
64
+
65
+ ---
66
+
67
+ ## Provider → Ce qu'Hermes attend
68
+
69
+ ### Z.AI (id: `zai`)
70
+
71
+ | Param | Valeur attendue | Source dans Hermes |
72
+ |---|---|---|
73
+ | Provider ID | `zai` | config.yaml ou settings |
74
+ | API Key | `ZAI_ANTHROPIC_FALLBACK_KEY` (cle primaire) ou `Z_AI_API_KEY` (fallback ancien) | `HERMES_HOME/.env` → `os.environ` |
75
+ | Base URL | `https://api.z.ai/api/coding/paas/v4` | credential pool (seed par writeAuthJson) |
76
+ | Model | `glm-5.2` | settings `env.ANTHROPIC_MODEL` |
77
+
78
+ ```json
79
+ // settings_[agent].json — Z.AI correct
80
+ {
81
+ "env": {
82
+ "ANTHROPIC_AUTH_TOKEN": "$ZAI_ANTHROPIC_FALLBACK_KEY",
83
+ "ANTHROPIC_BASE_URL": "https://api.z.ai/api/coding/paas/v4",
84
+ "ANTHROPIC_MODEL": "glm-5.2"
85
+ }
86
+ }
87
+ ```
88
+
89
+ ```bash
90
+ # .env minimal pour Z.AI
91
+ ZAI_ANTHROPIC_FALLBACK_KEY=<your-zai-key-here>
92
+ ```
93
+
94
+ Le credential pool `auth.json` est ecrit par `writeAuthJson()` dans `NousHermesRunner.ts`. La cle `ZAI_ANTHROPIC_FALLBACK_KEY` est envoyee par `agentCustomEnv` → Hermes seed le credential pool avec le bon endpoint.
95
+
96
+ ---
97
+
98
+ ### Z.AI Multi-Token (E/Y)
99
+
100
+ Deamon a 2 tokens Z.AI (E=primary, Y=secondary). Le credential pool peut contenir les deux:
101
+
102
+ | Token | Label dans auth.json | Cle dans .env |
103
+ |---|---|---|
104
+ | Primary | `ANTHROPIC_AUTH_TOKEN_E` | `ANTHROPIC_AUTH_TOKEN_E` = `<your-zai-token-E>` |
105
+ | Secondary | `ANTHROPIC_AUTH_TOKEN_Y` | `ANTHROPIC_AUTH_TOKEN_Y` = `<your-zai-token-Y>` |
106
+
107
+ Pour qu'un agent utilise le token Y (secondary) au lieu de E (primary), le settings doit utiliser `$ANTHROPIC_AUTH_TOKEN_Y` au lieu de `$ANTHROPIC_AUTH_TOKEN_E`.
108
+
109
+ ---
110
+
111
+ ### MiniMax CN (id: `minimax-cn`)
112
+
113
+ | Param | Valeur attendue | Source dans Hermes |
114
+ |---|---|---|
115
+ | Provider ID | `minimax-cn` | config.yaml ou settings |
116
+ | API Key | `MINIMAX_CN_API_KEY` **uniquement** | `HERMES_HOME/.env` → `os.environ` |
117
+ | Base URL | `https://api.minimaxi.com/anthropic` | hardcoded dans ProviderConfig |
118
+ | Model | `MiniMax-M3` | settings `env.ANTHROPIC_MODEL` |
119
+
120
+ ```json
121
+ // settings_[agent].json — MiniMax correct
122
+ {
123
+ "env": {
124
+ "ANTHROPIC_AUTH_TOKEN": "$MINIMAX_CN_API_KEY",
125
+ "ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic",
126
+ "ANTHROPIC_MODEL": "MiniMax-M3"
127
+ }
128
+ }
129
+ ```
130
+
131
+ ```bash
132
+ # .env minimal pour MiniMax CN
133
+ MINIMAX_CN_API_KEY=ton_token_minimax_ici
134
+ ```
135
+
136
+ **auth.json** stocke sous `MINIMAX_CN_API_KEY`.
137
+
138
+ #### MiniMax CN par défaut (convention)
139
+
140
+ Le préfixe `sk-cp-` est partagé entre MiniMax GLOBAL (`api.minimax.com`) et
141
+ MiniMax CN (`api.minimaxi.com`). L'URL est le seul signal qui disambiguïse.
142
+ Pour les setups où TOUS les tokens MiniMax sont CN (cas le plus commun),
143
+ le runner a un fallback par défaut : quand un token `sk-cp-*` est détecté
144
+ sans URL explicite, on bascule sur CN.
145
+
146
+ Controlable via env var :
147
+
148
+ ```bash
149
+ # Défaut (recommandé pour les setups CN-only)
150
+ OVERMIND_MINIMAX_DEFAULT=cn # sk-cp-* sans URL → minimax-cn
151
+
152
+ # Pour les setups GLOBAL-only
153
+ OVERMIND_MINIMAX_DEFAULT=global # sk-cp-* sans URL → minimax
154
+
155
+ # Strict mode (jamais d'inference, URL obligatoire)
156
+ OVERMIND_MINIMAX_DEFAULT=auto # sk-cp-* sans URL → minimax (no override)
157
+ ```
158
+
159
+ Si une URL explicite est présente dans `ANTHROPIC_BASE_URL`, elle gagne
160
+ toujours sur `OVERMIND_MINIMAX_DEFAULT`.
161
+
162
+ ---
163
+
164
+ ### OpenRouter — BANNIR pour LLM
165
+
166
+ | Param | Valeur attendue | Source |
167
+ |---|---|---|
168
+ | Provider ID | — | **Ne PAS utiliser** |
169
+ | API Key | `OPENROUTER_API_KEY` | `HERMES_HOME/.env` → `os.environ` |
170
+ | Base URL | `https://openrouter.ai/api/v1` | hardcoded |
171
+ | Guardrail | — | Force 404 si active |
172
+
173
+ **PROBLEME:** Si `OPENROUTER_API_KEY` est present (meme dans `OVERMIND_EMBEDDING_KEY` route via NousHermesRunner), Hermes le detecte et tente OpenRouter pour l'inference.
174
+
175
+ **auth.json** a une entree OpenRouter — si le status est `exhausted`, Hermes ne retry plus mais peut quand meme picker le provider "openrouter" dans le credential pool.
176
+
177
+ ---
178
+
179
+ ## Ne PAS passer --provider au CLI Hermes (NOUVEAU en 2.8.28)
180
+
181
+ Le runner Overmind **ne passe plus** le flag `--provider` au CLI Hermes.
182
+ Découverte empirique (le `Hermes-MiniMax-2.bat` du bureau marche mais
183
+ le sniperbot échoue) :
184
+
185
+ | Commande | Résultat |
186
+ |---|---|
187
+ | `hermes chat -q --provider minimax-cn ...` | **401** (bug plugin upstream) |
188
+ | `hermes chat --yolo` (sans --provider) | **200 OK** |
189
+
190
+ **Cause** : le flag `--provider` explicite active un code path buggé
191
+ dans le plugin Hermes upstream (`hermes-agent/plugins/model-providers/minimax/`)
192
+ qui envoie un format d'auth header rejeté par `api.minimaxi.com`.
193
+
194
+ **Fix appliqué** : le runner retire `--provider` de `cleanArgs` mais
195
+ loggue le `resolvedProvider` à INFO pour debug. Hermes auto-détecte
196
+ le bon provider depuis l'env var :
197
+ - `MINIMAX_CN_API_KEY` → plugin `minimax-cn`
198
+ - `MINIMAX_API_KEY` → plugin `minimax` (GLOBAL)
199
+ - `ZAI_ANTHROPIC_FALLBACK_KEY` ou `GLM_API_KEY` → plugin `zai`
200
+ - `ANTHROPIC_AUTH_TOKEN` avec préfixe `sk-ant-` → plugin `anthropic`
201
+
202
+ `ANTHROPIC_BASE_URL` et `ANTHROPIC_MODEL` sont toujours passés, donc
203
+ Hermes a assez d'info pour ne pas se tromper.
204
+
205
+
206
+ ## HERMES_HOME resolution (multi-OS, multi-install)
207
+
208
+ Chaque agent Hermes a son propre HERMES_HOME. Le path est resolu de maniere
209
+ deterministe par `getAgentHermesHome(agentName)` dans `src/lib/config.ts`.
210
+
211
+ Ordre de resolution (la premiere gagne):
212
+
213
+ ```
214
+ OVERMIND_AGENT_HOME (env var, set par l'install ou systemd)
215
+
216
+ <workspace>/.overmind/hermes/agent_<name>/.hermes (legacy, si deja existant)
217
+
218
+ $HOME/.overmind/hermes/agent_<name>/.hermes (Linux/Mac sudo npm -g)
219
+ %LOCALAPPDATA%\overmind\hermes\agent_<name>\.hermes (Windows npm -g)
220
+ %USERPROFILE%\overmind\hermes\agent_<name>\.hermes (Windows fallback)
221
+ ```
222
+
223
+ Pour un agent nomme `sniperbot_analyst`:
224
+ - Dev local (workspace = `~/overmind-mcp`):
225
+ `Workflow\.overmind\hermes\agent_sniperbot_analyst\.hermes` (si deja cree)
226
+ - Prod Linux: `~/.overmind/hermes/agent_sniperbot_analyst/.hermes`
227
+ - Prod Windows: `%LOCALAPPDATA%\overmind\hermes\agent_sniperbot_analyst\.hermes`
228
+
229
+ **Pourquoi c'est important**: avant, le runner Overmind calculait HERMES_HOME
230
+ depuis `process.cwd()`. Si le sniper etait lance depuis `~/overmind-mcp/`
231
+ et le runner depuis `Workflow\`, ils lisaient des `.hermes/.env` differents
232
+ et ecrivaient dans des `auth.json` differents. Maintenant, c'est cwd-independent.
233
+
234
+ Pour forcer un chemin explicite (ex: deploy Docker), set:
235
+ ```bash
236
+ export OVERMIND_AGENT_HOME=/var/lib/overmind/hermes
237
+ ```
238
+
239
+
240
+ ## Comment Hermes decide quel provider utiliser
241
+
242
+ Il y a DEUX niveaux de decision:
243
+
244
+ ### Niveau 1: Overmind runner (avant spawn)
245
+
246
+ `NousHermesRunner.writeAuthJson()` (l.782-918) vote entre 3 signaux pour determiner le `effectiveProvider` qui sera seed dans `auth.json` et le `.env` de l'agent:
247
+
248
+ 1. **Token prefix** (le plus fiable) — `detectTokenProvider()` reconnait:
249
+ - `sk-cp-...` ou `sk-mm-...` → `minimax`
250
+ - `32hex.32hex` ou 32-char hex → `zai`
251
+ - `sk-ant-...` → `anthropic`
252
+ - `sk-or-...` → `openrouter` (mais BLOQUE pour LLM par la suite)
253
+ - `sk-...` (autre) → `openai`
254
+ 2. **BASE_URL** (tres fiable, plus specifique que le token pour CN vs GLOBAL) — `api.minimaxi.com` → `minimax-cn`, `api.minimax.com` → `minimax`, `api.z.ai/api/coding/paas/v4` → `zai`, `anthropic.com` → `anthropic`, `openai.com` → `openai`.
255
+ 3. **ANTHROPIC_PROVIDER** hint du settings (le moins fiable).
256
+
257
+ **Cas special CN vs GLOBAL**: `sk-cp-` est ambigu entre `minimax` et `minimax-cn` (meme prefix). Si l'URL dit `minimaxi` (avec le `i`), c'est CN. Si `minimax` (sans le `i`), c'est GLOBAL. **L'URL gagne dans ce cas precis** parce qu'elle est la seule a desambiguïser.
258
+
259
+ ### Niveau 2: Hermes upstream (apres spawn)
260
+
261
+ Hermes relit son `auth.json` + `HERMES_HOME/.env` + `os.environ` avec sa propre logique (dans `hermes_cli/auth.py`):
262
+
263
+ ```
264
+ 1. Si `provider` explicite dans config.yaml → utilise ce provider
265
+ 2. Sinon si `ANTHROPIC_BASE_URL` contient openrouter → "openrouter"
266
+ 3. Sinon lit model name → compare avec model_defaults par provider
267
+ - "glm-*" → "zai"
268
+ - "MiniMax-*" → "minimax-cn"
269
+ 4. Sinon fallback: model.default dans config.yaml
270
+ ```
271
+
272
+ **Le runner a deja vote au Niveau 1** — donc ce que tu mets dans `auth.json` (via `writeAuthJson()`) determine ce qu'Hermes verra au Niveau 2. Si le runner a seed `minimax-cn` mais que `config.yaml` dit `provider: minimax`, Hermes va probablement se plaindre. **Garde les deux alignes** ou laisse le runner ecrire le `config.yaml` (ce qu'il fait deja a chaque run).
273
+
274
+ ---
275
+
276
+ ## Comment NousHermesRunner passe les vars a Hermes
277
+
278
+ Le runner lit `settings_[agent].json` → applique `interpolateEnvVars()` qui remplace `$VAR` par `process.env[VAR]` → envoie le tout dans `agentCustomEnv` au processus Hermes.
279
+
280
+ ```typescript
281
+ // Ce que NousHermesRunner.ts passe a Hermes (agentCustomEnv)
282
+ const agentCustomEnv = {
283
+ ...process.env, // HERMES_HOME/.env + Workflow/.env fusionnes
284
+ PYTHONIOENCODING: 'utf-8',
285
+ OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '', // VIDE (fixe)
286
+ NVIDIA_API_KEY: process.env.NVIDIA_API_KEY || process.env.NVAPI_KEY,
287
+ ANTHROPIC_AUTH_TOKEN: s.env.ANTHROPIC_AUTH_TOKEN, // interpolate
288
+ ANTHROPIC_BASE_URL: s.env.ANTHROPIC_BASE_URL, // interpolate
289
+ ANTHROPIC_MODEL: s.env.ANTHROPIC_MODEL, // interpolate
290
+ };
291
+ ```
292
+
293
+ Puis lance Hermes avec `--env-file` pour discord_llm + Workflow `.env` (via startpipeline.js).
294
+
295
+ ---
296
+
297
+ ## Le probleme de OPENROUTER_API_KEY
298
+
299
+ **AVANT le fix:**
300
+ ```typescript
301
+ OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || process.env.OVERMIND_EMBEDDING_KEY,
302
+ ```
303
+ → Si `OPENROUTER_API_KEY` vide mais `OVERMIND_EMBEDDING_KEY` present → passe quand meme une cle OpenRouter a Hermes → Hermes detecte `OPENROUTER_API_KEY` → tente OpenRouter → 404 guardrail.
304
+
305
+ **APRES le fix:**
306
+ ```typescript
307
+ OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '',
308
+ ```
309
+ → `OVERMIND_EMBEDDING_KEY` n'est plus redirige. Si `OPENROUTER_API_KEY` absent du `.env`, Hermes recoit string vide et ne pick pas OpenRouter.
310
+
311
+ ---
312
+
313
+ ## Comment Hermes obtient la API Key (le vrai flux)
314
+
315
+ Le `ANTHROPIC_AUTH_TOKEN` dans `settings.json` **ne passe pas directement** dans le body de la requete API. Hermes utilise son propre credential pool:
316
+
317
+ ```
318
+ settings_[agent].json
319
+ "env": {
320
+ "ANTHROPIC_AUTH_TOKEN": "$ZAI_ANTHROPIC_FALLBACK_KEY", ← Runner remplace $VAR → "token_reel"
321
+ "ANTHROPIC_BASE_URL": "https://api.z.ai/api/coding/paas/v4",
322
+ "ANTHROPIC_MODEL": "glm-5.2"
323
+ }
324
+ ↓ (interpolateEnvVars par NousHermesRunner)
325
+ agentCustomEnv envoye a Hermes:
326
+ ANTHROPIC_AUTH_TOKEN=token_reel
327
+ ANTHROPIC_BASE_URL=https://api.z.ai/api/coding/paas/v4
328
+ ANTHROPIC_MODEL=glm-5.2
329
+
330
+ MAIS Hermes ne lit PAS ANTHROPIC_AUTH_TOKEN directement.
331
+ Hermes lit le CREDENTIAL POOL (auth.json) + les .env vars listees dans api_key_env_vars.
332
+
333
+ Credential pool est seed par:
334
+ ZAI_ANTHROPIC_FALLBACK_KEY → "zai" avec base_url coding ✅
335
+ Z_AI_API_KEY → "zai" avec base_url non-coding (ancien)
336
+ MINIMAX_CN_API_KEY → "minimax-cn"
337
+ ```
338
+
339
+ Le `$VAR` dans `ANTHROPIC_AUTH_TOKEN` est juste une convenience pour que le token traverse le runner et arrive dans `process.env` du subprocess Hermes. C'est `process.env.ZAI_ANTHROPIC_FALLBACK_KEY` qui seed le credential pool.
340
+
341
+ ---
342
+
343
+ ## Le flow complet (Z.AI par exemple)
344
+
345
+ 1. `Workflow/.env` contient `ZAI_ANTHROPIC_FALLBACK_KEY=<TOKEN>`
346
+ 2. `startpipeline.js` charge `.env` → `process.env.ZAI_ANTHROPIC_FALLBACK_KEY`
347
+ 3. ` NousHermesRunner` lit `settings_zai.json` → `interpolateEnvVars()`
348
+ - `$ZAI_ANTHROPIC_FALLBACK_KEY` → `process.env["ZAI_ANTHROPIC_FALLBACK_KEY"]` → `"<TOKEN>"`
349
+ - `ANTHROPIC_AUTH_TOKEN="<TOKEN>"` (valeur concrete maintenant)
350
+ 4. `agentCustomEnv` envoye a Hermes:
351
+ - `ANTHROPIC_AUTH_TOKEN=<TOKEN>`
352
+ - `ANTHROPIC_BASE_URL=https://api.z.ai/api/coding/paas/v4`
353
+ - `ANTHROPIC_MODEL=glm-5.2`
354
+ 5. Hermes fait son propre lookup:
355
+ - `load_pool("zai")` → `_resolve_api_key_provider_secret("zai")`
356
+ - Cherche `ZAI_ANTHROPIC_FALLBACK_KEY` via `_get_env_prefer_dotenv()` dans `HERMES_HOME/.env` puis `os.environ`
357
+ - Trouve dans `os.environ` (herite du parent)
358
+ - `writeAuthJson()` ecrit dans `auth.json` avec base_url `https://api.z.ai/api/coding/paas/v4`
359
+ 6. API call → utilise le credential pool entry pour `zai` avec le bon endpoint
360
+
361
+ ---
362
+
363
+ ## OPENROUTER et Les Embeddings
364
+
365
+ **`OVERMIND_EMBEDDING_KEY`** = clef OpenRouter pour les **embeddings uniquement** (PostgresMemoryProvider du Workflow). Elle est dans le `.env` Overmind. Hermes n'a pas besoin de la voir pour l'LLM inference.
366
+
367
+ **NousHermesRunner ne doit jamais forwarder de clef OpenRouter a Hermes.** OpenRouter n'est pas un provider LLM dans ce setup. Si `OPENROUTER_API_KEY` arrive jusqu'a Hermes, il detecte la clef et tente OpenRouter pour l'inference → 404 guardrail.
368
+
369
+ **Fix applique:**
370
+ ```typescript
371
+ OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '',
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Le config.yaml ecrit par NousHermesRunner (exemple sniperbot_analyst)
377
+
378
+ ```yaml
379
+ mcp_servers:
380
+ memory-server:
381
+ url: "http://localhost:3099/mcp"
382
+ discord-server:
383
+ url: "http://localhost:3141/mcp"
384
+ x-mcp-server:
385
+ url: "http://localhost:3142/mcp"
386
+ postgresql-server:
387
+ url: "http://localhost:5433/mcp"
388
+
389
+ model:
390
+ default: glm-5.2
391
+ provider: z-ai
392
+
393
+ tts:
394
+ provider: elevenlabs
395
+ voice: charlie
396
+ voice_id: IKne3meq5aSn9XLyUdCD
397
+ model: eleven_multilingual_v2
398
+ ```
399
+
400
+ Ce config est ecrit dans `.overmind/hermes/agent_<name>/.hermes/config.yaml` a chaque run. Les valeurs viennent de `settings_<agent>.json` + defaults.
401
+
402
+ ---
403
+
404
+ ## Checklist pour ajouter un nouveau provider
405
+
406
+ 1. **Verifier le ProviderConfig** dans `hermes-agent/hermes_cli/auth.py`
407
+ - Verifier `api_key_env_vars` (les vars que Hermes cherche)
408
+ - Verifier `inference_base_url` (URL par defaut)
409
+ - Verifier `base_url_env_var` (optionnel, surcharge URL)
410
+
411
+ 2. **Ajouter dans Workflow/.env**
412
+ ```bash
413
+ MAISON_API_KEY=cle_api_du_fournisseur
414
+ ```
415
+
416
+ 3. **Ajouter dans settings_[agent].json**
417
+ ```json
418
+ {
419
+ "env": {
420
+ "ANTHROPIC_AUTH_TOKEN": "$MAISON_API_KEY",
421
+ "ANTHROPIC_BASE_URL": "https://api.fournisseur.com/v1",
422
+ "ANTHROPIC_MODEL": "model-name"
423
+ }
424
+ }
425
+ ```
426
+
427
+ 4. **Verifier auth.json** — apres premiere utilisation, Hermes stocke le token avec status.
428
+ - Si `exhausted` → Hermes skip ce provider automatiquement
429
+ - Si `ok` → utilise le token
430
+
431
+ 5. **NE JAMAIS** faire de mapping `AUTRE_CHOSE_API_KEY → OPENROUTER_API_KEY` — ca force OpenRouter.
432
+
433
+ 6. **Pour eviter OpenRouter:** pas de `OPENROUTER_API_KEY` dans `HERMES_HOME/.env`
434
+
435
+ ---
436
+
437
+ ## Resume
438
+
439
+ | Tu veux... | Utilise ces vars |
440
+ |---|---|
441
+ | Z.AI (glm-5.2) | `ZAI_ANTHROPIC_FALLBACK_KEY` dans `.env` + settings `$ZAI_ANTHROPIC_FALLBACK_KEY` |
442
+ | Z.AI secondary (token Y) | `ANTHROPIC_AUTH_TOKEN_Y` dans `.env` + settings `$ANTHROPIC_AUTH_TOKEN_Y` |
443
+ | MiniMax CN | `MINIMAX_CN_API_KEY` dans `.env` + settings `$MINIMAX_CN_API_KEY` |
444
+ | Embeddings OpenRouter | `OVERMIND_EMBEDDING_KEY` (pour embeddings, PAS LLM) |
445
+ | Eviter OpenRouter LLM | Pas de `OPENROUTER_API_KEY` dans `HERMES_HOME/.env` |
446
+
447
+ ---
448
+
449
+ ## Gemini / @google/gemini-cli (id: `gemini`)
450
+
451
+ Le runner `gemini` utilise **`@google/gemini-cli`** (npm, v0.43.0) en headless mode.
452
+ Le CLI est installé via `npm install -g @google/gemini-cli` et disponible dans le PATH.
453
+
454
+ ### Installation
455
+
456
+ ```bash
457
+ npm install -g @google/gemini-cli
458
+ gemini --version # → 0.43.0
459
+ ```
460
+
461
+ ### Flags CLI utilisés
462
+
463
+ | Flag | Valeur | Rôle |
464
+ |---|---|---|
465
+ | `-p` / `--prompt` | prompt text | Mode headless (non-interactif) |
466
+ | `--approval-mode` | `yolo` | Auto-approve tous les outils |
467
+ | `--session-id` | UUID | Session persistante entre appels |
468
+ | `--acp` | (flag) | Active le protocol agent (ACP) |
469
+ | `--model` | `antigravity/<MODE>` | Passe le mode Antigravity comme contexte |
470
+ | `--output-format` | `json` | Output structuré pour parser session_id |
471
+
472
+ ### Commandes equivalents (CLI direct)
473
+
474
+ ```bash
475
+ # Test quick
476
+ gemini -p "Dis-moi bonjour" --approval-mode yolo
477
+
478
+ # Avec session
479
+ gemini -p "Analyse ce code" --approval-mode yolo --session-id <uuid> --acp
480
+
481
+ # Mode PLAN
482
+ gemini -p "Planifie cette tache" --model antigravity/PLAN --approval-mode yolo --acp
483
+
484
+ # List sessions
485
+ gemini --list-sessions
486
+ ```
487
+
488
+ ### Modes Antigravity (parametre `mode`)
489
+
490
+ Le mode est passe via `--model antigravity/<MODE>` pour donner du contexte au modele.
491
+
492
+ || Mode | Usage |
493
+ |---|---|
494
+ | `GENERAL` | Mode par defaut, taches polyvalentes |
495
+ | `CONTEXT_CHECK` | Verification de contexte code |
496
+ | `PLAN` | Planification de taches complexes |
497
+ | `COMMAND` | Execution de commandes shell |
498
+ | `CASCADE` | Execution en cascade multi-agents |
499
+ | `EVAL` | Evaluation et revue de code |
500
+ | `ANTIGRAVITY_REVIEW` | Revue automatique Antigravity |
501
+ | `MQUERY` | Recherche multi-source |
502
+ | `COMMIT_MESSAGE` | Generation de messages de commit |
503
+ | `CHECKPOINT` | Sauvegarde de checkpoint |
504
+ | `FAST_APPLY` | Application rapide de patches |
505
+
506
+ ### Utilisation Overmind (run_agent)
507
+
508
+ ```typescript
509
+ // run_agent avec runner: 'gemini'
510
+ const result = await runAgent({
511
+ runner: 'gemini', // GeminiRunner → gemini CLI npm
512
+ prompt: 'Analyse ce code',
513
+ agentName: 'expert_python',
514
+ mode: 'GENERAL', // GENERAL, PLAN, COMMAND, CASCADE, EVAL, etc.
515
+ autoResume: false,
516
+ configPath: './Workflow',
517
+ });
518
+
519
+ // ou directement via run_gemini.ts
520
+ const result = await runGeminiAgent({
521
+ prompt: '...',
522
+ mode: 'PLAN',
523
+ });
524
+ ```
525
+
526
+ ### Configuration agent
527
+
528
+ Chaque agent stocke sa config dans `.antigravity/agent_<nom>/`:
529
+ - `mcp.json` — serveurs MCP actifs (copies depuis settings_<agent>.json)
530
+ - Session store — sessions persistees
531
+
532
+ ### Verification installation
533
+
534
+ ```bash
535
+ gemini --version
536
+ # → 0.43.0
537
+
538
+ gemini mcp list
539
+ # → liste les MCP servers configures
540
+ ```
541
+
542
+ ### Erreurs connues
543
+
544
+ | Erreur | Cause | Fix |
545
+ |---|---|---|
546
+ | `GEMINI_CLI_NOT_INSTALLED` | `@google/gemini-cli` pas dans le PATH | `npm install -g @google/gemini-cli` |
547
+ | `EXIT_CODE_1` | Session invalide ou prompt rejete | Retry sans sessionId |
548
+ | `TIMEOUT` | Reponse > 15min | Augmente `CONFIG.TIMEOUT_MS` |
549
+
550
+ ### Ce qui a change (historique)
551
+
552
+ || Avant (session 2025) | Maintenant |
553
+ |---|---|---|
554
+ | Spawn `language_server_windows_x64.exe` avec flags inexistants | Spawn `gemini` (npm bin) avec flags reels |
555
+ | `--mode --prompt-file --session --output-format` (flags Go inexistants) | `-p --approval-mode yolo --session-id --acp --model --output-format json` |
556
+ | Auth via OAuth interne Antigravity IDE | Auth via Google account du CLI npm |
557
557
  | Config `.antigravity/<agent>/` | Config `.antigravity/<agent>/` (MCP + sessions) |