diff --git a/litellm/types/utils.py b/litellm/types/utils.py index c613169111f..654ad736cde 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3366,6 +3366,7 @@ class CustomPricingLiteLLMParams(MirroredPricingParams): input_cost_per_token_above_272k_tokens_priority: float | None = None input_cost_per_token_above_272k_tokens_flex: float | None = None input_cost_per_query: float | None = None + input_cost_per_result: float | None = None input_cost_per_image: float | None = None input_cost_per_image_above_128k_tokens: float | None = None input_cost_per_audio_per_second: float | None = None diff --git a/tests/test_litellm/llms/xquik/search/test_xquik_search_transformation.py b/tests/test_litellm/llms/xquik/search/test_xquik_search_transformation.py index 1dc8e8c427f..9d55e958559 100644 --- a/tests/test_litellm/llms/xquik/search/test_xquik_search_transformation.py +++ b/tests/test_litellm/llms/xquik/search/test_xquik_search_transformation.py @@ -131,6 +131,11 @@ def test_get_complete_url_appends_endpoint_once(api_base: str | None, expected: assert _config().get_complete_url(api_base, {}) == expected +def test_get_complete_url_rejects_non_mapping_parameters() -> None: + with pytest.raises(ValueError, match="request parameters must be a mapping"): + _config().get_complete_url(None, {}, data={"_xquik_params": ["invalid"]}) + + def test_transform_request_maps_unified_parameters() -> None: params = _params( ["latest", "launch"], @@ -195,11 +200,26 @@ def test_transform_response_maps_standard_and_xquik_fields() -> None: assert response._hidden_params["headers"]["x-request-id"] == "request-1" -def test_transform_response_builds_url_and_title_for_degraded_tweet() -> None: +@pytest.mark.parametrize( + ("tweet", "expected_title", "expected_url"), + [ + ( + {"id": "123", "author": {"username": "somebody"}}, + "@somebody", + "https://x.com/somebody/status/123", + ), + ({"id": "123", "author": {"name": "Somebody"}}, "Somebody", ""), + ({"id": "123"}, "X post 123", ""), + ({}, "X post", ""), + ], +) +def test_transform_response_builds_url_and_title_for_degraded_tweet( + tweet: dict[str, object], expected_title: str, expected_url: str +) -> None: response = _config().transform_search_response( _response( { - "tweets": [{"id": "123", "author": {"username": "somebody"}}], + "tweets": [tweet], "has_next_page": False, "next_cursor": "", } @@ -207,8 +227,8 @@ def test_transform_response_builds_url_and_title_for_degraded_tweet() -> None: logging_obj=None, ) result = response.results[0] - assert result.title == "@somebody" - assert result.url == "https://x.com/somebody/status/123" + assert result.title == expected_title + assert result.url == expected_url assert result.snippet == "" assert result.date is None diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index d655eb96a02..fc18ebf26f6 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -732,6 +732,7 @@ def validate_model_cost_values(model_data, exceptions=None): "output_cost_per_second", "output_cost_per_second_1080p", "input_cost_per_query", + "input_cost_per_result", "input_cost_per_request", "input_cost_per_audio_token", "output_cost_per_audio_token", @@ -890,6 +891,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): "regional_processing_uplift_multiplier_us": {"type": "number"}, "input_cost_per_pixel": {"type": "number"}, "input_cost_per_query": {"type": "number"}, + "input_cost_per_result": {"type": "number"}, "input_cost_per_request": {"type": "number"}, "input_cost_per_second": {"type": "number"}, "input_cost_per_token": {"type": "number"}, diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts index d311bfa3cbc..d1b2e30613c 100644 --- a/ui/litellm-dashboard/src/lib/http/schema.d.ts +++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts @@ -27521,6 +27521,8 @@ export interface components { input_cost_per_pixel?: number | null; /** Input Cost Per Query */ input_cost_per_query?: number | null; + /** Input Cost Per Result */ + input_cost_per_result?: number | null; /** Input Cost Per Second */ input_cost_per_second?: number | null; /** Input Cost Per Token */ @@ -36730,6 +36732,8 @@ export interface components { input_cost_per_pixel?: number | null; /** Input Cost Per Query */ input_cost_per_query?: number | null; + /** Input Cost Per Result */ + input_cost_per_result?: number | null; /** Input Cost Per Second */ input_cost_per_second?: number | null; /** Input Cost Per Token */