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
@@ -327,6 +327,60 @@ describe('system.tokenUsage handler', () => {
});
});
describe('system.contextUsage handler', () => {
it('returns empty sessions when no getContextUsage provided', async () => {
const handlers = createSystemHandlers({
startTime: Date.now(),
version: '0.1.0',
getSessionCount: () => 0,
getToolCount: () => 0,
getConnectionCount: () => 0,
});
const req: GatewayRequest = { id: 21, method: 'system.contextUsage' };
const result = await handlers['system.contextUsage'](req) as GatewayResponse;
expect(result.id).toBe(21);
const r = result.result as { sessions: unknown[] };
expect(r.sessions).toEqual([]);
});
it('returns session context budget data from getContextUsage callback', async () => {
const mockUsage = [
{
sessionId: 'telegram:user1',
budget: {
estimatedTokens: 120000,
contextWindow: 200000,
remainingTokens: 80000,
usagePct: 60,
thresholdPct: 80,
thresholdTokens: 160000,
shouldCompact: false,
},
},
];
const handlers = createSystemHandlers({
startTime: Date.now(),
version: '0.1.0',
getSessionCount: () => 1,
getToolCount: () => 0,
getConnectionCount: () => 1,
getContextUsage: () => mockUsage,
});
const req: GatewayRequest = { id: 22, method: 'system.contextUsage' };
const result = await handlers['system.contextUsage'](req) as GatewayResponse;
const r = result.result as { sessions: typeof mockUsage };
expect(r.sessions).toHaveLength(1);
expect(r.sessions[0].sessionId).toBe('telegram:user1');
expect(r.sessions[0].budget.usagePct).toBe(60);
expect(r.sessions[0].budget.shouldCompact).toBe(false);
});
});
describe('system.sessionAnalytics handler', () => {
it('returns empty analytics when callback is not provided', async () => {
const handlers = createSystemHandlers({
@@ -614,6 +668,16 @@ describe('tool handlers', () => {
describe('agent handlers', () => {
const mockAgent = {
process: vi.fn(async () => 'response text'),
consumeContextAlert: vi.fn(() => undefined),
getContextBudget: vi.fn(() => ({
estimatedTokens: 0,
contextWindow: 128000,
remainingTokens: 128000,
usagePct: 0,
thresholdPct: 80,
thresholdTokens: 102400,
shouldCompact: false,
})),
setOnToolUse: vi.fn(),
};