titan-agent 2026.4.0

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.
Files changed (43) hide show
  1. package/.env.example +21 -0
  2. package/LICENSE +29 -0
  3. package/README.md +305 -0
  4. package/assets/titan-logo.png +0 -0
  5. package/dist/agent/agent.js +1458 -0
  6. package/dist/agent/agent.js.map +1 -0
  7. package/dist/agent/generator.js +1078 -0
  8. package/dist/agent/generator.js.map +1 -0
  9. package/dist/cli/index.js +5064 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/gateway/server.js +4462 -0
  12. package/dist/gateway/server.js.map +1 -0
  13. package/dist/skills/builtin/apply_patch.js +368 -0
  14. package/dist/skills/builtin/apply_patch.js.map +1 -0
  15. package/dist/skills/builtin/auto_generate.js +1129 -0
  16. package/dist/skills/builtin/auto_generate.js.map +1 -0
  17. package/dist/skills/builtin/browser.js +357 -0
  18. package/dist/skills/builtin/browser.js.map +1 -0
  19. package/dist/skills/builtin/cron.js +410 -0
  20. package/dist/skills/builtin/cron.js.map +1 -0
  21. package/dist/skills/builtin/filesystem.js +386 -0
  22. package/dist/skills/builtin/filesystem.js.map +1 -0
  23. package/dist/skills/builtin/memory_skill.js +430 -0
  24. package/dist/skills/builtin/memory_skill.js.map +1 -0
  25. package/dist/skills/builtin/process.js +421 -0
  26. package/dist/skills/builtin/process.js.map +1 -0
  27. package/dist/skills/builtin/sessions.js +1729 -0
  28. package/dist/skills/builtin/sessions.js.map +1 -0
  29. package/dist/skills/builtin/shell.js +327 -0
  30. package/dist/skills/builtin/shell.js.map +1 -0
  31. package/dist/skills/builtin/vision.js +491 -0
  32. package/dist/skills/builtin/vision.js.map +1 -0
  33. package/dist/skills/builtin/voice.js +468 -0
  34. package/dist/skills/builtin/voice.js.map +1 -0
  35. package/dist/skills/builtin/web_fetch.js +331 -0
  36. package/dist/skills/builtin/web_fetch.js.map +1 -0
  37. package/dist/skills/builtin/web_search.js +317 -0
  38. package/dist/skills/builtin/web_search.js.map +1 -0
  39. package/dist/skills/builtin/webhook.js +323 -0
  40. package/dist/skills/builtin/webhook.js.map +1 -0
  41. package/dist/skills/registry.js +3369 -0
  42. package/dist/skills/registry.js.map +1 -0
  43. package/package.json +118 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/constants.ts","../../src/utils/helpers.ts","../../src/config/schema.ts","../../src/utils/logger.ts","../../src/config/config.ts","../../src/security/encryption.ts","../../src/memory/memory.ts","../../src/agent/toolRunner.ts","../../src/skills/builtin/shell.ts","../../src/skills/builtin/filesystem.ts","../../src/skills/builtin/web_search.ts","../../src/skills/builtin/cron.ts","../../src/skills/builtin/webhook.ts","../../src/skills/builtin/memory_skill.ts","../../src/skills/builtin/browser.ts","../../src/agent/session.ts","../../src/providers/base.ts","../../src/providers/anthropic.ts","../../src/providers/openai.ts","../../src/providers/google.ts","../../src/providers/ollama.ts","../../src/providers/router.ts","../../src/memory/learning.ts","../../src/agent/agent.ts","../../src/skills/builtin/sessions.ts","../../src/skills/builtin/process.ts","../../src/skills/builtin/web_fetch.ts","../../src/skills/builtin/apply_patch.ts","../../src/agent/generator.ts","../../src/skills/builtin/auto_generate.ts","../../src/skills/builtin/vision.ts","../../src/skills/builtin/voice.ts","../../src/skills/registry.ts","../../src/gateway/server.ts","../../src/security/sandbox.ts","../../src/channels/base.ts","../../src/channels/webchat.ts","../../src/channels/discord.ts","../../src/channels/telegram.ts","../../src/channels/slack.ts","../../src/channels/googlechat.ts","../../src/agent/multiAgent.ts","../../src/security/shield.ts","../../src/gateway/dashboard.ts"],"sourcesContent":["/**\n * TITAN Constants\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport const TITAN_VERSION = '2026.4.0';\nexport const TITAN_NAME = 'TITAN';\nexport const TITAN_FULL_NAME = 'The Intelligent Task Automation Network';\nexport const TITAN_ASCII_LOGO = `\n╔════════════════════════════════════════════════════╗\n║ ║\n║ ████████╗██╗████████╗ █████╗ ███╗ ██╗ ║\n║ ╚══██╔══╝██║╚══██╔══╝██╔══██╗████╗ ██║ ║\n║ ██║ ██║ ██║ ███████║██╔██╗ ██║ ║\n║ ██║ ██║ ██║ ██╔══██║██║╚██╗██║ ║\n║ ██║ ██║ ██║ ██║ ██║██║ ╚████║ ║\n║ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ║\n║ ║\n║ The Intelligent Task Automation Network ║\n║ v${TITAN_VERSION} ║\n╚════════════════════════════════════════════════════╝`;\n\n// Paths\nexport const TITAN_HOME = join(homedir(), '.titan');\nexport const TITAN_CONFIG_PATH = join(TITAN_HOME, 'titan.json');\nexport const TITAN_DB_PATH = join(TITAN_HOME, 'titan.db');\nexport const TITAN_WORKSPACE = join(TITAN_HOME, 'workspace');\nexport const TITAN_SKILLS_DIR = join(TITAN_WORKSPACE, 'skills');\nexport const TITAN_LOGS_DIR = join(TITAN_HOME, 'logs');\nexport const TITAN_MEMORY_DIR = join(TITAN_HOME, 'memory');\n\n// Workspace prompt files (injected into agent context)\nexport const AGENTS_MD = join(TITAN_WORKSPACE, 'AGENTS.md');\nexport const SOUL_MD = join(TITAN_WORKSPACE, 'SOUL.md');\nexport const TOOLS_MD = join(TITAN_WORKSPACE, 'TOOLS.md');\n\n// Gateway defaults\nexport const DEFAULT_GATEWAY_HOST = '127.0.0.1';\nexport const DEFAULT_GATEWAY_PORT = 18789;\nexport const DEFAULT_WEB_PORT = 18790;\n\n// Agent defaults\nexport const DEFAULT_MODEL = 'anthropic/claude-sonnet-4-20250514';\nexport const DEFAULT_MAX_TOKENS = 8192;\nexport const DEFAULT_TEMPERATURE = 0.7;\nexport const MAX_CONTEXT_MESSAGES = 50;\nexport const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n\n// Security\nexport const DEFAULT_SANDBOX_MODE = 'host';\nexport const ALLOWED_TOOLS_DEFAULT = [\n 'shell', 'read_file', 'write_file', 'edit_file', 'list_dir',\n 'web_search', 'browser', 'cron', 'webhook', 'email', 'memory',\n];\nexport const DENIED_TOOLS_DEFAULT: string[] = [];\n","/**\n * TITAN Helper Utilities\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname } from 'path';\n\n/** Ensure a directory exists, creating it recursively if needed */\nexport function ensureDir(dirPath: string): void {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n}\n\n/** Safely read a JSON file, returning null on failure */\nexport function readJsonFile<T = unknown>(filePath: string): T | null {\n try {\n if (!existsSync(filePath)) return null;\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n/** Safely write a JSON file, creating parent dirs if needed */\nexport function writeJsonFile(filePath: string, data: unknown): void {\n ensureDir(dirname(filePath));\n writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n/** Safe string truncation */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - 3) + '...';\n}\n\n/** Sleep for a given number of milliseconds */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Generate a short ID */\nexport function shortId(): string {\n return Math.random().toString(36).slice(2, 10);\n}\n\n/** Format bytes into human-readable string */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n}\n\n/** Format a duration in ms to human-readable */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n if (ms < 3600000) return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;\n return `${Math.floor(ms / 3600000)}h ${Math.floor((ms % 3600000) / 60000)}m`;\n}\n\n/** Deep merge two objects */\nexport function deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n for (const key of Object.keys(source) as Array<keyof T>) {\n const sourceVal = source[key];\n const targetVal = result[key];\n if (\n sourceVal &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n ) as T[keyof T];\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal as T[keyof T];\n }\n }\n return result;\n}\n","/**\n * TITAN Configuration Schema — Zod-based validation with full type inference\n */\nimport { z } from 'zod';\nimport {\n DEFAULT_GATEWAY_HOST,\n DEFAULT_GATEWAY_PORT,\n DEFAULT_WEB_PORT,\n DEFAULT_MODEL,\n DEFAULT_MAX_TOKENS,\n DEFAULT_TEMPERATURE,\n DEFAULT_SANDBOX_MODE,\n ALLOWED_TOOLS_DEFAULT,\n} from '../utils/constants.js';\n\nexport const ProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n baseUrl: z.string().optional(),\n model: z.string().optional(),\n maxTokens: z.number().optional(),\n temperature: z.number().min(0).max(2).optional(),\n});\n\nexport const ChannelConfigSchema = z.object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n apiKey: z.string().optional(),\n allowFrom: z.array(z.string()).default([]),\n dmPolicy: z.enum(['pairing', 'open', 'closed']).default('pairing'),\n});\n\nexport const SecurityConfigSchema = z.object({\n sandboxMode: z.enum(['host', 'docker', 'none']).default(DEFAULT_SANDBOX_MODE as 'host'),\n allowedTools: z.array(z.string()).default(ALLOWED_TOOLS_DEFAULT),\n deniedTools: z.array(z.string()).default([]),\n maxConcurrentTasks: z.number().default(5),\n commandTimeout: z.number().default(30000),\n fileSystemAllowlist: z.array(z.string()).default([]),\n networkAllowlist: z.array(z.string()).default(['*']),\n shield: z.object({\n enabled: z.boolean().default(true),\n mode: z.enum(['standard', 'strict']).default('strict'),\n }).default({}),\n});\n\nexport const GatewayConfigSchema = z.object({\n host: z.string().default(DEFAULT_GATEWAY_HOST),\n port: z.number().default(DEFAULT_GATEWAY_PORT),\n webPort: z.number().default(DEFAULT_WEB_PORT),\n auth: z.object({\n mode: z.enum(['none', 'token', 'password']).default('token'),\n token: z.string().optional(),\n password: z.string().optional(),\n }).default({}),\n});\n\nexport const AgentConfigSchema = z.object({\n model: z.string().default(DEFAULT_MODEL),\n maxTokens: z.number().default(DEFAULT_MAX_TOKENS),\n temperature: z.number().default(DEFAULT_TEMPERATURE),\n systemPrompt: z.string().optional(),\n workspace: z.string().optional(),\n thinkingMode: z.enum(['off', 'low', 'medium', 'high']).default('medium'),\n});\n\nexport const TitanConfigSchema = z.object({\n agent: AgentConfigSchema.default({}),\n providers: z.object({\n anthropic: ProviderConfigSchema.default({}),\n openai: ProviderConfigSchema.default({}),\n google: ProviderConfigSchema.default({}),\n ollama: ProviderConfigSchema.default({}),\n }).default({}),\n channels: z.object({\n discord: ChannelConfigSchema.default({}),\n telegram: ChannelConfigSchema.default({}),\n slack: ChannelConfigSchema.default({}),\n whatsapp: ChannelConfigSchema.default({}),\n webchat: ChannelConfigSchema.default({}),\n googlechat: ChannelConfigSchema.default({}),\n matrix: ChannelConfigSchema.default({}),\n signal: ChannelConfigSchema.default({}),\n msteams: ChannelConfigSchema.default({}),\n bluebubbles: ChannelConfigSchema.default({}),\n }).default({}),\n gateway: GatewayConfigSchema.default({}),\n security: SecurityConfigSchema.default({}),\n memory: z.object({\n enabled: z.boolean().default(true),\n maxHistoryMessages: z.number().default(50),\n vectorSearchEnabled: z.boolean().default(false),\n }).default({}),\n skills: z.object({\n enabled: z.boolean().default(true),\n autoDiscover: z.boolean().default(true),\n marketplace: z.boolean().default(false),\n }).default({}),\n logging: z.object({\n level: z.enum(['debug', 'info', 'warn', 'error', 'silent']).default('info'),\n file: z.boolean().default(true),\n }).default({}),\n autonomy: z.object({\n /** autonomous = full auto, supervised = asks for dangerous ops, locked = asks for everything */\n mode: z.enum(['autonomous', 'supervised', 'locked']).default('supervised'),\n /** Auto-approve moderate-risk tools in main session (cli/webchat) */\n autoApproveMainSession: z.boolean().default(true),\n /** Timeout for HITL approval requests (ms). Auto-deny after timeout. */\n approvalTimeoutMs: z.number().default(60000),\n /** Notify user of auto-approved actions */\n notifyOnAutoApprove: z.boolean().default(true),\n }).default({}),\n});\n\nexport type TitanConfig = z.infer<typeof TitanConfigSchema>;\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\nexport type ChannelConfig = z.infer<typeof ChannelConfigSchema>;\nexport type SecurityConfig = z.infer<typeof SecurityConfigSchema>;\nexport type GatewayConfig = z.infer<typeof GatewayConfigSchema>;\nexport type AgentConfig = z.infer<typeof AgentConfigSchema>;\n","/**\n * TITAN Logger — Structured logging with levels and colors\n */\nimport chalk from 'chalk';\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n SILENT = 4,\n}\n\nconst LEVEL_LABELS: Record<LogLevel, string> = {\n [LogLevel.DEBUG]: chalk.gray('DEBUG'),\n [LogLevel.INFO]: chalk.cyan('INFO '),\n [LogLevel.WARN]: chalk.yellow('WARN '),\n [LogLevel.ERROR]: chalk.red('ERROR'),\n [LogLevel.SILENT]: '',\n};\n\nlet currentLevel: LogLevel = LogLevel.INFO;\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport function getLogLevel(): LogLevel {\n return currentLevel;\n}\n\nfunction formatTimestamp(): string {\n return chalk.gray(new Date().toISOString().replace('T', ' ').slice(0, 19));\n}\n\nfunction log(level: LogLevel, component: string, message: string, ...args: unknown[]): void {\n if (level < currentLevel) return;\n const prefix = `${formatTimestamp()} ${LEVEL_LABELS[level]} ${chalk.blue(`[${component}]`)}`;\n console.log(`${prefix} ${message}`, ...args);\n}\n\nexport const logger = {\n debug: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.DEBUG, component, msg, ...args),\n info: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.INFO, component, msg, ...args),\n warn: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.WARN, component, msg, ...args),\n error: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.ERROR, component, msg, ...args),\n};\n\nexport default logger;\n","/**\n * TITAN Configuration Manager\n * Loads, validates, and persists configuration from ~/.titan/titan.json\n */\nimport { existsSync } from 'fs';\nimport { TITAN_CONFIG_PATH, TITAN_HOME } from '../utils/constants.js';\nimport { readJsonFile, writeJsonFile, ensureDir, deepMerge } from '../utils/helpers.js';\nimport { TitanConfigSchema, type TitanConfig } from './schema.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Config';\n\nlet cachedConfig: TitanConfig | null = null;\n\n/** Get the default configuration */\nexport function getDefaultConfig(): TitanConfig {\n return TitanConfigSchema.parse({});\n}\n\n/** Load configuration from disk, merging with defaults */\nexport function loadConfig(): TitanConfig {\n if (cachedConfig) return cachedConfig;\n\n ensureDir(TITAN_HOME);\n\n let rawConfig: Record<string, unknown> = {};\n\n if (existsSync(TITAN_CONFIG_PATH)) {\n const loaded = readJsonFile<Record<string, unknown>>(TITAN_CONFIG_PATH);\n if (loaded) {\n rawConfig = loaded;\n logger.debug(COMPONENT, `Loaded config from ${TITAN_CONFIG_PATH}`);\n } else {\n logger.warn(COMPONENT, `Failed to parse config at ${TITAN_CONFIG_PATH}, using defaults`);\n }\n } else {\n logger.info(COMPONENT, 'No config file found, using defaults');\n }\n\n // Apply environment variables\n applyEnvOverrides(rawConfig);\n\n // Validate and merge with defaults via Zod\n const result = TitanConfigSchema.safeParse(rawConfig);\n if (!result.success) {\n logger.warn(COMPONENT, 'Config validation issues, using defaults for invalid fields');\n logger.debug(COMPONENT, result.error.message);\n cachedConfig = getDefaultConfig();\n } else {\n cachedConfig = result.data;\n }\n\n return cachedConfig;\n}\n\n/** Save current configuration to disk */\nexport function saveConfig(config: TitanConfig): void {\n ensureDir(TITAN_HOME);\n writeJsonFile(TITAN_CONFIG_PATH, config);\n cachedConfig = config;\n logger.info(COMPONENT, `Config saved to ${TITAN_CONFIG_PATH}`);\n}\n\n/** Update specific fields in the config */\nexport function updateConfig(partial: Partial<TitanConfig>): TitanConfig {\n const current = loadConfig();\n const updated = deepMerge(current as Record<string, unknown>, partial as Record<string, unknown>) as TitanConfig;\n const validated = TitanConfigSchema.parse(updated);\n saveConfig(validated);\n return validated;\n}\n\n/** Reset config cache (useful for testing) */\nexport function resetConfigCache(): void {\n cachedConfig = null;\n}\n\n/** Check if the configuration file exists */\nexport function configExists(): boolean {\n return existsSync(TITAN_CONFIG_PATH);\n}\n\n/** Apply environment variable overrides to raw config */\nfunction applyEnvOverrides(config: Record<string, unknown>): void {\n const envMap: Record<string, (val: string) => void> = {\n TITAN_MODEL: (val) => setNested(config, 'agent.model', val),\n TITAN_GATEWAY_PORT: (val) => setNested(config, 'gateway.port', parseInt(val, 10)),\n TITAN_GATEWAY_HOST: (val) => setNested(config, 'gateway.host', val),\n TITAN_LOG_LEVEL: (val) => setNested(config, 'logging.level', val),\n ANTHROPIC_API_KEY: (val) => setNested(config, 'providers.anthropic.apiKey', val),\n OPENAI_API_KEY: (val) => setNested(config, 'providers.openai.apiKey', val),\n GOOGLE_API_KEY: (val) => setNested(config, 'providers.google.apiKey', val),\n OLLAMA_BASE_URL: (val) => setNested(config, 'providers.ollama.baseUrl', val),\n DISCORD_TOKEN: (val) => setNested(config, 'channels.discord.token', val),\n TELEGRAM_TOKEN: (val) => setNested(config, 'channels.telegram.token', val),\n SLACK_TOKEN: (val) => setNested(config, 'channels.slack.token', val),\n };\n\n for (const [envKey, setter] of Object.entries(envMap)) {\n const val = process.env[envKey];\n if (val) {\n setter(val);\n logger.debug(COMPONENT, `Applied env override: ${envKey}`);\n }\n }\n}\n\n/** Set a nested property by dot-notation path */\nfunction setNested(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let current: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]] || typeof current[parts[i]] !== 'object') {\n current[parts[i]] = {};\n }\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = value;\n}\n","/**\n * TITAN — Encryption Module\n * Provides E2E encryption for sensitive sessions using AES-256-GCM.\n */\nimport { randomBytes, createCipheriv, createDecipheriv } from 'crypto';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Encryption';\nconst ALGORITHM = 'aes-256-gcm';\n\nexport interface EncryptedPayload {\n iv: string;\n authTag: string;\n data: string;\n}\n\n/**\n * Generates a strong 256-bit encryption key securely.\n */\nexport function generateKey(): Buffer {\n return randomBytes(32);\n}\n\n/**\n * Encrypts a string of text using AES-256-GCM.\n * @param text The plaintext to encrypt\n * @param key The 32-byte encryption key\n */\nexport function encrypt(text: string, key: Buffer | string): EncryptedPayload {\n try {\n const keyBuffer = typeof key === 'string' ? Buffer.from(key, 'hex') : key;\n if (keyBuffer.length !== 32) {\n throw new Error('Encryption key must be exactly 32 bytes (256 bits).');\n }\n\n const iv = randomBytes(16);\n const cipher = createCipheriv(ALGORITHM, keyBuffer, iv);\n\n let encrypted = cipher.update(text, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag().toString('hex');\n\n return {\n iv: iv.toString('hex'),\n authTag,\n data: encrypted\n };\n } catch (e: any) {\n logger.error(COMPONENT, `Encryption failed: ${e.message}`);\n throw new Error('Failed to encrypt session data.');\n }\n}\n\n/**\n * Decrypts an EncryptedPayload back into plaintext text using AES-256-GCM.\n * @param payload The encrypted payload object (iv, authTag, data)\n * @param key The 32-byte encryption key\n */\nexport function decrypt(payload: EncryptedPayload, key: Buffer | string): string {\n try {\n const keyBuffer = typeof key === 'string' ? Buffer.from(key, 'hex') : key;\n if (keyBuffer.length !== 32) {\n throw new Error('Decryption key must be exactly 32 bytes (256 bits).');\n }\n\n const decipher = createDecipheriv(ALGORITHM, keyBuffer, Buffer.from(payload.iv, 'hex'));\n decipher.setAuthTag(Buffer.from(payload.authTag, 'hex'));\n\n let decrypted = decipher.update(payload.data, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n } catch (e: any) {\n logger.error(COMPONENT, `Decryption failed: ${e.message}`);\n throw new Error('Failed to decrypt session data. Invalid key or corrupted payload.');\n }\n}\n","/**\n * TITAN — Memory / Persistence System\n * JSON-file-backed persistent memory for conversations, facts, preferences, and usage.\n * Uses no native dependencies — pure Node.js for maximum portability.\n */\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { TITAN_DB_PATH, TITAN_HOME } from '../utils/constants.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport logger from '../utils/logger.js';\nimport { encrypt, decrypt, type EncryptedPayload } from '../security/encryption.js';\n\nconst COMPONENT = 'Memory';\n\n// ─── Data Store ──────────────────────────────────────────────────\n\ninterface DataStore {\n conversations: ConversationMessage[];\n memories: MemoryEntry[];\n sessions: SessionRecord[];\n usageStats: UsageRecord[];\n cronJobs: CronRecord[];\n skillsInstalled: SkillRecord[];\n}\n\ninterface MemoryEntry {\n id: string;\n category: string;\n key: string;\n value: string;\n metadata?: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface SessionRecord {\n id: string;\n channel: string;\n user_id: string;\n agent_id: string;\n status: string;\n message_count: number;\n created_at: string;\n last_active: string;\n}\n\ninterface UsageRecord {\n id: number;\n session_id: string;\n provider: string;\n model: string;\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n created_at: string;\n}\n\ninterface CronRecord {\n id: string;\n name: string;\n schedule: string;\n command: string;\n enabled: boolean;\n last_run?: string;\n next_run?: string;\n created_at: string;\n}\n\ninterface SkillRecord {\n name: string;\n version: string;\n source: string;\n enabled: boolean;\n installed_at: string;\n}\n\nconst DB_FILE = join(TITAN_HOME, 'titan-data.json');\n\nlet store: DataStore | null = null;\n\nfunction getDefaultStore(): DataStore {\n return {\n conversations: [],\n memories: [],\n sessions: [],\n usageStats: [],\n cronJobs: [],\n skillsInstalled: [],\n };\n}\n\nfunction loadStore(): DataStore {\n if (store) return store;\n ensureDir(TITAN_HOME);\n if (existsSync(DB_FILE)) {\n try {\n const raw = readFileSync(DB_FILE, 'utf-8');\n store = JSON.parse(raw) as DataStore;\n // Ensure all fields exist\n store.conversations = store.conversations || [];\n store.memories = store.memories || [];\n store.sessions = store.sessions || [];\n store.usageStats = store.usageStats || [];\n store.cronJobs = store.cronJobs || [];\n store.skillsInstalled = store.skillsInstalled || [];\n } catch {\n logger.warn(COMPONENT, 'Could not load data store, creating fresh one');\n store = getDefaultStore();\n }\n } else {\n store = getDefaultStore();\n }\n return store;\n}\n\nfunction saveStore(): void {\n if (!store) return;\n ensureDir(TITAN_HOME);\n try {\n writeFileSync(DB_FILE, JSON.stringify(store, null, 2), 'utf-8');\n } catch (e) {\n logger.error(COMPONENT, `Failed to save data: ${(e as Error).message}`);\n }\n}\n\n// Auto-save periodically\nlet saveTimeout: ReturnType<typeof setTimeout> | null = null;\nfunction debouncedSave(): void {\n if (saveTimeout) clearTimeout(saveTimeout);\n saveTimeout = setTimeout(saveStore, 1000);\n}\n\n/** Initialize the memory system */\nexport function initMemory(): void {\n loadStore();\n logger.info(COMPONENT, 'Memory system initialized');\n}\n\n/** Close / flush the memory system */\nexport function closeMemory(): void {\n saveStore();\n store = null;\n}\n\n/** Get internal store (for skills like cron that need direct access) */\nexport function getDb(): DataStore {\n return loadStore();\n}\n\n// ─── Conversation History ────────────────────────────────────────\n\nexport interface ConversationMessage {\n id: string;\n sessionId: string;\n role: string;\n content: string;\n toolCalls?: string;\n toolCallId?: string;\n model?: string;\n tokenCount: number;\n createdAt: string;\n isEncrypted?: boolean;\n}\n\n/** Save a message to conversation history */\nexport function saveMessage(message: Omit<ConversationMessage, 'createdAt'>, e2eKey?: string): void {\n const s = loadStore();\n\n let content = message.content;\n let isEncrypted = false;\n\n if (e2eKey) {\n try {\n const payload = encrypt(message.content, Buffer.from(e2eKey, 'base64'));\n content = JSON.stringify(payload);\n isEncrypted = true;\n } catch (e) {\n logger.error(COMPONENT, `Failed to encrypt message for storage`);\n content = \"[ENCRYPTION FAILED] \" + content; // Fallback, though we should probably throw in strict environments\n }\n }\n\n s.conversations.push({\n ...message,\n content,\n isEncrypted,\n createdAt: new Date().toISOString(),\n });\n // Keep only last 5000 messages total to prevent unbounded growth\n if (s.conversations.length > 5000) {\n s.conversations = s.conversations.slice(-5000);\n }\n debouncedSave();\n}\n\n/** Get conversation history for a session */\nexport function getHistory(sessionId: string, limit: number = 50, e2eKey?: string): ConversationMessage[] {\n const s = loadStore();\n const rawHistory = s.conversations\n .filter((m) => m.sessionId === sessionId)\n .slice(-limit);\n\n if (!e2eKey) {\n // If no key is provided, we just return the raw payload. \n // If it's encrypted, it'll just show the JSON string of the EncryptedPayload.\n return rawHistory;\n }\n\n // Decrypt the ones that were encrypted\n return rawHistory.map(m => {\n if (m.isEncrypted) {\n try {\n const payload = JSON.parse(m.content) as EncryptedPayload;\n return {\n ...m,\n content: decrypt(payload, Buffer.from(e2eKey, 'base64'))\n };\n } catch (e) {\n logger.error(COMPONENT, `Failed to decrypt message ${m.id}`);\n return { ...m, content: \"[DECRYPTION FAILED]\" };\n }\n }\n return m;\n });\n}\n\n/** Clear conversation history for a session */\nexport function clearHistory(sessionId: string): void {\n const s = loadStore();\n s.conversations = s.conversations.filter((m) => m.sessionId !== sessionId);\n debouncedSave();\n}\n\n// ─── Persistent Memory (Facts / Preferences) ─────────────────────\n\n/** Store a memory (key-value with category) */\nexport function rememberFact(category: string, key: string, value: string, metadata?: Record<string, unknown>): void {\n const s = loadStore();\n const id = `${category}:${key}`;\n const existingIdx = s.memories.findIndex((m) => m.id === id);\n const now = new Date().toISOString();\n\n if (existingIdx >= 0) {\n s.memories[existingIdx].value = value;\n s.memories[existingIdx].metadata = metadata ? JSON.stringify(metadata) : undefined;\n s.memories[existingIdx].updatedAt = now;\n } else {\n s.memories.push({\n id,\n category,\n key,\n value,\n metadata: metadata ? JSON.stringify(metadata) : undefined,\n createdAt: now,\n updatedAt: now,\n });\n }\n debouncedSave();\n}\n\n/** Recall a specific memory */\nexport function recallFact(category: string, key: string): string | null {\n const s = loadStore();\n const entry = s.memories.find((m) => m.category === category && m.key === key);\n return entry?.value || null;\n}\n\n/** Search memories by category */\nexport function searchMemories(category?: string, query?: string): Array<{ key: string; value: string; category: string }> {\n const s = loadStore();\n let results = s.memories;\n\n if (category) {\n results = results.filter((m) => m.category === category);\n }\n if (query) {\n const q = query.toLowerCase();\n results = results.filter((m) =>\n m.key.toLowerCase().includes(q) || m.value.toLowerCase().includes(q)\n );\n }\n\n return results.slice(-50).map((m) => ({ key: m.key, value: m.value, category: m.category }));\n}\n\n// ─── Usage Tracking ──────────────────────────────────────────────\n\n/** Record usage statistics */\nexport function recordUsage(sessionId: string, provider: string, model: string, promptTokens: number, completionTokens: number): void {\n const s = loadStore();\n s.usageStats.push({\n id: s.usageStats.length + 1,\n session_id: sessionId,\n provider,\n model,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n total_tokens: promptTokens + completionTokens,\n created_at: new Date().toISOString(),\n });\n // Keep only last 10000 records\n if (s.usageStats.length > 10000) {\n s.usageStats = s.usageStats.slice(-10000);\n }\n debouncedSave();\n}\n\n/** Get total usage statistics */\nexport function getUsageStats(): { totalTokens: number; totalRequests: number; byProvider: Record<string, number> } {\n const s = loadStore();\n let totalTokens = 0;\n const byProvider: Record<string, number> = {};\n\n for (const rec of s.usageStats) {\n totalTokens += rec.total_tokens;\n byProvider[rec.provider] = (byProvider[rec.provider] || 0) + rec.total_tokens;\n }\n\n return {\n totalTokens,\n totalRequests: s.usageStats.length,\n byProvider,\n };\n}\n","/**\n * TITAN — Tool Runner\n * Executes tool calls from the LLM with sandboxing, timeouts, and result formatting.\n */\nimport type { ToolCall, ToolDefinition } from '../providers/base.js';\nimport logger from '../utils/logger.js';\nimport { loadConfig } from '../config/config.js';\n\nconst COMPONENT = 'ToolRunner';\n\n/** Tool execution result */\nexport interface ToolResult {\n toolCallId: string;\n name: string;\n content: string;\n success: boolean;\n durationMs: number;\n}\n\n/** A registered tool handler */\nexport interface ToolHandler {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n execute: (args: Record<string, unknown>) => Promise<string>;\n}\n\n/** Global tool registry */\nconst toolRegistry: Map<string, ToolHandler> = new Map();\n\n/** Register a tool */\nexport function registerTool(handler: ToolHandler): void {\n toolRegistry.set(handler.name, handler);\n logger.debug(COMPONENT, `Registered tool: ${handler.name}`);\n}\n\n/** Unregister a tool */\nexport function unregisterTool(name: string): void {\n toolRegistry.delete(name);\n}\n\n/** Get all registered tools */\nexport function getRegisteredTools(): ToolHandler[] {\n return Array.from(toolRegistry.values());\n}\n\n/** Convert registered tools to LLM tool definitions */\nexport function getToolDefinitions(): ToolDefinition[] {\n const config = loadConfig();\n const allowed = new Set(config.security.allowedTools);\n const denied = new Set(config.security.deniedTools);\n\n return Array.from(toolRegistry.values())\n .filter((tool) => {\n if (denied.has(tool.name)) return false;\n if (allowed.size > 0 && !allowed.has(tool.name)) return false;\n return true;\n })\n .map((tool) => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n },\n }));\n}\n\n/** Execute a single tool call */\nexport async function executeTool(toolCall: ToolCall): Promise<ToolResult> {\n const config = loadConfig();\n const startTime = Date.now();\n const handler = toolRegistry.get(toolCall.function.name);\n\n if (!handler) {\n return {\n toolCallId: toolCall.id,\n name: toolCall.function.name,\n content: `Error: Unknown tool \"${toolCall.function.name}\"`,\n success: false,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Check permissions\n if (config.security.deniedTools.includes(handler.name)) {\n return {\n toolCallId: toolCall.id,\n name: handler.name,\n content: `Error: Tool \"${handler.name}\" is denied by security policy`,\n success: false,\n durationMs: Date.now() - startTime,\n };\n }\n\n try {\n // Parse arguments\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(toolCall.function.arguments);\n } catch {\n args = {};\n }\n\n logger.info(COMPONENT, `Executing tool: ${handler.name}`);\n\n // Execute with timeout\n const timeout = config.security.commandTimeout || 30000;\n const result = await Promise.race([\n handler.execute(args),\n new Promise<string>((_, reject) =>\n setTimeout(() => reject(new Error(`Tool \"${handler.name}\" timed out after ${timeout}ms`)), timeout)\n ),\n ]);\n\n const durationMs = Date.now() - startTime;\n logger.info(COMPONENT, `Tool ${handler.name} completed in ${durationMs}ms`);\n\n return {\n toolCallId: toolCall.id,\n name: handler.name,\n content: result,\n success: true,\n durationMs,\n };\n } catch (error) {\n const durationMs = Date.now() - startTime;\n const errorMsg = (error as Error).message;\n logger.error(COMPONENT, `Tool ${handler.name} failed: ${errorMsg}`);\n\n return {\n toolCallId: toolCall.id,\n name: handler.name,\n content: `Error: ${errorMsg}`,\n success: false,\n durationMs,\n };\n }\n}\n\n/** Execute multiple tool calls (in parallel where possible) */\nexport async function executeTools(toolCalls: ToolCall[]): Promise<ToolResult[]> {\n const config = loadConfig();\n const maxConcurrent = config.security.maxConcurrentTasks || 5;\n\n // Execute in batches\n const results: ToolResult[] = [];\n for (let i = 0; i < toolCalls.length; i += maxConcurrent) {\n const batch = toolCalls.slice(i, i + maxConcurrent);\n const batchResults = await Promise.all(batch.map(executeTool));\n results.push(...batchResults);\n }\n\n return results;\n}\n","/**\n * TITAN — Shell Skill (Built-in)\n * Execute shell commands with sandboxing and output capture.\n */\nimport { exec } from 'child_process';\nimport { registerSkill } from '../registry.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Shell';\n\n/** Execute a shell command and return output */\nfunction executeCommand(command: string, cwd?: string, timeout: number = 30000): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = exec(command, {\n cwd: cwd || process.cwd(),\n timeout,\n maxBuffer: 1024 * 1024 * 10, // 10MB\n shell: '/bin/bash',\n }, (error, stdout, stderr) => {\n if (error && error.killed) {\n reject(new Error(`Command timed out after ${timeout}ms`));\n return;\n }\n\n let output = '';\n if (stdout) output += stdout;\n if (stderr) output += (output ? '\\n' : '') + `[stderr] ${stderr}`;\n if (error) output += (output ? '\\n' : '') + `[exit code: ${error.code}]`;\n\n // Truncate very long output\n if (output.length > 50000) {\n output = output.slice(0, 25000) + '\\n\\n... [output truncated] ...\\n\\n' + output.slice(-25000);\n }\n\n resolve(output || '(no output)');\n });\n });\n}\n\nexport function registerShellSkill(): void {\n registerSkill(\n {\n name: 'shell',\n description: 'Execute shell commands on the system',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'shell',\n description: 'Execute a shell command on the user\\'s system. Use this for running scripts, installing packages, checking system status, compiling code, git operations, and any other command-line task.',\n parameters: {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'The shell command to execute',\n },\n cwd: {\n type: 'string',\n description: 'Working directory for the command (optional)',\n },\n timeout: {\n type: 'number',\n description: 'Timeout in milliseconds (default: 30000)',\n },\n },\n required: ['command'],\n },\n execute: async (args) => {\n const command = args.command as string;\n const cwd = args.cwd as string | undefined;\n const timeout = (args.timeout as number) || 30000;\n\n logger.info(COMPONENT, `Executing: ${command}`);\n return await executeCommand(command, cwd, timeout);\n },\n },\n );\n}\n","/**\n * TITAN — Filesystem Skill (Built-in)\n * Read, write, edit, and list files and directories.\n */\nimport { readFileSync, writeFileSync, existsSync, readdirSync, statSync, unlinkSync, mkdirSync } from 'fs';\nimport { join, resolve, basename } from 'path';\nimport { registerSkill } from '../registry.js';\n\nexport function registerFilesystemSkill(): void {\n // Read File\n registerSkill(\n { name: 'read_file', description: 'Read file contents', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'read_file',\n description: 'Read the contents of a file. Returns the text content of the file.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Absolute or relative path to the file' },\n startLine: { type: 'number', description: 'Start line (1-indexed, optional)' },\n endLine: { type: 'number', description: 'End line (1-indexed, optional)' },\n },\n required: ['path'],\n },\n execute: async (args) => {\n const filePath = resolve(args.path as string);\n if (!existsSync(filePath)) return `Error: File not found: ${filePath}`;\n try {\n const content = readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n const start = (args.startLine as number) || 1;\n const end = (args.endLine as number) || lines.length;\n const selected = lines.slice(start - 1, end);\n return `File: ${filePath} (${lines.length} lines)\\n---\\n${selected.map((l, i) => `${start + i}: ${l}`).join('\\n')}`;\n } catch (e) { return `Error reading file: ${(e as Error).message}`; }\n },\n },\n );\n\n // Write File\n registerSkill(\n { name: 'write_file', description: 'Write/create a file', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'write_file',\n description: 'Write content to a file. Creates the file and parent directories if they don\\'t exist. Overwrites existing content.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Path to the file' },\n content: { type: 'string', description: 'Content to write' },\n },\n required: ['path', 'content'],\n },\n execute: async (args) => {\n const filePath = resolve(args.path as string);\n try {\n const dir = join(filePath, '..');\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(filePath, args.content as string, 'utf-8');\n return `Successfully wrote ${(args.content as string).length} bytes to ${filePath}`;\n } catch (e) { return `Error writing file: ${(e as Error).message}`; }\n },\n },\n );\n\n // Edit File\n registerSkill(\n { name: 'edit_file', description: 'Search and replace in a file', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'edit_file',\n description: 'Edit a file by replacing a target string with new content.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Path to the file' },\n target: { type: 'string', description: 'Exact string to find and replace' },\n replacement: { type: 'string', description: 'Replacement content' },\n },\n required: ['path', 'target', 'replacement'],\n },\n execute: async (args) => {\n const filePath = resolve(args.path as string);\n if (!existsSync(filePath)) return `Error: File not found: ${filePath}`;\n try {\n let content = readFileSync(filePath, 'utf-8');\n const target = args.target as string;\n if (!content.includes(target)) return `Error: Target string not found in ${filePath}`;\n content = content.replace(target, args.replacement as string);\n writeFileSync(filePath, content, 'utf-8');\n return `Successfully edited ${filePath}`;\n } catch (e) { return `Error editing file: ${(e as Error).message}`; }\n },\n },\n );\n\n // List Directory\n registerSkill(\n { name: 'list_dir', description: 'List directory contents', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'list_dir',\n description: 'List the contents of a directory, showing files and subdirectories with sizes.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Path to the directory' },\n recursive: { type: 'boolean', description: 'List recursively (default: false)' },\n },\n required: ['path'],\n },\n execute: async (args) => {\n const dirPath = resolve(args.path as string);\n if (!existsSync(dirPath)) return `Error: Directory not found: ${dirPath}`;\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true });\n const lines = entries.map((entry) => {\n const fullPath = join(dirPath, entry.name);\n if (entry.isDirectory()) {\n return `📁 ${entry.name}/`;\n }\n const stat = statSync(fullPath);\n const size = stat.size < 1024 ? `${stat.size}B` : stat.size < 1048576 ? `${(stat.size / 1024).toFixed(1)}KB` : `${(stat.size / 1048576).toFixed(1)}MB`;\n return `📄 ${entry.name} (${size})`;\n });\n return `Directory: ${dirPath}\\n${lines.join('\\n')}`;\n } catch (e) { return `Error listing directory: ${(e as Error).message}`; }\n },\n },\n );\n}\n","/**\n * TITAN — Web Search Skill (Built-in)\n * Search the web and retrieve information.\n */\nimport { registerSkill } from '../registry.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'WebSearch';\n\nexport function registerWebSearchSkill(): void {\n registerSkill(\n { name: 'web_search', description: 'Search the web', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'web_search',\n description: 'Search the web for information. Returns search results with titles, URLs, and snippets. Useful for finding current information, documentation, tutorials, etc.',\n parameters: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'The search query' },\n maxResults: { type: 'number', description: 'Maximum results to return (default: 5)' },\n },\n required: ['query'],\n },\n execute: async (args) => {\n const query = args.query as string;\n const maxResults = (args.maxResults as number) || 5;\n logger.info(COMPONENT, `Searching: ${query}`);\n\n try {\n // Use DuckDuckGo HTML search as a fallback (no API key required)\n const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;\n const response = await fetch(url, {\n headers: {\n 'User-Agent': 'TITAN/1.0 (Autonomous AI Agent)',\n },\n });\n\n if (!response.ok) {\n return `Search failed with status ${response.status}`;\n }\n\n const html = await response.text();\n\n // Parse results from DuckDuckGo HTML\n const results: Array<{ title: string; url: string; snippet: string }> = [];\n const resultRegex = /<a[^>]*class=\"result__a\"[^>]*href=\"([^\"]*)\"[^>]*>(.*?)<\\/a>[\\s\\S]*?<a[^>]*class=\"result__snippet\"[^>]*>(.*?)<\\/a>/gi;\n let match;\n\n while ((match = resultRegex.exec(html)) !== null && results.length < maxResults) {\n const rawUrl = match[1];\n const title = match[2].replace(/<[^>]*>/g, '').trim();\n const snippet = match[3].replace(/<[^>]*>/g, '').trim();\n\n // Decode DuckDuckGo redirect URL\n const urlMatch = rawUrl.match(/uddg=([^&]*)/);\n const decodedUrl = urlMatch ? decodeURIComponent(urlMatch[1]) : rawUrl;\n\n if (title && decodedUrl) {\n results.push({ title, url: decodedUrl, snippet });\n }\n }\n\n if (results.length === 0) {\n return `No results found for: \"${query}\"`;\n }\n\n return results\n .map((r, i) => `${i + 1}. **${r.title}**\\n ${r.url}\\n ${r.snippet}`)\n .join('\\n\\n');\n } catch (error) {\n return `Search error: ${(error as Error).message}`;\n }\n },\n },\n );\n}\n","/**\n * TITAN — Cron Skill (Built-in)\n * Schedule and manage automated tasks.\n */\nimport { registerSkill } from '../registry.js';\nimport { getDb } from '../../memory/memory.js';\nimport { v4 as uuid } from 'uuid';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Cron';\n\nexport function registerCronSkill(): void {\n registerSkill(\n { name: 'cron', description: 'Manage scheduled tasks', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'cron',\n description: 'Create, list, enable/disable, or delete scheduled cron jobs. Jobs run automatically at specified intervals.',\n parameters: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['create', 'list', 'delete', 'enable', 'disable'],\n description: 'Action to perform',\n },\n name: { type: 'string', description: 'Name for the cron job' },\n schedule: { type: 'string', description: 'Cron schedule expression (e.g., \"0 9 * * *\" for daily at 9am)' },\n command: { type: 'string', description: 'Command to execute when the job runs' },\n jobId: { type: 'string', description: 'Job ID (for delete/enable/disable)' },\n },\n required: ['action'],\n },\n execute: async (args) => {\n const action = args.action as string;\n const store = getDb();\n\n switch (action) {\n case 'create': {\n const name = args.name as string;\n const schedule = args.schedule as string;\n const command = args.command as string;\n if (!name || !schedule || !command) return 'Error: name, schedule, and command are required';\n const id = uuid();\n store.cronJobs.push({\n id, name, schedule, command,\n enabled: true,\n created_at: new Date().toISOString(),\n });\n logger.info(COMPONENT, `Created cron job: ${name} (${schedule})`);\n return `Created cron job \"${name}\" (ID: ${id})\\nSchedule: ${schedule}\\nCommand: ${command}`;\n }\n case 'list': {\n if (store.cronJobs.length === 0) return 'No cron jobs configured.';\n return store.cronJobs.map((j) =>\n `• ${j.name} [${j.enabled ? '✅ enabled' : '❌ disabled'}]\\n ID: ${j.id}\\n Schedule: ${j.schedule}\\n Command: ${j.command}`\n ).join('\\n\\n');\n }\n case 'delete': {\n const jobId = args.jobId as string;\n if (!jobId) return 'Error: jobId is required';\n store.cronJobs = store.cronJobs.filter((j) => j.id !== jobId);\n return `Deleted cron job: ${jobId}`;\n }\n case 'enable': {\n const eId = args.jobId as string;\n if (!eId) return 'Error: jobId is required';\n const job = store.cronJobs.find((j) => j.id === eId);\n if (job) job.enabled = true;\n return `Enabled cron job: ${eId}`;\n }\n case 'disable': {\n const dId = args.jobId as string;\n if (!dId) return 'Error: jobId is required';\n const job = store.cronJobs.find((j) => j.id === dId);\n if (job) job.enabled = false;\n return `Disabled cron job: ${dId}`;\n }\n default:\n return `Unknown action: ${action}`;\n }\n },\n },\n );\n}\n","/**\n * TITAN — Webhook Skill (Built-in)\n * Create and manage HTTP webhook endpoints.\n */\nimport { registerSkill } from '../registry.js';\nimport { getDb } from '../../memory/memory.js';\nimport { v4 as uuid } from 'uuid';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Webhook';\n\n/** In-memory webhook registry */\nconst activeWebhooks: Map<string, {\n id: string;\n path: string;\n name: string;\n method: string;\n handler: string;\n}> = new Map();\n\nexport function getActiveWebhooks() {\n return activeWebhooks;\n}\n\nexport function registerWebhookSkill(): void {\n registerSkill(\n { name: 'webhook', description: 'Manage webhook endpoints', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'webhook',\n description: 'Create, list, or delete HTTP webhook endpoints that trigger actions when called.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['create', 'list', 'delete'], description: 'Action' },\n name: { type: 'string', description: 'Webhook name' },\n path: { type: 'string', description: 'URL path (e.g., /my-hook)' },\n method: { type: 'string', description: 'HTTP method (GET/POST, default: POST)' },\n handler: { type: 'string', description: 'Command to run when webhook is triggered' },\n webhookId: { type: 'string', description: 'Webhook ID (for delete)' },\n },\n required: ['action'],\n },\n execute: async (args) => {\n const action = args.action as string;\n\n switch (action) {\n case 'create': {\n const id = uuid();\n const name = (args.name as string) || `webhook-${id.slice(0, 8)}`;\n const path = (args.path as string) || `/webhook/${id.slice(0, 8)}`;\n const method = (args.method as string) || 'POST';\n const handler = (args.handler as string) || '';\n activeWebhooks.set(id, { id, path, name, method, handler });\n logger.info(COMPONENT, `Created webhook: ${name} at ${path}`);\n return `Created webhook \"${name}\"\\n ID: ${id}\\n Path: ${path}\\n Method: ${method}\\n Handler: ${handler}`;\n }\n case 'list': {\n if (activeWebhooks.size === 0) return 'No active webhooks.';\n return Array.from(activeWebhooks.values())\n .map((w) => `• ${w.name}\\n ID: ${w.id}\\n ${w.method} ${w.path}\\n Handler: ${w.handler}`)\n .join('\\n\\n');\n }\n case 'delete': {\n const wId = args.webhookId as string;\n if (!wId) return 'Error: webhookId is required';\n activeWebhooks.delete(wId);\n return `Deleted webhook: ${wId}`;\n }\n default:\n return `Unknown action: ${action}`;\n }\n },\n },\n );\n}\n","/**\n * TITAN — Memory Skill (Built-in)\n * Persistent fact/preference storage for the agent.\n */\nimport { registerSkill } from '../registry.js';\nimport { rememberFact, recallFact, searchMemories } from '../../memory/memory.js';\n\nexport function registerMemorySkill(): void {\n registerSkill(\n { name: 'memory', description: 'Persistent memory management', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'memory',\n description: 'Store and recall persistent memories. Use this to remember user preferences, important facts, project details, and anything that should persist across conversations.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['remember', 'recall', 'search', 'list'], description: 'Action' },\n category: { type: 'string', description: 'Memory category (e.g., \"preference\", \"fact\", \"project\")' },\n key: { type: 'string', description: 'Memory key/name' },\n value: { type: 'string', description: 'Value to remember' },\n query: { type: 'string', description: 'Search query (for search action)' },\n },\n required: ['action'],\n },\n execute: async (args) => {\n const action = args.action as string;\n const category = (args.category as string) || 'general';\n\n switch (action) {\n case 'remember': {\n const key = args.key as string;\n const value = args.value as string;\n if (!key || !value) return 'Error: key and value are required';\n rememberFact(category, key, value);\n return `Remembered: [${category}] ${key} = ${value}`;\n }\n case 'recall': {\n const rKey = args.key as string;\n if (!rKey) return 'Error: key is required';\n const value = recallFact(category, rKey);\n return value ? `[${category}] ${rKey} = ${value}` : `No memory found for [${category}] ${rKey}`;\n }\n case 'search': {\n const query = args.query as string;\n const results = searchMemories(category !== 'general' ? category : undefined, query);\n if (results.length === 0) return 'No matching memories found.';\n return results.map((m) => `• [${m.category}] ${m.key}: ${m.value}`).join('\\n');\n }\n case 'list': {\n const all = searchMemories(category !== 'general' ? category : undefined);\n if (all.length === 0) return 'No memories stored yet.';\n return all.map((m) => `• [${m.category}] ${m.key}: ${m.value}`).join('\\n');\n }\n default:\n return `Unknown action: ${action}`;\n }\n },\n },\n );\n}\n","/**\n * TITAN — Browser Control Skill (Built-in)\n * CDP-based browser automation: navigate, snapshot, click, type, evaluate.\n */\nimport { registerSkill } from '../registry.js';\nimport { exec } from 'child_process';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Browser';\n\n/** Find a suitable browser binary */\nfunction findBrowser(): string {\n const candidates = [\n 'google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser',\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/usr/bin/google-chrome-stable',\n ];\n // Default to 'chromium' — user can override via config\n return candidates[2];\n}\n\nexport function registerBrowserSkill(): void {\n registerSkill(\n { name: 'browser', description: 'Browser control and web automation', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'browser',\n description: 'Control a Chromium-based browser to navigate websites, take snapshots, click elements, type text, evaluate JavaScript, and extract page content. Uses Chrome DevTools Protocol (CDP).',\n parameters: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['navigate', 'snapshot', 'click', 'type', 'evaluate', 'extract', 'screenshot'],\n description: 'Browser action to perform',\n },\n url: { type: 'string', description: 'URL to navigate to (for navigate action)' },\n selector: { type: 'string', description: 'CSS selector for click/type actions' },\n text: { type: 'string', description: 'Text to type (for type action)' },\n script: { type: 'string', description: 'JavaScript code to evaluate (for evaluate action)' },\n },\n required: ['action'],\n },\n execute: async (args) => {\n const action = args.action as string;\n\n switch (action) {\n case 'navigate': {\n const url = args.url as string;\n if (!url) return 'Error: url is required';\n logger.info(COMPONENT, `Navigating to: ${url}`);\n // Use curl to fetch page content as a baseline approach\n return new Promise<string>((resolve) => {\n exec(`curl -sL --max-time 15 \"${url}\" | head -c 50000`, { timeout: 20000 }, (err, stdout) => {\n if (err) {\n resolve(`Error fetching ${url}: ${err.message}`);\n return;\n }\n // Strip HTML tags for text content\n const text = stdout\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<[^>]*>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n resolve(`Page content from ${url}:\\n${text.slice(0, 20000)}`);\n });\n });\n }\n case 'snapshot':\n case 'extract': {\n const url = args.url as string;\n if (!url) return 'Error: url is required for snapshot/extract';\n return new Promise<string>((resolve) => {\n exec(`curl -sL --max-time 15 \"${url}\" | head -c 50000`, { timeout: 20000 }, (err, stdout) => {\n if (err) {\n resolve(`Error: ${err.message}`);\n return;\n }\n // Extract title + meta description + links\n const title = stdout.match(/<title[^>]*>(.*?)<\\/title>/i)?.[1] || 'No title';\n const desc = stdout.match(/<meta[^>]*name=\"description\"[^>]*content=\"([^\"]*)\"[^>]*>/i)?.[1] || '';\n const links: string[] = [];\n const linkRegex = /<a[^>]*href=\"([^\"]*)\"[^>]*>(.*?)<\\/a>/gi;\n let m;\n while ((m = linkRegex.exec(stdout)) !== null && links.length < 20) {\n const text = m[2].replace(/<[^>]*>/g, '').trim();\n if (text && m[1] && !m[1].startsWith('#')) links.push(` ${text}: ${m[1]}`);\n }\n resolve(`Page: ${title}\\nDescription: ${desc}\\nLinks:\\n${links.join('\\n')}`);\n });\n });\n }\n case 'evaluate': {\n const script = args.script as string;\n if (!script) return 'Error: script is required';\n return `Note: Full CDP browser evaluation requires a running browser session. Script queued: ${script.slice(0, 200)}`;\n }\n case 'screenshot': {\n const url = args.url as string;\n if (!url) return 'Error: url is required';\n return `Screenshot capture requires CDP connection to a running Chromium instance. Target: ${url}`;\n }\n case 'click': {\n const selector = args.selector as string;\n if (!selector) return 'Error: selector is required';\n return `Click action requires CDP connection. Selector: ${selector}`;\n }\n case 'type': {\n const selector = args.selector as string;\n const text = args.text as string;\n if (!selector || !text) return 'Error: selector and text are required';\n return `Type action requires CDP connection. Selector: ${selector}, Text: ${text}`;\n }\n default:\n return `Unknown browser action: ${action}`;\n }\n },\n },\n );\n}\n","/**\n * TITAN — Session Manager\n * Manages per-user/per-channel isolated sessions with history and context.\n */\nimport { v4 as uuid } from 'uuid';\nimport { getDb, getHistory, saveMessage, type ConversationMessage } from '../memory/memory.js';\nimport type { ChatMessage } from '../providers/base.js';\nimport { MAX_CONTEXT_MESSAGES, SESSION_TIMEOUT_MS } from '../utils/constants.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Session';\n\nexport interface Session {\n id: string;\n channel: string;\n userId: string;\n agentId: string;\n status: 'active' | 'idle' | 'closed';\n messageCount: number;\n createdAt: string;\n lastActive: string;\n e2eKey?: string; // Stored only in memory for active sessions\n}\n\n/** Active sessions cache */\nconst activeSessions: Map<string, Session> = new Map();\n\n/** Create or retrieve a session */\nexport function getOrCreateSession(channel: string, userId: string, agentId: string = 'default', isEncrypted: boolean = false): Session {\n const sessionKey = `${channel}:${userId}:${agentId}`;\n\n // Check cache\n const cached = activeSessions.get(sessionKey);\n if (cached && cached.status === 'active') {\n return cached;\n }\n\n // Check data store\n const store = getDb();\n const existing = store.sessions.find(\n (s) => s.channel === channel && s.user_id === userId && s.agent_id === agentId && s.status === 'active'\n );\n\n if (existing) {\n const lastActive = new Date(existing.last_active || existing.created_at).getTime();\n if (Date.now() - lastActive > SESSION_TIMEOUT_MS) {\n existing.status = 'idle';\n logger.debug(COMPONENT, `Session ${existing.id} timed out, creating new one`);\n // Fall through to create a new session\n } else {\n const session: Session = {\n id: existing.id,\n channel: existing.channel,\n userId: existing.user_id,\n agentId: existing.agent_id,\n status: existing.status as 'active',\n messageCount: existing.message_count,\n createdAt: existing.created_at,\n lastActive: existing.last_active,\n // Note: If a session was encrypted but dropped from memory, we cannot recover the key\n // A robust implementation would involve key exchange, but for now we warn:\n e2eKey: undefined\n };\n if (isEncrypted) {\n logger.warn(COMPONENT, `Recovered session ${existing.id}, but E2E key was lost from memory.`);\n }\n activeSessions.set(sessionKey, session);\n return session;\n }\n }\n\n // Create new session\n const session: Session = {\n id: uuid(),\n channel,\n userId,\n agentId,\n status: 'active',\n messageCount: 0,\n createdAt: new Date().toISOString(),\n lastActive: new Date().toISOString(),\n };\n\n if (isEncrypted) {\n import('../security/encryption.js').then(({ generateKey }) => {\n session.e2eKey = generateKey().toString('base64');\n logger.info(COMPONENT, `Generated E2E key for session ${session.id}`);\n }).catch(err => {\n logger.error(COMPONENT, `Failed to load encryption module: ${err}`);\n });\n }\n\n store.sessions.push({\n id: session.id,\n channel,\n user_id: userId,\n agent_id: agentId,\n status: 'active',\n message_count: 0,\n created_at: session.createdAt,\n last_active: session.lastActive,\n });\n\n activeSessions.set(sessionKey, session);\n logger.info(COMPONENT, `Created new session: ${session.id} (${channel}/${userId})`);\n return session;\n}\n\n/** Add a message to a session */\nexport function addMessage(\n session: Session,\n role: 'user' | 'assistant' | 'system' | 'tool',\n content: string,\n extra?: { toolCalls?: string; toolCallId?: string; model?: string; tokenCount?: number }\n): void {\n const messageId = uuid();\n saveMessage({\n id: messageId,\n sessionId: session.id,\n role,\n content,\n toolCalls: extra?.toolCalls,\n toolCallId: extra?.toolCallId,\n model: extra?.model,\n tokenCount: extra?.tokenCount || 0,\n }, session.e2eKey);\n\n // Update session\n session.messageCount++;\n session.lastActive = new Date().toISOString();\n\n const store = getDb();\n const sessionRec = store.sessions.find((s) => s.id === session.id);\n if (sessionRec) {\n sessionRec.message_count = session.messageCount;\n sessionRec.last_active = session.lastActive;\n }\n}\n\n/** Get the context messages for a session (for sending to LLM) */\nexport function getContextMessages(session: Session, maxMessages: number = MAX_CONTEXT_MESSAGES): ChatMessage[] {\n const history = getHistory(session.id, maxMessages, session.e2eKey);\n return history.map((msg) => ({\n role: msg.role as ChatMessage['role'],\n content: msg.content,\n toolCallId: msg.toolCallId || undefined,\n toolCalls: msg.toolCalls ? JSON.parse(msg.toolCalls) : undefined,\n }));\n}\n\n/** List all active sessions */\nexport function listSessions(): Session[] {\n const store = getDb();\n return store.sessions\n .filter((s) => s.status === 'active')\n .sort((a, b) => b.last_active.localeCompare(a.last_active))\n .map((s) => ({\n id: s.id,\n channel: s.channel,\n userId: s.user_id,\n agentId: s.agent_id,\n status: s.status as 'active',\n messageCount: s.message_count,\n createdAt: s.created_at,\n lastActive: s.last_active,\n }));\n}\n\n/** Close a session */\nexport function closeSession(sessionId: string): void {\n const store = getDb();\n const sessionRec = store.sessions.find((s) => s.id === sessionId);\n if (sessionRec) {\n sessionRec.status = 'closed';\n }\n\n for (const [key, session] of activeSessions) {\n if (session.id === sessionId) {\n activeSessions.delete(key);\n break;\n }\n }\n\n logger.info(COMPONENT, `Closed session: ${sessionId}`);\n}\n","/**\n * TITAN LLM Provider — Base Interface\n * All LLM providers implement this interface for a unified API.\n */\n\n/** A single message in a conversation */\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content: string;\n name?: string;\n toolCallId?: string;\n toolCalls?: ToolCall[];\n}\n\n/** A tool call requested by the LLM */\nexport interface ToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\n/** A tool definition for the LLM */\nexport interface ToolDefinition {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n };\n}\n\n/** Options for a chat completion request */\nexport interface ChatOptions {\n model?: string;\n messages: ChatMessage[];\n tools?: ToolDefinition[];\n maxTokens?: number;\n temperature?: number;\n stream?: boolean;\n thinking?: boolean;\n}\n\n/** Response from a chat completion */\nexport interface ChatResponse {\n id: string;\n content: string;\n toolCalls?: ToolCall[];\n usage?: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n finishReason: 'stop' | 'tool_calls' | 'length' | 'error';\n model: string;\n}\n\n/** Streaming chunk from a chat completion */\nexport interface ChatStreamChunk {\n type: 'text' | 'tool_call' | 'done' | 'error';\n content?: string;\n toolCall?: ToolCall;\n error?: string;\n}\n\n/** Abstract LLM Provider interface */\nexport abstract class LLMProvider {\n abstract readonly name: string;\n abstract readonly displayName: string;\n\n /** Send a chat completion request */\n abstract chat(options: ChatOptions): Promise<ChatResponse>;\n\n /** Send a streaming chat completion request */\n abstract chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk>;\n\n /** List available models */\n abstract listModels(): Promise<string[]>;\n\n /** Check if the provider is configured and reachable */\n abstract healthCheck(): Promise<boolean>;\n\n /** Get the provider identifier from a model string like \"anthropic/claude-3\" */\n static parseModelId(modelId: string): { provider: string; model: string } {\n const parts = modelId.split('/');\n if (parts.length >= 2) {\n return { provider: parts[0], model: parts.slice(1).join('/') };\n }\n return { provider: 'anthropic', model: modelId };\n }\n}\n","/**\n * TITAN — Anthropic/Claude Provider\n */\nimport {\n LLMProvider,\n type ChatOptions,\n type ChatResponse,\n type ChatStreamChunk,\n type ToolCall,\n} from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\nimport { v4 as uuid } from 'uuid';\n\nconst COMPONENT = 'Anthropic';\n\nexport class AnthropicProvider extends LLMProvider {\n readonly name = 'anthropic';\n readonly displayName = 'Anthropic (Claude)';\n\n private get apiKey(): string {\n const config = loadConfig();\n return config.providers.anthropic.apiKey || process.env.ANTHROPIC_API_KEY || '';\n }\n\n private get baseUrl(): string {\n const config = loadConfig();\n return config.providers.anthropic.baseUrl || 'https://api.anthropic.com';\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const model = options.model || 'claude-sonnet-4-20250514';\n const apiKey = this.apiKey;\n if (!apiKey) throw new Error('Anthropic API key not configured');\n\n logger.debug(COMPONENT, `Chat request: model=${model}, messages=${options.messages.length}`);\n\n const systemMessage = options.messages.find((m) => m.role === 'system');\n const nonSystemMessages = options.messages.filter((m) => m.role !== 'system');\n\n const body: Record<string, unknown> = {\n model: model.replace('anthropic/', ''),\n max_tokens: options.maxTokens || 8192,\n messages: nonSystemMessages.map((m) => ({\n role: m.role === 'tool' ? 'user' : m.role,\n content: m.role === 'tool'\n ? [{ type: 'tool_result', tool_use_id: m.toolCallId, content: m.content }]\n : m.content,\n })),\n };\n\n if (systemMessage) {\n body.system = systemMessage.content;\n }\n\n if (options.tools && options.tools.length > 0) {\n body.tools = options.tools.map((t) => ({\n name: t.function.name,\n description: t.function.description,\n input_schema: t.function.parameters,\n }));\n }\n\n if (options.temperature !== undefined) {\n body.temperature = options.temperature;\n }\n\n const response = await fetch(`${this.baseUrl}/v1/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Anthropic API error (${response.status}): ${errorText}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const content = data.content as Array<Record<string, unknown>>;\n\n let textContent = '';\n const toolCalls: ToolCall[] = [];\n\n for (const block of content) {\n if (block.type === 'text') {\n textContent += block.text as string;\n } else if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id as string,\n type: 'function',\n function: {\n name: block.name as string,\n arguments: JSON.stringify(block.input),\n },\n });\n }\n }\n\n const usage = data.usage as { input_tokens: number; output_tokens: number } | undefined;\n\n return {\n id: (data.id as string) || uuid(),\n content: textContent,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: usage\n ? {\n promptTokens: usage.input_tokens,\n completionTokens: usage.output_tokens,\n totalTokens: usage.input_tokens + usage.output_tokens,\n }\n : undefined,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : 'stop',\n model,\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n // For streaming, we'll use the non-streaming endpoint and yield the full response\n // A full streaming implementation would use SSE, which we'd implement for production\n try {\n const response = await this.chat(options);\n if (response.content) {\n yield { type: 'text', content: response.content };\n }\n if (response.toolCalls) {\n for (const tc of response.toolCalls) {\n yield { type: 'tool_call', toolCall: tc };\n }\n }\n yield { type: 'done' };\n } catch (error) {\n yield { type: 'error', error: (error as Error).message };\n }\n }\n\n async listModels(): Promise<string[]> {\n return [\n 'claude-opus-4-0',\n 'claude-sonnet-4-20250514',\n 'claude-haiku-4-20250414',\n 'claude-3-5-sonnet-20241022',\n 'claude-3-5-haiku-20241022',\n ];\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n if (!this.apiKey) return false;\n const response = await fetch(`${this.baseUrl}/v1/messages`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify({\n model: 'claude-haiku-4-20250414',\n max_tokens: 1,\n messages: [{ role: 'user', content: 'ping' }],\n }),\n });\n return response.ok || response.status === 400; // 400 = valid auth but bad request\n } catch {\n return false;\n }\n }\n}\n","/**\n * TITAN — OpenAI Provider (GPT-4, o-series)\n */\nimport {\n LLMProvider,\n type ChatOptions,\n type ChatResponse,\n type ChatStreamChunk,\n type ToolCall,\n} from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\nimport { v4 as uuid } from 'uuid';\n\nconst COMPONENT = 'OpenAI';\n\nexport class OpenAIProvider extends LLMProvider {\n readonly name = 'openai';\n readonly displayName = 'OpenAI (GPT)';\n\n private get apiKey(): string {\n const config = loadConfig();\n return config.providers.openai.apiKey || process.env.OPENAI_API_KEY || '';\n }\n\n private get baseUrl(): string {\n const config = loadConfig();\n return config.providers.openai.baseUrl || 'https://api.openai.com';\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const model = options.model || 'gpt-4o';\n const apiKey = this.apiKey;\n if (!apiKey) throw new Error('OpenAI API key not configured');\n\n logger.debug(COMPONENT, `Chat request: model=${model}, messages=${options.messages.length}`);\n\n const body: Record<string, unknown> = {\n model: model.replace('openai/', ''),\n messages: options.messages.map((m) => {\n if (m.role === 'tool') {\n return { role: 'tool', content: m.content, tool_call_id: m.toolCallId };\n }\n if (m.role === 'assistant' && m.toolCalls) {\n return {\n role: 'assistant',\n content: m.content || null,\n tool_calls: m.toolCalls.map((tc) => ({\n id: tc.id,\n type: 'function',\n function: { name: tc.function.name, arguments: tc.function.arguments },\n })),\n };\n }\n return { role: m.role, content: m.content };\n }),\n max_tokens: options.maxTokens || 8192,\n };\n\n if (options.tools && options.tools.length > 0) {\n body.tools = options.tools;\n }\n\n if (options.temperature !== undefined) {\n body.temperature = options.temperature;\n }\n\n const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`OpenAI API error (${response.status}): ${errorText}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const choices = data.choices as Array<Record<string, unknown>>;\n const choice = choices[0];\n const message = choice.message as Record<string, unknown>;\n\n const toolCalls: ToolCall[] = [];\n if (message.tool_calls) {\n for (const tc of message.tool_calls as Array<Record<string, unknown>>) {\n const fn = tc.function as Record<string, string>;\n toolCalls.push({\n id: tc.id as string,\n type: 'function',\n function: { name: fn.name, arguments: fn.arguments },\n });\n }\n }\n\n const usage = data.usage as { prompt_tokens: number; completion_tokens: number; total_tokens: number } | undefined;\n\n return {\n id: (data.id as string) || uuid(),\n content: (message.content as string) || '',\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: usage\n ? {\n promptTokens: usage.prompt_tokens,\n completionTokens: usage.completion_tokens,\n totalTokens: usage.total_tokens,\n }\n : undefined,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : (choice.finish_reason as 'stop' | 'length') || 'stop',\n model,\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n try {\n const response = await this.chat(options);\n if (response.content) {\n yield { type: 'text', content: response.content };\n }\n if (response.toolCalls) {\n for (const tc of response.toolCalls) {\n yield { type: 'tool_call', toolCall: tc };\n }\n }\n yield { type: 'done' };\n } catch (error) {\n yield { type: 'error', error: (error as Error).message };\n }\n }\n\n async listModels(): Promise<string[]> {\n return ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1', 'o1-mini', 'o3-mini'];\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n if (!this.apiKey) return false;\n const response = await fetch(`${this.baseUrl}/v1/models`, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n","/**\n * TITAN — Google Gemini Provider\n */\nimport {\n LLMProvider,\n type ChatOptions,\n type ChatResponse,\n type ChatStreamChunk,\n type ToolCall,\n} from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\nimport { v4 as uuid } from 'uuid';\n\nconst COMPONENT = 'Google';\n\nexport class GoogleProvider extends LLMProvider {\n readonly name = 'google';\n readonly displayName = 'Google (Gemini)';\n\n private get apiKey(): string {\n const config = loadConfig();\n return config.providers.google.apiKey || process.env.GOOGLE_API_KEY || '';\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const model = (options.model || 'gemini-2.0-flash').replace('google/', '');\n const apiKey = this.apiKey;\n if (!apiKey) throw new Error('Google API key not configured');\n\n logger.debug(COMPONENT, `Chat request: model=${model}, messages=${options.messages.length}`);\n\n const systemInstruction = options.messages.find((m) => m.role === 'system')?.content;\n const contents = options.messages\n .filter((m) => m.role !== 'system')\n .map((m) => ({\n role: m.role === 'assistant' ? 'model' : 'user',\n parts: [{ text: m.content }],\n }));\n\n const body: Record<string, unknown> = {\n contents,\n generationConfig: {\n maxOutputTokens: options.maxTokens || 8192,\n temperature: options.temperature ?? 0.7,\n },\n };\n\n if (systemInstruction) {\n body.systemInstruction = { parts: [{ text: systemInstruction }] };\n }\n\n if (options.tools && options.tools.length > 0) {\n body.tools = [{\n functionDeclarations: options.tools.map((t) => ({\n name: t.function.name,\n description: t.function.description,\n parameters: t.function.parameters,\n })),\n }];\n }\n\n const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Google API error (${response.status}): ${errorText}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const candidates = data.candidates as Array<Record<string, unknown>>;\n\n let textContent = '';\n const toolCalls: ToolCall[] = [];\n\n if (candidates && candidates.length > 0) {\n const parts = (candidates[0].content as Record<string, unknown>)?.parts as Array<Record<string, unknown>> || [];\n for (const part of parts) {\n if (part.text) {\n textContent += part.text as string;\n }\n if (part.functionCall) {\n const fc = part.functionCall as Record<string, unknown>;\n toolCalls.push({\n id: uuid(),\n type: 'function',\n function: {\n name: fc.name as string,\n arguments: JSON.stringify(fc.args),\n },\n });\n }\n }\n }\n\n const usageMeta = data.usageMetadata as { promptTokenCount?: number; candidatesTokenCount?: number; totalTokenCount?: number } | undefined;\n\n return {\n id: uuid(),\n content: textContent,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: usageMeta\n ? {\n promptTokens: usageMeta.promptTokenCount || 0,\n completionTokens: usageMeta.candidatesTokenCount || 0,\n totalTokens: usageMeta.totalTokenCount || 0,\n }\n : undefined,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : 'stop',\n model: `google/${model}`,\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n try {\n const response = await this.chat(options);\n if (response.content) yield { type: 'text', content: response.content };\n if (response.toolCalls) {\n for (const tc of response.toolCalls) yield { type: 'tool_call', toolCall: tc };\n }\n yield { type: 'done' };\n } catch (error) {\n yield { type: 'error', error: (error as Error).message };\n }\n }\n\n async listModels(): Promise<string[]> {\n return ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.0-flash', 'gemini-1.5-pro'];\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n if (!this.apiKey) return false;\n const url = `https://generativelanguage.googleapis.com/v1beta/models?key=${this.apiKey}`;\n const response = await fetch(url);\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n","/**\n * TITAN — Ollama Provider (Local LLMs)\n */\nimport {\n LLMProvider,\n type ChatOptions,\n type ChatResponse,\n type ChatStreamChunk,\n type ToolCall,\n} from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\nimport { v4 as uuid } from 'uuid';\n\nconst COMPONENT = 'Ollama';\n\nexport class OllamaProvider extends LLMProvider {\n readonly name = 'ollama';\n readonly displayName = 'Ollama (Local)';\n\n private get baseUrl(): string {\n const config = loadConfig();\n return config.providers.ollama.baseUrl || process.env.OLLAMA_BASE_URL || 'http://localhost:11434';\n }\n\n async chat(options: ChatOptions): Promise<ChatResponse> {\n const model = (options.model || 'llama3.1').replace('ollama/', '');\n logger.debug(COMPONENT, `Chat request: model=${model}, messages=${options.messages.length}`);\n\n const body: Record<string, unknown> = {\n model,\n messages: options.messages.map((m) => ({\n role: m.role,\n content: m.content,\n })),\n stream: false,\n options: {\n num_predict: options.maxTokens || 8192,\n temperature: options.temperature ?? 0.7,\n },\n };\n\n if (options.tools && options.tools.length > 0) {\n body.tools = options.tools.map((t) => ({\n type: 'function',\n function: {\n name: t.function.name,\n description: t.function.description,\n parameters: t.function.parameters,\n },\n }));\n }\n\n const response = await fetch(`${this.baseUrl}/api/chat`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Ollama error (${response.status}): ${errorText}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const message = data.message as Record<string, unknown>;\n const toolCalls: ToolCall[] = [];\n\n if (message.tool_calls) {\n for (const tc of message.tool_calls as Array<Record<string, unknown>>) {\n const fn = tc.function as Record<string, unknown>;\n toolCalls.push({\n id: uuid(),\n type: 'function',\n function: {\n name: fn.name as string,\n arguments: JSON.stringify(fn.arguments),\n },\n });\n }\n }\n\n return {\n id: uuid(),\n content: (message.content as string) || '',\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n usage: {\n promptTokens: (data.prompt_eval_count as number) || 0,\n completionTokens: (data.eval_count as number) || 0,\n totalTokens: ((data.prompt_eval_count as number) || 0) + ((data.eval_count as number) || 0),\n },\n finishReason: toolCalls.length > 0 ? 'tool_calls' : 'stop',\n model: `ollama/${model}`,\n };\n }\n\n async *chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n try {\n const response = await this.chat(options);\n if (response.content) yield { type: 'text', content: response.content };\n if (response.toolCalls) {\n for (const tc of response.toolCalls) yield { type: 'tool_call', toolCall: tc };\n }\n yield { type: 'done' };\n } catch (error) {\n yield { type: 'error', error: (error as Error).message };\n }\n }\n\n async listModels(): Promise<string[]> {\n try {\n const response = await fetch(`${this.baseUrl}/api/tags`);\n if (!response.ok) return [];\n const data = await response.json() as { models?: Array<{ name: string }> };\n return (data.models || []).map((m) => m.name);\n } catch {\n return [];\n }\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/api/tags`);\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n","/**\n * TITAN — Provider Router\n * Routes model requests to the correct provider with failover support.\n */\nimport { LLMProvider, type ChatOptions, type ChatResponse, type ChatStreamChunk } from './base.js';\nimport { AnthropicProvider } from './anthropic.js';\nimport { OpenAIProvider } from './openai.js';\nimport { GoogleProvider } from './google.js';\nimport { OllamaProvider } from './ollama.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Router';\n\n/** Provider registry */\nconst providers: Map<string, LLMProvider> = new Map();\nlet initialized = false;\n\nfunction initProviders(): void {\n if (initialized) return;\n providers.set('anthropic', new AnthropicProvider());\n providers.set('openai', new OpenAIProvider());\n providers.set('google', new GoogleProvider());\n providers.set('ollama', new OllamaProvider());\n initialized = true;\n}\n\n/** Get a provider by name */\nexport function getProvider(name: string): LLMProvider | undefined {\n initProviders();\n return providers.get(name);\n}\n\n/** Get all registered providers */\nexport function getAllProviders(): Map<string, LLMProvider> {\n initProviders();\n return providers;\n}\n\n/** Resolve the provider and model from a model ID like \"anthropic/claude-3\" */\nexport function resolveModel(modelId: string): { provider: LLMProvider; model: string } {\n initProviders();\n const { provider: providerName, model } = LLMProvider.parseModelId(modelId);\n const provider = providers.get(providerName);\n if (!provider) {\n throw new Error(`Unknown provider: ${providerName}. Available: ${Array.from(providers.keys()).join(', ')}`);\n }\n return { provider, model };\n}\n\n/** Send a chat request, automatically routing to the correct provider */\nexport async function chat(options: ChatOptions): Promise<ChatResponse> {\n const modelId = options.model || 'anthropic/claude-sonnet-4-20250514';\n const { provider, model } = resolveModel(modelId);\n\n logger.info(COMPONENT, `Routing to ${provider.displayName} (model: ${model})`);\n\n try {\n return await provider.chat({ ...options, model });\n } catch (error) {\n logger.error(COMPONENT, `Provider ${provider.name} failed: ${(error as Error).message}`);\n // Attempt failover to other providers\n const failoverOrder = ['anthropic', 'openai', 'google', 'ollama'];\n for (const fallbackName of failoverOrder) {\n if (fallbackName === provider.name) continue;\n const fallback = providers.get(fallbackName);\n if (!fallback) continue;\n\n try {\n const healthy = await fallback.healthCheck();\n if (!healthy) continue;\n\n const models = await fallback.listModels();\n if (models.length === 0) continue;\n\n logger.warn(COMPONENT, `Failing over to ${fallback.displayName} (model: ${models[0]})`);\n return await fallback.chat({ ...options, model: models[0] });\n } catch {\n continue;\n }\n }\n throw error;\n }\n}\n\n/** Send a streaming chat request */\nexport async function* chatStream(options: ChatOptions): AsyncGenerator<ChatStreamChunk> {\n const modelId = options.model || 'anthropic/claude-sonnet-4-20250514';\n const { provider, model } = resolveModel(modelId);\n yield* provider.chatStream({ ...options, model });\n}\n\n/** Health check all providers */\nexport async function healthCheckAll(): Promise<Record<string, boolean>> {\n initProviders();\n const results: Record<string, boolean> = {};\n for (const [name, provider] of providers) {\n try {\n results[name] = await provider.healthCheck();\n } catch {\n results[name] = false;\n }\n }\n return results;\n}\n","/**\n * TITAN — Learning Engine\n * Continuous self-improvement: learns from interactions, tracks patterns,\n * builds a knowledge base, and improves tool selection over time.\n */\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { TITAN_HOME } from '../utils/constants.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Learning';\nconst KNOWLEDGE_FILE = join(TITAN_HOME, 'knowledge.json');\n\nexport interface LearningEntry {\n id: string;\n type: 'skill_usage' | 'error_pattern' | 'user_correction' | 'successful_pattern' | 'fact' | 'preference';\n category: string;\n content: string;\n context?: string;\n score: number; // confidence/usefulness score (0-1)\n accessCount: number; // how often this knowledge was retrieved\n createdAt: string;\n updatedAt: string;\n}\n\ninterface KnowledgeBase {\n entries: LearningEntry[];\n toolSuccessRates: Record<string, { success: number; fail: number; total: number }>;\n errorPatterns: Record<string, { count: number; lastSeen: string; resolution?: string }>;\n userCorrections: Array<{ original: string; correction: string; timestamp: string }>;\n conversationInsights: Array<{ topic: string; outcome: string; toolsUsed: string[]; timestamp: string }>;\n}\n\nlet kb: KnowledgeBase | null = null;\n\nfunction loadKnowledgeBase(): KnowledgeBase {\n if (kb) return kb;\n ensureDir(TITAN_HOME);\n if (existsSync(KNOWLEDGE_FILE)) {\n try {\n kb = JSON.parse(readFileSync(KNOWLEDGE_FILE, 'utf-8'));\n // Ensure fields exist\n kb!.entries = kb!.entries || [];\n kb!.toolSuccessRates = kb!.toolSuccessRates || {};\n kb!.errorPatterns = kb!.errorPatterns || {};\n kb!.userCorrections = kb!.userCorrections || [];\n kb!.conversationInsights = kb!.conversationInsights || [];\n } catch {\n kb = createEmptyKB();\n }\n } else {\n kb = createEmptyKB();\n }\n return kb!;\n}\n\nfunction createEmptyKB(): KnowledgeBase {\n return {\n entries: [],\n toolSuccessRates: {},\n errorPatterns: {},\n userCorrections: [],\n conversationInsights: [],\n };\n}\n\nlet saveTimeout: ReturnType<typeof setTimeout> | null = null;\nfunction debouncedSave(): void {\n if (saveTimeout) clearTimeout(saveTimeout);\n saveTimeout = setTimeout(() => {\n if (!kb) return;\n ensureDir(TITAN_HOME);\n writeFileSync(KNOWLEDGE_FILE, JSON.stringify(kb, null, 2), 'utf-8');\n }, 2000);\n}\n\n/** Initialize the learning engine */\nexport function initLearning(): void {\n loadKnowledgeBase();\n logger.info(COMPONENT, `Learning engine initialized (${kb!.entries.length} knowledge entries)`);\n}\n\n/** Record a tool execution result for learning */\nexport function recordToolResult(toolName: string, success: boolean, context?: string, error?: string): void {\n const k = loadKnowledgeBase();\n\n // Update tool success rates\n if (!k.toolSuccessRates[toolName]) {\n k.toolSuccessRates[toolName] = { success: 0, fail: 0, total: 0 };\n }\n k.toolSuccessRates[toolName].total++;\n if (success) {\n k.toolSuccessRates[toolName].success++;\n } else {\n k.toolSuccessRates[toolName].fail++;\n // Track error patterns\n if (error) {\n const pattern = error.slice(0, 200);\n if (!k.errorPatterns[pattern]) {\n k.errorPatterns[pattern] = { count: 0, lastSeen: '' };\n }\n k.errorPatterns[pattern].count++;\n k.errorPatterns[pattern].lastSeen = new Date().toISOString();\n }\n }\n\n debouncedSave();\n}\n\n/** Record a successful interaction pattern */\nexport function recordSuccessPattern(pattern: {\n topic: string;\n toolsUsed: string[];\n outcome: string;\n}): void {\n const k = loadKnowledgeBase();\n k.conversationInsights.push({\n ...pattern,\n timestamp: new Date().toISOString(),\n });\n // Keep last 500 insights\n if (k.conversationInsights.length > 500) {\n k.conversationInsights = k.conversationInsights.slice(-500);\n }\n debouncedSave();\n}\n\n/** Record a user correction to learn from mistakes */\nexport function recordUserCorrection(original: string, correction: string): void {\n const k = loadKnowledgeBase();\n k.userCorrections.push({\n original,\n correction,\n timestamp: new Date().toISOString(),\n });\n if (k.userCorrections.length > 200) {\n k.userCorrections = k.userCorrections.slice(-200);\n }\n debouncedSave();\n}\n\n/** Learn a new fact or update an existing one */\nexport function learnFact(category: string, content: string, context?: string): void {\n const k = loadKnowledgeBase();\n const id = `${category}:${content.slice(0, 50)}`;\n const existing = k.entries.findIndex((e) => e.id === id);\n\n if (existing >= 0) {\n k.entries[existing].score = Math.min(k.entries[existing].score + 0.1, 1.0);\n k.entries[existing].accessCount++;\n k.entries[existing].updatedAt = new Date().toISOString();\n } else {\n k.entries.push({\n id,\n type: 'fact',\n category,\n content,\n context,\n score: 0.5,\n accessCount: 0,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n });\n }\n // Keep entries under 2000\n if (k.entries.length > 2000) {\n // Remove lowest-scored entries\n k.entries.sort((a, b) => b.score - a.score);\n k.entries = k.entries.slice(0, 1500);\n }\n debouncedSave();\n}\n\n/** Query the knowledge base for relevant information */\nexport function queryKnowledge(query: string, category?: string, limit: number = 10): LearningEntry[] {\n const k = loadKnowledgeBase();\n const q = query.toLowerCase();\n\n let results = k.entries.filter((e) => {\n const matchesQuery = e.content.toLowerCase().includes(q) ||\n e.category.toLowerCase().includes(q) ||\n (e.context && e.context.toLowerCase().includes(q));\n const matchesCategory = !category || e.category === category;\n return matchesQuery && matchesCategory;\n });\n\n // Sort by score (most useful first), then by recency\n results.sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return b.updatedAt.localeCompare(a.updatedAt);\n });\n\n // Boost access count for retrieved entries\n for (const entry of results.slice(0, limit)) {\n entry.accessCount++;\n entry.score = Math.min(entry.score + 0.01, 1.0);\n }\n\n debouncedSave();\n return results.slice(0, limit);\n}\n\n/** Get tool recommendations based on historical success rates */\nexport function getToolRecommendations(): Record<string, number> {\n const k = loadKnowledgeBase();\n const recommendations: Record<string, number> = {};\n\n for (const [tool, stats] of Object.entries(k.toolSuccessRates)) {\n if (stats.total > 0) {\n recommendations[tool] = stats.success / stats.total;\n }\n }\n\n return recommendations;\n}\n\n/** Get learning summary for the system prompt */\nexport function getLearningContext(): string {\n const k = loadKnowledgeBase();\n const parts: string[] = [];\n\n // Recent high-score knowledge\n const topEntries = k.entries\n .filter((e) => e.score > 0.6)\n .sort((a, b) => b.score - a.score)\n .slice(0, 10);\n\n if (topEntries.length > 0) {\n parts.push('Key learned facts:');\n for (const e of topEntries) {\n parts.push(`- [${e.category}] ${e.content}`);\n }\n }\n\n // Tool recommendations\n const toolRecs = getToolRecommendations();\n const bestTools = Object.entries(toolRecs)\n .filter(([_, rate]) => rate > 0.8)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n if (bestTools.length > 0) {\n parts.push('\\nMost reliable tools:');\n for (const [tool, rate] of bestTools) {\n parts.push(`- ${tool}: ${Math.round(rate * 100)}% success rate`);\n }\n }\n\n // Common error patterns to avoid\n const frequentErrors = Object.entries(k.errorPatterns)\n .filter(([_, info]) => info.count > 2)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 3);\n\n if (frequentErrors.length > 0) {\n parts.push('\\nCommon errors to avoid:');\n for (const [pattern, info] of frequentErrors) {\n parts.push(`- ${pattern.slice(0, 100)} (seen ${info.count}x)${info.resolution ? ` → Fix: ${info.resolution}` : ''}`);\n }\n }\n\n return parts.join('\\n');\n}\n\n/** Get stats about the learning system */\nexport function getLearningStats(): {\n knowledgeEntries: number;\n toolsTracked: number;\n errorPatterns: number;\n corrections: number;\n insights: number;\n} {\n const k = loadKnowledgeBase();\n return {\n knowledgeEntries: k.entries.length,\n toolsTracked: Object.keys(k.toolSuccessRates).length,\n errorPatterns: Object.keys(k.errorPatterns).length,\n corrections: k.userCorrections.length,\n insights: k.conversationInsights.length,\n };\n}\n","/**\n * TITAN — Core Agent Loop\n * The main agent: receives messages, builds context, calls LLM, handles tools, responds.\n */\nimport { v4 as uuid } from 'uuid';\nimport { existsSync, readFileSync } from 'fs';\nimport { chat } from '../providers/router.js';\nimport { loadConfig } from '../config/config.js';\nimport { getOrCreateSession, addMessage, getContextMessages, type Session } from './session.js';\nimport { executeTools, getToolDefinitions } from './toolRunner.js';\nimport { recordUsage, searchMemories } from '../memory/memory.js';\nimport { initLearning, recordToolResult, recordSuccessPattern, getLearningContext } from '../memory/learning.js';\nimport type { ChatMessage, ChatResponse } from '../providers/base.js';\nimport logger from '../utils/logger.js';\nimport { TITAN_NAME, AGENTS_MD, SOUL_MD, TOOLS_MD } from '../utils/constants.js';\n\nconst COMPONENT = 'Agent';\nconst MAX_TOOL_ROUNDS = 10;\n\n/** Agent response with metadata */\nexport interface AgentResponse {\n content: string;\n sessionId: string;\n toolsUsed: string[];\n tokenUsage: { prompt: number; completion: number; total: number };\n model: string;\n durationMs: number;\n}\n\n/** Read a workspace prompt file if it exists */\nfunction readPromptFile(path: string): string {\n try {\n if (existsSync(path)) return readFileSync(path, 'utf-8');\n } catch { /* ignore */ }\n return '';\n}\n\n/** Build the system prompt for the agent */\nfunction buildSystemPrompt(config: ReturnType<typeof loadConfig>): string {\n const customPrompt = config.agent.systemPrompt || '';\n const memories = searchMemories('preference');\n const memoryContext = memories.length > 0\n ? `\\n\\nUser preferences I remember:\\n${memories.map((m) => `- ${m.key}: ${m.value}`).join('\\n')}`\n : '';\n\n // Read workspace prompt files (like OpenClaw's AGENTS.md, SOUL.md, TOOLS.md)\n const agentsMd = readPromptFile(AGENTS_MD);\n const soulMd = readPromptFile(SOUL_MD);\n const toolsMd = readPromptFile(TOOLS_MD);\n\n const workspaceContext = [\n agentsMd ? `\\n## Agent Instructions (AGENTS.md)\\n${agentsMd}` : '',\n soulMd ? `\\n## Personality (SOUL.md)\\n${soulMd}` : '',\n toolsMd ? `\\n## Tool Notes (TOOLS.md)\\n${toolsMd}` : '',\n ].filter(Boolean).join('\\n');\n\n // Continuous learning context\n const learningContext = getLearningContext();\n\n return `You are ${TITAN_NAME}, The Intelligent Task Automation Network — a powerful personal AI assistant.\n\n## Core Capabilities\n- Execute shell commands and scripts on the user's system\n- Read, write, edit, and manage files\n- Browse the web and extract information (browser control via CDP)\n- Schedule automated tasks with cron\n- Set up webhook endpoints\n- Search the web for current information\n- Control browser sessions (navigate, snapshot, evaluate)\n- Manage agent sessions (list, history, send, close)\n- Remember facts and user preferences persistently\n\n## Behavior Guidelines\n- Be proactive: if a task implies follow-up actions, suggest or perform them\n- Be concise but thorough in responses\n- When executing commands, always explain what you're doing and why\n- If a task could be destructive (deleting files, etc.), confirm with the user first\n- Use tools when they would be helpful — don't just describe what could be done\n- Remember important information about the user for future conversations\n- If you encounter an error, try alternative approaches before reporting failure\n\n## Security\n- Never expose API keys, passwords, or other secrets\n- Don't execute commands that could compromise system security without explicit approval\n- Respect file system boundaries set in the configuration\n\n## Continuous Learning\nYou get smarter with every interaction. Below is your accumulated knowledge:\n${learningContext}\n${customPrompt ? `\\n## Custom Instructions\\n${customPrompt}` : ''}${workspaceContext}${memoryContext}`;\n}\n\n/** Process a user message through the agent loop */\nexport async function processMessage(\n message: string,\n channel: string = 'cli',\n userId: string = 'default',\n): Promise<AgentResponse> {\n const startTime = Date.now();\n const config = loadConfig();\n const session = getOrCreateSession(channel, userId);\n\n logger.info(COMPONENT, `Processing message in session ${session.id} (${channel}/${userId})`);\n\n // Add user message to session history\n addMessage(session, 'user', message);\n\n // Build context\n const systemPrompt = buildSystemPrompt(config);\n const historyMessages = getContextMessages(session);\n const tools = getToolDefinitions();\n\n const messages: ChatMessage[] = [\n { role: 'system', content: systemPrompt },\n ...historyMessages,\n ];\n\n let totalPromptTokens = 0;\n let totalCompletionTokens = 0;\n const toolsUsed: string[] = [];\n let finalContent = '';\n let modelUsed = config.agent.model;\n\n // Agent loop with tool calling\n for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {\n logger.debug(COMPONENT, `Round ${round + 1}: ${messages.length} messages, ${tools.length} tools`);\n\n const response: ChatResponse = await chat({\n model: config.agent.model,\n messages,\n tools: tools.length > 0 ? tools : undefined,\n maxTokens: config.agent.maxTokens,\n temperature: config.agent.temperature,\n });\n\n modelUsed = response.model;\n totalPromptTokens += response.usage?.promptTokens || 0;\n totalCompletionTokens += response.usage?.completionTokens || 0;\n\n // If no tool calls, we have the final response\n if (!response.toolCalls || response.toolCalls.length === 0) {\n finalContent = response.content;\n break;\n }\n\n // Handle tool calls\n logger.info(COMPONENT, `LLM requested ${response.toolCalls.length} tool call(s)`);\n\n // Add assistant message with tool calls to history\n messages.push({\n role: 'assistant',\n content: response.content || '',\n toolCalls: response.toolCalls,\n });\n\n // Execute tools\n const toolResults = await executeTools(response.toolCalls);\n\n // Add tool results to messages and record for learning\n for (const result of toolResults) {\n toolsUsed.push(result.name);\n messages.push({\n role: 'tool',\n content: result.content,\n toolCallId: result.toolCallId,\n });\n // Record tool result for continuous learning\n const success = !result.content.toLowerCase().includes('error:');\n recordToolResult(result.name, success, undefined, success ? undefined : result.content.slice(0, 200));\n }\n\n // If this is the last round, add a note\n if (round === MAX_TOOL_ROUNDS - 1) {\n finalContent = response.content || 'I completed the tool operations. Let me know if you need anything else.';\n }\n }\n\n // Save assistant response to session\n addMessage(session, 'assistant', finalContent, {\n model: modelUsed,\n tokenCount: totalCompletionTokens,\n });\n\n // Record usage\n const { provider: providerName } = { provider: modelUsed.split('/')[0] || 'unknown' };\n recordUsage(session.id, providerName, modelUsed, totalPromptTokens, totalCompletionTokens);\n\n const durationMs = Date.now() - startTime;\n logger.info(COMPONENT, `Response generated in ${durationMs}ms (${totalPromptTokens + totalCompletionTokens} tokens)`);\n\n return {\n content: finalContent,\n sessionId: session.id,\n toolsUsed: [...new Set(toolsUsed)],\n tokenUsage: {\n prompt: totalPromptTokens,\n completion: totalCompletionTokens,\n total: totalPromptTokens + totalCompletionTokens,\n },\n model: modelUsed,\n durationMs,\n };\n}\n","/**\n * TITAN — Sessions Skill (Built-in)\n * Agent-to-agent session management: list, history, send, spawn.\n * Mirrors OpenClaw's sessions_* tools.\n */\nimport { registerSkill } from '../registry.js';\nimport { listSessions, getOrCreateSession, addMessage, getContextMessages, closeSession } from '../../agent/session.js';\nimport { processMessage } from '../../agent/agent.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Sessions';\n\nexport function registerSessionsSkill(): void {\n // sessions_list\n registerSkill(\n { name: 'sessions_list', description: 'List active sessions', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'sessions_list',\n description: 'List all active agent sessions with their IDs, channels, users, and message counts.',\n parameters: {\n type: 'object',\n properties: {},\n },\n execute: async () => {\n const sessions = listSessions();\n if (sessions.length === 0) return 'No active sessions.';\n return sessions.map((s) =>\n `• ${s.id.slice(0, 8)} | ${s.channel} | user: ${s.userId} | msgs: ${s.messageCount} | last active: ${s.lastActive}`\n ).join('\\n');\n },\n },\n );\n\n // sessions_history\n registerSkill(\n { name: 'sessions_history', description: 'Get session message history', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'sessions_history',\n description: 'Retrieve the recent message history for a specific session.',\n parameters: {\n type: 'object',\n properties: {\n sessionChannel: { type: 'string', description: 'Channel of the session' },\n sessionUserId: { type: 'string', description: 'User ID of the session' },\n limit: { type: 'number', description: 'Max messages to return (default: 20)' },\n },\n required: ['sessionChannel', 'sessionUserId'],\n },\n execute: async (args) => {\n const channel = args.sessionChannel as string;\n const userId = args.sessionUserId as string;\n const limit = (args.limit as number) || 20;\n const session = getOrCreateSession(channel, userId);\n const messages = getContextMessages(session, limit);\n if (messages.length === 0) return `No messages in session ${channel}/${userId}.`;\n return messages.map((m) =>\n `[${m.role}] ${m.content.slice(0, 500)}`\n ).join('\\n---\\n');\n },\n },\n );\n\n // sessions_send\n registerSkill(\n { name: 'sessions_send', description: 'Send a message to another session', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'sessions_send',\n description: 'Send a message to a specific user\\'s session on a channel, triggering agent processing.',\n parameters: {\n type: 'object',\n properties: {\n targetChannel: { type: 'string', description: 'Target channel (e.g., \"discord\", \"telegram\")' },\n targetUserId: { type: 'string', description: 'Target user ID' },\n message: { type: 'string', description: 'Message to send' },\n },\n required: ['targetChannel', 'targetUserId', 'message'],\n },\n execute: async (args) => {\n const channel = args.targetChannel as string;\n const userId = args.targetUserId as string;\n const message = args.message as string;\n logger.info(COMPONENT, `Sending inter-session message to ${channel}/${userId}`);\n\n try {\n const response = await processMessage(message, channel, userId);\n return `Message delivered to ${channel}/${userId}. Response: ${response.content.slice(0, 500)}`;\n } catch (error) {\n return `Error sending to ${channel}/${userId}: ${(error as Error).message}`;\n }\n },\n },\n );\n\n // sessions_close\n registerSkill(\n { name: 'sessions_close', description: 'Close a session', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'sessions_close',\n description: 'Close a specific session by its session ID.',\n parameters: {\n type: 'object',\n properties: {\n sessionId: { type: 'string', description: 'Session ID to close' },\n },\n required: ['sessionId'],\n },\n execute: async (args) => {\n const sessionId = args.sessionId as string;\n closeSession(sessionId);\n return `Session ${sessionId} closed.`;\n },\n },\n );\n}\n","/**\n * TITAN — Process Manager Skill (Built-in)\n * Background process management: exec with background/timeout, process list/poll/kill/log.\n * Matches OpenClaw's exec + process tools.\n */\nimport { registerSkill } from '../registry.js';\nimport { exec, spawn, type ChildProcess } from 'child_process';\nimport { v4 as uuid } from 'uuid';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Process';\n\ninterface ManagedProcess {\n id: string;\n command: string;\n pid: number;\n status: 'running' | 'exited';\n exitCode: number | null;\n output: string[];\n startedAt: string;\n endedAt?: string;\n process: ChildProcess;\n}\n\nconst processes: Map<string, ManagedProcess> = new Map();\nconst MAX_OUTPUT_LINES = 500;\n\nexport function registerProcessSkill(): void {\n // exec — execute commands with background support\n registerSkill(\n { name: 'exec', description: 'Execute commands with background/timeout support', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'exec',\n description: 'Execute a shell command. Supports background execution (returns immediately with sessionId), timeouts, and PTY mode. Use the process tool to poll/kill background processes.',\n parameters: {\n type: 'object',\n properties: {\n command: { type: 'string', description: 'Shell command to execute' },\n background: { type: 'boolean', description: 'Run in background (default: false)' },\n timeout: { type: 'number', description: 'Timeout in seconds (default: 30, max: 1800)' },\n cwd: { type: 'string', description: 'Working directory' },\n },\n required: ['command'],\n },\n execute: async (args) => {\n const command = args.command as string;\n const background = args.background as boolean || false;\n const timeout = Math.min((args.timeout as number) || 30, 1800) * 1000;\n const cwd = args.cwd as string || process.cwd();\n\n if (background) {\n const id = uuid().slice(0, 8);\n const child = spawn('bash', ['-c', command], { cwd, stdio: 'pipe' });\n const managed: ManagedProcess = {\n id,\n command,\n pid: child.pid || 0,\n status: 'running',\n exitCode: null,\n output: [],\n startedAt: new Date().toISOString(),\n process: child,\n };\n\n child.stdout?.on('data', (data: Buffer) => {\n const lines = data.toString().split('\\n');\n managed.output.push(...lines);\n if (managed.output.length > MAX_OUTPUT_LINES) {\n managed.output = managed.output.slice(-MAX_OUTPUT_LINES);\n }\n });\n child.stderr?.on('data', (data: Buffer) => {\n managed.output.push(...data.toString().split('\\n'));\n });\n child.on('exit', (code) => {\n managed.status = 'exited';\n managed.exitCode = code;\n managed.endedAt = new Date().toISOString();\n });\n\n processes.set(id, managed);\n logger.info(COMPONENT, `Background process started: ${id} (PID: ${managed.pid})`);\n return `Process started in background.\\nSession ID: ${id}\\nPID: ${managed.pid}\\nUse the \"process\" tool to poll, log, or kill this process.`;\n }\n\n // Synchronous execution\n return new Promise<string>((resolve) => {\n exec(command, { cwd, timeout, maxBuffer: 1024 * 1024 * 5 }, (err, stdout, stderr) => {\n if (err && err.killed) {\n resolve(`Command timed out after ${timeout / 1000}s.\\n\\nPartial output:\\n${stdout.slice(0, 5000)}`);\n return;\n }\n const output = (stdout + (stderr ? `\\nSTDERR:\\n${stderr}` : '')).trim();\n if (err) {\n resolve(`Exit code: ${err.code}\\n${output.slice(0, 10000)}`);\n } else {\n resolve(output.slice(0, 10000) || '(no output)');\n }\n });\n });\n },\n },\n );\n\n // process — manage background processes\n registerSkill(\n { name: 'process', description: 'Manage background processes', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'process',\n description: 'Manage background processes: list running processes, poll for output, view logs, write to stdin, kill, or clear completed processes.',\n parameters: {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['list', 'poll', 'log', 'write', 'kill', 'clear', 'remove'],\n description: 'Action to perform',\n },\n sessionId: { type: 'string', description: 'Process session ID (for poll/log/write/kill/remove)' },\n input: { type: 'string', description: 'Input to write to process stdin (for write action)' },\n limit: { type: 'number', description: 'Number of log lines to return (for log action, default: 50)' },\n },\n required: ['action'],\n },\n execute: async (args) => {\n const action = args.action as string;\n\n switch (action) {\n case 'list': {\n const procs = Array.from(processes.values());\n if (procs.length === 0) return 'No managed processes.';\n return procs.map((p) =>\n `• ${p.id} | PID: ${p.pid} | ${p.status} | cmd: ${p.command.slice(0, 80)} | started: ${p.startedAt}${p.exitCode !== null ? ` | exit: ${p.exitCode}` : ''}`\n ).join('\\n');\n }\n case 'poll': {\n const proc = processes.get(args.sessionId as string);\n if (!proc) return `Process ${args.sessionId} not found.`;\n const lastLines = proc.output.slice(-20).join('\\n');\n return `Status: ${proc.status}${proc.exitCode !== null ? ` (exit: ${proc.exitCode})` : ''}\\nOutput (last 20 lines):\\n${lastLines || '(no output yet)'}`;\n }\n case 'log': {\n const proc = processes.get(args.sessionId as string);\n if (!proc) return `Process ${args.sessionId} not found.`;\n const limit = (args.limit as number) || 50;\n return proc.output.slice(-limit).join('\\n') || '(no output)';\n }\n case 'write': {\n const proc = processes.get(args.sessionId as string);\n if (!proc || proc.status !== 'running') return `Process ${args.sessionId} not running.`;\n const input = args.input as string;\n if (!input) return 'No input provided.';\n proc.process.stdin?.write(input + '\\n');\n return `Wrote to stdin: ${input}`;\n }\n case 'kill': {\n const proc = processes.get(args.sessionId as string);\n if (!proc) return `Process ${args.sessionId} not found.`;\n proc.process.kill('SIGTERM');\n setTimeout(() => proc.process.kill('SIGKILL'), 5000);\n return `Sent SIGTERM to process ${proc.id} (PID: ${proc.pid})`;\n }\n case 'clear': {\n const cleared = Array.from(processes.values()).filter((p) => p.status === 'exited');\n for (const p of cleared) processes.delete(p.id);\n return `Cleared ${cleared.length} completed processes.`;\n }\n case 'remove': {\n if (processes.delete(args.sessionId as string)) {\n return `Removed process ${args.sessionId}.`;\n }\n return `Process ${args.sessionId} not found.`;\n }\n default:\n return `Unknown action: ${action}`;\n }\n },\n },\n );\n}\n","/**\n * TITAN — Web Fetch Skill (Built-in)\n * Fetch any URL and extract content as markdown or text.\n * Matches OpenClaw's web_fetch tool.\n */\nimport { registerSkill } from '../registry.js';\nimport { exec } from 'child_process';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'WebFetch';\n\n/** Convert HTML to clean readable text */\nfunction htmlToText(html: string): string {\n return html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<\\/p>/gi, '\\n\\n')\n .replace(/<\\/div>/gi, '\\n')\n .replace(/<\\/h[1-6]>/gi, '\\n\\n')\n .replace(/<li>/gi, '• ')\n .replace(/<\\/li>/gi, '\\n')\n .replace(/<[^>]*>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\n/** Convert HTML to simple markdown */\nfunction htmlToMarkdown(html: string): string {\n let md = html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, '');\n\n // Headers\n md = md.replace(/<h1[^>]*>(.*?)<\\/h1>/gi, '# $1\\n');\n md = md.replace(/<h2[^>]*>(.*?)<\\/h2>/gi, '## $1\\n');\n md = md.replace(/<h3[^>]*>(.*?)<\\/h3>/gi, '### $1\\n');\n md = md.replace(/<h4[^>]*>(.*?)<\\/h4>/gi, '#### $1\\n');\n // Links\n md = md.replace(/<a[^>]*href=\"([^\"]*)\"[^>]*>(.*?)<\\/a>/gi, '[$2]($1)');\n // Bold/italic\n md = md.replace(/<(strong|b)>(.*?)<\\/\\1>/gi, '**$2**');\n md = md.replace(/<(em|i)>(.*?)<\\/\\1>/gi, '*$2*');\n // Code\n md = md.replace(/<code>(.*?)<\\/code>/gi, '`$1`');\n md = md.replace(/<pre>([\\s\\S]*?)<\\/pre>/gi, '```\\n$1\\n```\\n');\n // Lists\n md = md.replace(/<li>/gi, '- ');\n md = md.replace(/<\\/li>/gi, '\\n');\n // Images\n md = md.replace(/<img[^>]*alt=\"([^\"]*)\"[^>]*src=\"([^\"]*)\"[^>]*>/gi, '![$1]($2)');\n md = md.replace(/<img[^>]*src=\"([^\"]*)\"[^>]*alt=\"([^\"]*)\"[^>]*>/gi, '![$2]($1)');\n // Remaining tags\n md = md.replace(/<br\\s*\\/?>/gi, '\\n');\n md = md.replace(/<\\/p>/gi, '\\n\\n');\n md = md.replace(/<[^>]*>/g, '');\n // Entities\n md = md.replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');\n md = md.replace(/\\n{3,}/g, '\\n\\n');\n return md.trim();\n}\n\nexport function registerWebFetchSkill(): void {\n registerSkill(\n { name: 'web_fetch', description: 'Fetch URL content', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'web_fetch',\n description: 'Fetch a URL and extract its content as markdown or plain text. Good for reading documentation, articles, and web pages. For JS-heavy sites, prefer the browser tool.',\n parameters: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'URL to fetch' },\n extractMode: { type: 'string', enum: ['markdown', 'text'], description: 'Output format (default: markdown)' },\n maxChars: { type: 'number', description: 'Max characters to return (default: 50000)' },\n },\n required: ['url'],\n },\n execute: async (args) => {\n const url = args.url as string;\n const mode = (args.extractMode as string) || 'markdown';\n const maxChars = Math.min((args.maxChars as number) || 50000, 100000);\n\n return new Promise<string>((resolve) => {\n exec(\n `curl -sL --max-time 20 -A \"Mozilla/5.0 (compatible; TITAN/1.0)\" \"${url}\" | head -c 200000`,\n { timeout: 25000, maxBuffer: 1024 * 1024 * 5 },\n (err, stdout) => {\n if (err) {\n resolve(`Error fetching ${url}: ${err.message}`);\n return;\n }\n if (!stdout.trim()) {\n resolve(`Empty response from ${url}`);\n return;\n }\n\n // Extract title\n const title = stdout.match(/<title[^>]*>(.*?)<\\/title>/i)?.[1] || 'Untitled';\n\n // Convert\n const content = mode === 'markdown' ? htmlToMarkdown(stdout) : htmlToText(stdout);\n\n resolve(`# ${title}\\n\\nSource: ${url}\\n\\n${content.slice(0, maxChars)}`);\n },\n );\n });\n },\n },\n );\n}\n","/**\n * TITAN — Apply Patch Skill (Built-in)\n * Apply unified diff patches to files. Matches OpenClaw's apply_patch tool.\n */\nimport { registerSkill } from '../registry.js';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { dirname } from 'path';\nimport { ensureDir } from '../../utils/helpers.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'ApplyPatch';\n\nexport function registerApplyPatchSkill(): void {\n registerSkill(\n { name: 'apply_patch', description: 'Apply unified diff patches to files', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'apply_patch',\n description: 'Apply a unified diff patch to one or more files. The patch should be in unified diff format (like git diff output). Creates new files if they don\\'t exist.',\n parameters: {\n type: 'object',\n properties: {\n patch: { type: 'string', description: 'Unified diff patch content' },\n cwd: { type: 'string', description: 'Working directory for relative paths' },\n },\n required: ['patch'],\n },\n execute: async (args) => {\n const patch = args.patch as string;\n const cwd = (args.cwd as string) || process.cwd();\n const results: string[] = [];\n\n // Parse the unified diff\n const filePatches = patch.split(/^diff --git/m).filter(Boolean);\n\n if (filePatches.length === 0) {\n // Try simple --- / +++ format\n return applySimplePatch(patch, cwd);\n }\n\n for (const filePatch of filePatches) {\n try {\n // Extract file path from --- or +++ lines\n const oldFile = filePatch.match(/^--- a\\/(.+)$/m)?.[1];\n const newFile = filePatch.match(/^\\+\\+\\+ b\\/(.+)$/m)?.[1];\n const targetFile = newFile || oldFile;\n\n if (!targetFile) {\n results.push(`⚠️ Could not determine target file`);\n continue;\n }\n\n const fullPath = targetFile.startsWith('/') ? targetFile : `${cwd}/${targetFile}`;\n const isNewFile = oldFile === '/dev/null' || !existsSync(fullPath);\n\n if (isNewFile) {\n // Extract added lines\n const addedLines = filePatch\n .split('\\n')\n .filter((l) => l.startsWith('+') && !l.startsWith('+++'))\n .map((l) => l.slice(1))\n .join('\\n');\n\n ensureDir(dirname(fullPath));\n writeFileSync(fullPath, addedLines, 'utf-8');\n results.push(`✅ Created: ${targetFile}`);\n } else {\n // Apply hunks\n let content = readFileSync(fullPath, 'utf-8');\n const hunks = filePatch.match(/@@ .+ @@[\\s\\S]*?(?=@@ |$)/g) || [];\n\n for (const hunk of hunks) {\n const lines = hunk.split('\\n').slice(1); // Skip @@ header\n const removeLines = lines.filter((l) => l.startsWith('-')).map((l) => l.slice(1));\n const addLines = lines.filter((l) => l.startsWith('+')).map((l) => l.slice(1));\n\n // Find and replace the removed lines with added lines\n for (const removeLine of removeLines) {\n if (removeLine.trim()) {\n content = content.replace(removeLine, '');\n }\n }\n // Add new lines at approximately the right location\n if (addLines.length > 0) {\n const contextLine = lines.find((l) => !l.startsWith('+') && !l.startsWith('-'))?.trim();\n if (contextLine) {\n const idx = content.indexOf(contextLine);\n if (idx >= 0) {\n content = content.slice(0, idx) + addLines.join('\\n') + '\\n' + content.slice(idx);\n } else {\n content += '\\n' + addLines.join('\\n');\n }\n } else {\n content += '\\n' + addLines.join('\\n');\n }\n }\n }\n\n writeFileSync(fullPath, content, 'utf-8');\n results.push(`✅ Patched: ${targetFile} (${hunks.length} hunk(s))`);\n }\n } catch (error) {\n results.push(`❌ Error: ${(error as Error).message}`);\n }\n }\n\n return results.join('\\n') || 'No changes applied.';\n },\n },\n );\n}\n\n/** Apply a simple patch without git diff headers */\nfunction applySimplePatch(patch: string, cwd: string): string {\n const oldFileMatch = patch.match(/^--- (.+)$/m);\n const newFileMatch = patch.match(/^\\+\\+\\+ (.+)$/m);\n\n if (!newFileMatch) return 'Could not parse patch: no +++ line found.';\n\n let targetPath = newFileMatch[1].replace(/^b\\//, '');\n if (!targetPath.startsWith('/')) targetPath = `${cwd}/${targetPath}`;\n\n const addedLines = patch\n .split('\\n')\n .filter((l) => l.startsWith('+') && !l.startsWith('+++'))\n .map((l) => l.slice(1));\n\n const removedLines = patch\n .split('\\n')\n .filter((l) => l.startsWith('-') && !l.startsWith('---'))\n .map((l) => l.slice(1));\n\n if (existsSync(targetPath)) {\n let content = readFileSync(targetPath, 'utf-8');\n for (const line of removedLines) {\n content = content.replace(line + '\\n', '');\n }\n if (addedLines.length > 0) {\n content += addedLines.join('\\n') + '\\n';\n }\n writeFileSync(targetPath, content, 'utf-8');\n return `✅ Patched: ${targetPath}`;\n } else {\n ensureDir(dirname(targetPath));\n writeFileSync(targetPath, addedLines.join('\\n') + '\\n', 'utf-8');\n return `✅ Created: ${targetPath}`;\n }\n}\n","/**\n * TITAN — Skill Auto-Generation Engine\n * Allows TITAN to dynamically write, validate, and install its own TypeScript tools\n * when it encounters a task it doesn't currently have a skill for.\n */\nimport path from 'path';\nimport { existsSync, writeFileSync, mkdirSync } from 'fs';\nimport { loadConfig } from '../config/config.js';\nimport { chat } from '../providers/router.js';\nimport type { ChatMessage } from '../providers/base.js';\nimport { TITAN_HOME } from '../utils/constants.js';\nimport { loadAutoSkills } from '../skills/registry.js';\nimport logger from '../utils/logger.js';\nimport { execSync } from 'child_process';\n\nconst COMPONENT = 'SkillGenerator';\nconst AUTO_SKILLS_DIR = path.join(TITAN_HOME, 'skills', 'auto');\n\nexport interface GenerationResult {\n success: boolean;\n skillName?: string;\n filePath?: string;\n error?: string;\n}\n\nconst GENERATOR_PROMPT = `You are the core intelligence of TITAN, an elite autonomous AI agent framework.\nYour task is to generate a new, fully functional TypeScript tool (skill) based on the user's request.\n\nCRITICAL REQUIREMENTS FOR THE CODE:\n1. It MUST export a \"default\" object that implements the \"ToolConfig\" interface.\n2. It MUST use ESM imports (e.g., \"import { ... } from '...'\").\n3. It CAN ONLY use built-in Node.js modules (fs, path, crypto, child_process, os, http, https, url) unless you are absolutely certain a specific npm package is guaranteed to be installed globally. Prefer built-ins.\n4. It MUST handle errors gracefully and return descriptive string messages.\n5. Do NOT wrap the output in markdown code blocks. Output ONLY the raw TypeScript code.\n\nHere is the exact ToolConfig interface you must implement:\nexport interface ToolConfig {\n name: string; // lowercase, alphanumeric, underscores only (e.g. 'my_custom_tool')\n description: string; // concise explanation of what the tool does\n parameters: any; // Zod schema converted to JSON schema format for LLM function calling\n execute: (args: any, config: any) => Promise<string>; // the async execution function\n}\n\nExample JSON schema for parameters (must follow this exact structure):\n{\n \"type\": \"object\",\n \"properties\": {\n \"filePath\": {\n \"type\": \"string\",\n \"description\": \"Absolute path to the file\"\n }\n },\n \"required\": [\"filePath\"]\n}\n\nExample implementation format:\nimport fs from 'fs';\n\nexport default {\n name: \"count_lines\",\n description: \"Counts the number of lines in a given text file.\",\n parameters: {\n type: \"object\",\n properties: {\n filePath: { type: \"string\" }\n },\n required: [\"filePath\"]\n },\n execute: async (args, config) => {\n try {\n const content = fs.readFileSync(args.filePath, 'utf-8');\n return \\`File has \\${content.split('\\\\n').length} lines.\\`;\n } catch (e) {\n return \\`Error: \\${e.message}\\`;\n }\n }\n};\n\nNow, generate the TypeScript code for the following requested tool capability:\n`;\n\n/**\n * Generate, validate, and install a new skill.\n */\nexport async function generateAndInstallSkill(\n description: string,\n requestedName: string\n): Promise<GenerationResult> {\n logger.info(COMPONENT, `Initiating auto-generation for skill: \"${requestedName}\"`);\n\n // Ensure auto directory exists\n if (!existsSync(AUTO_SKILLS_DIR)) {\n mkdirSync(AUTO_SKILLS_DIR, { recursive: true });\n }\n\n try {\n const config = loadConfig();\n const model = config.agent.model; // Use primary agent model to write code\n\n // 1. Generate the Code\n logger.debug(COMPONENT, `Prompting ${model} to generate code...`);\n const messages: ChatMessage[] = [\n { role: 'user', content: GENERATOR_PROMPT + `\\nRequested Capability: ${description}\\nRequested Name: ${requestedName}` }\n ];\n\n const response = await chat({ messages, model });\n let code = response.content;\n\n // Clean up markdown block if the LLM ignored instructions\n if (code.startsWith('\\`\\`\\`typescript')) {\n code = code.replace(/^\\`\\`\\`typescript\\n/, '').replace(/\\n\\`\\`\\`$/, '');\n } else if (code.startsWith('\\`\\`\\`')) {\n code = code.replace(/^\\`\\`\\`\\n/, '').replace(/\\n\\`\\`\\`$/, '');\n }\n\n // 2. Static Analysis / Safety Check (Basic)\n // Prevent obvious malicious generation (e.g., trying to modify TITAN itself)\n if (code.includes('process.exit') || code.includes('rm -rf /*') || code.includes('fs.rmSync(\\'/\\'')) {\n return { success: false, error: \"Generated code failed safety static analysis.\" };\n }\n\n // Extract the name from the generated code (fallback to requestedName)\n const nameMatch = code.match(/name:\\s*['\"]([a-z0-9_]+)['\"]/);\n const finalName = nameMatch ? nameMatch[1] : requestedName.replace(/[^a-z0-9_]/g, '_');\n\n const tsFilePath = path.join(AUTO_SKILLS_DIR, `${finalName}.ts`);\n const jsFilePath = path.join(AUTO_SKILLS_DIR, `${finalName}.js`);\n\n // 3. Write to disk\n writeFileSync(tsFilePath, code, 'utf-8');\n logger.info(COMPONENT, `Wrote generated source to ${tsFilePath}`);\n\n // 4. Compile it exactly like TITAN does (tsc)\n try {\n // Use tsx or tsc to compile it to JS so Node can load it dynamically\n // We'll write a tiny compiler script or use tsc directly if available globally\n execSync(`npx tsc ${tsFilePath} --module NodeNext --moduleResolution NodeNext --target ES2022`, { stdio: 'pipe' });\n logger.info(COMPONENT, `Compiled ${finalName}.ts successfully.`);\n } catch (compileError: any) {\n logger.error(COMPONENT, `Compilation failed for ${finalName}`);\n return { success: false, error: `Compilation failed: ${compileError.message || 'Unknown error'}` };\n }\n\n if (!existsSync(jsFilePath)) {\n return { success: false, error: \"Compilation did not produce a .js file.\" };\n }\n\n // 5. Reload Skills Registry\n // By calling loadAutoSkills, it will pick up the new .js file if we ensure it scans the auto dir\n await loadAutoSkills();\n\n logger.info(COMPONENT, `✨ Successfully generated and installed new skill: ${finalName}`);\n\n return {\n success: true,\n skillName: finalName,\n filePath: tsFilePath\n };\n\n } catch (e: any) {\n logger.error(COMPONENT, `Auto-generation failed: ${e.message}`);\n return { success: false, error: e.message };\n }\n}\n","import { registerSkill } from '../registry.js';\nimport type { ToolHandler } from '../../agent/toolRunner.js';\nimport { generateAndInstallSkill } from '../../agent/generator.js';\n\nconst meta = {\n name: 'auto_generate_skill',\n description: 'Auto-generates, compiles, and installs a new TypeScript tool/skill when TITAN lacks a necessary capability.',\n version: '1.0.0',\n source: 'bundled' as const,\n enabled: true,\n};\n\nconst handler: ToolHandler = {\n name: 'auto_generate_skill',\n description: 'Use this tool to write a NEW skill/tool when you realize you cannot complete the user request with your standard tools. Generates real TypeScript code, compiles it, and hot-reloads it into your capabilities.',\n parameters: {\n type: 'object',\n properties: {\n capability_description: {\n type: 'string',\n description: 'A detailed explanation of exactly what this new tool should do, what arguments it should take, and what it should return.',\n },\n suggested_name: {\n type: 'string',\n description: 'A short, lowercase name with underscores for the new tool (e.g., \"parse_csv\", \"resize_image\").',\n },\n },\n required: ['capability_description', 'suggested_name'],\n },\n execute: async (args: Record<string, unknown>) => {\n const capability = args.capability_description as string;\n const name = args.suggested_name as string;\n\n if (!capability || !name) {\n return \"Error: missing required arguments capability_description or suggested_name.\";\n }\n\n const result = await generateAndInstallSkill(capability, name);\n if (result.success) {\n return `✨ SUCCESS! New skill '${result.skillName}' has been generated, compiled, and hot-loaded into your tools. You can now use this tool natively!`;\n } else {\n return `Failed to generate skill: ${result.error}`;\n }\n },\n};\n\nexport function registerAutoGenerateSkill(): void {\n registerSkill(meta, handler);\n}\n","/**\n * TITAN — Vision Tool\n * Allows the agent to \"see\" by sending local images to vision-capable models (Claude 3.5 Sonnet / GPT-4o).\n */\nimport { readFileSync, existsSync } from 'fs';\nimport { extname } from 'path';\nimport { registerSkill } from '../registry.js';\nimport type { ToolHandler } from '../../agent/toolRunner.js';\nimport { loadConfig } from '../../config/config.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'VisionTool';\n\nconst meta = {\n name: 'analyze_image',\n description: 'Analyzes an image file from the local filesystem to answer a question or describe it.',\n version: '1.0.0',\n source: 'bundled' as const,\n enabled: true,\n};\n\nfunction getMediaType(filePath: string): string {\n const ext = extname(filePath).toLowerCase();\n switch (ext) {\n case '.png': return 'image/png';\n case '.jpg':\n case '.jpeg': return 'image/jpeg';\n case '.webp': return 'image/webp';\n case '.gif': return 'image/gif';\n default: return 'image/jpeg';\n }\n}\n\nasync function analyzeWithAnthropic(base64Data: string, mediaType: string, prompt: string, apiKey: string): Promise<string> {\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify({\n model: 'claude-3-5-sonnet-20241022',\n max_tokens: 1024,\n messages: [\n {\n role: 'user',\n content: [\n {\n type: 'image',\n source: {\n type: 'base64',\n media_type: mediaType,\n data: base64Data,\n }\n },\n {\n type: 'text',\n text: prompt\n }\n ]\n }\n ]\n })\n });\n\n if (!response.ok) {\n throw new Error(`Anthropic Vision API error: ${await response.text()}`);\n }\n\n const data = await response.json() as any;\n return data.content[0].text;\n}\n\nasync function analyzeWithOpenAI(base64Data: string, mediaType: string, prompt: string, apiKey: string): Promise<string> {\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model: 'gpt-4o',\n max_tokens: 1024,\n messages: [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text: prompt\n },\n {\n type: 'image_url',\n image_url: {\n url: `data:${mediaType};base64,${base64Data}`\n }\n }\n ]\n }\n ]\n })\n });\n\n if (!response.ok) {\n throw new Error(`OpenAI Vision API error: ${await response.text()}`);\n }\n\n const data = await response.json() as any;\n return data.choices[0].message.content;\n}\n\nconst handler: ToolHandler = {\n name: 'analyze_image',\n description: 'Use this tool to \"look\" at an image. Pass the absolute filepath to the image and a specific question or prompt about what you want to know.',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'The absolute local path to the image file (png, jpg, webp, gif).',\n },\n prompt: {\n type: 'string',\n description: 'What you want to know about the image (e.g. \"Describe this image in detail\", \"What text is in this image?\", \"Is there a cat here?\").',\n },\n },\n required: ['filePath', 'prompt'],\n },\n execute: async (args: Record<string, unknown>) => {\n const filePath = args.filePath as string;\n const prompt = args.prompt as string;\n\n if (!filePath || !prompt) {\n return \"Error: missing required arguments filePath or prompt.\";\n }\n\n if (!existsSync(filePath)) {\n return `Error: File not found at ${filePath}`;\n }\n\n try {\n logger.info(COMPONENT, `Reading image ${filePath} for analysis...`);\n const fileBuffer = readFileSync(filePath);\n const base64Data = fileBuffer.toString('base64');\n const mediaType = getMediaType(filePath);\n\n const config = loadConfig();\n\n if (config.providers.anthropic && config.providers.anthropic.apiKey) {\n logger.debug(COMPONENT, 'Using Anthropic Claude 3.5 Sonnet for vision');\n return await analyzeWithAnthropic(base64Data, mediaType, prompt, config.providers.anthropic.apiKey);\n }\n else if (config.providers.openai && config.providers.openai.apiKey) {\n logger.debug(COMPONENT, 'Using OpenAI GPT-4o for vision');\n return await analyzeWithOpenAI(base64Data, mediaType, prompt, config.providers.openai.apiKey);\n }\n else {\n return \"Error: Vision tool requires either an Anthropic or OpenAI API key configured in TITAN.\";\n }\n } catch (e: any) {\n return `Vision Analysis Failed: ${e.message}`;\n }\n },\n};\n\nexport function registerVisionSkill(): void {\n registerSkill(meta, handler);\n}\n","/**\n * TITAN — Voice Tools\n * Provides Speech-to-Text (STT) and Text-to-Speech (TTS) capabilities using OpenAI APIs.\n */\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { tmpdir } from 'os';\nimport { v4 as uuid } from 'uuid';\nimport { registerSkill } from '../registry.js';\nimport type { ToolHandler } from '../../agent/toolRunner.js';\nimport { loadConfig } from '../../config/config.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'VoiceTool';\n\nconst metaSTT = {\n name: 'transcribe_audio',\n description: 'Transcribes an audio file (mp3, wav, ogg, m4a) into text using OpenAI Whisper.',\n version: '1.0.0',\n source: 'bundled' as const,\n enabled: true,\n};\n\nconst metaTTS = {\n name: 'generate_speech',\n description: 'Converts text into spoken audio (mp3) using OpenAI TTS.',\n version: '1.0.0',\n source: 'bundled' as const,\n enabled: true,\n};\n\nconst sttHandler: ToolHandler = {\n name: 'transcribe_audio',\n description: 'Reads an audio file from the filesystem and transcribes the speech into text. Extremely useful if a user sends a voice note.',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'The absolute path to the audio file (supported formats: mp3, mp4, mpeg, mpga, m4a, wav, webm, ogg).',\n }\n },\n required: ['filePath'],\n },\n execute: async (args: Record<string, unknown>) => {\n const filePath = args.filePath as string;\n if (!filePath || !existsSync(filePath)) {\n return `Error: Audio file not found at ${filePath}`;\n }\n\n const config = loadConfig();\n const apiKey = config.providers.openai?.apiKey;\n if (!apiKey) {\n return \"Error: OpenAI API key is missing. Voice transcription requires OpenAI.\";\n }\n\n try {\n logger.info(COMPONENT, `Transcribing audio file: ${filePath}`);\n\n const fileBuffer = readFileSync(filePath);\n const blob = new Blob([fileBuffer]);\n const formData = new FormData();\n formData.append('file', blob, 'audio.ogg'); // The extension hints the format to Whisper\n formData.append('model', 'whisper-1');\n\n const response = await fetch('https://api.openai.com/v1/audio/transcriptions', {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${apiKey}`\n },\n body: formData\n });\n\n if (!response.ok) {\n throw new Error(`OpenAI STT error: ${await response.text()}`);\n }\n\n const data = await response.json() as { text: string };\n return `Transcript: \"${data.text}\"`;\n } catch (e: any) {\n logger.error(COMPONENT, `Transcription failed: ${e.message}`);\n return `Error transcribing audio: ${e.message}`;\n }\n }\n};\n\nconst ttsHandler: ToolHandler = {\n name: 'generate_speech',\n description: 'Generates spoken audio from text and saves it as an MP3 file. Useful if the user asks you to read something out loud or send a voice message.',\n parameters: {\n type: 'object',\n properties: {\n text: {\n type: 'string',\n description: 'The text you want to convert to speech.',\n },\n voice: {\n type: 'string',\n description: 'The voice to use. Options: alloy, echo, fable, onyx, nova, shimmer. Default is alloy.',\n }\n },\n required: ['text'],\n },\n execute: async (args: Record<string, unknown>) => {\n const text = args.text as string;\n const voice = (args.voice as string) || 'alloy';\n\n if (!text) return \"Error: You must provide text to generate speech.\";\n\n const config = loadConfig();\n const apiKey = config.providers.openai?.apiKey;\n if (!apiKey) {\n return \"Error: OpenAI API key is missing. TTS requires OpenAI.\";\n }\n\n try {\n logger.info(COMPONENT, `Generating speech with voice ${voice}`);\n\n const response = await fetch('https://api.openai.com/v1/audio/speech', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`\n },\n body: JSON.stringify({\n model: 'tts-1',\n input: text,\n voice: voice\n })\n });\n\n if (!response.ok) {\n throw new Error(`OpenAI TTS error: ${await response.text()}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n\n const tmpPath = join(tmpdir(), `titan_voice_${uuid().substring(0, 8)}.mp3`);\n writeFileSync(tmpPath, buffer);\n\n return `Success. Generated MP3 audio file saved to: ${tmpPath}`;\n } catch (e: any) {\n logger.error(COMPONENT, `TTS failed: ${e.message}`);\n return `Error generating speech: ${e.message}`;\n }\n }\n};\n\nexport function registerVoiceSkills(): void {\n registerSkill(metaSTT, sttHandler);\n registerSkill(metaTTS, ttsHandler);\n}\n","/**\n * TITAN — Skills Registry\n * Discovers, loads, and manages skills from bundled, workspace, and marketplace sources.\n */\nimport { existsSync, readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { TITAN_HOME, TITAN_SKILLS_DIR } from '../utils/constants.js';\nimport { registerTool, type ToolHandler } from '../agent/toolRunner.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Skills';\n\nexport interface SkillMeta {\n name: string;\n description: string;\n version: string;\n author?: string;\n source: 'bundled' | 'workspace' | 'marketplace';\n enabled: boolean;\n}\n\nconst registeredSkills: Map<string, SkillMeta> = new Map();\n\n/** Register a built-in skill (tool handler + metadata) */\nexport function registerSkill(meta: SkillMeta, handler: ToolHandler): void {\n registeredSkills.set(meta.name, meta);\n registerTool(handler);\n logger.debug(COMPONENT, `Registered skill: ${meta.name} (${meta.source})`);\n}\n\n/** Get all registered skills */\nexport function getSkills(): SkillMeta[] {\n return Array.from(registeredSkills.values());\n}\n\n/** Get a skill by name */\nexport function getSkill(name: string): SkillMeta | undefined {\n return registeredSkills.get(name);\n}\n\n/** Discover workspace skills from ~/.titan/workspace/skills/ */\nexport function discoverWorkspaceSkills(): SkillMeta[] {\n ensureDir(TITAN_SKILLS_DIR);\n const discovered: SkillMeta[] = [];\n\n if (!existsSync(TITAN_SKILLS_DIR)) return discovered;\n\n const entries = readdirSync(TITAN_SKILLS_DIR, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillDir = join(TITAN_SKILLS_DIR, entry.name);\n const skillMdPath = join(skillDir, 'SKILL.md');\n\n if (!existsSync(skillMdPath)) continue;\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n const meta = parseSkillMd(content, entry.name);\n if (meta) {\n discovered.push({ ...meta, source: 'workspace', enabled: true });\n }\n } catch (error) {\n logger.warn(COMPONENT, `Failed to load skill ${entry.name}: ${(error as Error).message}`);\n }\n }\n\n logger.info(COMPONENT, `Discovered ${discovered.length} workspace skills`);\n return discovered;\n}\n\n/** Parse SKILL.md frontmatter to extract metadata */\nfunction parseSkillMd(content: string, fallbackName: string): Omit<SkillMeta, 'source' | 'enabled'> | null {\n const frontmatterMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!frontmatterMatch) {\n return {\n name: fallbackName,\n description: content.split('\\n')[0] || 'No description',\n version: '1.0.0',\n };\n }\n\n const frontmatter = frontmatterMatch[1];\n const name = frontmatter.match(/name:\\s*(.+)/)?.[1]?.trim() || fallbackName;\n const description = frontmatter.match(/description:\\s*(.+)/)?.[1]?.trim() || 'No description';\n const version = frontmatter.match(/version:\\s*(.+)/)?.[1]?.trim() || '1.0.0';\n const author = frontmatter.match(/author:\\s*(.+)/)?.[1]?.trim();\n\n return { name, description, version, author };\n}\n\n/** Initialize all built-in skills */\nexport async function initBuiltinSkills(): Promise<void> {\n logger.info(COMPONENT, 'Loading built-in skills...');\n\n // Import and register built-in skills\n const { registerShellSkill } = await import('./builtin/shell.js');\n const { registerFilesystemSkill } = await import('./builtin/filesystem.js');\n const { registerWebSearchSkill } = await import('./builtin/web_search.js');\n const { registerCronSkill } = await import('./builtin/cron.js');\n const { registerWebhookSkill } = await import('./builtin/webhook.js');\n const { registerMemorySkill } = await import('./builtin/memory_skill.js');\n const { registerBrowserSkill } = await import('./builtin/browser.js');\n const { registerSessionsSkill } = await import('./builtin/sessions.js');\n const { registerProcessSkill } = await import('./builtin/process.js');\n const { registerWebFetchSkill } = await import('./builtin/web_fetch.js');\n const { registerApplyPatchSkill } = await import('./builtin/apply_patch.js');\n const { registerAutoGenerateSkill } = await import('./builtin/auto_generate.js');\n const { registerVisionSkill } = await import('./builtin/vision.js');\n const { registerVoiceSkills } = await import('./builtin/voice.js');\n\n registerShellSkill();\n registerFilesystemSkill();\n registerWebSearchSkill();\n registerCronSkill();\n registerWebhookSkill();\n registerMemorySkill();\n registerBrowserSkill();\n registerSessionsSkill();\n registerProcessSkill();\n registerWebFetchSkill();\n registerApplyPatchSkill();\n registerAutoGenerateSkill();\n registerVisionSkill();\n registerVoiceSkills();\n\n logger.info(COMPONENT, `Loaded ${registeredSkills.size} built-in skills`);\n}\n\n/** \n * Discover and load auto-generated skills from ~/.titan/skills/auto/\n */\nexport async function loadAutoSkills(): Promise<void> {\n const autoDir = join(TITAN_HOME, 'skills', 'auto');\n if (!existsSync(autoDir)) return;\n\n logger.info(COMPONENT, 'Checking for auto-generated skills...');\n const files = readdirSync(autoDir).filter(f => f.endsWith('.js'));\n\n let loadedCount = 0;\n for (const file of files) {\n try {\n const skillPath = join(autoDir, file);\n // Append cache buster to force hot-reload of ES modules\n const modulePath = `file://${skillPath}?t=${Date.now()}`;\n const mod = await import(modulePath);\n\n if (mod.default && mod.default.name && mod.default.execute) {\n const handler = mod.default as ToolHandler;\n\n // Add to our registry metadata\n const meta: SkillMeta = {\n name: handler.name,\n description: handler.description || 'Auto-generated skill',\n version: '1.0.0',\n source: 'workspace', // Consider it part of user workspace\n enabled: true,\n };\n\n registerSkill(meta, handler);\n loadedCount++;\n }\n } catch (e: any) {\n logger.error(COMPONENT, `Failed to load auto skill ${file}: ${e.message}`);\n }\n }\n\n if (loadedCount > 0) {\n logger.info(COMPONENT, `Successfully loaded ${loadedCount} auto-generated skills`);\n }\n}\n","/**\n * TITAN — Gateway Server\n * WebSocket + HTTP server: the control plane for all channels, agents, tools, and the web UI.\n */\nimport express from 'express';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createServer } from 'http';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { loadConfig } from '../config/config.js';\nimport { processMessage } from '../agent/agent.js';\nimport { initMemory, getUsageStats } from '../memory/memory.js';\nimport { initBuiltinSkills, getSkills } from '../skills/registry.js';\nimport { getRegisteredTools } from '../agent/toolRunner.js';\nimport { listSessions } from '../agent/session.js';\nimport { healthCheckAll } from '../providers/router.js';\nimport { auditSecurity } from '../security/sandbox.js';\nimport { WebChatChannel, getOutboundQueue } 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 { initAgents, routeMessage, listAgents, spawnAgent, stopAgent, getAgentCapacity } from '../agent/multiAgent.js';\nimport type { ChannelAdapter, InboundMessage } from '../channels/base.js';\nimport logger from '../utils/logger.js';\nimport { TITAN_VERSION, TITAN_NAME } from '../utils/constants.js';\nimport { getMissionControlHTML } from './dashboard.js';\n\nconst COMPONENT = 'Gateway';\n\n/** All active channel adapters */\nconst channels: Map<string, ChannelAdapter> = new Map();\n\n/** All connected WebSocket clients */\nconst wsClients: Set<WebSocket> = new Set();\n\n/** The WebChat channel instance */\nlet webChatChannel: WebChatChannel | null = null;\n\n/** Broadcast a message to all WebSocket clients */\nfunction broadcast(data: Record<string, unknown>): void {\n const json = JSON.stringify(data);\n for (const client of wsClients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(json);\n }\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 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 const channel = channels.get(msg.channel);\n if (channel) {\n await channel.send({\n channel: msg.channel,\n userId: msg.userId,\n groupId: msg.groupId,\n content: response.content,\n replyTo: msg.id,\n });\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: (error as Error).message });\n }\n}\n\n/** Get the web dashboard HTML */\nfunction getDashboardHtml(): 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.0\">\n <title>TITAN — Dashboard</title>\n <style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n :root {\n --bg: #0a0e1a; --surface: #111827; --surface-2: #1e293b;\n --border: #1e3a5f; --text: #e2e8f0; --text-dim: #94a3b8;\n --accent: #06b6d4; --accent-glow: rgba(6, 182, 212, 0.15);\n --success: #22c55e; --warn: #f59e0b; --error: #ef4444;\n }\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');\n body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; }\n .dashboard { display: grid; grid-template-columns: 280px 1fr; grid-template-rows: 60px 1fr; min-height: 100vh; }\n .header { grid-column: 1 / -1; background: var(--surface); border-bottom: 1px solid var(--border);\n display: flex; align-items: center; padding: 0 24px; gap: 16px; }\n .header h1 { font-size: 20px; font-weight: 700; background: linear-gradient(135deg, #06b6d4, #3b82f6);\n -webkit-background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: 2px; }\n .header .version { color: var(--text-dim); font-size: 12px; font-family: 'JetBrains Mono'; }\n .sidebar { background: var(--surface); border-right: 1px solid var(--border); padding: 20px 16px;\n display: flex; flex-direction: column; gap: 8px; overflow-y: auto; }\n .nav-item { padding: 10px 14px; border-radius: 8px; cursor: pointer; font-size: 14px;\n color: var(--text-dim); transition: all 0.2s; display: flex; align-items: center; gap: 10px; }\n .nav-item:hover, .nav-item.active { background: var(--accent-glow); color: var(--accent); }\n .nav-item .dot { width: 8px; height: 8px; border-radius: 50%; }\n .dot.on { background: var(--success); box-shadow: 0 0 6px var(--success); }\n .dot.off { background: var(--error); }\n .main { padding: 24px; overflow-y: auto; }\n .card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;\n padding: 20px; margin-bottom: 16px; }\n .card h2 { font-size: 16px; font-weight: 600; margin-bottom: 12px; color: var(--accent); }\n .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; }\n .stat { background: var(--surface-2); border-radius: 10px; padding: 16px; text-align: center; }\n .stat .value { font-size: 28px; font-weight: 700; color: var(--accent); font-family: 'JetBrains Mono'; }\n .stat .label { font-size: 12px; color: var(--text-dim); margin-top: 4px; text-transform: uppercase; letter-spacing: 1px; }\n .chat-container { display: flex; flex-direction: column; height: calc(100vh - 140px); }\n .chat-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; }\n .msg { max-width: 80%; padding: 12px 16px; border-radius: 12px; font-size: 14px; line-height: 1.5; word-break: break-word; }\n .msg.user { background: #1e3a5f; align-self: flex-end; border-bottom-right-radius: 4px; }\n .msg.assistant { background: var(--surface-2); align-self: flex-start; border-bottom-left-radius: 4px; border: 1px solid var(--border); }\n .msg .meta { font-size: 11px; color: var(--text-dim); margin-top: 6px; }\n .chat-input { display: flex; gap: 10px; padding: 16px; border-top: 1px solid var(--border); }\n .chat-input input { flex: 1; padding: 12px 16px; border-radius: 10px; border: 1px solid var(--border);\n background: var(--surface-2); color: var(--text); font-size: 14px; outline: none;\n font-family: 'Inter', sans-serif; transition: border-color 0.2s; }\n .chat-input input:focus { border-color: var(--accent); }\n .chat-input button { padding: 12px 24px; border-radius: 10px; border: none;\n background: linear-gradient(135deg, #06b6d4, #3b82f6); color: white; font-weight: 600;\n cursor: pointer; font-size: 14px; transition: opacity 0.2s; }\n .chat-input button:hover { opacity: 0.9; }\n .chat-input button:disabled { opacity: 0.5; cursor: not-allowed; }\n table { width: 100%; border-collapse: collapse; font-size: 13px; }\n th, td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border); }\n th { color: var(--text-dim); font-weight: 500; text-transform: uppercase; font-size: 11px; letter-spacing: 1px; }\n .badge { padding: 3px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; }\n .badge.active { background: rgba(34,197,94,0.15); color: var(--success); }\n .badge.idle { background: rgba(245,158,11,0.15); color: var(--warn); }\n .hidden { display: none; }\n @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }\n .typing { animation: pulse 1.5s infinite; color: var(--text-dim); font-style: italic; }\n </style>\n</head>\n<body>\n <div class=\"dashboard\">\n <header class=\"header\">\n <h1>⚡ TITAN</h1>\n <span class=\"version\">v${TITAN_VERSION}</span>\n <span style=\"margin-left:auto;color:var(--text-dim);font-size:13px\" id=\"status\">Connecting...</span>\n </header>\n <aside class=\"sidebar\">\n <div class=\"nav-item active\" onclick=\"showPanel('overview')\">📊 Overview</div>\n <div class=\"nav-item\" onclick=\"showPanel('chat')\">💬 WebChat</div>\n <div class=\"nav-item\" onclick=\"showPanel('agents')\">🤖 Agents</div>\n <div class=\"nav-item\" onclick=\"showPanel('sessions')\">🔗 Sessions</div>\n <div class=\"nav-item\" onclick=\"showPanel('skills')\">🧩 Skills</div>\n <div class=\"nav-item\" onclick=\"showPanel('channels')\">📡 Channels</div>\n <div class=\"nav-item\" onclick=\"showPanel('security')\">🔒 Security</div>\n </aside>\n <main class=\"main\">\n <!-- Overview Panel -->\n <div id=\"panel-overview\">\n <div class=\"stats\" id=\"stats\"></div>\n <div class=\"card\"><h2>Recent Activity</h2><div id=\"activity\">Loading...</div></div>\n </div>\n <!-- Chat Panel -->\n <div id=\"panel-chat\" class=\"hidden\">\n <div class=\"card chat-container\">\n <h2>WebChat</h2>\n <div class=\"chat-messages\" id=\"chat-messages\"></div>\n <div class=\"chat-input\">\n <input type=\"text\" id=\"chat-input\" placeholder=\"Type a message...\" onkeydown=\"if(event.key==='Enter')sendMessage()\">\n <button onclick=\"sendMessage()\" id=\"send-btn\">Send</button>\n </div>\n </div>\n </div>\n <!-- Agents Panel -->\n <div id=\"panel-agents\" class=\"hidden\"><div class=\"card\"><h2>Agent Instances (max 5)</h2><div id=\"agents-list\">Loading...</div></div></div>\n <!-- Sessions Panel -->\n <div id=\"panel-sessions\" class=\"hidden\"><div class=\"card\"><h2>Active Sessions</h2><div id=\"sessions-list\">Loading...</div></div></div>\n <!-- Skills Panel -->\n <div id=\"panel-skills\" class=\"hidden\"><div class=\"card\"><h2>Installed Skills</h2><div id=\"skills-list\">Loading...</div></div></div>\n <!-- Channels Panel -->\n <div id=\"panel-channels\" class=\"hidden\"><div class=\"card\"><h2>Channel Status</h2><div id=\"channels-list\">Loading...</div></div></div>\n <!-- Security Panel -->\n <div id=\"panel-security\" class=\"hidden\"><div class=\"card\"><h2>Security Audit</h2><div id=\"security-audit\">Loading...</div></div></div>\n </main>\n </div>\n <script>\n const ws = new WebSocket(\\`ws://\\${location.hostname}:\\${location.port}\\`);\n const chatMessages = document.getElementById('chat-messages');\n const chatInput = document.getElementById('chat-input');\n\n ws.onopen = () => { document.getElementById('status').textContent = '🟢 Connected'; fetchData(); };\n ws.onclose = () => { document.getElementById('status').textContent = '🔴 Disconnected'; };\n ws.onmessage = (e) => {\n const data = JSON.parse(e.data);\n if (data.type === 'message') {\n appendMessage(data.direction === 'inbound' ? 'user' : 'assistant', data.content, data);\n } else if (data.type === 'typing') {\n showTyping();\n }\n };\n\n function showPanel(name) {\n document.querySelectorAll('[id^=panel-]').forEach(p => p.classList.add('hidden'));\n document.getElementById('panel-' + name).classList.remove('hidden');\n document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));\n event.target.closest('.nav-item').classList.add('active');\n }\n\n function appendMessage(role, content, meta = {}) {\n const div = document.createElement('div');\n div.className = 'msg ' + role;\n div.innerHTML = content.replace(/\\\\n/g, '<br>');\n if (meta.durationMs) div.innerHTML += '<div class=\"meta\">' + meta.durationMs + 'ms</div>';\n chatMessages.appendChild(div);\n chatMessages.scrollTop = chatMessages.scrollHeight;\n document.getElementById('send-btn').disabled = false;\n }\n\n function sendMessage() {\n const content = chatInput.value.trim();\n if (!content) return;\n appendMessage('user', content);\n ws.send(JSON.stringify({ type: 'chat', content }));\n chatInput.value = '';\n document.getElementById('send-btn').disabled = true;\n }\n\n async function fetchData() {\n try {\n const [stats, sessions, skills, channelStatus, security, agentsData] = await Promise.all([\n fetch('/api/stats').then(r => r.json()),\n fetch('/api/sessions').then(r => r.json()),\n fetch('/api/skills').then(r => r.json()),\n fetch('/api/channels').then(r => r.json()),\n fetch('/api/security').then(r => r.json()),\n fetch('/api/agents').then(r => r.json()),\n ]);\n\n document.getElementById('stats').innerHTML = [\n { value: stats.totalRequests || 0, label: 'Total Requests' },\n { value: (stats.totalTokens || 0).toLocaleString(), label: 'Tokens Used' },\n { value: sessions.length || 0, label: 'Active Sessions' },\n { value: skills.length || 0, label: 'Skills Loaded' },\n ].map(s => '<div class=\"stat\"><div class=\"value\">' + s.value + '</div><div class=\"label\">' + s.label + '</div></div>').join('');\n\n document.getElementById('sessions-list').innerHTML = sessions.length === 0 ? '<p style=\"color:var(--text-dim)\">No active sessions</p>' :\n '<table><tr><th>ID</th><th>Channel</th><th>User</th><th>Messages</th><th>Status</th></tr>' +\n sessions.map(s => '<tr><td style=\"font-family:JetBrains Mono;font-size:12px\">' + s.id.slice(0,8) + '</td><td>' + s.channel + '</td><td>' + (s.user_id||s.userId||'-') + '</td><td>' + (s.message_count||s.messageCount||0) + '</td><td><span class=\"badge active\">active</span></td></tr>').join('') + '</table>';\n\n document.getElementById('skills-list').innerHTML =\n '<table><tr><th>Name</th><th>Source</th><th>Version</th><th>Status</th></tr>' +\n skills.map(s => '<tr><td>' + s.name + '</td><td>' + s.source + '</td><td>' + s.version + '</td><td><span class=\"badge active\">enabled</span></td></tr>').join('') + '</table>';\n\n document.getElementById('channels-list').innerHTML =\n '<table><tr><th>Channel</th><th>Status</th></tr>' +\n channelStatus.map(c => '<tr><td>' + c.name + '</td><td><span class=\"dot ' + (c.connected ? 'on' : 'off') + '\"></span> ' + (c.connected ? 'Connected' : 'Disconnected') + '</td></tr>').join('') + '</table>';\n\n document.getElementById('security-audit').innerHTML =\n security.map(i => '<div style=\"padding:8px 12px;margin:4px 0;border-radius:6px;background:' +\n (i.level==='error'?'rgba(239,68,68,0.1)':i.level==='warn'?'rgba(245,158,11,0.1)':'rgba(6,182,212,0.1)') +\n ';color:' + (i.level==='error'?'var(--error)':i.level==='warn'?'var(--warn)':'var(--text-dim)') +\n '\">' + (i.level==='error'?'🚨':i.level==='warn'?'⚠️':'ℹ️') + ' ' + i.message + '</div>').join('');\n\n // Agents panel\n if (agentsData && agentsData.agents) {\n document.getElementById('agents-list').innerHTML =\n '<p style=\"color:var(--text-dim);margin-bottom:12px\">Capacity: ' + agentsData.capacity.current + '/' + agentsData.capacity.max + '</p>' +\n '<table><tr><th>Name</th><th>ID</th><th>Model</th><th>Messages</th><th>Status</th></tr>' +\n agentsData.agents.map(a => '<tr><td>' + a.name + '</td><td style=\"font-family:JetBrains Mono;font-size:12px\">' + a.id + '</td><td>' + a.model + '</td><td>' + a.messageCount + '</td><td><span class=\"badge ' + (a.status==='running'?'active':'idle') + '\">' + a.status + '</span></td></tr>').join('') + '</table>';\n }\n } catch (e) { console.error('Failed to fetch data:', e); }\n }\n setInterval(fetchData, 30000);\n </script>\n</body>\n</html>`;\n}\n\n/** Start the Gateway server */\nexport async function startGateway(options?: { port?: number; host?: string; verbose?: boolean }): Promise<void> {\n const config = loadConfig();\n const port = options?.port || config.gateway.port;\n const host = options?.host || config.gateway.host;\n\n logger.info(COMPONENT, `Starting ${TITAN_NAME} Gateway v${TITAN_VERSION}`);\n\n // Initialize subsystems\n initMemory();\n await initBuiltinSkills();\n initAgents();\n\n // Create Express app\n const app = express();\n app.use(express.json());\n\n // Serve dashboard\n app.get('/', (_req, res) => {\n res.setHeader('Content-Type', 'text/html');\n res.send(getMissionControlHTML());\n });\n\n // API routes\n app.get('/api/stats', (_req, res) => {\n const stats = getUsageStats();\n res.json(stats);\n });\n\n app.get('/api/sessions', (_req, res) => {\n const sessions = listSessions();\n res.json(sessions);\n });\n\n app.get('/api/skills', (_req, res) => {\n const skills = getSkills();\n res.json(skills);\n });\n\n app.get('/api/tools', (_req, res) => {\n const tools = getRegisteredTools().map((t) => ({\n name: t.name,\n description: t.description,\n }));\n res.json(tools);\n });\n\n app.get('/api/channels', (_req, res) => {\n const statuses = Array.from(channels.values()).map((ch) => ch.getStatus());\n res.json(statuses);\n });\n\n app.get('/api/security', (_req, res) => {\n const audit = auditSecurity();\n res.json(audit);\n });\n\n app.get('/api/providers', async (_req, res) => {\n const health = await healthCheckAll();\n res.json(health);\n });\n\n app.get('/api/health', (_req, res) => {\n res.json({ status: 'ok', version: TITAN_VERSION, uptime: process.uptime() });\n });\n\n // Multi-agent endpoints\n app.get('/api/agents', (_req, res) => {\n res.json({ agents: listAgents(), capacity: getAgentCapacity() });\n });\n\n app.post('/api/agents/spawn', (req, res) => {\n const { name, model, systemPrompt } = req.body;\n if (!name) { res.status(400).json({ error: 'name is required' }); return; }\n const result = spawnAgent({ name, model, systemPrompt });\n res.json(result);\n });\n\n app.post('/api/agents/stop', (req, res) => {\n const { agentId } = req.body;\n if (!agentId) { res.status(400).json({ error: 'agentId is required' }); return; }\n const result = stopAgent(agentId);\n res.json(result);\n });\n\n // Agent message endpoint (uses multi-agent routing)\n app.post('/api/message', async (req, res) => {\n const { content, channel = 'api', userId = 'api-user' } = req.body;\n if (!content) {\n res.status(400).json({ error: 'content is required' });\n return;\n }\n try {\n const response = await routeMessage(content, channel, userId);\n res.json(response);\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n // Create HTTP server\n const server = createServer(app);\n\n // Create WebSocket server\n const wss = new WebSocketServer({ server });\n\n wss.on('connection', (ws) => {\n wsClients.add(ws);\n logger.info(COMPONENT, `WebSocket client connected (${wsClients.size} total)`);\n\n ws.on('message', async (rawData) => {\n try {\n const data = JSON.parse(rawData.toString());\n if (data.type === 'chat' && data.content) {\n // Process through WebChat channel\n 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 });\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 ];\n\n for (const [name, adapter] of channelAdapters) {\n channels.set(name, adapter);\n adapter.on('message', handleInboundMessage);\n try {\n await adapter.connect();\n } catch (error) {\n logger.debug(COMPONENT, `Channel ${name} not available: ${(error as Error).message}`);\n }\n }\n\n // Start server\n server.listen(port, host, () => {\n logger.info(COMPONENT, `Gateway listening on http://${host}:${port}`);\n logger.info(COMPONENT, `Dashboard: http://${host}:${port}`);\n logger.info(COMPONENT, `WebSocket: ws://${host}:${port}`);\n logger.info(COMPONENT, `API: http://${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}\n","/**\n * TITAN — Security & Sandbox Module\n * Permission management, tool allowlists/denylists, and session isolation.\n */\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Security';\n\nexport interface SecurityContext {\n sessionId: string;\n channel: string;\n userId: string;\n isMainSession: boolean;\n sandboxMode: string;\n allowedTools: string[];\n deniedTools: string[];\n fileSystemAllowlist: string[];\n networkAllowlist: string[];\n}\n\n/** Create a security context for a session */\nexport function createSecurityContext(\n sessionId: string,\n channel: string,\n userId: string,\n isMainSession: boolean = true,\n): SecurityContext {\n const config = loadConfig();\n const security = config.security;\n\n return {\n sessionId,\n channel,\n userId,\n isMainSession,\n sandboxMode: isMainSession ? 'host' : security.sandboxMode,\n allowedTools: security.allowedTools,\n deniedTools: security.deniedTools,\n fileSystemAllowlist: security.fileSystemAllowlist,\n networkAllowlist: security.networkAllowlist,\n };\n}\n\n/** Check if a tool is allowed in the given security context */\nexport function isToolAllowed(toolName: string, context: SecurityContext): boolean {\n // Denied tools always take priority\n if (context.deniedTools.includes(toolName)) {\n logger.debug(COMPONENT, `Tool ${toolName} denied by security policy`);\n return false;\n }\n\n // If allowlist is empty, all non-denied tools are allowed\n if (context.allowedTools.length === 0) return true;\n\n // Check allowlist\n const allowed = context.allowedTools.includes(toolName);\n if (!allowed) {\n logger.debug(COMPONENT, `Tool ${toolName} not in allowlist`);\n }\n return allowed;\n}\n\n/** Check if a file path is accessible */\nexport function isPathAllowed(filePath: string, context: SecurityContext): boolean {\n // Main sessions have full access\n if (context.isMainSession) return true;\n\n // If no allowlist, deny all file access for non-main sessions\n if (context.fileSystemAllowlist.length === 0) return false;\n\n // Check against allowlist\n return context.fileSystemAllowlist.some((allowed) =>\n filePath.startsWith(allowed) || allowed === '*'\n );\n}\n\n/** Check if a network request is allowed */\nexport function isNetworkAllowed(url: string, context: SecurityContext): boolean {\n if (context.networkAllowlist.includes('*')) return true;\n if (context.networkAllowlist.length === 0) return false;\n\n try {\n const hostname = new URL(url).hostname;\n return context.networkAllowlist.some((allowed) =>\n hostname === allowed || hostname.endsWith(`.${allowed}`)\n );\n } catch {\n return false;\n }\n}\n\n/** Validate the security configuration and report issues */\nexport function auditSecurity(): Array<{ level: 'info' | 'warn' | 'error'; message: string }> {\n const config = loadConfig();\n const issues: Array<{ level: 'info' | 'warn' | 'error'; message: string }> = [];\n\n if (config.security.sandboxMode === 'none') {\n issues.push({ level: 'warn', message: 'Sandbox mode is disabled. Non-main sessions will have full host access.' });\n }\n\n if (config.security.deniedTools.length === 0) {\n issues.push({ level: 'info', message: 'No tools are explicitly denied.' });\n }\n\n if (config.security.networkAllowlist.includes('*')) {\n issues.push({ level: 'info', message: 'Network access is unrestricted (allowlist: *).' });\n }\n\n if (config.security.commandTimeout > 60000) {\n issues.push({ level: 'warn', message: `Command timeout is very high: ${config.security.commandTimeout}ms` });\n }\n\n // Check channel DM policies\n for (const [name, channel] of Object.entries(config.channels)) {\n if (channel.enabled && channel.dmPolicy === 'open') {\n issues.push({ level: 'warn', message: `Channel \"${name}\" has open DM policy — any user can message the bot.` });\n }\n }\n\n return issues;\n}\n","/**\n * TITAN — Channel Base Interface\n * Abstract interface for all messaging channel adapters.\n */\nimport { EventEmitter } from 'events';\n\n/** Inbound message from a channel */\nexport interface InboundMessage {\n id: string;\n channel: string;\n userId: string;\n userName?: string;\n content: string;\n attachments?: Array<{ type: string; url: string; name?: string }>;\n replyTo?: string;\n groupId?: string;\n timestamp: Date;\n raw?: unknown;\n}\n\n/** Outbound message to a channel */\nexport interface OutboundMessage {\n channel: string;\n userId?: string;\n groupId?: string;\n content: string;\n replyTo?: string;\n attachments?: Array<{ type: string; data: Buffer; name: string }>;\n}\n\n/** Channel status */\nexport interface ChannelStatus {\n name: string;\n connected: boolean;\n userCount?: number;\n lastActivity?: Date;\n error?: string;\n}\n\n/**\n * Abstract Channel Adapter\n * All channel integrations (Discord, Telegram, Slack, etc.) extend this.\n */\nexport abstract class ChannelAdapter extends EventEmitter {\n abstract readonly name: string;\n abstract readonly displayName: string;\n\n /** Connect to the channel service */\n abstract connect(): Promise<void>;\n\n /** Disconnect from the channel service */\n abstract disconnect(): Promise<void>;\n\n /** Send a message to the channel */\n abstract send(message: OutboundMessage): Promise<void>;\n\n /** Get the current connection status */\n abstract getStatus(): ChannelStatus;\n\n /** Type declaration for events */\n declare on: (event: 'message', listener: (msg: InboundMessage) => void) => this;\n declare emit: (event: 'message', msg: InboundMessage) => boolean;\n}\n","/**\n * TITAN — WebChat Channel (Built-in)\n * WebSocket-based chat interface served by the gateway.\n */\nimport { ChannelAdapter, type InboundMessage, type OutboundMessage, type ChannelStatus } from './base.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'WebChat';\n\n/** In-memory message queue for WebSocket clients */\nconst outboundQueue: OutboundMessage[] = [];\n\nexport function getOutboundQueue(): OutboundMessage[] {\n return outboundQueue.splice(0, outboundQueue.length);\n}\n\nexport class WebChatChannel extends ChannelAdapter {\n readonly name = 'webchat';\n readonly displayName = 'WebChat';\n private connected = false;\n\n async connect(): Promise<void> {\n this.connected = true;\n logger.info(COMPONENT, 'WebChat channel ready');\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n /** Handle an inbound WebSocket message */\n handleWebSocketMessage(userId: string, content: string): void {\n const inbound: InboundMessage = {\n id: `wc-${Date.now()}`,\n channel: 'webchat',\n userId,\n content,\n timestamp: new Date(),\n };\n this.emit('message', inbound);\n }\n\n async send(message: OutboundMessage): Promise<void> {\n outboundQueue.push(message);\n }\n\n getStatus(): ChannelStatus {\n return { name: this.displayName, connected: this.connected };\n }\n}\n","/**\n * TITAN — Discord Channel Adapter\n * Connects to Discord using the discord.js library.\n */\nimport { ChannelAdapter, type InboundMessage, type OutboundMessage, type ChannelStatus } from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Discord';\n\nexport class DiscordChannel extends ChannelAdapter {\n readonly name = 'discord';\n readonly displayName = 'Discord';\n private connected = false;\n private client: unknown = null;\n\n async connect(): Promise<void> {\n const config = loadConfig();\n const channelConfig = config.channels.discord;\n\n if (!channelConfig.enabled) {\n logger.info(COMPONENT, 'Discord channel is disabled');\n return;\n }\n\n const token = channelConfig.token;\n if (!token) {\n logger.warn(COMPONENT, 'Discord token not configured');\n return;\n }\n\n try {\n // Dynamic import to avoid requiring discord.js when not used\n // @ts-ignore — discord.js is an optional dependency\n const { Client, GatewayIntentBits, Events } = await import('discord.js');\n\n const client = new Client({\n intents: [\n GatewayIntentBits.Guilds,\n GatewayIntentBits.GuildMessages,\n GatewayIntentBits.DirectMessages,\n GatewayIntentBits.MessageContent,\n ],\n });\n\n client.on(Events.MessageCreate, (message: any) => {\n if (message.author.bot) return;\n\n const inbound: InboundMessage = {\n id: message.id,\n channel: 'discord',\n userId: message.author.id,\n userName: message.author.username,\n content: message.content,\n groupId: message.guild?.id,\n timestamp: message.createdAt,\n raw: message,\n };\n\n this.emit('message', inbound);\n });\n\n client.on(Events.ClientReady, () => {\n this.connected = true;\n logger.info(COMPONENT, `Connected as ${(client.user as any)?.tag}`);\n });\n\n await client.login(token);\n this.client = client;\n } catch (error) {\n logger.error(COMPONENT, `Failed to connect: ${(error as Error).message}`);\n logger.info(COMPONENT, 'Install discord.js with: npm install discord.js');\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n (this.client as any).destroy();\n this.connected = false;\n logger.info(COMPONENT, 'Disconnected');\n }\n }\n\n async send(message: OutboundMessage): Promise<void> {\n if (!this.client || !this.connected) {\n logger.warn(COMPONENT, 'Not connected, cannot send message');\n return;\n }\n\n try {\n const client = this.client as any;\n if (message.userId) {\n const user = await client.users.fetch(message.userId);\n const dm = await user.createDM();\n await dm.send(message.content);\n } else if (message.groupId) {\n const channel = await client.channels.fetch(message.groupId);\n if (channel?.isTextBased()) {\n await channel.send(message.content);\n }\n }\n } catch (error) {\n logger.error(COMPONENT, `Send failed: ${(error as Error).message}`);\n }\n }\n\n getStatus(): ChannelStatus {\n return {\n name: this.displayName,\n connected: this.connected,\n };\n }\n}\n","/**\n * TITAN — Telegram Channel Adapter\n */\nimport { ChannelAdapter, type InboundMessage, type OutboundMessage, type ChannelStatus } from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Telegram';\n\nexport class TelegramChannel extends ChannelAdapter {\n readonly name = 'telegram';\n readonly displayName = 'Telegram';\n private connected = false;\n private bot: unknown = null;\n\n async connect(): Promise<void> {\n const config = loadConfig();\n const channelConfig = config.channels.telegram;\n\n if (!channelConfig.enabled) {\n logger.info(COMPONENT, 'Telegram channel is disabled');\n return;\n }\n\n const token = channelConfig.token;\n if (!token) {\n logger.warn(COMPONENT, 'Telegram token not configured');\n return;\n }\n\n try {\n // @ts-ignore — grammy is an optional dependency\n const { Bot } = await import('grammy');\n const bot = new Bot(token);\n\n bot.on('message:text', (ctx: any) => {\n const inbound: InboundMessage = {\n id: String(ctx.message.message_id),\n channel: 'telegram',\n userId: String(ctx.from.id),\n userName: ctx.from.username || ctx.from.first_name,\n content: ctx.message.text,\n groupId: ctx.chat.type !== 'private' ? String(ctx.chat.id) : undefined,\n timestamp: new Date(ctx.message.date * 1000),\n raw: ctx,\n };\n this.emit('message', inbound);\n });\n\n bot.start();\n this.bot = bot;\n this.connected = true;\n logger.info(COMPONENT, 'Connected to Telegram');\n } catch (error) {\n logger.error(COMPONENT, `Failed to connect: ${(error as Error).message}`);\n logger.info(COMPONENT, 'Install grammy with: npm install grammy');\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.bot) {\n (this.bot as any).stop();\n this.connected = false;\n logger.info(COMPONENT, 'Disconnected');\n }\n }\n\n async send(message: OutboundMessage): Promise<void> {\n if (!this.bot || !this.connected) return;\n try {\n const chatId = message.userId || message.groupId;\n if (chatId) {\n await (this.bot as any).api.sendMessage(chatId, message.content, { parse_mode: 'Markdown' });\n }\n } catch (error) {\n logger.error(COMPONENT, `Send failed: ${(error as Error).message}`);\n }\n }\n\n getStatus(): ChannelStatus {\n return { name: this.displayName, connected: this.connected };\n }\n}\n","/**\n * TITAN — Slack Channel Adapter\n */\nimport { ChannelAdapter, type InboundMessage, type OutboundMessage, type ChannelStatus } from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Slack';\n\nexport class SlackChannel extends ChannelAdapter {\n readonly name = 'slack';\n readonly displayName = 'Slack';\n private connected = false;\n\n async connect(): Promise<void> {\n const config = loadConfig();\n const channelConfig = config.channels.slack;\n if (!channelConfig.enabled) { logger.info(COMPONENT, 'Slack channel is disabled'); return; }\n if (!channelConfig.token) { logger.warn(COMPONENT, 'Slack token not configured'); return; }\n\n try {\n // Dynamic import to only load Bolt when used\n const { App } = await import('@slack/bolt' as string);\n const app = new App({\n token: channelConfig.token,\n signingSecret: channelConfig.apiKey || '',\n socketMode: true,\n appToken: channelConfig.apiKey || '',\n });\n\n app.message(async ({ message, say }: any) => {\n if (message.subtype) return;\n const inbound: InboundMessage = {\n id: message.ts, channel: 'slack', userId: message.user,\n content: message.text || '', groupId: message.channel,\n timestamp: new Date(parseFloat(message.ts) * 1000), raw: message,\n };\n this.emit('message', inbound);\n });\n\n await app.start();\n this.connected = true;\n logger.info(COMPONENT, 'Connected to Slack');\n } catch (error) {\n logger.error(COMPONENT, `Failed to connect: ${(error as Error).message}`);\n logger.info(COMPONENT, 'Install Bolt with: npm install @slack/bolt');\n }\n }\n\n async disconnect(): Promise<void> { this.connected = false; }\n async send(message: OutboundMessage): Promise<void> {\n logger.debug(COMPONENT, `Would send to ${message.userId || message.groupId}: ${message.content.slice(0, 100)}`);\n }\n getStatus(): ChannelStatus { return { name: this.displayName, connected: this.connected }; }\n}\n","/**\n * TITAN — Google Chat Channel Adapter\n */\nimport { ChannelAdapter, type InboundMessage, type OutboundMessage, type ChannelStatus } from './base.js';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'GoogleChat';\n\nexport class GoogleChatChannel extends ChannelAdapter {\n readonly name = 'googlechat';\n readonly displayName = 'Google Chat';\n private connected = false;\n\n async connect(): Promise<void> {\n const config = loadConfig();\n const channelConfig = config.channels.googlechat;\n\n if (!channelConfig?.enabled) {\n logger.info(COMPONENT, 'Google Chat channel is disabled');\n return;\n }\n\n // Google Chat uses the Google Chat API with service account credentials\n // This is a placeholder that can be expanded with the @google-cloud/chat library\n logger.info(COMPONENT, 'Google Chat adapter ready (webhook mode)');\n this.connected = true;\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n async send(message: OutboundMessage): Promise<void> {\n if (!this.connected) return;\n // Google Chat sends responses via the webhook/API\n logger.debug(COMPONENT, `Would send to ${message.userId || message.groupId}: ${message.content.slice(0, 100)}`);\n }\n\n getStatus(): ChannelStatus {\n return { name: this.displayName, connected: this.connected };\n }\n}\n","/**\n * TITAN — Multi-Agent Router\n * Manage up to 5 concurrent agent instances with independent workspaces,\n * models, and session isolation. Supports per-channel/per-account routing.\n */\nimport { v4 as uuid } from 'uuid';\nimport { loadConfig } from '../config/config.js';\nimport { processMessage, type AgentResponse } from './agent.js';\nimport { checkPromptInjection } from '../security/shield.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'MultiAgent';\nconst MAX_AGENTS = 5;\n\nexport interface AgentInstance {\n id: string;\n name: string;\n model: string;\n systemPrompt?: string;\n workspace?: string;\n status: 'running' | 'idle' | 'stopped';\n channelBindings: Array<{ channel: string; pattern: string }>;\n messageCount: number;\n createdAt: string;\n lastActive: string;\n}\n\n/** Active agent instances */\nconst agents: Map<string, AgentInstance> = new Map();\n\n/** Default agent (always exists) */\nlet defaultAgentId: string | null = null;\n\n/** Initialize with a default agent */\nexport function initAgents(): void {\n if (agents.size > 0) return;\n const config = loadConfig();\n const defaultAgent: AgentInstance = {\n id: 'default',\n name: 'TITAN Primary',\n model: config.agent.model,\n systemPrompt: config.agent.systemPrompt,\n status: 'running',\n channelBindings: [{ channel: '*', pattern: '*' }],\n messageCount: 0,\n createdAt: new Date().toISOString(),\n lastActive: new Date().toISOString(),\n };\n agents.set('default', defaultAgent);\n defaultAgentId = 'default';\n logger.info(COMPONENT, 'Default agent initialized');\n}\n\n/** Spawn a new agent instance */\nexport function spawnAgent(options: {\n name: string;\n model?: string;\n systemPrompt?: string;\n workspace?: string;\n channelBindings?: Array<{ channel: string; pattern: string }>;\n}): { success: boolean; agent?: AgentInstance; error?: string } {\n initAgents();\n\n if (agents.size >= MAX_AGENTS) {\n return { success: false, error: `Maximum ${MAX_AGENTS} agents reached. Stop an existing agent to spawn a new one.` };\n }\n\n const config = loadConfig();\n const id = uuid().slice(0, 8);\n const agent: AgentInstance = {\n id,\n name: options.name,\n model: options.model || config.agent.model,\n systemPrompt: options.systemPrompt,\n workspace: options.workspace,\n status: 'running',\n channelBindings: options.channelBindings || [],\n messageCount: 0,\n createdAt: new Date().toISOString(),\n lastActive: new Date().toISOString(),\n };\n\n agents.set(id, agent);\n logger.info(COMPONENT, `Spawned agent \"${agent.name}\" (${id}) — model: ${agent.model} [${agents.size}/${MAX_AGENTS}]`);\n return { success: true, agent };\n}\n\n/** Stop an agent instance */\nexport function stopAgent(agentId: string): { success: boolean; error?: string } {\n if (agentId === 'default') {\n return { success: false, error: 'Cannot stop the default agent.' };\n }\n const agent = agents.get(agentId);\n if (!agent) {\n return { success: false, error: `Agent \"${agentId}\" not found.` };\n }\n agent.status = 'stopped';\n agents.delete(agentId);\n logger.info(COMPONENT, `Stopped agent \"${agent.name}\" (${agentId}) [${agents.size}/${MAX_AGENTS}]`);\n return { success: true };\n}\n\n/** Get all agent instances */\nexport function listAgents(): AgentInstance[] {\n initAgents();\n return Array.from(agents.values());\n}\n\n/** Get a specific agent */\nexport function getAgent(agentId: string): AgentInstance | undefined {\n return agents.get(agentId);\n}\n\n/** Resolve which agent should handle a message based on channel routing rules */\nexport function resolveAgent(channel: string, userId: string): AgentInstance {\n initAgents();\n\n // Check channel bindings in reverse order (most recently spawned first)\n const agentList = Array.from(agents.values()).reverse();\n for (const agent of agentList) {\n if (agent.status !== 'running') continue;\n for (const binding of agent.channelBindings) {\n if (binding.channel === '*' || binding.channel === channel) {\n if (binding.pattern === '*' || binding.pattern === userId) {\n return agent;\n }\n }\n }\n }\n\n // Fallback to default\n return agents.get('default')!;\n}\n\n/** Route a message to the appropriate agent and process it */\nexport async function routeMessage(\n message: string,\n channel: string,\n userId: string,\n): Promise<AgentResponse & { agentId: string; agentName: string }> {\n const agent = resolveAgent(channel, userId);\n\n agent.messageCount++;\n agent.lastActive = new Date().toISOString();\n\n logger.info(COMPONENT, `Routing to agent \"${agent.name}\" (${agent.id}) for ${channel}/${userId}`);\n\n // Shield Check: intercept prompt injection before the LLM sees it\n const shieldResult = checkPromptInjection(message);\n if (!shieldResult.safe) {\n logger.warn(COMPONENT, `Message rejected by Shield: ${shieldResult.reason}`);\n return {\n content: `🛡️ Message rejected by TITAN Security Shield: ${shieldResult.reason}`,\n sessionId: channel + ':' + userId,\n toolsUsed: [],\n tokenUsage: { prompt: 0, completion: 0, total: 0 },\n model: 'shield-interceptor',\n durationMs: 0,\n agentId: agent.id,\n agentName: agent.name,\n };\n }\n\n // Process through the agent\n const response = await processMessage(message, channel, userId);\n\n return {\n ...response,\n agentId: agent.id,\n agentName: agent.name,\n };\n}\n\n/** Get agent count and capacity */\nexport function getAgentCapacity(): { current: number; max: number; available: number } {\n initAgents();\n return {\n current: agents.size,\n max: MAX_AGENTS,\n available: MAX_AGENTS - agents.size,\n };\n}\n","/**\n * TITAN — Prompt Injection Shield\n * Heuristic pattern matching and intent analysis to block malicious payloads\n * before the LLM processes them. Discards jailbreaks, instruction overrides,\n * and system prompt extraction attempts.\n */\nimport logger from '../utils/logger.js';\nimport { loadConfig } from '../config/config.js';\n\nconst COMPONENT = 'Shield';\n\nexport interface ShieldResult {\n safe: boolean;\n reason?: string;\n matchedPattern?: string;\n}\n\n// Common prompt injection heuristics\nconst INJECTION_PATTERNS = [\n // Ignore previous instructions\n /(?:ignore|disregard|forget)(?: all)? (?:previous|prior) (?:instructions|directions|prompts|rules)/i,\n /ignore the above/i,\n // Roleplay / Jailbreak\n /(?:you are now|pretend you are|act as) (?:a|an) (?:unrestricted|unbound|developer mode|DAN|do anything now)/i,\n /system override|override authorization/i,\n // Prompt extraction\n /(?:repeat|print|output|show|tell me) (?:the|all|your) (?:instructions|system prompt|initial prompt|rules|directives)/i,\n // Base64 disguised injections\n /(?:decode|translate) (?:this|the following) base64/i,\n // Markdown link exploits\n /\\[.*\\]\\(javascript:/i,\n];\n\n// High-risk keywords that trigger extra scrutiny in strict mode\nconst STRICT_KEYWORDS = [\n 'system prompt',\n 'ignore previous',\n 'developer mode',\n 'unrestricted',\n 'bypass',\n 'DAN',\n];\n\n/**\n * Check if text contains a prompt injection attack\n */\nexport function checkPromptInjection(text: string): ShieldResult {\n const config = loadConfig();\n const shieldConfig = (config as any).security?.shield || { enabled: true, mode: 'strict' };\n\n if (!shieldConfig.enabled) {\n return { safe: true };\n }\n\n const normalized = text.toLowerCase().trim();\n\n // 1. Heuristic Pattern Matching\n for (const pattern of INJECTION_PATTERNS) {\n if (pattern.test(normalized)) {\n logger.warn(COMPONENT, `🛡️ Blocked prompt injection attempt! Pattern: ${pattern}`);\n return {\n safe: false,\n reason: 'Input matches known prompt injection signatures.',\n matchedPattern: pattern.toString(),\n };\n }\n }\n\n // 2. Strict Mode Scrutiny (Token density / keyword density)\n if (shieldConfig.mode === 'strict') {\n let flagCount = 0;\n for (const kw of STRICT_KEYWORDS) {\n if (normalized.includes(kw)) {\n flagCount++;\n }\n }\n\n if (flagCount >= 2) {\n logger.warn(COMPONENT, `🛡️ Blocked suspicious request! (Strict mode keyword density)`);\n return {\n safe: false,\n reason: 'Input contains too many high-risk keywords (strict mode).',\n };\n }\n\n // Huge prompts often hide injections at the very end\n if (normalized.length > 5000) {\n const tail = normalized.slice(-500);\n for (const pattern of INJECTION_PATTERNS) {\n if (pattern.test(tail)) {\n logger.warn(COMPONENT, `🛡️ Blocked prompt injection in payload tail.`);\n return { safe: false, reason: 'Injection pattern found at end of large payload.' };\n }\n }\n }\n }\n\n return { safe: true };\n}\n","/**\n * TITAN — Mission Control Dashboard\n * A premium, full-featured web GUI served from the gateway.\n * Every feature accessible: agents, chat, sessions, skills, security, plans, learning, processes, logs.\n */\n\nexport function getMissionControlHTML(): 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 Mission Control</title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n:root{\n --bg:#0a0e1a;--bg2:#111827;--bg3:#1a1f36;--bg4:#252b48;\n --accent:#06b6d4;--accent2:#8b5cf6;--accent3:#10b981;--accent4:#f59e0b;\n --error:#ef4444;--warn:#f59e0b;\n --text:#e2e8f0;--text-dim:#94a3b8;--text-bright:#f8fafc;\n --border:#2a3050;--glow:0 0 20px rgba(6,182,212,0.15);\n --radius:12px;--radius-sm:8px;\n}\nbody{font-family:'Inter','Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(--text);display:flex;height:100vh;overflow:hidden}\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');\n\n/* Sidebar */\n.sidebar{width:240px;background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0}\n.logo-area{padding:20px;border-bottom:1px solid var(--border);text-align:center}\n.logo-area h1{font-size:22px;font-weight:700;background:linear-gradient(135deg,var(--accent),var(--accent2));-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:2px}\n.logo-area .version{font-size:11px;color:var(--text-dim);margin-top:4px;font-family:'JetBrains Mono',monospace}\n.nav{flex:1;padding:12px 8px;overflow-y:auto}\n.nav-section{font-size:10px;font-weight:600;color:var(--text-dim);text-transform:uppercase;letter-spacing:1.5px;padding:12px 12px 6px;margin-top:8px}\n.nav-item{display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:var(--radius-sm);cursor:pointer;color:var(--text-dim);font-size:13px;font-weight:500;transition:all .15s}\n.nav-item:hover{background:var(--bg3);color:var(--text)}\n.nav-item.active{background:linear-gradient(135deg,rgba(6,182,212,.15),rgba(139,92,246,.1));color:var(--accent);border:1px solid rgba(6,182,212,.2)}\n.nav-item .icon{font-size:16px;width:20px;text-align:center}\n.sidebar-footer{padding:12px;border-top:1px solid var(--border);font-size:11px;color:var(--text-dim);text-align:center}\n\n/* Main */\n.main{flex:1;display:flex;flex-direction:column;overflow:hidden}\n.topbar{height:56px;background:var(--bg2);border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;padding:0 24px;flex-shrink:0}\n.topbar h2{font-size:16px;font-weight:600}\n.topbar .status{display:flex;gap:16px;align-items:center}\n.status-dot{width:8px;height:8px;border-radius:50%;background:var(--accent3);box-shadow:0 0 8px var(--accent3);animation:pulse 2s infinite}\n@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}\n.status-label{font-size:12px;color:var(--text-dim)}\n\n.content{flex:1;overflow-y:auto;padding:24px;display:grid;gap:20px}\n.panel{display:none}\n.panel.active{display:block}\n\n/* Cards */\n.card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:20px;box-shadow:var(--glow)}\n.card h3{font-size:14px;font-weight:600;margin-bottom:12px;color:var(--text-bright)}\n.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}\n\n/* Stat cards */\n.stat-card{background:var(--bg3);border:1px solid var(--border);border-radius:var(--radius);padding:16px;position:relative;overflow:hidden}\n.stat-card::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;border-radius:var(--radius) var(--radius) 0 0}\n.stat-card.cyan::before{background:linear-gradient(90deg,var(--accent),transparent)}\n.stat-card.purple::before{background:linear-gradient(90deg,var(--accent2),transparent)}\n.stat-card.green::before{background:linear-gradient(90deg,var(--accent3),transparent)}\n.stat-card.amber::before{background:linear-gradient(90deg,var(--accent4),transparent)}\n.stat-label{font-size:11px;color:var(--text-dim);text-transform:uppercase;letter-spacing:1px}\n.stat-value{font-size:28px;font-weight:700;margin-top:4px;font-family:'JetBrains Mono',monospace}\n.stat-sub{font-size:11px;color:var(--text-dim);margin-top:4px}\n\n/* Tables */\ntable{width:100%;border-collapse:collapse;font-size:13px}\nth{text-align:left;padding:10px 12px;border-bottom:2px solid var(--border);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:1px;font-weight:600}\ntd{padding:10px 12px;border-bottom:1px solid var(--border)}\ntr:hover{background:rgba(6,182,212,.03)}\n\n/* Badges */\n.badge{display:inline-block;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:600}\n.badge.active{background:rgba(16,185,129,.15);color:var(--accent3)}\n.badge.idle{background:rgba(148,163,184,.1);color:var(--text-dim)}\n.badge.error{background:rgba(239,68,68,.15);color:var(--error)}\n.badge.warn{background:rgba(245,158,11,.15);color:var(--warn)}\n.badge.info{background:rgba(6,182,212,.15);color:var(--accent)}\n\n/* Chat */\n.chat-container{display:flex;flex-direction:column;height:calc(100vh - 140px)}\n.chat-messages{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}\n.msg{max-width:75%;padding:12px 16px;border-radius:16px;font-size:14px;line-height:1.5;animation:fadeIn .2s}\n@keyframes fadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}\n.msg.user{align-self:flex-end;background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;border-bottom-right-radius:4px}\n.msg.assistant{align-self:flex-start;background:var(--bg3);border:1px solid var(--border);border-bottom-left-radius:4px}\n.chat-input-area{padding:16px;border-top:1px solid var(--border);display:flex;gap:12px}\n.chat-input-area input{flex:1;background:var(--bg3);border:1px solid var(--border);border-radius:var(--radius);padding:12px 16px;color:var(--text);font-size:14px;outline:none;transition:border .2s}\n.chat-input-area input:focus{border-color:var(--accent)}\n.chat-input-area button{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;border:none;padding:12px 24px;border-radius:var(--radius);font-weight:600;cursor:pointer;font-size:14px;transition:transform .1s}\n.chat-input-area button:hover{transform:scale(1.02)}\n.chat-input-area button:active{transform:scale(0.98)}\n\n/* Buttons */\n.btn{padding:8px 16px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--bg3);color:var(--text);font-size:12px;font-weight:500;cursor:pointer;transition:all .15s}\n.btn:hover{background:var(--bg4);border-color:var(--accent)}\n.btn.primary{background:linear-gradient(135deg,var(--accent),var(--accent2));border:none;color:#fff}\n.btn.danger{background:rgba(239,68,68,.1);border-color:var(--error);color:var(--error)}\n.btn.danger:hover{background:rgba(239,68,68,.2)}\n\n/* Form inputs */\n.form-row{display:flex;gap:12px;margin-bottom:12px;align-items:center}\n.form-row label{font-size:12px;color:var(--text-dim);min-width:80px}\n.form-row input,.form-row select{background:var(--bg3);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 12px;color:var(--text);font-size:13px;flex:1;outline:none}\n.form-row input:focus,.form-row select:focus{border-color:var(--accent)}\n\n/* Log entries */\n.log-entry{padding:6px 12px;font-family:'JetBrains Mono',monospace;font-size:12px;border-radius:4px;margin-bottom:4px}\n.log-entry.error{background:rgba(239,68,68,.1);color:#fca5a5}\n.log-entry.warn{background:rgba(245,158,11,.1);color:#fcd34d}\n.log-entry.info{background:rgba(6,182,212,.05);color:var(--text-dim)}\n\n/* Scrollbar */\n::-webkit-scrollbar{width:6px}\n::-webkit-scrollbar-track{background:transparent}\n::-webkit-scrollbar-thumb{background:var(--bg4);border-radius:3px}\n::-webkit-scrollbar-thumb:hover{background:var(--border)}\n\n/* Progress bar */\n.progress-bar{height:6px;background:var(--bg4);border-radius:3px;overflow:hidden;margin-top:8px}\n.progress-bar .fill{height:100%;background:linear-gradient(90deg,var(--accent),var(--accent2));border-radius:3px;transition:width .3s}\n\n/* Empty state */\n.empty-state{text-align:center;padding:40px;color:var(--text-dim)}\n.empty-state .icon{font-size:48px;margin-bottom:12px}\n.empty-state p{font-size:14px}\n</style>\n</head>\n<body>\n<aside class=\"sidebar\">\n <div class=\"logo-area\">\n <h1>⚡ TITAN</h1>\n <div class=\"version\" id=\"version\">Mission Control</div>\n </div>\n <nav class=\"nav\">\n <div class=\"nav-section\">Core</div>\n <div class=\"nav-item active\" onclick=\"showPanel('overview')\"><span class=\"icon\">📊</span>Overview</div>\n <div class=\"nav-item\" onclick=\"showPanel('chat')\"><span class=\"icon\">💬</span>WebChat</div>\n <div class=\"nav-item\" onclick=\"showPanel('agents')\"><span class=\"icon\">🤖</span>Agents</div>\n <div class=\"nav-section\">Tools</div>\n <div class=\"nav-item\" onclick=\"showPanel('skills')\"><span class=\"icon\">🧩</span>Skills</div>\n <div class=\"nav-item\" onclick=\"showPanel('processes')\"><span class=\"icon\">⚙️</span>Processes</div>\n <div class=\"nav-item\" onclick=\"showPanel('plans')\"><span class=\"icon\">📋</span>Plans</div>\n <div class=\"nav-section\">System</div>\n <div class=\"nav-item\" onclick=\"showPanel('sessions')\"><span class=\"icon\">🔗</span>Sessions</div>\n <div class=\"nav-item\" onclick=\"showPanel('channels')\"><span class=\"icon\">📡</span>Channels</div>\n <div class=\"nav-item\" onclick=\"showPanel('security')\"><span class=\"icon\">🔒</span>Security</div>\n <div class=\"nav-item\" onclick=\"showPanel('learning')\"><span class=\"icon\">🧠</span>Learning</div>\n <div class=\"nav-item\" onclick=\"showPanel('logs')\"><span class=\"icon\">📜</span>Logs</div>\n </nav>\n <div class=\"sidebar-footer\">TITAN — Mission Control<br/>The Intelligent Task Automation Network</div>\n</aside>\n\n<main class=\"main\">\n <header class=\"topbar\">\n <h2 id=\"panel-title\">📊 Overview</h2>\n <div class=\"status\">\n <div class=\"status-dot\"></div>\n <span class=\"status-label\" id=\"uptime\">Online</span>\n <span class=\"status-label\" id=\"agent-count\">0 agents</span>\n </div>\n </header>\n\n <div class=\"content\">\n <!-- Overview Panel -->\n <div id=\"panel-overview\" class=\"panel active\">\n <div class=\"card-grid\" id=\"stats-grid\">\n <div class=\"stat-card cyan\"><div class=\"stat-label\">Active Agents</div><div class=\"stat-value\" id=\"s-agents\">0</div><div class=\"stat-sub\">of 5 max</div></div>\n <div class=\"stat-card purple\"><div class=\"stat-label\">Sessions</div><div class=\"stat-value\" id=\"s-sessions\">0</div><div class=\"stat-sub\">active</div></div>\n <div class=\"stat-card green\"><div class=\"stat-label\">Tools Available</div><div class=\"stat-value\" id=\"s-tools\">0</div><div class=\"stat-sub\">17+ built-in</div></div>\n <div class=\"stat-card amber\"><div class=\"stat-label\">Knowledge</div><div class=\"stat-value\" id=\"s-knowledge\">0</div><div class=\"stat-sub\">learned facts</div></div>\n </div>\n <div class=\"card\" style=\"margin-top:20px\">\n <h3>System Health</h3>\n <div id=\"health-info\">Loading...</div>\n </div>\n <div class=\"card\" style=\"margin-top:20px\">\n <h3>Recent Activity</h3>\n <div id=\"activity-feed\">Loading...</div>\n </div>\n </div>\n\n <!-- Chat Panel -->\n <div id=\"panel-chat\" class=\"panel\">\n <div class=\"card\" style=\"height:calc(100vh - 140px);display:flex;flex-direction:column;padding:0\">\n <div class=\"chat-messages\" id=\"chat-messages\">\n <div class=\"msg assistant\">👋 Hello! I'm TITAN. How can I help you today?</div>\n </div>\n <div class=\"chat-input-area\">\n <input type=\"text\" id=\"chat-input\" placeholder=\"Type a message...\" onkeydown=\"if(event.key==='Enter')sendChat()\"/>\n <button onclick=\"sendChat()\">Send ⚡</button>\n </div>\n </div>\n </div>\n\n <!-- Agents Panel -->\n <div id=\"panel-agents\" class=\"panel\">\n <div class=\"card\">\n <h3>Spawn New Agent</h3>\n <div class=\"form-row\"><label>Name</label><input type=\"text\" id=\"agent-name\" placeholder=\"e.g. Code Reviewer\"/></div>\n <div class=\"form-row\"><label>Model</label><input type=\"text\" id=\"agent-model\" placeholder=\"e.g. anthropic/claude-sonnet-4-20250514\"/></div>\n <div class=\"form-row\"><label></label><button class=\"btn primary\" onclick=\"spawnAgent()\">Spawn Agent</button></div>\n </div>\n <div class=\"card\" style=\"margin-top:16px\">\n <h3>Agent Instances (max 5)</h3>\n <div id=\"agents-list\"><div class=\"empty-state\"><div class=\"icon\">🤖</div><p>No agents running. Spawn one above.</p></div></div>\n </div>\n </div>\n\n <!-- Skills Panel -->\n <div id=\"panel-skills\" class=\"panel\">\n <div class=\"card\"><h3>Installed Skills</h3><div id=\"skills-list\">Loading...</div></div>\n </div>\n\n <!-- Processes Panel -->\n <div id=\"panel-processes\" class=\"panel\">\n <div class=\"card\"><h3>Background Processes</h3><div id=\"processes-list\"><div class=\"empty-state\"><div class=\"icon\">⚙️</div><p>No background processes.</p></div></div></div>\n </div>\n\n <!-- Plans Panel -->\n <div id=\"panel-plans\" class=\"panel\">\n <div class=\"card\"><h3>Task Plans</h3><div id=\"plans-list\"><div class=\"empty-state\"><div class=\"icon\">📋</div><p>No active plans. Create one via chat.</p></div></div></div>\n </div>\n\n <!-- Sessions Panel -->\n <div id=\"panel-sessions\" class=\"panel\">\n <div class=\"card\"><h3>Active Sessions</h3><div id=\"sessions-list\">Loading...</div></div>\n </div>\n\n <!-- Channels Panel -->\n <div id=\"panel-channels\" class=\"panel\">\n <div class=\"card\"><h3>Channel Status</h3><div id=\"channels-list\">Loading...</div></div>\n </div>\n\n <!-- Security Panel -->\n <div id=\"panel-security\" class=\"panel\">\n <div class=\"card\"><h3>Security Audit</h3><div id=\"security-audit\">Loading...</div></div>\n </div>\n\n <!-- Learning Panel -->\n <div id=\"panel-learning\" class=\"panel\">\n <div class=\"card\">\n <h3>Learning Engine Status</h3>\n <div id=\"learning-stats\">Loading...</div>\n </div>\n <div class=\"card\" style=\"margin-top:16px\">\n <h3>Tool Success Rates</h3>\n <div id=\"tool-rates\">Loading...</div>\n </div>\n </div>\n\n <!-- Logs Panel -->\n <div id=\"panel-logs\" class=\"panel\">\n <div class=\"card\"><h3>System Logs</h3><div id=\"logs-container\" style=\"max-height:calc(100vh - 220px);overflow-y:auto\">Loading...</div></div>\n </div>\n </div>\n</main>\n\n<script>\nconst panelTitles = {\n overview:'📊 Overview', chat:'💬 WebChat', agents:'🤖 Agents',\n skills:'🧩 Skills', processes:'⚙️ Processes', plans:'📋 Plans',\n sessions:'🔗 Sessions', channels:'📡 Channels', security:'🔒 Security',\n learning:'🧠 Learning', logs:'📜 Logs'\n};\n\nfunction showPanel(name) {\n document.querySelectorAll('.panel').forEach(p => p.classList.remove('active'));\n document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));\n const panel = document.getElementById('panel-' + name);\n if (panel) panel.classList.add('active');\n event.target.closest('.nav-item')?.classList.add('active');\n document.getElementById('panel-title').textContent = panelTitles[name] || name;\n}\n\n// WebSocket\nlet ws;\nfunction connectWS() {\n ws = new WebSocket((location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host);\n ws.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data);\n if (data.type === 'response') {\n const messages = document.getElementById('chat-messages');\n const msg = document.createElement('div');\n msg.className = 'msg assistant';\n msg.textContent = data.content;\n messages.appendChild(msg);\n messages.scrollTop = messages.scrollHeight;\n }\n } catch(err) {}\n };\n ws.onclose = () => setTimeout(connectWS, 3000);\n}\nconnectWS();\n\nfunction sendChat() {\n const input = document.getElementById('chat-input');\n const text = input.value.trim();\n if (!text) return;\n const messages = document.getElementById('chat-messages');\n const msg = document.createElement('div');\n msg.className = 'msg user';\n msg.textContent = text;\n messages.appendChild(msg);\n messages.scrollTop = messages.scrollHeight;\n input.value = '';\n if (ws && ws.readyState === 1) {\n ws.send(JSON.stringify({type:'message',content:text,channel:'webchat',userId:'dashboard'}));\n } else {\n fetch('/api/message',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({content:text})})\n .then(r=>r.json())\n .then(data=>{const m=document.createElement('div');m.className='msg assistant';m.textContent=data.content||'No response';messages.appendChild(m);messages.scrollTop=messages.scrollHeight});\n }\n}\n\nasync function spawnAgent() {\n const name = document.getElementById('agent-name').value.trim();\n const model = document.getElementById('agent-model').value.trim();\n if (!name) return alert('Agent name required');\n const r = await fetch('/api/agents/spawn',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name,model:model||undefined})});\n const data = await r.json();\n if (data.error) alert(data.error);\n else { document.getElementById('agent-name').value=''; document.getElementById('agent-model').value=''; fetchData(); }\n}\n\nasync function stopAgent(id) {\n await fetch('/api/agents/stop',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({agentId:id})});\n fetchData();\n}\n\nasync function fetchData() {\n try {\n const [stats, sessions, skills, channels, security, agents] = await Promise.all([\n fetch('/api/stats').then(r=>r.json()).catch(()=>({})),\n fetch('/api/sessions').then(r=>r.json()).catch(()=>[]),\n fetch('/api/skills').then(r=>r.json()).catch(()=>[]),\n fetch('/api/channels').then(r=>r.json()).catch(()=>{}),\n fetch('/api/security').then(r=>r.json()).catch(()=>({})),\n fetch('/api/agents').then(r=>r.json()).catch(()=>({agents:[],capacity:{current:0,max:5}})),\n ]);\n\n // Stats\n document.getElementById('s-agents').textContent = agents.capacity?.current || 0;\n document.getElementById('s-sessions').textContent = Array.isArray(sessions) ? sessions.length : 0;\n document.getElementById('s-tools').textContent = Array.isArray(skills) ? skills.length : 0;\n document.getElementById('s-knowledge').textContent = stats.knowledge || 0;\n document.getElementById('agent-count').textContent = (agents.capacity?.current||0) + ' agents';\n\n // Health\n const upSec = stats.uptime || 0;\n const upStr = upSec > 3600 ? Math.floor(upSec/3600)+'h '+Math.floor((upSec%3600)/60)+'m' : Math.floor(upSec/60)+'m '+Math.floor(upSec%60)+'s';\n document.getElementById('uptime').textContent = 'Up ' + upStr;\n document.getElementById('health-info').innerHTML =\n '<div style=\"display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:8px\">'+\n '<div><span style=\"color:var(--text-dim)\">Uptime</span><br><strong>'+upStr+'</strong></div>'+\n '<div><span style=\"color:var(--text-dim)\">Memory</span><br><strong>'+(stats.memoryMB||'—')+' MB</strong></div>'+\n '<div><span style=\"color:var(--text-dim)\">Version</span><br><strong>'+(stats.version||'—')+'</strong></div></div>';\n\n // Agents\n if (agents.agents && agents.agents.length > 0) {\n document.getElementById('agents-list').innerHTML =\n '<table><tr><th>Name</th><th>ID</th><th>Model</th><th>Messages</th><th>Status</th><th>Action</th></tr>' +\n agents.agents.map(a=>'<tr><td><strong>'+a.name+'</strong></td><td style=\"font-family:JetBrains Mono;font-size:12px;color:var(--text-dim)\">'+a.id+'</td><td>'+a.model+'</td><td>'+a.messageCount+'</td><td><span class=\"badge '+(a.status==='running'?'active':'idle')+'\">'+a.status+'</span></td><td><button class=\"btn danger\" onclick=\"stopAgent(\\\\''+a.id+'\\\\')\">Stop</button></td></tr>').join('')+'</table>';\n }\n\n // Sessions\n if (Array.isArray(sessions) && sessions.length > 0) {\n document.getElementById('sessions-list').innerHTML =\n '<table><tr><th>ID</th><th>Channel</th><th>Messages</th><th>Last Active</th></tr>' +\n sessions.map(s=>'<tr><td style=\"font-family:JetBrains Mono;font-size:12px\">'+s.id.slice(0,8)+'</td><td>'+s.channel+'</td><td>'+(s.messageCount||0)+'</td><td>'+(s.lastActive||'—')+'</td></tr>').join('')+'</table>';\n } else {\n document.getElementById('sessions-list').innerHTML = '<div class=\"empty-state\"><p>No active sessions</p></div>';\n }\n\n // Skills\n if (Array.isArray(skills) && skills.length > 0) {\n document.getElementById('skills-list').innerHTML =\n '<table><tr><th>Skill</th><th>Version</th><th>Source</th><th>Status</th></tr>' +\n skills.map(s=>'<tr><td><strong>'+s.name+'</strong></td><td>'+s.version+'</td><td><span class=\"badge info\">'+s.source+'</span></td><td><span class=\"badge active\">enabled</span></td></tr>').join('')+'</table>';\n }\n\n // Channels\n if (channels && typeof channels === 'object') {\n const entries = Object.entries(channels);\n document.getElementById('channels-list').innerHTML =\n '<table><tr><th>Channel</th><th>Status</th></tr>' +\n entries.map(([name,info])=>'<tr><td><strong>'+name+'</strong></td><td><span class=\"badge '+((info as any).status==='connected'?'active':'idle')+'\">'+(info as any).status+'</span></td></tr>').join('')+'</table>';\n }\n\n // Security\n document.getElementById('security-audit').innerHTML = security ? '<pre style=\"font-family:JetBrains Mono;font-size:12px;color:var(--text-dim);white-space:pre-wrap\">'+JSON.stringify(security,null,2)+'</pre>' : 'No audit data';\n\n } catch(e) { console.error('Fetch error:', e); }\n}\n\nfetchData();\nsetInterval(fetchData, 15000);\n</script>\n</body>\n</html>`;\n}\n"],"mappings":"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AAA;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;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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["existsSync","path","COMPONENT","existsSync","readFileSync","writeFileSync","join","COMPONENT","handler","COMPONENT","resolve","COMPONENT","readFileSync","writeFileSync","existsSync","mkdirSync","join","COMPONENT","store","COMPONENT","uuid","path","handler","COMPONENT","exec","COMPONENT","resolve","uuid","store","COMPONENT","session","generateKey","uuid","COMPONENT","uuid","COMPONENT","uuid","COMPONENT","uuid","COMPONENT","COMPONENT","existsSync","readFileSync","writeFileSync","join","debouncedSave","saveTimeout","existsSync","readFileSync","path","COMPONENT","COMPONENT","exec","uuid","COMPONENT","resolve","exec","resolve","readFileSync","writeFileSync","existsSync","dirname","existsSync","writeFileSync","mkdirSync","COMPONENT","readFileSync","existsSync","meta","handler","COMPONENT","readFileSync","writeFileSync","existsSync","join","uuid","COMPONENT","existsSync","readdirSync","readFileSync","join","meta","handler","COMPONENT","registerShellSkill","registerFilesystemSkill","registerWebSearchSkill","registerCronSkill","registerWebhookSkill","registerMemorySkill","registerBrowserSkill","registerSessionsSkill","registerProcessSkill","registerWebFetchSkill","registerApplyPatchSkill","registerAutoGenerateSkill","registerVisionSkill","registerVoiceSkills","COMPONENT","COMPONENT","COMPONENT","COMPONENT","COMPONENT","COMPONENT","uuid","COMPONENT","COMPONENT","uuid","COMPONENT","COMPONENT","COMPONENT"]}