zhizhi/buffer/scripts/auto-router.js

151 lines
3.8 KiB
JavaScript
Raw 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.

/**
* buffer/scripts/auto-router.js
*
* 自动分流:根据消息来源和 dev_id 归档到对应目录
*
* 守护: PER-ZY001 铸渊
* 系统: SYS-GLW-0001
* 版权: 国作登字-2026-A-00037559
*/
const fs = require('fs');
const path = require('path');
const BUFFER_ROOT = path.join(__dirname, '..');
const INBOX = path.join(BUFFER_ROOT, 'inbox');
const CONFIG_PATH = path.join(BUFFER_ROOT, 'config', 'buffer-config.json');
// 来源 → 处理方式
const ROUTING_RULES = {
'gemini': { target: 'inbox/{dev_id}/', merge: true },
'notion': { target: 'inbox/{dev_id}/', merge: true },
'github': { target: 'inbox/{dev_id}/', merge: true },
'skyeye': { target: 'inbox/{dev_id}/', merge: false },
'system': { target: 'inbox/system/', merge: false },
};
const PRIORITY_RULES = {
'urgent': { flush_immediately: false, flag: true },
'normal': { flush_immediately: false, flag: false },
};
/**
* 核心铁律检查:禁止直接写入 grid-db/
*/
function validateNoDirectWrite(targetPath) {
if (targetPath.includes('grid-db/') || targetPath.includes('grid-db\\')) {
throw new Error(
'[BLOCKED] 违反铁律禁止直接写入 grid-db/' +
'所有写入必须经过 buffer/ 缓冲层'
);
}
}
/**
* 校验消息格式
*/
function validateMessage(msg) {
const errors = [];
if (!msg.message_id) {
errors.push('Missing message_id');
}
if (!msg.dev_id || !/^DEV-\d{3}$/.test(msg.dev_id)) {
errors.push(`Invalid dev_id: ${msg.dev_id}`);
}
if (!msg.source || !ROUTING_RULES[msg.source]) {
errors.push(`Invalid source: ${msg.source}`);
}
if (!msg.type) {
errors.push('Missing type');
}
if (!msg.created_at) {
errors.push('Missing created_at');
}
return errors;
}
/**
* 路由消息到正确的 inbox 子目录
*/
function routeMessage(msg) {
const rule = ROUTING_RULES[msg.source] || ROUTING_RULES['system'];
let targetDir;
if (msg.source === 'system' || !msg.dev_id) {
targetDir = path.join(INBOX, 'system');
} else {
targetDir = path.join(INBOX, msg.dev_id);
}
// 铁律检查
validateNoDirectWrite(targetDir);
// 确保目录存在
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
// 生成文件名
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `${timestamp}-${msg.type}.json`;
const filePath = path.join(targetDir, filename);
// 标记优先级
const priority = PRIORITY_RULES[msg.priority] || PRIORITY_RULES['normal'];
if (priority.flag) {
msg._urgent_flag = true;
}
// 确保状态为 pending
msg.status = 'pending';
fs.writeFileSync(filePath, JSON.stringify(msg, null, 2) + '\n');
console.log(`[auto-router] Routed ${msg.message_id} → ${path.relative(BUFFER_ROOT, filePath)}`);
return { filePath, merge: rule.merge };
}
/**
* 处理从标准输入或命令行参数传入的消息
*/
function main() {
const args = process.argv.slice(2);
if (args.length === 0) {
console.log('[auto-router] Usage: node auto-router.js <message.json>');
console.log('[auto-router] Or pipe JSON via stdin');
process.exit(0);
}
const inputPath = args[0];
if (!fs.existsSync(inputPath)) {
console.error(`[auto-router] File not found: ${inputPath}`);
process.exit(1);
}
let msg;
try {
msg = JSON.parse(fs.readFileSync(inputPath, 'utf8'));
} catch (err) {
console.error(`[auto-router] Failed to parse ${inputPath}: ${err.message}`);
process.exit(1);
}
const errors = validateMessage(msg);
if (errors.length > 0) {
console.error(`[auto-router] Validation failed: ${errors.join(', ')}`);
process.exit(1);
}
routeMessage(msg);
}
// Export for use by other scripts
module.exports = { routeMessage, validateMessage, validateNoDirectWrite, ROUTING_RULES };
if (require.main === module) {
main();
}