From 2cffbdbc957e3a414f94ec3d066212ad444e752c Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Sat, 3 Oct 2026 17:24:04 -0700 Subject: [PATCH] fix(lens): list recorded agents in the run now dialog The run now agent field used a native datalist, whose suggestions do not show inside the modal dialog, so the agent list looked empty even though /lens/agents returned names. Use the same Combobox as investigation setup. --- .../InvestigationsView.integration.test.tsx | 39 +++++++++++++++++++ .../investigations/detail/RunNowDialog.tsx | 39 +++++++++++++------ 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.integration.test.tsx b/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.integration.test.tsx index 15fe9bca2d1..b0a7e720d1f 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.integration.test.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.integration.test.tsx @@ -280,6 +280,45 @@ it("runs with saved settings from Run now without opening setup, then accepts an }); }); +it("lists recorded agents in Run now and runs the one picked from the list", async () => { + testQueryClient.clear(); + vi.mocked(apiClient.get).mockImplementation(async (path) => { + if (path === "/lens") + return { + lenses: [lens], + tracing_enabled: true, + workers: [ + { + id: "worker", + name: "Worker", + revoked: false, + analysis_key_id: "a".repeat(64), + scope: lens.scope, + last_seen: new Date().toISOString(), + }, + ], + }; + if (path === "/lens/lens/runs") return lens.jobs; + if (path === "/lens/agents") return ["billing-agent", "support-bot"]; + if (path === "/lens/activity/available") return { traces: true, requests: false }; + return { data: [] }; + }); + vi.mocked(apiClient.post).mockResolvedValue(lens); + const user = userEvent.setup(); + renderWithProviders(); + await user.click(await screen.findByRole("button", { name: "Run now" })); + const dialog = within(await screen.findByRole("dialog", { name: "Run now" })); + await user.click(dialog.getByRole("combobox", { name: "Agent" })); + expect(await screen.findByRole("option", { name: "support-bot" })).toBeVisible(); + await user.click(await screen.findByRole("option", { name: "billing-agent" })); + expect(dialog.getByRole("combobox", { name: "Agent" })).toHaveValue("billing-agent"); + await user.click(dialog.getByRole("button", { name: "Run now" })); + expect(apiClient.post).toHaveBeenCalledWith("/lens/lens/runs", { + accessToken: "test", + body: { agent_name: "billing-agent" }, + }); +}); + it("offers the interactive demo without starting an investigation", async () => { window.history.replaceState({}, "", "/lens/"); testQueryClient.clear(); diff --git a/ui/litellm-dashboard/src/components/lens/investigations/detail/RunNowDialog.tsx b/ui/litellm-dashboard/src/components/lens/investigations/detail/RunNowDialog.tsx index 45a8ae06040..af843e52396 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/detail/RunNowDialog.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/detail/RunNowDialog.tsx @@ -3,6 +3,14 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; +import { + Combobox, + ComboboxContent, + ComboboxEmpty, + ComboboxInput, + ComboboxItem, + ComboboxList, +} from "@/components/ui/combobox"; import { Dialog, DialogContent, @@ -93,18 +101,25 @@ export function RunNowDialog({
Traces to review