Compare commits

...
Author SHA1 Message Date
abeatrix 3756d583dd fix(llms): report prompt-only input token usage totals
Subtract cache read and write tokens from reported input token counts in
runtime usage events and run results to avoid double counting cached tokens.

Also add reasoningTokens to AgentUsageEvent so usage metadata can represent
reasoning token counts when providers return them.
2026-06-30 13:59:50 -07:00
3 changed files with 23 additions and 3 deletions
+9 -1
View File
@@ -362,7 +362,15 @@ export async function runAgent(
type: "run_result",
finishReason: result.finishReason,
iterations: result.iterations,
usage,
usage: usage && {
...usage,
inputTokens: Math.max(
0,
usage.inputTokens -
(usage.cacheReadTokens ?? 0) -
(usage.cacheWriteTokens ?? 0),
),
},
...(aggregateUsage ? { aggregateUsage } : {}),
durationMs: result.durationMs,
text: result.text,
@@ -336,17 +336,27 @@ export class RuntimeEventAdapter {
cacheWriteTokens: next.cacheWriteTokens,
totalCost: next.totalCost,
};
// Emit prompt-only inputTokens (excluding cache reads/writes) so consumers
// can explicitly add cache_read themselves, consistent with other agents.
const promptOnlyDeltaInput = Math.max(
0,
deltaInput - Math.max(0, deltaCacheRead) - Math.max(0, deltaCacheWrite),
);
const totalPromptOnlyInput = Math.max(
0,
next.inputTokens - next.cacheReadTokens - next.cacheWriteTokens,
);
return [
{
type: "usage",
inputTokens: Math.max(0, deltaInput),
inputTokens: promptOnlyDeltaInput,
outputTokens: Math.max(0, deltaOutput),
cacheReadTokens:
deltaCacheRead === 0 ? undefined : Math.max(0, deltaCacheRead),
cacheWriteTokens:
deltaCacheWrite === 0 ? undefined : Math.max(0, deltaCacheWrite),
cost: deltaCost === 0 ? undefined : deltaCost,
totalInputTokens: next.inputTokens,
totalInputTokens: totalPromptOnlyInput,
totalOutputTokens: next.outputTokens,
totalCacheReadTokens:
next.cacheReadTokens === 0 ? undefined : next.cacheReadTokens,
+2
View File
@@ -140,6 +140,8 @@ export interface AgentUsageEvent extends AgentEventMetadata {
cacheReadTokens?: number;
/** Tokens written to cache */
cacheWriteTokens?: number;
/** Number of tokens used for reasoning */
reasoningTokens?: number;
/** Cost for this turn */
cost?: number;