feat: Add UI for /stats slash command (#883)

This commit is contained in:
Abhi
2025-06-10 15:59:52 -04:00
committed by GitHub
parent 04e2fe0bff
commit 9c3f34890f
16 changed files with 649 additions and 109 deletions

View File

@@ -239,6 +239,8 @@ describe('Turn', () => {
candidates: [{ content: { parts: [{ text: 'First response' }] } }],
usageMetadata: mockMetadata1,
} as unknown as GenerateContentResponse;
// Add a small delay to ensure apiTimeMs is > 0
await new Promise((resolve) => setTimeout(resolve, 10));
yield {
functionCalls: [{ name: 'aTool' }],
usageMetadata: mockMetadata2,
@@ -262,7 +264,10 @@ describe('Turn', () => {
expect(metadataEvent.type).toBe(GeminiEventType.UsageMetadata);
// The value should be the *last* metadata object received.
expect(metadataEvent.value).toEqual(mockMetadata2);
expect(metadataEvent.value).toEqual(
expect.objectContaining(mockMetadata2),
);
expect(metadataEvent.value.apiTimeMs).toBeGreaterThan(0);
// Also check the public getter
expect(turn.getUsageMetadata()).toEqual(mockMetadata2);

View File

@@ -104,7 +104,7 @@ export type ServerGeminiChatCompressedEvent = {
export type ServerGeminiUsageMetadataEvent = {
type: GeminiEventType.UsageMetadata;
value: GenerateContentResponseUsageMetadata;
value: GenerateContentResponseUsageMetadata & { apiTimeMs?: number };
};
// The original union type, now composed of the individual types
@@ -137,6 +137,7 @@ export class Turn {
req: PartListUnion,
signal: AbortSignal,
): AsyncGenerator<ServerGeminiStreamEvent> {
const startTime = Date.now();
try {
const responseStream = await this.chat.sendMessageStream({
message: req,
@@ -174,9 +175,10 @@ export class Turn {
}
if (this.lastUsageMetadata) {
const durationMs = Date.now() - startTime;
yield {
type: GeminiEventType.UsageMetadata,
value: this.lastUsageMetadata,
value: { ...this.lastUsageMetadata, apiTimeMs: durationMs },
};
}
} catch (error) {