Update provider matching so github/<model> aliases can resolve capabilities from existing upstream model metadata, including OpenAI and Anthropic entries. Add regression tests for known github aliases and unknown-model fallback behavior.
The adapter was injecting `summary: "detailed"` into the reasoning config
when routing Anthropic thinking requests to OpenAI's Responses API.
Per the OpenAI spec, reasoning.summary is opt-in — it should not be
added unless the user explicitly requests it.
Three test isolation issues fixed:
1. test_mcp_debug.py: Replace deprecated asyncio.get_event_loop().run_until_complete()
with asyncio.run() in TestWrapSendWithDebugHeaders. In Python 3.10+,
get_event_loop() raises RuntimeError when no event loop is set in the
current thread, causing test_injects_headers and test_body_messages_unchanged
to fail in isolation.
2. test_mcp_server_manager.py: After _reload_mcp_manager_module() creates a new
global_mcp_server_manager instance, server.py still holds a stale reference
to the old instance. Tests in test_mcp_server.py that populate the new
manager's registry and then call server.py functions (e.g. _get_tools_from_mcp_servers)
get empty results because server.py reads from the old manager. Fix: update
server.py's module-level reference after each reload.
3. test_litellm_pre_call_utils.py: test_add_litellm_metadata_from_request_headers
sets litellm.callbacks without restoring it afterward. Add cleanup to restore
original callbacks after the test to prevent state leaking to subsequent tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four finally blocks in test_internal_user_endpoints.py and one in
test_ui_sso.py used the pattern:
if original_default_params is not None:
litellm.default_internal_user_params = original_default_params
else:
delattr(litellm, "default_internal_user_params")
Since the attribute is defined in litellm/__init__.py with a default of
None, `getattr(litellm, "default_internal_user_params", None)` returns
None. The else branch then calls delattr(), permanently removing the
attribute from the module for the rest of the process.
Subsequent tests in the same pytest-xdist worker (e.g.
test_add_new_member_* in test_management_helpers_utils.py) then fail
with: AttributeError: module 'litellm' has no attribute
'default_internal_user_params'
Fix: replace all five flawed finally blocks with a simple assignment:
litellm.default_internal_user_params = original_default_params
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LogRecord objects do not have a .message attribute by default — it is
only populated after the record has been formatted by a Formatter.
The correct way to retrieve the formatted log message is getMessage().
This fixes AttributeError: 'LogRecord' object has no attribute 'message'
in test_cost_calculation_uses_debug_level and
test_batch_cost_calculation_uses_debug_level.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The file had two unresolved git merge conflict markers from a merge of
litellm_oss_staging_02_17_2026 into main, causing a SyntaxError when
pytest tried to collect the test module.
Kept the instance-level mocking approach (from litellm_oss_staging) for
test_get_complete_url and test_validate_environment, which is consistent
with the rest of the file and avoids class-reference issues caused by
importlib.reload(litellm) in conftest.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The model_prices_and_context_window_backup.json file has 'inference_geo'
fields (e.g. on 'us/claude-sonnet-4-6') for geo-prefixed Anthropic models
used in cost calculation, but the JSON schema validator in test_utils.py
did not include 'inference_geo' as an allowed property.
This caused test_aaamodel_prices_and_context_window_json_is_valid to fail
with: Additional properties are not allowed ('inference_geo' was unexpected)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The test was using setattr() to set module-level attributes (including
proxy_logging_obj = MagicMock()) on the real litellm.proxy.proxy_server
module, but the finally block only had `pass` — no cleanup.
This left proxy_logging_obj as a MagicMock in subsequent tests running
in the same pytest-xdist worker, causing TypeError when log_db_metrics
decorator called asyncio.create_task(proxy_logging_obj.service_logging_obj
.async_service_success_hook(...)) — a MagicMock is not a coroutine.
Fix: save original attribute values before the test and restore them in
the finally block to ensure test isolation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The implementation correctly preserves tool_call order: existing results first
(call_1), then dummy results for missing ones (call_2). The test was asserting
the reverse order with incorrect comments. Fix the assertions to match the
actual correct behavior.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three test failures caused by the real langfuse SDK import being triggered
at test time:
1. test_langfuse_prompt_management.py: Both tests create LangfusePromptManagement()
which calls `import langfuse`. Since earlier TestLangfuseUsageDetails tests
remove sys.modules["langfuse"] via patch.dict teardown, the real langfuse
import runs and fails on Python 3.14 (pydantic v1 incompatibility).
Fix: add setup_method/teardown_method to mock sys.modules["langfuse"].
2. test_langfuse.py::test_max_langfuse_clients_limit: Same root cause — creates
LangFuseLogger() without mocking sys.modules["langfuse"].
Fix: wrap test body with patch.dict("sys.modules", {"langfuse": mock}).
3. test_langfuse_otel.py::test_extract_langfuse_metadata_with_header_enrichment:
Replaces sys.modules["litellm.integrations.langfuse.langfuse"] with a stub
without restoring it, causing patch() in later tests to target the stub
instead of the real module.
Fix: use monkeypatch.setitem() which auto-restores after the test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
test_role_mappings_override_default_internal_user_params was calling
delattr(litellm, 'default_internal_user_params') in its finally block
when the original value was None. This removes the attribute entirely from
the module, causing subsequent tests in the same xdist worker to get
AttributeError when accessing litellm.default_internal_user_params (because
litellm.__getattr__ has no handler for this name).
Fix: always restore the attribute by assignment (litellm.default_internal_user_params = original_default_params)
rather than deleting it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add routing prefixes bedrock/nova/<ARN> and bedrock/nova-2/<ARN> so
LiteLLM can identify the base model family for custom/imported Nova
models and enable the correct supported params (tools, web_search,
reasoning_effort).
Changes:
- Route nova/ and nova-2/ prefixed models to converse API
- Strip spec prefix before sending ARN to Bedrock
- Return sentinel base models (amazon.nova-custom, amazon.nova-2-custom)
so downstream Nova checks work
- Recognize nova-2/ prefix in _is_nova_2_model() for reasoning support
- Handle nova/nova-2 in get_bedrock_model_id() for proper ARN encoding
- Add unit tests for all new behavior
- /spend/calculate: wrap response in proper OpenAPI 3.x content structure
- /credentials: split stacked route decorators into separate handlers to
eliminate path parameter conflict between by_name and by_model routes
The retry loop in async_function_with_retries catches all exceptions
blindly and continues retrying even for non-retryable errors like 400
ContextWindowExceeded or 404 NotFoundError. This causes the original
retryable error to be raised instead of the actual non-retryable one.
Changes:
- Update original_exception to latest error on each retry attempt
- Add should_retry_this_error() check inside the retry loop to break
out immediately on non-retryable errors
- Respect _retry_policy_applies precedence
Fixes#21343
- Use custom_endpoint=False so Databricks SDK auth fallback works
(custom_endpoint=True was blocking it). The api_base returned by
databricks_validate_environment is discarded since get_complete_url
builds the URL separately.
- Remove unused verbose_logger import
- Remove unused json import in tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Databricks supports the Responses API natively for GPT models, but litellm
was falling back to the completion transformation handler which converts
responses requests to chat completion calls, losing response schema enforcement.
This adds DatabricksResponsesAPIConfig that passes responses API requests
directly to Databricks' /responses endpoint for GPT models, while non-GPT
models (Claude, Llama, etc.) continue using the completion transformation path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>