Commit graph

4746 commits

Author SHA1 Message Date
yuneng-jiang
a4199d3c09
Merge pull request #32886 from BerriAI/litellm_/topnav-breadcrumbs-gateway-11e9c2
feat(ui): root the gateway breadcrumb in the AI Gateway selector
2026-07-11 00:28:14 -07:00
tin-berri
0c23c40627
Merge pull request #32752 from BerriAI/litellm_mcp_configured_client_for_passthrough
fix(mcp): rework the dashboard credential-field lifecycle so the OAuth app is upstream-scoped
2026-07-11 00:13:13 -07:00
Yuneng Jiang
665c0dc508
feat(ui): always show the gateway selector with a discoverable Chat entry
The AI Gateway selector now always renders at the breadcrumb root, even with no plugins and Chat UI disabled, so the Chat feature stays discoverable. The Chat entry is always listed: clickable when enabled, and disabled with an "Admins can enable in Settings" hint when it is off.

Since the selector is now unconditional, the useViewSwitcherVisible hook and the section-crumb fallback added in the previous commit are removed
2026-07-11 00:02:00 -07:00
Yuneng Jiang
ba17c4526e
feat(ui): root the gateway breadcrumb in the AI Gateway selector
The AI Gateway select (ViewSwitcher) now sits at the root of the DashboardHeader breadcrumb instead of on the right, so the top bar reads [AI Gateway select] > Page to match the redesign. It keeps the same dropdown, including the Chat / Chat UI options.

When no plugins are registered and Chat UI is disabled there is nothing to switch between, so the breadcrumb falls back to the static section crumb rather than rendering a dangling leading separator
2026-07-10 23:25:19 -07:00
Yuneng Jiang
922ed1ad30
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/data-table-design-exploration-f3f5e9
# Conflicts:
#	ui/litellm-dashboard/eslint-metrics.json
2026-07-10 23:14:14 -07:00
Yuneng Jiang
472b64cc62
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/patch-endpoint-1d2646 2026-07-10 23:14:13 -07:00
Abhimanyu Kapur
3c714ed7a6 feat(auto_router): keyword tier overrides and semantic keyword matching for the complexity router
Add deterministic keyword-to-tier overrides and optional embedding-based
(semantic) keyword matching to the complexity router, and surface both in the
Add Auto Router UI behind a Router Type selector: "Auto-Router v2 [Recommended]"
(complexity tiers + keyword overrides + semantic matching, the default) and
"Semantic Router [to be deprecated]" (the existing utterance-based router,
unchanged). Keyword-to-tier overrides resolve to the highest tier matched
rather than the first keyword matched, so match order no longer affects the
routing decision.

Backend:
- config: KeywordTierRule model plus keyword_tier_rules, semantic_keyword_matching,
  embedding_model, and match_threshold on ComplexityRouterConfig, with a validator
  requiring an embedding model and rules when semantic matching is on
- complexity_router: evaluate keyword rules before scoring; lexical matches escalate
  to the most-severe matched tier (order-independent), and semantic mode reuses
  LiteLLMRouterEncoder + SemanticRouter to match paraphrases by cosine similarity,
  falling back to the scorer when nothing matches
- model management: clear complexity_routers on cache reload so config edits take effect

Frontend:
- Add Auto Router tab restores the Router Type radio (Auto-Router v2 recommended
  by default, Semantic Router still available) and sends keyword_tier_rules plus
  the semantic settings on the recommended path, instead of flattening keywords
  into custom_technical_keywords
- client-side guard blocks submit when semantic matching is enabled without an
  embedding model or without any keyword tier rules, mirroring the backend validator
- moved the "How Classification Works" explainer below Custom Technical Keywords
  and above Keyword Tier Overrides
- remove the Test Connection action from the recommended flow, which can't build a
  valid pre-save payload for a router (leaves a TODO for a JSON preview / config
  test follow-up)

Tests cover lexical escalation, semantic matching via the real library with injected
embeddings, the semantic config guard, config validation, the reload-clear
regression, and the frontend payload builder
2026-07-10 22:05:29 -07:00
Krrish Dholakia
109193f26a
feat(router): add LLM-based classifier option to complexity router (#32169)
* feat(router): add LLM-based classifier option to complexity router

Adds classifier_type: "heuristic" | "llm" to complexity_router_config.
When set to "llm", the router calls a configured model (e.g. a small
model like haiku) via structured output to pick the complexity tier,
falling back to the existing regex/keyword scorer on any error, empty
response, or unparseable output.

* feat(ui): add classifier_type option to complexity router UI, fix edit flow

Adds an "Advanced: Classification Method" section to ComplexityRouterConfig
with a heuristic/LLM toggle, revealing a classifier model picker and timeout
when LLM is selected.

Also fixes the auto router edit modal, which never rendered the complexity
router UI at all (it only handled the semantic router), and the "Edit Auto
Router" button visibility check, which was gated on auto_router_config and
never matched complexity router deployments.

* fix(router): attribute classifier calls to caller, raise default timeout

Forwards the original request's litellm_metadata into the classifier's
acompletion call. Without it, the proxy's cost-tracking gate sees no
user_api_key/team_id/user_id and silently drops spend logging and budget
accounting for every classifier call, letting an authenticated user rack
up unaccounted provider spend via repeated requests.

Also raises the default classifier timeout from 400ms to 3000ms (400ms
undershoots real LLM latency and would silently degrade to the heuristic
scorer on most requests) and corrects the module/class docstrings, which
still claimed zero external API calls after the llm classifier path was
added.

* fix(ci): resolve ruff strict-budget and frontend-lint failures

- Use PEP 585 generics (dict/tuple/list) in the new aclassify/_classify_with_llm
  signatures instead of typing.Dict/Tuple/List, and suppress BLE001 on the
  intentionally broad except in aclassify's fallback path with a reason.
- Fix prettier formatting in ComplexityRouterConfig.tsx.
- Regenerate eslint-metrics.json (was stale after the classifier UI changes).

* fix(ci): regenerate stale eslint-metrics.json

* fix(router): strip parent budget reservation from classifier metadata

The classifier's internal acompletion call previously forwarded the
parent request's full litellm_metadata, including its budget
reservation (user_api_key_budget_reservation / user_api_key_auth).
That reservation belongs to the routed completion the classifier is
deciding on, not to the classifier call itself, so it's now stripped
while key/team attribution fields are still forwarded for spend
logging.
2026-07-10 18:55:34 -07:00
Yuneng Jiang
e9246e924e
feat(team): add PATCH /team/{team_id} with JSON merge patch semantics
Add a RESTful PATCH /team/{team_id} that partially updates a team using RFC 7386 JSON Merge Patch. team_id comes from the path, and metadata is merged with the team's stored metadata instead of being replaced wholesale the way POST /team/update does: an omitted key is preserved, key: null deletes it, and any other value overwrites, recursing into nested objects. Every other field behaves the same as POST /team/update

The handler delegates to the existing update path, so authorization, budget checks, system-managed-key stripping, metadata encryption, cache refresh, and audit logging are shared rather than reimplemented. POST /team/update is untouched, so the change is purely additive
2026-07-10 18:46:13 -07:00
Tin
5dbd608e17 fix(mcp): reset the remove-app checkbox on a server switch so it never deletes the next server's stored app 2026-07-10 18:24:54 -07:00
Yuneng Jiang
72cbd8a658
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/data-table-design-exploration-f3f5e9 2026-07-10 18:18:03 -07:00
Yuneng Jiang
4c4dd1f05b
refactor(ui): use shadcn Label for the DataTable filter field
DataTableFilterField rendered a bare native label element. Swap it for the
shadcn Label primitive so the filter drawer's field labels share the same
typography and disabled-state handling as the rest of the form primitives
2026-07-10 18:13:33 -07:00
Tin
86506775c9 fix(mcp): preserve a stored client on OAuth-resume restore, add the edit upstream-mismatch warning, and type the credentials field 2026-07-10 18:06:54 -07:00
Yuneng Jiang
ae55170343
fix(ui): show filter-select label and shape loading skeletons per column
The workflow-runs Status filter leaked the internal "__all__" sentinel as its
displayed value because Base UI's Select.Value renders the raw value when no
items map or children function is given. Drop the sentinel and use Base UI's
native null handling: a null "All statuses" item plus a placeholder, with an
items map so a real selection renders its capitalized label rather than the
raw status string

The shared DataTable rendered every loading-skeleton cell as one identical
half-width bar, which read as a rigid grid instead of the table beneath it.
Vary the skeleton width per column and add a per-column skeleton shape hint
(text or twoLine) on ColumnMeta so identity columns like the workflow "Run"
cell get a two-line skeleton that matches their real content
2026-07-10 18:05:49 -07:00
ryan-crabbe-berri
fdfb122573
refactor(ui): convert caching page charts to shadcn/recharts (#32721)
* refactor(ui): convert caching page charts to shadcn/recharts

* test(ui): bind cache chart legend labels to fills so a category-order swap fails
2026-07-10 17:57:14 -07:00
Yuneng Jiang
a88a9bfcb2
feat(ui): add filter drawer and column visibility to shared DataTable
Adds server- and client-side column filtering to the shared DataTable via a
filterMode prop that mirrors the existing sorting and pagination modes, a global
search filter, a staged filter drawer ("Apply Filters" / "Reset") built on the
shadcn Sheet primitive (added via `npx shadcn add sheet`), and a table-aware
toolbar (search, refresh, active-filter chips, and a Columns menu). Also adds
skeleton loading rows, an icon empty state, and renders toolbar, table, and
pagination as a single card.

Migrates the two pilot tables onto the design as a proof of concept:
TeamVirtualKeysTable drives server-side filtering through the list API (key alias
via the search box, user via the drawer), and WorkflowRuns filters client-side in
memory. Both keep their existing behavioral tests green, with new coverage for the
filter drawer, the toolbar, the global search, and the server-filter query mapping.
2026-07-10 17:41:38 -07:00
Tin
1be846680a fix(mcp): show the upstream-mismatch warning on edit and return undefined from withoutMintedTokenCredentials so a restore never blanks a stored client 2026-07-10 17:22:33 -07:00
Yassin Kortam
3ea7f98725
feat(proxy): configure the coordination redis independently of the response cache (#32661)
* fix(proxy): build redis usage cache from REDIS_* env when cache backend is not Redis

Selecting a semantic (or any non-Redis-KV) response cache left
redis_usage_cache unset, silently downgrading cross-pod rate limits,
parallel-request limits, spend coordination, and the pod lock manager
to per-pod in-memory state. Fall back to a standalone RedisCache built
from REDIS_* environment variables, mirroring the existing
use_redis_transaction_buffer escape hatch, which now shares the same
helper.

Resolves LIT-3861

* feat(proxy): configure the coordination redis independently of the response cache

Adds general_settings.coordination_redis, an explicit block for the Redis
the proxy uses for cross-pod rate limits, parallel-request limits, spend
tracking, the pod lock manager, and shared health checks. Resolution order
is the explicit block, then a plain-Redis response-cache backend, then the
REDIS_* environment. Cluster and sentinel targets are supported, and a
cluster target now builds a RedisClusterCache so cluster-aware consumers
take the cluster path.

Admins can configure it from the Caching page of the dashboard via
/coordination_redis/settings, which reports which source is in effect,
redacts credentials on read, and offers a connection test. Settings saved
there are read back at startup so they take effect on restart.

Also fixes redis client construction so an explicitly configured host
outranks REDIS_URL in the environment. Previously the url branch stripped
the caller's host and port, so an explicit block, or a connection test
typed into the dashboard, silently targeted whatever REDIS_URL named

* fix(ui): move coordination_redis_settings into renamed _components directory

---------

Co-authored-by: Yucheng Zhu <yucheng@berri.ai>
2026-07-10 16:15:59 -07:00
Tin Chi Lo
8b8a28848c fix(ui): drop the saved qualifier from the OAuth client field labels
A plain optional label implies the field is persisted like any other form
field; the qualifier was only there to contrast with the removed not-saved
wording
2026-07-10 16:09:42 -07:00
Tin Chi Lo
3913a4af59 fix(ui): keep the original one-sentence DCR hint under the OAuth client ID field 2026-07-10 15:59:17 -07:00
Tin Chi Lo
2b4c054403 feat(ui): move the dcr_bridge toggle next to the OAuth app fields
Render DcrBridgeToggle inside PassthroughAuthorizeSection, after the OAuth
client ID/secret fields and just before the Authorize & Fetch Tools button,
in both the create and edit flows. Also update the section copy to say a
configured OAuth app is saved with the server, using the same wording as the
credential lifecycle rework in #32752 so whichever PR lands second rebases
cleanly
2026-07-10 15:47:05 -07:00
yuneng-jiang
eb7e4a567a
Merge pull request #32793 from BerriAI/litellm_/design-to-litellm-integration-7b0786
refactor(ui): full-height sidebar shell with content-scoped top bar
2026-07-10 15:31:48 -07:00
Yuneng Jiang
1c6d9faf7a
refactor(ui): move usage-card meter and sidebar button onto shared primitives
Addresses review nits on the sidebar shell. The Meter primitive now owns its bar color through a tone variant, so the usage card passes a tone instead of a bg-* class, and the near-limit tone goes back to 80% to match the previous usage indicator. The enterprise usage card is now explicitly gated on an active license, so it never renders for an unlicensed proxy rather than relying on seat/team data being null. The collapsed-rail control and the sidebar menu button render through the shadcn and Base UI button primitives instead of raw button elements; the menu button gains render/nativeButton passthrough while its group toggles stay native buttons, so the nav link leaves keep their link semantics. Adds a regression test that the card stays hidden without a license even when seat limits exist
2026-07-10 15:07:13 -07:00
Tin
1e78e96c5d fix(mcp): clear the DCR client ref and upstream warning on modal close, and reuse the ref in the temp OAuth payload 2026-07-10 14:45:54 -07:00
Tin
ececa9efcc test(mcp): speed up the auth-type-switch preserve tests so they do not time out under CI 2026-07-10 13:47:51 -07:00
Tin Chi Lo
47f33bda3f feat(ui): dcr_bridge toggle for client-forwarded MCP auth modes 2026-07-10 13:17:19 -07:00
Tin
a2f8e80a7b fix(mcp): rework the credential-field lifecycle so the OAuth app is upstream-scoped 2026-07-10 13:03:10 -07:00
ryan-crabbe-berri
81cd07118d
refactor(ui): colocate the skills view, keeping the AIHub-shared skill components (#32803)
* refactor(ui): colocate the skills view, keeping the AIHub-shared skill components

Group-1 split for the skills (claude_code_plugins) segment. It is a file-plus-
folder combo where part of the folder is shared with AIHub and the public model
hub: the skill types, skill_detail, MakeSkillPublicForm, and helpers stay in
@/components/claude_code_plugins (imported by AIHub's ModelHubTable and
SkillHubDashboard, plus public_model_hub, networking, and skill_hub_table_columns),
while the plugins-management view moves to skills/_components.

claude_code_plugins.tsx becomes skills/_components/index.tsx; add_plugin_form and
plugin_table move alongside it. The moved files' imports of the retained shared
files become @/components/claude_code_plugins paths, other escaping imports are
absolutized, and lint suppressions are re-keyed for moved files only (the staying
components keep their src/components keys). The shared components did not move, so
their consumers are untouched. No behavior change.

* refactor(ui): name the agents/guardrails view files instead of index.tsx

The moved view files were renamed to _components/index.tsx, which reads like a
barrel of re-exports rather than the single view component each actually is.
Rename them to match their default export (AgentsPanel.tsx, GuardrailsPanel.tsx)
and their colocated tests, and point page.tsx at the named file.
2026-07-10 12:34:36 -07:00
tin-berri
220aad0e7f
Merge pull request #32715 from BerriAI/litellm_lit4284_semantic_filter_fail_closed
fix(mcp): fail closed and surface semantic filter context window errors
2026-07-10 12:33:46 -07:00
yuneng-jiang
edb889bafb
Merge pull request #32680 from BerriAI/litellm_/elegant-edison-bf44a2
feat(ui): add shared composable DataTable component
2026-07-10 12:32:21 -07:00
Yuneng Jiang
50f002048e
fix(ui): scope the remaining e2e nav lookups to the new sidebar
login and internalUserIdentity used an unscoped "Virtual Keys" text check that now also matches the top-bar breadcrumb, and adminSettings navigated via antd menuitem roles the shadcn nav no longer emits. Scope these to the sidebar's complementary landmark and drive the Settings group by role (expand the button, then click the child link), matching the fixes already applied to the migration and navigation specs
2026-07-10 12:27:34 -07:00
Yuneng Jiang
94f27810fb
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/elegant-edison-bf44a2 2026-07-10 11:56:35 -07:00
ryan-crabbe-berri
270406b8ad
build(pre-commit): regenerate eslint-metrics.json instead of failing on drift (#32717)
The dashboard lint-budgets step ran check-lint-budgets.mjs in --check mode,
which fails and tells you to run `npm run lint:metrics` and re-stage by hand.
Add a --write mode that rewrites eslint-metrics.json from the same eslint
report, and have pre-commit use it, then flag drift via git diff so you
re-stage; this mirrors how the block below regenerates schema.d.ts. CI keeps
using --check, so it still fails on a stale committed metrics file.
2026-07-10 11:51:58 -07:00
Yuneng Jiang
87d979d399
fix(ui): keep the account menu in agent-plane mode and update e2e for the new sidebar
The redesigned sidebar + header shell is now scoped to the ai-gateway dashboard. Agent-control-plane (plugin) mode falls back to the original full-width Navbar, which carries the account menu, so preferences and sign-out stay reachable there; Chat and the public model hub already use that Navbar

Update the e2e specs the antd Menu -> shadcn nav swap broke. Sidebar items are now links/buttons rather than antd menuitems, and the top bar renders a breadcrumb whose current-page item is also a "Virtual Keys" link, so the migration and navigation smoke checks now scope their sidebar lookups to the complementary landmark and expand the new collapsible groups by data-slot. Also harden the collapsed-rail unit test to assert the icon and link rather than the CSS-hidden label
2026-07-10 11:51:23 -07:00
ryan-crabbe-berri
e2eee36438
chore(ui): make knip trustworthy and enforce dead-code in CI (#32727)
knip was producing garbage locally and was never wired into CI, so nobody
trusted it. Two structural problems: it silently degrades when deps are
missing (a partial worktree install flagged all 436 test files as unused),
and its config had blind spots that surfaced as false positives.

Fixes so a knip run means something:

- Register every playwright config (serverRootPath + migration variants), not
  just the main one. serverRootPath.config.ts is invoked via --config in
  test_server_root_path.yml, which knip can't see; it was falsely flagged as
  an unused file
- Treat src/components/ui/** as entry points. These are shadcn design-system
  primitives, intentionally part of the palette before every one is consumed;
  knip was flagging not-yet-used ones (e.g. select.tsx) as dead files and
  their sub-exports as unused. Marking the directory as the design-system
  surface is the correct fix, not deleting components someone is about to use
- Declare @ant-design/icons as a direct dependency. It was imported in ~198
  files but only resolved via antd hoisting, so every one showed up as an
  "unlisted dependency"
- Add an explicit vitest plugin block so test-file classification no longer
  rides on auto-detection
- Stage severities via rules: gate the now-clean categories (files,
  dependencies, unlisted, unresolved) as errors and keep exports/types/
  duplicates as warnings, so CI enforces what's at zero today while the
  remaining findings ratchet down in follow-ups
- Run npm run knip in the frontend-lint CI job, which installs with npm ci so
  it never sees a partial tree

knip now exits 0 with the gated categories clean
2026-07-10 11:50:27 -07:00
ryan-crabbe-berri
77a30a120c
refactor(ui): colocate agents and guardrails views, keeping shared selectors and types (#32728)
* refactor(ui): colocate agents and guardrails views, keeping shared selectors and types

The last two group-1 colocation splits. Both are file-plus-folder combos: the
page view is a top-level file (agents.tsx / guardrails.tsx) sitting beside a
supporting folder of the same name, and part of that folder is shared.

agents: agents/types (imported by the agents hook) stays in @/components/agents;
agents.tsx and the rest of the agents/ folder move into agents/_components (the
view file becomes _components/index.tsx).

guardrails: GuardrailSelector (imported by the Playground, the key edit view,
and the agents add-guardrail form) and types stay in @/components/guardrails;
guardrails.tsx and the other 47 folder files (including the tool_permission,
custom_code, content_filter, and llm_judge subfolders) move into
guardrails/_components.

Moved files' imports of the retained shared files become @/components paths,
other escaping relative imports are absolutized against @/, and moved test
files have their from/vi.mock/vi.importActual paths rewritten to match. Lint
suppressions are re-keyed for moved files only (the staying selector/types keep
their src/components keys). The shared selectors did not move, so their external
consumers are untouched. No behavior change.

* fix(ui): move the orphaned agents/guardrails view tests and drop dead GuardrailItem

Greptile follow-ups on the agents/guardrails colocation:

- agents.tsx and guardrails.tsx moved to their _components/index.tsx, but their
  sibling test files (src/components/agents.test.tsx, guardrails.test.tsx) were
  left behind still importing ./agents and ./guardrails, which broke a full
  vitest run. Move them to the matching _components/index.test.tsx and rewrite
  their view import to ./index, folder mocks to local ./ siblings, and
  networking to @/components/networking.
- Remove the unused GuardrailItem interface and its GuardrailDefinitionLocation
  import from the guardrails view (dead code carried over from before the move;
  state is typed as Guardrail[]).
2026-07-10 10:57:12 -07:00
devin-ai-integration[bot]
190ea0802d
fix(spend): sum multi-round session cost in logs UI (#32796)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
2026-07-10 10:44:33 -07:00
Yuneng Jiang
7d63e452f1
refactor(ui): move sidebar chrome onto shadcn primitives and whiten the sidebar
Follow-up to the full-height sidebar shell. Replaces hand-rolled markup in the sidebar, top bar, and account/usage docks with shadcn primitives so the surface reuses shared components instead of one-off elements

Adds three Base-UI-native primitives that follow the existing conventions (cva + data-slot, no Radix): Meter, Avatar, and Breadcrumb. Badge gains a render prop via Base UI useRender so it can render as an anchor, which activates the variant's existing [a&] styles

Wires the redesigned surface onto them: the version tag is an outline Badge linking to the release notes, the breadcrumb uses the Breadcrumb primitive, the Docs link is a ghost Button, the account initials use Avatar, and the Enterprise usage card uses Collapsible for its open state and Meter for the seat and team gauges. Meter is the correct element for a used-of-total measurement and Base UI ships it natively, so it replaces the hand-rolled bars

Sets the sidebar background to pure white by pointing the --sidebar token at oklch(1 0 0) in light mode, which keeps SidebarUsageCard consistent since it shares the token; the dark block is left untouched

Also repairs layout.test.tsx, which the shell refactor had left red: the dashboard shell now renders DashboardHeader in place of the old navbar, so the test mocks DashboardHeader and asserts on it instead of the navbar the layout no longer mounts
2026-07-10 10:30:36 -07:00
Tin
9bff278efe test(mcp): extract inline server fixtures so the eslint inline-object budget stays at baseline 2026-07-10 10:05:46 -07:00
Tin
cf1b407fbe fix(mcp): state the keep-existing convention for blank client fields and add explicit app removal on edit 2026-07-10 09:51:10 -07:00
Tin
57051d36d6 fix(mcp): keep admin-declared app credentials through OAuth invalidation for the client-forwarded modes 2026-07-10 09:41:25 -07:00
Yuneng Jiang
5a654c5c61
refactor(ui): full-height sidebar shell with content-scoped top bar
Move the admin dashboard to a standard fixed-viewport shell. The sidebar is now full-height with its own scrolling nav (fixed logo header, pinned footer) and the top bar sits only over the content, so the page can no longer scroll past the end of the sidebar

The brand, version, collapse toggle, and account menu move into the sidebar; the AI Gateway/Chat switch, docs/blog/community links, notifications, and worker switcher stay in the top bar. The sidebar is rebuilt on a new shadcn ui/sidebar primitive that uses the existing design-system tokens instead of the antd Menu

This is a pure move-around of the sidebar, header, and content with no behavioral change intended. Chat keeps its own shell and navbar and is deliberately out of scope
2026-07-10 09:30:33 -07:00
Tin Chi Lo
d2b7996170 test(ui): pin deriveErrorMessage against the ProxyException wire shape
Both automated reviewers assumed the semantic filter 400 reaches the
browser as FastAPI's flat detail dict and would render as raw JSON in
the test panel banner. The proxy converts a pre-call hook HTTPException
into a ProxyException that serializes as {"error": {"message": ...}},
which deriveErrorMessage unpacks first; pin that contract with direct
tests
2026-07-10 00:57:31 -07:00
Tin
931b617a51 feat(mcp): persist admin-entered OAuth app credentials for the client-forwarded modes 2026-07-10 00:45:38 -07:00
Tin Chi Lo
1e8c2f7240 fix(mcp): fail closed and surface semantic filter context window errors
Resolves LIT-4284

When the embedding model exceeded its context window, the MCP semantic
tool filter silently passed all tools through and reported N->N success
in the filter header; when the overflow happened while embedding tool
descriptions at router build time, the hook was never registered at all
and filtering was silently disabled

Semantic filtering now fails closed on context window overflows: the
request is rejected with HTTP 400 and a message that names the embedding
model and advises switching to one with a larger context window or
disabling the filter. Build time overflows are recorded on the filter so
the hook still registers and blocks MCP tool requests with the same
actionable error while leaving native-only requests untouched. The
dashboard test panel renders the backend message in an error banner
instead of a success state. OpenAI's embedding overflow message
(maximum input length is N tokens) now maps to ContextWindowExceededError
2026-07-10 00:41:54 -07:00
ryan-crabbe-berri
2a12707372
refactor(ui): colocate the policies view, keeping PolicySelector shared (#32720)
* refactor(ui): colocate the policies view, keeping PolicySelector shared

Group-1 colocation split. The policies folder lived in the shared src/components
dump but is only partly shared: PolicySelector (used by the Playground,
ComplianceUI, and key edit view) and its types stay in @/components/policies,
while the policy-management view (27 files: index, tables, forms, modals,
pipeline builder, and their tests) moves to policies/_components.

Moved files' imports of the retained shared files become @/components/policies
paths; other escaping relative imports are absolutized against the @/ alias
(including @/data/... and the repo test-utils via @/../tests/...), and moved
test files have both their `from` imports and `vi.mock` paths rewritten so the
mocks keep matching the source. Grandfathered lint suppressions for moved files
are re-keyed. PolicySelector did not move, so its external consumers are
untouched. No behavior change.

* fix(ui): keep PolicySelector.tsx eslint suppression at its original path

PolicySelector.tsx stays in src/components/policies (only the management view
moved to _components), but the suppression re-key wrongly moved its
no-nested-ternary entry to the phantom _components path, orphaning the real
file's suppression. Revert that one key. (Greptile P1 on #32720.)
2026-07-09 22:44:32 -07:00
ryan-crabbe-berri
3d5d5e1295
refactor(ui): colocate tag-management and vector-stores views, keeping the shared selectors (#32719)
Two of the group-1 colocation splits. Each of these folders lived in the shared
src/components dump but is only partly shared: the page's management view is
segment-owned, while a selector widget is reused by other features. So this
splits them rather than moving wholesale.

tag-management: TagSelector (used by playground) and its types stay in
@/components/tag_management; the management view (index, tag_info, TagTable,
CreateTagModal) moves to tag-management/_components.

vector-stores: VectorStoreSelector (used by organizations and playground) and
its types stay in @/components/vector_store_management; the rest of the
management UI moves to vector-stores/_components.

The moved files' imports of the retained shared files are rewritten to absolute
@/components paths, escaping relative imports are absolutized, and moved test
files have both their `from` imports and `vi.mock` paths rewritten to match.
Grandfathered lint suppressions for moved files are re-keyed. The external
consumers of the selectors are untouched (the selectors did not move). No
behavior change.
2026-07-09 22:19:11 -07:00
ryan-crabbe-berri
27cf064556
refactor(ui): colocate cost-tracking and prompts components into _components/ (#32716)
Renames each segment's local components/ folder to _components/ (private to the
route, matching Next's _ route-exclusion). Both folders are imported only by
their own page.tsx via the folder index (verified zero external importers
across src, tests, and e2e_tests), so each is a straight rename plus repointing
that one index import; a folder rename keeps every file at the same depth, so
all internal and relative imports are unaffected.

Grandfathered lint suppressions under the two folders (31 entries: cost-tracking
15, prompts 16) are re-keyed to the new paths with counts unchanged. No behavior
change.
2026-07-09 21:34:04 -07:00
ryan-crabbe-berri
592510ec18
feat(ui): shadcn charts foundation with tremor-compatible wrappers (#32668) 2026-07-09 18:18:52 -07:00
tin-berri
eec948dcb8
Merge pull request #32652 from BerriAI/litellm_mcp_stale_token_invalidation
fix(mcp): invalidate a browser-authorized upstream token when a mint-relevant field changes
2026-07-09 18:13:19 -07:00