feat(tinyfish): surface response headers + top-level response extras - #32301
feat(tinyfish): surface response headers + top-level response extras#32301ChenluJi wants to merge 1 commit into
Conversation
|
@greptileai review |
Greptile SummaryThis PR fixes two data-loss gaps in the TinyFish Search integration: top-level response envelope fields (
Confidence Score: 5/5Safe to merge — both changes follow well-established LiteLLM provider patterns and the new tests cover the exact behaviors being fixed. The model_extra spread is guarded by No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/llms/tinyfish/search/transformation.py | Adds top-level response extras pass-through via model_extra spreading and stashes response headers on _hidden_params, matching the existing pattern used by other providers. Logic is sound and well-commented. |
| tests/test_litellm/llms/tinyfish/test_tinyfish_search.py | Adds 5 new unit tests for header stashing and extras pass-through; reformats existing tests (line length); simplifies a few fixtures without weakening assertions. All tests use mocks only. |
| tests/search_tests/test_tinyfish_search.py | Single comment change only — removes internal tracker reference from a test docstring. No logic changes. |
Reviews (5): Last reviewed commit: "feat(tinyfish): surface top-level respon..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
@greptileai review |
533d2a1 to
6c5be5c
Compare
|
@greptileai review |
6c5be5c to
f7658d9
Compare
|
@greptileai review |
f7658d9 to
3d62ae9
Compare
Follow-up to BerriAI#31411 (superseded and merged as BerriAI#31997). Two related fixes so LiteLLM callers see what TinyFish actually returns. ## Top-level response extras (query, total_results, page, future fields) transform_search_response was constructing a fresh SearchResponse from just `results`, silently dropping every top-level extra that SearchResponse.model_validate(raw_json) had captured via extra='allow'. Reproduced twice against production — resp.query, resp.total_results, resp.page all absent, model_extra empty. Fix: spread parsed.model_extra at construction time. return SearchResponse( results=list(parsed.results[:max_results]), **(parsed.model_extra or {}), ) Future-proof: any new top-level field TinyFish adds rides through with no LiteLLM code change (SearchResponse's extra='allow' captures every non-declared field into parsed.model_extra automatically). ## Response headers surfaced on _hidden_params TinyFish sets useful response headers (X-Request-ID on every response; Retry-After and X-RateLimit-Limit on 429s). These were only accessible via BaseLLMException.headers on error paths; on the success path they were dropped entirely. Fix: stash headers on both LiteLLM-conventional channels, matching the convention used by Gemini/Volcengine/Manus/ChatGPT/OpenAI responses providers. response._hidden_params['headers'] = dict(raw_response.headers) response._hidden_params['additional_headers'] = ( process_response_headers(dict(raw_response.headers)) ) - 'headers' — raw dict for debugging. - 'additional_headers' — passed through process_response_headers so downstream LiteLLM consumers get sanitized keys (strips any x-litellm-* a misbehaving provider might set). Future-proof: no allowlist, no filtering. Any future response header flows through automatically. ## Tests Adds 5 new mock-only unit tests: - test_top_level_extras_flow_through - test_top_level_future_extras_flow_through - test_response_headers_stashed_on_hidden_params - test_response_headers_future_headers_flow_through - test_response_headers_strips_x_litellm_spoof 66 unit + integration tests pass locally. Live-tested against production TinyFish (23/23 regression checks). No request-side changes. No behavior change for per-result extras (already correct). Error paths unchanged.
3d62ae9 to
bf65ef9
Compare
|
Superseded by #32448 — same code, cleaner history and shorter diff. |
Summary
Follow-up to #31411 (superseded and merged as #31997). Two related fixes so LiteLLM callers see what TinyFish actually returns, plus small correctness cleanups.
1. Response headers surfaced on
_hidden_paramsTinyFish sets useful response headers —
x-request-idon every response,retry-afterandx-ratelimit-limiton 429s. Previously these were only accessible viaBaseLLMException.headerson error paths; on the success path they were dropped entirely.Fix: stash headers on both LiteLLM-conventional channels, matching the pattern used by Gemini / Volcengine / Manus / ChatGPT / OpenAI-responses providers.
_hidden_params["headers"]— raw dict from httpx, all keys lowercased (httpx normalizes)._hidden_params["additional_headers"]— passed throughprocess_response_headers, which prefixes anyx-litellm-*header a provider might set withllm_provider-so downstream LiteLLM code that trusts barex-litellm-*markers can't be spoofed. Provider values survive under the prefixed key for observability.Verified live:
resp._hidden_params["headers"]["x-request-id"]now populated. Covered by three new tests including a spoofing regression (test_response_headers_strips_x_litellm_spoof).2. Top-level response extras (
query,total_results,page, future fields)transform_search_responsewas building a freshSearchResponsefrom justresults, silently dropping every top-level field TinyFish's response carries beyondresults/object. Reproduced twice against production:resp.query,resp.total_results,resp.pageall absent,model_extraempty.Fix: mutate
parsed.resultsto its truncated slice and return the sameSearchResponseinstance rather than reconstructing. Every field pydantic populated duringmodel_validate— declared attributes AND__pydantic_extra__bucket — survives to the caller. Access viaresp.queryetc., or viaresp.model_extrafor enumeration.Future-proof: if LiteLLM upstream ever promotes a field from extras to declared (e.g.
SearchResponsegets a first-classtotal_resultsattribute), this code needs no change — pydantic will store the value wherever it stores it, and truncate-in-place preserves both storage buckets.Verified live against production:
query,total_results,pagenow surface. Covered bytest_top_level_extras_flow_through(real fields) andtest_top_level_future_extras_flow_through(proves the general "any envelope extra rides through" contract, which coversparameter_warningsand any future addition).3. Code cleanup
Small correctness fixes and hygiene, no behavior change for the common path:
floatin addition tostr | int | bool. Server-side rejection of a wrong-typed float now surfaces cleanly withTinyFish Search:attribution + docs link, rather than a raw pydantic union failure.Test plan
tests/test_litellm/llms/tinyfish/)tests/search_tests/test_tinyfish_search.py)x-request-idetc.) surface via both_hidden_params["headers"]and_hidden_params["additional_headers"]query,total_results,page) present on every responsemax_resultsboundaries (0, 1, 999) — client-side clamping intactBaseLLMExceptionwithTinyFish Search:prefix + docs linkcountry→locationmapping still worksNo behavior change for callers using per-result extras (already correct). Error paths unchanged. Request-side behavior unchanged for str/int/bool/dict params.