Repository navigation
test(integration): passthrough route cost cases - #42028
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
|
|
| "expected": { | ||
| "spend": 0.008624, | ||
| "input_cost": 0.00368, | ||
| "output_cost": 0.004944, | ||
| "prompt_tokens": 1840, | ||
| "completion_tokens": 412, | ||
| "breakdown_persisted": false, | ||
| "cost_header": false |
There was a problem hiding this comment.
These cases pin vendor prices without a source and date, violating a repository requirement that must be satisfied before merging
Context Used: AGENTS.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
These are not vendor prices. Every expected value is arithmetic over the test-owned cost_map in this same file, served at /_cost_map, e.g. 1840 x 2e-6 = 0.00368
There was a problem hiding this comment.
You're right — I misclassified these values. They are deterministic test expectations derived from the test-owned cost_map in cost_tracking_cases.json, served by the scripted upstream via /_cost_map; they are not uncited vendor-price assertions. For example, 1840 × 2e-6 = 0.00368. This comment does not apply and can be dismissed.
There was a problem hiding this comment.
You're right. These expected costs are derived from the test-owned cost_map served by the scripted upstream, not from vendor pricing. Since the fixture rates are defined and controlled within this test harness, an external price source and date are not required. I retract this comment.
There was a problem hiding this comment.
You're right — these are test-owned fixture prices, not uncited vendor prices. The scripted upstream's cost_map() loads cost_tracking_cases.json and serves its cost_map section at /_cost_map, so the expected values are intentionally derived from the same versioned test data. I retract the finding; no change is needed for this comment.
| scenario_id: Final = ( | ||
| segments[0].split(":", 1)[0] | ||
| if segments and self.scenario_store.get(segments[0].split(":", 1)[0]) is not None | ||
| else request.headers.get("x-scripted-scenario", "") | ||
| ) |
There was a problem hiding this comment.
This suite asserts what the gateway bills for a scripted upstream response, matching every existing case here. Forwarded path and body fidelity is a separate concern, out of scope
There was a problem hiding this comment.
That scope distinction is fair. These cases specifically validate gateway billing and persistence for scripted passthrough responses, consistent with the existing integration cases; path/body fidelity would require separate forwarding-contract tests. I’m withdrawing this concern for this PR.
There was a problem hiding this comment.
That scope distinction is fair. This shard validates passthrough billing and persisted spend, while request forwarding is covered by tests/integration/providers/test_request_boundary.py through /__observations, consistent with the native cost cases. I withdraw the request about malformed paths and bodies.
There was a problem hiding this comment.
That distinction is fair. Since this shard specifically validates passthrough billing persistence, and request forwarding/shape is covered by tests/integration/providers/test_request_boundary.py (including analogous native 400 cost cases), I withdraw the request to add forwarding assertions here. No further change needed.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…passthrough Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
TLDR
Problem this solves:
/gemini/*,/anthropic/*or/bedrock/*spend rows are rightHow it solves it:
endpoint, with$MODELin the pathcost_header: falseGEMINI_API_BASEandANTHROPIC_API_BASEpointed at the upstreamUser Flow
Before: a proxy admin has no shard proving what passthrough calls cost
x-goog-api-keyset to their virtual key and get Google's body backpass_through_endpointrow, becausetests/integration/run.py costonly covers native endpointsAfter: each of those calls has a scripted case with the exact spend and row pinned
tests/integration/run.py costRelevant issues
Builds on #42024 (needs
breakdown_persisted). Diff shows both until that one lands, then this rebases to mainAffected release
Linear ticket
Resolves LIT-8187
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Test data only, the proxy code path is unchanged. Proof is the shard against the scripted upstream that the shard itself starts (no provider spend by design)
Before (247c4dd)
tests/integration/run.py cost -k passthroughselects nothingAfter (110d4c2)
tests/integration/run.py cost -k passthroughagainst a fresh proxy and empty Redis:6 passed, 403 deselected12 passedmake lintpassesType
✅ Test
Caveats (if any)
High
generateContentprices viagemini/gemini-3.1-pro, streaming via the baregemini-3.1-pro(vertex) entry. Both cases are first principles against their own entry, and the names say which key each one hits. With the real map the two rates differ, so a user pays a different price for the same tokens depending onstreamMedium
/openai/*passthrough are excluded. Their logging only kicks in when the upstream hostname isapi.anthropic.comor*.openai.com, so with the scripted upstream they persist a$0row. Vertex passthrough has no api base override at all, so it is excluded toox-litellm-response-costheader, so those cases only check it when present. Gemini and Anthropic rows also persist nocost_breakdownLow
x-goog-api-keycarrying the virtual key, not the Bearer headerLink to Devin session: https://app.devin.ai/sessions/5425681f498543a19de84adcf8daeed8
Open in Devin Desktop: https://app.devin.ai/desktop/session/5425681f498543a19de84adcf8daeed8?variant=devin