fix(ai): preserve input token counts from message_start in Anthropic provider

Proxies like Portkey omit input_tokens in message_delta events (it's nullable
per the SDK). The previous code unconditionally overwrote usage fields, causing
input token counts to reset to 0.

Now only updates usage fields when they are present (not null), preserving
the correct input_tokens value captured from message_start.

Fixes #1045
This commit is contained in:
Mario Zechner 2026-01-29 00:06:51 +01:00
parent 4f9deddd47
commit 8b5c81f21f
2 changed files with 15 additions and 4 deletions

View file

@ -6,6 +6,7 @@
- Fixed Anthropic provider to handle `sensitive` stop_reason returned by API ([#978](https://github.com/badlogic/pi-mono/issues/978))
- Fixed DeepSeek API compatibility by detecting `deepseek.com` URLs and disabling unsupported `developer` role ([#1048](https://github.com/badlogic/pi-mono/issues/1048))
- Fixed Anthropic provider to preserve input token counts when proxies omit them in `message_delta` events ([#1045](https://github.com/badlogic/pi-mono/issues/1045))
## [0.50.1] - 2026-01-26

View file

@ -304,10 +304,20 @@ export const streamAnthropic: StreamFunction<"anthropic-messages", AnthropicOpti
if (event.delta.stop_reason) {
output.stopReason = mapStopReason(event.delta.stop_reason);
}
output.usage.input = event.usage.input_tokens || 0;
output.usage.output = event.usage.output_tokens || 0;
output.usage.cacheRead = event.usage.cache_read_input_tokens || 0;
output.usage.cacheWrite = event.usage.cache_creation_input_tokens || 0;
// Only update usage fields if present (not null).
// Preserves input_tokens from message_start when proxies omit it in message_delta.
if (event.usage.input_tokens != null) {
output.usage.input = event.usage.input_tokens;
}
if (event.usage.output_tokens != null) {
output.usage.output = event.usage.output_tokens;
}
if (event.usage.cache_read_input_tokens != null) {
output.usage.cacheRead = event.usage.cache_read_input_tokens;
}
if (event.usage.cache_creation_input_tokens != null) {
output.usage.cacheWrite = event.usage.cache_creation_input_tokens;
}
// Anthropic doesn't provide total_tokens, compute from components
output.usage.totalTokens =
output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;