@@ -247,5 +247,167 @@ def test_config_with_explicit_top_p(self):
247247 self .assertEqual (config .top_p , 0.9 )
248248
249249
250+ @pytest .mark .unit
251+ class TestACELiteLLMConfiguration (unittest .TestCase ):
252+ """Test ACELiteLLM configuration parameter passing."""
253+
254+ def _mock_response (self ):
255+ """Create mock LiteLLM response."""
256+ mock = MagicMock ()
257+ mock .choices = [
258+ MagicMock (
259+ message = MagicMock (
260+ content = '{"reasoning":"test","bullet_ids":[],"final_answer":"ok"}'
261+ )
262+ )
263+ ]
264+ mock .usage = None
265+ mock .model = "gpt-4"
266+ return mock
267+
268+ @patch ("ace.llm_providers.litellm_client.completion" )
269+ def test_api_key_passed_to_client (self , mock_completion ):
270+ """Test api_key parameter is passed to LiteLLMClient."""
271+ mock_completion .return_value = self ._mock_response ()
272+
273+ from ace .integrations import ACELiteLLM
274+
275+ agent = ACELiteLLM (model = "gpt-4" , api_key = "test-key-123" )
276+ self .assertEqual (agent .llm .config .api_key , "test-key-123" )
277+
278+ @patch ("ace.llm_providers.litellm_client.completion" )
279+ def test_base_url_maps_to_api_base (self , mock_completion ):
280+ """Test base_url maps to api_base in config."""
281+ mock_completion .return_value = self ._mock_response ()
282+
283+ from ace .integrations import ACELiteLLM
284+
285+ agent = ACELiteLLM (model = "openai/local" , base_url = "http://localhost:1234/v1" )
286+ self .assertEqual (agent .llm .config .api_base , "http://localhost:1234/v1" )
287+
288+ @patch ("ace.llm_providers.litellm_client.completion" )
289+ def test_extra_headers_passed (self , mock_completion ):
290+ """Test extra_headers parameter is passed through."""
291+ mock_completion .return_value = self ._mock_response ()
292+
293+ from ace .integrations import ACELiteLLM
294+
295+ headers = {"X-Custom" : "value" , "X-Tenant-ID" : "team-alpha" }
296+ agent = ACELiteLLM (model = "gpt-4" , extra_headers = headers )
297+ self .assertEqual (agent .llm .config .extra_headers , headers )
298+
299+ @patch ("ace.llm_providers.litellm_client.completion" )
300+ def test_ssl_verify_false (self , mock_completion ):
301+ """Test ssl_verify=False is passed through."""
302+ mock_completion .return_value = self ._mock_response ()
303+
304+ from ace .integrations import ACELiteLLM
305+
306+ agent = ACELiteLLM (model = "gpt-4" , ssl_verify = False )
307+ self .assertEqual (agent .llm .config .ssl_verify , False )
308+
309+ @patch ("ace.llm_providers.litellm_client.completion" )
310+ def test_ssl_verify_path (self , mock_completion ):
311+ """Test ssl_verify with CA bundle path."""
312+ mock_completion .return_value = self ._mock_response ()
313+
314+ from ace .integrations import ACELiteLLM
315+
316+ agent = ACELiteLLM (model = "gpt-4" , ssl_verify = "/path/to/ca.pem" )
317+ self .assertEqual (agent .llm .config .ssl_verify , "/path/to/ca.pem" )
318+
319+ @patch ("ace.llm_providers.litellm_client.completion" )
320+ def test_kwargs_passed_through (self , mock_completion ):
321+ """Test **llm_kwargs are passed to LiteLLMClient."""
322+ mock_completion .return_value = self ._mock_response ()
323+
324+ from ace .integrations import ACELiteLLM
325+
326+ agent = ACELiteLLM (model = "gpt-4" , timeout = 120 , max_retries = 5 )
327+ self .assertEqual (agent .llm .config .timeout , 120 )
328+ self .assertEqual (agent .llm .config .max_retries , 5 )
329+
330+ @patch ("ace.llm_providers.litellm_client.completion" )
331+ def test_backward_compatibility (self , mock_completion ):
332+ """Test that existing code without new params still works."""
333+ mock_completion .return_value = self ._mock_response ()
334+
335+ from ace .integrations import ACELiteLLM
336+
337+ agent = ACELiteLLM (model = "gpt-4o-mini" , max_tokens = 1024 , temperature = 0.5 )
338+ self .assertEqual (agent .model , "gpt-4o-mini" )
339+ self .assertEqual (agent .llm .config .max_tokens , 1024 )
340+ self .assertEqual (agent .llm .config .temperature , 0.5 )
341+ # New params should be None by default (api_key may be picked up from env vars)
342+ self .assertIsNone (agent .llm .config .extra_headers )
343+ self .assertIsNone (agent .llm .config .ssl_verify )
344+
345+
346+ @pytest .mark .unit
347+ class TestLiteLLMClientDirectConfig (unittest .TestCase ):
348+ """Test LiteLLMClient direct configuration."""
349+
350+ def _mock_response (self ):
351+ """Create mock LiteLLM response."""
352+ mock = MagicMock ()
353+ mock .choices = [MagicMock (message = MagicMock (content = "Test response" ))]
354+ mock .usage = None
355+ mock .model = "gpt-4"
356+ return mock
357+
358+ @patch ("ace.llm_providers.litellm_client.completion" )
359+ def test_extra_headers_in_call_params (self , mock_completion ):
360+ """Test extra_headers is included in LiteLLM call_params."""
361+ mock_completion .return_value = self ._mock_response ()
362+
363+ from ace .llm_providers import LiteLLMClient
364+
365+ headers = {"X-Custom" : "value" }
366+ client = LiteLLMClient (model = "gpt-4" , extra_headers = headers )
367+ client .complete ("Test prompt" )
368+
369+ call_kwargs = mock_completion .call_args [1 ]
370+ self .assertEqual (call_kwargs ["extra_headers" ], headers )
371+
372+ @patch ("ace.llm_providers.litellm_client.completion" )
373+ def test_ssl_verify_false_in_call_params (self , mock_completion ):
374+ """Test ssl_verify=False is included in LiteLLM call_params."""
375+ mock_completion .return_value = self ._mock_response ()
376+
377+ from ace .llm_providers import LiteLLMClient
378+
379+ client = LiteLLMClient (model = "gpt-4" , ssl_verify = False )
380+ client .complete ("Test prompt" )
381+
382+ call_kwargs = mock_completion .call_args [1 ]
383+ self .assertEqual (call_kwargs ["ssl_verify" ], False )
384+
385+ @patch ("ace.llm_providers.litellm_client.completion" )
386+ def test_ssl_verify_path_in_call_params (self , mock_completion ):
387+ """Test ssl_verify path is included in LiteLLM call_params."""
388+ mock_completion .return_value = self ._mock_response ()
389+
390+ from ace .llm_providers import LiteLLMClient
391+
392+ client = LiteLLMClient (model = "gpt-4" , ssl_verify = "/path/to/ca.pem" )
393+ client .complete ("Test prompt" )
394+
395+ call_kwargs = mock_completion .call_args [1 ]
396+ self .assertEqual (call_kwargs ["ssl_verify" ], "/path/to/ca.pem" )
397+
398+ @patch ("ace.llm_providers.litellm_client.completion" )
399+ def test_ssl_verify_none_not_in_call_params (self , mock_completion ):
400+ """Test ssl_verify=None is NOT included in call_params."""
401+ mock_completion .return_value = self ._mock_response ()
402+
403+ from ace .llm_providers import LiteLLMClient
404+
405+ client = LiteLLMClient (model = "gpt-4" ) # ssl_verify defaults to None
406+ client .complete ("Test prompt" )
407+
408+ call_kwargs = mock_completion .call_args [1 ]
409+ self .assertNotIn ("ssl_verify" , call_kwargs )
410+
411+
250412if __name__ == "__main__" :
251413 unittest .main ()
0 commit comments