Repository navigation
fix(proxy): resolve pass-through endpoint type from the route, not just the host - #40137
Sunny-Soni00 wants to merge 4 commits into
Conversation
…st the host get_endpoint_type only matched Anthropic and OpenAI by hostname, so a pass-through endpoint pointed at a provider that speaks either API on any other host resolved to GENERIC. GENERIC matches no branch in the streaming logging dispatch, so the stream was recorded as "cannot parse chunks to standard response object" with no usage and no cost. Fall back to the request path once the existing host checks miss: a route ending in /v1/messages is Anthropic, one ending in /v1/chat/completions is OpenAI. The fallback can only fire where the function returns GENERIC today, so nothing that already classifies can reclassify. Suffix matching keeps routes like /v1/messages/count_tokens on the generic path. Fixes BerriAI#40117
There was a problem hiding this comment.
🟢 Approval recommended
The change is small, targeted, and includes regression tests covering both the fixed case and conservative fallback behavior.
Pull request overview
This PR fixes pass-through streaming accounting by resolving the endpoint type from the request path when hostname-based detection is insufficient, enabling correct Anthropic/OpenAI parsing and billing.
Changes:
- Extend
get_endpoint_typeto fall back to suffix-matching canonical routes (/v1/messages,/v1/chat/completions) - Add regression coverage ensuring Anthropic-compatible streamed pass-through calls on non-Anthropic hosts still produce usage and cost
- Add route-shape tests to keep unknown paths classified as
GENERIC
File summaries
| File | Description |
|---|---|
| litellm/proxy/pass_through_endpoints/pass_through_endpoints.py | Adds path-suffix fallback so endpoint type is not derived solely from hostname |
| tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py | Adds regression and route-shape tests validating correct endpoint typing and billing behavior |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Greptile SummaryThis PR extends pass-through endpoint classification to use canonical URL path suffixes when hostname checks do not identify the provider.
Confidence Score: 5/5The PR appears safe to merge; no actionable new defects or outstanding previous findings remain. The route fallback is restricted to the two intended canonical suffixes, unrelated paths remain generic, and the tests verify successful Anthropic stream accounting and OpenAI classification. All previous review threads are resolved, including the coarse helper return type corrected in the latest revision.
|
| Filename | Overview |
|---|---|
| litellm/proxy/pass_through_endpoints/pass_through_endpoints.py | Adds narrowly scoped route-suffix fallback classification after existing hostname-based checks. |
| tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py | Adds focused regression coverage and precisely types the stream-logging helper’s returned cost. |
Reviews (3): Last reviewed commit: "test(proxy): return the resolved cost in..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…ings Addresses review on BerriAI#40137: the new helper carried no return annotation, and the two regression docstrings restated what the assertions already show. Keeps only the part that is not obvious from the test, which is the failure each one pins.
Addresses review on BerriAI#40137: the helper's second element was an unparameterized dict. The tests only ever read response_cost from it, so hand back that value and drop the coarse type. Absent cost still reads as None, so the regression still fails on the unfixed classifier.
|
@Sunny-Soni00 resolve conflicts is needed |
…ection Resolves the conflict in test_pass_through_endpoints.py, where an upstream commit and this branch both appended tests at the end of the file. Both sets are kept, upstream's first, so this branch's change stays a pure append.
|
Conflict resolved by merging the latest litellm_internal_staging. Both sets of appended tests are kept, and the full pass-through suite passes locally. |
|
@Sunny-Soni00 PR review failed |
|
The one failing check is the Terraform provider Go test, which is failing on most open PRs today. This PR touches no Go code. |
|
@Sunny-Soni00 resolve conflicts is needed |
TLDR
Problem this solves:
How it solves it:
User Flow
Before: a developer who puts the gateway in front of a provider that speaks the Anthropic Messages API sees every streamed call logged at zero spend
https://<their-host>/v1/messagesPOST http://localhost:4000/my-provider/v1/messageswith"stream": trueand an ordinary Anthropic Messages bodycannot parse chunks to standard response objectfollowed by the raw streamAfter: the same call is logged as a normal response with real token counts and real spend
https://<their-host>/v1/messagesPOST http://localhost:4000/my-provider/v1/messageswith"stream": trueand an ordinary Anthropic Messages bodyRelevant issues
Fixes #40117
Linear ticket
Pre-Submission checklist
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)Screenshots / Proof of Fix
Shared setup, used unchanged for both runs. An Anthropic-compatible upstream is served on
127.0.0.1:9911, so the only thing that differs from a supported setup is the hostname, which is the whole point of the defect.POST /v1/messagesthere streams a normal Anthropic SSE response whose usage block reports 17 input tokens and 40 output tokens.config.yaml:The proxy is started the same way in both runs:
Before (6bb60f3)
grep -c "response_cost" litellm.logThe stream reached the client, and the proxy priced none of it.
After (c929dfd)
grep -oE "response_cost: [0-9.e-]+" litellm.logSame bytes on the wire to the client, and the request is now priced the same as it would be coming from api.anthropic.com.
Type
🐛 Bug Fix
Caveats (if any)
Medium
include_cost_in_streaming_usagekeys off the same endpoint type, so with that setting on, streams from these hosts now get cost added to their usage blockLow
Final Attestation