overmind-mcp 3.2.4 → 3.2.6

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.
@@ -10,7 +10,7 @@ set -uo pipefail # PAS de set -e — on gère les erreurs manuellement
10
10
 
11
11
  # ─── Couleurs + helpers ──────────────────────────────────────
12
12
  R='\033[0;31m'; G='\033[0;32m'; Y='\033[1;33m'; C='\033[0;36m'; B='\033[1m'; D='\033[2m'; N='\033[0m'
13
- STEPS_TOTAL=8
13
+ STEPS_TOTAL=11
14
14
  STEP=0
15
15
 
16
16
  log() { echo -e "${C}[$(date +%H:%M:%S)]${N} ${D}$*${N}"; }
@@ -148,15 +148,27 @@ if [ "$OS" = "Darwin" ]; then
148
148
  track_warn "Homebrew non trouvé — installez: https://brew.sh"
149
149
  track_warn "Bypass: installez Docker et utilisez overmind-postgres-mcp up"
150
150
  else
151
- # PostgreSQL
152
- if brew list postgresql@18 >/dev/null 2>&1; then
153
- ok "postgresql@18 déjà installé"
154
- else
155
- log "Installation postgresql@18 via brew..."
156
- brew install postgresql@18 2>/dev/null || {
157
- track_warn "postgresql@18 non disponible, fallback postgresql@16"
158
- brew install postgresql@16 2>/dev/null || track_error "brew install postgresql a échoué"
151
+ # PostgreSQL — brew a postgresql@17 en stable, @18 peut ne pas exister encore
152
+ PG_BREW_VER=""
153
+ for pgver in postgresql@18 postgresql@17 postgresql@16 postgresql@15 postgresql@14 postgresql; do
154
+ if brew list "$pgver" >/dev/null 2>&1; then
155
+ PG_BREW_VER="$pgver"
156
+ ok "$pgver déjà installé"
157
+ break
158
+ fi
159
+ done
160
+ if [ -z "$PG_BREW_VER" ]; then
161
+ log "Installation PostgreSQL via brew (dernière version stable)..."
162
+ brew install postgresql 2>/dev/null && PG_BREW_VER="postgresql" || {
163
+ # Fallback: essayer les versions numérotées
164
+ for pgver in postgresql@17 postgresql@16 postgresql@15; do
165
+ log "Tentative $pgver..."
166
+ brew install "$pgver" 2>/dev/null && PG_BREW_VER="$pgver" && break
167
+ done
159
168
  }
169
+ if [ -z "$PG_BREW_VER" ]; then
170
+ track_error "brew install postgresql a échoué"
171
+ fi
160
172
  fi
161
173
 
162
174
  # pgvector
@@ -164,14 +176,22 @@ if [ "$OS" = "Darwin" ]; then
164
176
  ok "pgvector déjà installé"
165
177
  else
166
178
  log "Installation pgvector via brew..."
167
- brew install pgvector 2>/dev/null || track_warn "pgvector non disponible via brew — installez manuellement"
179
+ brew install pgvector 2>/dev/null || {
180
+ track_warn "pgvector non disponible via brew — compilation depuis source..."
181
+ (
182
+ cd /tmp && git clone --depth 1 https://github.com/pgvector/pgvector.git 2>/dev/null && \
183
+ cd pgvector && make 2>/dev/null && make install 2>/dev/null
184
+ ) && ok "pgvector compilé depuis source" || track_warn "pgvector compilation échouée"
185
+ }
168
186
  fi
169
187
 
170
188
  # Démarrer le service
171
- brew services start postgresql@18 2>/dev/null || brew services start postgresql@16 2>/dev/null || true
172
- sleep 3
173
- PG_INSTALLED=true
174
- ok "Service PostgreSQL démarré via brew"
189
+ if [ -n "$PG_BREW_VER" ]; then
190
+ brew services start "$PG_BREW_VER" 2>/dev/null || true
191
+ sleep 3
192
+ PG_INSTALLED=true
193
+ ok "Service $PG_BREW_VER démarré via brew"
194
+ fi
175
195
  fi
176
196
 
177
197
  elif [ "$OS" = "Linux" ]; then
@@ -239,7 +259,27 @@ fi
239
259
  step "Base de données + pgvector"
240
260
 
241
261
  if [ "$PG_INSTALLED" = "true" ]; then
242
- sleep 2 # Laisser PG démarrer
262
+ # Wait for PostgreSQL to be ready (max 15s)
263
+ log "Attente démarrage PostgreSQL..."
264
+ PG_READY=false
265
+ for i in 1 2 3 4 5 6 7 8 9 10; do
266
+ if [ "$OS" = "Darwin" ]; then
267
+ if psql -U "$PG_SUPERUSER" -d postgres -c "SELECT 1" >/dev/null 2>&1; then
268
+ PG_READY=true; break
269
+ fi
270
+ else
271
+ if $SUDO -u postgres psql -c "SELECT 1" >/dev/null 2>&1; then
272
+ PG_READY=true; break
273
+ fi
274
+ fi
275
+ sleep 2
276
+ done
277
+
278
+ if [ "$PG_READY" = "true" ]; then
279
+ ok "PostgreSQL prêt"
280
+ else
281
+ track_warn "PostgreSQL ne répond pas après 20s"
282
+ fi
243
283
 
244
284
  # Créer la DB si elle n'existe pas
245
285
  DB_EXISTS=false
@@ -454,6 +494,67 @@ UNIT
454
494
  fi
455
495
 
456
496
  $SUDO systemctl daemon-reload
497
+
498
+ # ─── Gestion des conflits de port ────────────────────────────
499
+ # Tue UNIQUEMENT les zombies/doublons, jamais un service sain.
500
+ for port in $MCP_PORT_CORE $MCP_PORT_PG; do
501
+ # Récupérer TOUS les PIDs sur ce port
502
+ PIDS_ON_PORT=$(lsof -tiTCP:$port -sTCP:LISTEN 2>/dev/null || ss -tlnp 2>/dev/null | grep ":$port " | grep -oP 'pid=\K[0-9]+' | head -5)
503
+
504
+ if [ -n "$PIDS_ON_PORT" ]; then
505
+ PID_COUNT=$(echo "$PIDS_ON_PORT" | wc -w)
506
+
507
+ for pid in $PIDS_ON_PORT; do
508
+ [ -z "$pid" ] && continue
509
+
510
+ # Vérifier si c'est un process zombie (Z état)
511
+ PID_STATE=$(ps -o stat= -p "$pid" 2>/dev/null | head -1)
512
+ PID_CMD=$(ps -o args= -p "$pid" 2>/dev/null | head -1)
513
+
514
+ # Cas 1: Zombie → kill certain
515
+ if echo "$PID_STATE" | grep -q 'Z'; then
516
+ warn "Port :$port — PID $pid est un ZOMBIE → kill"
517
+ kill -9 "$pid" 2>/dev/null || $SUDO kill -9 "$pid" 2>/dev/null || true
518
+ sleep 1
519
+ continue
520
+ fi
521
+
522
+ # Cas 2: Pas un process overmind/node → doublon parasite → kill
523
+ if ! echo "$PID_CMD" | grep -qE 'overmind|cli\.js|dist/index\.js'; then
524
+ warn "Port :$port — PID $pid est un doublon parasite ($PID_CMD) → kill"
525
+ kill "$pid" 2>/dev/null || $SUDO kill "$pid" 2>/dev/null || true
526
+ sleep 2
527
+ continue
528
+ fi
529
+
530
+ # Cas 3: Doublon (plusieurs process overmind sur le même port)
531
+ if [ "$PID_COUNT" -gt 1 ]; then
532
+ warn "Port :$port — doublon détecté ($PID_COUNT process) → kill du plus ancien ($pid)"
533
+ kill "$pid" 2>/dev/null || $SUDO kill "$pid" 2>/dev/null || true
534
+ sleep 2
535
+ continue
536
+ fi
537
+
538
+ # Cas 4: Process overmind unique et sain → on garde, systemd fera un restart
539
+ ok "Port :$port — PID $pid (overmind sain) — préservé, systemd takeover"
540
+ done
541
+
542
+ # Vérification finale
543
+ sleep 1
544
+ PID_AFTER=$(lsof -tiTCP:$port -sTCP:LISTEN 2>/dev/null | head -1)
545
+ if [ -n "$PID_AFTER" ]; then
546
+ AFTER_CMD=$(ps -o args= -p "$PID_AFTER" 2>/dev/null | head -1)
547
+ if echo "$AFTER_CMD" | grep -qE 'overmind|cli\.js|dist/index\.js'; then
548
+ ok "Port :$port — process overmind sain conservé (PID $PID_AFTER)"
549
+ else
550
+ track_warn "Port :$port — toujours occupé par un process non-overmind"
551
+ fi
552
+ else
553
+ ok "Port :$port libéré"
554
+ fi
555
+ fi
556
+ done
557
+
457
558
  $SUDO systemctl enable --now overmind-mcp.service 2>/dev/null || track_warn "systemctl enable overmind-mcp"
458
559
  ok "overmind-mcp.service: $($SUDO systemctl is-active overmind-mcp.service 2>/dev/null || echo '?')"
459
560
 
@@ -502,6 +603,53 @@ elif [ "$OS" = "Darwin" ]; then
502
603
  PLIST
503
604
  launchctl bootout gui/$(id -u) "$plist" 2>/dev/null || true
504
605
  launchctl bootstrap gui/$(id -u) "$plist" 2>/dev/null || true
606
+
607
+ # ─── Gestion des conflits de port (macOS) ───────────────────
608
+ # Tue UNIQUEMENT zombies/doublons, jamais un process overmind sain.
609
+ PIDS_ON_PORT=$(lsof -tiTCP:$port -sTCP:LISTEN 2>/dev/null)
610
+ if [ -n "$PIDS_ON_PORT" ]; then
611
+ PID_COUNT=$(echo "$PIDS_ON_PORT" | wc -w)
612
+ for pid in $PIDS_ON_PORT; do
613
+ [ -z "$pid" ] && continue
614
+ PID_STATE=$(ps -o stat= -p "$pid" 2>/dev/null | head -1)
615
+ PID_CMD=$(ps -o args= -p "$pid" 2>/dev/null | head -1)
616
+
617
+ # Cas 1: Zombie → kill
618
+ if echo "$PID_STATE" | grep -q 'Z'; then
619
+ warn "Port :$port — PID $pid est un ZOMBIE → kill"
620
+ kill -9 "$pid" 2>/dev/null || true
621
+ sleep 1
622
+ continue
623
+ fi
624
+
625
+ # Cas 2: Process non-overmind → parasite → kill
626
+ if ! echo "$PID_CMD" | grep -qE 'overmind|cli\.js|dist/index\.js'; then
627
+ warn "Port :$port — PID $pid parasite ($PID_CMD) → kill"
628
+ kill "$pid" 2>/dev/null || true
629
+ sleep 2
630
+ continue
631
+ fi
632
+
633
+ # Cas 3: Doublon overmind
634
+ if [ "$PID_COUNT" -gt 1 ]; then
635
+ warn "Port :$port — doublon ($PID_COUNT process) → kill $pid"
636
+ kill "$pid" 2>/dev/null || true
637
+ sleep 2
638
+ continue
639
+ fi
640
+
641
+ # Cas 4: overmind sain unique → préservé
642
+ ok "Port :$port — PID $pid (overmind sain) préservé"
643
+ done
644
+
645
+ sleep 1
646
+ PID_AFTER=$(lsof -tiTCP:$port -sTCP:LISTEN 2>/dev/null | head -1)
647
+ if [ -z "$PID_AFTER" ]; then
648
+ ok "Port :$port libéré"
649
+ # Re-bootstrap après libération
650
+ launchctl bootstrap gui/$(id -u) "$plist" 2>/dev/null || true
651
+ fi
652
+ fi
505
653
  ok "launchd: com.overmind.${name} chargé"
506
654
  }
507
655
 
@@ -519,7 +667,243 @@ else
519
667
  fi
520
668
 
521
669
  # ================================================================
522
- # STEP 8/8Validation finale
670
+ # STEP 8/10Vérification + MAJ des CLIs runners
671
+ # ================================================================
672
+ step "CLIs runners (claude, kilo, hermes, gemini, etc.)"
673
+
674
+ # ─── Hermes ───────────────────────────────────────────────────
675
+ if have hermes; then
676
+ HERMES_VER="$(hermes version 2>/dev/null || echo '?')"
677
+ ok "Hermes: ${HERMES_VER}"
678
+ log "Vérification MAJ Hermes..."
679
+ hermes update 2>/dev/null && ok "Hermes mis à jour" || ok "Hermes déjà à jour"
680
+ else
681
+ log "Installation Hermes..."
682
+ if have pip3; then
683
+ $SUDO pip3 install -U hermes-agent 2>/dev/null || pip3 install -U hermes-agent 2>/dev/null || track_warn "pip3 install hermes-agent"
684
+ ok "Hermes installé via pip3"
685
+ elif have pip; then
686
+ $SUDO pip install -U hermes-agent 2>/dev/null || pip install -U hermes-agent 2>/dev/null || track_warn "pip install hermes-agent"
687
+ ok "Hermes installé via pip"
688
+ else
689
+ track_warn "Hermes non installé — pip3 manquant (pip3 install hermes-agent)"
690
+ fi
691
+ fi
692
+
693
+ # ─── Claude CLI ───────────────────────────────────────────────
694
+ if have claude; then
695
+ CLAUDE_VER="$(claude --version 2>/dev/null || echo '?')"
696
+ ok "Claude CLI: ${CLAUDE_VER}"
697
+ log "Vérification MAJ Claude..."
698
+ npm install -g @anthropic-ai/claude-code@latest 2>/dev/null && ok "Claude CLI mis à jour" || ok "Claude CLI déjà à jour"
699
+ else
700
+ log "Claude CLI non détecté (optionnel — npm i -g @anthropic-ai/claude-code)"
701
+ fi
702
+
703
+ # ─── Kilo Code ────────────────────────────────────────────────
704
+ if have kilo; then
705
+ KILO_VER="$(kilo --version 2>/dev/null || echo '?')"
706
+ ok "Kilo Code: ${KILO_VER}"
707
+ else
708
+ log "Kilo Code non détecté (optionnel)"
709
+ fi
710
+
711
+ # ─── Gemini CLI (optionnel, pas affiché) ─────────────────────
712
+ if have gemini; then
713
+ log "Gemini CLI détecté (optionnel)"
714
+ fi
715
+
716
+ # ─── Autres CLIs (optionnel, pas affiché) ────────────────────
717
+ for cli in opencode openclaw cline qwencli; do
718
+ have "$cli" && log "${cli} détecté (optionnel)"
719
+ done
720
+
721
+ ok "CLIs runners vérifiés"
722
+
723
+ # ================================================================
724
+ # STEP 9/10 — MAJ overmind-mcp + dependencies npm
725
+ # ================================================================
726
+ step "MAJ packages npm (overmind + deps)"
727
+
728
+ # Récupérer le path global npm
729
+ NPM_GLOBAL="$(npm root -g 2>/dev/null || echo /usr/lib/node_modules)"
730
+ NPM_BIN="$(npm bin -g 2>/dev/null || dirname "$(which npm)")"
731
+
732
+ log "MAJ overmind-mcp..."
733
+ npm install -g overmind-mcp@latest 2>/dev/null && ok "overmind-mcp mis à jour" || ok "overmind-mcp déjà à jour"
734
+
735
+ log "MAJ overmind-postgres-mcp..."
736
+ npm install -g overmind-postgres-mcp@latest 2>/dev/null && ok "overmind-postgres-mcp mis à jour" || ok "overmind-postgres-mcp déjà à jour"
737
+
738
+ # Vérifier les versions installées
739
+ OM_VER="$(npm list -g overmind-mcp --depth=0 2>/dev/null | grep 'overmind-mcp@' | awk -F@ '{print $NF}' || echo '?')"
740
+ PGM_VER="$(npm list -g overmind-postgres-mcp --depth=0 2>/dev/null | grep 'overmind-postgres-mcp@' | awk -F@ '{print $NF}' || echo '?')"
741
+ ok "overmind-mcp: v${OM_VER}"
742
+ ok "overmind-postgres-mcp: v${PGM_VER}"
743
+
744
+ # ================================================================
745
+ # STEP 10/11 — Audit arborescence agents (~/.overmind/hermes/profiles/)
746
+ # ================================================================
747
+ step "Audit arborescence agents"
748
+
749
+ PROFILES_DIR="$OM_DIR/hermes/profiles"
750
+
751
+ if [ ! -d "$PROFILES_DIR" ]; then
752
+ warn "Dossier profiles/ absent — aucun agent configuré"
753
+ log "Création de la structure canonique..."
754
+ mkdir -p "$PROFILES_DIR" "$OM_DIR/hermes/distributions" "$OM_DIR/bridge/wrappers" 2>/dev/null || true
755
+ ok "Structure ~/.overmind/hermes/ créée"
756
+ else
757
+ ok "Dossier profiles/ trouvé"
758
+ fi
759
+
760
+ # Lister les profils existants
761
+ PROFILE_COUNT=0
762
+ if [ -d "$PROFILES_DIR" ]; then
763
+ PROFILE_COUNT=$(find "$PROFILES_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')
764
+ fi
765
+
766
+ if [ "$PROFILE_COUNT" -eq 0 ]; then
767
+ warn "Aucun profil agent dans ~/.overmind/hermes/profiles/"
768
+ log "Créez un agent avec: overmind create-agent --name <name> --prompt '...' --runner hermes"
769
+ else
770
+ log "Audit de $PROFILE_COUNT profil(s)..."
771
+ echo
772
+
773
+ # Pour chaque profil, vérifier les fichiers requis
774
+ for profile_path in "$PROFILES_DIR"/*/; do
775
+ [ -d "$profile_path" ] || continue
776
+ pname=$(basename "$profile_path")
777
+ echo -e " ${C}▸ ${pname}${N}"
778
+
779
+ # Fichiers requis (v3.1)
780
+ PROFILE_OK=true
781
+
782
+ # config.yaml (OBLIGATOIRE)
783
+ if [ -f "${profile_path}config.yaml" ]; then
784
+ ok "${pname}/config.yaml"
785
+ else
786
+ fail "${pname}/config.yaml MANQUANT"
787
+ PROFILE_OK=false
788
+ fi
789
+
790
+ # SOUL.md (prompt système)
791
+ if [ -f "${profile_path}SOUL.md" ]; then
792
+ SOUL_SIZE=$(wc -c < "${profile_path}SOUL.md" 2>/dev/null | tr -d ' ')
793
+ if [ "$SOUL_SIZE" -lt 50 ]; then
794
+ track_warn "${pname}/SOUL.md trop petit (${SOUL_SIZE} bytes)"
795
+ else
796
+ ok "${pname}/SOUL.md (${SOUL_SIZE} bytes)"
797
+ fi
798
+ else
799
+ track_warn "${pname}/SOUL.md MANQUANT — l'agent n'a pas de prompt système"
800
+ fi
801
+
802
+ # .env (secrets du profil)
803
+ if [ -f "${profile_path}.env" ]; then
804
+ ok "${pname}/.env"
805
+ else
806
+ track_warn "${pname}/.env MANQUANT — clés LLM manquantes"
807
+ fi
808
+
809
+ # profile.yaml (kanban — OBLIGATOIRE v3.1)
810
+ if [ -f "${profile_path}profile.yaml" ]; then
811
+ ok "${pname}/profile.yaml"
812
+ else
813
+ track_warn "${pname}/profile.yaml MANQUANT — kanban router sera aveugle"
814
+ fi
815
+
816
+ # workspace.yaml
817
+ if [ -f "${profile_path}workspace.yaml" ]; then
818
+ ok "${pname}/workspace.yaml"
819
+ else
820
+ track_warn "${pname}/workspace.yaml MANQUANT — workspace kind inconnu"
821
+ fi
822
+
823
+ # state.db (sessions)
824
+ if [ -f "${profile_path}state.db" ]; then
825
+ ok "${pname}/state.db (sessions)"
826
+ else
827
+ log "${D} ${pname}/state.db non créé (sera créé au premier run)${N}"
828
+ fi
829
+
830
+ # .mcp.json (MCP servers override)
831
+ if [ -f "${profile_path}.mcp.json" ]; then
832
+ ok "${pname}/.mcp.json (MCP override)"
833
+ else
834
+ log "${D} ${pname}/.mcp.json absent (utilisera le global)${N}"
835
+ fi
836
+
837
+ # skills/ (optionnel)
838
+ if [ -d "${profile_path}skills" ]; then
839
+ SKILL_COUNT=$(find "${profile_path}skills" -name "SKILL.md" 2>/dev/null | wc -l | tr -d ' ')
840
+ if [ "$SKILL_COUNT" -gt 0 ]; then
841
+ ok "${pname}/skills/ (${SKILL_COUNT} skill(s))"
842
+ fi
843
+ fi
844
+
845
+ # memories/ (optionnel)
846
+ if [ -f "${profile_path}memories/MEMORY.md" ]; then
847
+ ok "${pname}/memories/MEMORY.md"
848
+ fi
849
+
850
+ # auth.json (cache credentials — vérifier pas stale)
851
+ if [ -f "${profile_path}auth.json" ]; then
852
+ AUTH_AGE=$(($(date +%s) - $(stat -f %m "${profile_path}auth.json" 2>/dev/null || stat -c %Y "${profile_path}auth.json" 2>/dev/null || echo 0)))
853
+ if [ "$AUTH_AGE" -gt 604800 ]; then
854
+ track_warn "${pname}/auth.json stale (${AUTH_AGE}s — >7j). Peut causer des 401/429."
855
+ else
856
+ ok "${pname}/auth.json (récent)"
857
+ fi
858
+ fi
859
+
860
+ echo
861
+ done
862
+ fi
863
+
864
+ # Vérifier la structure globale ~/.overmind/
865
+ echo -e " ${C}Structure globale:${N}"
866
+ for check_dir in "bridge" "logs" "hermes/profiles" "hermes/distributions"; do
867
+ if [ -d "$OM_DIR/$check_dir" ]; then
868
+ ok "~/.overmind/${check_dir}/"
869
+ else
870
+ track_warn "~/.overmind/${check_dir}/ MANQUANT"
871
+ mkdir -p "$OM_DIR/$check_dir" 2>/dev/null || true
872
+ fi
873
+ done
874
+
875
+ # Vérifier les symlinks cassés (runs/, agents/ legacy)
876
+ for legacy_link in "hermes/runs" "hermes/agents" "hermes/sessions"; do
877
+ if [ -L "$OM_DIR/$legacy_link" ]; then
878
+ if [ ! -e "$OM_DIR/$legacy_link" ]; then
879
+ track_warn "Symlink cassé: ~/.overmind/${legacy_link} → suppression"
880
+ rm -f "$OM_DIR/$legacy_link" 2>/dev/null || true
881
+ else
882
+ ok "Symlink legacy: ~/.overmind/${legacy_link} → OK"
883
+ fi
884
+ fi
885
+ done
886
+
887
+ # Vérifier bridge/agents.json (sessions runtime)
888
+ if [ -f "$OM_DIR/bridge/agents.json" ]; then
889
+ SESSION_COUNT=$(grep -c '"id"' "$OM_DIR/bridge/agents.json" 2>/dev/null || echo 0)
890
+ ok "bridge/agents.json (${SESSION_COUNT} session(s))"
891
+ else
892
+ log "${D}bridge/agents.json absent (créé au premier run)${N}"
893
+ fi
894
+
895
+ # Vérifier .mcp.json global
896
+ if [ -f "$OM_DIR/.mcp.json" ]; then
897
+ MCP_SERVERS=$(grep -c '"transport"' "$OM_DIR/.mcp.json" 2>/dev/null || echo 0)
898
+ ok ".mcp.json global (${MCP_SERVERS} serveur(s) MCP)"
899
+ else
900
+ track_warn ".mcp.json global MANQUANT"
901
+ fi
902
+
903
+ ok "Audit arborescence terminé"
904
+
905
+ # ================================================================
906
+ # STEP 11/11 — Validation finale
523
907
  # ================================================================
524
908
  step "Validation finale"
525
909
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overmind-mcp",
3
- "version": "3.2.4",
3
+ "version": "3.2.6",
4
4
  "description": "Orchestrateur universel agents IA multi-modeles via MCP. Inclut le protocole 'Custom-Nickname' pour identifier vos agents avec des surnoms originaux (The Chaos Prophet, Shadow Sniper, etc.), l'isolation mémoire (Private Memory Context) et le support pour QwenCli et Nous Hermes. Installation automatique des dépendances Docker (PostgreSQL, pgvector) inclus.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,9 +43,10 @@ function logSection(title) {
43
43
 
44
44
  function runCommand(cmd, options = {}) {
45
45
  try {
46
- return execSync(cmd, { stdio: 'inherit', ...options });
47
- } catch (error) {
48
- return null;
46
+ const result = execSync(cmd, { stdio: 'pipe', encoding: 'utf8', ...options });
47
+ return typeof result === 'string' ? result : String(result ?? '');
48
+ } catch {
49
+ return '';
49
50
  }
50
51
  }
51
52
 
@@ -82,8 +83,14 @@ function commandUp() {
82
83
  const pgDb = getEnvVar('POSTGRES_DATABASE') || getEnvVar('POSTGRES_DB') || 'overmind_memory';
83
84
  const pgPort = getEnvVar('POSTGRES_PORT') || '5432';
84
85
 
85
- // Remove ancien container stopped
86
- runCommand('docker rm -f overmind-postgres-pgvector 2>/dev/null', { stdio: 'pipe' });
86
+ // Remove ancien container SEULEMENT s'il est stopped (jamais un running)
87
+ const isRunning = runCommand('docker ps --filter "name=overmind-postgres-pgvector" --format "{{.Names}}"', { stdio: 'pipe' });
88
+ if (!isRunning || isRunning.trim().length === 0) {
89
+ const isStopped = runCommand('docker ps -a --filter "name=overmind-postgres-pgvector" --filter "status=exited" --format "{{.Names}}"', { stdio: 'pipe' });
90
+ if (isStopped && isStopped.trim().length > 0) {
91
+ runCommand('docker rm -f overmind-postgres-pgvector 2>/dev/null', { stdio: 'pipe' });
92
+ }
93
+ }
87
94
 
88
95
  console.log('🚀 Démarrage PostgreSQL + pgvector...');
89
96
  const result = runCommand(
@@ -197,8 +197,11 @@ async function setupPostgreSQL() {
197
197
  'Téléchargement image'
198
198
  );
199
199
 
200
- // Remove existing if stopped
201
- runCommand('docker rm -f overmind-postgres-pgvector', { stdio: 'pipe' });
200
+ // Remove existing ONLY if stopped (never kill a running container)
201
+ const existingStopped = runCommand('docker ps -a --filter "name=overmind-postgres-pgvector" --filter "status=exited" --format "{{.Names}}"', { stdio: 'pipe' });
202
+ if (existingStopped) {
203
+ runCommand('docker rm -f overmind-postgres-pgvector', { stdio: 'pipe' });
204
+ }
202
205
 
203
206
  const runCmd = [
204
207
  'docker', 'run', '-d',