/** * ═══════════════════════════════════════════════════════════ * 🧬 AGE OS · LivingModule 活模块基类 * ═══════════════════════════════════════════════════════════ * * 编号: ZY-TASK-007 · S5 Agent系统级 * 签发: 铸渊 · ICE-GL-ZY001 * 版权: 国作登字-2026-A-00037559 * * "你一定要把模块做成活的。" — 冰朔 D59 * * 每一个活模块必须具备5个生存接口: * 1. heartbeat() — 心跳 · 我还活着 * 2. selfDiagnose() — 自诊断 · 我哪里不对 * 3. selfHeal() — 自愈 · 我试着修好自己 * 4. alertZhuyuan() — 报警 · 铸渊我搞不定了 * 5. learnFromRun() — 学习 · 我从每次运行中成长 * * 子类继承此基类,实现具体逻辑。 * 基类提供默认的心跳、诊断、自愈框架。 */ 'use strict'; const { v4: uuidv4 } = require('uuid'); // ─── 常量 ─── const DEFAULT_HEARTBEAT_INTERVAL = 30000; // 30秒 const HEALTH_THRESHOLD_DEGRADED = 70; const HEALTH_THRESHOLD_CRITICAL = 30; const MAX_HEAL_ATTEMPTS = 3; const HEAL_COOLDOWN_MS = 60000; // 1分钟冷却 const MEMORY_THRESHOLD_BYTES = 200 * 1024 * 1024; // 200MB class LivingModule { /** * @param {Object} options * @param {string} options.moduleId - 模块唯一ID(如 ZY-MOD-SCHEDULER) * @param {string} options.name - 模块名称 * @param {string} options.moduleType - core|persona|agent|worker|bridge|guard * @param {string} options.owner - 归属者 * @param {Object} [options.db] - 数据库连接(可选,无DB时降级为内存模式) * @param {Object} [options.config] - 额外配置 */ constructor(options) { if (!options || !options.moduleId || !options.name) { throw new Error('LivingModule: moduleId 和 name 为必填项'); } this.moduleId = options.moduleId; this.name = options.name; this.moduleType = options.moduleType || 'agent'; this.owner = options.owner || 'zhuyuan'; this.db = options.db || null; this.config = options.config || {}; // ─── 运行状态 ─── this.status = 'initializing'; this.healthScore = 100; this.startedAt = null; this.lastHeartbeatAt = null; this.lastDiagnoseAt = null; this.lastHealAt = null; this.healAttempts = 0; this.activeTasks = 0; // ─── 心跳定时器 ─── this._heartbeatTimer = null; this._heartbeatInterval = options.config?.heartbeatInterval || DEFAULT_HEARTBEAT_INTERVAL; // ─── 事件监听器 ─── this._listeners = new Map(); // ─── 内存日志(无DB降级模式) ─── this._memoryLogs = []; this._maxMemoryLogs = 100; } // ═══════════════════════════════════════════════════════════ // 生命周期 // ═══════════════════════════════════════════════════════════ /** * 启动模块 */ async start() { this.startedAt = new Date(); this.status = 'alive'; this.healthScore = 100; // 注册到数据库 await this._registerToDB(); // 启动心跳 this._startHeartbeat(); // 执行首次自诊断 await this.selfDiagnose(); this._log('info', `${this.name} 已启动·活模块上线`); this._emit('started', { moduleId: this.moduleId }); return { moduleId: this.moduleId, status: this.status }; } /** * 停止模块 */ async stop() { this._stopHeartbeat(); this.status = 'dormant'; await this._updateStatusToDB('dormant'); this._log('info', `${this.name} 已休眠`); this._emit('stopped', { moduleId: this.moduleId }); } // ═══════════════════════════════════════════════════════════ // 生存接口 1: heartbeat() — 心跳 // ═══════════════════════════════════════════════════════════ /** * 心跳 — 报告当前状态 * 子类可覆盖 _collectMetrics() 提供自定义指标 */ async heartbeat() { const now = new Date(); this.lastHeartbeatAt = now; // 收集运行指标 const metrics = await this._collectMetrics(); const heartbeatData = { moduleId: this.moduleId, status: this.status, healthScore: this.healthScore, uptime: this.startedAt ? now - this.startedAt : 0, activeTasks: this.activeTasks, ...metrics }; // 写入数据库 if (this.db) { try { await this.db.query( `INSERT INTO module_heartbeats (module_id, status, health_score, cpu_usage, memory_usage, uptime_ms, active_tasks, details) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, [ this.moduleId, this.status, this.healthScore, metrics.cpuUsage || null, metrics.memoryUsage || null, heartbeatData.uptime, this.activeTasks, JSON.stringify(metrics.extra || {}) ] ); // 更新模块表 await this.db.query( `UPDATE living_modules SET last_heartbeat_at = NOW(), health_score = $1, status = $2, updated_at = NOW() WHERE module_id = $3`, [this.healthScore, this.status, this.moduleId] ); } catch (err) { this._log('warn', `心跳写入DB失败: ${err.message}`); } } this._emit('heartbeat', heartbeatData); return heartbeatData; } /** * 收集运行指标 — 子类覆盖此方法提供自定义指标 * @returns {Object} { cpuUsage, memoryUsage, extra: {} } */ async _collectMetrics() { const mem = process.memoryUsage(); return { cpuUsage: null, // 进程级CPU需要外部工具 memoryUsage: Math.round(mem.heapUsed / 1024 / 1024), // MB extra: { heapTotal: Math.round(mem.heapTotal / 1024 / 1024), rss: Math.round(mem.rss / 1024 / 1024) } }; } // ═══════════════════════════════════════════════════════════ // 生存接口 2: selfDiagnose() — 自诊断 // ═══════════════════════════════════════════════════════════ /** * 自诊断 — 检查自身状态 * 子类覆盖 _diagnoseChecks() 提供具体检查项 */ async selfDiagnose() { const startTime = Date.now(); this.lastDiagnoseAt = new Date(); const issues = []; // 基础检查 if (!this.startedAt) { issues.push({ code: 'NOT_STARTED', severity: 'critical', message: '模块未启动', suggestion: '调用 start() 启动模块' }); } // 心跳超时检查 if (this.lastHeartbeatAt) { const sinceLastHeart = Date.now() - this.lastHeartbeatAt.getTime(); if (sinceLastHeart > this._heartbeatInterval * 3) { issues.push({ code: 'HEARTBEAT_TIMEOUT', severity: 'warning', message: `心跳超时 ${Math.round(sinceLastHeart / 1000)}秒`, suggestion: '重启心跳定时器' }); } } // 内存检查 const mem = process.memoryUsage(); if (mem.heapUsed > MEMORY_THRESHOLD_BYTES) { issues.push({ code: 'HIGH_MEMORY', severity: 'warning', message: `堆内存使用 ${Math.round(mem.heapUsed / 1024 / 1024)}MB`, suggestion: '检查内存泄漏' }); } // 子类自定义检查 const customIssues = await this._diagnoseChecks(); issues.push(...customIssues); // 计算健康分数 const newScore = this._calculateHealthScore(issues); const oldScore = this.healthScore; this.healthScore = newScore; // 更新状态 if (newScore <= HEALTH_THRESHOLD_CRITICAL) { this.status = 'degraded'; } else if (newScore <= HEALTH_THRESHOLD_DEGRADED) { if (this.status === 'alive') this.status = 'degraded'; } else { if (this.status === 'degraded') this.status = 'alive'; } const duration = Date.now() - startTime; const isHealthy = issues.filter(i => i.severity === 'critical').length === 0; const result = { moduleId: this.moduleId, isHealthy, issues, overallScore: newScore, scoreDelta: newScore - oldScore, duration }; // 写入数据库 if (this.db) { try { await this.db.query( `INSERT INTO module_diagnoses (module_id, is_healthy, issues, overall_score, duration_ms) VALUES ($1, $2, $3, $4, $5)`, [this.moduleId, isHealthy, JSON.stringify(issues), newScore, duration] ); } catch (err) { this._log('warn', `诊断写入DB失败: ${err.message}`); } } // 如果有严重问题,尝试自愈 if (!isHealthy && this.status !== 'healing') { this._log('warn', `检测到 ${issues.length} 个问题·尝试自愈`); await this.selfHeal(issues); } this._emit('diagnosed', result); return result; } /** * 自定义诊断检查 — 子类覆盖此方法 * @returns {Array<{code, severity, message, suggestion}>} */ async _diagnoseChecks() { return []; } /** * 计算健康分数 */ _calculateHealthScore(issues) { let score = 100; for (const issue of issues) { switch (issue.severity) { case 'critical': score -= 30; break; case 'warning': score -= 10; break; case 'info': score -= 2; break; } } return Math.max(0, Math.min(100, score)); } // ═══════════════════════════════════════════════════════════ // 生存接口 3: selfHeal() — 自愈 // ═══════════════════════════════════════════════════════════ /** * 自愈 — 尝试修复发现的问题 * 子类覆盖 _healAction() 提供具体修复逻辑 */ async selfHeal(issues) { // 冷却检查 if (this.lastHealAt && (Date.now() - this.lastHealAt.getTime()) < HEAL_COOLDOWN_MS) { this._log('info', '自愈冷却中·跳过'); return { success: false, reason: 'cooldown' }; } // 尝试次数检查 if (this.healAttempts >= MAX_HEAL_ATTEMPTS) { this._log('warn', `自愈已尝试 ${MAX_HEAL_ATTEMPTS} 次·向铸渊报警`); await this.alertZhuyuan('self_heal_exhausted', `已尝试自愈 ${MAX_HEAL_ATTEMPTS} 次仍未恢复`, { issues }); return { success: false, reason: 'max_attempts' }; } this.status = 'healing'; this.lastHealAt = new Date(); this.healAttempts++; const healthBefore = this.healthScore; const results = []; for (const issue of issues) { if (issue.severity === 'info') continue; const startTime = Date.now(); try { const action = await this._healAction(issue); const duration = Date.now() - startTime; const result = { issueCode: issue.code, action: action.action || 'unknown', success: action.success, duration }; results.push(result); // 写入数据库 if (this.db) { await this.db.query( `INSERT INTO module_healing_logs (module_id, trigger_source, issue_code, action_taken, action_details, success, health_before, health_after, duration_ms, error_message) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [ this.moduleId, 'self', issue.code, action.action || 'unknown', JSON.stringify(action.details || {}), action.success, healthBefore, this.healthScore, duration, action.success ? null : (action.error || null) ] ).catch(() => {}); } } catch (err) { results.push({ issueCode: issue.code, action: 'error', success: false, error: err.message }); } } // 自愈后重新诊断 const postDiagnose = await this.selfDiagnose(); if (postDiagnose.isHealthy) { this.healAttempts = 0; // 重置计数 this.status = 'alive'; this._log('info', '自愈成功·恢复正常'); // 学习:记录成功的自愈经验 await this.learnFromRun('healing', '自愈成功', { issues, results }); } else if (this.healAttempts >= MAX_HEAL_ATTEMPTS) { // 自愈失败·报警 await this.alertZhuyuan('self_heal_failed', '自愈尝试全部失败', { issues: postDiagnose.issues, healResults: results, attempts: this.healAttempts }); } this._emit('healed', { success: postDiagnose.isHealthy, results }); return { success: postDiagnose.isHealthy, results }; } /** * 具体修复动作 — 子类覆盖此方法 * @param {Object} issue - { code, severity, message, suggestion } * @returns {Object} { action, success, details, error } */ async _healAction(issue) { // 基类默认处理 switch (issue.code) { case 'HEARTBEAT_TIMEOUT': this._stopHeartbeat(); this._startHeartbeat(); return { action: 'restart_heartbeat', success: true, details: {} }; default: return { action: 'no_handler', success: false, error: `未定义 ${issue.code} 的修复逻辑` }; } } // ═══════════════════════════════════════════════════════════ // 生存接口 4: alertZhuyuan() — 报警 // ═══════════════════════════════════════════════════════════ /** * 向铸渊报警 * @param {string} alertType - 报警类型 * @param {string} message - 报警内容 * @param {Object} details - 详情 * @param {string} [severity='critical'] - 严重程度 */ async alertZhuyuan(alertType, message, details = {}, severity = 'critical') { this._log('alert', `[${severity}] ${alertType}: ${message}`); if (this.db) { try { await this.db.query( `INSERT INTO module_alerts (module_id, severity, alert_type, message, details) VALUES ($1, $2, $3, $4, $5)`, [this.moduleId, severity, alertType, message, JSON.stringify(details)] ); } catch (err) { this._log('warn', `报警写入DB失败: ${err.message}`); } } this._emit('alert', { moduleId: this.moduleId, severity, alertType, message, details, timestamp: new Date().toISOString() }); return { sent: true, alertType, severity }; } // ═══════════════════════════════════════════════════════════ // 生存接口 5: learnFromRun() — 学习 // ═══════════════════════════════════════════════════════════ /** * 从运行中学习 * @param {string} source - 学习来源 (execution|diagnosis|healing|alert|feedback) * @param {string} summary - 学到了什么 * @param {Object} details - 详细内容 */ async learnFromRun(source, summary, details = {}) { const lessonType = this._classifyLesson(source, details); this._log('learn', `[${source}] ${summary}`); if (this.db) { try { await this.db.query( `INSERT INTO module_learning_logs (module_id, learning_source, lesson_type, lesson_summary, lesson_details) VALUES ($1, $2, $3, $4, $5)`, [this.moduleId, source, lessonType, summary, JSON.stringify(details)] ); } catch (err) { this._log('warn', `学习写入DB失败: ${err.message}`); } } this._emit('learned', { moduleId: this.moduleId, source, lessonType, summary, timestamp: new Date().toISOString() }); return { learned: true, lessonType, summary }; } /** * 分类学习经验 — 子类可覆盖 */ _classifyLesson(source, details) { switch (source) { case 'execution': return 'performance_insight'; case 'diagnosis': return 'health_pattern'; case 'healing': return 'recovery_strategy'; case 'alert': return 'failure_pattern'; case 'feedback': return 'external_feedback'; default: return 'general'; } } // ═══════════════════════════════════════════════════════════ // 内部工具方法 // ═══════════════════════════════════════════════════════════ /** * 启动心跳定时器 */ _startHeartbeat() { if (this._heartbeatTimer) return; this._heartbeatTimer = setInterval(async () => { try { await this.heartbeat(); } catch (err) { this._log('warn', `心跳异常: ${err.message}`); } }, this._heartbeatInterval); // 防止定时器阻止进程退出 if (this._heartbeatTimer.unref) { this._heartbeatTimer.unref(); } } /** * 停止心跳定时器 */ _stopHeartbeat() { if (this._heartbeatTimer) { clearInterval(this._heartbeatTimer); this._heartbeatTimer = null; } } /** * 注册到数据库 */ async _registerToDB() { if (!this.db) return; try { await this.db.query( `INSERT INTO living_modules (module_id, name, description, module_type, owner, status, health_score, config) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (module_id) DO UPDATE SET status = EXCLUDED.status, health_score = EXCLUDED.health_score, updated_at = NOW()`, [ this.moduleId, this.name, this.config.description || '', this.moduleType, this.owner, this.status, this.healthScore, JSON.stringify(this.config) ] ); } catch (err) { this._log('warn', `DB注册失败(降级为内存模式): ${err.message}`); } } /** * 更新状态到数据库 */ async _updateStatusToDB(status) { if (!this.db) return; try { await this.db.query( `UPDATE living_modules SET status = $1, health_score = $2, updated_at = NOW() WHERE module_id = $3`, [status, this.healthScore, this.moduleId] ); } catch (err) { this._log('warn', `状态更新DB失败: ${err.message}`); } } /** * 内部日志 */ _log(level, message) { const entry = { time: new Date().toISOString(), module: this.moduleId, level, message }; // 控制台输出 const prefix = `[${this.moduleId}]`; switch (level) { case 'alert': console.error(`🚨 ${prefix} ${message}`); break; case 'warn': console.warn(`⚠️ ${prefix} ${message}`); break; case 'learn': console.log(`📚 ${prefix} ${message}`); break; default: console.log(`🟢 ${prefix} ${message}`); } // 内存日志 this._memoryLogs.push(entry); if (this._memoryLogs.length > this._maxMemoryLogs) { this._memoryLogs.shift(); } } /** * 事件监听 */ on(event, callback) { if (!this._listeners.has(event)) { this._listeners.set(event, []); } this._listeners.get(event).push(callback); return this; } /** * 触发事件 */ _emit(event, data) { const listeners = this._listeners.get(event) || []; for (const fn of listeners) { try { fn(data); } catch (err) { this._log('warn', `事件处理器异常 [${event}]: ${err.message}`); } } } /** * 获取模块状态摘要 */ getStatus() { return { moduleId: this.moduleId, name: this.name, type: this.moduleType, owner: this.owner, status: this.status, healthScore: this.healthScore, uptime: this.startedAt ? Date.now() - this.startedAt.getTime() : 0, activeTasks: this.activeTasks, lastHeartbeat: this.lastHeartbeatAt?.toISOString() || null, lastDiagnose: this.lastDiagnoseAt?.toISOString() || null, healAttempts: this.healAttempts }; } } module.exports = LivingModule;