#!/usr/bin/env node
import fs from 'fs';
import path from 'path';
import http from 'http';
import { fileURLToPath } from 'url';
import { PassThrough } from 'stream';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Initialize OVERMIND_WORKSPACE to project directory to prevent global .env overrides
process.env.OVERMIND_WORKSPACE = process.env.OVERMIND_WORKSPACE || path.resolve(__dirname, '../..');
function loadEnvQuietly(envPath) {
    try {
        if (fs.existsSync(envPath)) {
            const content = fs.readFileSync(envPath, 'utf8');
            content.split('\n').forEach((line) => {
                const trimmed = line.trim();
                // Skip empty lines and full comment lines
                if (!trimmed || trimmed.startsWith('#'))
                    return;
                // Parse KEY=VALUE (value can contain '=')
                const eqIdx = trimmed.indexOf('=');
                if (eqIdx === -1)
                    return;
                const key = trimmed.slice(0, eqIdx).trim();
                if (!key)
                    return;
                let value = trimmed.slice(eqIdx + 1).trim();
                // Strip trailing comments only when preceded by whitespace (not in quoted values)
                // e.g. FOO=hello # comment  → strips "# comment"
                //      BAR=http://foo.com#fragment → preserves "#fragment"
                if (!value.startsWith('"') && !value.startsWith("'")) {
                    value = value.replace(/\s+#.*$/, '').trim();
                }
                // Strip quotes
                if (value.startsWith('"') && value.endsWith('"'))
                    value = value.slice(1, -1);
                else if (value.startsWith("'") && value.endsWith("'"))
                    value = value.slice(1, -1);
                if (!process.env[key])
                    process.env[key] = value;
            });
        }
    }
    catch (_e) {
        // Ignore silently
    }
}
// Atomic write: write to temp file first, then rename (atomic on POSIX, prevents corruption on crash)
function atomicWriteFile(filePath, content) {
    const tmp = filePath + '.tmp.' + Math.random().toString(36).slice(2);
    fs.writeFileSync(tmp, content, 'utf8');
    fs.renameSync(tmp, filePath);
}
// Auto-formatteur de .env — Classifie tous les providers connus, préserve les valeurs
function autoFormatEnvFile(envPath) {
    try {
        if (!fs.existsSync(envPath))
            return;
        const content = fs.readFileSync(envPath, 'utf8');
        // Parser robuste : ignore commentaires, lit les lignes KEY=VALUE (valeur peut contenir '=')
        const envVars = {};
        for (const line of content.split('\n')) {
            const trimmed = line.trim();
            if (!trimmed || trimmed.startsWith('#'))
                continue;
            const eqIdx = trimmed.indexOf('=');
            if (eqIdx === -1)
                continue;
            const key = trimmed.slice(0, eqIdx).trim();
            const value = trimmed.slice(eqIdx + 1).trim();
            if (key)
                envVars[key] = value;
        }
        if (Object.keys(envVars).length === 0)
            return;
        const usedKeys = new Set();
        // Tri naturel pour les clés avec suffixes numériques (KEY, KEY_2, KEY_3…)
        function naturalSort(pairs) {
            return pairs.sort((a, b) => a[0].localeCompare(b[0], undefined, { numeric: true, sensitivity: 'base' }));
        }
        function extract(prefix, exactMatch = false) {
            const res = [];
            const prefixes = Array.isArray(prefix) ? prefix : [prefix];
            for (const key of Object.keys(envVars)) {
                if (usedKeys.has(key))
                    continue;
                const matches = exactMatch
                    ? prefixes.includes(key)
                    : prefixes.some((p) => key.startsWith(p));
                if (matches) {
                    res.push([key, envVars[key]]);
                    usedKeys.add(key);
                }
            }
            return naturalSort(res);
        }
        // ─── SECTIONS ──────────────────────────────────────────────────────────────
        const sections = [
            // ── Overmind Infrastructure ──
            {
                title: '🌐 OVERMIND CORE & INFRASTRUCTURE',
                vars: extract(['OVERMIND_WORKSPACE', 'OVERMIND_MEMORY_TYPE'], true),
            },
            { title: '⚙️  GLOBAL SETTINGS', vars: extract(['API_TIMEOUT_MS'], true) },
            { title: '🗄️  DATABASE (PostgreSQL / pgvector)', vars: extract('POSTGRES_') },
            { title: '🧠 EMBEDDINGS & VECTOR MEMORY', vars: extract('OVERMIND_EMBEDDING_') },
            // ── LLM Providers (Europe / USA) ──
            { title: '🤖 LLM PROVIDER - Mistral AI 🇫🇷', vars: extract('MISTRAL_') },
            { title: '🤖 LLM PROVIDER - OpenAI 🇺🇸', vars: extract('OPENAI_') },
            { title: '🤖 LLM PROVIDER - Anthropic 🇺🇸', vars: extract('ANTHROPIC_') },
            {
                title: '🤖 LLM PROVIDER - Google Gemini 🇺🇸',
                vars: extract(['GEMINI_API_KEY', 'GEMINI_MODEL', 'GOOGLE_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY'], true),
            },
            {
                title: '🤖 LLM PROVIDER - NVIDIA NIM 🇺🇸',
                vars: [
                    ...extract(['NVAPI_KEY', 'NVIDIA_API_KEY', 'NVIDIA_API_BASE'], true),
                    ...extract('NVIDIA_'),
                ],
            },
            {
                title: '🤖 LLM PROVIDER - OpenRouter 🇺🇸',
                vars: extract(['OPENROUTER_API_KEY', 'OPENROUTER_BASE_URL', 'OPENROUTER_MODEL'], true),
            },
            {
                title: '🤖 LLM PROVIDER - xAI / Grok 🇺🇸',
                vars: extract(['XAI_API_KEY', 'XAI_BASE_URL', 'GROK_API_KEY', 'GROK_MODEL'], true),
            },
            { title: '🤖 LLM PROVIDER - Groq 🇺🇸', vars: extract('GROQ_') },
            { title: '🤖 LLM PROVIDER - Together AI 🇺🇸', vars: extract('TOGETHER_') },
            { title: '🤖 LLM PROVIDER - Cohere 🇺🇸', vars: extract('COHERE_') },
            { title: '🤖 LLM PROVIDER - Replicate 🇺🇸', vars: extract('REPLICATE_') },
            {
                title: '🤖 LLM PROVIDER - HuggingFace 🇺🇸',
                vars: extract(['HUGGINGFACE_API_KEY', 'HF_TOKEN', 'HUGGING_FACE_HUB_TOKEN'], true),
            },
            { title: '🤖 LLM PROVIDER - Perplexity 🇺🇸', vars: extract('PERPLEXITY_') },
            { title: '🤖 LLM PROVIDER - SambaNova 🇺🇸', vars: extract('SAMBANOVA_') },
            {
                title: '🤖 LLM PROVIDER - Azure OpenAI ☁️',
                vars: extract([
                    'AZURE_API_KEY',
                    'AZURE_API_BASE',
                    'AZURE_OPENAI_API_KEY',
                    'AZURE_OPENAI_ENDPOINT',
                    'AZURE_OPENAI_API_VERSION',
                ], true),
            },
            {
                title: '🤖 LLM PROVIDER - ElevenLabs 🎙️',
                vars: extract(['ELEVENLABS_API_KEY', 'ELEVENLABS_VOICE_ID', 'ELEVENLABS_MODEL_ID'], true),
            },
            {
                title: '🤖 LLM PROVIDER - AWS Bedrock ☁️',
                vars: extract([
                    'AWS_ACCESS_KEY_ID',
                    'AWS_SECRET_ACCESS_KEY',
                    'AWS_SESSION_TOKEN',
                    'AWS_REGION',
                    'AWS_DEFAULT_REGION',
                    'AWS_ENDPOINT_URL',
                ], true),
            },
            // ── LLM Providers (Chine / Asie) ──
            { title: '🤖 LLM PROVIDER - DeepSeek 🇨🇳', vars: extract('DEEPSEEK_') },
            { title: '🤖 LLM PROVIDER - Alibaba DashScope 🇨🇳', vars: extract('ALIBABA_') },
            {
                title: '🤖 LLM PROVIDER - Qwen (DashScope) 🇨🇳',
                vars: extract([
                    'QWEN_API_KEY',
                    'QWEN_BASE_URL',
                    'QWEN_MODEL',
                    'DASHSCOPE_API_KEY',
                    'DASHSCOPE_BASE_URL',
                ], true),
            },
            { title: '🤖 LLM PROVIDER - SiliconFlow 🇨🇳', vars: extract('SILICONFLOW_') },
            {
                title: '🤖 LLM PROVIDER - Minimax 🇨🇳',
                vars: [...extract('MINIMAXI_'), ...extract('MINIMAX_')],
            },
            { title: '🤖 LLM PROVIDER - Ilmu AI / Z.AI 🇨🇳', vars: extract('Z_AI_') },
            {
                title: '🤖 LLM PROVIDER - Moonshot / Kimi 🇨🇳',
                vars: extract(['MOONSHOT_API_KEY', 'MOONSHOT_BASE_URL', 'MOONSHOT_MODEL', 'KIMI_API_KEY'], true),
            },
            {
                title: '🤖 LLM PROVIDER - Baidu / ERNIE 🇨🇳',
                vars: extract(['BAIDU_API_KEY', 'ERNIE_API_KEY', 'WENXIN_API_KEY'], true),
            },
            {
                title: '🤖 LLM PROVIDER - ZhipuAI / GLM 🇨🇳',
                vars: [...extract(['ZHIPU_API_KEY', 'GLM_API_KEY'], true), ...extract('ZHIPUAI_')],
            },
            // ── Services & Intégrations ──
            {
                title: '💬 SERVICE - Discord',
                vars: extract([
                    'DISCORD_TOKEN',
                    'DISCORD_BOT_TOKEN',
                    'DISCORD_CHANNEL_ID',
                    'DISCORD_GUILD_ID',
                    'DISCORD_WEBHOOK_URL',
                    'DISCORD_CLIENT_ID',
                    'DISCORD_CLIENT_SECRET',
                ], true),
            },
            {
                title: '🐦 SERVICE - Twitter / X',
                vars: extract([
                    'TWITTER_API_KEY',
                    'TWITTER_API_SECRET',
                    'TWITTER_ACCESS_TOKEN',
                    'TWITTER_ACCESS_SECRET',
                    'TWITTER_BEARER_TOKEN',
                    'X_API_KEY',
                    'X_BEARER_TOKEN',
                    'X_API_SECRET',
                    'X_ACCESS_TOKEN',
                    'X_ACCESS_SECRET',
                ], true),
            },
            {
                title: '📱 SERVICE - Telegram',
                vars: extract(['TELEGRAM_BOT_TOKEN', 'TELEGRAM_CHAT_ID'], true),
            },
            {
                title: '📱 SERVICE - Twilio / SMS',
                vars: extract([
                    'TWILIO_ACCOUNT_SID',
                    'TWILIO_AUTH_TOKEN',
                    'TWILIO_PHONE_NUMBER',
                    'TWILIO_API_KEY',
                    'TWILIO_API_SECRET',
                ], true),
            },
            {
                title: '🐙 SERVICE - GitHub',
                vars: extract([
                    'GITHUB_TOKEN',
                    'GITHUB_API_KEY',
                    'GH_TOKEN',
                    'GITHUB_CLIENT_ID',
                    'GITHUB_CLIENT_SECRET',
                ], true),
            },
            {
                title: '▲ SERVICE - Vercel',
                vars: extract([
                    'VERCEL_TOKEN',
                    'VERCEL_API_TOKEN',
                    'VERCEL_PROJECT_ID',
                    'VERCEL_ORG_ID',
                    'VERCEL_TEAM_ID',
                ], true),
            },
            {
                title: '🔺 SERVICE - Supabase',
                vars: extract(['SUPABASE_URL', 'SUPABASE_ANON_KEY', 'SUPABASE_SERVICE_ROLE_KEY', 'SUPABASE_JWT_SECRET'], true),
            },
            { title: '🎮 SERVICE - Riot Games', vars: extract(['RIOT_API_KEY', 'RIOT_REGION'], true) },
            {
                title: '🔍 SERVICE - Search (Serper/Tavily)',
                vars: extract(['SERPER_API_KEY', 'TAVILY_API_KEY', 'SERPAPI_KEY', 'BRAVE_SEARCH_API_KEY'], true),
            },
            {
                title: '📰 SERVICE - Market Data & News',
                vars: extract([
                    'FINNHUB_API_KEY',
                    'NEWSAPI_KEY',
                    'ALPHAVANTAGE_API_KEY',
                    'POLYGON_API_KEY',
                    'TIINGO_API_KEY',
                ], true),
            },
        ];
        // Clés restantes non classifiées → section fourre-tout
        const uncategorized = [];
        for (const key of Object.keys(envVars)) {
            if (!usedKeys.has(key))
                uncategorized.push([key, envVars[key]]);
        }
        if (uncategorized.length > 0) {
            sections.push({ title: '📁 AUTRES / NON-CLASSIFIÉS', vars: naturalSort(uncategorized) });
        }
        // ─── RENDU ──────────────────────────────────────────────────────────────────
        let newContent = '';
        for (const section of sections) {
            if (section.vars.length > 0) {
                newContent += `# ==========================================\n`;
                newContent += `# ${section.title}\n`;
                newContent += `# ==========================================\n`;
                for (const [k, v] of section.vars) {
                    newContent += `${k}=${v}\n`;
                }
                newContent += `\n`;
            }
        }
        // N'écrire sur le disque que si quelque chose a changé (optimisation I/O)
        if (content.trim() !== newContent.trim()) {
            atomicWriteFile(envPath, newContent.trim() + '\n');
        }
    }
    catch (_e) {
        // Ignorer silencieusement pour ne pas crasher le boot
    }
}
const localEnvPath = path.resolve(__dirname, '../../.env');
// Auto-détection et injection de OVERMIND_WORKSPACE s'il est manquant — NE PAS écraser s'il existe déjà
try {
    if (!fs.existsSync(localEnvPath)) {
        const workspacePath = path.resolve(__dirname, '../../');
        atomicWriteFile(localEnvPath, `OVERMIND_WORKSPACE=${workspacePath}\n`);
    }
    else {
        const currentContent = fs.readFileSync(localEnvPath, 'utf8');
        const match = currentContent.match(/^OVERMIND_WORKSPACE=(.*)$/m);
        if (!match || !match[1]?.trim()) {
            const workspacePath = path.resolve(__dirname, '../../');
            if (!currentContent.includes('OVERMIND_WORKSPACE=')) {
                atomicWriteFile(localEnvPath, currentContent.trim() + `\nOVERMIND_WORKSPACE=${workspacePath}\n`);
            }
            else {
                const newContent = currentContent.replace(/^OVERMIND_WORKSPACE=.*$/m, `OVERMIND_WORKSPACE=${workspacePath}`);
                atomicWriteFile(localEnvPath, newContent);
            }
        }
    }
}
catch (_e) {
    // Ignorer l'erreur silencieusement
}
// Classifie et réorganise automatiquement le .env à chaque démarrage d'Overmind
autoFormatEnvFile(localEnvPath);
// 🎯 Priorité de chargement (premier trouvé gagne, car loadEnvQuietly ne réécrit pas) :
//   1) $OVERMIND_ENV_FILE         → fichier explicite passé par le client MCP
//   2) <process.cwd()>/.env       → si lancé depuis un dossier projet
//   3) <bin>/../../.env           → fallback historique (utile en dev local)
const externalEnvCandidates = [];
if (process.env.OVERMIND_ENV_FILE)
    externalEnvCandidates.push(process.env.OVERMIND_ENV_FILE);
const cwdEnv = path.resolve(process.cwd(), '.env');
if (cwdEnv !== localEnvPath)
    externalEnvCandidates.push(cwdEnv);
for (const candidate of externalEnvCandidates) {
    loadEnvQuietly(candidate);
}
// Load OverMind's specific environment variables
loadEnvQuietly(localEnvPath);
// Inherit PostgreSQL Server environment variables (Database credentials, Embeddings)
loadEnvQuietly(path.resolve(__dirname, '../../../serveur_PostGreSQL/.env'));
// 🔍 Vérification des configurations critiques
function checkMissingConfigs() {
    const missingCore = [];
    const missingDb = [];
    // Vérification CORE
    if (!process.env.OVERMIND_WORKSPACE)
        missingCore.push('OVERMIND_WORKSPACE');
    if (!process.env.OVERMIND_MEMORY_TYPE)
        missingCore.push('OVERMIND_MEMORY_TYPE');
    // Vérification DB
    if (!process.env.POSTGRES_HOST)
        missingDb.push('POSTGRES_HOST');
    if (!process.env.POSTGRES_DATABASE)
        missingDb.push('POSTGRES_DATABASE');
    if (!process.env.POSTGRES_USER)
        missingDb.push('POSTGRES_USER');
    if (!process.env.POSTGRES_PASSWORD)
        missingDb.push('POSTGRES_PASSWORD');
    if (missingCore.length > 0) {
        console.error(`\n[Overmind] ⚠️ ATTENTION : Configuration 'CORE & INFRASTRUCTURE' incomplète !`);
        console.error(`[Overmind] ❌ Il manque : ${missingCore.join(', ')}\n`);
    }
    if (missingDb.length > 0) {
        console.error(`\n[Overmind] ⚠️ ATTENTION : Configuration 'DATABASE' incomplète (Imported from postgresql-server) !`);
        console.error(`[Overmind] ❌ Il manque : ${missingDb.join(', ')}\n`);
    }
}
checkMissingConfigs();
import { rootLogger } from '../lib/logger.js';
// 💥 ERROR HANDLING: Catch everything to avoid silent EOFs
process.on('uncaughtException', (err) => {
    rootLogger.fatal({ err }, '💥 UNCAUGHT EXCEPTION');
    rootLogger.flush();
    process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
    rootLogger.fatal({ reason, promise }, '💥 UNHANDLED REJECTION');
    rootLogger.flush();
});
// Ensure logs are flushed on exit
process.on('SIGINT', () => {
    rootLogger.info('🛑 Received SIGINT, flushing logs...');
    rootLogger.flush();
    process.exit(0);
});
process.on('SIGTERM', () => {
    rootLogger.info('🛑 Received SIGTERM, flushing logs...');
    rootLogger.flush();
    process.exit(0);
});
// 🛡️ SHIELD: Prevent any library from logging to stdout during initialization
// This is critical for MCP servers because any non-JSON output on stdout kills the handshake (EOF).
console.log = (...args) => rootLogger.info(args.length > 1 ? { args } : args[0]);
console.info = (...args) => rootLogger.info(args.length > 1 ? { args } : args[0]);
console.warn = (...args) => rootLogger.warn(args.length > 1 ? { args } : args[0]);
console.error = (...args) => rootLogger.error(args.length > 1 ? { args } : args[0]);
// 🛡️ ULTIMATE SHIELD: Proxy process.stdout.write to redirect non-JSON data to stderr
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
process.stdout.write = function (chunk, encoding, callback) {
    const str = typeof chunk === 'string' ? chunk : chunk.toString();
    const trimmed = str.trim();
    // Handle overload: if encoding is a function, it's actually the callback
    if (typeof encoding === 'function') {
        callback = encoding;
        encoding = undefined;
    }
    // Skip empty chunks or pure whitespace (often used as delimiters/keep-alive)
    if (trimmed === '') {
        return originalStdoutWrite(chunk, encoding, callback);
    }
    // Allow JSON-RPC (starts with { or [)
    if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
        try {
            const parsed = JSON.parse(trimmed);
            // BLOCK ARRAYS on stdout (Batch responses are not standard in MCP)
            if (Array.isArray(parsed)) {
                rootLogger.warn({ raw: str }, '🛡️ [SHIELD] Blocked array-as-JSON-RPC on stdout');
                return process.stderr.write(chunk, encoding, callback);
            }
            // Check for JSON-RPC (Response or Notification)
            if (parsed.jsonrpc === '2.0') {
                return originalStdoutWrite(chunk, encoding, callback);
            }
            // Block non-RPC JSON
            rootLogger.warn({ raw: str }, '🛡️ [SHIELD] Blocked non-JSON-RPC (Object) on stdout');
            return process.stderr.write(chunk, encoding, callback);
        }
        catch (e) {
            // Malformed JSON-like content
            rootLogger.debug({ raw: str, err: e.message }, '🛡️ [SHIELD] Blocked malformed JSON-like content on stdout');
            return process.stderr.write(chunk, encoding, callback);
        }
    }
    // Redirect everything else to stderr (via Pino)
    rootLogger.debug({ raw: trimmed }, '🛡️ [SHIELD] Intercepted non-JSON stdout write');
    return process.stderr.write(chunk, encoding, callback);
};
// 🛡️ STDIN INTERCEPTOR: Detect and unroll JSON-RPC Batches [req1, req2]
// FastMCP/Zod only support single objects. Intercepting before FastMCP starts.
const originalStdin = process.stdin;
const stdinProxy = new PassThrough();
originalStdin.on('data', (chunk) => {
    const str = chunk.toString();
    const trimmed = str.trim();
    // 🔍 [DEBUG] Log every incoming chunk that looks like JSON
    if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
        rootLogger.debug({
            length: trimmed.length,
            preview: trimmed.substring(0, 100),
            isBatch: trimmed.startsWith('['),
        }, '[SHIELD] STDIN chunk received');
    }
    // If it's a batch, unroll it into separate JSON chunks
    if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
        try {
            const parsed = JSON.parse(trimmed);
            if (Array.isArray(parsed)) {
                rootLogger.warn({ count: parsed.length }, '[SHIELD] Unrolling JSON-RPC BATCH on STDIN');
                for (const item of parsed) {
                    stdinProxy.write(JSON.stringify(item) + '\n');
                }
                return;
            }
        }
        catch (_e) {
            // Not a valid batch or partial JSON, pass through as-is
        }
    }
    stdinProxy.write(chunk);
});
// Hijack process.stdin for FastMCP and any other consumers
Object.defineProperty(process, 'stdin', {
    value: stdinProxy,
    writable: false,
    configurable: true,
});
// Setup completed - Dynamically import server components AFTER process.env is configured
const { initTelemetry } = await import('../lib/telemetry.js');
initTelemetry();
const { createServer } = await import('../server.js');
const { updateConfig } = await import('../lib/config.js');
const cliArgs = process.argv.slice(2);
let settingsPath, mcpPath;
let memoryOnly = false;
let memoryToolsOnly = false;
let sslCert;
let sslKey;
let sslCa;
let transportType = 'stdio';
let httpPort = 3099;
let httpHost = 'localhost';
let httpEndpoint = '/mcp';
for (let i = 0; i < cliArgs.length; i++) {
    if (cliArgs[i] === '--settings' && cliArgs[i + 1]) {
        settingsPath = cliArgs[i + 1];
        i++;
    }
    else if (cliArgs[i] === '--mcp-config' && cliArgs[i + 1]) {
        mcpPath = cliArgs[i + 1];
        i++;
    }
    else if (cliArgs[i] === '--memory-only') {
        memoryOnly = true;
    }
    else if (cliArgs[i] === '--memory-tools-only') {
        memoryToolsOnly = true;
    }
    else if (cliArgs[i] === '--transport' && cliArgs[i + 1]) {
        const t = cliArgs[i + 1];
        if (t === 'http-stream' || t === 'httpStream') {
            transportType = 'httpStream';
        }
        i++;
    }
    else if (cliArgs[i] === '--port' && cliArgs[i + 1]) {
        httpPort = parseInt(cliArgs[i + 1], 10);
        i++;
    }
    else if (cliArgs[i] === '--host' && cliArgs[i + 1]) {
        httpHost = cliArgs[i + 1];
        i++;
    }
    else if (cliArgs[i] === '--endpoint' && cliArgs[i + 1]) {
        httpEndpoint = cliArgs[i + 1];
        i++;
    }
    else if (cliArgs[i] === '--ssl-cert' && cliArgs[i + 1]) {
        sslCert = cliArgs[i + 1];
        i++;
    }
    else if (cliArgs[i] === '--ssl-key' && cliArgs[i + 1]) {
        sslKey = cliArgs[i + 1];
        i++;
    }
    else if (cliArgs[i] === '--ssl-ca' && cliArgs[i + 1]) {
        sslCa = cliArgs[i + 1];
        i++;
    }
}
if (settingsPath || mcpPath) {
    updateConfig(settingsPath, mcpPath);
    // Do NOT log to stderr during MCP initialization as it can cause EOF errors in some clients
}
const server = createServer('OverMind-MCP', memoryOnly, memoryToolsOnly);
rootLogger.info(memoryOnly ? '[Overmind] [START] Démarrage du serveur mémoire...' : (memoryToolsOnly ? '[Overmind] [START] Démarrage serveur (memory tools only)...' : '[Overmind] [START] Démarrage du serveur...'));
// HTTP Singleton mode (OVERMIND_HTTP_MODE=true in .env)
// Les serveurs memory et postgresql tournent deja en singleton sur leurs ports,
// Overmind se configure en client HTTP pour aggreguer les outils
if (process.env.OVERMIND_HTTP_MODE === 'true') {
    rootLogger.info('[Overmind] [HTTP] Mode singleton actif — memory sur port ' + (process.env.MEMORY_HTTP_PORT || '3099') + ', postgresql sur port ' + (process.env.POSTGRES_HTTP_PORT || '5433'));
    rootLogger.info('[Overmind] [HTTP] Les outils sont exposés via la couche HTTP des serveurs distants');
    // En mode HTTP singleton, Overmind CLI ne démarre pas son propre serveur MCP
    // Il agit comme client pour les serveurs distants (memory + postgresql)
    // Les agents se connectent directement aux endpoints HTTP des serveurs distants
    process.exit(0);
}
if (transportType === 'httpStream') {
    const httpStreamConfig = {
        port: httpPort,
        host: httpHost,
        endpoint: httpEndpoint,
        stateless: true,
    };
    if (sslCert)
        httpStreamConfig.sslCert = sslCert;
    if (sslKey)
        httpStreamConfig.sslKey = sslKey;
    if (sslCa)
        httpStreamConfig.sslCa = sslCa;
    const protocol = sslCert && sslKey ? 'https' : 'http';
    // PATCH: Monkey-patch http.createServer to disable Node.js default 5min requestTimeout
    // Without this, SSE streams from long-running agent calls get killed after 300s
    const origCreateServer = http.createServer.bind(http);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    http.createServer = function (requestListener) {
        const hServer = origCreateServer(requestListener);
        hServer.requestTimeout = 0;
        hServer.headersTimeout = 0;
        hServer.keepAliveTimeout = 0;
        // Keep patch active to ensure all HTTP/S servers in this process have no timeouts
        return hServer;
    };
    server.start({ transportType: 'httpStream', httpStream: httpStreamConfig });
    rootLogger.info(`[Overmind] [READY] Serveur HTTP${sslCert ? 'S' : ''} sur ${protocol}://${httpHost}:${httpPort}${httpEndpoint}`);
}
else {
    server.start({ transportType: 'stdio' });
    rootLogger.info(memoryOnly ? '[Overmind] [READY] Serveur mémoire prêt sur STDIO.' : '[Overmind] [READY] Serveur prêt sur STDIO.');
}
//# sourceMappingURL=cli.js.map