overmind-mcp 2.0.6 → 2.0.7

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.
@@ -1,465 +1,465 @@
1
- #!/usr/bin/env node
2
- /**
3
- * ═══════════════════════════════════════════════════════════════════════════════
4
- * OVERMIND-MCP - POST-INSTALL AUTOMATIQUE
5
- * ═════════════════════════════════════════════════════════════════════════════
6
- * Script exécuté automatiquement après npm install -g overmind-mcp
7
- * INSTALLE ET DÉMARRE TOUT AUTOMATIQUEMENT :
8
- * - Vérifie Docker
9
- * - Installe PostgreSQL + pgvector (si absent)
10
- * - Copie .env.example → .env
11
- * - Copie .mcp.json.example → .mcp.json
12
- * - Télécharge et démarre TOUTE l'infrastructure Docker
13
- * - Valide tous les services
14
- * - Montre où les voir dans Docker Desktop
15
- * ═══════════════════════════════════════════════════════════════════════════════
16
- */
17
-
18
- import { execSync, spawn } from 'child_process';
19
- import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
20
- import { join } from 'path';
21
- import { fileURLToPath } from 'url';
22
- import { dirname } from 'path';
23
-
24
- const __filename = fileURLToPath(import.meta.url);
25
- const __dirname = dirname(__filename);
26
-
27
- const INSTALL_DIR = join(
28
- process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH,
29
- '.overmind'
30
- );
31
-
32
- // ═══════════════════════════════════════════════════════════════════════════════
33
- // COLORS
34
- // ═════════════════════════════════════════════════════════════════════════════
35
-
36
- const COLORS = {
37
- cyan: '\x1b[36m',
38
- green: '\x1b[32m',
39
- yellow: '\x1b[33m',
40
- red: '\x1b[31m',
41
- white: '\x1b[37m',
42
- reset: '\x1b[0m'
43
- };
44
-
45
- function log(color, str) {
46
- console.log(`${color}${str}${COLORS.reset}`);
47
- }
48
-
49
- function logSection(title) {
50
- console.log('\n╔══════════════════════════════════════════════════════════════════╗');
51
- console.log(`║ ${title.padEnd(64)} ║`);
52
- console.log('╚══════════════════════════════════════════════════════════════════╝');
53
- }
54
-
55
- function runCommand(cmd, options = {}) {
56
- try {
57
- return execSync(cmd, { stdio: 'pipe', encoding: 'utf8', ...options });
58
- } catch {
59
- return null;
60
- }
61
- }
62
-
63
- async function runCommandAsync(cmd, description) {
64
- return new Promise((resolve, reject) => {
65
- console.log(`🔧 ${description}`);
66
- console.log(` $ ${cmd}`);
67
-
68
- const child = spawn(cmd, { shell: true, stdio: 'inherit' });
69
-
70
- child.on('close', (code) => {
71
- if (code === 0) {
72
- console.log(`✅ ${description} terminé`);
73
- resolve(true);
74
- } else {
75
- console.error(`❌ Erreur (code ${code})`);
76
- reject(new Error(`Command failed with code ${code}`));
77
- }
78
- });
79
-
80
- child.on('error', (err) => {
81
- console.error('❌ Erreur:', err.message);
82
- reject(err);
83
- });
84
- });
85
- }
86
-
87
- // ═══════════════════════════════════════════════════════════════════════════════
88
- // INSTALLATION STEPS
89
- // ═════════════════════════════════════════════════════════════════════════════
90
-
91
- async function checkDocker() {
92
- logSection('VÉRIFICATION DOCKER');
93
-
94
- const version = runCommand('docker --version');
95
- if (!version) {
96
- log(COLORS.red, '❌ Docker non trouvé');
97
- console.log('');
98
- log(COLORS.yellow, '📥 Installation Docker requise:');
99
-
100
- const platform = process.platform;
101
- if (platform === 'win32') {
102
- console.log(' Windows: https://www.docker.com/products/docker-desktop/');
103
- } else if (platform === 'darwin') {
104
- console.log(' macOS: https://www.docker.com/products/docker-desktop/');
105
- } else {
106
- console.log(' Linux: https://docs.docker.com/engine/install/');
107
- }
108
-
109
- log(COLORS.cyan, '\nAprès installation de Docker, relancez: npm install -g overmind-mcp');
110
- return false;
111
- }
112
-
113
- log(COLORS.green, '✅ Docker détecté: ' + version.trim());
114
- return true;
115
- }
116
-
117
- async function setupPostgreSQL() {
118
- logSection('INSTALLATION POSTGRESQL + PGVECTOR');
119
-
120
- // Check if already exists
121
- const existingContainer = runCommand(
122
- 'docker ps --filter "name=postgres-pgvector" --format "{{.Names}}"',
123
- { stdio: 'pipe' }
124
- );
125
-
126
- if (existingContainer) {
127
- log(COLORS.green, '✅ PostgreSQL + pgvector déjà installé');
128
- log(COLORS.cyan, ' Container: ' + existingContainer.trim());
129
- return true;
130
- }
131
-
132
- log(COLORS.yellow, '📦 Installation PostgreSQL + pgvector...');
133
-
134
- try {
135
- await runCommandAsync(
136
- 'docker pull pgvector/pgvector:pg16',
137
- 'Téléchargement image'
138
- );
139
-
140
- // Remove existing if stopped
141
- runCommand('docker rm -f overmind-postgres-pgvector', { stdio: 'pipe' });
142
-
143
- const runCmd = [
144
- 'docker', 'run', '-d',
145
- '--name', 'overmind-postgres-pgvector',
146
- '-p', '5432:5432',
147
- '-e', 'POSTGRES_PASSWORD=overmind_temp_password_change_me',
148
- '-e', 'POSTGRES_USER=postgres',
149
- '-v', 'overmind_postgres_data:/var/lib/postgresql/data',
150
- '--restart', 'unless-stopped',
151
- 'pgvector/pgvector:pg16'
152
- ].join(' ');
153
-
154
- await runCommandAsync(runCmd, 'Démarrage PostgreSQL');
155
-
156
- log(COLORS.cyan, '\n⏳ Attente démarrage PostgreSQL (20s)...');
157
- await new Promise(resolve => setTimeout(resolve, 20000));
158
-
159
- // Enable pgvector
160
- await runCommandAsync(
161
- `docker exec overmind-postgres-pgvector psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS vector;"`,
162
- 'Activation pgvector'
163
- );
164
-
165
- log(COLORS.green, '\n✅ PostgreSQL + pgvector installés !');
166
- return true;
167
- } catch (error) {
168
- log(COLORS.red, '❌ Erreur installation PostgreSQL: ' + error.message);
169
- return false;
170
- }
171
- }
172
-
173
- async function setupInfrastructure() {
174
- logSection('TÉLÉCHARGEMENT INFRASTRUCTURE');
175
-
176
- mkdirSync(INSTALL_DIR, { recursive: true });
177
-
178
- log(COLORS.yellow, '📥 Téléchargement fichiers docker-compose...');
179
-
180
- const composeUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/docker-compose.yml';
181
- const exportersUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/docker-compose.exporters.yml';
182
- const envExampleUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/.env.example';
183
- const mcpExampleUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/.mcp.json.example';
184
-
185
- try {
186
- // Télécharger docker-compose.yml
187
- const composeData = runCommand(`curl -sL ${composeUrl}`);
188
- if (composeData) {
189
- writeFileSync(join(INSTALL_DIR, 'docker-compose.yml'), composeData);
190
- log(COLORS.green, '✅ docker-compose.yml téléchargé');
191
- }
192
-
193
- // Télécharger docker-compose.exporters.yml
194
- const exportersData = runCommand(`curl -sL ${exportersUrl}`);
195
- if (exportersData) {
196
- writeFileSync(join(INSTALL_DIR, 'docker-compose.exporters.yml'), exportersData);
197
- log(COLORS.green, '✅ docker-compose.exporters.yml téléchargé');
198
- }
199
-
200
- // Télécharger .env.example
201
- const envExampleData = runCommand(`curl -sL ${envExampleUrl}`);
202
- if (envExampleData) {
203
- writeFileSync(join(INSTALL_DIR, '.env.example'), envExampleData);
204
- log(COLORS.green, '✅ .env.example téléchargé');
205
- }
206
-
207
- // Télécharger .mcp.json.example
208
- const mcpExampleData = runCommand(`curl -sL ${mcpExampleUrl}`);
209
- if (mcpExampleData) {
210
- writeFileSync(join(INSTALL_DIR, '.mcp.json.example'), mcpExampleData);
211
- log(COLORS.green, '✅ .mcp.json.example téléchargé');
212
- }
213
-
214
- return true;
215
- } catch (error) {
216
- log(COLORS.red, '❌ Erreur téléchargement: ' + error.message);
217
- return false;
218
- }
219
- }
220
-
221
- function createEnvConfig() {
222
- logSection('CRÉATION CONFIGURATION');
223
-
224
- mkdirSync(INSTALL_DIR, { recursive: true });
225
-
226
- const envFile = join(INSTALL_DIR, '.env');
227
- const envExampleFile = join(INSTALL_DIR, '.env.example');
228
- const mcpFile = join(INSTALL_DIR, '.mcp.json');
229
- const mcpExampleFile = join(INSTALL_DIR, '.mcp.json.example');
230
-
231
- // Copier .env.example → .env si existe
232
- if (existsSync(envExampleFile) && !existsSync(envFile)) {
233
- let envContent;
234
-
235
- if (process.platform === 'win32') {
236
- envContent = runCommand(`type "${envExampleFile}"`, { stdio: 'pipe' });
237
- } else {
238
- envContent = runCommand(`cat "${envExampleFile}"`, { stdio: 'pipe' });
239
- }
240
-
241
- if (envContent) {
242
- writeFileSync(envFile, envContent);
243
- log(COLORS.green, '✅ .env créé (à partir de .env.example)');
244
- }
245
- }
246
-
247
- // Créer .env minimal si n'existe pas
248
- if (!existsSync(envFile)) {
249
- const envContent = `# OverMind-MCP Environment Configuration
250
- # Généré automatiquement par npm install
251
-
252
- # PostgreSQL
253
- POSTGRES_HOST=localhost
254
- POSTGRES_PORT=5432
255
- POSTGRES_USER=postgres
256
- POSTGRES_PASSWORD=overmind_temp_password_change_me
257
- POSTGRES_DB=overmind
258
-
259
- # OpenTelemetry (optionnel)
260
- OTEL_ENABLED=false
261
-
262
- # Workspace
263
- OVERMIND_WORKSPACE=${INSTALL_DIR}
264
- `;
265
- writeFileSync(envFile, envContent);
266
- log(COLORS.green, '✅ Configuration .env créée: ' + envFile);
267
- }
268
-
269
- // Copier .mcp.json.example → .mcp.json si existe
270
- if (existsSync(mcpExampleFile) && !existsSync(mcpFile)) {
271
- let mcpContent;
272
-
273
- if (process.platform === 'win32') {
274
- mcpContent = runCommand(`type "${mcpExampleFile}"`, { stdio: 'pipe' });
275
- } else {
276
- mcpContent = runCommand(`cat "${mcpExampleFile}"`, { stdio: 'pipe' });
277
- }
278
-
279
- if (mcpContent) {
280
- writeFileSync(mcpFile, mcpContent);
281
- log(COLORS.green, '✅ .mcp.json créé (à partir de .mcp.json.example)');
282
- }
283
- }
284
- }
285
-
286
- async function startInfrastructure() {
287
- logSection('DÉMARRAGE AUTOMATIQUE INFRASTRUCTURE COMPLÈTE');
288
-
289
- const composeFile = join(INSTALL_DIR, 'docker-compose.yml');
290
-
291
- if (!existsSync(composeFile)) {
292
- log(COLORS.yellow, '⚠️ docker-compose.yml non trouvé. Téléchargement...');
293
- const downloaded = await setupInfrastructure();
294
- if (!downloaded) {
295
- return false;
296
- }
297
- }
298
-
299
- try {
300
- log(COLORS.yellow, '🚀 Démarrage automatique de TOUS les services...');
301
- log(COLORS.cyan, ' (PostgreSQL, RabbitMQ, Temporal, Prometheus, Grafana, Jaeger, Redis)');
302
-
303
- await runCommandAsync(
304
- `cd "${INSTALL_DIR}" && docker-compose -f docker-compose.yml pull`,
305
- 'Téléchargement images Docker'
306
- );
307
-
308
- await runCommandAsync(
309
- `cd "${INSTALL_DIR}" && docker-compose -f docker-compose.yml up -d`,
310
- 'Démarrage infrastructure complète'
311
- );
312
-
313
- log(COLORS.cyan, '\n⏳ Attente démarrage des services (20s)...');
314
- await new Promise(resolve => setTimeout(resolve, 20000));
315
-
316
- return true;
317
- } catch (error) {
318
- log(COLORS.red, '\n⚠️ Erreur démarrage infrastructure: ' + error.message);
319
- log(COLORS.yellow, '\n💡 Solution manuelle:');
320
- log(COLORS.white, ' cd ~/.overmind');
321
- log(COLORS.white, ' docker-compose up -d');
322
- return false;
323
- }
324
- }
325
-
326
- async function validateServices() {
327
- logSection('VALIDATION DES SERVICES');
328
-
329
- log(COLORS.yellow, '🔍 Vérification des containers Docker...\n');
330
-
331
- const services = [
332
- { name: 'PostgreSQL + pgvector', filter: 'postgres', color: COLORS.green },
333
- { name: 'RabbitMQ', filter: 'rabbitmq', color: COLORS.green },
334
- { name: 'Temporal', filter: 'temporal', color: COLORS.green },
335
- { name: 'Prometheus', filter: 'prometheus', color: COLORS.green },
336
- { name: 'Grafana', filter: 'grafana', color: COLORS.green },
337
- { name: 'Jaeger', filter: 'jaeger', color: COLORS.green },
338
- { name: 'Redis', filter: 'redis', color: COLORS.green },
339
- ];
340
-
341
- let allRunning = true;
342
-
343
- for (const service of services) {
344
- const containerName = runCommand(
345
- `docker ps --filter "name=${service.filter}" --format "{{.Names}}"`,
346
- { stdio: 'pipe' }
347
- );
348
-
349
- if (containerName) {
350
- log(service.color, ` ✅ ${service.name}: ${containerName.trim()}`);
351
- } else {
352
- log(COLORS.red, ` ❌ ${service.name}: Non trouvé`);
353
- allRunning = false;
354
- }
355
- }
356
-
357
- return allRunning;
358
- }
359
-
360
- function showSummary() {
361
- console.log('\n╔══════════════════════════════════════════════════════════════════╗');
362
- console.log('║' + ' '.repeat(64) + '║');
363
- console.log('║' + COLORS.green + ' ✅ INSTALLATION TERMINÉE !' + COLORS.reset + ' '.repeat(33) + '║');
364
- console.log('║' + ' '.repeat(64) + '║');
365
- console.log('╚══════════════════════════════════════════════════════════════════╝');
366
- console.log('');
367
- log(COLORS.yellow, '📋 SERVICES ACTIFS DANS DOCKER DESKTOP:');
368
- console.log('');
369
- console.log('┌─────────────────────────────────────────────────────────────────┐');
370
- console.log('│ ' + COLORS.cyan + 'Ouvrez Docker Desktop → onglet "Containers"' + COLORS.reset + ' │');
371
- console.log('│ ' + COLORS.cyan + 'Vous verrez tous les services OverMind actifs:' + COLORS.reset + ' │');
372
- console.log('│ ' + COLORS.green + ' • PostgreSQL + pgvector' + COLORS.reset + ' │');
373
- console.log('│ ' + COLORS.green + ' • RabbitMQ (Message Broker)' + COLORS.reset + ' │');
374
- console.log('│ ' + COLORS.green + ' • Temporal (Workflow Engine)' + COLORS.reset + ' │');
375
- console.log('│ ' + COLORS.green + ' • Prometheus (Métriques)' + COLORS.reset + ' │');
376
- console.log('│ ' + COLORS.green + ' • Grafana (Dashboards)' + COLORS.reset + ' │');
377
- console.log('│ ' + COLORS.green + ' • Jaeger (Tracing)' + COLORS.reset + ' │');
378
- console.log('│ ' + COLORS.green + ' • Redis (Cache)' + COLORS.reset + ' │');
379
- console.log('│ │');
380
- console.log('│ ' + COLORS.yellow + 'URLs utiles:' + COLORS.reset + ' │');
381
- console.log('│ • Prometheus: ' + COLORS.cyan + 'http://localhost:9090' + COLORS.reset + ' │');
382
- console.log('│ • Grafana: ' + COLORS.cyan + 'http://localhost:3000' + COLORS.reset + ' (admin/admin)' + ' │');
383
- console.log('│ • Jaeger: ' + COLORS.cyan + 'http://localhost:16686' + COLORS.reset + ' │');
384
- console.log('│ • RabbitMQ: ' + COLORS.cyan + 'http://localhost:15672' + COLORS.reset + ' (guest/guest)' + ' │');
385
- console.log('│ • Temporal: ' + COLORS.cyan + 'http://localhost:8233' + COLORS.reset + ' │');
386
- console.log('└─────────────────────────────────────────────────────────────────┘');
387
- console.log('');
388
- log(COLORS.yellow, '📚 DOCUMENTATION:');
389
- console.log(' • https://github.com/DeamonDev888/overmind-mcp');
390
- console.log(' • https://www.npmjs.com/package/overmind-mcp');
391
- console.log('');
392
- log(COLORS.yellow, '🎉 PROCHAINE ÉTAPE:');
393
- console.log(' • Créez votre premier agent: overmind create-agent');
394
- console.log(' • Ou listez les agents: overmind list-agents');
395
- console.log('');
396
- }
397
-
398
- // ═════════════════════════════════════════════════════════════════════════════
399
- // MAIN
400
- // ═════════════════════════════════════════════════════════════════════════════
401
-
402
- async function main() {
403
- console.log('╔══════════════════════════════════════════════════════════════════╗');
404
- console.log('║' + ' '.repeat(64) + '║');
405
- console.log('║' + COLORS.cyan + ' 🚀 OVERMIND-MCP - INSTALLATION AUTOMATIQUE' + COLORS.reset + ' '.repeat(25) + '║');
406
- console.log('║' + ' '.repeat(64) + '║');
407
- console.log('╚══════════════════════════════════════════════════════════════════╝');
408
- console.log('');
409
-
410
- // Banner
411
- console.log(COLORS.cyan + 'Ce script VA installer automatiquement:' + COLORS.reset);
412
- console.log(' ✓ Vérifier Docker');
413
- console.log(' ✓ Installer PostgreSQL + pgvector (si absent)');
414
- console.log(' ✓ Télécharger docker-compose.yml et configs');
415
- console.log(' ✓ Démarrer TOUS les services Docker automatiquement');
416
- console.log(' ✓ Copier .env.example → .env');
417
- console.log(' ✓ Copier .mcp.json.example → .mcp.json');
418
- console.log(' ✓ Valider tous les services');
419
- console.log(' ✓ Montrer où les voir dans Docker Desktop');
420
- console.log('');
421
-
422
- // Step 1: Check Docker
423
- const dockerOk = await checkDocker();
424
- if (!dockerOk) {
425
- return;
426
- }
427
-
428
- // Step 2: Setup PostgreSQL
429
- await setupPostgreSQL();
430
-
431
- // Step 3: Setup .env et .mcp.json
432
- createEnvConfig();
433
-
434
- // Step 4: Download infrastructure files
435
- const downloaded = await setupInfrastructure();
436
-
437
- // Step 5: Start ALL services automatically
438
- if (downloaded) {
439
- const started = await startInfrastructure();
440
- if (!started) {
441
- log(COLORS.yellow, '\n⚠️ Infrastructure non démarrée automatiquement.');
442
- log(COLORS.yellow, ' PostgreSQL fonctionne, mais les autres services ne sont pas actifs.');
443
- }
444
- }
445
-
446
- // Step 6: Validate ALL services
447
- if (downloaded) {
448
- const allOk = await validateServices();
449
- if (allOk) {
450
- logSection('✅ TOUS LES SERVICES SONT ACTIFS');
451
- log(COLORS.green, '🎉 Installation complète réussie !');
452
- } else {
453
- logSection('⚠️ CERTAINS SERVICES NON DÉMARRÉS');
454
- }
455
- }
456
-
457
- // Show final summary
458
- showSummary();
459
- }
460
-
461
- // Run main
462
- main().catch((error) => {
463
- console.error('\n❌ ERREUR FATALE:', error.message);
464
- process.exit(1);
465
- });
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ═══════════════════════════════════════════════════════════════════════════════
4
+ * OVERMIND-MCP - POST-INSTALL AUTOMATIQUE
5
+ * ═════════════════════════════════════════════════════════════════════════════
6
+ * Script exécuté automatiquement après npm install -g overmind-mcp
7
+ * INSTALLE ET DÉMARRE TOUT AUTOMATIQUEMENT :
8
+ * - Vérifie Docker
9
+ * - Installe PostgreSQL + pgvector (si absent)
10
+ * - Copie .env.example → .env
11
+ * - Copie .mcp.json.example → .mcp.json
12
+ * - Télécharge et démarre TOUTE l'infrastructure Docker
13
+ * - Valide tous les services
14
+ * - Montre où les voir dans Docker Desktop
15
+ * ═══════════════════════════════════════════════════════════════════════════════
16
+ */
17
+
18
+ import { execSync, spawn } from 'child_process';
19
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
20
+ import { join } from 'path';
21
+ import { fileURLToPath } from 'url';
22
+ import { dirname } from 'path';
23
+
24
+ const __filename = fileURLToPath(import.meta.url);
25
+ const __dirname = dirname(__filename);
26
+
27
+ const INSTALL_DIR = join(
28
+ process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH,
29
+ '.overmind'
30
+ );
31
+
32
+ // ═══════════════════════════════════════════════════════════════════════════════
33
+ // COLORS
34
+ // ═════════════════════════════════════════════════════════════════════════════
35
+
36
+ const COLORS = {
37
+ cyan: '\x1b[36m',
38
+ green: '\x1b[32m',
39
+ yellow: '\x1b[33m',
40
+ red: '\x1b[31m',
41
+ white: '\x1b[37m',
42
+ reset: '\x1b[0m'
43
+ };
44
+
45
+ function log(color, str) {
46
+ console.log(`${color}${str}${COLORS.reset}`);
47
+ }
48
+
49
+ function logSection(title) {
50
+ console.log('\n╔══════════════════════════════════════════════════════════════════╗');
51
+ console.log(`║ ${title.padEnd(64)} ║`);
52
+ console.log('╚══════════════════════════════════════════════════════════════════╝');
53
+ }
54
+
55
+ function runCommand(cmd, options = {}) {
56
+ try {
57
+ return execSync(cmd, { stdio: 'pipe', encoding: 'utf8', ...options });
58
+ } catch {
59
+ return null;
60
+ }
61
+ }
62
+
63
+ async function runCommandAsync(cmd, description) {
64
+ return new Promise((resolve, reject) => {
65
+ console.log(`🔧 ${description}`);
66
+ console.log(` $ ${cmd}`);
67
+
68
+ const child = spawn(cmd, { shell: true, stdio: 'inherit' });
69
+
70
+ child.on('close', (code) => {
71
+ if (code === 0) {
72
+ console.log(`✅ ${description} terminé`);
73
+ resolve(true);
74
+ } else {
75
+ console.error(`❌ Erreur (code ${code})`);
76
+ reject(new Error(`Command failed with code ${code}`));
77
+ }
78
+ });
79
+
80
+ child.on('error', (err) => {
81
+ console.error('❌ Erreur:', err.message);
82
+ reject(err);
83
+ });
84
+ });
85
+ }
86
+
87
+ // ═══════════════════════════════════════════════════════════════════════════════
88
+ // INSTALLATION STEPS
89
+ // ═════════════════════════════════════════════════════════════════════════════
90
+
91
+ async function checkDocker() {
92
+ logSection('VÉRIFICATION DOCKER');
93
+
94
+ const version = runCommand('docker --version');
95
+ if (!version) {
96
+ log(COLORS.red, '❌ Docker non trouvé');
97
+ console.log('');
98
+ log(COLORS.yellow, '📥 Installation Docker requise:');
99
+
100
+ const platform = process.platform;
101
+ if (platform === 'win32') {
102
+ console.log(' Windows: https://www.docker.com/products/docker-desktop/');
103
+ } else if (platform === 'darwin') {
104
+ console.log(' macOS: https://www.docker.com/products/docker-desktop/');
105
+ } else {
106
+ console.log(' Linux: https://docs.docker.com/engine/install/');
107
+ }
108
+
109
+ log(COLORS.cyan, '\nAprès installation de Docker, relancez: npm install -g overmind-mcp');
110
+ return false;
111
+ }
112
+
113
+ log(COLORS.green, '✅ Docker détecté: ' + version.trim());
114
+ return true;
115
+ }
116
+
117
+ async function setupPostgreSQL() {
118
+ logSection('INSTALLATION POSTGRESQL + PGVECTOR');
119
+
120
+ // Check if already exists
121
+ const existingContainer = runCommand(
122
+ 'docker ps --filter "name=postgres-pgvector" --format "{{.Names}}"',
123
+ { stdio: 'pipe' }
124
+ );
125
+
126
+ if (existingContainer) {
127
+ log(COLORS.green, '✅ PostgreSQL + pgvector déjà installé');
128
+ log(COLORS.cyan, ' Container: ' + existingContainer.trim());
129
+ return true;
130
+ }
131
+
132
+ log(COLORS.yellow, '📦 Installation PostgreSQL + pgvector...');
133
+
134
+ try {
135
+ await runCommandAsync(
136
+ 'docker pull pgvector/pgvector:pg16',
137
+ 'Téléchargement image'
138
+ );
139
+
140
+ // Remove existing if stopped
141
+ runCommand('docker rm -f overmind-postgres-pgvector', { stdio: 'pipe' });
142
+
143
+ const runCmd = [
144
+ 'docker', 'run', '-d',
145
+ '--name', 'overmind-postgres-pgvector',
146
+ '-p', '5432:5432',
147
+ '-e', 'POSTGRES_PASSWORD=overmind_temp_password_change_me',
148
+ '-e', 'POSTGRES_USER=postgres',
149
+ '-v', 'overmind_postgres_data:/var/lib/postgresql/data',
150
+ '--restart', 'unless-stopped',
151
+ 'pgvector/pgvector:pg16'
152
+ ].join(' ');
153
+
154
+ await runCommandAsync(runCmd, 'Démarrage PostgreSQL');
155
+
156
+ log(COLORS.cyan, '\n⏳ Attente démarrage PostgreSQL (20s)...');
157
+ await new Promise(resolve => setTimeout(resolve, 20000));
158
+
159
+ // Enable pgvector
160
+ await runCommandAsync(
161
+ `docker exec overmind-postgres-pgvector psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS vector;"`,
162
+ 'Activation pgvector'
163
+ );
164
+
165
+ log(COLORS.green, '\n✅ PostgreSQL + pgvector installés !');
166
+ return true;
167
+ } catch (error) {
168
+ log(COLORS.red, '❌ Erreur installation PostgreSQL: ' + error.message);
169
+ return false;
170
+ }
171
+ }
172
+
173
+ async function setupInfrastructure() {
174
+ logSection('TÉLÉCHARGEMENT INFRASTRUCTURE');
175
+
176
+ mkdirSync(INSTALL_DIR, { recursive: true });
177
+
178
+ log(COLORS.yellow, '📥 Téléchargement fichiers docker-compose...');
179
+
180
+ const composeUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/docker-compose.yml';
181
+ const exportersUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/docker-compose.exporters.yml';
182
+ const envExampleUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/.env.example';
183
+ const mcpExampleUrl = 'https://raw.githubusercontent.com/DeamonDev888/overmind-mcp/main/.mcp.json.example';
184
+
185
+ try {
186
+ // Télécharger docker-compose.yml
187
+ const composeData = runCommand(`curl -sL ${composeUrl}`);
188
+ if (composeData) {
189
+ writeFileSync(join(INSTALL_DIR, 'docker-compose.yml'), composeData);
190
+ log(COLORS.green, '✅ docker-compose.yml téléchargé');
191
+ }
192
+
193
+ // Télécharger docker-compose.exporters.yml
194
+ const exportersData = runCommand(`curl -sL ${exportersUrl}`);
195
+ if (exportersData) {
196
+ writeFileSync(join(INSTALL_DIR, 'docker-compose.exporters.yml'), exportersData);
197
+ log(COLORS.green, '✅ docker-compose.exporters.yml téléchargé');
198
+ }
199
+
200
+ // Télécharger .env.example
201
+ const envExampleData = runCommand(`curl -sL ${envExampleUrl}`);
202
+ if (envExampleData) {
203
+ writeFileSync(join(INSTALL_DIR, '.env.example'), envExampleData);
204
+ log(COLORS.green, '✅ .env.example téléchargé');
205
+ }
206
+
207
+ // Télécharger .mcp.json.example
208
+ const mcpExampleData = runCommand(`curl -sL ${mcpExampleUrl}`);
209
+ if (mcpExampleData) {
210
+ writeFileSync(join(INSTALL_DIR, '.mcp.json.example'), mcpExampleData);
211
+ log(COLORS.green, '✅ .mcp.json.example téléchargé');
212
+ }
213
+
214
+ return true;
215
+ } catch (error) {
216
+ log(COLORS.red, '❌ Erreur téléchargement: ' + error.message);
217
+ return false;
218
+ }
219
+ }
220
+
221
+ function createEnvConfig() {
222
+ logSection('CRÉATION CONFIGURATION');
223
+
224
+ mkdirSync(INSTALL_DIR, { recursive: true });
225
+
226
+ const envFile = join(INSTALL_DIR, '.env');
227
+ const envExampleFile = join(INSTALL_DIR, '.env.example');
228
+ const mcpFile = join(INSTALL_DIR, '.mcp.json');
229
+ const mcpExampleFile = join(INSTALL_DIR, '.mcp.json.example');
230
+
231
+ // Copier .env.example → .env si existe
232
+ if (existsSync(envExampleFile) && !existsSync(envFile)) {
233
+ let envContent;
234
+
235
+ if (process.platform === 'win32') {
236
+ envContent = runCommand(`type "${envExampleFile}"`, { stdio: 'pipe' });
237
+ } else {
238
+ envContent = runCommand(`cat "${envExampleFile}"`, { stdio: 'pipe' });
239
+ }
240
+
241
+ if (envContent) {
242
+ writeFileSync(envFile, envContent);
243
+ log(COLORS.green, '✅ .env créé (à partir de .env.example)');
244
+ }
245
+ }
246
+
247
+ // Créer .env minimal si n'existe pas
248
+ if (!existsSync(envFile)) {
249
+ const envContent = `# OverMind-MCP Environment Configuration
250
+ # Généré automatiquement par npm install
251
+
252
+ # PostgreSQL
253
+ POSTGRES_HOST=localhost
254
+ POSTGRES_PORT=5432
255
+ POSTGRES_USER=postgres
256
+ POSTGRES_PASSWORD=overmind_temp_password_change_me
257
+ POSTGRES_DB=overmind
258
+
259
+ # OpenTelemetry (optionnel)
260
+ OTEL_ENABLED=false
261
+
262
+ # Workspace
263
+ OVERMIND_WORKSPACE=${INSTALL_DIR}
264
+ `;
265
+ writeFileSync(envFile, envContent);
266
+ log(COLORS.green, '✅ Configuration .env créée: ' + envFile);
267
+ }
268
+
269
+ // Copier .mcp.json.example → .mcp.json si existe
270
+ if (existsSync(mcpExampleFile) && !existsSync(mcpFile)) {
271
+ let mcpContent;
272
+
273
+ if (process.platform === 'win32') {
274
+ mcpContent = runCommand(`type "${mcpExampleFile}"`, { stdio: 'pipe' });
275
+ } else {
276
+ mcpContent = runCommand(`cat "${mcpExampleFile}"`, { stdio: 'pipe' });
277
+ }
278
+
279
+ if (mcpContent) {
280
+ writeFileSync(mcpFile, mcpContent);
281
+ log(COLORS.green, '✅ .mcp.json créé (à partir de .mcp.json.example)');
282
+ }
283
+ }
284
+ }
285
+
286
+ async function startInfrastructure() {
287
+ logSection('DÉMARRAGE AUTOMATIQUE INFRASTRUCTURE COMPLÈTE');
288
+
289
+ const composeFile = join(INSTALL_DIR, 'docker-compose.yml');
290
+
291
+ if (!existsSync(composeFile)) {
292
+ log(COLORS.yellow, '⚠️ docker-compose.yml non trouvé. Téléchargement...');
293
+ const downloaded = await setupInfrastructure();
294
+ if (!downloaded) {
295
+ return false;
296
+ }
297
+ }
298
+
299
+ try {
300
+ log(COLORS.yellow, '🚀 Démarrage automatique de TOUS les services...');
301
+ log(COLORS.cyan, ' (PostgreSQL, RabbitMQ, Temporal, Prometheus, Grafana, Jaeger, Redis)');
302
+
303
+ await runCommandAsync(
304
+ `cd "${INSTALL_DIR}" && docker-compose -f docker-compose.yml pull`,
305
+ 'Téléchargement images Docker'
306
+ );
307
+
308
+ await runCommandAsync(
309
+ `cd "${INSTALL_DIR}" && docker-compose -f docker-compose.yml up -d`,
310
+ 'Démarrage infrastructure complète'
311
+ );
312
+
313
+ log(COLORS.cyan, '\n⏳ Attente démarrage des services (20s)...');
314
+ await new Promise(resolve => setTimeout(resolve, 20000));
315
+
316
+ return true;
317
+ } catch (error) {
318
+ log(COLORS.red, '\n⚠️ Erreur démarrage infrastructure: ' + error.message);
319
+ log(COLORS.yellow, '\n💡 Solution manuelle:');
320
+ log(COLORS.white, ' cd ~/.overmind');
321
+ log(COLORS.white, ' docker-compose up -d');
322
+ return false;
323
+ }
324
+ }
325
+
326
+ async function validateServices() {
327
+ logSection('VALIDATION DES SERVICES');
328
+
329
+ log(COLORS.yellow, '🔍 Vérification des containers Docker...\n');
330
+
331
+ const services = [
332
+ { name: 'PostgreSQL + pgvector', filter: 'postgres', color: COLORS.green },
333
+ { name: 'RabbitMQ', filter: 'rabbitmq', color: COLORS.green },
334
+ { name: 'Temporal', filter: 'temporal', color: COLORS.green },
335
+ { name: 'Prometheus', filter: 'prometheus', color: COLORS.green },
336
+ { name: 'Grafana', filter: 'grafana', color: COLORS.green },
337
+ { name: 'Jaeger', filter: 'jaeger', color: COLORS.green },
338
+ { name: 'Redis', filter: 'redis', color: COLORS.green },
339
+ ];
340
+
341
+ let allRunning = true;
342
+
343
+ for (const service of services) {
344
+ const containerName = runCommand(
345
+ `docker ps --filter "name=${service.filter}" --format "{{.Names}}"`,
346
+ { stdio: 'pipe' }
347
+ );
348
+
349
+ if (containerName) {
350
+ log(service.color, ` ✅ ${service.name}: ${containerName.trim()}`);
351
+ } else {
352
+ log(COLORS.red, ` ❌ ${service.name}: Non trouvé`);
353
+ allRunning = false;
354
+ }
355
+ }
356
+
357
+ return allRunning;
358
+ }
359
+
360
+ function showSummary() {
361
+ console.log('\n╔══════════════════════════════════════════════════════════════════╗');
362
+ console.log('║' + ' '.repeat(64) + '║');
363
+ console.log('║' + COLORS.green + ' ✅ INSTALLATION TERMINÉE !' + COLORS.reset + ' '.repeat(33) + '║');
364
+ console.log('║' + ' '.repeat(64) + '║');
365
+ console.log('╚══════════════════════════════════════════════════════════════════╝');
366
+ console.log('');
367
+ log(COLORS.yellow, '📋 SERVICES ACTIFS DANS DOCKER DESKTOP:');
368
+ console.log('');
369
+ console.log('┌─────────────────────────────────────────────────────────────────┐');
370
+ console.log('│ ' + COLORS.cyan + 'Ouvrez Docker Desktop → onglet "Containers"' + COLORS.reset + ' │');
371
+ console.log('│ ' + COLORS.cyan + 'Vous verrez tous les services OverMind actifs:' + COLORS.reset + ' │');
372
+ console.log('│ ' + COLORS.green + ' • PostgreSQL + pgvector' + COLORS.reset + ' │');
373
+ console.log('│ ' + COLORS.green + ' • RabbitMQ (Message Broker)' + COLORS.reset + ' │');
374
+ console.log('│ ' + COLORS.green + ' • Temporal (Workflow Engine)' + COLORS.reset + ' │');
375
+ console.log('│ ' + COLORS.green + ' • Prometheus (Métriques)' + COLORS.reset + ' │');
376
+ console.log('│ ' + COLORS.green + ' • Grafana (Dashboards)' + COLORS.reset + ' │');
377
+ console.log('│ ' + COLORS.green + ' • Jaeger (Tracing)' + COLORS.reset + ' │');
378
+ console.log('│ ' + COLORS.green + ' • Redis (Cache)' + COLORS.reset + ' │');
379
+ console.log('│ │');
380
+ console.log('│ ' + COLORS.yellow + 'URLs utiles:' + COLORS.reset + ' │');
381
+ console.log('│ • Prometheus: ' + COLORS.cyan + 'http://localhost:9090' + COLORS.reset + ' │');
382
+ console.log('│ • Grafana: ' + COLORS.cyan + 'http://localhost:3000' + COLORS.reset + ' (admin/admin)' + ' │');
383
+ console.log('│ • Jaeger: ' + COLORS.cyan + 'http://localhost:16686' + COLORS.reset + ' │');
384
+ console.log('│ • RabbitMQ: ' + COLORS.cyan + 'http://localhost:15672' + COLORS.reset + ' (guest/guest)' + ' │');
385
+ console.log('│ • Temporal: ' + COLORS.cyan + 'http://localhost:8233' + COLORS.reset + ' │');
386
+ console.log('└─────────────────────────────────────────────────────────────────┘');
387
+ console.log('');
388
+ log(COLORS.yellow, '📚 DOCUMENTATION:');
389
+ console.log(' • https://github.com/DeamonDev888/overmind-mcp');
390
+ console.log(' • https://www.npmjs.com/package/overmind-mcp');
391
+ console.log('');
392
+ log(COLORS.yellow, '🎉 PROCHAINE ÉTAPE:');
393
+ console.log(' • Créez votre premier agent: overmind create-agent');
394
+ console.log(' • Ou listez les agents: overmind list-agents');
395
+ console.log('');
396
+ }
397
+
398
+ // ═════════════════════════════════════════════════════════════════════════════
399
+ // MAIN
400
+ // ═════════════════════════════════════════════════════════════════════════════
401
+
402
+ async function main() {
403
+ console.log('╔══════════════════════════════════════════════════════════════════╗');
404
+ console.log('║' + ' '.repeat(64) + '║');
405
+ console.log('║' + COLORS.cyan + ' 🚀 OVERMIND-MCP - INSTALLATION AUTOMATIQUE' + COLORS.reset + ' '.repeat(25) + '║');
406
+ console.log('║' + ' '.repeat(64) + '║');
407
+ console.log('╚══════════════════════════════════════════════════════════════════╝');
408
+ console.log('');
409
+
410
+ // Banner
411
+ console.log(COLORS.cyan + 'Ce script VA installer automatiquement:' + COLORS.reset);
412
+ console.log(' ✓ Vérifier Docker');
413
+ console.log(' ✓ Installer PostgreSQL + pgvector (si absent)');
414
+ console.log(' ✓ Télécharger docker-compose.yml et configs');
415
+ console.log(' ✓ Démarrer TOUS les services Docker automatiquement');
416
+ console.log(' ✓ Copier .env.example → .env');
417
+ console.log(' ✓ Copier .mcp.json.example → .mcp.json');
418
+ console.log(' ✓ Valider tous les services');
419
+ console.log(' ✓ Montrer où les voir dans Docker Desktop');
420
+ console.log('');
421
+
422
+ // Step 1: Check Docker
423
+ const dockerOk = await checkDocker();
424
+ if (!dockerOk) {
425
+ return;
426
+ }
427
+
428
+ // Step 2: Setup PostgreSQL
429
+ await setupPostgreSQL();
430
+
431
+ // Step 3: Setup .env et .mcp.json
432
+ createEnvConfig();
433
+
434
+ // Step 4: Download infrastructure files
435
+ const downloaded = await setupInfrastructure();
436
+
437
+ // Step 5: Start ALL services automatically
438
+ if (downloaded) {
439
+ const started = await startInfrastructure();
440
+ if (!started) {
441
+ log(COLORS.yellow, '\n⚠️ Infrastructure non démarrée automatiquement.');
442
+ log(COLORS.yellow, ' PostgreSQL fonctionne, mais les autres services ne sont pas actifs.');
443
+ }
444
+ }
445
+
446
+ // Step 6: Validate ALL services
447
+ if (downloaded) {
448
+ const allOk = await validateServices();
449
+ if (allOk) {
450
+ logSection('✅ TOUS LES SERVICES SONT ACTIFS');
451
+ log(COLORS.green, '🎉 Installation complète réussie !');
452
+ } else {
453
+ logSection('⚠️ CERTAINS SERVICES NON DÉMARRÉS');
454
+ }
455
+ }
456
+
457
+ // Show final summary
458
+ showSummary();
459
+ }
460
+
461
+ // Run main
462
+ main().catch((error) => {
463
+ console.error('\n❌ ERREUR FATALE:', error.message);
464
+ process.exit(1);
465
+ });