overmind-mcp 0.0.2-alpha
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/LICENSE +21 -0
- package/README.md +137 -0
- package/assets/overmind_core_closeup.png +0 -0
- package/assets/overmind_mcp_banner.png +0 -0
- package/assets/overmind_mcp_banner_slim.png +0 -0
- package/assets/overmind_mcp_final_banner.png +0 -0
- package/assets/overmind_mcp_pro_banner.png +0 -0
- package/assets/overmind_mcp_pro_banner_v2.png +0 -0
- package/assets/overmind_mcp_pro_banner_v3.png +0 -0
- package/assets/terminal_preview.png +0 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +481 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/InstallHelper.d.ts +14 -0
- package/dist/lib/InstallHelper.d.ts.map +1 -0
- package/dist/lib/InstallHelper.js +113 -0
- package/dist/lib/InstallHelper.js.map +1 -0
- package/dist/lib/config.d.ts +58 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +110 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/envUtils.d.ts +10 -0
- package/dist/lib/envUtils.d.ts.map +1 -0
- package/dist/lib/envUtils.js +24 -0
- package/dist/lib/envUtils.js.map +1 -0
- package/dist/lib/loadEnv.d.ts +2 -0
- package/dist/lib/loadEnv.d.ts.map +1 -0
- package/dist/lib/loadEnv.js +26 -0
- package/dist/lib/loadEnv.js.map +1 -0
- package/dist/lib/logger.d.ts +8 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +81 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/modelMapping.d.ts +18 -0
- package/dist/lib/modelMapping.d.ts.map +1 -0
- package/dist/lib/modelMapping.js +88 -0
- package/dist/lib/modelMapping.js.map +1 -0
- package/dist/lib/sessions.d.ts +4 -0
- package/dist/lib/sessions.d.ts.map +1 -0
- package/dist/lib/sessions.js +108 -0
- package/dist/lib/sessions.js.map +1 -0
- package/dist/memory/MemoryFactory.d.ts +11 -0
- package/dist/memory/MemoryFactory.d.ts.map +1 -0
- package/dist/memory/MemoryFactory.js +19 -0
- package/dist/memory/MemoryFactory.js.map +1 -0
- package/dist/memory/PostgresMemoryProvider.d.ts +29 -0
- package/dist/memory/PostgresMemoryProvider.d.ts.map +1 -0
- package/dist/memory/PostgresMemoryProvider.js +372 -0
- package/dist/memory/PostgresMemoryProvider.js.map +1 -0
- package/dist/memory/types.d.ts +70 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +2 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/prompts/agent_prompts.d.ts +2 -0
- package/dist/prompts/agent_prompts.d.ts.map +1 -0
- package/dist/prompts/agent_prompts.js +21 -0
- package/dist/prompts/agent_prompts.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +174 -0
- package/dist/server.js.map +1 -0
- package/dist/services/AgentManager.d.ts +28 -0
- package/dist/services/AgentManager.d.ts.map +1 -0
- package/dist/services/AgentManager.js +393 -0
- package/dist/services/AgentManager.js.map +1 -0
- package/dist/services/ClaudeRunner.d.ts +27 -0
- package/dist/services/ClaudeRunner.d.ts.map +1 -0
- package/dist/services/ClaudeRunner.js +426 -0
- package/dist/services/ClaudeRunner.js.map +1 -0
- package/dist/services/ClineRunner.d.ts +23 -0
- package/dist/services/ClineRunner.d.ts.map +1 -0
- package/dist/services/ClineRunner.js +95 -0
- package/dist/services/ClineRunner.js.map +1 -0
- package/dist/services/GeminiRunner.d.ts +23 -0
- package/dist/services/GeminiRunner.d.ts.map +1 -0
- package/dist/services/GeminiRunner.js +236 -0
- package/dist/services/GeminiRunner.js.map +1 -0
- package/dist/services/KiloRunner.d.ts +32 -0
- package/dist/services/KiloRunner.d.ts.map +1 -0
- package/dist/services/KiloRunner.js +413 -0
- package/dist/services/KiloRunner.js.map +1 -0
- package/dist/services/NousHermesRunner.d.ts +24 -0
- package/dist/services/NousHermesRunner.d.ts.map +1 -0
- package/dist/services/NousHermesRunner.js +318 -0
- package/dist/services/NousHermesRunner.js.map +1 -0
- package/dist/services/OpenClawRunner.d.ts +22 -0
- package/dist/services/OpenClawRunner.d.ts.map +1 -0
- package/dist/services/OpenClawRunner.js +89 -0
- package/dist/services/OpenClawRunner.js.map +1 -0
- package/dist/services/OpenCodeRunner.d.ts +22 -0
- package/dist/services/OpenCodeRunner.d.ts.map +1 -0
- package/dist/services/OpenCodeRunner.js +91 -0
- package/dist/services/OpenCodeRunner.js.map +1 -0
- package/dist/services/PromptManager.d.ts +16 -0
- package/dist/services/PromptManager.d.ts.map +1 -0
- package/dist/services/PromptManager.js +54 -0
- package/dist/services/PromptManager.js.map +1 -0
- package/dist/services/QwenCliRunner.d.ts +22 -0
- package/dist/services/QwenCliRunner.d.ts.map +1 -0
- package/dist/services/QwenCliRunner.js +90 -0
- package/dist/services/QwenCliRunner.js.map +1 -0
- package/dist/tools/config_example.d.ts +18 -0
- package/dist/tools/config_example.d.ts.map +1 -0
- package/dist/tools/config_example.js +253 -0
- package/dist/tools/config_example.js.map +1 -0
- package/dist/tools/create_agent.d.ts +41 -0
- package/dist/tools/create_agent.d.ts.map +1 -0
- package/dist/tools/create_agent.js +75 -0
- package/dist/tools/create_agent.js.map +1 -0
- package/dist/tools/get_agent_configs.d.ts +18 -0
- package/dist/tools/get_agent_configs.d.ts.map +1 -0
- package/dist/tools/get_agent_configs.js +43 -0
- package/dist/tools/get_agent_configs.js.map +1 -0
- package/dist/tools/initialization_check.d.ts +2 -0
- package/dist/tools/initialization_check.d.ts.map +1 -0
- package/dist/tools/initialization_check.js +23 -0
- package/dist/tools/initialization_check.js.map +1 -0
- package/dist/tools/manage_agents.d.ts +80 -0
- package/dist/tools/manage_agents.d.ts.map +1 -0
- package/dist/tools/manage_agents.js +161 -0
- package/dist/tools/manage_agents.js.map +1 -0
- package/dist/tools/manage_prompts.d.ts +30 -0
- package/dist/tools/manage_prompts.d.ts.map +1 -0
- package/dist/tools/manage_prompts.js +64 -0
- package/dist/tools/manage_prompts.js.map +1 -0
- package/dist/tools/memory_runs.d.ts +14 -0
- package/dist/tools/memory_runs.d.ts.map +1 -0
- package/dist/tools/memory_runs.js +77 -0
- package/dist/tools/memory_runs.js.map +1 -0
- package/dist/tools/memory_search.d.ts +14 -0
- package/dist/tools/memory_search.d.ts.map +1 -0
- package/dist/tools/memory_search.js +46 -0
- package/dist/tools/memory_search.js.map +1 -0
- package/dist/tools/memory_store.d.ts +26 -0
- package/dist/tools/memory_store.d.ts.map +1 -0
- package/dist/tools/memory_store.js +46 -0
- package/dist/tools/memory_store.js.map +1 -0
- package/dist/tools/metadata.d.ts +20 -0
- package/dist/tools/metadata.d.ts.map +1 -0
- package/dist/tools/metadata.js +240 -0
- package/dist/tools/metadata.js.map +1 -0
- package/dist/tools/run_agent.d.ts +30 -0
- package/dist/tools/run_agent.d.ts.map +1 -0
- package/dist/tools/run_agent.js +80 -0
- package/dist/tools/run_agent.js.map +1 -0
- package/dist/tools/run_agent_cli.d.ts +21 -0
- package/dist/tools/run_agent_cli.d.ts.map +1 -0
- package/dist/tools/run_agent_cli.js +129 -0
- package/dist/tools/run_agent_cli.js.map +1 -0
- package/dist/tools/run_agents_parallel.d.ts +34 -0
- package/dist/tools/run_agents_parallel.d.ts.map +1 -0
- package/dist/tools/run_agents_parallel.js +104 -0
- package/dist/tools/run_agents_parallel.js.map +1 -0
- package/dist/tools/run_claude.d.ts +19 -0
- package/dist/tools/run_claude.d.ts.map +1 -0
- package/dist/tools/run_claude.js +99 -0
- package/dist/tools/run_claude.js.map +1 -0
- package/dist/tools/run_cline.d.ts +28 -0
- package/dist/tools/run_cline.d.ts.map +1 -0
- package/dist/tools/run_cline.js +77 -0
- package/dist/tools/run_cline.js.map +1 -0
- package/dist/tools/run_gemini.d.ts +24 -0
- package/dist/tools/run_gemini.d.ts.map +1 -0
- package/dist/tools/run_gemini.js +81 -0
- package/dist/tools/run_gemini.js.map +1 -0
- package/dist/tools/run_hermes.d.ts +25 -0
- package/dist/tools/run_hermes.d.ts.map +1 -0
- package/dist/tools/run_hermes.js +93 -0
- package/dist/tools/run_hermes.js.map +1 -0
- package/dist/tools/run_kilo.d.ts +32 -0
- package/dist/tools/run_kilo.d.ts.map +1 -0
- package/dist/tools/run_kilo.js +92 -0
- package/dist/tools/run_kilo.js.map +1 -0
- package/dist/tools/run_openclaw.d.ts +24 -0
- package/dist/tools/run_openclaw.d.ts.map +1 -0
- package/dist/tools/run_openclaw.js +74 -0
- package/dist/tools/run_openclaw.js.map +1 -0
- package/dist/tools/run_opencode.d.ts +24 -0
- package/dist/tools/run_opencode.d.ts.map +1 -0
- package/dist/tools/run_opencode.js +74 -0
- package/dist/tools/run_opencode.js.map +1 -0
- package/dist/tools/run_qwencli.d.ts +24 -0
- package/dist/tools/run_qwencli.d.ts.map +1 -0
- package/dist/tools/run_qwencli.js +59 -0
- package/dist/tools/run_qwencli.js.map +1 -0
- package/package.json +86 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeaMoN888
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# 🧠 OverMind-MCP
|
|
2
|
+
|
|
3
|
+
_Orchestrateur universel agents IA multi-modeles via MCP pour piloter Claude-Code, Gemini-cli, QwenCli, Nous Hermes, Kilo/Cline, OpenClaw, GLM, Minimax, Kimi, Ollama et plus sans limite._
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://discord.gg/4AR82phtBz"><img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Discord"></a>
|
|
9
|
+
<a href="https://deamondev888.github.io/overmind-mcp/"><img src="https://img.shields.io/badge/Documentation-Live-00fff5?style=for-the-badge&logo=google-chrome&logoColor=white" alt="Live Doc"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
## 👋 C'est quoi ?
|
|
13
|
+
|
|
14
|
+
**OverMind-MCP** est une conscience supérieure conçue pour orchestrer, commander et automatiser une flotte illimitée d'agents IA. Compatible avec **Claude-Code, Gemini-cli, QwenCli, Nous Hermes, Kilo/Cline, OpenClaw**, et prêt pour **GLM, Minimax, Kimi, Ollama** et bien d'autres. Plus qu'un simple runner, c'est le **Cortex Central** de votre infrastructure IA.
|
|
15
|
+
|
|
16
|
+
Il transforme les outils CLI isolés en une force coordonnée, pilotable par API ou par MCP, capable d'exécuter des missions complexes en 2 secondes chrono. de creer et d orchestrer des pipeline de plusieurs agent. il est expert en outils MCP et peu etre scripté pour les faire fonctionner ensemble et les mettre en productions
|
|
17
|
+
|
|
18
|
+
## ✨ Ce que ça fait
|
|
19
|
+
|
|
20
|
+
- 🔌 **Contrôle Total** : Lancez des missions complexes via MCP ou directement via le code (Claude, Gemini, QwenCli, Hermes).
|
|
21
|
+
- 🏗️ **Architecture Pro** : Basé sur des services (`AgentManager`, `ClaudeRunner`, `PromptManager`) pour une stabilité maximale.
|
|
22
|
+
- 🧠 **Mémoire Haute-Performance (4096D)** : Système RAG intégré via PostgreSQL + `pgvector` supportant les embeddings SOTA (Qwen 8B).
|
|
23
|
+
- 🕵️ **Auto-Diagnostic CLI** : Détecte automatiquement les runners manquants et fournit les instructions/liens officiels pour l'installation.
|
|
24
|
+
- 🛡️ **Mémoire Ségréguée** : Chaque agent peut posséder ses propres souvenirs isolés tout en ayant accès au socle de connaissances global.
|
|
25
|
+
- 🛠️ **Capacités Étendues** : L'agent piloté peut utiliser VOS outils (Base de données, Scrapers, etc.).
|
|
26
|
+
- 🤖 **Multi-Agents** : Créez, configurez et gérez des personnalités d'agents isolées (Prompts & Settings dédiés).
|
|
27
|
+
- 📦 **Prêt pour l'Intégration** : Importable comme un module NPM dans vos autres projets.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🚀 Commencer (Guide Facile)
|
|
32
|
+
|
|
33
|
+
### Option 1 : Utilisation Globale ou Package distant NPM
|
|
34
|
+
|
|
35
|
+
Si vous souhaitez l'installer globalement sans cloner de repo, vous pouvez utiliser :
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g overmind-mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Configuration MCP (Client) pour l'Option 1 :**
|
|
42
|
+
Pour connecter l'orchestrateur distant à un client ou à Cursor,Antigravity ou Claude Code, pointez simplement via `npx` :
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"overmind": {
|
|
48
|
+
"command": "npx",
|
|
49
|
+
"args": ["-y", "overmind-mcp@latest"]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### Option 2 : Installation Locale (Développement ou hébergement précis)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# 1. Cloner le repo localement
|
|
61
|
+
git clone https://github.com/DeamonDev888/overmind-mcp overmind-mcp
|
|
62
|
+
cd overmind-mcp
|
|
63
|
+
|
|
64
|
+
# 2. Installer les dépendances
|
|
65
|
+
pnpm install
|
|
66
|
+
|
|
67
|
+
# 3. Build le projet
|
|
68
|
+
pnpm run build
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Pour que l'agent puisse voir vos autres serveurs MCP locaux, copiez le fichier d'exemple :
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cp .mcp.json.example .mcp.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Configuration MCP (Client) pour l'Option 2 :**
|
|
78
|
+
Pour connecter ce runner à un client en pointant vers votre version locale compilée :
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"mcpServers": {
|
|
83
|
+
"overmind": {
|
|
84
|
+
"command": "node",
|
|
85
|
+
"args": ["/LE_CHEMIN_ABSOLU_VERS_LE_DOSSIER_CLONE/dist/bin/cli.js"]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 📦 Utilisation comme Bibliothèque
|
|
94
|
+
|
|
95
|
+
Vous pouvez désormais importer le moteur du runner dans vos propres scripts :
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { runAgent, AgentManager, updateConfig } from 'overmind-mcp';
|
|
99
|
+
|
|
100
|
+
// 1. Initialisation
|
|
101
|
+
updateConfig('./settings.json', './mcp.local.json');
|
|
102
|
+
|
|
103
|
+
// 2. Gestion des agents
|
|
104
|
+
const manager = new AgentManager();
|
|
105
|
+
await manager.createAgent('expert-seo', 'Tu es un expert SEO...', 'claude-3-5-sonnet');
|
|
106
|
+
|
|
107
|
+
// 3. Lancer une exécution via l'Orchestrateur Unifié
|
|
108
|
+
const { content, isError } = await runAgent({
|
|
109
|
+
runner: 'claude',
|
|
110
|
+
agentName: 'expert-seo',
|
|
111
|
+
prompt: 'Analyse le site example.com',
|
|
112
|
+
autoResume: true,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (!isError) {
|
|
116
|
+
console.log('🤖 Résultat:', content[0].text);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 📂 Structure du Projet
|
|
123
|
+
|
|
124
|
+
- `src/services/` : Le cœur du système (Logique métier isolée en services).
|
|
125
|
+
- `src/tools/` : Les outils MCP qui appellent les services.
|
|
126
|
+
- `src/bin/cli.ts` : Le point d'entrée exécutable pour le terminal.
|
|
127
|
+
- `src/server.ts` : La définition du serveur FastMCP.
|
|
128
|
+
- `src/index.ts` : Les exports publics (API de la bibliothèque).
|
|
129
|
+
- `.claude/` : Stockage des agents (Prompts `.md` et Settings `.json`).
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+

|
|
134
|
+
|
|
135
|
+
_Note : L'**OverMind** punit et martyrise les **OpenClaw** qui n'écoutent pas._ 😈
|
|
136
|
+
|
|
137
|
+
_Projet propulsé par DeaMoN888 - 2026_
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":""}
|
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { PassThrough } from 'stream';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
// Helper to manually parse .env without any noisy console.logs from external packages (dotenvx corrupts MCP JSON streams)
|
|
9
|
+
function loadEnvQuietly(envPath) {
|
|
10
|
+
try {
|
|
11
|
+
if (fs.existsSync(envPath)) {
|
|
12
|
+
const content = fs.readFileSync(envPath, 'utf8');
|
|
13
|
+
content.split('\n').forEach((line) => {
|
|
14
|
+
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/);
|
|
15
|
+
if (match) {
|
|
16
|
+
const key = match[1];
|
|
17
|
+
let value = match[2] || '';
|
|
18
|
+
value = value.replace(/\s*#.*$/, '').trim();
|
|
19
|
+
if (value.startsWith('"') && value.endsWith('"'))
|
|
20
|
+
value = value.slice(1, -1);
|
|
21
|
+
else if (value.startsWith("'") && value.endsWith("'"))
|
|
22
|
+
value = value.slice(1, -1);
|
|
23
|
+
if (!process.env[key])
|
|
24
|
+
process.env[key] = value;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (_e) {
|
|
30
|
+
// Ignore silently
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// 🪄 Auto-formatteur de .env — Classifie tous les providers connus, préserve les valeurs
|
|
34
|
+
function autoFormatEnvFile(envPath) {
|
|
35
|
+
try {
|
|
36
|
+
if (!fs.existsSync(envPath))
|
|
37
|
+
return;
|
|
38
|
+
const content = fs.readFileSync(envPath, 'utf8');
|
|
39
|
+
// Parser robuste : ignore commentaires, lit les lignes KEY=VALUE (valeur peut contenir '=')
|
|
40
|
+
const envVars = {};
|
|
41
|
+
for (const line of content.split('\n')) {
|
|
42
|
+
const trimmed = line.trim();
|
|
43
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
44
|
+
continue;
|
|
45
|
+
const eqIdx = trimmed.indexOf('=');
|
|
46
|
+
if (eqIdx === -1)
|
|
47
|
+
continue;
|
|
48
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
49
|
+
const value = trimmed.slice(eqIdx + 1).trim();
|
|
50
|
+
if (key)
|
|
51
|
+
envVars[key] = value;
|
|
52
|
+
}
|
|
53
|
+
if (Object.keys(envVars).length === 0)
|
|
54
|
+
return;
|
|
55
|
+
const usedKeys = new Set();
|
|
56
|
+
// Tri naturel pour les clés avec suffixes numériques (KEY, KEY_2, KEY_3…)
|
|
57
|
+
function naturalSort(pairs) {
|
|
58
|
+
return pairs.sort((a, b) => a[0].localeCompare(b[0], undefined, { numeric: true, sensitivity: 'base' }));
|
|
59
|
+
}
|
|
60
|
+
function extract(prefix, exactMatch = false) {
|
|
61
|
+
const res = [];
|
|
62
|
+
const prefixes = Array.isArray(prefix) ? prefix : [prefix];
|
|
63
|
+
for (const key of Object.keys(envVars)) {
|
|
64
|
+
if (usedKeys.has(key))
|
|
65
|
+
continue;
|
|
66
|
+
const matches = exactMatch
|
|
67
|
+
? prefixes.includes(key)
|
|
68
|
+
: prefixes.some((p) => key.startsWith(p));
|
|
69
|
+
if (matches) {
|
|
70
|
+
res.push([key, envVars[key]]);
|
|
71
|
+
usedKeys.add(key);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return naturalSort(res);
|
|
75
|
+
}
|
|
76
|
+
// ─── SECTIONS ──────────────────────────────────────────────────────────────
|
|
77
|
+
const sections = [
|
|
78
|
+
// ── Overmind Infrastructure ──
|
|
79
|
+
{
|
|
80
|
+
title: '🌐 OVERMIND CORE & INFRASTRUCTURE',
|
|
81
|
+
vars: extract(['OVERMIND_WORKSPACE', 'OVERMIND_MEMORY_TYPE'], true),
|
|
82
|
+
},
|
|
83
|
+
{ title: '⚙️ GLOBAL SETTINGS', vars: extract(['API_TIMEOUT_MS'], true) },
|
|
84
|
+
{ title: '🗄️ DATABASE (PostgreSQL / pgvector)', vars: extract('POSTGRES_') },
|
|
85
|
+
{ title: '🧠 EMBEDDINGS & VECTOR MEMORY', vars: extract('OVERMIND_EMBEDDING_') },
|
|
86
|
+
// ── LLM Providers (Europe / USA) ──
|
|
87
|
+
{ title: '🤖 LLM PROVIDER - Mistral AI 🇫🇷', vars: extract('MISTRAL_') },
|
|
88
|
+
{ title: '🤖 LLM PROVIDER - OpenAI 🇺🇸', vars: extract('OPENAI_') },
|
|
89
|
+
{ title: '🤖 LLM PROVIDER - Anthropic 🇺🇸', vars: extract('ANTHROPIC_') },
|
|
90
|
+
{
|
|
91
|
+
title: '🤖 LLM PROVIDER - Google Gemini 🇺🇸',
|
|
92
|
+
vars: extract(['GEMINI_API_KEY', 'GEMINI_MODEL', 'GOOGLE_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY'], true),
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
title: '🤖 LLM PROVIDER - NVIDIA NIM 🇺🇸',
|
|
96
|
+
vars: [
|
|
97
|
+
...extract(['NVAPI_KEY', 'NVIDIA_API_KEY', 'NVIDIA_API_BASE'], true),
|
|
98
|
+
...extract('NVIDIA_'),
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
title: '🤖 LLM PROVIDER - OpenRouter 🇺🇸',
|
|
103
|
+
vars: extract(['OPENROUTER_API_KEY', 'OPENROUTER_BASE_URL', 'OPENROUTER_MODEL'], true),
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
title: '🤖 LLM PROVIDER - xAI / Grok 🇺🇸',
|
|
107
|
+
vars: extract(['XAI_API_KEY', 'XAI_BASE_URL', 'GROK_API_KEY', 'GROK_MODEL'], true),
|
|
108
|
+
},
|
|
109
|
+
{ title: '🤖 LLM PROVIDER - Groq 🇺🇸', vars: extract('GROQ_') },
|
|
110
|
+
{ title: '🤖 LLM PROVIDER - Together AI 🇺🇸', vars: extract('TOGETHER_') },
|
|
111
|
+
{ title: '🤖 LLM PROVIDER - Cohere 🇺🇸', vars: extract('COHERE_') },
|
|
112
|
+
{ title: '🤖 LLM PROVIDER - Replicate 🇺🇸', vars: extract('REPLICATE_') },
|
|
113
|
+
{
|
|
114
|
+
title: '🤖 LLM PROVIDER - HuggingFace 🇺🇸',
|
|
115
|
+
vars: extract(['HUGGINGFACE_API_KEY', 'HF_TOKEN', 'HUGGING_FACE_HUB_TOKEN'], true),
|
|
116
|
+
},
|
|
117
|
+
{ title: '🤖 LLM PROVIDER - Perplexity 🇺🇸', vars: extract('PERPLEXITY_') },
|
|
118
|
+
{ title: '🤖 LLM PROVIDER - SambaNova 🇺🇸', vars: extract('SAMBANOVA_') },
|
|
119
|
+
{
|
|
120
|
+
title: '🤖 LLM PROVIDER - Azure OpenAI ☁️',
|
|
121
|
+
vars: extract([
|
|
122
|
+
'AZURE_API_KEY',
|
|
123
|
+
'AZURE_API_BASE',
|
|
124
|
+
'AZURE_OPENAI_API_KEY',
|
|
125
|
+
'AZURE_OPENAI_ENDPOINT',
|
|
126
|
+
'AZURE_OPENAI_API_VERSION',
|
|
127
|
+
], true),
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
title: '🤖 LLM PROVIDER - ElevenLabs 🎙️',
|
|
131
|
+
vars: extract(['ELEVENLABS_API_KEY', 'ELEVENLABS_VOICE_ID', 'ELEVENLABS_MODEL_ID'], true),
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
title: '🤖 LLM PROVIDER - AWS Bedrock ☁️',
|
|
135
|
+
vars: extract([
|
|
136
|
+
'AWS_ACCESS_KEY_ID',
|
|
137
|
+
'AWS_SECRET_ACCESS_KEY',
|
|
138
|
+
'AWS_SESSION_TOKEN',
|
|
139
|
+
'AWS_REGION',
|
|
140
|
+
'AWS_DEFAULT_REGION',
|
|
141
|
+
'AWS_ENDPOINT_URL',
|
|
142
|
+
], true),
|
|
143
|
+
},
|
|
144
|
+
// ── LLM Providers (Chine / Asie) ──
|
|
145
|
+
{ title: '🤖 LLM PROVIDER - DeepSeek 🇨🇳', vars: extract('DEEPSEEK_') },
|
|
146
|
+
{ title: '🤖 LLM PROVIDER - Alibaba DashScope 🇨🇳', vars: extract('ALIBABA_') },
|
|
147
|
+
{
|
|
148
|
+
title: '🤖 LLM PROVIDER - Qwen (DashScope) 🇨🇳',
|
|
149
|
+
vars: extract([
|
|
150
|
+
'QWEN_API_KEY',
|
|
151
|
+
'QWEN_BASE_URL',
|
|
152
|
+
'QWEN_MODEL',
|
|
153
|
+
'DASHSCOPE_API_KEY',
|
|
154
|
+
'DASHSCOPE_BASE_URL',
|
|
155
|
+
], true),
|
|
156
|
+
},
|
|
157
|
+
{ title: '🤖 LLM PROVIDER - SiliconFlow 🇨🇳', vars: extract('SILICONFLOW_') },
|
|
158
|
+
{
|
|
159
|
+
title: '🤖 LLM PROVIDER - Minimax 🇨🇳',
|
|
160
|
+
vars: [...extract('MINIMAXI_'), ...extract('MINIMAX_')],
|
|
161
|
+
},
|
|
162
|
+
{ title: '🤖 LLM PROVIDER - Ilmu AI / Z.AI 🇨🇳', vars: extract('Z_AI_') },
|
|
163
|
+
{
|
|
164
|
+
title: '🤖 LLM PROVIDER - Moonshot / Kimi 🇨🇳',
|
|
165
|
+
vars: extract(['MOONSHOT_API_KEY', 'MOONSHOT_BASE_URL', 'MOONSHOT_MODEL', 'KIMI_API_KEY'], true),
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
title: '🤖 LLM PROVIDER - Baidu / ERNIE 🇨🇳',
|
|
169
|
+
vars: extract(['BAIDU_API_KEY', 'ERNIE_API_KEY', 'WENXIN_API_KEY'], true),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
title: '🤖 LLM PROVIDER - ZhipuAI / GLM 🇨🇳',
|
|
173
|
+
vars: [...extract(['ZHIPU_API_KEY', 'GLM_API_KEY'], true), ...extract('ZHIPUAI_')],
|
|
174
|
+
},
|
|
175
|
+
// ── Services & Intégrations ──
|
|
176
|
+
{
|
|
177
|
+
title: '💬 SERVICE - Discord',
|
|
178
|
+
vars: extract([
|
|
179
|
+
'DISCORD_TOKEN',
|
|
180
|
+
'DISCORD_BOT_TOKEN',
|
|
181
|
+
'DISCORD_CHANNEL_ID',
|
|
182
|
+
'DISCORD_GUILD_ID',
|
|
183
|
+
'DISCORD_WEBHOOK_URL',
|
|
184
|
+
'DISCORD_CLIENT_ID',
|
|
185
|
+
'DISCORD_CLIENT_SECRET',
|
|
186
|
+
], true),
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
title: '🐦 SERVICE - Twitter / X',
|
|
190
|
+
vars: extract([
|
|
191
|
+
'TWITTER_API_KEY',
|
|
192
|
+
'TWITTER_API_SECRET',
|
|
193
|
+
'TWITTER_ACCESS_TOKEN',
|
|
194
|
+
'TWITTER_ACCESS_SECRET',
|
|
195
|
+
'TWITTER_BEARER_TOKEN',
|
|
196
|
+
'X_API_KEY',
|
|
197
|
+
'X_BEARER_TOKEN',
|
|
198
|
+
'X_API_SECRET',
|
|
199
|
+
'X_ACCESS_TOKEN',
|
|
200
|
+
'X_ACCESS_SECRET',
|
|
201
|
+
], true),
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
title: '📱 SERVICE - Telegram',
|
|
205
|
+
vars: extract(['TELEGRAM_BOT_TOKEN', 'TELEGRAM_CHAT_ID'], true),
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
title: '📱 SERVICE - Twilio / SMS',
|
|
209
|
+
vars: extract([
|
|
210
|
+
'TWILIO_ACCOUNT_SID',
|
|
211
|
+
'TWILIO_AUTH_TOKEN',
|
|
212
|
+
'TWILIO_PHONE_NUMBER',
|
|
213
|
+
'TWILIO_API_KEY',
|
|
214
|
+
'TWILIO_API_SECRET',
|
|
215
|
+
], true),
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
title: '🐙 SERVICE - GitHub',
|
|
219
|
+
vars: extract([
|
|
220
|
+
'GITHUB_TOKEN',
|
|
221
|
+
'GITHUB_API_KEY',
|
|
222
|
+
'GH_TOKEN',
|
|
223
|
+
'GITHUB_CLIENT_ID',
|
|
224
|
+
'GITHUB_CLIENT_SECRET',
|
|
225
|
+
], true),
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
title: '▲ SERVICE - Vercel',
|
|
229
|
+
vars: extract([
|
|
230
|
+
'VERCEL_TOKEN',
|
|
231
|
+
'VERCEL_API_TOKEN',
|
|
232
|
+
'VERCEL_PROJECT_ID',
|
|
233
|
+
'VERCEL_ORG_ID',
|
|
234
|
+
'VERCEL_TEAM_ID',
|
|
235
|
+
], true),
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
title: '🔺 SERVICE - Supabase',
|
|
239
|
+
vars: extract(['SUPABASE_URL', 'SUPABASE_ANON_KEY', 'SUPABASE_SERVICE_ROLE_KEY', 'SUPABASE_JWT_SECRET'], true),
|
|
240
|
+
},
|
|
241
|
+
{ title: '🎮 SERVICE - Riot Games', vars: extract(['RIOT_API_KEY', 'RIOT_REGION'], true) },
|
|
242
|
+
{
|
|
243
|
+
title: '🔍 SERVICE - Search (Serper/Tavily)',
|
|
244
|
+
vars: extract(['SERPER_API_KEY', 'TAVILY_API_KEY', 'SERPAPI_KEY', 'BRAVE_SEARCH_API_KEY'], true),
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
title: '📰 SERVICE - Market Data & News',
|
|
248
|
+
vars: extract([
|
|
249
|
+
'FINNHUB_API_KEY',
|
|
250
|
+
'NEWSAPI_KEY',
|
|
251
|
+
'ALPHAVANTAGE_API_KEY',
|
|
252
|
+
'POLYGON_API_KEY',
|
|
253
|
+
'TIINGO_API_KEY',
|
|
254
|
+
], true),
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
// Clés restantes non classifiées → section fourre-tout
|
|
258
|
+
const uncategorized = [];
|
|
259
|
+
for (const key of Object.keys(envVars)) {
|
|
260
|
+
if (!usedKeys.has(key))
|
|
261
|
+
uncategorized.push([key, envVars[key]]);
|
|
262
|
+
}
|
|
263
|
+
if (uncategorized.length > 0) {
|
|
264
|
+
sections.push({ title: '📁 AUTRES / NON-CLASSIFIÉS', vars: naturalSort(uncategorized) });
|
|
265
|
+
}
|
|
266
|
+
// ─── RENDU ──────────────────────────────────────────────────────────────────
|
|
267
|
+
let newContent = '';
|
|
268
|
+
for (const section of sections) {
|
|
269
|
+
if (section.vars.length > 0) {
|
|
270
|
+
newContent += `# ==========================================\n`;
|
|
271
|
+
newContent += `# ${section.title}\n`;
|
|
272
|
+
newContent += `# ==========================================\n`;
|
|
273
|
+
for (const [k, v] of section.vars) {
|
|
274
|
+
newContent += `${k}=${v}\n`;
|
|
275
|
+
}
|
|
276
|
+
newContent += `\n`;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// N'écrire sur le disque que si quelque chose a changé (optimisation I/O)
|
|
280
|
+
if (content.trim() !== newContent.trim()) {
|
|
281
|
+
fs.writeFileSync(envPath, newContent.trim() + '\n', 'utf8');
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (_e) {
|
|
285
|
+
// Ignorer silencieusement pour ne pas crasher le boot
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const localEnvPath = path.resolve(__dirname, '../../.env');
|
|
289
|
+
// Auto-détection et injection de OVERMIND_WORKSPACE s'il est manquant — NE PAS écraser s'il existe déjà
|
|
290
|
+
try {
|
|
291
|
+
if (!fs.existsSync(localEnvPath)) {
|
|
292
|
+
const workspacePath = path.resolve(__dirname, '../../');
|
|
293
|
+
fs.writeFileSync(localEnvPath, `OVERMIND_WORKSPACE=${workspacePath}\n`, 'utf8');
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
const currentContent = fs.readFileSync(localEnvPath, 'utf8');
|
|
297
|
+
// Vérifier que OVERMIND_WORKSPACE n'existe pas OU n'a pas de valeur (ligne vide)
|
|
298
|
+
const match = currentContent.match(/^OVERMIND_WORKSPACE=(.*)$/m);
|
|
299
|
+
if (!match || !match[1]?.trim()) {
|
|
300
|
+
const workspacePath = path.resolve(__dirname, '../../');
|
|
301
|
+
if (!currentContent.includes('OVERMIND_WORKSPACE=')) {
|
|
302
|
+
fs.appendFileSync(localEnvPath, `\nOVERMIND_WORKSPACE=${workspacePath}\n`, 'utf8');
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// Remplacer la ligne vide/videuse
|
|
306
|
+
const newContent = currentContent.replace(/^OVERMIND_WORKSPACE=.*$/m, `OVERMIND_WORKSPACE=${workspacePath}`);
|
|
307
|
+
fs.writeFileSync(localEnvPath, newContent, 'utf8');
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Si OVERMIND_WORKSPACE a déjà une valeur → ne rien faire, ne pas écraser
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (_e) {
|
|
314
|
+
// Ignorer l'erreur silencieusement
|
|
315
|
+
}
|
|
316
|
+
// Classifie et réorganise automatiquement le .env à chaque démarrage d'Overmind
|
|
317
|
+
autoFormatEnvFile(localEnvPath);
|
|
318
|
+
// Load OverMind's specific environment variables
|
|
319
|
+
loadEnvQuietly(localEnvPath);
|
|
320
|
+
// Inherit PostgreSQL Server environment variables (Database credentials, Embeddings)
|
|
321
|
+
loadEnvQuietly(path.resolve(__dirname, '../../../serveur_PostGreSQL/.env'));
|
|
322
|
+
// 🔍 Vérification des configurations critiques
|
|
323
|
+
function checkMissingConfigs() {
|
|
324
|
+
const missingCore = [];
|
|
325
|
+
const missingDb = [];
|
|
326
|
+
// Vérification CORE
|
|
327
|
+
if (!process.env.OVERMIND_WORKSPACE)
|
|
328
|
+
missingCore.push('OVERMIND_WORKSPACE');
|
|
329
|
+
if (!process.env.OVERMIND_MEMORY_TYPE)
|
|
330
|
+
missingCore.push('OVERMIND_MEMORY_TYPE');
|
|
331
|
+
// Vérification DB
|
|
332
|
+
if (!process.env.POSTGRES_HOST)
|
|
333
|
+
missingDb.push('POSTGRES_HOST');
|
|
334
|
+
if (!process.env.POSTGRES_DATABASE)
|
|
335
|
+
missingDb.push('POSTGRES_DATABASE');
|
|
336
|
+
if (!process.env.POSTGRES_USER)
|
|
337
|
+
missingDb.push('POSTGRES_USER');
|
|
338
|
+
if (!process.env.POSTGRES_PASSWORD)
|
|
339
|
+
missingDb.push('POSTGRES_PASSWORD');
|
|
340
|
+
if (missingCore.length > 0) {
|
|
341
|
+
console.error(`\n[Overmind] ⚠️ ATTENTION : Configuration 'CORE & INFRASTRUCTURE' incomplète !`);
|
|
342
|
+
console.error(`[Overmind] ❌ Il manque : ${missingCore.join(', ')}\n`);
|
|
343
|
+
}
|
|
344
|
+
if (missingDb.length > 0) {
|
|
345
|
+
console.error(`\n[Overmind] ⚠️ ATTENTION : Configuration 'DATABASE' incomplète (Imported from postgresql-server) !`);
|
|
346
|
+
console.error(`[Overmind] ❌ Il manque : ${missingDb.join(', ')}\n`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
checkMissingConfigs();
|
|
350
|
+
import { rootLogger } from '../lib/logger.js';
|
|
351
|
+
// 💥 ERROR HANDLING: Catch everything to avoid silent EOFs
|
|
352
|
+
process.on('uncaughtException', (err) => {
|
|
353
|
+
rootLogger.fatal({ err }, '💥 UNCAUGHT EXCEPTION');
|
|
354
|
+
rootLogger.flush();
|
|
355
|
+
process.exit(1);
|
|
356
|
+
});
|
|
357
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
358
|
+
rootLogger.fatal({ reason, promise }, '💥 UNHANDLED REJECTION');
|
|
359
|
+
rootLogger.flush();
|
|
360
|
+
});
|
|
361
|
+
// Ensure logs are flushed on exit
|
|
362
|
+
process.on('SIGINT', () => {
|
|
363
|
+
rootLogger.info('🛑 Received SIGINT, flushing logs...');
|
|
364
|
+
rootLogger.flush();
|
|
365
|
+
process.exit(0);
|
|
366
|
+
});
|
|
367
|
+
process.on('SIGTERM', () => {
|
|
368
|
+
rootLogger.info('🛑 Received SIGTERM, flushing logs...');
|
|
369
|
+
rootLogger.flush();
|
|
370
|
+
process.exit(0);
|
|
371
|
+
});
|
|
372
|
+
// 🛡️ SHIELD: Prevent any library from logging to stdout during initialization
|
|
373
|
+
// This is critical for MCP servers because any non-JSON output on stdout kills the handshake (EOF).
|
|
374
|
+
console.log = (...args) => rootLogger.info(args.length > 1 ? { args } : args[0]);
|
|
375
|
+
console.info = (...args) => rootLogger.info(args.length > 1 ? { args } : args[0]);
|
|
376
|
+
console.warn = (...args) => rootLogger.warn(args.length > 1 ? { args } : args[0]);
|
|
377
|
+
console.error = (...args) => rootLogger.error(args.length > 1 ? { args } : args[0]);
|
|
378
|
+
// 🛡️ ULTIMATE SHIELD: Proxy process.stdout.write to redirect non-JSON data to stderr
|
|
379
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
380
|
+
process.stdout.write = function (chunk, encoding, callback) {
|
|
381
|
+
const str = typeof chunk === 'string' ? chunk : chunk.toString();
|
|
382
|
+
const trimmed = str.trim();
|
|
383
|
+
// Handle overload: if encoding is a function, it's actually the callback
|
|
384
|
+
if (typeof encoding === 'function') {
|
|
385
|
+
callback = encoding;
|
|
386
|
+
encoding = undefined;
|
|
387
|
+
}
|
|
388
|
+
// Skip empty chunks or pure whitespace (often used as delimiters/keep-alive)
|
|
389
|
+
if (trimmed === '') {
|
|
390
|
+
return originalStdoutWrite(chunk, encoding, callback);
|
|
391
|
+
}
|
|
392
|
+
// Allow JSON-RPC (starts with { or [)
|
|
393
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
394
|
+
try {
|
|
395
|
+
const parsed = JSON.parse(trimmed);
|
|
396
|
+
// BLOCK ARRAYS on stdout (Batch responses are not standard in MCP)
|
|
397
|
+
if (Array.isArray(parsed)) {
|
|
398
|
+
rootLogger.warn({ raw: str }, '🛡️ [SHIELD] Blocked array-as-JSON-RPC on stdout');
|
|
399
|
+
return process.stderr.write(chunk, encoding, callback);
|
|
400
|
+
}
|
|
401
|
+
// Check for JSON-RPC (Response or Notification)
|
|
402
|
+
if (parsed.jsonrpc === '2.0') {
|
|
403
|
+
return originalStdoutWrite(chunk, encoding, callback);
|
|
404
|
+
}
|
|
405
|
+
// Block non-RPC JSON
|
|
406
|
+
rootLogger.warn({ raw: str }, '🛡️ [SHIELD] Blocked non-JSON-RPC (Object) on stdout');
|
|
407
|
+
return process.stderr.write(chunk, encoding, callback);
|
|
408
|
+
}
|
|
409
|
+
catch (e) {
|
|
410
|
+
// Malformed JSON-like content
|
|
411
|
+
rootLogger.debug({ raw: str, err: e.message }, '🛡️ [SHIELD] Blocked malformed JSON-like content on stdout');
|
|
412
|
+
return process.stderr.write(chunk, encoding, callback);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Redirect everything else to stderr (via Pino)
|
|
416
|
+
rootLogger.debug({ raw: trimmed }, '🛡️ [SHIELD] Intercepted non-JSON stdout write');
|
|
417
|
+
return process.stderr.write(chunk, encoding, callback);
|
|
418
|
+
};
|
|
419
|
+
// 🛡️ STDIN INTERCEPTOR: Detect and unroll JSON-RPC Batches [req1, req2]
|
|
420
|
+
// FastMCP/Zod only support single objects. Intercepting before FastMCP starts.
|
|
421
|
+
const originalStdin = process.stdin;
|
|
422
|
+
const stdinProxy = new PassThrough();
|
|
423
|
+
originalStdin.on('data', (chunk) => {
|
|
424
|
+
const str = chunk.toString();
|
|
425
|
+
const trimmed = str.trim();
|
|
426
|
+
// 🔍 [DEBUG] Log every incoming chunk that looks like JSON
|
|
427
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
428
|
+
rootLogger.debug({
|
|
429
|
+
length: trimmed.length,
|
|
430
|
+
preview: trimmed.substring(0, 100),
|
|
431
|
+
isBatch: trimmed.startsWith('['),
|
|
432
|
+
}, '[SHIELD] STDIN chunk received');
|
|
433
|
+
}
|
|
434
|
+
// If it's a batch, unroll it into separate JSON chunks
|
|
435
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
436
|
+
try {
|
|
437
|
+
const parsed = JSON.parse(trimmed);
|
|
438
|
+
if (Array.isArray(parsed)) {
|
|
439
|
+
rootLogger.warn({ count: parsed.length }, '[SHIELD] Unrolling JSON-RPC BATCH on STDIN');
|
|
440
|
+
for (const item of parsed) {
|
|
441
|
+
stdinProxy.write(JSON.stringify(item) + '\n');
|
|
442
|
+
}
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
catch (_e) {
|
|
447
|
+
// Not a valid batch or partial JSON, pass through as-is
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
stdinProxy.write(chunk);
|
|
451
|
+
});
|
|
452
|
+
// Hijack process.stdin for FastMCP and any other consumers
|
|
453
|
+
Object.defineProperty(process, 'stdin', {
|
|
454
|
+
value: stdinProxy,
|
|
455
|
+
writable: false,
|
|
456
|
+
configurable: true,
|
|
457
|
+
});
|
|
458
|
+
// Setup completed - Dynamically import server components AFTER process.env is configured
|
|
459
|
+
const { createServer } = await import('../server.js');
|
|
460
|
+
const { updateConfig } = await import('../lib/config.js');
|
|
461
|
+
const cliArgs = process.argv.slice(2);
|
|
462
|
+
let settingsPath, mcpPath;
|
|
463
|
+
for (let i = 0; i < cliArgs.length; i++) {
|
|
464
|
+
if (cliArgs[i] === '--settings' && cliArgs[i + 1]) {
|
|
465
|
+
settingsPath = cliArgs[i + 1];
|
|
466
|
+
i++;
|
|
467
|
+
}
|
|
468
|
+
else if (cliArgs[i] === '--mcp-config' && cliArgs[i + 1]) {
|
|
469
|
+
mcpPath = cliArgs[i + 1];
|
|
470
|
+
i++;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (settingsPath || mcpPath) {
|
|
474
|
+
updateConfig(settingsPath, mcpPath);
|
|
475
|
+
// Do NOT log to stderr during MCP initialization as it can cause EOF errors in some clients
|
|
476
|
+
}
|
|
477
|
+
const server = createServer();
|
|
478
|
+
rootLogger.info('[Overmind] [START] Démarrage du serveur...');
|
|
479
|
+
server.start({ transportType: 'stdio' });
|
|
480
|
+
rootLogger.info('[Overmind] [READY] Serveur prêt sur STDIO.');
|
|
481
|
+
//# sourceMappingURL=cli.js.map
|