diff --git a/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.tsx b/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.tsx index 187e96df238..f7756471dec 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/InvestigationsView.tsx @@ -282,6 +282,7 @@ export function InvestigationsView({ results={results} agents={Array.isArray(agents.data) ? agents.data : []} queue={{ + api, lenses, workers: query.data?.workers ?? [], onConnect: () => setWorkerSetup(true), diff --git a/ui/litellm-dashboard/src/components/lens/investigations/detail/InvestigationDetail.tsx b/ui/litellm-dashboard/src/components/lens/investigations/detail/InvestigationDetail.tsx index 431bc9eefd3..a2f06a5af12 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/detail/InvestigationDetail.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/detail/InvestigationDetail.tsx @@ -7,6 +7,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { RunsTab } from "./RunsTab"; import { InvestigationProgress } from "../InvestigationProgress"; import { LiveRun } from "../live/LiveRun"; +import { LiveRunLoader } from "../live/LiveRunLoader"; import { type QueueContext } from "../useQueueReason"; import { liveJob } from "../../model/live"; import { RunNowDialog } from "./RunNowDialog"; @@ -109,7 +110,12 @@ export function InvestigationDetail({ onCancel={readOnly ? undefined : () => void update((api) => api.cancelRun(lens.id))} /> )} - {live && } + {live && + (queue ? ( + + ) : ( + + ))} {runNow && ( void; name: string; @@ -86,7 +88,10 @@ export function LiveDrawer({ phase={following ? phase : SETTLED} /> ) : ( -

Waiting for the first trace review.

+
+

Waiting for the first trace…

+ {waiting} +
)}
diff --git a/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRun.tsx b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRun.tsx index 1a4fcf44fe2..d046fbd4069 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRun.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRun.tsx @@ -50,6 +50,12 @@ export function LiveRun({ if (review) pin(review); setDrawerOpen(true); }; + const waiting = reason && ( + <> + + + + ); return ( <> @@ -57,14 +63,7 @@ export function LiveRun({ - - - - ) - } + waiting={waiting} playback={playback} reviewed={reviewed} selected={job.coverage.selected} @@ -97,6 +96,7 @@ export function LiveRun({ groups={conclusions(decided, job.settings.checks)} decided={decided.length} scope={job.reviewed > reviews.length ? `From the latest ${reviews.length} of ${job.reviewed} reviewed traces` : ""} + waiting={waiting} onPick={pin} onFollow={() => setPinned(null)} /> diff --git a/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRunLoader.tsx b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRunLoader.tsx new file mode 100644 index 00000000000..2e7e854365a --- /dev/null +++ b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveRunLoader.tsx @@ -0,0 +1,21 @@ +"use client"; + +import type { Job } from "../../model/types"; +import type { QueueContext } from "../useQueueReason"; +import { LiveRun } from "./LiveRun"; +import { useJobReviews } from "./useJobReviews"; + +export function LiveRunLoader({ + lensId, + job, + name, + queue, +}: { + lensId: string; + job: Job; + name: string; + queue: QueueContext; +}) { + const reviews = useJobReviews(queue.api, lensId, job); + return ; +} diff --git a/ui/litellm-dashboard/src/components/lens/investigations/live/LiveStrip.tsx b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveStrip.tsx index 3a7db401f5a..b493e286084 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/live/LiveStrip.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveStrip.tsx @@ -112,7 +112,7 @@ export function LiveStrip({ )}
- diff --git a/ui/litellm-dashboard/src/components/lens/investigations/live/useJobReviews.ts b/ui/litellm-dashboard/src/components/lens/investigations/live/useJobReviews.ts new file mode 100644 index 00000000000..e6c47f40119 --- /dev/null +++ b/ui/litellm-dashboard/src/components/lens/investigations/live/useJobReviews.ts @@ -0,0 +1,18 @@ +"use client"; + +import { useQuery } from "@tanstack/react-query"; +import { useState } from "react"; + +import { lensQueries } from "../../api/queries"; +import type { LensApi } from "../../api/service"; +import { appendPage, EMPTY_FEED, type ReviewFeed } from "../../model/live"; +import type { Job, Review } from "../../model/types"; + +export function useJobReviews(api: LensApi, lensId: string, job: Pick): readonly Review[] { + const [feed, setFeed] = useState(EMPTY_FEED); + const live = job.status === "queued" || job.status === "running"; + const { data } = useQuery(lensQueries.reviews(api, { lensId, jobId: job.id, after: feed.cursor, live })); + const next = data ? appendPage(feed, data) : feed; + if (next !== feed) setFeed(next); + return next.reviews; +} diff --git a/ui/litellm-dashboard/src/components/lens/investigations/useQueueReason.ts b/ui/litellm-dashboard/src/components/lens/investigations/useQueueReason.ts index 7337892d671..155f8564e59 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/useQueueReason.ts +++ b/ui/litellm-dashboard/src/components/lens/investigations/useQueueReason.ts @@ -2,10 +2,12 @@ import { useNow } from "@/hooks/useNow"; +import type { LensApi } from "../api/service"; import { queueReason, type QueueReason } from "../model/status"; import type { Job, Lens, LensList } from "../model/types"; export interface QueueContext { + api: LensApi; lenses: readonly Lens[]; workers: readonly LensList["workers"][number][]; onConnect: () => void;