guanghulab/scripts/neural/convert-workorder-to-command.js
2026-05-10 13:12:44 +08:00

148 lines
4.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.

// scripts/neural/convert-workorder-to-command.js
// 🧬 工单→下行指令 转化器
// Notion Agent 调用此脚本,将工单转化为铸渊可执行的下行指令
// 输入:工单 JSON 文件路径
// 输出:下行指令 JSON写入 deploy-queue/pending/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const DEPLOY_QUEUE = 'data/deploy-queue/pending';
const NEURAL_MAP_PATH = 'skyeye/neural-map.json';
function loadJSON(p) {
try { return JSON.parse(fs.readFileSync(p, 'utf8')); }
catch (e) { return null; }
}
function generateCommandId() {
var now = new Date();
var cst = new Date(now.getTime() + 8 * 60 * 60 * 1000);
var date = cst.toISOString().split('T')[0].replace(/-/g, '');
var seq = crypto.randomBytes(2).toString('hex').toUpperCase();
return 'CMD-' + date + '-' + seq;
}
function convertWorkOrderToCommand(workOrder) {
var neuralMap = loadJSON(NEURAL_MAP_PATH);
if (!neuralMap) throw new Error('neural-map.json 不存在');
var commandId = generateCommandId();
var now = new Date().toISOString();
// 确定目标 Workflow
var targetWorkflowId = (workOrder.affected && workOrder.affected.workflows)
? workOrder.affected.workflows[0] : null;
var targetWorkflow = targetWorkflowId
? neuralMap.github_workflows[targetWorkflowId] : null;
// 确定指令类型
var instructionType = 'trigger_workflow';
var instructionParams = {};
var action = (workOrder.source && workOrder.source.rule_triggered) || '';
if (action.indexOf('cleanup') !== -1 || action.indexOf('clean') !== -1) {
instructionType = 'run_script';
instructionParams = {
script: 'scripts/neural/cleanup-old-reports.js',
args: { max_age_days: 7 }
};
} else if (action.indexOf('guard_restart') !== -1 || action.indexOf('quota') !== -1) {
instructionType = 'modify_config';
instructionParams = {
target_file: (workOrder.affected && workOrder.affected.guards && workOrder.affected.guards[0])
? 'skyeye/guards/' + workOrder.affected.guards[0] + '.json'
: null,
modifications: { status: 'active', mode: 'normal' }
};
} else {
instructionType = 'trigger_workflow';
instructionParams = {
event: 'workflow_dispatch',
inputs: {
reason: '工单 ' + workOrder.work_order_id + ' 自动触发',
source_work_order: workOrder.work_order_id
}
};
}
var assignedTo = (workOrder.assignment && workOrder.assignment.assigned_to) || 'AG-TY-01';
var assignedToName = (workOrder.assignment && workOrder.assignment.assigned_to_name) || '天眼 Notion 大脑';
var command = {
_protocol: 'neural-bridge-v3.0',
_type: 'downstream_command',
command_id: commandId,
parent_work_order: workOrder.work_order_id,
source: {
agent_id: assignedTo,
agent_name: assignedToName,
issued_at: now,
issued_reason: workOrder.title
},
target: {
workflow_id: targetWorkflowId || 'unknown',
workflow_file: targetWorkflow ? targetWorkflow.file : 'unknown',
brain: targetWorkflow ? targetWorkflow.brain : assignedTo
},
instruction: {
type: instructionType,
params: instructionParams
},
constraints: {
priority: workOrder.severity,
timeout_hours: (workOrder.constraints && workOrder.constraints.timeout_hours) || 24,
max_retries: (workOrder.constraints && workOrder.constraints.max_retries) || 2,
requires_human_approval: workOrder.severity === 'P0',
execution_window: {
start: '06:00 CST',
end: '23:00 CST'
}
},
expected_outcome: {
description: '解决工单 ' + workOrder.work_order_id + ': ' + workOrder.title,
verification: {
type: 'check_workflow_status',
workflow: targetWorkflowId,
expected_conclusion: 'success'
}
},
security: {
sfp: '⌜SFP::' + assignedTo + '::NeuralBridge::' + commandId + '::' + now + '⌝',
signature_chain: [assignedTo, '铸渊桥接层']
}
};
// 写入 deploy-queue
fs.mkdirSync(DEPLOY_QUEUE, { recursive: true });
fs.writeFileSync(
path.join(DEPLOY_QUEUE, commandId + '.json'),
JSON.stringify(command, null, 2)
);
console.log('✅ 工单 ' + workOrder.work_order_id + ' → 指令 ' + commandId);
console.log(' 类型: ' + instructionType);
console.log(' 目标: ' + (targetWorkflowId || '(待确定)'));
console.log(' 优先级: ' + workOrder.severity);
return command;
}
// CLI 入口
if (require.main === module) {
var woPath = process.argv[2];
if (!woPath) {
console.error('用法: node convert-workorder-to-command.js <work-order.json>');
process.exit(1);
}
var wo = loadJSON(woPath);
if (!wo) {
console.error('❌ 无法读取工单文件: ' + woPath);
process.exit(1);
}
convertWorkOrderToCommand(wo);
}
module.exports = { convertWorkOrderToCommand };