From 6358ff16b3e6cc338ea3d9fca47c22b5061e22cd Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Sun, 6 Sep 2026 23:19:03 +0800 Subject: [PATCH] fix(core): keep agent usage rounds cumulative --- .../core/src/agents/runtime/agent-core.ts | 2 +- .../src/agents/runtime/agent-headless.test.ts | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/core/src/agents/runtime/agent-core.ts b/packages/core/src/agents/runtime/agent-core.ts index 3aa9d45ce29..d65973a2c63 100644 --- a/packages/core/src/agents/runtime/agent-core.ts +++ b/packages/core/src/agents/runtime/agent-core.ts @@ -1207,7 +1207,7 @@ export class AgentCore { // Update token usage if available if (lastUsage) { - this.recordTokenUsage(lastUsage, turnCounter, roundStreamStart); + this.recordTokenUsage(lastUsage, cumulativeRounds, roundStreamStart); } if (functionCalls.length > 0) { diff --git a/packages/core/src/agents/runtime/agent-headless.test.ts b/packages/core/src/agents/runtime/agent-headless.test.ts index ef40d8c6945..f7d17f8c26b 100644 --- a/packages/core/src/agents/runtime/agent-headless.test.ts +++ b/packages/core/src/agents/runtime/agent-headless.test.ts @@ -51,6 +51,7 @@ import { type AgentStreamTextEvent, type AgentToolCallEvent, type AgentToolResultEvent, + type AgentUsageEvent, } from './agent-events.js'; import type { ModelConfig, @@ -661,6 +662,42 @@ describe('subagent.ts', () => { expect(scope.getExecutionSummary()).toMatchObject({ rounds: 2 }); }); + it('should keep usage rounds unique across finishing input segments', async () => { + const { config } = await createMockConfig(); + mockSendMessageStream.mockImplementation(async () => + (async function* () { + yield { + type: 'chunk', + value: { + candidates: [{ content: { parts: [{ text: 'Done.' }] } }], + usageMetadata: { totalTokenCount: 1 }, + }, + }; + })(), + ); + + const scope = await AgentHeadless.create( + 'test-agent', + config, + { systemPrompt: 'You are a test agent.' }, + defaultModelConfig, + defaultRunConfig, + ); + const usageRounds: number[] = []; + scope + .getEventEmitter() + .on(AgentEventType.USAGE_METADATA, (event: AgentUsageEvent) => { + usageRounds.push(event.round); + }); + + await scope.execute(new ContextState()); + await scope.executeExternalInputs(['late correction'], undefined, { + resetStats: false, + }); + + expect(usageRounds).toEqual([1, 2]); + }); + it('should preserve statistics for continuation work in the same logical turn', async () => { const { config } = await createMockConfig(); mockSendMessageStream.mockImplementation(