Skip to content

fix(llm): capture LiteLLM cost headers and inject into finish providerMetadata - #51957

Closed
BrunoSilva-neuro wants to merge 1 commit into
anomalyco:devfrom
BrunoSilva-neuro:litellm-cost-headers
Closed

BrunoSilva-neuro wants to merge 1 commit into
anomalyco:devfrom
BrunoSilva-neuro:litellm-cost-headers

Conversation

@BrunoSilva-neuro

@BrunoSilva-neuro BrunoSilva-neuro commented Sep 28, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #52127

Type of change

  • Bug fix

What does this PR do?

When using a LiteLLM proxy, some turns were recorded with $0.00 cost in opencode stats. Two root causes:

  1. OpenCode estimates cost locally from token counts and a price table. Models with no local price entry always produce $0.00.
  2. LiteLLM 1.98+ omits x-litellm-response-cost when it equals x-litellm-response-cost-original, so reading only the primary header misses those responses regardless.

This PR captures the authoritative cost directly from the proxy's response headers and attaches it to finish/step-finish events via providerMetadata.litellm:

packages/llm/src/route/transport/http.ts

  • Adds responseHeaders: Ref.Ref<Record<string,string>> to HttpPrepared as a side-channel, populated after the HTTP response arrives.
  • Reads x-litellm-response-cost with fallback to x-litellm-response-cost-original (handles the 1.98+ omission case). Also captures x-litellm-key-spend for audit purposes.
  • No-op when no LiteLLM headers are present — all other providers unaffected.

packages/llm/src/route/client.ts

  • After the protocol step reducer, maps finish/step-finish events to merge providerMetadata.litellm with the captured headers.
  • Duck-type guard on Prepared keeps WebSocket transport unaffected without interface changes.

How did you verify your code works?

Manually called the proxy /v1/messages endpoint twice with identical payloads. Request 1 returned x-litellm-response-cost: 0.000434; request 2 omitted that header but included x-litellm-response-cost-original: 0.000434. The fallback logic covers both cases. Could not run bun typecheck (tsgo unavailable in the environment) — happy to iterate on types if CI catches anything.

Screenshots / recordings

N/A — no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…rMetadata

LiteLLM 1.98+ omits the primary x-litellm-response-cost header when its
value equals x-litellm-response-cost-original (an optimisation introduced
to reduce response size). Callers that only read the primary header record
$0.00 cost for those responses.

Changes:
- packages/llm/src/route/transport/http.ts: add a Ref<Record<string,string>>
  to HttpPrepared as a side-channel; populate it from the HTTP response
  headers in frames(), reading x-litellm-response-cost with a fallback to
  x-litellm-response-cost-original when the primary header is absent; also
  capture x-litellm-key-spend for audit purposes.
- packages/llm/src/route/client.ts: after the protocol stream step, map
  finish and step-finish events to merge providerMetadata.litellm with the
  captured headers so downstream cost accounting always sees the true value.
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@github-actions github-actions Bot removed needs:issue needs:compliance This means the issue will auto-close after 2 hours. labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

LiteLLM proxy responses record $0.00 cost when x-litellm-response-cost header is omitted

1 participant