'use strict'; const assert = require('assert'); const { createBatchBudgetGuard } = require('../mcp/src/core/batch-budget-guard'); async function main() { const calls = []; const context = { usageTraceId: 'usage_smoke_budget', reportId: 'report_smoke_budget' }; const input = { budgetCny: 1, queryBillingImpl: async ({ operations }) => { calls.push(operations); return { status: 'ok', data: { balance: { availableQuota: 100 }, estimate: { quota: 1000, amountCny: 1.2, operations }, usage: { totals: { costCny: 0.8 } } } }; } }; const guard = createBatchBudgetGuard({ input, context, operationFactory: () => [{ model: 'voc-social', path: 'search_notes', count: 1, priceCnyPerCall: 1.2, quotaPerCall: 1000 }] }); const decision = await guard.beforeBatch({ keyword: '预算测试', batchIndex: 0 }); assert.strictEqual(decision.allowed, false); assert.strictEqual(decision.status, 'blocked'); assert.strictEqual(decision.budgetLimitCny, 1); assert.strictEqual(calls.length, 1); assert.strictEqual(guard.snapshot().keyword, '预算测试'); const rechargeGuard = createBatchBudgetGuard({ input: { budgetCny: 20, queryBillingImpl: async () => ({ status: 'ok', data: { balance: { availableQuota: 10 }, estimate: { quota: 1000, amountCny: 2, operations: [] }, usage: { totals: { costCny: 0 } } } }) }, context, operationFactory: () => [{ model: 'voc-social', path: 'search_notes', count: 1 }] }); const rechargeDecision = await rechargeGuard.beforeBatch({ keyword: '余额测试' }); assert.strictEqual(rechargeDecision.status, 'needs_recharge'); assert.strictEqual(rechargeDecision.allowed, false); process.stdout.write('budget guard smoke ok\n'); } main().catch(error => { process.stderr.write(`${error.stack || error}\n`); process.exitCode = 1; });