These jobs run on medium (2 CPU) but weren't using pytest-xdist,
leaving the second CPU idle. Added pytest-xdist dep and -n 2 to:
- auth_ui_unit_tests (~33 tests)
- litellm_router_unit_testing (~191 tests)
- mcp_testing (~112 tests)
- llm_responses_api_testing (~80 tests)
- search_testing (~53 tests)
- batches_testing (~45 tests)
- litellm_utils_testing (~205 tests)
- pass_through_unit_testing (~102 tests)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test asserts that a ttl=0 cached entry expires immediately, so the
second call should not return cached content. Both calls used the same
mock_response text, making the content != assertion always fail. Use
different mock_response values so a cache hit is distinguishable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use ubuntu-2204:2024.04.1 which ships with a recent Docker, eliminating
the 1-minute `curl get.docker.com | sh` upgrade step
- Switch image save/load from gzip to zstd -1 -T0 for ~3-5x faster
compression/decompression, saving ~30s on save and on each downstream load
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The isolate_litellm_state conftest fixture saved/restored litellm.callbacks
but never cleared it before each test, unlike the other callback lists. It
also didn't handle litellm.model_fallbacks. Leaked callbacks and fallback
config caused mocked tests to route through Router/fallback paths, hitting
real APIs with mock keys.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8 jobs had -n workers set higher than available vCPUs, causing context
switch overhead and degraded performance. Aligned -n to match resource_class:
- medium (2 CPU): enterprise -n 8→2, image_gen/logging/guardrails -n 4→2
- large (4 CPU): proxy_part1/llms/core/integrations -n 8→4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The check_batch_cost_job runs on a 10-40s interval and sets
batch_processed=True after sending the S3 callback. 30s (6×5s) wasn't
enough margin; 50s (10×5s) covers the worst-case poll interval plus
processing time, while still being 3.6x faster than the original 180s.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 4 integration tests were flaky in CI because the AsyncHTTPHandler.post
mock was bypassed when aiohttp transport is used. Mock at the higher
BaseLLMHTTPHandler.async_response_api_handler level instead, which
bypasses the HTTP layer entirely while still exercising router deployment
selection, pre-call checks, and response post-processing (item ID rewriting).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ui_build (medium → medium+) is on the critical path blocking 3 downstream
jobs. ui_unit_tests (medium+ → large, maxForks 3 → 5) targets ~7 min from ~11.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous approach populated _hidden_params to trigger the managed files
hook, but the hook also re-encodes response.id (batch ID), causing double-
encoding when the DB already stores unified IDs. Instead, resolve raw
output_file_id/error_file_id to unified IDs via a direct DB lookup (same
pattern as resolve_input_file_id_to_unified), which avoids the hook entirely.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace real OpenAI/Anthropic/Bedrock API calls with mock_response in
~20 cache tests to eliminate network-dependent flakiness
- Remove -x (fail-fast) from caching_unit_tests so all failures are reported
- Add parallelism: 2 with circleci tests run --split-by=timings
- Improve pip dependency cache key (v2-caching-deps) with fallback key
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests failed intermittently in CI (-n 8 workers) because cached
AsyncHTTPHandler instances from other tests bypassed the class-level
mock on AsyncHTTPHandler.post, causing real requests to OpenAI with
mock API keys. Router retries (default 2) masked the root cause.
- Add autouse fixture to flush litellm.in_memory_llm_clients_cache
before/after each test so mocks always apply to fresh clients
- Set num_retries=0 on all Router instances to surface mock failures
immediately instead of silently retrying
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a completed batch is served from the DB cache, _hidden_params was empty,
causing the managed files hook to skip output_file_id translation from raw
provider IDs to unified IDs. This fix populates unified_batch_id and model_id
on the early-return path, with a guard against double-encoding when the DB
already stores unified IDs.
Also reduces file deletion retry delay (20s→5s), reruns (5→2), and CI timeout
(30m→15m) to cut worst-case runtime from ~16min to ~4min.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4 mapped test jobs (llms, core, core_utils, integrations) were running on
xlarge with -n 16 workers on 8 vCPUs, causing unnecessary context switching.
Downsized to large with worker counts matched to available cores.
MCPs job (2 test files) downsized from large to medium.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Llama-3.2-3B-Instruct-Turbo is no longer available as a serverless model
on Together AI. Switch to Llama-3.3-70B-Instruct-Turbo which is still
available and has cost data in the model prices map.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add num_retries=0 to the async acompletion call to prevent retries
when the mock returns invalid response data. The test only validates
request payload format, not retry behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_router_context_window_check_pre_call_check_out_group: replace deprecated
gpt-3.5-turbo-1106 (removed from model_cost, returns max_input_tokens=0) with
gpt-4.1-mini + mock_response
- test_async_fallbacks: filter "Task was destroyed but it is pending" messages
that leak from parallel test execution in CI
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test_post_call_rule_streaming in test_rules.py sets
litellm.post_call_rules but never cleans up. Since
pytest_collection_modifyitems sorts tests by name across modules,
the leaked rule causes failures in test_streaming.py,
test_register_model.py, and test_sagemaker.py.
Add pre_call_rules and post_call_rules to the isolate_litellm_state
fixture's save/restore and clear lists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test relied on a global side effect (customLogger initialization in
litellm_logging.py) from prior tests' success callbacks to dispatch
failure callbacks. When tests run in parallel by file, no prior test
initializes customLogger, so the Router's deployment_callback_on_failure
was never invoked and cooldowns were never set.
Rewrite to directly call deployment_callback_on_failure with a proper
RateLimitError containing retry-after headers, testing the cooldown
logic without depending on the logging callback chain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_hanging_request_azure: mock httpx.AsyncClient.send to simulate slow
response instead of racing real network latency against a 10ms timeout.
The old non-existent deployment (gpt-4o-new-test) returned 404 faster
than the timeout, causing NotFoundError instead of APITimeoutError.
- test_completion_together_ai_llama: update model from deprecated
Meta-Llama-3.1-8B-Instruct-Turbo to Llama-3.2-3B-Instruct-Turbo
(Together AI removed the old model from serverless).
- conftest.py: clear litellm.callbacks list before each test to prevent
proxy hooks (SkillsInjectionHook, VirtualKeyModelMaxBudgetLimiter)
from leaking across tests via Router initialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test was failing because it depended on real API calls to deprecated
models. Now uses mock_response to validate streaming through the router
without external dependencies.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_async_fallbacks_streaming: replace deprecated gpt-3.5-turbo fallback
with gpt-4o-mini, fix use of module-level kwargs variable
- test_ausage_based_routing_fallbacks: remove Redis dependency to prevent
shared state across parallel CI containers (test already uses mock_response)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Router testing: add CircleCI parallelism=4 with timing-based test splitting
- Guardrails testing: add pytest-xdist -n 4, suppress DEBUG logs with LITELLM_LOG=WARNING
- Rewrite conftest.py in both test dirs for xdist compatibility (save/restore pattern)
- Fix module-level Router instances in test_router_fallback_handlers, test_router_custom_routing, test_acooldowns_router
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
build_and_test, helm_chart_testing, and test_bad_database_url each rebuilt
Dockerfile.database from scratch (~5-10 min each) despite build_docker_database_image
already building and persisting it to workspace. Now all three load the
pre-built image via workspace, eliminating 3 redundant Docker builds.
Also removes orphaned test_nonroot_image job definition (not referenced in workflow).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add restore_cache/save_cache for .next/cache to eliminate the
"No build cache found" warning and speed up subsequent Next.js builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test_bad_database_url only validates DB error handling — it doesn't need
the UI. Dockerfile.non_root does a full npm install + next build which is
unnecessary overhead for this test. Dockerfile.database skips the UI build
(build_admin_ui.sh is a no-op for OSS) making the Docker build much faster.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch ui_build from machine VM to docker executor (cimg/node:20.19)
- Add npm cache (restore_cache/save_cache) keyed on package-lock.json
- Use npm ci instead of rm -rf node_modules && npm install
- Gate ui_unit_tests behind ui_build (don't run tests if build fails)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ui_unit_tests was gated behind ui_build but not required for publishing.
This ensures UI unit tests must pass before PyPI publish.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch from machine VM to docker executor (cimg/node:20.19)
- Add npm cache with restore_cache/save_cache
- Use npm ci instead of npm install (stop deleting node_modules/package-lock.json)
- Enable parallel test execution with --pool forks --maxForks=3
- Bump resource_class to medium+ for 3 vCPUs
- Remove unnecessary requires: ui_build dependency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change no_output_timeout from 120m/60m to 15m across all test jobs
- Fix multi-line YAML formatting for no_output_timeout entries
- Reduce Playwright per-test timeout from 4min to 3min
- Add 15s actionTimeout and 30s navigationTimeout to Playwright config
Hanging tests now fail in 15min instead of 2hrs, cutting wasted CI time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
21 jobs were using xlarge (8 vCPU, 16GB) despite running trivial or
low-parallelism workloads. Downgrades 6 trivial container-check/UI jobs
to medium (2 vCPU) and 15 lightweight test jobs to large (4 vCPU).
Only the 5 high-parallelism mapped test jobs (-n 8/16) remain on xlarge.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add sagemaker_nova provider for Nova models on SageMaker
Add support for custom/fine-tuned Amazon Nova models (Nova Micro, Nova Lite,
Nova 2 Lite) deployed on SageMaker Inference real-time endpoints.
Nova uses OpenAI-compatible request/response format with additional
Nova-specific parameters (top_k, reasoning_effort, allowed_token_ids,
truncate_prompt_tokens) and requires stream:true in the request body.
Nova endpoints also reject 'model' in the request body.
Changes:
- New provider: sagemaker_nova/<endpoint-name>
- SagemakerNovaConfig inherits from SagemakerChatConfig
- Override transform_request to strip 'model' from request body
- Override supports_stream_param_in_request_body (True for Nova)
- Extend get_supported_openai_params with Nova-specific params
- Refactored SagemakerChatConfig to use custom_llm_provider param
instead of hardcoded strings (backwards-compatible)
- Consolidated main.py routing for sagemaker_chat and sagemaker_nova
- 22 unit tests + 9 integration tests (skip-gated)
- Documentation with SDK, streaming, multimodal, and proxy examples
- All tests verified against live SageMaker Nova endpoint
* fix: move integration tests to tests/local_testing/ per test directory policy
* fix: remove unused module-level SagemakerNovaConfig instance
The sagemaker_nova_config singleton was never imported or used — the
ProviderConfigManager creates its own instance via the lambda registered
in utils.py. Removing this leftover boilerplate.
---------
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
* docs: add Claude Code skills page for litellm-skills
* docs: move skills page to new 'Manage with AI Agents' section
* docs: simplify install to one-liner, rename to LiteLLM Skills
- Reduce RENDER_BATCH_SIZE from 5 to 3 for more frequent chart updates
- Add LoadingOutlined spinner at the start of all fetching Alert banners
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace subtle loading text with antd Alert banners that clearly communicate
pagination status, and batch state flushes to reduce chart re-renders.
- Replace inline loading text with warning Alert banners showing progress,
"open a new tab" link with ExportOutlined icon, and primary Stop button
- Batch setData calls every 5 pages instead of per-page to cut re-renders ~80%
- Reduce fetch delay from 500ms to 300ms for faster data loading
- Add "Charts will update periodically" messaging to set expectations
- Fix pre-existing TS error: Button icon prop was using render function instead of ReactNode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Map provider finish_reason "content_filtered" to the OpenAI-compatible "content_filter" and extend core_helpers tests to cover this case.
Made-with: Cursor
* fix: restore offline tiktoken cache for non-root envs
Made-with: Cursor
* chore: mkdir for custom tiktoken cache dir
Made-with: Cursor
* test: patch tiktoken.get_encoding in custom-dir test to avoid network
Made-with: Cursor
* test: clear CUSTOM_TIKTOKEN_CACHE_DIR in helper for test isolation
Made-with: Cursor
* test: restore default_encoding module state after custom-dir test
Made-with: Cursor
1. Replace ...args spread in useEffect deps with JSON.stringify(args) key
to prevent infinite re-renders when callers pass unstable array references.
2. Add missing agentCancelled partial-data message in EntityUsage so the
outer condition no longer renders an empty div.
3. Store setTimeout ID in a ref and clearTimeout on cleanup/cancel to avoid
orphaned timers under rapid re-renders.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test's partial vi.mock of @/components/networking was missing the daily
activity call exports now imported by EntityUsage via ENTITY_FETCH_FNS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(bedrock): respect s3_region_name for batch file uploads (#23569)
* fix(bedrock): respect s3_region_name for batch file uploads (GovCloud fix)
* fix: s3_region_name always wins over aws_region_name for S3 signing (Greptile feedback)
* fix: _filter_headers_for_aws_signature - Bedrock KB (#23571)
* fix: _filter_headers_for_aws_signature
* fix: filter None header values in all post-signing re-merge paths
Addresses Greptile feedback: None-valued headers were being filtered
during SigV4 signing but re-merged back into the final headers dict
afterward, which would cause downstream HTTP client failures.
Made-with: Cursor
* feat(router): tag_regex routing — route by User-Agent regex without per-developer tag config (#23594)
* feat(router): add tag_regex support for header-based routing
Adds a new `tag_regex` field to litellm_params that lets operators route
requests based on regex patterns matched against request headers — primarily
User-Agent — without requiring per-developer tag configuration.
Use case: route all Claude Code traffic (User-Agent: claude-code/x.y.z) to
a dedicated deployment by setting:
tag_regex:
- "^User-Agent: claude-code\\/"
in the deployment's litellm_params. Works alongside existing `tags` routing;
exact tag match takes precedence over regex match. Unmatched requests fall
through to deployments tagged `default`.
The matched deployment, pattern, and user_agent are recorded in
`metadata["tag_routing"]` so they flow through to SpendLogs automatically.
* fix(tag_regex): address backwards-compat, metadata overwrite, and warning noise
Three issues from code review:
1. Backwards-compat: `has_tag_filter` was widened to activate on any non-empty
User-Agent, which would raise ValueError for existing deployments using plain
tags without a `default` fallback. Fix: only activate header-based regex
filtering when at least one candidate deployment has `tag_regex` configured.
2. Metadata overwrite: `metadata["tag_routing"]` was overwritten for every
matching deployment in the loop, leaving inaccurate provenance when multiple
deployments match. Fix: write only for the first match.
3. Warning noise: an invalid regex pattern logged one warning per header string
rather than once per pattern. Fix: compile first (catching re.error once),
then iterate over header strings.
Also adds two new tests covering these cases, and adds docs page for
tag_regex routing with a Claude Code walk-through.
* refactor(tag_regex): remove unnecessary _healthy_list copy
* docs: merge tag_regex section into tag_routing.md, remove standalone page
- Add ## Regex-based tag routing (tag_regex) section to existing
tag_routing.md instead of a separate page
- Remove tag_regex_routing.md standalone doc (odd UX to have a separate
page for a sub-feature)
- Remove proxy/tag_regex_routing from sidebars.js
- Add match_any=False debug warning in tag_based_routing.py when regex
routing fires under strict mode (regex always uses OR semantics)
* fix(tag_regex): address greptile review - security docs, strict-mode enforcement, validation order
- Strengthen security note in tag_routing.md: explicitly state User-Agent
is client-supplied and can be set to any value; frame tag_regex as a
traffic classification hint, not an access-control mechanism
- Move tag_regex startup validation before _add_deployment() so an invalid
pattern never leaves partial router state
- Enforce match_any=False strict-tag policy: when a deployment has both
tags and tag_regex and the strict tag check fails, skip the regex fallback
rather than silently bypassing the operator's intent
- Extract per-deployment match logic into _match_deployment() helper to
keep get_deployments_for_tag() readable
- Add two new tests: strict-mode blocks regex fallback, regex-only
deployment still matches under match_any=False
* fix(ci): apply Black formatting to 14 files and stabilize flaky caplog tests
- Run Black formatter on 14 files that were failing the lint check
- Replace caplog-based assertions in TestAliasConflicts with
unittest.mock.patch on verbose_logger.warning for xdist compatibility
- The caplog fixture can produce empty text in pytest-xdist workers
in certain CI environments, causing flaky test failures
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>