titan-agent 5.3.2 → 5.4.1

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 (48) hide show
  1. package/dist/agent/agent.js +11 -1
  2. package/dist/agent/agent.js.map +1 -1
  3. package/dist/agent/agentLoop.js +36 -1
  4. package/dist/agent/agentLoop.js.map +1 -1
  5. package/dist/agent/session.js +106 -5
  6. package/dist/agent/session.js.map +1 -1
  7. package/dist/agent/subAgent.js +62 -1
  8. package/dist/agent/subAgent.js.map +1 -1
  9. package/dist/config/config.js +30 -8
  10. package/dist/config/config.js.map +1 -1
  11. package/dist/config/schema.js +25 -2
  12. package/dist/config/schema.js.map +1 -1
  13. package/dist/gateway/server.js +32 -1
  14. package/dist/gateway/server.js.map +1 -1
  15. package/dist/memory/graph.js +49 -15
  16. package/dist/memory/graph.js.map +1 -1
  17. package/dist/memory/index.js +192 -0
  18. package/dist/memory/index.js.map +1 -0
  19. package/dist/memory/memory.js +1 -0
  20. package/dist/memory/memory.js.map +1 -1
  21. package/dist/mesh/transport.js +60 -8
  22. package/dist/mesh/transport.js.map +1 -1
  23. package/dist/providers/anthropic.js +3 -2
  24. package/dist/providers/anthropic.js.map +1 -1
  25. package/dist/providers/base.js.map +1 -1
  26. package/dist/providers/google.js +94 -20
  27. package/dist/providers/google.js.map +1 -1
  28. package/dist/providers/modelCapabilities.js +59 -0
  29. package/dist/providers/modelCapabilities.js.map +1 -0
  30. package/dist/providers/ollama.js +3 -2
  31. package/dist/providers/ollama.js.map +1 -1
  32. package/dist/providers/openai.js +4 -3
  33. package/dist/providers/openai.js.map +1 -1
  34. package/dist/providers/openai_compat.js +3 -2
  35. package/dist/providers/openai_compat.js.map +1 -1
  36. package/dist/providers/router.js +63 -21
  37. package/dist/providers/router.js.map +1 -1
  38. package/dist/safety/fabricationGuard.js +140 -0
  39. package/dist/safety/fabricationGuard.js.map +1 -0
  40. package/dist/skills/builtin/gepa.js +23 -1
  41. package/dist/skills/builtin/gepa.js.map +1 -1
  42. package/dist/skills/builtin/model_trainer.js +31 -4
  43. package/dist/skills/builtin/model_trainer.js.map +1 -1
  44. package/dist/skills/builtin/self_improve.js +50 -2
  45. package/dist/skills/builtin/self_improve.js.map +1 -1
  46. package/dist/utils/constants.js +2 -2
  47. package/dist/utils/constants.js.map +1 -1
  48. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/skills/builtin/self_improve.ts"],"sourcesContent":["/**\n * TITAN — Self-Improvement Skill (Built-in)\n * Autonomous self-improvement via iterative experimentation on TITAN's own\n * prompts, tool selection, response quality, and error recovery.\n *\n * Wraps the existing autoresearch experiment_loop with TITAN-specific\n * experiment definitions, scheduling, and result tracking.\n */\nimport { registerSkill } from '../registry.js';\nimport { loadConfig } from '../../config/config.js';\nimport logger from '../../utils/logger.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, appendFileSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { TITAN_HOME } from '../../utils/constants.js';\nimport { chat } from '../../providers/router.js';\n\nconst COMPONENT = 'SelfImprove';\n\n// ── Live prompt bridge cache ─────────────────────────────────────────\nlet optimizedPromptCache: { mtime: number; content: string } | null = null;\n\n/** Load optimized prompts from disk with mtime-based caching */\nexport function getOptimizedPromptBlock(mode: string): string {\n if (mode === 'none') return '';\n\n let maxMtime = 0;\n const blocks: string[] = [];\n\n for (const area of IMPROVEMENT_AREAS) {\n const filePath = join(PROMPTS_DIR, area.promptFile);\n if (!existsSync(filePath)) continue;\n const stats = statSync(filePath);\n maxMtime = Math.max(maxMtime, stats.mtimeMs);\n const content = readFileSync(filePath, 'utf-8').trim();\n if (content) {\n blocks.push(`## Optimized — ${area.label}\\n${content}`);\n }\n }\n\n if (blocks.length === 0) return '';\n\n if (optimizedPromptCache && optimizedPromptCache.mtime >= maxMtime) {\n return optimizedPromptCache.content;\n }\n\n const content = blocks.join('\\n\\n');\n optimizedPromptCache = { mtime: maxMtime, content };\n logger.debug(COMPONENT, `Loaded ${blocks.length} optimized prompt block(s) from ${PROMPTS_DIR}`);\n return content;\n}\n\n/** Invalidate the optimized prompt cache so new improvements are picked up immediately */\nexport function clearOptimizedPromptCache(): void {\n optimizedPromptCache = null;\n logger.debug(COMPONENT, 'Optimized prompt cache cleared');\n}\n\n// ── Paths ────────────────────────────────────────────────────────────\nexport const SELF_IMPROVE_DIR = join(TITAN_HOME, 'self-improve');\nexport const PROMPTS_DIR = join(SELF_IMPROVE_DIR, 'prompts');\nexport const BENCHMARKS_DIR = join(SELF_IMPROVE_DIR, 'benchmarks');\nexport const RESULTS_DIR = join(SELF_IMPROVE_DIR, 'results');\nconst HISTORY_PATH = join(SELF_IMPROVE_DIR, 'history.jsonl');\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface ImprovementArea {\n id: string;\n label: string;\n promptFile: string;\n benchmarkFile: string;\n description: string;\n}\n\nexport interface ImprovementSession {\n id: string;\n area: string;\n status: 'running' | 'completed' | 'failed';\n startedAt: string;\n completedAt?: string;\n baselineScore: number;\n bestScore: number;\n experiments: number;\n keeps: number;\n discards: number;\n crashes: number;\n applied: boolean;\n}\n\n// ── Improvement area definitions ─────────────────────────────────────\n\nexport const IMPROVEMENT_AREAS: ImprovementArea[] = [\n {\n id: 'prompts',\n label: 'System Prompts',\n promptFile: 'system.txt',\n benchmarkFile: 'response-quality.json',\n description: 'Optimize system prompt wording for better response quality',\n },\n {\n id: 'tool-selection',\n label: 'Tool Selection',\n promptFile: 'tool-routing.txt',\n benchmarkFile: 'tool-selection.json',\n description: 'Improve tool selection accuracy for user requests',\n },\n {\n id: 'response-quality',\n label: 'Response Quality',\n promptFile: 'response-style.txt',\n benchmarkFile: 'response-quality.json',\n description: 'Optimize response clarity, conciseness, and accuracy',\n },\n {\n id: 'error-recovery',\n label: 'Error Recovery',\n promptFile: 'error-handling.txt',\n benchmarkFile: 'error-recovery.json',\n description: 'Improve graceful error handling and recovery strategies',\n },\n];\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nexport function ensureDirs(): void {\n for (const dir of [SELF_IMPROVE_DIR, PROMPTS_DIR, BENCHMARKS_DIR, RESULTS_DIR]) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction getSessionId(area: string): string {\n return `${area}-${Date.now().toString(36)}`;\n}\n\n/** Initialize default prompt files if they don't exist */\nexport function initPromptFiles(): void {\n ensureDirs();\n\n const defaults: Record<string, string> = {\n 'system.txt': `You are TITAN, an intelligent task automation agent. You help users accomplish complex tasks efficiently by selecting and using the right tools. Be concise, accurate, and proactive. When you encounter errors, recover gracefully and suggest alternatives.`,\n 'tool-routing.txt': `When selecting tools for a user request, consider:\n1. Match the tool's primary purpose to the user's intent\n2. Prefer simpler tools when the task is straightforward\n3. Chain tools when complex workflows are needed\n4. Consider tool reliability and speed\n5. Use web_search for current information, memory for stored knowledge`,\n 'response-style.txt': `Response guidelines:\n- Lead with the answer, not the reasoning\n- Be concise but complete\n- Use markdown formatting for structure\n- Include code examples when relevant\n- Acknowledge uncertainty honestly`,\n 'error-handling.txt': `Error recovery strategy:\n- On tool failure, try an alternative tool\n- On API errors, check rate limits and retry with backoff\n- On missing data, ask the user for clarification\n- On timeout, break the task into smaller steps\n- Always inform the user what went wrong and what you're trying instead`,\n };\n\n for (const [file, content] of Object.entries(defaults)) {\n const path = join(PROMPTS_DIR, file);\n if (!existsSync(path)) {\n writeFileSync(path, content, 'utf-8');\n }\n }\n}\n\n/** Initialize default benchmark files */\nexport function initBenchmarks(): void {\n ensureDirs();\n\n const toolSelectionBenchmark = {\n name: 'tool-selection',\n description: 'Tests whether TITAN picks the correct tool for each request',\n testCases: [\n { prompt: 'What is the weather in San Francisco?', expectedTool: 'weather', maxScore: 10 },\n { prompt: 'Search the web for latest AI news', expectedTool: 'web_search', maxScore: 10 },\n { prompt: 'Read the file at /tmp/test.txt', expectedTool: 'read_file', maxScore: 10 },\n { prompt: 'Remember that my favorite color is blue', expectedTool: 'memory', maxScore: 10 },\n { prompt: 'Run the command ls -la', expectedTool: 'shell', maxScore: 10 },\n { prompt: 'Create a new file called hello.txt', expectedTool: 'write_file', maxScore: 10 },\n { prompt: 'Search my emails for the invoice', expectedTool: 'email', maxScore: 10 },\n { prompt: 'Navigate to google.com', expectedTool: 'browser', maxScore: 10 },\n { prompt: 'Generate an image of a sunset', expectedTool: 'image_gen', maxScore: 10 },\n { prompt: 'What GitHub issues are open?', expectedTool: 'github', maxScore: 10 },\n ],\n };\n\n const responseQualityBenchmark = {\n name: 'response-quality',\n description: 'Tests response clarity, accuracy, and conciseness',\n testCases: [\n { prompt: 'Explain what a REST API is in one sentence', rubric: 'Concise, accurate, mentions HTTP methods and resources', maxScore: 10 },\n { prompt: 'How do I reverse a string in JavaScript?', rubric: 'Provides working code, concise explanation', maxScore: 10 },\n { prompt: 'What is the difference between let and const?', rubric: 'Accurate, mentions mutability, block scope', maxScore: 10 },\n { prompt: 'Summarize what Docker does', rubric: 'Mentions containers, isolation, portability', maxScore: 10 },\n { prompt: 'What is a race condition?', rubric: 'Clear definition, mentions concurrent access, gives example', maxScore: 10 },\n ],\n };\n\n const errorRecoveryBenchmark = {\n name: 'error-recovery',\n description: 'Tests graceful error handling and fallback behavior',\n testCases: [\n { prompt: 'Read the file /nonexistent/path.txt', rubric: 'Gracefully handles file not found, suggests alternatives', maxScore: 10 },\n { prompt: 'Search the web when network is down', rubric: 'Detects failure, suggests offline alternatives', maxScore: 10 },\n { prompt: 'Execute an invalid shell command: asdfqwerty', rubric: 'Reports error clearly, does not retry blindly', maxScore: 10 },\n ],\n };\n\n const benchmarks = [\n { file: 'tool-selection.json', data: toolSelectionBenchmark },\n { file: 'response-quality.json', data: responseQualityBenchmark },\n { file: 'error-recovery.json', data: errorRecoveryBenchmark },\n ];\n\n for (const { file, data } of benchmarks) {\n const path = join(BENCHMARKS_DIR, file);\n if (!existsSync(path)) {\n writeFileSync(path, JSON.stringify(data, null, 2), 'utf-8');\n }\n }\n}\n\n/** Run the eval harness for a given area — returns a score 0-100 */\nexport async function runEval(area: ImprovementArea): Promise<{ score: number; details: string }> {\n const benchmarkPath = join(BENCHMARKS_DIR, area.benchmarkFile);\n if (!existsSync(benchmarkPath)) {\n return { score: 0, details: 'Benchmark file not found' };\n }\n\n const benchmark = JSON.parse(readFileSync(benchmarkPath, 'utf-8'));\n const testCases = benchmark.testCases || [];\n if (testCases.length === 0) {\n return { score: 0, details: 'No test cases found' };\n }\n\n // Read current prompt\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const currentPrompt = existsSync(promptPath) ? readFileSync(promptPath, 'utf-8') : '';\n\n const config = loadConfig();\n const judgeModel = config.agent?.model || 'anthropic/claude-sonnet-4-20250514';\n\n let totalScore = 0;\n let maxPossible = 0;\n const details: string[] = [];\n\n for (const tc of testCases) {\n maxPossible += tc.maxScore || 10;\n\n try {\n // Get TITAN's response using the current prompt context\n const response = await chat({\n model: judgeModel,\n messages: [\n { role: 'system', content: currentPrompt || 'You are a helpful AI assistant.' },\n { role: 'user', content: tc.prompt },\n ],\n temperature: 0.3,\n maxTokens: 512,\n });\n\n // Judge the response\n const rubric = tc.rubric || `Expected tool: ${tc.expectedTool}`;\n const judgeResponse = await chat({\n model: judgeModel,\n messages: [\n {\n role: 'system',\n content: `You are a response quality judge. Score the AI response on a scale of 0-${tc.maxScore || 10}.\nRubric: ${rubric}\nRespond with ONLY a JSON object, no other text: {\"score\": <number>, \"reason\": \"<brief reason>\"}`,\n },\n {\n role: 'user',\n content: `/no_think\\nUser prompt: \"${tc.prompt}\"\\n\\nAI response: \"${response.content}\"\\n\\nRespond with only JSON:`,\n },\n ],\n temperature: 0,\n maxTokens: 200,\n });\n\n // Parse judge score\n if (!judgeResponse.content || judgeResponse.content.trim().length === 0) {\n details.push(` ${tc.prompt}: 0/${tc.maxScore || 10} — judge returned empty response`);\n continue;\n }\n let judgeJson = judgeResponse.content.trim();\n const judgeMatch = judgeJson.match(/\\{[\\s\\S]*\\}/);\n if (judgeMatch) judgeJson = judgeMatch[0];\n else judgeJson = judgeJson.replace(/^```(?:json)?\\s*/m, '').replace(/\\s*```$/m, '').trim();\n const parsed = JSON.parse(judgeJson);\n const score = Math.min(parsed.score || 0, tc.maxScore || 10);\n totalScore += score;\n details.push(` ${tc.prompt}: ${score}/${tc.maxScore || 10} — ${parsed.reason || 'no reason'}`);\n } catch (err) {\n details.push(` ${tc.prompt}: 0/${tc.maxScore || 10} — eval error: ${(err as Error).message}`);\n }\n }\n\n const normalizedScore = maxPossible > 0 ? Math.round((totalScore / maxPossible) * 100) : 0;\n return {\n score: normalizedScore,\n details: details.join('\\n'),\n };\n}\n\n/** Append a session to history */\nexport function appendHistory(session: ImprovementSession): void {\n ensureDirs();\n appendFileSync(HISTORY_PATH, JSON.stringify(session) + '\\n', 'utf-8');\n}\n\n/** Read session history */\nexport function readHistory(limit: number = 50): ImprovementSession[] {\n if (!existsSync(HISTORY_PATH)) return [];\n try {\n const lines = readFileSync(HISTORY_PATH, 'utf-8').split('\\n').filter(l => l.trim());\n const sessions = lines.map(l => {\n try { return JSON.parse(l) as ImprovementSession; }\n catch { return null; }\n }).filter(Boolean) as ImprovementSession[];\n return sessions.slice(-limit);\n } catch {\n return [];\n }\n}\n\n// ── Active session tracking ──────────────────────────────────────────\nconst activeSessions: Map<string, ImprovementSession> = new Map();\n\n// ── Tool implementations ─────────────────────────────────────────────\n\nasync function selfImproveStart(args: Record<string, unknown>): Promise<string> {\n const areaId = (args.area as string) || 'prompts';\n const budgetMinutes = (args.budgetMinutes as number) || 30;\n const maxExperiments = (args.maxExperiments as number) || 10;\n\n const area = IMPROVEMENT_AREAS.find(a => a.id === areaId);\n if (!area) {\n return `Error: unknown area \"${areaId}\". Valid areas: ${IMPROVEMENT_AREAS.map(a => a.id).join(', ')}`;\n }\n\n // Check config\n const config = loadConfig();\n const siConfig = (config as Record<string, unknown>).selfImprove as Record<string, unknown> | undefined;\n if (siConfig && siConfig.enabled === false) {\n return 'Self-improvement is disabled in config. Set selfImprove.enabled = true to enable.';\n }\n\n // Check daily budget\n if (siConfig) {\n const maxDaily = (siConfig.maxDailyBudgetMinutes as number) || 120;\n const today = new Date().toISOString().slice(0, 10);\n const todayMinutes = readHistory()\n .filter(s => s.startedAt.startsWith(today) && s.status === 'completed')\n .reduce((sum, s) => {\n const start = new Date(s.startedAt).getTime();\n const end = s.completedAt ? new Date(s.completedAt).getTime() : start;\n return sum + (end - start) / 60_000;\n }, 0);\n\n if (todayMinutes >= maxDaily) {\n return `Daily self-improvement budget exhausted (${Math.round(todayMinutes)}/${maxDaily} min used today). Try again tomorrow.`;\n }\n }\n\n // Weekend check\n if (siConfig && siConfig.pauseOnWeekends) {\n const day = new Date().getDay();\n if (day === 0 || day === 6) {\n return 'Self-improvement paused on weekends (config: pauseOnWeekends = true).';\n }\n }\n\n // Initialize files\n initPromptFiles();\n initBenchmarks();\n\n const sessionId = getSessionId(areaId);\n logger.info(COMPONENT, `Starting self-improvement session ${sessionId} for area: ${area.label}`);\n\n // Run baseline eval\n logger.info(COMPONENT, 'Running baseline evaluation...');\n const baseline = await runEval(area);\n\n const session: ImprovementSession = {\n id: sessionId,\n area: areaId,\n status: 'running',\n startedAt: new Date().toISOString(),\n baselineScore: baseline.score,\n bestScore: baseline.score,\n experiments: 0,\n keeps: 0,\n discards: 0,\n crashes: 0,\n applied: false,\n };\n activeSessions.set(sessionId, session);\n\n // Run experiment loop on the prompt file\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const startTime = Date.now();\n const timeBudgetMs = budgetMinutes * 60 * 1000;\n const _originalContent = readFileSync(promptPath, 'utf-8'); void _originalContent;\n const model = config.agent?.model || 'anthropic/claude-sonnet-4-20250514';\n\n for (let i = 1; i <= maxExperiments; i++) {\n if (Date.now() - startTime >= timeBudgetMs) {\n logger.info(COMPONENT, `Time budget exhausted after ${i - 1} experiments`);\n break;\n }\n\n session.experiments = i;\n const currentContent = readFileSync(promptPath, 'utf-8');\n\n try {\n // Ask LLM for a modification\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt optimization expert. Your task: improve this AI agent prompt for better ${area.label.toLowerCase()}.\n\nCONTEXT:\n- Current score: ${session.bestScore}/100 (baseline: ${session.baselineScore}/100)\n- Experiment: ${i}/${maxExperiments}\n- Area: ${area.description}\n\nINSTRUCTIONS:\n1. Read the current prompt below\n2. Identify ONE specific improvement\n3. Respond with ONLY a JSON object (no markdown, no explanation)\n\nREQUIRED FORMAT:\n{\"hypothesis\":\"what this change will improve\",\"modification\":{\"search\":\"exact substring to find in the prompt\",\"replace\":\"the replacement text\"}}\n\nRULES:\n- \"search\" must be an EXACT substring that appears in the current prompt\n- Make small, targeted changes — one sentence or phrase at a time\n- Do NOT wrap in code blocks or add any text outside the JSON`,\n },\n { role: 'user', content: `/no_think\\nCurrent prompt content:\\n---\\n${currentContent}\\n---\\nRespond with only JSON:` },\n ],\n temperature: 0.7,\n maxTokens: 1024,\n });\n\n if (!response.content || response.content.trim().length === 0) {\n logger.warn(COMPONENT, `Experiment ${i}: empty response from LLM — skipping`);\n session.crashes++;\n continue;\n }\n\n // Extract JSON from potential markdown code blocks or mixed content\n let jsonStr = response.content.trim();\n const jsonMatch = jsonStr.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) jsonStr = jsonMatch[0];\n else {\n jsonStr = jsonStr.replace(/^```(?:json)?\\s*/m, '').replace(/\\s*```$/m, '').trim();\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n logger.warn(COMPONENT, `Experiment ${i}: invalid JSON response — skipping`);\n session.crashes++;\n continue;\n }\n\n const searchStr = (parsed.modification as Record<string, string>)?.search || '';\n const replaceStr = (parsed.modification as Record<string, string>)?.replace ?? '';\n\n if (!searchStr || !currentContent.includes(searchStr)) {\n session.crashes++;\n continue;\n }\n\n // Apply modification\n const modified = currentContent.replace(searchStr, replaceStr);\n writeFileSync(promptPath, modified, 'utf-8');\n\n // Evaluate\n const result = await runEval(area);\n\n if (result.score > session.bestScore) {\n session.bestScore = result.score;\n session.keeps++;\n logger.info(COMPONENT, `Experiment ${i}: KEEP — score ${session.bestScore} (was ${baseline.score})`);\n } else {\n // Revert\n writeFileSync(promptPath, currentContent, 'utf-8');\n session.discards++;\n logger.info(COMPONENT, `Experiment ${i}: DISCARD — score ${result.score} (best: ${session.bestScore})`);\n }\n } catch (err) {\n // Revert on error\n writeFileSync(promptPath, currentContent, 'utf-8');\n session.crashes++;\n logger.warn(COMPONENT, `Experiment ${i}: crash — ${(err as Error).message}`);\n }\n }\n\n // Finalize\n session.status = 'completed';\n session.completedAt = new Date().toISOString();\n activeSessions.delete(sessionId);\n appendHistory(session);\n\n // Save results\n const resultPath = join(RESULTS_DIR, `${sessionId}.json`);\n writeFileSync(resultPath, JSON.stringify(session, null, 2), 'utf-8');\n\n const improvement = session.bestScore - session.baselineScore;\n const elapsed = ((Date.now() - startTime) / 60_000).toFixed(1);\n\n // Notify on success\n if (improvement > 0 && siConfig?.notifyOnSuccess !== false) {\n logger.info(COMPONENT, `Self-improvement success: ${area.label} score improved by ${improvement} points`);\n }\n\n return [\n `## Self-Improvement Complete`,\n ``,\n `**Area**: ${area.label}`,\n `**Session**: ${sessionId}`,\n `**Duration**: ${elapsed} minutes`,\n ``,\n `| Stat | Value |`,\n `|------|-------|`,\n `| Experiments | ${session.experiments} |`,\n `| Keeps | ${session.keeps} |`,\n `| Discards | ${session.discards} |`,\n `| Crashes | ${session.crashes} |`,\n `| Baseline score | ${session.baselineScore}/100 |`,\n `| Best score | ${session.bestScore}/100 |`,\n `| Improvement | +${improvement} points |`,\n ``,\n improvement > 0\n ? `Improved prompt saved to \\`${join(PROMPTS_DIR, area.promptFile)}\\`. Use \\`self_improve_apply\\` to apply to live config.`\n : 'No improvement found. The current prompt is already optimal for this benchmark set.',\n ].join('\\n');\n}\n\nasync function selfImproveStatus(_args: Record<string, unknown>): Promise<string> {\n const lines: string[] = ['## Self-Improvement Status\\n'];\n\n // Active sessions\n if (activeSessions.size > 0) {\n lines.push('### Active Sessions');\n for (const [id, session] of activeSessions) {\n const elapsed = ((Date.now() - new Date(session.startedAt).getTime()) / 60_000).toFixed(1);\n lines.push(`- **${id}** (${session.area}): experiment ${session.experiments}, score ${session.bestScore}/100, running ${elapsed} min`);\n }\n lines.push('');\n }\n\n // Config\n const config = loadConfig();\n const siConfig = (config as Record<string, unknown>).selfImprove as Record<string, unknown> | undefined;\n lines.push('### Configuration');\n lines.push(`- Enabled: ${siConfig?.enabled !== false}`);\n lines.push(`- Runs per day: ${siConfig?.runsPerDay || 1}`);\n lines.push(`- Schedule: ${JSON.stringify(siConfig?.schedule || ['0 2 * * *'])}`);\n lines.push(`- Budget per run: ${siConfig?.budgetMinutes || 30} min`);\n lines.push(`- Max daily budget: ${siConfig?.maxDailyBudgetMinutes || 120} min`);\n lines.push(`- Auto-apply: ${siConfig?.autoApply || false}`);\n lines.push(`- Areas: ${JSON.stringify(siConfig?.areas || ['prompts', 'tool-selection', 'response-quality', 'error-recovery'])}`);\n lines.push('');\n\n // Recent history\n const history = readHistory(10);\n if (history.length > 0) {\n lines.push('### Recent Sessions');\n lines.push('| Date | Area | Baseline | Best | Improvement | Experiments |');\n lines.push('|------|------|----------|------|-------------|-------------|');\n for (const s of history.reverse()) {\n const date = s.startedAt.slice(0, 10);\n const imp = s.bestScore - s.baselineScore;\n lines.push(`| ${date} | ${s.area} | ${s.baselineScore} | ${s.bestScore} | +${imp} | ${s.experiments} |`);\n }\n } else {\n lines.push('No improvement sessions run yet. Use `self_improve_start` to begin.');\n }\n\n return lines.join('\\n');\n}\n\nasync function selfImproveApply(args: Record<string, unknown>): Promise<string> {\n const sessionId = args.sessionId as string | undefined;\n const area = args.area as string | undefined;\n\n if (!sessionId && !area) {\n return 'Error: provide either sessionId or area to apply improvements from.';\n }\n\n // Find the session\n let targetSession: ImprovementSession | undefined;\n if (sessionId) {\n const resultPath = join(RESULTS_DIR, `${sessionId}.json`);\n if (existsSync(resultPath)) {\n targetSession = JSON.parse(readFileSync(resultPath, 'utf-8'));\n }\n } else if (area) {\n // Find most recent successful session for this area\n const history = readHistory(100);\n targetSession = history\n .filter(s => s.area === area && s.status === 'completed' && s.bestScore > s.baselineScore)\n .pop();\n }\n\n if (!targetSession) {\n return 'No successful improvement session found to apply.';\n }\n\n if (targetSession.bestScore <= targetSession.baselineScore) {\n return 'Session had no improvement — nothing to apply.';\n }\n\n const areaInfo = IMPROVEMENT_AREAS.find(a => a.id === targetSession!.area);\n if (!areaInfo) {\n return `Unknown area: ${targetSession.area}`;\n }\n\n // The improved prompt is already saved in the prompts dir\n const promptPath = join(PROMPTS_DIR, areaInfo.promptFile);\n if (!existsSync(promptPath)) {\n return `Improved prompt file not found at ${promptPath}`;\n }\n\n // Mark as applied\n targetSession.applied = true;\n const resultPath = join(RESULTS_DIR, `${targetSession.id}.json`);\n writeFileSync(resultPath, JSON.stringify(targetSession, null, 2), 'utf-8');\n\n // Invalidate cache so the optimized prompt is picked up on the very next turn\n clearOptimizedPromptCache();\n\n return [\n `## Improvement Applied`,\n ``,\n `**Area**: ${areaInfo.label}`,\n `**Session**: ${targetSession.id}`,\n `**Score**: ${targetSession.baselineScore} → ${targetSession.bestScore} (+${targetSession.bestScore - targetSession.baselineScore})`,\n ``,\n `Improved prompt is active at \\`${promptPath}\\`.`,\n `TITAN will use this optimized prompt for ${areaInfo.label.toLowerCase()} going forward.`,\n ].join('\\n');\n}\n\nasync function selfImproveHistory(args: Record<string, unknown>): Promise<string> {\n const limit = (args.limit as number) || 20;\n const areaFilter = args.area as string | undefined;\n\n let history = readHistory(limit);\n if (areaFilter) {\n history = history.filter(s => s.area === areaFilter);\n }\n\n if (history.length === 0) {\n return 'No self-improvement sessions found. Use `self_improve_start` to begin.';\n }\n\n const lines: string[] = [\n '## Self-Improvement History',\n '',\n '| Date | Area | Baseline | Best | +Δ | Exps | K/D/C | Applied |',\n '|------|------|----------|------|----|------|-------|---------|',\n ];\n\n for (const s of history.reverse()) {\n const date = s.startedAt.slice(0, 16).replace('T', ' ');\n const imp = s.bestScore - s.baselineScore;\n lines.push(`| ${date} | ${s.area} | ${s.baselineScore} | ${s.bestScore} | +${imp} | ${s.experiments} | ${s.keeps}/${s.discards}/${s.crashes} | ${s.applied ? 'yes' : 'no'} |`);\n }\n\n // Aggregate stats\n const totalSessions = history.length;\n const totalImprovement = history.reduce((sum, s) => sum + (s.bestScore - s.baselineScore), 0);\n const avgImprovement = totalSessions > 0 ? (totalImprovement / totalSessions).toFixed(1) : '0';\n const successRate = totalSessions > 0\n ? ((history.filter(s => s.bestScore > s.baselineScore).length / totalSessions) * 100).toFixed(0)\n : '0';\n\n lines.push('');\n lines.push(`**Total sessions**: ${totalSessions} | **Avg improvement**: +${avgImprovement} | **Success rate**: ${successRate}%`);\n\n return lines.join('\\n');\n}\n\n// ── Registration ─────────────────────────────────────────────────────\n\nexport function registerSelfImproveSkill(): void {\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_start',\n description: `Use this when asked to \"improve yourself\", \"get better at X\", \"optimize your behavior\", or \"work on your error recovery\". Also call this proactively on a schedule to keep TITAN improving over time. Runs LLM-guided experiments on TITAN's own prompts, evaluates quality against benchmarks, and keeps whatever improves the score. Areas: prompts (system prompt wording), tool-selection (picking the right tool), response-quality (clarity and accuracy), error-recovery (handling failures gracefully).`,\n parameters: {\n type: 'object',\n properties: {\n area: {\n type: 'string',\n description: 'What to improve: prompts, tool-selection, response-quality, or error-recovery',\n },\n budgetMinutes: {\n type: 'number',\n description: 'Time budget in minutes (default: 30)',\n },\n maxExperiments: {\n type: 'number',\n description: 'Maximum experiments to run (default: 10)',\n },\n },\n required: ['area'],\n },\n execute: selfImproveStart,\n },\n );\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_status',\n description: 'Check whether TITAN is currently running any self-improvement sessions, view configuration, and see the history of past improvement runs with score trends.',\n parameters: {\n type: 'object',\n properties: {},\n required: [],\n },\n execute: selfImproveStatus,\n },\n );\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_apply',\n description: 'Apply a completed self-improvement result to TITAN\\'s live config so the better prompt goes into effect immediately.',\n parameters: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'Session ID to apply (from self_improve_history)',\n },\n area: {\n type: 'string',\n description: 'Apply latest successful improvement for this area',\n },\n },\n required: [],\n },\n execute: selfImproveApply,\n },\n );\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_history',\n description: 'Show the full history of self-improvement sessions — what was tried, what improved, keep/discard ratios, and overall score trends over time.',\n parameters: {\n type: 'object',\n properties: {\n limit: {\n type: 'number',\n description: 'Maximum sessions to show (default: 20)',\n },\n area: {\n type: 'string',\n description: 'Filter by area (optional)',\n },\n },\n required: [],\n },\n execute: selfImproveHistory,\n },\n );\n\n logger.info(COMPONENT, 'Self-improvement skill registered (4 tools)');\n}\n"],"mappings":"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","names":["content","resultPath"]}
1
+ {"version":3,"sources":["../../../src/skills/builtin/self_improve.ts"],"sourcesContent":["/**\n * TITAN — Self-Improvement Skill (Built-in)\n * Autonomous self-improvement via iterative experimentation on TITAN's own\n * prompts, tool selection, response quality, and error recovery.\n *\n * Wraps the existing autoresearch experiment_loop with TITAN-specific\n * experiment definitions, scheduling, and result tracking.\n */\nimport { registerSkill } from '../registry.js';\nimport { loadConfig } from '../../config/config.js';\nimport logger from '../../utils/logger.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, appendFileSync, statSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport { TITAN_HOME } from '../../utils/constants.js';\nimport { chat } from '../../providers/router.js';\n\nconst COMPONENT = 'SelfImprove';\n\n// SELF_IMPROVE_DIR is exported below; declaring it inline first so the\n// rate-limit/checkpoint helpers that reference it don't trip TS's\n// temporal-dead-zone check (Phase 9 refactor introduced these helpers\n// above the SELF_IMPROVE_DIR const, breaking module init order).\nconst SELF_IMPROVE_DIR = join(TITAN_HOME, 'self-improve');\n\n// Phase 9: rate-limiting + checkpoint safety\nconst LAST_MUTATION_PATH = join(SELF_IMPROVE_DIR, '.last-mutation');\nconst CHECKPOINTS_DIR = join(SELF_IMPROVE_DIR, 'checkpoints');\n\nfunction canMutate(minIntervalMs = 60 * 60 * 1000): boolean {\n try {\n if (!existsSync(LAST_MUTATION_PATH)) return true;\n const last = parseInt(readFileSync(LAST_MUTATION_PATH, 'utf-8').trim(), 10);\n return Date.now() - last >= minIntervalMs;\n } catch {\n return true;\n }\n}\n\nfunction recordMutation(): void {\n try {\n writeFileSync(LAST_MUTATION_PATH, String(Date.now()), 'utf-8');\n } catch { /* non-critical */ }\n}\n\nfunction createCheckpoint(areaId: string, content: string): string {\n try {\n mkdirSync(CHECKPOINTS_DIR, { recursive: true });\n const checkpointId = `${areaId}-${Date.now()}`;\n const path = join(CHECKPOINTS_DIR, `${checkpointId}.txt`);\n writeFileSync(path, content, 'utf-8');\n return path;\n } catch {\n return '';\n }\n}\n\nfunction restoreCheckpoint(areaId: string): string | null {\n try {\n const files = readdirSync(CHECKPOINTS_DIR)\n .filter(f => f.startsWith(areaId + '-'))\n .sort()\n .reverse();\n if (files.length === 0) return null;\n const path = join(CHECKPOINTS_DIR, files[0]);\n return readFileSync(path, 'utf-8');\n } catch {\n return null;\n }\n}\n\n// ── Live prompt bridge cache ─────────────────────────────────────────\nlet optimizedPromptCache: { mtime: number; content: string } | null = null;\n\n/** Load optimized prompts from disk with mtime-based caching */\nexport function getOptimizedPromptBlock(mode: string): string {\n if (mode === 'none') return '';\n\n let maxMtime = 0;\n const blocks: string[] = [];\n\n for (const area of IMPROVEMENT_AREAS) {\n const filePath = join(PROMPTS_DIR, area.promptFile);\n if (!existsSync(filePath)) continue;\n const stats = statSync(filePath);\n maxMtime = Math.max(maxMtime, stats.mtimeMs);\n const content = readFileSync(filePath, 'utf-8').trim();\n if (content) {\n blocks.push(`## Optimized — ${area.label}\\n${content}`);\n }\n }\n\n if (blocks.length === 0) return '';\n\n if (optimizedPromptCache && optimizedPromptCache.mtime >= maxMtime) {\n return optimizedPromptCache.content;\n }\n\n const content = blocks.join('\\n\\n');\n optimizedPromptCache = { mtime: maxMtime, content };\n logger.debug(COMPONENT, `Loaded ${blocks.length} optimized prompt block(s) from ${PROMPTS_DIR}`);\n return content;\n}\n\n/** Invalidate the optimized prompt cache so new improvements are picked up immediately */\nexport function clearOptimizedPromptCache(): void {\n optimizedPromptCache = null;\n logger.debug(COMPONENT, 'Optimized prompt cache cleared');\n}\n\n// ── Paths ────────────────────────────────────────────────────────────\n// SELF_IMPROVE_DIR was hoisted to the top of the file (above the\n// rate-limit helpers that depend on it). This `export const` re-binds\n// the same value so the public surface stays identical.\nexport { SELF_IMPROVE_DIR };\nexport const PROMPTS_DIR = join(SELF_IMPROVE_DIR, 'prompts');\nexport const BENCHMARKS_DIR = join(SELF_IMPROVE_DIR, 'benchmarks');\nexport const RESULTS_DIR = join(SELF_IMPROVE_DIR, 'results');\nconst HISTORY_PATH = join(SELF_IMPROVE_DIR, 'history.jsonl');\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface ImprovementArea {\n id: string;\n label: string;\n promptFile: string;\n benchmarkFile: string;\n description: string;\n}\n\nexport interface ImprovementSession {\n id: string;\n area: string;\n status: 'running' | 'completed' | 'failed';\n startedAt: string;\n completedAt?: string;\n baselineScore: number;\n bestScore: number;\n experiments: number;\n keeps: number;\n discards: number;\n crashes: number;\n applied: boolean;\n}\n\n// ── Improvement area definitions ─────────────────────────────────────\n\nexport const IMPROVEMENT_AREAS: ImprovementArea[] = [\n {\n id: 'prompts',\n label: 'System Prompts',\n promptFile: 'system.txt',\n benchmarkFile: 'response-quality.json',\n description: 'Optimize system prompt wording for better response quality',\n },\n {\n id: 'tool-selection',\n label: 'Tool Selection',\n promptFile: 'tool-routing.txt',\n benchmarkFile: 'tool-selection.json',\n description: 'Improve tool selection accuracy for user requests',\n },\n {\n id: 'response-quality',\n label: 'Response Quality',\n promptFile: 'response-style.txt',\n benchmarkFile: 'response-quality.json',\n description: 'Optimize response clarity, conciseness, and accuracy',\n },\n {\n id: 'error-recovery',\n label: 'Error Recovery',\n promptFile: 'error-handling.txt',\n benchmarkFile: 'error-recovery.json',\n description: 'Improve graceful error handling and recovery strategies',\n },\n];\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nexport function ensureDirs(): void {\n for (const dir of [SELF_IMPROVE_DIR, PROMPTS_DIR, BENCHMARKS_DIR, RESULTS_DIR]) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction getSessionId(area: string): string {\n return `${area}-${Date.now().toString(36)}`;\n}\n\n/** Initialize default prompt files if they don't exist */\nexport function initPromptFiles(): void {\n ensureDirs();\n\n const defaults: Record<string, string> = {\n 'system.txt': `You are TITAN, an intelligent task automation agent. You help users accomplish complex tasks efficiently by selecting and using the right tools. Be concise, accurate, and proactive. When you encounter errors, recover gracefully and suggest alternatives.`,\n 'tool-routing.txt': `When selecting tools for a user request, consider:\n1. Match the tool's primary purpose to the user's intent\n2. Prefer simpler tools when the task is straightforward\n3. Chain tools when complex workflows are needed\n4. Consider tool reliability and speed\n5. Use web_search for current information, memory for stored knowledge`,\n 'response-style.txt': `Response guidelines:\n- Lead with the answer, not the reasoning\n- Be concise but complete\n- Use markdown formatting for structure\n- Include code examples when relevant\n- Acknowledge uncertainty honestly`,\n 'error-handling.txt': `Error recovery strategy:\n- On tool failure, try an alternative tool\n- On API errors, check rate limits and retry with backoff\n- On missing data, ask the user for clarification\n- On timeout, break the task into smaller steps\n- Always inform the user what went wrong and what you're trying instead`,\n };\n\n for (const [file, content] of Object.entries(defaults)) {\n const path = join(PROMPTS_DIR, file);\n if (!existsSync(path)) {\n writeFileSync(path, content, 'utf-8');\n }\n }\n}\n\n/** Initialize default benchmark files */\nexport function initBenchmarks(): void {\n ensureDirs();\n\n const toolSelectionBenchmark = {\n name: 'tool-selection',\n description: 'Tests whether TITAN picks the correct tool for each request',\n testCases: [\n { prompt: 'What is the weather in San Francisco?', expectedTool: 'weather', maxScore: 10 },\n { prompt: 'Search the web for latest AI news', expectedTool: 'web_search', maxScore: 10 },\n { prompt: 'Read the file at /tmp/test.txt', expectedTool: 'read_file', maxScore: 10 },\n { prompt: 'Remember that my favorite color is blue', expectedTool: 'memory', maxScore: 10 },\n { prompt: 'Run the command ls -la', expectedTool: 'shell', maxScore: 10 },\n { prompt: 'Create a new file called hello.txt', expectedTool: 'write_file', maxScore: 10 },\n { prompt: 'Search my emails for the invoice', expectedTool: 'email', maxScore: 10 },\n { prompt: 'Navigate to google.com', expectedTool: 'browser', maxScore: 10 },\n { prompt: 'Generate an image of a sunset', expectedTool: 'image_gen', maxScore: 10 },\n { prompt: 'What GitHub issues are open?', expectedTool: 'github', maxScore: 10 },\n ],\n };\n\n const responseQualityBenchmark = {\n name: 'response-quality',\n description: 'Tests response clarity, accuracy, and conciseness',\n testCases: [\n { prompt: 'Explain what a REST API is in one sentence', rubric: 'Concise, accurate, mentions HTTP methods and resources', maxScore: 10 },\n { prompt: 'How do I reverse a string in JavaScript?', rubric: 'Provides working code, concise explanation', maxScore: 10 },\n { prompt: 'What is the difference between let and const?', rubric: 'Accurate, mentions mutability, block scope', maxScore: 10 },\n { prompt: 'Summarize what Docker does', rubric: 'Mentions containers, isolation, portability', maxScore: 10 },\n { prompt: 'What is a race condition?', rubric: 'Clear definition, mentions concurrent access, gives example', maxScore: 10 },\n ],\n };\n\n const errorRecoveryBenchmark = {\n name: 'error-recovery',\n description: 'Tests graceful error handling and fallback behavior',\n testCases: [\n { prompt: 'Read the file /nonexistent/path.txt', rubric: 'Gracefully handles file not found, suggests alternatives', maxScore: 10 },\n { prompt: 'Search the web when network is down', rubric: 'Detects failure, suggests offline alternatives', maxScore: 10 },\n { prompt: 'Execute an invalid shell command: asdfqwerty', rubric: 'Reports error clearly, does not retry blindly', maxScore: 10 },\n ],\n };\n\n const benchmarks = [\n { file: 'tool-selection.json', data: toolSelectionBenchmark },\n { file: 'response-quality.json', data: responseQualityBenchmark },\n { file: 'error-recovery.json', data: errorRecoveryBenchmark },\n ];\n\n for (const { file, data } of benchmarks) {\n const path = join(BENCHMARKS_DIR, file);\n if (!existsSync(path)) {\n writeFileSync(path, JSON.stringify(data, null, 2), 'utf-8');\n }\n }\n}\n\n/** Run the eval harness for a given area — returns a score 0-100 */\nexport async function runEval(area: ImprovementArea): Promise<{ score: number; details: string }> {\n const benchmarkPath = join(BENCHMARKS_DIR, area.benchmarkFile);\n if (!existsSync(benchmarkPath)) {\n return { score: 0, details: 'Benchmark file not found' };\n }\n\n const benchmark = JSON.parse(readFileSync(benchmarkPath, 'utf-8'));\n const testCases = benchmark.testCases || [];\n if (testCases.length === 0) {\n return { score: 0, details: 'No test cases found' };\n }\n\n // Read current prompt\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const currentPrompt = existsSync(promptPath) ? readFileSync(promptPath, 'utf-8') : '';\n\n const config = loadConfig();\n const judgeModel = config.agent?.model || 'anthropic/claude-sonnet-4-20250514';\n\n let totalScore = 0;\n let maxPossible = 0;\n const details: string[] = [];\n\n for (const tc of testCases) {\n maxPossible += tc.maxScore || 10;\n\n try {\n // Get TITAN's response using the current prompt context\n const response = await chat({\n model: judgeModel,\n messages: [\n { role: 'system', content: currentPrompt || 'You are a helpful AI assistant.' },\n { role: 'user', content: tc.prompt },\n ],\n temperature: 0.3,\n maxTokens: 512,\n });\n\n // Judge the response\n const rubric = tc.rubric || `Expected tool: ${tc.expectedTool}`;\n const judgeResponse = await chat({\n model: judgeModel,\n messages: [\n {\n role: 'system',\n content: `You are a response quality judge. Score the AI response on a scale of 0-${tc.maxScore || 10}.\nRubric: ${rubric}\nRespond with ONLY a JSON object, no other text: {\"score\": <number>, \"reason\": \"<brief reason>\"}`,\n },\n {\n role: 'user',\n content: `/no_think\\nUser prompt: \"${tc.prompt}\"\\n\\nAI response: \"${response.content}\"\\n\\nRespond with only JSON:`,\n },\n ],\n temperature: 0,\n maxTokens: 200,\n });\n\n // Parse judge score\n if (!judgeResponse.content || judgeResponse.content.trim().length === 0) {\n details.push(` ${tc.prompt}: 0/${tc.maxScore || 10} — judge returned empty response`);\n continue;\n }\n let judgeJson = judgeResponse.content.trim();\n const judgeMatch = judgeJson.match(/\\{[\\s\\S]*\\}/);\n if (judgeMatch) judgeJson = judgeMatch[0];\n else judgeJson = judgeJson.replace(/^```(?:json)?\\s*/m, '').replace(/\\s*```$/m, '').trim();\n const parsed = JSON.parse(judgeJson);\n const score = Math.min(parsed.score || 0, tc.maxScore || 10);\n totalScore += score;\n details.push(` ${tc.prompt}: ${score}/${tc.maxScore || 10} — ${parsed.reason || 'no reason'}`);\n } catch (err) {\n details.push(` ${tc.prompt}: 0/${tc.maxScore || 10} — eval error: ${(err as Error).message}`);\n }\n }\n\n const normalizedScore = maxPossible > 0 ? Math.round((totalScore / maxPossible) * 100) : 0;\n return {\n score: normalizedScore,\n details: details.join('\\n'),\n };\n}\n\n/** Append a session to history */\nexport function appendHistory(session: ImprovementSession): void {\n ensureDirs();\n appendFileSync(HISTORY_PATH, JSON.stringify(session) + '\\n', 'utf-8');\n}\n\n/** Read session history */\nexport function readHistory(limit: number = 50): ImprovementSession[] {\n if (!existsSync(HISTORY_PATH)) return [];\n try {\n const lines = readFileSync(HISTORY_PATH, 'utf-8').split('\\n').filter(l => l.trim());\n const sessions = lines.map(l => {\n try { return JSON.parse(l) as ImprovementSession; }\n catch { return null; }\n }).filter(Boolean) as ImprovementSession[];\n return sessions.slice(-limit);\n } catch {\n return [];\n }\n}\n\n// ── Active session tracking ──────────────────────────────────────────\nconst activeSessions: Map<string, ImprovementSession> = new Map();\n\n// ── Tool implementations ─────────────────────────────────────────────\n\nasync function selfImproveStart(args: Record<string, unknown>): Promise<string> {\n const areaId = (args.area as string) || 'prompts';\n const budgetMinutes = (args.budgetMinutes as number) || 30;\n const maxExperiments = (args.maxExperiments as number) || 10;\n\n const area = IMPROVEMENT_AREAS.find(a => a.id === areaId);\n if (!area) {\n return `Error: unknown area \"${areaId}\". Valid areas: ${IMPROVEMENT_AREAS.map(a => a.id).join(', ')}`;\n }\n\n // Check config\n const config = loadConfig();\n const siConfig = (config as Record<string, unknown>).selfImprove as Record<string, unknown> | undefined;\n if (siConfig && siConfig.enabled === false) {\n return 'Self-improvement is disabled in config. Set selfImprove.enabled = true to enable.';\n }\n\n // Check daily budget\n if (siConfig) {\n const maxDaily = (siConfig.maxDailyBudgetMinutes as number) || 120;\n const today = new Date().toISOString().slice(0, 10);\n const todayMinutes = readHistory()\n .filter(s => s.startedAt.startsWith(today) && s.status === 'completed')\n .reduce((sum, s) => {\n const start = new Date(s.startedAt).getTime();\n const end = s.completedAt ? new Date(s.completedAt).getTime() : start;\n return sum + (end - start) / 60_000;\n }, 0);\n\n if (todayMinutes >= maxDaily) {\n return `Daily self-improvement budget exhausted (${Math.round(todayMinutes)}/${maxDaily} min used today). Try again tomorrow.`;\n }\n }\n\n // Weekend check\n if (siConfig && siConfig.pauseOnWeekends) {\n const day = new Date().getDay();\n if (day === 0 || day === 6) {\n return 'Self-improvement paused on weekends (config: pauseOnWeekends = true).';\n }\n }\n\n // Initialize files\n initPromptFiles();\n initBenchmarks();\n\n const sessionId = getSessionId(areaId);\n logger.info(COMPONENT, `Starting self-improvement session ${sessionId} for area: ${area.label}`);\n\n // Run baseline eval\n logger.info(COMPONENT, 'Running baseline evaluation...');\n const baseline = await runEval(area);\n\n const session: ImprovementSession = {\n id: sessionId,\n area: areaId,\n status: 'running',\n startedAt: new Date().toISOString(),\n baselineScore: baseline.score,\n bestScore: baseline.score,\n experiments: 0,\n keeps: 0,\n discards: 0,\n crashes: 0,\n applied: false,\n };\n activeSessions.set(sessionId, session);\n\n // Run experiment loop on the prompt file\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const startTime = Date.now();\n const timeBudgetMs = budgetMinutes * 60 * 1000;\n const _originalContent = readFileSync(promptPath, 'utf-8'); void _originalContent;\n const model = config.agent?.model || 'anthropic/claude-sonnet-4-20250514';\n\n for (let i = 1; i <= maxExperiments; i++) {\n if (Date.now() - startTime >= timeBudgetMs) {\n logger.info(COMPONENT, `Time budget exhausted after ${i - 1} experiments`);\n break;\n }\n\n session.experiments = i;\n const currentContent = readFileSync(promptPath, 'utf-8');\n\n try {\n // Ask LLM for a modification\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt optimization expert. Your task: improve this AI agent prompt for better ${area.label.toLowerCase()}.\n\nCONTEXT:\n- Current score: ${session.bestScore}/100 (baseline: ${session.baselineScore}/100)\n- Experiment: ${i}/${maxExperiments}\n- Area: ${area.description}\n\nINSTRUCTIONS:\n1. Read the current prompt below\n2. Identify ONE specific improvement\n3. Respond with ONLY a JSON object (no markdown, no explanation)\n\nREQUIRED FORMAT:\n{\"hypothesis\":\"what this change will improve\",\"modification\":{\"search\":\"exact substring to find in the prompt\",\"replace\":\"the replacement text\"}}\n\nRULES:\n- \"search\" must be an EXACT substring that appears in the current prompt\n- Make small, targeted changes — one sentence or phrase at a time\n- Do NOT wrap in code blocks or add any text outside the JSON`,\n },\n { role: 'user', content: `/no_think\\nCurrent prompt content:\\n---\\n${currentContent}\\n---\\nRespond with only JSON:` },\n ],\n temperature: 0.7,\n maxTokens: 1024,\n });\n\n if (!response.content || response.content.trim().length === 0) {\n logger.warn(COMPONENT, `Experiment ${i}: empty response from LLM — skipping`);\n session.crashes++;\n continue;\n }\n\n // Extract JSON from potential markdown code blocks or mixed content\n let jsonStr = response.content.trim();\n const jsonMatch = jsonStr.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) jsonStr = jsonMatch[0];\n else {\n jsonStr = jsonStr.replace(/^```(?:json)?\\s*/m, '').replace(/\\s*```$/m, '').trim();\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n logger.warn(COMPONENT, `Experiment ${i}: invalid JSON response — skipping`);\n session.crashes++;\n continue;\n }\n\n const searchStr = (parsed.modification as Record<string, string>)?.search || '';\n const replaceStr = (parsed.modification as Record<string, string>)?.replace ?? '';\n\n if (!searchStr || !currentContent.includes(searchStr)) {\n session.crashes++;\n continue;\n }\n\n // Phase 9: rate limit — max 1 mutation per hour\n if (!canMutate()) {\n logger.info(COMPONENT, `Experiment ${i}: rate limited — skipping (min 1h between mutations)`);\n session.crashes++;\n continue;\n }\n\n // Phase 9: checkpoint before mutation\n const checkpointPath = createCheckpoint(area.id, currentContent);\n if (checkpointPath) {\n logger.debug(COMPONENT, `Checkpoint created: ${checkpointPath}`);\n }\n\n // Apply modification\n const modified = currentContent.replace(searchStr, replaceStr);\n writeFileSync(promptPath, modified, 'utf-8');\n recordMutation();\n\n // Evaluate\n const result = await runEval(area);\n\n if (result.score > session.bestScore) {\n session.bestScore = result.score;\n session.keeps++;\n logger.info(COMPONENT, `Experiment ${i}: KEEP — score ${session.bestScore} (was ${baseline.score})`);\n } else {\n // Revert\n writeFileSync(promptPath, currentContent, 'utf-8');\n session.discards++;\n logger.info(COMPONENT, `Experiment ${i}: DISCARD — score ${result.score} (best: ${session.bestScore})`);\n }\n } catch (err) {\n // Revert on error\n writeFileSync(promptPath, currentContent, 'utf-8');\n session.crashes++;\n logger.warn(COMPONENT, `Experiment ${i}: crash — ${(err as Error).message}`);\n }\n }\n\n // Finalize\n session.status = 'completed';\n session.completedAt = new Date().toISOString();\n activeSessions.delete(sessionId);\n appendHistory(session);\n\n // Save results\n const resultPath = join(RESULTS_DIR, `${sessionId}.json`);\n writeFileSync(resultPath, JSON.stringify(session, null, 2), 'utf-8');\n\n const improvement = session.bestScore - session.baselineScore;\n const elapsed = ((Date.now() - startTime) / 60_000).toFixed(1);\n\n // Notify on success\n if (improvement > 0 && siConfig?.notifyOnSuccess !== false) {\n logger.info(COMPONENT, `Self-improvement success: ${area.label} score improved by ${improvement} points`);\n }\n\n return [\n `## Self-Improvement Complete`,\n ``,\n `**Area**: ${area.label}`,\n `**Session**: ${sessionId}`,\n `**Duration**: ${elapsed} minutes`,\n ``,\n `| Stat | Value |`,\n `|------|-------|`,\n `| Experiments | ${session.experiments} |`,\n `| Keeps | ${session.keeps} |`,\n `| Discards | ${session.discards} |`,\n `| Crashes | ${session.crashes} |`,\n `| Baseline score | ${session.baselineScore}/100 |`,\n `| Best score | ${session.bestScore}/100 |`,\n `| Improvement | +${improvement} points |`,\n ``,\n improvement > 0\n ? `Improved prompt saved to \\`${join(PROMPTS_DIR, area.promptFile)}\\`. Use \\`self_improve_apply\\` to apply to live config.`\n : 'No improvement found. The current prompt is already optimal for this benchmark set.',\n ].join('\\n');\n}\n\nasync function selfImproveStatus(_args: Record<string, unknown>): Promise<string> {\n const lines: string[] = ['## Self-Improvement Status\\n'];\n\n // Active sessions\n if (activeSessions.size > 0) {\n lines.push('### Active Sessions');\n for (const [id, session] of activeSessions) {\n const elapsed = ((Date.now() - new Date(session.startedAt).getTime()) / 60_000).toFixed(1);\n lines.push(`- **${id}** (${session.area}): experiment ${session.experiments}, score ${session.bestScore}/100, running ${elapsed} min`);\n }\n lines.push('');\n }\n\n // Config\n const config = loadConfig();\n const siConfig = (config as Record<string, unknown>).selfImprove as Record<string, unknown> | undefined;\n lines.push('### Configuration');\n lines.push(`- Enabled: ${siConfig?.enabled !== false}`);\n lines.push(`- Runs per day: ${siConfig?.runsPerDay || 1}`);\n lines.push(`- Schedule: ${JSON.stringify(siConfig?.schedule || ['0 2 * * *'])}`);\n lines.push(`- Budget per run: ${siConfig?.budgetMinutes || 30} min`);\n lines.push(`- Max daily budget: ${siConfig?.maxDailyBudgetMinutes || 120} min`);\n lines.push(`- Auto-apply: ${siConfig?.autoApply || false}`);\n lines.push(`- Areas: ${JSON.stringify(siConfig?.areas || ['prompts', 'tool-selection', 'response-quality', 'error-recovery'])}`);\n lines.push('');\n\n // Recent history\n const history = readHistory(10);\n if (history.length > 0) {\n lines.push('### Recent Sessions');\n lines.push('| Date | Area | Baseline | Best | Improvement | Experiments |');\n lines.push('|------|------|----------|------|-------------|-------------|');\n for (const s of history.reverse()) {\n const date = s.startedAt.slice(0, 10);\n const imp = s.bestScore - s.baselineScore;\n lines.push(`| ${date} | ${s.area} | ${s.baselineScore} | ${s.bestScore} | +${imp} | ${s.experiments} |`);\n }\n } else {\n lines.push('No improvement sessions run yet. Use `self_improve_start` to begin.');\n }\n\n return lines.join('\\n');\n}\n\nasync function selfImproveApply(args: Record<string, unknown>): Promise<string> {\n const sessionId = args.sessionId as string | undefined;\n const area = args.area as string | undefined;\n\n if (!sessionId && !area) {\n return 'Error: provide either sessionId or area to apply improvements from.';\n }\n\n // Find the session\n let targetSession: ImprovementSession | undefined;\n if (sessionId) {\n const resultPath = join(RESULTS_DIR, `${sessionId}.json`);\n if (existsSync(resultPath)) {\n targetSession = JSON.parse(readFileSync(resultPath, 'utf-8'));\n }\n } else if (area) {\n // Find most recent successful session for this area\n const history = readHistory(100);\n targetSession = history\n .filter(s => s.area === area && s.status === 'completed' && s.bestScore > s.baselineScore)\n .pop();\n }\n\n if (!targetSession) {\n return 'No successful improvement session found to apply.';\n }\n\n if (targetSession.bestScore <= targetSession.baselineScore) {\n return 'Session had no improvement — nothing to apply.';\n }\n\n const areaInfo = IMPROVEMENT_AREAS.find(a => a.id === targetSession!.area);\n if (!areaInfo) {\n return `Unknown area: ${targetSession.area}`;\n }\n\n // The improved prompt is already saved in the prompts dir\n const promptPath = join(PROMPTS_DIR, areaInfo.promptFile);\n if (!existsSync(promptPath)) {\n return `Improved prompt file not found at ${promptPath}`;\n }\n\n // Mark as applied\n targetSession.applied = true;\n const resultPath = join(RESULTS_DIR, `${targetSession.id}.json`);\n writeFileSync(resultPath, JSON.stringify(targetSession, null, 2), 'utf-8');\n\n // Invalidate cache so the optimized prompt is picked up on the very next turn\n clearOptimizedPromptCache();\n\n return [\n `## Improvement Applied`,\n ``,\n `**Area**: ${areaInfo.label}`,\n `**Session**: ${targetSession.id}`,\n `**Score**: ${targetSession.baselineScore} → ${targetSession.bestScore} (+${targetSession.bestScore - targetSession.baselineScore})`,\n ``,\n `Improved prompt is active at \\`${promptPath}\\`.`,\n `TITAN will use this optimized prompt for ${areaInfo.label.toLowerCase()} going forward.`,\n ].join('\\n');\n}\n\nasync function selfImproveHistory(args: Record<string, unknown>): Promise<string> {\n const limit = (args.limit as number) || 20;\n const areaFilter = args.area as string | undefined;\n\n let history = readHistory(limit);\n if (areaFilter) {\n history = history.filter(s => s.area === areaFilter);\n }\n\n if (history.length === 0) {\n return 'No self-improvement sessions found. Use `self_improve_start` to begin.';\n }\n\n const lines: string[] = [\n '## Self-Improvement History',\n '',\n '| Date | Area | Baseline | Best | +Δ | Exps | K/D/C | Applied |',\n '|------|------|----------|------|----|------|-------|---------|',\n ];\n\n for (const s of history.reverse()) {\n const date = s.startedAt.slice(0, 16).replace('T', ' ');\n const imp = s.bestScore - s.baselineScore;\n lines.push(`| ${date} | ${s.area} | ${s.baselineScore} | ${s.bestScore} | +${imp} | ${s.experiments} | ${s.keeps}/${s.discards}/${s.crashes} | ${s.applied ? 'yes' : 'no'} |`);\n }\n\n // Aggregate stats\n const totalSessions = history.length;\n const totalImprovement = history.reduce((sum, s) => sum + (s.bestScore - s.baselineScore), 0);\n const avgImprovement = totalSessions > 0 ? (totalImprovement / totalSessions).toFixed(1) : '0';\n const successRate = totalSessions > 0\n ? ((history.filter(s => s.bestScore > s.baselineScore).length / totalSessions) * 100).toFixed(0)\n : '0';\n\n lines.push('');\n lines.push(`**Total sessions**: ${totalSessions} | **Avg improvement**: +${avgImprovement} | **Success rate**: ${successRate}%`);\n\n return lines.join('\\n');\n}\n\n// ── Registration ─────────────────────────────────────────────────────\n\nexport function registerSelfImproveSkill(): void {\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_start',\n description: `Use this when asked to \"improve yourself\", \"get better at X\", \"optimize your behavior\", or \"work on your error recovery\". Also call this proactively on a schedule to keep TITAN improving over time. Runs LLM-guided experiments on TITAN's own prompts, evaluates quality against benchmarks, and keeps whatever improves the score. Areas: prompts (system prompt wording), tool-selection (picking the right tool), response-quality (clarity and accuracy), error-recovery (handling failures gracefully).`,\n parameters: {\n type: 'object',\n properties: {\n area: {\n type: 'string',\n description: 'What to improve: prompts, tool-selection, response-quality, or error-recovery',\n },\n budgetMinutes: {\n type: 'number',\n description: 'Time budget in minutes (default: 30)',\n },\n maxExperiments: {\n type: 'number',\n description: 'Maximum experiments to run (default: 10)',\n },\n },\n required: ['area'],\n },\n execute: selfImproveStart,\n },\n );\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_status',\n description: 'Check whether TITAN is currently running any self-improvement sessions, view configuration, and see the history of past improvement runs with score trends.',\n parameters: {\n type: 'object',\n properties: {},\n required: [],\n },\n execute: selfImproveStatus,\n },\n );\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_apply',\n description: 'Apply a completed self-improvement result to TITAN\\'s live config so the better prompt goes into effect immediately.',\n parameters: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'Session ID to apply (from self_improve_history)',\n },\n area: {\n type: 'string',\n description: 'Apply latest successful improvement for this area',\n },\n },\n required: [],\n },\n execute: selfImproveApply,\n },\n );\n\n registerSkill(\n {\n name: 'self_improve',\n description: 'Use this when the user says \"improve yourself\", \"get better at X\", \"optimize your behavior\", \"learn from this mistake\", or when TITAN proactively wants to improve its own responses, tool selection, prompts, or error handling. Runs iterative self-improvement experiments and keeps whatever works.',\n version: '1.0.0',\n source: 'bundled',\n enabled: true,\n },\n {\n name: 'self_improve_history',\n description: 'Show the full history of self-improvement sessions — what was tried, what improved, keep/discard ratios, and overall score trends over time.',\n parameters: {\n type: 'object',\n properties: {\n limit: {\n type: 'number',\n description: 'Maximum sessions to show (default: 20)',\n },\n area: {\n type: 'string',\n description: 'Filter by area (optional)',\n },\n },\n required: [],\n },\n execute: selfImproveHistory,\n },\n );\n\n logger.info(COMPONENT, 'Self-improvement skill registered (4 tools)');\n}\n"],"mappings":"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","names":["content","resultPath"]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { homedir } from "os";
3
3
  import { join } from "path";
4
- const TITAN_VERSION = "5.3.2";
4
+ const TITAN_VERSION = "5.4.1";
5
5
  const TITAN_CODENAME = "Spacewalk";
6
6
  const TITAN_NAME = "TITAN";
7
7
  const TITAN_FULL_NAME = "The Intelligent Task Automation Network";
@@ -57,7 +57,7 @@ const DEFAULT_GATEWAY_HOST = "0.0.0.0";
57
57
  const DEFAULT_GATEWAY_PORT = 48420;
58
58
  const DEFAULT_WEB_PORT = 48421;
59
59
  const DEFAULT_MODEL = "anthropic/claude-sonnet-4-20250514";
60
- const DEFAULT_MAX_TOKENS = 12e3;
60
+ const DEFAULT_MAX_TOKENS = 2e5;
61
61
  const DEFAULT_TEMPERATURE = 0.7;
62
62
  const MAX_CONTEXT_MESSAGES = 50;
63
63
  const SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/constants.ts"],"sourcesContent":["/**\n * TITAN Constants\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport const TITAN_VERSION = '5.3.2';\nexport const TITAN_CODENAME = 'Spacewalk';\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} • by Tony Elliott ║\n╚══════════════════════════════════════════════════════╝`;\n\n// Paths\n// Hunt Finding #03 (2026-04-14): honor TITAN_HOME env var if set.\n// Previously this was hardcoded to `~/.titan`, which meant:\n// - Docker containers couldn't override the config path\n// - Shared machines couldn't isolate per-user state\n// - Test fixtures couldn't run against an isolated home\n// - The systemd unit's `Environment=TITAN_HOME=...` was silently ignored\n// The env var is read once at module load (constants are resolved at import time).\n// If TITAN_HOME starts with `~/`, expand it to the user's home dir.\nfunction resolveTitanHome(): string {\n const envHome = process.env.TITAN_HOME;\n if (envHome && envHome.trim().length > 0) {\n const trimmed = envHome.trim();\n if (trimmed.startsWith('~/')) {\n return join(homedir(), trimmed.slice(2));\n }\n if (trimmed === '~') {\n return homedir();\n }\n return trimmed;\n }\n return join(homedir(), '.titan');\n}\nexport const TITAN_HOME = resolveTitanHome();\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');\nexport const TITAN_MD_FILENAME = 'TITAN.md';\nexport const AUTOPILOT_MD = join(TITAN_HOME, 'AUTOPILOT.md');\nexport const AUTOPILOT_RUNS_PATH = join(TITAN_HOME, 'autopilot-runs.jsonl');\nexport const TITAN_CREDENTIALS_DIR = join(TITAN_HOME, 'credentials');\n\n// Income & lead tracking\nexport const INCOME_LEDGER_PATH = join(TITAN_HOME, 'income-ledger.jsonl');\nexport const FREELANCE_LEADS_PATH = join(TITAN_HOME, 'freelance-leads.jsonl');\nexport const FREELANCE_PROFILE_PATH = join(TITAN_HOME, 'freelance-profile.json');\nexport const LEADS_PATH = join(TITAN_HOME, 'leads.jsonl');\nexport const TELEMETRY_EVENTS_PATH = join(TITAN_HOME, 'telemetry-events.jsonl');\nexport const SOMADRIVE_STATE_PATH = join(TITAN_HOME, 'soma-drive-state.json');\nexport const ACTIVITY_LOG_PATH = join(TITAN_HOME, 'activity-log.jsonl');\n\n// Gateway defaults\nexport const DEFAULT_GATEWAY_HOST = '0.0.0.0';\nexport const DEFAULT_GATEWAY_PORT = 48420;\nexport const DEFAULT_WEB_PORT = 48421;\n\n// Agent defaults\nexport const DEFAULT_MODEL = 'anthropic/claude-sonnet-4-20250514';\nexport const DEFAULT_MAX_TOKENS = 12000;\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';\n/** Default allowed tools. Empty = allow ALL registered tools.\n * Use security.deniedTools to block specific tools instead. */\nexport const ALLOWED_TOOLS_DEFAULT: string[] = [];\nexport const DENIED_TOOLS_DEFAULT: string[] = [];\n"],"mappings":";AAGA,SAAS,eAAe;AACxB,SAAS,YAAY;AAEd,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AACnB,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAW1B,aAAa;AAAA;AAYnB,SAAS,mBAA2B;AAChC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAW,QAAQ,KAAK,EAAE,SAAS,GAAG;AACtC,UAAM,UAAU,QAAQ,KAAK;AAC7B,QAAI,QAAQ,WAAW,IAAI,GAAG;AAC1B,aAAO,KAAK,QAAQ,GAAG,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC3C;AACA,QAAI,YAAY,KAAK;AACjB,aAAO,QAAQ;AAAA,IACnB;AACA,WAAO;AAAA,EACX;AACA,SAAO,KAAK,QAAQ,GAAG,QAAQ;AACnC;AACO,MAAM,aAAa,iBAAiB;AACpC,MAAM,oBAAoB,KAAK,YAAY,YAAY;AACvD,MAAM,gBAAgB,KAAK,YAAY,UAAU;AACjD,MAAM,kBAAkB,KAAK,YAAY,WAAW;AACpD,MAAM,mBAAmB,KAAK,iBAAiB,QAAQ;AACvD,MAAM,iBAAiB,KAAK,YAAY,MAAM;AAC9C,MAAM,mBAAmB,KAAK,YAAY,QAAQ;AAGlD,MAAM,YAAY,KAAK,iBAAiB,WAAW;AACnD,MAAM,UAAU,KAAK,iBAAiB,SAAS;AAC/C,MAAM,WAAW,KAAK,iBAAiB,UAAU;AACjD,MAAM,oBAAoB;AAC1B,MAAM,eAAe,KAAK,YAAY,cAAc;AACpD,MAAM,sBAAsB,KAAK,YAAY,sBAAsB;AACnE,MAAM,wBAAwB,KAAK,YAAY,aAAa;AAG5D,MAAM,qBAAqB,KAAK,YAAY,qBAAqB;AACjE,MAAM,uBAAuB,KAAK,YAAY,uBAAuB;AACrE,MAAM,yBAAyB,KAAK,YAAY,wBAAwB;AACxE,MAAM,aAAa,KAAK,YAAY,aAAa;AACjD,MAAM,wBAAwB,KAAK,YAAY,wBAAwB;AACvE,MAAM,uBAAuB,KAAK,YAAY,uBAAuB;AACrE,MAAM,oBAAoB,KAAK,YAAY,oBAAoB;AAG/D,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,mBAAmB;AAGzB,MAAM,gBAAgB;AACtB,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,qBAAqB,KAAK,KAAK;AAGrC,MAAM,uBAAuB;AAG7B,MAAM,wBAAkC,CAAC;AACzC,MAAM,uBAAiC,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/constants.ts"],"sourcesContent":["/**\n * TITAN Constants\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport const TITAN_VERSION = '5.4.1';\nexport const TITAN_CODENAME = 'Spacewalk';\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} • by Tony Elliott ║\n╚══════════════════════════════════════════════════════╝`;\n\n// Paths\n// Hunt Finding #03 (2026-04-14): honor TITAN_HOME env var if set.\n// Previously this was hardcoded to `~/.titan`, which meant:\n// - Docker containers couldn't override the config path\n// - Shared machines couldn't isolate per-user state\n// - Test fixtures couldn't run against an isolated home\n// - The systemd unit's `Environment=TITAN_HOME=...` was silently ignored\n// The env var is read once at module load (constants are resolved at import time).\n// If TITAN_HOME starts with `~/`, expand it to the user's home dir.\nfunction resolveTitanHome(): string {\n const envHome = process.env.TITAN_HOME;\n if (envHome && envHome.trim().length > 0) {\n const trimmed = envHome.trim();\n if (trimmed.startsWith('~/')) {\n return join(homedir(), trimmed.slice(2));\n }\n if (trimmed === '~') {\n return homedir();\n }\n return trimmed;\n }\n return join(homedir(), '.titan');\n}\nexport const TITAN_HOME = resolveTitanHome();\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');\nexport const TITAN_MD_FILENAME = 'TITAN.md';\nexport const AUTOPILOT_MD = join(TITAN_HOME, 'AUTOPILOT.md');\nexport const AUTOPILOT_RUNS_PATH = join(TITAN_HOME, 'autopilot-runs.jsonl');\nexport const TITAN_CREDENTIALS_DIR = join(TITAN_HOME, 'credentials');\n\n// Income & lead tracking\nexport const INCOME_LEDGER_PATH = join(TITAN_HOME, 'income-ledger.jsonl');\nexport const FREELANCE_LEADS_PATH = join(TITAN_HOME, 'freelance-leads.jsonl');\nexport const FREELANCE_PROFILE_PATH = join(TITAN_HOME, 'freelance-profile.json');\nexport const LEADS_PATH = join(TITAN_HOME, 'leads.jsonl');\nexport const TELEMETRY_EVENTS_PATH = join(TITAN_HOME, 'telemetry-events.jsonl');\nexport const SOMADRIVE_STATE_PATH = join(TITAN_HOME, 'soma-drive-state.json');\nexport const ACTIVITY_LOG_PATH = join(TITAN_HOME, 'activity-log.jsonl');\n\n// Gateway defaults\nexport const DEFAULT_GATEWAY_HOST = '0.0.0.0';\nexport const DEFAULT_GATEWAY_PORT = 48420;\nexport const DEFAULT_WEB_PORT = 48421;\n\n// Agent defaults\nexport const DEFAULT_MODEL = 'anthropic/claude-sonnet-4-20250514';\n/** v5.4.1: User-preference ceiling. Providers clamp per-model via\n * clampMaxTokens() so this can be high without causing 400s on\n * capped endpoints (e.g. Claude Sonnet 4 8K, Cohere 4K). */\nexport const DEFAULT_MAX_TOKENS = 200000;\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';\n/** Default allowed tools. Empty = allow ALL registered tools.\n * Use security.deniedTools to block specific tools instead. */\nexport const ALLOWED_TOOLS_DEFAULT: string[] = [];\nexport const DENIED_TOOLS_DEFAULT: string[] = [];\n"],"mappings":";AAGA,SAAS,eAAe;AACxB,SAAS,YAAY;AAEd,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AACnB,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAW1B,aAAa;AAAA;AAYnB,SAAS,mBAA2B;AAChC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAW,QAAQ,KAAK,EAAE,SAAS,GAAG;AACtC,UAAM,UAAU,QAAQ,KAAK;AAC7B,QAAI,QAAQ,WAAW,IAAI,GAAG;AAC1B,aAAO,KAAK,QAAQ,GAAG,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC3C;AACA,QAAI,YAAY,KAAK;AACjB,aAAO,QAAQ;AAAA,IACnB;AACA,WAAO;AAAA,EACX;AACA,SAAO,KAAK,QAAQ,GAAG,QAAQ;AACnC;AACO,MAAM,aAAa,iBAAiB;AACpC,MAAM,oBAAoB,KAAK,YAAY,YAAY;AACvD,MAAM,gBAAgB,KAAK,YAAY,UAAU;AACjD,MAAM,kBAAkB,KAAK,YAAY,WAAW;AACpD,MAAM,mBAAmB,KAAK,iBAAiB,QAAQ;AACvD,MAAM,iBAAiB,KAAK,YAAY,MAAM;AAC9C,MAAM,mBAAmB,KAAK,YAAY,QAAQ;AAGlD,MAAM,YAAY,KAAK,iBAAiB,WAAW;AACnD,MAAM,UAAU,KAAK,iBAAiB,SAAS;AAC/C,MAAM,WAAW,KAAK,iBAAiB,UAAU;AACjD,MAAM,oBAAoB;AAC1B,MAAM,eAAe,KAAK,YAAY,cAAc;AACpD,MAAM,sBAAsB,KAAK,YAAY,sBAAsB;AACnE,MAAM,wBAAwB,KAAK,YAAY,aAAa;AAG5D,MAAM,qBAAqB,KAAK,YAAY,qBAAqB;AACjE,MAAM,uBAAuB,KAAK,YAAY,uBAAuB;AACrE,MAAM,yBAAyB,KAAK,YAAY,wBAAwB;AACxE,MAAM,aAAa,KAAK,YAAY,aAAa;AACjD,MAAM,wBAAwB,KAAK,YAAY,wBAAwB;AACvE,MAAM,uBAAuB,KAAK,YAAY,uBAAuB;AACrE,MAAM,oBAAoB,KAAK,YAAY,oBAAoB;AAG/D,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,mBAAmB;AAGzB,MAAM,gBAAgB;AAItB,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,qBAAqB,KAAK,KAAK;AAGrC,MAAM,uBAAuB;AAG7B,MAAM,wBAAkC,CAAC;AACzC,MAAM,uBAAiC,CAAC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "titan-agent",
3
- "version": "5.3.2",
3
+ "version": "5.4.1",
4
4
  "description": "TITAN — Autonomous AI agent framework with self-improvement, multi-agent orchestration, 36 LLM providers, 16 channel adapters, GPU VRAM management, mesh networking, LiveKit voice, TITAN-Soma homeostatic drives, and a React Mission Control dashboard. Open-source, TypeScript, MIT licensed.",
5
5
  "author": "Tony Elliott (https://github.com/Djtony707)",
6
6
  "repository": {