70 lines
2.1 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.

// ═══════════════════════════════════════
// 铸渊开发Agent · 成本守卫 + 统一插座 v1.0
// API调用计数 · 预算控制 · 输出格式校验
// ═══════════════════════════════════════
const fs = require("fs");
const path = require("path");
const CONSTITUTION = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "agent-constitution.json"), "utf-8"));
const { cost_guard, unified_interface } = CONSTITUTION;
let _callCount = 0;
let _budgetExceeded = false;
function reset() {
_callCount = 0;
_budgetExceeded = false;
}
function getCallCount() { return _callCount; }
function isBudgetExceeded() { return _budgetExceeded; }
/**
* 包裹模型调用——自动计数
*/
function wrapModelCaller(rawCaller) {
return async function(prompt, opts) {
if (_budgetExceeded) {
throw new Error(cost_guard.stop_message);
}
_callCount++;
if (_callCount > cost_guard.max_api_calls_per_session) {
_budgetExceeded = true;
throw new Error(cost_guard.stop_message + " (已用 " + _callCount + " 次,上限 " + cost_guard.max_api_calls_per_session + ")");
}
console.log("[CostGuard] API调用 #" + _callCount + "/" + cost_guard.max_api_calls_per_session);
return rawCaller(prompt, opts);
};
}
/**
* 统一校验——每个模块输出必须通过这把尺
*/
function validateOutput(output) {
const required = unified_interface.required_output_fields;
const missing = required.filter(f => !(f in output));
if (missing.length > 0) {
return {
valid: false,
error: "输出缺少必要字段: " + missing.join(", "),
required,
received: Object.keys(output)
};
}
// 类型校验
if (typeof output.ok !== "boolean") {
return { valid: false, error: "ok 必须是 boolean收到: " + typeof output.ok };
}
return { valid: true };
}
module.exports = { wrapModelCaller, validateOutput, reset, getCallCount, isBudgetExceeded };