Skip to content

fix(core): use aggregate usage consistently across providers#1366

Merged
omeraplak merged 1 commit into
mainfrom
fix/consistent-usage-totals
Jul 1, 2026
Merged

fix(core): use aggregate usage consistently across providers#1366
omeraplak merged 1 commit into
mainfrom
fix/consistent-usage-totals

Conversation

@omeraplak

@omeraplak omeraplak commented Jul 1, 2026

Copy link
Copy Markdown
Member

PR Checklist

Please check if your PR fulfills the following requirements:

Bugs / Features

What is the current behavior?

Finish usage resolution prefers aggregate totalUsage for most providers, but switches to last-step usage for Anthropic/cache cases. That makes root span usage and onEnd.output.usage provider-dependent during tool-call runs.

The stream normalizer also rewrites finish totalUsage to the last step for Anthropic/cache streams.

What is the new behavior?

resolveFinishUsage now consistently prefers aggregate totalUsage whenever AI SDK provides it, falling back to usage only when no aggregate is available.

normalizeFinishUsageStream now preserves finish totalUsage instead of rewriting it by provider/cache metadata. Updated tests cover Anthropic/cache cases and assert aggregate usage is preserved.

fixes #1360

Related to #1359. The dashboard/export total fallback that double-counted cached/reasoning breakdowns is handled in companion PR: https://github.com/VoltAgent/console/pull/44

Notes for reviewers

Docs were not updated because this restores consistent bug-fix behavior rather than introducing a new public API.

Summary by CodeRabbit

  • Bug Fixes
    • Improved usage totals shown for streaming events, keeping the aggregate finish usage consistent across providers.
    • Anthropic-related finish events now preserve the correct total usage instead of replacing it with step-level values.
    • Streamed finish usage is no longer adjusted unexpectedly when cache-related or metadata fields are present.

@changeset-bot

changeset-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bb057e6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@voltagent/core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dbff5b57-44f3-4ecd-b7d1-6f3b79249508

📥 Commits

Reviewing files that changed from the base of the PR and between 887213b and bb057e6.

📒 Files selected for processing (4)
  • .changeset/consistent-usage-totals.md
  • packages/core/src/agent/agent.spec.ts
  • packages/core/src/utils/usage-normalizer.spec.ts
  • packages/core/src/utils/usage-normalizer.ts

📝 Walkthrough

Walkthrough

This PR simplifies resolveFinishUsage and normalizeFinishUsageStream in usage-normalizer.ts to always prefer aggregate totalUsage over usage, removing the previous provider-metadata-based logic that switched to last-step usage for Anthropic/cache cases. Related unit tests and a changeset are updated accordingly.

Changes

Aggregate Finish Usage Consistency

Layer / File(s) Summary
Simplify usage resolution logic
packages/core/src/utils/usage-normalizer.ts
resolveFinishUsage no longer inspects providerMetadata and simply returns totalUsage ?? usage; normalizeFinishUsageStream is reduced to a pass-through that no longer rewrites totalUsage based on last-step state.
Update tests and add changeset
packages/core/src/utils/usage-normalizer.spec.ts, packages/core/src/agent/agent.spec.ts, .changeset/consistent-usage-totals.md
Test assertions and names are updated to expect totalUsage to be preserved/kept for Anthropic and cache-field scenarios instead of being overridden by last-step usage; a changeset patch entry is added for @voltagent/core.

Sequence Diagram(s)

sequenceDiagram
  participant Provider
  participant streamText
  participant normalizeFinishUsageStream
  participant resolveFinishUsage
  participant onEndHook

  Provider->>streamText: stream finish-step/finish events (usage, totalUsage, providerMetadata)
  streamText->>normalizeFinishUsageStream: forward stream parts
  normalizeFinishUsageStream-->>streamText: yield parts unchanged
  streamText->>resolveFinishUsage: totalUsage, usage
  resolveFinishUsage-->>streamText: totalUsage ?? usage (provider-independent)
  streamText->>onEndHook: output.usage = resolved aggregate usage
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • VoltAgent/voltagent#973: Touches the same usage-normalizer finish-usage logic and agent.spec.ts assertions, previously introducing the last-step override this PR now reverses.
  • VoltAgent/voltagent#1163: Relies on resolveFinishUsage output (usageForFinish) in the structured-output failure path, tied to the same resolution logic changed here.

Poem

A rabbit hopped through usage code,
Found last-step totals were the wrong road,
Now totals sum up, clean and true,
For every provider, one usage view! 🥕
Hop, hop, hooray — consistency's due! 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the core fix: consistent aggregate usage across providers.
Description check ✅ Passed The description follows the template and includes checklist items, current/new behavior, issue links, and reviewer notes.
Linked Issues check ✅ Passed The code matches #1360 by preserving aggregate finish usage across providers and updating the related tests.
Out of Scope Changes check ✅ Passed The changes stay focused on usage normalization, tests, and a changeset, with no unrelated scope visible.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/consistent-usage-totals

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Re-trigger cubic

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying voltagent with  Cloudflare Pages  Cloudflare Pages

Latest commit: bb057e6
Status: ✅  Deploy successful!
Preview URL: https://019779e1.voltagent.pages.dev
Branch Preview URL: https://fix-consistent-usage-totals.voltagent.pages.dev

View logs

@omeraplak
omeraplak merged commit 6b26a8f into main Jul 1, 2026
23 checks passed
@omeraplak
omeraplak deleted the fix/consistent-usage-totals branch July 1, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: trace usage semantics differ by provider for tool-call runs

1 participant