fix(speech): forward api_key to the TTS bridge and isolate response hidden params

This commit is contained in:
mateo-berri 2026-08-26 16:23:33 -07:00
parent 4d1d7b446f
commit fdeab570a1
7 changed files with 52 additions and 10 deletions

View file

@ -99,7 +99,7 @@
"limit": 0
},
"reportUnknownArgumentType": {
"limit": 44530
"limit": 44528
},
"reportUnknownLambdaType": {
"limit": 109
@ -138,9 +138,9 @@
"limit": 139
},
"reportUnusedImport": {
"limit": 545
"limit": 544
},
"reportUnusedVariable": {
"limit": 146
"limit": 145
}
}

View file

@ -8013,7 +8013,7 @@ def speech(
if max_retries is None:
max_retries = litellm.num_retries or openai.DEFAULT_MAX_RETRIES
litellm_params_dict: Final = get_litellm_params(metadata=metadata, **kwargs)
litellm_params_dict: Final = get_litellm_params(metadata=metadata, api_key=api_key or dynamic_api_key, **kwargs)
# Get provider-specific text-to-speech config and map parameters
text_to_speech_provider_config = ProviderConfigManager.get_provider_text_to_speech_config(

View file

@ -107,10 +107,17 @@ EmbeddingInput = str | list[str]
class HttpxBinaryResponseContent(_HttpxBinaryResponseContent):
_hidden_params: dict = {}
_hidden_params: dict
def __init__(self, response: httpx.Response) -> None:
super().__init__(response)
self._hidden_params = {} # mutable-ok: mutable-dict contract shared with ModelResponse logging consumers
def set_response_cost(self, response_cost: float | None) -> None:
self._hidden_params = {"response_cost": response_cost}
if response_cost is None:
self._hidden_params.pop("response_cost", None)
return
self._hidden_params["response_cost"] = response_cost
class NotGiven:

View file

@ -108,7 +108,7 @@
"limit": 3
},
"F401": {
"limit": 14
"limit": 13
},
"LOG015": {
"limit": 5
@ -171,7 +171,7 @@
"limit": 175
},
"RUF012": {
"limit": 240
"limit": 239
},
"RUF015": {
"limit": 8
@ -183,7 +183,7 @@
"limit": 4
},
"RUF059": {
"limit": 67
"limit": 66
},
"RUF100": {
"limit": 0

View file

@ -3042,6 +3042,8 @@ async def test_aspeech_gemini_bridge_keeps_proxy_metadata_for_spend_tracking(
respx_mock: respx.MockRouter, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(litellm, "disable_aiohttp_transport", True)
monkeypatch.delenv("GEMINI_API_KEY", raising=False)
monkeypatch.delenv("GOOGLE_API_KEY", raising=False)
recorder: Final = _SuccessEventRecorder()
monkeypatch.setattr(litellm, "callbacks", [recorder])
mock_route: Final = respx_mock.post(
@ -3057,6 +3059,7 @@ async def test_aspeech_gemini_bridge_keeps_proxy_metadata_for_spend_tracking(
)
assert mock_route.called
assert mock_route.calls.last.request.headers["x-goog-api-key"] == "fake-gemini-key"
speech_event: Final = await _wait_for_success_event(recorder, call_type="aspeech")
assert speech_event.spend_metadata["user_api_key"] == "hashed-virtual-key"
assert speech_event.spend_metadata["user_api_key_user_id"] == "user-1"

View file

@ -7,6 +7,7 @@ import pytest
import json
import litellm
from litellm.types.llms.openai import HttpxBinaryResponseContent
def test_generic_event():
@ -522,3 +523,34 @@ class TestOpenAIFileObjectBatchGuardrailSerialization:
page = FileListPage(object="list", data=[self._file_object()], has_more=False)
assert "litellm_batch_guardrail" not in page.model_dump(mode="json")["data"][0]
def _binary_content(payload: bytes) -> HttpxBinaryResponseContent:
import httpx
return HttpxBinaryResponseContent(httpx.Response(200, content=payload))
def test_httpx_binary_response_content_hidden_params_are_per_instance():
first = _binary_content(b"first")
second = _binary_content(b"second")
first._hidden_params["response_cost"] = 0.5
assert second._hidden_params == {}
def test_set_response_cost_none_leaves_hidden_params_empty():
binary_response = _binary_content(b"audio")
binary_response.set_response_cost(None)
assert "response_cost" not in binary_response._hidden_params
binary_response.set_response_cost(0.25)
assert binary_response._hidden_params["response_cost"] == 0.25
binary_response.set_response_cost(None)
assert "response_cost" not in binary_response._hidden_params

View file

@ -3,7 +3,7 @@
"limit": 22733
},
"LIT002": {
"limit": 26864
"limit": 26863
},
"LIT003": {
"limit": 269