import test from 'node:test'; import { strict as assert } from 'assert'; import { withSpendGuard, AgentGuardBlockedError } from '../spend-guard'; import { withSpendGuardAnthropic } from './anthropic'; import { withSpendGuardBedrock } from './bedrock'; import { InMemorySpendStore } from '../store-memory'; import { InMemoryDecisionLogStore } from '../decision-log'; import { clearCostOverrides, setCostOverride } from '../cost-table'; import type { SpendPolicy } from '../types'; const scope = { tenantId: 'enforce-test' }; // A per_call cap of 1c that blocks: any priced call (>1c) is denied. Enforcement // is a hard deterministic limit — identical semantics across every binding. function blockPolicy(): SpendPolicy { return { id: 'enforce-block', name: 'enforce block', scope, caps: [{ window: 'per_call', amountCents: 1, action: 'block' }], mode: 'enforce', version: 1, effectiveFrom: '2026-07-16T00:00:00.000Z', }; } function harness() { clearCostOverrides(); // Deterministic priced models per provider family. setCostOverride('gpt-price-test', { inputCentsPerKtok: 100, outputCentsPerKtok: 100 }); setCostOverride('claude-price-test', { inputCentsPerKtok: 100, outputCentsPerKtok: 100 }); setCostOverride('amazon.price-test', { inputCentsPerKtok: 100, outputCentsPerKtok: 100 }); return { spendStore: new InMemorySpendStore(), logStore: new InMemoryDecisionLogStore(), tokenEstimator: () => 1000, }; } test('OpenAI binding: priced call over the cap is BLOCKED and provider never called', async () => { const cfg = harness(); let providerCalled = false; const client = withSpendGuard( { chat: { completions: { create: async () => { providerCalled = true; return {}; } } } }, { policy: blockPolicy(), scope, config: cfg }, ); await assert.rejects( () => client.chat.completions.create({ model: 'gpt-price-test', messages: [{ content: 'x' }], max_tokens: 1000 }), (e) => e instanceof AgentGuardBlockedError && e.decision.action === 'block' && e.decision.projectedCents === 200, ); assert.equal(providerCalled, false, 'block prevents the provider dispatch'); }); test('Anthropic binding: priced call over the cap is BLOCKED', async () => { const cfg = harness(); let providerCalled = false; const client = withSpendGuardAnthropic( { messages: { create: async () => { providerCalled = true; return {}; } } }, { policy: blockPolicy(), scope, config: cfg }, ); await assert.rejects( () => client.messages.create({ model: 'claude-price-test', messages: [{ role: 'user', content: 'x' }], max_tokens: 1000 }), (e) => e instanceof AgentGuardBlockedError && e.decision.projectedCents === 200, ); assert.equal(providerCalled, false); }); test('Bedrock binding: priced InvokeModel call over the cap is BLOCKED', async () => { const cfg = harness(); let providerCalled = false; class InvokeModelCommand { constructor(public input: Record) {} } const client = withSpendGuardBedrock( { send: async () => { providerCalled = true; return {}; } }, { policy: blockPolicy(), scope, config: cfg }, ); await assert.rejects( () => client.send(new InvokeModelCommand({ modelId: 'amazon.price-test', body: JSON.stringify({ max_tokens: 1000, messages: [{ role: 'user', content: [{ type: 'text', text: 'x' }] }] }), })), (e) => e instanceof AgentGuardBlockedError && e.decision.projectedCents === 200, ); assert.equal(providerCalled, false); }); test('non-InvokeModel Bedrock commands pass through ungated (cost/enforce only on inference)', async () => { const cfg = harness(); let passed = false; class ListFoundationModelsCommand { constructor(public input: Record) {} } const client = withSpendGuardBedrock( { send: async () => { passed = true; return { models: [] }; } }, { policy: blockPolicy(), scope, config: cfg }, ); const res = await client.send(new ListFoundationModelsCommand({})); assert.deepEqual(res, { models: [] }); assert.equal(passed, true); });