feat(gateway): expose context usage and warning events

This commit is contained in:
William Valentin
2026-02-16 15:44:09 -08:00
parent 8758ea8f1c
commit fee8be1de0
11 changed files with 645 additions and 334 deletions
+64
View File
@@ -9,6 +9,16 @@ import { initAuditLogger } from '../../audit/index.js';
describe('createAgentHandlers command fast-path', () => {
const mockAgent = {
process: vi.fn(async () => 'agent response'),
consumeContextAlert: vi.fn(() => undefined as unknown),
getContextBudget: vi.fn(() => ({
estimatedTokens: 100,
contextWindow: 200000,
remainingTokens: 199900,
usagePct: 0.05,
thresholdPct: 80,
thresholdTokens: 160000,
shouldCompact: false,
})),
getUsage: vi.fn(() => ({
primary: { inputTokens: 10, outputTokens: 5, calls: 1 },
delegation: {},
@@ -169,12 +179,56 @@ describe('createAgentHandlers command fast-path', () => {
expect(mockAgent.process).not.toHaveBeenCalled();
expect(((sent[0] as GatewayEvent).data as { content: string }).content).toContain('Set queue.mode=followup');
});
it('emits context_warning event before done when orchestrator reports an alert', async () => {
mockAgent.consumeContextAlert.mockReturnValueOnce({
level: 'checkpoint',
message: 'Context usage is 86.0% (172000/200000 estimated tokens).',
budget: {
estimatedTokens: 172000,
contextWindow: 200000,
remainingTokens: 28000,
usagePct: 86,
thresholdPct: 80,
thresholdTokens: 160000,
shouldCompact: true,
},
actions: {
checkpointSaved: true,
autoCompacted: false,
checkpointNamespace: 'session/checkpoints/ws/conn-1',
},
});
const sent: OutboundMessage[] = [];
const send = vi.fn((msg: OutboundMessage) => sent.push(msg));
await handlers['agent.send']({
id: 6,
method: 'agent.send',
params: { message: 'hello', connectionId: 'conn-1' },
}, send);
expect(sent).toHaveLength(2);
expect((sent[0] as GatewayEvent).event).toBe('context_warning');
expect((sent[1] as GatewayEvent).event).toBe('done');
});
});
describe('createAgentHandlers queue policy resolution', () => {
it('passes resolved per-request queue policy into lane enqueue', async () => {
const mockAgent = {
process: vi.fn(async () => 'ok'),
consumeContextAlert: vi.fn(() => undefined),
getContextBudget: vi.fn(() => ({
estimatedTokens: 0,
contextWindow: 128000,
remainingTokens: 128000,
usagePct: 0,
thresholdPct: 80,
thresholdTokens: 102400,
shouldCompact: false,
})),
getUsage: vi.fn(() => ({
primary: { inputTokens: 0, outputTokens: 0, calls: 0 },
delegation: {},
@@ -234,6 +288,16 @@ describe('createAgentHandlers queue policy resolution', () => {
const sessionBridge = {
getAgent: vi.fn(() => ({
process: vi.fn(async () => 'ok'),
consumeContextAlert: vi.fn(() => undefined),
getContextBudget: vi.fn(() => ({
estimatedTokens: 0,
contextWindow: 128000,
remainingTokens: 128000,
usagePct: 0,
thresholdPct: 80,
thresholdTokens: 102400,
shouldCompact: false,
})),
getUsage: vi.fn(() => ({
primary: { inputTokens: 0, outputTokens: 0, calls: 0 },
delegation: {},