overmind-mcp 2.8.24 → 2.8.26
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.
- package/dist/lib/config.d.ts +36 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +91 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/envUtils.d.ts.map +1 -1
- package/dist/lib/envUtils.js +12 -3
- package/dist/lib/envUtils.js.map +1 -1
- package/dist/services/NousHermesRunner.d.ts.map +1 -1
- package/dist/services/NousHermesRunner.js +121 -60
- package/dist/services/NousHermesRunner.js.map +1 -1
- package/dist/services/hermesTokenResolver.d.ts +74 -0
- package/dist/services/hermesTokenResolver.d.ts.map +1 -0
- package/dist/services/hermesTokenResolver.js +140 -0
- package/dist/services/hermesTokenResolver.js.map +1 -0
- package/dist/tools/agent_control.d.ts +1 -1
- package/dist/tools/config_example.d.ts +2 -2
- package/dist/tools/create_agent.d.ts +1 -1
- package/dist/tools/manage_agents.d.ts +1 -1
- package/dist/tools/run_agent.d.ts +1 -1
- package/dist/tools/run_agents_parallel.d.ts +1 -1
- package/docs/provider-config-map.md +94 -8
- package/package.json +1 -1
- package/scripts/migrate-hermes-home.mjs +133 -0
|
@@ -5,15 +5,22 @@
|
|
|
5
5
|
Chaque variable suit cette priorite (la premiere gagne):
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
|
|
9
|
-
↓
|
|
10
|
-
settings_[agent].json → env (apres interpolation $VAR par process.env)
|
|
8
|
+
process.env (env du parent, herite par le spawn)
|
|
11
9
|
↓
|
|
12
10
|
Workflow/.env (C:\Users\Deamon\Desktop\Backup\Serveur MCP\Workflow\.env)
|
|
13
11
|
↓
|
|
14
|
-
|
|
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
15
|
```
|
|
16
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
|
+
|
|
17
24
|
**MAIS** pour `OPENROUTER_API_KEY` uniquement:
|
|
18
25
|
- Hermes lit d'abord `HERMES_HOME/.env` puis `os.environ`
|
|
19
26
|
- Si present dans `auth.json` avec status `exhausted` → skip
|
|
@@ -108,7 +115,7 @@ Pour qu'un agent utilise le token Y (secondary) au lieu de E (primary), le setti
|
|
|
108
115
|
| Provider ID | `minimax-cn` | config.yaml ou settings |
|
|
109
116
|
| API Key | `MINIMAX_CN_API_KEY` **uniquement** | `HERMES_HOME/.env` → `os.environ` |
|
|
110
117
|
| Base URL | `https://api.minimaxi.com/anthropic` | hardcoded dans ProviderConfig |
|
|
111
|
-
| Model | `MiniMax-
|
|
118
|
+
| Model | `MiniMax-M3` | settings `env.ANTHROPIC_MODEL` |
|
|
112
119
|
|
|
113
120
|
```json
|
|
114
121
|
// settings_[agent].json — MiniMax correct
|
|
@@ -116,18 +123,42 @@ Pour qu'un agent utilise le token Y (secondary) au lieu de E (primary), le setti
|
|
|
116
123
|
"env": {
|
|
117
124
|
"ANTHROPIC_AUTH_TOKEN": "$MINIMAX_CN_API_KEY",
|
|
118
125
|
"ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic",
|
|
119
|
-
"ANTHROPIC_MODEL": "MiniMax-
|
|
126
|
+
"ANTHROPIC_MODEL": "MiniMax-M3"
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
```
|
|
123
130
|
|
|
124
131
|
```bash
|
|
125
|
-
# .env minimal pour MiniMax
|
|
132
|
+
# .env minimal pour MiniMax CN
|
|
126
133
|
MINIMAX_CN_API_KEY=ton_token_minimax_ici
|
|
127
134
|
```
|
|
128
135
|
|
|
129
136
|
**auth.json** stocke sous `MINIMAX_CN_API_KEY`.
|
|
130
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
|
+
|
|
131
162
|
---
|
|
132
163
|
|
|
133
164
|
### OpenRouter — BANNIR pour LLM
|
|
@@ -145,8 +176,63 @@ MINIMAX_CN_API_KEY=ton_token_minimax_ici
|
|
|
145
176
|
|
|
146
177
|
---
|
|
147
178
|
|
|
179
|
+
## HERMES_HOME resolution (multi-OS, multi-install)
|
|
180
|
+
|
|
181
|
+
Chaque agent Hermes a son propre HERMES_HOME. Le path est resolu de maniere
|
|
182
|
+
deterministe par `getAgentHermesHome(agentName)` dans `src/lib/config.ts`.
|
|
183
|
+
|
|
184
|
+
Ordre de resolution (la premiere gagne):
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
OVERMIND_AGENT_HOME (env var, set par l'install ou systemd)
|
|
188
|
+
↓
|
|
189
|
+
<workspace>/.overmind/hermes/agent_<name>/.hermes (legacy, si deja existant)
|
|
190
|
+
↓
|
|
191
|
+
$HOME/.overmind/hermes/agent_<name>/.hermes (Linux/Mac sudo npm -g)
|
|
192
|
+
%LOCALAPPDATA%\overmind\hermes\agent_<name>\.hermes (Windows npm -g)
|
|
193
|
+
%USERPROFILE%\overmind\hermes\agent_<name>\.hermes (Windows fallback)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Pour un agent nomme `sniperbot_analyst`:
|
|
197
|
+
- Dev local (workspace = `C:\Users\Deamon\Desktop\Backup\Serveur MCP\Workflow`):
|
|
198
|
+
`Workflow\.overmind\hermes\agent_sniperbot_analyst\.hermes` (si deja cree)
|
|
199
|
+
- Prod Linux: `~/.overmind/hermes/agent_sniperbot_analyst/.hermes`
|
|
200
|
+
- Prod Windows: `%LOCALAPPDATA%\overmind\hermes\agent_sniperbot_analyst\.hermes`
|
|
201
|
+
|
|
202
|
+
**Pourquoi c'est important**: avant, le runner Overmind calculait HERMES_HOME
|
|
203
|
+
depuis `process.cwd()`. Si le sniper etait lance depuis `C:\Users\Deamon\Desktop\Backup\Serveur MCP\`
|
|
204
|
+
et le runner depuis `Workflow\`, ils lisaient des `.hermes/.env` differents
|
|
205
|
+
et ecrivaient dans des `auth.json` differents. Maintenant, c'est cwd-independent.
|
|
206
|
+
|
|
207
|
+
Pour forcer un chemin explicite (ex: deploy Docker), set:
|
|
208
|
+
```bash
|
|
209
|
+
export OVERMIND_AGENT_HOME=/var/lib/overmind/hermes
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
|
|
148
213
|
## Comment Hermes decide quel provider utiliser
|
|
149
214
|
|
|
215
|
+
Il y a DEUX niveaux de decision:
|
|
216
|
+
|
|
217
|
+
### Niveau 1: Overmind runner (avant spawn)
|
|
218
|
+
|
|
219
|
+
`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:
|
|
220
|
+
|
|
221
|
+
1. **Token prefix** (le plus fiable) — `detectTokenProvider()` reconnait:
|
|
222
|
+
- `sk-cp-...` ou `sk-mm-...` → `minimax`
|
|
223
|
+
- `32hex.32hex` ou 32-char hex → `zai`
|
|
224
|
+
- `sk-ant-...` → `anthropic`
|
|
225
|
+
- `sk-or-...` → `openrouter` (mais BLOQUE pour LLM par la suite)
|
|
226
|
+
- `sk-...` (autre) → `openai`
|
|
227
|
+
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`.
|
|
228
|
+
3. **ANTHROPIC_PROVIDER** hint du settings (le moins fiable).
|
|
229
|
+
|
|
230
|
+
**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.
|
|
231
|
+
|
|
232
|
+
### Niveau 2: Hermes upstream (apres spawn)
|
|
233
|
+
|
|
234
|
+
Hermes relit son `auth.json` + `HERMES_HOME/.env` + `os.environ` avec sa propre logique (dans `hermes_cli/auth.py`):
|
|
235
|
+
|
|
150
236
|
```
|
|
151
237
|
1. Si `provider` explicite dans config.yaml → utilise ce provider
|
|
152
238
|
2. Sinon si `ANTHROPIC_BASE_URL` contient openrouter → "openrouter"
|
|
@@ -156,7 +242,7 @@ MINIMAX_CN_API_KEY=ton_token_minimax_ici
|
|
|
156
242
|
4. Sinon fallback: model.default dans config.yaml
|
|
157
243
|
```
|
|
158
244
|
|
|
159
|
-
Le
|
|
245
|
+
**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).
|
|
160
246
|
|
|
161
247
|
---
|
|
162
248
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "overmind-mcp",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.26",
|
|
4
4
|
"description": "Orchestrateur universel agents IA multi-modeles via MCP. Inclut le protocole 'Custom-Nickname' pour identifier vos agents avec des surnoms originaux (The Chaos Prophet, Shadow Sniper, etc.), l'isolation mémoire (Private Memory Context) et le support pour QwenCli et Nous Hermes. Installation automatique des dépendances Docker (PostgreSQL, pgvector) inclus.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* migrate-hermes-home.js — One-shot migration for HERMES_HOME path change.
|
|
4
|
+
*
|
|
5
|
+
* Background: HERMES_HOME was previously computed from process.cwd() which
|
|
6
|
+
* produced different paths depending on where the runner was launched from.
|
|
7
|
+
* Starting with Overmind 2.8.27, HERMES_HOME is resolved from
|
|
8
|
+
* OVERMIND_AGENT_HOME or $HOME/.overmind/hermes/agent_<name>/.hermes.
|
|
9
|
+
*
|
|
10
|
+
* This script migrates any existing state from the legacy workspace-relative
|
|
11
|
+
* paths (e.g. <workflow>/.overmind/hermes/agent_<name>/) to the new canonical
|
|
12
|
+
* HOME-based path. Safe to run multiple times.
|
|
13
|
+
*
|
|
14
|
+
* Usage: node scripts/migrate-hermes-home.js [--dry-run]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
import os from 'os';
|
|
20
|
+
|
|
21
|
+
const args = process.argv.slice(2);
|
|
22
|
+
const dryRun = args.includes('--dry-run');
|
|
23
|
+
|
|
24
|
+
function log(msg) {
|
|
25
|
+
process.stdout.write(`[migrate-hermes-home] ${msg}\n`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function findLegacyBases(workspaceDir) {
|
|
29
|
+
const legacy = [];
|
|
30
|
+
for (const sub of ['.overmind/hermes', '.overmind/hermes/agent_*']) {
|
|
31
|
+
const full = path.join(workspaceDir, sub);
|
|
32
|
+
if (fs.existsSync(full)) {
|
|
33
|
+
try {
|
|
34
|
+
const entries = fs.readdirSync(full, { withFileTypes: true });
|
|
35
|
+
for (const e of entries) {
|
|
36
|
+
if (e.isDirectory() && e.name.startsWith('agent_')) {
|
|
37
|
+
legacy.push(path.join(full, e.name));
|
|
38
|
+
} else if (e.isDirectory() && e.name === 'central') {
|
|
39
|
+
legacy.push(path.join(full, e.name));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} catch { /* ignore */ }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return legacy;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getCanonicalBase(platform) {
|
|
49
|
+
const homeBase = process.env.LOCALAPPDATA
|
|
50
|
+
|| process.env.USERPROFILE
|
|
51
|
+
|| os.homedir();
|
|
52
|
+
return platform === 'win32'
|
|
53
|
+
? path.join(homeBase, 'overmind', 'hermes')
|
|
54
|
+
: path.join(homeBase, '.overmind', 'hermes');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function migrateOne(src, dst) {
|
|
58
|
+
// src = legacy agent dir (e.g. <workspace>/.overmind/hermes/agent_foo)
|
|
59
|
+
// dst = canonical agent dir (e.g. ~/.overmind/hermes/agent_foo)
|
|
60
|
+
if (fs.existsSync(dst)) {
|
|
61
|
+
log(` SKIP: destination already exists: ${dst}`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (dryRun) {
|
|
65
|
+
log(` DRY-RUN: would move ${src} -> ${dst}`);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
// Make parent if missing
|
|
69
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
70
|
+
// Use rename for atomicity (works on same-filesystem; cross-fs would need copy+delete)
|
|
71
|
+
try {
|
|
72
|
+
fs.renameSync(src, dst);
|
|
73
|
+
log(` MOVED: ${src} -> ${dst}`);
|
|
74
|
+
return true;
|
|
75
|
+
} catch (e) {
|
|
76
|
+
if (e.code === 'EXDEV') {
|
|
77
|
+
// Cross-device: copy + delete
|
|
78
|
+
log(` CROSS-FS: copying ${src} -> ${dst}`);
|
|
79
|
+
copyDirSync(src, dst);
|
|
80
|
+
fs.rmSync(src, { recursive: true, force: true });
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
throw e;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function copyDirSync(src, dst) {
|
|
88
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
89
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
90
|
+
const s = path.join(src, entry.name);
|
|
91
|
+
const d = path.join(dst, entry.name);
|
|
92
|
+
if (entry.isDirectory()) {
|
|
93
|
+
copyDirSync(s, d);
|
|
94
|
+
} else if (entry.isFile()) {
|
|
95
|
+
fs.copyFileSync(s, d);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function main() {
|
|
101
|
+
const workspaceDir = process.env.OVERMIND_WORKSPACE
|
|
102
|
+
|| process.cwd();
|
|
103
|
+
const platform = process.platform;
|
|
104
|
+
const canonicalBase = getCanonicalBase(platform);
|
|
105
|
+
|
|
106
|
+
log(`workspace: ${workspaceDir}`);
|
|
107
|
+
log(`platform: ${platform}`);
|
|
108
|
+
log(`canonical: ${canonicalBase}`);
|
|
109
|
+
log(`mode: ${dryRun ? 'DRY-RUN' : 'LIVE'}`);
|
|
110
|
+
log('');
|
|
111
|
+
|
|
112
|
+
const legacy = findLegacyBases(workspaceDir);
|
|
113
|
+
if (legacy.length === 0) {
|
|
114
|
+
log('No legacy .overmind directories found. Nothing to migrate.');
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let moved = 0;
|
|
119
|
+
for (const src of legacy) {
|
|
120
|
+
const name = path.basename(src);
|
|
121
|
+
const dst = path.join(canonicalBase, name);
|
|
122
|
+
log(`Migrating ${name}:`);
|
|
123
|
+
if (migrateOne(src, dst)) moved++;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
log('');
|
|
127
|
+
log(`Done. ${moved}/${legacy.length} agent directories migrated.`);
|
|
128
|
+
if (dryRun) {
|
|
129
|
+
log('Re-run without --dry-run to actually perform the migration.');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
main();
|