354 lines
11 KiB
JavaScript
Raw Normal View History

/**
*
* 🤖 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}`);
}
/**
* 执行单个Agentv2.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 };