Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
- Add Complexity Router section to auto_routing.md
- Include comparison table with semantic auto router
- Add Python SDK and Proxy Server configuration examples
- Document all configuration options (tier boundaries, token thresholds, dimension weights)
- Explain how complexity scoring works
- Use word boundary matching for short keywords (<5 chars) to avoid
false positives (e.g., 'api' matching 'capital', 'git' matching 'digital')
- Remove 'ok' from simple keywords (too many false positives)
- Add tests for keyword false positive prevention
- Fix test expectations for edge cases (empty string content, list content)
Addresses: 2/5 Greptile score feedback on PR #21789
Fixes 5 issues flagged in code review:
1. **Mutable singleton mutation bug** - Now always creates a new
ComplexityRouterConfig instance instead of reusing DEFAULT_COMPLEXITY_CONFIG
singleton, preventing cross-instance config pollution.
2. **Substring matching false positives** - Added word boundaries (spaces)
to short keywords like 'ok', 'try', 'api', 'git', 'node', 'java', 'vue'
to prevent matching within longer words (e.g., 'capital' matching 'api').
3. **Redundant message extraction** - Simplified to single reverse loop that
extracts both last user message and last system prompt efficiently.
4. **Unused imports** - Removed unused DEFAULT_CREATIVE_KEYWORDS and
DEFAULT_MULTI_STEP_PATTERNS imports.
5. **Missing async_pre_routing_hook tests** - Added comprehensive tests for:
- Multi-turn conversations
- List-type content handling
- No user message case
- Empty string content
- Message preservation
- Singleton mutation prevention
The _is_auto_router_deployment() was matching all auto_router/* models,
causing complexity_router to fail initialization. Now it explicitly
excludes auto_router/complexity_router which has its own handler.
Adds a new rule-based routing strategy that classifies requests by complexity
and routes them to appropriate models - without any external API calls.
- Weighted scoring across 7 dimensions: token count, code presence, reasoning
markers, technical terms, simple indicators, multi-step patterns, questions
- Maps to 4 tiers: SIMPLE, MEDIUM, COMPLEX, REASONING
- Each tier configurable to a different model
- Zero API calls, <1ms latency
- Inspired by ClawRouter
```yaml
model_list:
- model_name: smart_router
litellm_params:
model: auto_router/complexity_router
complexity_router_config:
tiers:
SIMPLE: gemini-2.0-flash
MEDIUM: gpt-4o-mini
COMPLEX: claude-sonnet-4
REASONING: claude-opus-4
```
- Cost optimization: route simple queries to cheaper models
- Quality optimization: route complex queries to capable models
- Zero configuration: works out of the box with sensible defaults
Adds a new rule-based routing strategy that classifies requests by complexity
and routes them to appropriate models - without any external API calls.
## Features
- Weighted scoring across 7 dimensions: token count, code presence, reasoning
markers, technical terms, simple indicators, multi-step patterns, questions
- Maps to 4 tiers: SIMPLE, MEDIUM, COMPLEX, REASONING
- Each tier configurable to a different model
- Zero API calls, <1ms latency
- Inspired by ClawRouter
## Configuration
```yaml
model_list:
- model_name: smart_router
litellm_params:
model: auto_router/complexity_router
complexity_router_config:
tiers:
SIMPLE: gemini-2.0-flash
MEDIUM: gpt-4o-mini
COMPLEX: claude-sonnet-4
REASONING: claude-opus-4
```
## Use Cases
- Cost optimization: route simple queries to cheaper models
- Quality optimization: route complex queries to capable models
- Zero configuration: works out of the box with sensible defaults
* fix(tests): isolate flaky files endpoint tests from global proxy state
* test(secret_managers): add mocked unit test for write/read JSON secret cycle
* fix(security): fix CVE-2025-69873 and CVE-2026-26996 in docs dependencies
Use npm overrides to pin patched versions:
- ajv@6.12.6 → 6.14.0 (fixes ReDoS CVE-2025-69873)
- ajv@8.17.1 → 8.18.0 (fixes ReDoS CVE-2025-69873)
- minimatch@3.1.2 → 10.2.1 (fixes DoS CVE-2026-26996)
serve-handler only calls minimatch(path, pattern) so the 3.x→10.x
upgrade is safe.
* fix(ruff): add missing Set and Dict imports to fix F821 errors
* fix(security): scope ajv overrides to avoid top-level version conflict
Replacing global 'ajv: 8.18.0' override with scoped 'schema-utils@4'
override. The global override conflicted with the nested file-loader/
null-loader/url-loader overrides, causing npm to install ajv@6 at the
top level where ajv-keywords@5.x requires ajv@8 (ajv/dist/compile/codegen).
Now:
- schema-utils@3 + loaders → ajv@6.14.0 (safe minor bump)
- schema-utils@4 → ajv@8.18.0 (safe minor bump)
- top-level ajv unmodified (stays at 8.x for ajv-keywords@5)
* fix(security): allowlist minimatch and tar CVEs from nodejs_wheel, bump tar override to >=7.5.8
* fix(ruff): add missing Set and Dict imports to fix F821 errors
* fix(ci): add semantic_router dep to guardrails_testing job
The test_build_routes_combined_templates test calls build_routes() which
imports from semantic_router, but the guardrails_testing CI job didn't
install it.
* fix(security): fix CVE-2025-69873 and CVE-2026-26996 in docs dependencies
Use npm overrides to pin patched versions:
- ajv@6.12.6 → 6.14.0 (fixes ReDoS CVE-2025-69873)
- ajv@8.17.1 → 8.18.0 (fixes ReDoS CVE-2025-69873)
- minimatch@3.1.2 → 10.2.1 (fixes DoS CVE-2026-26996)
serve-handler only calls minimatch(path, pattern) so the 3.x→10.x
upgrade is safe.
* fix(ruff): add missing Set and Dict imports to fix F821 errors
* fix(security): scope ajv overrides to avoid top-level version conflict
Replacing global 'ajv: 8.18.0' override with scoped 'schema-utils@4'
override. The global override conflicted with the nested file-loader/
null-loader/url-loader overrides, causing npm to install ajv@6 at the
top level where ajv-keywords@5.x requires ajv@8 (ajv/dist/compile/codegen).
Now:
- schema-utils@3 + loaders → ajv@6.14.0 (safe minor bump)
- schema-utils@4 → ajv@8.18.0 (safe minor bump)
- top-level ajv unmodified (stays at 8.x for ajv-keywords@5)
* fix(tests): read CI_CD_DEFAULT_ANTHROPIC_MODEL env var in bedrock KB tests
* fix(tests): read CI_CD_DEFAULT_ANTHROPIC_MODEL env var in test_router
* fix(tests): read CI_CD_DEFAULT_ANTHROPIC_MODEL env var in test_router_retries
* fix(tests): read CI_CD_DEFAULT_ANTHROPIC_MODEL env var in test_router_timeout
SpendLogsMetadata added new fields (user_api_key, status, error_information,
etc.) that weren't in the expected spend_logs_payload.json fixture, causing
test_async_gcs_pub_sub_v1 to fail.
* feat(ui): add forward_client_headers_to_llm_api toggle to general settings
* feat(ui): add forward_client_headers_to_llm_api toggle to UI Settings tab
- Add toggle to UISettings.tsx frontend (switch + label + description)
- Add field to UISettings model and ALLOWED_UI_SETTINGS_FIELDS
- Sync setting to general_settings on get/update so proxy picks it up at runtime
---------
Co-authored-by: shin-bot-litellm <shin-bot-litellm@users.noreply.github.com>
* fix: reset db_health_cache in source module to prevent stale cache hits
The test was reassigning db_health_cache via `global` in the test module,
which doesn't affect the _health_endpoints module's variable. When a prior
test set the cache to "connected" within 2 minutes, _db_health_readiness_check
returned early without calling health_check(), causing assert_called_once to fail.
Also use PrismaError with a connection message so it's properly recognized
as a connection error by PrismaDBExceptionHandler.is_database_connection_error.
* fix: replace asyncio.sleep with polling loop in spend logs tests
The GLOBAL_LOGGING_WORKER processes callbacks via an async queue, so
asyncio.sleep(1) is a race condition - under CI load the worker may not
have processed the queued task within 1 second. Replace with a polling
helper that waits up to 10 seconds for the mock to be called.
Also add metadata.attempted_retries and metadata.max_retries to
ignored_keys since these are new fields.
* fix: isolate test_skip_server_startup from CI environment
Remove mix_stderr=False (unsupported in some Click versions). Strip
DATABASE_URL/DIRECT_URL from environment during the test to prevent
real prisma operations when these are set in CI.
Prisma Python client does not support nested select within include.
Use include user:True to fetch the full user object; model_validator
extracts user_email from it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>