The main dashboard at /?page=api-keys is rendered by src/app/page.tsx
(legacy query-param routing), not the (dashboard)/layout.tsx. This
commit adds the CommandPalette to the correct page so Cmd+K works
from any page when using the legacy routing system.
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
- 4 tests for VirtualKeysTable search bar (render, hint, typing, API param)
- 7 tests for CommandPalette (open/close with Cmd+K, placeholder, search,
no results, result selection with onSelectKey callback)
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
- Add inline search input to VirtualKeysTable that filters keys by alias
via server-side API call (debounced, resets to page 1 on search)
- Create global CommandPalette component (Cmd+K / Ctrl+K) for quick key
search from any page, with keyboard navigation and result selection
- Wire CommandPalette into the dashboard layout for global availability
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
* feat(redis): add circuit breaker to RedisCache to fast-fail when Redis is down (#24181)
* feat(redis): add circuit breaker env var constants
* feat(redis): add RedisCircuitBreaker and apply guard decorator to all async ops
* fix(dual_cache): fall back to L1 instead of re-raising on Redis increment failures
* test(caching): add circuit breaker unit tests
* fix(redis): fast-fail concurrent HALF_OPEN probes — only one probe at a time
* fix(dual_cache): return None fallback when in_memory_cache is absent and Redis fails
* test(caching): add regression tests for HALF_OPEN concurrency and None fallback
* Fix blocking sync next in __anext__ (#24177)
* Fix blocking sync next
* Update tests/test_litellm/litellm_core_utils/test_streaming_handler.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix PEP 479 regression in __anext__ sync iterator exhaustion
asyncio.to_thread re-raises thread exceptions inside a coroutine, where
PEP 479 converts StopIteration to RuntimeError before any except clause
can catch it. Add _next_sync_or_exhausted() module-level helper that
catches StopIteration in the thread and returns a sentinel instead, then
raise StopAsyncIteration in the coroutine.
Also rewrites the non-blocking test to use asyncio.gather() instead of
asyncio.create_task() (which returned None on Python 3.9 / pytest-asyncio
in CI), and adds an exhaustion regression test that drains the wrapper
fully and asserts no RuntimeError leaks out.
---------
Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat: add git-subdir source type to claude-code/plugins API (#24223)
Support a third plugin source type `git-subdir` alongside the existing
`github` and `url` types, as documented in the official Claude Code
plugin marketplaces spec.
New format: {"source": "git-subdir", "url": "...", "path": "subdir/path"}
- Validates url and path fields are present and non-empty
- Rejects absolute paths, '..' segments, backslashes, and percent-encoded
traversal sequences (including double-encoded variants via regex check)
- Extracts path validation into _validate_git_subdir_path() helper
- Updates Pydantic field description to document all three source types
- Adds isValidUrl() check for url/git-subdir source types in the UI form
- Adds "Git Subdir" option to the UI form with a required Path field
- Adds unit tests covering success, update, missing/empty fields,
path traversal variants, and unknown source type
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* [FEAT] add extract_header and extract_footer to Mistral OCR supported params (#24213)
* docs: add git-subdir source type to claude-code plugin marketplace docs (#24289)
* fix(ui): swap J/K keyboard navigation in log details drawer (#24279) (#24286)
J should navigate down (next) and K should navigate up (previous),
matching vim/standard conventions.
* fix: use async_set_cache in user_api_key_auth hot path (#24302)
* fix: use async_set_cache in auth hot path to avoid blocking event loop
* test: assert no blocking set_cache call in _user_api_key_auth_builder
* test: broaden blocking call check to all sync DualCache methods
* test: fix regression test to actually catch blocking cache calls
* fix: ruff lint unused variable + UI build MessageManager error
- litellm/caching/redis_cache.py: remove unused variable 'e' in circuit
breaker exception handler (F841)
- add_plugin_form.tsx: use MessageManager.error() instead of undefined
message.error() for git URL validation
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
* docs: add REDIS_CIRCUIT_BREAKER env vars to config_settings reference
Add REDIS_CIRCUIT_BREAKER_FAILURE_THRESHOLD and
REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT to the environment variables
reference table so test_env_keys.py passes.
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
---------
Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Vincenzo Barrea <manamana88@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Robert Kirscht <rkirscht242@gmail.com>
Co-authored-by: Imgyu Kim <kimimgo@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
The special name check (all_team_servers, all_proxy_servers) was an elif
after the server_id-is-not-None check, making it unreachable since special
names are non-None strings. Split into separate if blocks so the special
name guard runs before the duplicate-ID check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The team MCP manager feature was reverted in PR #24255, so the test
needs to go back to the original single auth failure test that expects
a 403 for non-admin users.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test_create_mcp_server_auth_failure test expected a 403 for non-admin
users, but the team MCP manager feature changed the auth flow to first
check for team_id (400) before checking permissions. Split into two tests:
one for missing team_id (400) and one for non-manager rejection (403).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes CI failure in test_api_docs.py which validates that all Pydantic
model fields are documented in endpoint docstrings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add pytest.importorskip("mcp") at module level so tests skip cleanly
in CI environments without the mcp package (instead of ImportError)
- Import LiteLLM_TeamTableCachedObj into MCP_AVAILABLE block so type
annotations resolve for static analysis and get_type_hints()
- Remove string quotes from type annotations now that the import exists
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(moonshot): preserve reasoning_content on Pydantic Message objects in multi-turn tool calls
The condition 'reasoning_content not in msg' doesn't work correctly for
Pydantic Message objects because they don't support the 'in' operator
like dicts do. This caused reasoning_content to be stripped from
assistant messages in multi-turn conversation history.
Changed the condition to use msg.get('reasoning_content') instead,
which works correctly for both dicts and Pydantic models.
Fixes#23765
* added newline eof
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Update tests/test_litellm/llms/moonshot/test_moonshot_chat_transformation.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Simplify assertions in test_moonshot_chat_transformation
Removed redundant assertions for non-assistant messages.
---------
Co-authored-by: BillionClaw <267901332+BillionClaw@users.noreply.github.com>
Co-authored-by: Aarish Alam <arishalam121@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
- Set output_cost_per_second to 0.0 (was 0.0001) for whisper-1 and
azure/whisper-1: transcription is billed on input duration only,
not output duration
- Fix cost_per_second() in openai/cost_calculation.py: change elif to if
so input_cost_per_second is evaluated independently of output_cost_per_second,
and remove the erroneous completion_cost = 0.0 assignment that masked
any previously-set output cost
- Add TestCostPerSecondArithmetic unit tests covering both cost fields,
the None-guard, and zero-duration edge case
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The Gemini REST API documents the embedding task type parameter as
camelCase `taskType`. The existing transformation functions convert
`dimensions` to `outputDimensionality` but miss the parallel
`task_type` to `taskType` conversion. This adds that conversion to
both `transform_openai_input_gemini_content` (batchEmbedContents path)
and `transform_openai_input_gemini_embed_content` (embedContent path).
Fixes#24190
Add Google AI Studio (gemini/) and Vertex AI (vertex_ai/) as
supported providers for prompt caching. Same cache_control format
as Anthropic works - LiteLLM translates it to Google's context
caching API under the hood.
Includes SDK + proxy examples for both providers.
Non-streaming paths call _process_hidden_params_and_response_cost; streaming
assembles the full response later and skipped that, so litellm_params.metadata
lacked hidden_params (e.g. response_cost for OTEL/OpenSearch).
- Add _merge_hidden_params_from_response_into_metadata and call it from
success_handler and async_success_handler after cost is set, before
_build_standard_logging_payload.
- Unit tests for merge helper.
Tests: pytest tests/test_litellm/litellm_core_utils/test_litellm_logging.py
Made-with: Cursor
Addresses Greptile feedback about missing integration tests for PUT/DELETE
when invoked by mcp_server_manager role. Adds tests for edit success/403,
delete success with team cleanup/403, and the _remove_mcp_server_from_team
helper directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>