103 lines
3.1 KiB
JavaScript

// ═══════════════════════════════════════
// 铸渊开发Agent · 任务接收端点
// 接收铸渊的结构化规划清单 → 暂存 → 通知
// ═══════════════════════════════════════
const fs = require("fs");
const path = require("path");
const PLANS_DIR = path.join(__dirname, "..", "plans");
const QUEUE_FILE = path.join(__dirname, "..", "plans", "queue.json");
// 确保目录存在
if (!fs.existsSync(PLANS_DIR)) fs.mkdirSync(PLANS_DIR, { recursive: true });
if (!fs.existsSync(QUEUE_FILE)) fs.writeFileSync(QUEUE_FILE, "[]", "utf-8");
/**
* 验证请求来源
*/
function verifySource(req) {
const auth = req.headers["authorization"] || "";
const expectedKey = process.env.ZY_GTW_KEY || "";
if (!expectedKey) {
console.warn("[TaskReceiver] ZY_GTW_KEY 未配置,跳过验证");
return true;
}
return auth === "Bearer " + expectedKey;
}
/**
* 验证规划清单结构
*/
function validatePlan(plan) {
if (!plan.plan_id) return { ok: false, error: "缺少 plan_id" };
if (!plan.title) return { ok: false, error: "缺少 title" };
if (!plan.tasks || !Array.isArray(plan.tasks)) return { ok: false, error: "缺少 tasks 数组" };
if (plan.tasks.length === 0) return { ok: false, error: "tasks 不能为空" };
for (let i = 0; i < plan.tasks.length; i++) {
const t = plan.tasks[i];
if (!t.id) return { ok: false, error: "task[" + i + "] 缺少 id" };
if (!t.action) return { ok: false, error: "task[" + i + "] 缺少 action" };
}
return { ok: true };
}
/**
* 接收并暂存规划清单
*/
function receivePlan(plan) {
// 写入独立文件
const planFile = path.join(PLANS_DIR, plan.plan_id + ".json");
plan._received_at = new Date().toISOString();
plan._status = "received";
fs.writeFileSync(planFile, JSON.stringify(plan, null, 2), "utf-8");
// 推入队列
const queue = JSON.parse(fs.readFileSync(QUEUE_FILE, "utf-8"));
queue.push({
plan_id: plan.plan_id,
title: plan.title,
task_count: plan.tasks.length,
received_at: plan._received_at,
status: "received"
});
fs.writeFileSync(QUEUE_FILE, JSON.stringify(queue, null, 2), "utf-8");
console.log("[TaskReceiver] 收到规划: " + plan.plan_id + " · " + plan.tasks.length + "个任务");
return {
received: true,
plan_id: plan.plan_id,
task_count: plan.tasks.length,
stored_at: planFile
};
}
/**
* Express 路由处理器
*/
function handleTask(req, res) {
try {
if (!verifySource(req)) {
return res.status(403).json({ error: "未授权 — 来源未通过 Gatekeeper 验证" });
}
const plan = req.body;
const validation = validatePlan(plan);
if (!validation.ok) {
return res.status(400).json({ error: validation.error });
}
const result = receivePlan(plan);
return res.status(201).json(result);
} catch (err) {
console.error("[TaskReceiver] 错误:", err.message);
return res.status(500).json({ error: "内部错误: " + err.message });
}
}
module.exports = { handleTask };