diff --git a/ui/litellm-dashboard/src/components/lens/LensModeSwitch.tsx b/ui/litellm-dashboard/src/components/lens/LensModeSwitch.tsx
index 0cfa9e47bce..16bea129f86 100644
--- a/ui/litellm-dashboard/src/components/lens/LensModeSwitch.tsx
+++ b/ui/litellm-dashboard/src/components/lens/LensModeSwitch.tsx
@@ -57,15 +57,15 @@ export function LensModeSwitch({
setup?: string;
}) {
const connected = useWorkerConnected(workers);
- const settingsTitle = connected ? "Worker connected" : "Connect worker";
- const tabs = Object.entries(LENS_TABS).filter(([view]) => view !== "settings" || workers);
+ const workerTitle = connected ? "Worker connected" : "Connect worker";
+ const settingsTitle = workers === null ? LENS_TABS.settings : workerTitle;
return (
- {tabs.map(([view, label]) => {
+ {Object.entries(LENS_TABS).map(([view, label]) => {
const Icon = MODE_ICONS[view as LensTab];
const workerDisconnected = view === "settings" && workers !== null && !connected;
return (
diff --git a/ui/litellm-dashboard/src/components/lens/LensWorkspace.integration.test.tsx b/ui/litellm-dashboard/src/components/lens/LensWorkspace.integration.test.tsx
index ce99bbae283..d9a5b5826f0 100644
--- a/ui/litellm-dashboard/src/components/lens/LensWorkspace.integration.test.tsx
+++ b/ui/litellm-dashboard/src/components/lens/LensWorkspace.integration.test.tsx
@@ -280,8 +280,8 @@ describe("Lens interactive demo", () => {
});
renderWithProviders(, { onUrlUpdate });
const tabs = within(screen.getByRole("tablist", { name: "Lens" }));
- const settings = await tabs.findByRole("tab", { name: "Settings" });
- expect(settings).toHaveAttribute("title", "Worker connected");
+ const settings = tabs.getByRole("tab", { name: "Settings" });
+ await waitFor(() => expect(settings).toHaveAttribute("title", "Worker connected"));
await user.click(settings);
await expectUrl(onUrlUpdate, (url) => expect(url.get("tab")).toBe("settings"));
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
@@ -357,7 +357,7 @@ describe("Lens interactive demo", () => {
onUrlUpdate,
});
const panel = within(await screen.findByRole("region", { name: "Settings" }));
- await user.click(panel.getByText("Advanced options"));
+ await user.click(await panel.findByText("Advanced options"));
await user.click(panel.getByRole("switch", { name: "Use an existing virtual key" }));
await user.click(panel.getByRole("combobox", { name: "Charge analysis to" }));
await user.click(await screen.findByRole("option", { name: "Analysis" }));
@@ -378,18 +378,28 @@ describe("Lens interactive demo", () => {
expect(await screen.findByRole("region", { name: "New investigation" })).toBeVisible();
});
- it("hides the Settings tab for read-only sessions", async () => {
- renderWithProviders();
- expect(await screen.findByRole("tablist", { name: "Lens" })).toBeVisible();
- await waitFor(() => expect(network).toHaveBeenCalled());
- expect(screen.queryByRole("tab", { name: "Settings" })).not.toBeInTheDocument();
- });
-
- it("sends read-only sessions following a Settings link to the default tab", async () => {
+ it("opens Settings for read-only sessions without the worker controls", async () => {
renderWithProviders(, {
searchParams: "?tab=settings",
});
- expect(await screen.findByRole("tab", { name: "Traces", selected: true })).toBeVisible();
+ expect(await screen.findByRole("tab", { name: "Settings", selected: true })).toBeVisible();
+ const panel = within(screen.getByRole("region", { name: "Settings" }));
+ expect(await panel.findByRole("status")).toHaveTextContent("Tracing is not enabled");
+ expect(panel.getByRole("switch", { name: "Show the introduction on each new session" })).toBeVisible();
+ expect(panel.queryByRole("heading", { name: "Analysis worker" })).not.toBeInTheDocument();
+ });
+
+ it("shows the Settings tab before /lens answers and when it fails", async () => {
+ network.mockImplementation(async (input) =>
+ requestPath(input) === "/lens"
+ ? Response.json({ detail: "boom" }, { status: 500 })
+ : Response.json({ data: [], traces: true, requests: false }),
+ );
+ renderWithProviders();
+ const tabs = within(screen.getByRole("tablist", { name: "Lens" }));
+ expect(tabs.getByRole("tab", { name: "Settings" })).toHaveAttribute("title", "Settings");
+ await waitFor(() => expect(network.mock.calls.some(([input]) => requestPath(input) === "/lens")).toBe(true));
+ expect(tabs.getByRole("tab", { name: "Settings" })).toBeVisible();
});
it("turns the worker health dot off once heartbeats expire even when polling returns unchanged data", async () => {
@@ -412,8 +422,8 @@ describe("Lens interactive demo", () => {
});
renderWithProviders();
const tabs = within(screen.getByRole("tablist", { name: "Lens" }));
- const settings = await tabs.findByRole("tab", { name: "Settings" });
- expect(settings).toHaveAttribute("title", "Worker connected");
+ const settings = tabs.getByRole("tab", { name: "Settings" });
+ await waitFor(() => expect(settings).toHaveAttribute("title", "Worker connected"));
await vi.advanceTimersByTimeAsync(130000);
await waitFor(() => expect(settings).toHaveAttribute("title", "Connect worker"));
} finally {
diff --git a/ui/litellm-dashboard/src/components/lens/LensWorkspace.tsx b/ui/litellm-dashboard/src/components/lens/LensWorkspace.tsx
index ccd2f665564..9fa1c1df8d6 100644
--- a/ui/litellm-dashboard/src/components/lens/LensWorkspace.tsx
+++ b/ui/litellm-dashboard/src/components/lens/LensWorkspace.tsx
@@ -86,7 +86,7 @@ function LensContent({ userRole, readOnly }: Omit
const isAdmin = isProxyAdminRole(userRole);
const canConfigure = canViewInvestigations && !readOnly;
const defaultTab = lensId ? "investigations" : "traces";
- const activeTab = tab === "settings" && !canConfigure ? defaultTab : tab ?? defaultTab;
+ const activeTab = tab ?? defaultTab;
const intro = useLensIntro({ demo, settingUp });
const { activity, list } = useLensOverview(
canViewInvestigations,
@@ -192,21 +192,20 @@ function LensContent({ userRole, readOnly }: Omit
)}
- {workers && list && (
-
-
- New investigation
-
- ) : undefined
- }
- onOpenTraces={() => setTab("traces")}
- />
-
- )}
+
+
+ New investigation
+
+ ) : undefined
+ }
+ onOpenTraces={() => setTab("traces")}
+ />
+
void;
}) {
return (
-
-
-
-
+ {tracingEnabled !== undefined && }
+ {workers && (
+
+
+
+ )}
);