titan-agent 6.0.0 → 6.0.2
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/agent/somaInitiative.js +69 -10
- package/dist/agent/somaInitiative.js.map +1 -1
- package/dist/config/schema.js +11 -17
- package/dist/config/schema.js.map +1 -1
- package/dist/gateway/routes/agents.js +7 -2
- package/dist/gateway/routes/agents.js.map +1 -1
- package/dist/gateway/server.js +8 -0
- package/dist/gateway/server.js.map +1 -1
- package/dist/providers/defaultModel.js +140 -0
- package/dist/providers/defaultModel.js.map +1 -0
- package/dist/providers/router.js +3 -2
- 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\n/**\n * Session-token TTL — configurable via `gateway.auth.tokenTtlMs`.\n * Pre-v5.7.2 this was hardcoded to 24h, which silently expired Tony's\n * sessions overnight and (combined with the cleanup timer) wiped\n * auth-tokens.json to `[]`. Default is now 30 days for self-hosted use.\n */\nfunction getAuthTokenTtlMs(): number {\n try {\n const cfg = loadConfig();\n const v = cfg.gateway?.auth?.tokenTtlMs;\n if (typeof v === 'number' && v > 0) return v;\n } catch { /* fall through */ }\n return 30 * 24 * 60 * 60 * 1000; // 30 days\n}\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 = getAuthTokenTtlMs();\n const now = Date.now();\n let dropped = 0;\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 } else {\n dropped++;\n }\n }\n }\n if (dropped > 0) {\n logger.info(COMPONENT, `[Auth] Dropped ${dropped} expired session token(s) at boot (TTL: ${Math.round(ttlMs / 3600_000)}h).`);\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.\n// Pre-v5.7.2 this used a hardcoded 24h TTL which clobbered auth-tokens.json\n// to `[]` overnight on self-hosted single-user TITANs. Now reads the\n// configured `gateway.auth.tokenTtlMs` (default 30 days).\ntokenCleanupInterval = setInterval(() => {\n const now = Date.now();\n const ttlMs = getAuthTokenTtlMs();\n let purged = 0;\n for (const [tok, entry] of authTokens) {\n if (now - entry.createdAt > ttlMs) { authTokens.delete(tok); purged++; }\n }\n // Only persist if something actually changed — avoids needless disk writes\n // on idle TITANs and avoids the \"everything got nuked\" failure mode.\n if (purged > 0) {\n logger.info(COMPONENT, `[Auth] Purged ${purged} expired session token(s).`);\n saveAuthTokens();\n }\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 // v6.0 step 11 — Start the somaInitiative proactive loop on gateway boot.\n // Without this, the loop's `startSomaInitiative()` function is dead code\n // and the \"TITAN acts without being asked\" v6.0 promise is unobservable.\n // The loop is self-throttling (5-min pulse, conservative confidence\n // floor, frustration-aware throttling) so we can wire it on without\n // risk of spam. Errors are swallowed so a Soma bug never breaks boot.\n try {\n const { startSomaInitiative } = await import('../agent/somaInitiative.js');\n startSomaInitiative({ userId: 'default-user' });\n } catch (err) {\n logger.warn(COMPONENT, `somaInitiative failed to start: ${(err as Error).message}`);\n }\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 /**\n * v6.0 Step 13 helper — pick the drive that deviates most from its\n * baseline as the \"dominant\" mood. Returns a label the mascot uses for\n * its status text. Neutral when no drive deviates more than 0.1.\n */\n function pickDominantDrive(\n current: Record<string, number>,\n baseline: Record<string, number>,\n ): { drive: string; label: string; delta: number } {\n let best = { drive: 'neutral', label: 'TITAN is steady', delta: 0 };\n for (const drive of Object.keys(current)) {\n const delta = (current[drive] ?? 0) - (baseline[drive] ?? 0);\n const abs = Math.abs(delta);\n if (abs <= 0.1) continue;\n if (abs > Math.abs(best.delta)) {\n const direction = delta > 0 ? 'elevated' : 'low';\n const label = direction === 'elevated'\n ? `TITAN is ${driveAdjective(drive, true)}`\n : `TITAN is ${driveAdjective(drive, false)}`;\n best = { drive, label, delta };\n }\n }\n return best;\n }\n\n function driveAdjective(drive: string, elevated: boolean): string {\n const map: Record<string, [string, string]> = {\n // Soma profile (per-user moods).\n curiosity: ['curious', 'incurious'],\n focus: ['focused', 'unfocused'],\n fatigue: ['tired', 'energized'],\n satisfaction: ['satisfied', 'restless'],\n frustration: ['frustrated', 'calm'],\n // v6.0.3 — Soma organism drives (the real homeostatic layer).\n // `elevated` here means satisfaction > baseline; \"low\" satisfaction\n // is the side that produces visible pressure.\n purpose: ['aligned', 'aimless'],\n hunger: ['fed', 'hungry'],\n safety: ['secure', 'on edge'],\n social: ['social', 'isolated'],\n };\n const pair = map[drive];\n if (!pair) return drive;\n return elevated ? pair[0] : pair[1];\n }\n\n // v6.0 Step 8 — Widget runtime `titan.*` API surface.\n // These endpoints let widgets inside the iframe sandbox call back into\n // TITAN as first-class clients of the agent (not just dumb React UI).\n\n /**\n * GET /api/tools — list registered tool names + descriptions.\n * v4.12 shape preserved: { tools, total, count } with optional `?q=` filter.\n * v6.0 step 8 expanded by adding `parameters` per tool so widgets can\n * discover the call shape dynamically.\n */\n app.get('/api/tools', async (req, res) => {\n try {\n const { getRegisteredTools } = await import('../agent/toolRunner.js');\n const q = typeof req.query.q === 'string' ? req.query.q.toLowerCase().trim() : '';\n const all = getRegisteredTools().map(t => ({\n name: t.name,\n description: typeof t.description === 'string' ? t.description.slice(0, 500) : '',\n parameters: t.parameters,\n }));\n const filtered = q\n ? all.filter(t => t.name.toLowerCase().includes(q) || t.description.toLowerCase().includes(q))\n : all;\n res.json({ tools: filtered, total: all.length, count: filtered.length });\n } catch (err) {\n res.status(500).json({ error: 'tools_unavailable', message: (err as Error).message });\n }\n });\n\n /**\n * POST /api/tools/run — invoke a tool by name. Widget runtime entry point\n * for `titan.tools.run(name, args)`. Subject to the same intent / approval\n * gates as the agent's own calls.\n */\n app.post('/api/tools/run', async (req, res) => {\n try {\n const { name, args } = (req.body || {}) as { name?: string; args?: Record<string, unknown> };\n if (!name || typeof name !== 'string') {\n res.status(400).json({ error: 'invalid_input', message: '\"name\" is required.' });\n return;\n }\n const { executeTool } = await import('../agent/toolRunner.js');\n const result = await executeTool({\n id: `widget-${Date.now()}`,\n type: 'function',\n function: { name, arguments: JSON.stringify(args || {}) },\n });\n res.json({\n name: result.name,\n success: result.success !== false,\n content: result.content,\n });\n } catch (err) {\n res.status(500).json({ error: 'tool_run_failed', message: (err as Error).message });\n }\n });\n\n /**\n * GET /api/memory/:key — read a single memory value. Widget-friendly\n * minimal surface; uses the `widget` category to keep widget-scoped\n * facts separate from the agent's general memory namespace.\n */\n app.get('/api/memory/:key', async (req, res) => {\n try {\n const { recallFact } = await import('../memory/memory.js');\n const value = recallFact('widget', req.params.key);\n res.json({ key: req.params.key, value: value ?? null });\n } catch (err) {\n res.status(500).json({ error: 'memory_read_failed', message: (err as Error).message });\n }\n });\n\n /** POST /api/memory — write a single key/value to the widget memory category. */\n app.post('/api/memory', async (req, res) => {\n try {\n const { key, value } = (req.body || {}) as { key?: string; value?: unknown };\n if (!key || typeof key !== 'string') {\n res.status(400).json({ error: 'invalid_input', message: '\"key\" is required.' });\n return;\n }\n const { rememberFact } = await import('../memory/memory.js');\n const v = typeof value === 'string' ? value : JSON.stringify(value);\n rememberFact('widget', key, v);\n res.json({ key, stored: true });\n } catch (err) {\n res.status(500).json({ error: 'memory_write_failed', message: (err as Error).message });\n }\n });\n\n /** GET /api/persona/current — convenience endpoint for `titan.persona`. */\n app.get('/api/persona/current', async (_req, res) => {\n try {\n const { getActivePersonaContent } = await import('../personas/manager.js');\n const cfg = loadConfig();\n const personaId = cfg.agent?.persona || 'default';\n const content = getActivePersonaContent(personaId);\n res.json({ content: content || null, personaId });\n } catch (err) {\n res.status(500).json({ error: 'persona_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0 Step 4 — Spaces REST API. The SPA's Spaces sidebar reads + writes\n // the server-side `~/.titan/spaces.json` via these endpoints. The agent's\n // canvas_spaces tools mutate the same file, so the SPA + agent agree on\n // a single source of truth regardless of which one made the change.\n app.get('/api/spaces', async (_req, res) => {\n try {\n const { readSpaces, getActiveSpace } = await import('../storage/spaces.js');\n const file = readSpaces();\n const active = getActiveSpace();\n res.json({\n spaces: file.spaces,\n activeSpaceId: active?.id ?? null,\n });\n } catch (err) {\n res.status(500).json({ error: 'spaces_unavailable', message: (err as Error).message });\n }\n });\n\n app.post('/api/spaces', async (req, res) => {\n try {\n const { createSpace } = await import('../storage/spaces.js');\n const { name, icon, color, agentInstructions, starterWidgets, makeActive } = (req.body || {}) as Record<string, unknown>;\n if (typeof name !== 'string' || !name.trim()) {\n res.status(400).json({ error: 'invalid_input', message: '\"name\" is required.' });\n return;\n }\n const space = createSpace({\n name: name.trim(),\n icon: typeof icon === 'string' ? icon : undefined,\n color: typeof color === 'string' ? color : undefined,\n agentInstructions: typeof agentInstructions === 'string' ? agentInstructions : undefined,\n starterWidgets: Array.isArray(starterWidgets) ? starterWidgets : undefined,\n makeActive: Boolean(makeActive),\n });\n res.json({ space });\n } catch (err) {\n res.status(500).json({ error: 'create_failed', message: (err as Error).message });\n }\n });\n\n app.patch('/api/spaces/:id', async (req, res) => {\n try {\n const { updateSpace } = await import('../storage/spaces.js');\n const patch = (req.body || {}) as Record<string, unknown>;\n const space = updateSpace(req.params.id, {\n name: typeof patch.name === 'string' ? patch.name : undefined,\n icon: typeof patch.icon === 'string' ? patch.icon : undefined,\n color: typeof patch.color === 'string' ? patch.color : undefined,\n agentInstructions: typeof patch.agentInstructions === 'string' ? patch.agentInstructions : undefined,\n widgets: Array.isArray(patch.widgets) ? patch.widgets : undefined,\n });\n if (!space) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json({ space });\n } catch (err) {\n res.status(500).json({ error: 'update_failed', message: (err as Error).message });\n }\n });\n\n app.post('/api/spaces/:id/activate', async (req, res) => {\n try {\n const { switchSpace } = await import('../storage/spaces.js');\n const space = switchSpace(req.params.id);\n if (!space) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json({ space });\n } catch (err) {\n res.status(500).json({ error: 'switch_failed', message: (err as Error).message });\n }\n });\n\n app.delete('/api/spaces/:id', async (req, res) => {\n try {\n const { archiveSpace } = await import('../storage/spaces.js');\n const result = archiveSpace(req.params.id);\n if (!result) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json({ archived: result.archived, remaining: result.remaining });\n } catch (err) {\n res.status(500).json({ error: 'archive_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/spaces/presets', async (_req, res) => {\n try {\n const { listStarterPresets } = await import('../storage/starterSpaces.js');\n res.json({ presets: listStarterPresets() });\n } catch (err) {\n res.status(500).json({ error: 'presets_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0 Step 13 — Soma drive state surface for the mascot + status bar.\n // Returns CURRENT drive levels (organism layer) + per-user BASELINE\n // (Soma profile). The SPA's mascot listens to this and renders the\n // mood-tint, breathing animation, and \"TITAN is curious / focused /\n // frustrated\" status-bar text.\n //\n // v6.0.3 — Previously this endpoint mapped neurotransmitter names\n // (dopamine, cortisol, norepinephrine) onto drive ids, but Soma stores\n // drives by id (curiosity, hunger, safety, social, purpose), so every\n // field always missed and the mascot read a flat baseline. Now we\n // surface the REAL drive levels — the mascot's mood actually moves.\n app.get('/api/soma/drives', async (req, res) => {\n try {\n const userId = getUserIdFromReq(req as Parameters<typeof getUserIdFromReq>[0]);\n const { readSomaProfile } = await import('../storage/somaProfile.js');\n const profile = readSomaProfile(userId);\n let current: Record<string, number> | null = null;\n let asOf: string | null = null;\n try {\n const { getHormonalState } = await import('../organism/hormones.js');\n const state = getHormonalState();\n if (state.available) {\n current = { ...state.levels };\n asOf = state.asOf;\n }\n } catch { /* organism may be off — fall back to baseline */ }\n // Build a baseline that includes every drive present in `current`\n // (the Soma drive layer ships purpose/hunger/curiosity/safety/social;\n // the per-user Soma profile stores per-drive baselines — but those\n // are keyed by feel-name, not drive-id, so we synthesise a neutral\n // 0.7 baseline for any drive id the profile doesn't cover. Without\n // this the deviation math compares hunger=0.15 to baseline=0\n // and reports an artificial delta of +0.15, instead of correctly\n // flagging hunger as low).\n const baseline: Record<string, number> = { ...profile.baseline };\n if (current) {\n for (const k of Object.keys(current)) {\n if (!(k in baseline)) baseline[k] = 0.7;\n }\n }\n res.json({\n userId,\n baseline,\n current: current ?? baseline,\n asOf,\n dominant: pickDominantDrive(current ?? baseline, baseline),\n });\n } catch (err) {\n res.status(500).json({ error: 'soma_drives_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Full Soma state. Returns the latest persisted drive tick + the\n // hormonal block the SOMA page needs to render the elevated-drive line\n // (\"Body state: hunger 15% · curiosity 37%\") and the inspector\n // sparklines. Previously this endpoint didn't exist; the SomaView fell\n // back to /api/watch/snapshot which doesn't include the hormonal block,\n // so it always showed \"All drives satiated — routine operation.\"\n app.get('/api/soma/state', async (_req, res) => {\n try {\n const cfg = loadConfig();\n const organismEnabled = (cfg.organism as { enabled?: boolean } | undefined)?.enabled ?? true;\n const { loadDriveHistory } = await import('../organism/drives.js');\n const { buildBlock } = await import('../organism/hormones.js');\n const history = loadDriveHistory();\n if (!history) {\n res.json({\n enabled: organismEnabled,\n message: organismEnabled\n ? 'Soma is enabled but no drive tick has run yet. Wait ~60s.'\n : 'Soma is disabled. Enable via organism.enabled in config.',\n drives: [],\n totalPressure: 0,\n dominantDrives: [],\n hormonal: { available: false, asOf: null, levels: {}, elevated: [], dominant: null },\n });\n return;\n }\n const block = buildBlock(history.latest.drives, history.latest.timestamp);\n res.json({\n enabled: organismEnabled,\n timestamp: history.latest.timestamp,\n drives: history.latest.drives,\n totalPressure: history.latest.totalPressure,\n dominantDrives: history.latest.dominantDrives,\n hormonal: block,\n });\n } catch (err) {\n res.status(500).json({ error: 'soma_state_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Ring-buffered drive history. Used by the SOMA page for\n // sparklines + the \"last 24h\" trend graphs. `hours` query param caps\n // the slice; default 24h.\n app.get('/api/soma/history', async (req, res) => {\n try {\n const cfg = loadConfig();\n const organismEnabled = (cfg.organism as { enabled?: boolean } | undefined)?.enabled ?? true;\n const { loadDriveHistory } = await import('../organism/drives.js');\n const hours = Math.max(1, Math.min(168, parseInt(String(req.query.hours ?? '24'), 10) || 24));\n const history = loadDriveHistory();\n if (!history) {\n res.json({ enabled: organismEnabled, history: [], latest: null });\n return;\n }\n const cutoff = Date.now() - hours * 60 * 60 * 1000;\n const slice = history.history.filter(p => new Date(p.timestamp).getTime() >= cutoff);\n res.json({ enabled: organismEnabled, history: slice, latest: history.latest });\n } catch (err) {\n res.status(500).json({ error: 'soma_history_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Recent Soma advisories (somaInitiative pulses that didn't\n // map to 'nothing'). The canvas notification card polls this; the\n // mascot speech bubble can quote the most recent one.\n app.get('/api/soma/advisories', async (req, res) => {\n try {\n const userId = getUserIdFromReq(req as Parameters<typeof getUserIdFromReq>[0]);\n const { readRecentAdvisories } = await import('../agent/somaInitiative.js');\n const limit = Math.max(1, Math.min(50, parseInt(String(req.query.limit ?? '10'), 10) || 10));\n const advisories = readRecentAdvisories(userId, limit);\n res.json({ userId, advisories });\n } catch (err) {\n res.status(500).json({ error: 'advisories_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.5 — Time Travel surface. TITAN's shadow-git layer\n // (~/.titan/file-checkpoints/) already snapshots every file before any\n // write/edit/append tool runs, but pre-v6.0.5 we had no UI for it.\n // These three endpoints expose:\n // GET /api/time-travel/checkpoints → newest-first list, optional ?file= filter\n // GET /api/time-travel/diff/:id → diff vs current file\n // POST /api/time-travel/restore/:id → restore the file to that checkpoint\n app.get('/api/time-travel/checkpoints', async (req, res) => {\n try {\n const { listAllCheckpoints, listCheckpoints } = await import('../agent/shadowGit.js');\n const file = typeof req.query.file === 'string' ? req.query.file : '';\n const limit = Math.max(1, Math.min(500, parseInt(String(req.query.limit ?? '100'), 10) || 100));\n const checkpoints = file ? listCheckpoints(file) : listAllCheckpoints(limit);\n res.json({ count: checkpoints.length, checkpoints });\n } catch (err) {\n res.status(500).json({ error: 'time_travel_list_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/time-travel/diff/:id', async (req, res) => {\n try {\n const { diffCheckpoint } = await import('../agent/shadowGit.js');\n const id = String(req.params.id || '').trim();\n if (!id) { res.status(400).json({ error: 'missing_checkpoint_id' }); return; }\n const diff = diffCheckpoint(id);\n res.json({ checkpointId: id, diff });\n } catch (err) {\n res.status(500).json({ error: 'time_travel_diff_failed', message: (err as Error).message });\n }\n });\n\n app.post('/api/time-travel/restore/:id', async (req, res) => {\n try {\n const { restoreCheckpoint } = await import('../agent/shadowGit.js');\n const id = String(req.params.id || '').trim();\n if (!id) { res.status(400).json({ error: 'missing_checkpoint_id' }); return; }\n const result = restoreCheckpoint(id);\n const ok = !result.toLowerCase().startsWith('restore failed') && !result.toLowerCase().startsWith('no checkpoints') && !result.toLowerCase().includes('not found');\n res.json({ ok, checkpointId: id, message: result });\n } catch (err) {\n res.status(500).json({ error: 'time_travel_restore_failed', message: (err as Error).message });\n }\n });\n\n // v6.0.0-beta.4 — Mission API. The \"work without me\" surface.\n //\n // TITAN already has a deep autonomy stack: durable journal, stateless\n // reducer, 11-phase goal driver, crash recovery, budget enforcement.\n // What was missing was an ergonomic entry point (one prompt → an\n // autonomous mission) and live visibility (what's the driver doing\n // right now? what got done overnight?). These five endpoints close that\n // gap and feed the Mission Driver + Daily Digest canvas widgets.\n //\n // POST /api/mission/run → single-prompt mission creation\n // GET /api/missions/active → live driver state for every active goal\n // GET /api/missions/recent?hours= → completed goals in last N hours\n // GET /api/missions/digest?hours= → human-readable \"what got done\" summary\n // POST /api/mission/:id/cancel → cancel a running mission\n\n app.post('/api/mission/run', async (req, res) => {\n try {\n const description = String(req.body?.description ?? req.body?.prompt ?? '').trim();\n if (!description || description.length < 10) {\n res.status(400).json({ error: 'description_required', message: 'Provide a description (>=10 chars) of what TITAN should accomplish autonomously.' });\n return;\n }\n const title = String(req.body?.title ?? '').trim() || description.split(/[.!?\\n]/)[0].slice(0, 80);\n const priority = Math.max(1, Math.min(5, Number(req.body?.priority) || 3));\n const budgetLimit = Math.max(0.01, Math.min(50, Number(req.body?.budgetUsd) || 2));\n const tags: string[] = Array.isArray(req.body?.tags) ? req.body.tags.map(String) : ['mission', 'autonomous'];\n\n // Decompose the description into 3–6 subtasks via the LLM. Use the\n // small/fast tier — this is a one-shot planning call, not an agent\n // loop. The driver then ticks through the subtasks autonomously.\n let subtasks: Array<{ title: string; description: string; dependsOn?: string[] }> | undefined = undefined;\n try {\n const { spawnSubAgent } = await import('../agent/subAgent.js');\n const decomposePrompt = [\n `Decompose this autonomous mission into 3-6 concrete, independently-runnable subtasks.`,\n ``,\n `Mission: ${description}`,\n ``,\n `Return STRICT JSON: { \"subtasks\": [ { \"title\": \"...\", \"description\": \"...\" }, ... ] }.`,\n `Each title <= 60 chars, each description <= 200 chars.`,\n `Order subtasks dependency-aware (later ones may reference earlier output).`,\n `Do NOT add a verification subtask — the driver verifies automatically.`,\n `Do NOT wrap in markdown — pure JSON.`,\n ].join('\\n');\n const result = await spawnSubAgent({\n name: 'mission-decomposer',\n task: decomposePrompt,\n tier: 'fast',\n maxRounds: 1,\n });\n const raw = (result.content || '').trim();\n const jsonStart = raw.indexOf('{');\n const jsonEnd = raw.lastIndexOf('}');\n if (jsonStart >= 0 && jsonEnd > jsonStart) {\n const parsed = JSON.parse(raw.slice(jsonStart, jsonEnd + 1)) as { subtasks?: Array<{ title?: string; description?: string }> };\n if (Array.isArray(parsed.subtasks) && parsed.subtasks.length >= 1) {\n subtasks = parsed.subtasks\n .filter(s => typeof s?.title === 'string' && typeof s?.description === 'string')\n .slice(0, 6)\n .map(s => ({ title: String(s.title).slice(0, 80), description: String(s.description).slice(0, 280) }));\n }\n }\n } catch (err) {\n logger.warn(COMPONENT, `Mission decomposition failed, creating goal with no subtasks: ${(err as Error).message}`);\n }\n\n const { createGoal } = await import('../agent/goals.js');\n const goal = createGoal({\n title,\n description,\n priority,\n budgetLimit,\n tags,\n subtasks,\n force: req.body?.force === true,\n });\n logger.info(COMPONENT, `[Mission] Created mission goal \"${title}\" (id=${goal.id}, subtasks=${(subtasks?.length ?? 0)})`);\n res.json({\n ok: true,\n goal: { id: goal.id, title: goal.title, status: goal.status, priority: goal.priority, subtaskCount: goal.subtasks?.length ?? 0 },\n message: subtasks?.length\n ? `Mission \"${title}\" created with ${subtasks.length} subtasks. Driver will pick it up on the next tick (within 10s).`\n : `Mission \"${title}\" created. Decomposition skipped — add subtasks via the Goals API or chat.`,\n });\n } catch (err) {\n res.status(500).json({ error: 'mission_create_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/missions/active', async (_req, res) => {\n try {\n const { listActiveDrivers } = await import('../agent/goalDriver.js');\n const { listGoals } = await import('../agent/goals.js');\n const drivers = listActiveDrivers();\n const goals = listGoals('active');\n const goalsById = new Map(goals.map(g => [g.id, g]));\n const missions = drivers.map(d => {\n const goal = goalsById.get(d.goalId);\n const completed = Object.values(d.subtaskStates).filter(s => s.verificationResult?.passed === true).length;\n const total = Object.keys(d.subtaskStates).length || (goal?.subtasks?.length ?? 0);\n return {\n goalId: d.goalId,\n title: goal?.title || '(unknown goal)',\n phase: d.phase,\n startedAt: d.startedAt,\n currentSubtaskId: d.currentSubtaskId ?? null,\n subtasks: { total, completed },\n budget: d.budget,\n blockedReason: d.blockedReason ?? null,\n lastHistory: (d.history || []).slice(-3),\n };\n });\n res.json({ count: missions.length, missions });\n } catch (err) {\n res.status(500).json({ error: 'missions_active_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/missions/recent', async (req, res) => {\n try {\n const hours = Math.max(1, Math.min(168, parseInt(String(req.query.hours ?? '24'), 10) || 24));\n const { listAllDrivers } = await import('../agent/goalDriver.js');\n const { listGoals } = await import('../agent/goals.js');\n const all = listAllDrivers();\n const cutoff = Date.now() - hours * 60 * 60 * 1000;\n const goalsById = new Map(listGoals().map(g => [g.id, g]));\n const recent = all\n .filter(d => ['done', 'failed', 'cancelled'].includes(d.phase))\n .filter(d => {\n const completedAt = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return new Date(completedAt).getTime() >= cutoff;\n })\n .map(d => {\n const goal = goalsById.get(d.goalId);\n const completedAt = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return {\n goalId: d.goalId,\n title: goal?.title || '(unknown goal)',\n phase: d.phase as 'done' | 'failed' | 'cancelled',\n startedAt: d.startedAt,\n completedAt,\n durationMs: new Date(completedAt).getTime() - new Date(d.startedAt).getTime(),\n subtaskCount: Object.keys(d.subtaskStates).length || (goal?.subtasks?.length ?? 0),\n budget: d.budget,\n lessonsLearned: d.retrospective?.lessonsLearned ?? [],\n };\n })\n .sort((a, b) => (a.completedAt < b.completedAt ? 1 : -1));\n res.json({ hours, count: recent.length, missions: recent });\n } catch (err) {\n res.status(500).json({ error: 'missions_recent_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/missions/digest', async (req, res) => {\n try {\n const hours = Math.max(1, Math.min(168, parseInt(String(req.query.hours ?? '24'), 10) || 24));\n const { listAllDrivers, listActiveDrivers } = await import('../agent/goalDriver.js');\n const { listGoals } = await import('../agent/goals.js');\n const cutoff = Date.now() - hours * 60 * 60 * 1000;\n const all = listAllDrivers();\n const active = listActiveDrivers();\n const goalsById = new Map(listGoals().map(g => [g.id, g]));\n const completed = all.filter(d => d.phase === 'done').filter(d => {\n const at = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return new Date(at).getTime() >= cutoff;\n });\n const failed = all.filter(d => d.phase === 'failed').filter(d => {\n const at = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return new Date(at).getTime() >= cutoff;\n });\n const blocked = active.filter(d => d.phase === 'blocked');\n const totalCostUsd = [...completed, ...failed].reduce((sum, d) => sum + (d.budget?.costUsd ?? 0), 0);\n const totalTokens = [...completed, ...failed].reduce((sum, d) => sum + (d.budget?.tokensUsed ?? 0), 0);\n const lessons = completed.flatMap(d => d.retrospective?.lessonsLearned ?? []).slice(0, 10);\n\n const summary: string[] = [];\n summary.push(`Last ${hours}h: ${completed.length} mission(s) completed, ${failed.length} failed, ${active.length} active, ${blocked.length} blocked for approval.`);\n if (completed.length > 0) {\n summary.push(``);\n summary.push(`Completed:`);\n for (const d of completed.slice(0, 10)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId} (${Math.round((d.budget?.costUsd ?? 0) * 100) / 100} USD, ${Math.round(((d.history?.[d.history.length - 1]?.at ? new Date(d.history[d.history.length - 1].at).getTime() : Date.now()) - new Date(d.startedAt).getTime()) / 1000)}s)`);\n }\n }\n if (failed.length > 0) {\n summary.push(``);\n summary.push(`Failed (need review):`);\n for (const d of failed.slice(0, 5)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId}`);\n }\n }\n if (blocked.length > 0) {\n summary.push(``);\n summary.push(`Blocked for approval:`);\n for (const d of blocked.slice(0, 5)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId} — ${d.blockedReason?.question ?? '(no reason given)'}`);\n }\n }\n if (active.length > 0 && blocked.length < active.length) {\n summary.push(``);\n summary.push(`In progress:`);\n for (const d of active.filter(a => a.phase !== 'blocked').slice(0, 10)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId} [${d.phase}]`);\n }\n }\n\n res.json({\n hours,\n stats: {\n completed: completed.length,\n failed: failed.length,\n active: active.length,\n blocked: blocked.length,\n totalCostUsd: Math.round(totalCostUsd * 1000) / 1000,\n totalTokens,\n },\n summaryText: summary.join('\\n'),\n recentLessons: lessons,\n });\n } catch (err) {\n res.status(500).json({ error: 'mission_digest_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/mission/:id', async (req, res) => {\n try {\n const goalId = String(req.params.id || '').trim();\n if (!goalId) { res.status(400).json({ error: 'missing_goal_id' }); return; }\n const { getGoal } = await import('../agent/goals.js');\n const { getDriverState } = await import('../agent/goalDriver.js');\n const goal = getGoal(goalId);\n if (!goal) { res.status(404).json({ error: 'goal_not_found' }); return; }\n const state = getDriverState(goalId);\n res.json({\n goal: {\n id: goal.id,\n title: goal.title,\n description: goal.description,\n status: goal.status,\n priority: goal.priority,\n progress: goal.progress,\n totalCost: goal.totalCost,\n createdAt: goal.createdAt,\n completedAt: goal.completedAt,\n tags: goal.tags ?? [],\n subtasks: (goal.subtasks ?? []).map(s => ({\n id: s.id,\n title: s.title,\n description: s.description,\n status: s.status,\n dependsOn: s.dependsOn ?? [],\n retries: s.retries,\n completedAt: s.completedAt,\n })),\n },\n driver: state ? {\n phase: state.phase,\n startedAt: state.startedAt,\n currentSubtaskId: state.currentSubtaskId ?? null,\n budget: state.budget,\n blockedReason: state.blockedReason ?? null,\n historyTail: (state.history ?? []).slice(-10),\n subtaskStates: state.subtaskStates,\n } : null,\n });\n } catch (err) {\n res.status(500).json({ error: 'mission_get_failed', message: (err as Error).message });\n }\n });\n\n app.post('/api/mission/:id/cancel', async (req, res) => {\n try {\n const goalId = String(req.params.id || '').trim();\n if (!goalId) { res.status(400).json({ error: 'missing_goal_id' }); return; }\n const { getDriverState } = await import('../agent/goalDriver.js');\n const { updateGoal } = await import('../agent/goals.js');\n const state = getDriverState(goalId);\n if (state) {\n state.userControls.cancelRequested = true;\n // The driver will observe this on its next tick and transition.\n }\n updateGoal(goalId, { status: 'paused' });\n res.json({ ok: true, message: `Mission ${goalId} marked for cancellation. Driver will stop on the next tick.` });\n } catch (err) {\n res.status(500).json({ error: 'mission_cancel_failed', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Manual trigger for the daily-gift loop. The 22h cron path\n // still fires on its own; this endpoint lets the user click \"send me\n // something now\" in the SOMA panel and see what Soma comes up with\n // without waiting a day. We bypass the 18h cooldown by passing a\n // `force` flag (the gift module respects this).\n app.post('/api/soma/gift', async (req, res) => {\n try {\n const userId = getUserIdFromReq(req as Parameters<typeof getUserIdFromReq>[0]);\n const force = req.body?.force !== false;\n const { tryDailyGift } = await import('../agent/somaInitiative.js');\n // Fire-and-forget — the LLM call inside can take 20-60s; we don't\n // want the HTTP request to block that long. The result lands as a\n // create_widget side-channel event on the user's open SSE stream.\n void tryDailyGift(userId, { force }).then(result => {\n logger.info(COMPONENT, `[SomaGift] manual trigger: attempted=${result.attempted} reason=${result.reason}`);\n }).catch(err => {\n logger.warn(COMPONENT, `[SomaGift] manual trigger failed: ${(err as Error).message}`);\n });\n res.json({ ok: true, message: 'Soma is thinking about what to gift you. A widget will appear on your canvas shortly (or Soma will decline if nothing fits).' });\n } catch (err) {\n res.status(500).json({ error: 'gift_unavailable', message: (err as Error).message });\n }\n });\n\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 (v6.0 — TIGHTENED + Bucket-C-aware) ─═══\n // Fast-path: when the user is EXPLICITLY asking to add a known system\n // widget — \"add the cron widget\", \"open the VRAM dashboard\", \"pin the\n // training panel\" — bypass the LLM and emit the _____widget gate\n // directly. Faster + deterministic for unambiguous asks.\n //\n // ## History\n //\n // - v5.5.28 fix: gated the shortcut on `hasExplicitWidgetIntent` (the\n // message must mention a widget-noun). Helped, but still too loose.\n // Words like \"tools\" or \"panel\" appear in normal English (\"the\n // fb_post tool\", \"control panel\") and would flip the gate to true,\n // then any inner trigger like \"backup\" or \"training\" would hijack\n // the prompt.\n //\n // - v6.0 fix (now): **require an IMPERATIVE verb + widget noun\n // together**, NOT just one of them. The whole point of v6.0 is\n // \"generation-first\" — TITAN builds custom widgets on demand,\n // doesn't shove users into a pre-built shortcut. The shortcut now\n // only fires for true imperative asks. Also drops 'tools' and\n // 'monitor' from the noun list (both too noisy). Also drops the\n // killed-Bucket-C panels (paperclip).\n //\n // Test coverage: tests/unit/widget-shortcut-hijack.test.ts\n const imperativeRe = /\\b(?:add|open|show|pin|create|launch|put|give\\s+me|i\\s+want|let'?s\\s+see|i\\s+need)\\b/i;\n const widgetNounRe = /\\b(?:widget|panel|dashboard|hub|gallery|kitchen|scheduler)\\b/i;\n const hasExplicitWidgetIntent = imperativeRe.test(content) && widgetNounRe.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|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|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|form fill|web automation)\\b/i, source: 'system:browser', name: 'Browser Tools', w: 6, h: 5 },\n // v6.0 step 1 — system:paperclip removed (Bucket C / killed branding).\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 // Hoisted so the `finally` block can release the widget side-channel\n // subscription whether the request streamed, errored, or finished early.\n let unsubscribeWidgets: (() => void) | null = null;\n // v6.0.2 — SSE keep-alive heartbeat. Cloud models (e.g. deepseek-v4-pro)\n // can spend 60-180s in a single non-streaming `think` phase. The frontend\n // (ui/src/api/client.ts) treats >60s of total silence as a dead stream\n // and aborts. SSE comment lines (`:<text>\\n\\n`) reset the client read\n // timer without affecting event parsing. Emit one every 15s for the\n // lifetime of the stream so long thinks no longer trigger phantom\n // \"stream went silent\" errors.\n let heartbeatInterval: ReturnType<typeof setInterval> | 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 // Fire the first heartbeat immediately + every 15s thereafter. Stays\n // under the client's 60s quiet ceiling with plenty of headroom even\n // if one heartbeat is delayed by event-loop pressure.\n heartbeatInterval = setInterval(() => {\n if (clientDisconnected) return;\n safeWrite(`: heartbeat ${Date.now()}\\n\\n`);\n }, 15_000);\n\n // Canvas widget side-channel — subscribe to the per-session widget\n // bus for the duration of this stream and forward events as their\n // own SSE event type. Released in the finally block below so we\n // never leak listeners. See src/agent/widgetEmitter.ts.\n if (requestedSessionId) {\n try {\n const { subscribe: subscribeWidgets } = await import('../agent/widgetEmitter.js');\n unsubscribeWidgets = subscribeWidgets(requestedSessionId, (evt) => {\n safeWrite(`event: widget\\ndata: ${JSON.stringify({ mode: evt.mode, widget: evt.widget, timestamp: evt.timestamp })}\\n\\n`);\n });\n } catch (err) {\n logger.warn(COMPONENT, `widgetEmitter subscribe failed: ${err instanceof Error ? err.message : String(err)}`);\n }\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 // onWidget is wired through the widgetEmitter subscription above\n // rather than through this callback bag, because the tool that\n // fires it (create_widget) runs in toolRunner.ts and has its own\n // direct path to the per-session bus.\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 // Release the canvas-widget side-channel subscription (if any) so the\n // emitter doesn't accumulate dead listeners across long-lived servers.\n if (unsubscribeWidgets) {\n try { unsubscribeWidgets(); } catch { /* never let cleanup break the request */ }\n }\n // Stop the SSE heartbeat — must clear on every exit path or the\n // interval leaks for the lifetime of the process.\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = null;\n }\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","getRegisteredTools","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\n/**\n * Session-token TTL — configurable via `gateway.auth.tokenTtlMs`.\n * Pre-v5.7.2 this was hardcoded to 24h, which silently expired Tony's\n * sessions overnight and (combined with the cleanup timer) wiped\n * auth-tokens.json to `[]`. Default is now 30 days for self-hosted use.\n */\nfunction getAuthTokenTtlMs(): number {\n try {\n const cfg = loadConfig();\n const v = cfg.gateway?.auth?.tokenTtlMs;\n if (typeof v === 'number' && v > 0) return v;\n } catch { /* fall through */ }\n return 30 * 24 * 60 * 60 * 1000; // 30 days\n}\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 = getAuthTokenTtlMs();\n const now = Date.now();\n let dropped = 0;\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 } else {\n dropped++;\n }\n }\n }\n if (dropped > 0) {\n logger.info(COMPONENT, `[Auth] Dropped ${dropped} expired session token(s) at boot (TTL: ${Math.round(ttlMs / 3600_000)}h).`);\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.\n// Pre-v5.7.2 this used a hardcoded 24h TTL which clobbered auth-tokens.json\n// to `[]` overnight on self-hosted single-user TITANs. Now reads the\n// configured `gateway.auth.tokenTtlMs` (default 30 days).\ntokenCleanupInterval = setInterval(() => {\n const now = Date.now();\n const ttlMs = getAuthTokenTtlMs();\n let purged = 0;\n for (const [tok, entry] of authTokens) {\n if (now - entry.createdAt > ttlMs) { authTokens.delete(tok); purged++; }\n }\n // Only persist if something actually changed — avoids needless disk writes\n // on idle TITANs and avoids the \"everything got nuked\" failure mode.\n if (purged > 0) {\n logger.info(COMPONENT, `[Auth] Purged ${purged} expired session token(s).`);\n saveAuthTokens();\n }\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 // v6.0 step 11 — Start the somaInitiative proactive loop on gateway boot.\n // Without this, the loop's `startSomaInitiative()` function is dead code\n // and the \"TITAN acts without being asked\" v6.0 promise is unobservable.\n // The loop is self-throttling (5-min pulse, conservative confidence\n // floor, frustration-aware throttling) so we can wire it on without\n // risk of spam. Errors are swallowed so a Soma bug never breaks boot.\n try {\n const { startSomaInitiative } = await import('../agent/somaInitiative.js');\n startSomaInitiative({ userId: 'default-user' });\n } catch (err) {\n logger.warn(COMPONENT, `somaInitiative failed to start: ${(err as Error).message}`);\n }\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 /**\n * v6.0 Step 13 helper — pick the drive that deviates most from its\n * baseline as the \"dominant\" mood. Returns a label the mascot uses for\n * its status text. Neutral when no drive deviates more than 0.1.\n */\n function pickDominantDrive(\n current: Record<string, number>,\n baseline: Record<string, number>,\n ): { drive: string; label: string; delta: number } {\n let best = { drive: 'neutral', label: 'TITAN is steady', delta: 0 };\n for (const drive of Object.keys(current)) {\n const delta = (current[drive] ?? 0) - (baseline[drive] ?? 0);\n const abs = Math.abs(delta);\n if (abs <= 0.1) continue;\n if (abs > Math.abs(best.delta)) {\n const direction = delta > 0 ? 'elevated' : 'low';\n const label = direction === 'elevated'\n ? `TITAN is ${driveAdjective(drive, true)}`\n : `TITAN is ${driveAdjective(drive, false)}`;\n best = { drive, label, delta };\n }\n }\n return best;\n }\n\n function driveAdjective(drive: string, elevated: boolean): string {\n const map: Record<string, [string, string]> = {\n // Soma profile (per-user moods).\n curiosity: ['curious', 'incurious'],\n focus: ['focused', 'unfocused'],\n fatigue: ['tired', 'energized'],\n satisfaction: ['satisfied', 'restless'],\n frustration: ['frustrated', 'calm'],\n // v6.0.3 — Soma organism drives (the real homeostatic layer).\n // `elevated` here means satisfaction > baseline; \"low\" satisfaction\n // is the side that produces visible pressure.\n purpose: ['aligned', 'aimless'],\n hunger: ['fed', 'hungry'],\n safety: ['secure', 'on edge'],\n social: ['social', 'isolated'],\n };\n const pair = map[drive];\n if (!pair) return drive;\n return elevated ? pair[0] : pair[1];\n }\n\n // v6.0 Step 8 — Widget runtime `titan.*` API surface.\n // These endpoints let widgets inside the iframe sandbox call back into\n // TITAN as first-class clients of the agent (not just dumb React UI).\n\n /**\n * GET /api/tools — list registered tool names + descriptions.\n * v4.12 shape preserved: { tools, total, count } with optional `?q=` filter.\n * v6.0 step 8 expanded by adding `parameters` per tool so widgets can\n * discover the call shape dynamically.\n */\n app.get('/api/tools', async (req, res) => {\n try {\n const { getRegisteredTools } = await import('../agent/toolRunner.js');\n const q = typeof req.query.q === 'string' ? req.query.q.toLowerCase().trim() : '';\n const all = getRegisteredTools().map(t => ({\n name: t.name,\n description: typeof t.description === 'string' ? t.description.slice(0, 500) : '',\n parameters: t.parameters,\n }));\n const filtered = q\n ? all.filter(t => t.name.toLowerCase().includes(q) || t.description.toLowerCase().includes(q))\n : all;\n res.json({ tools: filtered, total: all.length, count: filtered.length });\n } catch (err) {\n res.status(500).json({ error: 'tools_unavailable', message: (err as Error).message });\n }\n });\n\n /**\n * POST /api/tools/run — invoke a tool by name. Widget runtime entry point\n * for `titan.tools.run(name, args)`. Subject to the same intent / approval\n * gates as the agent's own calls.\n */\n app.post('/api/tools/run', async (req, res) => {\n try {\n const { name, args } = (req.body || {}) as { name?: string; args?: Record<string, unknown> };\n if (!name || typeof name !== 'string') {\n res.status(400).json({ error: 'invalid_input', message: '\"name\" is required.' });\n return;\n }\n const { executeTool } = await import('../agent/toolRunner.js');\n const result = await executeTool({\n id: `widget-${Date.now()}`,\n type: 'function',\n function: { name, arguments: JSON.stringify(args || {}) },\n });\n res.json({\n name: result.name,\n success: result.success !== false,\n content: result.content,\n });\n } catch (err) {\n res.status(500).json({ error: 'tool_run_failed', message: (err as Error).message });\n }\n });\n\n /**\n * GET /api/memory/:key — read a single memory value. Widget-friendly\n * minimal surface; uses the `widget` category to keep widget-scoped\n * facts separate from the agent's general memory namespace.\n */\n app.get('/api/memory/:key', async (req, res) => {\n try {\n const { recallFact } = await import('../memory/memory.js');\n const value = recallFact('widget', req.params.key);\n res.json({ key: req.params.key, value: value ?? null });\n } catch (err) {\n res.status(500).json({ error: 'memory_read_failed', message: (err as Error).message });\n }\n });\n\n /** POST /api/memory — write a single key/value to the widget memory category. */\n app.post('/api/memory', async (req, res) => {\n try {\n const { key, value } = (req.body || {}) as { key?: string; value?: unknown };\n if (!key || typeof key !== 'string') {\n res.status(400).json({ error: 'invalid_input', message: '\"key\" is required.' });\n return;\n }\n const { rememberFact } = await import('../memory/memory.js');\n const v = typeof value === 'string' ? value : JSON.stringify(value);\n rememberFact('widget', key, v);\n res.json({ key, stored: true });\n } catch (err) {\n res.status(500).json({ error: 'memory_write_failed', message: (err as Error).message });\n }\n });\n\n /** GET /api/persona/current — convenience endpoint for `titan.persona`. */\n app.get('/api/persona/current', async (_req, res) => {\n try {\n const { getActivePersonaContent } = await import('../personas/manager.js');\n const cfg = loadConfig();\n const personaId = cfg.agent?.persona || 'default';\n const content = getActivePersonaContent(personaId);\n res.json({ content: content || null, personaId });\n } catch (err) {\n res.status(500).json({ error: 'persona_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0 Step 4 — Spaces REST API. The SPA's Spaces sidebar reads + writes\n // the server-side `~/.titan/spaces.json` via these endpoints. The agent's\n // canvas_spaces tools mutate the same file, so the SPA + agent agree on\n // a single source of truth regardless of which one made the change.\n app.get('/api/spaces', async (_req, res) => {\n try {\n const { readSpaces, getActiveSpace } = await import('../storage/spaces.js');\n const file = readSpaces();\n const active = getActiveSpace();\n res.json({\n spaces: file.spaces,\n activeSpaceId: active?.id ?? null,\n });\n } catch (err) {\n res.status(500).json({ error: 'spaces_unavailable', message: (err as Error).message });\n }\n });\n\n app.post('/api/spaces', async (req, res) => {\n try {\n const { createSpace } = await import('../storage/spaces.js');\n const { name, icon, color, agentInstructions, starterWidgets, makeActive } = (req.body || {}) as Record<string, unknown>;\n if (typeof name !== 'string' || !name.trim()) {\n res.status(400).json({ error: 'invalid_input', message: '\"name\" is required.' });\n return;\n }\n const space = createSpace({\n name: name.trim(),\n icon: typeof icon === 'string' ? icon : undefined,\n color: typeof color === 'string' ? color : undefined,\n agentInstructions: typeof agentInstructions === 'string' ? agentInstructions : undefined,\n starterWidgets: Array.isArray(starterWidgets) ? starterWidgets : undefined,\n makeActive: Boolean(makeActive),\n });\n res.json({ space });\n } catch (err) {\n res.status(500).json({ error: 'create_failed', message: (err as Error).message });\n }\n });\n\n app.patch('/api/spaces/:id', async (req, res) => {\n try {\n const { updateSpace } = await import('../storage/spaces.js');\n const patch = (req.body || {}) as Record<string, unknown>;\n const space = updateSpace(req.params.id, {\n name: typeof patch.name === 'string' ? patch.name : undefined,\n icon: typeof patch.icon === 'string' ? patch.icon : undefined,\n color: typeof patch.color === 'string' ? patch.color : undefined,\n agentInstructions: typeof patch.agentInstructions === 'string' ? patch.agentInstructions : undefined,\n widgets: Array.isArray(patch.widgets) ? patch.widgets : undefined,\n });\n if (!space) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json({ space });\n } catch (err) {\n res.status(500).json({ error: 'update_failed', message: (err as Error).message });\n }\n });\n\n app.post('/api/spaces/:id/activate', async (req, res) => {\n try {\n const { switchSpace } = await import('../storage/spaces.js');\n const space = switchSpace(req.params.id);\n if (!space) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json({ space });\n } catch (err) {\n res.status(500).json({ error: 'switch_failed', message: (err as Error).message });\n }\n });\n\n app.delete('/api/spaces/:id', async (req, res) => {\n try {\n const { archiveSpace } = await import('../storage/spaces.js');\n const result = archiveSpace(req.params.id);\n if (!result) {\n res.status(404).json({ error: 'not_found' });\n return;\n }\n res.json({ archived: result.archived, remaining: result.remaining });\n } catch (err) {\n res.status(500).json({ error: 'archive_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/spaces/presets', async (_req, res) => {\n try {\n const { listStarterPresets } = await import('../storage/starterSpaces.js');\n res.json({ presets: listStarterPresets() });\n } catch (err) {\n res.status(500).json({ error: 'presets_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0 Step 13 — Soma drive state surface for the mascot + status bar.\n // Returns CURRENT drive levels (organism layer) + per-user BASELINE\n // (Soma profile). The SPA's mascot listens to this and renders the\n // mood-tint, breathing animation, and \"TITAN is curious / focused /\n // frustrated\" status-bar text.\n //\n // v6.0.3 — Previously this endpoint mapped neurotransmitter names\n // (dopamine, cortisol, norepinephrine) onto drive ids, but Soma stores\n // drives by id (curiosity, hunger, safety, social, purpose), so every\n // field always missed and the mascot read a flat baseline. Now we\n // surface the REAL drive levels — the mascot's mood actually moves.\n app.get('/api/soma/drives', async (req, res) => {\n try {\n const userId = getUserIdFromReq(req as Parameters<typeof getUserIdFromReq>[0]);\n const { readSomaProfile } = await import('../storage/somaProfile.js');\n const profile = readSomaProfile(userId);\n let current: Record<string, number> | null = null;\n let asOf: string | null = null;\n try {\n const { getHormonalState } = await import('../organism/hormones.js');\n const state = getHormonalState();\n if (state.available) {\n current = { ...state.levels };\n asOf = state.asOf;\n }\n } catch { /* organism may be off — fall back to baseline */ }\n // Build a baseline that includes every drive present in `current`\n // (the Soma drive layer ships purpose/hunger/curiosity/safety/social;\n // the per-user Soma profile stores per-drive baselines — but those\n // are keyed by feel-name, not drive-id, so we synthesise a neutral\n // 0.7 baseline for any drive id the profile doesn't cover. Without\n // this the deviation math compares hunger=0.15 to baseline=0\n // and reports an artificial delta of +0.15, instead of correctly\n // flagging hunger as low).\n const baseline: Record<string, number> = { ...profile.baseline };\n if (current) {\n for (const k of Object.keys(current)) {\n if (!(k in baseline)) baseline[k] = 0.7;\n }\n }\n res.json({\n userId,\n baseline,\n current: current ?? baseline,\n asOf,\n dominant: pickDominantDrive(current ?? baseline, baseline),\n });\n } catch (err) {\n res.status(500).json({ error: 'soma_drives_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Full Soma state. Returns the latest persisted drive tick + the\n // hormonal block the SOMA page needs to render the elevated-drive line\n // (\"Body state: hunger 15% · curiosity 37%\") and the inspector\n // sparklines. Previously this endpoint didn't exist; the SomaView fell\n // back to /api/watch/snapshot which doesn't include the hormonal block,\n // so it always showed \"All drives satiated — routine operation.\"\n app.get('/api/soma/state', async (_req, res) => {\n try {\n const cfg = loadConfig();\n const organismEnabled = (cfg.organism as { enabled?: boolean } | undefined)?.enabled ?? true;\n const { loadDriveHistory } = await import('../organism/drives.js');\n const { buildBlock } = await import('../organism/hormones.js');\n const history = loadDriveHistory();\n if (!history) {\n res.json({\n enabled: organismEnabled,\n message: organismEnabled\n ? 'Soma is enabled but no drive tick has run yet. Wait ~60s.'\n : 'Soma is disabled. Enable via organism.enabled in config.',\n drives: [],\n totalPressure: 0,\n dominantDrives: [],\n hormonal: { available: false, asOf: null, levels: {}, elevated: [], dominant: null },\n });\n return;\n }\n const block = buildBlock(history.latest.drives, history.latest.timestamp);\n res.json({\n enabled: organismEnabled,\n timestamp: history.latest.timestamp,\n drives: history.latest.drives,\n totalPressure: history.latest.totalPressure,\n dominantDrives: history.latest.dominantDrives,\n hormonal: block,\n });\n } catch (err) {\n res.status(500).json({ error: 'soma_state_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Ring-buffered drive history. Used by the SOMA page for\n // sparklines + the \"last 24h\" trend graphs. `hours` query param caps\n // the slice; default 24h.\n app.get('/api/soma/history', async (req, res) => {\n try {\n const cfg = loadConfig();\n const organismEnabled = (cfg.organism as { enabled?: boolean } | undefined)?.enabled ?? true;\n const { loadDriveHistory } = await import('../organism/drives.js');\n const hours = Math.max(1, Math.min(168, parseInt(String(req.query.hours ?? '24'), 10) || 24));\n const history = loadDriveHistory();\n if (!history) {\n res.json({ enabled: organismEnabled, history: [], latest: null });\n return;\n }\n const cutoff = Date.now() - hours * 60 * 60 * 1000;\n const slice = history.history.filter(p => new Date(p.timestamp).getTime() >= cutoff);\n res.json({ enabled: organismEnabled, history: slice, latest: history.latest });\n } catch (err) {\n res.status(500).json({ error: 'soma_history_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Recent Soma advisories (somaInitiative pulses that didn't\n // map to 'nothing'). The canvas notification card polls this; the\n // mascot speech bubble can quote the most recent one.\n app.get('/api/soma/advisories', async (req, res) => {\n try {\n const userId = getUserIdFromReq(req as Parameters<typeof getUserIdFromReq>[0]);\n const { readRecentAdvisories } = await import('../agent/somaInitiative.js');\n const limit = Math.max(1, Math.min(50, parseInt(String(req.query.limit ?? '10'), 10) || 10));\n const advisories = readRecentAdvisories(userId, limit);\n res.json({ userId, advisories });\n } catch (err) {\n res.status(500).json({ error: 'advisories_unavailable', message: (err as Error).message });\n }\n });\n\n // v6.0.5 — Time Travel surface. TITAN's shadow-git layer\n // (~/.titan/file-checkpoints/) already snapshots every file before any\n // write/edit/append tool runs, but pre-v6.0.5 we had no UI for it.\n // These three endpoints expose:\n // GET /api/time-travel/checkpoints → newest-first list, optional ?file= filter\n // GET /api/time-travel/diff/:id → diff vs current file\n // POST /api/time-travel/restore/:id → restore the file to that checkpoint\n app.get('/api/time-travel/checkpoints', async (req, res) => {\n try {\n const { listAllCheckpoints, listCheckpoints } = await import('../agent/shadowGit.js');\n const file = typeof req.query.file === 'string' ? req.query.file : '';\n const limit = Math.max(1, Math.min(500, parseInt(String(req.query.limit ?? '100'), 10) || 100));\n const checkpoints = file ? listCheckpoints(file) : listAllCheckpoints(limit);\n res.json({ count: checkpoints.length, checkpoints });\n } catch (err) {\n res.status(500).json({ error: 'time_travel_list_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/time-travel/diff/:id', async (req, res) => {\n try {\n const { diffCheckpoint } = await import('../agent/shadowGit.js');\n const id = String(req.params.id || '').trim();\n if (!id) { res.status(400).json({ error: 'missing_checkpoint_id' }); return; }\n const diff = diffCheckpoint(id);\n res.json({ checkpointId: id, diff });\n } catch (err) {\n res.status(500).json({ error: 'time_travel_diff_failed', message: (err as Error).message });\n }\n });\n\n app.post('/api/time-travel/restore/:id', async (req, res) => {\n try {\n const { restoreCheckpoint } = await import('../agent/shadowGit.js');\n const id = String(req.params.id || '').trim();\n if (!id) { res.status(400).json({ error: 'missing_checkpoint_id' }); return; }\n const result = restoreCheckpoint(id);\n const ok = !result.toLowerCase().startsWith('restore failed') && !result.toLowerCase().startsWith('no checkpoints') && !result.toLowerCase().includes('not found');\n res.json({ ok, checkpointId: id, message: result });\n } catch (err) {\n res.status(500).json({ error: 'time_travel_restore_failed', message: (err as Error).message });\n }\n });\n\n // v6.0.0-beta.4 — Mission API. The \"work without me\" surface.\n //\n // TITAN already has a deep autonomy stack: durable journal, stateless\n // reducer, 11-phase goal driver, crash recovery, budget enforcement.\n // What was missing was an ergonomic entry point (one prompt → an\n // autonomous mission) and live visibility (what's the driver doing\n // right now? what got done overnight?). These five endpoints close that\n // gap and feed the Mission Driver + Daily Digest canvas widgets.\n //\n // POST /api/mission/run → single-prompt mission creation\n // GET /api/missions/active → live driver state for every active goal\n // GET /api/missions/recent?hours= → completed goals in last N hours\n // GET /api/missions/digest?hours= → human-readable \"what got done\" summary\n // POST /api/mission/:id/cancel → cancel a running mission\n\n app.post('/api/mission/run', async (req, res) => {\n try {\n const description = String(req.body?.description ?? req.body?.prompt ?? '').trim();\n if (!description || description.length < 10) {\n res.status(400).json({ error: 'description_required', message: 'Provide a description (>=10 chars) of what TITAN should accomplish autonomously.' });\n return;\n }\n const title = String(req.body?.title ?? '').trim() || description.split(/[.!?\\n]/)[0].slice(0, 80);\n const priority = Math.max(1, Math.min(5, Number(req.body?.priority) || 3));\n const budgetLimit = Math.max(0.01, Math.min(50, Number(req.body?.budgetUsd) || 2));\n const tags: string[] = Array.isArray(req.body?.tags) ? req.body.tags.map(String) : ['mission', 'autonomous'];\n\n // Decompose the description into 3–6 subtasks via the LLM. Use the\n // small/fast tier — this is a one-shot planning call, not an agent\n // loop. The driver then ticks through the subtasks autonomously.\n let subtasks: Array<{ title: string; description: string; dependsOn?: string[] }> | undefined = undefined;\n try {\n const { spawnSubAgent } = await import('../agent/subAgent.js');\n const decomposePrompt = [\n `Decompose this autonomous mission into 3-6 concrete, independently-runnable subtasks.`,\n ``,\n `Mission: ${description}`,\n ``,\n `Return STRICT JSON: { \"subtasks\": [ { \"title\": \"...\", \"description\": \"...\" }, ... ] }.`,\n `Each title <= 60 chars, each description <= 200 chars.`,\n `Order subtasks dependency-aware (later ones may reference earlier output).`,\n `Do NOT add a verification subtask — the driver verifies automatically.`,\n `Do NOT wrap in markdown — pure JSON.`,\n ].join('\\n');\n const result = await spawnSubAgent({\n name: 'mission-decomposer',\n task: decomposePrompt,\n tier: 'fast',\n maxRounds: 1,\n });\n const raw = (result.content || '').trim();\n const jsonStart = raw.indexOf('{');\n const jsonEnd = raw.lastIndexOf('}');\n if (jsonStart >= 0 && jsonEnd > jsonStart) {\n const parsed = JSON.parse(raw.slice(jsonStart, jsonEnd + 1)) as { subtasks?: Array<{ title?: string; description?: string }> };\n if (Array.isArray(parsed.subtasks) && parsed.subtasks.length >= 1) {\n subtasks = parsed.subtasks\n .filter(s => typeof s?.title === 'string' && typeof s?.description === 'string')\n .slice(0, 6)\n .map(s => ({ title: String(s.title).slice(0, 80), description: String(s.description).slice(0, 280) }));\n }\n }\n } catch (err) {\n logger.warn(COMPONENT, `Mission decomposition failed, creating goal with no subtasks: ${(err as Error).message}`);\n }\n\n const { createGoal } = await import('../agent/goals.js');\n const goal = createGoal({\n title,\n description,\n priority,\n budgetLimit,\n tags,\n subtasks,\n force: req.body?.force === true,\n });\n logger.info(COMPONENT, `[Mission] Created mission goal \"${title}\" (id=${goal.id}, subtasks=${(subtasks?.length ?? 0)})`);\n res.json({\n ok: true,\n goal: { id: goal.id, title: goal.title, status: goal.status, priority: goal.priority, subtaskCount: goal.subtasks?.length ?? 0 },\n message: subtasks?.length\n ? `Mission \"${title}\" created with ${subtasks.length} subtasks. Driver will pick it up on the next tick (within 10s).`\n : `Mission \"${title}\" created. Decomposition skipped — add subtasks via the Goals API or chat.`,\n });\n } catch (err) {\n res.status(500).json({ error: 'mission_create_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/missions/active', async (_req, res) => {\n try {\n const { listActiveDrivers } = await import('../agent/goalDriver.js');\n const { listGoals } = await import('../agent/goals.js');\n const drivers = listActiveDrivers();\n const goals = listGoals('active');\n const goalsById = new Map(goals.map(g => [g.id, g]));\n const missions = drivers.map(d => {\n const goal = goalsById.get(d.goalId);\n const completed = Object.values(d.subtaskStates).filter(s => s.verificationResult?.passed === true).length;\n const total = Object.keys(d.subtaskStates).length || (goal?.subtasks?.length ?? 0);\n return {\n goalId: d.goalId,\n title: goal?.title || '(unknown goal)',\n phase: d.phase,\n startedAt: d.startedAt,\n currentSubtaskId: d.currentSubtaskId ?? null,\n subtasks: { total, completed },\n budget: d.budget,\n blockedReason: d.blockedReason ?? null,\n lastHistory: (d.history || []).slice(-3),\n };\n });\n res.json({ count: missions.length, missions });\n } catch (err) {\n res.status(500).json({ error: 'missions_active_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/missions/recent', async (req, res) => {\n try {\n const hours = Math.max(1, Math.min(168, parseInt(String(req.query.hours ?? '24'), 10) || 24));\n const { listAllDrivers } = await import('../agent/goalDriver.js');\n const { listGoals } = await import('../agent/goals.js');\n const all = listAllDrivers();\n const cutoff = Date.now() - hours * 60 * 60 * 1000;\n const goalsById = new Map(listGoals().map(g => [g.id, g]));\n const recent = all\n .filter(d => ['done', 'failed', 'cancelled'].includes(d.phase))\n .filter(d => {\n const completedAt = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return new Date(completedAt).getTime() >= cutoff;\n })\n .map(d => {\n const goal = goalsById.get(d.goalId);\n const completedAt = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return {\n goalId: d.goalId,\n title: goal?.title || '(unknown goal)',\n phase: d.phase as 'done' | 'failed' | 'cancelled',\n startedAt: d.startedAt,\n completedAt,\n durationMs: new Date(completedAt).getTime() - new Date(d.startedAt).getTime(),\n subtaskCount: Object.keys(d.subtaskStates).length || (goal?.subtasks?.length ?? 0),\n budget: d.budget,\n lessonsLearned: d.retrospective?.lessonsLearned ?? [],\n };\n })\n .sort((a, b) => (a.completedAt < b.completedAt ? 1 : -1));\n res.json({ hours, count: recent.length, missions: recent });\n } catch (err) {\n res.status(500).json({ error: 'missions_recent_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/missions/digest', async (req, res) => {\n try {\n const hours = Math.max(1, Math.min(168, parseInt(String(req.query.hours ?? '24'), 10) || 24));\n const { listAllDrivers, listActiveDrivers } = await import('../agent/goalDriver.js');\n const { listGoals } = await import('../agent/goals.js');\n const cutoff = Date.now() - hours * 60 * 60 * 1000;\n const all = listAllDrivers();\n const active = listActiveDrivers();\n const goalsById = new Map(listGoals().map(g => [g.id, g]));\n const completed = all.filter(d => d.phase === 'done').filter(d => {\n const at = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return new Date(at).getTime() >= cutoff;\n });\n const failed = all.filter(d => d.phase === 'failed').filter(d => {\n const at = d.history?.[d.history.length - 1]?.at ?? d.startedAt;\n return new Date(at).getTime() >= cutoff;\n });\n const blocked = active.filter(d => d.phase === 'blocked');\n const totalCostUsd = [...completed, ...failed].reduce((sum, d) => sum + (d.budget?.costUsd ?? 0), 0);\n const totalTokens = [...completed, ...failed].reduce((sum, d) => sum + (d.budget?.tokensUsed ?? 0), 0);\n const lessons = completed.flatMap(d => d.retrospective?.lessonsLearned ?? []).slice(0, 10);\n\n const summary: string[] = [];\n summary.push(`Last ${hours}h: ${completed.length} mission(s) completed, ${failed.length} failed, ${active.length} active, ${blocked.length} blocked for approval.`);\n if (completed.length > 0) {\n summary.push(``);\n summary.push(`Completed:`);\n for (const d of completed.slice(0, 10)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId} (${Math.round((d.budget?.costUsd ?? 0) * 100) / 100} USD, ${Math.round(((d.history?.[d.history.length - 1]?.at ? new Date(d.history[d.history.length - 1].at).getTime() : Date.now()) - new Date(d.startedAt).getTime()) / 1000)}s)`);\n }\n }\n if (failed.length > 0) {\n summary.push(``);\n summary.push(`Failed (need review):`);\n for (const d of failed.slice(0, 5)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId}`);\n }\n }\n if (blocked.length > 0) {\n summary.push(``);\n summary.push(`Blocked for approval:`);\n for (const d of blocked.slice(0, 5)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId} — ${d.blockedReason?.question ?? '(no reason given)'}`);\n }\n }\n if (active.length > 0 && blocked.length < active.length) {\n summary.push(``);\n summary.push(`In progress:`);\n for (const d of active.filter(a => a.phase !== 'blocked').slice(0, 10)) {\n const g = goalsById.get(d.goalId);\n summary.push(` • ${g?.title ?? d.goalId} [${d.phase}]`);\n }\n }\n\n res.json({\n hours,\n stats: {\n completed: completed.length,\n failed: failed.length,\n active: active.length,\n blocked: blocked.length,\n totalCostUsd: Math.round(totalCostUsd * 1000) / 1000,\n totalTokens,\n },\n summaryText: summary.join('\\n'),\n recentLessons: lessons,\n });\n } catch (err) {\n res.status(500).json({ error: 'mission_digest_failed', message: (err as Error).message });\n }\n });\n\n app.get('/api/mission/:id', async (req, res) => {\n try {\n const goalId = String(req.params.id || '').trim();\n if (!goalId) { res.status(400).json({ error: 'missing_goal_id' }); return; }\n const { getGoal } = await import('../agent/goals.js');\n const { getDriverState } = await import('../agent/goalDriver.js');\n const goal = getGoal(goalId);\n if (!goal) { res.status(404).json({ error: 'goal_not_found' }); return; }\n const state = getDriverState(goalId);\n res.json({\n goal: {\n id: goal.id,\n title: goal.title,\n description: goal.description,\n status: goal.status,\n priority: goal.priority,\n progress: goal.progress,\n totalCost: goal.totalCost,\n createdAt: goal.createdAt,\n completedAt: goal.completedAt,\n tags: goal.tags ?? [],\n subtasks: (goal.subtasks ?? []).map(s => ({\n id: s.id,\n title: s.title,\n description: s.description,\n status: s.status,\n dependsOn: s.dependsOn ?? [],\n retries: s.retries,\n completedAt: s.completedAt,\n })),\n },\n driver: state ? {\n phase: state.phase,\n startedAt: state.startedAt,\n currentSubtaskId: state.currentSubtaskId ?? null,\n budget: state.budget,\n blockedReason: state.blockedReason ?? null,\n historyTail: (state.history ?? []).slice(-10),\n subtaskStates: state.subtaskStates,\n } : null,\n });\n } catch (err) {\n res.status(500).json({ error: 'mission_get_failed', message: (err as Error).message });\n }\n });\n\n app.post('/api/mission/:id/cancel', async (req, res) => {\n try {\n const goalId = String(req.params.id || '').trim();\n if (!goalId) { res.status(400).json({ error: 'missing_goal_id' }); return; }\n const { getDriverState } = await import('../agent/goalDriver.js');\n const { updateGoal } = await import('../agent/goals.js');\n const state = getDriverState(goalId);\n if (state) {\n state.userControls.cancelRequested = true;\n // The driver will observe this on its next tick and transition.\n }\n updateGoal(goalId, { status: 'paused' });\n res.json({ ok: true, message: `Mission ${goalId} marked for cancellation. Driver will stop on the next tick.` });\n } catch (err) {\n res.status(500).json({ error: 'mission_cancel_failed', message: (err as Error).message });\n }\n });\n\n // v6.0.3 — Manual trigger for the daily-gift loop. The 22h cron path\n // still fires on its own; this endpoint lets the user click \"send me\n // something now\" in the SOMA panel and see what Soma comes up with\n // without waiting a day. We bypass the 18h cooldown by passing a\n // `force` flag (the gift module respects this).\n app.post('/api/soma/gift', async (req, res) => {\n try {\n const userId = getUserIdFromReq(req as Parameters<typeof getUserIdFromReq>[0]);\n const force = req.body?.force !== false;\n const { tryDailyGift } = await import('../agent/somaInitiative.js');\n // Fire-and-forget — the LLM call inside can take 20-60s; we don't\n // want the HTTP request to block that long. The result lands as a\n // create_widget side-channel event on the user's open SSE stream.\n void tryDailyGift(userId, { force }).then(result => {\n logger.info(COMPONENT, `[SomaGift] manual trigger: attempted=${result.attempted} reason=${result.reason}`);\n }).catch(err => {\n logger.warn(COMPONENT, `[SomaGift] manual trigger failed: ${(err as Error).message}`);\n });\n res.json({ ok: true, message: 'Soma is thinking about what to gift you. A widget will appear on your canvas shortly (or Soma will decline if nothing fits).' });\n } catch (err) {\n res.status(500).json({ error: 'gift_unavailable', message: (err as Error).message });\n }\n });\n\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 (v6.0 — TIGHTENED + Bucket-C-aware) ─═══\n // Fast-path: when the user is EXPLICITLY asking to add a known system\n // widget — \"add the cron widget\", \"open the VRAM dashboard\", \"pin the\n // training panel\" — bypass the LLM and emit the _____widget gate\n // directly. Faster + deterministic for unambiguous asks.\n //\n // ## History\n //\n // - v5.5.28 fix: gated the shortcut on `hasExplicitWidgetIntent` (the\n // message must mention a widget-noun). Helped, but still too loose.\n // Words like \"tools\" or \"panel\" appear in normal English (\"the\n // fb_post tool\", \"control panel\") and would flip the gate to true,\n // then any inner trigger like \"backup\" or \"training\" would hijack\n // the prompt.\n //\n // - v6.0 fix (now): **require an IMPERATIVE verb + widget noun\n // together**, NOT just one of them. The whole point of v6.0 is\n // \"generation-first\" — TITAN builds custom widgets on demand,\n // doesn't shove users into a pre-built shortcut. The shortcut now\n // only fires for true imperative asks. Also drops 'tools' and\n // 'monitor' from the noun list (both too noisy). Also drops the\n // killed-Bucket-C panels (paperclip).\n //\n // Test coverage: tests/unit/widget-shortcut-hijack.test.ts\n const imperativeRe = /\\b(?:add|open|show|pin|create|launch|put|give\\s+me|i\\s+want|let'?s\\s+see|i\\s+need)\\b/i;\n const widgetNounRe = /\\b(?:widget|panel|dashboard|hub|gallery|kitchen|scheduler)\\b/i;\n const hasExplicitWidgetIntent = imperativeRe.test(content) && widgetNounRe.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|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|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|form fill|web automation)\\b/i, source: 'system:browser', name: 'Browser Tools', w: 6, h: 5 },\n // v6.0 step 1 — system:paperclip removed (Bucket C / killed branding).\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 // Hoisted so the `finally` block can release the widget side-channel\n // subscription whether the request streamed, errored, or finished early.\n let unsubscribeWidgets: (() => void) | null = null;\n // v6.0.2 — SSE keep-alive heartbeat. Cloud models (e.g. deepseek-v4-pro)\n // can spend 60-180s in a single non-streaming `think` phase. The frontend\n // (ui/src/api/client.ts) treats >60s of total silence as a dead stream\n // and aborts. SSE comment lines (`:<text>\\n\\n`) reset the client read\n // timer without affecting event parsing. Emit one every 15s for the\n // lifetime of the stream so long thinks no longer trigger phantom\n // \"stream went silent\" errors.\n let heartbeatInterval: ReturnType<typeof setInterval> | 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 // Fire the first heartbeat immediately + every 15s thereafter. Stays\n // under the client's 60s quiet ceiling with plenty of headroom even\n // if one heartbeat is delayed by event-loop pressure.\n heartbeatInterval = setInterval(() => {\n if (clientDisconnected) return;\n safeWrite(`: heartbeat ${Date.now()}\\n\\n`);\n }, 15_000);\n\n // Canvas widget side-channel — subscribe to the per-session widget\n // bus for the duration of this stream and forward events as their\n // own SSE event type. Released in the finally block below so we\n // never leak listeners. See src/agent/widgetEmitter.ts.\n if (requestedSessionId) {\n try {\n const { subscribe: subscribeWidgets } = await import('../agent/widgetEmitter.js');\n unsubscribeWidgets = subscribeWidgets(requestedSessionId, (evt) => {\n safeWrite(`event: widget\\ndata: ${JSON.stringify({ mode: evt.mode, widget: evt.widget, timestamp: evt.timestamp })}\\n\\n`);\n });\n } catch (err) {\n logger.warn(COMPONENT, `widgetEmitter subscribe failed: ${err instanceof Error ? err.message : String(err)}`);\n }\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 // onWidget is wired through the widgetEmitter subscription above\n // rather than through this callback bag, because the tool that\n // fires it (create_widget) runs in toolRunner.ts and has its own\n // direct path to the per-session bus.\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 // Release the canvas-widget side-channel subscription (if any) so the\n // emitter doesn't accumulate dead listeners across long-lived servers.\n if (unsubscribeWidgets) {\n try { unsubscribeWidgets(); } catch { /* never let cleanup break the request */ }\n }\n // Stop the SSE heartbeat — must clear on every exit path or the\n // interval leaks for the lifetime of the process.\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = null;\n }\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 // v6.0.1 — Model-agnostic boot diagnostic. Log which provider TITAN\n // resolved for the default agent model + why. Users see at a glance\n // whether the picker chose what they expected (e.g. \"openai because\n // OPENAI_API_KEY is set\") and can correct their env / config.\n try {\n // Lazy require so the picker stays tree-shakeable + side-effect-free.\n void import('../providers/defaultModel.js').then(({ pickDefaultModel }) => {\n const pick = pickDefaultModel();\n logger.info(COMPONENT, `Default model: ${pick.model} (${pick.provider}) — ${pick.reason}`);\n }).catch(() => { /* non-critical */ });\n } catch { /* non-critical */ }\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":";AAIA,OAAO,aAAiE;AACxE,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,yBAAyB;AAClD,OAAO,SAAS;AAChB,SAAS,MAAM,eAAwB;AACvC,SAAS,qBAAqB;AAC9B,SAAS,SAAS,YAAY,YAAY,MAAM,eAAe;AAC/D,SAAS,aAAa,uBAAuB;AAC7C,SAAS,MAAgB,aAAa;AACtC,OAAO,QAAQ;AACf,SAAS,YAAY,oBAAoB;AAEzC,SAAS,aAAa,mBAAyC;AAC/D,SAAS,sBAAsB;AAC/B,SAAS,oBAAoB;AAC7B,SAAS,YAAY,aAAa,qBAAwC;AAC1E,SAAS,mBAAmB,iBAA6C;AAGzE,SAAS,0BAA0B;AACnC,SAAS,cAAc,4BAA4B;AACnD,SAAS,gBAAgB,mBAAmB,iBAAiB,YAAY,wBAAwB;AAEjG,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,yBAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAC5B,SAAS,2BAA2B;AACpC,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AACjC,SAAS,YAAY,cAAc,kBAAkB;AACrD,SAAS,gCAAgC;AAEzC,OAAO,UAAU,sBAAsB;AACvC,SAAS,eAAe,YAAY,gBAAgB,kBAAkB;AACtE,SAAS,mBAAmB,2BAA2B;AACvD,SAA+B,wBAAwB,+BAA+B;AACtF,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,qBAAwC,oBAAoB,sBAAsB,kBAAkB,qBAAqB,qBAAqB,kBAAkB,+BAA0F;AACnQ,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,mBAAmB,0BAA0B;AACtD,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,cAAc,0BAA0B,cAAc,YAAY,eAAe,wBAAwB;AAClH,SAAS,0BAA0B;AACnC,SAAS,mBAAmB,iBAAiB;AAC7C,SAAS,qBAAqB;AAC9B,SAAS,cAAc,wBAAwB;AAC/C,SAAS,WAA0B,YAAY,kBAAkB;AACjE,SAAS,sBAAsB;AAE/B,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,+BAA+B;AACxC,SAAS,eAAe,qBAAyC;AACjE,SAAS,YAAY,YAAY,mBAAmB;AACpD,SAAS,iBAAiB,qBAAqB,sBAAsB,uBAAuB;AAC5F,SAAS,wBAAwB;AACjC,SAAS,8BAA8B;AAEvC,SAAS,aAAa,kBAAmC;AACzD,SAAS,uBAAuB,+BAA+B;AAC/D,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,yBAAyB;AAClC,SAAS,gCAAgC;AACzC,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAElC,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AAEtC,SAAS,2BAA2B;AAEpC,MAAM,YAAY;AAGlB,SAAS,aAAqB;AAC1B,QAAM,MAAM,QAAQ,EAAE,CAAC;AACvB,QAAM,QAAQ,KAAK,EAAE,UAAU;AAC/B,SAAO,KAAK,IAAI,GAAG,MAAM,KAAK;AAClC;AAGA,MAAM,4BAA4B,CAAC,cAAc,kBAAkB,eAAe;AAGlF,IAAI,aAAqD;AAGzD,IAAI,uBAA8D;AAClE,IAAI,2BAAkE;AACtE,IAAI,wBAA+D;AACnE,IAAI,8BAAqE;AACzE,IAAI,yBAA8C;AAClD,IAAI,oBAAoB;AACjB,SAAS,uBAA+B;AAAE,SAAO;AAAmB;AAC3E,IAAI,wBAAuC;AAI3C,MAAM,gBAAgB;AAAA,EAClB;AAAA,EAAwB;AAAA,EAA6B;AAAA,EACrD;AAAA,EAA4B;AAAA,EAA8B;AAAA,EAC1D;AAAA,EAA+B;AACnC;AACA,MAAM,kBAAkB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AACJ;AACA,SAAS,gBAAgB,QAAyB;AAC9C,SAAO,gBAAgB,KAAK,QAAM,GAAG,KAAK,MAAM,CAAC;AACrD;AA2BA,SAAS,kBAAkB,KAA+B;AACxD,QAAM,OAAO,IAAI,WAAW,OAAO,GAAG,GAAG,YAAY;AACrD,QAAM,SAAS,IAAI;AAGnB,MACE,IAAI,SAAS,mBAAmB,KAChC,IAAI,SAAS,YAAY,KACzB,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,oBAAoB,GACjC;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,QAAQ,QAAQ,aAAa,OAAO,gBAAgB;AAAA,IACtE;AAAA,EACF;AAGA,MACE,IAAI,SAAS,YAAY,KACzB,IAAI,SAAS,KAAK,KAClB,IAAI,SAAS,OAAO,KACpB,IAAI,SAAS,mBAAmB,GAChC;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,SAAS,QAAQ,IAAI,OAAO,QAAQ;AAAA,IACtD;AAAA,EACF;AAGA,MACE,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,iBAAiB,KAC9B,IAAI,SAAS,iBAAiB,KAC9B,IAAI,SAAS,yBAAyB,KACtC,IAAI,SAAS,oBAAoB,GACjC;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,QAAQ,QAAQ,aAAa,OAAO,cAAc;AAAA,IACpE;AAAA,EACF;AAGA,MACE,IAAI,SAAS,iBAAiB,KAC9B,IAAI,SAAS,eAAe,KAC5B,IAAI,SAAS,eAAe,KAC5B,IAAI,SAAS,iBAAiB,KAC9B,IAAI,SAAS,gBAAgB,GAC7B;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,QAAQ,QAAQ,aAAa,OAAO,eAAe;AAAA,IACrE;AAAA,EACF;AAGA,MACE,IAAI,SAAS,KAAK,KAClB,IAAI,SAAS,KAAK,KAClB,IAAI,SAAS,cAAc,KAC3B,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,iBAAiB,KAC9B,IAAI,SAAS,iBAAiB,GAC9B;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,QAAQ,QAAQ,aAAa,OAAO,gBAAgB;AAAA,IACtE;AAAA,EACF;AAGA,MACE,IAAI,SAAS,SAAS,KACtB,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,SAAS,GACtB;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,SAAS,QAAQ,IAAI,OAAO,QAAQ;AAAA,IACtD;AAAA,EACF;AAGA,MACE,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAChE,IAAI,SAAS,SAAS,KAAK,IAAI,SAAS,UAAU,GAClD;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,SAAS,QAAQ,IAAI,OAAO,QAAQ;AAAA,IACtD;AAAA,EACF;AAGA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS,UAAU;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAGA,MAAM,cAAc;AAAA,EAClB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,eAAe;AACjB;AAEO,SAAS,cAA6B;AACzC,SAAO,IAAI,QAAQ,CAACA,aAAY;AAE5B,QAAI,sBAAsB;AAAE,oBAAc,oBAAoB;AAAG,6BAAuB;AAAA,IAAM;AAC9F,QAAI,0BAA0B;AAAE,oBAAc,wBAAwB;AAAG,iCAA2B;AAAA,IAAM;AAC1G,QAAI,uBAAuB;AAAE,oBAAc,qBAAqB;AAAG,8BAAwB;AAAA,IAAM;AACjG,QAAI,6BAA6B;AAAE,oBAAc,2BAA2B;AAAG,oCAA8B;AAAA,IAAM;AACnH,QAAI,wBAAwB;AAAE,6BAAuB;AAAG,+BAAyB;AAAA,IAAM;AAEvF,QAAI,YAAY;AAEZ,YAAM,eAAe,WAAW,MAAM;AAClC,eAAO,KAAK,WAAW,0DAAqD;AAC5E,oBAAY,sBAAsB;AAClC,qBAAa;AACb,QAAAA,SAAQ;AAAA,MACZ,GAAG,GAAI;AACP,mBAAa,MAAM;AAEnB,iBAAW,MAAM,MAAM;AACnB,qBAAa,YAAY;AACzB,qBAAa;AACb,QAAAA,SAAQ;AAAA,MACZ,CAAC;AAAA,IACL,OAAO;AACH,MAAAA,SAAQ;AAAA,IACZ;AAAA,EACJ,CAAC;AACL;AAcA,MAAM,WAAyB,CAAC;AAChC,MAAM,gBAAgB;AAGtB,MAAM,cAAiE;AAAA,EACrE,iBAAiB,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA,EACxC,gBAAgB,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EAC5C,eAAe,EAAE,OAAO,IAAI,QAAQ,GAAG;AAAA,EACvC,UAAU,EAAE,OAAO,KAAK,QAAQ,GAAG;AAAA,EACnC,eAAe,EAAE,OAAO,MAAM,QAAQ,IAAI;AAAA,EAC1C,eAAe,EAAE,OAAO,IAAI,QAAQ,GAAG;AAAA,EACvC,UAAU,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA;AAAA,EAChC,QAAQ,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EACpC,YAAY,EAAE,OAAO,MAAM,QAAQ,KAAK;AAC1C;AAEA,SAAS,aAAa,OAAe,cAAsB,kBAAkC;AAC3F,QAAM,MAAM,OAAO,KAAK,WAAW,EAAE,KAAK,OAAK,MAAM,YAAY,EAAE,SAAS,CAAC,CAAC;AAC9E,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,YAAY,GAAG;AAC7B,UAAQ,eAAe,MAAM,QAAQ,mBAAmB,MAAM,UAAU;AAC1E;AAEA,SAAS,WAAW,OAAe,YAAkE,YAAoB,WAAyB;AAChJ,MAAI,CAAC,WAAY;AACjB,QAAM,SAAS,WAAW,UAAU;AACpC,QAAM,aAAa,WAAW,cAAc;AAC5C,QAAM,WAAW,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI;AAC7D,QAAM,QAAoB;AAAA,IACxB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa,SAAS;AAAA,IACtB,kBAAkB,aAAa,OAAO,QAAQ,UAAU;AAAA,IACxD;AAAA,IACA;AAAA,EACF;AACA,WAAS,KAAK,KAAK;AACnB,MAAI,SAAS,SAAS,cAAe,UAAS,OAAO,GAAG,SAAS,SAAS,aAAa;AACzF;AAGA,MAAM,mBAAmB,KAAK,YAAY,kBAAkB;AAQ5D,SAAS,oBAA4B;AACjC,MAAI;AACA,UAAM,MAAM,WAAW;AACvB,UAAM,IAAI,IAAI,SAAS,MAAM;AAC7B,QAAI,OAAO,MAAM,YAAY,IAAI,EAAG,QAAO;AAAA,EAC/C,QAAQ;AAAA,EAAqB;AAC7B,SAAO,KAAK,KAAK,KAAK,KAAK;AAC/B;AAEA,SAAS,iBAAqE;AAC1E,QAAM,MAAM,oBAAI,IAAmD;AACnE,MAAI;AACA,QAAI,GAAG,WAAW,gBAAgB,GAAG;AACjC,YAAM,MAAM,KAAK,MAAM,GAAG,aAAa,kBAAkB,OAAO,CAAC;AACjE,UAAI,MAAM,QAAQ,GAAG,GAAG;AACpB,cAAM,QAAQ,kBAAkB;AAChC,cAAM,MAAM,KAAK,IAAI;AACrB,YAAI,UAAU;AACd,mBAAW,QAAQ,KAAK;AACpB,cAAI,QAAQ,OAAO,KAAK,UAAU,YAAY,OAAO,KAAK,cAAc,YAAY,OAAO,KAAK,WAAW,UAAU;AACjH,gBAAI,MAAM,KAAK,aAAa,OAAO;AAC/B,kBAAI,IAAI,KAAK,OAAO,EAAE,WAAW,KAAK,WAAW,QAAQ,KAAK,OAAO,CAAC;AAAA,YAC1E,OAAO;AACH;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AACA,YAAI,UAAU,GAAG;AACb,iBAAO,KAAK,WAAW,kBAAkB,OAAO,2CAA2C,KAAK,MAAM,QAAQ,IAAQ,CAAC,KAAK;AAAA,QAChI;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,QAAQ;AAAA,EAER;AACA,SAAO;AACX;AAEA,SAAS,iBAAuB;AAC5B,MAAI;AACA,UAAM,UAAU,CAAC;AACjB,eAAW,CAAC,OAAO,KAAK,KAAK,YAAY;AACrC,cAAQ,KAAK,EAAE,OAAO,WAAW,MAAM,WAAW,QAAQ,MAAM,OAAO,CAAC;AAAA,IAC5E;AACA,OAAG,cAAc,kBAAkB,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,EACvE,QAAQ;AAAA,EAER;AACJ;AAEA,MAAM,aAAa,eAAe;AAGlC,SAAS,iBAAiB,KAAsD;AAC9E,QAAM,QAAQ,IAAI,QAAQ,eAAe,QAAQ,WAAW,EAAE;AAC9D,MAAI,OAAO;AACT,UAAM,QAAQ,WAAW,IAAI,KAAK;AAClC,QAAI,MAAO,QAAO,MAAM;AAAA,EAC1B;AACA,SAAO;AACT;AAGA,MAAM,gBAAgB,oBAAI,IAA6B;AAEvD,MAAM,oBAAoB,oBAAI,IAAoB;AAGlD,MAAM,gBAAgB,oBAAI,IAAoB;AAG9C,8BAA8B,YAAY,MAAM;AAC5C,QAAM,MAAM,KAAK,IAAI;AACrB,aAAW,CAAC,IAAI,UAAU,KAAK,eAAe;AAC1C,QAAI,WAAW,OAAO,WAAY,OAAO,kBAAkB,IAAI,EAAE,KAAK,KAAM,KAAS;AACjF,oBAAc,OAAO,EAAE;AACvB,wBAAkB,OAAO,EAAE;AAC3B,oBAAc,OAAO,EAAE;AAAA,IAC3B;AAAA,EACJ;AACJ,GAAG,GAAM;AACT,4BAA4B,MAAM;AAMlC,uBAAuB,YAAY,MAAM;AACrC,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,QAAQ,kBAAkB;AAChC,MAAI,SAAS;AACb,aAAW,CAAC,KAAK,KAAK,KAAK,YAAY;AACnC,QAAI,MAAM,MAAM,YAAY,OAAO;AAAE,iBAAW,OAAO,GAAG;AAAG;AAAA,IAAU;AAAA,EAC3E;AAGA,MAAI,SAAS,GAAG;AACZ,WAAO,KAAK,WAAW,iBAAiB,MAAM,4BAA4B;AAC1E,mBAAe;AAAA,EACnB;AACJ,GAAG,GAAO;AACV,qBAAqB,MAAM;AAG3B,SAAS,YAAY,GAAW,GAAoB;AAChD,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,SAAO,gBAAgB,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC;AACzD;AAGA,SAAS,aAAa,OAA2B,QAAgD;AAC/F,QAAM,OAAO,OAAO,QAAQ;AAC5B,MAAI,CAAC,QAAQ,KAAK,SAAS,OAAQ,QAAO;AAC1C,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,KAAK,SAAS,SAAS;AACzB,QAAI,CAAC,KAAK,OAAO;AACf,aAAO,KAAK,WAAW,2HAAsH;AAC7I,aAAO;AAAA,IACT;AACA,WAAO,YAAY,OAAO,KAAK,KAAK;AAAA,EACtC;AACA,MAAI,KAAK,SAAS,YAAY;AAC5B,UAAM,QAAQ,WAAW,IAAI,KAAK;AAClC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,QAAQ,KAAK,KAAK,KAAK;AAC7B,QAAI,KAAK,IAAI,IAAI,MAAM,YAAY,OAAO;AACtC,iBAAW,OAAO,KAAK;AACvB,qBAAe;AACf,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGA,SAAS,eAAuB;AAC9B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDT;AAGA,MAAM,WAAwC,oBAAI,IAAI;AAOtD,MAAM,YAAkC,oBAAI,IAAI;AAChD,MAAM,uBAAuB,KAAK,OAAO;AAGzC,IAAI,iBAAwC;AAG5C,SAAS,UAAU,MAA+B,QAAuB;AACvE,QAAM,OAAO,KAAK,UAAU,IAAI;AAChC,aAAW,UAAU,WAAW;AAC9B,QAAI,OAAO,eAAe,UAAU,MAAM;AAExC,UAAI,UAAW,OAA2B,eAAgB,OAA2B,gBAAgB,OAAQ;AAC7G,UAAI;AACF,eAAO,KAAK,IAAI;AAAA,MAClB,SAAS,KAAK;AACZ,eAAO,KAAK,WAAW,0BAA2B,IAAc,OAAO,EAAE;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AACF;AAGA,yBAAyB,aAAa,CAAC,UAAU;AAC7C,QAAM,UAAU,MAAM,SAAS,cAAc,cAAc,MAAM,SAAS,aAAa,aAAa,MAAM;AAC1G,YAAU,EAAE,MAAM,SAAS,GAAG,MAAM,MAAM,WAAW,MAAM,WAAW,SAAS,MAAM,SAAS,YAAY,MAAM,WAAW,MAAM,UAAU,CAAC;AAChJ,CAAC;AAGD,YAAY,GAAG,oBAAoB,CAAC,SAAS;AACzC,YAAU;AAAA,IACN,MAAM;AAAA,IACN,SAAS,sCAAgC,KAAgC,YAAY;AAAA,kBAAe,KAAgC,SAAS;AAAA,IAC7I,QAAQ;AAAA,IACR,WAAY,KAAgC;AAAA,EAChD,CAAC;AACL,CAAC;AACD,YAAY,GAAG,uBAAuB,CAAC,SAAS;AAC5C,QAAM,IAAI;AACV,YAAU;AAAA,IACN,MAAM;AAAA,IACN,SAAS,iCAA4B,EAAE,YAAY;AAAA,mBAAgB,EAAE,UAAuB,KAAK,IAAI,CAAC;AAAA,aAAS,EAAE,WAAqB,IAAI,MAAM,GAAG,GAAG,CAAC;AAAA,IACvJ,QAAQ;AAAA,IACR,WAAW,EAAE;AAAA,EACjB,CAAC;AACL,CAAC;AACD,YAAY,GAAG,0BAA0B,CAAC,SAAS;AAC/C,QAAM,IAAI;AACV,YAAU;AAAA,IACN,MAAM;AAAA,IACN,SAAS,oCAA0B,EAAE,YAAY;AAAA,EAAK,EAAE,MAAM;AAAA,IAC9D,QAAQ;AAAA,IACR,WAAW,EAAE;AAAA,EACjB,CAAC;AACL,CAAC;AACD,YAAY,GAAG,wBAAwB,CAAC,SAAS;AAC7C,QAAM,IAAI;AACV,YAAU;AAAA,IACN,MAAM;AAAA,IACN,SAAS,eAAQ,EAAE,IAAI,OAAO,EAAE,QAAQ,EAAE;AAAA,IAC1C,QAAQ;AAAA,IACR,WAAW,EAAE;AAAA,EACjB,CAAC;AACL,CAAC;AACD,YAAY,GAAG,0BAA0B,CAAC,SAAS;AAC/C,QAAM,IAAI;AACV,QAAM,OAAO,EAAE,UAAU,WAAM;AAC/B,YAAU;AAAA,IACN,MAAM;AAAA,IACN,SAAS,GAAG,IAAI,MAAM,EAAE,IAAI,MAAM,EAAE,UAAU,cAAc,QAAQ,KAAK,EAAE,UAAU;AAAA,IACrF,QAAQ;AAAA,IACR,WAAW,EAAE;AAAA,EACjB,CAAC;AACL,CAAC;AACD,YAAY,GAAG,oBAAoB,CAAC,SAAS;AACzC,QAAM,IAAI;AACV,YAAU;AAAA,IACN,MAAM;AAAA,IACN,SAAS,qBAAc,EAAE,KAAK,IAAI,EAAE,SAAS,aAAQ,EAAE,YAAY;AAAA,IACnE,QAAQ;AAAA,IACR,WAAW,EAAE;AAAA,EACjB,CAAC;AACL,CAAC;AAMD,eAAe,SAAS,aAAqB,KAA8G;AACzJ,QAAM,UAAU,SAAS,IAAI,WAAW;AACxC,MAAI,CAAC,QAAS;AACd,MAAI;AACF,UAAM,QAAQ,QAAQ,GAAG;AAAA,EAC3B,SAAS,KAAK;AACZ,WAAO,KAAK,WAAW,wBAAwB,WAAW,MAAO,IAAc,OAAO,EAAE;AAAA,EAC1F;AACF;AAGA,eAAe,qBAAqB,KAAoC;AACtE,SAAO,KAAK,WAAW,IAAI,IAAI,OAAO,KAAK,IAAI,YAAY,IAAI,MAAM,KAAK,IAAI,QAAQ,MAAM,GAAG,GAAG,CAAC,EAAE;AAGrG,YAAU;AAAA,IACR,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS,IAAI;AAAA,IACb,QAAQ,IAAI;AAAA,IACZ,UAAU,IAAI;AAAA,IACd,SAAS,IAAI;AAAA,IACb,WAAW,IAAI,UAAU,YAAY;AAAA,EACvC,CAAC;AAGD,QAAM,cAAc,MAAM,mBAAmB,IAAI,SAAS,IAAI,SAAS,IAAI,MAAM;AACjF,MAAI,aAAa;AACf,UAAM,SAAS,IAAI,SAAS,EAAE,SAAS,IAAI,SAAS,QAAQ,IAAI,QAAQ,SAAS,IAAI,SAAS,SAAS,YAAY,UAAU,SAAS,IAAI,GAAG,CAAC;AAC9I,cAAU,EAAE,MAAM,WAAW,WAAW,YAAY,SAAS,IAAI,SAAS,QAAQ,IAAI,QAAQ,SAAS,YAAY,UAAU,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAClK;AAAA,EACF;AAGA,QAAM,QAAQ,kBAAkB,IAAI,OAAO;AAC3C,MAAI,OAAO;AACT,UAAM,EAAE,SAAS,KAAK,IAAI;AAC1B,UAAM,SAAiC,CAAC;AACxC,QAAI,MAAM;AAAE,aAAO,MAAM,IAAI;AAAM,aAAO,OAAO,IAAI;AAAM,aAAO,OAAO,IAAI;AAAA,IAAM;AACnF,QAAI;AACF,UAAI,eAAe;AACnB,uBAAiB,QAAQ,UAAU,SAAS,MAAM,GAAG;AACnD,cAAM,IAAI,MAAM,eAAe,KAAK,QAAQ,IAAI,SAAS,IAAI,MAAM;AACnE,yBAAiB,eAAe,SAAS,MAAM,EAAE;AAAA,MACnD;AACA,YAAM,SAAS,IAAI,SAAS,EAAE,SAAS,IAAI,SAAS,QAAQ,IAAI,QAAQ,SAAS,IAAI,SAAS,SAAS,cAAc,SAAS,IAAI,GAAG,CAAC;AACtI,gBAAU,EAAE,MAAM,WAAW,WAAW,YAAY,SAAS,IAAI,SAAS,QAAQ,IAAI,QAAQ,SAAS,cAAc,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAC1J;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,WAAW,MAAM,aAAa,IAAI,SAAS,IAAI,SAAS,IAAI,MAAM;AAGxE,UAAM,SAAS,IAAI,SAAS;AAAA,MAC1B,SAAS,IAAI;AAAA,MACb,QAAQ,IAAI;AAAA,MACZ,SAAS,IAAI;AAAA,MACb,SAAS,SAAS;AAAA,MAClB,SAAS,IAAI;AAAA,IACf,CAAC;AAGD,cAAU;AAAA,MACR,MAAM;AAAA,MACN,WAAW;AAAA,MACX,SAAS,IAAI;AAAA,MACb,QAAQ,IAAI;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,MACpB,YAAY,SAAS;AAAA,MACrB,YAAY,SAAS;AAAA,MACrB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,MAAM,WAAW,6BAA8B,MAAgB,OAAO,EAAE;AAC/E,cAAU,EAAE,MAAM,SAAS,SAAS,oEAAoE,CAAC;AAAA,EAC3G;AACF;AAGA,eAAsB,aAAa,SAA4J;AAC7L,QAAM,SAAS,WAAW;AAC1B,iBAAe,cAAc;AAC7B,QAAM,OAAO,SAAS,QAAQ,OAAO,QAAQ;AAC7C,MAAI,OAAO,SAAS,QAAQ,OAAO,QAAQ;AAM3C,MAAI;AACF,UAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,sBAAsB;AACrE,UAAM,UAAW,OAAO,QAA+K;AACvM,0BAAsB;AAAA,MACpB,aAAa,SAAS;AAAA,MACtB,oBAAoB,SAAS;AAAA,MAC7B,uBAAuB,SAAS;AAAA,MAChC,kBAAkB,SAAS;AAAA,MAC3B,eAAe,SAAS;AAAA,IAC1B,CAAC;AAAA,EACH,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,mDAAoD,EAAY,OAAO,yDAAoD;AAAA,EACpJ;AAEA,SAAO,KAAK,WAAW,YAAY,UAAU,aAAa,aAAa,EAAE;AAMzE,MAAI;AACF,UAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,qBAAqB;AACpE,UAAM,QAAQ,sBAAsB,UAAU;AAC9C,QAAI,MAAM,UAAU,GAAG;AACrB,aAAO,KAAK,WAAW,SAAS,MAAM,OAAO,8BAA8B,UAAU,sBAAiB,MAAM,QAAQ,OAAO,MAAM,QAAQ,CAAC,CAAC,KAAK;AAAA,IAClJ;AAAA,EACF,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,qBAAsB,EAAY,OAAO,EAAE;AAAA,EACpE;AAKA,MAAI;AACF,UAAM,EAAE,YAAY,gBAAgB,IAAI,MAAM,OAAO,4BAA4B;AACjF,eAAW,aAAa;AACxB,UAAM,QAAQ,gBAAgB;AAC9B,QAAI,MAAM,aAAa,QAAQ,MAAM,QAAQ;AAC3C,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,oBAAoB;AACvD;AAAA,QACE,MAAM;AAAA,QACN;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,UACE,mBAAmB,MAAM;AAAA,UACzB,kBAAkB,MAAM;AAAA,UACxB,kBAAkB,MAAM;AAAA,UACxB,gBAAgB,MAAM;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,KAAK,WAAW,gCAAiC,IAAc,OAAO,EAAE;AAAA,EACjF;AAMA,MAAI,CAAC,SAAS,iBAAiB;AAC7B,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,qBAAqB;AAChE,UAAM,SAAS,MAAM,kBAAkB;AACvC,QAAI,CAAC,OAAO,IAAI;AACd,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,uDAAkD;AAChE,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,MAAM,OAAO,OAAO,EAAE;AACpC,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,0BAA0B;AACxC,cAAQ,MAAM,mCAAmC;AACjD,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,oCAAoC;AAClD,cAAQ,MAAM,2DAA2D;AACzE,cAAQ,MAAM,oDAAoD;AAClE,cAAQ,MAAM,qEAAqE;AACnF,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,8BAA8B;AAC5C,cAAQ,MAAM,kCAAkC;AAChD,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,mCAAmC;AACjD,cAAQ,MAAM,uDAAuD;AACrE,cAAQ,MAAM,EAAE;AAChB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO,KAAK,WAAW,0BAA0B,OAAO,OAAO,EAAE;AAAA,EACnE;AAGA,MAAI,OAAO,UAAU,SAAS,cAAc;AAC1C,WAAO,KAAK,WAAW,iJAAkI;AACzJ,WAAO,KAAK,WAAW,mFAAmF;AAAA,EAC5G;AACA,MAAI,OAAO,aAAa,SAAS;AAC/B,WAAO,KAAK,WAAW,kFAAwE;AAAA,EACjG,OAAO;AACL,WAAO,KAAK,WAAW,2GAA4F;AAAA,EACrH;AACA,MAAI,OAAO,SAAS,SAAS;AAC3B,WAAO,KAAK,WAAW,8EAAoE;AAAA,EAC7F;AAGA,uBAAqB;AAOrB,cAAY,MAAM,qBAAqB,GAAG,KAAK,GAAI;AAGnD,QAAM,gBAAgB,MAAM,IAAI,QAAiB,CAACA,aAAY;AAC5D,UAAM,SAAS,IAAI,aAAa;AAChC,WAAO,KAAK,SAAS,MAAMA,SAAQ,KAAK,CAAC;AACzC,WAAO,KAAK,aAAa,MAAM;AAAE,aAAO,MAAM;AAAG,MAAAA,SAAQ,IAAI;AAAA,IAAG,CAAC;AACjE,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B,CAAC;AACD,MAAI,CAAC,eAAe;AAClB,WAAO,MAAM,WAAW,QAAQ,IAAI,+CAA+C;AACnF,WAAO,KAAK,WAAW,6BAA6B,OAAO,CAAC,EAAE;AAC9D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAsB;AACzD,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,2BAA2B;AACtE,sBAAkB,IAAO;AACzB,WAAO,KAAK,WAAW,0EAAqE;AAC5F,4BAAwB;AACxB,WAAO,KAAK,WAAW,mDAAmD;AAAA,EAC5E;AAGA,aAAW;AACX,eAAa;AACb,YAAU;AAGV,SAAO,0BAA0B,EAAE,KAAK,CAAC,EAAE,qBAAqB,MAAM;AACpE,yBAAqB;AAAA,EACvB,CAAC,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AAGjB,SAAO,sBAAsB,EAAE,KAAK,CAAC,EAAE,YAAY,MAAM;AACvD,gBAAY,EAAE,KAAK,QAAM;AACvB,UAAI,GAAI,QAAO,KAAK,WAAW,2CAA2C;AAAA,IAC5E,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnB,CAAC,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AAEjB,QAAM,kBAAkB;AACxB,aAAW;AAQX,MAAI;AACF,UAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,4BAA4B;AACzE,wBAAoB,EAAE,QAAQ,eAAe,CAAC;AAAA,EAChD,SAAS,KAAK;AACZ,WAAO,KAAK,WAAW,mCAAoC,IAAc,OAAO,EAAE;AAAA,EACpF;AAGA,QAAM,2BAA2B,SAAS,qBAAqB;AAC/D,QAAM,sBAAsB,SAAS,gBAAgB;AACrD,QAAM,iBAAiB,oBAAI,IAAgD;AAM3E,WAAS,YAAY,KAAsB;AACvC,WAAQ,IAAI,QAAQ,iBAAiB,GAAc,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,KAChE,IAAI,MACJ,IAAI,QAAQ,iBACZ;AAAA,EACX;AAEA,WAAS,UAAU,UAAkB,aAAqB;AACtD,WAAO,CAAC,KAAc,KAAe,SAAuB;AACxD,YAAM,MAAM,YAAY,GAAG;AAC3B,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,QAAQ,eAAe,IAAI,GAAG;AACpC,UAAI,CAAC,SAAS,MAAM,MAAM,SAAS;AAC/B,uBAAe,IAAI,KAAK,EAAE,OAAO,GAAG,SAAS,MAAM,SAAS,CAAC;AAC7D,aAAK;AAAA,MACT,WAAW,MAAM,QAAQ,aAAa;AAClC,cAAM;AACN,aAAK;AAAA,MACT,OAAO;AACH,cAAM,aAAa,KAAK,MAAM,MAAM,UAAU,OAAO,GAAI;AACzD,eAAO,KAAK,WAAW,sBAAsB,GAAG,kBAAkB,MAAM,KAAK,IAAI,WAAW,OAAO,QAAQ,KAAK;AAChH,YAAI,UAAU,eAAe,OAAO,UAAU,CAAC;AAC/C,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,WAAW,CAAC;AAAA,MACnE;AAAA,IACJ;AAAA,EACJ;AAgBA,MAAI,wBAAwB;AAC5B,QAAM,2BAA2B,MAAM;AACnC,UAAM,MAAM,WAAW;AACvB,UAAM,IAAI,IAAI,SAAS;AACvB,QAAI,OAAO,MAAM,YAAY,IAAI,KAAK,KAAK,IAAM,QAAO;AACxD,WAAO;AAAA,EACX,GAAG;AAEH,WAAS,iBAAiB,eAAuB;AAC7C,WAAO,CAAC,MAAe,KAAe,SAAuB;AACzD,UAAI,yBAAyB,eAAe;AACxC,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kDAA6C,CAAC;AAC5E;AAAA,MACJ;AACA;AAIA,UAAI,cAAc;AAClB,UAAI,GAAG,SAAS,MAAM;AAClB,YAAI,YAAa;AACjB,sBAAc;AACd,gCAAwB,KAAK,IAAI,GAAG,wBAAwB,CAAC;AAAA,MACjE,CAAC;AACD,WAAK;AAAA,IACT;AAAA,EACJ;AAGA,6BAA2B,YAAY,MAAM;AACzC,UAAM,MAAM,KAAK,IAAI;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,gBAAgB;AACvC,UAAI,MAAM,MAAM,QAAS,gBAAe,OAAO,GAAG;AAAA,IACtD;AAEA,QAAI,eAAe,OAAO,KAAQ;AAC9B,YAAM,UAAU,CAAC,GAAG,eAAe,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO;AACxF,YAAM,WAAW,QAAQ,MAAM,GAAG,QAAQ,SAAS,GAAM;AACzD,iBAAW,CAAC,GAAG,KAAK,SAAU,gBAAe,OAAO,GAAG;AAAA,IAC3D;AAAA,EACJ,GAAG,GAAM;AACT,2BAAyB,MAAM;AAG/B,QAAM,MAAM,QAAQ;AAKpB,QAAM,aAAa,cAAc,YAAY,GAAG;AAChD,QAAM,YAAY,QAAQ,UAAU;AACpC,QAAM,aAAa,KAAK,WAAW,eAAe;AAClD,QAAM,cAAc,KAAK,YAAY,YAAY;AACjD,QAAM,aAAa,GAAG,WAAW,WAAW;AAC5C,MAAI,kBAAiC;AACrC,MAAI,YAAY;AAEd,sBAAkB,GAAG,aAAa,aAAa,MAAM;AACrD,QAAI,IAAI,QAAQ,OAAO,YAAY,EAAE,OAAO,MAAM,CAAC,CAAC;AAEpD,OAAG,UAAU,aAAa,EAAE,UAAU,IAAK,GAAG,MAAM;AAClD,UAAI;AACF,0BAAkB,GAAG,aAAa,aAAa,MAAM;AAAA,MACvD,QAAQ;AAAA,MAAwC;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,MAAI,IAAI,QAAQ,KAAK,EAAE,OAAO,MAAM,CAAC,CAAC;AAGtC,MAAI,IAAI,CAAC,KAAK,KAAK,SAAS;AAC1B,UAAM,QAAQ,KAAK,IAAI;AACvB,QAAI,GAAG,UAAU,MAAM;AACrB,YAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,aAAO,KAAK,WAAW,GAAG,IAAI,MAAM,IAAI,IAAI,IAAI,WAAM,IAAI,UAAU,KAAK,QAAQ,KAAK;AAAA,IACxF,CAAC;AACD,SAAK;AAAA,EACP,CAAC;AAGD,MAAI,IAAI,OAAO,yBAAyB,CAAC;AAGzC,MAAI,IAAI,kBAAkB,sBAAsB,CAAC;AACjD,MAAI,IAAI,cAAc,wBAAwB,CAAC;AAI/C,MAAI,IAAI,aAAa,OAAO,KAAc,QAAkB;AAC1D,UAAM,MAAM,WAAW;AACvB,UAAM,aAAa,IAAI,WAAW,QAAQ,WAAW,QAAQ,IAAI,eAAe;AAChF,UAAM,aAAa,IAAI,KAAK,QAAQ,aAAa,EAAE;AACnD,UAAM,YAAY,GAAG,UAAU,GAAG,UAAU;AAE5C,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,WAAW;AAAA,QACtC,QAAQ,IAAI;AAAA,QACZ,SAAS;AAAA,UACP,gBAAgB,IAAI,QAAQ,cAAc,KAAK;AAAA,UAC/C,QAAQ,IAAI,QAAQ,QAAQ,KAAK;AAAA,QACnC;AAAA,QACA,MAAM,IAAI,WAAW,SAAS,IAAI,WAAW,SAAS,KAAK,UAAU,IAAI,IAAI,IAAI;AAAA,MACnF,CAAC;AAED,UAAI,OAAO,SAAS,MAAM;AAC1B,eAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAEvC,YAAI,IAAI,YAAY,MAAM,oBAAoB;AAC5C,cAAI,UAAU,KAAK,KAAK;AAAA,QAC1B;AAAA,MACF,CAAC;AAED,UAAI,SAAS,MAAM;AACjB,cAAM,SAAS,SAAS,KAAK,UAAU;AAEvC,eAAO,MAAM;AACX,gBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,cAAI,KAAM;AACV,cAAI,MAAM,OAAO,KAAK,KAAK,CAAC;AAAA,QAC9B;AAAA,MACF;AACA,UAAI,IAAI;AAAA,IACV,SAAS,KAAK;AACZ,aAAO,MAAM,WAAW,uBAAwB,IAAc,OAAO,EAAE;AACvE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACvF;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,CAAC,KAAiD,KAAc,KAAe,SAAuB;AAC5G,QAAI,IAAI,SAAS,oBAAoB;AACnC,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,8BAA8B,CAAC;AAC7D;AAAA,IACF;AACA,QAAI,IAAI,SAAS,uBAAuB;AACtC,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAC9C;AAAA,IACF;AACA,SAAK,GAAG;AAAA,EACV,CAAC;AAGD,MAAI,IAAI,CAAC,KAAK,KAAK,SAAS;AACxB,QAAI,UAAU,0BAA0B,SAAS;AACjD,QAAI,UAAU,mBAAmB,YAAY;AAC7C,QAAI,UAAU,oBAAoB,eAAe;AACjD,QAAI,UAAU,mBAAmB,iCAAiC;AAClE,QAAI,UAAU,2BAA2B;AAAA,MACrC;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA;AAAA,MACA;AAAA,MACA;AAAA,IACJ,EAAE,KAAK,IAAI,CAAC;AACZ,QAAI,aAAa,cAAc;AAC/B,SAAK;AAAA,EACT,CAAC;AAGD,QAAM,cAAc,OAAO,QAAQ,QAAQ;AAC3C,QAAM,mBAAmB,oBAAI,IAAI;AAAA,IAC7B,oBAAoB,WAAW;AAAA,IAC/B,oBAAoB,WAAW;AAAA,IAC/B,qBAAqB,WAAW;AAAA,IAChC,qBAAqB,WAAW;AAAA,EACpC,CAAC;AACD,QAAM,wBAAwB;AAAA,IAC1B;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACJ;AACA,WAASC,iBAAgB,QAAyB;AAC9C,QAAI,iBAAiB,IAAI,MAAM,EAAG,QAAO;AACzC,WAAO,sBAAsB,KAAK,QAAM,GAAG,KAAK,MAAM,CAAC;AAAA,EAC3D;AACA,MAAI,IAAI,CAAC,KAAK,KAAK,SAAS;AACxB,UAAM,SAAS,IAAI,QAAQ;AAC3B,QAAI,UAAUA,iBAAgB,MAAM,GAAG;AACnC,UAAI,UAAU,+BAA+B,MAAM;AACnD,UAAI,UAAU,oCAAoC,MAAM;AACxD,UAAI,UAAU,gCAAgC,iCAAiC;AAC/E,UAAI,UAAU,gCAAgC,6BAA6B;AAAA,IAC/E;AACA,QAAI,IAAI,WAAW,WAAW;AAAE,UAAI,WAAW,GAAG;AAAG;AAAA,IAAQ;AAC7D,SAAK;AAAA,EACT,CAAC;AAGD,MAAI,IAAI,UAAU,CAAC,MAAM,QAAQ;AAC/B,QAAI,UAAU,gBAAgB,WAAW;AACzC,QAAI,KAAK,aAAa,CAAC;AAAA,EACzB,CAAC;AAED,MAAI,KAAK,cAAc,UAAU,KAAO,CAAC,GAAG,CAAC,KAAK,QAAQ;AACxD,UAAM,MAAM,WAAW;AACvB,UAAM,OAAO,IAAI,QAAQ;AACzB,QAAI,CAAC,QAAQ,KAAK,SAAS,QAAQ;AACjC,UAAI,KAAK,EAAE,OAAO,SAAS,CAAC;AAC5B;AAAA,IACF;AACA,UAAM,EAAE,SAAS,IAAI,IAAI;AACzB,QAAI,QAAQ;AACZ,QAAI,KAAK,SAAS,cAAc,KAAK,YAAY,YAAY,YAAY,UAAU,KAAK,QAAQ,EAAG,SAAQ;AAC3G,QAAI,KAAK,SAAS,WAAW,KAAK,SAAS,YAAY,YAAY,UAAU,KAAK,KAAK,EAAG,SAAQ;AAClG,QAAI,CAAC,OAAO;AAAE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,CAAC;AAAG;AAAA,IAAQ;AAC3E,UAAM,QAAQ,YAAY,EAAE,EAAE,SAAS,KAAK;AAC5C,eAAW,IAAI,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,QAAQ,QAAQ,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC;AACpF,mBAAe;AACf,QAAI,KAAK,EAAE,MAAM,CAAC;AAAA,EACpB,CAAC;AAGD,MAAI,IAAI,YAAY,CAAC,MAAM,QAAQ;AACjC,QAAI,UAAU,gBAAgB,2BAA2B;AACzD,QAAI,KAAK,oBAAoB,CAAC;AAAA,EAChC,CAAC;AAMD,MAAI,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS;AAClC,UAAM,MAAM,WAAW;AACvB,UAAM,OAAO,IAAI,QAAQ;AACzB,QAAI,CAAC,QAAQ,KAAK,SAAS,QAAQ;AAAE,WAAK;AAAG;AAAA,IAAQ;AAErD,QAAI,KAAK,SAAS,WAAW,CAAC,KAAK,OAAO;AAAE,WAAK;AAAG;AAAA,IAAQ;AAE5D,QAAI,IAAI,SAAS,UAAU;AAAE,WAAK;AAAG;AAAA,IAAQ;AAC7C,QAAI,IAAI,SAAS,sBAAsB;AAAE,WAAK;AAAG;AAAA,IAAQ;AACzD,QAAI,IAAI,KAAK,WAAW,UAAU,GAAG;AAAE,WAAK;AAAG;AAAA,IAAQ;AACvD,UAAM,SAAS,IAAI,QAAQ;AAC3B,UAAM,QAAQ,QAAQ,WAAW,SAAS,IAAI,OAAO,MAAM,CAAC,IAAK,IAAI,MAAM;AAC3E,QAAI,aAAa,OAAO,GAAG,GAAG;AAAE,WAAK;AAAG;AAAA,IAAQ;AAChD,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,EAChD,CAAC;AAGD,MAAI,IAAI,qBAAqB,CAAC,MAAM,KAAK,SAAS;AAChD,QAAI,qBAAqB,GAAG;AAAE,WAAK;AAAG;AAAA,IAAQ;AAC9C,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,4BAA4B,MAAM,sDAAsD,CAAC;AAAA,EACzH,CAAC;AAGD,MAAI,IAAI,WAAW,CAAC,MAAM,QAAQ;AAChC,QAAI,UAAU,gBAAgB,WAAW;AACzC,QAAI,KAAK,sBAAsB,CAAC;AAAA,EAClC,CAAC;AAGD,MAAI,IAAI,KAAK,CAAC,MAAM,QAAQ;AAC1B,QAAI,cAAc,iBAAiB;AACjC,UAAI,UAAU,iBAAiB,qCAAqC;AACpE,UAAI,UAAU,UAAU,UAAU;AAClC,UAAI,UAAU,WAAW,GAAG;AAC5B,UAAI,KAAK,eAAe;AAAA,IAC1B,OAAO;AACL,UAAI,UAAU,gBAAgB,WAAW;AACzC,UAAI,KAAK,sBAAsB,CAAC;AAAA,IAClC;AAAA,EACF,CAAC;AAQD,WAAS,kBACP,SACA,UACiD;AACjD,QAAI,OAAO,EAAE,OAAO,WAAW,OAAO,mBAAmB,OAAO,EAAE;AAClE,eAAW,SAAS,OAAO,KAAK,OAAO,GAAG;AACxC,YAAM,SAAS,QAAQ,KAAK,KAAK,MAAM,SAAS,KAAK,KAAK;AAC1D,YAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,UAAI,OAAO,IAAK;AAChB,UAAI,MAAM,KAAK,IAAI,KAAK,KAAK,GAAG;AAC9B,cAAM,YAAY,QAAQ,IAAI,aAAa;AAC3C,cAAM,QAAQ,cAAc,aACxB,YAAY,eAAe,OAAO,IAAI,CAAC,KACvC,YAAY,eAAe,OAAO,KAAK,CAAC;AAC5C,eAAO,EAAE,OAAO,OAAO,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,eAAe,OAAe,UAA2B;AAChE,UAAM,MAAwC;AAAA;AAAA,MAE5C,WAAc,CAAC,WAAe,WAAW;AAAA,MACzC,OAAc,CAAC,WAAe,WAAW;AAAA,MACzC,SAAc,CAAC,SAAe,WAAW;AAAA,MACzC,cAAc,CAAC,aAAe,UAAU;AAAA,MACxC,aAAc,CAAC,cAAe,MAAM;AAAA;AAAA;AAAA;AAAA,MAIpC,SAAc,CAAC,WAAe,SAAS;AAAA,MACvC,QAAc,CAAC,OAAe,QAAQ;AAAA,MACtC,QAAc,CAAC,UAAe,SAAS;AAAA,MACvC,QAAc,CAAC,UAAe,UAAU;AAAA,IAC1C;AACA,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,WAAW,KAAK,CAAC,IAAI,KAAK,CAAC;AAAA,EACpC;AAYA,MAAI,IAAI,cAAc,OAAO,KAAK,QAAQ;AACxC,QAAI;AACF,YAAM,EAAE,oBAAAC,oBAAmB,IAAI,MAAM,OAAO,wBAAwB;AACpE,YAAM,IAAI,OAAO,IAAI,MAAM,MAAM,WAAW,IAAI,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI;AAC/E,YAAM,MAAMA,oBAAmB,EAAE,IAAI,QAAM;AAAA,QACzC,MAAM,EAAE;AAAA,QACR,aAAa,OAAO,EAAE,gBAAgB,WAAW,EAAE,YAAY,MAAM,GAAG,GAAG,IAAI;AAAA,QAC/E,YAAY,EAAE;AAAA,MAChB,EAAE;AACF,YAAM,WAAW,IACb,IAAI,OAAO,OAAK,EAAE,KAAK,YAAY,EAAE,SAAS,CAAC,KAAK,EAAE,YAAY,YAAY,EAAE,SAAS,CAAC,CAAC,IAC3F;AACJ,UAAI,KAAK,EAAE,OAAO,UAAU,OAAO,IAAI,QAAQ,OAAO,SAAS,OAAO,CAAC;AAAA,IACzE,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACtF;AAAA,EACF,CAAC;AAOD,MAAI,KAAK,kBAAkB,OAAO,KAAK,QAAQ;AAC7C,QAAI;AACF,YAAM,EAAE,MAAM,KAAK,IAAK,IAAI,QAAQ,CAAC;AACrC,UAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,SAAS,sBAAsB,CAAC;AAC/E;AAAA,MACF;AACA,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,wBAAwB;AAC7D,YAAM,SAAS,MAAM,YAAY;AAAA,QAC/B,IAAI,UAAU,KAAK,IAAI,CAAC;AAAA,QACxB,MAAM;AAAA,QACN,UAAU,EAAE,MAAM,WAAW,KAAK,UAAU,QAAQ,CAAC,CAAC,EAAE;AAAA,MAC1D,CAAC;AACD,UAAI,KAAK;AAAA,QACP,MAAM,OAAO;AAAA,QACb,SAAS,OAAO,YAAY;AAAA,QAC5B,SAAS,OAAO;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACpF;AAAA,EACF,CAAC;AAOD,MAAI,IAAI,oBAAoB,OAAO,KAAK,QAAQ;AAC9C,QAAI;AACF,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,qBAAqB;AACzD,YAAM,QAAQ,WAAW,UAAU,IAAI,OAAO,GAAG;AACjD,UAAI,KAAK,EAAE,KAAK,IAAI,OAAO,KAAK,OAAO,SAAS,KAAK,CAAC;AAAA,IACxD,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACvF;AAAA,EACF,CAAC;AAGD,MAAI,KAAK,eAAe,OAAO,KAAK,QAAQ;AAC1C,QAAI;AACF,YAAM,EAAE,KAAK,MAAM,IAAK,IAAI,QAAQ,CAAC;AACrC,UAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,SAAS,qBAAqB,CAAC;AAC9E;AAAA,MACF;AACA,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,qBAAqB;AAC3D,YAAM,IAAI,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AAClE,mBAAa,UAAU,KAAK,CAAC;AAC7B,UAAI,KAAK,EAAE,KAAK,QAAQ,KAAK,CAAC;AAAA,IAChC,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACxF;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,wBAAwB,OAAO,MAAM,QAAQ;AACnD,QAAI;AACF,YAAM,EAAE,wBAAwB,IAAI,MAAM,OAAO,wBAAwB;AACzE,YAAM,MAAM,WAAW;AACvB,YAAM,YAAY,IAAI,OAAO,WAAW;AACxC,YAAM,UAAU,wBAAwB,SAAS;AACjD,UAAI,KAAK,EAAE,SAAS,WAAW,MAAM,UAAU,CAAC;AAAA,IAClD,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACxF;AAAA,EACF,CAAC;AAMD,MAAI,IAAI,eAAe,OAAO,MAAM,QAAQ;AAC1C,QAAI;AACF,YAAM,EAAE,YAAY,eAAe,IAAI,MAAM,OAAO,sBAAsB;AAC1E,YAAM,OAAO,WAAW;AACxB,YAAM,SAAS,eAAe;AAC9B,UAAI,KAAK;AAAA,QACP,QAAQ,KAAK;AAAA,QACb,eAAe,QAAQ,MAAM;AAAA,MAC/B,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACvF;AAAA,EACF,CAAC;AAED,MAAI,KAAK,eAAe,OAAO,KAAK,QAAQ;AAC1C,QAAI;AACF,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,sBAAsB;AAC3D,YAAM,EAAE,MAAM,MAAM,OAAO,mBAAmB,gBAAgB,WAAW,IAAK,IAAI,QAAQ,CAAC;AAC3F,UAAI,OAAO,SAAS,YAAY,CAAC,KAAK,KAAK,GAAG;AAC5C,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,SAAS,sBAAsB,CAAC;AAC/E;AAAA,MACF;AACA,YAAM,QAAQ,YAAY;AAAA,QACxB,MAAM,KAAK,KAAK;AAAA,QAChB,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,QACxC,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,QAC3C,mBAAmB,OAAO,sBAAsB,WAAW,oBAAoB;AAAA,QAC/E,gBAAgB,MAAM,QAAQ,cAAc,IAAI,iBAAiB;AAAA,QACjE,YAAY,QAAQ,UAAU;AAAA,MAChC,CAAC;AACD,UAAI,KAAK,EAAE,MAAM,CAAC;AAAA,IACpB,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,SAAU,IAAc,QAAQ,CAAC;AAAA,IAClF;AAAA,EACF,CAAC;AAED,MAAI,MAAM,mBAAmB,OAAO,KAAK,QAAQ;AAC/C,QAAI;AACF,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,sBAAsB;AAC3D,YAAM,QAAS,IAAI,QAAQ,CAAC;AAC5B,YAAM,QAAQ,YAAY,IAAI,OAAO,IAAI;AAAA,QACvC,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAAA,QACpD,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAAA,QACpD,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,QACvD,mBAAmB,OAAO,MAAM,sBAAsB,WAAW,MAAM,oBAAoB;AAAA,QAC3F,SAAS,MAAM,QAAQ,MAAM,OAAO,IAAI,MAAM,UAAU;AAAA,MAC1D,CAAC;AACD,UAAI,CAAC,OAAO;AACV,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,YAAY,CAAC;AAC3C;AAAA,MACF;AACA,UAAI,KAAK,EAAE,MAAM,CAAC;AAAA,IACpB,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,SAAU,IAAc,QAAQ,CAAC;AAAA,IAClF;AAAA,EACF,CAAC;AAED,MAAI,KAAK,4BAA4B,OAAO,KAAK,QAAQ;AACvD,QAAI;AACF,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,sBAAsB;AAC3D,YAAM,QAAQ,YAAY,IAAI,OAAO,EAAE;AACvC,UAAI,CAAC,OAAO;AACV,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,YAAY,CAAC;AAC3C;AAAA,MACF;AACA,UAAI,KAAK,EAAE,MAAM,CAAC;AAAA,IACpB,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,SAAU,IAAc,QAAQ,CAAC;AAAA,IAClF;AAAA,EACF,CAAC;AAED,MAAI,OAAO,mBAAmB,OAAO,KAAK,QAAQ;AAChD,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,sBAAsB;AAC5D,YAAM,SAAS,aAAa,IAAI,OAAO,EAAE;AACzC,UAAI,CAAC,QAAQ;AACX,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,YAAY,CAAC;AAC3C;AAAA,MACF;AACA,UAAI,KAAK,EAAE,UAAU,OAAO,UAAU,WAAW,OAAO,UAAU,CAAC;AAAA,IACrE,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACnF;AAAA,EACF,CAAC;AAED,MAAI,IAAI,uBAAuB,OAAO,MAAM,QAAQ;AAClD,QAAI;AACF,YAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,6BAA6B;AACzE,UAAI,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;AAAA,IAC5C,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACxF;AAAA,EACF,CAAC;AAaD,MAAI,IAAI,oBAAoB,OAAO,KAAK,QAAQ;AAC9C,QAAI;AACF,YAAM,SAAS,iBAAiB,GAA6C;AAC7E,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,2BAA2B;AACpE,YAAM,UAAU,gBAAgB,MAAM;AACtC,UAAI,UAAyC;AAC7C,UAAI,OAAsB;AAC1B,UAAI;AACF,cAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,yBAAyB;AACnE,cAAM,QAAQ,iBAAiB;AAC/B,YAAI,MAAM,WAAW;AACnB,oBAAU,EAAE,GAAG,MAAM,OAAO;AAC5B,iBAAO,MAAM;AAAA,QACf;AAAA,MACF,QAAQ;AAAA,MAAoD;AAS5D,YAAM,WAAmC,EAAE,GAAG,QAAQ,SAAS;AAC/D,UAAI,SAAS;AACX,mBAAW,KAAK,OAAO,KAAK,OAAO,GAAG;AACpC,cAAI,EAAE,KAAK,UAAW,UAAS,CAAC,IAAI;AAAA,QACtC;AAAA,MACF;AACA,UAAI,KAAK;AAAA,QACP;AAAA,QACA;AAAA,QACA,SAAS,WAAW;AAAA,QACpB;AAAA,QACA,UAAU,kBAAkB,WAAW,UAAU,QAAQ;AAAA,MAC3D,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAQD,MAAI,IAAI,mBAAmB,OAAO,MAAM,QAAQ;AAC9C,QAAI;AACF,YAAM,MAAM,WAAW;AACvB,YAAM,kBAAmB,IAAI,UAAgD,WAAW;AACxF,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,uBAAuB;AACjE,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,yBAAyB;AAC7D,YAAM,UAAU,iBAAiB;AACjC,UAAI,CAAC,SAAS;AACZ,YAAI,KAAK;AAAA,UACP,SAAS;AAAA,UACT,SAAS,kBACL,8DACA;AAAA,UACJ,QAAQ,CAAC;AAAA,UACT,eAAe;AAAA,UACf,gBAAgB,CAAC;AAAA,UACjB,UAAU,EAAE,WAAW,OAAO,MAAM,MAAM,QAAQ,CAAC,GAAG,UAAU,CAAC,GAAG,UAAU,KAAK;AAAA,QACrF,CAAC;AACD;AAAA,MACF;AACA,YAAM,QAAQ,WAAW,QAAQ,OAAO,QAAQ,QAAQ,OAAO,SAAS;AACxE,UAAI,KAAK;AAAA,QACP,SAAS;AAAA,QACT,WAAW,QAAQ,OAAO;AAAA,QAC1B,QAAQ,QAAQ,OAAO;AAAA,QACvB,eAAe,QAAQ,OAAO;AAAA,QAC9B,gBAAgB,QAAQ,OAAO;AAAA,QAC/B,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC3F;AAAA,EACF,CAAC;AAKD,MAAI,IAAI,qBAAqB,OAAO,KAAK,QAAQ;AAC/C,QAAI;AACF,YAAM,MAAM,WAAW;AACvB,YAAM,kBAAmB,IAAI,UAAgD,WAAW;AACxF,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,uBAAuB;AACjE,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,SAAS,OAAO,IAAI,MAAM,SAAS,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;AAC5F,YAAM,UAAU,iBAAiB;AACjC,UAAI,CAAC,SAAS;AACZ,YAAI,KAAK,EAAE,SAAS,iBAAiB,SAAS,CAAC,GAAG,QAAQ,KAAK,CAAC;AAChE;AAAA,MACF;AACA,YAAM,SAAS,KAAK,IAAI,IAAI,QAAQ,KAAK,KAAK;AAC9C,YAAM,QAAQ,QAAQ,QAAQ,OAAO,OAAK,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,KAAK,MAAM;AACnF,UAAI,KAAK,EAAE,SAAS,iBAAiB,SAAS,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAAA,IAC/E,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,4BAA4B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC7F;AAAA,EACF,CAAC;AAKD,MAAI,IAAI,wBAAwB,OAAO,KAAK,QAAQ;AAClD,QAAI;AACF,YAAM,SAAS,iBAAiB,GAA6C;AAC7E,YAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,4BAA4B;AAC1E,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,OAAO,IAAI,MAAM,SAAS,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;AAC3F,YAAM,aAAa,qBAAqB,QAAQ,KAAK;AACrD,UAAI,KAAK,EAAE,QAAQ,WAAW,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC3F;AAAA,EACF,CAAC;AASD,MAAI,IAAI,gCAAgC,OAAO,KAAK,QAAQ;AAC1D,QAAI;AACF,YAAM,EAAE,oBAAoB,gBAAgB,IAAI,MAAM,OAAO,uBAAuB;AACpF,YAAM,OAAO,OAAO,IAAI,MAAM,SAAS,WAAW,IAAI,MAAM,OAAO;AACnE,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,SAAS,OAAO,IAAI,MAAM,SAAS,KAAK,GAAG,EAAE,KAAK,GAAG,CAAC;AAC9F,YAAM,cAAc,OAAO,gBAAgB,IAAI,IAAI,mBAAmB,KAAK;AAC3E,UAAI,KAAK,EAAE,OAAO,YAAY,QAAQ,YAAY,CAAC;AAAA,IACrD,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAED,MAAI,IAAI,6BAA6B,OAAO,KAAK,QAAQ;AACvD,QAAI;AACF,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,uBAAuB;AAC/D,YAAM,KAAK,OAAO,IAAI,OAAO,MAAM,EAAE,EAAE,KAAK;AAC5C,UAAI,CAAC,IAAI;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAG;AAAA,MAAQ;AAC7E,YAAM,OAAO,eAAe,EAAE;AAC9B,UAAI,KAAK,EAAE,cAAc,IAAI,KAAK,CAAC;AAAA,IACrC,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAED,MAAI,KAAK,gCAAgC,OAAO,KAAK,QAAQ;AAC3D,QAAI;AACF,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,uBAAuB;AAClE,YAAM,KAAK,OAAO,IAAI,OAAO,MAAM,EAAE,EAAE,KAAK;AAC5C,UAAI,CAAC,IAAI;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAG;AAAA,MAAQ;AAC7E,YAAM,SAAS,kBAAkB,EAAE;AACnC,YAAM,KAAK,CAAC,OAAO,YAAY,EAAE,WAAW,gBAAgB,KAAK,CAAC,OAAO,YAAY,EAAE,WAAW,gBAAgB,KAAK,CAAC,OAAO,YAAY,EAAE,SAAS,WAAW;AACjK,UAAI,KAAK,EAAE,IAAI,cAAc,IAAI,SAAS,OAAO,CAAC;AAAA,IACpD,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,8BAA8B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC/F;AAAA,EACF,CAAC;AAiBD,MAAI,KAAK,oBAAoB,OAAO,KAAK,QAAQ;AAC/C,QAAI;AACF,YAAM,cAAc,OAAO,IAAI,MAAM,eAAe,IAAI,MAAM,UAAU,EAAE,EAAE,KAAK;AACjF,UAAI,CAAC,eAAe,YAAY,SAAS,IAAI;AAC3C,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,SAAS,mFAAmF,CAAC;AACnJ;AAAA,MACF;AACA,YAAM,QAAQ,OAAO,IAAI,MAAM,SAAS,EAAE,EAAE,KAAK,KAAK,YAAY,MAAM,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE;AACjG,YAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,IAAI,MAAM,QAAQ,KAAK,CAAC,CAAC;AACzE,YAAM,cAAc,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,IAAI,MAAM,SAAS,KAAK,CAAC,CAAC;AACjF,YAAM,OAAiB,MAAM,QAAQ,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI,CAAC,WAAW,YAAY;AAK3G,UAAI,WAA4F;AAChG,UAAI;AACF,cAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAsB;AAC7D,cAAM,kBAAkB;AAAA,UACtB;AAAA,UACA;AAAA,UACA,YAAY,WAAW;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AACX,cAAM,SAAS,MAAM,cAAc;AAAA,UACjC,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,WAAW;AAAA,QACb,CAAC;AACD,cAAM,OAAO,OAAO,WAAW,IAAI,KAAK;AACxC,cAAM,YAAY,IAAI,QAAQ,GAAG;AACjC,cAAM,UAAU,IAAI,YAAY,GAAG;AACnC,YAAI,aAAa,KAAK,UAAU,WAAW;AACzC,gBAAM,SAAS,KAAK,MAAM,IAAI,MAAM,WAAW,UAAU,CAAC,CAAC;AAC3D,cAAI,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,SAAS,UAAU,GAAG;AACjE,uBAAW,OAAO,SACf,OAAO,OAAK,OAAO,GAAG,UAAU,YAAY,OAAO,GAAG,gBAAgB,QAAQ,EAC9E,MAAM,GAAG,CAAC,EACV,IAAI,QAAM,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,GAAG,aAAa,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,EAAE,EAAE;AAAA,UACzG;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,eAAO,KAAK,WAAW,iEAAkE,IAAc,OAAO,EAAE;AAAA,MAClH;AAEA,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,mBAAmB;AACvD,YAAM,OAAO,WAAW;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,IAAI,MAAM,UAAU;AAAA,MAC7B,CAAC;AACD,aAAO,KAAK,WAAW,mCAAmC,KAAK,SAAS,KAAK,EAAE,cAAe,UAAU,UAAU,CAAE,GAAG;AACvH,UAAI,KAAK;AAAA,QACP,IAAI;AAAA,QACJ,MAAM,EAAE,IAAI,KAAK,IAAI,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,UAAU,KAAK,UAAU,cAAc,KAAK,UAAU,UAAU,EAAE;AAAA,QAC/H,SAAS,UAAU,SACf,YAAY,KAAK,kBAAkB,SAAS,MAAM,qEAClD,YAAY,KAAK;AAAA,MACvB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC;AAED,MAAI,IAAI,wBAAwB,OAAO,MAAM,QAAQ;AACnD,QAAI;AACF,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,wBAAwB;AACnE,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,mBAAmB;AACtD,YAAM,UAAU,kBAAkB;AAClC,YAAM,QAAQ,UAAU,QAAQ;AAChC,YAAM,YAAY,IAAI,IAAI,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACnD,YAAM,WAAW,QAAQ,IAAI,OAAK;AAChC,cAAM,OAAO,UAAU,IAAI,EAAE,MAAM;AACnC,cAAM,YAAY,OAAO,OAAO,EAAE,aAAa,EAAE,OAAO,OAAK,EAAE,oBAAoB,WAAW,IAAI,EAAE;AACpG,cAAM,QAAQ,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,MAAM,UAAU,UAAU;AAChF,eAAO;AAAA,UACL,QAAQ,EAAE;AAAA,UACV,OAAO,MAAM,SAAS;AAAA,UACtB,OAAO,EAAE;AAAA,UACT,WAAW,EAAE;AAAA,UACb,kBAAkB,EAAE,oBAAoB;AAAA,UACxC,UAAU,EAAE,OAAO,UAAU;AAAA,UAC7B,QAAQ,EAAE;AAAA,UACV,eAAe,EAAE,iBAAiB;AAAA,UAClC,cAAc,EAAE,WAAW,CAAC,GAAG,MAAM,EAAE;AAAA,QACzC;AAAA,MACF,CAAC;AACD,UAAI,KAAK,EAAE,OAAO,SAAS,QAAQ,SAAS,CAAC;AAAA,IAC/C,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC3F;AAAA,EACF,CAAC;AAED,MAAI,IAAI,wBAAwB,OAAO,KAAK,QAAQ;AAClD,QAAI;AACF,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,SAAS,OAAO,IAAI,MAAM,SAAS,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;AAC5F,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,wBAAwB;AAChE,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,mBAAmB;AACtD,YAAM,MAAM,eAAe;AAC3B,YAAM,SAAS,KAAK,IAAI,IAAI,QAAQ,KAAK,KAAK;AAC9C,YAAM,YAAY,IAAI,IAAI,UAAU,EAAE,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACzD,YAAM,SAAS,IACZ,OAAO,OAAK,CAAC,QAAQ,UAAU,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC,EAC7D,OAAO,OAAK;AACX,cAAM,cAAc,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG,MAAM,EAAE;AAC/D,eAAO,IAAI,KAAK,WAAW,EAAE,QAAQ,KAAK;AAAA,MAC5C,CAAC,EACA,IAAI,OAAK;AACR,cAAM,OAAO,UAAU,IAAI,EAAE,MAAM;AACnC,cAAM,cAAc,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG,MAAM,EAAE;AAC/D,eAAO;AAAA,UACL,QAAQ,EAAE;AAAA,UACV,OAAO,MAAM,SAAS;AAAA,UACtB,OAAO,EAAE;AAAA,UACT,WAAW,EAAE;AAAA,UACb;AAAA,UACA,YAAY,IAAI,KAAK,WAAW,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AAAA,UAC5E,cAAc,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,MAAM,UAAU,UAAU;AAAA,UAChF,QAAQ,EAAE;AAAA,UACV,gBAAgB,EAAE,eAAe,kBAAkB,CAAC;AAAA,QACtD;AAAA,MACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAO,EAAE,cAAc,EAAE,cAAc,IAAI,EAAG;AAC1D,UAAI,KAAK,EAAE,OAAO,OAAO,OAAO,QAAQ,UAAU,OAAO,CAAC;AAAA,IAC5D,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC3F;AAAA,EACF,CAAC;AAED,MAAI,IAAI,wBAAwB,OAAO,KAAK,QAAQ;AAClD,QAAI;AACF,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,SAAS,OAAO,IAAI,MAAM,SAAS,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;AAC5F,YAAM,EAAE,gBAAgB,kBAAkB,IAAI,MAAM,OAAO,wBAAwB;AACnF,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,mBAAmB;AACtD,YAAM,SAAS,KAAK,IAAI,IAAI,QAAQ,KAAK,KAAK;AAC9C,YAAM,MAAM,eAAe;AAC3B,YAAM,SAAS,kBAAkB;AACjC,YAAM,YAAY,IAAI,IAAI,UAAU,EAAE,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACzD,YAAM,YAAY,IAAI,OAAO,OAAK,EAAE,UAAU,MAAM,EAAE,OAAO,OAAK;AAChE,cAAM,KAAK,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG,MAAM,EAAE;AACtD,eAAO,IAAI,KAAK,EAAE,EAAE,QAAQ,KAAK;AAAA,MACnC,CAAC;AACD,YAAM,SAAS,IAAI,OAAO,OAAK,EAAE,UAAU,QAAQ,EAAE,OAAO,OAAK;AAC/D,cAAM,KAAK,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG,MAAM,EAAE;AACtD,eAAO,IAAI,KAAK,EAAE,EAAE,QAAQ,KAAK;AAAA,MACnC,CAAC;AACD,YAAM,UAAU,OAAO,OAAO,OAAK,EAAE,UAAU,SAAS;AACxD,YAAM,eAAe,CAAC,GAAG,WAAW,GAAG,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,QAAQ,WAAW,IAAI,CAAC;AACnG,YAAM,cAAc,CAAC,GAAG,WAAW,GAAG,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,QAAQ,cAAc,IAAI,CAAC;AACrG,YAAM,UAAU,UAAU,QAAQ,OAAK,EAAE,eAAe,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,EAAE;AAEzF,YAAM,UAAoB,CAAC;AAC3B,cAAQ,KAAK,QAAQ,KAAK,MAAM,UAAU,MAAM,0BAA0B,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,QAAQ,MAAM,wBAAwB;AAClK,UAAI,UAAU,SAAS,GAAG;AACxB,gBAAQ,KAAK,EAAE;AACf,gBAAQ,KAAK,YAAY;AACzB,mBAAW,KAAK,UAAU,MAAM,GAAG,EAAE,GAAG;AACtC,gBAAM,IAAI,UAAU,IAAI,EAAE,MAAM;AAChC,kBAAQ,KAAK,YAAO,GAAG,SAAS,EAAE,MAAM,KAAK,KAAK,OAAO,EAAE,QAAQ,WAAW,KAAK,GAAG,IAAI,GAAG,SAAS,KAAK,QAAQ,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,KAAK,GAAI,CAAC,IAAI;AAAA,QAChR;AAAA,MACF;AACA,UAAI,OAAO,SAAS,GAAG;AACrB,gBAAQ,KAAK,EAAE;AACf,gBAAQ,KAAK,uBAAuB;AACpC,mBAAW,KAAK,OAAO,MAAM,GAAG,CAAC,GAAG;AAClC,gBAAM,IAAI,UAAU,IAAI,EAAE,MAAM;AAChC,kBAAQ,KAAK,YAAO,GAAG,SAAS,EAAE,MAAM,EAAE;AAAA,QAC5C;AAAA,MACF;AACA,UAAI,QAAQ,SAAS,GAAG;AACtB,gBAAQ,KAAK,EAAE;AACf,gBAAQ,KAAK,uBAAuB;AACpC,mBAAW,KAAK,QAAQ,MAAM,GAAG,CAAC,GAAG;AACnC,gBAAM,IAAI,UAAU,IAAI,EAAE,MAAM;AAChC,kBAAQ,KAAK,YAAO,GAAG,SAAS,EAAE,MAAM,WAAM,EAAE,eAAe,YAAY,mBAAmB,EAAE;AAAA,QAClG;AAAA,MACF;AACA,UAAI,OAAO,SAAS,KAAK,QAAQ,SAAS,OAAO,QAAQ;AACvD,gBAAQ,KAAK,EAAE;AACf,gBAAQ,KAAK,cAAc;AAC3B,mBAAW,KAAK,OAAO,OAAO,OAAK,EAAE,UAAU,SAAS,EAAE,MAAM,GAAG,EAAE,GAAG;AACtE,gBAAM,IAAI,UAAU,IAAI,EAAE,MAAM;AAChC,kBAAQ,KAAK,YAAO,GAAG,SAAS,EAAE,MAAM,KAAK,EAAE,KAAK,GAAG;AAAA,QACzD;AAAA,MACF;AAEA,UAAI,KAAK;AAAA,QACP;AAAA,QACA,OAAO;AAAA,UACL,WAAW,UAAU;AAAA,UACrB,QAAQ,OAAO;AAAA,UACf,QAAQ,OAAO;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,cAAc,KAAK,MAAM,eAAe,GAAI,IAAI;AAAA,UAChD;AAAA,QACF;AAAA,QACA,aAAa,QAAQ,KAAK,IAAI;AAAA,QAC9B,eAAe;AAAA,MACjB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC;AAED,MAAI,IAAI,oBAAoB,OAAO,KAAK,QAAQ;AAC9C,QAAI;AACF,YAAM,SAAS,OAAO,IAAI,OAAO,MAAM,EAAE,EAAE,KAAK;AAChD,UAAI,CAAC,QAAQ;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAG;AAAA,MAAQ;AAC3E,YAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,mBAAmB;AACpD,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,wBAAwB;AAChE,YAAM,OAAO,QAAQ,MAAM;AAC3B,UAAI,CAAC,MAAM;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iBAAiB,CAAC;AAAG;AAAA,MAAQ;AACxE,YAAM,QAAQ,eAAe,MAAM;AACnC,UAAI,KAAK;AAAA,QACP,MAAM;AAAA,UACJ,IAAI,KAAK;AAAA,UACT,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,UACf,UAAU,KAAK;AAAA,UACf,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,aAAa,KAAK;AAAA,UAClB,MAAM,KAAK,QAAQ,CAAC;AAAA,UACpB,WAAW,KAAK,YAAY,CAAC,GAAG,IAAI,QAAM;AAAA,YACxC,IAAI,EAAE;AAAA,YACN,OAAO,EAAE;AAAA,YACT,aAAa,EAAE;AAAA,YACf,QAAQ,EAAE;AAAA,YACV,WAAW,EAAE,aAAa,CAAC;AAAA,YAC3B,SAAS,EAAE;AAAA,YACX,aAAa,EAAE;AAAA,UACjB,EAAE;AAAA,QACJ;AAAA,QACA,QAAQ,QAAQ;AAAA,UACd,OAAO,MAAM;AAAA,UACb,WAAW,MAAM;AAAA,UACjB,kBAAkB,MAAM,oBAAoB;AAAA,UAC5C,QAAQ,MAAM;AAAA,UACd,eAAe,MAAM,iBAAiB;AAAA,UACtC,cAAc,MAAM,WAAW,CAAC,GAAG,MAAM,GAAG;AAAA,UAC5C,eAAe,MAAM;AAAA,QACvB,IAAI;AAAA,MACN,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACvF;AAAA,EACF,CAAC;AAED,MAAI,KAAK,2BAA2B,OAAO,KAAK,QAAQ;AACtD,QAAI;AACF,YAAM,SAAS,OAAO,IAAI,OAAO,MAAM,EAAE,EAAE,KAAK;AAChD,UAAI,CAAC,QAAQ;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAG;AAAA,MAAQ;AAC3E,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,wBAAwB;AAChE,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,mBAAmB;AACvD,YAAM,QAAQ,eAAe,MAAM;AACnC,UAAI,OAAO;AACT,cAAM,aAAa,kBAAkB;AAAA,MAEvC;AACA,iBAAW,QAAQ,EAAE,QAAQ,SAAS,CAAC;AACvC,UAAI,KAAK,EAAE,IAAI,MAAM,SAAS,WAAW,MAAM,+DAA+D,CAAC;AAAA,IACjH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,SAAU,IAAc,QAAQ,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC;AAOD,MAAI,KAAK,kBAAkB,OAAO,KAAK,QAAQ;AAC7C,QAAI;AACF,YAAM,SAAS,iBAAiB,GAA6C;AAC7E,YAAM,QAAQ,IAAI,MAAM,UAAU;AAClC,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,4BAA4B;AAIlE,WAAK,aAAa,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,YAAU;AAClD,eAAO,KAAK,WAAW,wCAAwC,OAAO,SAAS,WAAW,OAAO,MAAM,EAAE;AAAA,MAC3G,CAAC,EAAE,MAAM,SAAO;AACd,eAAO,KAAK,WAAW,qCAAsC,IAAc,OAAO,EAAE;AAAA,MACtF,CAAC;AACD,UAAI,KAAK,EAAE,IAAI,MAAM,SAAS,+HAA+H,CAAC;AAAA,IAChK,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,SAAU,IAAc,QAAQ,CAAC;AAAA,IACrF;AAAA,EACF,CAAC;AAED,MAAI,IAAI,cAAc,CAAC,MAAM,QAAQ;AACnC,UAAM,QAAQ,cAAc;AAC5B,UAAM,MAAM,WAAW;AACvB,UAAM,cAAc,IAAI,MAAM,SAAS;AACvC,UAAM,MAAM,QAAQ,YAAY;AAChC,UAAM,eAAe,WAAW,EAAE,OAAO,OAAK,EAAE,WAAW,SAAS,EAAE;AACtE,UAAM,iBAAiB,aAAa,EAAE;AACtC,QAAI,KAAK;AAAA,MACP,GAAG;AAAA,MACH,SAAS;AAAA,MACT,QAAQ,QAAQ,OAAO;AAAA,MACvB,OAAO,YAAY,QAAQ,aAAa,EAAE;AAAA,MAC1C,UAAU,YAAY,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MACvC,UAAU,KAAK,MAAM,IAAI,MAAM,OAAO,IAAI;AAAA,MAC1C,aAAa;AAAA,QACX,UAAU,IAAI;AAAA,QACd,WAAW,IAAI;AAAA,QACf,KAAK,IAAI;AAAA,QACT,UAAU,IAAI;AAAA,QACd,cAAc,IAAI;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,QACN,eAAe,YAAY;AAAA,QAC3B,YAAY,YAAY;AAAA,QACxB,WAAW,YAAY;AAAA,QACvB,eAAe,YAAY;AAAA,QAC3B,eAAe,KAAK,MAAM,QAAQ,OAAO,CAAC;AAAA,QAC1C,eAAe,KAAK,MAAM,IAAI,WAAW,OAAO,IAAI;AAAA,QACpD;AAAA,QACA,WAAW,MAAM;AAAE,cAAI;AAAE,mBAAO,oBAAoB;AAAA,UAAG,QAAQ;AAAE,mBAAO;AAAA,UAAM;AAAA,QAAE,GAAG;AAAA,MACrF;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,eAAe,mBAAmB,CAAC;AAG3C,MAAI,IAAI,oBAAoB,wBAAwB,CAAC;AAGrD,MAAI,IAAI,kBAAkB,sBAAsB,CAAC;AAGjD,MAAI,IAAI,qBAAqB,wBAAwB,CAAC;AAGtD,MAAI,IAAI,iBAAiB,qBAAqB,aAAa,CAAC;AAG5D,MAAI,IAAI,QAAQ,yBAAyB,CAAC;AAC1C,MAAI,IAAI,QAAQ,mBAAmB,QAAQ,CAAC;AAC5C,MAAI,IAAI,QAAQ,kBAAkB,CAAC;AAKnC,MAAI,IAAI,oBAAoB,OAAO,MAAM,QAAQ;AAC/C,QAAI;AACF,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,kBAAkB;AACzD,UAAI,KAAK,cAAc,CAAC;AAAA,IAC1B,QAAQ;AAAE,UAAI,KAAK,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,GAAG,iBAAiB,CAAC,GAAG,YAAY,EAAE,CAAC;AAAA,IAAG;AAAA,EAC1F,CAAC;AAED,MAAI,IAAI,8BAA8B,OAAO,KAAK,QAAQ;AACxD,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,kBAAkB;AACxD,YAAM,QAAQ,aAAa,IAAI,OAAO,SAAS;AAC/C,UAAI,CAAC,OAAO;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mCAAmC,CAAC;AAAG;AAAA,MAAQ;AAC3F,UAAI,KAAK,KAAK;AAAA,IAChB,QAAQ;AAAE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,CAAC;AAAA,IAAG;AAAA,EACjE,CAAC;AAGD,MAAI,IAAI,8BAA8B,OAAO,MAAM,QAAQ;AACzD,QAAI;AACF,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,wBAAwB;AAC/D,YAAM,QAAQ,SAAS,KAAK,MAAM,SAAmB,MAAM,EAAE;AAC7D,UAAI,KAAK,EAAE,YAAY,cAAc,KAAK,EAAE,CAAC;AAAA,IAC/C,QAAQ;AAAE,UAAI,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,IAAG;AAAA,EAC1C,CAAC;AAGD,MAAI,IAAI,eAAe,OAAO,MAAM,QAAQ;AAC1C,QAAI;AACF,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,oBAAoB;AAC7D,YAAM,QAAQ,SAAS,KAAK,MAAM,SAAmB,MAAM,EAAE;AAC7D,UAAI,KAAK,EAAE,QAAQ,gBAAgB,KAAK,EAAE,CAAC;AAAA,IAC7C,QAAQ;AAAE,UAAI,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;AAAA,IAAG;AAAA,EACtC,CAAC;AAOD,MAAI,IAAI,sBAAsB,OAAO,MAAM,QAAQ;AACjD,QAAI;AACF,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,oBAAoB;AAC5D,YAAM,QAAQ,eAAe;AAC7B,UAAI,CAAC,OAAO;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,gBAAgB,CAAC;AAAG;AAAA,MAAQ;AACxE,UAAI,KAAK,KAAK;AAAA,IAChB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,kBAAmB,EAAY,OAAO,EAAE;AAChE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,eAAe,OAAO,MAAM,QAAQ;AAC1C,QAAI;AACF,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,oBAAoB;AAC5D,YAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,SAAS,OAAO,KAAK,MAAM,SAAS,IAAI,GAAG,EAAE,KAAK,IAAI,CAAC,GAAG,GAAG;AAC7F,UAAI,KAAK,EAAE,OAAO,eAAe,KAAK,EAAE,CAAC;AAAA,IAC3C,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,gBAAiB,EAAY,OAAO,EAAE;AAC9D,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,qBAAqB,OAAO,KAAK,QAAQ;AAC/C,QAAI;AACF,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,oBAAoB;AAG5D,UAAI,CAAC,sBAAsB,KAAK,IAAI,OAAO,IAAI,GAAG;AAChD,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,0BAA0B,CAAC;AACzD;AAAA,MACF;AACA,YAAM,QAAQ,eAAe,IAAI,OAAO,IAAI;AAC5C,UAAI,CAAC,OAAO;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAAG;AAAA,MAAQ;AACjF,UAAI,KAAK,KAAK;AAAA,IAChB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,iBAAkB,EAAY,OAAO,EAAE;AAC/D,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,KAAK,wBAAwB,OAAO,MAAM,QAAQ;AACpD,QAAI;AACF,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,oBAAoB;AAC3D,YAAM,QAAQ,MAAM,cAAc;AAClC,UAAI,KAAK,KAAK;AAAA,IAChB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,oBAAqB,EAAY,OAAO,EAAE;AAClE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,SAAU,EAAY,QAAQ,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC;AAOD,MAAI,IAAI,yBAAyB,OAAO,MAAM,QAAQ;AACpD,QAAI;AACF,YAAM,MAAM,WAAW;AACvB,YAAM,WAAW,IAAI;AACrB,UAAI,KAAK;AAAA,QACP,SAAS,UAAU,WAAW;AAAA,QAC9B,gBAAgB,UAAU,kBAAkB;AAAA,QAC5C,aAAa,UAAU,eAAe,CAAC;AAAA,QACvC,UAAU,UAAU,YAAY,CAAC;AAAA,MACnC,CAAC;AAAA,IACH,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,0BAA2B,EAAY,OAAO,EAAE;AACxE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,gCAAgC,OAAO,KAAK,QAAQ;AAC1D,QAAI;AACF,YAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,6BAA6B;AAC5E,YAAM,UAAU,OAAO,IAAI,MAAM,YAAY,WAAW,IAAI,MAAM,UAAU;AAC5E,UAAI,KAAK,sBAAsB,EAAE,QAAQ,CAAC,CAAC;AAAA,IAC7C,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,4BAA6B,EAAY,OAAO,EAAE;AAC1E,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAQD,MAAI,IAAI,wBAAwB,OAAO,MAAM,QAAQ;AACnD,QAAI;AACF,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,4BAA4B;AACjE,UAAI,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;AAAA,IACrC,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,yBAA0B,EAAY,OAAO,EAAE;AACvE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,8BAA8B,CAAC;AAAA,IAC/D;AAAA,EACF,CAAC;AAED,MAAI,KAAK,wBAAwB,OAAO,KAAK,QAAQ;AACnD,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,4BAA4B;AAClE,YAAM,OAAQ,IAAI,QAAQ,CAAC;AAC3B,UAAI,CAAC,KAAK,cAAc,CAAC,KAAK,eAAe,OAAO,KAAK,YAAY,UAAU;AAC7E,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oDAAoD,CAAC;AACnF;AAAA,MACF;AACA,YAAM,SAAS,aAAa;AAAA,QAC1B,YAAY,KAAK;AAAA,QACjB,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK;AAAA,QACd,SAAS,KAAK;AAAA,QACd,MAAM,KAAK;AAAA,QACX,IAAI,KAAK;AAAA,MACX,CAAC;AACD,UAAI,KAAK,MAAM;AAAA,IACjB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,2BAA4B,EAAY,OAAO,EAAE;AACzE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,EAAY,QAAQ,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,OAAO,4BAA4B,OAAO,KAAK,QAAQ;AACzD,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,4BAA4B;AAClE,YAAM,KAAK,aAAa,IAAI,OAAO,EAAE;AACrC,UAAI,CAAC,IAAI;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,CAAC;AAAG;AAAA,MAAQ;AACxE,UAAI,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,IAC5B,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,2BAA4B,EAAY,OAAO,EAAE;AACzE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,gBAAgB,CAAC;AAAA,IACjD;AAAA,EACF,CAAC;AAED,MAAI,KAAK,mCAAmC,OAAO,KAAK,QAAQ;AAC9D,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,4BAA4B;AAClE,YAAM,SAAU,IAAI,QAAQ,OAAO,IAAI,KAAK,WAAW,WAAY,IAAI,KAAK,SAAS;AACrF,YAAM,SAAS,aAAa,IAAI,OAAO,IAAI,QAAQ,QAAQ;AAC3D,UAAI,CAAC,QAAQ;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,CAAC;AAAG;AAAA,MAAQ;AAC5E,UAAI,KAAK,MAAM;AAAA,IACjB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,2BAA4B,EAAY,OAAO,EAAE;AACzE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,gBAAgB,CAAC;AAAA,IACjD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,mCAAmC,OAAO,KAAK,QAAQ;AAC7D,QAAI;AACF,YAAM,EAAE,WAAW,eAAe,IAAI,MAAM,OAAO,4BAA4B;AAC/E,YAAM,SAAS,UAAU,IAAI,OAAO,EAAE;AACtC,UAAI,CAAC,QAAQ;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mBAAmB,CAAC;AAAG;AAAA,MAAQ;AAC5E,YAAM,MAAM,WAAW;AACvB,YAAM,UAAW,IAAI,UAA+I;AACpK,YAAM,SAAS,eAAe,QAAQ;AAAA,QACpC,YAAY,SAAS;AAAA,QACrB,eAAe,SAAS;AAAA,QACxB,gBAAgB,SAAS;AAAA,QACzB,qBAAqB,SAAS;AAAA,MAChC,CAAC;AACD,UAAI,KAAK,EAAE,QAAQ,OAAO,CAAC;AAAA,IAC7B,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,2BAA4B,EAAY,OAAO,EAAE;AACzE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,+BAA+B,OAAO,MAAM,QAAQ;AAC1D,QAAI;AACF,YAAM,EAAE,aAAa,eAAe,IAAI,MAAM,OAAO,4BAA4B;AACjF,YAAM,UAAU,YAAY;AAC5B,YAAM,MAAM,WAAW;AACvB,YAAM,UAAW,IAAI,UAA+I;AACpK,YAAM,MAAM,QAAQ,IAAI,aAAW;AAAA,QACjC;AAAA,QACA,QAAQ,eAAe,QAAQ;AAAA,UAC7B,YAAY,SAAS;AAAA,UACrB,eAAe,SAAS;AAAA,UACxB,gBAAgB,SAAS;AAAA,UACzB,qBAAqB,SAAS;AAAA,QAChC,CAAC;AAAA,MACH,EAAE;AACF,UAAI,KAAK,EAAE,SAAS,IAAI,CAAC;AAAA,IAC3B,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,+BAAgC,EAAY,OAAO,EAAE;AAC7E,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,oBAAoB,OAAO,MAAM,QAAQ;AAC/C,UAAM,SAAkF,CAAC;AACzF,QAAI,UAAsC;AAG1C,QAAI;AACF,YAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,OAAO,qBAAqB;AACpD,YAAM,KAAKA,OAAM;AACjB,aAAO,SAAS,EAAE,QAAQ,MAAM,QAAQ,GAAG,GAAG,SAAS,MAAM,cAAc,GAAG,SAAS,MAAM,YAAY;AAAA,IAC3G,SAAS,GAAG;AACV,aAAO,SAAS,EAAE,QAAQ,QAAQ,QAAS,EAAY,QAAQ;AAC/D,gBAAU;AAAA,IACZ;AAGA,QAAI;AACF,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,oBAAoB;AAC3D,YAAM,QAAQA,eAAc;AAC5B,aAAO,QAAQ,EAAE,QAAQ,MAAM,QAAQ,GAAG,MAAM,YAAY,cAAc,MAAM,WAAW,YAAY;AAAA,IACzG,SAAS,GAAG;AACV,aAAO,QAAQ,EAAE,QAAQ,QAAQ,QAAS,EAAY,QAAQ;AAC9D,gBAAU;AAAA,IACZ;AAGA,QAAI;AACF,YAAM,EAAE,wBAAwB,IAAI,MAAM,OAAO,sBAAsB;AACvE,aAAO,UAAU,EAAE,QAAQ,wBAAwB,IAAI,OAAO,YAAY,QAAQ,wBAAwB,IAAI,UAAU,0BAA0B;AAClJ,UAAI,CAAC,wBAAwB,KAAK,YAAY,KAAM,WAAU;AAAA,IAChE,SAAS,GAAG;AACV,aAAO,UAAU,EAAE,QAAQ,QAAQ,QAAS,EAAY,QAAQ;AAChE,gBAAU;AAAA,IACZ;AAGA,QAAI;AACF,YAAM,iBAAiB,MAAM,eAAe;AAC5C,YAAM,UAAU,OAAO,QAAQ,cAAc;AAC7C,YAAM,mBAAmB,QAAQ,OAAO,CAAC,CAAC,EAAE,OAAO,MAAM,OAAO,EAAE;AAClE,aAAO,YAAY,EAAE,QAAQ,mBAAmB,IAAI,OAAO,QAAQ,QAAQ,GAAG,gBAAgB,IAAI,QAAQ,MAAM,WAAW;AAC3H,UAAI,qBAAqB,EAAG,WAAU;AAAA,IACxC,SAAS,GAAG;AACV,aAAO,YAAY,EAAE,QAAQ,QAAQ,QAAS,EAAY,QAAQ;AAClE,gBAAU;AAAA,IACZ;AAGA,QAAI;AACF,YAAM,YAAY,MAAM,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE;AACvF,aAAO,WAAW,EAAE,QAAQ,YAAY,IAAI,OAAO,YAAY,QAAQ,GAAG,SAAS,IAAI,SAAS,IAAI,aAAa;AACjH,UAAI,cAAc,KAAK,YAAY,KAAM,WAAU;AAAA,IACrD,SAAS,GAAG;AACV,aAAO,WAAW,EAAE,QAAQ,QAAQ,QAAS,EAAY,QAAQ;AACjE,gBAAU;AAAA,IACZ;AAGA,UAAM,QAAQ,QAAQ,OAAO,OAAO;AACpC,UAAM,IAAI,QAAQ,CAACJ,aAAY,aAAaA,QAAO,CAAC;AACpD,UAAM,QAAQ,OAAO,QAAQ,OAAO,OAAO,IAAI,KAAK;AACpD,UAAM,QAAQ,QAAQ;AACtB,WAAO,YAAY,EAAE,QAAQ,QAAQ,MAAM,OAAO,QAAQ,MAAM,aAAa,QAAQ,QAAQ,GAAG,MAAM,QAAQ,CAAC,CAAC,SAAS;AACzH,QAAI,SAAS,IAAK,WAAU;AAAA,aACnB,SAAS,OAAO,YAAY,KAAM,WAAU;AAErD,QAAI,OAAO,YAAY,OAAO,MAAM,YAAY,aAAa,MAAM,GAAG,EAAE,KAAK;AAAA,MAC3E,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ,QAAQ,OAAO;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,iBAAiB,CAAC,MAAM,QAAQ;AACtC,QAAI;AACF,UAAI,KAAK,EAAE,UAAU,aAAa,GAAG,QAAQ,iBAAiB,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,IAC9E,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AACjE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IAClG;AAAA,EACF,CAAC;AAED,MAAI,KAAK,iBAAiB,CAAC,KAAK,QAAQ;AACtC,QAAI;AACF,YAAM,EAAE,MAAM,QAAQ,aAAa,gBAAgB,IAAI,IAAI;AAC3D,UAAI,CAAC,QAAQ,CAAC,QAAQ;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,+BAA+B,CAAC;AAAG;AAAA,MAAQ;AACjG,YAAM,UAAU,WAAW,EAAE,MAAM,QAAQ,aAAa,eAAe,YAAY,iBAAiB,mBAAmB,GAAG,CAAQ;AAClI,UAAI,OAAO,GAAG,EAAE,KAAK,OAAO;AAAA,IAC9B,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AACjE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IAClG;AAAA,EACF,CAAC;AAED,MAAI,OAAO,qBAAqB,CAAC,KAAK,QAAQ;AAC5C,QAAI;AACF,oBAAc,IAAI,OAAO,EAAE;AAC3B,UAAI,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACvB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AACjE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IAClG;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,QAAQ,kBAAkB,CAAC;AACnC,MAAI,IAAI,QAAQ,qBAAqB,SAAS,CAAC;AAC/C,MAAI,IAAI,QAAQ,oBAAoB,CAAC;AACrC,MAAI,IAAI,QAAQ,gBAAgB,CAAC;AACjC,MAAI,IAAI,QAAQ,mBAAmB,CAAC;AAIpC,MAAI,KAAK,gBAAgB,UAAU,0BAA0B,mBAAmB,GAAG,iBAAiB,uBAAuB,GAAG,OAAO,KAAK,QAAQ;AAKhJ,UAAM,OAAQ,IAAI,QAAQ,CAAC;AAC3B,UAAM,UAAW,OAAO,KAAK,YAAY,YAAY,KAAK,WAAa,OAAO,KAAK,YAAY,YAAY,KAAK,WAAY;AAC5H,UAAM,EAAE,SAAS,YAAY,SAAS,YAAY,SAAS,WAAW,oBAAoB,OAAO,gBAAgB,qBAAqB,IAAI;AAI1I,UAAM,UAAU,eAAe,IAAI,QAAQ,WAAW,sBAAsB,YAAY;AACxF,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kDAAkD,CAAC;AACjF;AAAA,IACF;AAMA,QAAI,kBAAkB,OAAO,mBAAmB,UAAU;AACxD,YAAM,EAAE,iBAAiB,sBAAsB,IAAI,MAAM,OAAO,wBAAwB;AACxF,UAAI,CAAC,gBAAgB,cAAc,GAAG;AACpC,cAAM,YAAY,sBAAsB;AACxC,cAAM,wBAAwB,eAAe,MAAM,GAAG,EAAE,CAAC,KAAK;AAE9D,cAAM,KAAK,sBAAsB,YAAY;AAC7C,cAAM,cAAc,UAAU,OAAO,OAAK,EAAE,WAAW,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC;AACpG,YAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UACnB,OAAO;AAAA,UACP,SAAS,kBAAkB,cAAc,gBAAgB,qBAAqB;AAAA,UAC9E,aAAa,YAAY,SAAS,IAAI,YAAY,IAAI,OAAK,GAAG,CAAC,MAAM,IAAI;AAAA,UACzE,oBAAoB;AAAA,QACtB,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,YAAY,QAAQ,aAAc,UAAU;AA0B/D,UAAM,eAAe;AACrB,UAAM,eAAe;AACrB,UAAM,0BAA0B,aAAa,KAAK,OAAO,KAAK,aAAa,KAAK,OAAO;AACvF,UAAM,wBAAwG;AAAA,MAC1G,EAAE,SAAS,0CAA0C,QAAQ,iBAAiB,MAAM,kBAAkB,GAAG,GAAG,GAAG,EAAE;AAAA,MACjH,EAAE,SAAS,gDAAgD,QAAQ,mBAAmB,MAAM,sBAAsB,GAAG,GAAG,GAAG,EAAE;AAAA,MAC7H,EAAE,SAAS,kDAAkD,QAAQ,kBAAkB,MAAM,kBAAkB,GAAG,GAAG,GAAG,EAAE;AAAA,MAC1H,EAAE,SAAS,4BAA4B,QAAQ,eAAe,MAAM,gBAAgB,GAAG,GAAG,GAAG,EAAE;AAAA,MAC/F,EAAE,SAAS,qDAAqD,QAAQ,gBAAgB,MAAM,YAAY,GAAG,GAAG,GAAG,EAAE;AAAA,MACrH,EAAE,SAAS,0CAA0C,QAAQ,eAAe,MAAM,kBAAkB,GAAG,GAAG,GAAG,EAAE;AAAA,MAC/G,EAAE,SAAS,8CAA8C,QAAQ,sBAAsB,MAAM,eAAe,GAAG,GAAG,GAAG,EAAE;AAAA,MACvH,EAAE,SAAS,iCAAiC,QAAQ,mBAAmB,MAAM,oBAAoB,GAAG,GAAG,GAAG,EAAE;AAAA,MAC5G,EAAE,SAAS,sCAAsC,QAAQ,gBAAgB,MAAM,gBAAgB,GAAG,GAAG,GAAG,EAAE;AAAA,MAC1G,EAAE,SAAS,6CAA6C,QAAQ,kBAAkB,MAAM,iBAAiB,GAAG,GAAG,GAAG,EAAE;AAAA;AAAA,MAEpH,EAAE,SAAS,+CAA+C,QAAQ,eAAe,MAAM,YAAY,GAAG,GAAG,GAAG,EAAE;AAAA,IAClH;AACA,UAAM,kBAAkB,0BAClB,sBAAsB,KAAK,OAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,IACvD;AACN,QAAI,iBAAiB;AACjB,YAAM,WAAW;AAAA,aAA2B,gBAAgB,IAAI,qCAAqC,gBAAgB,MAAM,WAAW,gBAAgB,CAAC,UAAU,gBAAgB,CAAC;AAClL,YAAM,eAAe,eAAe,gBAAgB,IAAI;AACxD,yBAAmB,UAAU,EAAE,SAAS,QAAQ,KAAK,CAAC;AACtD,UAAI,IAAI,QAAQ,WAAW,qBAAqB;AAC5C,YAAI,UAAU,gBAAgB,mBAAmB;AACjD,YAAI,aAAa;AACjB,cAAMK,YAAW,cAAc,GAAG;AAClC,QAAAA,UAAS;AAAA,QAAuB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC,CAAC;AAAA;AAAA,CAAM;AAC5E,QAAAA,UAAS;AAAA,QAAuB,KAAK,UAAU,EAAE,MAAM,SAAS,SAAS,CAAC,CAAC;AAAA;AAAA,CAAM;AACjF,QAAAA,UAAS;AAAA,QAAsB,KAAK,UAAU,EAAE,SAAS,eAAe,SAAS,UAAU,WAAW,sBAAsB,MAAM,YAAY,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AACvK,YAAI,IAAI;AAAA,MACZ,OAAO;AACH,YAAI,KAAK,EAAE,SAAS,eAAe,SAAS,UAAU,WAAW,sBAAsB,MAAM,WAAW,CAAC,GAAG,OAAO,UAAU,YAAY,EAAE,CAAC;AAAA,MAChJ;AACA;AAAA,IACJ;AAEA,UAAM,YAAY,QAAQ,OAAO,OAAO;AACxC,UAAM,WAAW,IAAI,QAAQ,WAAW;AAGxC,QAAI,sBAAsB,CAAC,0BAA0B,KAAK,kBAAkB,GAAG;AAC7E,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAC3D;AAAA,IACF;AAGA,UAAM,kBAAkB,IAAI,gBAAgB;AAC5C,QAAI,oBAAoB;AACtB,oBAAc,IAAI,oBAAoB,eAAe;AACrD,wBAAkB,IAAI,oBAAoB,KAAK,IAAI,CAAC;AAEpD,UAAI,CAAC,cAAc,IAAI,kBAAkB,GAAG;AAC1C,sBAAc,IAAI,oBAAoB,iBAAiB,GAAG,CAAC;AAAA,MAC7D;AAAA,IACF;AAGA,QAAI;AACF,YAAM,cAAc,MAAM,mBAAmB,SAAS,SAAS,MAAM;AACrE,UAAI,aAAa;AACf,2BAAmB,UAAU,EAAE,SAAS,QAAQ,KAAK,CAAC;AACtD,cAAM,cAAc,OAAO,QAAQ,OAAO,OAAO,IAAI,SAAS,IAAI;AAClE,6BAAqB,QAAQ,aAAa,EAAE,QAAQ,CAAC;AACrD,YAAI,UAAU;AACZ,cAAI,UAAU,gBAAgB,mBAAmB;AACjD,cAAI,UAAU,iBAAiB,UAAU;AACzC,cAAI,UAAU,cAAc,YAAY;AACxC,cAAI,UAAU,qBAAqB,IAAI;AACvC,cAAI,aAAa;AACjB,gBAAMA,YAAW,cAAc,GAAG;AAClC,UAAAA,UAAS;AAAA,QAAsB,KAAK,UAAU,EAAE,SAAS,YAAY,UAAU,WAAW,MAAM,YAAY,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AACtH,cAAI,IAAI;AAAA,QACV,OAAO;AACL,cAAI,KAAK,EAAE,SAAS,YAAY,UAAU,WAAW,MAAM,WAAW,CAAC,GAAG,OAAO,SAAS,CAAC;AAAA,QAC7F;AACA;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAAqC;AAK7C,QAAI;AACF,YAAM,aAAa;AACnB,YAAM,aAAa;AACnB,YAAM,aAAa;AACnB,UAAI,WAAW,KAAK,OAAO,MAAM,WAAW,KAAK,OAAO,KAAK,WAAW,KAAK,OAAO,IAAI;AACtF,cAAM,WAAW,QAAQ,MAAM,UAAU;AACzC,cAAM,WAAW,QAAQ,MAAM,UAAU;AACzC,cAAM,MAAM,WAAW;AACvB,YAAI,QAAQ;AACZ,YAAI,aAAa,CAAC,IAAI,eAAe,SAAS,IAAI,cAAc,UAAU,SAAS,CAAC,IAAI;AAEtF,cAAI,cAAc,QAAQ,SAAS,CAAC;AACpC,kBAAQ;AACR,iBAAO,KAAK,WAAW,wGAAwG;AAAA,QACjI;AACA,YAAI,YAAY,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,CAAC,IAAI,eAAe,OAAO,IAAI,cAAc,QAAQ,SAAS,CAAC,EAAE,QAAQ,QAAQ,EAAE,IAAI;AACrI,cAAI,cAAc,MAAM,SAAS,CAAC,EAAE,QAAQ,QAAQ,EAAE;AACtD,kBAAQ;AAAA,QACV;AACA,YAAI,OAAO;AACT,uBAAa,EAAE,eAAe,IAAI,cAAc,CAAC;AACjD,iBAAO,KAAK,WAAW,yDAAyD;AAAA,QAClF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAA6C;AAGrD,UAAM,gBAAgB,0BAA0B,WAAW,EAAE,SAAS,sBAAsB;AAC5F,QAAI,qBAAqB,eAAe;AACtC,yBAAmB,UAAU,EAAE,SAAS,QAAQ,OAAO,CAAC;AACxD,uBAAiB,UAAU,EAAE,MAAM,OAAO,CAAC;AAC3C,UAAI,UAAU;AACZ,YAAI,UAAU,gBAAgB,mBAAmB;AACjD,YAAI,aAAa;AACjB,cAAMA,YAAW,cAAc,GAAG;AAClC,QAAAA,UAAS;AAAA,QAAsB,KAAK,UAAU,EAAE,OAAO,cAAc,CAAC,CAAC;AAAA;AAAA,CAAM;AAC7E,YAAI,IAAI;AAAA,MACV,OAAO;AACL,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sEAAiE,CAAC;AAAA,MAClG;AACA;AAAA,IACF;AACA;AACA,wBAAoB,IAAI;AAExB,QAAI,qBAAqB;AACzB,QAAI,WAA4C;AAGhD,QAAI,qBAA0C;AAQ9C,QAAI,oBAA2D;AAC/D,QAAI;AACF,UAAI,UAAU;AACZ,YAAI,UAAU,gBAAgB,mBAAmB;AACjD,YAAI,UAAU,iBAAiB,UAAU;AACzC,YAAI,UAAU,cAAc,YAAY;AACxC,YAAI,UAAU,qBAAqB,IAAI;AACvC,YAAI,aAAa;AAEjB,YAAI,GAAG,SAAS,MAAM;AACpB,+BAAqB;AAErB,0BAAgB,MAAM,qBAAqB;AAAA,QAC7C,CAAC;AAED,mBAAW,cAAc,GAAG;AAC5B,cAAM,YAAY,CAAC,SAAiB;AAClC,cAAI,mBAAoB;AACxB,cAAI;AAAE,qBAAU,IAAI;AAAA,UAAG,QAAQ;AAAE,iCAAqB;AAAA,UAAM;AAAA,QAC9D;AAKA,4BAAoB,YAAY,MAAM;AACpC,cAAI,mBAAoB;AACxB,oBAAU,eAAe,KAAK,IAAI,CAAC;AAAA;AAAA,CAAM;AAAA,QAC3C,GAAG,IAAM;AAMT,YAAI,oBAAoB;AACtB,cAAI;AACF,kBAAM,EAAE,WAAW,iBAAiB,IAAI,MAAM,OAAO,2BAA2B;AAChF,iCAAqB,iBAAiB,oBAAoB,CAAC,QAAQ;AACjE,wBAAU;AAAA,QAAwB,KAAK,UAAU,EAAE,MAAM,IAAI,MAAM,QAAQ,IAAI,QAAQ,WAAW,IAAI,UAAU,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YAC1H,CAAC;AAAA,UACH,SAAS,KAAK;AACZ,mBAAO,KAAK,WAAW,mCAAmC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,UAC9G;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,aAAa,SAAS,SAAS,YAAY;AAAA,UAChE,iBAAiB;AAAA,YACf,SAAS,CAAC,UAAkB;AAC1B,wBAAU;AAAA,QAAuB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YACxE;AAAA,YACA,YAAY,CAAC,MAAc,SAAkC;AAC3D,wBAAU;AAAA,QAA2B,KAAK,UAAU,EAAE,MAAM,MAAM,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YAClG;AAAA,YACA,cAAc,CAAC,MAAc,QAAgB,YAAoB,SAAkB,SAAkB;AACnG,wBAAU;AAAA,QAA0B,KAAK,UAAU,EAAE,MAAM,QAAQ,OAAO,MAAM,GAAG,GAAG,GAAG,YAAY,SAAS,MAAM,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YACpJ;AAAA,YACA,YAAY,MAAM;AAChB,wBAAU;AAAA,QAA0B,KAAK,UAAU,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YACrF;AAAA,YACA,SAAS,CAAC,OAAe,cAAsB;AAC7C,wBAAU;AAAA,QAAuB,KAAK,UAAU,EAAE,OAAO,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YACpG;AAAA;AAAA;AAAA;AAAA,YAIA,SAAS,CAAC,SAAS;AACjB,wBAAU;AAAA,QAAuB,KAAK,UAAU,EAAE,GAAG,MAAM,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YAC3F;AAAA,YACA,YAAY,CAAC,SAAS;AACpB,wBAAU;AAAA,QAA0B,KAAK,UAAU,EAAE,GAAG,MAAM,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YAC9F;AAAA;AAAA;AAAA;AAAA;AAAA,UAKF;AAAA,UACA,iBAAiB;AAAA,UACjB,QAAQ,gBAAgB;AAAA,UACxB,WAAW;AAAA,UACX,eAAe;AAAA,UACf,sBAAsB,OAAO,yBAAyB,WAAW,uBAAuB;AAAA,QAC1F,CAAC;AACD,2BAAmB,UAAU,EAAE,SAAS,QAAQ,KAAK,CAAC;AACtD,YAAI,SAAS,WAAW;AACtB,qBAAW,QAAQ,SAAS,UAAW,qBAAoB,UAAU,EAAE,KAAK,CAAC;AAAA,QAC/E;AACA,YAAI,SAAS,YAAY;AACvB,cAAI,SAAS,WAAW,OAAQ,kBAAiB,UAAU,EAAE,MAAM,SAAS,GAAG,SAAS,WAAW,MAAM;AACzG,cAAI,SAAS,WAAW,WAAY,kBAAiB,UAAU,EAAE,MAAM,aAAa,GAAG,SAAS,WAAW,UAAU;AAAA,QACvH;AACA,YAAI,SAAS,MAAO,yBAAwB,UAAU,EAAE,OAAO,SAAS,OAAO,UAAU,UAAU,CAAC;AACpG,mBAAW,SAAS,SAAS,WAAW,SAAS,YAAY,SAAS,cAAc,GAAG,SAAS,aAAa,EAAE;AAE/G,YAAI;AACF,gBAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,+BAA+B;AACzE,gBAAM,YAAY;AAAA,YAChB,SAAS,WAAW;AAAA,YACpB;AAAA,YACA;AAAA,UACF;AACA,cAAI,UAAU,WAAW;AACvB,mBAAO,KAAK,WAAW,wDAAwD,UAAU,OAAO,KAAK,IAAI,CAAC,EAAE;AAC5G,qBAAS,UAAU,UAAU;AAAA,UAC/B;AAAA,QACF,QAAQ;AAAA,QAA8B;AACtC,YAAI,CAAC,oBAAoB;AACvB,oBAAU;AAAA,QAAsB,KAAK,UAAU,EAAE,SAAS,SAAS,SAAS,WAAW,SAAS,WAAW,YAAY,SAAS,YAAY,OAAO,SAAS,OAAO,WAAW,SAAS,WAAW,iBAAiB,SAAS,gBAAgB,CAAC,CAAC;AAAA;AAAA,CAAM;AACpP,cAAI;AAAE,gBAAI,IAAI;AAAA,UAAG,QAAQ;AAAA,UAAoB;AAAA,QAC/C;AAAA,MACF,OAAO;AACL,cAAM,WAAW,MAAM,aAAa,SAAS,SAAS,YAAY;AAAA,UAChE,iBAAiB;AAAA,UACjB,QAAQ,gBAAgB;AAAA,UACxB,WAAW;AAAA,UACX,eAAe;AAAA,UACf,sBAAsB,OAAO,yBAAyB,WAAW,uBAAuB;AAAA,QAC1F,CAAC;AACD,2BAAmB,UAAU,EAAE,SAAS,QAAQ,KAAK,CAAC;AACtD,YAAI,SAAS,WAAW;AACtB,qBAAW,QAAQ,SAAS,UAAW,qBAAoB,UAAU,EAAE,KAAK,CAAC;AAAA,QAC/E;AACA,YAAI,SAAS,YAAY;AACvB,cAAI,SAAS,WAAW,OAAQ,kBAAiB,UAAU,EAAE,MAAM,SAAS,GAAG,SAAS,WAAW,MAAM;AACzG,cAAI,SAAS,WAAW,WAAY,kBAAiB,UAAU,EAAE,MAAM,aAAa,GAAG,SAAS,WAAW,UAAU;AAAA,QACvH;AACA,YAAI,SAAS,MAAO,yBAAwB,UAAU,EAAE,OAAO,SAAS,OAAO,UAAU,UAAU,CAAC;AACpG,mBAAW,SAAS,SAAS,WAAW,SAAS,YAAY,SAAS,cAAc,GAAG,SAAS,aAAa,EAAE;AAK/G,YAAI;AACF,gBAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,+BAA+B;AACzE,gBAAM,YAAY;AAAA,YAChB,SAAS,WAAW;AAAA,YACpB;AAAA,YACA;AAAA,UACF;AACA,cAAI,UAAU,WAAW;AACvB,mBAAO,KAAK,WAAW,oDAAoD,UAAU,OAAO,KAAK,IAAI,CAAC,EAAE;AACxG,qBAAS,UAAU,UAAU;AAAA,UAC/B;AAAA,QACF,QAAQ;AAAA,QAA6C;AACrD,YAAI,KAAK,QAAQ;AAAA,MACnB;AAAA,IACF,SAAS,OAAO;AACd,yBAAmB,UAAU,EAAE,SAAS,QAAQ,QAAQ,CAAC;AACzD,uBAAiB,UAAU,EAAE,MAAM,UAAU,CAAC;AAG9C,UAAI;AACF,cAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,4BAA4B;AACtE,cAAM,iBAAiB,OAAO;AAAA,UAC5B,QAAQ;AAAA,UACR;AAAA,UACA,WAAW;AAAA,UACX,OAAO,OAAO,mBAAmB,WAAW,iBAAiB;AAAA,UAC7D,iBAAiB,OAAO,YAAY,WAAW,UAAU;AAAA,UACzD,YAAY;AAAA,QACd,CAAC;AAAA,MACH,QAAQ;AAAA,MAAqD;AAE7D,YAAM,aAAa,kBAAkB,KAAc;AACnD,UAAI,YAAY,CAAC,sBAAsB,UAAU;AAC/C,YAAI;AAAE,mBAAS;AAAA,QAAsB,KAAK,UAAU,UAAU,CAAC;AAAA;AAAA,CAAM;AAAG,cAAI,IAAI;AAAA,QAAG,QAAQ;AAAA,QAAoB;AAAA,MACjH,WAAW,CAAC,UAAU;AACpB,YAAI,OAAO,WAAW,MAAM,EAAE,KAAK,UAAU;AAAA,MAC/C;AAAA,IACF,UAAE;AACA;AACA,0BAAoB,IAAI;AACxB,YAAM,cAAc,OAAO,QAAQ,OAAO,OAAO,IAAI,SAAS,IAAI;AAClE,2BAAqB,QAAQ,aAAa,EAAE,QAAQ,CAAC;AACrD,UAAI,mBAAoB,eAAc,OAAO,kBAAkB;AAG/D,UAAI,oBAAoB;AACtB,YAAI;AAAE,6BAAmB;AAAA,QAAG,QAAQ;AAAA,QAA4C;AAAA,MAClF;AAGA,UAAI,mBAAmB;AACrB,sBAAc,iBAAiB;AAC/B,4BAAoB;AAAA,MACtB;AAAA,IACF;AAAA,EACF,CAAC;AAGD,MAAI,KAAK,oBAAoB,UAAU,KAAO,EAAE,GAAG,iBAAiB,EAAE,GAAG,OAAO,KAAK,QAAQ;AAC3F,UAAM,EAAE,SAAS,MAAM,IAAI,IAAI;AAC/B,QAAI,CAAC,SAAS;AAAE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,sBAAsB,CAAC;AAAG;AAAA,IAAQ;AAEhF,QAAI,UAAU,gBAAgB,mBAAmB;AACjD,QAAI,UAAU,iBAAiB,UAAU;AACzC,QAAI,UAAU,cAAc,YAAY;AACxC,QAAI,UAAU,qBAAqB,IAAI;AACvC,QAAI,aAAa;AACjB,UAAM,WAAW,cAAc,GAAG;AAElC,QAAI;AACF,YAAMC,UAAS,WAAW;AAC1B,YAAM,UAAU,SAASA,QAAO,MAAM,SAAS;AAC/C,YAAM,iBAAiB,CAAC,EAAE,MAAM,UAAmB,SAAS,2CAA2C,CAAC;AACxG,YAAM,eAAe,CAAC,EAAE,MAAM,QAAiB,QAAQ,CAAC;AAExD,uBAAiB,SAAS,WAAW,EAAE,OAAO,SAAS,UAAU,CAAC,GAAG,gBAAgB,GAAG,YAAY,GAAG,WAAWA,QAAO,MAAM,WAAW,aAAaA,QAAO,MAAM,YAAY,CAAC,GAAG;AAClL,iBAAS,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA,CAAM;AAC7C,YAAI,MAAM,SAAS,UAAU,MAAM,SAAS,QAAS;AAAA,MACvD;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,WAAW,iBAAkB,MAAgB,OAAO,EAAE;AACnE,eAAS,SAAS,KAAK,UAAU,EAAE,MAAM,SAAS,OAAO,0DAA0D,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,IAC7H;AACA,QAAI,IAAI;AAAA,EACV,CAAC;AAGD,MAAI,IAAI,cAAc,CAAC,MAAM,QAAQ;AACnC,QAAI,KAAK,cAAc,CAAC;AAAA,EAC1B,CAAC;AAGD,MAAI,IAAI,cAAc,CAAC,KAAK,QAAQ;AAClC,UAAM,QAAQ,SAAS,IAAI,MAAM,KAAe,KAAK;AACrD,UAAM,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAQ,EAAE,YAAY;AACnE,UAAM,SAAS,SAAS,OAAO,OAAK,EAAE,aAAa,MAAM;AAGzD,UAAM,UAAsK,CAAC;AAC7K,eAAW,KAAK,QAAQ;AACtB,UAAI,CAAC,QAAQ,EAAE,KAAK,EAAG,SAAQ,EAAE,KAAK,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,kBAAkB,GAAG,aAAa,GAAG,kBAAkB,GAAG,eAAe,EAAE;AACrJ,YAAM,IAAI,QAAQ,EAAE,KAAK;AACzB,QAAE;AACF,QAAE,gBAAgB,EAAE;AACpB,QAAE,oBAAoB,EAAE;AACxB,QAAE,eAAe,EAAE;AACnB,QAAE,oBAAoB,EAAE;AACxB,QAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,KAAK,EAAE,cAAc,EAAE;AAAA,IAC5E;AAGA,eAAW,KAAK,OAAO,OAAO,OAAO,GAAG;AACtC,QAAE,mBAAmB,KAAK,MAAM,EAAE,mBAAmB,GAAK,IAAI;AAC9D,QAAE,gBAAgB,KAAK,MAAM,EAAE,aAAa;AAAA,IAC9C;AAEA,UAAM,YAAY,OAAO,OAAO,OAAO,EAAE,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,kBAAkB,CAAC;AAEvF,QAAI,KAAK;AAAA,MACP,QAAQ,GAAG,KAAK;AAAA,MAChB,eAAe,OAAO;AAAA,MACtB,aAAa,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,aAAa,CAAC;AAAA,MAC7D,kBAAkB,KAAK,MAAM,YAAY,GAAK,IAAI;AAAA,MAClD;AAAA,MACA,eAAe,OAAO,MAAM,GAAG;AAAA;AAAA,IACjC,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,eAAe,OAAO,MAAM,QAAQ;AAC1C,UAAM,OAAO,MAAM,cAAc;AACjC,QAAI,KAAK,IAAI;AAAA,EACf,CAAC;AAED,MAAI,KAAK,eAAe,CAAC,KAAK,QAAQ;AACpC,UAAM,aAAa,GAAG,WAAW,KAAK,QAAQ,IAAI,GAAG,MAAM,CAAC;AAC5D,UAAM,YAAY,GAAG,WAAW,qBAAqB,KACnC,GAAG,WAAW,KAAK,QAAQ,IAAI,GAAG,kBAAkB,CAAC;AACvE,UAAM,UAAU,IAAI,MAAM,YAAY;AAEtC,QAAI;AACJ,QAAI,cAA6B;AAEjC,QAAI,YAAY;AAEd,gBAAU;AACV,UAAI,SAAS;AAEX,sBAAc;AAAA,MAChB;AAAA,IACF,WAAW,WAAW;AAEpB,gBAAU;AACV,UAAI,SAAS;AACX,sBAAc;AAAA,MAChB;AAAA,IACF,OAAO;AAEL,gBAAU;AAAA,IACZ;AAEA,WAAO,KAAK,WAAW,sBAAsB,OAAO,WAAW,UAAU,eAAe,SAAS,aAAa,OAAO,GAAG;AAExH,SAAK,SAAS,EAAE,SAAS,KAAQ,GAAG,CAAC,OAAO,QAAQ,YAAY;AAC9D,UAAI,OAAO;AACT,eAAO,MAAM,WAAW,kBAAkB,MAAM,OAAO,EAAE;AACzD,YAAI,CAAC,IAAI,YAAa,KAAI,KAAK,EAAE,IAAI,OAAO,OAAO,MAAM,QAAQ,CAAC;AAClE;AAAA,MACF;AAEA,aAAO,KAAK,WAAW,oCAAoC,MAAM,EAAE;AACnE,UAAI,CAAC,IAAI,aAAa;AACpB,YAAI,KAAK,EAAE,IAAI,MAAM,SAAS,oBAAoB,YAAY,SAAS,QAAQ,OAAO,MAAM,IAAI,EAAE,CAAC;AAAA,MACrG;AAEA,UAAI,SAAS;AACX,eAAO,KAAK,WAAW,oCAAoC;AAC3D,cAAM,MAAM,QAAQ,IAAI;AAExB,YAAI,gBAAgB,aAAa;AAE/B,gBAAM,aAAa;AACnB,aAAG,cAAc,YAAY;AAAA,YAC3B;AAAA,YACA;AAAA,YACA,OAAO,GAAG;AAAA,YACV;AAAA,UACF,EAAE,KAAK,IAAI,GAAG,EAAE,MAAM,IAAM,CAAC;AAC7B,gBAAM,QAAQ,CAAC,UAAU,GAAG,EAAE,UAAU,MAAM,OAAO,SAAS,CAAC,EAAE,MAAM;AAAA,QACzE,OAAO;AAEL,gBAAM,aAAa;AACnB,aAAG,cAAc,YAAY;AAAA,YAC3B;AAAA,YACA;AAAA,YACA,OAAO,GAAG;AAAA,YACV;AAAA,UACF,EAAE,KAAK,IAAI,GAAG,EAAE,MAAM,IAAM,CAAC;AAC7B,gBAAM,QAAQ,CAAC,UAAU,GAAG,EAAE,UAAU,MAAM,OAAO,SAAS,CAAC,EAAE,MAAM;AAAA,QACzE;AAEA,mBAAW,MAAM;AACf,iBAAO,KAAK,WAAW,wBAAwB;AAC/C,kBAAQ,KAAK,CAAC;AAAA,QAChB,GAAG,GAAI;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,eAAe,CAAC,MAAM,QAAQ;AACpC,UAAM,MAAM,WAAW;AAEvB,QAAI,KAAK;AAAA,MACP,OAAO,IAAI,MAAM;AAAA,MACjB,UAAU,IAAI,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MAC5C,OAAO;AAAA,QACL,SAAS,QAAQ,IAAI,OAAO,OAAO;AAAA,QACnC,YAAY,IAAI,OAAO,cAAc;AAAA,QACrC,UAAU,IAAI,OAAO,YAAY;AAAA,QACjC,WAAW,IAAI,OAAO,aAAa;AAAA,QACnC,QAAQ,IAAI,OAAO,UAAU;AAAA,QAC7B,UAAU,IAAI,OAAO,YAAY;AAAA,QACjC,QAAQ,IAAI,OAAO,UAAU;AAAA,QAC7B,WAAW,IAAI,OAAO,aAAa;AAAA,QACnC,OAAO,IAAI,OAAO,SAAS;AAAA,MAC7B;AAAA,MACA,OAAO,EAAE,GAAG,IAAI,OAAO,cAAc,QAAW,wBAAwB,QAAQ,IAAI,MAAM,YAAY,EAAE;AAAA,MACxG,UAAU,IAAI;AAAA,MACd,UAAU;AAAA,QACR,aAAa,IAAI,SAAS;AAAA,QAC1B,QAAQ,IAAI,SAAS;AAAA,QACrB,aAAa,IAAI,SAAS,eAAe,CAAC;AAAA,QAC1C,kBAAkB,IAAI,SAAS,oBAAoB,CAAC;AAAA,MACtD;AAAA,MACA,SAAS;AAAA,QACP,MAAM,IAAI,QAAQ;AAAA,QAClB,MAAM,IAAI,QAAQ;AAAA,QAClB,MAAM,EAAE,MAAM,IAAI,QAAQ,KAAK,KAAK;AAAA,MACtC;AAAA,MACA,SAAS,IAAI;AAAA,MACb,WAAW;AAAA,QACT,WAAW,EAAE,YAAY,QAAQ,IAAI,UAAU,WAAW,MAAM,EAAE;AAAA,QAClE,QAAQ,EAAE,YAAY,QAAQ,IAAI,UAAU,QAAQ,MAAM,EAAE;AAAA,QAC5D,QAAQ,EAAE,YAAY,QAAQ,IAAI,UAAU,QAAQ,MAAM,EAAE;AAAA,QAC5D,QAAQ,EAAE,SAAS,IAAI,UAAU,QAAQ,WAAW,yBAAyB;AAAA,QAC7E,MAAM,EAAE,YAAY,QAAQ,IAAI,UAAU,MAAM,MAAM,EAAE;AAAA,QACxD,SAAS,EAAE,YAAY,QAAQ,IAAI,UAAU,SAAS,MAAM,EAAE;AAAA,QAC9D,WAAW,EAAE,YAAY,QAAQ,IAAI,UAAU,WAAW,MAAM,EAAE;AAAA,QAClE,KAAK,EAAE,YAAY,QAAQ,IAAI,UAAU,KAAK,MAAM,EAAE;AAAA,QACtD,UAAU,EAAE,YAAY,QAAQ,IAAI,UAAU,UAAU,MAAM,EAAE;AAAA,QAChE,UAAU,EAAE,YAAY,QAAQ,IAAI,UAAU,UAAU,MAAM,EAAE;AAAA,QAChE,YAAY,EAAE,YAAY,QAAQ,IAAI,UAAU,YAAY,MAAM,EAAE;AAAA,MACtE;AAAA,MACA,OAAO;AAAA,QACL,QAAQ;AAAA,UACN,aAAa,QAAQ,IAAI,OAAO,QAAQ,QAAQ;AAAA,UAChD,iBAAiB,QAAQ,IAAI,OAAO,QAAQ,YAAY;AAAA,QAC1D;AAAA,MACF;AAAA,MACA,UAAU,OAAO;AAAA,QACf,OAAO,QAAQ,IAAI,QAAQ,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM;AAC3C,gBAAM,KAAK;AACX,iBAAO,CAAC,GAAG,EAAE,SAAS,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,YAAY,UAAU,CAAC;AAAA,QACjF,CAAC;AAAA,MACH;AAAA,MACA,SAAS,MAAM;AACb,cAAM,KAAM,IAAgC;AAC5C,YAAI,CAAC,GAAI,QAAO,EAAE,SAAS,OAAO,WAAW,OAAO,OAAO,EAAE,SAAS,OAAO,KAAK,wBAAwB,GAAG,KAAK,EAAE,SAAS,OAAO,SAAS,mBAAmB,WAAW,wBAAwB,GAAG,WAAW,EAAE,SAAS,OAAO,YAAY,aAAa,YAAY,GAAG,EAAE;AAC7Q,eAAO;AAAA,UACL,SAAS,QAAQ,GAAG,OAAO;AAAA,UAC3B,WAAW,QAAQ,GAAG,UAAU,QAAQ,IAAI,cAAc;AAAA,UAC1D,OAAO,GAAG,SAAS,EAAE,SAAS,OAAO,KAAK,wBAAwB;AAAA,UAClE,KAAK,GAAG,OAAO,EAAE,SAAS,OAAO,SAAS,mBAAmB,WAAW,wBAAwB;AAAA,UAChG,WAAW,GAAG,aAAa,EAAE,SAAS,OAAO,YAAY,aAAa,YAAY,GAAG;AAAA,QACvF;AAAA,MACF,GAAG;AAAA,MACH,MAAM;AAAA,QACJ,SAAS,QAAQ,IAAI,MAAM,OAAO;AAAA,QAClC,MAAM,QAAQ,IAAI,MAAM,IAAI;AAAA,QAC5B,WAAW,QAAQ,IAAI,MAAM,SAAS;AAAA,QACtC,UAAU,IAAI,MAAM,YAAY;AAAA,QAChC,aAAa,QAAQ,IAAI,MAAM,WAAW;AAAA,MAC5C;AAAA,MACA,UAAU;AAAA,QACR,SAAS,QAAQ,IAAI,UAAU,OAAO;AAAA,QACtC,kBAAkB,QAAQ,IAAI,UAAU,gBAAgB;AAAA,QACxD,mBAAmB,OAAO,IAAI,UAAU,iBAAiB,KAAK;AAAA,QAC9D,eAAe,QAAQ,IAAI,UAAU,aAAa;AAAA,QAClD,gBAAgB,OAAO,IAAI,UAAU,cAAc,KAAK;AAAA,MAC1D;AAAA,MACA,aAAa;AAAA,QACX,SAAS,QAAS,IAA4B,aAAa,OAAO;AAAA,QAClE,qBAAsB,IAA4B,aAAa,uBAAuB;AAAA,QACtF,qBAAsB,IAA4B,aAAa,uBAAuB;AAAA,QACtF,mBAAoB,IAA4B,aAAa,qBAAqB;AAAA,MACpF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,MAAI,KAAK,eAAe,OAAO,KAAK,QAAQ;AAC1C,QAAI;AACF,YAAM,OAAO,IAAI;AACjB,YAAM,MAAM,WAAW;AAEvB,YAAM,QAAQ,gBAAgB,GAAG;AAGjC,YAAM,gBAA0B,CAAC;AAEjC,UAAI,KAAK,OAAO;AAKd,cAAM,gBAAgB,gBAAgB,KAAK,KAAK;AAChD,YAAI,eAAe;AACjB,cAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,UAAU,aAAa,GAAG,CAAC;AACzD;AAAA,QACF;AAEA,cAAM,WAAW,KAAK;AACtB,cAAM,iBAAiB,SAAS,MAAM,GAAG,EAAE,CAAC;AAC5C,YAAI,kBAAkB,mBAAmB,UAAU;AACjD,gBAAM,EAAE,YAAY,IAAI,MAAM,OAAO,wBAAwB;AAC7D,cAAI,CAAC,YAAY,cAAc,GAAG;AAChC,gBAAI,OAAO,GAAG,EAAE,KAAK;AAAA,cACnB,OAAO,qBAAqB,cAAc;AAAA,YAC5C,CAAC;AACD;AAAA,UACF;AAAA,QACF;AACA,cAAM,MAAM,QAAQ;AACpB,sBAAc,KAAK,aAAa;AAAA,MAClC;AACA,UAAI,KAAK,cAAc;AAAE,cAAM,SAAS,OAAO,KAAK;AAAwD,sBAAc,KAAK,eAAe;AAAA,MAAG;AACjJ,UAAI,KAAK,aAAa;AAAE,cAAM,SAAS,cAAc,KAAK;AAA2C,sBAAc,KAAK,sBAAsB;AAAA,MAAG;AACjJ,UAAI,KAAK,UAAU;AAAE,cAAM,QAAQ,QAAQ,KAAK;AAAkD,sBAAc,KAAK,eAAe;AAAA,MAAG;AAEvI,UAAI,KAAK,iBAAiB,QAAW;AAAE,cAAM,UAAU,UAAU,SAAS,KAAK;AAAwB,sBAAc,KAAK,4BAA4B;AAAA,MAAG;AACzJ,UAAI,KAAK,cAAc,QAAW;AAAE,cAAM,UAAU,OAAO,SAAS,KAAK;AAAqB,sBAAc,KAAK,yBAAyB;AAAA,MAAG;AAC7I,UAAI,KAAK,cAAc,QAAW;AAAE,cAAM,UAAU,OAAO,SAAS,KAAK;AAAqB,sBAAc,KAAK,yBAAyB;AAAA,MAAG;AAC7I,UAAI,KAAK,cAAc,QAAW;AAAE,cAAM,UAAU,OAAO,UAAU,KAAK;AAAqB,sBAAc,KAAK,0BAA0B;AAAA,MAAG;AAC/I,UAAI,KAAK,YAAY,QAAW;AAAE,cAAM,UAAU,KAAK,SAAS,KAAK;AAAmB,sBAAc,KAAK,uBAAuB;AAAA,MAAG;AACrI,UAAI,KAAK,eAAe,QAAW;AAAE,cAAM,UAAU,QAAQ,SAAS,KAAK;AAAsB,sBAAc,KAAK,0BAA0B;AAAA,MAAG;AACjJ,UAAI,KAAK,iBAAiB,QAAW;AAAE,cAAM,UAAU,UAAU,SAAS,KAAK;AAAwB,sBAAc,KAAK,4BAA4B;AAAA,MAAG;AACzJ,UAAI,KAAK,WAAW,QAAW;AAAE,cAAM,UAAU,IAAI,SAAS,KAAK;AAAkB,sBAAc,KAAK,sBAAsB;AAAA,MAAG;AACjI,UAAI,KAAK,gBAAgB,QAAW;AAAE,cAAM,UAAU,SAAS,SAAS,KAAK;AAAuB,sBAAc,KAAK,2BAA2B;AAAA,MAAG;AACrJ,UAAI,KAAK,gBAAgB,QAAW;AAAE,cAAM,UAAU,SAAS,SAAS,KAAK;AAAuB,sBAAc,KAAK,2BAA2B;AAAA,MAAG;AACrJ,UAAI,KAAK,kBAAkB,QAAW;AAAE,cAAM,UAAU,WAAW,SAAS,KAAK;AAAyB,sBAAc,KAAK,6BAA6B;AAAA,MAAG;AAE7J,UAAI,KAAK,wBAAwB,QAAW;AAC1C,YAAI,CAAC,MAAM,MAAO,CAAC,MAAkC,QAAQ,EAAE,QAAQ,CAAC,EAAE;AAC1E,cAAM,MAAM,OAAO,WAAW,KAAK;AACnC,sBAAc,KAAK,uBAAuB;AAAA,MAC5C;AACA,UAAI,KAAK,4BAA4B,QAAW;AAC9C,YAAI,CAAC,MAAM,MAAO,CAAC,MAAkC,QAAQ,EAAE,QAAQ,CAAC,EAAE;AAC1E,cAAM,MAAM,OAAO,eAAe,KAAK;AACvC,sBAAc,KAAK,2BAA2B;AAAA,MAChD;AAEA,UAAI,KAAK,cAAc,QAAW;AAAE,cAAM,MAAM,YAAY,OAAO,KAAK,SAAS;AAAG,sBAAc,KAAK,iBAAiB;AAAA,MAAG;AAC3H,UAAI,KAAK,gBAAgB,QAAW;AAAE,cAAM,MAAM,cAAc,OAAO,KAAK,WAAW;AAAG,sBAAc,KAAK,mBAAmB;AAAA,MAAG;AACnI,UAAI,KAAK,iBAAiB,QAAW;AAAE,cAAM,MAAM,eAAe,KAAK;AAAwB,sBAAc,KAAK,oBAAoB;AAAA,MAAG;AAEzI,UAAI,KAAK,kBAAkB,QAAW;AAAE,cAAM,SAAS,OAAO,UAAU,QAAQ,KAAK,aAAa;AAAG,sBAAc,KAAK,yBAAyB;AAAA,MAAG;AACpJ,UAAI,KAAK,eAAe,QAAW;AAAE,cAAM,SAAS,OAAO,OAAO,KAAK;AAAqC,sBAAc,KAAK,sBAAsB;AAAA,MAAG;AACxJ,UAAI,KAAK,gBAAgB,QAAW;AAAE,cAAM,SAAS,cAAc,KAAK;AAAyB,sBAAc,KAAK,sBAAsB;AAAA,MAAG;AAC7I,UAAI,KAAK,qBAAqB,QAAW;AAAE,cAAM,SAAS,mBAAmB,KAAK;AAA8B,sBAAc,KAAK,2BAA2B;AAAA,MAAG;AAEjK,UAAI,KAAK,gBAAgB,QAAW;AAAE,cAAM,QAAQ,OAAO,OAAO,KAAK,WAAW;AAAG,sBAAc,KAAK,cAAc;AAAA,MAAG;AACzH,UAAI,KAAK,oBAAoB,QAAW;AAAE,cAAM,QAAQ,KAAK,OAAO,KAAK;AAAkD,sBAAc,KAAK,mBAAmB;AAAA,MAAG;AACpK,UAAI,KAAK,oBAAoB,QAAW;AAAE,cAAM,QAAQ,KAAK,WAAW,KAAK;AAA2B,sBAAc,KAAK,uBAAuB;AAAA,MAAG;AACrJ,UAAI,KAAK,iBAAiB,QAAW;AAAE,cAAM,QAAQ,KAAK,QAAQ,KAAK;AAAwB,sBAAc,KAAK,oBAAoB;AAAA,MAAG;AAEzI,UAAI,KAAK,UAAU,UAAa,OAAO,KAAK,UAAU,UAAU;AAC9D,cAAM,IAAI,KAAK;AACf,YAAI,EAAE,YAAY,OAAW,OAAM,MAAM,UAAU,QAAQ,EAAE,OAAO;AACpE,YAAI,EAAE,eAAe,OAAW,OAAM,MAAM,aAAa,OAAO,EAAE,UAAU;AAC5E,YAAI,EAAE,kBAAkB,OAAW,OAAM,MAAM,gBAAgB,OAAO,EAAE,aAAa;AACrF,YAAI,EAAE,qBAAqB,OAAW,OAAM,MAAM,mBAAmB,OAAO,EAAE,gBAAgB;AAC9F,YAAI,EAAE,aAAa,OAAW,OAAM,MAAM,WAAW,OAAO,EAAE,QAAQ;AACtE,YAAI,EAAE,aAAa,OAAW,OAAM,MAAM,WAAW,OAAO,EAAE,QAAQ;AACtE,YAAI,EAAE,cAAc,OAAW,OAAM,MAAM,YAAY,OAAO,EAAE,SAAS;AACzE,YAAI,EAAE,WAAW,OAAW,OAAM,MAAM,SAAS,OAAO,EAAE,MAAM;AAChE,YAAI,EAAE,WAAW,OAAW,OAAM,MAAM,SAAS,OAAO,EAAE,MAAM;AAChE,YAAI,EAAE,cAAc,OAAW,OAAM,MAAM,YAAY,OAAO,EAAE,SAAS;AACzE,YAAI,EAAE,UAAU,OAAW,CAAC,MAAM,MAAkC,QAAQ,OAAO,EAAE,KAAK,KAAK;AAC/F,sBAAc,KAAK,OAAO;AAAA,MAC5B;AAEA,UAAI,KAAK,qBAAqB,QAAW;AAAE,cAAM,cAAc,MAAM,KAAK;AAA4B,sBAAc,KAAK,mBAAmB;AAAA,MAAG;AAC/I,UAAI,KAAK,uBAAuB,QAAW;AAAE,cAAM,cAAc,QAAQ,KAAK;AAA8B,sBAAc,KAAK,qBAAqB;AAAA,MAAG;AAEvJ,UAAI,KAAK,aAAa,UAAa,OAAO,KAAK,aAAa,UAAU;AACpE,mBAAW,CAAC,IAAI,GAAG,KAAK,OAAO,QAAQ,KAAK,QAAmC,GAAG;AAChF,cAAI,MAAM,SAAS,EAAiC,GAAG;AACrD,mBAAO,OAAO,MAAM,SAAS,EAAiC,GAAG,GAAG;AACpE,0BAAc,KAAK,YAAY,EAAE,EAAE;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,UAAa,OAAO,KAAK,WAAW,UAAU;AAChE,cAAM,KAAK,KAAK;AAChB,cAAM,QAAU,MAAkC,UAAU,CAAC;AAC7D,YAAI,GAAG,YAAY,OAAW,OAAM,UAAU,QAAQ,GAAG,OAAO;AAChE,YAAI,GAAG,WAAW,OAAW,OAAM,SAAS,OAAO,GAAG,MAAM;AAC5D,YAAI,GAAG,UAAU,UAAa,OAAO,GAAG,UAAU,UAAU;AAC1D,gBAAM,QAAS,MAAM,SAAS,CAAC;AAC/B,gBAAM,MAAM,GAAG;AACf,cAAI,IAAI,YAAY,OAAW,OAAM,UAAU,QAAQ,IAAI,OAAO;AAClE,cAAI,IAAI,QAAQ,OAAW,OAAM,MAAM,OAAO,IAAI,GAAG;AACrD,gBAAM,QAAQ;AAAA,QAChB;AACA,YAAI,GAAG,QAAQ,UAAa,OAAO,GAAG,QAAQ,UAAU;AACtD,gBAAM,MAAO,MAAM,OAAO,CAAC;AAC3B,gBAAM,MAAM,GAAG;AACf,cAAI,IAAI,YAAY,OAAW,KAAI,UAAU,QAAQ,IAAI,OAAO;AAChE,cAAI,IAAI,YAAY,OAAW,KAAI,UAAU,OAAO,IAAI,OAAO;AAC/D,cAAI,IAAI,cAAc,OAAW,KAAI,YAAY,OAAO,IAAI,SAAS;AACrE,gBAAM,MAAM;AAAA,QACd;AACA,YAAI,GAAG,cAAc,UAAa,OAAO,GAAG,cAAc,UAAU;AAClE,gBAAM,KAAM,MAAM,aAAa,CAAC;AAChC,gBAAM,MAAM,GAAG;AACf,cAAI,IAAI,YAAY,OAAW,IAAG,UAAU,QAAQ,IAAI,OAAO;AAC/D,cAAI,IAAI,eAAe,OAAW,IAAG,aAAa,OAAO,IAAI,UAAU;AACvE,cAAI,IAAI,eAAe,OAAW,IAAG,aAAa,OAAO,IAAI,UAAU;AACvE,gBAAM,YAAY;AAAA,QACpB;AACA,QAAC,MAAkC,SAAS;AAC5C,sBAAc,KAAK,QAAQ;AAAA,MAC7B;AAEA,UAAI,KAAK,aAAa,UAAa,OAAO,KAAK,aAAa,UAAU;AACpE,cAAM,MAAM,KAAK;AACjB,YAAI,CAAC,MAAM,SAAU,CAAC,MAAkC,WAAW,CAAC;AACpE,YAAI,IAAI,YAAY,OAAW,OAAM,SAAS,UAAU,QAAQ,IAAI,OAAO;AAC3E,YAAI,IAAI,qBAAqB,OAAW,OAAM,SAAS,mBAAmB,QAAQ,IAAI,gBAAgB;AACtG,YAAI,IAAI,sBAAsB,OAAW,OAAM,SAAS,oBAAoB,OAAO,IAAI,iBAAiB;AACxG,YAAI,IAAI,kBAAkB,OAAW,OAAM,SAAS,gBAAgB,QAAQ,IAAI,aAAa;AAC7F,YAAI,IAAI,mBAAmB,OAAW,OAAM,SAAS,iBAAiB,OAAO,IAAI,cAAc;AAC/F,sBAAc,KAAK,UAAU;AAAA,MAC/B;AAGA,YAAM,mBAAmB,CAAC,SAAiB,KAAa,WAAoC;AAC1F,cAAM,MAAM,KAAK,OAAO;AACxB,YAAI,OAAO,OAAO,KAAK;AACrB,iBAAO,GAAG,IAAI,QAAQ,IAAI,GAAG,CAAC;AAC9B,wBAAc,KAAK,GAAG,OAAO,IAAI,GAAG,EAAE;AAAA,QACxC;AAAA,MACF;AACA,UAAI,KAAK,aAAa,UAAa,OAAO,KAAK,aAAa,UAAU;AACpE,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,SAAU,CAAC,MAAkC,WAAW,CAAC;AACpE,cAAM,KAAK,MAAM;AACjB,YAAI,EAAE,SAAS,OAAW,IAAG,OAAO,EAAE;AACtC,YAAI,EAAE,qBAAqB,OAAW,IAAG,mBAAmB,QAAQ,EAAE,gBAAgB;AACtF,YAAI,EAAE,wBAAwB,OAAW,IAAG,sBAAsB,QAAQ,EAAE,mBAAmB;AAC/F,sBAAc,KAAK,UAAU;AAAA,MAC/B;AACA,UAAI,KAAK,YAAY,UAAa,OAAO,KAAK,YAAY,UAAU;AAClE,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,QAAS,CAAC,MAAkC,UAAU,CAAC;AAClE,YAAI,EAAE,YAAY,OAAW,OAAM,QAAQ,UAAU,QAAQ,EAAE,OAAO;AACtE,YAAI,EAAE,WAAW,OAAW,OAAM,QAAQ,SAAS,QAAQ,EAAE,MAAM;AACnE,sBAAc,KAAK,SAAS;AAAA,MAC9B;AACA,UAAI,KAAK,gBAAgB,UAAa,OAAO,KAAK,gBAAgB,UAAU;AAC1E,cAAM,KAAK,KAAK;AAChB,YAAI,CAAC,MAAM,YAAa,CAAC,MAAkC,cAAc,CAAC;AAC1E,YAAI,GAAG,YAAY,OAAW,OAAM,YAAY,UAAU,QAAQ,GAAG,OAAO;AAC5E,sBAAc,KAAK,aAAa;AAAA,MAClC;AACA,UAAI,KAAK,SAAS,UAAa,OAAO,KAAK,SAAS,UAAU;AAC5D,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,KAAM,CAAC,MAAkC,OAAO,CAAC;AAC5D,YAAI,EAAE,YAAY,OAAW,OAAM,KAAK,UAAU,QAAQ,EAAE,OAAO;AACnE,sBAAc,KAAK,MAAM;AAAA,MAC3B;AACA,UAAI,KAAK,cAAc,UAAa,OAAO,KAAK,cAAc,UAAU;AACtE,cAAM,KAAK,KAAK;AAChB,YAAI,CAAC,MAAM,UAAW,CAAC,MAAkC,YAAY,CAAC;AACtE,YAAI,GAAG,YAAY,OAAW,OAAM,UAAU,UAAU,QAAQ,GAAG,OAAO;AAC1E,YAAI,GAAG,UAAU,UAAa,OAAO,GAAG,UAAU,UAAU;AAC1D,gBAAM,MAAM,GAAG;AACf,gBAAM,MAAO,MAAM;AACnB,cAAI,CAAC,IAAI,MAAO,KAAI,QAAQ,CAAC;AAC7B,cAAI,IAAI,iBAAiB,OAAW,CAAC,IAAI,MAAkC,eAAe,QAAQ,IAAI,YAAY;AAAA,QACpH;AACA,sBAAc,KAAK,WAAW;AAAA,MAChC;AACA,UAAI,KAAK,UAAU,UAAa,OAAO,KAAK,UAAU,UAAU;AAC9D,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,MAAO,CAAC,MAAkC,QAAQ,CAAC;AAC9D,YAAI,EAAE,YAAY,OAAW,OAAM,MAAM,UAAU,QAAQ,EAAE,OAAO;AACpE,sBAAc,KAAK,OAAO;AAAA,MAC5B;AACA,UAAI,KAAK,QAAQ,UAAa,OAAO,KAAK,QAAQ,UAAU;AAC1D,cAAM,MAAM,KAAK;AACjB,YAAI,CAAC,MAAM,IAAK,CAAC,MAAkC,MAAM,EAAE,QAAQ,CAAC,EAAE;AACtE,YAAI,IAAI,WAAW,UAAa,OAAO,IAAI,WAAW,UAAU;AAC9D,gBAAM,MAAM,IAAI;AAChB,gBAAM,OAAQ,MAAM;AACpB,cAAI,CAAC,KAAK,OAAQ,MAAK,SAAS,CAAC;AACjC,cAAI,IAAI,YAAY,OAAW,CAAC,KAAK,OAAmC,UAAU,QAAQ,IAAI,OAAO;AAAA,QACvG;AACA,sBAAc,KAAK,KAAK;AAAA,MAC1B;AACA,UAAI,KAAK,aAAa,UAAa,OAAO,KAAK,aAAa,UAAU;AACpE,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,SAAU,CAAC,MAAkC,WAAW,CAAC;AACpE,YAAI,EAAE,YAAY,OAAW,OAAM,SAAS,UAAU,QAAQ,EAAE,OAAO;AACvE,sBAAc,KAAK,UAAU;AAAA,MAC/B;AACA,UAAI,KAAK,UAAU,UAAa,OAAO,KAAK,UAAU,UAAU;AAC9D,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,MAAO,CAAC,MAAkC,QAAQ,CAAC;AAC9D,YAAI,EAAE,YAAY,OAAW,OAAM,MAAM,UAAU,QAAQ,EAAE,OAAO;AACpE,sBAAc,KAAK,OAAO;AAAA,MAC5B;AACA,UAAI,KAAK,WAAW,UAAa,OAAO,KAAK,WAAW,UAAU;AAChE,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,OAAQ,CAAC,MAAkC,SAAS,CAAC;AAChE,YAAI,EAAE,YAAY,OAAW,OAAM,OAAO,UAAU,QAAQ,EAAE,OAAO;AACrE,sBAAc,KAAK,QAAQ;AAAA,MAC7B;AACA,UAAI,KAAK,UAAU,UAAa,OAAO,KAAK,UAAU,UAAU;AAC9D,cAAM,IAAI,KAAK;AACf,cAAM,OAAQ,MAAM;AACpB,YAAI,CAAC,KAAK,MAAO,MAAK,QAAQ,CAAC;AAC/B,YAAI,EAAE,YAAY,OAAW,CAAC,KAAK,MAAkC,UAAU,QAAQ,EAAE,OAAO;AAChG,sBAAc,KAAK,gBAAgB;AAAA,MACrC;AACA,UAAI,KAAK,cAAc,UAAa,OAAO,KAAK,cAAc,UAAU;AACtE,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,UAAW,CAAC,MAAkC,YAAY,CAAC;AACtE,YAAI,EAAE,YAAY,OAAW,OAAM,UAAU,UAAU,QAAQ,EAAE,OAAO;AACxE,sBAAc,KAAK,WAAW;AAAA,MAChC;AACA,UAAI,KAAK,iBAAiB,UAAa,OAAO,KAAK,iBAAiB,UAAU;AAC5E,cAAM,IAAI,KAAK;AACf,YAAI,CAAC,MAAM,aAAc,CAAC,MAAkC,eAAe,CAAC;AAC5E,YAAI,EAAE,eAAe,OAAW,OAAM,aAAa,aAAa,QAAQ,EAAE,UAAU;AACpF,sBAAc,KAAK,cAAc;AAAA,MACnC;AACA,UAAI,KAAK,gBAAgB,UAAa,OAAO,KAAK,gBAAgB,UAAU;AAC1E,cAAM,KAAK,KAAK;AAChB,YAAI,CAAC,MAAM,YAAa,CAAC,MAAkC,cAAc,CAAC;AAC1E,YAAI,GAAG,cAAc,OAAW,OAAM,YAAY,YAAY,QAAQ,GAAG,SAAS;AAClF,sBAAc,KAAK,aAAa;AAAA,MAClC;AACA,UAAI,KAAK,WAAW,UAAa,OAAO,KAAK,WAAW,UAAU;AAChE,cAAM,MAAM,KAAK;AACjB,YAAI,CAAC,MAAM,OAAQ,CAAC,MAAkC,SAAS,CAAC;AAChE,YAAI,IAAI,wBAAwB,OAAW,OAAM,OAAO,sBAAsB,QAAQ,IAAI,mBAAmB;AAC7G,sBAAc,KAAK,QAAQ;AAAA,MAC7B;AAEA,UAAI,cAAc,WAAW,GAAG;AAC9B,cAAM,cAAc;AAAA,UAAC;AAAA,UAAS;AAAA,UAAgB;AAAA,UAAe;AAAA,UAAY;AAAA,UAAgB;AAAA,UACvF;AAAA,UAAa;AAAA,UAAa;AAAA,UAAW;AAAA,UAAc;AAAA,UAAgB;AAAA,UACnE;AAAA,UAAe;AAAA,UAAe;AAAA,UAAiB;AAAA,UAAa;AAAA,UAAe;AAAA,UAC3E;AAAA,UAAiB;AAAA,UAAc;AAAA,UAAe;AAAA,UAAoB;AAAA,UAAe;AAAA,UACjF;AAAA,UAAmB;AAAA,UAAgB;AAAA,UAAY;AAAA,UAAuB;AAAA,UACtE;AAAA,UAAoB;AAAA,UAAsB;AAAA,UAAS;AAAA,UAAU;AAAA,UAC7D;AAAA,UAAY;AAAA,UAAW;AAAA,UAAe;AAAA,UAAQ;AAAA,UAAa;AAAA,UAAS;AAAA,UACpE;AAAA,UAAY;AAAA,UAAS;AAAA,UAAU;AAAA,UAAS;AAAA,UAAa;AAAA,UAAgB;AAAA,UAAe;AAAA,QAAQ;AAC9F,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wCAAwC,YAAY,CAAC;AACnF;AAAA,MACF;AAEA,mBAAa,KAAK;AAGlB,YAAM,gBAAgB,cAAc;AAAA,QAAO,WACzC,0BAA0B,KAAK,aAAW;AACxC,cAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,mBAAO,MAAM,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC;AAAA,UAC9C;AACA,iBAAO,UAAU;AAAA,QACnB,CAAC;AAAA,MACH;AAEA,UAAI,KAAK,EAAE,IAAI,MAAM,iBAAiB,cAAc,SAAS,GAAG,cAAc,CAAC;AAAA,IACjF,SAAS,GAAG;AAEV,YAAM,oBAAqB,EAAY,SAAS,cAAe,EAAY,SAAS,SAAS,YAAY;AACzG,UAAI,OAAO,oBAAoB,MAAM,GAAG,EAAE,KAAK,EAAE,OAAQ,EAAY,QAAQ,CAAC;AAAA,IAChF;AAAA,EACF,CAAC;AAID,MAAI,IAAI,eAAe,OAAO,KAAK,QAAQ;AACzC,UAAM,MAAM,WAAW;AAGvB,UAAM,eAAe,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,YAAY;AACxE,UAAM,SAAS,MAAM,kBAAkB,YAAY;AAInD,UAAM,UAAoC,CAAC;AAC3C,UAAM,gBAAyC,CAAC;AAChD,eAAW,KAAK,QAAQ;AACtB,UAAI,CAAC,QAAQ,EAAE,QAAQ,EAAG,SAAQ,EAAE,QAAQ,IAAI,CAAC;AACjD,cAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;AAG7B,UAAI,EAAE,EAAE,YAAY,eAAgB,eAAc,EAAE,QAAQ,IAAI,EAAE;AAAA,IACpE;AACA,QAAI,KAAK;AAAA,MACP,GAAG;AAAA,MACH,SAAS,IAAI,MAAM;AAAA,MACnB,SAAS,gBAAgB;AAAA,MACzB,OAAO;AAAA,QACL;AAAA,QACA,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,yBAAyB,OAAO,MAAM,QAAQ;AACpD,QAAI;AACF,YAAM,EAAE,wBAAwB,IAAI,MAAM,OAAO,wBAAwB;AACzE,YAAM,WAAW,wBAAwB;AACzC,YAAM,SAAS,MAAM,eAAe;AACpC,YAAM,YAAY,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,OAAO,OAAO;AAAA,QACjE;AAAA,QACA;AAAA,QACA,gBAAgB,SAAS,IAAI,KAAK,EAAE,OAAO,WAAW,cAAc,EAAE;AAAA,MACxE,EAAE;AACF,UAAI,KAAK,EAAE,WAAW,OAAO,UAAU,OAAO,CAAC;AAAA,IACjD,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AACjE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IAClG;AAAA,EACF,CAAC;AAED,MAAI,KAAK,8BAA8B,OAAO,KAAK,QAAQ;AACzD,QAAI;AACF,YAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,wBAAwB;AACrE,0BAAoB,IAAI,OAAO,IAAI;AACnC,UAAI,KAAK,EAAE,OAAO,MAAM,UAAU,IAAI,OAAO,KAAK,CAAC;AAAA,IACrD,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AACjE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IAClG;AAAA,EACF,CAAC;AAED,MAAI,IAAI,wBAAwB,OAAO,MAAM,QAAQ;AACnD,UAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,UAAM,MAAM,WAAW;AACvB,QAAI,KAAK;AAAA,MACP;AAAA,MACA,SAAS,IAAI,MAAM;AAAA,MACnB,SAAS,gBAAgB;AAAA,IAC3B,CAAC;AAAA,EACH,CAAC;AAED,MAAI,IAAI,uBAAuB,CAAC,MAAM,QAAQ;AAC5C,UAAM,QAAQ,iBAAiB;AAC/B,QAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,CAAC;AAAA,EACpC,CAAC;AAOD,WAAS,gBAAgB,OAA+B;AACtD,QAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,KAAK;AACzE,aAAO;AAAA,IACT;AACA,QAAI,CAAC,uBAAuB,KAAK,KAAK,GAAG;AACvC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,qBAAqB,OAAO,KAAK,QAAQ;AAChD,QAAI;AACF,YAAM,EAAE,MAAM,IAAI,IAAI;AACtB,UAAI,CAAC,OAAO;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,CAAC;AAAG;AAAA,MAAQ;AAC5E,YAAM,WAAW,gBAAgB,KAAK;AACtC,UAAI,UAAU;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,SAAS,CAAC;AAAG;AAAA,MAAQ;AACnE,YAAM,MAAM,WAAW;AAEvB,YAAM,UAAU,IAAI,MAAM,gBAAgB,CAAC;AAC3C,YAAM,WAAW,QAAQ,KAAK,KAAK;AAGnC,YAAM,CAAC,cAAc,GAAG,UAAU,IAAI,SAAS,MAAM,GAAG;AACxD,YAAM,YAAY,WAAW,KAAK,GAAG,KAAK;AAQ1C,UAAI,gBAAgB,iBAAiB,UAAU;AAC7C,cAAM,EAAE,YAAY,IAAI,MAAM,OAAO,wBAAwB;AAC7D,YAAI,CAAC,YAAY,YAAY,GAAG;AAC9B,iBAAO,KAAK,WAAW,mCAAmC,YAAY,oBAAe;AACrF,cAAI,OAAO,GAAG,EAAE,KAAK;AAAA,YACnB,OAAO,qBAAqB,YAAY;AAAA,UAC1C,CAAC;AACD;AAAA,QACF;AAAA,MACF;AAGA,UAAI,iBAAiB,UAAU;AAC7B,cAAM,aAAa,IAAI,UAAU,QAAQ,WAAW;AAEpD,YAAI,UAAU,SAAS,QAAQ,GAAG;AAChC,iBAAO,KAAK,WAAW,qCAAqC,SAAS,wCAAmC;AAAA,QAC1G,OAAO;AAEL,cAAI;AACF,kBAAM,QAAQ,MAAM,MAAM,GAAG,UAAU,aAAa;AAAA,cAClD,QAAQ;AAAA,cACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,cAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAAA,cACxC,QAAQ,YAAY,QAAQ,GAAI;AAAA,YAClC,CAAC;AACD,gBAAI,CAAC,MAAM,IAAI;AACb,qBAAO,KAAK,WAAW,wBAAwB,SAAS,+BAA+B,MAAM,MAAM,GAAG;AACtG,kBAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,UAAU,SAAS,qDAAqD,SAAS,GAAG,CAAC;AACnH;AAAA,YACF;AACA,mBAAO,KAAK,WAAW,wCAAwC,SAAS,UAAU;AAAA,UACpF,SAAS,KAAK;AAEZ,mBAAO,MAAM,WAAW,uCAAuC,UAAU,KAAM,IAAc,OAAO,EAAE;AACtG,gBAAI,OAAO,GAAG,EAAE,KAAK;AAAA,cACnB,OAAO,wBAAwB,SAAS,qCAAgC,UAAU;AAAA,YACpF,CAAC;AACD;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,cAAc;AAGvB,eAAO,KAAK,WAAW,wCAAwC,aAAa,YAAY,CAAC,YAAY,SAAS,GAAG;AAAA,MACnH;AAGA,mBAAa,EAAE,OAAO,EAAE,GAAG,IAAI,OAAO,OAAO,SAAS,EAAE,CAAC;AAEzD,8BAAwB,IAAI,MAAM,KAAK;AACvC,aAAO,KAAK,WAAW,sBAAsB,QAAQ,GAAG,aAAa,QAAQ,YAAY,KAAK,MAAM,EAAE,EAAE;AACxG,UAAI,KAAK,EAAE,SAAS,MAAM,OAAO,UAAU,OAAO,aAAa,QAAQ,QAAQ,OAAU,CAAC;AAAA,IAC5F,SAAS,KAAK;AACZ,aAAO,MAAM,WAAW,wBAAyB,IAAc,OAAO,EAAE;AACxE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAMD,MAAI,KAAK,oBAAoB,OAAO,KAAK,QAAQ;AAC/C,QAAI;AACF,YAAM,OAAO,IAAI;AACjB,YAAM,UAAU,KAAK,QAAQ,CAAC,KAAK,KAAK,IAAK,KAAK,UAAU,CAAC;AAC7D,UAAI,QAAQ,WAAW,GAAG;AACxB,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,mDAAmD,CAAC;AAClF;AAAA,MACF;AAEA,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,wBAAwB;AAC5D,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,kCAAkC;AAE7E,YAAM,UAAU,CAAC;AACjB,iBAAW,WAAW,SAAS;AAC7B,YAAI;AACF,gBAAM,SAAS,MAAM,WAAW,OAAO;AACvC,4BAAkB,MAAM;AACxB,kBAAQ,KAAK,MAAM;AAAA,QACrB,SAAS,KAAK;AACZ,kBAAQ,KAAK,EAAE,OAAO,SAAS,OAAQ,IAAc,QAAQ,CAAC;AAAA,QAChE;AAAA,MACF;AACA,UAAI,KAAK,EAAE,QAAQ,QAAQ,QAAQ,QAAQ,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAED,MAAI,IAAI,oBAAoB,OAAO,MAAM,QAAQ;AAC/C,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,kCAAkC;AACxE,YAAM,WAAW,aAAa;AAC9B,UAAI,KAAK;AAAA,QACP,WAAW,SAAS;AAAA,QACpB,OAAO,OAAO,KAAK,SAAS,MAAM,EAAE;AAAA,QACpC,QAAQ,SAAS;AAAA,MACnB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,gBAAgB,CAAC,MAAM,QAAQ;AACrC,UAAM,UAAU,YAAY;AAC5B,QAAI,KAAK;AAAA,MACP,MAAM,QAAQ,QAAQ;AAAA,MACtB,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,cAAc,QAAQ,SAAS;AAAA,MAC/B,WAAW,QAAQ,MAAM;AAAA,IAC3B,CAAC;AAAA,EACH,CAAC;AAED,MAAI,KAAK,gBAAgB,CAAC,KAAK,QAAQ;AACrC,QAAI;AACF,YAAM,EAAE,MAAM,eAAe,IAAI,IAAI;AACrC,YAAM,UAAU,YAAY;AAC5B,UAAI,SAAS,OAAW,SAAQ,OAAO;AACvC,UAAI,mBAAmB,OAAW,SAAQ,iBAAiB;AAC3D,kBAAY,OAAO;AACnB,UAAI,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,IACvB,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,iBAAiB,CAAC,MAAM,QAAQ;AACtC,QAAI,KAAK,iBAAiB,CAAC;AAAA,EAC7B,CAAC;AAED,MAAI,IAAI,uBAAuB,CAAC,MAAM,QAAQ;AAC5C,QAAI,KAAK,iBAAiB,CAAC;AAAA,EAC7B,CAAC;AAGD,MAAI,IAAI,aAAa,CAAC,KAAK,QAAQ;AACjC,QAAI;AACF,YAAM,UAAU,eAAe;AAC/B,UAAI,CAAC,WAAW,CAAC,GAAG,WAAW,OAAO,GAAG;AACvC,YAAI,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;AACtB;AAAA,MACF;AACA,YAAM,YAAY,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,OAAiB,EAAE,IAAI;AAE9E,YAAM,QAAQ,GAAG,SAAS,OAAO;AACjC,YAAM,WAAW,KAAK,IAAI,MAAM,MAAM,GAAM;AAC5C,YAAM,KAAK,GAAG,SAAS,SAAS,GAAG;AACnC,YAAM,MAAM,OAAO,MAAM,QAAQ;AACjC,SAAG,SAAS,IAAI,KAAK,GAAG,UAAU,KAAK,IAAI,GAAG,MAAM,OAAO,QAAQ,CAAC;AACpE,SAAG,UAAU,EAAE;AACf,YAAM,UAAU,IAAI,SAAS,OAAO;AACpC,YAAM,MAAM,QAAQ,MAAM,IAAI,EAAE,OAAO,OAAO;AAE9C,YAAM,QAAQ,MAAM,OAAO,WAAW,IAAI,MAAM,CAAC,IAAI;AACrD,YAAM,OAAO,MAAM,MAAM,CAAC,KAAK,IAAI,GAAG,SAAS,CAAC;AAEhD,YAAM,YAAY,KAAK;AAAA,QAAI,UACzB,KACG,QAAQ,mCAAmC,kCAAkC,EAC7E,QAAQ,mCAAmC,kBAAkB,EAC7D,QAAQ,yCAAyC,oBAAoB,EACrE,QAAQ,wCAAwC,qBAAqB,EACrE,QAAQ,oCAAoC,mBAAmB;AAAA,MACpE;AACA,UAAI,KAAK,EAAE,OAAO,UAAU,CAAC;AAAA,IAC/B,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,MAAI,OAAO,aAAa,CAAC,MAAM,QAAQ;AACrC,QAAI;AACF,YAAM,YAAY,KAAK,QAAQ,GAAG,QAAQ;AAC1C,YAAM,QAAQ,CAAC,cAAc,kBAAkB,iBAAiB;AAChE,YAAM,UAAoB,CAAC;AAC3B,iBAAW,KAAK,OAAO;AACrB,cAAM,IAAI,KAAK,WAAW,CAAC;AAC3B,YAAI,GAAG,WAAW,CAAC,GAAG;AACpB,aAAG,WAAW,CAAC;AACf,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AACA,iBAAW;AACX,aAAO,KAAK,WAAW,oCAAoC,QAAQ,KAAK,IAAI,KAAK,MAAM,EAAE;AACzF,UAAI,KAAK,EAAE,SAAS,MAAM,SAAS,YAAY,QAAQ,KAAK,IAAI,KAAK,MAAM,yBAAyB,CAAC;AAAA,IACvG,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AAAG,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iEAAiE,CAAC;AAAA,IACtK;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,QAAQ,sBAAsB,CAAC;AAGvC,MAAI,IAAI,QAAQ,mBAAmB,CAAC;AACpC,MAAI,IAAI,QAAQ,kBAAkB,CAAC;AACnC,MAAI,IAAI,cAAc,kBAAkB,CAAC;AAGzC,MAAI,IAAI,QAAQ,mBAAmB,CAAC;AAGpC,MAAI,IAAI,QAAQ;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,IAAI,QAAQ;AAAE,aAAO;AAAA,IAAmB,GAAG,IAAI,MAAM,GAAW;AAAE,0BAAoB;AAAA,IAAG,EAAE;AAAA,IAC7F;AAAA,IACA;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,QAAQ,iBAAiB,SAAS,CAAC;AAG3C,MAAI,IAAI,QAAQ,qBAAqB,CAAC;AAGtC,MAAI,IAAI,uBAAuB,OAAO,MAAM,QAAQ;AAClD,QAAI;AACF,YAAM,EAAE,eAAe,eAAe,IAAI,MAAM,OAAO,qCAAqC;AAC5F,UAAI,KAAK,EAAE,WAAW,cAAc,GAAG,YAAY,eAAe,EAAE,CAAC;AAAA,IACvE,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,yBAA0B,EAAY,OAAO,EAAE;AACvE,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,6BAA6B,CAAC;AAAA,IAC9D;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,iBAAiB,OAAO,MAAM,QAAQ;AAC5C,QAAI;AACF,YAAM,EAAE,cAAc,eAAAF,eAAc,IAAI,MAAM,OAAO,oBAAoB;AACzE,YAAM,EAAE,OAAO,MAAM,IAAI,aAAa;AACtC,YAAM,QAAQA,eAAc;AAC5B,UAAI,KAAK,EAAE,YAAY,MAAM,OAAO,OAAO,MAAM,CAAC;AAAA,IACpD,SAAS,GAAG;AACV,aAAO,MAAM,WAAW,mBAAoB,EAAY,OAAO,EAAE;AACjE,UAAI,KAAK,EAAE,YAAY,OAAO,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;AAAA,IACjE;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,aAAa,CAAC,MAAM,QAAQ;AAClC,QAAI,KAAK;AAAA,MACP,SAAS;AAAA,MACT,MAAM,EAAE,OAAO,qBAAqB,SAAS,cAAc;AAAA,MAC3D,OAAO,CAAC;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAED,MAAI,IAAI,SAAS,CAAC,MAAM,QAAQ;AAC9B,QAAI,UAAU,gBAAgB,0BAA0B;AACxD,QAAI,KAAK,mKAAmK,aAAa,sBAAsB;AAAA,EACjN,CAAC;AAGD,MAAI,YAAY;AACd,QAAI,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;AAO/B,UACE,IAAI,KAAK,WAAW,OAAO,KAC3B,IAAI,KAAK,WAAW,aAAa,KACjC,IAAI,KAAK,WAAW,MAAM,KAC1B,IAAI,SAAS,SACb,IAAI,SAAS,cACb,IAAI,SAAS,aACb,IAAI,SAAS,UACb;AACA,eAAO,KAAK;AAAA,MACd;AACA,UAAI,UAAU,iBAAiB,qCAAqC;AACpE,UAAI,UAAU,UAAU,UAAU;AAClC,UAAI,UAAU,WAAW,GAAG;AAC5B,UAAI,KAAK,mBAAmB,GAAG,aAAa,aAAa,MAAM,CAAC;AAAA,IAClE,CAAC;AAAA,EACH;AAIA,QAAM,WAAW,KAAK,QAAQ,GAAG,UAAU,SAAS,WAAW;AAC/D,QAAM,UAAU,KAAK,QAAQ,GAAG,UAAU,SAAS,eAAe;AAClE,QAAM,WAAW,GAAG,WAAW,QAAQ,KAAK,GAAG,WAAW,OAAO;AAEjE,MAAI,UAAU;AACZ,UAAM,OAAO,GAAG,aAAa,QAAQ;AACrC,UAAM,MAAM,GAAG,aAAa,OAAO;AACnC,iBAAa,kBAAkB,EAAE,MAAM,IAAI,GAAG,GAAG;AACjD,WAAO,KAAK,WAAW,oCAAoC,QAAQ,GAAG;AAAA,EACxE,OAAO;AACL,iBAAa,aAAa,GAAG;AAAA,EAC/B;AAGA,QAAM,MAAM,IAAI,gBAAgB,EAAE,QAAQ,WAAW,CAAC;AAEtD,MAAI,GAAG,cAAc,OAAO,IAAI,QAAQ;AACvC,QAAI;AACH,YAAM,MAAM,WAAW;AACvB,YAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,IAAI,EAAE;AAGhE,UAAI,IAAI,aAAa,IAAI,MAAM,MAAM,UAAU,IAAI,KAAK,WAAW,IAAI,KAAK,QAAQ;AAClF,cAAM,aAAa,IAAI,aAAa,IAAI,QAAQ,KAAK;AACrD,cAAM,YAAY,IAAI,aAAa,IAAI,MAAM,KAAK;AAClD,cAAM,EAAE,gBAAgB,oBAAoB,IAAI,MAAM,OAAO,sBAAsB;AACnF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,qBAAqB;AAEhE,YAAI,CAAC,eAAe,WAAW,YAAY,IAAI,KAAK,MAAM,GAAG;AAC3D,iBAAO,KAAK,WAAW,8BAA8B,UAAU,QAAQ,IAAI,OAAO,aAAa,EAAE;AACjG,aAAG,MAAM,MAAM,kBAAkB;AACjC;AAAA,QACF;AAEA,cAAM,EAAE,yBAAyB,IAAI,MAAM,OAAO,sBAAsB;AAExE,4BAAoB,IAAI,YAAY,kBAAkB,GAAG,OAAO,KAAK,UAAU;AAE7E,gBAAM,UAAU,WAAW,EAAE;AAC7B,cAAI,CAAC,QAAQ,mBAAmB;AAC9B,kBAAM,EAAE,OAAO,+CAA+C,CAAC;AAC/D;AAAA,UACF;AAEA,cAAI,yBAAyB,KAAK,QAAQ,gBAAgB;AACxD,kBAAM,EAAE,OAAO,mDAA8C,CAAC;AAC9D;AAAA,UACF;AAEA,cAAI;AACF,kBAAM,SAAS,MAAM,eAAe,IAAI,QAAQ,SAAmB,QAAQ,IAAI,YAAY;AAAA,cACzF,OAAO,IAAI,QAAQ;AAAA,YACrB,CAAC;AACD,kBAAM,EAAE,GAAG,OAAO,CAAC;AAAA,UACrB,SAAS,KAAK;AACZ,kBAAM,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,UACzC;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAIA,YAAM,SAAS,IAAI,QAAQ;AAC3B,UAAI,QAAQ;AACV,cAAM,cAAe,IAAI,QAAoC;AAC7D,cAAM,kBAAkB,eAAe,CAAC,GAAG,IAAI,OAAK,IAAI,OAAO,IAAI,EAAE,QAAQ,uBAAuB,MAAM,CAAC,GAAG,CAAC;AAC/G,cAAM,UAAUH,iBAAgB,MAAM,KAAK,eAAe,KAAK,OAAK,EAAE,KAAK,MAAM,CAAC;AAClF,YAAI,CAAC,SAAS;AACZ,iBAAO,KAAK,WAAW,8BAA8B,MAAM,qBAAqB;AAChF,aAAG,MAAM,MAAM,oBAAoB;AACnC;AAAA,QACF;AAAA,MACF;AAGA,YAAM,OAAO,IAAI,QAAQ;AACzB,UAAI,QAAQ,KAAK,SAAS,QAAQ;AAChC,cAAM,QAAQ,IAAI,aAAa,IAAI,OAAO,KAAK;AAC/C,YAAI,CAAC,aAAa,OAAO,GAAG,GAAG;AAC7B,aAAG,MAAM,MAAM,cAAc;AAC7B;AAAA,QACF;AAAA,MACF;AAGA,YAAM,WAAW;AACjB,eAAS,cAAc,IAAI,aAAa,IAAI,QAAQ,KAAK;AACzD,gBAAU,IAAI,QAAQ;AACtB,aAAO,KAAK,WAAW,+BAA+B,UAAU,IAAI,gBAAgB,SAAS,WAAW,GAAG;AAE3G,SAAG,GAAG,WAAW,OAAO,SAAS,aAAa;AAC5C,YAAI;AAEF,cAAI,SAAU;AAGd,gBAAM,WAAW,OAAO,YAAY,WAAW,OAAO,WAAW,OAAO,IAAK,QAAmB;AAChG,cAAI,WAAW,sBAAsB;AACnC,mBAAO,KAAK,WAAW,iCAAiC,WAAW,OAAO,MAAM,QAAQ,CAAC,CAAC,qBAAgB;AAC1G,gBAAI,GAAG,eAAe,UAAU,MAAM;AACpC,iBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,SAAS,SAAS,+BAA+B,CAAC,CAAC;AAAA,YACpF;AACA;AAAA,UACF;AAEA,cAAI;AACJ,cAAI;AACF,mBAAO,KAAK,MAAM,QAAQ,SAAS,CAAC;AAAA,UACtC,SAAS,UAAU;AACjB,mBAAO,KAAK,WAAW,2BAA4B,SAAmB,OAAO,EAAE;AAC/E,gBAAI,GAAG,eAAe,UAAU,MAAM;AACpC,iBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,SAAS,SAAS,uBAAuB,CAAC,CAAC;AAAA,YAC5E;AACA;AAAA,UACF;AAGA,eAAK,KAAK,SAAS,UAAU,KAAK,SAAS,cAAc,KAAK,SAAS;AAErE,gBAAI,KAAK,WAAW,SAAS,gBAAgB;AAC3C,oBAAM,aAAa,KAAK,UAAU;AAElC,wBAAU;AAAA,gBACR,MAAM;AAAA,gBAAW,WAAW;AAAA,gBAAW,SAAS;AAAA,gBAChD,QAAQ;AAAA,gBAAY,SAAS,KAAK;AAAA,gBAClC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,cACpC,CAAC;AAED,kBAAI;AACF,sBAAM,WAAW,MAAM,aAAa,KAAK,SAAS,WAAW,YAAY;AAAA,kBACvE,iBAAiB;AAAA,oBACf,SAAS,CAAC,UAAkB;AAC1B,0BAAI,GAAG,eAAe,UAAU,MAAM;AACpC,2BAAG,KAAK,KAAK,UAAU,EAAE,MAAM,SAAS,MAAM,MAAM,CAAC,CAAC;AAAA,sBACxD;AAAA,oBACF;AAAA,oBACA,YAAY,CAAC,MAAc,SAAkC;AAC3D,0BAAI,GAAG,eAAe,UAAU,MAAM;AACpC,2BAAG,KAAK,KAAK,UAAU,EAAE,MAAM,aAAa,MAAM,KAAK,CAAC,CAAC;AAAA,sBAC3D;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF,CAAC;AAED,oBAAI,GAAG,eAAe,UAAU,MAAM;AACpC,qBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,QAAQ,SAAS,SAAS,SAAS,OAAO,SAAS,OAAO,YAAY,SAAS,YAAY,YAAY,SAAS,WAAW,CAAC,CAAC;AAAA,gBAC9J;AAEA,2BAAW,UAAU,WAAW;AAC9B,wBAAM,SAAS;AACf,sBAAI,WAAW,MAAM,OAAO,eAAe,UAAU,QAAQ,OAAO,gBAAgB,YAAY;AAC9F,2BAAO,KAAK,KAAK,UAAU;AAAA,sBACzB,MAAM;AAAA,sBAAW,WAAW;AAAA,sBAAY,SAAS;AAAA,sBACjD,QAAQ;AAAA,sBAAY,SAAS,SAAS;AAAA,sBACtC,OAAO,SAAS;AAAA,sBAAO,YAAY,SAAS;AAAA,sBAC5C,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,oBACpC,CAAC,CAAC;AAAA,kBACJ;AAAA,gBACF;AAAA,cACF,SAAS,KAAK;AACZ,oBAAI,GAAG,eAAe,UAAU,MAAM;AACpC,qBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,QAAQ,SAAS,UAAW,IAAc,OAAO,GAAG,CAAC,CAAC;AAAA,gBACvF;AAAA,cACF;AAAA,YACF,WAAW,gBAAgB;AACzB,6BAAe,uBAAuB,KAAK,UAAU,gBAAgB,KAAK,OAAO;AAAA,YACnF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,iBAAO,MAAM,WAAW,oBAAqB,MAAgB,OAAO,EAAE;AAAA,QACxE;AAAA,MACF,CAAC;AAED,SAAG,GAAG,SAAS,MAAM;AACnB,kBAAU,OAAO,EAAE;AACnB,eAAO,MAAM,WAAW,kCAAkC,UAAU,IAAI,SAAS;AAAA,MACnF,CAAC;AAAA,IACF,SAAS,KAAK;AACX,aAAO,MAAM,WAAW,uCAAwC,IAAc,OAAO,EAAE;AACvF,UAAI;AAAE,WAAG,MAAM,MAAM,gBAAgB;AAAA,MAAG,QAAQ;AAAA,MAAkC;AAAA,IACrF;AAAA,EACD,CAAC;AAGD,mBAAiB,IAAI,eAAe;AACpC,WAAS,IAAI,WAAW,cAAc;AACtC,QAAM,eAAe,QAAQ;AAC7B,iBAAe,GAAG,WAAW,oBAAoB;AAGjD,QAAM,kBAAmD;AAAA,IACvD,CAAC,WAAW,IAAI,eAAe,CAAC;AAAA,IAChC,CAAC,YAAY,IAAI,gBAAgB,CAAC;AAAA,IAClC,CAAC,SAAS,IAAI,aAAa,CAAC;AAAA,IAC5B,CAAC,cAAc,IAAI,kBAAkB,CAAC;AAAA,IACtC,CAAC,YAAY,IAAI,gBAAgB,CAAC;AAAA,IAClC,CAAC,UAAU,IAAI,cAAc,CAAC;AAAA,IAC9B,CAAC,UAAU,IAAI,cAAc,CAAC;AAAA,IAC9B,CAAC,WAAW,IAAI,eAAe,CAAC;AAAA,IAChC,CAAC,OAAO,IAAI,WAAW,CAAC;AAAA,IACxB,CAAC,cAAc,IAAI,kBAAkB,CAAC;AAAA,IACtC,CAAC,QAAQ,IAAI,YAAY,CAAC;AAAA,IAC1B,CAAC,iBAAiB,IAAI,oBAAoB,CAAC;AAAA,IAC3C,CAAC,QAAQ,IAAI,YAAY,CAAC;AAAA,IAC1B,CAAC,SAAS,IAAI,aAAa,CAAC;AAAA,IAC5B,CAAC,aAAa,IAAI,iBAAiB,CAAC;AAAA,EACtC;AAEA,aAAW,CAAC,MAAM,OAAO,KAAK,iBAAiB;AAC7C,YAAQ,GAAG,WAAW,oBAAoB;AAC1C,QAAI;AACF,YAAM,QAAQ,QAAQ;AACtB,eAAS,IAAI,MAAM,OAAO;AAAA,IAC5B,SAAS,OAAO;AACd,aAAO,MAAM,WAAW,WAAW,IAAI,mBAAoB,MAAgB,OAAO,EAAE;AAAA,IACtF;AAAA,EACF;AAGA,QAAM,mBAAmB,SAAS,IAAI,WAAW;AACjD,MAAI,kBAAkB;AAEpB,QAAI,IAAI,0BAA0B,CAAC,KAAK,QAAQ;AAC9C,YAAM,SAAS,iBAAiB,aAAa,IAAI,KAA+B;AAChF,UAAI,OAAO,OAAO,MAAM,EAAE,KAAK,OAAO,IAAI;AAAA,IAC5C,CAAC;AAGD,QAAI,KAAK,0BAA0B,QAAQ,KAAK,GAAG,CAAC,KAAK,QAAQ;AAC/D,uBAAiB,cAAc,IAAI,IAAI;AACvC,UAAI,WAAW,GAAG;AAAA,IACpB,CAAC;AAGD,QAAI,IAAI,sBAAsB,CAAC,KAAK,QAAQ;AAC1C,YAAM,SAAS,iBAAiB,aAAa,IAAI,KAA+B;AAChF,UAAI,OAAO,OAAO,MAAM,EAAE,KAAK,OAAO,IAAI;AAAA,IAC5C,CAAC;AACD,QAAI,KAAK,sBAAsB,QAAQ,KAAK,GAAG,CAAC,KAAK,QAAQ;AAC3D,uBAAiB,cAAc,IAAI,IAAI;AACvC,UAAI,WAAW,GAAG;AAAA,IACpB,CAAC;AAED,WAAO,KAAK,WAAW,iFAAiF,iBAAiB,eAAe,CAAC,GAAG;AAAA,EAC9I;AAOA;AACE,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,MAAM,OAAO,6BAA6B;AAE9C,UAAM,YAAa,OAAO,UAAkE;AAC5F,UAAM,gBAAgB,WAAW,YAAY;AAE7C,UAAM,kBAAkB,MAAM;AAC5B,YAAM,MAAM,WAAW;AACvB,YAAM,IAAK,IAAI,UAAkE,UAAU,CAAC;AAC5F,aAAO;AAAA,QACL,WAAY,EAAE,aAAwB,QAAQ,IAAI,qBAAqB;AAAA,QACvE,aAAc,EAAE,eAA0B,QAAQ,IAAI,uBAAuB;AAAA,QAC7E,OAAQ,EAAE,SAAoB;AAAA,QAC9B,gBAAiB,EAAE,kBAA+B,CAAC;AAAA,QACnD,YAAa,EAAE,cAAyB,QAAQ,IAAI,sBAAsB;AAAA,MAC5E;AAAA,IACF;AAGA,UAAM,aAAa,QAAQ,WAAW,EAAE,UAAU,MAAM,CAAC;AAGzD,UAAM,mBAAmB,CAAC,QAAiC;AACzD,YAAM,MAAM,gBAAgB;AAI5B,YAAMM,QAAO,IAAI,WAAW,QAAQ,OAAO,EAAE,KAAK,WAAW,IAAI,QAAQ,IAAI;AAC7E,aAAOA,QAAO,IAAI;AAAA,IACpB;AAEA,UAAM,kBAAkB,CAAC,QAAkC;AACzD,YAAM,EAAE,UAAU,IAAI,gBAAgB;AACtC,UAAI,CAAC,WAAW;AAGd,eAAO,KAAK,WAAW,gEAA2D;AAClF,eAAO;AAAA,MACT;AACA,YAAM,YAAa,IAAI,QAAQ,oBAAoB,KAAgB;AACnE,YAAM,MAAM,iBAAiB,GAAG;AAChC,YAAM,SAAU,IAAI,QAAQ,CAAC;AAC7B,aAAO,wBAAwB,WAAW,WAAW,KAAK,MAAM;AAAA,IAClE;AAGA,QAAI,KAAK,6BAA6B,YAAY,OAAO,KAAK,QAAQ;AACpE,UAAI;AACF,YAAI,CAAC,eAAe;AAAE,cAAI,KAAK,UAAU,EAAE,KAAK,YAAY,CAAC;AAAG;AAAA,QAAQ;AACxE,YAAI,CAAC,gBAAgB,GAAG,GAAG;AACzB,iBAAO,KAAK,WAAW,yCAAyC;AAChE,cAAI,OAAO,GAAG,EAAE,KAAK,WAAW;AAAG;AAAA,QACrC;AAEA,cAAM,OAAQ,IAAI,MAAM,QAAmB;AAC3C,cAAM,KAAM,IAAI,MAAM,MAAiB;AACvC,cAAM,YAAa,IAAI,MAAM,aAAwB;AACrD,cAAM,UAAW,IAAI,MAAM,WAAsB;AACjD,cAAM,EAAE,gBAAgB,OAAO,WAAW,IAAI,gBAAgB;AAK9D,cAAM,aAAa,UAAU,WAAW,UAAU;AAClD,cAAM,cAAc,aAAa,KAAK;AAEtC,YAAI,eAAe,SAAS,KAAK,CAAC,gBAAgB,aAAa,cAAc,GAAG;AAC9E,iBAAO,KAAK,WAAW,eAAe,SAAS,uCAAuC,WAAW,EAAE;AACnG,cAAI,KAAK,UAAU,EAAE,KAAK,YAAY,CAAC;AACvC;AAAA,QACF;AAEA,eAAO,KAAK,WAAW,eAAe,SAAS,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC,aAAa,WAAW,EAAE;AAG1G,cAAM,WAAW;AACjB,cAAM,QAAQ,MAAM,mBAAmB,UAAU,KAAK;AACtD,cAAMA,QAAO,WAAW,QAAQ,OAAO,EAAE,KAAK,WAAW,IAAI,QAAQ,IAAI;AACzE,YAAI,CAAC,OAAO;AAIV,cAAI,KAAK,UAAU,EAAE,KAAK,kBAAkB,WAAW,2BAA2B,CAAC;AACnF;AAAA,QACF;AACA,cAAM,WAAW,GAAGA,KAAI,qBAAqB,KAAK;AAClD,cAAM,YAAY,GAAGA,KAAI;AACzB,YAAI,KAAK,UAAU,EAAE,KAAK,mBAAmB,UAAU,SAAS,CAAC;AAAA,MACnE,SAAS,GAAG;AACV,eAAO,MAAM,WAAW,+BAAgC,EAAY,OAAO,EAAE;AAC7E,YAAI,OAAO,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,4BAA4B,CAAC;AAAA,MACvF;AAAA,IACF,CAAC;AAOD,QAAI,KAAK,4BAA4B,YAAY,OAAO,KAAK,QAAQ;AACnE,UAAI;AACF,YAAI,CAAC,eAAe;AAAE,cAAI,KAAK,UAAU,EAAE,KAAK,YAAY,CAAC;AAAG;AAAA,QAAQ;AACxE,YAAI,CAAC,gBAAgB,GAAG,GAAG;AACzB,cAAI,OAAO,GAAG,EAAE,KAAK,WAAW;AAAG;AAAA,QACrC;AAEA,cAAM,UAAW,IAAI,MAAM,WAAsB;AACjD,cAAM,OAAQ,IAAI,MAAM,QAAmB;AAC3C,cAAM,KAAM,IAAI,MAAM,MAAiB;AACvC,cAAM,YAAa,IAAI,MAAM,aAAwB;AACrD,cAAM,gBAAiB,IAAI,MAAM,gBAA2B,IAAI,KAAK;AACrE,cAAM,EAAE,OAAO,YAAY,eAAe,IAAI,gBAAgB;AAE9D,cAAM,aAAa,UAAU,WAAW,UAAU;AAClD,cAAM,cAAc,aAAa,KAAK;AACtC,YAAI,eAAe,SAAS,KAAK,CAAC,gBAAgB,aAAa,cAAc,GAAG;AAC9E,cAAI,KAAK,UAAU,EAAE,KAAK,YAAY,CAAC;AAAG;AAAA,QAC5C;AAEA,cAAMA,QAAO,WAAW,QAAQ,OAAO,EAAE,KAAK,WAAW,IAAI,QAAQ,IAAI;AACzE,cAAM,YAAY,GAAGA,KAAI;AAEzB,YAAI,CAAC,cAAc;AAEjB,gBAAM,MAAM;AACZ,gBAAM,KAAK,MAAM,mBAAmB,KAAK,KAAK;AAC9C,cAAI,IAAI;AACN,gBAAI,KAAK,UAAU,EAAE,KAAK,mBAAmB,GAAGA,KAAI,qBAAqB,EAAE,IAAI,SAAS,CAAC;AAAA,UAC3F,OAAO;AACL,gBAAI,KAAK,UAAU,EAAE,KAAK,kBAAkB,GAAG,CAAC;AAAA,UAClD;AACA;AAAA,QACF;AAEA,eAAO,KAAK,WAAW,kBAAkB,aAAa,MAAM,GAAG,EAAE,CAAC,GAAG;AAOrE,cAAM,SAAQ,oBAAI,KAAK,GAAE,mBAAmB,SAAS;AAAA,UACnD,SAAS;AAAA,UAAQ,MAAM;AAAA,UAAW,OAAO;AAAA,UAAQ,KAAK;AAAA,QACxD,CAAC;AACD,cAAM,oBAAoB;AAAA,UACxB;AAAA,UACA,YAAY,KAAK;AAAA,UACjB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAOX,cAAM,QAAQ,eAAe,OAAO;AACpC,cAAM,UAAU,GAAGA,KAAI,gCAAgC,KAAK;AAO5D,SAAC,YAAY;AACX,cAAI;AACF,kBAAM,cAAc,eAAe,OAAO;AAC1C,kBAAM,aAAc,QAAQ,IAAI,sBAC3B;AACL,kBAAM,SAAS,MAAM;AAAA,cACnB;AAAA,cACA;AAAA,cACA,eAAe,OAAO;AAAA,cACtB;AAAA,gBACE,GAAI,cAAc,EAAE,WAAW,YAAY,IAAI,CAAC;AAAA,gBAChD,OAAO;AAAA,gBACP,cAAc;AAAA,gBACd,UAAU;AAAA,cACZ;AAAA,cACA;AAAA,cACA,YAAY,QAAQ,IAAM;AAAA,YAC5B;AACA,gBAAI,QAAQ,UAAW,gBAAe,SAAS,OAAO,SAAS;AAE/D,gBAAI,SAAS,QAAQ,WAAW,IAAI,KAAK;AACzC,gBAAI,CAAC,MAAO,SAAQ;AACpB,gBAAI,MAAM,SAAS,IAAK,SAAQ,MAAM,MAAM,GAAG,GAAG,EAAE,QAAQ,UAAU,EAAE,IAAI;AAE5E,kBAAM,QAAQ,MAAM,mBAAmB,OAAO,KAAK;AACnD,gBAAI,CAAC,OAAO;AACV,2BAAa,OAAO,YAAY;AAChC;AAAA,YACF;AACA,6BAAiB,OAAO,OAAO,KAAK;AAAA,UACtC,SAAS,GAAG;AACV,mBAAO,KAAK,WAAW,oCAAqC,EAAY,OAAO,EAAE;AACjF,yBAAa,OAAQ,EAAY,OAAO;AAAA,UAC1C;AAAA,QACF,GAAG;AAGH,YAAI,KAAK,UAAU,EAAE,KAAK,sBAAsB,SAAS,CAAC,CAAC;AAAA,MAC7D,SAAS,GAAG;AACV,eAAO,MAAM,WAAW,8BAA+B,EAAY,OAAO,EAAE;AAC5E,YAAI,OAAO,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,uBAAuB,CAAC;AAAA,MAClF;AAAA,IACF,CAAC;AASD,UAAM,kBAAkB,OAAO,KAAsB,QAA0B;AAC7E,UAAI;AACF,YAAI,CAAC,eAAe;AAAE,cAAI,KAAK,UAAU,EAAE,KAAK,YAAY,CAAC;AAAG;AAAA,QAAQ;AACxE,YAAI,CAAC,gBAAgB,GAAG,GAAG;AACzB,iBAAO,KAAK,WAAW,yCAAyC,IAAI,MAAM,WAAW,IAAI,MAAM,KAAK,GAAG;AACvG,cAAI,OAAO,GAAG,EAAE,KAAK,WAAW;AAAG;AAAA,QACrC;AAEA,cAAM,QAAS,IAAI,MAAM,SAAoB;AAC7C,cAAM,MAAM,YAAY,KAAK;AAC7B,eAAO,KAAK,WAAW,qBAAqB,IAAI,MAAM,UAAU,MAAM,MAAM,GAAE,CAAC,CAAC,WAAW,KAAK,UAAU,SAAS,EAAE;AACrH,cAAM,EAAE,OAAO,WAAW,IAAI,gBAAgB;AAC9C,cAAMA,QAAO,WAAW,QAAQ,OAAO,EAAE,KAAK,WAAW,IAAI,QAAQ,IAAI;AACzE,cAAM,UAAU,GAAGA,KAAI,gCAAgC,KAAK;AAC5D,cAAM,YAAY,GAAGA,KAAI;AAEzB,YAAI,CAAC,KAAK;AAER,gBAAM,MAAM;AACZ,gBAAM,KAAK,MAAM,mBAAmB,KAAK,KAAK;AAC9C,cAAI,GAAI,KAAI,KAAK,UAAU,EAAE,KAAK,mBAAmB,GAAGA,KAAI,qBAAqB,EAAE,IAAI,SAAS,CAAC;AAAA,cAC5F,KAAI,KAAK,UAAU,EAAE,KAAK,kBAAkB,GAAG,CAAC;AACrD;AAAA,QACF;AAEA,YAAI,IAAI,WAAW,WAAW,IAAI,YAAY;AAC5C,iBAAO,KAAK,WAAW,yBAAyB,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,IAAI,aAAa,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG;AACjH,gBAAM,WAAW,GAAGA,KAAI,qBAAqB,IAAI,UAAU;AAC3D,cAAI,KAAK,UAAU,EAAE,KAAK,mBAAmB,UAAU,SAAS,CAAC;AACjE;AAAA,QACF;AAEA,YAAI,IAAI,WAAW,SAAS;AAC1B,iBAAO,KAAK,WAAW,qBAAqB,IAAI,KAAK,EAAE;AACvD,gBAAM,MAAM;AACZ,gBAAM,KAAK,MAAM,mBAAmB,KAAK,KAAK;AAC9C,cAAI,GAAI,KAAI,KAAK,UAAU,EAAE,KAAK,mBAAmB,GAAGA,KAAI,qBAAqB,EAAE,IAAI,SAAS,CAAC;AAAA,cAC5F,KAAI,KAAK,UAAU,EAAE,KAAK,kBAAkB,GAAG,CAAC;AACrD;AAAA,QACF;AAOA,cAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC7B,YAAI,MAAM,KAAQ;AAChB,iBAAO,KAAK,WAAW,4BAA4B,GAAG,IAAI;AAC1D,uBAAa,OAAO,SAAS;AAC7B,gBAAM,MAAM;AACZ,gBAAM,KAAK,MAAM,mBAAmB,KAAK,KAAK;AAC9C,cAAI,GAAI,KAAI,KAAK,UAAU,EAAE,KAAK,mBAAmB,GAAGA,KAAI,qBAAqB,EAAE,IAAI,SAAS,CAAC;AAAA,cAC5F,KAAI,KAAK,UAAU,EAAE,KAAK,kBAAkB,GAAG,CAAC;AACrD;AAAA,QACF;AAMA,cAAM,SAAS;AACf,cAAM,cAAc,OAAO,eAAe;AAC1C,cAAM,eAAe,MAAM,OAAS,MAAO,cAAc,MAAS;AAClE,YAAI,cAAc;AAChB,gBAAM,UAAU;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,gBAAM,SAAS,QAAQ,cAAc,QAAQ,MAAM;AACnD,iBAAO,cAAc,cAAc;AACnC,gBAAM,KAAK,MAAM,mBAAmB,QAAQ,KAAK;AACjD,cAAI,IAAI;AACN,gBAAI,KAAK,UAAU,EAAE,KAAK;AAAA;AAAA,UAE5BA,KAAI,qBAAqB,EAAE;AAAA;AAAA,4BAET,OAAO;AAAA,YACvB;AACA;AAAA,UACF;AAAA,QAEF;AACA,YAAI,KAAK,UAAU,EAAE,KAAK,sBAAsB,SAAS,CAAC,CAAC;AAAA,MAC7D,SAAS,GAAG;AACV,eAAO,MAAM,WAAW,4BAA6B,EAAY,OAAO,EAAE;AAC1E,YAAI,OAAO,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,uBAAuB,CAAC;AAAA,MAClF;AAAA,IACF;AACA,QAAI,KAAK,0BAA0B,YAAY,eAAe;AAC9D,QAAI,IAAI,0BAA0B,eAAe;AAGjD,QAAI,KAAK,+BAA+B,YAAY,CAAC,KAAK,QAAQ;AAChE,UAAI;AACF,cAAM,UAAW,IAAI,MAAM,WAAsB;AACjD,cAAM,SAAU,IAAI,MAAM,cAAyB;AACnD,cAAM,WAAY,IAAI,MAAM,gBAA2B;AACvD,eAAO,KAAK,WAAW,eAAe,QAAQ,MAAM,GAAG,EAAE,CAAC,cAAc,MAAM,GAAG,WAAW,aAAa,QAAQ,MAAM,EAAE,EAAE;AAC3H,YAAI,WAAW,eAAe,WAAW,YAAY,WAAW,cAAc,WAAW,eAAe,WAAW,QAAQ;AACzH,kBAAQ,OAAO;AAAA,QACjB;AACA,YAAI,WAAW,GAAG;AAAA,MACpB,SAAS,GAAG;AACV,eAAO,KAAK,WAAW,0BAA2B,EAAY,OAAO,EAAE;AACvE,YAAI,WAAW,GAAG;AAAA,MACpB;AAAA,IACF,CAAC;AAOD,QAAI,IAAI,4BAA4B,OAAO,KAAK,QAAQ;AACtD,YAAM,QAAQ,IAAI,OAAO;AACzB,YAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,UAAI,CAAC,OAAO;AAAE,YAAI,OAAO,GAAG,EAAE,KAAK,SAAS;AAAG;AAAA,MAAQ;AACvD,UAAI,UAAU,gBAAgB,MAAM,IAAI;AACxC,UAAI,UAAU,kBAAkB,OAAO,MAAM,IAAI,MAAM,CAAC;AACxD,UAAI,UAAU,iBAAiB,qBAAqB;AACpD,UAAI,KAAK,MAAM,GAAG;AAAA,IACpB,CAAC;AAED,WAAO,KAAK,WAAW,+IAA+I;AAAA,EACxK;AAGA,oBAAkB;AAClB,qBAAmB;AACnB,iBAAe,EAAE,MAAM,CAAC,MAAM,OAAO,KAAK,WAAW,mBAAmB,EAAE,OAAO,EAAE,CAAC;AACpF,wBAAsB,GAAG;AAGzB,yBAAuB,EAAE,MAAM,CAAC,MAAM,OAAO,KAAK,WAAW,iBAAkB,EAAY,OAAO,EAAE,CAAC;AAGrG,oBAAkB;AAGlB,gBAAc,MAAM;AAGpB,MAAI,OAAO,MAAM,YAAY,OAAO;AAClC,WAAO,yBAAyB,EAAE,KAAK,CAAC,EAAE,qBAAqB,MAAM;AACnE,2BAAqB,EAAE,MAAM,CAAC,MAAM,OAAO,KAAK,WAAW,2BAA4B,EAAY,OAAO,EAAE,CAAC;AAAA,IAC/G,CAAC,EAAE,MAAM,MAAM;AAAA,IAAiB,CAAC;AAAA,EACnC;AAGA,MAAI,OAAO,aAAa,SAAS;AAC/B,oBAAgB,OAAO,WAAW;AAClC,qBAAiB;AACjB,2BAAuB;AACvB,WAAO,KAAK,WAAW,kEAAkE;AAIzF,QAAI;AACF,YAAM,EAAE,4BAA4B,IAAI,MAAM,OAAO,yBAAyB;AAC9E,YAAM,4BAA4B;AAAA,IACpC,SAAS,GAAG;AACV,aAAO,KAAK,WAAW,iCAAkC,EAAY,OAAO,EAAE;AAAA,IAChF;AAAA,EACF;AAMA,MAAI;AACF,UAAM,EAAE,cAAc,qBAAqB,YAAY,IAAI,MAAM,OAAO,uBAAuB;AAC/F,UAAM,WAAW,aAAa;AAC9B,WAAO,KAAK,WAAW,mCAA8B,SAAS,OAAO,YAAY,KAAK,SAAS,SAAS,OAAO,OAAK,EAAE,eAAe,SAAS,EAAE,MAAM,yBAAyB;AAC/K,eAAW,MAAM,SAAS,SAAS,OAAO,OAAK,EAAE,eAAe,SAAS,EAAE,MAAM,EAAE,GAAG;AACpF,aAAO,KAAK,YAAY,kBAAkB,GAAG,IAAI,MAAM,GAAG,OAAO,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,IAClF;AAGA,IAAC,WAAoE,yBAAyB,MAAM;AAClG,YAAM,KAAK,YAAY;AACvB,aAAO,KAAK,oBAAoB,EAAE,IAAI;AAAA,IACxC;AAAA,EACF,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,+BAAgC,EAAY,OAAO,EAAE;AAAA,EAC9E;AAOA,MAAI;AACF,UAAM,EAAE,cAAc,qBAAqB,IAAI,MAAM,OAAO,mBAAmB;AAC/E,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,UAAM,UAAU,MAAM;AACpB,OAAC,YAAY;AACX,YAAI;AACF,wBAAc,MAAM,qBAAqB;AACzC,qBAAW,KAAK,IAAI;AAAA,QACtB,QAAQ;AAAA,QAAW;AAAA,MACrB,GAAG;AAAA,IACL;AACA,YAAQ;AACR,gBAAY,SAAS,GAAM,EAAE,QAAQ;AACrC,IAAC,WAAsE,2BAA2B,MAAM;AAGtG,UAAI,KAAK,IAAI,IAAI,WAAW,QAAW,gBAAgB,IAAI;AAEzD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,UAAM,aAAa;AACnB,WAAO,KAAK,WAAW,6CAA6C;AAAA,EACtE,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,iCAAkC,EAAY,OAAO,EAAE;AAAA,EAChF;AAKA,MAAI;AACF,UAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,4BAA4B;AAC1E,IAAC,WAEE,+BAA+B,CAAC,cAAsB;AACvD,UAAI;AAAE,eAAO,qBAAqB,SAAS;AAAA,MAAG,QAAQ;AAAE,eAAO;AAAA,MAAI;AAAA,IACrE;AACA,WAAO,KAAK,WAAW,mCAAmC;AAAA,EAC5D,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,qCAAsC,EAAY,OAAO,EAAE;AAAA,EACpF;AAKA,MAAI;AACF,UAAM,EAAE,wBAAwB,IAAI,MAAM,OAAO,6BAA6B;AAC9E,IAAC,WAAgF,8BAA8B,MAAM;AACnH,UAAI;AAAE,eAAO,wBAAwB;AAAA,MAAG,QAAQ;AAAE,eAAO;AAAA,MAAM;AAAA,IACjE;AACA,WAAO,KAAK,WAAW,sCAAsC;AAAA,EAC/D,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,8BAA+B,EAAY,OAAO,EAAE;AAAA,EAC7E;AAKA,MAAI;AACF,UAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,yBAAyB;AACtE,UAAM,EAAE,mBAAAC,mBAAkB,IAAI,MAAM,OAAO,cAAc;AACzD,UAAM,EAAE,kBAAAC,kBAAiB,IAAI,MAAM,OAAO,uBAAuB;AAKjE,UAAM,IAAI;AAKV,gBAAY,MAAM;AAChB,OAAC,YAAY;AACX,YAAI;AACF,gBAAM,OAAO,oBAAoB;AACjC,gBAAM,OAAO,MAAM,KAAK,YAAY;AACpC,cAAI,MAAM,OAAO,OAAO,KAAK,IAAI,YAAY,YAAY,KAAK,IAAI,UAAU,GAAG;AAC7E,cAAE,oBAAoB;AAAA,cACpB,SAAS,KAAK,IAAI;AAAA,cAClB,QAAQ,KAAK,IAAI;AAAA,cACjB,QAAQ,KAAK,IAAI,UAAW,KAAK,IAAI,UAAU,KAAK,IAAI;AAAA,YAC1D;AAAA,UACF,OAAO;AACL,cAAE,oBAAoB;AAAA,UACxB;AAAA,QACF,QAAQ;AAAA,QAAoB;AAAA,MAC9B,GAAG;AAAA,IACL,GAAG,IAAM,EAAE,QAAQ;AAGnB,MAAE,0BAA0B,MAAM;AAChC,UAAI;AACF,cAAM,IAAID,mBAAkB;AAC5B,eAAO,EAAE,eAAe,EAAE,eAAe,WAAW,EAAE,UAAU;AAAA,MAClE,QAAQ;AAAE,eAAO;AAAA,MAAM;AAAA,IACzB;AAMA,MAAE,oCAAoC,MAAM;AAC1C,UAAI;AACF,cAAM,QAAQC,kBAAiB;AAC/B,eAAO,MAAM,2BAA2B,MAAM,iBAAiB;AAAA,MACjE,QAAQ;AAAE,eAAO;AAAA,MAAG;AAAA,IACtB;AAEA,WAAO,KAAK,WAAW,4DAA4D;AAAA,EACrF,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,mCAAoC,EAAY,OAAO,EAAE;AAAA,EAClF;AAOA,MAAI;AACF,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,oBAAoB;AAC7D,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,yBAAyB;AACrE,oBAAgB,eAAe,YAAY;AACzC,UAAI;AAAE,cAAM,mBAAmB;AAAA,MAAG,SAAS,GAAG;AAAE,eAAO,MAAM,WAAW,sBAAuB,EAAY,OAAO,EAAE;AAAA,MAAG;AAAA,IACzH,GAAG,GAAO;AACV,WAAO,KAAK,WAAW,+CAA+C;AAAA,EACxE,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,+BAAgC,EAAY,OAAO,EAAE;AAAA,EAC9E;AAMA,MAAI;AACF,UAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,0BAA0B;AACxE,yBAAqB;AACrB,UAAM,EAAE,sBAAsB,0BAA0B,IAAI,MAAM,OAAO,6BAA6B;AACtG,UAAM,UAAU,MAAM,0BAA0B;AAChD,WAAO,KAAK,WAAW,uBAAuB,QAAQ,OAAO,kBAAkB,QAAQ,SAAS,uCAAuC,QAAQ,UAAU,qCAAqC;AAC9L,yBAAqB,KAAQ,CAAC;AAAA,EAChC,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,4CAA6C,EAAY,OAAO,EAAE;AAAA,EAC3F;AAIA,MAAI;AACF,UAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,yBAAyB;AACvE,yBAAqB;AAAA,EACvB,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,8BAA+B,EAAY,OAAO,EAAE;AAAA,EAC7E;AAIA,MAAI;AACF,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,oBAAoB;AAC5D,mBAAe;AAAA,EACjB,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,uBAAwB,EAAY,OAAO,EAAE;AAAA,EACtE;AAMA,MAAI;AACF,UAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,4BAA4B;AACzE,wBAAoB;AAAA,EACtB,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,oCAAqC,EAAY,OAAO,EAAE;AAAA,EACnF;AAIA,MAAI;AACF,UAAM,EAAE,oBAAoB,YAAY,IAAI,MAAM,OAAO,2BAA2B;AACpF,UAAM,eAAe,YAAY,MAAM;AACrC,YAAM,YAAY;AAChB,YAAI;AACF,qBAAW,KAAK,mBAAmB,GAAG;AACpC,gBAAI;AAAE,oBAAM,YAAY,EAAE,SAAS;AAAA,YAAG,QAAQ;AAAA,YAAW;AAAA,UAC3D;AAAA,QACF,QAAQ;AAAA,QAAW;AAAA,MACrB,GAAG;AAAA,IACL,GAAG,IAAM;AACT,iBAAa,QAAQ;AACrB,WAAO,KAAK,WAAW,yCAAyC;AAAA,EAClE,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,8BAA+B,EAAY,OAAO,EAAE;AAAA,EAC7E;AAKA,MAAI;AACF,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,oBAAoB;AAC7D,UAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,4BAA4B;AACzE,oBAAgB,yBAAyB,YAAY;AACnD,UAAI;AAAE,4BAAoB;AAAA,MAAG,SAAS,GAAG;AAAE,eAAO,MAAM,WAAW,0BAA2B,EAAY,OAAO,EAAE;AAAA,MAAG;AAAA,IACxH,GAAG,IAAS;AAAA,EACd,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,0CAA2C,EAAY,OAAO,EAAE;AAAA,EACzF;AAOA,MAAI;AACF,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,oBAAoB;AAC7D,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,yBAAyB;AACjE,oBAAgB,eAAe,YAAY;AACzC,UAAI;AAAE,cAAM,eAAe;AAAA,MAAG,SAAS,GAAG;AAAE,eAAO,MAAM,WAAW,iBAAkB,EAAY,OAAO,EAAE;AAAA,MAAG;AAAA,IAChH,GAAG,KAAK,KAAK,KAAK,GAAI;AACtB,WAAO,KAAK,WAAW,6CAA6C;AAAA,EACtE,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,+BAAgC,EAAY,OAAO,EAAE;AAAA,EAC9E;AAIA,MAAI;AACF,UAAM,aAAc,OAKf;AACL,QAAI,YAAY,SAAS;AACvB,aAAO,KAAK,WAAW,qCAAqC;AAC5D,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,kCAAkC;AAC7E,YAAM,SAAS,WAAW,kBAAkB;AAC5C,YAAM,YAAY,YAAY,MAAM;AAClC,0BAAkB,EAAE,MAAM,CAAC,MAAa,OAAO,MAAM,WAAW,iBAAiB,EAAE,OAAO,EAAE,CAAC;AAAA,MAC/F,GAAG,MAAM;AACT,MAAC,UAAgD,QAAQ;AAIzD,UAAI,WAAW,eAAe,OAAO;AACnC,cAAM,EAAE,IAAI,eAAe,IAAI,MAAM,OAAO,0BAA0B;AACtE,uBAAe,iBAAiB,OAAO,YAAY;AACjD,cAAI;AACF,kBAAM,KAAM,QAAoC,cAAc;AAC9D,gBAAI,CAAC,GAAG,WAAW,WAAW,EAAG;AACjC,kBAAM,aAAc,QAAoC;AACxD,gBAAI,CAAC,WAAY;AAEjB,uBAAW,YAAY;AACrB,kBAAI;AACF,sBAAM,EAAE,eAAe,IAAI,MAAM,OAAO,gCAAgC;AACxE,sBAAM,WAAW,MAAM,eAAe,UAAU;AAEhD,oBAAI,UAAU,WAAW,cAAc,WAAW,QAAQ;AACxD,wBAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,4BAA4B;AACtE,wBAAM,iBAAiB,UAAU;AAAA,gBACnC;AAAA,cACF,SAAS,GAAG;AACV,uBAAO,KAAK,WAAW,+BAAgC,EAAY,OAAO,EAAE;AAAA,cAC9E;AAAA,YACF,GAAG,GAAI;AAAA,UACT,SAAS,GAAG;AACV,mBAAO,MAAM,WAAW,8BAA+B,EAAY,OAAO,EAAE;AAAA,UAC9E;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AACV,WAAO,KAAK,WAAW,8BAA+B,EAAY,OAAO,EAAE;AAAA,EAC7E;AAGA,aAAW;AAGX,uBAAqB,OAAO,QAAQ;AAClC,cAAU;AAAA,MACR,MAAM;AAAA,MACN,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,CAAC;AAAA,EACH,CAAC,EAAE,MAAM,CAAC,MAAa,OAAO,KAAK,WAAW,mBAAmB,EAAE,OAAO,EAAE,CAAC;AAG7E,2BAAyB,OAAO,SAAS,UAAU;AACjD,UAAM,SAAS,kBAAkB,QAAQ,IAAI,KAAK,MAAM,MAAM;AAAA;AAAA,aAAkB,QAAQ,MAAM;AAC9F,UAAM,WAAW,MAAM,eAAe,QAAQ,WAAW,QAAQ;AACjE,cAAU,EAAE,MAAM,mBAAmB,SAAS,QAAQ,MAAM,UAAU,SAAS,SAAS,MAAM,CAAC;AAC/F,WAAO,KAAK,WAAW,YAAY,QAAQ,IAAI,gBAAgB,SAAS,QAAQ,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,EACjG,CAAC;AACD,eAAa;AAGb,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,oBAAoB;AACxD,aAAW;AAGX,MAAI,OAAO,KAAK,WAAW,CAAC,OAAO,KAAK,QAAQ;AAC9C,WAAO,KAAK,WAAW,+FAA+F;AAAA,EACxH;AACA,MAAI,OAAO,KAAK,WAAW,OAAO,KAAK,QAAQ;AAC7C,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,qBAAqB;AAChE,UAAM,EAAE,gBAAgB,qBAAqB,wBAAwB,YAAY,IAAI,MAAM,OAAO,sBAAsB;AACxH,UAAM,EAAE,eAAe,gBAAgB,oBAAoB,IAAI,MAAM,OAAO,sBAAsB;AAClG,UAAM,SAAS,kBAAkB;AAGjC,gBAAY,OAAO,KAAK,QAAQ;AAGhC,wBAAoB,CAAC,SAAS;AAC5B,gBAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,UACf,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,UACX,SAAS,KAAK;AAAA,UACd,QAAQ,KAAK;AAAA,UACb,eAAe,KAAK;AAAA,QACtB;AAAA,MACF,CAAC;AACD,aAAO,KAAK,WAAW,8BAA8B,KAAK,QAAQ,KAAK,KAAK,OAAO,IAAI,KAAK,IAAI,uCAAkC;AAAA,IACpI,CAAC;AAGD,2BAAuB,CAAC,SAAS;AAC/B,UAAI,OAAO,KAAK,QAAQ;AACtB,sBAAc,KAAK,SAAS,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,EAC9D,KAAK,CAAC,OAAO;AACZ,cAAI,IAAI;AACN,sBAAU,EAAE,MAAM,uBAAuB,KAAK,CAAC;AAC/C,mBAAO,KAAK,WAAW,+BAA+B,KAAK,QAAQ,EAAE;AAAA,UACvE;AAAA,QACF,CAAC,EACA,MAAM,MAAM,OAAO,MAAM,WAAW,8BAA8B,KAAK,QAAQ,EAAE,CAAC;AAAA,MACvF;AAAA,IACF,CAAC;AAED,UAAM,eAAe,QAAQ,MAAM;AAAA,MACjC,MAAM,OAAO,KAAK;AAAA,MAClB,WAAW,OAAO,KAAK;AAAA,MACvB,aAAa,OAAO,KAAK;AAAA,MACzB,oBAAoB,OAAO,KAAK;AAAA,IAClC,CAAC;AAGD,QAAI,SAAS,aAAa;AACxB,aAAO;AACP,aAAO,KAAK,WAAW,6EAAwE;AAAA,IACjG;AAGA,QAAI,OAAO,KAAK,YAAY,SAAS,GAAG;AACtC,iBAAW,QAAQ,OAAO,KAAK,aAAa;AAC1C,cAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,cAAM,WAAW,MAAM,CAAC;AACxB,cAAM,WAAW,SAAS,MAAM,CAAC,KAAK,SAAS,EAAE;AACjD,YAAI,CAAC,YAAY,MAAM,QAAQ,GAAG;AAChC,iBAAO,KAAK,WAAW,iCAAiC,IAAI,wDAAmD;AAC/G;AAAA,QACF;AACA,sBAAc,UAAU,UAAU,QAAQ,OAAO,KAAK,MAAM,EACzD,MAAM,MAAM,OAAO,MAAM,WAAW,4BAA4B,IAAI,EAAE,CAAC;AAAA,MAC5E;AAAA,IACF;AAGA,mBAAe,QAAQ,YAAY;AACjC,YAAM,EAAE,0BAA0B,aAAa,IAAI,MAAM,OAAO,sBAAsB;AACtF,YAAM,SAAS,MAAM,kBAAkB;AACvC,YAAM,MAAM,WAAW;AACvB,YAAM,WAAW,aAAa,IAAI,KAAK,IAAI,OAAO,KAAK,gBAAgB,CAAC;AACxE,YAAM,OAAO,KAAK,IAAI,GAAG,MAAM,MAAM,WAAW,GAAG;AACnD,aAAO;AAAA,QACL,UAAU,WAAW;AAAA,QACrB,SAAS;AAAA,QACT,QAAQ,OAAO,IAAI,OAAK,EAAE,EAAE;AAAA,QAC5B,MAAM,KAAK,MAAM,OAAO,GAAG,IAAI;AAAA,MACjC;AAAA,IACF,GAAG,OAAO,KAAK,uBAAuB,GAAM;AAG5C,wBAAoB,GAAM;AAE1B,UAAM,OAAO,OAAO,KAAK,cAAc,iBAAiB;AACxD,WAAO,KAAK,WAAW,4BAAuB,OAAO,MAAM,GAAG,CAAC,CAAC,eAAe,OAAO,KAAK,IAAI,iBAAiB,OAAO,KAAK,SAAS,iBAAiB,OAAO,KAAK,QAAQ,YAAY,IAAI,EAAE;AAAA,EAC9L;AAGA,aAAW,GAAG,SAAS,CAAC,QAA+B;AACrD,QAAI,IAAI,SAAS,cAAc;AAC7B,aAAO,KAAK,WAAW,QAAQ,IAAI,kFAAkF;AACrH,aAAO,KAAK,WAAW,+BAA+B,IAAI,IAAI,IAAI,EAAE;AACpE,cAAQ,KAAK,CAAC;AAAA,IAChB,OAAO;AACL,aAAO,MAAM,WAAW,iBAAiB,IAAI,OAAO,EAAE;AAAA,IACxD;AAAA,EACF,CAAC;AAQD,MAAI;AACF,UAAM,IAAI,QAAc,CAAC,mBAAmB;AAC1C,YAAM,QAAQ,IAAI,iBAAiB,EAAE,MAAM,aAAa,MAAM,SAAS,IAAI,CAAC;AAC5E,YAAM,KAAK,WAAW,MAAM;AAC1B,eAAO;AAAA,UAAK;AAAA,UACV,mEAAmE,IAAI,kCACvC,IAAI,IAAI,IAAI,oGACN,IAAI;AAAA,QAC5C;AACA,cAAM,QAAQ;AACd,uBAAe;AAAA,MACjB,CAAC;AACD,YAAM,KAAK,SAAS,MAAM;AAExB,uBAAe;AAAA,MACjB,CAAC;AACD,YAAM,KAAK,WAAW,MAAM;AAC1B,cAAM,QAAQ;AACd,uBAAe;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AAGA,QAAM,gBAAgB,OAAO,WAAW,QAAQ,WAAW,QAAQ,IAAI,eAAe;AACtF,QAAM,aAAa,OAAO,OAAO,UAAU;AAE3C,0BAAwB,YAAY,MAAM;AACxC,UAAM,YAAY;AAClB,UAAI;AACJ,cAAM,MAAM,KAAK,IAAI;AACrB,oBAAY,aAAY,oBAAI,KAAK,GAAE,YAAY;AAG/C,YAAI;AACF,gBAAM,OAAO,MAAM,MAAM,GAAG,aAAa,aAAa,EAAE,QAAQ,YAAY,QAAQ,GAAI,EAAE,CAAC;AAC3F,sBAAY,gBAAgB,KAAK;AAAA,QACnC,QAAQ;AACN,cAAI,YAAY,eAAe;AAC7B,mBAAO,KAAK,WAAW,uCAAuC;AAAA,UAChE;AACA,sBAAY,gBAAgB;AAAA,QAC9B;AAIA,YAAI;AACF,gBAAM,OAAO,MAAM,MAAM,GAAG,UAAU,WAAW;AAAA,YAC/C,QAAQ,YAAY,QAAQ,GAAI;AAAA,UAClC,CAAC;AACD,sBAAY,aAAa,KAAK;AAAA,QAChC,QAAQ;AACN,sBAAY,aAAa;AAAA,QAC3B;AAGA,YAAI,oBAAoB,KAAK,sBAAsB,YAAY,eAAe;AAC5E,cAAI,MAAM,YAAY,oBAAoB,KAAS;AACjD,gBAAI,CAAC,YAAY,eAAe;AAC9B,qBAAO,KAAK,WAAW,mBAAmB,iBAAiB,oCAAoC;AAC/F,0BAAY,gBAAgB;AAAA,YAC9B;AAAA,UACF;AAAA,QACF,OAAO;AACL,sBAAY,gBAAgB;AAC5B,sBAAY,oBAAoB;AAChC,sBAAY,gBAAgB;AAAA,QAC9B;AAGA,cAAM,MAAM,QAAQ,YAAY;AAChC,cAAM,SAAS,KAAK,MAAM,IAAI,WAAW,OAAO,IAAI;AACpD,cAAM,QAAQ,KAAK,MAAM,IAAI,MAAM,OAAO,IAAI;AAC9C,YAAI,SAAS,MAAM;AACjB,iBAAO,KAAK,WAAW,0CAAqC,MAAM,IAAI;AAAA,QACxE;AAGA,cAAM,gBAAgB,OAAO,UAAU,eAAe;AACtD,YAAI,QAAQ,gBAAgB,KAAK;AAC/B,iBAAO,MAAM,WAAW,8BAAyB,KAAK,6BAA6B,aAAa,wCAAwC;AACxI,kCAAwB,KAAK,IAAI,IAAI,yBAAyB,OAAO,SAAS,sBAAsB,KAAK,CAAC;AAAA,QAC5G,WAAW,QAAQ,gBAAgB,OAAO,0BAA0B,MAAM;AACxE,kCAAwB;AAAA,QAC1B;AAGA,YAAI;AACF,gBAAM,cAAc,OAAO,UAAU,kBAAkB;AACvD,gBAAM,EAAE,UAAU,IAAI,MAAM,OAAO,eAAe;AAClD,gBAAM,KAAK,UAAU,MAAM,CAAC,OAAO,UAAU,GAAG,EAAE,UAAU,SAAS,SAAS,IAAK,CAAC;AACpF,gBAAM,SAAS,SAAS,GAAG,QAAQ,MAAM,GAAI,EAAE,CAAC,KAAK,KAAK,EAAE;AAC5D,cAAI,SAAS,cAAc,KAAK;AAC9B,mBAAO,MAAM,WAAW,wBAAmB,MAAM,cAAc,UAAU,yBAAyB,WAAW,oCAAoC;AAAA,UACnJ;AAAA,QACF,QAAQ;AAAA,QAAkD;AAG1D,YAAI;AAAE,0BAAgB,SAAS;AAAA,QAAG,QAAQ;AAAA,QAAqB;AAAA,MAC/D,SAAS,KAAK;AACZ,eAAO,MAAM,WAAW,yBAA0B,IAAc,OAAO,EAAE;AAAA,MAC3E;AAAA,IACA,GAAG;AAAA,EACL,GAAG,GAAM;AACT,wBAAsB,MAAM;AAE5B,SAAO,KAAK,WAAW,uCAAuC;AAU9D,QAAM,kBAAkB;AAAA;AAAA,IAEtB;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACF;AACA,WAAS,aAAa,MAAsB;AAC1C,QAAI,UAAU;AACd,eAAW,WAAW,iBAAiB;AACrC,gBAAU,QAAQ,QAAQ,SAAS,YAAY;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,OAAO,MAAkD,QAAiB;AAC5F,QAAI;AACF,YAAM,MAAM,WAAW;AACvB,UAAI,CAAC,IAAI,WAAW,QAAS;AAC7B,UAAI,CAAE,IAAI,WAAqD,aAAc;AAI7E,YAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,2BAA2B;AACxE,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,qBAAqB;AAChE,YAAM,OAAO,QAAQ;AACrB,YAAM,WAAY,eAAe,QAAS,IAAI,SAAS,IAAI,UAAW,OAAO,GAAG;AAChF,YAAM,QAAQ,aAAa,SAAS,MAAM,IAAI,EAAE,KAAK,OAAO,CAAC,EAAE,MAAM,GAAG,GAAI;AAC5E,YAAM,UAAU,aAAa,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG;AAC3F,YAAM,cAAc,GAAG,IAAI,KAAK,QAAQ,MAAM,yBAAyB,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG;AACxG,YAAM,oBAAoB;AAAA,QACxB,MAAM;AAAA,QACN,WAAW,kBAAkB;AAAA,QAC7B,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,EAAE,KAAK;AAAA,MAClB,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,UAAQ,GAAG,sBAAsB,CAAC,WAAW;AAC3C,WAAO,MAAM,WAAW,wBAAwB,MAAM,EAAE;AACxD,SAAK,YAAY,sBAAsB,MAAM;AAAA,EAC/C,CAAC;AAGD,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,WAAO,MAAM,WAAW,uBAAuB,IAAI,OAAO;AAAA,EAAK,IAAI,SAAS,EAAE,EAAE;AAChF,SAAK,YAAY,qBAAqB,GAAG;AAEzC,eAAW,MAAM;AACf,cAAQ,KAAK,CAAC;AAAA,IAChB,GAAG,IAAI,EAAE,MAAM;AAAA,EACjB,CAAC;AAID,QAAM,KAAK,oBAAoB;AAC/B,KAAG,SAAS,SAAS,MAAM,QAAQ,QAAQ,GAAG,MAAM,IAAI,QAAc,CAACT,aAAY;AACjF,eAAW,WAAW,CAAC,KAAK,QAAQ,GAAG,UAAU,WAAW,GAAG,KAAK,QAAQ,GAAG,UAAU,cAAc,CAAC,GAAG;AACzG,UAAI;AACF,YAAI,CAAC,GAAG,WAAW,OAAO,EAAG;AAC7B,cAAM,MAAM,SAAS,GAAG,aAAa,SAAS,OAAO,EAAE,KAAK,CAAC;AAC7D,gBAAQ,KAAK,KAAK,SAAS;AAC3B,WAAG,WAAW,OAAO;AACrB,eAAO,KAAK,WAAW,0BAA0B,OAAO,GAAG;AAAA,MAC7D,QAAQ;AAAA,MAAwB;AAAA,IAClC;AACA,IAAAA,SAAQ;AAAA,EACV,CAAC,CAAC;AACF,KAAG,SAAS,aAAa,MAAM,QAAQ,QAAQ,GAAG,MAAM;AAAE,kBAAc;AAAG,WAAO,QAAQ,QAAQ;AAAA,EAAG,CAAC;AACtG,KAAG,SAAS,UAAU,MAAM,QAAQ,QAAQ,GAAG,MAAM;AAAE,eAAW;AAAG,WAAO,QAAQ,QAAQ;AAAA,EAAG,CAAC;AAChG,KAAG,SAAS,eAAe,MAAM,QAAQ,QAAQ,GAAG,MAAM;AAAE,wBAAoB;AAAG,WAAO,QAAQ,QAAQ;AAAA,EAAG,CAAC;AAC9G,KAAG,SAAS,UAAU,MAAM,QAAQ,QAAQ,GAAG,MAAM;AAAE,eAAW;AAAG,WAAO,QAAQ,QAAQ;AAAA,EAAG,CAAC;AAEhG,QAAM,mBAAmB,OAAO,WAAmB;AACjD,WAAO,KAAK,WAAW,YAAY,MAAM,qCAAgC;AACzE,UAAM,GAAG,QAAQ;AACjB,gBAAY;AACZ,eAAW;AACX,QAAI;AAAE,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,sBAAsB;AAAG,mBAAa;AAAA,IAAG,QAAQ;AAAA,IAAe;AAC5G,UAAM,YAAY;AAClB,WAAO,KAAK,WAAW,2BAA2B;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,GAAG,UAAU,MAAM,iBAAiB,QAAQ,CAAC;AACrD,UAAQ,GAAG,WAAW,MAAM,iBAAiB,SAAS,CAAC;AAGvD,MAAI,IAAI,CAAC,KAAY,MAAuB,KAAuB,UAAgC;AACjG,QAAI,eAAe,eAAe,UAAU,KAAK;AAC/C,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,+BAA+B,CAAC;AAC9D;AAAA,IACF;AACA,WAAO,MAAM,WAAW,oBAAoB,IAAI,OAAO,EAAE;AACzD,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAA,EACzD,CAAC;AAED,aAAW,OAAO,MAAM,MAAM,MAAM;AAClC,UAAM,QAAQ,WAAW,UAAU;AACnC,UAAM,UAAU,WAAW,QAAQ;AACnC,WAAO,KAAK,WAAW,wBAAwB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;AACxE,WAAO,KAAK,WAAW,cAAc,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;AAC9D,WAAO,KAAK,WAAW,cAAc,OAAO,MAAM,IAAI,IAAI,IAAI,EAAE;AAChE,WAAO,KAAK,WAAW,QAAQ,KAAK,MAAM,IAAI,IAAI,IAAI,aAAa;AACnE,WAAO,KAAK,WAAW;AAAA,YAAe,MAAM,KAAK,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,EAAE,WAAW,KAAK,EAAE,UAAU,EAAE,YAAY,WAAM,QAAG,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AACxJ,WAAO,KAAK,WAAW,WAAW,UAAU,EAAE,MAAM,SAAS;AAC7D,WAAO,KAAK,WAAW,UAAU,mBAAmB,EAAE,MAAM,aAAa;AAMzE,QAAI;AAEF,WAAK,OAAO,8BAA8B,EAAE,KAAK,CAAC,EAAE,iBAAiB,MAAM;AACzE,cAAM,OAAO,iBAAiB;AAC9B,eAAO,KAAK,WAAW,kBAAkB,KAAK,KAAK,KAAK,KAAK,QAAQ,YAAO,KAAK,MAAM,EAAE;AAAA,MAC3F,CAAC,EAAE,MAAM,MAAM;AAAA,MAAqB,CAAC;AAAA,IACvC,QAAQ;AAAA,IAAqB;AAG7B,QAAI;AACF,YAAM,aAAa,KAAK,QAAQ,GAAG,UAAU,qBAAqB;AAClE,UAAI,GAAG,WAAW,UAAU,GAAG;AAC7B,cAAM,SAAS,KAAK,MAAM,GAAG,aAAa,YAAY,OAAO,CAAC;AAC9D,YAAI,OAAO,mBAAmB,OAAO,oBAAoB,eAAe;AACtE,iBAAO,KAAK,WAAW;AAAA,8BAA0B,aAAa,oBAAoB,OAAO,eAAe,GAAG;AAC3G,iBAAO,KAAK,WAAW,+FAA+F;AACtH,iBAAO,KAAK,WAAW;AAAA,CAA0E;AAAA,QACnG;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAAqB;AAG7B,QAAI,OAAO,QAAQ,SAAS;AAC1B,kBAAY,MAAM,OAAO,MAAM,EAAE,MAAM,CAAC,MAAM;AAC5C,eAAO,MAAM,WAAW,wBAAyB,EAAY,OAAO,EAAE;AAAA,MACxE,CAAC;AAAA,IACH;AAGA,2BAAuB,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACvC,4BAAwB,MAAM,aAAa,EAAE,MAAM;AAAA,EACrD,CAAC;AACH;","names":["resolve","isAllowedOrigin","getRegisteredTools","getDb","getGraphStats","sseWrite","config","host","getMetricsSummary","getLearningStats"]}
|