Commit graph

364 commits

Author SHA1 Message Date
Ishaan Jaff
373e5e316b
feat(mcp): BYOM — non-admin MCP server submission + admin review workflow (#23205)
* feat(mcp): add BYOM (Bring Your Own MCPs) submission + admin review workflow

Non-admins can now submit MCP servers for review via POST /v1/mcp/server/register.
Admins get a Submissions tab in the UI to approve or reject pending servers.
Approved servers enter the active runtime; rejected ones stay out with notes.

- DB: add approval_status, submitted_by, submitted_at, reviewed_at, review_notes
  to LiteLLM_MCPServerTable with migration
- Backend: new endpoints register, submissions, approve, reject
- reload_servers_from_database now only loads approval_status=active servers
- UI: Submissions tab with stat cards, card list, confirm dialogs; non-admin
  "Submit MCP Server" button wired to /register endpoint
- Fix get_mcp_submissions to filter by submitted_at IS NOT NULL (not submitted_by,
  which can be null for team-scoped keys without an associated user)

* feat(mcp): rename nav item to Team MCPs + add New badge

* fix(mcp): revert nav label, rename Submissions tab to Team MCPs + New badge

* feat(mcp): add MCP Standards — required fields config + CI-style checks on submissions

Adds a "Standards" tab (admin-only) to MCP Servers where admins define which
server fields are required for a submission to pass. Each submission card in
Team MCPs then shows a green ✓ or red ✗ for each required field, with a
summary "N/M checks" badge in the header — like GitHub CI status rows.

Also adds a `source_url` field (GitHub / Source URL) to the MCP server schema
so non-admins can link to the source repo when submitting a server.

- schema.prisma: add `source_url String?` to LiteLLM_MCPServerTable
- migration: 20260309000001_add_mcp_source_url
- _types.py: source_url on NewMCPServerRequest, UpdateMCPServerRequest, LiteLLM_MCPServerTable
- types.tsx: source_url on MCPServer interface
- create_mcp_server.tsx: GitHub/Source URL form field
- MCPStandardsSettings.tsx: new — toggle which fields are required (stored in general settings as mcp_required_fields)
- mcp_servers.tsx: Standards tab (admin-only)
- MCPSubmissionsTab.tsx: load required fields + CI-style check pills on each card

* refactor(mcp): move submission rules into Team MCPs tab, grouped free-form UI

Folds the Standards tab into Team MCPs. Submission Rules panel now lives at the
top of the Team MCPs tab — collapsible, shows active rules as chips when closed,
expands to a grouped checkbox editor (Documentation / Source / Connection /
Security). Removes the separate Standards tab from the nav.

MCPStandardsSettings.tsx is now constants-only (FIELD_GROUPS, MCP_REQUIRED_FIELD_DEFS,
SETTINGS_KEY) — the UI lives in MCPSubmissionsTab.

* feat(mcp): add mcp_required_fields to ConfigGeneralSettings + config/list endpoint

Registers mcp_required_fields as a proper general_settings field so the UI
can read/write it via /config/list and /config/field/update without the
"Invalid field" error. Also fixes a pre-existing pyright None-check issue
in _sync_ui_settings_to_general_settings.

* ui(mcp): GitHub-style PR checks panel on submission cards

* ui: rename Team MCPs -> Submitted Tools, Team Guardrails -> Submitted Guardrails

* address greptile review feedback (greploop iteration 1)

* fix: inline import, add approval workflow tests, rename Submitted MCPs

* fix(mcp): allow re-approval of rejected MCP server submissions

* fix(mcp): evict rejected servers from runtime; enforce mcp_required_fields on /register

* fix(mcp): sort submissions newest-first; force active status on admin-created servers

* fix(mcp): add missing mock in test, show Approve for rejected, clear submission metadata, drop spurious Content-Type

* fix(mcp/ui): show Reject for active servers; show submit form to non-admins with team-key note

* fix(mcp): conditional reload on reject; view-only admin for submissions; block admin from /register

* fix(mcp): match auth_type required-field validation to UI compliance check (reject 'none')

* fix(mcp): block view-only admin from /register; log settings failure; warn on active server reject

* fix(mcp): allow view-only admin to use /register; add _validate_mcp_required_fields tests

* fix(mcp): validate field names in mcp_required_fields; surface backend error in submit UI

* fix(mcp): fix falsy field check; add field-name validation; add take limit; document server-managed fields; close dialog on error
2026-03-10 13:58:59 -07:00
mubashir1osmani
88d0f9d834 added comments 2026-03-10 13:56:15 -04:00
mubashir1osmani
7ffaa6f74e fix(tag-usage): remove broken compute_tag_metadata_totals causing cost panel to show 0
The tag daily activity endpoint used compute_tag_metadata_totals which
deduplicates by request_id, but LiteLLM_DailyTagSpend stores aggregated
daily records where request_id is either NULL or stale. This caused all
metadata totals (total_spend, total_requests, etc.) to be 0 in the UI
cost panel. Now uses the same standard totals as every other entity type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 18:48:27 -04:00
Aarish Alam
e21b06265a
fix fkey violation on deleting user (#23115) 2026-03-09 08:53:11 -07:00
yuneng-jiang
3a1ac964f7 fix: pass organization_ids=None in get_users test calls
When calling get_users() directly (not via FastAPI), Query() defaults
are not resolved. Pass organization_ids=None explicitly to avoid
'Query' object has no attribute 'split' error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 23:15:16 -08:00
yuneng-jiang
ac5128493e fix: repair test regressions from org admin auth changes
- test_get_users_*: pass proxy admin user_api_key_dict since get_users
  now calls _authorize_user_list_request which checks user_role
- test_validate_team_member_add_permissions_non_admin: set
  organization_id on mock team since _is_user_org_admin_for_team
  accesses it

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 23:10:53 -08:00
yuneng-jiang
ce317148b9 feat: org admin access to team management — backend auth, UI visibility, tests
- Add _is_user_org_admin_for_team() reusable helper to common_utils.py
- Grant org admins access to /team/list, /team/info, /team/member_add,
  /team/member_delete, /team/member_update, /team/model/add,
  /team/model/delete, /team/permissions_list, /team/permissions_update
- Make validate_membership async with org admin fallback
- Add /user/list to self_managed_routes (endpoint handles own auth)
- UI: org admins see Members, Member Permissions, Settings tabs in team view
- UI: CreateUserButton uses useOrganizations() for org dropdown
- UI: org admin delete-member respects disable_team_admin_delete_team_user
- Add 16 unit tests for _is_user_org_admin_for_team, validate_membership,
  _user_is_org_admin route check, and privilege escalation prevention

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 22:43:09 -08:00
yuneng-jiang
9e531195ec
Merge pull request #23057 from BerriAI/litellm_fix_user_filter_scope
[Fix] User Filter Scope - Make Org-Scoping Opt-In
2026-03-07 18:22:26 -08:00
Ryan Crabbe
2cd0c767ee fix: regression test 2026-03-07 16:40:29 -08:00
Ryan Crabbe
daf7c0c3a8 fix: scoping virtual keys in the teams view to be applying the team filter globally instead of an or branch 2026-03-07 16:23:12 -08:00
yuneng-jiang
af61132a3f refactor: use DualCache for UI settings reads and get_team_object for team lookup
- Add get_ui_settings_cached() helper that reads from DualCache first,
  falls back to DB, and populates cache on miss.
- Update update_ui_settings() to set cache after DB write so subsequent
  reads see new values immediately.
- Replace raw prisma_client.db.litellm_teamtable.find_unique with the
  existing get_team_object helper which uses DualCache.
- Update all tests to mock get_ui_settings_cached and get_team_object
  instead of raw DB calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:56:43 -08:00
yuneng-jiang
c631708df6 feat: add opt-in scope_user_search_to_org flag for /user/filter/ui
PR #22722 made org-scoping unconditional on /user/filter/ui, which broke
team admins who aren't org admins (403 when searching users to add).
This makes org-scoping opt-in via a new UI Settings toggle, restoring
open search by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:38:31 -08:00
yuneng-jiang
034e83e716
Revert "[Fix] Team Usage Spend Truncated Due to Pagination" 2026-03-06 23:23:20 -08:00
Harshit28j
1452237ec6 fix req changes 2026-03-07 12:45:49 +05:30
Harshit28j
d78752b85b feat: feature flag on validate key alias 2026-03-07 12:32:21 +05:30
yuneng-jiang
be379b7b1e
Merge pull request #22722 from atapia27/feat/org-exclusive-add-member
org-exclusive-add-member
2026-03-06 22:24:05 -08:00
yuneng-jiang
4eee2b752d
Merge pull request #23011 from BerriAI/litellm_key-aliases-internal-user
[Fix] Internal Users Cannot Access Key Aliases on Request Logs Page
2026-03-06 21:23:22 -08:00
yuneng-jiang
b314e8d20a
Merge pull request #20688 from BerriAI/litellm_budget_tier_enforcement_for_keys
[Fix] Budget-linked keys never had spend reset
2026-03-06 20:44:58 -08:00
yuneng-jiang
12005c4a02 Fix /key/aliases auth for internal users and scope results by role
Internal users were blocked from accessing /key/aliases because the route
was missing from key_management_routes. Added the route and scoped query
results so non-admin users only see aliases for their own keys and their
teams' keys, matching /key/list behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:20:10 -08:00
yuneng-jiang
c2b03c15b9
Merge pull request #22939 from BerriAI/litellm_hashicorp_vault_backend
feat: Hashicorp Vault config override backend endpoints
2026-03-06 17:59:46 -08:00
hliu-roblox
07ac97aff4
feat(key_management): allow @ in key_alias for email-based aliases (#23003)
Adds @ to the _KEY_ALIAS_PATTERN allowed character set so that
key aliases like user/user@example.com are accepted. Updates tests
to cover email-based alias formats.
2026-03-06 17:24:42 -08:00
yuneng-jiang
8523bb6b48
Merge pull request #22956 from BerriAI/litellm_key_null_duration
[Fix] Key Expiry Default Duration
2026-03-05 21:06:55 -08:00
yuneng-jiang
e468b0278f [Fix] Key Expiry Default Duration - support null to never expire
Support passing duration=null on /key/update to reset a key's expiry to never expires, alongside the existing "-1" magic string (kept for backward compat).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:54:30 -08:00
yuneng-jiang
99c4f3cbea
Merge pull request #22938 from BerriAI/litellm_fix_team_usage_spend
[Fix] Team Usage Spend Truncated Due to Pagination
2026-03-05 20:45:27 -08:00
ryan-crabbe
11f83ff522
Merge branch 'main' into litellm_hashicorp_vault_backend 2026-03-05 17:27:33 -08:00
yuneng-jiang
d0e480414c Fix team usage spend showing lower than expected values
The /team/daily/activity endpoint used Prisma pagination (page_size=1000)
but the UI only fetched page 1. Teams with many keys/models easily exceed
1000 rows in LiteLLM_DailyTeamSpend, causing truncated totals.

Switches the endpoint to use SQL GROUP BY via get_daily_activity_aggregated
with include_entity_breakdown=True, returning all data in a single response
while preserving per-team breakdown. Also adds timezone parameter support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:00:51 -08:00
Ryan Crabbe
21718d208d feat: Hashicorp Vault config override backend endpoints
Add CRUD endpoints for managing Hashicorp Vault configuration via the
proxy admin API, with background sync, env var management, and
connection testing. Fix pre-existing bug where premium check ran after
global state mutation, and guard DELETE against clearing non-Vault
secret managers.
2026-03-05 16:57:08 -08:00
Julio Quinteros Pro
1ec6502f88 Fix tool management tests using wrong field name call_policy
Tests used call_policy throughout but the actual API model uses
input_policy and output_policy. Updated _make_tool_row helper,
list filter query param, and policy update request/response assertions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:17 -03:00
milan-berri
98b9bc8b72
fix: resolve base_model in /cost/estimate for Azure custom deployments (#22724)
The _resolve_model_for_cost_lookup function was only checking
litellm_params.model when resolving model names from the router.
For Azure custom deployment names (e.g. azure/openai/gpt-5.3-codex),
this deployment name doesn't exist in the model cost map, so cost
returned /bin/zsh.

Now checks model_info.base_model and litellm_params.base_model first,
falling back to litellm_params.model only if no base_model is set.
This matches how the router resolves base_model everywhere else.
2026-03-03 15:43:02 -08:00
Harshit Jain
1c9ecd4ec6
Merge pull request #22384 from BerriAI/litellm_aws_edge_case
Litellm aws edge case
2026-02-28 19:52:55 +05:30
Harshit28j
0b7d8b9a0d fix: edge case when key alias empty 2026-02-28 16:05:55 +05:30
yuneng-jiang
6d8b5b75ce [Feature] Key list endpoint: Add project_id and access_group_id filters
Add filtering capabilities to /key/list endpoint for project_id and access_group_id parameters. Both filters work globally across all visibility rules and stack with existing sort/pagination params. Added comprehensive unit tests for the new filters.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-27 21:25:44 -08:00
Alejandro Tapia
f1c563d2b2 org-exclusive-add-member 2026-02-27 14:58:17 -08:00
yuneng-jiang
cde23e9b6e fix: normalize null list fields to [] in update_data before DB write
When a client sends null for assigned_team_ids or assigned_key_ids, ensure
the DB receives [] instead of null, preventing null from being stored where
empty list is expected. Extend test to verify the DB call uses [].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:53:30 -08:00
yuneng-jiang
2144e79bad fix: guard against null assigned_*_ids in update_access_group delta computation
set(None) raises TypeError when a client sends null for assigned_team_ids or
assigned_key_ids. Add `or []` to handle null safely, consistent with create.
Add test covering this case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:48:04 -08:00
yuneng-jiang
516b18feca [Feature] Access group CRUD: Add bidirectional sync for teams/keys
When creating, updating, or deleting access groups, automatically keep
team and key access_group_ids in sync with the access group's assigned_team_ids
and assigned_key_ids. Includes transaction-based DB updates, cache patching,
and handles out-of-sync data by unioning assigned_* fields with hasSome queries.

Adds 12 new tests covering sync behavior across all three CRUD operations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:07:51 -08:00
yuneng-jiang
857a324f7a Merge remote-tracking branch 'origin' into litellm_key_info_crash_fix 2026-02-26 10:04:54 -08:00
Sameer Kankute
9c7f8138e1 FIx : litellm/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py 2026-02-26 12:43:06 +05:30
yuneng-jiang
386c148b8d use raw SQL in key_aliases to avoid loading full rows into memory
Replace Prisma ORM count/find_many calls with two query_raw calls that
only project the key_alias column. The Prisma client wrapper does not
support SELECT projection via find_many, so raw SQL is used to keep
memory usage proportional to the page size rather than total key count.
Update tests to mock query_raw instead of count/find_many.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-25 21:48:53 -08:00
yuneng-jiang
06e87eea87 remove unsupported select param from find_many call
LiteLLM_VerificationTokenActions.find_many() does not support the
select keyword argument. Remove it and drop the corresponding test.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-25 21:40:56 -08:00
yuneng-jiang
0b0809a3d5 optimize key_aliases to select only key_alias column and add unit tests
Add select={"key_alias": True} to the find_many call so only the alias
column is fetched from the database instead of full token rows. Add
five unit tests in test_key_management_endpoints.py covering response
shape, pagination skip/take computation, search filter injection,
absence of contains filter when no search term is given, and the
select-only-alias optimization.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-25 21:03:15 -08:00
Ishaan Jaff
60bcb26dc8
feat(agents): assign virtual keys to agents (#22045)
* feat(agents): assign virtual keys to agents

- Add agent_id field to LiteLLM_VerificationToken (schema.prisma + _types.py)
- Pass agent_id through key generation endpoint so keys can be scoped to an agent
- Refactor Add Agent wizard to 3-step flow (Configure → Assign Key → Ready)
  - Configure: all agent fields, custom/other type with just name+description
  - Assign Key: create new key or reassign existing key to agent
  - URL is now optional for easy discovery
- Add "Agent" ownership option to Create Key modal on Virtual Keys page
  with agent selector dropdown
- Extract CreatedKeyDisplay into shared component, reused in both flows
- Add keyCreateForAgentCall networking helper
- Add test for agent_id key generation

* fix(agents): code quality fixes from self-review

- Fix test_generate_key_helper_fn_agent_id: remove bare except clause,
  use explicit assert mock_insert.called, use .kwargs for clean arg access
- Remove no-op conditional in handleNext (both branches were identical)
- Validate selectedExistingKey before calling keyUpdateCall
- Validate selectedAgentId before setting on formValues in create_key_button

* fix(ui): replace deprecated Tremor Button with Ant Design Button in CreatedKeyDisplay
2026-02-24 18:28:16 -08:00
Ishaan Jaff
360643e213
[Feat] UI - Allow using AI to understand Usage patterns (#22042)
* Add Ask AI chat component to Usage page

- Create UsageAIChatModal component with streaming chat interface
- Integrate with existing model hub for model selection
- Pass usage data context (spend, models, providers, keys) to AI
- Add Ask AI button next to Export Data button in global view
- Add tests for the new component and integration

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Convert Ask AI from modal to right-side sliding panel

- Replace UsageAIChatModal with UsageAIChatPanel
- Panel slides in from right side, usage page stays visible
- Full-height panel with header, model selector, chat area, and input
- Smooth CSS transition for open/close animation
- Update tests for new panel component (34 tests passing)

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Remove build output directory from tracking

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Add backend AI usage chat endpoint with tool calling

Backend:
- New /usage/ai/chat SSE streaming endpoint
- AI agent has get_usage_data tool that queries /user/daily/activity/aggregated
- Follows same architecture as policy AI suggest (litellm.acompletion + tools)
- Non-admin users are restricted to their own data
- 12 backend unit tests

Frontend:
- Panel now calls /usage/ai/chat backend endpoint via SSE
- Removed direct OpenAI client calls from frontend
- Added usageAiChatStream networking function following enrichPolicyTemplateStream pattern

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Make model selection optional, default to gpt-4o-mini on backend

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Add team/tag tools, status indicators, and improved AI agent

- AI agent now has 3 tools: get_usage_data, get_team_usage_data, get_tag_usage_data
- Stream status events (Thinking... Fetching... Analyzing...) to UI
- Frontend shows spinner + status text during tool execution
- Better system prompt guiding tool selection
- Entity summariser for team/tag data with ranked breakdowns
- 13 backend tests, 34 frontend tests passing

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Fix: inject today's date into system prompt so AI resolves relative dates correctly

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Show tool calls as distinct steps + render markdown in responses

- Backend emits tool_call events with tool_name, label, args, and status
- Frontend shows each tool call as a step with ✓/spinner/✗ indicator
- Tool call steps show icon, label, date range, and filters
- AI responses rendered with ReactMarkdown (bold, lists, tables, code)
- Cursor-like UX: Thinking → tool calls → Analyzing → streamed answer

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Refactor backend for code quality: proper types, constants, all functions ≤50 LOC

- TypedDict for SSE events (SSEStatusEvent, SSEToolCallEvent, etc.) and ToolHandler
- Constants for table names, entity fields, temperature, page sizes, top-N limits
- Shared _query_activity() eliminates duplicated fetch logic
- _accumulate_breakdown() + _ranked_lines() replace inline aggregation loops
- Extracted _process_tool_call() and _stream_final_response() from main stream fn
- Black + Ruff clean, all 15 functions verified ≤50 LOC
- Replaced Tremor Button with Antd Button in panel (Tremor deprecated per AGENTS.md)

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Address greptile review: security fixes and input validation

- Restrict team/tag tools to admin-only users (non-admins only get get_usage_data)
- Constrain ChatMessage.role to Literal['user', 'assistant'] to prevent system prompt injection
- Add test for base tools restriction (non-admin gets 1 tool, admin gets 3)
- Issues 3 (unused imports) and 4 (inline datetime) were already fixed in prior commit

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Address greptile round 2: sanitize errors, defense-in-depth allowlist, revert tsconfig

- Sanitize error messages: generic 'An internal error occurred' sent to client,
  full exception logged server-side via verbose_proxy_logger
- Defense-in-depth: _process_tool_call validates fn_name against role-based
  allowlist before dispatch (even though LLM only receives allowed tools)
- Revert tsconfig.json jsx back to 'preserve' (Next.js recommended default)

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Role-scoped system prompt + additional test coverage

- System prompt is now role-aware: admin sees all 3 tool descriptions,
  non-admin only sees get_usage_data (consistent with tool filtering)
- Added tests: non-admin prompt excludes team/tag tools, date injection
- 15 backend tests, 34 frontend tests passing

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Fix LLM arg validation + cap conversation size at 20 messages

- _resolve_fetch_kwargs uses .get() with ValueError for missing dates
  (handles malformed LLM tool arguments gracefully)
- MAX_CHAT_MESSAGES = 20 constant; backend truncates to last 20
- Frontend also sends only last 20 messages per request
- Prevents excessive token usage and context-length errors

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>
2026-02-24 16:40:04 -08:00
Ishaan Jaff
6ee50ff73e
feat(proxy): tool policies - auto-discover tools + policy enforcement guardrail (#22041)
* feat(proxy): tool policies - auto-discover tools, manage policies, guardrail enforcement

- New LiteLLM_ToolTable in schema.prisma to store discovered tools
- Auto-discovery: tools seen in LLM responses get upserted via ToolDiscoveryQueue
  (hooks into DBSpendUpdateWriter, same pipeline as spend tracking)
- Management endpoints: GET /v1/tool/list, GET /v1/tool/{name}, POST /v1/tool/policy
- ToolPolicyGuardrail: blocks tool_calls in responses based on policy setting
- UI: Tool Policies page under Guardrails section with policy selector,
  filters by policy/team/key, live tail, sortable table
- Unit tests for queue, writer, endpoints, guardrail

* feat(tool-policies): track call_count + discover tools from request body and /messages API

- Add call_count column to LiteLLM_ToolTable; incremented on every flush
- Extract tools from request body too (not just response tool_calls):
  - OpenAI /chat/completions: tools[].function.name
  - Anthropic /messages pass-through: request_body.tools[].name
- Show call_count column in UI table (sortable)
- UI: drop dual_llm option, keep only trusted/blocked

* fix: address greptile review feedback

- Remove redundant @@index([tool_name]) from schema.prisma (tool_name has @unique which already creates an index)
- Replace gen_random_uuid()::text with str(uuid.uuid4()) for portability
- Rewrite test_tool_registry_writer.py to mock execute_raw/query_raw (actual implementation) instead of Prisma model methods
- Fix test patches in test_tool_management_endpoints.py to target source modules since imports are inside function bodies
- Add "Tool Policies" page title to ToolPolicies.tsx

* fix: address greptile review round 2

- Replace NOW() with Python datetime parameter in tool_registry_writer (SQLite portability)
- Fix cache key collision in tool_policy_guardrail: use null-byte separator instead of colon
- Remove type==function filter from request-side tool extraction to match response-side behavior
- Clear seen_tool_names on flush so call_count increments per batch cycle not per pod lifetime

* fix: address greptile review round 3

- Fix test_seen_names_persist_across_flushes to match actual per-flush-cycle behavior
- Update module docstring in tool_discovery_queue.py to accurately describe flush behavior
- Add created_at/updated_at to raw SQL INSERT in batch_upsert_tools and update_tool_policy

* fix: cache tool policies per tool name not per combination

Previously the cache key was built from the full set of tool names in a
request, so each unique combination of tools got its own cold cache entry
and triggered a separate DB query. With N distinct tools across requests
this was effectively a DB hit on every request.

Now each tool name is cached individually. Cache hits are checked per
tool, only missing tools are fetched from DB in a single batch query,
and each result is cached separately. Once a tool's policy is warm,
any subsequent request using that tool benefits from the cache regardless
of what other tools are in the request.

* Update ui/litellm-dashboard/src/components/ToolPolicies.tsx

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-24 16:27:06 -08:00
Sameer Kankute
c7aafdf794
Merge pull request #21926 from BerriAI/main
merge main in oss 21 02
2026-02-23 18:17:30 +05:30
Zhenting Huang
c845c334b4
fix(proxy): add model_ids param to access group endpoints for precise deployment tagging (#21655)
POST /access_group/new and PUT /access_group/{name}/update now accept an
optional model_ids list that targets specific deployments by their unique
model_id, instead of tagging every deployment that shares a model_name.

When model_ids is provided it takes priority over model_names, giving
API callers the same single-deployment precision that the UI already has
via PATCH /model/{model_id}/update.

Backward compatible: model_names continues to work as before.

Closes #21544
2026-02-21 00:39:57 -08:00
yuneng-jiang
b61537cd0f feat: expose user_email in organization members response
Add user_email field to LiteLLM_OrganizationMembershipTable with a model_validator
that populates it from the nested user object, and update the /organization/info
Prisma query to select user_email from the related user record.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 21:41:53 -08:00
yuneng-jiang
f7fb4a270f Merge remote-tracking branch 'origin' into litellm_usage_perf_fix 2026-02-20 15:37:56 -08:00
yuneng-jiang
c7fe400d4d [Fix] Service account visibility for team members
Regular team members could not see service accounts belonging to their
team. Additionally, former team members could still see service accounts
they created via the created_by filter after leaving the team.

- Add get_member_team_ids() to retrieve all teams a user belongs to
- Regular members now see team service accounts (user_id=NULL) but not
  other members' personal keys
- Scope created_by filter to the user's current team memberships
- Add 7 unit tests covering the new visibility rules
2026-02-19 16:29:43 -08:00
yuneng-jiang
e2e698944a perf: use SQL GROUP BY for aggregated daily activity endpoints
Replace find_many + Python-side aggregation with a single SQL GROUP BY
query via query_raw in get_daily_activity_aggregated. This collapses
rows across entities (users/teams/orgs) in the database, reducing ~150k
rows to ~2-3k grouped rows before transfer to Python.

Also adds composite indexes (entity_id, date) to all 6 daily spend
tables for faster filtered queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-19 14:36:28 -08:00