titan-agent 5.3.2 → 5.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.
- package/dist/agent/agent.js +11 -1
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/session.js +106 -5
- package/dist/agent/session.js.map +1 -1
- package/dist/agent/subAgent.js +62 -1
- package/dist/agent/subAgent.js.map +1 -1
- package/dist/config/schema.js +18 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/gateway/server.js +17 -1
- package/dist/gateway/server.js.map +1 -1
- package/dist/memory/graph.js +49 -15
- package/dist/memory/graph.js.map +1 -1
- package/dist/memory/index.js +192 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/memory.js +1 -0
- package/dist/memory/memory.js.map +1 -1
- package/dist/safety/fabricationGuard.js +140 -0
- package/dist/safety/fabricationGuard.js.map +1 -0
- package/dist/skills/builtin/gepa.js +23 -1
- package/dist/skills/builtin/gepa.js.map +1 -1
- package/dist/skills/builtin/model_trainer.js +31 -4
- package/dist/skills/builtin/model_trainer.js.map +1 -1
- package/dist/skills/builtin/self_improve.js +50 -2
- package/dist/skills/builtin/self_improve.js.map +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/skills/builtin/gepa.ts"],"sourcesContent":["/**\n * TITAN — GEPA: Genetic Evolution of Prompts & Agents\n * Population-based evolutionary optimization of TITAN's prompts and behaviors.\n *\n * Unlike the single-point LLM-guided optimization in self_improve.ts, GEPA\n * maintains a population of prompt variants and uses genetic operators:\n * - Tournament selection (pick best of K random candidates)\n * - LLM-guided crossover (merge two parent prompts)\n * - LLM-guided mutation (targeted search/replace modification)\n * - Elitism (top performers survive unchanged)\n *\n * Builds on the existing self-improvement eval harness, benchmarks, and session tracking.\n */\nimport { registerSkill } from '../registry.js';\nimport { loadConfig } from '../../config/config.js';\nimport logger from '../../utils/logger.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { chat } from '../../providers/router.js';\nimport {\n SELF_IMPROVE_DIR,\n PROMPTS_DIR,\n IMPROVEMENT_AREAS,\n ensureDirs,\n initPromptFiles,\n initBenchmarks,\n runEval,\n appendHistory,\n readHistory,\n type ImprovementArea,\n type ImprovementSession,\n} from './self_improve.js';\n\nconst COMPONENT = 'GEPA';\n\n// ── Paths ────────────────────────────────────────────────────────────\n\nconst EVOLUTION_DIR = join(SELF_IMPROVE_DIR, 'evolution');\n\nfunction ensureEvolutionDirs(area: string): void {\n ensureDirs();\n mkdirSync(join(EVOLUTION_DIR, area), { recursive: true });\n}\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface Individual {\n id: string;\n content: string;\n fitness: number;\n generation: number;\n parentIds: string[];\n operation: 'seed' | 'crossover' | 'mutation' | 'elite';\n}\n\nexport interface Population {\n area: string;\n generation: number;\n individuals: Individual[];\n bestFitness: number;\n avgFitness: number;\n createdAt: string;\n}\n\nexport interface EvolutionConfig {\n populationSize: number;\n tournamentSize: number;\n eliteCount: number;\n mutationRate: number;\n crossoverRate: number;\n maxGenerations: number;\n budgetMinutes: number;\n}\n\ninterface EvolutionSession extends ImprovementSession {\n type: 'evolution';\n config: EvolutionConfig;\n generations: number;\n populationSize: number;\n bestIndividual: { id: string; fitness: number; generation: number };\n}\n\nconst DEFAULT_CONFIG: EvolutionConfig = {\n populationSize: 8,\n tournamentSize: 3,\n eliteCount: 2,\n mutationRate: 0.8,\n crossoverRate: 0.6,\n maxGenerations: 10,\n budgetMinutes: 60,\n};\n\n// ── Active sessions ──────────────────────────────────────────────────\n\nconst activeSessions: Map<string, EvolutionSession> = new Map();\n\n// ── Eval locks (serialize file writes per area) ─────────────────────\n\nconst evalLocks = new Map<string, Promise<void>>();\n\n// ── Core Evolution Functions ─────────────────────────────────────────\n\n/** Tournament selection: pick k random individuals, return the fittest */\nexport function tournamentSelect(individuals: Individual[], k: number): Individual {\n if (individuals.length === 0) throw new Error('Cannot select from empty population');\n if (individuals.length === 1) return individuals[0];\n const effectiveK = Math.min(k, individuals.length);\n const pool: Individual[] = [];\n for (let i = 0; i < effectiveK; i++) {\n const idx = Math.floor(Math.random() * individuals.length);\n pool.push(individuals[idx]);\n }\n pool.sort((a, b) => b.fitness - a.fitness);\n return pool[0];\n}\n\n/** LLM-guided crossover: merge two parent prompts */\nexport async function crossover(\n parent1: Individual,\n parent2: Individual,\n area: ImprovementArea,\n model: string,\n): Promise<string> {\n try {\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt engineering expert. Merge these two AI agent prompts into a single improved prompt for ${area.label.toLowerCase()}. Take the best elements from each parent. The merged prompt should be roughly the same length as the parents.\n\nRespond with ONLY the merged prompt text, nothing else. No markdown, no explanation.`,\n },\n {\n role: 'user',\n content: `/no_think\\nParent A (score ${parent1.fitness}/100):\\n---\\n${parent1.content}\\n---\\n\\nParent B (score ${parent2.fitness}/100):\\n---\\n${parent2.content}\\n---\\n\\nMerged prompt:`,\n },\n ],\n temperature: 0.7,\n maxTokens: 2048,\n });\n\n if (response.content && response.content.trim().length > 10) {\n return response.content.trim();\n }\n // Fallback: return higher-fitness parent\n return parent1.fitness >= parent2.fitness ? parent1.content : parent2.content;\n } catch (e) {\n logger.warn(COMPONENT, `Crossover failed: ${(e as Error).message}`);\n return parent1.fitness >= parent2.fitness ? parent1.content : parent2.content;\n }\n}\n\n/** LLM-guided mutation: apply a targeted modification */\nexport async function mutate(\n individual: Individual,\n area: ImprovementArea,\n model: string,\n): Promise<string> {\n try {\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt optimization expert. Make ONE targeted improvement to this AI agent prompt for better ${area.label.toLowerCase()}.\n\nRespond with ONLY a JSON object (no markdown, no explanation):\n{\"search\":\"exact substring to find\",\"replace\":\"replacement text\"}\n\nRULES:\n- \"search\" must be an EXACT substring in the current prompt\n- Make small, targeted changes — one sentence or phrase at a time`,\n },\n {\n role: 'user',\n content: `/no_think\\nCurrent prompt (score ${individual.fitness}/100):\\n---\\n${individual.content}\\n---\\nRespond with only JSON:`,\n },\n ],\n temperature: 0.8,\n maxTokens: 1024,\n });\n\n if (!response.content || response.content.trim().length === 0) {\n return individual.content;\n }\n\n let jsonStr = response.content.trim();\n const jsonMatch = jsonStr.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) jsonStr = jsonMatch[0];\n else jsonStr = jsonStr.replace(/^```(?:json)?\\s*/m, '').replace(/\\s*```$/m, '').trim();\n\n const parsed = JSON.parse(jsonStr);\n const searchStr = parsed.search || '';\n const replaceStr = parsed.replace ?? '';\n\n if (searchStr && individual.content.includes(searchStr)) {\n return individual.content.replace(searchStr, replaceStr);\n }\n return individual.content;\n } catch (e) {\n logger.warn(COMPONENT, `Mutation failed: ${(e as Error).message}`);\n return individual.content;\n }\n}\n\n/** Evaluate an individual's fitness using the self-improve eval harness */\nasync function evaluateIndividual(\n individual: Individual,\n area: ImprovementArea,\n): Promise<number> {\n // Serialize evaluations per area to prevent file corruption\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const lockKey = area.id;\n while (evalLocks.has(lockKey)) {\n await evalLocks.get(lockKey);\n }\n const originalContent = existsSync(promptPath) ? readFileSync(promptPath, 'utf-8') : '';\n let resolve: () => void;\n evalLocks.set(lockKey, new Promise<void>(r => { resolve = r; }));\n try {\n writeFileSync(promptPath, individual.content, 'utf-8');\n const result = await runEval(area);\n individual.fitness = result.score;\n return result.score;\n } finally {\n writeFileSync(promptPath, originalContent, 'utf-8');\n evalLocks.delete(lockKey);\n resolve!();\n }\n}\n\n/** Initialize generation 0: seed from current prompt + LLM-generated variants */\nexport async function initPopulation(\n area: ImprovementArea,\n config: EvolutionConfig,\n model: string,\n): Promise<Population> {\n ensureEvolutionDirs(area.id);\n initPromptFiles();\n initBenchmarks();\n\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const originalContent = readFileSync(promptPath, 'utf-8');\n\n const individuals: Individual[] = [];\n\n // Individual #0: the current prompt (the \"Adam\")\n const adam: Individual = {\n id: 'gen0-ind0',\n content: originalContent,\n fitness: 0,\n generation: 0,\n parentIds: [],\n operation: 'seed',\n };\n individuals.push(adam);\n\n // Generate variants via LLM\n for (let i = 1; i < config.populationSize; i++) {\n try {\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt engineering expert. Rephrase and restructure this AI agent prompt with a different emphasis or approach. The goal is ${area.description.toLowerCase()}. Keep roughly the same length and intent, but vary the wording, structure, and priorities.\n\nRespond with ONLY the new prompt text, nothing else.`,\n },\n {\n role: 'user',\n content: `/no_think\\nOriginal prompt:\\n---\\n${originalContent}\\n---\\n\\nVariant ${i} (try a ${['more concise', 'more detailed', 'more structured', 'more conversational', 'more directive', 'more examples-focused', 'more rule-based'][i % 7]} approach):`,\n },\n ],\n temperature: 0.9,\n maxTokens: 2048,\n });\n\n const content = response.content?.trim() || originalContent;\n individuals.push({\n id: `gen0-ind${i}`,\n content: content.length > 10 ? content : originalContent,\n fitness: 0,\n generation: 0,\n parentIds: [],\n operation: 'seed',\n });\n } catch (e) {\n logger.warn(COMPONENT, `Failed to generate variant ${i}: ${(e as Error).message}`);\n // Use original with slight perturbation marker\n individuals.push({\n id: `gen0-ind${i}`,\n content: originalContent,\n fitness: 0,\n generation: 0,\n parentIds: [],\n operation: 'seed',\n });\n }\n }\n\n // Evaluate all individuals\n for (const ind of individuals) {\n ind.fitness = await evaluateIndividual(ind, area);\n logger.debug(COMPONENT, `Gen 0 | ${ind.id}: fitness ${ind.fitness}`);\n }\n\n const population: Population = {\n area: area.id,\n generation: 0,\n individuals,\n bestFitness: Math.max(...individuals.map(i => i.fitness)),\n avgFitness: Math.round(individuals.reduce((s, i) => s + i.fitness, 0) / individuals.length),\n createdAt: new Date().toISOString(),\n };\n\n // Save generation 0\n const genPath = join(EVOLUTION_DIR, area.id, 'gen-0.json');\n writeFileSync(genPath, JSON.stringify(population, null, 2), 'utf-8');\n\n return population;\n}\n\n/** Evolve one generation */\nexport async function evolveGeneration(\n population: Population,\n area: ImprovementArea,\n config: EvolutionConfig,\n model: string,\n): Promise<Population> {\n const nextGen = population.generation + 1;\n const sorted = [...population.individuals].sort((a, b) => b.fitness - a.fitness);\n\n const newIndividuals: Individual[] = [];\n\n // Elitism: preserve top performers\n for (let i = 0; i < Math.min(config.eliteCount, sorted.length); i++) {\n newIndividuals.push({\n ...sorted[i],\n id: `gen${nextGen}-ind${i}`,\n generation: nextGen,\n parentIds: [sorted[i].id],\n operation: 'elite',\n });\n }\n\n // Fill remaining slots\n while (newIndividuals.length < config.populationSize) {\n const idx = newIndividuals.length;\n let content: string;\n let parentIds: string[];\n let operation: Individual['operation'];\n\n if (Math.random() < config.crossoverRate) {\n // Crossover\n const parent1 = tournamentSelect(population.individuals, config.tournamentSize);\n const parent2 = tournamentSelect(population.individuals, config.tournamentSize);\n content = await crossover(parent1, parent2, area, model);\n parentIds = [parent1.id, parent2.id];\n operation = 'crossover';\n } else {\n // Clone from tournament winner\n const parent = tournamentSelect(population.individuals, config.tournamentSize);\n content = parent.content;\n parentIds = [parent.id];\n operation = 'mutation';\n }\n\n // Apply mutation with probability\n if (Math.random() < config.mutationRate) {\n const tempInd: Individual = {\n id: `gen${nextGen}-ind${idx}`,\n content,\n fitness: 0,\n generation: nextGen,\n parentIds,\n operation,\n };\n content = await mutate(tempInd, area, model);\n if (operation !== 'crossover') operation = 'mutation';\n }\n\n newIndividuals.push({\n id: `gen${nextGen}-ind${idx}`,\n content,\n fitness: 0,\n generation: nextGen,\n parentIds,\n operation,\n });\n }\n\n // Evaluate all new (non-elite) individuals\n for (const ind of newIndividuals) {\n if (ind.operation === 'elite') continue; // Already has fitness from parent\n ind.fitness = await evaluateIndividual(ind, area);\n logger.debug(COMPONENT, `Gen ${nextGen} | ${ind.id}: fitness ${ind.fitness} (${ind.operation})`);\n }\n\n const newPopulation: Population = {\n area: area.id,\n generation: nextGen,\n individuals: newIndividuals,\n bestFitness: Math.max(...newIndividuals.map(i => i.fitness)),\n avgFitness: Math.round(newIndividuals.reduce((s, i) => s + i.fitness, 0) / newIndividuals.length),\n createdAt: new Date().toISOString(),\n };\n\n // Save generation\n const genPath = join(EVOLUTION_DIR, area.id, `gen-${nextGen}.json`);\n writeFileSync(genPath, JSON.stringify(newPopulation, null, 2), 'utf-8');\n\n return newPopulation;\n}\n\n/** Main evolution loop */\nexport async function runEvolution(\n areaId: string,\n userConfig: Partial<EvolutionConfig> = {},\n): Promise<string> {\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 appConfig = loadConfig();\n const siConfig = (appConfig 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).`;\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 const config: EvolutionConfig = { ...DEFAULT_CONFIG, ...userConfig };\n const model = appConfig.agent?.model || 'anthropic/claude-sonnet-4-20250514';\n const startTime = Date.now();\n const timeBudgetMs = config.budgetMinutes * 60 * 1000;\n\n const sessionId = `gepa-${areaId}-${Date.now().toString(36)}`;\n logger.info(COMPONENT, `Starting evolution ${sessionId} for ${area.label} (pop=${config.populationSize}, gens=${config.maxGenerations})`);\n\n // Initialize population\n let population = await initPopulation(area, config, model);\n const baselineScore = population.bestFitness;\n\n const session: EvolutionSession = {\n id: sessionId,\n area: areaId,\n type: 'evolution',\n status: 'running',\n startedAt: new Date().toISOString(),\n baselineScore,\n bestScore: baselineScore,\n experiments: 0,\n keeps: 0,\n discards: 0,\n crashes: 0,\n applied: false,\n config,\n generations: 0,\n populationSize: config.populationSize,\n bestIndividual: {\n id: population.individuals.sort((a, b) => b.fitness - a.fitness)[0].id,\n fitness: baselineScore,\n generation: 0,\n },\n };\n activeSessions.set(sessionId, session);\n\n const generationLog: { gen: number; best: number; avg: number }[] = [\n { gen: 0, best: population.bestFitness, avg: population.avgFitness },\n ];\n\n let staleCount = 0;\n\n // Evolution loop\n for (let gen = 1; gen <= config.maxGenerations; gen++) {\n if (Date.now() - startTime >= timeBudgetMs) {\n logger.info(COMPONENT, `Time budget exhausted after ${gen - 1} generations`);\n break;\n }\n\n try {\n population = await evolveGeneration(population, area, config, model);\n session.generations = gen;\n session.experiments += config.populationSize;\n\n generationLog.push({\n gen,\n best: population.bestFitness,\n avg: population.avgFitness,\n });\n\n logger.info(COMPONENT, `Gen ${gen}: best=${population.bestFitness}, avg=${population.avgFitness}`);\n\n if (population.bestFitness > session.bestScore) {\n session.bestScore = population.bestFitness;\n const best = population.individuals.sort((a, b) => b.fitness - a.fitness)[0];\n session.bestIndividual = { id: best.id, fitness: best.fitness, generation: gen };\n session.keeps++;\n staleCount = 0;\n } else {\n session.discards++;\n staleCount++;\n }\n\n // Early stop on fitness plateau\n if (staleCount >= 3) {\n logger.info(COMPONENT, `Early stop: no improvement in ${staleCount} consecutive generations`);\n break;\n }\n } catch (e) {\n session.crashes++;\n logger.warn(COMPONENT, `Generation ${gen} crashed: ${(e as Error).message}`);\n }\n }\n\n // Apply best individual to prompt file\n const bestGen = session.bestIndividual.generation;\n const bestGenPath = join(EVOLUTION_DIR, area.id, `gen-${bestGen}.json`);\n if (existsSync(bestGenPath)) {\n const bestPop: Population = JSON.parse(readFileSync(bestGenPath, 'utf-8'));\n const bestInd = bestPop.individuals.sort((a, b) => b.fitness - a.fitness)[0];\n if (bestInd && session.bestScore > baselineScore) {\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n writeFileSync(promptPath, bestInd.content, 'utf-8');\n session.applied = true;\n logger.info(COMPONENT, `Applied best individual ${bestInd.id} (fitness ${bestInd.fitness}) to ${area.promptFile}`);\n }\n }\n\n // Finalize session\n session.status = 'completed';\n session.completedAt = new Date().toISOString();\n activeSessions.delete(sessionId);\n appendHistory(session as unknown as ImprovementSession);\n\n // Save lineage\n const lineagePath = join(EVOLUTION_DIR, area.id, 'lineage.json');\n const lineage: Individual[] = [];\n for (const g of generationLog) {\n const genPath = join(EVOLUTION_DIR, area.id, `gen-${g.gen}.json`);\n if (existsSync(genPath)) {\n const pop: Population = JSON.parse(readFileSync(genPath, 'utf-8'));\n for (const ind of pop.individuals) {\n lineage.push({\n id: ind.id,\n content: '', // Omit content in lineage for size\n fitness: ind.fitness,\n generation: ind.generation,\n parentIds: ind.parentIds,\n operation: ind.operation,\n });\n }\n }\n }\n writeFileSync(lineagePath, JSON.stringify(lineage, null, 2), 'utf-8');\n\n const elapsed = ((Date.now() - startTime) / 60_000).toFixed(1);\n const improvement = session.bestScore - baselineScore;\n\n // Build generation progression table\n const genTable = generationLog\n .map(g => `| ${g.gen} | ${g.best} | ${g.avg} |`)\n .join('\\n');\n\n return [\n `## GEPA Evolution Complete`,\n ``,\n `**Area**: ${area.label}`,\n `**Session**: ${sessionId}`,\n `**Duration**: ${elapsed} minutes`,\n ``,\n `### Configuration`,\n `| Setting | Value |`,\n `|---------|-------|`,\n `| Population size | ${config.populationSize} |`,\n `| Tournament size | ${config.tournamentSize} |`,\n `| Elite count | ${config.eliteCount} |`,\n `| Mutation rate | ${config.mutationRate} |`,\n `| Crossover rate | ${config.crossoverRate} |`,\n ``,\n `### Results`,\n `| Stat | Value |`,\n `|------|-------|`,\n `| Generations | ${session.generations} |`,\n `| Total evaluations | ${session.experiments} |`,\n `| Baseline score | ${baselineScore}/100 |`,\n `| Best score | ${session.bestScore}/100 |`,\n `| Improvement | +${improvement} points |`,\n `| Best individual | ${session.bestIndividual.id} (gen ${session.bestIndividual.generation}) |`,\n ``,\n `### Fitness Progression`,\n `| Gen | Best | Avg |`,\n `|-----|------|-----|`,\n genTable,\n ``,\n improvement > 0\n ? `Evolved prompt applied to \\`${join(PROMPTS_DIR, area.promptFile)}\\`.`\n : 'No improvement found. Current prompt is already optimal for this benchmark set.',\n ].join('\\n');\n}\n\n// ── Tool Implementations ─────────────────────────────────────────────\n\nasync function gepaEvolve(args: Record<string, unknown>): Promise<string> {\n const areaId = (args.area as string) || 'prompts';\n const userConfig: Partial<EvolutionConfig> = {};\n\n if (args.populationSize) userConfig.populationSize = args.populationSize as number;\n if (args.maxGenerations) userConfig.maxGenerations = args.maxGenerations as number;\n if (args.budgetMinutes) userConfig.budgetMinutes = args.budgetMinutes as number;\n if (args.tournamentSize) userConfig.tournamentSize = args.tournamentSize as number;\n if (args.eliteCount) userConfig.eliteCount = args.eliteCount as number;\n if (args.mutationRate) userConfig.mutationRate = args.mutationRate as number;\n if (args.crossoverRate) userConfig.crossoverRate = args.crossoverRate as number;\n\n return runEvolution(areaId, userConfig);\n}\n\nasync function gepaStatus(args: Record<string, unknown>): Promise<string> {\n const areaFilter = args.area as string | undefined;\n const lines: string[] = ['## GEPA Evolution 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}**: gen ${session.generations}, best ${session.bestScore}/100, pop ${session.populationSize}, running ${elapsed} min`);\n }\n lines.push('');\n }\n\n // Latest populations per area\n const areas = areaFilter ? [areaFilter] : IMPROVEMENT_AREAS.map(a => a.id);\n let hasData = false;\n\n for (const aId of areas) {\n const areaDir = join(EVOLUTION_DIR, aId);\n if (!existsSync(areaDir)) continue;\n\n // Find latest generation\n let latestGen = -1;\n try {\n for (let g = 50; g >= 0; g--) {\n if (existsSync(join(areaDir, `gen-${g}.json`))) {\n latestGen = g;\n break;\n }\n }\n } catch { /* ignore */ }\n\n if (latestGen < 0) continue;\n hasData = true;\n\n const genPath = join(areaDir, `gen-${latestGen}.json`);\n const pop: Population = JSON.parse(readFileSync(genPath, 'utf-8'));\n const areaInfo = IMPROVEMENT_AREAS.find(a => a.id === aId);\n\n lines.push(`### ${areaInfo?.label || aId}`);\n lines.push(`- **Latest generation**: ${latestGen}`);\n lines.push(`- **Best fitness**: ${pop.bestFitness}/100`);\n lines.push(`- **Avg fitness**: ${pop.avgFitness}/100`);\n lines.push(`- **Population size**: ${pop.individuals.length}`);\n\n // Fitness trend (last 5 gens)\n const trend: string[] = [];\n for (let g = Math.max(0, latestGen - 4); g <= latestGen; g++) {\n const gPath = join(areaDir, `gen-${g}.json`);\n if (existsSync(gPath)) {\n const gPop: Population = JSON.parse(readFileSync(gPath, 'utf-8'));\n trend.push(`gen${g}:${gPop.bestFitness}`);\n }\n }\n if (trend.length > 0) {\n lines.push(`- **Trend**: ${trend.join(' → ')}`);\n }\n lines.push('');\n }\n\n if (!hasData && activeSessions.size === 0) {\n lines.push('No evolution data found. Use `gepa_evolve` to start.');\n }\n\n return lines.join('\\n');\n}\n\nasync function gepaHistory(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(100);\n // Filter to evolution sessions\n history = history.filter(s => (s as unknown as EvolutionSession).type === 'evolution');\n if (areaFilter) {\n history = history.filter(s => s.area === areaFilter);\n }\n history = history.slice(-limit);\n\n if (history.length === 0) {\n return 'No GEPA evolution sessions found. Use `gepa_evolve` to start.';\n }\n\n const lines: string[] = [\n '## GEPA Evolution History',\n '',\n '| Date | Area | Baseline | Best | +Δ | Gens | Pop | Applied |',\n '|------|------|----------|------|----|------|-----|---------|',\n ];\n\n for (const s of [...history].reverse()) {\n const es = s as unknown as EvolutionSession;\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} | ${es.generations || '?'} | ${es.populationSize || '?'} | ${s.applied ? 'yes' : 'no'} |`);\n }\n\n // Aggregate\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\nconst SKILL_META = {\n name: 'gepa',\n description: 'Genetic Evolution of Prompts & Agents — population-based evolutionary optimization of TITAN\\'s prompts using tournament selection, crossover, and mutation. Use when \"evolve prompts\", \"genetic optimization\", or \"population-based improvement\" is requested.',\n version: '1.0.0',\n source: 'bundled' as const,\n enabled: true,\n};\n\nexport function registerGepaSkill(): void {\n registerSkill(SKILL_META, {\n name: 'gepa_evolve',\n description: `Run genetic evolution on TITAN's prompts. Maintains a population of prompt variants, uses tournament selection to pick parents, crossover to combine them, and mutation to explore. Elitism preserves the best. Areas: prompts, tool-selection, response-quality, error-recovery.`,\n parameters: {\n type: 'object',\n properties: {\n area: {\n type: 'string',\n description: 'What to evolve: prompts, tool-selection, response-quality, or error-recovery',\n },\n populationSize: {\n type: 'number',\n description: 'Number of prompt variants per generation (default: 8)',\n },\n maxGenerations: {\n type: 'number',\n description: 'Maximum generations to evolve (default: 10)',\n },\n budgetMinutes: {\n type: 'number',\n description: 'Time budget in minutes (default: 60)',\n },\n },\n required: ['area'],\n },\n execute: gepaEvolve,\n });\n\n registerSkill(SKILL_META, {\n name: 'gepa_status',\n description: 'Check current GEPA evolution status — active runs, population snapshots, fitness trends across generations.',\n parameters: {\n type: 'object',\n properties: {\n area: {\n type: 'string',\n description: 'Filter by area (optional)',\n },\n },\n required: [],\n },\n execute: gepaStatus,\n });\n\n registerSkill(SKILL_META, {\n name: 'gepa_history',\n description: 'View GEPA evolution history — past runs, best scores, generation counts, and improvement trends.',\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: gepaHistory,\n });\n\n logger.info(COMPONENT, 'GEPA evolution skill registered (3 tools)');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/skills/builtin/gepa.ts"],"sourcesContent":["/**\n * TITAN — GEPA: Genetic Evolution of Prompts & Agents\n * Population-based evolutionary optimization of TITAN's prompts and behaviors.\n *\n * Unlike the single-point LLM-guided optimization in self_improve.ts, GEPA\n * maintains a population of prompt variants and uses genetic operators:\n * - Tournament selection (pick best of K random candidates)\n * - LLM-guided crossover (merge two parent prompts)\n * - LLM-guided mutation (targeted search/replace modification)\n * - Elitism (top performers survive unchanged)\n *\n * Builds on the existing self-improvement eval harness, benchmarks, and session tracking.\n */\nimport { registerSkill } from '../registry.js';\nimport { loadConfig } from '../../config/config.js';\nimport logger from '../../utils/logger.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { chat } from '../../providers/router.js';\nimport {\n SELF_IMPROVE_DIR,\n PROMPTS_DIR,\n IMPROVEMENT_AREAS,\n ensureDirs,\n initPromptFiles,\n initBenchmarks,\n runEval,\n appendHistory,\n readHistory,\n type ImprovementArea,\n type ImprovementSession,\n} from './self_improve.js';\n\nconst COMPONENT = 'GEPA';\n\n// ── Paths ────────────────────────────────────────────────────────────\n\nconst EVOLUTION_DIR = join(SELF_IMPROVE_DIR, 'evolution');\n\nfunction ensureEvolutionDirs(area: string): void {\n ensureDirs();\n mkdirSync(join(EVOLUTION_DIR, area), { recursive: true });\n}\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface Individual {\n id: string;\n content: string;\n fitness: number;\n generation: number;\n parentIds: string[];\n operation: 'seed' | 'crossover' | 'mutation' | 'elite';\n}\n\nexport interface Population {\n area: string;\n generation: number;\n individuals: Individual[];\n bestFitness: number;\n avgFitness: number;\n createdAt: string;\n}\n\nexport interface EvolutionConfig {\n populationSize: number;\n tournamentSize: number;\n eliteCount: number;\n mutationRate: number;\n crossoverRate: number;\n maxGenerations: number;\n budgetMinutes: number;\n}\n\ninterface EvolutionSession extends ImprovementSession {\n type: 'evolution';\n config: EvolutionConfig;\n generations: number;\n populationSize: number;\n bestIndividual: { id: string; fitness: number; generation: number };\n}\n\nconst DEFAULT_CONFIG: EvolutionConfig = {\n populationSize: 8,\n tournamentSize: 3,\n eliteCount: 2,\n mutationRate: 0.8,\n crossoverRate: 0.6,\n maxGenerations: 10,\n budgetMinutes: 60,\n};\n\n// ── Active sessions ──────────────────────────────────────────────────\n\nconst activeSessions: Map<string, EvolutionSession> = new Map();\n\n// ── Eval locks (serialize file writes per area) ─────────────────────\n\nconst evalLocks = new Map<string, Promise<void>>();\n\n// ── Core Evolution Functions ─────────────────────────────────────────\n\n/** Tournament selection: pick k random individuals, return the fittest */\nexport function tournamentSelect(individuals: Individual[], k: number): Individual {\n if (individuals.length === 0) throw new Error('Cannot select from empty population');\n if (individuals.length === 1) return individuals[0];\n const effectiveK = Math.min(k, individuals.length);\n const pool: Individual[] = [];\n for (let i = 0; i < effectiveK; i++) {\n const idx = Math.floor(Math.random() * individuals.length);\n pool.push(individuals[idx]);\n }\n pool.sort((a, b) => b.fitness - a.fitness);\n return pool[0];\n}\n\n/** LLM-guided crossover: merge two parent prompts */\nexport async function crossover(\n parent1: Individual,\n parent2: Individual,\n area: ImprovementArea,\n model: string,\n): Promise<string> {\n try {\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt engineering expert. Merge these two AI agent prompts into a single improved prompt for ${area.label.toLowerCase()}. Take the best elements from each parent. The merged prompt should be roughly the same length as the parents.\n\nRespond with ONLY the merged prompt text, nothing else. No markdown, no explanation.`,\n },\n {\n role: 'user',\n content: `/no_think\\nParent A (score ${parent1.fitness}/100):\\n---\\n${parent1.content}\\n---\\n\\nParent B (score ${parent2.fitness}/100):\\n---\\n${parent2.content}\\n---\\n\\nMerged prompt:`,\n },\n ],\n temperature: 0.7,\n maxTokens: 2048,\n });\n\n if (response.content && response.content.trim().length > 10) {\n return response.content.trim();\n }\n // Fallback: return higher-fitness parent\n return parent1.fitness >= parent2.fitness ? parent1.content : parent2.content;\n } catch (e) {\n logger.warn(COMPONENT, `Crossover failed: ${(e as Error).message}`);\n return parent1.fitness >= parent2.fitness ? parent1.content : parent2.content;\n }\n}\n\n/** LLM-guided mutation: apply a targeted modification */\nexport async function mutate(\n individual: Individual,\n area: ImprovementArea,\n model: string,\n): Promise<string> {\n try {\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt optimization expert. Make ONE targeted improvement to this AI agent prompt for better ${area.label.toLowerCase()}.\n\nRespond with ONLY a JSON object (no markdown, no explanation):\n{\"search\":\"exact substring to find\",\"replace\":\"replacement text\"}\n\nRULES:\n- \"search\" must be an EXACT substring in the current prompt\n- Make small, targeted changes — one sentence or phrase at a time`,\n },\n {\n role: 'user',\n content: `/no_think\\nCurrent prompt (score ${individual.fitness}/100):\\n---\\n${individual.content}\\n---\\nRespond with only JSON:`,\n },\n ],\n temperature: 0.8,\n maxTokens: 1024,\n });\n\n if (!response.content || response.content.trim().length === 0) {\n return individual.content;\n }\n\n let jsonStr = response.content.trim();\n const jsonMatch = jsonStr.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) jsonStr = jsonMatch[0];\n else jsonStr = jsonStr.replace(/^```(?:json)?\\s*/m, '').replace(/\\s*```$/m, '').trim();\n\n const parsed = JSON.parse(jsonStr);\n const searchStr = parsed.search || '';\n const replaceStr = parsed.replace ?? '';\n\n if (searchStr && individual.content.includes(searchStr)) {\n return individual.content.replace(searchStr, replaceStr);\n }\n return individual.content;\n } catch (e) {\n logger.warn(COMPONENT, `Mutation failed: ${(e as Error).message}`);\n return individual.content;\n }\n}\n\n/** Evaluate an individual's fitness using the self-improve eval harness */\nasync function evaluateIndividual(\n individual: Individual,\n area: ImprovementArea,\n): Promise<number> {\n // Serialize evaluations per area to prevent file corruption\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const lockKey = area.id;\n while (evalLocks.has(lockKey)) {\n await evalLocks.get(lockKey);\n }\n const originalContent = existsSync(promptPath) ? readFileSync(promptPath, 'utf-8') : '';\n let resolve: () => void;\n evalLocks.set(lockKey, new Promise<void>(r => { resolve = r; }));\n try {\n writeFileSync(promptPath, individual.content, 'utf-8');\n const result = await runEval(area);\n individual.fitness = result.score;\n return result.score;\n } finally {\n writeFileSync(promptPath, originalContent, 'utf-8');\n evalLocks.delete(lockKey);\n resolve!();\n }\n}\n\n/** Initialize generation 0: seed from current prompt + LLM-generated variants */\nexport async function initPopulation(\n area: ImprovementArea,\n config: EvolutionConfig,\n model: string,\n): Promise<Population> {\n ensureEvolutionDirs(area.id);\n initPromptFiles();\n initBenchmarks();\n\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n const originalContent = readFileSync(promptPath, 'utf-8');\n\n const individuals: Individual[] = [];\n\n // Individual #0: the current prompt (the \"Adam\")\n const adam: Individual = {\n id: 'gen0-ind0',\n content: originalContent,\n fitness: 0,\n generation: 0,\n parentIds: [],\n operation: 'seed',\n };\n individuals.push(adam);\n\n // Generate variants via LLM\n for (let i = 1; i < config.populationSize; i++) {\n try {\n const response = await chat({\n model,\n messages: [\n {\n role: 'system',\n content: `You are a prompt engineering expert. Rephrase and restructure this AI agent prompt with a different emphasis or approach. The goal is ${area.description.toLowerCase()}. Keep roughly the same length and intent, but vary the wording, structure, and priorities.\n\nRespond with ONLY the new prompt text, nothing else.`,\n },\n {\n role: 'user',\n content: `/no_think\\nOriginal prompt:\\n---\\n${originalContent}\\n---\\n\\nVariant ${i} (try a ${['more concise', 'more detailed', 'more structured', 'more conversational', 'more directive', 'more examples-focused', 'more rule-based'][i % 7]} approach):`,\n },\n ],\n temperature: 0.9,\n maxTokens: 2048,\n });\n\n const content = response.content?.trim() || originalContent;\n individuals.push({\n id: `gen0-ind${i}`,\n content: content.length > 10 ? content : originalContent,\n fitness: 0,\n generation: 0,\n parentIds: [],\n operation: 'seed',\n });\n } catch (e) {\n logger.warn(COMPONENT, `Failed to generate variant ${i}: ${(e as Error).message}`);\n // Use original with slight perturbation marker\n individuals.push({\n id: `gen0-ind${i}`,\n content: originalContent,\n fitness: 0,\n generation: 0,\n parentIds: [],\n operation: 'seed',\n });\n }\n }\n\n // Evaluate all individuals\n for (const ind of individuals) {\n ind.fitness = await evaluateIndividual(ind, area);\n logger.debug(COMPONENT, `Gen 0 | ${ind.id}: fitness ${ind.fitness}`);\n }\n\n const population: Population = {\n area: area.id,\n generation: 0,\n individuals,\n bestFitness: Math.max(...individuals.map(i => i.fitness)),\n avgFitness: Math.round(individuals.reduce((s, i) => s + i.fitness, 0) / individuals.length),\n createdAt: new Date().toISOString(),\n };\n\n // Save generation 0\n const genPath = join(EVOLUTION_DIR, area.id, 'gen-0.json');\n writeFileSync(genPath, JSON.stringify(population, null, 2), 'utf-8');\n\n return population;\n}\n\n/** Evolve one generation */\nexport async function evolveGeneration(\n population: Population,\n area: ImprovementArea,\n config: EvolutionConfig,\n model: string,\n): Promise<Population> {\n const nextGen = population.generation + 1;\n const sorted = [...population.individuals].sort((a, b) => b.fitness - a.fitness);\n\n const newIndividuals: Individual[] = [];\n\n // Elitism: preserve top performers\n for (let i = 0; i < Math.min(config.eliteCount, sorted.length); i++) {\n newIndividuals.push({\n ...sorted[i],\n id: `gen${nextGen}-ind${i}`,\n generation: nextGen,\n parentIds: [sorted[i].id],\n operation: 'elite',\n });\n }\n\n // Fill remaining slots\n while (newIndividuals.length < config.populationSize) {\n const idx = newIndividuals.length;\n let content: string;\n let parentIds: string[];\n let operation: Individual['operation'];\n\n if (Math.random() < config.crossoverRate) {\n // Crossover\n const parent1 = tournamentSelect(population.individuals, config.tournamentSize);\n const parent2 = tournamentSelect(population.individuals, config.tournamentSize);\n content = await crossover(parent1, parent2, area, model);\n parentIds = [parent1.id, parent2.id];\n operation = 'crossover';\n } else {\n // Clone from tournament winner\n const parent = tournamentSelect(population.individuals, config.tournamentSize);\n content = parent.content;\n parentIds = [parent.id];\n operation = 'mutation';\n }\n\n // Apply mutation with probability\n if (Math.random() < config.mutationRate) {\n const tempInd: Individual = {\n id: `gen${nextGen}-ind${idx}`,\n content,\n fitness: 0,\n generation: nextGen,\n parentIds,\n operation,\n };\n content = await mutate(tempInd, area, model);\n if (operation !== 'crossover') operation = 'mutation';\n }\n\n newIndividuals.push({\n id: `gen${nextGen}-ind${idx}`,\n content,\n fitness: 0,\n generation: nextGen,\n parentIds,\n operation,\n });\n }\n\n // Evaluate all new (non-elite) individuals\n for (const ind of newIndividuals) {\n if (ind.operation === 'elite') continue; // Already has fitness from parent\n ind.fitness = await evaluateIndividual(ind, area);\n logger.debug(COMPONENT, `Gen ${nextGen} | ${ind.id}: fitness ${ind.fitness} (${ind.operation})`);\n }\n\n const newPopulation: Population = {\n area: area.id,\n generation: nextGen,\n individuals: newIndividuals,\n bestFitness: Math.max(...newIndividuals.map(i => i.fitness)),\n avgFitness: Math.round(newIndividuals.reduce((s, i) => s + i.fitness, 0) / newIndividuals.length),\n createdAt: new Date().toISOString(),\n };\n\n // Save generation\n const genPath = join(EVOLUTION_DIR, area.id, `gen-${nextGen}.json`);\n writeFileSync(genPath, JSON.stringify(newPopulation, null, 2), 'utf-8');\n\n return newPopulation;\n}\n\n/** Main evolution loop */\nexport async function runEvolution(\n areaId: string,\n userConfig: Partial<EvolutionConfig> = {},\n): Promise<string> {\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 appConfig = loadConfig();\n const siConfig = (appConfig 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).`;\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 const config: EvolutionConfig = { ...DEFAULT_CONFIG, ...userConfig };\n const model = appConfig.agent?.model || 'anthropic/claude-sonnet-4-20250514';\n const startTime = Date.now();\n const timeBudgetMs = config.budgetMinutes * 60 * 1000;\n\n const sessionId = `gepa-${areaId}-${Date.now().toString(36)}`;\n logger.info(COMPONENT, `Starting evolution ${sessionId} for ${area.label} (pop=${config.populationSize}, gens=${config.maxGenerations})`);\n\n // Initialize population\n let population = await initPopulation(area, config, model);\n const baselineScore = population.bestFitness;\n\n const session: EvolutionSession = {\n id: sessionId,\n area: areaId,\n type: 'evolution',\n status: 'running',\n startedAt: new Date().toISOString(),\n baselineScore,\n bestScore: baselineScore,\n experiments: 0,\n keeps: 0,\n discards: 0,\n crashes: 0,\n applied: false,\n config,\n generations: 0,\n populationSize: config.populationSize,\n bestIndividual: {\n id: population.individuals.sort((a, b) => b.fitness - a.fitness)[0].id,\n fitness: baselineScore,\n generation: 0,\n },\n };\n activeSessions.set(sessionId, session);\n\n const generationLog: { gen: number; best: number; avg: number }[] = [\n { gen: 0, best: population.bestFitness, avg: population.avgFitness },\n ];\n\n let staleCount = 0;\n\n // Evolution loop\n for (let gen = 1; gen <= config.maxGenerations; gen++) {\n if (Date.now() - startTime >= timeBudgetMs) {\n logger.info(COMPONENT, `Time budget exhausted after ${gen - 1} generations`);\n break;\n }\n\n try {\n population = await evolveGeneration(population, area, config, model);\n session.generations = gen;\n session.experiments += config.populationSize;\n\n generationLog.push({\n gen,\n best: population.bestFitness,\n avg: population.avgFitness,\n });\n\n logger.info(COMPONENT, `Gen ${gen}: best=${population.bestFitness}, avg=${population.avgFitness}`);\n\n if (population.bestFitness > session.bestScore) {\n session.bestScore = population.bestFitness;\n const best = population.individuals.sort((a, b) => b.fitness - a.fitness)[0];\n session.bestIndividual = { id: best.id, fitness: best.fitness, generation: gen };\n session.keeps++;\n staleCount = 0;\n } else {\n session.discards++;\n staleCount++;\n }\n\n // Early stop on fitness plateau\n if (staleCount >= 3) {\n logger.info(COMPONENT, `Early stop: no improvement in ${staleCount} consecutive generations`);\n break;\n }\n } catch (e) {\n session.crashes++;\n logger.warn(COMPONENT, `Generation ${gen} crashed: ${(e as Error).message}`);\n }\n }\n\n // Apply best individual to prompt file\n const bestGen = session.bestIndividual.generation;\n const bestGenPath = join(EVOLUTION_DIR, area.id, `gen-${bestGen}.json`);\n if (existsSync(bestGenPath)) {\n const bestPop: Population = JSON.parse(readFileSync(bestGenPath, 'utf-8'));\n const bestInd = bestPop.individuals.sort((a, b) => b.fitness - a.fitness)[0];\n if (bestInd && session.bestScore > baselineScore) {\n const promptPath = join(PROMPTS_DIR, area.promptFile);\n writeFileSync(promptPath, bestInd.content, 'utf-8');\n session.applied = true;\n logger.info(COMPONENT, `Applied best individual ${bestInd.id} (fitness ${bestInd.fitness}) to ${area.promptFile}`);\n }\n }\n\n // Finalize session\n session.status = 'completed';\n session.completedAt = new Date().toISOString();\n activeSessions.delete(sessionId);\n appendHistory(session as unknown as ImprovementSession);\n\n // Save lineage\n const lineagePath = join(EVOLUTION_DIR, area.id, 'lineage.json');\n const lineage: Individual[] = [];\n for (const g of generationLog) {\n const genPath = join(EVOLUTION_DIR, area.id, `gen-${g.gen}.json`);\n if (existsSync(genPath)) {\n const pop: Population = JSON.parse(readFileSync(genPath, 'utf-8'));\n for (const ind of pop.individuals) {\n lineage.push({\n id: ind.id,\n content: '', // Omit content in lineage for size\n fitness: ind.fitness,\n generation: ind.generation,\n parentIds: ind.parentIds,\n operation: ind.operation,\n });\n }\n }\n }\n writeFileSync(lineagePath, JSON.stringify(lineage, null, 2), 'utf-8');\n\n const elapsed = ((Date.now() - startTime) / 60_000).toFixed(1);\n const improvement = session.bestScore - baselineScore;\n\n // Build generation progression table\n const genTable = generationLog\n .map(g => `| ${g.gen} | ${g.best} | ${g.avg} |`)\n .join('\\n');\n\n return [\n `## GEPA Evolution Complete`,\n ``,\n `**Area**: ${area.label}`,\n `**Session**: ${sessionId}`,\n `**Duration**: ${elapsed} minutes`,\n ``,\n `### Configuration`,\n `| Setting | Value |`,\n `|---------|-------|`,\n `| Population size | ${config.populationSize} |`,\n `| Tournament size | ${config.tournamentSize} |`,\n `| Elite count | ${config.eliteCount} |`,\n `| Mutation rate | ${config.mutationRate} |`,\n `| Crossover rate | ${config.crossoverRate} |`,\n ``,\n `### Results`,\n `| Stat | Value |`,\n `|------|-------|`,\n `| Generations | ${session.generations} |`,\n `| Total evaluations | ${session.experiments} |`,\n `| Baseline score | ${baselineScore}/100 |`,\n `| Best score | ${session.bestScore}/100 |`,\n `| Improvement | +${improvement} points |`,\n `| Best individual | ${session.bestIndividual.id} (gen ${session.bestIndividual.generation}) |`,\n ``,\n `### Fitness Progression`,\n `| Gen | Best | Avg |`,\n `|-----|------|-----|`,\n genTable,\n ``,\n improvement > 0\n ? `Evolved prompt applied to \\`${join(PROMPTS_DIR, area.promptFile)}\\`.`\n : 'No improvement found. Current prompt is already optimal for this benchmark set.',\n ].join('\\n');\n}\n\n// ── Tool Implementations ─────────────────────────────────────────────\n\nasync function gepaEvolve(args: Record<string, unknown>): Promise<string> {\n const areaId = (args.area as string) || 'prompts';\n const userConfig: Partial<EvolutionConfig> = {};\n\n if (args.populationSize) userConfig.populationSize = args.populationSize as number;\n if (args.maxGenerations) userConfig.maxGenerations = args.maxGenerations as number;\n if (args.budgetMinutes) userConfig.budgetMinutes = args.budgetMinutes as number;\n if (args.tournamentSize) userConfig.tournamentSize = args.tournamentSize as number;\n if (args.eliteCount) userConfig.eliteCount = args.eliteCount as number;\n if (args.mutationRate) userConfig.mutationRate = args.mutationRate as number;\n if (args.crossoverRate) userConfig.crossoverRate = args.crossoverRate as number;\n\n return runEvolution(areaId, userConfig);\n}\n\nasync function gepaStatus(args: Record<string, unknown>): Promise<string> {\n const areaFilter = args.area as string | undefined;\n const lines: string[] = ['## GEPA Evolution 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}**: gen ${session.generations}, best ${session.bestScore}/100, pop ${session.populationSize}, running ${elapsed} min`);\n }\n lines.push('');\n }\n\n // Latest populations per area\n const areas = areaFilter ? [areaFilter] : IMPROVEMENT_AREAS.map(a => a.id);\n let hasData = false;\n\n for (const aId of areas) {\n const areaDir = join(EVOLUTION_DIR, aId);\n if (!existsSync(areaDir)) continue;\n\n // Find latest generation\n let latestGen = -1;\n try {\n for (let g = 50; g >= 0; g--) {\n if (existsSync(join(areaDir, `gen-${g}.json`))) {\n latestGen = g;\n break;\n }\n }\n } catch { /* ignore */ }\n\n if (latestGen < 0) continue;\n hasData = true;\n\n const genPath = join(areaDir, `gen-${latestGen}.json`);\n const pop: Population = JSON.parse(readFileSync(genPath, 'utf-8'));\n const areaInfo = IMPROVEMENT_AREAS.find(a => a.id === aId);\n\n lines.push(`### ${areaInfo?.label || aId}`);\n lines.push(`- **Latest generation**: ${latestGen}`);\n lines.push(`- **Best fitness**: ${pop.bestFitness}/100`);\n lines.push(`- **Avg fitness**: ${pop.avgFitness}/100`);\n lines.push(`- **Population size**: ${pop.individuals.length}`);\n\n // Fitness trend (last 5 gens)\n const trend: string[] = [];\n for (let g = Math.max(0, latestGen - 4); g <= latestGen; g++) {\n const gPath = join(areaDir, `gen-${g}.json`);\n if (existsSync(gPath)) {\n const gPop: Population = JSON.parse(readFileSync(gPath, 'utf-8'));\n trend.push(`gen${g}:${gPop.bestFitness}`);\n }\n }\n if (trend.length > 0) {\n lines.push(`- **Trend**: ${trend.join(' → ')}`);\n }\n lines.push('');\n }\n\n if (!hasData && activeSessions.size === 0) {\n lines.push('No evolution data found. Use `gepa_evolve` to start.');\n }\n\n return lines.join('\\n');\n}\n\nasync function gepaHistory(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(100);\n // Filter to evolution sessions\n history = history.filter(s => (s as unknown as EvolutionSession).type === 'evolution');\n if (areaFilter) {\n history = history.filter(s => s.area === areaFilter);\n }\n history = history.slice(-limit);\n\n if (history.length === 0) {\n return 'No GEPA evolution sessions found. Use `gepa_evolve` to start.';\n }\n\n const lines: string[] = [\n '## GEPA Evolution History',\n '',\n '| Date | Area | Baseline | Best | +Δ | Gens | Pop | Applied |',\n '|------|------|----------|------|----|------|-----|---------|',\n ];\n\n for (const s of [...history].reverse()) {\n const es = s as unknown as EvolutionSession;\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} | ${es.generations || '?'} | ${es.populationSize || '?'} | ${s.applied ? 'yes' : 'no'} |`);\n }\n\n // Aggregate\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\nconst SKILL_META = {\n name: 'gepa',\n description: 'Genetic Evolution of Prompts & Agents — population-based evolutionary optimization of TITAN\\'s prompts using tournament selection, crossover, and mutation. Use when \"evolve prompts\", \"genetic optimization\", or \"population-based improvement\" is requested.',\n version: '1.0.0',\n source: 'bundled' as const,\n enabled: true,\n};\n\nexport function registerGepaSkill(): void {\n registerSkill(SKILL_META, {\n name: 'gepa_evolve',\n description: `Run genetic evolution on TITAN's prompts. Maintains a population of prompt variants, uses tournament selection to pick parents, crossover to combine them, and mutation to explore. Elitism preserves the best. Areas: prompts, tool-selection, response-quality, error-recovery.`,\n parameters: {\n type: 'object',\n properties: {\n area: {\n type: 'string',\n description: 'What to evolve: prompts, tool-selection, response-quality, or error-recovery',\n },\n populationSize: {\n type: 'number',\n description: 'Number of prompt variants per generation (default: 8)',\n },\n maxGenerations: {\n type: 'number',\n description: 'Maximum generations to evolve (default: 10)',\n },\n budgetMinutes: {\n type: 'number',\n description: 'Time budget in minutes (default: 60)',\n },\n },\n required: ['area'],\n },\n execute: gepaEvolve,\n });\n\n registerSkill(SKILL_META, {\n name: 'gepa_status',\n description: 'Check current GEPA evolution status — active runs, population snapshots, fitness trends across generations.',\n parameters: {\n type: 'object',\n properties: {\n area: {\n type: 'string',\n description: 'Filter by area (optional)',\n },\n },\n required: [],\n },\n execute: gepaStatus,\n });\n\n registerSkill(SKILL_META, {\n name: 'gepa_history',\n description: 'View GEPA evolution history — past runs, best scores, generation counts, and improvement trends.',\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: gepaHistory,\n });\n\n // Phase 9: GEPA daemon watcher — runs once per day if self-improvement is enabled.\n // Wrapped in an async IIFE so registerGepaSkill() can stay synchronous\n // (the registry doesn't await skill registration) while still using\n // dynamic import() for the daemon module.\n void (async () => {\n try {\n const { registerWatcher } = await import('../../agent/daemon.js');\n registerWatcher('gepa-daily-evolve', async () => {\n const cfg = loadConfig();\n if (!cfg.selfImprove?.enabled) {\n logger.debug(COMPONENT, 'GEPA daily watcher skipped — selfImprove.disabled');\n return;\n }\n // Pick a random area each day\n const area = IMPROVEMENT_AREAS[Math.floor(Math.random() * IMPROVEMENT_AREAS.length)];\n logger.info(COMPONENT, `GEPA daily watcher starting evolution for area: ${area.id}`);\n try {\n await gepaEvolve({ area: area.id, budgetMinutes: 30, maxGenerations: 5 });\n } catch (e) {\n logger.error(COMPONENT, `GEPA daily watcher failed: ${(e as Error).message}`);\n }\n }, 24 * 60 * 60 * 1000); // 24 hours\n logger.info(COMPONENT, 'GEPA daily watcher registered (24h interval)');\n } catch {\n logger.warn(COMPONENT, 'Daemon system not available — GEPA daily watcher not registered');\n }\n })();\n\n logger.info(COMPONENT, 'GEPA evolution skill registered (3 tools + daily watcher)');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -232,23 +232,50 @@ def main():
|
|
|
232
232
|
start = time.time()
|
|
233
233
|
|
|
234
234
|
if not HAS_UNSLOTH:
|
|
235
|
-
# Simulation mode \u2014
|
|
235
|
+
# Simulation mode \u2014 still produces a evaluable val_score so the
|
|
236
|
+
# autopilot can benchmark improvements. Score is derived from data
|
|
237
|
+
# quality (line count, JSON validity) rather than fake constants.
|
|
238
|
+
import random
|
|
236
239
|
print(f"[SIM] Loading base model: {BASE_MODEL}")
|
|
237
240
|
print(f"[SIM] Training data: {DATA_PATH}")
|
|
238
241
|
time.sleep(2)
|
|
242
|
+
|
|
243
|
+
# Compute a data-quality heuristic that stays stable across runs
|
|
244
|
+
data_score = 0.0
|
|
245
|
+
try:
|
|
246
|
+
with open(DATA_PATH, "r") as f:
|
|
247
|
+
lines = f.readlines()
|
|
248
|
+
total = len(lines)
|
|
249
|
+
valid_json = sum(1 for line in lines if line.strip() and line.strip().startswith("{"))
|
|
250
|
+
data_score = min(100.0, (valid_json / max(total, 1)) * 100.0 + total * 0.5)
|
|
251
|
+
except Exception:
|
|
252
|
+
data_score = 45.0
|
|
253
|
+
|
|
254
|
+
best_loss = 999.0
|
|
239
255
|
for epoch in range(1, EPOCHS + 1):
|
|
240
256
|
elapsed = time.time() - start
|
|
241
257
|
if elapsed > MAX_MINUTES * 60:
|
|
242
258
|
print(f"[SIM] Time budget exhausted at epoch {epoch}")
|
|
243
259
|
break
|
|
244
|
-
loss = 2.5 - (epoch * 0.3)
|
|
260
|
+
loss = max(0.5, 2.5 - (epoch * 0.3) - (data_score / 100.0))
|
|
261
|
+
best_loss = min(best_loss, loss)
|
|
245
262
|
print(f"Epoch {epoch}/{EPOCHS} \u2014 loss: {loss:.4f}")
|
|
246
263
|
time.sleep(1)
|
|
247
264
|
|
|
265
|
+
# val_score = inverse of loss, scaled to 0-100, boosted by data quality
|
|
266
|
+
val_score = round(min(100.0, max(0.0, (3.0 - best_loss) * 40.0 + data_score * 0.2)), 2)
|
|
267
|
+
|
|
248
268
|
# Write results
|
|
249
269
|
with open(os.path.join(OUTPUT_DIR, "results.json"), "w") as f:
|
|
250
|
-
json.dump({
|
|
251
|
-
|
|
270
|
+
json.dump({
|
|
271
|
+
"status": "simulated",
|
|
272
|
+
"epochs": EPOCHS,
|
|
273
|
+
"final_loss": round(best_loss, 4),
|
|
274
|
+
"val_score": val_score,
|
|
275
|
+
"model_path": None,
|
|
276
|
+
"note": "unsloth not installed \u2014 score is a data-quality heuristic"
|
|
277
|
+
}, f)
|
|
278
|
+
print(f"Training complete (simulated) \u2014 val_score: {val_score}")
|
|
252
279
|
return
|
|
253
280
|
|
|
254
281
|
# Real training with unsloth
|