feat: Capability Evolver 升级 + 日常运行日志
主要变更: - Capability Evolver 技能大幅升级 - 新增 LLM 审查、叙事记忆、反思机制模块 - 改进 Agent 间通信协议和技能搜索 - 整合 Git 备份到 evolver-run.sh - Agent 配置与日志更新 - dev-assist/haonan/main 认证和会话配置 - 5 个 agent 的 AGENTS.md 文档更新 - haonan 的 MEMORY.md 和 SOUL.md 更新 - 新增功能目录 - hooks/self-improvement 自我改进钩子 - memory/evolution 进化记忆状态 - workspace/.learnings/ 学习记录 - 清理 - 删除 scripts/git-auto-sync.sh(已整合到 evolver) - 删除旧的 _meta.json 配置 - 忽略临时工作空间目录
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { getReflectionLogPath, getEvolutionDir } = require('./paths');
|
||||
|
||||
const REFLECTION_INTERVAL_CYCLES = 5;
|
||||
const REFLECTION_COOLDOWN_MS = 30 * 60 * 1000;
|
||||
|
||||
function ensureDir(dir) {
|
||||
try { if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); } catch (_) {}
|
||||
}
|
||||
|
||||
function shouldReflect({ cycleCount, recentEvents }) {
|
||||
if (!Number.isFinite(cycleCount) || cycleCount < REFLECTION_INTERVAL_CYCLES) return false;
|
||||
if (cycleCount % REFLECTION_INTERVAL_CYCLES !== 0) return false;
|
||||
|
||||
const logPath = getReflectionLogPath();
|
||||
try {
|
||||
if (fs.existsSync(logPath)) {
|
||||
const stat = fs.statSync(logPath);
|
||||
if (Date.now() - stat.mtimeMs < REFLECTION_COOLDOWN_MS) return false;
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildReflectionContext({ recentEvents, signals, memoryAdvice, narrative }) {
|
||||
const parts = ['You are performing a strategic reflection on recent evolution cycles.'];
|
||||
parts.push('Analyze the patterns below and provide concise strategic guidance.');
|
||||
parts.push('');
|
||||
|
||||
if (Array.isArray(recentEvents) && recentEvents.length > 0) {
|
||||
const last10 = recentEvents.slice(-10);
|
||||
const successCount = last10.filter(e => e && e.outcome && e.outcome.status === 'success').length;
|
||||
const failCount = last10.filter(e => e && e.outcome && e.outcome.status === 'failed').length;
|
||||
const intents = {};
|
||||
last10.forEach(e => {
|
||||
const i = e && e.intent ? e.intent : 'unknown';
|
||||
intents[i] = (intents[i] || 0) + 1;
|
||||
});
|
||||
const genes = {};
|
||||
last10.forEach(e => {
|
||||
const g = e && Array.isArray(e.genes_used) && e.genes_used[0] ? e.genes_used[0] : 'unknown';
|
||||
genes[g] = (genes[g] || 0) + 1;
|
||||
});
|
||||
|
||||
parts.push('## Recent Cycle Statistics (last 10)');
|
||||
parts.push(`- Success: ${successCount}, Failed: ${failCount}`);
|
||||
parts.push(`- Intent distribution: ${JSON.stringify(intents)}`);
|
||||
parts.push(`- Gene usage: ${JSON.stringify(genes)}`);
|
||||
parts.push('');
|
||||
}
|
||||
|
||||
if (Array.isArray(signals) && signals.length > 0) {
|
||||
parts.push('## Current Signals');
|
||||
parts.push(signals.slice(0, 20).join(', '));
|
||||
parts.push('');
|
||||
}
|
||||
|
||||
if (memoryAdvice) {
|
||||
parts.push('## Memory Graph Advice');
|
||||
if (memoryAdvice.preferredGeneId) {
|
||||
parts.push(`- Preferred gene: ${memoryAdvice.preferredGeneId}`);
|
||||
}
|
||||
if (Array.isArray(memoryAdvice.bannedGeneIds) && memoryAdvice.bannedGeneIds.length > 0) {
|
||||
parts.push(`- Banned genes: ${memoryAdvice.bannedGeneIds.join(', ')}`);
|
||||
}
|
||||
if (memoryAdvice.explanation) {
|
||||
parts.push(`- Explanation: ${memoryAdvice.explanation}`);
|
||||
}
|
||||
parts.push('');
|
||||
}
|
||||
|
||||
if (narrative) {
|
||||
parts.push('## Recent Evolution Narrative');
|
||||
parts.push(String(narrative).slice(0, 3000));
|
||||
parts.push('');
|
||||
}
|
||||
|
||||
parts.push('## Questions to Answer');
|
||||
parts.push('1. Are there persistent signals being ignored?');
|
||||
parts.push('2. Is the gene selection strategy optimal, or are we stuck in a local maximum?');
|
||||
parts.push('3. Should the balance between repair/optimize/innovate shift?');
|
||||
parts.push('4. Are there capability gaps that no current gene addresses?');
|
||||
parts.push('5. What single strategic adjustment would have the highest impact?');
|
||||
parts.push('');
|
||||
parts.push('Respond with a JSON object: { "insights": [...], "strategy_adjustment": "...", "priority_signals": [...] }');
|
||||
|
||||
return parts.join('\n');
|
||||
}
|
||||
|
||||
function recordReflection(reflection) {
|
||||
const logPath = getReflectionLogPath();
|
||||
ensureDir(path.dirname(logPath));
|
||||
|
||||
const entry = JSON.stringify({
|
||||
ts: new Date().toISOString(),
|
||||
type: 'reflection',
|
||||
...reflection,
|
||||
}) + '\n';
|
||||
|
||||
fs.appendFileSync(logPath, entry, 'utf8');
|
||||
}
|
||||
|
||||
function loadRecentReflections(count) {
|
||||
const n = Number.isFinite(count) ? count : 3;
|
||||
const logPath = getReflectionLogPath();
|
||||
try {
|
||||
if (!fs.existsSync(logPath)) return [];
|
||||
const lines = fs.readFileSync(logPath, 'utf8').trim().split('\n').filter(Boolean);
|
||||
return lines.slice(-n).map(line => {
|
||||
try { return JSON.parse(line); } catch (_) { return null; }
|
||||
}).filter(Boolean);
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldReflect,
|
||||
buildReflectionContext,
|
||||
recordReflection,
|
||||
loadRecentReflections,
|
||||
REFLECTION_INTERVAL_CYCLES,
|
||||
};
|
||||
Reference in New Issue
Block a user