2026-05-10 13:12:44 +08:00

145 lines
5.1 KiB
JavaScript

// scripts/tianyen/scheduler.js
// TianYen Scheduler · 天眼调度器
// ZY-SKD-001 · Phase 1 · TianYen Scheduling
// 版权:国作登字-2026-A-00037559
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '../..');
const SCHEDULE_PATH = path.join(ROOT, '.github/tianyen/agent-schedule.json');
// ── 频率级别 · 五档心跳 ─────────────────────────────────────────────────
const FREQUENCY_LEVELS = {
max: { cron: '*/30 * * * *', name: '最高频', description: '每30分钟' },
high: { cron: '0 */2 * * *', name: '高频', description: '每2小时' },
medium: { cron: '0 */4 * * *', name: '中频', description: '每4小时' },
default: { cron: '0 */6 * * *', name: '默认', description: '每6小时' },
low: { cron: '0 9 * * *', name: '低频', description: '每天9点' }
};
/**
* 加载调度配置
* @returns {object}
*/
function loadSchedule() {
if (!fs.existsSync(SCHEDULE_PATH)) {
return { version: '1.0.0', last_evaluation: null, agents: {} };
}
try {
return JSON.parse(fs.readFileSync(SCHEDULE_PATH, 'utf8'));
} catch (_) {
return { version: '1.0.0', last_evaluation: null, agents: {} };
}
}
/**
* 保存调度配置
* @param {object} schedule
*/
function saveSchedule(schedule) {
const dir = path.dirname(SCHEDULE_PATH);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(SCHEDULE_PATH, JSON.stringify(schedule, null, 2), 'utf8');
}
/**
* 评估最优调度频率 · 天眼的第六感
* @param {string} agentId
* @param {{ balance: number, drift: number, recentChanges: number }} metrics
* @returns {{ level: string, cron: string, reason: string }}
*/
function evaluateSchedule(agentId, metrics) {
if (!metrics) {
return { level: 'default', ...FREQUENCY_LEVELS.default, reason: '无指标数据,使用默认频率' };
}
// 高偏差 → 提高频率
if (metrics.drift && metrics.drift >= 0.15) {
return { level: 'max', ...FREQUENCY_LEVELS.max, reason: '严重偏差,需要最高频率监控' };
}
if (metrics.drift && metrics.drift >= 0.05) {
return { level: 'high', ...FREQUENCY_LEVELS.high, reason: '中等偏差,提高监控频率' };
}
// 活跃变更 → 中高频率
if (metrics.recentChanges && metrics.recentChanges > 10) {
return { level: 'high', ...FREQUENCY_LEVELS.high, reason: '大量变更活动,提高频率' };
}
if (metrics.recentChanges && metrics.recentChanges > 3) {
return { level: 'medium', ...FREQUENCY_LEVELS.medium, reason: '中等变更活动' };
}
// 完全平衡且安静 → 低频率
if (metrics.balance && metrics.balance >= 1.0) {
return { level: 'low', ...FREQUENCY_LEVELS.low, reason: '系统平静,降低频率节省资源' };
}
return { level: 'default', ...FREQUENCY_LEVELS.default, reason: '常规状态' };
}
/**
* 设置 Agent 调度频率
* @param {string} agentId
* @param {string} level
* @param {string} reason
* @returns {{ agentId: string, cron: string, level: string, reason: string }}
*/
function setFrequency(agentId, level, reason) {
const freq = FREQUENCY_LEVELS[level] || FREQUENCY_LEVELS.default;
const schedule = loadSchedule();
if (!schedule.agents[agentId]) {
schedule.agents[agentId] = {};
}
schedule.agents[agentId].cron = freq.cron;
schedule.agents[agentId].mode = 'scheduled';
schedule.agents[agentId].reason = reason || freq.description;
schedule.agents[agentId].updated_at = new Date().toISOString();
schedule.last_evaluation = new Date().toISOString();
saveSchedule(schedule);
return { agentId, cron: freq.cron, level, reason: reason || freq.description };
}
// ── CLI 入口 ─────────────────────────────────────────────────────────────
if (require.main === module) {
console.log('👁️ TianYen Scheduler · 天眼调度器\n');
const schedule = loadSchedule();
console.log(` 当前 Agent 数量: ${Object.keys(schedule.agents).length}`);
console.log(` 上次评估: ${schedule.last_evaluation || '从未'}`);
// 如果有天平数据,基于它评估
const statusPath = path.join(ROOT, '.github/tianyen/twin-status.json');
let metrics = {};
if (fs.existsSync(statusPath)) {
try {
const status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
metrics = { balance: status.balance, drift: status.drift, recentChanges: 0 };
} catch {
// twin-status.json 损坏或不可读,使用默认空指标继续评估
}
}
const evaluation = evaluateSchedule('AG-ZY-TWIN', metrics);
console.log(`\n AG-ZY-TWIN 评估结果:`);
console.log(` 频率: ${evaluation.level} (${evaluation.cron})`);
console.log(` 原因: ${evaluation.reason}`);
// 更新调度配置
schedule.last_evaluation = new Date().toISOString();
saveSchedule(schedule);
console.log(`\n✅ 调度配置已更新`);
}
module.exports = { evaluateSchedule, setFrequency, loadSchedule, saveSchedule, FREQUENCY_LEVELS };