fix: clean up /clear and /resume (#22007)

This commit is contained in:
Jack Wotherspoon
2026-03-11 16:23:23 +01:00
committed by GitHub
parent 99bbbc2170
commit b804fe9662
9 changed files with 282 additions and 22 deletions
@@ -15,6 +15,7 @@ import {
type ApiErrorEvent,
type ApiResponseEvent,
} from './types.js';
import { type ConversationRecord } from '../services/chatRecordingService.js';
import type {
CompletedToolCall,
ErroredToolCall,
@@ -698,6 +699,121 @@ describe('UiTelemetryService', () => {
});
});
describe('clear', () => {
it('should reset metrics and last prompt token count', () => {
// Set up initial state with some metrics
const event = {
'event.name': EVENT_API_RESPONSE,
model: 'gemini-2.5-pro',
duration_ms: 500,
usage: {
input_token_count: 100,
output_token_count: 200,
total_token_count: 300,
cached_content_token_count: 50,
thoughts_token_count: 20,
tool_token_count: 30,
},
} as ApiResponseEvent & { 'event.name': typeof EVENT_API_RESPONSE };
service.addEvent(event);
service.setLastPromptTokenCount(123);
expect(service.getMetrics().models['gemini-2.5-pro']).toBeDefined();
expect(service.getLastPromptTokenCount()).toBe(123);
service.clear();
expect(service.getMetrics().models).toEqual({});
expect(service.getLastPromptTokenCount()).toBe(0);
});
it('should emit clear and update events', () => {
const clearSpy = vi.fn();
const updateSpy = vi.fn();
service.on('clear', clearSpy);
service.on('update', updateSpy);
const newSessionId = 'new-session-id';
service.clear(newSessionId);
expect(clearSpy).toHaveBeenCalledWith(newSessionId);
expect(updateSpy).toHaveBeenCalledOnce();
const { metrics, lastPromptTokenCount } = updateSpy.mock.calls[0][0];
expect(metrics.models).toEqual({});
expect(lastPromptTokenCount).toBe(0);
});
});
describe('hydrate', () => {
it('should aggregate metrics from a ConversationRecord', () => {
const conversation = {
sessionId: 'resumed-session',
messages: [
{
type: 'user',
content: 'Hello',
},
{
type: 'gemini',
model: 'gemini-1.5-pro',
tokens: {
input: 10,
output: 20,
total: 30,
cached: 5,
thoughts: 2,
tool: 3,
},
toolCalls: [
{ name: 'test_tool', status: 'success' },
{ name: 'test_tool', status: 'error' },
],
},
{
type: 'gemini',
model: 'gemini-1.5-pro',
tokens: {
input: 100,
output: 200,
total: 300,
cached: 50,
thoughts: 20,
tool: 30,
},
},
],
} as unknown as ConversationRecord;
const clearSpy = vi.fn();
const updateSpy = vi.fn();
service.on('clear', clearSpy);
service.on('update', updateSpy);
service.hydrate(conversation);
expect(clearSpy).toHaveBeenCalledWith('resumed-session');
const metrics = service.getMetrics();
const modelMetrics = metrics.models['gemini-1.5-pro'];
expect(modelMetrics).toBeDefined();
expect(modelMetrics.tokens.prompt).toBe(110); // 10 + 100
expect(modelMetrics.tokens.candidates).toBe(220); // 20 + 200
expect(modelMetrics.tokens.cached).toBe(55); // 5 + 50
expect(modelMetrics.tokens.thoughts).toBe(22); // 2 + 20
expect(modelMetrics.tokens.tool).toBe(33); // 3 + 30
expect(modelMetrics.tokens.input).toBe(55); // 110 - 55
expect(metrics.tools.totalCalls).toBe(2);
expect(metrics.tools.totalSuccess).toBe(1);
expect(metrics.tools.totalFail).toBe(1);
expect(metrics.tools.byName['test_tool'].count).toBe(2);
expect(service.getLastPromptTokenCount()).toBe(300); // 100 (input) + 200 (output)
expect(updateSpy).toHaveBeenCalled();
});
});
describe('Tool Call Event with Line Count Metadata', () => {
it('should aggregate valid line count metadata', () => {
const toolCall = createFakeCompletedToolCall('test_tool', true, 100);