#!/bin/bash # Centralized Logging Configuration (Bug #18) export LOG_LEVEL=${LOG_LEVEL:-"info"} export LOG_FILE=${LOG_FILE:-"/app/verdant_claw.log"} # Mask sensitive env vars in logs (Bug #13) log() { local msg=$(echo "$1" | sed -E 's/(nvapi|sk|gsk)[a-zA-Z0-9]+/\1*****/g') echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] [$LOG_LEVEL] $msg" | tee -a $LOG_FILE } # Trap SIGTERM for graceful shutdown (Bug #12) cleanup() { log "Shutting down services gracefully..." kill $(jobs -p) 2>/dev/null sleep 2 log "Shutdown complete" exit 0 } trap cleanup SIGTERM SIGINT # Parse API_KEYS_JSON secret (Bug #9) # Supports multi-key rotation: "nvidia_2" → NVIDIA_API_KEY_2 if [ -n "$API_KEYS_JSON" ]; then log "Parsing API keys from JSON..." # Primary keys export NVIDIA_API_KEY=$(echo $API_KEYS_JSON | jq -r '.nvidia // empty') export OPENAI_API_KEY=$(echo $API_KEYS_JSON | jq -r '.openai // empty') export ANTHROPIC_API_KEY=$(echo $API_KEYS_JSON | jq -r '.anthropic // empty') export GOOGLE_API_KEY=$(echo $API_KEYS_JSON | jq -r '.google // empty') export GROQ_API_KEY=$(echo $API_KEYS_JSON | jq -r '.groq // empty') # Rotation keys (nvidia_2, openai_2, etc.) for provider in nvidia openai anthropic google groq; do for i in $(seq 2 5); do val=$(echo $API_KEYS_JSON | jq -r ".${provider}_${i} // empty") if [ -n "$val" ] && [ "$val" != "null" ]; then envname=$(echo "${provider}_API_KEY_${i}" | tr '[:lower:]' '[:upper:]') export "$envname=$val" log "✓ Loaded rotation key: $envname" fi done done log "✓ API keys loaded from JSON" else log "⚠️ WARNING: API_KEYS_JSON not set!" fi # Function to start service with retry (Bug #15) start_with_retry() { local name=$1 local cmd=$2 local max_attempts=3 for i in $(seq 1 $max_attempts); do log "Starting $name (attempt $i/$max_attempts)..." $cmd & local pid=$! sleep 5 if ps -p $pid > /dev/null; then log "✓ $name started (PID: $pid)" return 0 fi log "⚠️ $name failed to start, retrying..." done log "❌ ERROR: $name failed after $max_attempts attempts" return 1 } # Check if ports are available (Bug #4) check_port() { local port=$1 if netstat -tlnp 2>/dev/null | grep -q ":$port"; then log "❌ ERROR: Port $port already in use!" return 1 fi return 0 } log "Verifying infrastructure ports..." for port in 7860 7861 7687 20128; do check_port $port || exit 1 done # 🚀 Start Services start_with_retry "Memgraph" "memgraph --bolt-port 7687" || exit 1 start_with_retry "OmniRoute" "node /app/scripts/omniroute.js --config /app/config/omniroute-masterfile.json --port 20128" || exit 1 start_with_retry "Graph Viewer" "node /app/scripts/graph-viewer.js" || exit 1 log "All infrastructure ready! Launching Pi Root Agent..." # Start Pi Agent (as main process) cd /app/mom-infra npm run pi -- --port 7860 --extensions /app/agent-pi/pi-extensions --skills /app/agent-pi/skills --prompts /app/agent-pi/commands