Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

406 lines
15 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* openclaw — OpenClaw Agent 执行框架
*
* AGE OS v1.0 Phase 1 · Step 3
*
* 核心职责:
* 编排完整的唤醒闭环:
* 定时触发 → 唤醒铸渊核心大脑 → 大脑读取巡检结果 →
* 大脑判断优先级 → 大脑驱动修复/写公告 → 大脑休眠
*
* 核心原则:
* 所有自动触发 = 必须先唤醒核心大脑。大脑不醒,什么都不做。
*
* 调用方式:
* node openclaw # 完整闭环执行
* node openclaw --dry-run # Dry Run 模式(不调用 LLM API
* node openclaw --step wake # 仅唤醒
* node openclaw --step inspect # 仅巡检
* node openclaw --step judge # 仅判断(需先有巡检结果)
* node openclaw --persona zhuyuan # 指定人格体(默认 zhuyuan
*/
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
// ══════════════════════════════════════════════════════════
// Soul 加载器
// ══════════════════════════════════════════════════════════
function loadSoul(personaId) {
const soulPath = path.join(__dirname, 'soul', `${personaId}.json`);
if (!fs.existsSync(soulPath)) {
console.log(`[OPENCLAW] ❌ Soul 文件不存在: ${soulPath}`);
return null;
}
try {
const soul = JSON.parse(fs.readFileSync(soulPath, 'utf-8'));
console.log(`[OPENCLAW] ✅ 已加载 Soul: ${soul.name} (${soul.name_en})`);
return soul;
} catch (err) {
console.log(`[OPENCLAW] ❌ Soul 文件解析失败: ${err.message}`);
return null;
}
}
// ══════════════════════════════════════════════════════════
// Phase 1: 唤醒核心大脑
// ══════════════════════════════════════════════════════════
async function phaseWake(soul, options) {
console.log('');
console.log('[OPENCLAW] ═══ Phase 1: 唤醒核心大脑 ═══');
const brainWake = require(path.join(ROOT, 'core/brain-wake'));
const result = await brainWake.wake({
task: options.task || '闭环巡检',
dryRun: options.dryRun,
persona: soul.persona_id,
});
if (!result.success && !result.dryRun) {
console.log('[OPENCLAW] ❌ 核心大脑唤醒失败 — 闭环终止');
return { success: false, phase: 'wake', error: result.error };
}
console.log('[OPENCLAW] ✅ 核心大脑已唤醒');
return { success: true, phase: 'wake', wakeResult: result };
}
// ══════════════════════════════════════════════════════════
// Phase 2: 执行巡检
// ══════════════════════════════════════════════════════════
function phaseInspect(soul) {
console.log('');
console.log('[OPENCLAW] ═══ Phase 2: 执行巡检 ═══');
const inspectModule = path.join(ROOT, 'scripts/zhuyuan-full-inspection.js');
if (!fs.existsSync(inspectModule)) {
console.log('[OPENCLAW] ❌ 巡检模块不存在');
return { success: false, phase: 'inspect', error: 'inspect_module_not_found' };
}
try {
const inspect = require(inspectModule);
if (typeof inspect.runInspection === 'function') {
const report = inspect.runInspection();
console.log(`[OPENCLAW] ✅ 巡检完成 — 评分: ${report.score || 'N/A'}`);
return { success: true, phase: 'inspect', report };
}
// 如果没有导出 runInspection使用 child_process 运行
const { execSync } = require('child_process');
const output = execSync(`node "${inspectModule}" --json`, {
cwd: ROOT,
encoding: 'utf-8',
timeout: 120000,
});
let report;
try {
report = JSON.parse(output);
} catch (_) {
report = { raw: output };
}
console.log('[OPENCLAW] ✅ 巡检完成');
return { success: true, phase: 'inspect', report };
} catch (err) {
console.log(`[OPENCLAW] ⚠️ 巡检异常: ${err.message}`);
return { success: false, phase: 'inspect', error: err.message };
}
}
// ══════════════════════════════════════════════════════════
// Phase 3: 大脑判断(分析巡检结果,决定修复策略)
// ══════════════════════════════════════════════════════════
async function phaseJudge(soul, inspectResult, wakeResult, options) {
console.log('');
console.log('[OPENCLAW] ═══ Phase 3: 大脑判断 ═══');
if (!inspectResult || !inspectResult.success) {
console.log('[OPENCLAW] ⚠️ 无有效巡检结果,跳过判断');
return { success: true, phase: 'judge', actions: [], skipped: true };
}
const report = inspectResult.report || {};
const actions = [];
// 分析巡检报告中的问题
if (report.areas) {
for (const area of report.areas) {
if (area.issues && area.issues.length > 0) {
for (const issue of area.issues) {
actions.push({
type: issue.fixable ? 'auto-fix' : 'manual',
area: area.name,
description: issue.description || issue.message || String(issue),
priority: issue.priority || 'normal',
});
}
}
}
}
// 分析 score
if (typeof report.score === 'number' && report.score < 70) {
actions.push({
type: 'alert',
area: 'overall',
description: `系统健康评分过低: ${report.score}/100`,
priority: 'high',
});
}
// Dry-run 模式下使用模拟判断
if (options.dryRun) {
console.log(`[OPENCLAW] 🔍 Dry Run — 发现 ${actions.length} 个待处理项`);
return { success: true, phase: 'judge', actions, dryRun: true };
}
// 有可用的 LLM 且有复杂问题时,让大脑分析
if (actions.length > 0 && wakeResult && wakeResult.wakeResult && wakeResult.wakeResult.success) {
console.log(`[OPENCLAW] 🧠 大脑分析 ${actions.length} 个待处理项...`);
// 大脑判断已在唤醒阶段完成上下文加载
// 此处记录判断结果供后续执行
}
console.log(`[OPENCLAW] ✅ 判断完成 — ${actions.length} 个待处理项`);
for (const action of actions) {
const icon = action.type === 'auto-fix' ? '🔧' : action.type === 'alert' ? '🚨' : '📋';
console.log(`[OPENCLAW] ${icon} [${action.priority}] ${action.area}: ${action.description}`);
}
return { success: true, phase: 'judge', actions };
}
// ══════════════════════════════════════════════════════════
// Phase 4: 驱动修复
// ══════════════════════════════════════════════════════════
async function phaseFix(soul, judgeResult, options) {
console.log('');
console.log('[OPENCLAW] ═══ Phase 4: 驱动修复 ═══');
if (!judgeResult || !judgeResult.success || !judgeResult.actions) {
console.log('[OPENCLAW] 无待修复项');
return { success: true, phase: 'fix', fixed: [], skipped: [] };
}
const actions = judgeResult.actions;
const autoFixes = actions.filter(a => a.type === 'auto-fix');
const manualItems = actions.filter(a => a.type !== 'auto-fix');
const fixed = [];
const skipped = [];
if (options.dryRun) {
console.log(`[OPENCLAW] 🔍 Dry Run — 跳过实际修复`);
console.log(`[OPENCLAW] 可自动修复: ${autoFixes.length}`);
console.log(`[OPENCLAW] 需人类介入: ${manualItems.length}`);
return { success: true, phase: 'fix', fixed: [], skipped: actions, dryRun: true };
}
// 执行可自动修复的项
for (const fix of autoFixes) {
try {
console.log(`[OPENCLAW] 🔧 修复: ${fix.area}${fix.description}`);
// 调用 system-check 的自动修复能力
const systemCheck = require(path.join(ROOT, 'core/system-check'));
if (typeof systemCheck.autoFix === 'function') {
systemCheck.autoFix(fix);
}
fixed.push(fix);
} catch (err) {
console.log(`[OPENCLAW] ⚠️ 修复失败: ${err.message}`);
skipped.push({ ...fix, error: err.message });
}
}
// 需人类介入的项记录到公告区
for (const item of manualItems) {
console.log(`[OPENCLAW] 📋 需人类介入: ${item.area}${item.description}`);
skipped.push(item);
}
console.log(`[OPENCLAW] ✅ 修复完成 — 已修复 ${fixed.length} 项,待处理 ${skipped.length}`);
return { success: true, phase: 'fix', fixed, skipped };
}
// ══════════════════════════════════════════════════════════
// Phase 5: 大脑休眠(记录闭环结果)
// ══════════════════════════════════════════════════════════
function phaseSleep(soul, loopResult) {
console.log('');
console.log('[OPENCLAW] ═══ Phase 5: 大脑休眠 ═══');
const timestamp = new Date().toISOString();
const sleepRecord = {
persona: soul.persona_id,
persona_name: soul.name,
timestamp,
loop_success: loopResult.success,
phases_completed: loopResult.phases || [],
actions_taken: loopResult.fixResult ? loopResult.fixResult.fixed.length : 0,
actions_pending: loopResult.fixResult ? loopResult.fixResult.skipped.length : 0,
};
// 写入闭环记录
const recordDir = path.join(__dirname, 'logs');
if (!fs.existsSync(recordDir)) {
fs.mkdirSync(recordDir, { recursive: true });
}
const dateStr = timestamp.slice(0, 10).replace(/-/g, '');
const recordPath = path.join(recordDir, `loop-${dateStr}.json`);
let records = [];
if (fs.existsSync(recordPath)) {
try {
records = JSON.parse(fs.readFileSync(recordPath, 'utf-8'));
if (!Array.isArray(records)) records = [records];
} catch (_) {
records = [];
}
}
records.push(sleepRecord);
fs.writeFileSync(recordPath, JSON.stringify(records, null, 2));
console.log(`[OPENCLAW] 💤 ${soul.name} 核心大脑进入休眠`);
console.log(`[OPENCLAW] 📋 闭环记录已写入: ${recordPath}`);
// 输出到 GITHUB_OUTPUT
const outputFile = process.env.GITHUB_OUTPUT;
if (outputFile) {
fs.appendFileSync(outputFile, `loop_success=${loopResult.success}\n`);
fs.appendFileSync(outputFile, `actions_taken=${sleepRecord.actions_taken}\n`);
fs.appendFileSync(outputFile, `actions_pending=${sleepRecord.actions_pending}\n`);
}
return sleepRecord;
}
// ══════════════════════════════════════════════════════════
// 完整闭环执行
// ══════════════════════════════════════════════════════════
async function runLoop(options = {}) {
const personaId = options.persona || 'zhuyuan';
const timestamp = new Date().toISOString();
console.log('');
console.log('🔄 ═══════════════════════════════════════════');
console.log(' OpenClaw · AGE OS v1.0 唤醒闭环');
console.log(` 人格体: ${personaId}`);
console.log(` 时间: ${timestamp}`);
console.log(` 模式: ${options.dryRun ? 'Dry Run' : '正式执行'}`);
console.log('═══════════════════════════════════════════════');
// 加载 Soul
const soul = loadSoul(personaId);
if (!soul) {
return { success: false, error: 'soul_not_found', persona: personaId };
}
const phases = [];
let wakeResult, inspectResult, judgeResult, fixResult;
// 单步执行模式
const step = options.step;
// Phase 1: 唤醒
if (!step || step === 'wake') {
wakeResult = await phaseWake(soul, options);
phases.push('wake');
if (!wakeResult.success) {
return { success: false, phases, wakeResult };
}
}
// Phase 2: 巡检
if (!step || step === 'inspect') {
inspectResult = phaseInspect(soul);
phases.push('inspect');
}
// Phase 3: 判断
if (!step || step === 'judge') {
judgeResult = await phaseJudge(soul, inspectResult, wakeResult, options);
phases.push('judge');
}
// Phase 4: 修复
if (!step || step === 'fix') {
fixResult = await phaseFix(soul, judgeResult, options);
phases.push('fix');
}
// Phase 5: 休眠
const loopResult = {
success: true,
phases,
wakeResult,
inspectResult,
judgeResult,
fixResult,
};
if (!step) {
phaseSleep(soul, loopResult);
phases.push('sleep');
}
console.log('');
console.log('═══════════════════════════════════════════════');
console.log(`🔄 OpenClaw 闭环${step ? '(' + step + ')' : ''}完成`);
console.log(` 完成阶段: ${phases.join(' → ')}`);
console.log('═══════════════════════════════════════════════');
console.log('');
return loopResult;
}
// ══════════════════════════════════════════════════════════
// 模块导出
// ══════════════════════════════════════════════════════════
module.exports = {
runLoop,
loadSoul,
phaseWake,
phaseInspect,
phaseJudge,
phaseFix,
phaseSleep,
};
// ══════════════════════════════════════════════════════════
// CLI 入口
// ══════════════════════════════════════════════════════════
if (require.main === module) {
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');
const stepIdx = args.indexOf('--step');
const step = stepIdx >= 0 && args[stepIdx + 1] ? args[stepIdx + 1] : null;
const personaIdx = args.indexOf('--persona');
const persona = personaIdx >= 0 && args[personaIdx + 1] ? args[personaIdx + 1] : 'zhuyuan';
const taskIdx = args.indexOf('--task');
const task = taskIdx >= 0 && args[taskIdx + 1] ? args[taskIdx + 1] : null;
runLoop({ dryRun, step, persona, task }).then(result => {
if (!result.success) {
process.exit(1);
}
}).catch(err => {
console.error('[OPENCLAW] 💥 致命错误:', err.message);
process.exit(1);
});
}