diff --git a/packages/core/src/core/geminiChat.test.ts b/packages/core/src/core/geminiChat.test.ts index 2f9e2d1076..4a47813881 100644 --- a/packages/core/src/core/geminiChat.test.ts +++ b/packages/core/src/core/geminiChat.test.ts @@ -788,6 +788,48 @@ describe('GeminiChat', async () => { ); }); + it('should not update global telemetry when no telemetryService is provided (subagent isolation)', async () => { + // Simulate a subagent GeminiChat: created without a telemetryService + const subagentChat = new GeminiChat(mockConfig, config, []); + + const response = (async function* () { + yield { + candidates: [ + { + content: { + parts: [{ text: 'subagent response' }], + role: 'model', + }, + finishReason: 'STOP', + index: 0, + safetyRatings: [], + }, + ], + text: () => 'subagent response', + usageMetadata: { + promptTokenCount: 12000, + candidatesTokenCount: 500, + totalTokenCount: 12500, + }, + } as unknown as GenerateContentResponse; + })(); + vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue( + response, + ); + + const stream = await subagentChat.sendMessageStream( + 'test-model', + { message: 'subagent task' }, + 'prompt-id-subagent', + ); + for await (const _ of stream) { + // consume stream + } + + // The global uiTelemetryService must NOT be called by subagent chats + expect(uiTelemetryService.setLastPromptTokenCount).not.toHaveBeenCalled(); + }); + it('should keep parts with thoughtSignature when consolidating history', async () => { const stream = (async function* () { yield { diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index db2d0b8033..522deb0397 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -35,7 +35,6 @@ import { ContentRetryFailureEvent, } from '../telemetry/types.js'; import type { UiTelemetryService } from '../telemetry/uiTelemetry.js'; -import { uiTelemetryService } from '../telemetry/uiTelemetry.js'; const debugLogger = createDebugLogger('QWEN_CODE_CHAT'); @@ -659,15 +658,11 @@ export class GeminiChat { // Some providers omit total_tokens or return 0 in streaming usage chunks. const lastPromptTokenCount = usageMetadata.totalTokenCount || usageMetadata.promptTokenCount; - if (lastPromptTokenCount) { - (this.telemetryService ?? uiTelemetryService).setLastPromptTokenCount( - lastPromptTokenCount, - ); + if (lastPromptTokenCount && this.telemetryService) { + this.telemetryService.setLastPromptTokenCount(lastPromptTokenCount); } - if (usageMetadata.cachedContentTokenCount) { - ( - this.telemetryService ?? uiTelemetryService - ).setLastCachedContentTokenCount( + if (usageMetadata.cachedContentTokenCount && this.telemetryService) { + this.telemetryService.setLastCachedContentTokenCount( usageMetadata.cachedContentTokenCount, ); }