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.
@@ -35,4 +35,40 @@ export declare function isValidAgentName(name: string): boolean;
35
35
  export declare function getWorkspaceDir(): string;
36
36
  export declare function resolveConfigPath(configPath: string, workspaceDirOverride?: string): string;
37
37
  export declare function updateConfig(newSettingsPath?: string, newMcpPath?: string): void;
38
+ /**
39
+ * Resolve the canonical HERMES_HOME directory for an agent.
40
+ *
41
+ * This is the SINGLE source of truth for where per-agent Hermes state lives.
42
+ * Prior implementations computed this from `process.cwd()` which was non-
43
+ * deterministic (any process spawned from a different cwd would create or
44
+ * read a different HERMES_HOME). That caused the "two HERMES_HOME" problem
45
+ * where one Overmind process wrote its agent's `.hermes/.env` to
46
+ * `<workflow>/.overmind/...` while another process (e.g. a CLI launched
47
+ * from `<backup root>/.overmind/...`) read a different `.hermes/.env`
48
+ * — leading to credential drift, stale auth.json, and silent 401s.
49
+ *
50
+ * Resolution order (deterministic, multi-OS, multi-install):
51
+ * 1. `OVERMIND_AGENT_HOME` env var (set by the install script or systemd
52
+ * EnvironmentFile) — wins if set, because the operator declared it
53
+ * explicitly. The runner just trusts it.
54
+ * 2. `<workspace>/.overmind/hermes/agent_<name>/.hermes` — the legacy
55
+ * path. Kept as fallback for users who have existing state there.
56
+ * 3. `~/.overmind/hermes/agent_<name>/.hermes` — the canonical home dir
57
+ * location for `npm -g sudo` installs (Linux/Mac prod) and
58
+ * `%LOCALAPPDATA%\overmind\hermes\agent_<name>\.hermes` on Windows.
59
+ * Created if missing.
60
+ *
61
+ * Both `.hermes/` directory AND its parent are returned via the two-call
62
+ * pattern: `getAgentHermesHome(name)` returns the `.hermes/` path,
63
+ * `getAgentOvermindHome(name)` returns the parent (where SOUL.md lives).
64
+ *
65
+ * Safe under all install modes:
66
+ * - Dev local (`pnpm dev` from source repo): uses workspace fallback
67
+ * - Prod npm-g (Linux/Mac, `sudo npm i -g overmind-mcp`): uses HOME
68
+ * - Prod npm-g (Windows): uses %LOCALAPPDATA%
69
+ * - Docker / systemd: operator sets OVERMIND_AGENT_HOME explicitly
70
+ */
71
+ export declare function getAgentHermesHome(agentName: string | null | undefined): string;
72
+ /** Parent of getAgentHermesHome — the .overmind/hermes/agent_<name> dir. */
73
+ export declare function getAgentOvermindHome(agentName: string | null | undefined): string;
38
74
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;YACjB,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;KACH,CAAC;IACF,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;IACF,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAQD,QAAA,IAAI,WAAW,QAAU,CAAC;AAM1B,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,eAAO,MAAM,cAAc,EAAE,UA0B5B,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,UAAuD,CAAC;AAI7E,wBAAgB,mBAAmB,SAElC;AAED,oDAAoD;AACpD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,eAAe,IAAI,MAAM,CA+DxC;AAQD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAkB3F;AAED,wBAAgB,YAAY,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,QAGzE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;YACjB,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;KACH,CAAC;IACF,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;IACF,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAQD,QAAA,IAAI,WAAW,QAAU,CAAC;AAM1B,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,eAAO,MAAM,cAAc,EAAE,UA0B5B,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,UAAuD,CAAC;AAI7E,wBAAgB,mBAAmB,SAElC;AAED,oDAAoD;AACpD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,eAAe,IAAI,MAAM,CA+DxC;AAQD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAkB3F;AAED,wBAAgB,YAAY,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,QAGzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAiD/E;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAEjF"}
@@ -136,4 +136,95 @@ export function updateConfig(newSettingsPath, newMcpPath) {
136
136
  if (newMcpPath)
137
137
  CONFIG.CLAUDE.PATHS.MCP = newMcpPath;
138
138
  }
139
+ /**
140
+ * Resolve the canonical HERMES_HOME directory for an agent.
141
+ *
142
+ * This is the SINGLE source of truth for where per-agent Hermes state lives.
143
+ * Prior implementations computed this from `process.cwd()` which was non-
144
+ * deterministic (any process spawned from a different cwd would create or
145
+ * read a different HERMES_HOME). That caused the "two HERMES_HOME" problem
146
+ * where one Overmind process wrote its agent's `.hermes/.env` to
147
+ * `<workflow>/.overmind/...` while another process (e.g. a CLI launched
148
+ * from `<backup root>/.overmind/...`) read a different `.hermes/.env`
149
+ * — leading to credential drift, stale auth.json, and silent 401s.
150
+ *
151
+ * Resolution order (deterministic, multi-OS, multi-install):
152
+ * 1. `OVERMIND_AGENT_HOME` env var (set by the install script or systemd
153
+ * EnvironmentFile) — wins if set, because the operator declared it
154
+ * explicitly. The runner just trusts it.
155
+ * 2. `<workspace>/.overmind/hermes/agent_<name>/.hermes` — the legacy
156
+ * path. Kept as fallback for users who have existing state there.
157
+ * 3. `~/.overmind/hermes/agent_<name>/.hermes` — the canonical home dir
158
+ * location for `npm -g sudo` installs (Linux/Mac prod) and
159
+ * `%LOCALAPPDATA%\overmind\hermes\agent_<name>\.hermes` on Windows.
160
+ * Created if missing.
161
+ *
162
+ * Both `.hermes/` directory AND its parent are returned via the two-call
163
+ * pattern: `getAgentHermesHome(name)` returns the `.hermes/` path,
164
+ * `getAgentOvermindHome(name)` returns the parent (where SOUL.md lives).
165
+ *
166
+ * Safe under all install modes:
167
+ * - Dev local (`pnpm dev` from source repo): uses workspace fallback
168
+ * - Prod npm-g (Linux/Mac, `sudo npm i -g overmind-mcp`): uses HOME
169
+ * - Prod npm-g (Windows): uses %LOCALAPPDATA%
170
+ * - Docker / systemd: operator sets OVERMIND_AGENT_HOME explicitly
171
+ */
172
+ export function getAgentHermesHome(agentName) {
173
+ const name = agentName ? `agent_${agentName}` : 'central';
174
+ const hermesSub = '.hermes';
175
+ // 1. Explicit override (operator-declared, e.g. via systemd EnvironmentFile
176
+ // or install script). The env var points to the PARENT directory
177
+ // (the .overmind/hermes/agent_<name> dir, not the .hermes subdir).
178
+ if (process.env.OVERMIND_AGENT_HOME) {
179
+ return path.join(process.env.OVERMIND_AGENT_HOME, hermesSub);
180
+ }
181
+ // 2. Legacy fallback: <workspace>/.overmind/hermes/<name>/.hermes
182
+ // Preserves backward compat with existing installs that have state
183
+ // in the workspace-relative .overmind directory.
184
+ try {
185
+ const ws = getWorkspaceDir();
186
+ const legacy = path.join(ws, '.overmind', 'hermes', name, hermesSub);
187
+ // If the legacy path already exists (i.e. previous runs created state
188
+ // there), use it — this is the "be conservative, don't break existing
189
+ // installs" rule. Only fall through to HOME-based if legacy is fresh.
190
+ if (fs.existsSync(legacy))
191
+ return legacy;
192
+ }
193
+ catch {
194
+ // getWorkspaceDir can throw if HOME is unset in some sandboxed envs.
195
+ // That's OK — we still have the HOME-based fallback below.
196
+ }
197
+ // 3. HOME-based canonical location (works for sudo npm -g installs).
198
+ // Linux/Mac: $HOME/.overmind/hermes/<name>/.hermes
199
+ // Windows: %LOCALAPPDATA%\overmind\hermes\<name>\.hermes
200
+ // (USERPROFILE is also accepted as a Windows fallback.)
201
+ const homeBase = process.env.LOCALAPPDATA
202
+ || process.env.USERPROFILE
203
+ || os.homedir();
204
+ const overmindRoot = process.platform === 'win32'
205
+ ? path.join(homeBase, 'overmind', 'hermes', name)
206
+ : path.join(homeBase, '.overmind', 'hermes', name);
207
+ // Create parent if missing (write-enabled). This makes the function safe
208
+ // to call before any agent has been initialized.
209
+ try {
210
+ fs.mkdirSync(overmindRoot, { recursive: true });
211
+ }
212
+ catch (e) {
213
+ // Permission denied or readonly fs — fall back to legacy workspace path.
214
+ // We don't throw here because callers (writeAuthJson, spawnHermes) need
215
+ // to be able to continue even if HOME-based mkdir fails.
216
+ const ws = (() => { try {
217
+ return getWorkspaceDir();
218
+ }
219
+ catch {
220
+ return process.cwd();
221
+ } })();
222
+ return path.join(ws, '.overmind', 'hermes', name, hermesSub);
223
+ }
224
+ return path.join(overmindRoot, hermesSub);
225
+ }
226
+ /** Parent of getAgentHermesHome — the .overmind/hermes/agent_<name> dir. */
227
+ export function getAgentOvermindHome(agentName) {
228
+ return path.dirname(getAgentHermesHome(agentName));
229
+ }
139
230
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA8B9C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,+CAA+C;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,IAAI,WAAW,GAAG,OAAO,CAAC;AAC1B,IAAI,CAAC;IACH,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC1C,WAAW,GAAG,GAAG,CAAC,OAAO,IAAI,WAAW,CAAC;AAC3C,CAAC;AAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,UAAU,EAAE,MAAM,EAAE,aAAa;IACjC,qBAAqB,EAAE,MAAM,EAAE,sDAAsD;IACrF,eAAe,EAAE,KAAK,EAAE,iCAAiC;IACzD,MAAM,EAAE;QACN,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,gCAAgC;QACxF,KAAK,EAAE;YACL,QAAQ,EAAE,yBAAyB;YACnC,GAAG,EAAE,WAAW;SACjB;KACF;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,aAAa,EAAE,gBAAgB;QAC/B,KAAK,EAAE;YACL,QAAQ,EAAE,yBAAyB;SACpC;KACF;IACD,MAAM,EAAE;QACN,IAAI,EAAE,SAAS;QACf,aAAa,EAAE,cAAc;QAC7B,KAAK,EAAE;YACL,QAAQ,EAAE,yBAAyB;SACpC;KACF;CACF,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,MAAM,GAAe,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;AAE7E,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAE7C,MAAM,UAAU,mBAAmB;IACjC,kBAAkB,GAAG,IAAI,CAAC;AAC5B,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,kBAAkB,CAAC;IAErF,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACnC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,IACE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAC1C,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,EAChD,CAAC;YACD,YAAY,GAAG,GAAG,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,IAAI,OAAO,GAAG,GAAG,CAAC;YAClB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,EAAE,CAAC;gBACzC,IACE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;oBAC9C,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,EACpD,CAAC;oBACD,YAAY,GAAG,OAAO,CAAC;oBACvB,MAAM;gBACR,CAAC;gBACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBAClD,IACE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;oBAC/C,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,EACrD,CAAC;oBACD,YAAY,GAAG,QAAQ,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;oBAC7B,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;oBACnD,IAAI,CAAC;wBACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;4BACjC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;4BAChD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,EACpC,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAC5C,CAAC;wBACJ,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,uCAAuC;wBACvC,YAAY,GAAG,GAAG,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,iGAAiG;IACjG,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IAC/D,IAAI,eAAe,EAAE,CAAC;QACpB,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,kBAAkB,GAAG,YAAY,CAAC;IAClC,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,sEAAsE;AACtE,0EAA0E;AAC1E,0EAA0E;AAC1E,iFAAiF;AACjF,yEAAyE;AAEzE,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,oBAA6B;IACjF,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAEnD,MAAM,YAAY,GAAG,oBAAoB,IAAI,eAAe,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAExD,0CAA0C;IAC1C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,4BAA4B,UAAU,6BAA6B,CAAC,CAAC;IACvF,CAAC;IAED,4DAA4D;IAC5D,IAAI,UAAU,KAAK,WAAW,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;QAChE,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IACjD,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,eAAwB,EAAE,UAAmB;IACxE,IAAI,eAAe;QAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,eAAe,CAAC;IACpE,IAAI,UAAU;QAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,UAAU,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"envUtils.d.ts","sourceRoot":"","sources":["../../src/lib/envUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,cAAc,GACf,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,cAAc,EAAE,GAChB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAAA;CAAE,CAAC;AAMtC,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE,OAAO,CAAC,MAAM,CAAiB,GACvC,cAAc,CA8BhB;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAIhD"}
1
+ {"version":3,"file":"envUtils.d.ts","sourceRoot":"","sources":["../../src/lib/envUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,cAAc,GACf,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,cAAc,EAAE,GAChB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAAA;CAAE,CAAC;AAMtC,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE,OAAO,CAAC,MAAM,CAAiB,GACvC,cAAc,CAsChB;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAIhD"}
@@ -7,9 +7,18 @@
7
7
  const unresolvedVars = [];
8
8
  export function interpolateEnvVars(obj, visited = new WeakSet()) {
9
9
  if (typeof obj === 'string') {
10
- // Replace unresolved vars with empty string and track which keys are missing
11
- return obj.replace(/\$(\w+)|\${(\w+)}/g, (_, name1, name2) => {
12
- const name = name1 || name2;
10
+ // Match $VAR and ${VAR}. The closing '}' MUST be inside the match so it does
11
+ // not leak into the output. The previous regex `\$(\w+)|\${\w+}` (a) had only
12
+ // one capture group (so `name2` was always undefined, and `${VAR}` crashed
13
+ // on `process.env[undefined]`), and (b) did not consume the '}' — leaking
14
+ // it as literal text. Fixed: explicit capture group on each alternation branch,
15
+ // closing brace consumed by the first branch.
16
+ return obj.replace(/\$\{(\w+)\}|\$(\w+)/g, (_, braced, bare) => {
17
+ const name = braced || bare;
18
+ // Defensive: should never happen, but if name is undefined (no capture
19
+ // matched), treat as literal text rather than crashing on process.env[undefined].
20
+ if (name === undefined)
21
+ return _;
13
22
  const value = process.env[name];
14
23
  if (value === undefined)
15
24
  unresolvedVars.push(name);
@@ -1 +1 @@
1
- {"version":3,"file":"envUtils.js","sourceRoot":"","sources":["../../src/lib/envUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,+EAA+E;AAC/E,oFAAoF;AACpF,MAAM,cAAc,GAAa,EAAE,CAAC;AAEpC,MAAM,UAAU,kBAAkB,CAChC,GAAmB,EACnB,UAA2B,IAAI,OAAO,EAAE;IAExC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,6EAA6E;QAC7E,OAAO,GAAG,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC3D,MAAM,IAAI,GAAG,KAAK,IAAI,KAAK,CAAC;YAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,KAAK,KAAK,SAAS;gBAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,+BAA+B;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,CAAC,cAAc;QAC5B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEjB,MAAM,MAAM,GAAmC,EAAE,CAAC;QAClD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,qBAAqB;IACnC,MAAM,IAAI,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC;IACjC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"envUtils.js","sourceRoot":"","sources":["../../src/lib/envUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,+EAA+E;AAC/E,oFAAoF;AACpF,MAAM,cAAc,GAAa,EAAE,CAAC;AAEpC,MAAM,UAAU,kBAAkB,CAChC,GAAmB,EACnB,UAA2B,IAAI,OAAO,EAAE;IAExC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,6EAA6E;QAC7E,8EAA8E;QAC9E,2EAA2E;QAC3E,0EAA0E;QAC1E,gFAAgF;QAChF,8CAA8C;QAC9C,OAAO,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;YAC7D,MAAM,IAAI,GAAG,MAAM,IAAI,IAAI,CAAC;YAC5B,uEAAuE;YACvE,kFAAkF;YAClF,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,CAAC,CAAC;YACjC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,KAAK,KAAK,SAAS;gBAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,+BAA+B;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,CAAC,cAAc;QAC5B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEjB,MAAM,MAAM,GAAmC,EAAE,CAAC;QAClD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,qBAAqB;IACnC,MAAM,IAAI,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC;IACjC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"NousHermesRunner.d.ts","sourceRoot":"","sources":["../../src/services/NousHermesRunner.ts"],"names":[],"mappings":"AA2DA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsFD;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,OAAO,CAAoB;;IAMnC,gBAAgB,IAAI,IAAI;IAclB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAkC3D,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;CAi1B1E"}
1
+ {"version":3,"file":"NousHermesRunner.d.ts","sourceRoot":"","sources":["../../src/services/NousHermesRunner.ts"],"names":[],"mappings":"AA2DA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAuGD;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,OAAO,CAAoB;;IAMnC,gBAAgB,IAAI,IAAI;IAclB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAkC3D,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;CAk5B1E"}
@@ -3,7 +3,7 @@ import path from 'path';
3
3
  import { spawn } from 'child_process';
4
4
  import { exec } from 'child_process';
5
5
  import { promisify } from 'util';
6
- import { CONFIG, resolveConfigPath, getWorkspaceDir } from '../lib/config.js';
6
+ import { CONFIG, resolveConfigPath, getWorkspaceDir, getAgentHermesHome, getAgentOvermindHome } from '../lib/config.js';
7
7
  import { getLastSessionId, saveSessionId } from '../lib/sessions.js';
8
8
  import { linkSessionToPid } from '../lib/processRegistry.js';
9
9
  import { interpolateEnvVars } from '../lib/envUtils.js';
@@ -52,6 +52,22 @@ const killProcessTree = (child) => {
52
52
  setTimeout(finish, 5000);
53
53
  });
54
54
  };
55
+ /**
56
+ * Default base URL for a given provider. Used when settings_<agent>.json
57
+ * doesn't specify ANTHROPIC_BASE_URL. Each provider has its canonical
58
+ * endpoint baked in here so the runner doesn't need an external config.
59
+ */
60
+ function defaultBaseUrlFor(provider) {
61
+ switch (provider) {
62
+ case 'minimax-cn': return 'https://api.minimaxi.com/anthropic';
63
+ case 'minimax': return 'https://api.minimax.com/anthropic';
64
+ case 'zai':
65
+ case 'z-ai': return 'https://api.z.ai/api/coding/paas/v4';
66
+ case 'anthropic': return 'https://api.anthropic.com';
67
+ case 'openai': return 'https://api.openai.com/v1';
68
+ default: return 'https://api.z.ai/api/coding/paas/v4';
69
+ }
70
+ }
55
71
  /**
56
72
  * Find hermes binary across platforms (Windows, Linux, macOS)
57
73
  * Priority: HERMES_BIN_PATH env > PATH > platform-specific paths > pip show
@@ -203,11 +219,13 @@ export class NousHermesRunner {
203
219
  const MAX_BUF = 10 * 1024 * 1024;
204
220
  const timeoutMs = this.timeoutMs;
205
221
  const HARD_TIMEOUT_MS = 60000;
206
- // HERMES_HOME setup
207
- const overmindHermesPath = path.resolve(cwd, '.overmind', 'hermes', agentName ? `agent_${agentName}` : 'central');
208
- const overmindHermesSubPath = path.join(overmindHermesPath, '.hermes');
222
+ // HERMES_HOME setup — use the canonical helper (multi-OS, multi-install safe).
223
+ // This replaces the previous cwd-relative resolution that caused HERMES_HOME
224
+ // drift between dev/prod installs and between different spawn cwd's.
225
+ const overmindHermesPath = getAgentOvermindHome(agentName);
226
+ const overmindHermesSubPath = getAgentHermesHome(agentName);
209
227
  if (agentName && !fs.existsSync(overmindHermesPath)) {
210
- return { result: '', error: `INVALID_AGENT: Agent Hermes "${agentName}" non trouvé.` };
228
+ return { result: '', error: `INVALID_AGENT: Agent Hermes "${agentName}" non trouvé (HERMES_HOME=${overmindHermesSubPath}).` };
211
229
  }
212
230
  // Load agent settings + MCP config (same pattern as ClaudeRunner)
213
231
  let systemPrompt = '';
@@ -225,7 +243,7 @@ export class NousHermesRunner {
225
243
  // OVERMIND_AGENT_HOME tells Hermes (v0.13.0+) to read agent-specific .env FIRST
226
244
  // get_env_value() in Hermes checks OVERMIND_AGENT_HOME/.hermes/.env before HERMES_HOME/.env
227
245
  // This allows $VAR expansion done by Overmind to take precedence over gateway .env
228
- ...(agentName ? { OVERMIND_AGENT_HOME: path.resolve(cwd, '.overmind', 'hermes', `agent_${agentName}`) } : {}),
246
+ ...(agentName ? { OVERMIND_AGENT_HOME: getAgentOvermindHome(agentName) } : {}),
229
247
  // NOTE: do NOT pre-seed GLM_API_KEY with '' here. The real value comes from
230
248
  // settings_<agent>.json (merged below) or from the agent's .hermes/.env file.
231
249
  // Seeding '' here used to win against Object.assign() whenever interpolateEnvVars()
@@ -425,6 +443,12 @@ export class NousHermesRunner {
425
443
  // OpenRouter → "sk-or-..." → env OPENROUTER_API_KEY (BLOCKED for LLM)
426
444
  // Mistral → (variable) → env MISTRAL_API_KEY_*
427
445
  // Other → unknown → env ANTHROPIC_AUTH_TOKEN (default Anthropic)
446
+ //
447
+ // NOTE: This function-local copy mirrors the canonical implementation in
448
+ // src/services/hermesTokenResolver.ts. The runner uses these local closures
449
+ // so it doesn't have to thread env/logger through every call site; the
450
+ // canonical exported versions exist for testing and for any future caller
451
+ // that wants the same behavior without instantiating NousHermesRunner.
428
452
  const TOKEN_PREFIX_PROVIDERS = [
429
453
  // Z.AI: c78a134949fc4c369911c24e9fa4b84c.OZhHX5Obs6qF1ISt (32hex.32hex — 2 blocks)
430
454
  { test: (t) => /^[0-9a-f]{32}\.[0-9a-zA-Z]+$/i.test(t), provider: 'zai', envKey: 'ZAI_ANTHROPIC_FALLBACK_KEY' },
@@ -453,42 +477,10 @@ export class NousHermesRunner {
453
477
  // ============================================================
454
478
  // TOKEN RESOLUTION ORDER (settings.env first, then process.env, then detection)
455
479
  // ============================================================
456
- // IMPORTANT — provider/credentials mapping (Hermes v0.16.0):
457
- // minimax-cn → MINIMAX_CN_API_KEY (NOT ANTHROPIC_AUTH_TOKEN)
458
- // minimax → MINIMAX_API_KEY
459
- // zai → GLM_API_KEY or ZAI_ANTHROPIC_FALLBACK_KEY
460
- // z-ai (alt) → Z_AI_API_KEY
461
- // anthropic → ANTHROPIC_AUTH_TOKEN (any of _1.._5, _E, _F, _Y)
462
- //
463
- // The agent's settings_<name>.json MUST use the env var name that matches
464
- // its ANTHROPIC_PROVIDER value, otherwise Hermes upstream will silently
465
- // 401 even though Overmind has the key. The minimax plugin in Hermes
466
- // (plugins/model-providers/minimax/init.py) decides the env var name — not Overmind.
467
- //
468
- // Resolution order (NEW in 2.8.16+):
469
- // 1. settings_<agent>.json env block (explicit, agent-specific — WINS)
470
- // 2. agent's .hermes/.env (isolated override)
471
- // 3. process.env (global .env via systemd EnvironmentFile)
472
- // 4. Detection by token prefix (subtilisation — last resort, maps to right provider)
473
- //
474
- // (Full list moved to top of scope for use in RAW pre-interpolation capture.)
475
- // See const TOKEN_KEYS at top of runHermesAgent() function.
476
- /**
477
- * Resolve a token with explicit settings priority + provider detection.
478
- *
479
- * Strategy:
480
- * 1. Read settings_<agent>.json env block.
481
- * - If user set a LITERAL token (e.g. "sk-cp-..."), use it directly.
482
- * - If user set a $VAR REFERENCE (e.g. "$GLM_API_KEY_Y"), RESOLVE IT.
483
- * - If $VAR is found in process.env → use the resolved value.
484
- * - If $VAR is NOT found in process.env → FAIL LOUD. Do NOT silently
485
- * fall back to TOKEN_KEYS (the user explicitly said "use THIS var").
486
- * - If user set something else (e.g. template, expression), try to resolve.
487
- * 2. If no settings token (or settings has no env block at all), fall back
488
- * to TOKEN_KEYS iteration in priority order from process.env.
489
- * 3. For each candidate, sniff the token prefix to know which provider it
490
- * belongs to, and re-map to the right env var name for that provider.
491
- */
480
+ // See src/services/hermesTokenResolver.ts for the canonical exported version
481
+ // and the rationale for the 3-pass strategy. The local closure below
482
+ // captures agentCustomEnv, TOKEN_KEYS, agentName, logger, and tmpSettingsPath
483
+ // from the enclosing scope so call sites stay terse.
492
484
  function resolveTokenWithDetection(explicitSettingsTokens) {
493
485
  // Step 1: settings_<agent>.json env block takes ABSOLUTE priority
494
486
  // (whatever the user explicitly set in their agent config wins)
@@ -520,21 +512,47 @@ export class NousHermesRunner {
520
512
  logger.info({ agentName, tokenKey: t.key, detectedProvider: detected.provider, mappedTo: detected.envKey }, '[SUBTILISATION] Using explicit settings_<agent>.json token, re-mapping to detected provider env var.');
521
513
  return { tokenEnvKey: t.key, tokenValue: resolvedValue, detectedProvider: detected.provider, source: 'settings-explicit' };
522
514
  }
523
- // Step 2: iterate TOKEN_KEYS in priority order, picking the first non-empty
515
+ const candidates = [];
524
516
  for (const tk of TOKEN_KEYS) {
525
517
  const v = agentCustomEnv[tk];
526
518
  if (v && typeof v === 'string' && v.length > 0) {
527
- const detected = detectTokenProvider(v);
528
- // If the env-var name doesn't match the detected provider, re-map.
529
- // (e.g. ANTHROPIC_AUTH_TOKEN=sk-cp-... → real env should be MINIMAX_API_KEY)
530
- if (detected.envKey !== tk && detected.provider !== 'unknown') {
531
- logger.info({ agentName, sourceKey: tk, detectedProvider: detected.provider, remappedTo: detected.envKey }, '[SUBTILISATION] Token prefix detected provider mismatch — re-mapping env var.');
532
- return { tokenEnvKey: detected.envKey, tokenValue: v, detectedProvider: detected.provider, source: 'detected' };
533
- }
534
- return { tokenEnvKey: tk, tokenValue: v, detectedProvider: detected.provider, source: 'env-fallback' };
519
+ candidates.push({ key: tk, value: v, detected: detectTokenProvider(v) });
535
520
  }
536
521
  }
537
- return null;
522
+ if (candidates.length === 0)
523
+ return null;
524
+ // Pass A: any candidate whose env-var name already matches its detected provider
525
+ // (e.g. MINIMAX_API_KEY=sk-cp-... → detected.envKey='MINIMAX_API_KEY' → match).
526
+ // TOKEN_KEYS ordering means provider-specific keys come first, so this preserves
527
+ // the user's explicit choice over a generic-key re-map.
528
+ for (const c of candidates) {
529
+ if (c.detected.provider !== 'unknown' && c.detected.envKey === c.key) {
530
+ return {
531
+ tokenEnvKey: c.key,
532
+ tokenValue: c.value,
533
+ detectedProvider: c.detected.provider,
534
+ source: 'env-fallback',
535
+ };
536
+ }
537
+ }
538
+ // Pass B: re-map the first candidate to the right provider env-var name.
539
+ const first = candidates[0];
540
+ if (first.detected.provider !== 'unknown' && first.detected.envKey !== first.key) {
541
+ logger.info({ agentName, sourceKey: first.key, detectedProvider: first.detected.provider, remappedTo: first.detected.envKey }, '[SUBTILISATION] Token prefix detected provider mismatch — re-mapping env var.');
542
+ return {
543
+ tokenEnvKey: first.detected.envKey,
544
+ tokenValue: first.value,
545
+ detectedProvider: first.detected.provider,
546
+ source: 'detected',
547
+ };
548
+ }
549
+ // Pass C (rare): all candidates have provider='unknown' or envKey already matches.
550
+ return {
551
+ tokenEnvKey: first.key,
552
+ tokenValue: first.value,
553
+ detectedProvider: first.detected.provider,
554
+ source: 'env-fallback',
555
+ };
538
556
  }
539
557
  const getAvailableFallbacks = () => {
540
558
  const fb = [];
@@ -586,6 +604,10 @@ export class NousHermesRunner {
586
604
  if (!fs.existsSync(overmindHermesSubPath))
587
605
  fs.mkdirSync(overmindHermesSubPath, { recursive: true });
588
606
  agentCustomEnv.HERMES_HOME = overmindHermesSubPath;
607
+ // HOME / USERPROFILE override: point Hermes at the parent .overmind dir,
608
+ // NOT the cwd. This makes relative .hermes lookups inside Hermes
609
+ // (e.g. `~/.hermes/.env` resolution) resolve to the same canonical
610
+ // location regardless of where the spawn came from.
589
611
  if (process.platform === 'win32')
590
612
  agentCustomEnv.USERPROFILE = overmindHermesPath;
591
613
  else
@@ -699,11 +721,32 @@ export class NousHermesRunner {
699
721
  return;
700
722
  try {
701
723
  const authPath = path.join(overmindHermesSubPath, 'auth.json');
702
- const auth = { version: 1, providers: {}, credential_pool: {} };
703
- if (fs.existsSync(authPath))
704
- Object.assign(auth, JSON.parse(fs.readFileSync(authPath, 'utf8')));
705
- if (!auth.credential_pool)
706
- auth.credential_pool = {};
724
+ // Read existing auth.json to preserve non-credential_pool state
725
+ // (e.g. oauth tokens, settings, version). But we PRUNE credential_pool
726
+ // entries for OTHER providers — those are stale from previous provider
727
+ // configs and Hermes may pick them up by mistake, causing silent 401s
728
+ // on the wrong endpoint. This is the source of the "auth.json drift"
729
+ // bug where the runner would seed `minimax-cn` credentials while a stale
730
+ // `zai` entry with last_status="exhausted" still existed in the pool.
731
+ let preservedAuth = { version: 1, providers: {} };
732
+ if (fs.existsSync(authPath)) {
733
+ try {
734
+ const parsed = JSON.parse(fs.readFileSync(authPath, 'utf8'));
735
+ // Keep the version + any oauth providers; drop credential_pool entirely
736
+ // (it will be re-seeded below with only the effectiveProvider's entries).
737
+ preservedAuth = {
738
+ version: parsed.version ?? 1,
739
+ providers: parsed.providers ?? {},
740
+ };
741
+ }
742
+ catch (e) {
743
+ logger.warn({ authPath, error: e }, 'auth.json was malformed; re-creating from scratch');
744
+ }
745
+ }
746
+ const auth = {
747
+ ...preservedAuth,
748
+ credential_pool: {},
749
+ };
707
750
  const cleanCp = auth.credential_pool;
708
751
  // Determine effective provider from MULTIPLE signals
709
752
  // Priority: TOKEN PREFIX (most reliable) > BASE_URL (very reliable) > settings.ANTHROPIC_PROVIDER (hint only)
@@ -739,6 +782,19 @@ export class NousHermesRunner {
739
782
  // SPECIAL CASE: if token says "minimax" and URL says "minimax-cn" (or vice versa),
740
783
  // the URL wins because the token prefix sk-cp- is shared between both endpoints.
741
784
  // The URL is the only signal that can disambiguate CN vs GLOBAL.
785
+ //
786
+ // DEFAULT FOR MiniMax WHEN AMBIGUOUS:
787
+ // The sk-cp- prefix is shared between MiniMax GLOBAL and MiniMax CN. The
788
+ // URL is the only signal that disambiguates. For users whose setup
789
+ // exclusively uses CN tokens (the most common case for non-China
790
+ // operators), an absent/ambiguous URL should default to CN rather than
791
+ // silently picking GLOBAL and getting a 401. Override via env var:
792
+ // OVERMIND_MINIMAX_DEFAULT=cn (default: CN when ambiguous)
793
+ // OVERMIND_MINIMAX_DEFAULT=global (treat sk-cp-* as GLOBAL)
794
+ // OVERMIND_MINIMAX_DEFAULT=auto (never infer, require URL to disambiguate)
795
+ const minimaxDefault = (process.env.OVERMIND_MINIMAX_DEFAULT || 'cn').toLowerCase();
796
+ const minimaxDefaults = { cn: 'minimax-cn', global: 'minimax', auto: 'minimax' };
797
+ const minimaxFallback = minimaxDefaults[minimaxDefault] || minimaxDefaults.cn;
742
798
  let effectiveProvider;
743
799
  if (detectedFromToken.provider === 'minimax' && detectedFromUrl === 'minimax-cn') {
744
800
  // URL has more specific info than the token prefix
@@ -749,6 +805,11 @@ export class NousHermesRunner {
749
805
  effectiveProvider = 'minimax';
750
806
  logger.info({ agentName, tokenSays: 'minimax-cn', urlSays: 'minimax', settingsHint }, '[SUBTILISATION] URL is more specific than token prefix (minimax vs minimax-cn) — using URL.');
751
807
  }
808
+ else if (detectedFromToken.provider === 'minimax' && !detectedFromUrl) {
809
+ // Token says MiniMax, no URL hint — use OVERMIND_MINIMAX_DEFAULT
810
+ effectiveProvider = minimaxFallback;
811
+ logger.info({ agentName, tokenSays: 'minimax', urlSays: '(none)', minimaxDefault, effectiveProvider }, '[SUBTILISATION] MiniMax token without explicit URL — applying OVERMIND_MINIMAX_DEFAULT.');
812
+ }
752
813
  else if (detectedFromToken.provider !== 'unknown') {
753
814
  effectiveProvider = detectedFromToken.provider;
754
815
  if (settingsHint && settingsHint !== effectiveProvider) {
@@ -771,7 +832,7 @@ export class NousHermesRunner {
771
832
  id: `${effectiveProvider}-default`, label: tokenInfo.tokenEnvKey, auth_type: 'api_key',
772
833
  priority: 0, source: `env:${tokenInfo.tokenEnvKey}`, access_token: tokenInfo.tokenValue,
773
834
  last_status: null, last_error_code: null,
774
- base_url: baseUrlHint || 'https://api.z.ai/api/coding/paas/v4',
835
+ base_url: baseUrlHint || defaultBaseUrlFor(effectiveProvider),
775
836
  request_count: 0,
776
837
  }];
777
838
  fs.writeFileSync(authPath, JSON.stringify(auth, null, 2), 'utf8');
@@ -789,7 +850,7 @@ export class NousHermesRunner {
789
850
  // 2. ANTHROPIC_PROVIDER (the kebab-case provider name)
790
851
  dotLines.push(`ANTHROPIC_PROVIDER=${effectiveProvider}`);
791
852
  // 3. ANTHROPIC_BASE_URL (from settings, or fallback)
792
- const resolvedBaseUrl = baseUrlHint || 'https://api.z.ai/api/coding/paas/v4';
853
+ const resolvedBaseUrl = baseUrlHint || defaultBaseUrlFor(effectiveProvider);
793
854
  dotLines.push(`ANTHROPIC_BASE_URL=${resolvedBaseUrl}`);
794
855
  // 4. ANTHROPIC_AUTH_TOKEN = literal token value (for backward compat with older Hermes versions)
795
856
  // (Hermes reads this env var directly — no more provider-specific mapping)
@@ -819,7 +880,7 @@ export class NousHermesRunner {
819
880
  // ANTHROPIC_AUTH_TOKEN already set above
820
881
  }
821
882
  fs.writeFileSync(dotEnvPath, dotLines.join('\n') + '\n', 'utf8');
822
- logger.info({ agentName, effectiveProvider, baseUrl: resolvedBaseUrl, model: finalModel, sourceKey: tokenInfo.tokenEnvKey, detectedProvider: detectedFromToken.provider }, '[AUTH] Wrote agent .env with 4 canonical Hermes fields + provider-specific seeds.');
883
+ logger.info({ agentName, effectiveProvider, baseUrl: resolvedBaseUrl, model: finalModel, sourceKey: tokenInfo.tokenEnvKey, detectedProvider: detectedFromToken.provider, envKeysWritten: dotLines.length }, '[AUTH] Wrote agent .env with 4 canonical Hermes fields + provider-specific seeds.');
823
884
  }
824
885
  catch (e) {
825
886
  logger.warn({ error: e, agentName }, '[AUTH] Failed to write auth.json or agent .env');