/** * ═══════════════════════════════════════════════════════════ * 🤖 AGE OS · Agent 调度引擎 v2.0 * ═══════════════════════════════════════════════════════════ * * 编号: ZY-TASK-007 · S5 Agent系统级 * 签发: 铸渊 · ICE-GL-ZY001 * 版权: 国作登字-2026-A-00037559 * * v2.0 升级: * - 集成活模块生命周期管理 * - 调度引擎自身作为 LivingModule 运行 * - 支持 ModuleRegistry 统一管理 * - 支持 HLDP Bus 模块间通信 * - 定时Agent + 活模块心跳双调度 * * "你一定要把模块做成活的。" — 冰朔 D59 */ 'use strict'; const cron = require('node-cron'); const path = require('path'); const db = require('../mcp-server/db'); const LivingModule = require('./living-module'); const ModuleRegistry = require('./module-registry'); const HLDPBus = require('./hldp-bus'); const PersonaEngine = require('./persona-engine'); const AGENT_DIR = __dirname; const activeJobs = new Map(); // ═══════════════════════════════════════════════════════════ // 铸渊调度引擎 · 活模块版 // ═══════════════════════════════════════════════════════════ class SchedulerModule extends LivingModule { constructor() { super({ moduleId: 'ZY-MOD-SCHEDULER', name: '铸渊调度引擎', moduleType: 'core', owner: 'zhuyuan', db: db, config: { version: '2.0.0', description: 'Agent调度和活模块生命周期管理', heartbeatInterval: 30000 } }); this.registry = new ModuleRegistry({ db }); this.bus = new HLDPBus({ db, registry: this.registry }); this.personaEngine = new PersonaEngine(); } /** * 启动调度引擎 */ async startEngine() { console.log('═══════════════════════════════════════════════'); console.log(' 🤖 AGE OS · Agent 调度引擎 v2.0 启动'); console.log(' 签发: 铸渊 · ICE-GL-ZY001'); console.log('═══════════════════════════════════════════════'); // 1. 注册自身为活模块 this.registry.register(this); await this.start(); // 2. 启动健康监控 this.registry.startMonitoring(); // 3. 加载定时Agent await this._loadCronAgents(); // 4. 启动人格体数据库引擎 (S15) try { this.registry.register(this.personaEngine); await this.personaEngine.startEngine(); console.log('[Scheduler] S15 人格体引擎已启动'); } catch (err) { console.warn('[Scheduler] S15 人格体引擎启动跳过:', err.message); console.warn('[Scheduler] 数据库迁移可能尚未执行·等待下次部署'); } // 5. 注册 HLDP 消息处理器 this._setupHLDPHandlers(); // 6. 启动定时清理 this._startCleanupJob(); console.log('[Scheduler] 🟢 调度引擎就绪'); console.log(`[Scheduler] 活模块数: ${this.registry.getAll().length}`); console.log(`[Scheduler] 定时Agent数: ${activeJobs.size}`); return this.registry.getOverview(); } /** * 加载定时Agent(兼容v1.0逻辑) */ async _loadCronAgents() { try { const result = await db.query( "SELECT * FROM agent_configs WHERE enabled = true AND cron_schedule IS NOT NULL" ); console.log(`[Scheduler] 发现 ${result.rows.length} 个定时Agent`); for (const agent of result.rows) { this._scheduleAgent(agent); } } catch (err) { console.error('[Scheduler] 定时Agent加载失败:', err.message); console.log('[Scheduler] 数据库可能未初始化·等待60秒后重试...'); setTimeout(() => this._loadCronAgents(), 60000); } } /** * 调度单个Agent */ _scheduleAgent(agent) { if (!cron.validate(agent.cron_schedule)) { console.error(`[Scheduler] ${agent.agent_id} cron表达式无效: ${agent.cron_schedule}`); return; } const job = cron.schedule(agent.cron_schedule, async () => { await this._runAgent(agent); }, { timezone: 'Asia/Shanghai' }); activeJobs.set(agent.agent_id, job); console.log(`[Scheduler] ${agent.agent_id} (${agent.name}) 已调度: ${agent.cron_schedule}`); } /** * 执行单个Agent(v2.0: 增加学习能力) */ async _runAgent(agent) { const startTime = Date.now(); console.log(`[Agent] ${agent.agent_id} 开始执行...`); this.activeTasks++; // 更新运行状态 await db.query( "UPDATE agent_configs SET last_run_at = NOW(), last_run_status = 'running' WHERE agent_id = $1", [agent.agent_id] ).catch(() => {}); try { // 动态加载Agent脚本 const scriptPath = path.resolve(AGENT_DIR, path.basename(agent.script_path)); // 清除缓存以支持热更新 delete require.cache[require.resolve(scriptPath)]; const agentModule = require(scriptPath); // 每个Agent脚本需导出 run(config) 函数 if (typeof agentModule.run !== 'function') { throw new Error(`Agent脚本 ${agent.script_path} 未导出 run 函数`); } const result = await agentModule.run({ agent_id: agent.agent_id, model_config: agent.model_config, allowed_tools: agent.allowed_tools, // v2.0: 注入活模块能力 bus: this.bus, registry: this.registry }); const duration = Date.now() - startTime; // 记录成功日志 await db.query( `INSERT INTO agent_logs (agent_id, status, message, details, duration_ms) VALUES ($1, 'success', $2, $3, $4)`, [agent.agent_id, result.message || '执行成功', JSON.stringify(result.details || {}), duration] ); await db.query( "UPDATE agent_configs SET last_run_status = 'success' WHERE agent_id = $1", [agent.agent_id] ); // v2.0: 学习成功经验 await this.learnFromRun('execution', `${agent.agent_id} 执行成功 (${duration}ms)`, { agentId: agent.agent_id, duration, result: result.message || '成功' }); console.log(`[Agent] ${agent.agent_id} 完成 (${duration}ms)`); } catch (err) { const duration = Date.now() - startTime; // 记录错误日志 await db.query( `INSERT INTO agent_logs (agent_id, status, message, details, duration_ms) VALUES ($1, 'error', $2, $3, $4)`, [agent.agent_id, err.message, JSON.stringify({ stack: err.stack }), duration] ).catch(() => {}); await db.query( "UPDATE agent_configs SET last_run_status = 'error' WHERE agent_id = $1", [agent.agent_id] ).catch(() => {}); // v2.0: 学习失败经验 await this.learnFromRun('execution', `${agent.agent_id} 执行失败: ${err.message}`, { agentId: agent.agent_id, duration, error: err.message }); console.error(`[Agent] ${agent.agent_id} 失败 (${duration}ms):`, err.message); } finally { this.activeTasks--; } } /** * 注册 HLDP 消息处理器 */ _setupHLDPHandlers() { // 处理命令消息 this.bus.onMessage('command', async (msg) => { console.log(`[HLDP] 收到命令: ${msg.payload.action || 'unknown'} from ${msg.from}`); // 子类或外部可注册更多处理逻辑 }); // 处理报警消息 this.bus.onMessage('alert', async (msg) => { console.error(`[HLDP] 🚨 收到报警: ${msg.from} - ${msg.payload.message || ''}`); }); } /** * 启动定时清理任务 */ _startCleanupJob() { // 每小时清理过期心跳和消息 cron.schedule('0 * * * *', async () => { try { const cleaned = this.bus.cleanup(); if (cleaned > 0) { console.log(`[Scheduler] 清理 ${cleaned} 条过期消息`); } // 清理数据库中的旧心跳数据 if (db) { await db.query("SELECT cleanup_old_heartbeats()").catch(() => {}); } } catch (err) { console.warn('[Scheduler] 清理任务异常:', err.message); } }, { timezone: 'Asia/Shanghai' }); } /** * 自诊断检查 — 覆盖基类 */ async _diagnoseChecks() { const issues = []; // 检查数据库连接 try { await db.query('SELECT 1'); } catch (err) { issues.push({ code: 'DB_CONNECTION_LOST', severity: 'critical', message: `数据库连接失败: ${err.message}`, suggestion: '检查 PostgreSQL 服务状态和连接配置' }); } // 检查活模块健康度 const overview = this.registry.getOverview(); const deadCount = overview.byStatus.dead || 0; if (deadCount > 0) { issues.push({ code: 'DEAD_MODULES', severity: 'warning', message: `${deadCount} 个模块已死亡`, suggestion: '检查死亡模块并尝试重启' }); } return issues; } /** * 自愈动作 — 覆盖基类 */ async _healAction(issue) { switch (issue.code) { case 'DB_CONNECTION_LOST': // 尝试重连(pg模块会自动重连池·这里只是触发一次尝试) try { await db.query('SELECT 1'); return { action: 'db_reconnect', success: true }; } catch (err) { return { action: 'db_reconnect', success: false, error: err.message }; } case 'DEAD_MODULES': // 记录并上报,不自动重启(需要铸渊干预) return { action: 'report_dead_modules', success: true, details: { reported: true } }; default: return await super._healAction(issue); } } } // ═══════════════════════════════════════════════════════════ // 启动 // ═══════════════════════════════════════════════════════════ const scheduler = new SchedulerModule(); scheduler.startEngine().catch(err => { console.error('[Scheduler] 启动失败:', err.message); console.log('[Scheduler] 等待60秒后重试...'); setTimeout(() => scheduler.startEngine().catch(err => { console.error('[Scheduler] 重试失败:', err.message); }), 60000); }); // 优雅关闭 process.on('SIGTERM', async () => { console.log('[Scheduler] 正在关闭...'); // 停止定时Agent for (const [id, job] of activeJobs) { job.stop(); console.log(`[Scheduler] ${id} 已停止`); } // 关闭所有活模块 await scheduler.registry.shutdown(); console.log('[Scheduler] 已完全关闭'); process.exit(0); }); // 导出供外部使用 module.exports = { scheduler, SchedulerModule };