From 2d576b5695595d79988c37f27404c895e6bb3bf7 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Thu, 11 Jun 2026 18:17:06 -0700 Subject: [PATCH] feat(ui): migrate mcp-servers, search-tools, tag-management, vector-stores, and memory to path routes (#30261) * feat(ui): cut mcp-servers, search-tools, tag-management, vector-stores, and memory over to path routes Continues the page-by-page App Router migration. All five legacy switch arms passed only accessToken/userRole/userID, so each route wrapper is a thin useAuthorized() + render. MIGRATED_PAGES routes the sidebar and redirects the legacy ?page= URLs; the e2e fixture picks all five up in the migration smoke and sidebar specs automatically. * refactor(ui): colocate MemoryView under the memory route The legacy switch was its only importer, so the three files move wholesale into (dashboard)/memory/components. mcp_tools, SearchTools, tag_management, and vector_store_management stay at src/components for now: each has importers on other pages (teams, playground, guardrails), so their colocation needs a shared/page split as a follow-up. --- .../e2e_tests/fixtures/migratedPages.ts | 10 +++++++--- ui/litellm-dashboard/eslint-suppressions.json | 2 +- .../src/app/(dashboard)/mcp-servers/page.tsx | 9 +++++++++ .../memory/components}/MemoryEditModal.tsx | 2 +- .../(dashboard)/memory/components}/MemoryView.tsx | 4 ++-- .../(dashboard)/memory/components}/index.tsx | 0 .../src/app/(dashboard)/memory/page.tsx | 9 +++++++++ ui/litellm-dashboard/src/app/(dashboard)/page.tsx | 15 --------------- .../src/app/(dashboard)/search-tools/page.tsx | 9 +++++++++ .../src/app/(dashboard)/tag-management/page.tsx | 9 +++++++++ .../src/app/(dashboard)/vector-stores/page.tsx | 9 +++++++++ .../src/utils/migratedPages.test.ts | 11 +++++++++++ ui/litellm-dashboard/src/utils/migratedPages.ts | 5 +++++ 13 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx rename ui/litellm-dashboard/src/{components/MemoryView => app/(dashboard)/memory/components}/MemoryEditModal.tsx (98%) rename ui/litellm-dashboard/src/{components/MemoryView => app/(dashboard)/memory/components}/MemoryView.tsx (99%) rename ui/litellm-dashboard/src/{components/MemoryView => app/(dashboard)/memory/components}/index.tsx (100%) create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx diff --git a/ui/litellm-dashboard/e2e_tests/fixtures/migratedPages.ts b/ui/litellm-dashboard/e2e_tests/fixtures/migratedPages.ts index f2a8fc45f12..a56ce79d8f1 100644 --- a/ui/litellm-dashboard/e2e_tests/fixtures/migratedPages.ts +++ b/ui/litellm-dashboard/e2e_tests/fixtures/migratedPages.ts @@ -10,9 +10,8 @@ * * Keep this in lockstep with MIGRATED_PAGES in src/utils/migratedPages.ts. * Pending (add as each PR lands): the leaf-pages batch - * (caching, cost-tracking, guardrails, logs, mcp-servers, memory, - * policies, prompts, search-tools, skills, tag-management, tool-policies, - * transform-request, ui-theme, vector-stores). + * (caching, cost-tracking, guardrails, logs, policies, prompts, skills, + * tool-policies, transform-request, ui-theme). */ export const MIGRATED_E2E_PAGES: Record = { api_ref: "api-reference", @@ -22,6 +21,11 @@ export const MIGRATED_E2E_PAGES: Record = { budgets: "budgets", workflows: "workflows", "guardrails-monitor": "guardrails-monitor", + "mcp-servers": "mcp-servers", + "search-tools": "search-tools", + "tag-management": "tag-management", + "vector-stores": "vector-stores", + memory: "memory", }; export const MIGRATED_E2E_SEGMENTS: string[] = [...new Set(Object.values(MIGRATED_E2E_PAGES))]; diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json index 9f7c2e5c389..b838736ba26 100644 --- a/ui/litellm-dashboard/eslint-suppressions.json +++ b/ui/litellm-dashboard/eslint-suppressions.json @@ -444,7 +444,7 @@ "count": 1 } }, - "src/components/MemoryView/MemoryView.tsx": { + "src/app/(dashboard)/memory/components/MemoryView.tsx": { "react-hooks/set-state-in-effect": { "count": 1 } diff --git a/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx new file mode 100644 index 00000000000..dfc7ca15896 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/page.tsx @@ -0,0 +1,9 @@ +"use client"; + +import { MCPServers } from "@/components/mcp_tools"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; + +export default function McpServers() { + const { accessToken, userRole, userId } = useAuthorized(); + return ; +} diff --git a/ui/litellm-dashboard/src/components/MemoryView/MemoryEditModal.tsx b/ui/litellm-dashboard/src/app/(dashboard)/memory/components/MemoryEditModal.tsx similarity index 98% rename from ui/litellm-dashboard/src/components/MemoryView/MemoryEditModal.tsx rename to ui/litellm-dashboard/src/app/(dashboard)/memory/components/MemoryEditModal.tsx index 9e8c18a7f9d..594b35ddade 100644 --- a/ui/litellm-dashboard/src/components/MemoryView/MemoryEditModal.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/memory/components/MemoryEditModal.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { Form, Input, Modal, Typography } from "antd"; -import type { MemoryRow } from "../networking"; +import type { MemoryRow } from "@/components/networking"; const { Text } = Typography; diff --git a/ui/litellm-dashboard/src/components/MemoryView/MemoryView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/memory/components/MemoryView.tsx similarity index 99% rename from ui/litellm-dashboard/src/components/MemoryView/MemoryView.tsx rename to ui/litellm-dashboard/src/app/(dashboard)/memory/components/MemoryView.tsx index b859072d359..402de29e0c5 100644 --- a/ui/litellm-dashboard/src/components/MemoryView/MemoryView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/memory/components/MemoryView.tsx @@ -12,9 +12,9 @@ import { ReloadOutlined, SearchOutlined, } from "@ant-design/icons"; -import { MemoryRow, createMemory, deleteMemory, fetchMemoryList, updateMemory } from "../networking"; +import { MemoryRow, createMemory, deleteMemory, fetchMemoryList, updateMemory } from "@/components/networking"; import { MemoryEditModal } from "./MemoryEditModal"; -import DeleteResourceModal from "../common_components/DeleteResourceModal"; +import DeleteResourceModal from "@/components/common_components/DeleteResourceModal"; const { Text, Paragraph, Title } = Typography; diff --git a/ui/litellm-dashboard/src/components/MemoryView/index.tsx b/ui/litellm-dashboard/src/app/(dashboard)/memory/components/index.tsx similarity index 100% rename from ui/litellm-dashboard/src/components/MemoryView/index.tsx rename to ui/litellm-dashboard/src/app/(dashboard)/memory/components/index.tsx diff --git a/ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx new file mode 100644 index 00000000000..6eb0fb57143 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/memory/page.tsx @@ -0,0 +1,9 @@ +"use client"; + +import { MemoryView } from "./components/MemoryView"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; + +export default function Memory() { + const { accessToken, userRole, userId } = useAuthorized(); + return ; +} diff --git a/ui/litellm-dashboard/src/app/(dashboard)/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/page.tsx index 0bf79f492f1..9758786331f 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/page.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/page.tsx @@ -14,7 +14,6 @@ import GeneralSettings from "@/components/general_settings"; import GuardrailsPanel from "@/components/guardrails"; import PoliciesPanel from "@/components/policies"; import { Team } from "@/components/key_team_helpers/key_list"; -import { MCPServers } from "@/components/mcp_tools"; import ModelHubTable from "@/components/AIHub/ModelHubTable"; import { Organization, proxyBaseUrl, getInProductNudgesCall } from "@/components/networking"; import NewUsagePage from "@/components/UsagePage/components/UsagePageView"; @@ -24,17 +23,13 @@ import Organizations, { fetchOrganizations } from "@/components/organizations"; import PassThroughSettings from "@/components/pass_through_settings"; import PromptsPanel from "@/components/prompts"; import PublicModelHub from "@/components/public_model_hub"; -import { SearchTools } from "@/components/SearchTools"; import Settings from "@/components/settings"; import { SurveyPrompt, SurveyModal, ClaudeCodePrompt, ClaudeCodeModal } from "@/components/survey"; -import TagManagement from "@/components/tag_management"; import TransformRequestPanel from "@/components/transform_request"; import UIThemeSettings from "@/components/ui_theme_settings"; import Usage from "@/components/usage"; import UserDashboard from "@/components/user_dashboard"; -import VectorStoreManagement from "@/components/vector_store_management"; import ToolPoliciesView from "@/components/ToolPoliciesView"; -import { MemoryView } from "@/components/MemoryView"; import SpendLogsTable from "@/components/view_logs"; import ViewUserDashboard from "@/components/view_users"; import { useAuth } from "@/contexts/AuthContext"; @@ -433,20 +428,10 @@ function CreateKeyPageContent() { accessToken={accessToken} premiumUser={premiumUser} /> - ) : page == "mcp-servers" ? ( - - ) : page == "search-tools" ? ( - - ) : page == "tag-management" ? ( - ) : page == "skills" || page == "claude-code-plugins" ? ( - ) : page == "vector-stores" ? ( - ) : page == "tool-policies" ? ( - ) : page == "memory" ? ( - ) : page == "new_usage" ? ( ) : ( diff --git a/ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx new file mode 100644 index 00000000000..6616ee0efe0 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/search-tools/page.tsx @@ -0,0 +1,9 @@ +"use client"; + +import { SearchTools } from "@/components/SearchTools"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; + +export default function SearchToolsPage() { + const { accessToken, userRole, userId } = useAuthorized(); + return ; +} diff --git a/ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx new file mode 100644 index 00000000000..8a6ffd67388 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/tag-management/page.tsx @@ -0,0 +1,9 @@ +"use client"; + +import TagManagement from "@/components/tag_management"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; + +export default function TagManagementPage() { + const { accessToken, userRole, userId } = useAuthorized(); + return ; +} diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx new file mode 100644 index 00000000000..ba280c1c313 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/page.tsx @@ -0,0 +1,9 @@ +"use client"; + +import VectorStoreManagement from "@/components/vector_store_management"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; + +export default function VectorStores() { + const { accessToken, userRole, userId } = useAuthorized(); + return ; +} diff --git a/ui/litellm-dashboard/src/utils/migratedPages.test.ts b/ui/litellm-dashboard/src/utils/migratedPages.test.ts index e837cd33b3d..656b91a6c32 100644 --- a/ui/litellm-dashboard/src/utils/migratedPages.test.ts +++ b/ui/litellm-dashboard/src/utils/migratedPages.test.ts @@ -64,6 +64,17 @@ describe("migratedHref / legacyPageHref", () => { expect(MIGRATED_PAGES.workflows).toBe("workflows"); expect(MIGRATED_PAGES["guardrails-monitor"]).toBe("guardrails-monitor"); }); + + it("maps the mcp-servers, search-tools, tag-management, vector-stores, and memory ids to their routes", async () => { + vi.doMock("@/components/networking", () => ({ serverRootPath: "/" })); + const { MIGRATED_PAGES } = await import("./migratedPages"); + + expect(MIGRATED_PAGES["mcp-servers"]).toBe("mcp-servers"); + expect(MIGRATED_PAGES["search-tools"]).toBe("search-tools"); + expect(MIGRATED_PAGES["tag-management"]).toBe("tag-management"); + expect(MIGRATED_PAGES["vector-stores"]).toBe("vector-stores"); + expect(MIGRATED_PAGES.memory).toBe("memory"); + }); }); describe("dev server (NODE_ENV=development)", () => { diff --git a/ui/litellm-dashboard/src/utils/migratedPages.ts b/ui/litellm-dashboard/src/utils/migratedPages.ts index 1ab854f582d..8f8a21d97c6 100644 --- a/ui/litellm-dashboard/src/utils/migratedPages.ts +++ b/ui/litellm-dashboard/src/utils/migratedPages.ts @@ -18,6 +18,11 @@ export const MIGRATED_PAGES: Record = { budgets: "budgets", workflows: "workflows", "guardrails-monitor": "guardrails-monitor", + "mcp-servers": "mcp-servers", + "search-tools": "search-tools", + "tag-management": "tag-management", + "vector-stores": "vector-stores", + memory: "memory", }; function uiBase(): string {