This repository has been archived on 2026-08-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
openclaw/skills/capability-evolver/src/gep/reflection.js
T
starmen1265 0878535cb8 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 配置
  - 忽略临时工作空间目录
2026-03-05 19:20:35 +08:00

128 lines
4.2 KiB
JavaScript

'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,
};