UNPKG

overmind-mcp

Version:

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

307 lines (236 loc) • 13.6 kB
LA SUBTILISATION — comment Overmind devine ton provider LLM à partir de ton token ============================================================================== Version: Overmind 2.8.28 (2026-06-07) Hermes requis: v0.16.0+ Concept (1 phrase) ------------------ Le runner Overmind ne te demande PAS quel provider tu utilises. Il LIT ton token, en déduit le préfixe, et MAPPE automatiquement vers le bon env var que le plugin provider de Hermes attend. Pourquoi ça existe ----------------- Les tokens de providers LLM ont des préfixes distincts que tu ne connais peut-être pas : sk-cp-... -> MiniMax (env: MINIMAX_API_KEY, MINIMAX_CN_API_KEY) sk-mm-... -> MiniMax (variante) sk-ant-... -> Anthropic (env: ANTHROPIC_AUTH_TOKEN) sk-or-... -> OpenRouter (BLOQUÉ pour LLM, embeddings only) sk-... -> OpenAI (env: OPENAI_API_KEY) 32hex.32hex -> Z.AI / GLM (env: ZAI_ANTHROPIC_FALLBACK_KEY, GLM_API_KEY) 32hex -> Z.AI (variante single-block) 16hex+ -> Z.AI (catch-all hex) CAS SPÉCIAL : sk-cp- est ambigu entre MiniMax GLOBAL et MiniMax CN ------------------------------------------------------------------ Meme prefix. Pour desambiguïser, le runner regarde l'ANTHROPIC_BASE_URL : - api.minimaxi.com (avec le i) -> minimax-cn - api.minimax.com (sans le i) -> minimax (GLOBAL) L'URL gagne dans ce cas parce qu'elle est la seule a desambiguïser. Ce que tu mets dans settings_<agent>.json : { "env": { "ANTHROPIC_AUTH_TOKEN": "$ANTHROPIC_AUTH_TOKEN_2", "ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic", "ANTHROPIC_MODEL": "MiniMax-M3", "ANTHROPIC_PROVIDER": "minimax-cn" } } Le runner voit ANTHROPIC_BASE_URL contient "minimaxi" -> effectiveProvider = minimax-cn. Il seed auth.json avec MINIMAX_CN_API_KEY et the bon endpoint. Hermes route vers le plugin minimax-cn. CONVENTION : MiniMax = CN par defaut ------------------------------------- Le prefixe sk-cp- est partage entre MiniMax GLOBAL (api.minimax.com) et MiniMax CN (api.minimaxi.com). L'URL est le seul signal qui desambigüise. Pour les setups ou TOUS les tokens MiniMax sont CN (le cas le plus commun), le runner a un fallback par defaut : quand un token sk-cp-* est detecte sans URL explicite, on bascule sur minimax-cn au lieu de minimax (GLOBAL). Controlable via la variable d'environnement OVERMIND_MINIMAX_DEFAULT : OVERMIND_MINIMAX_DEFAULT=cn (defaut) sk-cp-* sans URL -> minimax-cn OVERMIND_MINIMAX_DEFAULT=global sk-cp-* sans URL -> minimax OVERMIND_MINIMAX_DEFAULT=auto sk-cp-* sans URL -> minimax (no override) Si ANTHROPIC_BASE_URL est explicite dans les settings, l'URL gagne TOUJOURS sur OVERMIND_MINIMAX_DEFAULT (le vote 3-signal reste prioritaire). Pour ton setup actuel (tous les tokens sk-cp-* sont CN), le defaut "cn" est ce que tu veux. Pas besoin de le set explicitement, mais c'est plus safe de le mettre dans le .env pour clarifier l'intention. Comment ça marche en pratique ---------------------------- 1. Tu écris un settings_<agent>.json minimal : { "env": { "ANTHROPIC_MODEL": "MiniMax-M3", "ANTHROPIC_AUTH_TOKEN": "$ANTHROPIC_AUTH_TOKEN_2", "ANTHROPIC_PROVIDER": "minimax-cn", "ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic" } } 2. Overmind (etapes detaillees) : a. Lit le settings BRUT (AVANT interpolation des $VAR) b. Voit "$ANTHROPIC_AUTH_TOKEN_2" -> le résout depuis process.env c. Obtient la valeur du token (ex: "sk-cp-...m0") d. SNIFF le préfixe -> détecte "sk-cp-" -> provider = minimax e. RECONCILIE 3 signaux (vote par priorite) : - token détecté : minimax (subtilisation par préfixe) - URL du base : minimax-cn (api.minimaxi.com) - settings hint : minimax-cn (ANTHROPIC_PROVIDER) URL gagne (plus specifique que le token) -> effectiveProvider = minimax-cn f. PRUNE auth.json (enleve les vieux credential_pool entries d'autres providers comme zai/minimax qui etaient stales) g. ECRIT le .env de l'agent avec les 4 champs canoniques : ANTHROPIC_MODEL=MiniMax-M3 ANTHROPIC_AUTH_TOKEN=*** ANTHROPIC_PROVIDER=minimax-cn ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic + seed provider-specific (MINIMAX_CN_API_KEY=*** h. ECRIT auth.json avec le bucket minimax-cn uniquement (les autres buckets du fichier sont preserves comme providers oauth, mais credential_pool est reset pour eviter le drift) i. INVOQUE Hermes qui lit son .env et route vers le bon endpoint RESOLUTION DES TOKENS (3-pass strategy, NOUVEAU en 2.8.16+) ----------------------------------------------------------- Quand l'agent a PLUSIEURS clés dans son env (cas fréquent : le user met plusieurs providers dans Workflow/.env), le runner ne prend plus la première claire comme avant. Il fait 3 passes : Pass 1: settings_<agent>.json env block -> WINS si une clé de token est là - Litteral token ("sk-cp-...") -> utilisé tel quel - Reference $VAR ("$MINIMAX_CN_API_KEY") -> résolue depuis process.env - $VAR introuvable ? FAIL LOUD (throw MISSING_ENV_VAR) - On ne fallback PAS silencieusement sur une autre clé Pass A: prefer keys whose NAME matches the detected provider - Si MINIMAX_API_KEY=*** ET ANTHROPIC_AUTH_TOKEN=*** sont tous les deux présents, le user a explicitement mis la provider-specific, on respecte son choix -> MINIMAX_API_KEY gagne - FIX bug : avant, la 1re clé de TOKEN_KEYS (ANTHROPIC_AUTH_TOKEN) gagnait TOUJOURS par re-map, ce qui ecrase silencieusement la provider-specific que le user avait set explicitement Pass B: re-map la 1re clé vers le bon provider - Si seulement ANTHROPIC_AUTH_TOKEN=*** alors on sait que c'est un MiniMax (sk-cp-*), on le re-mappe vers MINIMAX_API_KEY Pass C: rare, fallback si rien ne match INTERPOLATION $VAR DANS settings_<agent>.json (FIX BUG) -------------------------------------------------------- Le runner utilise interpolateEnvVars() (src/lib/envUtils.ts) pour résoudre les references $VAR et ${VAR} avant d'utiliser les settings. Bug fixé en 2.8.25 : la regex precedente `\$(\w+)|\${\w+}` avait DEUX bugs : (a) Un seul groupe capturant au lieu de deux — ${VAR} causait un crash sur process.env[undefined] (b) Le } fermant n'etait pas consomme — fuyait comme texte literal Nouvelle regex : `\$\{(\w+)\}|\$(\w+)` (deux groupes, un par branche, } consomme). Exemples : "${HOME}" -> C:\Users\Deamon (correct, } consomme) "$HOME" -> C:\Users\Deamon (correct, bare form) "sk-${REGION}-x" -> sk-cp-x (correct, mixed) "$$" -> "" (correct, escape not supported) Ce que tu n'as PAS besoin de faire ---------------------------------- - Tu n'as pas à deviner quel env var name le plugin Hermes attend - Tu n'as pas à lire plugins/model-providers/minimax/init.py - Tu n'as pas à mapper manuellement $KEY vers le bon provider - Tu n'as pas à tester 50 combinaisons d'env var names - Tu n'as pas à te soucier du cwd du process pour HERMES_HOME (v3.1: injecté par HermesRunner) Tu mets ton token, Overmind s'occupe du reste. HERMES_HOME : résolution déterministe (NOUVEAU en 2.8.27) --------------------------------------------------------- Le path où Hermes stocke son état (.env, auth.json, sessions, state.db) est résolu par getAgentHermesHome(agentName) dans src/lib/config.ts. Ordre de résolution : 1. $OVERMIND_AGENT_HOME (env var, set par l'install sudo ou systemd) 2. <workspace>/.overmind/hermes/agent_<name>/.hermes (legacy, si existe) 3. $HOME/.overmind/hermes/agent_<name>/.hermes (Linux/Mac sudo) %LOCALAPPDATA%\overmind\hermes\agent_<name>\.hermes (Windows) %USERPROFILE%\overmind\hermes\agent_<name>\.hermes (Windows fallback) Pour un agent "sniperbot_analyst" : - Dev local: Workflow\.overmind\hermes\agent_sniperbot_analyst\.hermes - Prod Linux: ~/.overmind/hermes/agent_sniperbot_analyst/.hermes - Prod Win: %LOCALAPPDATA%\overmind\hermes\agent_sniperbot_analyst\.hermes Pour forcer un path explicite (Docker, deploy custom) : export OVERMIND_AGENT_HOME=/var/lib/overmind/hermes Pour migrer un ancien install (state dans le workspace-relative path) : cd ~/overmind-mcp node scripts/migrate-hermes-home.mjs --dry-run # preview node scripts/migrate-hermes-home.mjs # apply Les 3 signaux que vote Overmind (priorité décroissante) -------------------------------------------------------- 1. PRÉFIXE DU TOKEN (le plus fiable — c'est la vérité du fournisseur) 2. URL DU BASE (très fiable — l'API elle-même) 3. ANTHROPIC_PROVIDER (le moins fiable — c'est juste un hint que tu donnes) Si les 3 ne sont pas d'accord, Overmind LOG un warning explicite mais utilise le token (signal le plus fiable). Exception : sk-cp- + URL disambiguent -> l'URL gagne (cf. plus haut). Si tu donnes une clé foireuse ----------------------------- - Token sk-cp- mais URL api.z.ai -> warning, mais token wins -> Hermes va appeler api.z.ai avec une clé MiniMax -> 401 du provider Z.AI - Token 32hex.32hex mais provider "minimax" -> warning, mais token wins -> Hermes va appeler le plugin zai avec un token Z.AI -> OK L'erreur 401 finale n'est PAS un bug du runner, c'est le provider LLM qui rejette la clé (expirée, mauvaise région, etc.). Comment Hermes obtient la API Key (le vrai flux) ----------------------------------------------- Le `ANTHROPIC_AUTH_TOKEN` dans `settings.json` NE PASSE PAS DIRECTEMENT dans le body de la requête API. Hermes utilise son propre credential pool : settings_[agent].json "env": { "ANTHROPIC_AUTH_TOKEN": "$MINIMAX_CN_API_KEY" } ↓ (interpolateEnvVars par NousHermesRunner) agentCustomEnv envoyé a Hermes: ANTHROPIC_AUTH_TOKEN=*** Hermes ne lit PAS ANTHROPIC_AUTH_TOKEN directement. Hermes lit le CREDENTIAL POOL (auth.json) + les .env vars listees dans api_key_env_vars. Credential pool est seed par: ZAI_ANTHROPIC_FALLBACK_KEY -> "zai" avec base_url coding Z_AI_API_KEY -> "zai" avec base_url non-coding (ancien) MINIMAX_CN_API_KEY -> "minimax-cn" MINIMAX_API_KEY -> "minimax" (GLOBAL) Le $VAR dans ANTHROPIC_AUTH_TOKEN is juste une convenience pour que le token traverse le runner et arrive dans process.env du subprocess Hermes. C'est process.env.MINIMAX_CN_API_KEY qui seed le credential pool. PRUNING auth.json (NOUVEAU en 2.8.27) -------------------------------------- A chaque run, le runner PRUNE credential_pool dans auth.json pour ne laisser que les entries du effectiveProvider. Cela evite que Hermes picke un vieux bucket (ex: zai avec last_status="exhausted") au lieu du nouveau (ex: minimax-cn fraichement seede). Le version + les oauth providers sont préservés, seul credential_pool est re-seedé from scratch. Symptôme résolu : "Anthropic 401 invalid api key" avec token prefix correct (sk-cp-...) qui était en fait servi par un vieux credential zai dans le pool, pas par le nouveau MINIMAX_CN_API_KEY du .env. NE PAS PASSER --provider au CLI Hermes (NOUVEAU en 2.8.28) ----------------------------------------------------------- Découverte empirique : quand le runner Overmind passait `hermes chat -q --provider minimax-cn` (avec un settings qui a déjà `ANTHROPIC_PROVIDER=minimax-cn`), le plugin Hermes upstream renvoyait 401. Mais `hermes chat --yolo` (SANS --provider, juste les env vars MINIMAX_CN_API_KEY + ANTHROPIC_BASE_URL + ANTHROPIC_MODEL) marchait. Cause : le flag --provider explicite active un code path buggé dans le plugin Hermes qui envoie un format d'auth header rejeté par api.minimaxi.com. Sans --provider, Hermes auto-détecte le provider depuis l'env var (MINIMAX_CN_API_KEY, ZAI_ANTHROPIC_FALLBACK_KEY, etc.) et passe par le bon code path. Fix appliqué en 2.8.28 : le runner ne passe PLUS --provider. Le resolvedProvider est juste loggué en INFO pour debug. Hermes choisit le bon plugin depuis l'env. Référence : ~/launcher/Hermes-MiniMax-2.bat marche parce qu'il fait juste `hermes chat --yolo` (pas --provider). Implementation -------------- La logique de subtilisation vit à deux endroits : 1. src/services/hermesTokenResolver.ts (canonique, exporté) - Utilisé par les tests unitaires - Source de vérité de la stratégie 3-pass 2. src/services/NousHermesRunner.ts (closure locale, dans runAgentInternal) - Copie miroir de la version canonique, pour ne pas avoir à thread 5 args (agentName, agentCustomEnv, TOKEN_KEYS, logger, ...) à chaque appel - DOIT rester sync avec la version canonique Si les deux divergent, c'est un bug. Pour résumer en 1 ligne ----------------------- La subtilisation = Overmind sniffe le préfixe de ton token, vote entre token/URL/settings pour confirmer, et mappe automatiquement vers le bon provider et le bon env var, sans que tu aies à configurer le mapping provider <-> env var toi-même. Le path HERMES_HOME est déterministe, auth.json est pruné à chaque run, et l'interpolation ${VAR} est robuste.