Commit graph

3204 commits

Author SHA1 Message Date
yuneng-jiang
efa5a3fc69 [Feature] UI - Search Tools: Add permissions UI, modernize page, infinite team dropdown
Add search_tools permission support across the UI (key create/edit, team create,
object permissions view) with breaking-change alerts for the new least-privilege
default. Modernize the Search Tools page with AntD Tabs, a Test playground tab,
and ProviderLogo integration. Migrate TeamDropdown to self-fetching infinite
scroll pattern using useInfiniteTeams hook. Scope search tools visibility for
internal users based on their team memberships.

Backend: Add search_tools field to Prisma schema (all copies), Pydantic models
(ObjectPermissionBase + ObjectPermissionTable), and allowed routes for virtual
keys. Add permission filtering to /search_tools/list endpoint. Include
object_permission in team list v2 queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:23:49 -07:00
yuneng-jiang
75bd742d18
Merge pull request #24239 from BerriAI/litellm_ui_vitest_coverage
[Test] UI: Add vitest coverage for 10 untested components
2026-03-21 14:38:35 -07:00
yuneng-jiang
dae638b2f0 fix(test): update internal user test to match new create flow
Internal users can now see the create modal (with a team selection
prompt). Updated the test from asserting the modal is hidden to
asserting the team selection prompt is shown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:14:34 -07:00
yuneng-jiang
1a63a7bab8 fix(test): update mcp_servers tests for removed Alias column and Team header
- Remove assertions for alias text (column was removed)
- Disambiguate "Team" filter label from "Team (Owner)" column header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:11:54 -07:00
yuneng-jiang
5c953c6b61 fix(ui): handle nullable userRole after removing early return guard
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:04:58 -07:00
yuneng-jiang
8366d24e22 fix(ui): use old leftnav (SidebarProvider) in dashboard layout for path-routed pages
The dashboard layout was using Sidebar2, which routed all entries to
path-based URLs like /ui/keys — but only api-reference has been migrated.
Switch back to the old leftnav so unmigrated pages navigate to the legacy
root page (?page=X) and migrated pages use path routing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:14:56 -07:00
yuneng-jiang
83eac06b32 feat(ui): add TeamDropdown to MCP create form, fix health recheck cache
- Add TeamDropdown as first field in create MCP server form
- For internal users, hide form fields until team is selected
- Fix useMCPServerHealth to append new servers to cache on recheck

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:12:36 -07:00
yuneng-jiang
456e326c95 fix(ui): reduce MCP table columns and add explicit column widths
Removed low-value columns (Alias, Auth Type, Updated) to reduce
horizontal overflow. Added explicit size hints to remaining columns.
DataTable now applies column sizes to header and body cells.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:11:22 -07:00
yuneng-jiang
478ec3d392 fix(ui): remove early loading return, let DataTable handle loading state
The early return on missing auth params blocked the entire page from
rendering. The hooks already guard on accessToken being available, and
DataTable shows its own loading state via isLoading prop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:04:30 -07:00
yuneng-jiang
baa1fa4151 feat(ui): add Team (Owner) column to MCP servers table
Shows the owning team alias resolved from team_id. Global servers
(team_id=null) display "Global". Header includes info icon explaining
that only servers from teams with mcp:read permission are visible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:03:25 -07:00
yuneng-jiang
79ca00bbec fix(ui): show helpful empty state for internal users without MCP access
The list endpoint returns an empty list (not 403) when a user has no
MCP servers available. For internal users, show a message suggesting
they may need mcp:read permission or team MCP server assignments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:59:44 -07:00
yuneng-jiang
017d87b7ab fix(ui): show helpful error when user lacks MCP read permission
Replace "Missing required authentication parameters" with a loading
state. When the MCP servers fetch fails (e.g. 403), show a clear
error message with steps on how to get mcp:read permission.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:58:38 -07:00
yuneng-jiang
f51078761a types(ui): add team_id to MCPServer interface 2026-03-21 12:24:41 -07:00
yuneng-jiang
31bc13eb17 Merge branch 'main' into litellm_yj_march_20_2026 2026-03-21 10:27:05 -07:00
yuneng-jiang
5905100cdc address greptile review feedback (greploop iteration 3)
- Fix double error handling in getTeamPermissionsCall: return empty data
  on HTTP error instead of calling handleError + throwing, preventing
  duplicate error notifications

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:35:54 -07:00
yuneng-jiang
290706a708 address greptile review feedback (greploop iteration 3)
- Fix double error handling in getTeamPermissionsCall: return empty data
  on HTTP error instead of calling handleError + throwing, preventing
  duplicate error notifications

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:35:36 -07:00
yuneng-jiang
24be81094b address greptile review feedback (greploop iteration 2)
- Fix unknown permissions duplication: seed selected state with only known
  permissions so existingUnknown and selected are disjoint on save
- Disable Add MCP Server button for non-admins without a team selected,
  show tooltip explaining they need to select a team first

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:28:27 -07:00
yuneng-jiang
42fe911e1c address greptile review feedback (greploop iteration 1)
- Separate save failure from refresh failure: close drawer after successful
  save even if teamInfoCall refresh fails
- Preserve unknown permissions not in availablePermissions when saving,
  preventing silent drops of permissions from newer backend versions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:21:39 -07:00
yuneng-jiang
4f98b4ea3c address greptile review feedback
- Type onUpdate as () => Promise<void> and await it before closing drawer
- Replace accessToken! assertion with explicit null guard
- Gate fetchAvailableTeamMemberPermissions behind canEditTeam check
- Pass team_id for admins too when a team is selected in the filter

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:59:42 -07:00
yuneng-jiang
18fae5377e [Feature] UI - MCP: Team member permissions drawer and CRUD access
Add UI support for the MCP team management permissions introduced in PR #24266.

- Add MemberPermissionsDrawer component (Ant Design Drawer) for managing
  per-member MCP permissions (mcp:read, mcp:create, mcp:update, mcp:delete)
- Add permissions button to team member table actions column
- Fetch available permissions from GET /team/available_permissions
- Pass extra_permissions in team member update API calls
- Allow all users to create MCP servers directly (backend enforces permissions)
- Pass team_id when non-admin users create MCP servers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:52:55 -07:00
yuneng-jiang
db8050bb60
Merge pull request #24259 from BerriAI/litellm_ui_refactor_policy_versions_hook
[Refactor] UI - Policies: Extract usePolicyVersions Hook
2026-03-20 23:45:31 -07:00
yuneng-jiang
492c0cd3ba address greptile review feedback (greploop iteration 3)
- Move callbacks outside try/catch so only mutation errors are caught,
  not errors from onVersionCreated/onVersionStatusUpdated callbacks
- Replace policyName! non-null assertion with DISABLED_POLICY_KEY
  sentinel to avoid undefined in cache keys when query is disabled

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:39:01 -07:00
yuneng-jiang
41d12ed106 address greptile review feedback (greploop iteration 2)
- Add PolicyVersionsData type for select output; specify TData generic
  so consumers get Policy[] (not Policy[] | undefined) for versions
- Remove empty-string queryKey fallback — use policyName! since
  enabled:false prevents fetch when policyName is null
- Add cache invalidation tests for both mutation hooks
- Add explanatory comment for ?? [] fallback in component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:33:50 -07:00
yuneng-jiang
80e55804af [Fix] UI - Policies: Type accuracy and mutation guard for usePolicyVersions
- Make PolicyVersionsResponse.versions optional (Policy[] | undefined)
  to match real API shape — select fallback handles normalization
- Add policyName guard to useUpdatePolicyVersionStatus mutationFn
  to fail loudly instead of silently skipping cache invalidation
- Add test for null policyName in updateStatus mutation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:27:02 -07:00
yuneng-jiang
8aa1ebfb07 [Fix] UI - Policies: Fix unhandled promise rejections and isPending semantics
- Wrap mutateAsync calls in try/catch to swallow re-thrown errors
  (notifications already handled by onError in mutation hooks)
- Use isLoading instead of isPending for version loading state —
  isPending is true when query is disabled with no cache, isLoading
  is only true during active fetches (matches original behavior)
- Add isLoading assertions to disabled-state tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:04:25 -07:00
yuneng-jiang
2ca4fa6189
Merge branch 'main' into litellm_yj_march_19_2026 2026-03-20 17:28:41 -07:00
yuneng-jiang
79aea5ddcf [Refactor] UI - Policies: Extract usePolicyVersions hook from FlowBuilderPage
Replace useEffect + useState fetch pattern for policy version management
with React Query hooks (useQuery + useMutation), following established
codebase conventions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 16:25:40 -07:00
yuneng-jiang
3ea69c9539 Merge remote-tracking branch 'origin' into litellm_yj_march_19_2026 2026-03-20 12:37:26 -07:00
yuneng-jiang
4b80094b90 [Test] UI: Add vitest coverage for 10 previously untested components
Add tests for ResponseTimeIndicator, KeyValueInput, QueryParamInput,
RoutePreview, OnboardingModal, EditUserModal, ModelFilters,
AuditLogDrawer, PassThroughInfoView, and EmailSettings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 12:04:10 -07:00
yuneng-jiang
8c396e5ca9
Merge pull request #24172 from BerriAI/litellm_extract_useChatHistory_hook
[Refactor] Extract useChatHistory hook from ChatUI.tsx
2026-03-20 00:17:07 -07:00
yuneng-jiang
bdf24757c0
Merge pull request #24189 from BerriAI/litellm_teams_table_modernize
[Feature] UI - Teams: Modernize Teams Table
2026-03-20 00:16:47 -07:00
yuneng-jiang
9b519c4754
Merge pull request #24192 from BerriAI/litellm_migrate_antd_message_to_context_api
[Fix] UI: AntD Messages Not Rendering
2026-03-20 00:16:04 -07:00
yuneng-jiang
34d954f8cb [Fix] UI: Migrate AntD message API to use context-based MessageManager
AntD v5 static message API doesn't render without an App wrapper or
useMessage() context holder. Mirrors the existing notification pattern
by adding message.useMessage() to AntdGlobalProvider and routing all
calls through a new MessageManager module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 23:29:38 -07:00
Ryan Crabbe
ad43a35d76 feat: add control plane for multi-proxy worker management
Adds a control plane capability that enables a central admin instance
to manage multiple regional worker proxies from a single UI.

Backend:
- Worker registry loaded from YAML config (worker_id, name, url)
- /.well-known/litellm-ui-config exposes is_control_plane and workers list
- /v3/login + /v3/login/exchange: opaque code exchange for cross-origin
  username/password auth (JWT never in URL/logs, single-use 60s TTL)
- SSO cookie handoff with return_to → opaque code → exchange
- _validate_return_to: full origin validation (scheme+hostname+port)
- Startup warning when control_plane_url set without Redis
- Both /v3 endpoints gated behind control_plane_url config

Frontend:
- Worker selector dropdown on login page (gated behind is_control_plane)
- Cross-origin SSO code exchange handling on callback
- switchToWorkerUrl: localStorage-persisted worker URL for API calls
- useWorker hook: shared worker state management
- WorkerDropdown in navbar for switching workers
- Logout/switch clears worker state from localStorage

Tests:
- 7 tests for /v3/login + /v3/login/exchange
- 10 tests for _validate_return_to
- 2 tests for control plane discovery endpoint
2026-03-19 22:50:19 -07:00
yuneng-jiang
883611aa91 [Feature] UI - Teams: Modernize teams table with AntD, server-side pagination, and v2 API
Migrate the OldTeams table from Tremor to Ant Design components, matching the
Access Groups page pattern. Switch from /team/list to /v2/team/list for
server-side pagination, filtering, and sorting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:42:15 -07:00
yuneng-jiang
f34fe4758a fix: stale closure, simplified session isolation, debounce-race in useChatHistory
- clearChatHistory: use functional setChatHistory updater so blob URL
  revocation operates on the latest snapshot, not a stale closure capture.
- Simplified mode: skip sessionStorage hydration and persistence for
  messageTraceId, responsesSessionId, and useApiSessionManagement so
  embedded widgets don't cross-contaminate the full playground session.
- Debounce race: skip re-writing empty chatHistory to sessionStorage
  after clearChatHistory already removed the key.
- Added 5 new tests covering these fixes (39 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 21:19:51 -07:00
yuneng-jiang
954bfcbd42 chore: remove verbose console.log calls from useChatHistory hook
Removes 17 console.log statements that fired on every streaming chunk
in updateTextUI, updateTimingData, updateUsageData, and other hot-path
functions. The console.error for sessionStorage parse failures is kept.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 20:46:51 -07:00
yuneng-jiang
e88425b881 refactor: wire ChatUI to use useChatHistory hook
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:09:20 -07:00
yuneng-jiang
f3c6915d61 feat: add useChatHistory hook with tests (extracted from ChatUI)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:09:20 -07:00
yuneng-jiang
2e70c23307 Gate legacy redirect on authLoading to ensure proxyBaseUrl is resolved
The redirect useEffect fires before getUiConfig() completes, so
proxyBaseUrl is always "" on first render. Gate on !authLoading so
the redirect only fires after config is fetched, matching the pattern
used by the login redirect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 14:05:56 -07:00
yuneng-jiang
e9e5ed989c Move legacy redirect from render phase to useEffect
router.replace was called directly during render, which is unsafe in
React 18 concurrent mode. Move it into a useEffect and use a computed
flag (isLegacyRedirect) to show LoadingScreen while redirecting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:59:45 -07:00
yuneng-jiang
895951744d Fix leftnav navigation regression and useProxySettings initial state
The leftnav was updated to emit page="api-reference" but only "api_ref"
was in LEGACY_REDIRECTS, causing clicks to fall through to the default
Usage page. Add "api-reference" entry to the redirect map. Also include
LITELLM_UI_API_DOC_BASE_URL in the hook's initial state to avoid a
brief flash of incorrect base URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:36:21 -07:00
yuneng-jiang
519afa494c [Refactor] UI - API Reference: Migrate to path-based routing
Move the API Reference page from query-param routing (?page=api_ref) to
Next.js path-based routing (/ui/api-reference). Add a LEGACY_REDIRECTS
map in the root page.tsx so users with old bookmarks are seamlessly
redirected. Future page migrations only need one new map entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 12:57:17 -07:00
yuneng-jiang
0b07f628ff [Test] UI: Add vitest coverage for 10 previously untested components
Add unit tests for:
- SimpleToolCallBlock, SimpleMessageBlock, CollapsibleMessage, HistoryTree (log details drawer)
- OnboardingForm (onboarding flow)
- TeamsHeaderTabs, TeamsTable (teams page)
- transform_key_info, filter_helpers (key/team helpers)
- queryKeysFactory (query key generation utility)

47 new tests covering conditional rendering, user interactions, data transformation, and error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 10:30:03 -07:00
yuneng-jiang
d984b293de [Feature] UI - Leftnav: Add external link icon to Learning Resources
Add ExportOutlined icon next to nav items that link to external pages,
making it clear to users when a link opens in a new tab.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:56:25 -07:00
yuneng-jiang
0b63979d45 Fix build: cast endpointType to EndpointType at call site
ChatUI stores endpointType as string but the narrowed prop expects
EndpointType — add explicit cast at the call site.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:04:42 -07:00
yuneng-jiang
ebe329cdce Fix build: use as any for SyntaxHighlighter style prop
Matches the cast used in ChatUI.tsx — the react-syntax-highlighter
type definitions don't accept CSSProperties directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:02:18 -07:00
yuneng-jiang
b55cb249fe Address Greptile feedback: use EndpointType enum, add CHAT MCP test
- Narrow endpointType prop from string to EndpointType enum
- Add missing test for MCP events on CHAT endpoint

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 16:46:41 -07:00
yuneng-jiang
3ba18d7084 [Refactor] UI - Playground: Extract ChatMessageBubble from ChatUI
Extract the chat message bubble rendering (~165 lines) into a dedicated
ChatMessageBubble component with 15 Vitest tests covering all display branches.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 16:38:58 -07:00
yuneng-jiang
d98440f452 Merge remote-tracking branch 'origin' into litellm_yj_march_18_2026 2026-03-18 16:20:07 -07:00