From 4ae75d93d916cf37595b731d21855f8fffe0a7d0 Mon Sep 17 00:00:00 2001 From: Jesus Velarde Date: Tue, 3 Nov 2026 15:47:58 -0800 Subject: [PATCH 1/3] feat(ui): add opt-in [BETA] Enable Moyai setting Moyai stays hidden from the workspace switcher and shows as Disabled in UI settings until an admin turns on enable_moyai_ui. --- .../proxy_setting_endpoints.py | 6 +++ .../test_proxy_setting_endpoints.py | 30 +++++++++++++ .../Navbar/ViewSwitcher.integration.test.tsx | 17 ++++++- .../src/components/Navbar/ViewSwitcher.tsx | 35 ++++++++------- .../UISettings/UISettings.test.tsx | 40 ++++++++++++++++- .../AdminSettings/UISettings/UISettings.tsx | 45 ++++++++++++++++--- ui/litellm-dashboard/src/i18n/locales/en.json | 6 +++ 7 files changed, 154 insertions(+), 25 deletions(-) diff --git a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py index 30df407e853..5559ab8c829 100644 --- a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py +++ b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py @@ -375,6 +375,11 @@ class UISettings(LiteLLMBaseModel): description="If true, shows the Chat page in the UI sidebar, letting users chat with an LLM and connect their own MCP server credentials via OAuth.", ) + enable_moyai_ui: bool = Field( + default=False, + description="If true, shows Moyai in the UI workspace switcher and lets admins connect a Moyai deployment.", + ) + moyai_url: str | None = Field( default=None, description="URL of a connected Moyai deployment. When set, the Moyai entry in the UI navigation opens this deployment instead of the Moyai landing page.", @@ -430,6 +435,7 @@ ALLOWED_UI_SETTINGS_FIELDS: Final = { "disable_custom_api_keys", "disable_key_generate_for_org_admin", "enable_chat_ui", + "enable_moyai_ui", "moyai_url", TEAM_ADMIN_EDITABLE_TEAM_FIELDS_SETTING, } diff --git a/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py b/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py index 4087c3e6413..619c4372955 100644 --- a/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py +++ b/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py @@ -4035,6 +4035,36 @@ class TestEnableChatUISetting: assert response.json()["values"]["enable_chat_ui"] is False +class TestEnableMoyaiUISetting: + def test_moyai_ui_is_off_when_nothing_is_stored(self, mock_auth, monkeypatch): + TestPtuCostAttributionUISetting._mock_prisma(monkeypatch) + + response = client.get("/get/ui_settings") + + assert response.status_code == 200 + assert response.json()["values"]["enable_moyai_ui"] is False + + def test_admin_can_turn_moyai_ui_on(self, mock_auth, monkeypatch): + from litellm.proxy._types import UserAPIKeyAuth + from litellm.proxy.auth.user_api_key_auth import user_api_key_auth + + app.dependency_overrides[user_api_key_auth] = lambda: UserAPIKeyAuth( + user_id="test-user-123", + user_role=LitellmUserRoles.PROXY_ADMIN, + ) + monkeypatch.setattr("litellm.proxy.proxy_server.store_model_in_db", True) + mock_prisma = TestPtuCostAttributionUISetting._mock_prisma(monkeypatch) + + try: + response = client.patch("/update/ui_settings", json={"enable_moyai_ui": True}) + finally: + app.dependency_overrides.clear() + + assert response.status_code == 200 + upsert_data = mock_prisma.db.litellm_uisettings.upsert.call_args.kwargs["data"] + assert json.loads(upsert_data["create"]["ui_settings"])["enable_moyai_ui"] is True + + class TestApplyUserBudgetToTeamKeysUISetting: """``apply_user_budget_to_team_keys`` mirrors general_settings on every GET. diff --git a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx index 8786d7df631..7488ecede51 100644 --- a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx @@ -179,7 +179,9 @@ describe("ViewSwitcher", () => { it("should switch from Chat to the connected Moyai deployment", async () => { state.pathname = "/ui/chat"; - const settings = { values: { enable_chat_ui: true, moyai_url: "https://moyai.example.com" } }; + const settings = { + values: { enable_chat_ui: true, enable_moyai_ui: true, moyai_url: "https://moyai.example.com" }, + }; getUiSettingsMock.mockResolvedValue(settings); const user = userEvent.setup(); renderSwitcher(); @@ -189,7 +191,20 @@ describe("ViewSwitcher", () => { expect(assignSpy).toHaveBeenCalledWith("https://moyai.example.com"); }); + it("should hide Moyai from the switcher until an admin enables it", async () => { + getUiSettingsMock.mockResolvedValue({ + values: { enable_chat_ui: true, enable_moyai_ui: false, moyai_url: "https://moyai.example.com" }, + }); + const user = userEvent.setup(); + renderSwitcher(); + + await user.click(screen.getByRole("button", { name: "Switch workspace, current: AI Gateway" })); + await screen.findByRole("menuitem", { name: "Chat Chat UI for using LLMs, MCPs, Agents" }); + expect(screen.queryByRole("menuitem", { name: /Moyai/ })).not.toBeInTheDocument(); + }); + it("should keep the local Moyai route available when Chat is disabled", async () => { + getUiSettingsMock.mockResolvedValue({ values: { enable_chat_ui: false, enable_moyai_ui: true } }); const user = userEvent.setup(); renderSwitcher(); diff --git a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx index 8469a8edc35..28b86220e13 100644 --- a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.tsx @@ -87,6 +87,7 @@ export default function ViewSwitcher({ className, contentClassName }: ViewSwitch const pathname = usePathname(); const chatEnabled = Boolean(uiSettings?.values?.enable_chat_ui); + const moyaiEnabled = Boolean(uiSettings?.values?.enable_moyai_ui); const moyaiUrl = (uiSettings?.values?.moyai_url as string | undefined) ?? null; const normalizedPathname = (pathname ?? "").replace(/\/+$/, ""); @@ -137,6 +138,23 @@ export default function ViewSwitcher({ className, contentClassName }: ViewSwitch onClick: chatEnabled ? () => window.location.assign(uiHref(CHAT)) : undefined, }; + const moyaiItem: ViewSwitcherItem = { + key: MOYAI, + label: ( +
+ + + + Moyai{" "} + Cloud Coding Agent + + + {isMoyaiRoute && } +
+ ), + onClick: () => window.location.assign(moyaiUrl ?? uiHref(MOYAI)), + }; + const items: ViewSwitcherItem[] = [ ...modeEntries.map((e) => ({ key: e.key, @@ -152,22 +170,7 @@ export default function ViewSwitcher({ className, contentClassName }: ViewSwitch onClick: () => selectMode(e.key), })), chatItem, - { - key: MOYAI, - label: ( -
- - - - Moyai{" "} - Cloud Coding Agent - - - {isMoyaiRoute && } -
- ), - onClick: () => window.location.assign(moyaiUrl ?? uiHref(MOYAI)), - }, + ...(moyaiEnabled ? [moyaiItem] : []), ]; return ( diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx index c2bfd6076d4..cd8b8bd42f0 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx @@ -173,7 +173,11 @@ describe("UISettings", () => { buildSettingsResponse({ data: { ...buildSettingsResponse().data, - values: { ...buildSettingsResponse().data.values, moyai_url: "https://moyai.example.com" }, + values: { + ...buildSettingsResponse().data.values, + enable_moyai_ui: true, + moyai_url: "https://moyai.example.com", + }, }, }), ); @@ -192,12 +196,46 @@ describe("UISettings", () => { }); it("shows a link to the Moyai page when not connected", () => { + mockUseUISettings.mockReturnValue( + buildSettingsResponse({ + data: { + ...buildSettingsResponse().data, + values: { ...buildSettingsResponse().data.values, enable_moyai_ui: true }, + }, + }), + ); render(); expect(screen.getByText("Not connected")).toBeInTheDocument(); expect(screen.getByRole("link", { name: "Connect from the Moyai page" })).toHaveAttribute("href", "/ui/moyai"); }); + it("shows Moyai as disabled without a connect link until an admin enables it", () => { + render(); + + expect(screen.getByText("Disabled")).toBeInTheDocument(); + expect(screen.queryByText("Not connected")).not.toBeInTheDocument(); + expect(screen.queryByRole("link", { name: "Connect from the Moyai page" })).not.toBeInTheDocument(); + }); + + it("enables Moyai by patching enable_moyai_ui", () => { + const mutateMock = vi.fn((_settings, options) => { + options?.onSuccess?.(); + }); + mockUseUpdateUISettings.mockReturnValue({ mutate: mutateMock, isPending: false, error: null }); + render(); + + act(() => { + fireEvent.click(screen.getByRole("switch", { name: "Enable Moyai" })); + }); + + expect(mutateMock).toHaveBeenCalledWith( + { enable_moyai_ui: true }, + expect.objectContaining({ onSuccess: expect.any(Function) }), + ); + expect(toast.success).toHaveBeenCalledWith("UI settings updated successfully"); + }); + it("should toggle require auth for public AI Hub setting and call update", () => { const mutateMock = vi.fn((_settings, options) => { options?.onSuccess?.(); diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx index 6fe86c0f352..aec2c294006 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx @@ -1,6 +1,7 @@ "use client"; import { useTranslation } from "react-i18next"; +import type { TFunction } from "i18next"; import { useTerminology } from "@/contexts/TerminologyContext"; import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings"; import { useUpdateUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUpdateUISettings"; @@ -53,6 +54,12 @@ function SettingRow({ ); } +function moyaiStatusLabel(t: TFunction, isEnabled: boolean, url: string | null): string { + if (!isEnabled) return t("adminPanel.uiSettings.moyai.disabled"); + if (url) return t("adminPanel.uiSettings.moyai.connectedTo", { url }); + return t("adminPanel.uiSettings.moyai.notConnected"); +} + export default function UISettings() { const { t } = useTranslation(); const term = useTerminology(); @@ -68,6 +75,7 @@ export default function UISettings() { const forwardLLMProviderAuthHeadersProperty = schema?.properties?.forward_llm_provider_auth_headers; const enableProjectsUIProperty = schema?.properties?.enable_projects_ui; const enableChatUIProperty = schema?.properties?.enable_chat_ui; + const enableMoyaiUIProperty = schema?.properties?.enable_moyai_ui; const enabledPagesProperty = schema?.properties?.enabled_ui_pages_internal_users; const disableAgentsProperty = schema?.properties?.disable_agents_for_internal_users; const allowAgentsTeamAdminsProperty = schema?.properties?.allow_agents_for_team_admins; @@ -81,6 +89,8 @@ export default function UISettings() { "last_7_days"; const usageRangeConfigOwned = data?.source?.usage_default_time_range === "config"; const moyaiUrl = (values.moyai_url as string | undefined) ?? null; + const isMoyaiEnabled = Boolean(values.enable_moyai_ui); + const moyaiStatus = moyaiStatusLabel(t, isMoyaiEnabled, moyaiUrl); const isDisabledForInternalUsers = Boolean(values.disable_model_add_for_internal_users); const isDisabledTeamAdminDeleteTeamUser = Boolean(values.disable_team_admin_delete_team_user); const isAgentsDisabled = Boolean(values.disable_agents_for_internal_users); @@ -183,6 +193,20 @@ export default function UISettings() { ); }; + const handleToggleEnableMoyaiUI = (checked: boolean) => { + updateSettings( + { enable_moyai_ui: checked }, + { + onSuccess: () => { + toast.success(t("adminPanel.uiSettings.toasts.updated")); + }, + onError: (error) => { + toast.fromError(error); + }, + }, + ); + }; + const handleToggleRequireAuthForPublicAIHub = (checked: boolean) => { updateSettings( { require_auth_for_public_ai_hub: checked }, @@ -447,6 +471,16 @@ export default function UISettings() { enableChatUIProperty?.description ?? t("adminPanel.uiSettings.settings.enableChat.description") } /> + @@ -454,17 +488,14 @@ export default function UISettings() {

Moyai

-

- {moyaiUrl - ? t("adminPanel.uiSettings.moyai.connectedTo", { url: moyaiUrl }) - : t("adminPanel.uiSettings.moyai.notConnected")} -

+

{moyaiStatus}

- {moyaiUrl ? ( + {moyaiUrl && ( - ) : ( + )} + {!moyaiUrl && isMoyaiEnabled && ( {t("adminPanel.uiSettings.moyai.connectLink")} diff --git a/ui/litellm-dashboard/src/i18n/locales/en.json b/ui/litellm-dashboard/src/i18n/locales/en.json index b4b78c53f38..f78be1523fc 100644 --- a/ui/litellm-dashboard/src/i18n/locales/en.json +++ b/ui/litellm-dashboard/src/i18n/locales/en.json @@ -2853,6 +2853,11 @@ "label": "Enable Chat page (page will refresh)", "description": "If enabled, shows the Chat page in the UI sidebar, letting users chat with an LLM and connect their own MCP server credentials via OAuth." }, + "enableMoyai": { + "ariaLabel": "Enable Moyai", + "label": "[BETA] Enable Moyai", + "description": "If enabled, shows Moyai in the workspace switcher and lets admins connect a Moyai deployment." + }, "disableAgents": { "label": "Disable agents for internal users" }, @@ -2877,6 +2882,7 @@ "moyai": { "connectedTo": "Connected to {{url}}", "notConnected": "Not connected", + "disabled": "Disabled", "disconnect": "Disconnect", "connectLink": "Connect from the Moyai page" } From 5ef1eb8c848ab3faa30b123888aeb7567583acc5 Mon Sep 17 00:00:00 2001 From: Jesus Velarde Date: Tue, 3 Nov 2026 16:01:39 -0800 Subject: [PATCH 2/3] feat(ui): make Moyai on by default with an opt-out toggle --- .../proxy_setting_endpoints.py | 2 +- .../test_proxy_setting_endpoints.py | 16 ++++++++++---- .../Navbar/ViewSwitcher.integration.test.tsx | 2 +- .../UISettings/UISettings.test.tsx | 22 ++++++++++++++++--- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py index 5559ab8c829..715a32abc38 100644 --- a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py +++ b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py @@ -376,7 +376,7 @@ class UISettings(LiteLLMBaseModel): ) enable_moyai_ui: bool = Field( - default=False, + default=True, description="If true, shows Moyai in the UI workspace switcher and lets admins connect a Moyai deployment.", ) diff --git a/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py b/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py index 619c4372955..0a599052c83 100644 --- a/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py +++ b/tests/unit/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py @@ -4036,15 +4036,23 @@ class TestEnableChatUISetting: class TestEnableMoyaiUISetting: - def test_moyai_ui_is_off_when_nothing_is_stored(self, mock_auth, monkeypatch): + def test_moyai_ui_is_on_when_nothing_is_stored(self, mock_auth, monkeypatch): TestPtuCostAttributionUISetting._mock_prisma(monkeypatch) response = client.get("/get/ui_settings") + assert response.status_code == 200 + assert response.json()["values"]["enable_moyai_ui"] is True + + def test_admin_can_turn_moyai_ui_off(self, mock_auth, monkeypatch): + TestPtuCostAttributionUISetting._mock_prisma(monkeypatch, stored={"enable_moyai_ui": False}) + + response = client.get("/get/ui_settings") + assert response.status_code == 200 assert response.json()["values"]["enable_moyai_ui"] is False - def test_admin_can_turn_moyai_ui_on(self, mock_auth, monkeypatch): + def test_admin_can_patch_moyai_ui_off(self, mock_auth, monkeypatch): from litellm.proxy._types import UserAPIKeyAuth from litellm.proxy.auth.user_api_key_auth import user_api_key_auth @@ -4056,13 +4064,13 @@ class TestEnableMoyaiUISetting: mock_prisma = TestPtuCostAttributionUISetting._mock_prisma(monkeypatch) try: - response = client.patch("/update/ui_settings", json={"enable_moyai_ui": True}) + response = client.patch("/update/ui_settings", json={"enable_moyai_ui": False}) finally: app.dependency_overrides.clear() assert response.status_code == 200 upsert_data = mock_prisma.db.litellm_uisettings.upsert.call_args.kwargs["data"] - assert json.loads(upsert_data["create"]["ui_settings"])["enable_moyai_ui"] is True + assert json.loads(upsert_data["create"]["ui_settings"])["enable_moyai_ui"] is False class TestApplyUserBudgetToTeamKeysUISetting: diff --git a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx index 7488ecede51..8134c744e65 100644 --- a/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx +++ b/ui/litellm-dashboard/src/components/Navbar/ViewSwitcher.integration.test.tsx @@ -191,7 +191,7 @@ describe("ViewSwitcher", () => { expect(assignSpy).toHaveBeenCalledWith("https://moyai.example.com"); }); - it("should hide Moyai from the switcher until an admin enables it", async () => { + it("should hide Moyai from the switcher when an admin turns it off", async () => { getUiSettingsMock.mockResolvedValue({ values: { enable_chat_ui: true, enable_moyai_ui: false, moyai_url: "https://moyai.example.com" }, }); diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx index cd8b8bd42f0..bd043e5b61d 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx @@ -210,7 +210,15 @@ describe("UISettings", () => { expect(screen.getByRole("link", { name: "Connect from the Moyai page" })).toHaveAttribute("href", "/ui/moyai"); }); - it("shows Moyai as disabled without a connect link until an admin enables it", () => { + it("shows Moyai as disabled without a connect link when an admin turns it off", () => { + mockUseUISettings.mockReturnValue( + buildSettingsResponse({ + data: { + ...buildSettingsResponse().data, + values: { ...buildSettingsResponse().data.values, enable_moyai_ui: false }, + }, + }), + ); render(); expect(screen.getByText("Disabled")).toBeInTheDocument(); @@ -218,11 +226,19 @@ describe("UISettings", () => { expect(screen.queryByRole("link", { name: "Connect from the Moyai page" })).not.toBeInTheDocument(); }); - it("enables Moyai by patching enable_moyai_ui", () => { + it("turns Moyai off by patching enable_moyai_ui", () => { const mutateMock = vi.fn((_settings, options) => { options?.onSuccess?.(); }); mockUseUpdateUISettings.mockReturnValue({ mutate: mutateMock, isPending: false, error: null }); + mockUseUISettings.mockReturnValue( + buildSettingsResponse({ + data: { + ...buildSettingsResponse().data, + values: { ...buildSettingsResponse().data.values, enable_moyai_ui: true }, + }, + }), + ); render(); act(() => { @@ -230,7 +246,7 @@ describe("UISettings", () => { }); expect(mutateMock).toHaveBeenCalledWith( - { enable_moyai_ui: true }, + { enable_moyai_ui: false }, expect.objectContaining({ onSuccess: expect.any(Function) }), ); expect(toast.success).toHaveBeenCalledWith("UI settings updated successfully"); From 6f8b22d03ae6bcb55d961b1e1257b16cc2213e66 Mon Sep 17 00:00:00 2001 From: Jesus Velarde Date: Tue, 3 Nov 2026 16:36:09 -0800 Subject: [PATCH 3/3] fix(ui): lock the Moyai switch when the config file sets enable_moyai_ui --- .../UISettings/UISettings.test.tsx | 16 +++++++++++ .../AdminSettings/UISettings/UISettings.tsx | 28 ++++++++++++------- ui/litellm-dashboard/src/i18n/locales/en.json | 3 +- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx index bd043e5b61d..4aade313698 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx @@ -226,6 +226,22 @@ describe("UISettings", () => { expect(screen.queryByRole("link", { name: "Connect from the Moyai page" })).not.toBeInTheDocument(); }); + it("locks the Moyai switch when the config file owns enable_moyai_ui", () => { + mockUseUISettings.mockReturnValue( + buildSettingsResponse({ + data: { + ...buildSettingsResponse().data, + values: { ...buildSettingsResponse().data.values, enable_moyai_ui: false }, + source: { enable_moyai_ui: "config" }, + }, + }), + ); + render(); + + expect(screen.getByRole("switch", { name: "Enable Moyai" })).toHaveAttribute("aria-disabled", "true"); + expect(screen.getByText(/Managed by general_settings.enable_moyai_ui in the config file/)).toBeInTheDocument(); + }); + it("turns Moyai off by patching enable_moyai_ui", () => { const mutateMock = vi.fn((_settings, options) => { options?.onSuccess?.(); diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx index aec2c294006..d95232d013f 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx @@ -90,6 +90,7 @@ export default function UISettings() { const usageRangeConfigOwned = data?.source?.usage_default_time_range === "config"; const moyaiUrl = (values.moyai_url as string | undefined) ?? null; const isMoyaiEnabled = Boolean(values.enable_moyai_ui); + const moyaiConfigOwned = data?.source?.enable_moyai_ui === "config"; const moyaiStatus = moyaiStatusLabel(t, isMoyaiEnabled, moyaiUrl); const isDisabledForInternalUsers = Boolean(values.disable_model_add_for_internal_users); const isDisabledTeamAdminDeleteTeamUser = Boolean(values.disable_team_admin_delete_team_user); @@ -471,16 +472,23 @@ export default function UISettings() { enableChatUIProperty?.description ?? t("adminPanel.uiSettings.settings.enableChat.description") } /> - +
+ + {moyaiConfigOwned && ( +

+ {t("adminPanel.uiSettings.settings.enableMoyai.managedByConfig")} +

+ )} +
diff --git a/ui/litellm-dashboard/src/i18n/locales/en.json b/ui/litellm-dashboard/src/i18n/locales/en.json index f78be1523fc..f3903ca4f27 100644 --- a/ui/litellm-dashboard/src/i18n/locales/en.json +++ b/ui/litellm-dashboard/src/i18n/locales/en.json @@ -2856,7 +2856,8 @@ "enableMoyai": { "ariaLabel": "Enable Moyai", "label": "[BETA] Enable Moyai", - "description": "If enabled, shows Moyai in the workspace switcher and lets admins connect a Moyai deployment." + "description": "If enabled, shows Moyai in the workspace switcher and lets admins connect a Moyai deployment.", + "managedByConfig": "Managed by general_settings.enable_moyai_ui in the config file. Change it there." }, "disableAgents": { "label": "Disable agents for internal users"