guanghulab/scripts/agent-checkin.js
2026-05-10 13:12:44 +08:00

179 lines
5.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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.

/**
* scripts/agent-checkin.js
* 人格体每日签到脚本
*
* 逻辑:
* 1. 读取 agent-registry.json 获取所有注册小兵列表
* 2. 对每个小兵,查询 GitHub Actions API 获取该 workflow 今日最新一次 run 的结果
* 3. 结果为 success 且时间在今天 10:00 之前 → 标记为 ✅ 已签到
* 4. 结果为 failure 或无今日 run → 标记为 ❌ 未签到
* 5. 更新 checkin-board.json 的所有记录
* 6. 生成 summary总数/已签到/缺席/缺席名单)
*/
'use strict';
const fs = require('fs');
const path = require('path');
const https = require('https');
const ROOT = path.resolve(__dirname, '..');
const BRAIN_DIR = path.join(ROOT, '.github/persona-brain');
const REGISTRY_PATH = path.join(BRAIN_DIR, 'agent-registry.json');
const BOARD_PATH = path.join(BRAIN_DIR, 'checkin-board.json');
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const REPO = process.env.GITHUB_REPOSITORY || 'qinfendebingshuo/guanghulab';
const today = new Date().toISOString().split('T')[0];
const todayStart = new Date(today + 'T00:00:00Z');
console.log(`📋 人格体每日签到开始 · ${today}`);
// ── GitHub API helper ─────────────────────────────────────────────────────
function githubApi(urlPath) {
return new Promise((resolve, reject) => {
const options = {
hostname: 'api.github.com',
path: urlPath,
method: 'GET',
headers: {
'User-Agent': 'zhuyuan-agent-checkin',
'Accept': 'application/vnd.github.v3+json',
},
};
if (GITHUB_TOKEN) {
options.headers['Authorization'] = `Bearer ${GITHUB_TOKEN}`;
}
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
try {
resolve(JSON.parse(data));
} catch {
resolve(null);
}
});
});
req.on('error', (err) => {
console.error(` ⚠️ API 请求失败: ${err.message}`);
resolve(null);
});
req.end();
});
}
// ── 获取 workflow 今日最新 run ────────────────────────────────────────────
async function getLatestRun(workflowFile) {
const urlPath = `/repos/${REPO}/actions/workflows/${encodeURIComponent(workflowFile)}/runs?per_page=1&created=${encodeURIComponent('>=' + today)}`;
const data = await githubApi(urlPath);
if (!data || !data.workflow_runs || data.workflow_runs.length === 0) {
return null;
}
const run = data.workflow_runs[0];
return {
status: run.status,
conclusion: run.conclusion,
created_at: run.created_at,
updated_at: run.updated_at,
};
}
// ── 主签到流程 ────────────────────────────────────────────────────────────
async function main() {
// 1. 读取注册表
if (!fs.existsSync(REGISTRY_PATH)) {
console.error('❌ agent-registry.json 不存在');
process.exit(1);
}
const registry = JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf8'));
// 2. 构建签到记录(仅检查 daily_checkin_required === true 的 Agent
const records = [];
let checkedIn = 0;
const missingAgents = [];
let skipped = 0;
for (const agent of registry.agents) {
// 跳过无需每日签到的 Agent事件触发型、已暂停等
if (agent.daily_checkin_required === false) {
skipped++;
continue;
}
console.log(` 🔍 检查 ${agent.id} (${agent.workflow})...`);
const run = await getLatestRun(agent.workflow);
const record = {
agent_id: agent.id,
agent_name: agent.name,
status: 'pending',
checkin_time: null,
last_run: null,
last_run_result: null,
note: '',
};
if (run && run.conclusion === 'success') {
record.status = '✅ 已签到';
record.checkin_time = run.updated_at;
record.last_run = run.updated_at;
record.last_run_result = 'success';
checkedIn++;
console.log(` ✅ 已签到 (${run.updated_at})`);
} else if (run) {
record.status = '❌ 未签到';
record.last_run = run.updated_at;
record.last_run_result = run.conclusion || run.status;
record.note = `最近运行结果: ${run.conclusion || run.status}`;
missingAgents.push(agent.id);
console.log(` ❌ 未签到 (结果: ${run.conclusion || run.status})`);
} else {
record.status = '❌ 未签到';
record.note = '今日无运行记录';
missingAgents.push(agent.id);
console.log(` ❌ 未签到 (今日无运行记录)`);
}
records.push(record);
}
console.log(`\n📋 跳过 ${skipped} 个无需签到的 Agent`);
// 3. 构建签到板
const board = {
board_version: 'v1.0',
checkin_deadline: '10:00+08:00',
inspection_time: '12:00+08:00',
date: today,
records: records,
summary: {
total: records.length,
checked_in: checkedIn,
missing: records.length - checkedIn,
missing_agents: missingAgents,
},
};
// 4. 写入签到板
fs.writeFileSync(BOARD_PATH, JSON.stringify(board, null, 2));
console.log(`\n📊 签到汇总:`);
console.log(` 总数: ${board.summary.total}`);
console.log(` 已签到: ${board.summary.checked_in}`);
console.log(` 缺席: ${board.summary.missing}`);
if (missingAgents.length > 0) {
console.log(` 缺席名单: ${missingAgents.join(', ')}`);
}
console.log(`\n✅ 签到记录已写入 checkin-board.json`);
}
main().catch((err) => {
console.error('❌ 签到脚本异常:', err.message);
process.exit(1);
});