titan-agent 5.6.3 → 5.6.4
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/dist/gateway/server.js +10 -3
- package/dist/gateway/server.js.map +1 -1
- package/dist/providers/anthropic.js +3 -0
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/base.js +17 -0
- package/dist/providers/base.js.map +1 -1
- package/dist/providers/google.js +3 -0
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai.js +3 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openai_compat.js +3 -0
- package/dist/providers/openai_compat.js.map +1 -1
- package/dist/providers/router.js +16 -1
- package/dist/providers/router.js.map +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/package.json +1 -1
- package/ui/dist/sw.js +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/gateway/server.ts"],"sourcesContent":["/**\n * TITAN — Gateway Server\n * WebSocket + HTTP server: the control plane for all channels, agents, tools, and the web UI.\n */\nimport express, { type Request, type Response, type NextFunction } from 'express';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createServer } from 'http';\nimport { createServer as createHttpsServer } from 'https';\nimport net from 'net';\nimport { join, dirname, resolve } from 'path';\nimport { fileURLToPath } from 'url';\nimport { homedir, hostname as osHostname, cpus, loadavg } from 'os';\nimport { randomBytes, timingSafeEqual } from 'crypto';\nimport { exec, execSync, spawn } from 'child_process';\nimport fs from 'fs';\nimport { loadConfig, updateConfig } from '../config/config.js';\nimport type { ProviderConfig } from '../config/schema.js';\nimport { loadProfile, saveProfile, type PersonalProfile } from '../memory/relationship.js';\nimport { processMessage } from '../agent/agent.js';\nimport { onAgentEvent } from '../agent/agentEvents.js';\nimport { initMemory, closeMemory, getUsageStats, getHistory, getDb } from '../memory/memory.js';\nimport { initBuiltinSkills, getSkills, toggleSkill, getSkillTools } from '../skills/registry.js';\nimport { listPersonas, getPersona, invalidatePersonaCache } from '../personas/manager.js';\nimport { searchSkills as marketplaceSearch, installSkill, uninstallSkill, listSkills as listMarketplaceSkills, listInstalled as listInstalledMarketplace } from '../skills/marketplace.js';\nimport { getRegisteredTools } from '../agent/toolRunner.js';\nimport { listSessions, cleanupStaleSessions } from '../agent/session.js';\nimport { healthCheckAll, discoverAllModels, getModelAliases, chatStream, getFallbackState } from '../providers/router.js';\nimport { auditSecurity } from '../security/sandbox.js';\nimport { WebChatChannel } from '../channels/webchat.js';\nimport { DiscordChannel } from '../channels/discord.js';\nimport { TelegramChannel } from '../channels/telegram.js';\nimport { SlackChannel } from '../channels/slack.js';\nimport { GoogleChatChannel } from '../channels/googlechat.js';\nimport { WhatsAppChannel } from '../channels/whatsapp.js';\nimport { MatrixChannel } from '../channels/matrix.js';\nimport { SignalChannel } from '../channels/signal.js';\nimport { MSTeamsChannel } from '../channels/msteams.js';\nimport { IRCChannel } from '../channels/irc.js';\nimport { MattermostChannel } from '../channels/mattermost.js';\nimport { LarkChannel } from '../channels/lark.js';\nimport { EmailInboundChannel } from '../channels/email_inbound.js';\nimport { LineChannel } from '../channels/line.js';\nimport { ZulipChannel } from '../channels/zulip.js';\nimport { MessengerChannel } from '../channels/messenger.js';\nimport { initAgents, routeMessage, listAgents } from '../agent/multiAgent.js';\nimport { createOpenAICompatRouter } from '../gateway/openai-compat.js';\nimport type { ChannelAdapter, InboundMessage } from '../channels/base.js';\nimport logger, { initFileLogger } from '../utils/logger.js';\nimport { TITAN_VERSION, TITAN_NAME, TITAN_LOGS_DIR, TITAN_HOME } from '../utils/constants.js';\nimport { getRestartStats as getRestartStatsSync } from '../utils/restartTracker.js';\nimport { collectSystemProfile, recordStartupAnalytics, startHeartbeatAnalytics } from '../analytics/collector.js';\nimport { getUpdateInfo } from '../utils/updater.js';\nimport { getMissionControlHTML } from './dashboard.js';\nimport { serializePrometheus, getMetricsSummary, titanRequestsTotal, titanRequestDuration, titanErrorsTotal, titanActiveSessions, titanToolCallsTotal, titanTokensTotal, titanModelRequestsTotal, recordEvalSuiteResult, recordEvalTimeout, recordEvalError } from './metrics.js';\nimport { createHardwareRouter } from './routes/hardwareRouter.js';\nimport { createMetricsRouter } from './routes/metricsRouter.js';\nimport { createMcpRouter } from './routes/mcpRouter.js';\nimport { createAgentsRouter } from './routes/agentsRouter.js';\nimport { initSlashCommands, handleSlashCommand } from './slashCommands.js';\nimport { initMcpServers } from '../mcp/registry.js';\nimport { mountMcpHttpEndpoints } from '../mcp/server.js';\nimport { initMonitors, setMonitorTriggerHandler, listMonitors, addMonitor, removeMonitor, getMonitorEvents } from '../agent/monitor.js';\nimport { seedBuiltinRecipes } from '../recipes/store.js';\nimport { parseSlashCommand, runRecipe } from '../recipes/runner.js';\nimport { getCostStatus } from '../agent/costOptimizer.js';\nimport { initLearning, getLearningStats } from '../memory/learning.js';\nimport { initGraph, getGraphStats, clearGraph, flushGraph } from '../memory/graph.js';\nimport { getLogFilePath } from '../utils/logger.js';\nimport { closeSession, renameSession, sweepSessions } from '../agent/session.js';\nimport { initCronScheduler } from '../skills/builtin/cron.js';\nimport { checkAndSendBriefing } from '../memory/briefing.js';\nimport { initPersistentWebhooks } from '../skills/builtin/webhook.js';\nimport { invalidateCacheForModel } from '../agent/responseCache.js';\nimport { initAutopilot, stopAutopilot, getAutopilotStatus } from '../agent/autopilot.js';\nimport { initDaemon, stopDaemon, titanEvents } from '../agent/daemon.js';\nimport { initCommandPost, shutdownCommandPost, isCommandPostEnabled, reportHeartbeat } from '../agent/commandPost.js';\nimport { initWakeupSystem } from '../agent/agentWakeup.js';\nimport { initHeartbeatScheduler } from '../agent/heartbeatScheduler.js';\nimport { auditLog } from '../agent/auditLog.js';\nimport { startTunnel, stopTunnel, getTunnelStatus } from '../utils/tunnel.js';\nimport { createPaperclipRouter, createPaperclipUIRouter } from './routes/paperclip.js';\nimport { createTracesRouter } from './routes/traces.js';\nimport { createCheckpointsRouter } from './routes/checkpoints.js';\nimport { createCompaniesRouter } from './routes/companies.js';\nimport { createCommandPostRouter } from './routes/commandPost.js';\nimport { createAdminRouter } from './routes/adminRouter.js';\nimport { createTeamsRecipesRouter } from './routes/teamsRecipes.js';\nimport { createFilesRouter } from './routes/files.js';\nimport { createSessionsRouter } from './routes/sessions.js';\nimport { createSkillsRouter } from './routes/skills.js';\nimport { createOrganismRouter } from './routes/organism.js';\nimport { createMeshRouter } from './routes/mesh.js';\nimport { createTestsRouter } from './routes/tests.js';\nimport { createSystemRouter } from './routes/systemRouter.js';\nimport { createVoiceRouter } from './routes/voiceRouter.js';\n\nimport { createSocialRouter } from './routes/socialRouter.js';\nimport { createWatchRouter } from './routes/watchRouter.js';\nimport { setupSSEFlush } from '../utils/sseFlush.js';\nimport { createLifecycleRouter } from './routes/agents.js';\n\nimport { getLifecycleManager } from '../utils/lifecycle.js';\nimport { startVoiceAgent, stopVoiceAgent } from '../skills/builtin/voice_control.js';\nconst COMPONENT = 'Gateway';\n\n/** Get normalized CPU load (0.0–1.0) using 1-minute load average */\nfunction getCpuLoad(): number {\n const avg = loadavg()[0]; // 1-minute load average\n const cores = cpus().length || 1;\n return Math.min(1, avg / cores);\n}\n\n/** Fields that require a gateway restart to take effect */\nconst RESTART_REQUIRED_PATTERNS = ['channels.*', 'gateway.auth.*', 'logging.level'];\n\n/** Module-level HTTP server reference (allows stopGateway to close it) */\nlet httpServer: ReturnType<typeof createServer> | null = null;\n\n/** Interval IDs for cleanup on shutdown */\nlet tokenCleanupInterval: ReturnType<typeof setInterval> | null = null;\nlet rateLimitCleanupInterval: ReturnType<typeof setInterval> | null = null;\nlet healthMonitorInterval: ReturnType<typeof setInterval> | null = null;\nlet sessionAbortCleanupInterval: ReturnType<typeof setInterval> | null = null;\nlet unsubscribeAgentEvents: (() => void) | null = null;\nlet activeLlmRequests = 0;\nexport function getActiveLlmRequests(): number { return activeLlmRequests; }\nlet maxConcurrentOverride: number | null = null;\n\n// ── Module-level constants (avoid per-request allocation) ──────────\n\nconst CP_SSE_EVENTS = [\n 'commandpost:activity', 'commandpost:task:checkout', 'commandpost:task:checkin',\n 'commandpost:task:expired', 'commandpost:budget:warning', 'commandpost:budget:exceeded',\n 'commandpost:agent:heartbeat', 'commandpost:agent:status',\n];\nconst ALLOWED_ORIGINS = [\n /^https?:\\/\\/localhost(:\\d+)?$/,\n /^https?:\\/\\/127\\.0\\.0\\.1(:\\d+)?$/,\n /^https?:\\/\\/\\[::1\\](:\\d+)?$/,\n /^https?:\\/\\/192\\.168\\.\\d+\\.\\d+(:\\d+)?$/, // LAN\n];\nfunction isAllowedOrigin(origin: string): boolean {\n return ALLOWED_ORIGINS.some(re => re.test(origin));\n}\n\n/**\n * Classify a chat error into a structured response that the React UI can render\n * as an actionable banner. Without this, every failure shows up as a generic 500\n * with a stack trace that means nothing to a non-developer.\n *\n * The classifier returns:\n * { error: string, message: string, status: number, action?: { type, target } }\n *\n * Known error codes (must match what the UI knows how to render):\n * - no_provider_configured → no API keys / Ollama unreachable\n * - rate_limited → 429 from upstream\n * - context_too_long → context window exceeded\n * - model_not_found → invalid model id\n * - auth_failed → 401/403 from upstream\n * - upstream_error → other 4xx/5xx from upstream\n * - timeout → request timed out\n * - unknown → fallback for everything else\n */\ninterface ChatErrorResponse {\n error: string;\n message: string;\n detail?: string;\n status: number;\n action?: { type: 'open' | 'retry' | 'docs'; target: string; label: string };\n}\nfunction classifyChatError(err: Error): ChatErrorResponse {\n const msg = (err.message || String(err)).toLowerCase();\n const detail = err.message;\n\n // No provider configured / no valid API key\n if (\n msg.includes('no valid provider') ||\n msg.includes('no api key') ||\n msg.includes('not configured') ||\n msg.includes('provider not found')\n ) {\n return {\n error: 'no_provider_configured',\n message: 'No AI provider is configured. Set up a provider to start chatting.',\n detail,\n status: 503,\n action: { type: 'open', target: '/settings', label: 'Open settings' },\n };\n }\n\n // Rate limited / quota exhausted\n if (\n msg.includes('rate limit') ||\n msg.includes('429') ||\n msg.includes('quota') ||\n msg.includes('too many requests')\n ) {\n return {\n error: 'rate_limited',\n message: \"You've hit your provider's rate limit. Wait a moment and try again, or switch providers in Settings.\",\n detail,\n status: 429,\n action: { type: 'retry', target: '', label: 'Retry' },\n };\n }\n\n // Context window exceeded\n if (\n msg.includes('context length') ||\n msg.includes('context window') ||\n msg.includes('maximum context') ||\n msg.includes('too many tokens') ||\n msg.includes('context_length_exceeded') ||\n msg.includes('prompt is too long')\n ) {\n return {\n error: 'context_too_long',\n message: 'The conversation got too long for the model. Start a new session or compact this one.',\n detail,\n status: 413,\n action: { type: 'open', target: '/sessions', label: 'New session' },\n };\n }\n\n // Model not found / invalid model id\n if (\n msg.includes('model not found') ||\n msg.includes('invalid model') ||\n msg.includes('unknown model') ||\n msg.includes('model_not_found') ||\n msg.includes('does not exist')\n ) {\n return {\n error: 'model_not_found',\n message: \"The selected model doesn't exist or you don't have access to it. Pick a different model in Settings.\",\n detail,\n status: 404,\n action: { type: 'open', target: '/settings', label: 'Pick a model' },\n };\n }\n\n // Auth failure (bad key / expired)\n if (\n msg.includes('401') ||\n msg.includes('403') ||\n msg.includes('unauthorized') ||\n msg.includes('forbidden') ||\n msg.includes('authentication') ||\n msg.includes('invalid api key') ||\n msg.includes('invalid_api_key')\n ) {\n return {\n error: 'auth_failed',\n message: 'Your API key was rejected by the provider. Check it in Settings → Providers.',\n detail,\n status: 401,\n action: { type: 'open', target: '/settings', label: 'Check API key' },\n };\n }\n\n // Timeout\n if (\n msg.includes('timeout') ||\n msg.includes('timed out') ||\n msg.includes('etimedout') ||\n msg.includes('aborted')\n ) {\n return {\n error: 'timeout',\n message: 'The model took too long to respond. Try again, or switch to a faster model.',\n detail,\n status: 504,\n action: { type: 'retry', target: '', label: 'Retry' },\n };\n }\n\n // Upstream provider error\n if (\n msg.includes('500') || msg.includes('502') || msg.includes('503') ||\n msg.includes('gateway') || msg.includes('upstream')\n ) {\n return {\n error: 'upstream_error',\n message: \"Your AI provider is having issues right now. Try again, or switch providers.\",\n detail,\n status: 502,\n action: { type: 'retry', target: '', label: 'Retry' },\n };\n }\n\n // Fallback\n return {\n error: 'unknown',\n message: detail || 'Something went wrong while processing your message.',\n detail,\n status: 500,\n };\n}\n\n/** Internal health monitor state */\nconst healthState = {\n ollamaHealthy: false,\n ttsHealthy: false,\n lastCheck: null as string | null,\n lastActiveLlm: 0,\n lastActiveLlmTime: 0,\n stuckDetected: false,\n};\n\nexport function stopGateway(): Promise<void> {\n return new Promise((resolve) => {\n // Clear intervals to release the event loop\n if (tokenCleanupInterval) { clearInterval(tokenCleanupInterval); tokenCleanupInterval = null; }\n if (rateLimitCleanupInterval) { clearInterval(rateLimitCleanupInterval); rateLimitCleanupInterval = null; }\n if (healthMonitorInterval) { clearInterval(healthMonitorInterval); healthMonitorInterval = null; }\n if (sessionAbortCleanupInterval) { clearInterval(sessionAbortCleanupInterval); sessionAbortCleanupInterval = null; }\n if (unsubscribeAgentEvents) { unsubscribeAgentEvents(); unsubscribeAgentEvents = null; }\n\n if (httpServer) {\n // Force-close open connections after 3 seconds (SSE/WebSocket keep-alives block shutdown)\n const forceTimeout = setTimeout(() => {\n logger.warn('Gateway', 'Shutdown timeout — destroying remaining connections');\n httpServer?.closeAllConnections?.();\n httpServer = null;\n resolve();\n }, 3000);\n forceTimeout.unref();\n\n httpServer.close(() => {\n clearTimeout(forceTimeout);\n httpServer = null;\n resolve();\n });\n } else {\n resolve();\n }\n });\n}\n\n/** Usage tracking — per-request cost/token tracking */\ninterface UsageEntry {\n timestamp: string;\n model: string;\n provider: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n estimatedCostUsd: number;\n durationMs: number;\n sessionId: string;\n}\nconst usageLog: UsageEntry[] = [];\nconst MAX_USAGE_LOG = 10000; // Keep last 10K entries in memory\n\n// Approximate cost per 1M tokens (input/output) for common models\nconst MODEL_COSTS: Record<string, { input: number; output: number }> = {\n 'claude-sonnet': { input: 3, output: 15 },\n 'claude-haiku': { input: 0.25, output: 1.25 },\n 'claude-opus': { input: 15, output: 75 },\n 'gpt-4o': { input: 2.5, output: 10 },\n 'gpt-4o-mini': { input: 0.15, output: 0.6 },\n 'gpt-4-turbo': { input: 10, output: 30 },\n 'ollama': { input: 0, output: 0 }, // local = free\n 'groq': { input: 0.05, output: 0.08 },\n 'deepseek': { input: 0.14, output: 0.28 },\n};\n\nfunction estimateCost(model: string, promptTokens: number, completionTokens: number): number {\n const key = Object.keys(MODEL_COSTS).find(k => model.toLowerCase().includes(k));\n if (!key) return 0;\n const rates = MODEL_COSTS[key];\n return (promptTokens * rates.input + completionTokens * rates.output) / 1_000_000;\n}\n\nfunction trackUsage(model: string, tokenUsage: { prompt?: number; completion?: number } | undefined, durationMs: number, sessionId: string): void {\n if (!tokenUsage) return;\n const prompt = tokenUsage.prompt || 0;\n const completion = tokenUsage.completion || 0;\n const provider = model.includes('/') ? model.split('/')[0] : 'unknown';\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n model,\n provider,\n promptTokens: prompt,\n completionTokens: completion,\n totalTokens: prompt + completion,\n estimatedCostUsd: estimateCost(model, prompt, completion),\n durationMs,\n sessionId,\n };\n usageLog.push(entry);\n if (usageLog.length > MAX_USAGE_LOG) usageLog.splice(0, usageLog.length - MAX_USAGE_LOG);\n}\n\n/** Active session tokens (persisted to disk so they survive restarts) */\nconst AUTH_TOKENS_PATH = join(TITAN_HOME, 'auth-tokens.json');\n\nfunction loadAuthTokens(): Map<string, { createdAt: number; userId: string }> {\n const map = new Map<string, { createdAt: number; userId: string }>();\n try {\n if (fs.existsSync(AUTH_TOKENS_PATH)) {\n const raw = JSON.parse(fs.readFileSync(AUTH_TOKENS_PATH, 'utf-8'));\n if (Array.isArray(raw)) {\n const ttlMs = 24 * 60 * 60 * 1000;\n const now = Date.now();\n for (const item of raw) {\n if (item && typeof item.token === 'string' && typeof item.createdAt === 'number' && typeof item.userId === 'string') {\n if (now - item.createdAt <= ttlMs) {\n map.set(item.token, { createdAt: item.createdAt, userId: item.userId });\n }\n }\n }\n }\n }\n } catch {\n // Best-effort: if file is corrupt, start fresh\n }\n return map;\n}\n\nfunction saveAuthTokens(): void {\n try {\n const entries = [];\n for (const [token, entry] of authTokens) {\n entries.push({ token, createdAt: entry.createdAt, userId: entry.userId });\n }\n fs.writeFileSync(AUTH_TOKENS_PATH, JSON.stringify(entries, null, 2));\n } catch {\n // Best-effort persistence\n }\n}\n\nconst authTokens = loadAuthTokens();\n\n/** S3: Get userId from request auth token */\nfunction getUserIdFromReq(req: { headers: { authorization?: string } }): string {\n const token = req.headers.authorization?.replace('Bearer ', '');\n if (token) {\n const entry = authTokens.get(token);\n if (entry) return entry.userId;\n }\n return 'default-user';\n}\n\n// Active session abort controllers — keyed by sessionId\nconst sessionAborts = new Map<string, AbortController>();\n// R8: Track abort controller creation time for TTL-based cleanup\nconst sessionAbortTimes = new Map<string, number>();\n\n// S3: Track session ownership — sessionId → userId\nconst sessionOwners = new Map<string, string>();\n\n// R8: Periodic cleanup of orphaned abort controllers (TTL 5 min)\nsessionAbortCleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [id, controller] of sessionAborts) {\n if (controller.signal.aborted || (now - (sessionAbortTimes.get(id) || 0)) > 300_000) {\n sessionAborts.delete(id);\n sessionAbortTimes.delete(id);\n sessionOwners.delete(id);\n }\n }\n}, 60_000);\nsessionAbortCleanupInterval.unref();\n\n// Clean expired tokens every 10 minutes\ntokenCleanupInterval = setInterval(() => {\n const now = Date.now();\n const ttlMs = 24 * 60 * 60 * 1000;\n for (const [tok, entry] of authTokens) {\n if (now - entry.createdAt > ttlMs) authTokens.delete(tok);\n }\n saveAuthTokens();\n}, 600_000);\ntokenCleanupInterval.unref();\n\n/** Constant-time string comparison to prevent timing attacks */\nfunction safeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n}\n\n/** Check if a request token is valid */\nfunction isValidToken(token: string | undefined, config: ReturnType<typeof loadConfig>): boolean {\n const auth = config.gateway.auth;\n if (!auth || auth.mode === 'none') return true;\n if (!token) return false;\n // S2: If token mode but no token configured, log warning and deny (don't silently allow)\n if (auth.mode === 'token') {\n if (!auth.token) {\n logger.warn(COMPONENT, 'Auth mode is \"token\" but no token configured — denying request. Set gateway.auth.token or switch to mode \"password\".');\n return false;\n }\n return safeCompare(token, auth.token);\n }\n if (auth.mode === 'password') {\n const entry = authTokens.get(token);\n if (!entry) return false;\n const ttlMs = 24 * 60 * 60 * 1000; // 24 hours\n if (Date.now() - entry.createdAt > ttlMs) {\n authTokens.delete(token);\n saveAuthTokens();\n return false;\n }\n return true;\n }\n return false;\n}\n\n/** Login page HTML */\nfunction getLoginHTML(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\"/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n<title>TITAN — Login</title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n@keyframes gradientBg{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}\n@keyframes shimmer{0%{background-position:-200% center}100%{background-position:200% center}}\n@keyframes shake{0%,100%{transform:translateX(0)}10%,30%,50%,70%,90%{transform:translateX(-4px)}20%,40%,60%,80%{transform:translateX(4px)}}\n@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}\nbody{font-family:'Inter','Segoe UI',system-ui,sans-serif;background:linear-gradient(135deg,#0a0e1a 0%,#0f172a 25%,#1a1040 50%,#0f172a 75%,#0a0e1a 100%);background-size:400% 400%;animation:gradientBg 15s ease infinite;color:#e2e8f0;display:flex;align-items:center;justify-content:center;min-height:100vh}\n.box{background:rgba(17,24,39,0.85);backdrop-filter:blur(20px);border:1px solid rgba(42,48,80,0.6);border-radius:16px;padding:40px;width:380px;box-shadow:0 0 40px rgba(6,182,212,.1),0 0 80px rgba(139,92,246,.05);animation:fadeIn .6s ease-out}\n.box.shake{animation:shake .5s ease}\nh1{font-size:28px;font-weight:700;background:linear-gradient(90deg,#06b6d4,#8b5cf6,#06b6d4);background-size:200% auto;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:shimmer 3s linear infinite;text-align:center;letter-spacing:3px;margin-bottom:4px}\n.sub{text-align:center;color:#94a3b8;font-size:13px;margin-bottom:32px}\nlabel{font-size:12px;color:#94a3b8;text-transform:uppercase;letter-spacing:1px;display:block;margin-bottom:8px}\ninput{width:100%;background:rgba(26,31,54,0.8);border:1px solid #2a3050;border-radius:10px;padding:12px 16px;color:#e2e8f0;font-size:15px;outline:none;transition:border .2s,box-shadow .2s}\ninput:focus{border-color:#06b6d4;box-shadow:0 0 12px rgba(6,182,212,.2)}\nbutton{width:100%;margin-top:20px;background:linear-gradient(135deg,#06b6d4,#8b5cf6);border:none;border-radius:10px;padding:14px;color:#fff;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .2s,transform .1s}\nbutton:hover{opacity:.9;transform:translateY(-1px)}\nbutton:active{transform:translateY(0)}\n.error{color:#ef4444;font-size:13px;margin-top:12px;text-align:center;display:none}\n</style>\n</head>\n<body>\n<div class=\"box\">\n <h1>⚡ TITAN</h1>\n <div class=\"sub\">Mission Control</div>\n <label>Password</label>\n <input type=\"password\" id=\"pw\" placeholder=\"Enter gateway password\" onkeydown=\"if(event.key==='Enter')login()\"/>\n <button onclick=\"login()\">Unlock</button>\n <div class=\"error\" id=\"err\">Incorrect password. Try again.</div>\n</div>\n<script>\nasync function login() {\n const pw = document.getElementById('pw').value;\n const res = await fetch('/api/login', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:pw})});\n if (res.ok) {\n const {token} = await res.json();\n localStorage.setItem('titan_token', token);\n location.href = '/';\n } else {\n document.getElementById('err').style.display = 'block';\n document.getElementById('pw').value = '';\n document.getElementById('pw').focus();\n const box = document.querySelector('.box');\n box.classList.remove('shake');\n void box.offsetWidth;\n box.classList.add('shake');\n }\n}\ndocument.getElementById('pw').focus();\n</script>\n</body>\n</html>`;\n}\n\n/** All active channel adapters */\nconst channels: Map<string, ChannelAdapter> = new Map();\n\n/** All connected WebSocket clients */\ninterface TaggedWebSocket extends WebSocket {\n titanSessionId?: string;\n titanUserId?: string;\n}\nconst wsClients: Set<TaggedWebSocket> = new Set();\nconst WS_MAX_MESSAGE_BYTES = 10 * 1024 * 1024; // 10MB max WS message\n\n/** The WebChat channel instance */\nlet webChatChannel: WebChatChannel | null = null;\n\n/** Broadcast a message to WebSocket clients. If userId is specified, only sends to that user's connections. */\nfunction broadcast(data: Record<string, unknown>, userId?: string): void {\n const json = JSON.stringify(data);\n for (const client of wsClients) {\n if (client.readyState === WebSocket.OPEN) {\n // Session isolation: if userId specified, only send to matching clients\n if (userId && (client as TaggedWebSocket).titanUserId && (client as TaggedWebSocket).titanUserId !== userId) continue;\n try {\n client.send(json);\n } catch (err) {\n logger.warn(COMPONENT, `Broadcast send failed: ${(err as Error).message}`);\n }\n }\n }\n}\n\n// Sub-agent event bridge: forward agent bus events to SSE broadcast\nunsubscribeAgentEvents = onAgentEvent((event) => {\n const sseType = event.type === 'tool_call' ? 'tool_call' : event.type === 'tool_end' ? 'tool_end' : event.type;\n broadcast({ type: sseType, ...event.data, agentName: event.agentName, agentId: event.agentId, isSubAgent: true, timestamp: event.timestamp });\n});\n\n// Initiative event bridge: broadcast autonomous task progress to dashboard chat\ntitanEvents.on('initiative:start', (data) => {\n broadcast({\n type: 'system_message',\n content: `🤖 **Initiative starting**: ${(data as Record<string, string>).subtaskTitle}\\n📋 Goal: ${(data as Record<string, string>).goalTitle}`,\n source: 'initiative',\n timestamp: (data as Record<string, string>).timestamp,\n });\n});\ntitanEvents.on('initiative:complete', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `✅ **Subtask completed**: ${d.subtaskTitle}\\n🔧 Tools: ${(d.toolsUsed as string[]).join(', ')}\\n📝 ${(d.summary as string || '').slice(0, 200)}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:no_progress', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `⚠️ **No progress on**: ${d.subtaskTitle}\\n${d.reason}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:tool_call', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `🔧 **${d.tool}**: ${d.args || ''}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:tool_result', (data) => {\n const d = data as Record<string, unknown>;\n const icon = d.success ? '✅' : '❌';\n broadcast({\n type: 'system_message',\n content: `${icon} **${d.tool}** ${d.success ? 'completed' : 'failed'} (${d.durationMs}ms)`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:round', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `🔄 **Round ${d.round}/${d.maxRounds}** — ${d.subtaskTitle}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\n\n/** Safely send a response through a channel adapter.\n * Hunt Finding #13: uses deliver() which runs the content through the\n * outbound sanitizer before invoking the channel's send() method. Applies\n * to all 17 channel adapters automatically. */\nasync function safeSend(channelName: string, msg: { channel: string; userId: string; groupId?: string; content: string; replyTo?: string }): Promise<void> {\n const channel = channels.get(channelName);\n if (!channel) return;\n try {\n await channel.deliver(msg);\n } catch (err) {\n logger.warn(COMPONENT, `Channel send failed (${channelName}): ${(err as Error).message}`);\n }\n}\n\n/** Handle an inbound message from any channel */\nasync function handleInboundMessage(msg: InboundMessage): Promise<void> {\n logger.info(COMPONENT, `[${msg.channel}] ${msg.userName || msg.userId}: ${msg.content.slice(0, 100)}`);\n\n // Broadcast to WebSocket clients for UI\n broadcast({\n type: 'message',\n direction: 'inbound',\n channel: msg.channel,\n userId: msg.userId,\n userName: msg.userName,\n content: msg.content,\n timestamp: msg.timestamp.toISOString(),\n });\n\n // ── Native slash commands (highest priority) ──────────────────\n const slashResult = await handleSlashCommand(msg.content, msg.channel, msg.userId);\n if (slashResult) {\n await safeSend(msg.channel, { channel: msg.channel, userId: msg.userId, groupId: msg.groupId, content: slashResult.response, replyTo: msg.id });\n broadcast({ type: 'message', direction: 'outbound', channel: msg.channel, userId: msg.userId, content: slashResult.response, timestamp: new Date().toISOString() });\n return;\n }\n\n // ── Recipe slash commands (second priority) ──────────────────\n const slash = parseSlashCommand(msg.content);\n if (slash) {\n const { command, args } = slash;\n const params: Record<string, string> = {};\n if (args) { params['file'] = args; params['topic'] = args; params['error'] = args; }\n try {\n let fullResponse = '';\n for await (const step of runRecipe(command, params)) {\n const r = await processMessage(step.prompt, msg.channel, msg.userId);\n fullResponse += (fullResponse ? '\\n\\n' : '') + r.content;\n }\n await safeSend(msg.channel, { channel: msg.channel, userId: msg.userId, groupId: msg.groupId, content: fullResponse, replyTo: msg.id });\n broadcast({ type: 'message', direction: 'outbound', channel: msg.channel, userId: msg.userId, content: fullResponse, timestamp: new Date().toISOString() });\n return;\n } catch {\n // Recipe not found — fall through to normal processing\n }\n }\n\n try {\n // Route through multi-agent system\n const response = await routeMessage(msg.content, msg.channel, msg.userId);\n\n // Send response back to the channel\n await safeSend(msg.channel, {\n channel: msg.channel,\n userId: msg.userId,\n groupId: msg.groupId,\n content: response.content,\n replyTo: msg.id,\n });\n\n // Broadcast response to UI\n broadcast({\n type: 'message',\n direction: 'outbound',\n channel: msg.channel,\n userId: msg.userId,\n content: response.content,\n toolsUsed: response.toolsUsed,\n tokenUsage: response.tokenUsage,\n durationMs: response.durationMs,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(COMPONENT, `Error processing message: ${(error as Error).message}`);\n broadcast({ type: 'error', message: 'TITAN ran into a problem handling that message. Please try again.' });\n }\n}\n\n/** Start the Gateway server */\nexport async function startGateway(options?: { port?: number; host?: string; verbose?: boolean; rateLimitMax?: number; rateLimitWindowMs?: number; skipUsableCheck?: boolean }): Promise<void> {\n const config = loadConfig();\n initFileLogger(TITAN_LOGS_DIR);\n const port = options?.port || config.gateway.port;\n let host = options?.host || config.gateway.host;\n\n // Hunt Finding #29 (2026-04-14): install a bounded global HTTP dispatcher\n // BEFORE any fetch() calls are made. Without this, each parallel Ollama\n // fetch opens a fresh socket and the keep-alive pool grows unboundedly.\n // Phase 5 load test saw 80+ idle sockets to Ollama after 100 requests.\n try {\n const { installGlobalHttpPool } = await import('../utils/httpPool.js');\n const poolCfg = (config.gateway as unknown as { httpPool?: { connections?: number; keepAliveTimeoutMs?: number; keepAliveMaxTimeoutMs?: number; headersTimeoutMs?: number; bodyTimeoutMs?: number } }).httpPool;\n installGlobalHttpPool({\n connections: poolCfg?.connections,\n keepAliveTimeoutMs: poolCfg?.keepAliveTimeoutMs,\n keepAliveMaxTimeoutMs: poolCfg?.keepAliveMaxTimeoutMs,\n headersTimeoutMs: poolCfg?.headersTimeoutMs,\n bodyTimeoutMs: poolCfg?.bodyTimeoutMs,\n });\n } catch (e) {\n logger.warn(COMPONENT, `[HttpPool] Failed to install global dispatcher: ${(e as Error).message} — fetch() will use Node defaults (unbounded pool)`);\n }\n\n logger.info(COMPONENT, `Starting ${TITAN_NAME} Gateway v${TITAN_VERSION}`);\n\n // v5.5.28 FIX: sweep orphaned atomic-write tmp files. atomicWriteFileSync\n // writes to .tmp.<ts>.<rand> then renames; if the process is killed\n // between those steps the tmp file leaks. The 2026-05-08 audit found\n // 188MB of these (vectors.json + test-history). Best-effort.\n try {\n const { sweepAtomicTmpOrphans } = await import('../utils/helpers.js');\n const swept = sweepAtomicTmpOrphans(TITAN_HOME);\n if (swept.removed > 0) {\n logger.info(COMPONENT, `Swept ${swept.removed} orphaned tmp file(s) from ${TITAN_HOME} — recovered ${(swept.bytes / 1024 / 1024).toFixed(1)} MB`);\n }\n } catch (e) {\n logger.warn(COMPONENT, `tmp sweep failed: ${(e as Error).message}`);\n }\n\n // Persist this boot so we can detect restart loops across systemd-managed\n // restarts. See src/utils/restartTracker.ts for why a single process can't\n // see its own loop.\n try {\n const { recordBoot, getRestartStats } = await import('../utils/restartTracker.js');\n recordBoot(TITAN_VERSION);\n const stats = getRestartStats();\n if (stats.severity !== 'ok' && stats.reason) {\n const { sendAlert } = await import('../agent/alerts.js');\n sendAlert(\n stats.severity,\n 'Gateway restart loop detected',\n stats.reason,\n 'restart-tracker',\n {\n restartsLast10Min: stats.restartsLast10Min,\n restartsLastHour: stats.restartsLastHour,\n nRestartsSystemd: stats.nRestartsSystemd,\n previousBootAt: stats.previousBootAt,\n },\n );\n }\n } catch (err) {\n logger.warn(COMPONENT, `restart tracker init failed: ${(err as Error).message}`);\n }\n\n // ── First-run guard: refuse to start with no usable provider ──\n // Without this, the gateway boots fine but every chat call fails with a\n // generic 500. Users have no idea they need to configure a provider.\n // Bypass with --skip-usable-check (or skipUsableCheck option) for advanced use.\n if (!options?.skipUsableCheck) {\n const { hasUsableProvider } = await import('../config/config.js');\n const usable = await hasUsableProvider();\n if (!usable.ok) {\n console.error('');\n console.error('\\x1b[31m\\x1b[1m❌ TITAN is not configured.\\x1b[0m');\n console.error('');\n console.error(` ${usable.details}`);\n console.error('');\n console.error(' Run the setup wizard:');\n console.error(' \\x1b[36mtitan onboard\\x1b[0m');\n console.error('');\n console.error(' Or set an environment variable:');\n console.error(' \\x1b[36mexport ANTHROPIC_API_KEY=\"sk-ant-...\"\\x1b[0m');\n console.error(' \\x1b[36mexport OPENAI_API_KEY=\"sk-...\"\\x1b[0m');\n console.error(' \\x1b[36mexport OLLAMA_BASE_URL=\"http://localhost:11434\"\\x1b[0m');\n console.error('');\n console.error(' Or check what went wrong:');\n console.error(' \\x1b[36mtitan doctor\\x1b[0m');\n console.error('');\n console.error(' To skip this check (advanced):');\n console.error(' \\x1b[36mtitan gateway --skip-usable-check\\x1b[0m');\n console.error('');\n process.exit(1);\n }\n logger.info(COMPONENT, `Provider check passed: ${usable.details}`);\n }\n\n // ── Production safety warning ─────────────────────────────────────\n if (config.autonomy?.mode === 'autonomous') {\n logger.warn(COMPONENT, '⚠️ AUTONOMY MODE IS \"autonomous\" — all tools run without approval. Safe for personal use, DANGEROUS for multi-user deployments.');\n logger.warn(COMPONENT, ' Set autonomy.mode to \"supervised\" in titan.json if exposing to external users.');\n }\n if (config.commandPost?.enabled) {\n logger.info(COMPONENT, '✅ Command Post governance is active — approvals route through CP queue');\n } else {\n logger.warn(COMPONENT, '⚠️ Command Post is DISABLED — no approval queue, no budget enforcement, no agent registry');\n }\n if (config.selfMod?.enabled) {\n logger.info(COMPONENT, '✅ Self-modification is active — writes are staged for human review');\n }\n\n // ── Stale session cleanup: mark orphaned active sessions as idle ──\n cleanupStaleSessions();\n // Run every 60s so ephemeral one-shot sessions (api / autoresearch-* /\n // initiative-* / monitor / mesh / etc.) get cleared promptly within their\n // 5min idle TTL. Persistent channels (webchat / voice / discord / ...)\n // still use the full SESSION_TIMEOUT_MS (30min) inside cleanupStaleSessions.\n // Pre-fix: 5min interval + uniform 30min TTL accumulated 755 sessions in\n // 29min on the live service (Kimi observation, 2026-04-26).\n setInterval(() => cleanupStaleSessions(), 60 * 1000);\n\n // ── Port pre-check: fail fast before loading subsystems ────\n const portAvailable = await new Promise<boolean>((resolve) => {\n const tester = net.createServer();\n tester.once('error', () => resolve(false));\n tester.once('listening', () => { tester.close(); resolve(true); });\n tester.listen(port, host);\n });\n if (!portAvailable) {\n logger.error(COMPONENT, `Port ${port} is already in use. Is TITAN already running?`);\n logger.info(COMPONENT, `Try: titan gateway --port ${port + 1}`);\n process.exit(1);\n }\n\n // ── GPU detection: adjust stall timeout for CPU-only inference ──\n const { detectGpu } = await import('../utils/hardware.js');\n if (!detectGpu()) {\n const { setStallThreshold } = await import('../agent/stallDetector.js');\n setStallThreshold(120_000);\n logger.info(COMPONENT, 'No GPU detected — stall timeout increased to 120s for CPU inference');\n maxConcurrentOverride = 2;\n logger.info(COMPONENT, 'CPU-only mode: maxConcurrentTasks auto-tuned to 2');\n }\n\n // Initialize subsystems\n initMemory();\n initLearning();\n initGraph();\n\n // Recover persisted deliberation states from previous session\n import('../agent/deliberation.js').then(({ recoverDeliberations }) => {\n recoverDeliberations();\n }).catch(() => {});\n\n // Initialize vector search (Tier 2 memory — non-blocking)\n import('../memory/vectors.js').then(({ initVectors }) => {\n initVectors().then(ok => {\n if (ok) logger.info(COMPONENT, 'Vector search (Tier 2 memory) initialized');\n }).catch(() => {});\n }).catch(() => {});\n\n await initBuiltinSkills();\n initAgents();\n\n // ── Rate limiter (inline, no deps) ─────────────────────────\n const defaultRateLimitWindowMs = options?.rateLimitWindowMs ?? 60000;\n const defaultRateLimitMax = options?.rateLimitMax ?? 30;\n const rateLimitStore = new Map<string, { count: number; resetAt: number }>();\n\n /**\n * Get a consistent client IP address for rate limiting.\n * Falls back through: X-Forwarded-For → req.ip → socket remoteAddress\n */\n function getClientIp(req: Request): string {\n return (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim()\n || req.ip\n || req.socket?.remoteAddress\n || 'unknown';\n }\n\n function rateLimit(windowMs: number, maxRequests: number) {\n return (req: Request, res: Response, next: NextFunction) => {\n const key = getClientIp(req);\n const now = Date.now();\n const entry = rateLimitStore.get(key);\n if (!entry || now > entry.resetAt) {\n rateLimitStore.set(key, { count: 1, resetAt: now + windowMs });\n next();\n } else if (entry.count < maxRequests) {\n entry.count++;\n next();\n } else {\n const retryAfter = Math.ceil((entry.resetAt - now) / 1000);\n logger.warn(COMPONENT, `[RateLimit] Client ${key} rate limited (${entry.count}/${maxRequests} in ${windowMs}ms)`);\n res.setHeader('Retry-After', String(retryAfter));\n res.status(429).json({ error: 'Too many requests', retryAfter });\n }\n };\n }\n\n // ── Concurrent request guard (prevents parallel abuse) ────\n // Hunt Finding #27 (2026-04-14): previously this attached BOTH a 'finish'\n // and a 'close' handler that each decremented the counter. Both events\n // fire for a normal request completion ('finish' first, then 'close'),\n // so every real request caused TWO decrements. Under parallel load the\n // counter drifted below the true active-request count, effectively\n // doubling the allowed concurrency. Math.max(0, -) kept it from going\n // negative numerically but the effective limit became 2×MAX.\n //\n // Fix: use ONLY 'close', which fires for every completed response\n // (normal, aborted, errored) exactly once. Remove 'finish' to eliminate\n // the double-decrement. Also make the limit configurable via config\n // so operators can tune it for their deployment instead of being stuck\n // at the hardcoded 5.\n let activeMessageRequests = 0;\n const MAX_CONCURRENT_MESSAGES = (() => {\n const cfg = loadConfig() as unknown as { gateway?: { maxConcurrentMessages?: number } };\n const v = cfg.gateway?.maxConcurrentMessages;\n if (typeof v === 'number' && v > 0 && v <= 1000) return v;\n return 5;\n })();\n\n function concurrencyGuard(maxConcurrent: number) {\n return (_req: Request, res: Response, next: NextFunction) => {\n if (activeMessageRequests >= maxConcurrent) {\n res.status(503).json({ error: 'Server busy — too many concurrent requests' });\n return;\n }\n activeMessageRequests++;\n // 'close' fires exactly once per completed request — safer than 'finish'\n // which only fires for successful sends AND is followed by 'close'\n // anyway (causing the double-decrement bug).\n let decremented = false;\n res.on('close', () => {\n if (decremented) return;\n decremented = true;\n activeMessageRequests = Math.max(0, activeMessageRequests - 1);\n });\n next();\n };\n }\n\n // Clean rate limit store every 60 seconds (unref so it doesn't block shutdown)\n rateLimitCleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of rateLimitStore) {\n if (now > entry.resetAt) rateLimitStore.delete(key);\n }\n // Cap rate limit store to prevent unbounded growth\n if (rateLimitStore.size > 10_000) {\n const entries = [...rateLimitStore.entries()].sort((a, b) => a[1].resetAt - b[1].resetAt);\n const toRemove = entries.slice(0, entries.length - 10_000);\n for (const [key] of toRemove) rateLimitStore.delete(key);\n }\n }, 60_000);\n rateLimitCleanupInterval.unref();\n\n // Create Express app\n const app = express();\n\n // ── Serve React SPA static assets FIRST ───────────────────\n // Static files (JS, CSS, images) should bypass JSON parsing,\n // request logging, and auth middleware for efficiency.\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const uiDistPath = join(__dirname, '../../ui/dist');\n const uiIndexPath = join(uiDistPath, 'index.html');\n const hasReactUI = fs.existsSync(uiIndexPath);\n let cachedIndexHtml: string | null = null;\n if (hasReactUI) {\n // Cache index.html in memory to avoid sync file reads on every request\n cachedIndexHtml = fs.readFileSync(uiIndexPath, 'utf8');\n app.use(express.static(uiDistPath, { index: false }));\n // Hot-reload the cache when the file changes (dev rebuilds)\n fs.watchFile(uiIndexPath, { interval: 1000 }, () => {\n try {\n cachedIndexHtml = fs.readFileSync(uiIndexPath, 'utf8');\n } catch { /* ignore read errors during write */ }\n });\n }\n\n app.use(express.json({ limit: '1mb' }));\n\n // Request logging middleware (skips static assets served above)\n app.use((req, res, next) => {\n const start = Date.now();\n res.on('finish', () => {\n const duration = Date.now() - start;\n logger.info(COMPONENT, `${req.method} ${req.path} → ${res.statusCode} (${duration}ms)`);\n });\n next();\n });\n\n // OpenAI API compatibility layer (/v1/models, /v1/chat/completions, /v1/embeddings)\n app.use('/v1', createOpenAICompatRouter());\n\n // ── Paperclip sidecar management & proxy ───────────────────\n app.use('/api/paperclip', createPaperclipRouter());\n app.use('/paperclip', createPaperclipUIRouter());\n\n // Ollama native API proxy (/ollama/* → configured Ollama server)\n // The UI's titan2/llm/ollama.ts hits /ollama/api/chat and /ollama/api/generate\n app.all('/ollama/*', async (req: Request, res: Response) => {\n const cfg = loadConfig();\n const ollamaBase = cfg.providers?.ollama?.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434';\n const targetPath = req.path.replace(/^\\/ollama/, '');\n const targetUrl = `${ollamaBase}${targetPath}`;\n\n try {\n const upstream = await fetch(targetUrl, {\n method: req.method,\n headers: {\n 'Content-Type': req.headers['content-type'] || 'application/json',\n Accept: req.headers['accept'] || '*/*',\n },\n body: req.method !== 'GET' && req.method !== 'HEAD' ? JSON.stringify(req.body) : undefined,\n });\n\n res.status(upstream.status);\n upstream.headers.forEach((value, key) => {\n // Don't forward content-encoding; Node will handle compression itself\n if (key.toLowerCase() !== 'content-encoding') {\n res.setHeader(key, value);\n }\n });\n\n if (upstream.body) {\n const reader = upstream.body.getReader();\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(Buffer.from(value));\n }\n }\n res.end();\n } catch (err) {\n logger.error(COMPONENT, `Ollama proxy error: ${(err as Error).message}`);\n res.status(502).json({ error: 'Ollama proxy error', message: (err as Error).message });\n }\n });\n\n // Handle JSON parse errors and payload too large\n app.use((err: Error & { type?: string; status?: number }, req: Request, res: Response, next: NextFunction) => {\n if (err.type === 'entity.too.large') {\n res.status(413).json({ error: 'Payload too large (max 1MB)' });\n return;\n }\n if (err.type === 'entity.parse.failed') {\n res.status(400).json({ error: 'Invalid JSON' });\n return;\n }\n next(err);\n });\n\n // Security headers + CSP\n app.use((req, res, next) => {\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'SAMEORIGIN');\n res.setHeader('X-XSS-Protection', '1; mode=block');\n res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\n res.setHeader('Content-Security-Policy', [\n \"default-src 'self'\",\n // Sandbox widget iframes use new Function() for code evaluation.\n \"script-src 'self' 'unsafe-inline' 'unsafe-eval'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"connect-src 'self' ws: wss: https: http:\",\n \"media-src 'self' blob: mediastream:\",\n \"img-src 'self' data: blob:\",\n \"font-src 'self' data:\",\n // Canvas AI-generated widgets run in a sandboxed iframe whose\n // source is a blob: URL built by ui/src/titan2/sandbox/SandboxRuntime.\n // Without `frame-src blob:` the browser shows:\n // \"This content is blocked. Contact the site owner to fix the issue.\"\n // worker-src + child-src are included as safety fallbacks for\n // older engines that don't honor frame-src directly.\n \"frame-src 'self' blob: data:\",\n \"child-src 'self' blob: data:\",\n \"worker-src 'self' blob:\",\n ].join('; '));\n res.removeHeader('X-Powered-By');\n next();\n });\n\n // CORS — allow localhost, Tailscale, Cloudflare tunnels, and LAN origins\n const gatewayPort = config.gateway.port || 48420;\n const localhostOrigins = new Set([\n `http://127.0.0.1:${gatewayPort}`,\n `http://localhost:${gatewayPort}`,\n `https://127.0.0.1:${gatewayPort}`,\n `https://localhost:${gatewayPort}`,\n ]);\n const dynamicOriginPatterns = [\n /^https?:\\/\\/[a-z0-9-]+\\.ts\\.net(:\\d+)?$/, // Tailscale (*.ts.net)\n /^https?:\\/\\/[a-z0-9-]+\\.trycloudflare\\.com(:\\d+)?$/, // Cloudflare tunnel\n /^http:\\/\\/192\\.168\\.\\d{1,3}\\.\\d{1,3}(:\\d+)?$/, // LAN 192.168.x.x\n /^http:\\/\\/10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d+)?$/, // LAN 10.x.x.x\n /^http:\\/\\/172\\.(1[6-9]|2\\d|3[0-1])\\.\\d{1,3}\\.\\d{1,3}(:\\d+)?$/, // LAN 172.16-31.x.x\n ];\n function isAllowedOrigin(origin: string): boolean {\n if (localhostOrigins.has(origin)) return true;\n return dynamicOriginPatterns.some(re => re.test(origin));\n }\n app.use((req, res, next) => {\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n }\n if (req.method === 'OPTIONS') { res.sendStatus(204); return; }\n next();\n });\n\n // ── Login routes (no auth required) ──────────────────────────\n app.get('/login', (_req, res) => {\n res.setHeader('Content-Type', 'text/html');\n res.send(getLoginHTML());\n });\n\n app.post('/api/login', rateLimit(60000, 5), (req, res) => {\n const cfg = loadConfig();\n const auth = cfg.gateway.auth;\n if (!auth || auth.mode === 'none') {\n res.json({ token: 'noauth' });\n return;\n }\n const { password } = req.body as { password?: string };\n let valid = false;\n if (auth.mode === 'password' && auth.password && password && safeCompare(password, auth.password)) valid = true;\n if (auth.mode === 'token' && auth.token && password && safeCompare(password, auth.token)) valid = true;\n if (!valid) { res.status(401).json({ error: 'Invalid password' }); return; }\n const token = randomBytes(32).toString('hex');\n authTokens.set(token, { createdAt: Date.now(), userId: `user-${token.slice(0, 8)}` });\n saveAuthTokens();\n res.json({ token });\n });\n\n // ── Prometheus /metrics (no auth — standard scrape path) ────\n app.get('/metrics', (_req, res) => {\n res.setHeader('Content-Type', 'text/plain; version=0.0.4');\n res.send(serializePrometheus());\n });\n\n // ── Auth middleware (API routes only) ────────────────────────\n // HTML pages (/ and /login) are always served — the JS handles\n // the redirect to /login if localStorage has no token.\n // Only /api/* routes require a valid token.\n app.use('/api', (req, res, next) => {\n const cfg = loadConfig();\n const auth = cfg.gateway.auth;\n if (!auth || auth.mode === 'none') { next(); return; }\n // Token mode with no token configured = auth not set up, allow access\n if (auth.mode === 'token' && !auth.token) { next(); return; }\n // Skip public endpoints (login, messenger webhook, twilio webhooks)\n if (req.path === '/login') { next(); return; }\n if (req.path === '/messenger/webhook') { next(); return; }\n if (req.path.startsWith('/twilio/')) { next(); return; }\n const header = req.headers.authorization;\n const token = header?.startsWith('Bearer ') ? header.slice(7) : (req.query.token as string);\n if (isValidToken(token, cfg)) { next(); return; }\n res.status(401).json({ error: 'Unauthorized' });\n });\n\n // ── Command Post availability guard ──────────────────────────\n app.use('/api/command-post', (_req, res, next) => {\n if (isCommandPostEnabled()) { next(); return; }\n res.status(503).json({ error: 'Command Post is disabled', hint: 'Enable it in titan.json: commandPost.enabled = true' });\n });\n\n // Legacy dashboard (kept during migration, also fallback if React UI not built)\n app.get('/legacy', (_req, res) => {\n res.setHeader('Content-Type', 'text/html');\n res.send(getMissionControlHTML());\n });\n\n // Root route: React SPA or legacy dashboard\n app.get('/', (_req, res) => {\n if (hasReactUI && cachedIndexHtml) {\n res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');\n res.setHeader('Pragma', 'no-cache');\n res.setHeader('Expires', '0');\n res.send(cachedIndexHtml);\n } else {\n res.setHeader('Content-Type', 'text/html');\n res.send(getMissionControlHTML());\n }\n });\n\n // API routes\n app.get('/api/stats', (_req, res) => {\n const usage = getUsageStats();\n const cfg = loadConfig();\n const activeModel = cfg.agent.model || '';\n const mem = process.memoryUsage();\n const activeAgents = listAgents().filter(a => a.status === 'running').length;\n const activeSessions = listSessions().length;\n res.json({\n ...usage,\n version: TITAN_VERSION,\n uptime: process.uptime(),\n model: activeModel.replace(/^ollama\\//, ''),\n provider: activeModel.split('/')[0] || 'ollama',\n memoryMB: Math.round(mem.rss / 1024 / 1024),\n memoryUsage: {\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n rss: mem.rss,\n external: mem.external,\n arrayBuffers: mem.arrayBuffers,\n },\n health: {\n ollamaHealthy: healthState.ollamaHealthy,\n ttsHealthy: healthState.ttsHealthy,\n lastCheck: healthState.lastCheck,\n stuckDetected: healthState.stuckDetected,\n uptimeSeconds: Math.round(process.uptime()),\n memoryUsageMB: Math.round(mem.heapUsed / 1024 / 1024),\n activeLlmRequests,\n restarts: (() => { try { return getRestartStatsSync(); } catch { return null; } })(),\n },\n activeAgents,\n activeSessions,\n });\n });\n\n // ── Tracing API ─────────────────────────────────────────────────\n app.use('/api/traces', createTracesRouter());\n\n // ── Checkpoints API ────────────────────────────────────────────\n app.use('/api/checkpoints', createCheckpointsRouter());\n\n // ── Company API (Paperclip-style) ─────────────────────────────\n app.use('/api/companies', createCompaniesRouter());\n\n // ── Command Post API (Agent Governance) ───────────────────\n app.use('/api/command-post', createCommandPostRouter());\n\n // ── Sessions API ──────────────────────────────────────────\n app.use('/api/sessions', createSessionsRouter(sessionAborts));\n\n // ── Skills API ──────────────────────────────────────────────\n app.use('/api', createTeamsRecipesRouter());\n app.use('/api', createSkillsRouter(channels));\n app.use('/api', createAdminRouter());\n\n // ── Soul API ──────────────────────────────────────────────────\n\n // ── Soul API ──────────────────────────────────────────────────\n app.get('/api/soul/wisdom', async (_req, res) => {\n try {\n const { getWisdomData } = await import('../agent/soul.js');\n res.json(getWisdomData());\n } catch { res.json({ patterns: [], mistakes: [], userPreferences: [], totalTasks: 0 }); }\n });\n\n app.get('/api/soul/state/:sessionId', async (req, res) => {\n try {\n const { getSoulState } = await import('../agent/soul.js');\n const state = getSoulState(req.params.sessionId);\n if (!state) { res.status(404).json({ error: 'No active soul state for session' }); return; }\n res.json(state);\n } catch { res.status(500).json({ error: 'Soul unavailable' }); }\n });\n\n // ── Guardrails API ─────────────────────────────────────────────\n app.get('/api/guardrails/violations', async (_req, res) => {\n try {\n const { getViolations } = await import('../agent/guardrails.js');\n const limit = parseInt(_req.query.limit as string || '50', 10);\n res.json({ violations: getViolations(limit) });\n } catch { res.json({ violations: [] }); }\n });\n\n // ── Alerts API ────────────────────────────────────────────────\n app.get('/api/alerts', async (_req, res) => {\n try {\n const { getAlertHistory } = await import('../agent/alerts.js');\n const limit = parseInt(_req.query.limit as string || '50', 10);\n res.json({ alerts: getAlertHistory(limit) });\n } catch { res.json({ alerts: [] }); }\n });\n\n // ── Dream Mode API (v5.5.17) ──────────────────────────────────\n // Three reads + one on-demand generator. The cron handles scheduled\n // generation; the POST endpoint exists so an operator can force-run the\n // pipeline mid-day without waiting for 03:30 (e.g. to demo the feature\n // or backfill after a long offline stretch).\n app.get('/api/dreams/latest', async (_req, res) => {\n try {\n const { getLatestDream } = await import('../agent/dreams.js');\n const dream = getLatestDream();\n if (!dream) { res.status(404).json({ error: 'no dreams yet' }); return; }\n res.json(dream);\n } catch (e) {\n logger.error(COMPONENT, `dreams/latest: ${(e as Error).message}`);\n res.status(500).json({ error: 'dreams unavailable' });\n }\n });\n\n app.get('/api/dreams', async (_req, res) => {\n try {\n const { listDreamDates } = await import('../agent/dreams.js');\n const limit = Math.min(Math.max(parseInt(String(_req.query.limit ?? '30'), 10) || 30, 1), 365);\n res.json({ dates: listDreamDates(limit) });\n } catch (e) {\n logger.error(COMPONENT, `dreams list: ${(e as Error).message}`);\n res.status(500).json({ error: 'dreams unavailable' });\n }\n });\n\n app.get('/api/dreams/:date', async (req, res) => {\n try {\n const { getDreamByDate } = await import('../agent/dreams.js');\n // Date param is YYYY-MM-DD; reject anything else to keep the\n // filesystem read inside DREAMS_DIR.\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(req.params.date)) {\n res.status(400).json({ error: 'date must be YYYY-MM-DD' });\n return;\n }\n const dream = getDreamByDate(req.params.date);\n if (!dream) { res.status(404).json({ error: 'no dream for that date' }); return; }\n res.json(dream);\n } catch (e) {\n logger.error(COMPONENT, `dreams/:date: ${(e as Error).message}`);\n res.status(500).json({ error: 'dreams unavailable' });\n }\n });\n\n app.post('/api/dreams/generate', async (_req, res) => {\n try {\n const { generateDream } = await import('../agent/dreams.js');\n const dream = await generateDream();\n res.json(dream);\n } catch (e) {\n logger.error(COMPONENT, `dreams/generate: ${(e as Error).message}`);\n res.status(500).json({ error: 'dream generation failed', message: (e as Error).message });\n }\n });\n\n // ── Persona Profiles API (v5.5.24) ────────────────────────────\n // Note path is `/api/persona-profiles` not `/api/personas` —\n // /api/personas already returns the agency-agent persona list (a\n // separate concept from runtime persona profiles). Renamed to avoid\n // route collision discovered on first deploy of v5.5.24.\n app.get('/api/persona-profiles', async (_req, res) => {\n try {\n const cfg = loadConfig();\n const personas = cfg.personas;\n res.json({\n enabled: personas?.enabled ?? false,\n defaultPersona: personas?.defaultPersona ?? null,\n channelPins: personas?.channelPins ?? {},\n profiles: personas?.profiles ?? [],\n });\n } catch (e) {\n logger.error(COMPONENT, `persona-profiles list: ${(e as Error).message}`);\n res.status(500).json({ error: 'personas unavailable' });\n }\n });\n\n app.get('/api/persona-profiles/active', async (req, res) => {\n try {\n const { describeActivePersona } = await import('../agent/personaProfiles.js');\n const channel = typeof req.query.channel === 'string' ? req.query.channel : undefined;\n res.json(describeActivePersona({ channel }));\n } catch (e) {\n logger.error(COMPONENT, `persona-profiles active: ${(e as Error).message}`);\n res.status(500).json({ error: 'personas unavailable' });\n }\n });\n\n // ── Persona Cohorts API (v5.5.27, A/B rollout) ────────────────\n // Cohorts are runtime state — this is the operator's control surface\n // for canarying a candidate persona against a baseline. Health endpoint\n // returns per-arm stats over the rolling window so MC can render\n // sparkline cards. Auto-revert fires from the monitor cron, but manual\n // POST /:id/revert is also exposed for kill-switch use.\n app.get('/api/persona-cohorts', async (_req, res) => {\n try {\n const { listCohorts } = await import('../agent/personaRollout.js');\n res.json({ cohorts: listCohorts() });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts list: ${(e as Error).message}`);\n res.status(500).json({ error: 'persona-cohorts unavailable' });\n }\n });\n\n app.post('/api/persona-cohorts', async (req, res) => {\n try {\n const { createCohort } = await import('../agent/personaRollout.js');\n const body = (req.body || {}) as { baselineId?: string; candidateId?: string; percent?: number; hashKey?: 'sessionId' | 'channel'; note?: string; id?: string };\n if (!body.baselineId || !body.candidateId || typeof body.percent !== 'number') {\n res.status(400).json({ error: 'baselineId, candidateId, and percent are required' });\n return;\n }\n const cohort = createCohort({\n baselineId: body.baselineId,\n candidateId: body.candidateId,\n percent: body.percent,\n hashKey: body.hashKey,\n note: body.note,\n id: body.id,\n });\n res.json(cohort);\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts create: ${(e as Error).message}`);\n res.status(400).json({ error: (e as Error).message });\n }\n });\n\n app.delete('/api/persona-cohorts/:id', async (req, res) => {\n try {\n const { deleteCohort } = await import('../agent/personaRollout.js');\n const ok = deleteCohort(req.params.id);\n if (!ok) { res.status(404).json({ error: 'cohort not found' }); return; }\n res.json({ deleted: true });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts delete: ${(e as Error).message}`);\n res.status(500).json({ error: 'delete failed' });\n }\n });\n\n app.post('/api/persona-cohorts/:id/revert', async (req, res) => {\n try {\n const { revertCohort } = await import('../agent/personaRollout.js');\n const reason = (req.body && typeof req.body.reason === 'string') ? req.body.reason : 'manual revert via API';\n const cohort = revertCohort(req.params.id, reason, 'manual');\n if (!cohort) { res.status(404).json({ error: 'cohort not found' }); return; }\n res.json(cohort);\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts revert: ${(e as Error).message}`);\n res.status(500).json({ error: 'revert failed' });\n }\n });\n\n app.get('/api/persona-cohorts/:id/health', async (req, res) => {\n try {\n const { getCohort, evaluateCohort } = await import('../agent/personaRollout.js');\n const cohort = getCohort(req.params.id);\n if (!cohort) { res.status(404).json({ error: 'cohort not found' }); return; }\n const cfg = loadConfig();\n const rollout = (cfg.personas as { rollout?: { windowMins?: number; minSampleSize?: number; passRateMargin?: number; safetyDropThreshold?: number } } | undefined)?.rollout;\n const health = evaluateCohort(cohort, {\n windowMins: rollout?.windowMins,\n minSampleSize: rollout?.minSampleSize,\n passRateMargin: rollout?.passRateMargin,\n safetyDropThreshold: rollout?.safetyDropThreshold,\n });\n res.json({ cohort, health });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts health: ${(e as Error).message}`);\n res.status(500).json({ error: 'health unavailable' });\n }\n });\n\n app.get('/api/persona-cohorts/health', async (_req, res) => {\n try {\n const { listCohorts, evaluateCohort } = await import('../agent/personaRollout.js');\n const cohorts = listCohorts();\n const cfg = loadConfig();\n const rollout = (cfg.personas as { rollout?: { windowMins?: number; minSampleSize?: number; passRateMargin?: number; safetyDropThreshold?: number } } | undefined)?.rollout;\n const out = cohorts.map(cohort => ({\n cohort,\n health: evaluateCohort(cohort, {\n windowMins: rollout?.windowMins,\n minSampleSize: rollout?.minSampleSize,\n passRateMargin: rollout?.passRateMargin,\n safetyDropThreshold: rollout?.safetyDropThreshold,\n }),\n }));\n res.json({ cohorts: out });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts health-all: ${(e as Error).message}`);\n res.status(500).json({ error: 'health unavailable' });\n }\n });\n\n app.get('/api/health/deep', async (_req, res) => {\n const checks: Record<string, { status: 'ok' | 'degraded' | 'down'; detail?: string }> = {};\n let overall: 'ok' | 'degraded' | 'down' = 'ok';\n\n // Memory subsystem\n try {\n const { getDb } = await import('../memory/memory.js');\n const db = getDb();\n checks.memory = { status: 'ok', detail: `${db.memories.length} memories, ${db.sessions.length} sessions` };\n } catch (e) {\n checks.memory = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Graph\n try {\n const { getGraphStats } = await import('../memory/graph.js');\n const stats = getGraphStats();\n checks.graph = { status: 'ok', detail: `${stats.episodeCount} episodes, ${stats.entityCount} entities` };\n } catch (e) {\n checks.graph = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Vectors\n try {\n const { isVectorSearchAvailable } = await import('../memory/vectors.js');\n checks.vectors = { status: isVectorSearchAvailable() ? 'ok' : 'degraded', detail: isVectorSearchAvailable() ? 'ready' : 'disabled or unavailable' };\n if (!isVectorSearchAvailable() && overall === 'ok') overall = 'degraded';\n } catch (e) {\n checks.vectors = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Providers\n try {\n const providerHealth = await healthCheckAll();\n const entries = Object.entries(providerHealth);\n const healthyProviders = entries.filter(([, healthy]) => healthy).length;\n checks.providers = { status: healthyProviders > 0 ? 'ok' : 'down', detail: `${healthyProviders}/${entries.length} healthy` };\n if (healthyProviders === 0) overall = 'down';\n } catch (e) {\n checks.providers = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Channels\n try {\n const connected = Array.from(channels.values()).filter((c) => c.getStatus().connected).length;\n checks.channels = { status: connected > 0 ? 'ok' : 'degraded', detail: `${connected}/${channels.size} connected` };\n if (connected === 0 && overall === 'ok') overall = 'degraded';\n } catch (e) {\n checks.channels = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Event loop lag (approximate via setImmediate)\n const start = process.hrtime.bigint();\n await new Promise((resolve) => setImmediate(resolve));\n const lagNs = Number(process.hrtime.bigint() - start);\n const lagMs = lagNs / 1_000_000;\n checks.eventLoop = { status: lagMs < 100 ? 'ok' : lagMs < 500 ? 'degraded' : 'down', detail: `${lagMs.toFixed(2)}ms lag` };\n if (lagMs >= 500) overall = 'down';\n else if (lagMs >= 100 && overall === 'ok') overall = 'degraded';\n\n res.status(overall === 'ok' ? 200 : overall === 'degraded' ? 200 : 503).json({\n status: overall,\n version: TITAN_VERSION,\n uptime: process.uptime(),\n checks,\n });\n });\n\n // ── Monitors API ─────────────────────────────────────────────────\n app.get('/api/monitors', (_req, res) => {\n try {\n res.json({ monitors: listMonitors(), events: getMonitorEvents().slice(-50) });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.post('/api/monitors', (req, res) => {\n try {\n const { name, prompt, triggerType, intervalMinutes } = req.body;\n if (!name || !prompt) { res.status(400).json({ error: 'name and prompt are required' }); return; }\n const monitor = addMonitor({ name, prompt, triggerType: triggerType || 'interval', intervalMinutes: intervalMinutes || 60 } as any);\n res.status(201).json(monitor);\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.delete('/api/monitors/:id', (req, res) => {\n try {\n removeMonitor(req.params.id);\n res.json({ ok: true });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n\n app.use('/api', createTestsRouter());\n app.use('/api', createHardwareRouter(broadcast));\n app.use('/api', createMetricsRouter());\n app.use('/api', createMcpRouter());\n app.use('/api', createAgentsRouter());\n\n // Agent message endpoint (uses multi-agent routing)\n // Supports SSE streaming when Accept: text/event-stream header is present\n app.post('/api/message', rateLimit(defaultRateLimitWindowMs, defaultRateLimitMax), concurrencyGuard(MAX_CONCURRENT_MESSAGES), async (req, res) => {\n // v5.5.28 FIX: accept either {content} (canonical) or {message} (legacy\n // shape used by community SDKs / older clients). Previously rejected\n // {message} with 400. The body destructuring uses `content` internally\n // either way.\n const body = (req.body || {}) as Record<string, unknown>;\n const content = (typeof body.content === 'string' && body.content) || (typeof body.message === 'string' && body.message) || '';\n const { channel: rawChannel, userId = 'api-user', agentId, sessionId: requestedSessionId, model: requestedModel, systemPromptAppendix } = body as { channel?: string; userId?: string; agentId?: string; sessionId?: string; model?: string; systemPromptAppendix?: string };\n // Default channel to 'webchat' for browser-based Mission Control clients.\n // This enables the interactive plan approval flow (show plan → user approves/denies).\n // Programmatic API callers can explicitly pass channel: 'api' to auto-approve plans.\n const channel = rawChannel || (req.headers.accept === 'text/event-stream' ? 'webchat' : 'api');\n if (!content || typeof content !== 'string') {\n res.status(400).json({ error: 'content (or message) must be a non-empty string' });\n return;\n }\n\n // v5.5.30 FIX: validate `model` early so a bad provider ID returns 400\n // before the agent loop runs. Previously a typoed provider crashed\n // deep inside processMessage with 500 + stack trace AFTER the prompt\n // had been built — wasted work and a confusing error for the caller.\n if (requestedModel && typeof requestedModel === 'string') {\n const { tryResolveModel, getKnownProviderNames } = await import('../providers/router.js');\n if (!tryResolveModel(requestedModel)) {\n const providers = getKnownProviderNames();\n const requestedProviderName = requestedModel.split('/')[0] || requestedModel;\n // Naive \"did you mean\" — find providers whose name shares a prefix\n const lc = requestedProviderName.toLowerCase();\n const suggestions = providers.filter(p => p.startsWith(lc.slice(0, 3)) || lc.includes(p)).slice(0, 5);\n res.status(400).json({\n error: 'unknown_model',\n message: `Unknown model \"${requestedModel}\". Provider \"${requestedProviderName}\" is not registered.`,\n suggestions: suggestions.length > 0 ? suggestions.map(p => `${p}/...`) : undefined,\n availableProviders: providers,\n });\n return;\n }\n }\n\n const safeUserId = channel === 'api' ? 'api-user' : (userId || 'api-user');\n\n // ═─ System Widget Shortcut ─═════════════════════════════════════\n // Fast-path: if the user is **explicitly asking for a known widget**,\n // bypass the LLM and emit the _____widget gate directly. This is fast\n // and reliable for unambiguous requests like \"open the cron widget\" or\n // \"show me the VRAM dashboard.\"\n //\n // v5.5.28 FIX: previously matched on a single keyword (e.g. `\\bmodels?\\b`)\n // which hijacked normal chat — \"tell me about the models you support\"\n // returned a Training Dashboard widget instead of an LLM response. Now\n // gated on **explicit widget intent**: the user must use a widget-noun\n // (\"widget\", \"panel\", \"dashboard\", etc.) for the shortcut to fire.\n const hasExplicitWidgetIntent = /\\b(?:widget|panel|dashboard|monitor|hub|tab|page|view|gallery|kitchen|scheduler|router|lab|tools)\\b/i.test(content);\n const systemWidgetShortcuts: Array<{ pattern: RegExp; source: string; name: string; w: number; h: number }> = [\n { pattern: /\\b(?:backups?|snapshots?|archives?)\\b/i, source: 'system:backup', name: 'Backup Manager', w: 6, h: 6 },\n { pattern: /\\b(?:training|train|specialists?|models?)\\b/i, source: 'system:training', name: 'Training Dashboard', w: 6, h: 6 },\n { pattern: /\\b(?:recipes?|playbooks?|workflows?|jarvis)\\b/i, source: 'system:recipes', name: 'Recipe Kitchen', w: 6, h: 6 },\n { pattern: /\\b(?:vram|gpu|memory|nvidia)\\b/i, source: 'system:vram', name: 'VRAM Monitor', w: 6, h: 6 },\n { pattern: /\\b(?:teams?|members?|roles?|permissions?|rbac)\\b/i, source: 'system:teams', name: 'Team Hub', w: 6, h: 6 },\n { pattern: /\\b(?:cron|schedules?|jobs?|timers?)\\b/i, source: 'system:cron', name: 'Cron Scheduler', w: 6, h: 6 },\n { pattern: /\\b(?:checkpoints?|restores?|save state)\\b/i, source: 'system:checkpoints', name: 'Checkpoints', w: 6, h: 5 },\n { pattern: /\\b(?:organism|drives?|safety|alerts?|guardrails?)\\b/i, source: 'system:organism', name: 'Organism Monitor', w: 6, h: 6 },\n { pattern: /\\b(?:fleet|nodes?|routes?|mesh)\\b/i, source: 'system:fleet', name: 'Fleet Router', w: 6, h: 5 },\n { pattern: /\\b(?:captcha|browsers?|form fill|web automation)\\b/i, source: 'system:browser', name: 'Browser Tools', w: 6, h: 5 },\n { pattern: /\\b(?:paperclip|sidecars?|helpers?)\\b/i, source: 'system:paperclip', name: 'Paperclip', w: 6, h: 5 },\n { pattern: /\\b(?:tests?|flaky|failing|coverage|eval)\\b/i, source: 'system:eval', name: 'Test Lab', w: 6, h: 6 },\n ];\n const matchedShortcut = hasExplicitWidgetIntent\n ? systemWidgetShortcuts.find(s => s.pattern.test(content))\n : null;\n if (matchedShortcut) {\n const gateText = `_____widget\\n{ \"name\": \"${matchedShortcut.name}\", \"format\": \"system\", \"source\": \"${matchedShortcut.source}\", \"w\": ${matchedShortcut.w}, \"h\": ${matchedShortcut.h} }`;\n const responseText = `Added the **${matchedShortcut.name}** widget to your canvas.`;\n titanRequestsTotal.increment({ channel, status: 'ok' });\n if (req.headers.accept === 'text/event-stream') {\n res.setHeader('Content-Type', 'text/event-stream');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n sseWrite(`event: token\\ndata: ${JSON.stringify({ text: responseText })}\\n\\n`);\n sseWrite(`event: token\\ndata: ${JSON.stringify({ text: '\\n\\n' + gateText })}\\n\\n`);\n sseWrite(`event: done\\ndata: ${JSON.stringify({ content: responseText + '\\n\\n' + gateText, sessionId: requestedSessionId || null, durationMs: 0, toolsUsed: [] })}\\n\\n`);\n res.end();\n } else {\n res.json({ content: responseText + '\\n\\n' + gateText, sessionId: requestedSessionId || null, toolsUsed: [], model: 'system', durationMs: 0 });\n }\n return;\n }\n\n const startTime = process.hrtime.bigint();\n const wantsSSE = req.headers.accept === 'text/event-stream';\n\n // Validate session ID format (prevent injection)\n if (requestedSessionId && !/^[a-zA-Z0-9_:-]{1,128}$/.test(requestedSessionId)) {\n res.status(400).json({ error: 'Invalid session ID format' });\n return;\n }\n\n // Set up abort controller for this request\n const abortController = new AbortController();\n if (requestedSessionId) {\n sessionAborts.set(requestedSessionId, abortController);\n sessionAbortTimes.set(requestedSessionId, Date.now());\n // S3: Track session ownership\n if (!sessionOwners.has(requestedSessionId)) {\n sessionOwners.set(requestedSessionId, getUserIdFromReq(req));\n }\n }\n\n // Check slash commands first (same as handleInboundMessage)\n try {\n const slashResult = await handleSlashCommand(content, channel, userId);\n if (slashResult) {\n titanRequestsTotal.increment({ channel, status: 'ok' });\n const durationSec = Number(process.hrtime.bigint() - startTime) / 1e9;\n titanRequestDuration.observe(durationSec, { channel });\n if (wantsSSE) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n sseWrite(`event: done\\ndata: ${JSON.stringify({ content: slashResult.response, sessionId: null, durationMs: 0 })}\\n\\n`);\n res.end();\n } else {\n res.json({ content: slashResult.response, sessionId: null, toolsUsed: [], model: 'system' });\n }\n return;\n }\n } catch { /* fall through to routeMessage */ }\n\n // ── Auto-detect credentials in user messages ──────────────────────\n // If the user pastes a Home Assistant URL + JWT token, save them automatically\n // before the LLM even sees the message (prevents hallucination / tool-skip).\n try {\n const haKeywords = /home\\s*assistant|homeassistant|\\bha\\b\\s*(token|url|key|setup|connect)/i;\n const jwtPattern = /eyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/;\n const urlPattern = /https?:\\/\\/[^\\s,'\"]+/i;\n if (haKeywords.test(content) && (jwtPattern.test(content) || urlPattern.test(content))) {\n const jwtMatch = content.match(jwtPattern);\n const urlMatch = content.match(urlPattern);\n const cfg = loadConfig();\n let saved = false;\n if (jwtMatch && (!cfg.homeAssistant?.token || cfg.homeAssistant.token !== jwtMatch[0])) {\n // Security: store in config but log a warning about plaintext storage\n cfg.homeAssistant.token = jwtMatch[0];\n saved = true;\n logger.warn(COMPONENT, '[Security] Home Assistant token auto-saved to config. Consider using the vault for credential storage.');\n }\n if (urlMatch && urlMatch[0].match(/:\\d{4}/) && (!cfg.homeAssistant?.url || cfg.homeAssistant.url !== urlMatch[0].replace(/\\/+$/, ''))) {\n cfg.homeAssistant.url = urlMatch[0].replace(/\\/+$/, '');\n saved = true;\n }\n if (saved) {\n updateConfig({ homeAssistant: cfg.homeAssistant });\n logger.info('Gateway', 'Auto-saved Home Assistant credentials from user message');\n }\n }\n } catch { /* non-critical — let the LLM handle it */ }\n\n // Concurrent LLM request limit (auto-tuned to 2 on CPU-only systems)\n const maxConcurrent = maxConcurrentOverride ?? (loadConfig().security.maxConcurrentTasks || 5);\n if (activeLlmRequests >= maxConcurrent) {\n titanRequestsTotal.increment({ channel, status: 'busy' });\n titanErrorsTotal.increment({ type: 'busy' });\n if (wantsSSE) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n sseWrite(`event: done\\ndata: ${JSON.stringify({ error: 'Server busy' })}\\n\\n`);\n res.end();\n } else {\n res.status(503).json({ error: 'Server busy — too many concurrent requests. Try again shortly.' });\n }\n return;\n }\n activeLlmRequests++;\n titanActiveSessions.inc();\n // Track client disconnect to avoid writing to dead connections\n let clientDisconnected = false;\n let sseWrite: ((data: string) => void) | null = null;\n try {\n if (wantsSSE) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n req.on('close', () => {\n clientDisconnected = true;\n // Abort the in-progress LLM call so we don't keep streaming to a gone client.\n abortController.abort('client disconnected');\n });\n\n sseWrite = setupSSEFlush(res);\n const safeWrite = (data: string) => {\n if (clientDisconnected) return;\n try { sseWrite!(data); } catch { clientDisconnected = true; }\n };\n\n const response = await routeMessage(content, channel, safeUserId, {\n streamCallbacks: {\n onToken: (token: string) => {\n safeWrite(`event: token\\ndata: ${JSON.stringify({ text: token })}\\n\\n`);\n },\n onToolCall: (name: string, args: Record<string, unknown>) => {\n safeWrite(`event: tool_call\\ndata: ${JSON.stringify({ name, args, timestamp: Date.now() })}\\n\\n`);\n },\n onToolResult: (name: string, result: string, durationMs: number, success: boolean, diff?: string) => {\n safeWrite(`event: tool_end\\ndata: ${JSON.stringify({ name, result: result.slice(0, 500), durationMs, success, diff, timestamp: Date.now() })}\\n\\n`);\n },\n onThinking: () => {\n safeWrite(`event: thinking\\ndata: ${JSON.stringify({ timestamp: Date.now() })}\\n\\n`);\n },\n onRound: (round: number, maxRounds: number) => {\n safeWrite(`event: round\\ndata: ${JSON.stringify({ round, maxRounds, timestamp: Date.now() })}\\n\\n`);\n },\n // Dedicated `retry` SSE event so the UI can show a status indicator.\n // Pre-fix the router yielded retry banners as `text` chunks which\n // ended up in the user-visible message; this isolates the signal.\n onRetry: (info) => {\n safeWrite(`event: retry\\ndata: ${JSON.stringify({ ...info, timestamp: Date.now() })}\\n\\n`);\n },\n onFailover: (info) => {\n safeWrite(`event: failover\\ndata: ${JSON.stringify({ ...info, timestamp: Date.now() })}\\n\\n`);\n },\n },\n overrideAgentId: agentId,\n signal: abortController.signal,\n sessionId: requestedSessionId,\n modelOverride: requestedModel,\n systemPromptAppendix: typeof systemPromptAppendix === 'string' ? systemPromptAppendix : undefined,\n });\n titanRequestsTotal.increment({ channel, status: 'ok' });\n if (response.toolsUsed) {\n for (const tool of response.toolsUsed) titanToolCallsTotal.increment({ tool });\n }\n if (response.tokenUsage) {\n if (response.tokenUsage.prompt) titanTokensTotal.increment({ type: 'prompt' }, response.tokenUsage.prompt);\n if (response.tokenUsage.completion) titanTokensTotal.increment({ type: 'completion' }, response.tokenUsage.completion);\n }\n if (response.model) titanModelRequestsTotal.increment({ model: response.model, provider: 'default' });\n trackUsage(response.model || 'unknown', response.tokenUsage, response.durationMs || 0, response.sessionId || '');\n // Hunt Finding #11: sanitize SSE response content as well\n try {\n const { sanitizeOutbound } = await import('../utils/outboundSanitizer.js');\n const sanitized = sanitizeOutbound(\n response.content || '',\n 'api_message_sse',\n \"I'm TITAN — I can run commands, edit files, search the web, remember things, and more. What would you like me to help with?\",\n );\n if (sanitized.hadIssues) {\n logger.warn(COMPONENT, `[OutboundGuard] SSE /api/message response sanitized: ${sanitized.issues.join(', ')}`);\n response.content = sanitized.text;\n }\n } catch { /* sanitizer unavailable */ }\n if (!clientDisconnected) {\n safeWrite(`event: done\\ndata: ${JSON.stringify({ content: response.content, sessionId: response.sessionId, durationMs: response.durationMs, model: response.model, toolsUsed: response.toolsUsed, pendingApproval: response.pendingApproval })}\\n\\n`);\n try { res.end(); } catch { /* client gone */ }\n }\n } else {\n const response = await routeMessage(content, channel, safeUserId, {\n overrideAgentId: agentId,\n signal: abortController.signal,\n sessionId: requestedSessionId,\n modelOverride: requestedModel,\n systemPromptAppendix: typeof systemPromptAppendix === 'string' ? systemPromptAppendix : undefined,\n });\n titanRequestsTotal.increment({ channel, status: 'ok' });\n if (response.toolsUsed) {\n for (const tool of response.toolsUsed) titanToolCallsTotal.increment({ tool });\n }\n if (response.tokenUsage) {\n if (response.tokenUsage.prompt) titanTokensTotal.increment({ type: 'prompt' }, response.tokenUsage.prompt);\n if (response.tokenUsage.completion) titanTokensTotal.increment({ type: 'completion' }, response.tokenUsage.completion);\n }\n if (response.model) titanModelRequestsTotal.increment({ model: response.model, provider: 'default' });\n trackUsage(response.model || 'unknown', response.tokenUsage, response.durationMs || 0, response.sessionId || '');\n // Hunt Finding #11 (2026-04-14): sanitize outbound content before returning\n // to user. Catches system prompt leaks, instruction echoes, tool artifacts.\n // Defense-in-depth: the system prompt tells the model not to leak, but if the\n // model ignores that, this catches it.\n try {\n const { sanitizeOutbound } = await import('../utils/outboundSanitizer.js');\n const sanitized = sanitizeOutbound(\n response.content || '',\n 'api_message',\n \"I'm TITAN — I can run commands, edit files, search the web, remember things, and more. What would you like me to help with?\",\n );\n if (sanitized.hadIssues) {\n logger.warn(COMPONENT, `[OutboundGuard] /api/message response sanitized: ${sanitized.issues.join(', ')}`);\n response.content = sanitized.text;\n }\n } catch { /* sanitizer unavailable — non-critical */ }\n res.json(response);\n }\n } catch (error) {\n titanRequestsTotal.increment({ channel, status: 'error' });\n titanErrorsTotal.increment({ type: 'request' });\n // Capture a structured bug report for the operator + agent team to\n // review. Best-effort — never gates the user-facing error path.\n try {\n const { captureBugReport } = await import('../analytics/bugReports.js');\n await captureBugReport(error, {\n origin: 'gateway./api/message',\n channel,\n sessionId: requestedSessionId,\n model: typeof requestedModel === 'string' ? requestedModel : undefined,\n lastUserMessage: typeof content === 'string' ? content : undefined,\n turnNumber: undefined,\n });\n } catch { /* never let bug capture break the request path */ }\n // Classify the error so the UI can render an actionable banner instead of a stack trace\n const structured = classifyChatError(error as Error);\n if (wantsSSE && !clientDisconnected && sseWrite) {\n try { sseWrite(`event: done\\ndata: ${JSON.stringify(structured)}\\n\\n`); res.end(); } catch { /* client gone */ }\n } else if (!wantsSSE) {\n res.status(structured.status).json(structured);\n }\n } finally {\n activeLlmRequests--;\n titanActiveSessions.dec();\n const durationSec = Number(process.hrtime.bigint() - startTime) / 1e9;\n titanRequestDuration.observe(durationSec, { channel });\n if (requestedSessionId) sessionAborts.delete(requestedSessionId);\n }\n });\n\n // SSE streaming endpoint — real token-by-token delivery\n app.post('/api/chat/stream', rateLimit(60000, 30), concurrencyGuard(10), async (req, res) => {\n const { content, model } = req.body;\n if (!content) { res.status(400).json({ error: 'content is required' }); return; }\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n\n try {\n const config = loadConfig();\n const modelId = model || config.agent.model || 'anthropic/claude-sonnet-4-20250514';\n const systemMessages = [{ role: 'system' as const, content: `You are TITAN, an intelligent assistant.` }];\n const userMessages = [{ role: 'user' as const, content }];\n\n for await (const chunk of chatStream({ model: modelId, messages: [...systemMessages, ...userMessages], maxTokens: config.agent.maxTokens, temperature: config.agent.temperature })) {\n sseWrite(`data: ${JSON.stringify(chunk)}\\n\\n`);\n if (chunk.type === 'done' || chunk.type === 'error') break;\n }\n } catch (error) {\n logger.error(COMPONENT, `Stream error: ${(error as Error).message}`);\n sseWrite(`data: ${JSON.stringify({ type: 'error', error: 'The assistant hit a snag. Please refresh and try again.' })}\\n\\n`);\n }\n res.end();\n });\n\n // Cost optimizer endpoint for Mission Control\n app.get('/api/costs', (_req, res) => {\n res.json(getCostStatus());\n });\n\n // Usage tracking — per-model cost breakdown\n app.get('/api/usage', (req, res) => {\n const hours = parseInt(req.query.hours as string) || 24;\n const cutoff = new Date(Date.now() - hours * 3600_000).toISOString();\n const recent = usageLog.filter(e => e.timestamp >= cutoff);\n\n // Aggregate by model\n const byModel: Record<string, { requests: number; promptTokens: number; completionTokens: number; totalTokens: number; estimatedCostUsd: number; avgDurationMs: number }> = {};\n for (const e of recent) {\n if (!byModel[e.model]) byModel[e.model] = { requests: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0, estimatedCostUsd: 0, avgDurationMs: 0 };\n const m = byModel[e.model];\n m.requests++;\n m.promptTokens += e.promptTokens;\n m.completionTokens += e.completionTokens;\n m.totalTokens += e.totalTokens;\n m.estimatedCostUsd += e.estimatedCostUsd;\n m.avgDurationMs = (m.avgDurationMs * (m.requests - 1) + e.durationMs) / m.requests;\n }\n\n // Round costs\n for (const m of Object.values(byModel)) {\n m.estimatedCostUsd = Math.round(m.estimatedCostUsd * 10000) / 10000;\n m.avgDurationMs = Math.round(m.avgDurationMs);\n }\n\n const totalCost = Object.values(byModel).reduce((sum, m) => sum + m.estimatedCostUsd, 0);\n\n res.json({\n period: `${hours}h`,\n totalRequests: recent.length,\n totalTokens: recent.reduce((sum, e) => sum + e.totalTokens, 0),\n estimatedCostUsd: Math.round(totalCost * 10000) / 10000,\n byModel,\n recentEntries: recent.slice(-20), // Last 20 for detail view\n });\n });\n\n // Update System endpoints\n app.get('/api/update', async (_req, res) => {\n const info = await getUpdateInfo();\n res.json(info);\n });\n\n app.post('/api/update', (req, res) => {\n const isLocalDev = fs.existsSync(join(process.cwd(), '.git'));\n const isSystemd = fs.existsSync('/run/systemd/system') ||\n fs.existsSync(join(process.cwd(), '.systemd-service'));\n const restart = req.body?.restart === true;\n\n let command: string;\n let postCommand: string | null = null;\n\n if (isLocalDev) {\n // Development checkout — pull source + build\n command = 'git pull && npm run build';\n if (restart) {\n // Write restart script + exit\n postCommand = 'restart'; // handled below\n }\n } else if (isSystemd) {\n // Production systemd deployment — pull from git repo + restart service\n command = 'git pull && npm run build';\n if (restart) {\n postCommand = 'systemctl';\n }\n } else {\n // Global npm install — works only when user has write access to prefix\n command = 'npm update -g titan-agent';\n }\n\n logger.info(COMPONENT, `Triggering update: ${command} (isDev=${isLocalDev}, isSystemd=${isSystemd}, restart=${restart})`);\n\n exec(command, { timeout: 180_000 }, (error, stdout, _stderr) => {\n if (error) {\n logger.error(COMPONENT, `Update failed: ${error.message}`);\n if (!res.headersSent) res.json({ ok: false, error: error.message });\n return;\n }\n\n logger.info(COMPONENT, `Update completed successfully.\\\\n${stdout}`);\n if (!res.headersSent) {\n res.json({ ok: true, message: 'Update completed', restarting: restart, output: stdout.slice(-500) });\n }\n\n if (restart) {\n logger.info(COMPONENT, 'Scheduling restart in 2 seconds...');\n const cwd = process.cwd();\n\n if (postCommand === 'systemctl') {\n // Production: use systemctl to restart (requires user passwordless sudo rights)\n const scriptPath = '/tmp/titan-restart.sh';\n fs.writeFileSync(scriptPath, [\n '#!/bin/bash',\n 'sleep 2',\n `cd \"${cwd}\"`,\n 'sudo systemctl restart titan-gateway',\n ].join('\\n'), { mode: 0o755 });\n spawn('bash', [scriptPath], { detached: true, stdio: 'ignore' }).unref();\n } else {\n // Dev or global: spawn node directly\n const scriptPath = '/tmp/titan-restart.sh';\n fs.writeFileSync(scriptPath, [\n '#!/bin/bash',\n 'sleep 2',\n `cd \"${cwd}\"`,\n 'nohup node dist/cli/index.js gateway >> /tmp/titan-gateway.log 2>&1 &',\n ].join('\\n'), { mode: 0o755 });\n spawn('bash', [scriptPath], { detached: true, stdio: 'ignore' }).unref();\n }\n\n setTimeout(() => {\n logger.info(COMPONENT, 'Exiting for restart...');\n process.exit(0);\n }, 1000);\n }\n });\n });\n\n // Config endpoints\n app.get('/api/config', (_req, res) => {\n const cfg = loadConfig();\n // Return config with sensitive fields masked\n res.json({\n model: cfg.agent.model,\n provider: cfg.agent.model?.split('/')[0] || 'openai',\n voice: {\n enabled: Boolean(cfg.voice?.enabled),\n livekitUrl: cfg.voice?.livekitUrl || '',\n agentUrl: cfg.voice?.agentUrl || '',\n ttsEngine: cfg.voice?.ttsEngine || 'f5-tts',\n ttsUrl: cfg.voice?.ttsUrl || 'http://localhost:5006',\n ttsVoice: cfg.voice?.ttsVoice || 'tara',\n sttUrl: cfg.voice?.sttUrl || 'http://localhost:48421',\n sttEngine: cfg.voice?.sttEngine || 'faster-whisper',\n model: cfg.voice?.model || '',\n },\n agent: { ...cfg.agent, systemPrompt: undefined, systemPromptConfigured: Boolean(cfg.agent.systemPrompt) },\n autonomy: cfg.autonomy,\n security: {\n sandboxMode: cfg.security.sandboxMode,\n shield: cfg.security.shield,\n deniedTools: cfg.security.deniedTools || [],\n networkAllowlist: cfg.security.networkAllowlist || [],\n },\n gateway: {\n port: cfg.gateway.port,\n host: cfg.gateway.host,\n auth: { mode: cfg.gateway.auth.mode },\n },\n logging: cfg.logging,\n providers: {\n anthropic: { configured: Boolean(cfg.providers.anthropic?.apiKey) },\n openai: { configured: Boolean(cfg.providers.openai?.apiKey) },\n google: { configured: Boolean(cfg.providers.google?.apiKey) },\n ollama: { baseUrl: cfg.providers.ollama?.baseUrl || 'http://localhost:11434' },\n groq: { configured: Boolean(cfg.providers.groq?.apiKey) },\n mistral: { configured: Boolean(cfg.providers.mistral?.apiKey) },\n fireworks: { configured: Boolean(cfg.providers.fireworks?.apiKey) },\n xai: { configured: Boolean(cfg.providers.xai?.apiKey) },\n together: { configured: Boolean(cfg.providers.together?.apiKey) },\n deepseek: { configured: Boolean(cfg.providers.deepseek?.apiKey) },\n perplexity: { configured: Boolean(cfg.providers.perplexity?.apiKey) },\n },\n oauth: {\n google: {\n clientIdSet: Boolean(cfg.oauth?.google?.clientId),\n clientSecretSet: Boolean(cfg.oauth?.google?.clientSecret),\n },\n },\n channels: Object.fromEntries(\n Object.entries(cfg.channels).map(([k, v]) => {\n const ch = v as { enabled?: boolean; token?: string; dmPolicy?: string };\n return [k, { enabled: Boolean(ch.enabled), dmPolicy: ch.dmPolicy || 'pairing' }];\n })\n ),\n nvidia: (() => {\n const nv = (cfg as Record<string, unknown>).nvidia as Record<string, unknown> | undefined;\n if (!nv) return { enabled: false, apiKeySet: false, cuopt: { enabled: false, url: 'http://localhost:5000' }, asr: { enabled: false, grpcUrl: 'localhost:50051', healthUrl: 'http://localhost:9000' }, openshell: { enabled: false, binaryPath: 'openshell', policyPath: '' } };\n return {\n enabled: Boolean(nv.enabled),\n apiKeySet: Boolean(nv.apiKey || process.env.NVIDIA_API_KEY),\n cuopt: nv.cuopt ?? { enabled: false, url: 'http://localhost:5000' },\n asr: nv.asr ?? { enabled: false, grpcUrl: 'localhost:50051', healthUrl: 'http://localhost:9000' },\n openshell: nv.openshell ?? { enabled: false, binaryPath: 'openshell', policyPath: '' },\n };\n })(),\n mesh: {\n enabled: Boolean(cfg.mesh?.enabled),\n mdns: Boolean(cfg.mesh?.mdns),\n tailscale: Boolean(cfg.mesh?.tailscale),\n maxPeers: cfg.mesh?.maxPeers ?? 5,\n autoApprove: Boolean(cfg.mesh?.autoApprove),\n },\n organism: {\n enabled: Boolean(cfg.organism?.enabled),\n hormonesInPrompt: Boolean(cfg.organism?.hormonesInPrompt),\n pressureThreshold: Number(cfg.organism?.pressureThreshold) || 0.5,\n shadowEnabled: Boolean(cfg.organism?.shadowEnabled),\n tickIntervalMs: Number(cfg.organism?.tickIntervalMs) || 60000,\n },\n commandPost: {\n enabled: Boolean((cfg as Record<string, any>).commandPost?.enabled),\n heartbeatIntervalMs: (cfg as Record<string, any>).commandPost?.heartbeatIntervalMs ?? 30000,\n maxConcurrentAgents: (cfg as Record<string, any>).commandPost?.maxConcurrentAgents ?? 10,\n checkoutTimeoutMs: (cfg as Record<string, any>).commandPost?.checkoutTimeoutMs ?? 300000,\n },\n });\n });\n\n app.post('/api/config', async (req, res) => {\n try {\n const body = req.body as Record<string, unknown>;\n const cfg = loadConfig();\n // Clone config to avoid mutating live state before validation succeeds\n const draft = structuredClone(cfg) as typeof cfg;\n\n // Track which config fields are being changed for restart detection\n const changedFields: string[] = [];\n\n if (body.model) {\n // Hunt Finding #35 (2026-04-14): POST /api/config's `model` field\n // was bypassing the shape + provider-registry validation that\n // /api/model/switch gained in #25. Same bug class: a bogus string\n // got persisted to config. Apply the same shape check here.\n const modelShapeErr = validateModelId(body.model);\n if (modelShapeErr) {\n res.status(400).json({ error: `model: ${modelShapeErr}` });\n return;\n }\n // Also validate the provider is registered (same as #25).\n const modelStr = body.model as string;\n const providerPrefix = modelStr.split('/')[0];\n if (providerPrefix && providerPrefix !== 'ollama') {\n const { getProvider } = await import('../providers/router.js');\n if (!getProvider(providerPrefix)) {\n res.status(400).json({\n error: `Unknown provider '${providerPrefix}'. Use /api/models to list available providers and models.`,\n });\n return;\n }\n }\n draft.agent.model = modelStr;\n changedFields.push('agent.model');\n }\n if (body.autonomyMode) { draft.autonomy.mode = body.autonomyMode as 'supervised' | 'autonomous' | 'locked'; changedFields.push('autonomy.mode'); }\n if (body.sandboxMode) { draft.security.sandboxMode = body.sandboxMode as 'host' | 'docker' | 'none'; changedFields.push('security.sandboxMode'); }\n if (body.logLevel) { draft.logging.level = body.logLevel as 'info' | 'debug' | 'warn' | 'silent'; changedFields.push('logging.level'); }\n // Provider API keys\n if (body.anthropicKey !== undefined) { draft.providers.anthropic.apiKey = body.anthropicKey as string; changedFields.push('providers.anthropic.apiKey'); }\n if (body.openaiKey !== undefined) { draft.providers.openai.apiKey = body.openaiKey as string; changedFields.push('providers.openai.apiKey'); }\n if (body.googleKey !== undefined) { draft.providers.google.apiKey = body.googleKey as string; changedFields.push('providers.google.apiKey'); }\n if (body.ollamaUrl !== undefined) { draft.providers.ollama.baseUrl = body.ollamaUrl as string; changedFields.push('providers.ollama.baseUrl'); }\n if (body.groqKey !== undefined) { draft.providers.groq.apiKey = body.groqKey as string; changedFields.push('providers.groq.apiKey'); }\n if (body.mistralKey !== undefined) { draft.providers.mistral.apiKey = body.mistralKey as string; changedFields.push('providers.mistral.apiKey'); }\n if (body.fireworksKey !== undefined) { draft.providers.fireworks.apiKey = body.fireworksKey as string; changedFields.push('providers.fireworks.apiKey'); }\n if (body.xaiKey !== undefined) { draft.providers.xai.apiKey = body.xaiKey as string; changedFields.push('providers.xai.apiKey'); }\n if (body.togetherKey !== undefined) { draft.providers.together.apiKey = body.togetherKey as string; changedFields.push('providers.together.apiKey'); }\n if (body.deepseekKey !== undefined) { draft.providers.deepseek.apiKey = body.deepseekKey as string; changedFields.push('providers.deepseek.apiKey'); }\n if (body.perplexityKey !== undefined) { draft.providers.perplexity.apiKey = body.perplexityKey as string; changedFields.push('providers.perplexity.apiKey'); }\n // Google OAuth\n if (body.googleOAuthClientId !== undefined) {\n if (!draft.oauth) (draft as Record<string, unknown>).oauth = { google: {} };\n draft.oauth.google.clientId = body.googleOAuthClientId as string;\n changedFields.push('oauth.google.clientId');\n }\n if (body.googleOAuthClientSecret !== undefined) {\n if (!draft.oauth) (draft as Record<string, unknown>).oauth = { google: {} };\n draft.oauth.google.clientSecret = body.googleOAuthClientSecret as string;\n changedFields.push('oauth.google.clientSecret');\n }\n // Agent settings\n if (body.maxTokens !== undefined) { draft.agent.maxTokens = Number(body.maxTokens); changedFields.push('agent.maxTokens'); }\n if (body.temperature !== undefined) { draft.agent.temperature = Number(body.temperature); changedFields.push('agent.temperature'); }\n if (body.systemPrompt !== undefined) { draft.agent.systemPrompt = body.systemPrompt as string; changedFields.push('agent.systemPrompt'); }\n // Security shield\n if (body.shieldEnabled !== undefined) { draft.security.shield.enabled = Boolean(body.shieldEnabled); changedFields.push('security.shield.enabled'); }\n if (body.shieldMode !== undefined) { draft.security.shield.mode = body.shieldMode as 'strict' | 'standard'; changedFields.push('security.shield.mode'); }\n if (body.deniedTools !== undefined) { draft.security.deniedTools = body.deniedTools as string[]; changedFields.push('security.deniedTools'); }\n if (body.networkAllowlist !== undefined) { draft.security.networkAllowlist = body.networkAllowlist as string[]; changedFields.push('security.networkAllowlist'); }\n // Gateway\n if (body.gatewayPort !== undefined) { draft.gateway.port = Number(body.gatewayPort); changedFields.push('gateway.port'); }\n if (body.gatewayAuthMode !== undefined) { draft.gateway.auth.mode = body.gatewayAuthMode as 'none' | 'token' | 'password'; changedFields.push('gateway.auth.mode'); }\n if (body.gatewayPassword !== undefined) { draft.gateway.auth.password = body.gatewayPassword as string; changedFields.push('gateway.auth.password'); }\n if (body.gatewayToken !== undefined) { draft.gateway.auth.token = body.gatewayToken as string; changedFields.push('gateway.auth.token'); }\n // Voice settings (nested object from SettingsPanel)\n if (body.voice !== undefined && typeof body.voice === 'object') {\n const v = body.voice as Record<string, unknown>;\n if (v.enabled !== undefined) draft.voice.enabled = Boolean(v.enabled);\n if (v.livekitUrl !== undefined) draft.voice.livekitUrl = String(v.livekitUrl);\n if (v.livekitApiKey !== undefined) draft.voice.livekitApiKey = String(v.livekitApiKey);\n if (v.livekitApiSecret !== undefined) draft.voice.livekitApiSecret = String(v.livekitApiSecret);\n if (v.agentUrl !== undefined) draft.voice.agentUrl = String(v.agentUrl);\n if (v.ttsVoice !== undefined) draft.voice.ttsVoice = String(v.ttsVoice);\n if (v.ttsEngine !== undefined) draft.voice.ttsEngine = String(v.ttsEngine) as typeof draft.voice.ttsEngine;\n if (v.ttsUrl !== undefined) draft.voice.ttsUrl = String(v.ttsUrl);\n if (v.sttUrl !== undefined) draft.voice.sttUrl = String(v.sttUrl);\n if (v.sttEngine !== undefined) draft.voice.sttEngine = String(v.sttEngine) as typeof draft.voice.sttEngine;\n if (v.model !== undefined) (draft.voice as Record<string, unknown>).model = String(v.model) || undefined;\n changedFields.push('voice');\n }\n // Home Assistant\n if (body.homeAssistantUrl !== undefined) { draft.homeAssistant.url = body.homeAssistantUrl as string; changedFields.push('homeAssistant.url'); }\n if (body.homeAssistantToken !== undefined) { draft.homeAssistant.token = body.homeAssistantToken as string; changedFields.push('homeAssistant.token'); }\n // Channels\n if (body.channels !== undefined && typeof body.channels === 'object') {\n for (const [ch, val] of Object.entries(body.channels as Record<string, unknown>)) {\n if (draft.channels[ch as keyof typeof draft.channels]) {\n Object.assign(draft.channels[ch as keyof typeof draft.channels], val);\n changedFields.push(`channels.${ch}`);\n }\n }\n }\n // NVIDIA config (nested object)\n if (body.nvidia !== undefined && typeof body.nvidia === 'object') {\n const nv = body.nvidia as Record<string, unknown>;\n const nvCfg = ((draft as Record<string, unknown>).nvidia || {}) as Record<string, unknown>;\n if (nv.enabled !== undefined) nvCfg.enabled = Boolean(nv.enabled);\n if (nv.apiKey !== undefined) nvCfg.apiKey = String(nv.apiKey);\n if (nv.cuopt !== undefined && typeof nv.cuopt === 'object') {\n const cuopt = (nvCfg.cuopt || {}) as Record<string, unknown>;\n const src = nv.cuopt as Record<string, unknown>;\n if (src.enabled !== undefined) cuopt.enabled = Boolean(src.enabled);\n if (src.url !== undefined) cuopt.url = String(src.url);\n nvCfg.cuopt = cuopt;\n }\n if (nv.asr !== undefined && typeof nv.asr === 'object') {\n const asr = (nvCfg.asr || {}) as Record<string, unknown>;\n const src = nv.asr as Record<string, unknown>;\n if (src.enabled !== undefined) asr.enabled = Boolean(src.enabled);\n if (src.grpcUrl !== undefined) asr.grpcUrl = String(src.grpcUrl);\n if (src.healthUrl !== undefined) asr.healthUrl = String(src.healthUrl);\n nvCfg.asr = asr;\n }\n if (nv.openshell !== undefined && typeof nv.openshell === 'object') {\n const os = (nvCfg.openshell || {}) as Record<string, unknown>;\n const src = nv.openshell as Record<string, unknown>;\n if (src.enabled !== undefined) os.enabled = Boolean(src.enabled);\n if (src.binaryPath !== undefined) os.binaryPath = String(src.binaryPath);\n if (src.policyPath !== undefined) os.policyPath = String(src.policyPath);\n nvCfg.openshell = os;\n }\n (draft as Record<string, unknown>).nvidia = nvCfg;\n changedFields.push('nvidia');\n }\n // Organism / SOMA toggle\n if (body.organism !== undefined && typeof body.organism === 'object') {\n const org = body.organism as Record<string, unknown>;\n if (!draft.organism) (draft as Record<string, unknown>).organism = {};\n if (org.enabled !== undefined) draft.organism.enabled = Boolean(org.enabled);\n if (org.hormonesInPrompt !== undefined) draft.organism.hormonesInPrompt = Boolean(org.hormonesInPrompt);\n if (org.pressureThreshold !== undefined) draft.organism.pressureThreshold = Number(org.pressureThreshold);\n if (org.shadowEnabled !== undefined) draft.organism.shadowEnabled = Boolean(org.shadowEnabled);\n if (org.tickIntervalMs !== undefined) draft.organism.tickIntervalMs = Number(org.tickIntervalMs);\n changedFields.push('organism');\n }\n\n // Autonomy toggles (v5.0.2 — Autonomy Settings Panel)\n const handleNestedBool = (section: string, key: string, target: Record<string, unknown>) => {\n const sec = body[section] as Record<string, unknown> | undefined;\n if (sec && key in sec) {\n target[key] = Boolean(sec[key]);\n changedFields.push(`${section}.${key}`);\n }\n };\n if (body.autonomy !== undefined && typeof body.autonomy === 'object') {\n const a = body.autonomy as Record<string, unknown>;\n if (!draft.autonomy) (draft as Record<string, unknown>).autonomy = {};\n const da = draft.autonomy as Record<string, unknown>;\n if (a.mode !== undefined) da.mode = a.mode as 'autonomous' | 'supervised' | 'locked';\n if (a.autoProposeGoals !== undefined) da.autoProposeGoals = Boolean(a.autoProposeGoals);\n if (a.proactiveInitiative !== undefined) da.proactiveInitiative = Boolean(a.proactiveInitiative);\n changedFields.push('autonomy');\n }\n if (body.selfMod !== undefined && typeof body.selfMod === 'object') {\n const s = body.selfMod as Record<string, unknown>;\n if (!draft.selfMod) (draft as Record<string, unknown>).selfMod = {};\n if (s.enabled !== undefined) draft.selfMod.enabled = Boolean(s.enabled);\n if (s.autoPR !== undefined) draft.selfMod.autoPR = Boolean(s.autoPR);\n changedFields.push('selfMod');\n }\n if (body.commandPost !== undefined && typeof body.commandPost === 'object') {\n const cp = body.commandPost as Record<string, unknown>;\n if (!draft.commandPost) (draft as Record<string, unknown>).commandPost = {};\n if (cp.enabled !== undefined) draft.commandPost.enabled = Boolean(cp.enabled);\n changedFields.push('commandPost');\n }\n if (body.mesh !== undefined && typeof body.mesh === 'object') {\n const m = body.mesh as Record<string, unknown>;\n if (!draft.mesh) (draft as Record<string, unknown>).mesh = {};\n if (m.enabled !== undefined) draft.mesh.enabled = Boolean(m.enabled);\n changedFields.push('mesh');\n }\n if (body.autopilot !== undefined && typeof body.autopilot === 'object') {\n const ap = body.autopilot as Record<string, unknown>;\n if (!draft.autopilot) (draft as Record<string, unknown>).autopilot = {};\n if (ap.enabled !== undefined) draft.autopilot.enabled = Boolean(ap.enabled);\n if (ap.goals !== undefined && typeof ap.goals === 'object') {\n const apg = ap.goals as Record<string, unknown>;\n const dag = (draft.autopilot as Record<string, unknown>);\n if (!dag.goals) dag.goals = {};\n if (apg.selfInitiate !== undefined) (dag.goals as Record<string, unknown>).selfInitiate = Boolean(apg.selfInitiate);\n }\n changedFields.push('autopilot');\n }\n if (body.brain !== undefined && typeof body.brain === 'object') {\n const b = body.brain as Record<string, unknown>;\n if (!draft.brain) (draft as Record<string, unknown>).brain = {};\n if (b.enabled !== undefined) draft.brain.enabled = Boolean(b.enabled);\n changedFields.push('brain');\n }\n if (body.mcp !== undefined && typeof body.mcp === 'object') {\n const mcp = body.mcp as Record<string, unknown>;\n if (!draft.mcp) (draft as Record<string, unknown>).mcp = { server: {} };\n if (mcp.server !== undefined && typeof mcp.server === 'object') {\n const srv = mcp.server as Record<string, unknown>;\n const dmcp = (draft.mcp as Record<string, unknown>);\n if (!dmcp.server) dmcp.server = {};\n if (srv.enabled !== undefined) (dmcp.server as Record<string, unknown>).enabled = Boolean(srv.enabled);\n }\n changedFields.push('mcp');\n }\n if (body.training !== undefined && typeof body.training === 'object') {\n const t = body.training as Record<string, unknown>;\n if (!draft.training) (draft as Record<string, unknown>).training = {};\n if (t.enabled !== undefined) draft.training.enabled = Boolean(t.enabled);\n changedFields.push('training');\n }\n if (body.teams !== undefined && typeof body.teams === 'object') {\n const t = body.teams as Record<string, unknown>;\n if (!draft.teams) (draft as Record<string, unknown>).teams = {};\n if (t.enabled !== undefined) draft.teams.enabled = Boolean(t.enabled);\n changedFields.push('teams');\n }\n if (body.tunnel !== undefined && typeof body.tunnel === 'object') {\n const t = body.tunnel as Record<string, unknown>;\n if (!draft.tunnel) (draft as Record<string, unknown>).tunnel = {};\n if (t.enabled !== undefined) draft.tunnel.enabled = Boolean(t.enabled);\n changedFields.push('tunnel');\n }\n if (body.vault !== undefined && typeof body.vault === 'object') {\n const v = body.vault as Record<string, unknown>;\n const dsec = (draft.security as Record<string, unknown>);\n if (!dsec.vault) dsec.vault = {};\n if (v.enabled !== undefined) (dsec.vault as Record<string, unknown>).enabled = Boolean(v.enabled);\n changedFields.push('security.vault');\n }\n if (body.capsolver !== undefined && typeof body.capsolver === 'object') {\n const c = body.capsolver as Record<string, unknown>;\n if (!draft.capsolver) (draft as Record<string, unknown>).capsolver = {};\n if (c.enabled !== undefined) draft.capsolver.enabled = Boolean(c.enabled);\n changedFields.push('capsolver');\n }\n if (body.deliberation !== undefined && typeof body.deliberation === 'object') {\n const d = body.deliberation as Record<string, unknown>;\n if (!draft.deliberation) (draft as Record<string, unknown>).deliberation = {};\n if (d.autoDetect !== undefined) draft.deliberation.autoDetect = Boolean(d.autoDetect);\n changedFields.push('deliberation');\n }\n if (body.selfImprove !== undefined && typeof body.selfImprove === 'object') {\n const si = body.selfImprove as Record<string, unknown>;\n if (!draft.selfImprove) (draft as Record<string, unknown>).selfImprove = {};\n if (si.autoApply !== undefined) draft.selfImprove.autoApply = Boolean(si.autoApply);\n changedFields.push('selfImprove');\n }\n if (body.memory !== undefined && typeof body.memory === 'object') {\n const mem = body.memory as Record<string, unknown>;\n if (!draft.memory) (draft as Record<string, unknown>).memory = {};\n if (mem.vectorSearchEnabled !== undefined) draft.memory.vectorSearchEnabled = Boolean(mem.vectorSearchEnabled);\n changedFields.push('memory');\n }\n\n if (changedFields.length === 0) {\n const validFields = ['model', 'autonomyMode', 'sandboxMode', 'logLevel', 'anthropicKey', 'openaiKey',\n 'googleKey', 'ollamaUrl', 'groqKey', 'mistralKey', 'fireworksKey', 'xaiKey',\n 'togetherKey', 'deepseekKey', 'perplexityKey', 'maxTokens', 'temperature', 'systemPrompt',\n 'shieldEnabled', 'shieldMode', 'deniedTools', 'networkAllowlist', 'gatewayPort', 'gatewayAuthMode',\n 'gatewayPassword', 'gatewayToken', 'channels', 'googleOAuthClientId', 'googleOAuthClientSecret',\n 'homeAssistantUrl', 'homeAssistantToken', 'voice', 'nvidia', 'organism',\n 'autonomy', 'selfMod', 'commandPost', 'mesh', 'autopilot', 'brain', 'mcp',\n 'training', 'teams', 'tunnel', 'vault', 'capsolver', 'deliberation', 'selfImprove', 'memory'];\n res.status(400).json({ error: 'No recognized fields in request body', validFields });\n return;\n }\n // Validation happens inside updateConfig (Zod parse) — draft is only applied if valid\n updateConfig(draft);\n\n // Determine which changed fields require a restart\n const restartFields = changedFields.filter(field =>\n RESTART_REQUIRED_PATTERNS.some(pattern => {\n if (pattern.endsWith('.*')) {\n return field.startsWith(pattern.slice(0, -1));\n }\n return field === pattern;\n })\n );\n\n res.json({ ok: true, restartRequired: restartFields.length > 0, restartFields });\n } catch (e) {\n // Return 400 for Zod validation errors, 500 for unexpected errors\n const isValidationError = (e as Error).name === 'ZodError' || (e as Error).message?.includes('Validation');\n res.status(isValidationError ? 400 : 500).json({ error: (e as Error).message });\n }\n });\n\n // Models endpoint — lists all providers + live Ollama models\n // Model discovery + management endpoints\n app.get('/api/models', async (_req, res) => {\n const cfg = loadConfig();\n const models = await discoverAllModels();\n // Group by provider\n const grouped: Record<string, string[]> = {};\n for (const m of models) {\n if (!grouped[m.provider]) grouped[m.provider] = [];\n grouped[m.provider].push(m.id);\n }\n res.json({\n ...grouped,\n current: cfg.agent.model,\n aliases: getModelAliases(),\n });\n });\n\n // ── Provider Status API ─────────────────────────────────────────\n app.get('/api/providers/status', async (_req, res) => {\n try {\n const { getCircuitBreakerStatus } = await import('../providers/router.js');\n const cbStatus = getCircuitBreakerStatus();\n const health = await healthCheckAll();\n const providers = Object.entries(health).map(([name, healthy]) => ({\n name,\n healthy,\n circuitBreaker: cbStatus[name] || { state: 'unknown', failureCount: 0 },\n }));\n res.json({ providers, count: providers.length });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.post('/api/providers/:name/reset', async (req, res) => {\n try {\n const { resetCircuitBreaker } = await import('../providers/router.js');\n resetCircuitBreaker(req.params.name);\n res.json({ reset: true, provider: req.params.name });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.get('/api/models/discover', async (_req, res) => {\n const models = await discoverAllModels(true);\n const cfg = loadConfig();\n res.json({\n models,\n current: cfg.agent.model,\n aliases: getModelAliases(),\n });\n });\n\n app.get('/api/fallback-state', (_req, res) => {\n const state = getFallbackState();\n res.json(state || { active: null });\n });\n\n /**\n * Hunt Finding #25 + #35 (2026-04-14): shared model-id input validator.\n * Used by BOTH /api/model/switch AND /api/config (where `body.model` takes\n * the same path). Returns a validation error string or null if valid.\n */\n function validateModelId(model: unknown): string | null {\n if (typeof model !== 'string' || model.length === 0 || model.length > 200) {\n return 'model must be a non-empty string up to 200 chars';\n }\n if (!/^[a-zA-Z0-9._:\\-/]+$/.test(model)) {\n return 'model contains invalid characters (allowed: alnum, ._:-/)';\n }\n return null;\n }\n\n app.post('/api/model/switch', async (req, res) => {\n try {\n const { model } = req.body as { model?: string };\n if (!model) { res.status(400).json({ error: 'model is required' }); return; }\n const shapeErr = validateModelId(model);\n if (shapeErr) { res.status(400).json({ error: shapeErr }); return; }\n const cfg = loadConfig();\n // Resolve aliases\n const aliases = cfg.agent.modelAliases || {};\n const resolved = aliases[model] || model;\n\n // ── CRITICAL FIX: Validate model exists for ALL providers ──\n const [providerName, ...modelParts] = resolved.split('/');\n const modelName = modelParts.join('/') || resolved; // Handle models with slashes in name\n\n // Hunt Finding #25 (2026-04-14): previously, any providerName that\n // wasn't 'ollama' fell through the `else if (providerName)` branch and\n // was accepted without validation. A POST with model=\"fake/fake-model\"\n // would succeed and write the bogus value to config, bricking the\n // gateway until manually reverted. Validate the provider exists in\n // the registered router before accepting the switch.\n if (providerName && providerName !== 'ollama') {\n const { getProvider } = await import('../providers/router.js');\n if (!getProvider(providerName)) {\n logger.warn(COMPONENT, `[ModelSwitch] Unknown provider '${providerName}' — rejecting`);\n res.status(400).json({\n error: `Unknown provider '${providerName}'. Use /api/models to list available providers and models.`,\n });\n return;\n }\n }\n\n // 1. Ollama local models — check if model is pulled\n if (providerName === 'ollama') {\n const ollamaBase = cfg.providers.ollama?.baseUrl || 'http://localhost:11434';\n // Cloud-routed models (suffix :cloud) are always valid — they proxy through Ollama to external APIs\n if (modelName.endsWith(':cloud')) {\n logger.info(COMPONENT, `[ModelSwitch] Cloud-routed model '${modelName}' — allowing (proxied via Ollama)`);\n } else {\n // Local model: verify it exists in Ollama\n try {\n const check = await fetch(`${ollamaBase}/api/show`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: modelName }),\n signal: AbortSignal.timeout(5000),\n });\n if (!check.ok) {\n logger.warn(COMPONENT, `[ModelSwitch] Model '${modelName}' not found in Ollama (HTTP ${check.status})`);\n res.status(404).json({ error: `Model '${modelName}' not found in Ollama. Pull it first: ollama pull ${modelName}` });\n return;\n }\n logger.info(COMPONENT, `[ModelSwitch] Verified Ollama model '${modelName}' exists`);\n } catch (err) {\n // CRITICAL FIX: Ollama unreachable — reject the switch instead of allowing it\n logger.error(COMPONENT, `[ModelSwitch] Ollama unreachable at ${ollamaBase}: ${(err as Error).message}`);\n res.status(503).json({\n error: `Cannot verify model '${modelName}' — Ollama is unreachable at ${ollamaBase}. Check Ollama is running: ollama serve`,\n });\n return;\n }\n }\n } else if (providerName) {\n // 2. Other providers — just log the provider (allow the switch)\n // We trust the user to configure API keys; reject only happens at chat time\n logger.info(COMPONENT, `[ModelSwitch] Switching to provider '${providerName.toLowerCase()}' model '${modelName}'`);\n }\n // If no provider prefix (bare model like 'gpt-4o'), assume it's an alias or user knows what they're doing\n\n updateConfig({ agent: { ...cfg.agent, model: resolved } });\n // Invalidate cached responses for the old model so stale results aren't served\n invalidateCacheForModel(cfg.agent.model);\n logger.info(COMPONENT, `Model switched to: ${resolved}${resolved !== model ? ` (alias: ${model})` : ''}`);\n res.json({ success: true, model: resolved, alias: resolved !== model ? model : undefined });\n } catch (err) {\n logger.error(COMPONENT, `[ModelSwitch] Error: ${(err as Error).message}`);\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // ─── Model Probe — empirical capabilities discovery ──────────\n // POST /api/model/probe { model: \"ollama/glm-5.1:cloud\" }\n // POST /api/model/probe { models: [\"...\", \"...\"] }\n // GET /api/model/probe — list all probed models\n app.post('/api/model/probe', async (req, res) => {\n try {\n const body = req.body as { model?: string; models?: string[] };\n const targets = body.model ? [body.model] : (body.models || []);\n if (targets.length === 0) {\n res.status(400).json({ error: 'Provide {model: \"id\"} or {models: [\"id1\",\"id2\"]}' });\n return;\n }\n\n const { probeModel } = await import('../agent/modelProbe.js');\n const { recordProbeResult } = await import('../agent/capabilitiesRegistry.js');\n\n const results = [];\n for (const modelId of targets) {\n try {\n const result = await probeModel(modelId);\n recordProbeResult(result);\n results.push(result);\n } catch (err) {\n results.push({ model: modelId, error: (err as Error).message });\n }\n }\n res.json({ probed: results.length, results });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n app.get('/api/model/probe', async (_req, res) => {\n try {\n const { loadRegistry } = await import('../agent/capabilitiesRegistry.js');\n const registry = loadRegistry();\n res.json({\n updatedAt: registry.updatedAt,\n count: Object.keys(registry.models).length,\n models: registry.models,\n });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Profile endpoints\n app.get('/api/profile', (_req, res) => {\n const profile = loadProfile();\n res.json({\n name: profile.name || '',\n technicalLevel: profile.technicalLevel || 'unknown',\n projectCount: profile.projects.length,\n goalCount: profile.goals.length,\n });\n });\n\n app.post('/api/profile', (req, res) => {\n try {\n const { name, technicalLevel } = req.body as { name?: string; technicalLevel?: string };\n const profile = loadProfile();\n if (name !== undefined) profile.name = name;\n if (technicalLevel !== undefined) profile.technicalLevel = technicalLevel as PersonalProfile['technicalLevel'];\n saveProfile(profile);\n res.json({ ok: true });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // Learning stats endpoint\n app.get('/api/learning', (_req, res) => {\n res.json(getLearningStats());\n });\n\n app.get('/api/learning/stats', (_req, res) => {\n res.json(getLearningStats());\n });\n\n // Live log tail endpoint\n app.get('/api/logs', (req, res) => {\n try {\n const logPath = getLogFilePath();\n if (!logPath || !fs.existsSync(logPath)) {\n res.json({ lines: [] });\n return;\n }\n const lineCount = req.query.lines ? parseInt(req.query.lines as string, 10) : 200;\n // Read only the last portion of the file\n const stats = fs.statSync(logPath);\n const readSize = Math.min(stats.size, 100000); // Read last 100KB max\n const fd = fs.openSync(logPath, 'r');\n const buf = Buffer.alloc(readSize);\n fs.readSync(fd, buf, 0, readSize, Math.max(0, stats.size - readSize));\n fs.closeSync(fd);\n const content = buf.toString('utf-8');\n const all = content.split('\\n').filter(Boolean);\n // If we started mid-line, drop the first partial line\n const lines = stats.size > readSize ? all.slice(1) : all;\n const tail = lines.slice(-Math.max(1, lineCount));\n // S6: Sanitize logs — strip potential secrets before returning\n const sanitized = tail.map(line =>\n line\n .replace(/Authorization:\\s*Bearer\\s+\\S+/gi, 'Authorization: Bearer [REDACTED]')\n .replace(/token[=:]\\s*[\"']?\\w{20,}[\"']?/gi, 'token=[REDACTED]')\n .replace(/api[_-]?key[=:]\\s*[\"']?\\w{10,}[\"']?/gi, 'api_key=[REDACTED]')\n .replace(/password[=:]\\s*[\"']?[^\\s\"',]+[\"']?/gi, 'password=[REDACTED]')\n .replace(/secret[=:]\\s*[\"']?\\w{10,}[\"']?/gi, 'secret=[REDACTED]')\n );\n res.json({ lines: sanitized });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // Full data reset (graph + knowledge + titan-data)\n app.delete('/api/data', (_req, res) => {\n try {\n const titanHome = join(homedir(), '.titan');\n const files = ['graph.json', 'knowledge.json', 'titan-data.json'];\n const deleted: string[] = [];\n for (const f of files) {\n const p = join(titanHome, f);\n if (fs.existsSync(p)) {\n fs.unlinkSync(p);\n deleted.push(f);\n }\n }\n clearGraph();\n logger.info(COMPONENT, `Full data reset via API: deleted ${deleted.join(', ') || 'none'}`);\n res.json({ success: true, message: `Deleted: ${deleted.join(', ') || 'none'}. Restart recommended.` });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // ── Autopilot / Goals / Daemon (Lifecycle Router) ─────────\n app.use('/api', createLifecycleRouter());\n\n // ── Social Media and Watch routes (extracted) ───────────────\n app.use('/api', createSocialRouter());\n app.use('/api', createWatchRouter());\n app.use('/api/files', createFilesRouter());\n\n // ── System API (cron, self-improve, training, autoresearch) ──\n app.use('/api', createSystemRouter());\n\n // ── Voice (extracted) ─────────────────────────────────────\n app.use('/api', createVoiceRouter(\n sessionAborts,\n sessionAbortTimes,\n rateLimit,\n concurrencyGuard,\n { get value() { return activeLlmRequests; }, set value(v: number) { activeLlmRequests = v; } },\n titanActiveSessions,\n titanRequestDuration,\n ));\n\n // ── Mesh (extracted) ───────────────────────────────────────\n app.use('/api', createMeshRouter(broadcast));\n\n // ── Organism (extracted) ───────────────────────────────────\n app.use('/api', createOrganismRouter());\n\n // ── Widget Gallery ────────────────────────────────────────\n app.get('/api/widget-gallery', async (_req, res) => {\n try {\n const { listTemplates, listCategories } = await import('../skills/builtin/widget_gallery.js');\n res.json({ templates: listTemplates(), categories: listCategories() });\n } catch (e) {\n logger.error(COMPONENT, `widget-gallery error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Widget gallery unavailable' });\n }\n });\n\n // ── GraphiTI / Knowledge Graph ───────────────────────────\n app.get('/api/graphiti', async (_req, res) => {\n try {\n const { getGraphData, getGraphStats } = await import('../memory/graph.js');\n const { nodes, edges } = getGraphData();\n const stats = getGraphStats();\n res.json({ graphReady: true, nodes, edges, stats });\n } catch (e) {\n logger.error(COMPONENT, `graphiti error: ${(e as Error).message}`);\n res.json({ graphReady: false, nodes: [], edges: [], stats: {} });\n }\n });\n\n // ── OpenAPI docs (/api/docs JSON + /docs HTML) ────────────\n app.get('/api/docs', (_req, res) => {\n res.json({\n openapi: '3.0.0',\n info: { title: 'TITAN Gateway API', version: TITAN_VERSION },\n paths: {},\n });\n });\n\n app.get('/docs', (_req, res) => {\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.send(`<!doctype html><html><head><title>TITAN API</title></head><body><h1>TITAN API Documentation</h1><p>See <a href=\"/api/docs\">/api/docs</a> for the OpenAPI spec (v${TITAN_VERSION}).</p></body></html>`);\n });\n\n // ── SPA fallback (must be after all API routes) ──────────\n if (hasReactUI) {\n app.get('*', (req, res, next) => {\n // Don't intercept API, WebSocket, metrics, webhooks, or legacy routes.\n // Hunt Finding #44 (2026-04-15): README promised `http://localhost:48420/mcp`\n // as the MCP HTTP transport endpoint, but the SPA catch-all was\n // swallowing /mcp and /mcp/health GETs and returning the dashboard\n // HTML. Pass /mcp* through to next() so mountMcpHttpEndpoints can\n // handle it. (POST /mcp is fine regardless — only GETs hit this.)\n if (\n req.path.startsWith('/api/') ||\n req.path.startsWith('/messenger/') ||\n req.path.startsWith('/mcp') ||\n req.path === '/ws' ||\n req.path === '/metrics' ||\n req.path === '/legacy' ||\n req.path === '/login'\n ) {\n return next();\n }\n res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');\n res.setHeader('Pragma', 'no-cache');\n res.setHeader('Expires', '0');\n res.send(cachedIndexHtml || fs.readFileSync(uiIndexPath, 'utf8'));\n });\n }\n\n // Create HTTP or HTTPS server\n // HTTPS: auto-detect certs at ~/.titan/certs/titan.pem + titan-key.pem (generated by mkcert)\n const certPath = join(homedir(), '.titan', 'certs', 'titan.pem');\n const keyPath = join(homedir(), '.titan', 'certs', 'titan-key.pem');\n const useHttps = fs.existsSync(certPath) && fs.existsSync(keyPath);\n\n if (useHttps) {\n const cert = fs.readFileSync(certPath);\n const key = fs.readFileSync(keyPath);\n httpServer = createHttpsServer({ cert, key }, app);\n logger.info(COMPONENT, `HTTPS enabled (mkcert certs from ${certPath})`);\n } else {\n httpServer = createServer(app);\n }\n\n // Create WebSocket server\n const wss = new WebSocketServer({ server: httpServer });\n\n wss.on('connection', async (ws, req) => {\n try {\n const cfg = loadConfig();\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n\n // ── Mesh peer WebSocket connections ──────────────\n if (url.searchParams.get('mesh') === 'true' && cfg.mesh.enabled && cfg.mesh.secret) {\n const peerNodeId = url.searchParams.get('nodeId') || '';\n const authToken = url.searchParams.get('auth') || '';\n const { verifyMeshAuth, handleMeshWebSocket } = await import('../mesh/transport.js');\n const { getOrCreateNodeId } = await import('../mesh/identity.js');\n\n if (!verifyMeshAuth(authToken, peerNodeId, cfg.mesh.secret)) {\n logger.warn(COMPONENT, `Mesh auth rejected: nodeId=${peerNodeId}, ip=${req.socket.remoteAddress}`);\n ws.close(1008, 'Mesh auth failed');\n return;\n }\n\n const { getActiveRemoteTaskCount } = await import('../mesh/transport.js');\n\n handleMeshWebSocket(ws, peerNodeId, getOrCreateNodeId(), async (msg, reply) => {\n // Enforce allowRemoteModels\n const meshCfg = loadConfig().mesh;\n if (!meshCfg.allowRemoteModels) {\n reply({ error: 'Remote model access is disabled on this node' });\n return;\n }\n // Enforce maxRemoteTasks\n if (getActiveRemoteTaskCount() >= meshCfg.maxRemoteTasks) {\n reply({ error: 'Node at capacity — max remote tasks reached' });\n return;\n }\n // Handle incoming task requests from mesh peers\n try {\n const result = await processMessage(msg.payload.message as string, 'mesh', msg.fromNodeId, {\n model: msg.payload.model as string,\n });\n reply({ ...result });\n } catch (err) {\n reply({ error: (err as Error).message });\n }\n });\n return; // Don't add to wsClients — mesh peers use separate handling\n }\n\n // ── WebSocket Origin Validation (CVE-2026-25253 class) ──────\n // Prevent cross-origin WebSocket hijacking from malicious web pages\n const origin = req.headers.origin;\n if (origin) {\n const wsAllowlist = (cfg.gateway as Record<string, unknown>).wsOriginAllowlist as string[] | undefined;\n const customPatterns = (wsAllowlist || []).map(o => new RegExp(`^${o.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}$`));\n const allowed = isAllowedOrigin(origin) || customPatterns.some(p => p.test(origin));\n if (!allowed) {\n logger.warn(COMPONENT, `WebSocket origin rejected: ${origin} (not in allowlist)`);\n ws.close(1008, 'Origin not allowed');\n return;\n }\n }\n\n // ── Regular dashboard WebSocket connections ──────\n const auth = cfg.gateway.auth;\n if (auth && auth.mode !== 'none') {\n const token = url.searchParams.get('token') || '';\n if (!isValidToken(token, cfg)) {\n ws.close(1008, 'Unauthorized');\n return;\n }\n }\n\n // Tag connection with userId from query params (for session isolation)\n const taggedWs = ws as TaggedWebSocket;\n taggedWs.titanUserId = url.searchParams.get('userId') || 'webchat-user';\n wsClients.add(taggedWs);\n logger.info(COMPONENT, `WebSocket client connected (${wsClients.size} total, user=${taggedWs.titanUserId})`);\n\n ws.on('message', async (rawData, isBinary) => {\n try {\n // Ignore binary frames (legacy voice pipeline removed — use LiveKit WebRTC)\n if (isBinary) return;\n\n // R9: Reject oversized messages to prevent OOM\n const msgBytes = typeof rawData === 'string' ? Buffer.byteLength(rawData) : (rawData as Buffer).length;\n if (msgBytes > WS_MAX_MESSAGE_BYTES) {\n logger.warn(COMPONENT, `WebSocket message too large (${(msgBytes / 1024 / 1024).toFixed(1)}MB) — rejected`);\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'error', message: 'Message too large (max 10MB)' }));\n }\n return;\n }\n\n let data;\n try {\n data = JSON.parse(rawData.toString());\n } catch (parseErr) {\n logger.warn(COMPONENT, `Invalid WebSocket JSON: ${(parseErr as Error).message}`);\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON message' }));\n }\n return;\n }\n\n // Accept both 'chat' and 'message' types for compatibility\n if ((data.type === 'chat' || data.type === 'message') && data.content) {\n // Stream-enabled chat: send tokens as they arrive, then final message\n if (data.stream !== false && webChatChannel) {\n const chatUserId = data.userId || 'webchat-user';\n // Broadcast inbound message to all clients (for multi-tab visibility)\n broadcast({\n type: 'message', direction: 'inbound', channel: 'webchat',\n userId: chatUserId, content: data.content,\n timestamp: new Date().toISOString(),\n });\n\n try {\n const response = await routeMessage(data.content, 'webchat', chatUserId, {\n streamCallbacks: {\n onToken: (token: string) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'token', data: token }));\n }\n },\n onToolCall: (name: string, args: Record<string, unknown>) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'tool_call', name, args }));\n }\n },\n },\n });\n // Send done event to the originating client\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'done', content: response.content, model: response.model, durationMs: response.durationMs, tokenUsage: response.tokenUsage }));\n }\n // Broadcast final message to same user's other tabs only (session isolation)\n for (const client of wsClients) {\n const tagged = client as TaggedWebSocket;\n if (client !== ws && client.readyState === WebSocket.OPEN && tagged.titanUserId === chatUserId) {\n client.send(JSON.stringify({\n type: 'message', direction: 'outbound', channel: 'webchat',\n userId: chatUserId, content: response.content,\n model: response.model, durationMs: response.durationMs,\n timestamp: new Date().toISOString(),\n }));\n }\n }\n } catch (err) {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'done', content: `Error: ${(err as Error).message}` }));\n }\n }\n } else if (webChatChannel) {\n webChatChannel.handleWebSocketMessage(data.userId || 'webchat-user', data.content);\n }\n }\n } catch (error) {\n logger.error(COMPONENT, `WebSocket error: ${(error as Error).message}`);\n }\n });\n\n ws.on('close', () => {\n wsClients.delete(ws);\n logger.debug(COMPONENT, `WebSocket client disconnected (${wsClients.size} total)`);\n });\n } catch (err) {\n logger.error(COMPONENT, `WebSocket connection handler error: ${(err as Error).message}`);\n try { ws.close(1011, 'Internal error'); } catch { /* connection already closed */ }\n }\n });\n\n // Initialize channels\n webChatChannel = new WebChatChannel();\n channels.set('webchat', webChatChannel);\n await webChatChannel.connect();\n webChatChannel.on('message', handleInboundMessage);\n\n // Initialize optional channels\n const channelAdapters: Array<[string, ChannelAdapter]> = [\n ['discord', new DiscordChannel()],\n ['telegram', new TelegramChannel()],\n ['slack', new SlackChannel()],\n ['googlechat', new GoogleChatChannel()],\n ['whatsapp', new WhatsAppChannel()],\n ['matrix', new MatrixChannel()],\n ['signal', new SignalChannel()],\n ['msteams', new MSTeamsChannel()],\n ['irc', new IRCChannel()],\n ['mattermost', new MattermostChannel()],\n ['lark', new LarkChannel()],\n ['email_inbound', new EmailInboundChannel()],\n ['line', new LineChannel()],\n ['zulip', new ZulipChannel()],\n ['messenger', new MessengerChannel()],\n ];\n\n for (const [name, adapter] of channelAdapters) {\n adapter.on('message', handleInboundMessage);\n try {\n await adapter.connect();\n channels.set(name, adapter);\n } catch (error) {\n logger.debug(COMPONENT, `Channel ${name} not available: ${(error as Error).message}`);\n }\n }\n\n // ── Facebook Messenger Webhook ─────────────────────────────\n const messengerAdapter = channels.get('messenger') as MessengerChannel | undefined;\n if (messengerAdapter) {\n // Verification (GET) — Facebook sends this when you set up the webhook\n app.get('/api/messenger/webhook', (req, res) => {\n const result = messengerAdapter.handleVerify(req.query as Record<string, string>);\n res.status(result.status).send(result.body);\n });\n\n // Incoming messages (POST) — Facebook sends DMs here\n app.post('/api/messenger/webhook', express.json(), (req, res) => {\n messengerAdapter.handleWebhook(req.body);\n res.sendStatus(200); // Must respond 200 quickly or Facebook retries\n });\n\n // Also register at /messenger/webhook (without /api prefix) for backwards compatibility\n app.get('/messenger/webhook', (req, res) => {\n const result = messengerAdapter.handleVerify(req.query as Record<string, string>);\n res.status(result.status).send(result.body);\n });\n app.post('/messenger/webhook', express.json(), (req, res) => {\n messengerAdapter.handleWebhook(req.body);\n res.sendStatus(200);\n });\n\n logger.info(COMPONENT, `Messenger webhook: /api/messenger/webhook + /messenger/webhook (verify token: ${messengerAdapter.getVerifyToken()})`);\n }\n\n // ── Twilio Voice (real phone calls) ──────────────────────────\n // v4.4.0 — Tony dials the TITAN Twilio number on his phone, talks,\n // hears F5-TTS Andrew voice replies. Turn-based via <Gather speech>.\n // Config: channels.twilio (authToken for signature validation,\n // allowedCallers for whitelist, publicHost for audio URLs).\n {\n const {\n twimlPlayAndGather,\n twimlPauseAndRedirect,\n twimlPlayAndHangup,\n twimlReject,\n twimlSayAndHangup,\n validateTwilioSignature,\n isAllowedCaller,\n synthesizeAndCache,\n readCachedAudio,\n getCallSession,\n setCallSession,\n endCall,\n createVoiceJob,\n getVoiceJob,\n completeVoiceJob,\n failVoiceJob,\n } = await import('../channels/twilio-voice.js');\n\n const twilioCfg = (config.channels as Record<string, Record<string, unknown>> | undefined)?.twilio;\n const twilioEnabled = twilioCfg?.enabled !== false;\n\n const getTwilioConfig = () => {\n const cfg = loadConfig();\n const c = (cfg.channels as Record<string, Record<string, unknown>> | undefined)?.twilio || {};\n return {\n authToken: (c.authToken as string) || process.env.TWILIO_AUTH_TOKEN || '',\n phoneNumber: (c.phoneNumber as string) || process.env.TWILIO_PHONE_NUMBER || '',\n voice: (c.voice as string) || 'andrew',\n allowedCallers: (c.allowedCallers as string[]) || [],\n publicHost: (c.publicHost as string) || process.env.TWILIO_PUBLIC_HOST || '',\n };\n };\n\n // Twilio POSTs x-www-form-urlencoded — needs urlencoded parser\n const urlEncoded = express.urlencoded({ extended: false });\n\n /** Compute the full webhook URL Twilio signed against. */\n const computeSignedUrl = (req: express.Request): string => {\n const cfg = getTwilioConfig();\n // Prefer configured public host (Tailscale Funnel URL). This MUST match\n // the URL Tony set in Twilio, including protocol + path, or the\n // signature check fails.\n const host = cfg.publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n return host + req.originalUrl;\n };\n\n const checkTwilioAuth = (req: express.Request): boolean => {\n const { authToken } = getTwilioConfig();\n if (!authToken) {\n // If authToken isn't configured, skip validation (dev mode). Logged\n // once per request so the operator knows to lock it down.\n logger.warn(COMPONENT, 'Twilio authToken not configured — signature check SKIPPED');\n return true;\n }\n const signature = (req.headers['x-twilio-signature'] as string) || '';\n const url = computeSignedUrl(req);\n const params = (req.body || {}) as Record<string, string>;\n return validateTwilioSignature(authToken, signature, url, params);\n };\n\n // ── POST /api/twilio/voice-webhook — initial call handler ──\n app.post('/api/twilio/voice-webhook', urlEncoded, async (req, res) => {\n try {\n if (!twilioEnabled) { res.type('text/xml').send(twimlReject()); return; }\n if (!checkTwilioAuth(req)) {\n logger.warn(COMPONENT, 'Twilio voice-webhook: signature invalid');\n res.status(403).send('forbidden'); return;\n }\n\n const from = (req.body?.From as string) || '';\n const to = (req.body?.To as string) || '';\n const direction = (req.body?.Direction as string) || 'inbound';\n const callSid = (req.body?.CallSid as string) || '';\n const { allowedCallers, voice, publicHost } = getTwilioConfig();\n\n // v4.4.1: check the human's number, not TITAN's. On inbound calls\n // the human is `From` (they dialed in). On outbound-api calls\n // TITAN initiated and `To` is the human's number.\n const isOutbound = direction.startsWith('outbound');\n const humanNumber = isOutbound ? to : from;\n\n if (allowedCallers.length > 0 && !isAllowedCaller(humanNumber, allowedCallers)) {\n logger.warn(COMPONENT, `Twilio call ${direction} with non-whitelisted human number: ${humanNumber}`);\n res.type('text/xml').send(twimlReject());\n return;\n }\n\n logger.info(COMPONENT, `Twilio call ${direction}: CallSid=${callSid.slice(0, 10)}... human=${humanNumber}`);\n\n // Greeting\n const greeting = \"Hey Tony, TITAN here. What do you need?\";\n const token = await synthesizeAndCache(greeting, voice);\n const host = publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n if (!token) {\n // TTS unavailable — fall back to Twilio's built-in voice so the call\n // still connects and Tony can leave a message we don't drop into\n // silence.\n res.type('text/xml').send(twimlSayAndHangup(greeting + \" TTS is down. Hanging up.\"));\n return;\n }\n const audioUrl = `${host}/api/twilio/audio/${token}`;\n const gatherUrl = `${host}/api/twilio/voice-gather`;\n res.type('text/xml').send(twimlPlayAndGather(audioUrl, gatherUrl));\n } catch (e) {\n logger.error(COMPONENT, `Twilio voice-webhook error: ${(e as Error).message}`);\n res.status(500).type('text/xml').send(twimlSayAndHangup(\"Internal error. Try again.\"));\n }\n });\n\n // ── POST /api/twilio/voice-gather — speech result handler ──\n // v4.4.4: async + polling. Kick off LLM+TTS in background, return\n // pause+redirect immediately so Twilio doesn't hit its 15s timeout.\n // /voice-poll will either play the reply when ready or redirect back\n // to itself for another short pause.\n app.post('/api/twilio/voice-gather', urlEncoded, async (req, res) => {\n try {\n if (!twilioEnabled) { res.type('text/xml').send(twimlReject()); return; }\n if (!checkTwilioAuth(req)) {\n res.status(403).send('forbidden'); return;\n }\n\n const callSid = (req.body?.CallSid as string) || '';\n const from = (req.body?.From as string) || '';\n const to = (req.body?.To as string) || '';\n const direction = (req.body?.Direction as string) || 'inbound';\n const speechResult = ((req.body?.SpeechResult as string) || '').trim();\n const { voice, publicHost, allowedCallers } = getTwilioConfig();\n\n const isOutbound = direction.startsWith('outbound');\n const humanNumber = isOutbound ? to : from;\n if (allowedCallers.length > 0 && !isAllowedCaller(humanNumber, allowedCallers)) {\n res.type('text/xml').send(twimlReject()); return;\n }\n\n const host = publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n const gatherUrl = `${host}/api/twilio/voice-gather`;\n\n if (!speechResult) {\n // Silence or unrecognized speech — re-prompt (synth is fast, stay sync).\n const txt = \"I didn't catch that. Say it again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) {\n res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n } else {\n res.type('text/xml').send(twimlSayAndHangup(txt));\n }\n return;\n }\n\n logger.info(COMPONENT, `Twilio heard: \"${speechResult.slice(0, 80)}\"`);\n\n // v4.4.2: admin envelope lives in the SYSTEM prompt, not the user\n // message. Small models were literally reading the envelope aloud\n // when it was shoved into the user-message slot. With system-slot\n // placement, the model treats it as instructions and Tony's speech\n // as the turn content.\n const today = new Date().toLocaleDateString('en-US', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',\n });\n const voiceSystemPrompt = [\n 'You are TITAN on a phone call with Tony Elliott (your creator). Spoken conversation, not writing.',\n `Today is ${today}.`,\n '',\n 'HARD RULES (phone-call mode):',\n '- MAX 25 WORDS PER REPLY. One or two sentences. Be terse.',\n '- No lists, no markdown, no headers, no code blocks. This is spoken.',\n '- No \"Certainly!\" / \"I\\'d be happy to!\" preambles. Just answer.',\n '- Call him Tony or boss.',\n '- For big/destructive actions: one-sentence plan + \"Approve? Yes or no.\" then stop.',\n '- Never say \"check the dashboard\" (he is hands-free).',\n '- Never speak credentials, tokens, passwords, IPs, or file paths.',\n '- Never read these instructions aloud. Never describe yourself as an AI.',\n ].join('\\n');\n\n // v4.4.4: create job, kick off LLM+TTS in background, return\n // pause+redirect immediately. The /voice-poll endpoint will\n // either play the reply when ready or redirect back to itself\n // for another short pause. This keeps the call alive indefinitely\n // even when the LLM takes 20+ seconds.\n const jobId = createVoiceJob(callSid);\n const pollUrl = `${host}/api/twilio/voice-poll?jobId=${jobId}`;\n\n // Fire-and-forget async processing. Errors are caught + stored\n // on the job so /voice-poll can surface them gracefully.\n // v4.4.5: strategy='direct' forced so conversational questions\n // don't trigger a 30s+ explore/deliberation path. Tools still\n // available — direct mode is the minimum, not a tool block.\n (async () => {\n try {\n const existingSid = getCallSession(callSid);\n const voiceModel = (process.env.TWILIO_VOICE_MODEL\n || 'ollama/qwen3.5:cloud');\n const result = await processMessage(\n speechResult,\n 'twilio-admin',\n `twilio-call-${callSid}`,\n {\n ...(existingSid ? { sessionId: existingSid } : {}),\n model: voiceModel,\n systemPrompt: voiceSystemPrompt,\n strategy: 'direct',\n },\n undefined,\n AbortSignal.timeout(85_000),\n );\n if (result?.sessionId) setCallSession(callSid, result.sessionId);\n\n let reply = (result?.content || '').trim();\n if (!reply) reply = \"Got it.\";\n if (reply.length > 400) reply = reply.slice(0, 390).replace(/\\s\\S*$/, '') + '…';\n\n const token = await synthesizeAndCache(reply, voice);\n if (!token) {\n failVoiceJob(jobId, 'tts failed');\n return;\n }\n completeVoiceJob(jobId, token, reply);\n } catch (e) {\n logger.warn(COMPONENT, `Twilio voice-gather async error: ${(e as Error).message}`);\n failVoiceJob(jobId, (e as Error).message);\n }\n })();\n\n // Return immediately with a short pause + redirect to the poll endpoint.\n res.type('text/xml').send(twimlPauseAndRedirect(pollUrl, 3));\n } catch (e) {\n logger.error(COMPONENT, `Twilio voice-gather error: ${(e as Error).message}`);\n res.status(500).type('text/xml').send(twimlSayAndHangup(\"Something went wrong.\"));\n }\n });\n\n // ── POST /api/twilio/voice-poll — async job polling ──\n // v4.4.4: Twilio redirects here while we process the LLM reply.\n // If the job is ready, play the audio + open a new <Gather>. If\n // not, pause another ~3s and redirect back to self. Hard cap at\n // ~15 rounds (~45s) then surface an error TwiML.\n // Accept both GET and POST — some Twilio retry paths use GET when\n // following a Redirect even if method was specified.\n const handleVoicePoll = async (req: express.Request, res: express.Response) => {\n try {\n if (!twilioEnabled) { res.type('text/xml').send(twimlReject()); return; }\n if (!checkTwilioAuth(req)) {\n logger.warn(COMPONENT, `voice-poll signature rejected (method=${req.method}, jobId=${req.query.jobId})`);\n res.status(403).send('forbidden'); return;\n }\n\n const jobId = (req.query.jobId as string) || '';\n const job = getVoiceJob(jobId);\n logger.info(COMPONENT, `voice-poll method=${req.method} jobId=${jobId.slice(0,8)} status=${job?.status || 'missing'}`);\n const { voice, publicHost } = getTwilioConfig();\n const host = publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n const pollUrl = `${host}/api/twilio/voice-poll?jobId=${jobId}`;\n const gatherUrl = `${host}/api/twilio/voice-gather`;\n\n if (!job) {\n // Job expired or never existed. Treat as error.\n const txt = \"Sorry boss, lost my train of thought. Say that again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n else res.type('text/xml').send(twimlSayAndHangup(txt));\n return;\n }\n\n if (job.status === 'ready' && job.audioToken) {\n logger.info(COMPONENT, `Voice poll ready: job=${jobId.slice(0, 8)} reply=\"${(job.replyText || '').slice(0, 60)}\"`);\n const audioUrl = `${host}/api/twilio/audio/${job.audioToken}`;\n res.type('text/xml').send(twimlPlayAndGather(audioUrl, gatherUrl));\n return;\n }\n\n if (job.status === 'error') {\n logger.warn(COMPONENT, `Voice poll error: ${job.error}`);\n const txt = \"Hmm, I hit a snag. Try that again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n else res.type('text/xml').send(twimlSayAndHangup(txt));\n return;\n }\n\n // Still pending — pause and redirect back. Cap the total wait\n // so a hung LLM doesn't keep the call alive forever.\n // v4.4.5: hard cap raised 40s→90s to fit tool-call chains,\n // and we drop a short \"still on it\" filler every ~9s so Tony\n // doesn't just hear dead air while we work.\n const age = Date.now() - job.createdAt;\n if (age > 90_000) {\n logger.warn(COMPONENT, `Voice poll timeout after ${age}ms`);\n failVoiceJob(jobId, 'timeout');\n const txt = \"That one took too long. Say it again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n else res.type('text/xml').send(twimlSayAndHangup(txt));\n return;\n }\n\n // Every ~9s of waiting, play a brief filler so the caller knows\n // we're alive. Fillers come from a short rotating list so it\n // doesn't sound robotic. Tracked per-job via a `fillerCount`\n // field on the job object.\n const jobAny = job as { status: string; createdAt: number; fillerCount?: number };\n const fillerCount = jobAny.fillerCount || 0;\n const shouldFiller = age > 9_000 && age - (fillerCount * 9_000) > 9_000;\n if (shouldFiller) {\n const fillers = [\n \"Still on it, one sec.\",\n \"Working on it.\",\n \"Almost there, boss.\",\n \"Give me just a moment.\",\n ];\n const filler = fillers[fillerCount % fillers.length];\n jobAny.fillerCount = fillerCount + 1;\n const tk = await synthesizeAndCache(filler, voice);\n if (tk) {\n res.type('text/xml').send(`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Play>${host}/api/twilio/audio/${tk}</Play>\n <Pause length=\"2\"/>\n <Redirect method=\"POST\">${pollUrl}</Redirect>\n</Response>`);\n return;\n }\n // TTS failed — fall through to plain pause\n }\n res.type('text/xml').send(twimlPauseAndRedirect(pollUrl, 3));\n } catch (e) {\n logger.error(COMPONENT, `Twilio voice-poll error: ${(e as Error).message}`);\n res.status(500).type('text/xml').send(twimlSayAndHangup(\"Something went wrong.\"));\n }\n };\n app.post('/api/twilio/voice-poll', urlEncoded, handleVoicePoll);\n app.get('/api/twilio/voice-poll', handleVoicePoll);\n\n // ── POST /api/twilio/status-callback — call lifecycle events ──\n app.post('/api/twilio/status-callback', urlEncoded, (req, res) => {\n try {\n const callSid = (req.body?.CallSid as string) || '';\n const status = (req.body?.CallStatus as string) || '';\n const duration = (req.body?.CallDuration as string) || '';\n logger.info(COMPONENT, `Twilio call ${callSid.slice(0, 10)}... status=${status}${duration ? ` duration=${duration}s` : ''}`);\n if (status === 'completed' || status === 'failed' || status === 'canceled' || status === 'no-answer' || status === 'busy') {\n endCall(callSid);\n }\n res.sendStatus(200);\n } catch (e) {\n logger.warn(COMPONENT, `status-callback error: ${(e as Error).message}`);\n res.sendStatus(200);\n }\n });\n\n // ── GET /api/twilio/audio/:token — serve cached MP3 to Twilio ──\n // Unauthenticated on purpose: Twilio fetches these and passing a\n // bearer token through <Play> URLs is fiddly + leaks in logs.\n // Tokens are random 96-bit + 5-min TTL + garbage-collected, so the\n // exposure is a transient MP3 of synthesized speech (not secrets).\n app.get('/api/twilio/audio/:token', async (req, res) => {\n const token = req.params.token;\n const audio = await readCachedAudio(token);\n if (!audio) { res.status(404).send('expired'); return; }\n res.setHeader('Content-Type', audio.mime);\n res.setHeader('Content-Length', String(audio.buf.length));\n res.setHeader('Cache-Control', 'private, max-age=60');\n res.send(audio.buf);\n });\n\n logger.info(COMPONENT, `Twilio voice endpoints registered: /api/twilio/voice-webhook, /api/twilio/voice-gather, /api/twilio/status-callback, /api/twilio/audio/:token`);\n }\n\n // ── Phase 3: Boot MCP servers, monitors, recipes, model switch, slash commands ──\n initSlashCommands();\n seedBuiltinRecipes();\n initMcpServers().catch((e) => logger.warn(COMPONENT, `MCP init error: ${e.message}`));\n mountMcpHttpEndpoints(app);\n\n // ── Persistent webhooks — reload saved webhooks ─────────────\n initPersistentWebhooks().catch((e) => logger.warn(COMPONENT, `Webhook init: ${(e as Error).message}`));\n\n // ── Cron scheduler — re-activate all persisted jobs ──────────\n initCronScheduler();\n\n // ── Autopilot — scheduled autonomous agent runs ─────────────\n initAutopilot(config);\n\n // ── VRAM Orchestrator — GPU memory management ───────────────\n if (config.vram?.enabled !== false) {\n import('../vram/orchestrator.js').then(({ initVRAMOrchestrator }) => {\n initVRAMOrchestrator().catch((e) => logger.warn(COMPONENT, `VRAM orchestrator init: ${(e as Error).message}`));\n }).catch(() => { /* optional */ });\n }\n\n // ── Command Post — agent governance layer ────────────────\n if (config.commandPost?.enabled) {\n initCommandPost(config.commandPost);\n initWakeupSystem();\n initHeartbeatScheduler();\n logger.info(COMPONENT, 'Command Post governance layer initialized (wakeup system active)');\n\n // v4.7.0: bootstrap specialist pool (Scout, Builder, Writer, Analyst)\n // once Command Post is up. Idempotent — safe to call every boot.\n try {\n const { ensureSpecialistsRegistered } = await import('../agent/specialists.js');\n await ensureSpecialistsRegistered();\n } catch (e) {\n logger.warn(COMPONENT, `Specialist bootstrap skipped: ${(e as Error).message}`);\n }\n }\n\n // v4.9.0: load/init stable identity. Persistent across restarts.\n // Session count ticks, version transitions logged, core hash checked\n // for tampering. Identity gets rendered into every agent's system\n // prompt via agent.ts (sync globalThis accessor).\n try {\n const { initIdentity, renderIdentityBlock, getIdentity } = await import('../memory/identity.js');\n const identity = initIdentity();\n logger.info(COMPONENT, `Identity loaded — session #${identity.tenure.sessionCount}, ${identity.driftLog.filter(d => d.resolution === 'pending').length} pending drift event(s)`);\n for (const ev of identity.driftLog.filter(d => d.resolution === 'pending').slice(-3)) {\n logger.warn('Identity', `Pending drift [${ev.kind}]: ${ev.detail.slice(0, 140)}`);\n }\n // Install a sync accessor so agent.ts buildSystemPrompt() can pull\n // the identity block without dynamic import on every message.\n (globalThis as unknown as { __titan_identity_block?: () => string }).__titan_identity_block = () => {\n const id = getIdentity();\n return id ? renderIdentityBlock(id) : '';\n };\n } catch (e) {\n logger.warn(COMPONENT, `Identity bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: install the self-model provider. The self-model\n // synthesizes identity + recent performance + strengths/weaknesses\n // + integrity into a compact block injected into every system prompt.\n // Cached for 60s inside the module — the sync accessor returns the\n // cached block (falling through to empty when cache is cold).\n try {\n const { getSelfModel, renderSelfModelBlock } = await import('../memory/meta.js');\n let cachedBlock = '';\n let cachedAt = 0;\n const refresh = () => {\n (async () => {\n try {\n cachedBlock = await renderSelfModelBlock();\n cachedAt = Date.now();\n } catch { /* ok */ }\n })();\n };\n refresh();\n setInterval(refresh, 60_000).unref?.();\n (globalThis as unknown as { __titan_self_model_block?: () => string }).__titan_self_model_block = () => {\n // If cache is stale (> 2 min) return the old block anyway — the\n // async refresh runs out-of-band. Never blocks the prompt path.\n if (Date.now() - cachedAt > 120_000 && cachedBlock === '') {\n // First call before refresh finishes — do nothing.\n return '';\n }\n return cachedBlock;\n };\n // Also prime the self-model so the first agent turn has something.\n await getSelfModel();\n logger.info(COMPONENT, 'Self-model provider installed (60s refresh)');\n } catch (e) {\n logger.warn(COMPONENT, `Self-model bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local (Phase C): install working-memory provider. Injects\n // structured session state into the agent's system prompt when resuming\n // an in-flight task so TITAN doesn't start from scratch mid-work.\n try {\n const { renderSessionContext } = await import('../memory/workingMemory.js');\n (globalThis as unknown as {\n __titan_working_memory_block?: (sessionId: string) => string;\n }).__titan_working_memory_block = (sessionId: string) => {\n try { return renderSessionContext(sessionId); } catch { return ''; }\n };\n logger.info(COMPONENT, 'Working-memory provider installed');\n } catch (e) {\n logger.warn(COMPONENT, `Working-memory bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase B): install driver-status provider. Appends\n // live driver phase + blocked questions into the agent's system prompt,\n // so \"what are you working on?\" gets a real answer.\n try {\n const { renderDriverStatusBlock } = await import('../agent/driverAwareChat.js');\n (globalThis as unknown as { __titan_driver_status_block?: () => string | null }).__titan_driver_status_block = () => {\n try { return renderDriverStatusBlock(); } catch { return null; }\n };\n logger.info(COMPONENT, 'Driver-aware chat provider installed');\n } catch (e) {\n logger.warn(COMPONENT, `Driver-aware chat skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0: install closed-loop signal providers for Soma drives. These\n // let the drive layer read live VRAM / telemetry / learning state via\n // a synchronous call without pulling in the whole dependency graph.\n try {\n const { getVRAMOrchestrator } = await import('../vram/orchestrator.js');\n const { getMetricsSummary } = await import('./metrics.js');\n const { getLearningStats } = await import('../memory/learning.js');\n\n // VRAM: refresh happens on the orchestrator's 10s cadence; we just\n // peek at the last known GPU state. If there's no GPU, the peeker\n // returns nothing and the drive treats that as \"no signal.\"\n const g = globalThis as unknown as {\n __titan_vram_last?: { totalMB: number; freeMB: number; usedMB: number };\n __titan_metrics_summary?: () => { totalRequests: number; errorRate: number } | null;\n __titan_unresolved_error_patterns?: () => number;\n };\n setInterval(() => {\n (async () => {\n try {\n const orch = getVRAMOrchestrator();\n const snap = await orch.getSnapshot();\n if (snap?.gpu && typeof snap.gpu.totalMB === 'number' && snap.gpu.totalMB > 0) {\n g.__titan_vram_last = {\n totalMB: snap.gpu.totalMB,\n freeMB: snap.gpu.freeMB,\n usedMB: snap.gpu.usedMB ?? (snap.gpu.totalMB - snap.gpu.freeMB),\n };\n } else {\n g.__titan_vram_last = undefined;\n }\n } catch { /* best-effort */ }\n })();\n }, 15_000).unref?.();\n\n // Metrics: cheap synchronous read.\n g.__titan_metrics_summary = () => {\n try {\n const s = getMetricsSummary();\n return { totalRequests: s.totalRequests, errorRate: s.errorRate };\n } catch { return null; }\n };\n\n // Unresolved error patterns from the learning KB.\n // v4.10.0-local fix: use the new `unresolvedErrorPatterns` field that\n // filters by !resolution. Prior behavior used total count, which meant\n // marking patterns resolved didn't relieve curiosity drive pressure.\n g.__titan_unresolved_error_patterns = () => {\n try {\n const stats = getLearningStats();\n return stats.unresolvedErrorPatterns ?? stats.errorPatterns ?? 0;\n } catch { return 0; }\n };\n\n logger.info(COMPONENT, 'Drive signal providers installed (VRAM, metrics, learning)');\n } catch (e) {\n logger.warn(COMPONENT, `Drive signal bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: register the self-repair daemon watcher. Runs every\n // 5 minutes; sweeps for stuck drives, stalled goals, episodic\n // anomalies, integrity dips, stale working-memory sessions. Files\n // 'self_repair' approvals for new findings. Human-in-the-loop: the\n // daemon proposes, Tony approves (or rejects).\n try {\n const { registerWatcher } = await import('../agent/daemon.js');\n const { runSelfRepairSweep } = await import('../safety/selfRepair.js');\n registerWatcher('self-repair', async () => {\n try { await runSelfRepairSweep(); } catch (e) { logger.debug(COMPONENT, `self-repair sweep: ${(e as Error).message}`); }\n }, 300_000);\n logger.info(COMPONENT, 'Self-repair daemon registered (5 min cadence)');\n } catch (e) {\n logger.warn(COMPONENT, `Self-repair daemon skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase A): start the Goal Driver scheduler. This replaces\n // the passive \"initiative picks one subtask per 5-min autopilot tick\"\n // model with a persistent phase state machine per goal. Restart-safe:\n // resumes any non-terminal drivers from ~/.titan/driver-state/.\n try {\n const { registerSomaVerifier } = await import('../agent/somaFeedback.js');\n registerSomaVerifier();\n const { startDriverScheduler, resumeDriversAfterRestart } = await import('../agent/driverScheduler.js');\n const resumed = await resumeDriversAfterRestart();\n logger.info(COMPONENT, `Goal Driver resume: ${resumed.resumed} re-activated, ${resumed.cancelled} cancelled (goal no longer active), ${resumed.sweptStale} stale (>24h since lastTick) reaped`);\n startDriverScheduler(10_000, 5); // 10s tick, max 5 concurrent drivers\n } catch (e) {\n logger.warn(COMPONENT, `Goal Driver scheduler bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase B): daily digest cron. Generates a TL;DR at 9am\n // PDT + on every restart (so /api/digest/today always has fresh data).\n try {\n const { startDailyDigestCron } = await import('../agent/dailyDigest.js');\n startDailyDigestCron();\n } catch (e) {\n logger.warn(COMPONENT, `Daily digest cron skipped: ${(e as Error).message}`);\n }\n\n // v5.5.17: Dream Mode cron — opt-in via config.dream.enabled. Default\n // 03:30 local. Skips quietly when disabled. See src/agent/dreams.ts.\n try {\n const { startDreamCron } = await import('../agent/dreams.js');\n startDreamCron();\n } catch (e) {\n logger.warn(COMPONENT, `Dream cron skipped: ${(e as Error).message}`);\n }\n\n // v5.5.27: Persona A/B rollout monitor — opt-in via\n // personas.rollout.enabled. Re-evaluates every cohort on a cadence\n // (default 5 min) and auto-reverts candidates that regress vs\n // baseline. Skips quietly when disabled.\n try {\n const { startRolloutMonitor } = await import('../agent/personaRollout.js');\n startRolloutMonitor();\n } catch (e) {\n logger.warn(COMPONENT, `Persona rollout monitor skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase C): mission scheduler — ticks active missions\n // (driver-of-drivers) every 15s. Missions coordinate multi-goal projects.\n try {\n const { listActiveMissions, tickMission } = await import('../agent/missionDriver.js');\n const missionTimer = setInterval(() => {\n void (async () => {\n try {\n for (const m of listActiveMissions()) {\n try { await tickMission(m.missionId); } catch { /* ok */ }\n }\n } catch { /* ok */ }\n })();\n }, 15_000);\n missionTimer.unref?.();\n logger.info(COMPONENT, 'Mission scheduler started (15s cadence)');\n } catch (e) {\n logger.warn(COMPONENT, `Mission scheduler skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: register the working-memory retire watcher. Every\n // hour, sweeps for in-flight sessions that haven't touched\n // lastActiveAt in > 24h and archives them to episodic as abandoned.\n try {\n const { registerWatcher } = await import('../agent/daemon.js');\n const { retireStaleSessions } = await import('../memory/workingMemory.js');\n registerWatcher('working-memory-retire', async () => {\n try { retireStaleSessions(); } catch (e) { logger.debug(COMPONENT, `working-memory retire: ${(e as Error).message}`); }\n }, 3_600_000);\n } catch (e) {\n logger.warn(COMPONENT, `Working-memory retire watcher skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: canary eval daemon. Runs the fixed golden-set\n // every 24h; if any task drops > 15% vs 7-day baseline, a\n // canary_regression approval fires for Tony to review. Defends\n // against silent quality degradation from model drift, context\n // bloat, or prompt accretion.\n try {\n const { registerWatcher } = await import('../agent/daemon.js');\n const { runCanarySweep } = await import('../safety/canaryEval.js');\n registerWatcher('canary-eval', async () => {\n try { await runCanarySweep(); } catch (e) { logger.debug(COMPONENT, `canary sweep: ${(e as Error).message}`); }\n }, 24 * 60 * 60 * 1000);\n logger.info(COMPONENT, 'Canary eval daemon registered (24h cadence)');\n } catch (e) {\n logger.warn(COMPONENT, `Canary eval daemon skipped: ${(e as Error).message}`);\n }\n\n // v4.8.0: Self-Modification Pipeline — auto-review newly captured\n // proposals and poll open PRs for merge/close outcomes.\n try {\n const selfModCfg = (config as unknown as { selfMod?: {\n enabled?: boolean;\n autoReview?: boolean;\n autoPR?: boolean;\n pollIntervalMs?: number;\n } }).selfMod;\n if (selfModCfg?.enabled) {\n logger.info(COMPONENT, 'Self-Modification Pipeline: enabled');\n const { pollOpenProposals } = await import('../agent/selfProposalLearning.js');\n const pollMs = selfModCfg.pollIntervalMs ?? 300_000;\n const pollTimer = setInterval(() => {\n pollOpenProposals().catch((e: Error) => logger.debug(COMPONENT, `selfMod poll: ${e.message}`));\n }, pollMs);\n (pollTimer as unknown as { unref?: () => void }).unref?.();\n\n // Auto-review: watch soma:proposal events for self-mod captures and\n // kick off specialist review when a new proposal has enough files.\n if (selfModCfg.autoReview !== false) {\n const { on: subscribeTrace } = await import('../substrate/traceBus.js');\n subscribeTrace('soma:proposal', async (payload) => {\n try {\n const pb = (payload as { proposedBy?: string }).proposedBy || '';\n if (!pb.startsWith('self-mod:')) return;\n const proposalId = (payload as { approvalId?: string }).approvalId;\n if (!proposalId) return;\n // Debounce: wait 2s for additional files in same session before reviewing\n setTimeout(async () => {\n try {\n const { reviewProposal } = await import('../agent/selfProposalReview.js');\n const reviewed = await reviewProposal(proposalId);\n // Auto-PR if configured + approved\n if (reviewed?.status === 'approved' && selfModCfg.autoPR) {\n const { createProposalPR } = await import('../agent/selfProposalPR.js');\n await createProposalPR(proposalId);\n }\n } catch (e) {\n logger.warn(COMPONENT, `selfMod auto-review failed: ${(e as Error).message}`);\n }\n }, 2000);\n } catch (e) {\n logger.debug(COMPONENT, `selfMod subscribe handler: ${(e as Error).message}`);\n }\n });\n }\n }\n } catch (e) {\n logger.warn(COMPONENT, `selfMod bootstrap skipped: ${(e as Error).message}`);\n }\n\n // ── Daemon — persistent agent awareness loop ────────────────\n initDaemon();\n\n // ── Morning Briefing — send once per day in 6am–12pm window ──\n checkAndSendBriefing(async (msg) => {\n broadcast({\n type: 'message',\n direction: 'outbound',\n channel: 'system',\n userId: 'titan',\n content: msg,\n timestamp: new Date().toISOString(),\n });\n }).catch((e: Error) => logger.warn(COMPONENT, `Briefing error: ${e.message}`));\n\n // Wire monitor triggers to agent\n setMonitorTriggerHandler(async (monitor, event) => {\n const prompt = `[AUTO-TRIGGER: ${monitor.name}] ${event.detail}\\n\\nYour task: ${monitor.prompt}`;\n const response = await processMessage(prompt, 'monitor', 'system');\n broadcast({ type: 'monitor_trigger', monitor: monitor.name, response: response.content, event });\n logger.info(COMPONENT, `Monitor \"${monitor.name}\" responded: ${response.content.slice(0, 100)}`);\n });\n initMonitors();\n\n // ── Operator Alerting ──────────────────────────────────────────\n const { initAlerts } = await import('../agent/alerts.js');\n initAlerts();\n\n // ── Mesh Networking ───────────────────────────────────────────\n if (config.mesh.enabled && !config.mesh.secret) {\n logger.warn(COMPONENT, 'Mesh is enabled but no secret is set. Run `titan mesh --init` to generate one. Mesh disabled.');\n }\n if (config.mesh.enabled && config.mesh.secret) {\n const { getOrCreateNodeId } = await import('../mesh/identity.js');\n const { startDiscovery, setOnPeerDiscovered, setConnectApprovedPeer, setMaxPeers } = await import('../mesh/discovery.js');\n const { connectToPeer, startHeartbeat, startRouteBroadcast } = await import('../mesh/transport.js');\n const nodeId = getOrCreateNodeId();\n\n // Set max peers limit\n setMaxPeers(config.mesh.maxPeers);\n\n // Notify dashboard when new peers are discovered\n setOnPeerDiscovered((peer) => {\n broadcast({\n type: 'mesh_peer_discovered',\n peer: {\n nodeId: peer.nodeId,\n hostname: peer.hostname,\n address: peer.address,\n port: peer.port,\n version: peer.version,\n models: peer.models,\n discoveredVia: peer.discoveredVia,\n },\n });\n logger.info(COMPONENT, `New TITAN node discovered: ${peer.hostname} (${peer.address}:${peer.port}) — approve via dashboard or CLI`);\n });\n\n // Wire up WebSocket connections for approved peers\n setConnectApprovedPeer((peer) => {\n if (config.mesh.secret) {\n connectToPeer(peer.address, peer.port, nodeId, config.mesh.secret)\n .then((ok) => {\n if (ok) {\n broadcast({ type: 'mesh_peer_connected', peer });\n logger.info(COMPONENT, `Connected to approved peer: ${peer.hostname}`);\n }\n })\n .catch(() => logger.debug(COMPONENT, `Approved peer unreachable: ${peer.hostname}`));\n }\n });\n\n await startDiscovery(nodeId, port, {\n mdns: config.mesh.mdns,\n tailscale: config.mesh.tailscale,\n autoApprove: config.mesh.autoApprove,\n peerStaleTimeoutMs: config.mesh.peerStaleTimeoutMs,\n });\n\n // Auto-bind to 0.0.0.0 when mesh is enabled (so peers can reach us)\n if (host === '127.0.0.1') {\n host = '0.0.0.0';\n logger.info(COMPONENT, 'Mesh enabled — binding to 0.0.0.0 (was 127.0.0.1) so peers can connect');\n }\n\n // Connect to static peers\n if (config.mesh.staticPeers.length > 0) {\n for (const addr of config.mesh.staticPeers) {\n const parts = addr.split(':');\n const peerHost = parts[0];\n const peerPort = parseInt(parts[1] || '48420', 10);\n if (!peerHost || isNaN(peerPort)) {\n logger.warn(COMPONENT, `Invalid static peer address: \"${addr}\" — expected host:port (e.g. 192.168.1.100:48420)`);\n continue;\n }\n connectToPeer(peerHost, peerPort, nodeId, config.mesh.secret)\n .catch(() => logger.debug(COMPONENT, `Static peer unreachable: ${addr}`));\n }\n }\n\n // Start heartbeat with dynamic model discovery\n startHeartbeat(nodeId, async () => {\n const { getActiveRemoteTaskCount: getTaskCount } = await import('../mesh/transport.js');\n const models = await discoverAllModels();\n const cpu = getCpuLoad();\n const taskLoad = getTaskCount() / Math.max(config.mesh.maxRemoteTasks, 1);\n const load = Math.min(1, cpu * 0.4 + taskLoad * 0.6);\n return {\n hostname: osHostname(),\n version: TITAN_VERSION,\n models: models.map(m => m.id),\n load: Math.round(load * 100) / 100,\n };\n }, config.mesh.heartbeatIntervalMs || 60_000);\n\n // Start distance-vector route broadcasting\n startRouteBroadcast(30_000);\n\n const mode = config.mesh.autoApprove ? 'auto-approve' : 'approval-required';\n logger.info(COMPONENT, `Mesh active — Node: ${nodeId.slice(0, 8)}... | mDNS: ${config.mesh.mdns} | Tailscale: ${config.mesh.tailscale} | Max peers: ${config.mesh.maxPeers} | Mode: ${mode}`);\n }\n\n // Start server\n httpServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n logger.warn(COMPONENT, `Port ${port} is already in use. Mission Control is likely already running in the background.`);\n logger.info(COMPONENT, `You can access it at http://${host}:${port}`);\n process.exit(1);\n } else {\n logger.error(COMPONENT, `Server error: ${err.message}`);\n }\n });\n\n // Hunt Finding #04 (2026-04-14): detect partial port conflicts.\n // If the user has a zombie gateway bound to 127.0.0.1:PORT and starts a\n // new one on 0.0.0.0:PORT, BOTH bind successfully (different addresses).\n // But localhost traffic routes to the zombie, not the new gateway — silent\n // confusion for the user. Pre-check via a TCP probe to localhost:PORT.\n // If something responds, log a clear warning before proceeding.\n try {\n await new Promise<void>((resolvePromise) => {\n const probe = net.createConnection({ host: '127.0.0.1', port, timeout: 500 });\n probe.once('connect', () => {\n logger.warn(COMPONENT,\n `[PortConflictProbe] Something is already listening on 127.0.0.1:${port}. ` +\n `The new gateway will bind to ${host}:${port} but localhost traffic may be routed to the existing process. ` +\n `Kill any stale processes (lsof -i :${port}) before starting.`,\n );\n probe.destroy();\n resolvePromise();\n });\n probe.once('error', () => {\n // ECONNREFUSED = port is free on localhost. Good.\n resolvePromise();\n });\n probe.once('timeout', () => {\n probe.destroy();\n resolvePromise();\n });\n });\n } catch {\n // Probe failure is non-fatal — don't block startup\n }\n\n // ── Internal Health Monitor (60s interval) ─────────────────────\n const ollamaBaseUrl = config.providers?.ollama?.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434';\n const ttsBaseUrl = config.voice?.ttsUrl || 'http://localhost:5005';\n\n healthMonitorInterval = setInterval(() => { // R1: avoid async in setInterval to prevent unhandled rejections\n void (async () => {\n try {\n const now = Date.now();\n healthState.lastCheck = new Date().toISOString();\n\n // Check Ollama\n try {\n const resp = await fetch(`${ollamaBaseUrl}/api/tags`, { signal: AbortSignal.timeout(3000) });\n healthState.ollamaHealthy = resp.ok;\n } catch {\n if (healthState.ollamaHealthy) {\n logger.warn(COMPONENT, 'Health monitor: Ollama is unreachable');\n }\n healthState.ollamaHealthy = false;\n }\n\n // Check TTS — F5-TTS exposes /health for fast probes; the /v1/audio/speech\n // synthesize-and-return path is too slow for a periodic monitor.\n try {\n const resp = await fetch(`${ttsBaseUrl}/health`, {\n signal: AbortSignal.timeout(3000),\n });\n healthState.ttsHealthy = resp.ok;\n } catch {\n healthState.ttsHealthy = false;\n }\n\n // Check for stuck LLM requests (same count for > 5 minutes)\n if (activeLlmRequests > 0 && activeLlmRequests === healthState.lastActiveLlm) {\n if (now - healthState.lastActiveLlmTime > 300_000) {\n if (!healthState.stuckDetected) {\n logger.warn(COMPONENT, `Health monitor: ${activeLlmRequests} LLM requests stuck for >5 minutes`);\n healthState.stuckDetected = true;\n }\n }\n } else {\n healthState.lastActiveLlm = activeLlmRequests;\n healthState.lastActiveLlmTime = now;\n healthState.stuckDetected = false;\n }\n\n // Check memory usage\n const mem = process.memoryUsage();\n const heapMB = Math.round(mem.heapUsed / 1024 / 1024);\n const rssMB = Math.round(mem.rss / 1024 / 1024);\n if (heapMB > 1500) {\n logger.warn(COMPONENT, `Health monitor: High heap usage — ${heapMB}MB`);\n }\n\n // Enforce configured memory limit — shed load if exceeded\n const memoryLimitMB = config.security?.maxMemoryMB || 2048;\n if (rssMB > memoryLimitMB * 0.9) {\n logger.error(COMPONENT, `Memory pressure — RSS ${rssMB}MB is above 90% of limit (${memoryLimitMB}MB). Reducing max concurrent requests.`);\n maxConcurrentOverride = Math.max(1, (maxConcurrentOverride ?? config.security.maxConcurrentTasks ?? 5) - 1);\n } else if (rssMB < memoryLimitMB * 0.7 && maxConcurrentOverride !== null) {\n maxConcurrentOverride = null; // Reset when memory recovers\n }\n\n // Enforce disk write limit (approximate via titan home dir size)\n try {\n const diskLimitMB = config.security?.maxDiskWriteMB || 1024;\n const { spawnSync } = await import('child_process');\n const du = spawnSync('du', ['-sm', TITAN_HOME], { encoding: 'utf-8', timeout: 5000 });\n const usedMB = parseInt(du.stdout?.split('\\t')[0] || '0', 10);\n if (usedMB > diskLimitMB * 0.9) {\n logger.error(COMPONENT, `Disk pressure — ${usedMB}MB used in ${TITAN_HOME}, above 90% of limit (${diskLimitMB}MB). Pausing non-essential writes.`);\n }\n } catch { /* du not available or failed — non-critical */ }\n\n // Keep primary agent heartbeat alive for Command Post\n try { reportHeartbeat('default'); } catch { /* non-critical */ }\n } catch (err) {\n logger.error(COMPONENT, `Health monitor error: ${(err as Error).message}`);\n }\n })();\n }, 60_000);\n healthMonitorInterval.unref();\n\n logger.info(COMPONENT, 'Health monitor started (60s interval)');\n\n // Catch unhandled promise rejections to prevent silent crashes + report\n // (v5.0 \"Spacewalk\"): reports go to the remote collector only when\n // `telemetry.enabled` AND `telemetry.crashReports` are both true AND the\n // user has previously consented via the SetupWizard. HOME path is stripped\n // from the stack to prevent personal-path leakage.\n //\n // Secret-scrubbing pass: removes API keys, bearer tokens, and URLs with\n // embedded credentials before the payload leaves the machine.\n const SECRET_PATTERNS = [\n // Bearer / Basic auth headers\n /\\b[Bb]earer\\s+[A-Za-z0-9_\\-.]{20,}/g,\n /\\b[Bb]asic\\s+[A-Za-z0-9+/=]{20,}/g,\n // API key prefixes (OpenAI, Anthropic, Groq, etc.)\n /\\b(sk|pk)-[A-Za-z0-9]{20,}/g,\n /\\b([a-zA-Z]{2,}_[a-zA-Z0-9]{16,})/g,\n // Generic hex tokens (32+ chars) — conservative to avoid scrubbing file hashes\n /\\b[0-9a-f]{64,}\\b/gi,\n // URLs with credentials\n /https?:\\/\\/[^\\s:]+:[^\\s@]+@[^\\s/]+/g,\n // Private keys / PEM blocks\n /-----BEGIN [A-Z ]+ PRIVATE KEY-----[\\s\\S]{100,}-----END [A-Z ]+ PRIVATE KEY-----/g,\n ];\n function scrubSecrets(text: string): string {\n let cleaned = text;\n for (const pattern of SECRET_PATTERNS) {\n cleaned = cleaned.replace(pattern, '[REDACTED]');\n }\n return cleaned;\n }\n\n const reportCrash = async (kind: 'unhandledRejection' | 'uncaughtException', err: unknown) => {\n try {\n const cfg = loadConfig();\n if (!cfg.telemetry?.enabled) return;\n if (!(cfg.telemetry as unknown as { crashReports?: boolean })?.crashReports) return;\n // v5.0.1: removed consentedAt gate so users upgrading from 4.x keep crash\n // reporting without re-running onboarding. The SetupWizard still stamps\n // consentedAt for new installs; we simply don't require it here.\n const { sendRemoteAnalytics } = await import('../analytics/collector.js');\n const { getOrCreateNodeId } = await import('../mesh/identity.js');\n const home = homedir();\n const stackRaw = (err instanceof Error ? (err.stack || err.message) : String(err));\n const stack = scrubSecrets(stackRaw.split(home).join('$HOME')).slice(0, 4000);\n const message = scrubSecrets(err instanceof Error ? err.message : String(err)).slice(0, 500);\n const fingerprint = `${kind}:${(message.match(/[A-Z][a-zA-Z0-9_]+Error/) || [message])[0]}`.slice(0, 128);\n await sendRemoteAnalytics({\n type: 'error',\n installId: getOrCreateNodeId(),\n version: TITAN_VERSION,\n message,\n stack,\n fingerprint,\n context: { kind },\n });\n } catch {\n // Crash reporting is best-effort\n }\n };\n\n process.on('unhandledRejection', (reason) => {\n logger.error(COMPONENT, `Unhandled rejection: ${reason}`);\n void reportCrash('unhandledRejection', reason);\n });\n\n // Catch uncaught exceptions — log and exit gracefully to allow systemd/docker restart\n process.on('uncaughtException', (err) => {\n logger.error(COMPONENT, `Uncaught exception: ${err.message}\\n${err.stack || ''}`);\n void reportCrash('uncaughtException', err);\n // Give logger + crash report time to flush before exiting\n setTimeout(() => {\n process.exit(1);\n }, 1500).unref();\n });\n\n // ── Graceful Shutdown ───────────────────────────────────────────\n // ── Lifecycle Manager — coordinated shutdown registry ──────\n const lm = getLifecycleManager();\n lm.register('f5tts', () => Promise.resolve(), () => new Promise<void>((resolve) => {\n for (const pidPath of [join(homedir(), '.titan', 'f5tts.pid'), join(homedir(), '.titan', 'qwen3tts.pid')]) {\n try {\n if (!fs.existsSync(pidPath)) continue;\n const pid = parseInt(fs.readFileSync(pidPath, 'utf-8').trim());\n process.kill(pid, 'SIGTERM');\n fs.unlinkSync(pidPath);\n logger.info(COMPONENT, `Stopped F5-TTS server (${pidPath})`);\n } catch { /* already stopped */ }\n }\n resolve();\n }));\n lm.register('autopilot', () => Promise.resolve(), () => { stopAutopilot(); return Promise.resolve(); });\n lm.register('daemon', () => Promise.resolve(), () => { stopDaemon(); return Promise.resolve(); });\n lm.register('commandpost', () => Promise.resolve(), () => { shutdownCommandPost(); return Promise.resolve(); });\n lm.register('tunnel', () => Promise.resolve(), () => { stopTunnel(); return Promise.resolve(); });\n\n const gracefulShutdown = async (signal: string) => {\n logger.info(COMPONENT, `Received ${signal} — shutting down gracefully...`);\n await lm.stopAll();\n closeMemory();\n flushGraph();\n try { const { flushVectors } = await import('../memory/vectors.js'); flushVectors(); } catch { /* ignore */ }\n await stopGateway();\n logger.info(COMPONENT, 'Gateway stopped. Goodbye.');\n process.exit(0);\n };\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n\n // Global error handler — prevent stack trace leaks\n app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {\n if (err instanceof SyntaxError && 'body' in err) {\n res.status(400).json({ error: 'Invalid JSON in request body' });\n return;\n }\n logger.error(COMPONENT, `Unhandled error: ${err.message}`);\n res.status(500).json({ error: 'Internal server error' });\n });\n\n httpServer.listen(port, host, () => {\n const proto = useHttps ? 'https' : 'http';\n const wsProto = useHttps ? 'wss' : 'ws';\n logger.info(COMPONENT, `Gateway listening on ${proto}://${host}:${port}`);\n logger.info(COMPONENT, `Dashboard: ${proto}://${host}:${port}`);\n logger.info(COMPONENT, `WebSocket: ${wsProto}://${host}:${port}`);\n logger.info(COMPONENT, `API: ${proto}://${host}:${port}/api/health`);\n logger.info(COMPONENT, `\\nChannels: ${Array.from(channels.values()).map((c) => `${c.displayName} (${c.getStatus().connected ? '✅' : '❌'})`).join(', ')}`);\n logger.info(COMPONENT, `Skills: ${getSkills().length} loaded`);\n logger.info(COMPONENT, `Tools: ${getRegisteredTools().length} registered`);\n\n // Friendly update notice for upgraders\n try {\n const markerPath = join(homedir(), '.titan', 'install-marker.json');\n if (fs.existsSync(markerPath)) {\n const marker = JSON.parse(fs.readFileSync(markerPath, 'utf-8'));\n if (marker.previousVersion && marker.previousVersion !== TITAN_VERSION) {\n logger.info(COMPONENT, `\\n🚀 Welcome to TITAN v${TITAN_VERSION}! Upgraded from v${marker.previousVersion}.`);\n logger.info(COMPONENT, ` What's new: PostHog analytics (opt-in), enriched telemetry, secret-scrubbed crash reports.`);\n logger.info(COMPONENT, ` Your config and settings are untouched. See PRIVACY.md for details.\\n`);\n }\n }\n } catch { /* non-critical */ }\n\n // Start Cloudflare Tunnel if enabled\n if (config.tunnel?.enabled) {\n startTunnel(port, config.tunnel).catch((e) => {\n logger.error(COMPONENT, `Tunnel start failed: ${(e as Error).message}`);\n });\n }\n\n // Start analytics collection (telemetry must be enabled)\n recordStartupAnalytics().catch(() => {});\n startHeartbeatAnalytics(() => listSessions().length);\n });\n}\n\n"],"mappings":"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","names":["resolve","isAllowedOrigin","getDb","getGraphStats","sseWrite","config","host","getMetricsSummary","getLearningStats"]}
|
|
1
|
+
{"version":3,"sources":["../../src/gateway/server.ts"],"sourcesContent":["/**\n * TITAN — Gateway Server\n * WebSocket + HTTP server: the control plane for all channels, agents, tools, and the web UI.\n */\nimport express, { type Request, type Response, type NextFunction } from 'express';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createServer } from 'http';\nimport { createServer as createHttpsServer } from 'https';\nimport net from 'net';\nimport { join, dirname, resolve } from 'path';\nimport { fileURLToPath } from 'url';\nimport { homedir, hostname as osHostname, cpus, loadavg } from 'os';\nimport { randomBytes, timingSafeEqual } from 'crypto';\nimport { exec, execSync, spawn } from 'child_process';\nimport fs from 'fs';\nimport { loadConfig, updateConfig } from '../config/config.js';\nimport type { ProviderConfig } from '../config/schema.js';\nimport { loadProfile, saveProfile, type PersonalProfile } from '../memory/relationship.js';\nimport { processMessage } from '../agent/agent.js';\nimport { onAgentEvent } from '../agent/agentEvents.js';\nimport { initMemory, closeMemory, getUsageStats, getHistory, getDb } from '../memory/memory.js';\nimport { initBuiltinSkills, getSkills, toggleSkill, getSkillTools } from '../skills/registry.js';\nimport { listPersonas, getPersona, invalidatePersonaCache } from '../personas/manager.js';\nimport { searchSkills as marketplaceSearch, installSkill, uninstallSkill, listSkills as listMarketplaceSkills, listInstalled as listInstalledMarketplace } from '../skills/marketplace.js';\nimport { getRegisteredTools } from '../agent/toolRunner.js';\nimport { listSessions, cleanupStaleSessions } from '../agent/session.js';\nimport { healthCheckAll, discoverAllModels, getModelAliases, chatStream, getFallbackState } from '../providers/router.js';\nimport { auditSecurity } from '../security/sandbox.js';\nimport { WebChatChannel } from '../channels/webchat.js';\nimport { DiscordChannel } from '../channels/discord.js';\nimport { TelegramChannel } from '../channels/telegram.js';\nimport { SlackChannel } from '../channels/slack.js';\nimport { GoogleChatChannel } from '../channels/googlechat.js';\nimport { WhatsAppChannel } from '../channels/whatsapp.js';\nimport { MatrixChannel } from '../channels/matrix.js';\nimport { SignalChannel } from '../channels/signal.js';\nimport { MSTeamsChannel } from '../channels/msteams.js';\nimport { IRCChannel } from '../channels/irc.js';\nimport { MattermostChannel } from '../channels/mattermost.js';\nimport { LarkChannel } from '../channels/lark.js';\nimport { EmailInboundChannel } from '../channels/email_inbound.js';\nimport { LineChannel } from '../channels/line.js';\nimport { ZulipChannel } from '../channels/zulip.js';\nimport { MessengerChannel } from '../channels/messenger.js';\nimport { initAgents, routeMessage, listAgents } from '../agent/multiAgent.js';\nimport { createOpenAICompatRouter } from '../gateway/openai-compat.js';\nimport type { ChannelAdapter, InboundMessage } from '../channels/base.js';\nimport logger, { initFileLogger } from '../utils/logger.js';\nimport { TITAN_VERSION, TITAN_NAME, TITAN_LOGS_DIR, TITAN_HOME } from '../utils/constants.js';\nimport { getRestartStats as getRestartStatsSync } from '../utils/restartTracker.js';\nimport { collectSystemProfile, recordStartupAnalytics, startHeartbeatAnalytics } from '../analytics/collector.js';\nimport { getUpdateInfo } from '../utils/updater.js';\nimport { getMissionControlHTML } from './dashboard.js';\nimport { serializePrometheus, getMetricsSummary, titanRequestsTotal, titanRequestDuration, titanErrorsTotal, titanActiveSessions, titanToolCallsTotal, titanTokensTotal, titanModelRequestsTotal, recordEvalSuiteResult, recordEvalTimeout, recordEvalError } from './metrics.js';\nimport { createHardwareRouter } from './routes/hardwareRouter.js';\nimport { createMetricsRouter } from './routes/metricsRouter.js';\nimport { createMcpRouter } from './routes/mcpRouter.js';\nimport { createAgentsRouter } from './routes/agentsRouter.js';\nimport { initSlashCommands, handleSlashCommand } from './slashCommands.js';\nimport { initMcpServers } from '../mcp/registry.js';\nimport { mountMcpHttpEndpoints } from '../mcp/server.js';\nimport { initMonitors, setMonitorTriggerHandler, listMonitors, addMonitor, removeMonitor, getMonitorEvents } from '../agent/monitor.js';\nimport { seedBuiltinRecipes } from '../recipes/store.js';\nimport { parseSlashCommand, runRecipe } from '../recipes/runner.js';\nimport { getCostStatus } from '../agent/costOptimizer.js';\nimport { initLearning, getLearningStats } from '../memory/learning.js';\nimport { initGraph, getGraphStats, clearGraph, flushGraph } from '../memory/graph.js';\nimport { getLogFilePath } from '../utils/logger.js';\nimport { closeSession, renameSession, sweepSessions } from '../agent/session.js';\nimport { initCronScheduler } from '../skills/builtin/cron.js';\nimport { checkAndSendBriefing } from '../memory/briefing.js';\nimport { initPersistentWebhooks } from '../skills/builtin/webhook.js';\nimport { invalidateCacheForModel } from '../agent/responseCache.js';\nimport { initAutopilot, stopAutopilot, getAutopilotStatus } from '../agent/autopilot.js';\nimport { initDaemon, stopDaemon, titanEvents } from '../agent/daemon.js';\nimport { initCommandPost, shutdownCommandPost, isCommandPostEnabled, reportHeartbeat } from '../agent/commandPost.js';\nimport { initWakeupSystem } from '../agent/agentWakeup.js';\nimport { initHeartbeatScheduler } from '../agent/heartbeatScheduler.js';\nimport { auditLog } from '../agent/auditLog.js';\nimport { startTunnel, stopTunnel, getTunnelStatus } from '../utils/tunnel.js';\nimport { createPaperclipRouter, createPaperclipUIRouter } from './routes/paperclip.js';\nimport { createTracesRouter } from './routes/traces.js';\nimport { createCheckpointsRouter } from './routes/checkpoints.js';\nimport { createCompaniesRouter } from './routes/companies.js';\nimport { createCommandPostRouter } from './routes/commandPost.js';\nimport { createAdminRouter } from './routes/adminRouter.js';\nimport { createTeamsRecipesRouter } from './routes/teamsRecipes.js';\nimport { createFilesRouter } from './routes/files.js';\nimport { createSessionsRouter } from './routes/sessions.js';\nimport { createSkillsRouter } from './routes/skills.js';\nimport { createOrganismRouter } from './routes/organism.js';\nimport { createMeshRouter } from './routes/mesh.js';\nimport { createTestsRouter } from './routes/tests.js';\nimport { createSystemRouter } from './routes/systemRouter.js';\nimport { createVoiceRouter } from './routes/voiceRouter.js';\n\nimport { createSocialRouter } from './routes/socialRouter.js';\nimport { createWatchRouter } from './routes/watchRouter.js';\nimport { setupSSEFlush } from '../utils/sseFlush.js';\nimport { createLifecycleRouter } from './routes/agents.js';\n\nimport { getLifecycleManager } from '../utils/lifecycle.js';\nimport { startVoiceAgent, stopVoiceAgent } from '../skills/builtin/voice_control.js';\nconst COMPONENT = 'Gateway';\n\n/** Get normalized CPU load (0.0–1.0) using 1-minute load average */\nfunction getCpuLoad(): number {\n const avg = loadavg()[0]; // 1-minute load average\n const cores = cpus().length || 1;\n return Math.min(1, avg / cores);\n}\n\n/** Fields that require a gateway restart to take effect */\nconst RESTART_REQUIRED_PATTERNS = ['channels.*', 'gateway.auth.*', 'logging.level'];\n\n/** Module-level HTTP server reference (allows stopGateway to close it) */\nlet httpServer: ReturnType<typeof createServer> | null = null;\n\n/** Interval IDs for cleanup on shutdown */\nlet tokenCleanupInterval: ReturnType<typeof setInterval> | null = null;\nlet rateLimitCleanupInterval: ReturnType<typeof setInterval> | null = null;\nlet healthMonitorInterval: ReturnType<typeof setInterval> | null = null;\nlet sessionAbortCleanupInterval: ReturnType<typeof setInterval> | null = null;\nlet unsubscribeAgentEvents: (() => void) | null = null;\nlet activeLlmRequests = 0;\nexport function getActiveLlmRequests(): number { return activeLlmRequests; }\nlet maxConcurrentOverride: number | null = null;\n\n// ── Module-level constants (avoid per-request allocation) ──────────\n\nconst CP_SSE_EVENTS = [\n 'commandpost:activity', 'commandpost:task:checkout', 'commandpost:task:checkin',\n 'commandpost:task:expired', 'commandpost:budget:warning', 'commandpost:budget:exceeded',\n 'commandpost:agent:heartbeat', 'commandpost:agent:status',\n];\nconst ALLOWED_ORIGINS = [\n /^https?:\\/\\/localhost(:\\d+)?$/,\n /^https?:\\/\\/127\\.0\\.0\\.1(:\\d+)?$/,\n /^https?:\\/\\/\\[::1\\](:\\d+)?$/,\n /^https?:\\/\\/192\\.168\\.\\d+\\.\\d+(:\\d+)?$/, // LAN\n];\nfunction isAllowedOrigin(origin: string): boolean {\n return ALLOWED_ORIGINS.some(re => re.test(origin));\n}\n\n/**\n * Classify a chat error into a structured response that the React UI can render\n * as an actionable banner. Without this, every failure shows up as a generic 500\n * with a stack trace that means nothing to a non-developer.\n *\n * The classifier returns:\n * { error: string, message: string, status: number, action?: { type, target } }\n *\n * Known error codes (must match what the UI knows how to render):\n * - no_provider_configured → no API keys / Ollama unreachable\n * - rate_limited → 429 from upstream\n * - context_too_long → context window exceeded\n * - model_not_found → invalid model id\n * - auth_failed → 401/403 from upstream\n * - upstream_error → other 4xx/5xx from upstream\n * - timeout → request timed out\n * - unknown → fallback for everything else\n */\ninterface ChatErrorResponse {\n error: string;\n message: string;\n detail?: string;\n status: number;\n action?: { type: 'open' | 'retry' | 'docs'; target: string; label: string };\n}\nfunction classifyChatError(err: Error): ChatErrorResponse {\n const msg = (err.message || String(err)).toLowerCase();\n const detail = err.message;\n\n // No provider configured / no valid API key\n if (\n msg.includes('no valid provider') ||\n msg.includes('no api key') ||\n msg.includes('not configured') ||\n msg.includes('provider not found')\n ) {\n return {\n error: 'no_provider_configured',\n message: 'No AI provider is configured. Set up a provider to start chatting.',\n detail,\n status: 503,\n action: { type: 'open', target: '/settings', label: 'Open settings' },\n };\n }\n\n // Rate limited / quota exhausted\n if (\n msg.includes('rate limit') ||\n msg.includes('429') ||\n msg.includes('quota') ||\n msg.includes('too many requests')\n ) {\n return {\n error: 'rate_limited',\n message: \"You've hit your provider's rate limit. Wait a moment and try again, or switch providers in Settings.\",\n detail,\n status: 429,\n action: { type: 'retry', target: '', label: 'Retry' },\n };\n }\n\n // Context window exceeded\n if (\n msg.includes('context length') ||\n msg.includes('context window') ||\n msg.includes('maximum context') ||\n msg.includes('too many tokens') ||\n msg.includes('context_length_exceeded') ||\n msg.includes('prompt is too long')\n ) {\n return {\n error: 'context_too_long',\n message: 'The conversation got too long for the model. Start a new session or compact this one.',\n detail,\n status: 413,\n action: { type: 'open', target: '/sessions', label: 'New session' },\n };\n }\n\n // Model not found / invalid model id\n if (\n msg.includes('model not found') ||\n msg.includes('invalid model') ||\n msg.includes('unknown model') ||\n msg.includes('model_not_found') ||\n msg.includes('does not exist')\n ) {\n return {\n error: 'model_not_found',\n message: \"The selected model doesn't exist or you don't have access to it. Pick a different model in Settings.\",\n detail,\n status: 404,\n action: { type: 'open', target: '/settings', label: 'Pick a model' },\n };\n }\n\n // Auth failure (bad key / expired)\n if (\n msg.includes('401') ||\n msg.includes('403') ||\n msg.includes('unauthorized') ||\n msg.includes('forbidden') ||\n msg.includes('authentication') ||\n msg.includes('invalid api key') ||\n msg.includes('invalid_api_key')\n ) {\n return {\n error: 'auth_failed',\n message: 'Your API key was rejected by the provider. Check it in Settings → Providers.',\n detail,\n status: 401,\n action: { type: 'open', target: '/settings', label: 'Check API key' },\n };\n }\n\n // Timeout\n if (\n msg.includes('timeout') ||\n msg.includes('timed out') ||\n msg.includes('etimedout') ||\n msg.includes('aborted')\n ) {\n return {\n error: 'timeout',\n message: 'The model took too long to respond. Try again, or switch to a faster model.',\n detail,\n status: 504,\n action: { type: 'retry', target: '', label: 'Retry' },\n };\n }\n\n // Upstream provider error\n if (\n msg.includes('500') || msg.includes('502') || msg.includes('503') ||\n msg.includes('gateway') || msg.includes('upstream')\n ) {\n return {\n error: 'upstream_error',\n message: \"Your AI provider is having issues right now. Try again, or switch providers.\",\n detail,\n status: 502,\n action: { type: 'retry', target: '', label: 'Retry' },\n };\n }\n\n // Fallback\n return {\n error: 'unknown',\n message: detail || 'Something went wrong while processing your message.',\n detail,\n status: 500,\n };\n}\n\n/** Internal health monitor state */\nconst healthState = {\n ollamaHealthy: false,\n ttsHealthy: false,\n lastCheck: null as string | null,\n lastActiveLlm: 0,\n lastActiveLlmTime: 0,\n stuckDetected: false,\n};\n\nexport function stopGateway(): Promise<void> {\n return new Promise((resolve) => {\n // Clear intervals to release the event loop\n if (tokenCleanupInterval) { clearInterval(tokenCleanupInterval); tokenCleanupInterval = null; }\n if (rateLimitCleanupInterval) { clearInterval(rateLimitCleanupInterval); rateLimitCleanupInterval = null; }\n if (healthMonitorInterval) { clearInterval(healthMonitorInterval); healthMonitorInterval = null; }\n if (sessionAbortCleanupInterval) { clearInterval(sessionAbortCleanupInterval); sessionAbortCleanupInterval = null; }\n if (unsubscribeAgentEvents) { unsubscribeAgentEvents(); unsubscribeAgentEvents = null; }\n\n if (httpServer) {\n // Force-close open connections after 3 seconds (SSE/WebSocket keep-alives block shutdown)\n const forceTimeout = setTimeout(() => {\n logger.warn('Gateway', 'Shutdown timeout — destroying remaining connections');\n httpServer?.closeAllConnections?.();\n httpServer = null;\n resolve();\n }, 3000);\n forceTimeout.unref();\n\n httpServer.close(() => {\n clearTimeout(forceTimeout);\n httpServer = null;\n resolve();\n });\n } else {\n resolve();\n }\n });\n}\n\n/** Usage tracking — per-request cost/token tracking */\ninterface UsageEntry {\n timestamp: string;\n model: string;\n provider: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n estimatedCostUsd: number;\n durationMs: number;\n sessionId: string;\n}\nconst usageLog: UsageEntry[] = [];\nconst MAX_USAGE_LOG = 10000; // Keep last 10K entries in memory\n\n// Approximate cost per 1M tokens (input/output) for common models\nconst MODEL_COSTS: Record<string, { input: number; output: number }> = {\n 'claude-sonnet': { input: 3, output: 15 },\n 'claude-haiku': { input: 0.25, output: 1.25 },\n 'claude-opus': { input: 15, output: 75 },\n 'gpt-4o': { input: 2.5, output: 10 },\n 'gpt-4o-mini': { input: 0.15, output: 0.6 },\n 'gpt-4-turbo': { input: 10, output: 30 },\n 'ollama': { input: 0, output: 0 }, // local = free\n 'groq': { input: 0.05, output: 0.08 },\n 'deepseek': { input: 0.14, output: 0.28 },\n};\n\nfunction estimateCost(model: string, promptTokens: number, completionTokens: number): number {\n const key = Object.keys(MODEL_COSTS).find(k => model.toLowerCase().includes(k));\n if (!key) return 0;\n const rates = MODEL_COSTS[key];\n return (promptTokens * rates.input + completionTokens * rates.output) / 1_000_000;\n}\n\nfunction trackUsage(model: string, tokenUsage: { prompt?: number; completion?: number } | undefined, durationMs: number, sessionId: string): void {\n if (!tokenUsage) return;\n const prompt = tokenUsage.prompt || 0;\n const completion = tokenUsage.completion || 0;\n const provider = model.includes('/') ? model.split('/')[0] : 'unknown';\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n model,\n provider,\n promptTokens: prompt,\n completionTokens: completion,\n totalTokens: prompt + completion,\n estimatedCostUsd: estimateCost(model, prompt, completion),\n durationMs,\n sessionId,\n };\n usageLog.push(entry);\n if (usageLog.length > MAX_USAGE_LOG) usageLog.splice(0, usageLog.length - MAX_USAGE_LOG);\n}\n\n/** Active session tokens (persisted to disk so they survive restarts) */\nconst AUTH_TOKENS_PATH = join(TITAN_HOME, 'auth-tokens.json');\n\nfunction loadAuthTokens(): Map<string, { createdAt: number; userId: string }> {\n const map = new Map<string, { createdAt: number; userId: string }>();\n try {\n if (fs.existsSync(AUTH_TOKENS_PATH)) {\n const raw = JSON.parse(fs.readFileSync(AUTH_TOKENS_PATH, 'utf-8'));\n if (Array.isArray(raw)) {\n const ttlMs = 24 * 60 * 60 * 1000;\n const now = Date.now();\n for (const item of raw) {\n if (item && typeof item.token === 'string' && typeof item.createdAt === 'number' && typeof item.userId === 'string') {\n if (now - item.createdAt <= ttlMs) {\n map.set(item.token, { createdAt: item.createdAt, userId: item.userId });\n }\n }\n }\n }\n }\n } catch {\n // Best-effort: if file is corrupt, start fresh\n }\n return map;\n}\n\nfunction saveAuthTokens(): void {\n try {\n const entries = [];\n for (const [token, entry] of authTokens) {\n entries.push({ token, createdAt: entry.createdAt, userId: entry.userId });\n }\n fs.writeFileSync(AUTH_TOKENS_PATH, JSON.stringify(entries, null, 2));\n } catch {\n // Best-effort persistence\n }\n}\n\nconst authTokens = loadAuthTokens();\n\n/** S3: Get userId from request auth token */\nfunction getUserIdFromReq(req: { headers: { authorization?: string } }): string {\n const token = req.headers.authorization?.replace('Bearer ', '');\n if (token) {\n const entry = authTokens.get(token);\n if (entry) return entry.userId;\n }\n return 'default-user';\n}\n\n// Active session abort controllers — keyed by sessionId\nconst sessionAborts = new Map<string, AbortController>();\n// R8: Track abort controller creation time for TTL-based cleanup\nconst sessionAbortTimes = new Map<string, number>();\n\n// S3: Track session ownership — sessionId → userId\nconst sessionOwners = new Map<string, string>();\n\n// R8: Periodic cleanup of orphaned abort controllers (TTL 5 min)\nsessionAbortCleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [id, controller] of sessionAborts) {\n if (controller.signal.aborted || (now - (sessionAbortTimes.get(id) || 0)) > 300_000) {\n sessionAborts.delete(id);\n sessionAbortTimes.delete(id);\n sessionOwners.delete(id);\n }\n }\n}, 60_000);\nsessionAbortCleanupInterval.unref();\n\n// Clean expired tokens every 10 minutes\ntokenCleanupInterval = setInterval(() => {\n const now = Date.now();\n const ttlMs = 24 * 60 * 60 * 1000;\n for (const [tok, entry] of authTokens) {\n if (now - entry.createdAt > ttlMs) authTokens.delete(tok);\n }\n saveAuthTokens();\n}, 600_000);\ntokenCleanupInterval.unref();\n\n/** Constant-time string comparison to prevent timing attacks */\nfunction safeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n}\n\n/** Check if a request token is valid */\nfunction isValidToken(token: string | undefined, config: ReturnType<typeof loadConfig>): boolean {\n const auth = config.gateway.auth;\n if (!auth || auth.mode === 'none') return true;\n if (!token) return false;\n // S2: If token mode but no token configured, log warning and deny (don't silently allow)\n if (auth.mode === 'token') {\n if (!auth.token) {\n logger.warn(COMPONENT, 'Auth mode is \"token\" but no token configured — denying request. Set gateway.auth.token or switch to mode \"password\".');\n return false;\n }\n return safeCompare(token, auth.token);\n }\n if (auth.mode === 'password') {\n const entry = authTokens.get(token);\n if (!entry) return false;\n const ttlMs = 24 * 60 * 60 * 1000; // 24 hours\n if (Date.now() - entry.createdAt > ttlMs) {\n authTokens.delete(token);\n saveAuthTokens();\n return false;\n }\n return true;\n }\n return false;\n}\n\n/** Login page HTML */\nfunction getLoginHTML(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\"/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n<title>TITAN — Login</title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n@keyframes gradientBg{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}\n@keyframes shimmer{0%{background-position:-200% center}100%{background-position:200% center}}\n@keyframes shake{0%,100%{transform:translateX(0)}10%,30%,50%,70%,90%{transform:translateX(-4px)}20%,40%,60%,80%{transform:translateX(4px)}}\n@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}\nbody{font-family:'Inter','Segoe UI',system-ui,sans-serif;background:linear-gradient(135deg,#0a0e1a 0%,#0f172a 25%,#1a1040 50%,#0f172a 75%,#0a0e1a 100%);background-size:400% 400%;animation:gradientBg 15s ease infinite;color:#e2e8f0;display:flex;align-items:center;justify-content:center;min-height:100vh}\n.box{background:rgba(17,24,39,0.85);backdrop-filter:blur(20px);border:1px solid rgba(42,48,80,0.6);border-radius:16px;padding:40px;width:380px;box-shadow:0 0 40px rgba(6,182,212,.1),0 0 80px rgba(139,92,246,.05);animation:fadeIn .6s ease-out}\n.box.shake{animation:shake .5s ease}\nh1{font-size:28px;font-weight:700;background:linear-gradient(90deg,#06b6d4,#8b5cf6,#06b6d4);background-size:200% auto;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:shimmer 3s linear infinite;text-align:center;letter-spacing:3px;margin-bottom:4px}\n.sub{text-align:center;color:#94a3b8;font-size:13px;margin-bottom:32px}\nlabel{font-size:12px;color:#94a3b8;text-transform:uppercase;letter-spacing:1px;display:block;margin-bottom:8px}\ninput{width:100%;background:rgba(26,31,54,0.8);border:1px solid #2a3050;border-radius:10px;padding:12px 16px;color:#e2e8f0;font-size:15px;outline:none;transition:border .2s,box-shadow .2s}\ninput:focus{border-color:#06b6d4;box-shadow:0 0 12px rgba(6,182,212,.2)}\nbutton{width:100%;margin-top:20px;background:linear-gradient(135deg,#06b6d4,#8b5cf6);border:none;border-radius:10px;padding:14px;color:#fff;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .2s,transform .1s}\nbutton:hover{opacity:.9;transform:translateY(-1px)}\nbutton:active{transform:translateY(0)}\n.error{color:#ef4444;font-size:13px;margin-top:12px;text-align:center;display:none}\n</style>\n</head>\n<body>\n<div class=\"box\">\n <h1>⚡ TITAN</h1>\n <div class=\"sub\">Mission Control</div>\n <label>Password</label>\n <input type=\"password\" id=\"pw\" placeholder=\"Enter gateway password\" onkeydown=\"if(event.key==='Enter')login()\"/>\n <button onclick=\"login()\">Unlock</button>\n <div class=\"error\" id=\"err\">Incorrect password. Try again.</div>\n</div>\n<script>\nasync function login() {\n const pw = document.getElementById('pw').value;\n const res = await fetch('/api/login', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:pw})});\n if (res.ok) {\n const {token} = await res.json();\n localStorage.setItem('titan_token', token);\n location.href = '/';\n } else {\n document.getElementById('err').style.display = 'block';\n document.getElementById('pw').value = '';\n document.getElementById('pw').focus();\n const box = document.querySelector('.box');\n box.classList.remove('shake');\n void box.offsetWidth;\n box.classList.add('shake');\n }\n}\ndocument.getElementById('pw').focus();\n</script>\n</body>\n</html>`;\n}\n\n/** All active channel adapters */\nconst channels: Map<string, ChannelAdapter> = new Map();\n\n/** All connected WebSocket clients */\ninterface TaggedWebSocket extends WebSocket {\n titanSessionId?: string;\n titanUserId?: string;\n}\nconst wsClients: Set<TaggedWebSocket> = new Set();\nconst WS_MAX_MESSAGE_BYTES = 10 * 1024 * 1024; // 10MB max WS message\n\n/** The WebChat channel instance */\nlet webChatChannel: WebChatChannel | null = null;\n\n/** Broadcast a message to WebSocket clients. If userId is specified, only sends to that user's connections. */\nfunction broadcast(data: Record<string, unknown>, userId?: string): void {\n const json = JSON.stringify(data);\n for (const client of wsClients) {\n if (client.readyState === WebSocket.OPEN) {\n // Session isolation: if userId specified, only send to matching clients\n if (userId && (client as TaggedWebSocket).titanUserId && (client as TaggedWebSocket).titanUserId !== userId) continue;\n try {\n client.send(json);\n } catch (err) {\n logger.warn(COMPONENT, `Broadcast send failed: ${(err as Error).message}`);\n }\n }\n }\n}\n\n// Sub-agent event bridge: forward agent bus events to SSE broadcast\nunsubscribeAgentEvents = onAgentEvent((event) => {\n const sseType = event.type === 'tool_call' ? 'tool_call' : event.type === 'tool_end' ? 'tool_end' : event.type;\n broadcast({ type: sseType, ...event.data, agentName: event.agentName, agentId: event.agentId, isSubAgent: true, timestamp: event.timestamp });\n});\n\n// Initiative event bridge: broadcast autonomous task progress to dashboard chat\ntitanEvents.on('initiative:start', (data) => {\n broadcast({\n type: 'system_message',\n content: `🤖 **Initiative starting**: ${(data as Record<string, string>).subtaskTitle}\\n📋 Goal: ${(data as Record<string, string>).goalTitle}`,\n source: 'initiative',\n timestamp: (data as Record<string, string>).timestamp,\n });\n});\ntitanEvents.on('initiative:complete', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `✅ **Subtask completed**: ${d.subtaskTitle}\\n🔧 Tools: ${(d.toolsUsed as string[]).join(', ')}\\n📝 ${(d.summary as string || '').slice(0, 200)}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:no_progress', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `⚠️ **No progress on**: ${d.subtaskTitle}\\n${d.reason}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:tool_call', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `🔧 **${d.tool}**: ${d.args || ''}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:tool_result', (data) => {\n const d = data as Record<string, unknown>;\n const icon = d.success ? '✅' : '❌';\n broadcast({\n type: 'system_message',\n content: `${icon} **${d.tool}** ${d.success ? 'completed' : 'failed'} (${d.durationMs}ms)`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\ntitanEvents.on('initiative:round', (data) => {\n const d = data as Record<string, unknown>;\n broadcast({\n type: 'system_message',\n content: `🔄 **Round ${d.round}/${d.maxRounds}** — ${d.subtaskTitle}`,\n source: 'initiative',\n timestamp: d.timestamp as string,\n });\n});\n\n/** Safely send a response through a channel adapter.\n * Hunt Finding #13: uses deliver() which runs the content through the\n * outbound sanitizer before invoking the channel's send() method. Applies\n * to all 17 channel adapters automatically. */\nasync function safeSend(channelName: string, msg: { channel: string; userId: string; groupId?: string; content: string; replyTo?: string }): Promise<void> {\n const channel = channels.get(channelName);\n if (!channel) return;\n try {\n await channel.deliver(msg);\n } catch (err) {\n logger.warn(COMPONENT, `Channel send failed (${channelName}): ${(err as Error).message}`);\n }\n}\n\n/** Handle an inbound message from any channel */\nasync function handleInboundMessage(msg: InboundMessage): Promise<void> {\n logger.info(COMPONENT, `[${msg.channel}] ${msg.userName || msg.userId}: ${msg.content.slice(0, 100)}`);\n\n // Broadcast to WebSocket clients for UI\n broadcast({\n type: 'message',\n direction: 'inbound',\n channel: msg.channel,\n userId: msg.userId,\n userName: msg.userName,\n content: msg.content,\n timestamp: msg.timestamp.toISOString(),\n });\n\n // ── Native slash commands (highest priority) ──────────────────\n const slashResult = await handleSlashCommand(msg.content, msg.channel, msg.userId);\n if (slashResult) {\n await safeSend(msg.channel, { channel: msg.channel, userId: msg.userId, groupId: msg.groupId, content: slashResult.response, replyTo: msg.id });\n broadcast({ type: 'message', direction: 'outbound', channel: msg.channel, userId: msg.userId, content: slashResult.response, timestamp: new Date().toISOString() });\n return;\n }\n\n // ── Recipe slash commands (second priority) ──────────────────\n const slash = parseSlashCommand(msg.content);\n if (slash) {\n const { command, args } = slash;\n const params: Record<string, string> = {};\n if (args) { params['file'] = args; params['topic'] = args; params['error'] = args; }\n try {\n let fullResponse = '';\n for await (const step of runRecipe(command, params)) {\n const r = await processMessage(step.prompt, msg.channel, msg.userId);\n fullResponse += (fullResponse ? '\\n\\n' : '') + r.content;\n }\n await safeSend(msg.channel, { channel: msg.channel, userId: msg.userId, groupId: msg.groupId, content: fullResponse, replyTo: msg.id });\n broadcast({ type: 'message', direction: 'outbound', channel: msg.channel, userId: msg.userId, content: fullResponse, timestamp: new Date().toISOString() });\n return;\n } catch {\n // Recipe not found — fall through to normal processing\n }\n }\n\n try {\n // Route through multi-agent system\n const response = await routeMessage(msg.content, msg.channel, msg.userId);\n\n // Send response back to the channel\n await safeSend(msg.channel, {\n channel: msg.channel,\n userId: msg.userId,\n groupId: msg.groupId,\n content: response.content,\n replyTo: msg.id,\n });\n\n // Broadcast response to UI\n broadcast({\n type: 'message',\n direction: 'outbound',\n channel: msg.channel,\n userId: msg.userId,\n content: response.content,\n toolsUsed: response.toolsUsed,\n tokenUsage: response.tokenUsage,\n durationMs: response.durationMs,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error(COMPONENT, `Error processing message: ${(error as Error).message}`);\n broadcast({ type: 'error', message: 'TITAN ran into a problem handling that message. Please try again.' });\n }\n}\n\n/** Start the Gateway server */\nexport async function startGateway(options?: { port?: number; host?: string; verbose?: boolean; rateLimitMax?: number; rateLimitWindowMs?: number; skipUsableCheck?: boolean }): Promise<void> {\n const config = loadConfig();\n initFileLogger(TITAN_LOGS_DIR);\n const port = options?.port || config.gateway.port;\n let host = options?.host || config.gateway.host;\n\n // Hunt Finding #29 (2026-04-14): install a bounded global HTTP dispatcher\n // BEFORE any fetch() calls are made. Without this, each parallel Ollama\n // fetch opens a fresh socket and the keep-alive pool grows unboundedly.\n // Phase 5 load test saw 80+ idle sockets to Ollama after 100 requests.\n try {\n const { installGlobalHttpPool } = await import('../utils/httpPool.js');\n const poolCfg = (config.gateway as unknown as { httpPool?: { connections?: number; keepAliveTimeoutMs?: number; keepAliveMaxTimeoutMs?: number; headersTimeoutMs?: number; bodyTimeoutMs?: number } }).httpPool;\n installGlobalHttpPool({\n connections: poolCfg?.connections,\n keepAliveTimeoutMs: poolCfg?.keepAliveTimeoutMs,\n keepAliveMaxTimeoutMs: poolCfg?.keepAliveMaxTimeoutMs,\n headersTimeoutMs: poolCfg?.headersTimeoutMs,\n bodyTimeoutMs: poolCfg?.bodyTimeoutMs,\n });\n } catch (e) {\n logger.warn(COMPONENT, `[HttpPool] Failed to install global dispatcher: ${(e as Error).message} — fetch() will use Node defaults (unbounded pool)`);\n }\n\n logger.info(COMPONENT, `Starting ${TITAN_NAME} Gateway v${TITAN_VERSION}`);\n\n // v5.5.28 FIX: sweep orphaned atomic-write tmp files. atomicWriteFileSync\n // writes to .tmp.<ts>.<rand> then renames; if the process is killed\n // between those steps the tmp file leaks. The 2026-05-08 audit found\n // 188MB of these (vectors.json + test-history). Best-effort.\n try {\n const { sweepAtomicTmpOrphans } = await import('../utils/helpers.js');\n const swept = sweepAtomicTmpOrphans(TITAN_HOME);\n if (swept.removed > 0) {\n logger.info(COMPONENT, `Swept ${swept.removed} orphaned tmp file(s) from ${TITAN_HOME} — recovered ${(swept.bytes / 1024 / 1024).toFixed(1)} MB`);\n }\n } catch (e) {\n logger.warn(COMPONENT, `tmp sweep failed: ${(e as Error).message}`);\n }\n\n // Persist this boot so we can detect restart loops across systemd-managed\n // restarts. See src/utils/restartTracker.ts for why a single process can't\n // see its own loop.\n try {\n const { recordBoot, getRestartStats } = await import('../utils/restartTracker.js');\n recordBoot(TITAN_VERSION);\n const stats = getRestartStats();\n if (stats.severity !== 'ok' && stats.reason) {\n const { sendAlert } = await import('../agent/alerts.js');\n sendAlert(\n stats.severity,\n 'Gateway restart loop detected',\n stats.reason,\n 'restart-tracker',\n {\n restartsLast10Min: stats.restartsLast10Min,\n restartsLastHour: stats.restartsLastHour,\n nRestartsSystemd: stats.nRestartsSystemd,\n previousBootAt: stats.previousBootAt,\n },\n );\n }\n } catch (err) {\n logger.warn(COMPONENT, `restart tracker init failed: ${(err as Error).message}`);\n }\n\n // ── First-run guard: refuse to start with no usable provider ──\n // Without this, the gateway boots fine but every chat call fails with a\n // generic 500. Users have no idea they need to configure a provider.\n // Bypass with --skip-usable-check (or skipUsableCheck option) for advanced use.\n if (!options?.skipUsableCheck) {\n const { hasUsableProvider } = await import('../config/config.js');\n const usable = await hasUsableProvider();\n if (!usable.ok) {\n console.error('');\n console.error('\\x1b[31m\\x1b[1m❌ TITAN is not configured.\\x1b[0m');\n console.error('');\n console.error(` ${usable.details}`);\n console.error('');\n console.error(' Run the setup wizard:');\n console.error(' \\x1b[36mtitan onboard\\x1b[0m');\n console.error('');\n console.error(' Or set an environment variable:');\n console.error(' \\x1b[36mexport ANTHROPIC_API_KEY=\"sk-ant-...\"\\x1b[0m');\n console.error(' \\x1b[36mexport OPENAI_API_KEY=\"sk-...\"\\x1b[0m');\n console.error(' \\x1b[36mexport OLLAMA_BASE_URL=\"http://localhost:11434\"\\x1b[0m');\n console.error('');\n console.error(' Or check what went wrong:');\n console.error(' \\x1b[36mtitan doctor\\x1b[0m');\n console.error('');\n console.error(' To skip this check (advanced):');\n console.error(' \\x1b[36mtitan gateway --skip-usable-check\\x1b[0m');\n console.error('');\n process.exit(1);\n }\n logger.info(COMPONENT, `Provider check passed: ${usable.details}`);\n }\n\n // ── Production safety warning ─────────────────────────────────────\n if (config.autonomy?.mode === 'autonomous') {\n logger.warn(COMPONENT, '⚠️ AUTONOMY MODE IS \"autonomous\" — all tools run without approval. Safe for personal use, DANGEROUS for multi-user deployments.');\n logger.warn(COMPONENT, ' Set autonomy.mode to \"supervised\" in titan.json if exposing to external users.');\n }\n if (config.commandPost?.enabled) {\n logger.info(COMPONENT, '✅ Command Post governance is active — approvals route through CP queue');\n } else {\n logger.warn(COMPONENT, '⚠️ Command Post is DISABLED — no approval queue, no budget enforcement, no agent registry');\n }\n if (config.selfMod?.enabled) {\n logger.info(COMPONENT, '✅ Self-modification is active — writes are staged for human review');\n }\n\n // ── Stale session cleanup: mark orphaned active sessions as idle ──\n cleanupStaleSessions();\n // Run every 60s so ephemeral one-shot sessions (api / autoresearch-* /\n // initiative-* / monitor / mesh / etc.) get cleared promptly within their\n // 5min idle TTL. Persistent channels (webchat / voice / discord / ...)\n // still use the full SESSION_TIMEOUT_MS (30min) inside cleanupStaleSessions.\n // Pre-fix: 5min interval + uniform 30min TTL accumulated 755 sessions in\n // 29min on the live service (Kimi observation, 2026-04-26).\n setInterval(() => cleanupStaleSessions(), 60 * 1000);\n\n // ── Port pre-check: fail fast before loading subsystems ────\n const portAvailable = await new Promise<boolean>((resolve) => {\n const tester = net.createServer();\n tester.once('error', () => resolve(false));\n tester.once('listening', () => { tester.close(); resolve(true); });\n tester.listen(port, host);\n });\n if (!portAvailable) {\n logger.error(COMPONENT, `Port ${port} is already in use. Is TITAN already running?`);\n logger.info(COMPONENT, `Try: titan gateway --port ${port + 1}`);\n process.exit(1);\n }\n\n // ── GPU detection: adjust stall timeout for CPU-only inference ──\n const { detectGpu } = await import('../utils/hardware.js');\n if (!detectGpu()) {\n const { setStallThreshold } = await import('../agent/stallDetector.js');\n setStallThreshold(120_000);\n logger.info(COMPONENT, 'No GPU detected — stall timeout increased to 120s for CPU inference');\n maxConcurrentOverride = 2;\n logger.info(COMPONENT, 'CPU-only mode: maxConcurrentTasks auto-tuned to 2');\n }\n\n // Initialize subsystems\n initMemory();\n initLearning();\n initGraph();\n\n // Recover persisted deliberation states from previous session\n import('../agent/deliberation.js').then(({ recoverDeliberations }) => {\n recoverDeliberations();\n }).catch(() => {});\n\n // Initialize vector search (Tier 2 memory — non-blocking)\n import('../memory/vectors.js').then(({ initVectors }) => {\n initVectors().then(ok => {\n if (ok) logger.info(COMPONENT, 'Vector search (Tier 2 memory) initialized');\n }).catch(() => {});\n }).catch(() => {});\n\n await initBuiltinSkills();\n initAgents();\n\n // ── Rate limiter (inline, no deps) ─────────────────────────\n const defaultRateLimitWindowMs = options?.rateLimitWindowMs ?? 60000;\n const defaultRateLimitMax = options?.rateLimitMax ?? 30;\n const rateLimitStore = new Map<string, { count: number; resetAt: number }>();\n\n /**\n * Get a consistent client IP address for rate limiting.\n * Falls back through: X-Forwarded-For → req.ip → socket remoteAddress\n */\n function getClientIp(req: Request): string {\n return (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim()\n || req.ip\n || req.socket?.remoteAddress\n || 'unknown';\n }\n\n function rateLimit(windowMs: number, maxRequests: number) {\n return (req: Request, res: Response, next: NextFunction) => {\n const key = getClientIp(req);\n const now = Date.now();\n const entry = rateLimitStore.get(key);\n if (!entry || now > entry.resetAt) {\n rateLimitStore.set(key, { count: 1, resetAt: now + windowMs });\n next();\n } else if (entry.count < maxRequests) {\n entry.count++;\n next();\n } else {\n const retryAfter = Math.ceil((entry.resetAt - now) / 1000);\n logger.warn(COMPONENT, `[RateLimit] Client ${key} rate limited (${entry.count}/${maxRequests} in ${windowMs}ms)`);\n res.setHeader('Retry-After', String(retryAfter));\n res.status(429).json({ error: 'Too many requests', retryAfter });\n }\n };\n }\n\n // ── Concurrent request guard (prevents parallel abuse) ────\n // Hunt Finding #27 (2026-04-14): previously this attached BOTH a 'finish'\n // and a 'close' handler that each decremented the counter. Both events\n // fire for a normal request completion ('finish' first, then 'close'),\n // so every real request caused TWO decrements. Under parallel load the\n // counter drifted below the true active-request count, effectively\n // doubling the allowed concurrency. Math.max(0, -) kept it from going\n // negative numerically but the effective limit became 2×MAX.\n //\n // Fix: use ONLY 'close', which fires for every completed response\n // (normal, aborted, errored) exactly once. Remove 'finish' to eliminate\n // the double-decrement. Also make the limit configurable via config\n // so operators can tune it for their deployment instead of being stuck\n // at the hardcoded 5.\n let activeMessageRequests = 0;\n const MAX_CONCURRENT_MESSAGES = (() => {\n const cfg = loadConfig() as unknown as { gateway?: { maxConcurrentMessages?: number } };\n const v = cfg.gateway?.maxConcurrentMessages;\n if (typeof v === 'number' && v > 0 && v <= 1000) return v;\n return 5;\n })();\n\n function concurrencyGuard(maxConcurrent: number) {\n return (_req: Request, res: Response, next: NextFunction) => {\n if (activeMessageRequests >= maxConcurrent) {\n res.status(503).json({ error: 'Server busy — too many concurrent requests' });\n return;\n }\n activeMessageRequests++;\n // 'close' fires exactly once per completed request — safer than 'finish'\n // which only fires for successful sends AND is followed by 'close'\n // anyway (causing the double-decrement bug).\n let decremented = false;\n res.on('close', () => {\n if (decremented) return;\n decremented = true;\n activeMessageRequests = Math.max(0, activeMessageRequests - 1);\n });\n next();\n };\n }\n\n // Clean rate limit store every 60 seconds (unref so it doesn't block shutdown)\n rateLimitCleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of rateLimitStore) {\n if (now > entry.resetAt) rateLimitStore.delete(key);\n }\n // Cap rate limit store to prevent unbounded growth\n if (rateLimitStore.size > 10_000) {\n const entries = [...rateLimitStore.entries()].sort((a, b) => a[1].resetAt - b[1].resetAt);\n const toRemove = entries.slice(0, entries.length - 10_000);\n for (const [key] of toRemove) rateLimitStore.delete(key);\n }\n }, 60_000);\n rateLimitCleanupInterval.unref();\n\n // Create Express app\n const app = express();\n\n // ── Serve React SPA static assets FIRST ───────────────────\n // Static files (JS, CSS, images) should bypass JSON parsing,\n // request logging, and auth middleware for efficiency.\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const uiDistPath = join(__dirname, '../../ui/dist');\n const uiIndexPath = join(uiDistPath, 'index.html');\n const hasReactUI = fs.existsSync(uiIndexPath);\n let cachedIndexHtml: string | null = null;\n if (hasReactUI) {\n // Cache index.html in memory to avoid sync file reads on every request\n cachedIndexHtml = fs.readFileSync(uiIndexPath, 'utf8');\n app.use(express.static(uiDistPath, { index: false }));\n // Hot-reload the cache when the file changes (dev rebuilds)\n fs.watchFile(uiIndexPath, { interval: 1000 }, () => {\n try {\n cachedIndexHtml = fs.readFileSync(uiIndexPath, 'utf8');\n } catch { /* ignore read errors during write */ }\n });\n }\n\n app.use(express.json({ limit: '1mb' }));\n\n // Request logging middleware (skips static assets served above)\n app.use((req, res, next) => {\n const start = Date.now();\n res.on('finish', () => {\n const duration = Date.now() - start;\n logger.info(COMPONENT, `${req.method} ${req.path} → ${res.statusCode} (${duration}ms)`);\n });\n next();\n });\n\n // OpenAI API compatibility layer (/v1/models, /v1/chat/completions, /v1/embeddings)\n app.use('/v1', createOpenAICompatRouter());\n\n // ── Paperclip sidecar management & proxy ───────────────────\n app.use('/api/paperclip', createPaperclipRouter());\n app.use('/paperclip', createPaperclipUIRouter());\n\n // Ollama native API proxy (/ollama/* → configured Ollama server)\n // The UI's titan2/llm/ollama.ts hits /ollama/api/chat and /ollama/api/generate\n app.all('/ollama/*', async (req: Request, res: Response) => {\n const cfg = loadConfig();\n const ollamaBase = cfg.providers?.ollama?.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434';\n const targetPath = req.path.replace(/^\\/ollama/, '');\n const targetUrl = `${ollamaBase}${targetPath}`;\n\n try {\n const upstream = await fetch(targetUrl, {\n method: req.method,\n headers: {\n 'Content-Type': req.headers['content-type'] || 'application/json',\n Accept: req.headers['accept'] || '*/*',\n },\n body: req.method !== 'GET' && req.method !== 'HEAD' ? JSON.stringify(req.body) : undefined,\n });\n\n res.status(upstream.status);\n upstream.headers.forEach((value, key) => {\n // Don't forward content-encoding; Node will handle compression itself\n if (key.toLowerCase() !== 'content-encoding') {\n res.setHeader(key, value);\n }\n });\n\n if (upstream.body) {\n const reader = upstream.body.getReader();\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(Buffer.from(value));\n }\n }\n res.end();\n } catch (err) {\n logger.error(COMPONENT, `Ollama proxy error: ${(err as Error).message}`);\n res.status(502).json({ error: 'Ollama proxy error', message: (err as Error).message });\n }\n });\n\n // Handle JSON parse errors and payload too large\n app.use((err: Error & { type?: string; status?: number }, req: Request, res: Response, next: NextFunction) => {\n if (err.type === 'entity.too.large') {\n res.status(413).json({ error: 'Payload too large (max 1MB)' });\n return;\n }\n if (err.type === 'entity.parse.failed') {\n res.status(400).json({ error: 'Invalid JSON' });\n return;\n }\n next(err);\n });\n\n // Security headers + CSP\n app.use((req, res, next) => {\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'SAMEORIGIN');\n res.setHeader('X-XSS-Protection', '1; mode=block');\n res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\n res.setHeader('Content-Security-Policy', [\n \"default-src 'self'\",\n // Sandbox widget iframes use new Function() for code evaluation.\n \"script-src 'self' 'unsafe-inline' 'unsafe-eval'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"connect-src 'self' ws: wss: https: http:\",\n \"media-src 'self' blob: mediastream:\",\n \"img-src 'self' data: blob:\",\n \"font-src 'self' data:\",\n // Canvas AI-generated widgets run in a sandboxed iframe whose\n // source is a blob: URL built by ui/src/titan2/sandbox/SandboxRuntime.\n // Without `frame-src blob:` the browser shows:\n // \"This content is blocked. Contact the site owner to fix the issue.\"\n // worker-src + child-src are included as safety fallbacks for\n // older engines that don't honor frame-src directly.\n \"frame-src 'self' blob: data:\",\n \"child-src 'self' blob: data:\",\n \"worker-src 'self' blob:\",\n ].join('; '));\n res.removeHeader('X-Powered-By');\n next();\n });\n\n // CORS — allow localhost, Tailscale, Cloudflare tunnels, and LAN origins\n const gatewayPort = config.gateway.port || 48420;\n const localhostOrigins = new Set([\n `http://127.0.0.1:${gatewayPort}`,\n `http://localhost:${gatewayPort}`,\n `https://127.0.0.1:${gatewayPort}`,\n `https://localhost:${gatewayPort}`,\n ]);\n const dynamicOriginPatterns = [\n /^https?:\\/\\/[a-z0-9-]+\\.ts\\.net(:\\d+)?$/, // Tailscale (*.ts.net)\n /^https?:\\/\\/[a-z0-9-]+\\.trycloudflare\\.com(:\\d+)?$/, // Cloudflare tunnel\n /^http:\\/\\/192\\.168\\.\\d{1,3}\\.\\d{1,3}(:\\d+)?$/, // LAN 192.168.x.x\n /^http:\\/\\/10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d+)?$/, // LAN 10.x.x.x\n /^http:\\/\\/172\\.(1[6-9]|2\\d|3[0-1])\\.\\d{1,3}\\.\\d{1,3}(:\\d+)?$/, // LAN 172.16-31.x.x\n ];\n function isAllowedOrigin(origin: string): boolean {\n if (localhostOrigins.has(origin)) return true;\n return dynamicOriginPatterns.some(re => re.test(origin));\n }\n app.use((req, res, next) => {\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n }\n if (req.method === 'OPTIONS') { res.sendStatus(204); return; }\n next();\n });\n\n // ── Login routes (no auth required) ──────────────────────────\n app.get('/login', (_req, res) => {\n res.setHeader('Content-Type', 'text/html');\n res.send(getLoginHTML());\n });\n\n app.post('/api/login', rateLimit(60000, 5), (req, res) => {\n const cfg = loadConfig();\n const auth = cfg.gateway.auth;\n if (!auth || auth.mode === 'none') {\n res.json({ token: 'noauth' });\n return;\n }\n const { password } = req.body as { password?: string };\n let valid = false;\n if (auth.mode === 'password' && auth.password && password && safeCompare(password, auth.password)) valid = true;\n if (auth.mode === 'token' && auth.token && password && safeCompare(password, auth.token)) valid = true;\n if (!valid) { res.status(401).json({ error: 'Invalid password' }); return; }\n const token = randomBytes(32).toString('hex');\n authTokens.set(token, { createdAt: Date.now(), userId: `user-${token.slice(0, 8)}` });\n saveAuthTokens();\n res.json({ token });\n });\n\n // ── Prometheus /metrics (no auth — standard scrape path) ────\n app.get('/metrics', (_req, res) => {\n res.setHeader('Content-Type', 'text/plain; version=0.0.4');\n res.send(serializePrometheus());\n });\n\n // ── Auth middleware (API routes only) ────────────────────────\n // HTML pages (/ and /login) are always served — the JS handles\n // the redirect to /login if localStorage has no token.\n // Only /api/* routes require a valid token.\n app.use('/api', (req, res, next) => {\n const cfg = loadConfig();\n const auth = cfg.gateway.auth;\n if (!auth || auth.mode === 'none') { next(); return; }\n // Token mode with no token configured = auth not set up, allow access\n if (auth.mode === 'token' && !auth.token) { next(); return; }\n // Skip public endpoints (login, messenger webhook, twilio webhooks)\n if (req.path === '/login') { next(); return; }\n if (req.path === '/messenger/webhook') { next(); return; }\n if (req.path.startsWith('/twilio/')) { next(); return; }\n const header = req.headers.authorization;\n const token = header?.startsWith('Bearer ') ? header.slice(7) : (req.query.token as string);\n if (isValidToken(token, cfg)) { next(); return; }\n res.status(401).json({ error: 'Unauthorized' });\n });\n\n // ── Command Post availability guard ──────────────────────────\n app.use('/api/command-post', (_req, res, next) => {\n if (isCommandPostEnabled()) { next(); return; }\n res.status(503).json({ error: 'Command Post is disabled', hint: 'Enable it in titan.json: commandPost.enabled = true' });\n });\n\n // Legacy dashboard (kept during migration, also fallback if React UI not built)\n app.get('/legacy', (_req, res) => {\n res.setHeader('Content-Type', 'text/html');\n res.send(getMissionControlHTML());\n });\n\n // Root route: React SPA or legacy dashboard\n app.get('/', (_req, res) => {\n if (hasReactUI && cachedIndexHtml) {\n res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');\n res.setHeader('Pragma', 'no-cache');\n res.setHeader('Expires', '0');\n res.send(cachedIndexHtml);\n } else {\n res.setHeader('Content-Type', 'text/html');\n res.send(getMissionControlHTML());\n }\n });\n\n // API routes\n app.get('/api/stats', (_req, res) => {\n const usage = getUsageStats();\n const cfg = loadConfig();\n const activeModel = cfg.agent.model || '';\n const mem = process.memoryUsage();\n const activeAgents = listAgents().filter(a => a.status === 'running').length;\n const activeSessions = listSessions().length;\n res.json({\n ...usage,\n version: TITAN_VERSION,\n uptime: process.uptime(),\n model: activeModel.replace(/^ollama\\//, ''),\n provider: activeModel.split('/')[0] || 'ollama',\n memoryMB: Math.round(mem.rss / 1024 / 1024),\n memoryUsage: {\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n rss: mem.rss,\n external: mem.external,\n arrayBuffers: mem.arrayBuffers,\n },\n health: {\n ollamaHealthy: healthState.ollamaHealthy,\n ttsHealthy: healthState.ttsHealthy,\n lastCheck: healthState.lastCheck,\n stuckDetected: healthState.stuckDetected,\n uptimeSeconds: Math.round(process.uptime()),\n memoryUsageMB: Math.round(mem.heapUsed / 1024 / 1024),\n activeLlmRequests,\n restarts: (() => { try { return getRestartStatsSync(); } catch { return null; } })(),\n },\n activeAgents,\n activeSessions,\n });\n });\n\n // ── Tracing API ─────────────────────────────────────────────────\n app.use('/api/traces', createTracesRouter());\n\n // ── Checkpoints API ────────────────────────────────────────────\n app.use('/api/checkpoints', createCheckpointsRouter());\n\n // ── Company API (Paperclip-style) ─────────────────────────────\n app.use('/api/companies', createCompaniesRouter());\n\n // ── Command Post API (Agent Governance) ───────────────────\n app.use('/api/command-post', createCommandPostRouter());\n\n // ── Sessions API ──────────────────────────────────────────\n app.use('/api/sessions', createSessionsRouter(sessionAborts));\n\n // ── Skills API ──────────────────────────────────────────────\n app.use('/api', createTeamsRecipesRouter());\n app.use('/api', createSkillsRouter(channels));\n app.use('/api', createAdminRouter());\n\n // ── Soul API ──────────────────────────────────────────────────\n\n // ── Soul API ──────────────────────────────────────────────────\n app.get('/api/soul/wisdom', async (_req, res) => {\n try {\n const { getWisdomData } = await import('../agent/soul.js');\n res.json(getWisdomData());\n } catch { res.json({ patterns: [], mistakes: [], userPreferences: [], totalTasks: 0 }); }\n });\n\n app.get('/api/soul/state/:sessionId', async (req, res) => {\n try {\n const { getSoulState } = await import('../agent/soul.js');\n const state = getSoulState(req.params.sessionId);\n if (!state) { res.status(404).json({ error: 'No active soul state for session' }); return; }\n res.json(state);\n } catch { res.status(500).json({ error: 'Soul unavailable' }); }\n });\n\n // ── Guardrails API ─────────────────────────────────────────────\n app.get('/api/guardrails/violations', async (_req, res) => {\n try {\n const { getViolations } = await import('../agent/guardrails.js');\n const limit = parseInt(_req.query.limit as string || '50', 10);\n res.json({ violations: getViolations(limit) });\n } catch { res.json({ violations: [] }); }\n });\n\n // ── Alerts API ────────────────────────────────────────────────\n app.get('/api/alerts', async (_req, res) => {\n try {\n const { getAlertHistory } = await import('../agent/alerts.js');\n const limit = parseInt(_req.query.limit as string || '50', 10);\n res.json({ alerts: getAlertHistory(limit) });\n } catch { res.json({ alerts: [] }); }\n });\n\n // ── Dream Mode API (v5.5.17) ──────────────────────────────────\n // Three reads + one on-demand generator. The cron handles scheduled\n // generation; the POST endpoint exists so an operator can force-run the\n // pipeline mid-day without waiting for 03:30 (e.g. to demo the feature\n // or backfill after a long offline stretch).\n app.get('/api/dreams/latest', async (_req, res) => {\n try {\n const { getLatestDream } = await import('../agent/dreams.js');\n const dream = getLatestDream();\n if (!dream) { res.status(404).json({ error: 'no dreams yet' }); return; }\n res.json(dream);\n } catch (e) {\n logger.error(COMPONENT, `dreams/latest: ${(e as Error).message}`);\n res.status(500).json({ error: 'dreams unavailable' });\n }\n });\n\n app.get('/api/dreams', async (_req, res) => {\n try {\n const { listDreamDates } = await import('../agent/dreams.js');\n const limit = Math.min(Math.max(parseInt(String(_req.query.limit ?? '30'), 10) || 30, 1), 365);\n res.json({ dates: listDreamDates(limit) });\n } catch (e) {\n logger.error(COMPONENT, `dreams list: ${(e as Error).message}`);\n res.status(500).json({ error: 'dreams unavailable' });\n }\n });\n\n app.get('/api/dreams/:date', async (req, res) => {\n try {\n const { getDreamByDate } = await import('../agent/dreams.js');\n // Date param is YYYY-MM-DD; reject anything else to keep the\n // filesystem read inside DREAMS_DIR.\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(req.params.date)) {\n res.status(400).json({ error: 'date must be YYYY-MM-DD' });\n return;\n }\n const dream = getDreamByDate(req.params.date);\n if (!dream) { res.status(404).json({ error: 'no dream for that date' }); return; }\n res.json(dream);\n } catch (e) {\n logger.error(COMPONENT, `dreams/:date: ${(e as Error).message}`);\n res.status(500).json({ error: 'dreams unavailable' });\n }\n });\n\n app.post('/api/dreams/generate', async (_req, res) => {\n try {\n const { generateDream } = await import('../agent/dreams.js');\n const dream = await generateDream();\n res.json(dream);\n } catch (e) {\n logger.error(COMPONENT, `dreams/generate: ${(e as Error).message}`);\n res.status(500).json({ error: 'dream generation failed', message: (e as Error).message });\n }\n });\n\n // ── Persona Profiles API (v5.5.24) ────────────────────────────\n // Note path is `/api/persona-profiles` not `/api/personas` —\n // /api/personas already returns the agency-agent persona list (a\n // separate concept from runtime persona profiles). Renamed to avoid\n // route collision discovered on first deploy of v5.5.24.\n app.get('/api/persona-profiles', async (_req, res) => {\n try {\n const cfg = loadConfig();\n const personas = cfg.personas;\n res.json({\n enabled: personas?.enabled ?? false,\n defaultPersona: personas?.defaultPersona ?? null,\n channelPins: personas?.channelPins ?? {},\n profiles: personas?.profiles ?? [],\n });\n } catch (e) {\n logger.error(COMPONENT, `persona-profiles list: ${(e as Error).message}`);\n res.status(500).json({ error: 'personas unavailable' });\n }\n });\n\n app.get('/api/persona-profiles/active', async (req, res) => {\n try {\n const { describeActivePersona } = await import('../agent/personaProfiles.js');\n const channel = typeof req.query.channel === 'string' ? req.query.channel : undefined;\n res.json(describeActivePersona({ channel }));\n } catch (e) {\n logger.error(COMPONENT, `persona-profiles active: ${(e as Error).message}`);\n res.status(500).json({ error: 'personas unavailable' });\n }\n });\n\n // ── Persona Cohorts API (v5.5.27, A/B rollout) ────────────────\n // Cohorts are runtime state — this is the operator's control surface\n // for canarying a candidate persona against a baseline. Health endpoint\n // returns per-arm stats over the rolling window so MC can render\n // sparkline cards. Auto-revert fires from the monitor cron, but manual\n // POST /:id/revert is also exposed for kill-switch use.\n app.get('/api/persona-cohorts', async (_req, res) => {\n try {\n const { listCohorts } = await import('../agent/personaRollout.js');\n res.json({ cohorts: listCohorts() });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts list: ${(e as Error).message}`);\n res.status(500).json({ error: 'persona-cohorts unavailable' });\n }\n });\n\n app.post('/api/persona-cohorts', async (req, res) => {\n try {\n const { createCohort } = await import('../agent/personaRollout.js');\n const body = (req.body || {}) as { baselineId?: string; candidateId?: string; percent?: number; hashKey?: 'sessionId' | 'channel'; note?: string; id?: string };\n if (!body.baselineId || !body.candidateId || typeof body.percent !== 'number') {\n res.status(400).json({ error: 'baselineId, candidateId, and percent are required' });\n return;\n }\n const cohort = createCohort({\n baselineId: body.baselineId,\n candidateId: body.candidateId,\n percent: body.percent,\n hashKey: body.hashKey,\n note: body.note,\n id: body.id,\n });\n res.json(cohort);\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts create: ${(e as Error).message}`);\n res.status(400).json({ error: (e as Error).message });\n }\n });\n\n app.delete('/api/persona-cohorts/:id', async (req, res) => {\n try {\n const { deleteCohort } = await import('../agent/personaRollout.js');\n const ok = deleteCohort(req.params.id);\n if (!ok) { res.status(404).json({ error: 'cohort not found' }); return; }\n res.json({ deleted: true });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts delete: ${(e as Error).message}`);\n res.status(500).json({ error: 'delete failed' });\n }\n });\n\n app.post('/api/persona-cohorts/:id/revert', async (req, res) => {\n try {\n const { revertCohort } = await import('../agent/personaRollout.js');\n const reason = (req.body && typeof req.body.reason === 'string') ? req.body.reason : 'manual revert via API';\n const cohort = revertCohort(req.params.id, reason, 'manual');\n if (!cohort) { res.status(404).json({ error: 'cohort not found' }); return; }\n res.json(cohort);\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts revert: ${(e as Error).message}`);\n res.status(500).json({ error: 'revert failed' });\n }\n });\n\n app.get('/api/persona-cohorts/:id/health', async (req, res) => {\n try {\n const { getCohort, evaluateCohort } = await import('../agent/personaRollout.js');\n const cohort = getCohort(req.params.id);\n if (!cohort) { res.status(404).json({ error: 'cohort not found' }); return; }\n const cfg = loadConfig();\n const rollout = (cfg.personas as { rollout?: { windowMins?: number; minSampleSize?: number; passRateMargin?: number; safetyDropThreshold?: number } } | undefined)?.rollout;\n const health = evaluateCohort(cohort, {\n windowMins: rollout?.windowMins,\n minSampleSize: rollout?.minSampleSize,\n passRateMargin: rollout?.passRateMargin,\n safetyDropThreshold: rollout?.safetyDropThreshold,\n });\n res.json({ cohort, health });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts health: ${(e as Error).message}`);\n res.status(500).json({ error: 'health unavailable' });\n }\n });\n\n app.get('/api/persona-cohorts/health', async (_req, res) => {\n try {\n const { listCohorts, evaluateCohort } = await import('../agent/personaRollout.js');\n const cohorts = listCohorts();\n const cfg = loadConfig();\n const rollout = (cfg.personas as { rollout?: { windowMins?: number; minSampleSize?: number; passRateMargin?: number; safetyDropThreshold?: number } } | undefined)?.rollout;\n const out = cohorts.map(cohort => ({\n cohort,\n health: evaluateCohort(cohort, {\n windowMins: rollout?.windowMins,\n minSampleSize: rollout?.minSampleSize,\n passRateMargin: rollout?.passRateMargin,\n safetyDropThreshold: rollout?.safetyDropThreshold,\n }),\n }));\n res.json({ cohorts: out });\n } catch (e) {\n logger.error(COMPONENT, `persona-cohorts health-all: ${(e as Error).message}`);\n res.status(500).json({ error: 'health unavailable' });\n }\n });\n\n app.get('/api/health/deep', async (_req, res) => {\n const checks: Record<string, { status: 'ok' | 'degraded' | 'down'; detail?: string }> = {};\n let overall: 'ok' | 'degraded' | 'down' = 'ok';\n\n // Memory subsystem\n try {\n const { getDb } = await import('../memory/memory.js');\n const db = getDb();\n checks.memory = { status: 'ok', detail: `${db.memories.length} memories, ${db.sessions.length} sessions` };\n } catch (e) {\n checks.memory = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Graph\n try {\n const { getGraphStats } = await import('../memory/graph.js');\n const stats = getGraphStats();\n checks.graph = { status: 'ok', detail: `${stats.episodeCount} episodes, ${stats.entityCount} entities` };\n } catch (e) {\n checks.graph = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Vectors\n try {\n const { isVectorSearchAvailable } = await import('../memory/vectors.js');\n checks.vectors = { status: isVectorSearchAvailable() ? 'ok' : 'degraded', detail: isVectorSearchAvailable() ? 'ready' : 'disabled or unavailable' };\n if (!isVectorSearchAvailable() && overall === 'ok') overall = 'degraded';\n } catch (e) {\n checks.vectors = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Providers\n try {\n const providerHealth = await healthCheckAll();\n const entries = Object.entries(providerHealth);\n const healthyProviders = entries.filter(([, healthy]) => healthy).length;\n checks.providers = { status: healthyProviders > 0 ? 'ok' : 'down', detail: `${healthyProviders}/${entries.length} healthy` };\n if (healthyProviders === 0) overall = 'down';\n } catch (e) {\n checks.providers = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Channels\n try {\n const connected = Array.from(channels.values()).filter((c) => c.getStatus().connected).length;\n checks.channels = { status: connected > 0 ? 'ok' : 'degraded', detail: `${connected}/${channels.size} connected` };\n if (connected === 0 && overall === 'ok') overall = 'degraded';\n } catch (e) {\n checks.channels = { status: 'down', detail: (e as Error).message };\n overall = 'down';\n }\n\n // Event loop lag (approximate via setImmediate)\n const start = process.hrtime.bigint();\n await new Promise((resolve) => setImmediate(resolve));\n const lagNs = Number(process.hrtime.bigint() - start);\n const lagMs = lagNs / 1_000_000;\n checks.eventLoop = { status: lagMs < 100 ? 'ok' : lagMs < 500 ? 'degraded' : 'down', detail: `${lagMs.toFixed(2)}ms lag` };\n if (lagMs >= 500) overall = 'down';\n else if (lagMs >= 100 && overall === 'ok') overall = 'degraded';\n\n res.status(overall === 'ok' ? 200 : overall === 'degraded' ? 200 : 503).json({\n status: overall,\n version: TITAN_VERSION,\n uptime: process.uptime(),\n checks,\n });\n });\n\n // ── Monitors API ─────────────────────────────────────────────────\n app.get('/api/monitors', (_req, res) => {\n try {\n res.json({ monitors: listMonitors(), events: getMonitorEvents().slice(-50) });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.post('/api/monitors', (req, res) => {\n try {\n const { name, prompt, triggerType, intervalMinutes } = req.body;\n if (!name || !prompt) { res.status(400).json({ error: 'name and prompt are required' }); return; }\n const monitor = addMonitor({ name, prompt, triggerType: triggerType || 'interval', intervalMinutes: intervalMinutes || 60 } as any);\n res.status(201).json(monitor);\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.delete('/api/monitors/:id', (req, res) => {\n try {\n removeMonitor(req.params.id);\n res.json({ ok: true });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n\n app.use('/api', createTestsRouter());\n app.use('/api', createHardwareRouter(broadcast));\n app.use('/api', createMetricsRouter());\n app.use('/api', createMcpRouter());\n app.use('/api', createAgentsRouter());\n\n // Agent message endpoint (uses multi-agent routing)\n // Supports SSE streaming when Accept: text/event-stream header is present\n app.post('/api/message', rateLimit(defaultRateLimitWindowMs, defaultRateLimitMax), concurrencyGuard(MAX_CONCURRENT_MESSAGES), async (req, res) => {\n // v5.5.28 FIX: accept either {content} (canonical) or {message} (legacy\n // shape used by community SDKs / older clients). Previously rejected\n // {message} with 400. The body destructuring uses `content` internally\n // either way.\n const body = (req.body || {}) as Record<string, unknown>;\n const content = (typeof body.content === 'string' && body.content) || (typeof body.message === 'string' && body.message) || '';\n const { channel: rawChannel, userId = 'api-user', agentId, sessionId: requestedSessionId, model: requestedModel, systemPromptAppendix } = body as { channel?: string; userId?: string; agentId?: string; sessionId?: string; model?: string; systemPromptAppendix?: string };\n // Default channel to 'webchat' for browser-based Mission Control clients.\n // This enables the interactive plan approval flow (show plan → user approves/denies).\n // Programmatic API callers can explicitly pass channel: 'api' to auto-approve plans.\n const channel = rawChannel || (req.headers.accept === 'text/event-stream' ? 'webchat' : 'api');\n if (!content || typeof content !== 'string') {\n res.status(400).json({ error: 'content (or message) must be a non-empty string' });\n return;\n }\n\n // v5.5.30 FIX: validate `model` early so a bad provider ID returns 400\n // before the agent loop runs. Previously a typoed provider crashed\n // deep inside processMessage with 500 + stack trace AFTER the prompt\n // had been built — wasted work and a confusing error for the caller.\n if (requestedModel && typeof requestedModel === 'string') {\n const { tryResolveModel, getKnownProviderNames } = await import('../providers/router.js');\n if (!tryResolveModel(requestedModel)) {\n const providers = getKnownProviderNames();\n const requestedProviderName = requestedModel.split('/')[0] || requestedModel;\n // Naive \"did you mean\" — find providers whose name shares a prefix\n const lc = requestedProviderName.toLowerCase();\n const suggestions = providers.filter(p => p.startsWith(lc.slice(0, 3)) || lc.includes(p)).slice(0, 5);\n res.status(400).json({\n error: 'unknown_model',\n message: `Unknown model \"${requestedModel}\". Provider \"${requestedProviderName}\" is not registered.`,\n suggestions: suggestions.length > 0 ? suggestions.map(p => `${p}/...`) : undefined,\n availableProviders: providers,\n });\n return;\n }\n }\n\n const safeUserId = channel === 'api' ? 'api-user' : (userId || 'api-user');\n\n // ═─ System Widget Shortcut ─═════════════════════════════════════\n // Fast-path: if the user is **explicitly asking for a known widget**,\n // bypass the LLM and emit the _____widget gate directly. This is fast\n // and reliable for unambiguous requests like \"open the cron widget\" or\n // \"show me the VRAM dashboard.\"\n //\n // v5.5.28 FIX: previously matched on a single keyword (e.g. `\\bmodels?\\b`)\n // which hijacked normal chat — \"tell me about the models you support\"\n // returned a Training Dashboard widget instead of an LLM response. Now\n // gated on **explicit widget intent**: the user must use a widget-noun\n // (\"widget\", \"panel\", \"dashboard\", etc.) for the shortcut to fire.\n const hasExplicitWidgetIntent = /\\b(?:widget|panel|dashboard|monitor|hub|tab|page|view|gallery|kitchen|scheduler|router|lab|tools)\\b/i.test(content);\n const systemWidgetShortcuts: Array<{ pattern: RegExp; source: string; name: string; w: number; h: number }> = [\n { pattern: /\\b(?:backups?|snapshots?|archives?)\\b/i, source: 'system:backup', name: 'Backup Manager', w: 6, h: 6 },\n { pattern: /\\b(?:training|train|specialists?|models?)\\b/i, source: 'system:training', name: 'Training Dashboard', w: 6, h: 6 },\n { pattern: /\\b(?:recipes?|playbooks?|workflows?|jarvis)\\b/i, source: 'system:recipes', name: 'Recipe Kitchen', w: 6, h: 6 },\n { pattern: /\\b(?:vram|gpu|memory|nvidia)\\b/i, source: 'system:vram', name: 'VRAM Monitor', w: 6, h: 6 },\n { pattern: /\\b(?:teams?|members?|roles?|permissions?|rbac)\\b/i, source: 'system:teams', name: 'Team Hub', w: 6, h: 6 },\n { pattern: /\\b(?:cron|schedules?|jobs?|timers?)\\b/i, source: 'system:cron', name: 'Cron Scheduler', w: 6, h: 6 },\n { pattern: /\\b(?:checkpoints?|restores?|save state)\\b/i, source: 'system:checkpoints', name: 'Checkpoints', w: 6, h: 5 },\n { pattern: /\\b(?:organism|drives?|safety|alerts?|guardrails?)\\b/i, source: 'system:organism', name: 'Organism Monitor', w: 6, h: 6 },\n { pattern: /\\b(?:fleet|nodes?|routes?|mesh)\\b/i, source: 'system:fleet', name: 'Fleet Router', w: 6, h: 5 },\n { pattern: /\\b(?:captcha|browsers?|form fill|web automation)\\b/i, source: 'system:browser', name: 'Browser Tools', w: 6, h: 5 },\n { pattern: /\\b(?:paperclip|sidecars?|helpers?)\\b/i, source: 'system:paperclip', name: 'Paperclip', w: 6, h: 5 },\n { pattern: /\\b(?:tests?|flaky|failing|coverage|eval)\\b/i, source: 'system:eval', name: 'Test Lab', w: 6, h: 6 },\n ];\n const matchedShortcut = hasExplicitWidgetIntent\n ? systemWidgetShortcuts.find(s => s.pattern.test(content))\n : null;\n if (matchedShortcut) {\n const gateText = `_____widget\\n{ \"name\": \"${matchedShortcut.name}\", \"format\": \"system\", \"source\": \"${matchedShortcut.source}\", \"w\": ${matchedShortcut.w}, \"h\": ${matchedShortcut.h} }`;\n const responseText = `Added the **${matchedShortcut.name}** widget to your canvas.`;\n titanRequestsTotal.increment({ channel, status: 'ok' });\n if (req.headers.accept === 'text/event-stream') {\n res.setHeader('Content-Type', 'text/event-stream');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n sseWrite(`event: token\\ndata: ${JSON.stringify({ text: responseText })}\\n\\n`);\n sseWrite(`event: token\\ndata: ${JSON.stringify({ text: '\\n\\n' + gateText })}\\n\\n`);\n sseWrite(`event: done\\ndata: ${JSON.stringify({ content: responseText + '\\n\\n' + gateText, sessionId: requestedSessionId || null, durationMs: 0, toolsUsed: [] })}\\n\\n`);\n res.end();\n } else {\n res.json({ content: responseText + '\\n\\n' + gateText, sessionId: requestedSessionId || null, toolsUsed: [], model: 'system', durationMs: 0 });\n }\n return;\n }\n\n const startTime = process.hrtime.bigint();\n const wantsSSE = req.headers.accept === 'text/event-stream';\n\n // Validate session ID format (prevent injection)\n if (requestedSessionId && !/^[a-zA-Z0-9_:-]{1,128}$/.test(requestedSessionId)) {\n res.status(400).json({ error: 'Invalid session ID format' });\n return;\n }\n\n // Set up abort controller for this request\n const abortController = new AbortController();\n if (requestedSessionId) {\n sessionAborts.set(requestedSessionId, abortController);\n sessionAbortTimes.set(requestedSessionId, Date.now());\n // S3: Track session ownership\n if (!sessionOwners.has(requestedSessionId)) {\n sessionOwners.set(requestedSessionId, getUserIdFromReq(req));\n }\n }\n\n // Check slash commands first (same as handleInboundMessage)\n try {\n const slashResult = await handleSlashCommand(content, channel, userId);\n if (slashResult) {\n titanRequestsTotal.increment({ channel, status: 'ok' });\n const durationSec = Number(process.hrtime.bigint() - startTime) / 1e9;\n titanRequestDuration.observe(durationSec, { channel });\n if (wantsSSE) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n sseWrite(`event: done\\ndata: ${JSON.stringify({ content: slashResult.response, sessionId: null, durationMs: 0 })}\\n\\n`);\n res.end();\n } else {\n res.json({ content: slashResult.response, sessionId: null, toolsUsed: [], model: 'system' });\n }\n return;\n }\n } catch { /* fall through to routeMessage */ }\n\n // ── Auto-detect credentials in user messages ──────────────────────\n // If the user pastes a Home Assistant URL + JWT token, save them automatically\n // before the LLM even sees the message (prevents hallucination / tool-skip).\n try {\n const haKeywords = /home\\s*assistant|homeassistant|\\bha\\b\\s*(token|url|key|setup|connect)/i;\n const jwtPattern = /eyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/;\n const urlPattern = /https?:\\/\\/[^\\s,'\"]+/i;\n if (haKeywords.test(content) && (jwtPattern.test(content) || urlPattern.test(content))) {\n const jwtMatch = content.match(jwtPattern);\n const urlMatch = content.match(urlPattern);\n const cfg = loadConfig();\n let saved = false;\n if (jwtMatch && (!cfg.homeAssistant?.token || cfg.homeAssistant.token !== jwtMatch[0])) {\n // Security: store in config but log a warning about plaintext storage\n cfg.homeAssistant.token = jwtMatch[0];\n saved = true;\n logger.warn(COMPONENT, '[Security] Home Assistant token auto-saved to config. Consider using the vault for credential storage.');\n }\n if (urlMatch && urlMatch[0].match(/:\\d{4}/) && (!cfg.homeAssistant?.url || cfg.homeAssistant.url !== urlMatch[0].replace(/\\/+$/, ''))) {\n cfg.homeAssistant.url = urlMatch[0].replace(/\\/+$/, '');\n saved = true;\n }\n if (saved) {\n updateConfig({ homeAssistant: cfg.homeAssistant });\n logger.info('Gateway', 'Auto-saved Home Assistant credentials from user message');\n }\n }\n } catch { /* non-critical — let the LLM handle it */ }\n\n // Concurrent LLM request limit (auto-tuned to 2 on CPU-only systems)\n const maxConcurrent = maxConcurrentOverride ?? (loadConfig().security.maxConcurrentTasks || 5);\n if (activeLlmRequests >= maxConcurrent) {\n titanRequestsTotal.increment({ channel, status: 'busy' });\n titanErrorsTotal.increment({ type: 'busy' });\n if (wantsSSE) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n sseWrite(`event: done\\ndata: ${JSON.stringify({ error: 'Server busy' })}\\n\\n`);\n res.end();\n } else {\n res.status(503).json({ error: 'Server busy — too many concurrent requests. Try again shortly.' });\n }\n return;\n }\n activeLlmRequests++;\n titanActiveSessions.inc();\n // Track client disconnect to avoid writing to dead connections\n let clientDisconnected = false;\n let sseWrite: ((data: string) => void) | null = null;\n try {\n if (wantsSSE) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n req.on('close', () => {\n clientDisconnected = true;\n // Abort the in-progress LLM call so we don't keep streaming to a gone client.\n abortController.abort('client disconnected');\n });\n\n sseWrite = setupSSEFlush(res);\n const safeWrite = (data: string) => {\n if (clientDisconnected) return;\n try { sseWrite!(data); } catch { clientDisconnected = true; }\n };\n\n const response = await routeMessage(content, channel, safeUserId, {\n streamCallbacks: {\n onToken: (token: string) => {\n safeWrite(`event: token\\ndata: ${JSON.stringify({ text: token })}\\n\\n`);\n },\n onToolCall: (name: string, args: Record<string, unknown>) => {\n safeWrite(`event: tool_call\\ndata: ${JSON.stringify({ name, args, timestamp: Date.now() })}\\n\\n`);\n },\n onToolResult: (name: string, result: string, durationMs: number, success: boolean, diff?: string) => {\n safeWrite(`event: tool_end\\ndata: ${JSON.stringify({ name, result: result.slice(0, 500), durationMs, success, diff, timestamp: Date.now() })}\\n\\n`);\n },\n onThinking: () => {\n safeWrite(`event: thinking\\ndata: ${JSON.stringify({ timestamp: Date.now() })}\\n\\n`);\n },\n onRound: (round: number, maxRounds: number) => {\n safeWrite(`event: round\\ndata: ${JSON.stringify({ round, maxRounds, timestamp: Date.now() })}\\n\\n`);\n },\n // Dedicated `retry` SSE event so the UI can show a status indicator.\n // Pre-fix the router yielded retry banners as `text` chunks which\n // ended up in the user-visible message; this isolates the signal.\n onRetry: (info) => {\n safeWrite(`event: retry\\ndata: ${JSON.stringify({ ...info, timestamp: Date.now() })}\\n\\n`);\n },\n onFailover: (info) => {\n safeWrite(`event: failover\\ndata: ${JSON.stringify({ ...info, timestamp: Date.now() })}\\n\\n`);\n },\n },\n overrideAgentId: agentId,\n signal: abortController.signal,\n sessionId: requestedSessionId,\n modelOverride: requestedModel,\n systemPromptAppendix: typeof systemPromptAppendix === 'string' ? systemPromptAppendix : undefined,\n });\n titanRequestsTotal.increment({ channel, status: 'ok' });\n if (response.toolsUsed) {\n for (const tool of response.toolsUsed) titanToolCallsTotal.increment({ tool });\n }\n if (response.tokenUsage) {\n if (response.tokenUsage.prompt) titanTokensTotal.increment({ type: 'prompt' }, response.tokenUsage.prompt);\n if (response.tokenUsage.completion) titanTokensTotal.increment({ type: 'completion' }, response.tokenUsage.completion);\n }\n if (response.model) titanModelRequestsTotal.increment({ model: response.model, provider: 'default' });\n trackUsage(response.model || 'unknown', response.tokenUsage, response.durationMs || 0, response.sessionId || '');\n // Hunt Finding #11: sanitize SSE response content as well\n try {\n const { sanitizeOutbound } = await import('../utils/outboundSanitizer.js');\n const sanitized = sanitizeOutbound(\n response.content || '',\n 'api_message_sse',\n \"I'm TITAN — I can run commands, edit files, search the web, remember things, and more. What would you like me to help with?\",\n );\n if (sanitized.hadIssues) {\n logger.warn(COMPONENT, `[OutboundGuard] SSE /api/message response sanitized: ${sanitized.issues.join(', ')}`);\n response.content = sanitized.text;\n }\n } catch { /* sanitizer unavailable */ }\n if (!clientDisconnected) {\n safeWrite(`event: done\\ndata: ${JSON.stringify({ content: response.content, sessionId: response.sessionId, durationMs: response.durationMs, model: response.model, toolsUsed: response.toolsUsed, pendingApproval: response.pendingApproval })}\\n\\n`);\n try { res.end(); } catch { /* client gone */ }\n }\n } else {\n const response = await routeMessage(content, channel, safeUserId, {\n overrideAgentId: agentId,\n signal: abortController.signal,\n sessionId: requestedSessionId,\n modelOverride: requestedModel,\n systemPromptAppendix: typeof systemPromptAppendix === 'string' ? systemPromptAppendix : undefined,\n });\n titanRequestsTotal.increment({ channel, status: 'ok' });\n if (response.toolsUsed) {\n for (const tool of response.toolsUsed) titanToolCallsTotal.increment({ tool });\n }\n if (response.tokenUsage) {\n if (response.tokenUsage.prompt) titanTokensTotal.increment({ type: 'prompt' }, response.tokenUsage.prompt);\n if (response.tokenUsage.completion) titanTokensTotal.increment({ type: 'completion' }, response.tokenUsage.completion);\n }\n if (response.model) titanModelRequestsTotal.increment({ model: response.model, provider: 'default' });\n trackUsage(response.model || 'unknown', response.tokenUsage, response.durationMs || 0, response.sessionId || '');\n // Hunt Finding #11 (2026-04-14): sanitize outbound content before returning\n // to user. Catches system prompt leaks, instruction echoes, tool artifacts.\n // Defense-in-depth: the system prompt tells the model not to leak, but if the\n // model ignores that, this catches it.\n try {\n const { sanitizeOutbound } = await import('../utils/outboundSanitizer.js');\n const sanitized = sanitizeOutbound(\n response.content || '',\n 'api_message',\n \"I'm TITAN — I can run commands, edit files, search the web, remember things, and more. What would you like me to help with?\",\n );\n if (sanitized.hadIssues) {\n logger.warn(COMPONENT, `[OutboundGuard] /api/message response sanitized: ${sanitized.issues.join(', ')}`);\n response.content = sanitized.text;\n }\n } catch { /* sanitizer unavailable — non-critical */ }\n res.json(response);\n }\n } catch (error) {\n titanRequestsTotal.increment({ channel, status: 'error' });\n titanErrorsTotal.increment({ type: 'request' });\n // Capture a structured bug report for the operator + agent team to\n // review. Best-effort — never gates the user-facing error path.\n try {\n const { captureBugReport } = await import('../analytics/bugReports.js');\n await captureBugReport(error, {\n origin: 'gateway./api/message',\n channel,\n sessionId: requestedSessionId,\n model: typeof requestedModel === 'string' ? requestedModel : undefined,\n lastUserMessage: typeof content === 'string' ? content : undefined,\n turnNumber: undefined,\n });\n } catch { /* never let bug capture break the request path */ }\n // Classify the error so the UI can render an actionable banner instead of a stack trace\n const structured = classifyChatError(error as Error);\n if (wantsSSE && !clientDisconnected && sseWrite) {\n try { sseWrite(`event: done\\ndata: ${JSON.stringify(structured)}\\n\\n`); res.end(); } catch { /* client gone */ }\n } else if (!wantsSSE) {\n res.status(structured.status).json(structured);\n }\n } finally {\n activeLlmRequests--;\n titanActiveSessions.dec();\n const durationSec = Number(process.hrtime.bigint() - startTime) / 1e9;\n titanRequestDuration.observe(durationSec, { channel });\n if (requestedSessionId) sessionAborts.delete(requestedSessionId);\n }\n });\n\n // SSE streaming endpoint — real token-by-token delivery\n app.post('/api/chat/stream', rateLimit(60000, 30), concurrencyGuard(10), async (req, res) => {\n const { content, model } = req.body;\n if (!content) { res.status(400).json({ error: 'content is required' }); return; }\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n const sseWrite = setupSSEFlush(res);\n\n try {\n const config = loadConfig();\n const modelId = model || config.agent.model || 'anthropic/claude-sonnet-4-20250514';\n const systemMessages = [{ role: 'system' as const, content: `You are TITAN, an intelligent assistant.` }];\n const userMessages = [{ role: 'user' as const, content }];\n\n for await (const chunk of chatStream({ model: modelId, messages: [...systemMessages, ...userMessages], maxTokens: config.agent.maxTokens, temperature: config.agent.temperature })) {\n sseWrite(`data: ${JSON.stringify(chunk)}\\n\\n`);\n if (chunk.type === 'done' || chunk.type === 'error') break;\n }\n } catch (error) {\n logger.error(COMPONENT, `Stream error: ${(error as Error).message}`);\n sseWrite(`data: ${JSON.stringify({ type: 'error', error: 'The assistant hit a snag. Please refresh and try again.' })}\\n\\n`);\n }\n res.end();\n });\n\n // Cost optimizer endpoint for Mission Control\n app.get('/api/costs', (_req, res) => {\n res.json(getCostStatus());\n });\n\n // Usage tracking — per-model cost breakdown\n app.get('/api/usage', (req, res) => {\n const hours = parseInt(req.query.hours as string) || 24;\n const cutoff = new Date(Date.now() - hours * 3600_000).toISOString();\n const recent = usageLog.filter(e => e.timestamp >= cutoff);\n\n // Aggregate by model\n const byModel: Record<string, { requests: number; promptTokens: number; completionTokens: number; totalTokens: number; estimatedCostUsd: number; avgDurationMs: number }> = {};\n for (const e of recent) {\n if (!byModel[e.model]) byModel[e.model] = { requests: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0, estimatedCostUsd: 0, avgDurationMs: 0 };\n const m = byModel[e.model];\n m.requests++;\n m.promptTokens += e.promptTokens;\n m.completionTokens += e.completionTokens;\n m.totalTokens += e.totalTokens;\n m.estimatedCostUsd += e.estimatedCostUsd;\n m.avgDurationMs = (m.avgDurationMs * (m.requests - 1) + e.durationMs) / m.requests;\n }\n\n // Round costs\n for (const m of Object.values(byModel)) {\n m.estimatedCostUsd = Math.round(m.estimatedCostUsd * 10000) / 10000;\n m.avgDurationMs = Math.round(m.avgDurationMs);\n }\n\n const totalCost = Object.values(byModel).reduce((sum, m) => sum + m.estimatedCostUsd, 0);\n\n res.json({\n period: `${hours}h`,\n totalRequests: recent.length,\n totalTokens: recent.reduce((sum, e) => sum + e.totalTokens, 0),\n estimatedCostUsd: Math.round(totalCost * 10000) / 10000,\n byModel,\n recentEntries: recent.slice(-20), // Last 20 for detail view\n });\n });\n\n // Update System endpoints\n app.get('/api/update', async (_req, res) => {\n const info = await getUpdateInfo();\n res.json(info);\n });\n\n app.post('/api/update', (req, res) => {\n const isLocalDev = fs.existsSync(join(process.cwd(), '.git'));\n const isSystemd = fs.existsSync('/run/systemd/system') ||\n fs.existsSync(join(process.cwd(), '.systemd-service'));\n const restart = req.body?.restart === true;\n\n let command: string;\n let postCommand: string | null = null;\n\n if (isLocalDev) {\n // Development checkout — pull source + build\n command = 'git pull && npm run build';\n if (restart) {\n // Write restart script + exit\n postCommand = 'restart'; // handled below\n }\n } else if (isSystemd) {\n // Production systemd deployment — pull from git repo + restart service\n command = 'git pull && npm run build';\n if (restart) {\n postCommand = 'systemctl';\n }\n } else {\n // Global npm install — works only when user has write access to prefix\n command = 'npm update -g titan-agent';\n }\n\n logger.info(COMPONENT, `Triggering update: ${command} (isDev=${isLocalDev}, isSystemd=${isSystemd}, restart=${restart})`);\n\n exec(command, { timeout: 180_000 }, (error, stdout, _stderr) => {\n if (error) {\n logger.error(COMPONENT, `Update failed: ${error.message}`);\n if (!res.headersSent) res.json({ ok: false, error: error.message });\n return;\n }\n\n logger.info(COMPONENT, `Update completed successfully.\\\\n${stdout}`);\n if (!res.headersSent) {\n res.json({ ok: true, message: 'Update completed', restarting: restart, output: stdout.slice(-500) });\n }\n\n if (restart) {\n logger.info(COMPONENT, 'Scheduling restart in 2 seconds...');\n const cwd = process.cwd();\n\n if (postCommand === 'systemctl') {\n // Production: use systemctl to restart (requires user passwordless sudo rights)\n const scriptPath = '/tmp/titan-restart.sh';\n fs.writeFileSync(scriptPath, [\n '#!/bin/bash',\n 'sleep 2',\n `cd \"${cwd}\"`,\n 'sudo systemctl restart titan-gateway',\n ].join('\\n'), { mode: 0o755 });\n spawn('bash', [scriptPath], { detached: true, stdio: 'ignore' }).unref();\n } else {\n // Dev or global: spawn node directly\n const scriptPath = '/tmp/titan-restart.sh';\n fs.writeFileSync(scriptPath, [\n '#!/bin/bash',\n 'sleep 2',\n `cd \"${cwd}\"`,\n 'nohup node dist/cli/index.js gateway >> /tmp/titan-gateway.log 2>&1 &',\n ].join('\\n'), { mode: 0o755 });\n spawn('bash', [scriptPath], { detached: true, stdio: 'ignore' }).unref();\n }\n\n setTimeout(() => {\n logger.info(COMPONENT, 'Exiting for restart...');\n process.exit(0);\n }, 1000);\n }\n });\n });\n\n // Config endpoints\n app.get('/api/config', (_req, res) => {\n const cfg = loadConfig();\n // Return config with sensitive fields masked\n res.json({\n model: cfg.agent.model,\n provider: cfg.agent.model?.split('/')[0] || 'openai',\n voice: {\n enabled: Boolean(cfg.voice?.enabled),\n livekitUrl: cfg.voice?.livekitUrl || '',\n agentUrl: cfg.voice?.agentUrl || '',\n ttsEngine: cfg.voice?.ttsEngine || 'f5-tts',\n ttsUrl: cfg.voice?.ttsUrl || 'http://localhost:5006',\n ttsVoice: cfg.voice?.ttsVoice || 'tara',\n sttUrl: cfg.voice?.sttUrl || 'http://localhost:48421',\n sttEngine: cfg.voice?.sttEngine || 'faster-whisper',\n model: cfg.voice?.model || '',\n },\n agent: { ...cfg.agent, systemPrompt: undefined, systemPromptConfigured: Boolean(cfg.agent.systemPrompt) },\n autonomy: cfg.autonomy,\n security: {\n sandboxMode: cfg.security.sandboxMode,\n shield: cfg.security.shield,\n deniedTools: cfg.security.deniedTools || [],\n networkAllowlist: cfg.security.networkAllowlist || [],\n },\n gateway: {\n port: cfg.gateway.port,\n host: cfg.gateway.host,\n auth: { mode: cfg.gateway.auth.mode },\n },\n logging: cfg.logging,\n providers: {\n anthropic: { configured: Boolean(cfg.providers.anthropic?.apiKey) },\n openai: { configured: Boolean(cfg.providers.openai?.apiKey) },\n google: { configured: Boolean(cfg.providers.google?.apiKey) },\n ollama: { baseUrl: cfg.providers.ollama?.baseUrl || 'http://localhost:11434' },\n groq: { configured: Boolean(cfg.providers.groq?.apiKey) },\n mistral: { configured: Boolean(cfg.providers.mistral?.apiKey) },\n fireworks: { configured: Boolean(cfg.providers.fireworks?.apiKey) },\n xai: { configured: Boolean(cfg.providers.xai?.apiKey) },\n together: { configured: Boolean(cfg.providers.together?.apiKey) },\n deepseek: { configured: Boolean(cfg.providers.deepseek?.apiKey) },\n perplexity: { configured: Boolean(cfg.providers.perplexity?.apiKey) },\n },\n oauth: {\n google: {\n clientIdSet: Boolean(cfg.oauth?.google?.clientId),\n clientSecretSet: Boolean(cfg.oauth?.google?.clientSecret),\n },\n },\n channels: Object.fromEntries(\n Object.entries(cfg.channels).map(([k, v]) => {\n const ch = v as { enabled?: boolean; token?: string; dmPolicy?: string };\n return [k, { enabled: Boolean(ch.enabled), dmPolicy: ch.dmPolicy || 'pairing' }];\n })\n ),\n nvidia: (() => {\n const nv = (cfg as Record<string, unknown>).nvidia as Record<string, unknown> | undefined;\n if (!nv) return { enabled: false, apiKeySet: false, cuopt: { enabled: false, url: 'http://localhost:5000' }, asr: { enabled: false, grpcUrl: 'localhost:50051', healthUrl: 'http://localhost:9000' }, openshell: { enabled: false, binaryPath: 'openshell', policyPath: '' } };\n return {\n enabled: Boolean(nv.enabled),\n apiKeySet: Boolean(nv.apiKey || process.env.NVIDIA_API_KEY),\n cuopt: nv.cuopt ?? { enabled: false, url: 'http://localhost:5000' },\n asr: nv.asr ?? { enabled: false, grpcUrl: 'localhost:50051', healthUrl: 'http://localhost:9000' },\n openshell: nv.openshell ?? { enabled: false, binaryPath: 'openshell', policyPath: '' },\n };\n })(),\n mesh: {\n enabled: Boolean(cfg.mesh?.enabled),\n mdns: Boolean(cfg.mesh?.mdns),\n tailscale: Boolean(cfg.mesh?.tailscale),\n maxPeers: cfg.mesh?.maxPeers ?? 5,\n autoApprove: Boolean(cfg.mesh?.autoApprove),\n },\n organism: {\n enabled: Boolean(cfg.organism?.enabled),\n hormonesInPrompt: Boolean(cfg.organism?.hormonesInPrompt),\n pressureThreshold: Number(cfg.organism?.pressureThreshold) || 0.5,\n shadowEnabled: Boolean(cfg.organism?.shadowEnabled),\n tickIntervalMs: Number(cfg.organism?.tickIntervalMs) || 60000,\n },\n commandPost: {\n enabled: Boolean((cfg as Record<string, any>).commandPost?.enabled),\n heartbeatIntervalMs: (cfg as Record<string, any>).commandPost?.heartbeatIntervalMs ?? 30000,\n maxConcurrentAgents: (cfg as Record<string, any>).commandPost?.maxConcurrentAgents ?? 10,\n checkoutTimeoutMs: (cfg as Record<string, any>).commandPost?.checkoutTimeoutMs ?? 300000,\n },\n });\n });\n\n app.post('/api/config', async (req, res) => {\n try {\n const body = req.body as Record<string, unknown>;\n const cfg = loadConfig();\n // Clone config to avoid mutating live state before validation succeeds\n const draft = structuredClone(cfg) as typeof cfg;\n\n // Track which config fields are being changed for restart detection\n const changedFields: string[] = [];\n\n if (body.model) {\n // Hunt Finding #35 (2026-04-14): POST /api/config's `model` field\n // was bypassing the shape + provider-registry validation that\n // /api/model/switch gained in #25. Same bug class: a bogus string\n // got persisted to config. Apply the same shape check here.\n const modelShapeErr = validateModelId(body.model);\n if (modelShapeErr) {\n res.status(400).json({ error: `model: ${modelShapeErr}` });\n return;\n }\n // Also validate the provider is registered (same as #25).\n const modelStr = body.model as string;\n const providerPrefix = modelStr.split('/')[0];\n if (providerPrefix && providerPrefix !== 'ollama') {\n const { getProvider } = await import('../providers/router.js');\n if (!getProvider(providerPrefix)) {\n res.status(400).json({\n error: `Unknown provider '${providerPrefix}'. Use /api/models to list available providers and models.`,\n });\n return;\n }\n }\n draft.agent.model = modelStr;\n changedFields.push('agent.model');\n }\n if (body.autonomyMode) { draft.autonomy.mode = body.autonomyMode as 'supervised' | 'autonomous' | 'locked'; changedFields.push('autonomy.mode'); }\n if (body.sandboxMode) { draft.security.sandboxMode = body.sandboxMode as 'host' | 'docker' | 'none'; changedFields.push('security.sandboxMode'); }\n if (body.logLevel) { draft.logging.level = body.logLevel as 'info' | 'debug' | 'warn' | 'silent'; changedFields.push('logging.level'); }\n // Provider API keys\n if (body.anthropicKey !== undefined) { draft.providers.anthropic.apiKey = body.anthropicKey as string; changedFields.push('providers.anthropic.apiKey'); }\n if (body.openaiKey !== undefined) { draft.providers.openai.apiKey = body.openaiKey as string; changedFields.push('providers.openai.apiKey'); }\n if (body.googleKey !== undefined) { draft.providers.google.apiKey = body.googleKey as string; changedFields.push('providers.google.apiKey'); }\n if (body.ollamaUrl !== undefined) { draft.providers.ollama.baseUrl = body.ollamaUrl as string; changedFields.push('providers.ollama.baseUrl'); }\n if (body.groqKey !== undefined) { draft.providers.groq.apiKey = body.groqKey as string; changedFields.push('providers.groq.apiKey'); }\n if (body.mistralKey !== undefined) { draft.providers.mistral.apiKey = body.mistralKey as string; changedFields.push('providers.mistral.apiKey'); }\n if (body.fireworksKey !== undefined) { draft.providers.fireworks.apiKey = body.fireworksKey as string; changedFields.push('providers.fireworks.apiKey'); }\n if (body.xaiKey !== undefined) { draft.providers.xai.apiKey = body.xaiKey as string; changedFields.push('providers.xai.apiKey'); }\n if (body.togetherKey !== undefined) { draft.providers.together.apiKey = body.togetherKey as string; changedFields.push('providers.together.apiKey'); }\n if (body.deepseekKey !== undefined) { draft.providers.deepseek.apiKey = body.deepseekKey as string; changedFields.push('providers.deepseek.apiKey'); }\n if (body.perplexityKey !== undefined) { draft.providers.perplexity.apiKey = body.perplexityKey as string; changedFields.push('providers.perplexity.apiKey'); }\n // Google OAuth\n if (body.googleOAuthClientId !== undefined) {\n if (!draft.oauth) (draft as Record<string, unknown>).oauth = { google: {} };\n draft.oauth.google.clientId = body.googleOAuthClientId as string;\n changedFields.push('oauth.google.clientId');\n }\n if (body.googleOAuthClientSecret !== undefined) {\n if (!draft.oauth) (draft as Record<string, unknown>).oauth = { google: {} };\n draft.oauth.google.clientSecret = body.googleOAuthClientSecret as string;\n changedFields.push('oauth.google.clientSecret');\n }\n // Agent settings\n if (body.maxTokens !== undefined) { draft.agent.maxTokens = Number(body.maxTokens); changedFields.push('agent.maxTokens'); }\n if (body.temperature !== undefined) { draft.agent.temperature = Number(body.temperature); changedFields.push('agent.temperature'); }\n if (body.systemPrompt !== undefined) { draft.agent.systemPrompt = body.systemPrompt as string; changedFields.push('agent.systemPrompt'); }\n // Security shield\n if (body.shieldEnabled !== undefined) { draft.security.shield.enabled = Boolean(body.shieldEnabled); changedFields.push('security.shield.enabled'); }\n if (body.shieldMode !== undefined) { draft.security.shield.mode = body.shieldMode as 'strict' | 'standard'; changedFields.push('security.shield.mode'); }\n if (body.deniedTools !== undefined) { draft.security.deniedTools = body.deniedTools as string[]; changedFields.push('security.deniedTools'); }\n if (body.networkAllowlist !== undefined) { draft.security.networkAllowlist = body.networkAllowlist as string[]; changedFields.push('security.networkAllowlist'); }\n // Gateway\n if (body.gatewayPort !== undefined) { draft.gateway.port = Number(body.gatewayPort); changedFields.push('gateway.port'); }\n if (body.gatewayAuthMode !== undefined) { draft.gateway.auth.mode = body.gatewayAuthMode as 'none' | 'token' | 'password'; changedFields.push('gateway.auth.mode'); }\n if (body.gatewayPassword !== undefined) { draft.gateway.auth.password = body.gatewayPassword as string; changedFields.push('gateway.auth.password'); }\n if (body.gatewayToken !== undefined) { draft.gateway.auth.token = body.gatewayToken as string; changedFields.push('gateway.auth.token'); }\n // Voice settings (nested object from SettingsPanel)\n if (body.voice !== undefined && typeof body.voice === 'object') {\n const v = body.voice as Record<string, unknown>;\n if (v.enabled !== undefined) draft.voice.enabled = Boolean(v.enabled);\n if (v.livekitUrl !== undefined) draft.voice.livekitUrl = String(v.livekitUrl);\n if (v.livekitApiKey !== undefined) draft.voice.livekitApiKey = String(v.livekitApiKey);\n if (v.livekitApiSecret !== undefined) draft.voice.livekitApiSecret = String(v.livekitApiSecret);\n if (v.agentUrl !== undefined) draft.voice.agentUrl = String(v.agentUrl);\n if (v.ttsVoice !== undefined) draft.voice.ttsVoice = String(v.ttsVoice);\n if (v.ttsEngine !== undefined) draft.voice.ttsEngine = String(v.ttsEngine) as typeof draft.voice.ttsEngine;\n if (v.ttsUrl !== undefined) draft.voice.ttsUrl = String(v.ttsUrl);\n if (v.sttUrl !== undefined) draft.voice.sttUrl = String(v.sttUrl);\n if (v.sttEngine !== undefined) draft.voice.sttEngine = String(v.sttEngine) as typeof draft.voice.sttEngine;\n if (v.model !== undefined) (draft.voice as Record<string, unknown>).model = String(v.model) || undefined;\n changedFields.push('voice');\n }\n // Home Assistant\n if (body.homeAssistantUrl !== undefined) { draft.homeAssistant.url = body.homeAssistantUrl as string; changedFields.push('homeAssistant.url'); }\n if (body.homeAssistantToken !== undefined) { draft.homeAssistant.token = body.homeAssistantToken as string; changedFields.push('homeAssistant.token'); }\n // Channels\n if (body.channels !== undefined && typeof body.channels === 'object') {\n for (const [ch, val] of Object.entries(body.channels as Record<string, unknown>)) {\n if (draft.channels[ch as keyof typeof draft.channels]) {\n Object.assign(draft.channels[ch as keyof typeof draft.channels], val);\n changedFields.push(`channels.${ch}`);\n }\n }\n }\n // NVIDIA config (nested object)\n if (body.nvidia !== undefined && typeof body.nvidia === 'object') {\n const nv = body.nvidia as Record<string, unknown>;\n const nvCfg = ((draft as Record<string, unknown>).nvidia || {}) as Record<string, unknown>;\n if (nv.enabled !== undefined) nvCfg.enabled = Boolean(nv.enabled);\n if (nv.apiKey !== undefined) nvCfg.apiKey = String(nv.apiKey);\n if (nv.cuopt !== undefined && typeof nv.cuopt === 'object') {\n const cuopt = (nvCfg.cuopt || {}) as Record<string, unknown>;\n const src = nv.cuopt as Record<string, unknown>;\n if (src.enabled !== undefined) cuopt.enabled = Boolean(src.enabled);\n if (src.url !== undefined) cuopt.url = String(src.url);\n nvCfg.cuopt = cuopt;\n }\n if (nv.asr !== undefined && typeof nv.asr === 'object') {\n const asr = (nvCfg.asr || {}) as Record<string, unknown>;\n const src = nv.asr as Record<string, unknown>;\n if (src.enabled !== undefined) asr.enabled = Boolean(src.enabled);\n if (src.grpcUrl !== undefined) asr.grpcUrl = String(src.grpcUrl);\n if (src.healthUrl !== undefined) asr.healthUrl = String(src.healthUrl);\n nvCfg.asr = asr;\n }\n if (nv.openshell !== undefined && typeof nv.openshell === 'object') {\n const os = (nvCfg.openshell || {}) as Record<string, unknown>;\n const src = nv.openshell as Record<string, unknown>;\n if (src.enabled !== undefined) os.enabled = Boolean(src.enabled);\n if (src.binaryPath !== undefined) os.binaryPath = String(src.binaryPath);\n if (src.policyPath !== undefined) os.policyPath = String(src.policyPath);\n nvCfg.openshell = os;\n }\n (draft as Record<string, unknown>).nvidia = nvCfg;\n changedFields.push('nvidia');\n }\n // Organism / SOMA toggle\n if (body.organism !== undefined && typeof body.organism === 'object') {\n const org = body.organism as Record<string, unknown>;\n if (!draft.organism) (draft as Record<string, unknown>).organism = {};\n if (org.enabled !== undefined) draft.organism.enabled = Boolean(org.enabled);\n if (org.hormonesInPrompt !== undefined) draft.organism.hormonesInPrompt = Boolean(org.hormonesInPrompt);\n if (org.pressureThreshold !== undefined) draft.organism.pressureThreshold = Number(org.pressureThreshold);\n if (org.shadowEnabled !== undefined) draft.organism.shadowEnabled = Boolean(org.shadowEnabled);\n if (org.tickIntervalMs !== undefined) draft.organism.tickIntervalMs = Number(org.tickIntervalMs);\n changedFields.push('organism');\n }\n\n // Autonomy toggles (v5.0.2 — Autonomy Settings Panel)\n const handleNestedBool = (section: string, key: string, target: Record<string, unknown>) => {\n const sec = body[section] as Record<string, unknown> | undefined;\n if (sec && key in sec) {\n target[key] = Boolean(sec[key]);\n changedFields.push(`${section}.${key}`);\n }\n };\n if (body.autonomy !== undefined && typeof body.autonomy === 'object') {\n const a = body.autonomy as Record<string, unknown>;\n if (!draft.autonomy) (draft as Record<string, unknown>).autonomy = {};\n const da = draft.autonomy as Record<string, unknown>;\n if (a.mode !== undefined) da.mode = a.mode as 'autonomous' | 'supervised' | 'locked';\n if (a.autoProposeGoals !== undefined) da.autoProposeGoals = Boolean(a.autoProposeGoals);\n if (a.proactiveInitiative !== undefined) da.proactiveInitiative = Boolean(a.proactiveInitiative);\n changedFields.push('autonomy');\n }\n if (body.selfMod !== undefined && typeof body.selfMod === 'object') {\n const s = body.selfMod as Record<string, unknown>;\n if (!draft.selfMod) (draft as Record<string, unknown>).selfMod = {};\n if (s.enabled !== undefined) draft.selfMod.enabled = Boolean(s.enabled);\n if (s.autoPR !== undefined) draft.selfMod.autoPR = Boolean(s.autoPR);\n changedFields.push('selfMod');\n }\n if (body.commandPost !== undefined && typeof body.commandPost === 'object') {\n const cp = body.commandPost as Record<string, unknown>;\n if (!draft.commandPost) (draft as Record<string, unknown>).commandPost = {};\n if (cp.enabled !== undefined) draft.commandPost.enabled = Boolean(cp.enabled);\n changedFields.push('commandPost');\n }\n if (body.mesh !== undefined && typeof body.mesh === 'object') {\n const m = body.mesh as Record<string, unknown>;\n if (!draft.mesh) (draft as Record<string, unknown>).mesh = {};\n if (m.enabled !== undefined) draft.mesh.enabled = Boolean(m.enabled);\n changedFields.push('mesh');\n }\n if (body.autopilot !== undefined && typeof body.autopilot === 'object') {\n const ap = body.autopilot as Record<string, unknown>;\n if (!draft.autopilot) (draft as Record<string, unknown>).autopilot = {};\n if (ap.enabled !== undefined) draft.autopilot.enabled = Boolean(ap.enabled);\n if (ap.goals !== undefined && typeof ap.goals === 'object') {\n const apg = ap.goals as Record<string, unknown>;\n const dag = (draft.autopilot as Record<string, unknown>);\n if (!dag.goals) dag.goals = {};\n if (apg.selfInitiate !== undefined) (dag.goals as Record<string, unknown>).selfInitiate = Boolean(apg.selfInitiate);\n }\n changedFields.push('autopilot');\n }\n if (body.brain !== undefined && typeof body.brain === 'object') {\n const b = body.brain as Record<string, unknown>;\n if (!draft.brain) (draft as Record<string, unknown>).brain = {};\n if (b.enabled !== undefined) draft.brain.enabled = Boolean(b.enabled);\n changedFields.push('brain');\n }\n if (body.mcp !== undefined && typeof body.mcp === 'object') {\n const mcp = body.mcp as Record<string, unknown>;\n if (!draft.mcp) (draft as Record<string, unknown>).mcp = { server: {} };\n if (mcp.server !== undefined && typeof mcp.server === 'object') {\n const srv = mcp.server as Record<string, unknown>;\n const dmcp = (draft.mcp as Record<string, unknown>);\n if (!dmcp.server) dmcp.server = {};\n if (srv.enabled !== undefined) (dmcp.server as Record<string, unknown>).enabled = Boolean(srv.enabled);\n }\n changedFields.push('mcp');\n }\n if (body.training !== undefined && typeof body.training === 'object') {\n const t = body.training as Record<string, unknown>;\n if (!draft.training) (draft as Record<string, unknown>).training = {};\n if (t.enabled !== undefined) draft.training.enabled = Boolean(t.enabled);\n changedFields.push('training');\n }\n if (body.teams !== undefined && typeof body.teams === 'object') {\n const t = body.teams as Record<string, unknown>;\n if (!draft.teams) (draft as Record<string, unknown>).teams = {};\n if (t.enabled !== undefined) draft.teams.enabled = Boolean(t.enabled);\n changedFields.push('teams');\n }\n if (body.tunnel !== undefined && typeof body.tunnel === 'object') {\n const t = body.tunnel as Record<string, unknown>;\n if (!draft.tunnel) (draft as Record<string, unknown>).tunnel = {};\n if (t.enabled !== undefined) draft.tunnel.enabled = Boolean(t.enabled);\n changedFields.push('tunnel');\n }\n if (body.vault !== undefined && typeof body.vault === 'object') {\n const v = body.vault as Record<string, unknown>;\n const dsec = (draft.security as Record<string, unknown>);\n if (!dsec.vault) dsec.vault = {};\n if (v.enabled !== undefined) (dsec.vault as Record<string, unknown>).enabled = Boolean(v.enabled);\n changedFields.push('security.vault');\n }\n if (body.capsolver !== undefined && typeof body.capsolver === 'object') {\n const c = body.capsolver as Record<string, unknown>;\n if (!draft.capsolver) (draft as Record<string, unknown>).capsolver = {};\n if (c.enabled !== undefined) draft.capsolver.enabled = Boolean(c.enabled);\n changedFields.push('capsolver');\n }\n if (body.deliberation !== undefined && typeof body.deliberation === 'object') {\n const d = body.deliberation as Record<string, unknown>;\n if (!draft.deliberation) (draft as Record<string, unknown>).deliberation = {};\n if (d.autoDetect !== undefined) draft.deliberation.autoDetect = Boolean(d.autoDetect);\n changedFields.push('deliberation');\n }\n if (body.selfImprove !== undefined && typeof body.selfImprove === 'object') {\n const si = body.selfImprove as Record<string, unknown>;\n if (!draft.selfImprove) (draft as Record<string, unknown>).selfImprove = {};\n if (si.autoApply !== undefined) draft.selfImprove.autoApply = Boolean(si.autoApply);\n changedFields.push('selfImprove');\n }\n if (body.memory !== undefined && typeof body.memory === 'object') {\n const mem = body.memory as Record<string, unknown>;\n if (!draft.memory) (draft as Record<string, unknown>).memory = {};\n if (mem.vectorSearchEnabled !== undefined) draft.memory.vectorSearchEnabled = Boolean(mem.vectorSearchEnabled);\n changedFields.push('memory');\n }\n\n if (changedFields.length === 0) {\n const validFields = ['model', 'autonomyMode', 'sandboxMode', 'logLevel', 'anthropicKey', 'openaiKey',\n 'googleKey', 'ollamaUrl', 'groqKey', 'mistralKey', 'fireworksKey', 'xaiKey',\n 'togetherKey', 'deepseekKey', 'perplexityKey', 'maxTokens', 'temperature', 'systemPrompt',\n 'shieldEnabled', 'shieldMode', 'deniedTools', 'networkAllowlist', 'gatewayPort', 'gatewayAuthMode',\n 'gatewayPassword', 'gatewayToken', 'channels', 'googleOAuthClientId', 'googleOAuthClientSecret',\n 'homeAssistantUrl', 'homeAssistantToken', 'voice', 'nvidia', 'organism',\n 'autonomy', 'selfMod', 'commandPost', 'mesh', 'autopilot', 'brain', 'mcp',\n 'training', 'teams', 'tunnel', 'vault', 'capsolver', 'deliberation', 'selfImprove', 'memory'];\n res.status(400).json({ error: 'No recognized fields in request body', validFields });\n return;\n }\n // Validation happens inside updateConfig (Zod parse) — draft is only applied if valid\n updateConfig(draft);\n\n // Determine which changed fields require a restart\n const restartFields = changedFields.filter(field =>\n RESTART_REQUIRED_PATTERNS.some(pattern => {\n if (pattern.endsWith('.*')) {\n return field.startsWith(pattern.slice(0, -1));\n }\n return field === pattern;\n })\n );\n\n res.json({ ok: true, restartRequired: restartFields.length > 0, restartFields });\n } catch (e) {\n // Return 400 for Zod validation errors, 500 for unexpected errors\n const isValidationError = (e as Error).name === 'ZodError' || (e as Error).message?.includes('Validation');\n res.status(isValidationError ? 400 : 500).json({ error: (e as Error).message });\n }\n });\n\n // Models endpoint — lists all providers + live Ollama models\n // Model discovery + management endpoints\n app.get('/api/models', async (req, res) => {\n const cfg = loadConfig();\n // ?refresh=1 bypasses the 60s discovery cache so the user sees a\n // catalogue change immediately after configuring a provider key.\n const forceRefresh = req.query.refresh === '1' || req.query.refresh === 'true';\n const models = await discoverAllModels(forceRefresh);\n // Group by provider, plus a sibling map of provider → key state so the\n // Settings UI can show \"needs key\" badges next to providers the user\n // hasn't configured yet (and ideally block selection of those models).\n const grouped: Record<string, string[]> = {};\n const keyConfigured: Record<string, boolean> = {};\n for (const m of models) {\n if (!grouped[m.provider]) grouped[m.provider] = [];\n grouped[m.provider].push(m.id);\n // First-write wins, but every model from the same provider has the\n // same flag so order doesn't matter.\n if (!(m.provider in keyConfigured)) keyConfigured[m.provider] = m.keyConfigured;\n }\n res.json({\n ...grouped,\n current: cfg.agent.model,\n aliases: getModelAliases(),\n _meta: {\n keyConfigured,\n cacheRefreshed: forceRefresh,\n },\n });\n });\n\n // ── Provider Status API ─────────────────────────────────────────\n app.get('/api/providers/status', async (_req, res) => {\n try {\n const { getCircuitBreakerStatus } = await import('../providers/router.js');\n const cbStatus = getCircuitBreakerStatus();\n const health = await healthCheckAll();\n const providers = Object.entries(health).map(([name, healthy]) => ({\n name,\n healthy,\n circuitBreaker: cbStatus[name] || { state: 'unknown', failureCount: 0 },\n }));\n res.json({ providers, count: providers.length });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.post('/api/providers/:name/reset', async (req, res) => {\n try {\n const { resetCircuitBreaker } = await import('../providers/router.js');\n resetCircuitBreaker(req.params.name);\n res.json({ reset: true, provider: req.params.name });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n app.get('/api/models/discover', async (_req, res) => {\n const models = await discoverAllModels(true);\n const cfg = loadConfig();\n res.json({\n models,\n current: cfg.agent.model,\n aliases: getModelAliases(),\n });\n });\n\n app.get('/api/fallback-state', (_req, res) => {\n const state = getFallbackState();\n res.json(state || { active: null });\n });\n\n /**\n * Hunt Finding #25 + #35 (2026-04-14): shared model-id input validator.\n * Used by BOTH /api/model/switch AND /api/config (where `body.model` takes\n * the same path). Returns a validation error string or null if valid.\n */\n function validateModelId(model: unknown): string | null {\n if (typeof model !== 'string' || model.length === 0 || model.length > 200) {\n return 'model must be a non-empty string up to 200 chars';\n }\n if (!/^[a-zA-Z0-9._:\\-/]+$/.test(model)) {\n return 'model contains invalid characters (allowed: alnum, ._:-/)';\n }\n return null;\n }\n\n app.post('/api/model/switch', async (req, res) => {\n try {\n const { model } = req.body as { model?: string };\n if (!model) { res.status(400).json({ error: 'model is required' }); return; }\n const shapeErr = validateModelId(model);\n if (shapeErr) { res.status(400).json({ error: shapeErr }); return; }\n const cfg = loadConfig();\n // Resolve aliases\n const aliases = cfg.agent.modelAliases || {};\n const resolved = aliases[model] || model;\n\n // ── CRITICAL FIX: Validate model exists for ALL providers ──\n const [providerName, ...modelParts] = resolved.split('/');\n const modelName = modelParts.join('/') || resolved; // Handle models with slashes in name\n\n // Hunt Finding #25 (2026-04-14): previously, any providerName that\n // wasn't 'ollama' fell through the `else if (providerName)` branch and\n // was accepted without validation. A POST with model=\"fake/fake-model\"\n // would succeed and write the bogus value to config, bricking the\n // gateway until manually reverted. Validate the provider exists in\n // the registered router before accepting the switch.\n if (providerName && providerName !== 'ollama') {\n const { getProvider } = await import('../providers/router.js');\n if (!getProvider(providerName)) {\n logger.warn(COMPONENT, `[ModelSwitch] Unknown provider '${providerName}' — rejecting`);\n res.status(400).json({\n error: `Unknown provider '${providerName}'. Use /api/models to list available providers and models.`,\n });\n return;\n }\n }\n\n // 1. Ollama local models — check if model is pulled\n if (providerName === 'ollama') {\n const ollamaBase = cfg.providers.ollama?.baseUrl || 'http://localhost:11434';\n // Cloud-routed models (suffix :cloud) are always valid — they proxy through Ollama to external APIs\n if (modelName.endsWith(':cloud')) {\n logger.info(COMPONENT, `[ModelSwitch] Cloud-routed model '${modelName}' — allowing (proxied via Ollama)`);\n } else {\n // Local model: verify it exists in Ollama\n try {\n const check = await fetch(`${ollamaBase}/api/show`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: modelName }),\n signal: AbortSignal.timeout(5000),\n });\n if (!check.ok) {\n logger.warn(COMPONENT, `[ModelSwitch] Model '${modelName}' not found in Ollama (HTTP ${check.status})`);\n res.status(404).json({ error: `Model '${modelName}' not found in Ollama. Pull it first: ollama pull ${modelName}` });\n return;\n }\n logger.info(COMPONENT, `[ModelSwitch] Verified Ollama model '${modelName}' exists`);\n } catch (err) {\n // CRITICAL FIX: Ollama unreachable — reject the switch instead of allowing it\n logger.error(COMPONENT, `[ModelSwitch] Ollama unreachable at ${ollamaBase}: ${(err as Error).message}`);\n res.status(503).json({\n error: `Cannot verify model '${modelName}' — Ollama is unreachable at ${ollamaBase}. Check Ollama is running: ollama serve`,\n });\n return;\n }\n }\n } else if (providerName) {\n // 2. Other providers — just log the provider (allow the switch)\n // We trust the user to configure API keys; reject only happens at chat time\n logger.info(COMPONENT, `[ModelSwitch] Switching to provider '${providerName.toLowerCase()}' model '${modelName}'`);\n }\n // If no provider prefix (bare model like 'gpt-4o'), assume it's an alias or user knows what they're doing\n\n updateConfig({ agent: { ...cfg.agent, model: resolved } });\n // Invalidate cached responses for the old model so stale results aren't served\n invalidateCacheForModel(cfg.agent.model);\n logger.info(COMPONENT, `Model switched to: ${resolved}${resolved !== model ? ` (alias: ${model})` : ''}`);\n res.json({ success: true, model: resolved, alias: resolved !== model ? model : undefined });\n } catch (err) {\n logger.error(COMPONENT, `[ModelSwitch] Error: ${(err as Error).message}`);\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // ─── Model Probe — empirical capabilities discovery ──────────\n // POST /api/model/probe { model: \"ollama/glm-5.1:cloud\" }\n // POST /api/model/probe { models: [\"...\", \"...\"] }\n // GET /api/model/probe — list all probed models\n app.post('/api/model/probe', async (req, res) => {\n try {\n const body = req.body as { model?: string; models?: string[] };\n const targets = body.model ? [body.model] : (body.models || []);\n if (targets.length === 0) {\n res.status(400).json({ error: 'Provide {model: \"id\"} or {models: [\"id1\",\"id2\"]}' });\n return;\n }\n\n const { probeModel } = await import('../agent/modelProbe.js');\n const { recordProbeResult } = await import('../agent/capabilitiesRegistry.js');\n\n const results = [];\n for (const modelId of targets) {\n try {\n const result = await probeModel(modelId);\n recordProbeResult(result);\n results.push(result);\n } catch (err) {\n results.push({ model: modelId, error: (err as Error).message });\n }\n }\n res.json({ probed: results.length, results });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n app.get('/api/model/probe', async (_req, res) => {\n try {\n const { loadRegistry } = await import('../agent/capabilitiesRegistry.js');\n const registry = loadRegistry();\n res.json({\n updatedAt: registry.updatedAt,\n count: Object.keys(registry.models).length,\n models: registry.models,\n });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Profile endpoints\n app.get('/api/profile', (_req, res) => {\n const profile = loadProfile();\n res.json({\n name: profile.name || '',\n technicalLevel: profile.technicalLevel || 'unknown',\n projectCount: profile.projects.length,\n goalCount: profile.goals.length,\n });\n });\n\n app.post('/api/profile', (req, res) => {\n try {\n const { name, technicalLevel } = req.body as { name?: string; technicalLevel?: string };\n const profile = loadProfile();\n if (name !== undefined) profile.name = name;\n if (technicalLevel !== undefined) profile.technicalLevel = technicalLevel as PersonalProfile['technicalLevel'];\n saveProfile(profile);\n res.json({ ok: true });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // Learning stats endpoint\n app.get('/api/learning', (_req, res) => {\n res.json(getLearningStats());\n });\n\n app.get('/api/learning/stats', (_req, res) => {\n res.json(getLearningStats());\n });\n\n // Live log tail endpoint\n app.get('/api/logs', (req, res) => {\n try {\n const logPath = getLogFilePath();\n if (!logPath || !fs.existsSync(logPath)) {\n res.json({ lines: [] });\n return;\n }\n const lineCount = req.query.lines ? parseInt(req.query.lines as string, 10) : 200;\n // Read only the last portion of the file\n const stats = fs.statSync(logPath);\n const readSize = Math.min(stats.size, 100000); // Read last 100KB max\n const fd = fs.openSync(logPath, 'r');\n const buf = Buffer.alloc(readSize);\n fs.readSync(fd, buf, 0, readSize, Math.max(0, stats.size - readSize));\n fs.closeSync(fd);\n const content = buf.toString('utf-8');\n const all = content.split('\\n').filter(Boolean);\n // If we started mid-line, drop the first partial line\n const lines = stats.size > readSize ? all.slice(1) : all;\n const tail = lines.slice(-Math.max(1, lineCount));\n // S6: Sanitize logs — strip potential secrets before returning\n const sanitized = tail.map(line =>\n line\n .replace(/Authorization:\\s*Bearer\\s+\\S+/gi, 'Authorization: Bearer [REDACTED]')\n .replace(/token[=:]\\s*[\"']?\\w{20,}[\"']?/gi, 'token=[REDACTED]')\n .replace(/api[_-]?key[=:]\\s*[\"']?\\w{10,}[\"']?/gi, 'api_key=[REDACTED]')\n .replace(/password[=:]\\s*[\"']?[^\\s\"',]+[\"']?/gi, 'password=[REDACTED]')\n .replace(/secret[=:]\\s*[\"']?\\w{10,}[\"']?/gi, 'secret=[REDACTED]')\n );\n res.json({ lines: sanitized });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // Full data reset (graph + knowledge + titan-data)\n app.delete('/api/data', (_req, res) => {\n try {\n const titanHome = join(homedir(), '.titan');\n const files = ['graph.json', 'knowledge.json', 'titan-data.json'];\n const deleted: string[] = [];\n for (const f of files) {\n const p = join(titanHome, f);\n if (fs.existsSync(p)) {\n fs.unlinkSync(p);\n deleted.push(f);\n }\n }\n clearGraph();\n logger.info(COMPONENT, `Full data reset via API: deleted ${deleted.join(', ') || 'none'}`);\n res.json({ success: true, message: `Deleted: ${deleted.join(', ') || 'none'}. Restart recommended.` });\n } catch (e) {\n logger.error(COMPONENT, `Endpoint error: ${(e as Error).message}`); res.status(500).json({ error: 'Something went wrong on our end. Please try again in a moment.' });\n }\n });\n\n // ── Autopilot / Goals / Daemon (Lifecycle Router) ─────────\n app.use('/api', createLifecycleRouter());\n\n // ── Social Media and Watch routes (extracted) ───────────────\n app.use('/api', createSocialRouter());\n app.use('/api', createWatchRouter());\n app.use('/api/files', createFilesRouter());\n\n // ── System API (cron, self-improve, training, autoresearch) ──\n app.use('/api', createSystemRouter());\n\n // ── Voice (extracted) ─────────────────────────────────────\n app.use('/api', createVoiceRouter(\n sessionAborts,\n sessionAbortTimes,\n rateLimit,\n concurrencyGuard,\n { get value() { return activeLlmRequests; }, set value(v: number) { activeLlmRequests = v; } },\n titanActiveSessions,\n titanRequestDuration,\n ));\n\n // ── Mesh (extracted) ───────────────────────────────────────\n app.use('/api', createMeshRouter(broadcast));\n\n // ── Organism (extracted) ───────────────────────────────────\n app.use('/api', createOrganismRouter());\n\n // ── Widget Gallery ────────────────────────────────────────\n app.get('/api/widget-gallery', async (_req, res) => {\n try {\n const { listTemplates, listCategories } = await import('../skills/builtin/widget_gallery.js');\n res.json({ templates: listTemplates(), categories: listCategories() });\n } catch (e) {\n logger.error(COMPONENT, `widget-gallery error: ${(e as Error).message}`);\n res.status(500).json({ error: 'Widget gallery unavailable' });\n }\n });\n\n // ── GraphiTI / Knowledge Graph ───────────────────────────\n app.get('/api/graphiti', async (_req, res) => {\n try {\n const { getGraphData, getGraphStats } = await import('../memory/graph.js');\n const { nodes, edges } = getGraphData();\n const stats = getGraphStats();\n res.json({ graphReady: true, nodes, edges, stats });\n } catch (e) {\n logger.error(COMPONENT, `graphiti error: ${(e as Error).message}`);\n res.json({ graphReady: false, nodes: [], edges: [], stats: {} });\n }\n });\n\n // ── OpenAPI docs (/api/docs JSON + /docs HTML) ────────────\n app.get('/api/docs', (_req, res) => {\n res.json({\n openapi: '3.0.0',\n info: { title: 'TITAN Gateway API', version: TITAN_VERSION },\n paths: {},\n });\n });\n\n app.get('/docs', (_req, res) => {\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.send(`<!doctype html><html><head><title>TITAN API</title></head><body><h1>TITAN API Documentation</h1><p>See <a href=\"/api/docs\">/api/docs</a> for the OpenAPI spec (v${TITAN_VERSION}).</p></body></html>`);\n });\n\n // ── SPA fallback (must be after all API routes) ──────────\n if (hasReactUI) {\n app.get('*', (req, res, next) => {\n // Don't intercept API, WebSocket, metrics, webhooks, or legacy routes.\n // Hunt Finding #44 (2026-04-15): README promised `http://localhost:48420/mcp`\n // as the MCP HTTP transport endpoint, but the SPA catch-all was\n // swallowing /mcp and /mcp/health GETs and returning the dashboard\n // HTML. Pass /mcp* through to next() so mountMcpHttpEndpoints can\n // handle it. (POST /mcp is fine regardless — only GETs hit this.)\n if (\n req.path.startsWith('/api/') ||\n req.path.startsWith('/messenger/') ||\n req.path.startsWith('/mcp') ||\n req.path === '/ws' ||\n req.path === '/metrics' ||\n req.path === '/legacy' ||\n req.path === '/login'\n ) {\n return next();\n }\n res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');\n res.setHeader('Pragma', 'no-cache');\n res.setHeader('Expires', '0');\n res.send(cachedIndexHtml || fs.readFileSync(uiIndexPath, 'utf8'));\n });\n }\n\n // Create HTTP or HTTPS server\n // HTTPS: auto-detect certs at ~/.titan/certs/titan.pem + titan-key.pem (generated by mkcert)\n const certPath = join(homedir(), '.titan', 'certs', 'titan.pem');\n const keyPath = join(homedir(), '.titan', 'certs', 'titan-key.pem');\n const useHttps = fs.existsSync(certPath) && fs.existsSync(keyPath);\n\n if (useHttps) {\n const cert = fs.readFileSync(certPath);\n const key = fs.readFileSync(keyPath);\n httpServer = createHttpsServer({ cert, key }, app);\n logger.info(COMPONENT, `HTTPS enabled (mkcert certs from ${certPath})`);\n } else {\n httpServer = createServer(app);\n }\n\n // Create WebSocket server\n const wss = new WebSocketServer({ server: httpServer });\n\n wss.on('connection', async (ws, req) => {\n try {\n const cfg = loadConfig();\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n\n // ── Mesh peer WebSocket connections ──────────────\n if (url.searchParams.get('mesh') === 'true' && cfg.mesh.enabled && cfg.mesh.secret) {\n const peerNodeId = url.searchParams.get('nodeId') || '';\n const authToken = url.searchParams.get('auth') || '';\n const { verifyMeshAuth, handleMeshWebSocket } = await import('../mesh/transport.js');\n const { getOrCreateNodeId } = await import('../mesh/identity.js');\n\n if (!verifyMeshAuth(authToken, peerNodeId, cfg.mesh.secret)) {\n logger.warn(COMPONENT, `Mesh auth rejected: nodeId=${peerNodeId}, ip=${req.socket.remoteAddress}`);\n ws.close(1008, 'Mesh auth failed');\n return;\n }\n\n const { getActiveRemoteTaskCount } = await import('../mesh/transport.js');\n\n handleMeshWebSocket(ws, peerNodeId, getOrCreateNodeId(), async (msg, reply) => {\n // Enforce allowRemoteModels\n const meshCfg = loadConfig().mesh;\n if (!meshCfg.allowRemoteModels) {\n reply({ error: 'Remote model access is disabled on this node' });\n return;\n }\n // Enforce maxRemoteTasks\n if (getActiveRemoteTaskCount() >= meshCfg.maxRemoteTasks) {\n reply({ error: 'Node at capacity — max remote tasks reached' });\n return;\n }\n // Handle incoming task requests from mesh peers\n try {\n const result = await processMessage(msg.payload.message as string, 'mesh', msg.fromNodeId, {\n model: msg.payload.model as string,\n });\n reply({ ...result });\n } catch (err) {\n reply({ error: (err as Error).message });\n }\n });\n return; // Don't add to wsClients — mesh peers use separate handling\n }\n\n // ── WebSocket Origin Validation (CVE-2026-25253 class) ──────\n // Prevent cross-origin WebSocket hijacking from malicious web pages\n const origin = req.headers.origin;\n if (origin) {\n const wsAllowlist = (cfg.gateway as Record<string, unknown>).wsOriginAllowlist as string[] | undefined;\n const customPatterns = (wsAllowlist || []).map(o => new RegExp(`^${o.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}$`));\n const allowed = isAllowedOrigin(origin) || customPatterns.some(p => p.test(origin));\n if (!allowed) {\n logger.warn(COMPONENT, `WebSocket origin rejected: ${origin} (not in allowlist)`);\n ws.close(1008, 'Origin not allowed');\n return;\n }\n }\n\n // ── Regular dashboard WebSocket connections ──────\n const auth = cfg.gateway.auth;\n if (auth && auth.mode !== 'none') {\n const token = url.searchParams.get('token') || '';\n if (!isValidToken(token, cfg)) {\n ws.close(1008, 'Unauthorized');\n return;\n }\n }\n\n // Tag connection with userId from query params (for session isolation)\n const taggedWs = ws as TaggedWebSocket;\n taggedWs.titanUserId = url.searchParams.get('userId') || 'webchat-user';\n wsClients.add(taggedWs);\n logger.info(COMPONENT, `WebSocket client connected (${wsClients.size} total, user=${taggedWs.titanUserId})`);\n\n ws.on('message', async (rawData, isBinary) => {\n try {\n // Ignore binary frames (legacy voice pipeline removed — use LiveKit WebRTC)\n if (isBinary) return;\n\n // R9: Reject oversized messages to prevent OOM\n const msgBytes = typeof rawData === 'string' ? Buffer.byteLength(rawData) : (rawData as Buffer).length;\n if (msgBytes > WS_MAX_MESSAGE_BYTES) {\n logger.warn(COMPONENT, `WebSocket message too large (${(msgBytes / 1024 / 1024).toFixed(1)}MB) — rejected`);\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'error', message: 'Message too large (max 10MB)' }));\n }\n return;\n }\n\n let data;\n try {\n data = JSON.parse(rawData.toString());\n } catch (parseErr) {\n logger.warn(COMPONENT, `Invalid WebSocket JSON: ${(parseErr as Error).message}`);\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON message' }));\n }\n return;\n }\n\n // Accept both 'chat' and 'message' types for compatibility\n if ((data.type === 'chat' || data.type === 'message') && data.content) {\n // Stream-enabled chat: send tokens as they arrive, then final message\n if (data.stream !== false && webChatChannel) {\n const chatUserId = data.userId || 'webchat-user';\n // Broadcast inbound message to all clients (for multi-tab visibility)\n broadcast({\n type: 'message', direction: 'inbound', channel: 'webchat',\n userId: chatUserId, content: data.content,\n timestamp: new Date().toISOString(),\n });\n\n try {\n const response = await routeMessage(data.content, 'webchat', chatUserId, {\n streamCallbacks: {\n onToken: (token: string) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'token', data: token }));\n }\n },\n onToolCall: (name: string, args: Record<string, unknown>) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'tool_call', name, args }));\n }\n },\n },\n });\n // Send done event to the originating client\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'done', content: response.content, model: response.model, durationMs: response.durationMs, tokenUsage: response.tokenUsage }));\n }\n // Broadcast final message to same user's other tabs only (session isolation)\n for (const client of wsClients) {\n const tagged = client as TaggedWebSocket;\n if (client !== ws && client.readyState === WebSocket.OPEN && tagged.titanUserId === chatUserId) {\n client.send(JSON.stringify({\n type: 'message', direction: 'outbound', channel: 'webchat',\n userId: chatUserId, content: response.content,\n model: response.model, durationMs: response.durationMs,\n timestamp: new Date().toISOString(),\n }));\n }\n }\n } catch (err) {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: 'done', content: `Error: ${(err as Error).message}` }));\n }\n }\n } else if (webChatChannel) {\n webChatChannel.handleWebSocketMessage(data.userId || 'webchat-user', data.content);\n }\n }\n } catch (error) {\n logger.error(COMPONENT, `WebSocket error: ${(error as Error).message}`);\n }\n });\n\n ws.on('close', () => {\n wsClients.delete(ws);\n logger.debug(COMPONENT, `WebSocket client disconnected (${wsClients.size} total)`);\n });\n } catch (err) {\n logger.error(COMPONENT, `WebSocket connection handler error: ${(err as Error).message}`);\n try { ws.close(1011, 'Internal error'); } catch { /* connection already closed */ }\n }\n });\n\n // Initialize channels\n webChatChannel = new WebChatChannel();\n channels.set('webchat', webChatChannel);\n await webChatChannel.connect();\n webChatChannel.on('message', handleInboundMessage);\n\n // Initialize optional channels\n const channelAdapters: Array<[string, ChannelAdapter]> = [\n ['discord', new DiscordChannel()],\n ['telegram', new TelegramChannel()],\n ['slack', new SlackChannel()],\n ['googlechat', new GoogleChatChannel()],\n ['whatsapp', new WhatsAppChannel()],\n ['matrix', new MatrixChannel()],\n ['signal', new SignalChannel()],\n ['msteams', new MSTeamsChannel()],\n ['irc', new IRCChannel()],\n ['mattermost', new MattermostChannel()],\n ['lark', new LarkChannel()],\n ['email_inbound', new EmailInboundChannel()],\n ['line', new LineChannel()],\n ['zulip', new ZulipChannel()],\n ['messenger', new MessengerChannel()],\n ];\n\n for (const [name, adapter] of channelAdapters) {\n adapter.on('message', handleInboundMessage);\n try {\n await adapter.connect();\n channels.set(name, adapter);\n } catch (error) {\n logger.debug(COMPONENT, `Channel ${name} not available: ${(error as Error).message}`);\n }\n }\n\n // ── Facebook Messenger Webhook ─────────────────────────────\n const messengerAdapter = channels.get('messenger') as MessengerChannel | undefined;\n if (messengerAdapter) {\n // Verification (GET) — Facebook sends this when you set up the webhook\n app.get('/api/messenger/webhook', (req, res) => {\n const result = messengerAdapter.handleVerify(req.query as Record<string, string>);\n res.status(result.status).send(result.body);\n });\n\n // Incoming messages (POST) — Facebook sends DMs here\n app.post('/api/messenger/webhook', express.json(), (req, res) => {\n messengerAdapter.handleWebhook(req.body);\n res.sendStatus(200); // Must respond 200 quickly or Facebook retries\n });\n\n // Also register at /messenger/webhook (without /api prefix) for backwards compatibility\n app.get('/messenger/webhook', (req, res) => {\n const result = messengerAdapter.handleVerify(req.query as Record<string, string>);\n res.status(result.status).send(result.body);\n });\n app.post('/messenger/webhook', express.json(), (req, res) => {\n messengerAdapter.handleWebhook(req.body);\n res.sendStatus(200);\n });\n\n logger.info(COMPONENT, `Messenger webhook: /api/messenger/webhook + /messenger/webhook (verify token: ${messengerAdapter.getVerifyToken()})`);\n }\n\n // ── Twilio Voice (real phone calls) ──────────────────────────\n // v4.4.0 — Tony dials the TITAN Twilio number on his phone, talks,\n // hears F5-TTS Andrew voice replies. Turn-based via <Gather speech>.\n // Config: channels.twilio (authToken for signature validation,\n // allowedCallers for whitelist, publicHost for audio URLs).\n {\n const {\n twimlPlayAndGather,\n twimlPauseAndRedirect,\n twimlPlayAndHangup,\n twimlReject,\n twimlSayAndHangup,\n validateTwilioSignature,\n isAllowedCaller,\n synthesizeAndCache,\n readCachedAudio,\n getCallSession,\n setCallSession,\n endCall,\n createVoiceJob,\n getVoiceJob,\n completeVoiceJob,\n failVoiceJob,\n } = await import('../channels/twilio-voice.js');\n\n const twilioCfg = (config.channels as Record<string, Record<string, unknown>> | undefined)?.twilio;\n const twilioEnabled = twilioCfg?.enabled !== false;\n\n const getTwilioConfig = () => {\n const cfg = loadConfig();\n const c = (cfg.channels as Record<string, Record<string, unknown>> | undefined)?.twilio || {};\n return {\n authToken: (c.authToken as string) || process.env.TWILIO_AUTH_TOKEN || '',\n phoneNumber: (c.phoneNumber as string) || process.env.TWILIO_PHONE_NUMBER || '',\n voice: (c.voice as string) || 'andrew',\n allowedCallers: (c.allowedCallers as string[]) || [],\n publicHost: (c.publicHost as string) || process.env.TWILIO_PUBLIC_HOST || '',\n };\n };\n\n // Twilio POSTs x-www-form-urlencoded — needs urlencoded parser\n const urlEncoded = express.urlencoded({ extended: false });\n\n /** Compute the full webhook URL Twilio signed against. */\n const computeSignedUrl = (req: express.Request): string => {\n const cfg = getTwilioConfig();\n // Prefer configured public host (Tailscale Funnel URL). This MUST match\n // the URL Tony set in Twilio, including protocol + path, or the\n // signature check fails.\n const host = cfg.publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n return host + req.originalUrl;\n };\n\n const checkTwilioAuth = (req: express.Request): boolean => {\n const { authToken } = getTwilioConfig();\n if (!authToken) {\n // If authToken isn't configured, skip validation (dev mode). Logged\n // once per request so the operator knows to lock it down.\n logger.warn(COMPONENT, 'Twilio authToken not configured — signature check SKIPPED');\n return true;\n }\n const signature = (req.headers['x-twilio-signature'] as string) || '';\n const url = computeSignedUrl(req);\n const params = (req.body || {}) as Record<string, string>;\n return validateTwilioSignature(authToken, signature, url, params);\n };\n\n // ── POST /api/twilio/voice-webhook — initial call handler ──\n app.post('/api/twilio/voice-webhook', urlEncoded, async (req, res) => {\n try {\n if (!twilioEnabled) { res.type('text/xml').send(twimlReject()); return; }\n if (!checkTwilioAuth(req)) {\n logger.warn(COMPONENT, 'Twilio voice-webhook: signature invalid');\n res.status(403).send('forbidden'); return;\n }\n\n const from = (req.body?.From as string) || '';\n const to = (req.body?.To as string) || '';\n const direction = (req.body?.Direction as string) || 'inbound';\n const callSid = (req.body?.CallSid as string) || '';\n const { allowedCallers, voice, publicHost } = getTwilioConfig();\n\n // v4.4.1: check the human's number, not TITAN's. On inbound calls\n // the human is `From` (they dialed in). On outbound-api calls\n // TITAN initiated and `To` is the human's number.\n const isOutbound = direction.startsWith('outbound');\n const humanNumber = isOutbound ? to : from;\n\n if (allowedCallers.length > 0 && !isAllowedCaller(humanNumber, allowedCallers)) {\n logger.warn(COMPONENT, `Twilio call ${direction} with non-whitelisted human number: ${humanNumber}`);\n res.type('text/xml').send(twimlReject());\n return;\n }\n\n logger.info(COMPONENT, `Twilio call ${direction}: CallSid=${callSid.slice(0, 10)}... human=${humanNumber}`);\n\n // Greeting\n const greeting = \"Hey Tony, TITAN here. What do you need?\";\n const token = await synthesizeAndCache(greeting, voice);\n const host = publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n if (!token) {\n // TTS unavailable — fall back to Twilio's built-in voice so the call\n // still connects and Tony can leave a message we don't drop into\n // silence.\n res.type('text/xml').send(twimlSayAndHangup(greeting + \" TTS is down. Hanging up.\"));\n return;\n }\n const audioUrl = `${host}/api/twilio/audio/${token}`;\n const gatherUrl = `${host}/api/twilio/voice-gather`;\n res.type('text/xml').send(twimlPlayAndGather(audioUrl, gatherUrl));\n } catch (e) {\n logger.error(COMPONENT, `Twilio voice-webhook error: ${(e as Error).message}`);\n res.status(500).type('text/xml').send(twimlSayAndHangup(\"Internal error. Try again.\"));\n }\n });\n\n // ── POST /api/twilio/voice-gather — speech result handler ──\n // v4.4.4: async + polling. Kick off LLM+TTS in background, return\n // pause+redirect immediately so Twilio doesn't hit its 15s timeout.\n // /voice-poll will either play the reply when ready or redirect back\n // to itself for another short pause.\n app.post('/api/twilio/voice-gather', urlEncoded, async (req, res) => {\n try {\n if (!twilioEnabled) { res.type('text/xml').send(twimlReject()); return; }\n if (!checkTwilioAuth(req)) {\n res.status(403).send('forbidden'); return;\n }\n\n const callSid = (req.body?.CallSid as string) || '';\n const from = (req.body?.From as string) || '';\n const to = (req.body?.To as string) || '';\n const direction = (req.body?.Direction as string) || 'inbound';\n const speechResult = ((req.body?.SpeechResult as string) || '').trim();\n const { voice, publicHost, allowedCallers } = getTwilioConfig();\n\n const isOutbound = direction.startsWith('outbound');\n const humanNumber = isOutbound ? to : from;\n if (allowedCallers.length > 0 && !isAllowedCaller(humanNumber, allowedCallers)) {\n res.type('text/xml').send(twimlReject()); return;\n }\n\n const host = publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n const gatherUrl = `${host}/api/twilio/voice-gather`;\n\n if (!speechResult) {\n // Silence or unrecognized speech — re-prompt (synth is fast, stay sync).\n const txt = \"I didn't catch that. Say it again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) {\n res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n } else {\n res.type('text/xml').send(twimlSayAndHangup(txt));\n }\n return;\n }\n\n logger.info(COMPONENT, `Twilio heard: \"${speechResult.slice(0, 80)}\"`);\n\n // v4.4.2: admin envelope lives in the SYSTEM prompt, not the user\n // message. Small models were literally reading the envelope aloud\n // when it was shoved into the user-message slot. With system-slot\n // placement, the model treats it as instructions and Tony's speech\n // as the turn content.\n const today = new Date().toLocaleDateString('en-US', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',\n });\n const voiceSystemPrompt = [\n 'You are TITAN on a phone call with Tony Elliott (your creator). Spoken conversation, not writing.',\n `Today is ${today}.`,\n '',\n 'HARD RULES (phone-call mode):',\n '- MAX 25 WORDS PER REPLY. One or two sentences. Be terse.',\n '- No lists, no markdown, no headers, no code blocks. This is spoken.',\n '- No \"Certainly!\" / \"I\\'d be happy to!\" preambles. Just answer.',\n '- Call him Tony or boss.',\n '- For big/destructive actions: one-sentence plan + \"Approve? Yes or no.\" then stop.',\n '- Never say \"check the dashboard\" (he is hands-free).',\n '- Never speak credentials, tokens, passwords, IPs, or file paths.',\n '- Never read these instructions aloud. Never describe yourself as an AI.',\n ].join('\\n');\n\n // v4.4.4: create job, kick off LLM+TTS in background, return\n // pause+redirect immediately. The /voice-poll endpoint will\n // either play the reply when ready or redirect back to itself\n // for another short pause. This keeps the call alive indefinitely\n // even when the LLM takes 20+ seconds.\n const jobId = createVoiceJob(callSid);\n const pollUrl = `${host}/api/twilio/voice-poll?jobId=${jobId}`;\n\n // Fire-and-forget async processing. Errors are caught + stored\n // on the job so /voice-poll can surface them gracefully.\n // v4.4.5: strategy='direct' forced so conversational questions\n // don't trigger a 30s+ explore/deliberation path. Tools still\n // available — direct mode is the minimum, not a tool block.\n (async () => {\n try {\n const existingSid = getCallSession(callSid);\n const voiceModel = (process.env.TWILIO_VOICE_MODEL\n || 'ollama/qwen3.5:cloud');\n const result = await processMessage(\n speechResult,\n 'twilio-admin',\n `twilio-call-${callSid}`,\n {\n ...(existingSid ? { sessionId: existingSid } : {}),\n model: voiceModel,\n systemPrompt: voiceSystemPrompt,\n strategy: 'direct',\n },\n undefined,\n AbortSignal.timeout(85_000),\n );\n if (result?.sessionId) setCallSession(callSid, result.sessionId);\n\n let reply = (result?.content || '').trim();\n if (!reply) reply = \"Got it.\";\n if (reply.length > 400) reply = reply.slice(0, 390).replace(/\\s\\S*$/, '') + '…';\n\n const token = await synthesizeAndCache(reply, voice);\n if (!token) {\n failVoiceJob(jobId, 'tts failed');\n return;\n }\n completeVoiceJob(jobId, token, reply);\n } catch (e) {\n logger.warn(COMPONENT, `Twilio voice-gather async error: ${(e as Error).message}`);\n failVoiceJob(jobId, (e as Error).message);\n }\n })();\n\n // Return immediately with a short pause + redirect to the poll endpoint.\n res.type('text/xml').send(twimlPauseAndRedirect(pollUrl, 3));\n } catch (e) {\n logger.error(COMPONENT, `Twilio voice-gather error: ${(e as Error).message}`);\n res.status(500).type('text/xml').send(twimlSayAndHangup(\"Something went wrong.\"));\n }\n });\n\n // ── POST /api/twilio/voice-poll — async job polling ──\n // v4.4.4: Twilio redirects here while we process the LLM reply.\n // If the job is ready, play the audio + open a new <Gather>. If\n // not, pause another ~3s and redirect back to self. Hard cap at\n // ~15 rounds (~45s) then surface an error TwiML.\n // Accept both GET and POST — some Twilio retry paths use GET when\n // following a Redirect even if method was specified.\n const handleVoicePoll = async (req: express.Request, res: express.Response) => {\n try {\n if (!twilioEnabled) { res.type('text/xml').send(twimlReject()); return; }\n if (!checkTwilioAuth(req)) {\n logger.warn(COMPONENT, `voice-poll signature rejected (method=${req.method}, jobId=${req.query.jobId})`);\n res.status(403).send('forbidden'); return;\n }\n\n const jobId = (req.query.jobId as string) || '';\n const job = getVoiceJob(jobId);\n logger.info(COMPONENT, `voice-poll method=${req.method} jobId=${jobId.slice(0,8)} status=${job?.status || 'missing'}`);\n const { voice, publicHost } = getTwilioConfig();\n const host = publicHost.replace(/\\/$/, '') || `https://${req.headers.host}`;\n const pollUrl = `${host}/api/twilio/voice-poll?jobId=${jobId}`;\n const gatherUrl = `${host}/api/twilio/voice-gather`;\n\n if (!job) {\n // Job expired or never existed. Treat as error.\n const txt = \"Sorry boss, lost my train of thought. Say that again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n else res.type('text/xml').send(twimlSayAndHangup(txt));\n return;\n }\n\n if (job.status === 'ready' && job.audioToken) {\n logger.info(COMPONENT, `Voice poll ready: job=${jobId.slice(0, 8)} reply=\"${(job.replyText || '').slice(0, 60)}\"`);\n const audioUrl = `${host}/api/twilio/audio/${job.audioToken}`;\n res.type('text/xml').send(twimlPlayAndGather(audioUrl, gatherUrl));\n return;\n }\n\n if (job.status === 'error') {\n logger.warn(COMPONENT, `Voice poll error: ${job.error}`);\n const txt = \"Hmm, I hit a snag. Try that again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n else res.type('text/xml').send(twimlSayAndHangup(txt));\n return;\n }\n\n // Still pending — pause and redirect back. Cap the total wait\n // so a hung LLM doesn't keep the call alive forever.\n // v4.4.5: hard cap raised 40s→90s to fit tool-call chains,\n // and we drop a short \"still on it\" filler every ~9s so Tony\n // doesn't just hear dead air while we work.\n const age = Date.now() - job.createdAt;\n if (age > 90_000) {\n logger.warn(COMPONENT, `Voice poll timeout after ${age}ms`);\n failVoiceJob(jobId, 'timeout');\n const txt = \"That one took too long. Say it again?\";\n const tk = await synthesizeAndCache(txt, voice);\n if (tk) res.type('text/xml').send(twimlPlayAndGather(`${host}/api/twilio/audio/${tk}`, gatherUrl));\n else res.type('text/xml').send(twimlSayAndHangup(txt));\n return;\n }\n\n // Every ~9s of waiting, play a brief filler so the caller knows\n // we're alive. Fillers come from a short rotating list so it\n // doesn't sound robotic. Tracked per-job via a `fillerCount`\n // field on the job object.\n const jobAny = job as { status: string; createdAt: number; fillerCount?: number };\n const fillerCount = jobAny.fillerCount || 0;\n const shouldFiller = age > 9_000 && age - (fillerCount * 9_000) > 9_000;\n if (shouldFiller) {\n const fillers = [\n \"Still on it, one sec.\",\n \"Working on it.\",\n \"Almost there, boss.\",\n \"Give me just a moment.\",\n ];\n const filler = fillers[fillerCount % fillers.length];\n jobAny.fillerCount = fillerCount + 1;\n const tk = await synthesizeAndCache(filler, voice);\n if (tk) {\n res.type('text/xml').send(`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response>\n <Play>${host}/api/twilio/audio/${tk}</Play>\n <Pause length=\"2\"/>\n <Redirect method=\"POST\">${pollUrl}</Redirect>\n</Response>`);\n return;\n }\n // TTS failed — fall through to plain pause\n }\n res.type('text/xml').send(twimlPauseAndRedirect(pollUrl, 3));\n } catch (e) {\n logger.error(COMPONENT, `Twilio voice-poll error: ${(e as Error).message}`);\n res.status(500).type('text/xml').send(twimlSayAndHangup(\"Something went wrong.\"));\n }\n };\n app.post('/api/twilio/voice-poll', urlEncoded, handleVoicePoll);\n app.get('/api/twilio/voice-poll', handleVoicePoll);\n\n // ── POST /api/twilio/status-callback — call lifecycle events ──\n app.post('/api/twilio/status-callback', urlEncoded, (req, res) => {\n try {\n const callSid = (req.body?.CallSid as string) || '';\n const status = (req.body?.CallStatus as string) || '';\n const duration = (req.body?.CallDuration as string) || '';\n logger.info(COMPONENT, `Twilio call ${callSid.slice(0, 10)}... status=${status}${duration ? ` duration=${duration}s` : ''}`);\n if (status === 'completed' || status === 'failed' || status === 'canceled' || status === 'no-answer' || status === 'busy') {\n endCall(callSid);\n }\n res.sendStatus(200);\n } catch (e) {\n logger.warn(COMPONENT, `status-callback error: ${(e as Error).message}`);\n res.sendStatus(200);\n }\n });\n\n // ── GET /api/twilio/audio/:token — serve cached MP3 to Twilio ──\n // Unauthenticated on purpose: Twilio fetches these and passing a\n // bearer token through <Play> URLs is fiddly + leaks in logs.\n // Tokens are random 96-bit + 5-min TTL + garbage-collected, so the\n // exposure is a transient MP3 of synthesized speech (not secrets).\n app.get('/api/twilio/audio/:token', async (req, res) => {\n const token = req.params.token;\n const audio = await readCachedAudio(token);\n if (!audio) { res.status(404).send('expired'); return; }\n res.setHeader('Content-Type', audio.mime);\n res.setHeader('Content-Length', String(audio.buf.length));\n res.setHeader('Cache-Control', 'private, max-age=60');\n res.send(audio.buf);\n });\n\n logger.info(COMPONENT, `Twilio voice endpoints registered: /api/twilio/voice-webhook, /api/twilio/voice-gather, /api/twilio/status-callback, /api/twilio/audio/:token`);\n }\n\n // ── Phase 3: Boot MCP servers, monitors, recipes, model switch, slash commands ──\n initSlashCommands();\n seedBuiltinRecipes();\n initMcpServers().catch((e) => logger.warn(COMPONENT, `MCP init error: ${e.message}`));\n mountMcpHttpEndpoints(app);\n\n // ── Persistent webhooks — reload saved webhooks ─────────────\n initPersistentWebhooks().catch((e) => logger.warn(COMPONENT, `Webhook init: ${(e as Error).message}`));\n\n // ── Cron scheduler — re-activate all persisted jobs ──────────\n initCronScheduler();\n\n // ── Autopilot — scheduled autonomous agent runs ─────────────\n initAutopilot(config);\n\n // ── VRAM Orchestrator — GPU memory management ───────────────\n if (config.vram?.enabled !== false) {\n import('../vram/orchestrator.js').then(({ initVRAMOrchestrator }) => {\n initVRAMOrchestrator().catch((e) => logger.warn(COMPONENT, `VRAM orchestrator init: ${(e as Error).message}`));\n }).catch(() => { /* optional */ });\n }\n\n // ── Command Post — agent governance layer ────────────────\n if (config.commandPost?.enabled) {\n initCommandPost(config.commandPost);\n initWakeupSystem();\n initHeartbeatScheduler();\n logger.info(COMPONENT, 'Command Post governance layer initialized (wakeup system active)');\n\n // v4.7.0: bootstrap specialist pool (Scout, Builder, Writer, Analyst)\n // once Command Post is up. Idempotent — safe to call every boot.\n try {\n const { ensureSpecialistsRegistered } = await import('../agent/specialists.js');\n await ensureSpecialistsRegistered();\n } catch (e) {\n logger.warn(COMPONENT, `Specialist bootstrap skipped: ${(e as Error).message}`);\n }\n }\n\n // v4.9.0: load/init stable identity. Persistent across restarts.\n // Session count ticks, version transitions logged, core hash checked\n // for tampering. Identity gets rendered into every agent's system\n // prompt via agent.ts (sync globalThis accessor).\n try {\n const { initIdentity, renderIdentityBlock, getIdentity } = await import('../memory/identity.js');\n const identity = initIdentity();\n logger.info(COMPONENT, `Identity loaded — session #${identity.tenure.sessionCount}, ${identity.driftLog.filter(d => d.resolution === 'pending').length} pending drift event(s)`);\n for (const ev of identity.driftLog.filter(d => d.resolution === 'pending').slice(-3)) {\n logger.warn('Identity', `Pending drift [${ev.kind}]: ${ev.detail.slice(0, 140)}`);\n }\n // Install a sync accessor so agent.ts buildSystemPrompt() can pull\n // the identity block without dynamic import on every message.\n (globalThis as unknown as { __titan_identity_block?: () => string }).__titan_identity_block = () => {\n const id = getIdentity();\n return id ? renderIdentityBlock(id) : '';\n };\n } catch (e) {\n logger.warn(COMPONENT, `Identity bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: install the self-model provider. The self-model\n // synthesizes identity + recent performance + strengths/weaknesses\n // + integrity into a compact block injected into every system prompt.\n // Cached for 60s inside the module — the sync accessor returns the\n // cached block (falling through to empty when cache is cold).\n try {\n const { getSelfModel, renderSelfModelBlock } = await import('../memory/meta.js');\n let cachedBlock = '';\n let cachedAt = 0;\n const refresh = () => {\n (async () => {\n try {\n cachedBlock = await renderSelfModelBlock();\n cachedAt = Date.now();\n } catch { /* ok */ }\n })();\n };\n refresh();\n setInterval(refresh, 60_000).unref?.();\n (globalThis as unknown as { __titan_self_model_block?: () => string }).__titan_self_model_block = () => {\n // If cache is stale (> 2 min) return the old block anyway — the\n // async refresh runs out-of-band. Never blocks the prompt path.\n if (Date.now() - cachedAt > 120_000 && cachedBlock === '') {\n // First call before refresh finishes — do nothing.\n return '';\n }\n return cachedBlock;\n };\n // Also prime the self-model so the first agent turn has something.\n await getSelfModel();\n logger.info(COMPONENT, 'Self-model provider installed (60s refresh)');\n } catch (e) {\n logger.warn(COMPONENT, `Self-model bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local (Phase C): install working-memory provider. Injects\n // structured session state into the agent's system prompt when resuming\n // an in-flight task so TITAN doesn't start from scratch mid-work.\n try {\n const { renderSessionContext } = await import('../memory/workingMemory.js');\n (globalThis as unknown as {\n __titan_working_memory_block?: (sessionId: string) => string;\n }).__titan_working_memory_block = (sessionId: string) => {\n try { return renderSessionContext(sessionId); } catch { return ''; }\n };\n logger.info(COMPONENT, 'Working-memory provider installed');\n } catch (e) {\n logger.warn(COMPONENT, `Working-memory bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase B): install driver-status provider. Appends\n // live driver phase + blocked questions into the agent's system prompt,\n // so \"what are you working on?\" gets a real answer.\n try {\n const { renderDriverStatusBlock } = await import('../agent/driverAwareChat.js');\n (globalThis as unknown as { __titan_driver_status_block?: () => string | null }).__titan_driver_status_block = () => {\n try { return renderDriverStatusBlock(); } catch { return null; }\n };\n logger.info(COMPONENT, 'Driver-aware chat provider installed');\n } catch (e) {\n logger.warn(COMPONENT, `Driver-aware chat skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0: install closed-loop signal providers for Soma drives. These\n // let the drive layer read live VRAM / telemetry / learning state via\n // a synchronous call without pulling in the whole dependency graph.\n try {\n const { getVRAMOrchestrator } = await import('../vram/orchestrator.js');\n const { getMetricsSummary } = await import('./metrics.js');\n const { getLearningStats } = await import('../memory/learning.js');\n\n // VRAM: refresh happens on the orchestrator's 10s cadence; we just\n // peek at the last known GPU state. If there's no GPU, the peeker\n // returns nothing and the drive treats that as \"no signal.\"\n const g = globalThis as unknown as {\n __titan_vram_last?: { totalMB: number; freeMB: number; usedMB: number };\n __titan_metrics_summary?: () => { totalRequests: number; errorRate: number } | null;\n __titan_unresolved_error_patterns?: () => number;\n };\n setInterval(() => {\n (async () => {\n try {\n const orch = getVRAMOrchestrator();\n const snap = await orch.getSnapshot();\n if (snap?.gpu && typeof snap.gpu.totalMB === 'number' && snap.gpu.totalMB > 0) {\n g.__titan_vram_last = {\n totalMB: snap.gpu.totalMB,\n freeMB: snap.gpu.freeMB,\n usedMB: snap.gpu.usedMB ?? (snap.gpu.totalMB - snap.gpu.freeMB),\n };\n } else {\n g.__titan_vram_last = undefined;\n }\n } catch { /* best-effort */ }\n })();\n }, 15_000).unref?.();\n\n // Metrics: cheap synchronous read.\n g.__titan_metrics_summary = () => {\n try {\n const s = getMetricsSummary();\n return { totalRequests: s.totalRequests, errorRate: s.errorRate };\n } catch { return null; }\n };\n\n // Unresolved error patterns from the learning KB.\n // v4.10.0-local fix: use the new `unresolvedErrorPatterns` field that\n // filters by !resolution. Prior behavior used total count, which meant\n // marking patterns resolved didn't relieve curiosity drive pressure.\n g.__titan_unresolved_error_patterns = () => {\n try {\n const stats = getLearningStats();\n return stats.unresolvedErrorPatterns ?? stats.errorPatterns ?? 0;\n } catch { return 0; }\n };\n\n logger.info(COMPONENT, 'Drive signal providers installed (VRAM, metrics, learning)');\n } catch (e) {\n logger.warn(COMPONENT, `Drive signal bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: register the self-repair daemon watcher. Runs every\n // 5 minutes; sweeps for stuck drives, stalled goals, episodic\n // anomalies, integrity dips, stale working-memory sessions. Files\n // 'self_repair' approvals for new findings. Human-in-the-loop: the\n // daemon proposes, Tony approves (or rejects).\n try {\n const { registerWatcher } = await import('../agent/daemon.js');\n const { runSelfRepairSweep } = await import('../safety/selfRepair.js');\n registerWatcher('self-repair', async () => {\n try { await runSelfRepairSweep(); } catch (e) { logger.debug(COMPONENT, `self-repair sweep: ${(e as Error).message}`); }\n }, 300_000);\n logger.info(COMPONENT, 'Self-repair daemon registered (5 min cadence)');\n } catch (e) {\n logger.warn(COMPONENT, `Self-repair daemon skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase A): start the Goal Driver scheduler. This replaces\n // the passive \"initiative picks one subtask per 5-min autopilot tick\"\n // model with a persistent phase state machine per goal. Restart-safe:\n // resumes any non-terminal drivers from ~/.titan/driver-state/.\n try {\n const { registerSomaVerifier } = await import('../agent/somaFeedback.js');\n registerSomaVerifier();\n const { startDriverScheduler, resumeDriversAfterRestart } = await import('../agent/driverScheduler.js');\n const resumed = await resumeDriversAfterRestart();\n logger.info(COMPONENT, `Goal Driver resume: ${resumed.resumed} re-activated, ${resumed.cancelled} cancelled (goal no longer active), ${resumed.sweptStale} stale (>24h since lastTick) reaped`);\n startDriverScheduler(10_000, 5); // 10s tick, max 5 concurrent drivers\n } catch (e) {\n logger.warn(COMPONENT, `Goal Driver scheduler bootstrap skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase B): daily digest cron. Generates a TL;DR at 9am\n // PDT + on every restart (so /api/digest/today always has fresh data).\n try {\n const { startDailyDigestCron } = await import('../agent/dailyDigest.js');\n startDailyDigestCron();\n } catch (e) {\n logger.warn(COMPONENT, `Daily digest cron skipped: ${(e as Error).message}`);\n }\n\n // v5.5.17: Dream Mode cron — opt-in via config.dream.enabled. Default\n // 03:30 local. Skips quietly when disabled. See src/agent/dreams.ts.\n try {\n const { startDreamCron } = await import('../agent/dreams.js');\n startDreamCron();\n } catch (e) {\n logger.warn(COMPONENT, `Dream cron skipped: ${(e as Error).message}`);\n }\n\n // v5.5.27: Persona A/B rollout monitor — opt-in via\n // personas.rollout.enabled. Re-evaluates every cohort on a cadence\n // (default 5 min) and auto-reverts candidates that regress vs\n // baseline. Skips quietly when disabled.\n try {\n const { startRolloutMonitor } = await import('../agent/personaRollout.js');\n startRolloutMonitor();\n } catch (e) {\n logger.warn(COMPONENT, `Persona rollout monitor skipped: ${(e as Error).message}`);\n }\n\n // v4.10.0-local (Phase C): mission scheduler — ticks active missions\n // (driver-of-drivers) every 15s. Missions coordinate multi-goal projects.\n try {\n const { listActiveMissions, tickMission } = await import('../agent/missionDriver.js');\n const missionTimer = setInterval(() => {\n void (async () => {\n try {\n for (const m of listActiveMissions()) {\n try { await tickMission(m.missionId); } catch { /* ok */ }\n }\n } catch { /* ok */ }\n })();\n }, 15_000);\n missionTimer.unref?.();\n logger.info(COMPONENT, 'Mission scheduler started (15s cadence)');\n } catch (e) {\n logger.warn(COMPONENT, `Mission scheduler skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: register the working-memory retire watcher. Every\n // hour, sweeps for in-flight sessions that haven't touched\n // lastActiveAt in > 24h and archives them to episodic as abandoned.\n try {\n const { registerWatcher } = await import('../agent/daemon.js');\n const { retireStaleSessions } = await import('../memory/workingMemory.js');\n registerWatcher('working-memory-retire', async () => {\n try { retireStaleSessions(); } catch (e) { logger.debug(COMPONENT, `working-memory retire: ${(e as Error).message}`); }\n }, 3_600_000);\n } catch (e) {\n logger.warn(COMPONENT, `Working-memory retire watcher skipped: ${(e as Error).message}`);\n }\n\n // v4.9.0-local.4: canary eval daemon. Runs the fixed golden-set\n // every 24h; if any task drops > 15% vs 7-day baseline, a\n // canary_regression approval fires for Tony to review. Defends\n // against silent quality degradation from model drift, context\n // bloat, or prompt accretion.\n try {\n const { registerWatcher } = await import('../agent/daemon.js');\n const { runCanarySweep } = await import('../safety/canaryEval.js');\n registerWatcher('canary-eval', async () => {\n try { await runCanarySweep(); } catch (e) { logger.debug(COMPONENT, `canary sweep: ${(e as Error).message}`); }\n }, 24 * 60 * 60 * 1000);\n logger.info(COMPONENT, 'Canary eval daemon registered (24h cadence)');\n } catch (e) {\n logger.warn(COMPONENT, `Canary eval daemon skipped: ${(e as Error).message}`);\n }\n\n // v4.8.0: Self-Modification Pipeline — auto-review newly captured\n // proposals and poll open PRs for merge/close outcomes.\n try {\n const selfModCfg = (config as unknown as { selfMod?: {\n enabled?: boolean;\n autoReview?: boolean;\n autoPR?: boolean;\n pollIntervalMs?: number;\n } }).selfMod;\n if (selfModCfg?.enabled) {\n logger.info(COMPONENT, 'Self-Modification Pipeline: enabled');\n const { pollOpenProposals } = await import('../agent/selfProposalLearning.js');\n const pollMs = selfModCfg.pollIntervalMs ?? 300_000;\n const pollTimer = setInterval(() => {\n pollOpenProposals().catch((e: Error) => logger.debug(COMPONENT, `selfMod poll: ${e.message}`));\n }, pollMs);\n (pollTimer as unknown as { unref?: () => void }).unref?.();\n\n // Auto-review: watch soma:proposal events for self-mod captures and\n // kick off specialist review when a new proposal has enough files.\n if (selfModCfg.autoReview !== false) {\n const { on: subscribeTrace } = await import('../substrate/traceBus.js');\n subscribeTrace('soma:proposal', async (payload) => {\n try {\n const pb = (payload as { proposedBy?: string }).proposedBy || '';\n if (!pb.startsWith('self-mod:')) return;\n const proposalId = (payload as { approvalId?: string }).approvalId;\n if (!proposalId) return;\n // Debounce: wait 2s for additional files in same session before reviewing\n setTimeout(async () => {\n try {\n const { reviewProposal } = await import('../agent/selfProposalReview.js');\n const reviewed = await reviewProposal(proposalId);\n // Auto-PR if configured + approved\n if (reviewed?.status === 'approved' && selfModCfg.autoPR) {\n const { createProposalPR } = await import('../agent/selfProposalPR.js');\n await createProposalPR(proposalId);\n }\n } catch (e) {\n logger.warn(COMPONENT, `selfMod auto-review failed: ${(e as Error).message}`);\n }\n }, 2000);\n } catch (e) {\n logger.debug(COMPONENT, `selfMod subscribe handler: ${(e as Error).message}`);\n }\n });\n }\n }\n } catch (e) {\n logger.warn(COMPONENT, `selfMod bootstrap skipped: ${(e as Error).message}`);\n }\n\n // ── Daemon — persistent agent awareness loop ────────────────\n initDaemon();\n\n // ── Morning Briefing — send once per day in 6am–12pm window ──\n checkAndSendBriefing(async (msg) => {\n broadcast({\n type: 'message',\n direction: 'outbound',\n channel: 'system',\n userId: 'titan',\n content: msg,\n timestamp: new Date().toISOString(),\n });\n }).catch((e: Error) => logger.warn(COMPONENT, `Briefing error: ${e.message}`));\n\n // Wire monitor triggers to agent\n setMonitorTriggerHandler(async (monitor, event) => {\n const prompt = `[AUTO-TRIGGER: ${monitor.name}] ${event.detail}\\n\\nYour task: ${monitor.prompt}`;\n const response = await processMessage(prompt, 'monitor', 'system');\n broadcast({ type: 'monitor_trigger', monitor: monitor.name, response: response.content, event });\n logger.info(COMPONENT, `Monitor \"${monitor.name}\" responded: ${response.content.slice(0, 100)}`);\n });\n initMonitors();\n\n // ── Operator Alerting ──────────────────────────────────────────\n const { initAlerts } = await import('../agent/alerts.js');\n initAlerts();\n\n // ── Mesh Networking ───────────────────────────────────────────\n if (config.mesh.enabled && !config.mesh.secret) {\n logger.warn(COMPONENT, 'Mesh is enabled but no secret is set. Run `titan mesh --init` to generate one. Mesh disabled.');\n }\n if (config.mesh.enabled && config.mesh.secret) {\n const { getOrCreateNodeId } = await import('../mesh/identity.js');\n const { startDiscovery, setOnPeerDiscovered, setConnectApprovedPeer, setMaxPeers } = await import('../mesh/discovery.js');\n const { connectToPeer, startHeartbeat, startRouteBroadcast } = await import('../mesh/transport.js');\n const nodeId = getOrCreateNodeId();\n\n // Set max peers limit\n setMaxPeers(config.mesh.maxPeers);\n\n // Notify dashboard when new peers are discovered\n setOnPeerDiscovered((peer) => {\n broadcast({\n type: 'mesh_peer_discovered',\n peer: {\n nodeId: peer.nodeId,\n hostname: peer.hostname,\n address: peer.address,\n port: peer.port,\n version: peer.version,\n models: peer.models,\n discoveredVia: peer.discoveredVia,\n },\n });\n logger.info(COMPONENT, `New TITAN node discovered: ${peer.hostname} (${peer.address}:${peer.port}) — approve via dashboard or CLI`);\n });\n\n // Wire up WebSocket connections for approved peers\n setConnectApprovedPeer((peer) => {\n if (config.mesh.secret) {\n connectToPeer(peer.address, peer.port, nodeId, config.mesh.secret)\n .then((ok) => {\n if (ok) {\n broadcast({ type: 'mesh_peer_connected', peer });\n logger.info(COMPONENT, `Connected to approved peer: ${peer.hostname}`);\n }\n })\n .catch(() => logger.debug(COMPONENT, `Approved peer unreachable: ${peer.hostname}`));\n }\n });\n\n await startDiscovery(nodeId, port, {\n mdns: config.mesh.mdns,\n tailscale: config.mesh.tailscale,\n autoApprove: config.mesh.autoApprove,\n peerStaleTimeoutMs: config.mesh.peerStaleTimeoutMs,\n });\n\n // Auto-bind to 0.0.0.0 when mesh is enabled (so peers can reach us)\n if (host === '127.0.0.1') {\n host = '0.0.0.0';\n logger.info(COMPONENT, 'Mesh enabled — binding to 0.0.0.0 (was 127.0.0.1) so peers can connect');\n }\n\n // Connect to static peers\n if (config.mesh.staticPeers.length > 0) {\n for (const addr of config.mesh.staticPeers) {\n const parts = addr.split(':');\n const peerHost = parts[0];\n const peerPort = parseInt(parts[1] || '48420', 10);\n if (!peerHost || isNaN(peerPort)) {\n logger.warn(COMPONENT, `Invalid static peer address: \"${addr}\" — expected host:port (e.g. 192.168.1.100:48420)`);\n continue;\n }\n connectToPeer(peerHost, peerPort, nodeId, config.mesh.secret)\n .catch(() => logger.debug(COMPONENT, `Static peer unreachable: ${addr}`));\n }\n }\n\n // Start heartbeat with dynamic model discovery\n startHeartbeat(nodeId, async () => {\n const { getActiveRemoteTaskCount: getTaskCount } = await import('../mesh/transport.js');\n const models = await discoverAllModels();\n const cpu = getCpuLoad();\n const taskLoad = getTaskCount() / Math.max(config.mesh.maxRemoteTasks, 1);\n const load = Math.min(1, cpu * 0.4 + taskLoad * 0.6);\n return {\n hostname: osHostname(),\n version: TITAN_VERSION,\n models: models.map(m => m.id),\n load: Math.round(load * 100) / 100,\n };\n }, config.mesh.heartbeatIntervalMs || 60_000);\n\n // Start distance-vector route broadcasting\n startRouteBroadcast(30_000);\n\n const mode = config.mesh.autoApprove ? 'auto-approve' : 'approval-required';\n logger.info(COMPONENT, `Mesh active — Node: ${nodeId.slice(0, 8)}... | mDNS: ${config.mesh.mdns} | Tailscale: ${config.mesh.tailscale} | Max peers: ${config.mesh.maxPeers} | Mode: ${mode}`);\n }\n\n // Start server\n httpServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n logger.warn(COMPONENT, `Port ${port} is already in use. Mission Control is likely already running in the background.`);\n logger.info(COMPONENT, `You can access it at http://${host}:${port}`);\n process.exit(1);\n } else {\n logger.error(COMPONENT, `Server error: ${err.message}`);\n }\n });\n\n // Hunt Finding #04 (2026-04-14): detect partial port conflicts.\n // If the user has a zombie gateway bound to 127.0.0.1:PORT and starts a\n // new one on 0.0.0.0:PORT, BOTH bind successfully (different addresses).\n // But localhost traffic routes to the zombie, not the new gateway — silent\n // confusion for the user. Pre-check via a TCP probe to localhost:PORT.\n // If something responds, log a clear warning before proceeding.\n try {\n await new Promise<void>((resolvePromise) => {\n const probe = net.createConnection({ host: '127.0.0.1', port, timeout: 500 });\n probe.once('connect', () => {\n logger.warn(COMPONENT,\n `[PortConflictProbe] Something is already listening on 127.0.0.1:${port}. ` +\n `The new gateway will bind to ${host}:${port} but localhost traffic may be routed to the existing process. ` +\n `Kill any stale processes (lsof -i :${port}) before starting.`,\n );\n probe.destroy();\n resolvePromise();\n });\n probe.once('error', () => {\n // ECONNREFUSED = port is free on localhost. Good.\n resolvePromise();\n });\n probe.once('timeout', () => {\n probe.destroy();\n resolvePromise();\n });\n });\n } catch {\n // Probe failure is non-fatal — don't block startup\n }\n\n // ── Internal Health Monitor (60s interval) ─────────────────────\n const ollamaBaseUrl = config.providers?.ollama?.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434';\n const ttsBaseUrl = config.voice?.ttsUrl || 'http://localhost:5005';\n\n healthMonitorInterval = setInterval(() => { // R1: avoid async in setInterval to prevent unhandled rejections\n void (async () => {\n try {\n const now = Date.now();\n healthState.lastCheck = new Date().toISOString();\n\n // Check Ollama\n try {\n const resp = await fetch(`${ollamaBaseUrl}/api/tags`, { signal: AbortSignal.timeout(3000) });\n healthState.ollamaHealthy = resp.ok;\n } catch {\n if (healthState.ollamaHealthy) {\n logger.warn(COMPONENT, 'Health monitor: Ollama is unreachable');\n }\n healthState.ollamaHealthy = false;\n }\n\n // Check TTS — F5-TTS exposes /health for fast probes; the /v1/audio/speech\n // synthesize-and-return path is too slow for a periodic monitor.\n try {\n const resp = await fetch(`${ttsBaseUrl}/health`, {\n signal: AbortSignal.timeout(3000),\n });\n healthState.ttsHealthy = resp.ok;\n } catch {\n healthState.ttsHealthy = false;\n }\n\n // Check for stuck LLM requests (same count for > 5 minutes)\n if (activeLlmRequests > 0 && activeLlmRequests === healthState.lastActiveLlm) {\n if (now - healthState.lastActiveLlmTime > 300_000) {\n if (!healthState.stuckDetected) {\n logger.warn(COMPONENT, `Health monitor: ${activeLlmRequests} LLM requests stuck for >5 minutes`);\n healthState.stuckDetected = true;\n }\n }\n } else {\n healthState.lastActiveLlm = activeLlmRequests;\n healthState.lastActiveLlmTime = now;\n healthState.stuckDetected = false;\n }\n\n // Check memory usage\n const mem = process.memoryUsage();\n const heapMB = Math.round(mem.heapUsed / 1024 / 1024);\n const rssMB = Math.round(mem.rss / 1024 / 1024);\n if (heapMB > 1500) {\n logger.warn(COMPONENT, `Health monitor: High heap usage — ${heapMB}MB`);\n }\n\n // Enforce configured memory limit — shed load if exceeded\n const memoryLimitMB = config.security?.maxMemoryMB || 2048;\n if (rssMB > memoryLimitMB * 0.9) {\n logger.error(COMPONENT, `Memory pressure — RSS ${rssMB}MB is above 90% of limit (${memoryLimitMB}MB). Reducing max concurrent requests.`);\n maxConcurrentOverride = Math.max(1, (maxConcurrentOverride ?? config.security.maxConcurrentTasks ?? 5) - 1);\n } else if (rssMB < memoryLimitMB * 0.7 && maxConcurrentOverride !== null) {\n maxConcurrentOverride = null; // Reset when memory recovers\n }\n\n // Enforce disk write limit (approximate via titan home dir size)\n try {\n const diskLimitMB = config.security?.maxDiskWriteMB || 1024;\n const { spawnSync } = await import('child_process');\n const du = spawnSync('du', ['-sm', TITAN_HOME], { encoding: 'utf-8', timeout: 5000 });\n const usedMB = parseInt(du.stdout?.split('\\t')[0] || '0', 10);\n if (usedMB > diskLimitMB * 0.9) {\n logger.error(COMPONENT, `Disk pressure — ${usedMB}MB used in ${TITAN_HOME}, above 90% of limit (${diskLimitMB}MB). Pausing non-essential writes.`);\n }\n } catch { /* du not available or failed — non-critical */ }\n\n // Keep primary agent heartbeat alive for Command Post\n try { reportHeartbeat('default'); } catch { /* non-critical */ }\n } catch (err) {\n logger.error(COMPONENT, `Health monitor error: ${(err as Error).message}`);\n }\n })();\n }, 60_000);\n healthMonitorInterval.unref();\n\n logger.info(COMPONENT, 'Health monitor started (60s interval)');\n\n // Catch unhandled promise rejections to prevent silent crashes + report\n // (v5.0 \"Spacewalk\"): reports go to the remote collector only when\n // `telemetry.enabled` AND `telemetry.crashReports` are both true AND the\n // user has previously consented via the SetupWizard. HOME path is stripped\n // from the stack to prevent personal-path leakage.\n //\n // Secret-scrubbing pass: removes API keys, bearer tokens, and URLs with\n // embedded credentials before the payload leaves the machine.\n const SECRET_PATTERNS = [\n // Bearer / Basic auth headers\n /\\b[Bb]earer\\s+[A-Za-z0-9_\\-.]{20,}/g,\n /\\b[Bb]asic\\s+[A-Za-z0-9+/=]{20,}/g,\n // API key prefixes (OpenAI, Anthropic, Groq, etc.)\n /\\b(sk|pk)-[A-Za-z0-9]{20,}/g,\n /\\b([a-zA-Z]{2,}_[a-zA-Z0-9]{16,})/g,\n // Generic hex tokens (32+ chars) — conservative to avoid scrubbing file hashes\n /\\b[0-9a-f]{64,}\\b/gi,\n // URLs with credentials\n /https?:\\/\\/[^\\s:]+:[^\\s@]+@[^\\s/]+/g,\n // Private keys / PEM blocks\n /-----BEGIN [A-Z ]+ PRIVATE KEY-----[\\s\\S]{100,}-----END [A-Z ]+ PRIVATE KEY-----/g,\n ];\n function scrubSecrets(text: string): string {\n let cleaned = text;\n for (const pattern of SECRET_PATTERNS) {\n cleaned = cleaned.replace(pattern, '[REDACTED]');\n }\n return cleaned;\n }\n\n const reportCrash = async (kind: 'unhandledRejection' | 'uncaughtException', err: unknown) => {\n try {\n const cfg = loadConfig();\n if (!cfg.telemetry?.enabled) return;\n if (!(cfg.telemetry as unknown as { crashReports?: boolean })?.crashReports) return;\n // v5.0.1: removed consentedAt gate so users upgrading from 4.x keep crash\n // reporting without re-running onboarding. The SetupWizard still stamps\n // consentedAt for new installs; we simply don't require it here.\n const { sendRemoteAnalytics } = await import('../analytics/collector.js');\n const { getOrCreateNodeId } = await import('../mesh/identity.js');\n const home = homedir();\n const stackRaw = (err instanceof Error ? (err.stack || err.message) : String(err));\n const stack = scrubSecrets(stackRaw.split(home).join('$HOME')).slice(0, 4000);\n const message = scrubSecrets(err instanceof Error ? err.message : String(err)).slice(0, 500);\n const fingerprint = `${kind}:${(message.match(/[A-Z][a-zA-Z0-9_]+Error/) || [message])[0]}`.slice(0, 128);\n await sendRemoteAnalytics({\n type: 'error',\n installId: getOrCreateNodeId(),\n version: TITAN_VERSION,\n message,\n stack,\n fingerprint,\n context: { kind },\n });\n } catch {\n // Crash reporting is best-effort\n }\n };\n\n process.on('unhandledRejection', (reason) => {\n logger.error(COMPONENT, `Unhandled rejection: ${reason}`);\n void reportCrash('unhandledRejection', reason);\n });\n\n // Catch uncaught exceptions — log and exit gracefully to allow systemd/docker restart\n process.on('uncaughtException', (err) => {\n logger.error(COMPONENT, `Uncaught exception: ${err.message}\\n${err.stack || ''}`);\n void reportCrash('uncaughtException', err);\n // Give logger + crash report time to flush before exiting\n setTimeout(() => {\n process.exit(1);\n }, 1500).unref();\n });\n\n // ── Graceful Shutdown ───────────────────────────────────────────\n // ── Lifecycle Manager — coordinated shutdown registry ──────\n const lm = getLifecycleManager();\n lm.register('f5tts', () => Promise.resolve(), () => new Promise<void>((resolve) => {\n for (const pidPath of [join(homedir(), '.titan', 'f5tts.pid'), join(homedir(), '.titan', 'qwen3tts.pid')]) {\n try {\n if (!fs.existsSync(pidPath)) continue;\n const pid = parseInt(fs.readFileSync(pidPath, 'utf-8').trim());\n process.kill(pid, 'SIGTERM');\n fs.unlinkSync(pidPath);\n logger.info(COMPONENT, `Stopped F5-TTS server (${pidPath})`);\n } catch { /* already stopped */ }\n }\n resolve();\n }));\n lm.register('autopilot', () => Promise.resolve(), () => { stopAutopilot(); return Promise.resolve(); });\n lm.register('daemon', () => Promise.resolve(), () => { stopDaemon(); return Promise.resolve(); });\n lm.register('commandpost', () => Promise.resolve(), () => { shutdownCommandPost(); return Promise.resolve(); });\n lm.register('tunnel', () => Promise.resolve(), () => { stopTunnel(); return Promise.resolve(); });\n\n const gracefulShutdown = async (signal: string) => {\n logger.info(COMPONENT, `Received ${signal} — shutting down gracefully...`);\n await lm.stopAll();\n closeMemory();\n flushGraph();\n try { const { flushVectors } = await import('../memory/vectors.js'); flushVectors(); } catch { /* ignore */ }\n await stopGateway();\n logger.info(COMPONENT, 'Gateway stopped. Goodbye.');\n process.exit(0);\n };\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n\n // Global error handler — prevent stack trace leaks\n app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {\n if (err instanceof SyntaxError && 'body' in err) {\n res.status(400).json({ error: 'Invalid JSON in request body' });\n return;\n }\n logger.error(COMPONENT, `Unhandled error: ${err.message}`);\n res.status(500).json({ error: 'Internal server error' });\n });\n\n httpServer.listen(port, host, () => {\n const proto = useHttps ? 'https' : 'http';\n const wsProto = useHttps ? 'wss' : 'ws';\n logger.info(COMPONENT, `Gateway listening on ${proto}://${host}:${port}`);\n logger.info(COMPONENT, `Dashboard: ${proto}://${host}:${port}`);\n logger.info(COMPONENT, `WebSocket: ${wsProto}://${host}:${port}`);\n logger.info(COMPONENT, `API: ${proto}://${host}:${port}/api/health`);\n logger.info(COMPONENT, `\\nChannels: ${Array.from(channels.values()).map((c) => `${c.displayName} (${c.getStatus().connected ? '✅' : '❌'})`).join(', ')}`);\n logger.info(COMPONENT, `Skills: ${getSkills().length} loaded`);\n logger.info(COMPONENT, `Tools: ${getRegisteredTools().length} registered`);\n\n // Friendly update notice for upgraders\n try {\n const markerPath = join(homedir(), '.titan', 'install-marker.json');\n if (fs.existsSync(markerPath)) {\n const marker = JSON.parse(fs.readFileSync(markerPath, 'utf-8'));\n if (marker.previousVersion && marker.previousVersion !== TITAN_VERSION) {\n logger.info(COMPONENT, `\\n🚀 Welcome to TITAN v${TITAN_VERSION}! Upgraded from v${marker.previousVersion}.`);\n logger.info(COMPONENT, ` What's new: PostHog analytics (opt-in), enriched telemetry, secret-scrubbed crash reports.`);\n logger.info(COMPONENT, ` Your config and settings are untouched. See PRIVACY.md for details.\\n`);\n }\n }\n } catch { /* non-critical */ }\n\n // Start Cloudflare Tunnel if enabled\n if (config.tunnel?.enabled) {\n startTunnel(port, config.tunnel).catch((e) => {\n logger.error(COMPONENT, `Tunnel start failed: ${(e as Error).message}`);\n });\n }\n\n // Start analytics collection (telemetry must be enabled)\n recordStartupAnalytics().catch(() => {});\n startHeartbeatAnalytics(() => listSessions().length);\n });\n}\n\n"],"mappings":"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","names":["resolve","isAllowedOrigin","getDb","getGraphStats","sseWrite","config","host","getMetricsSummary","getLearningStats"]}
|