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 2c4f37fcf6f..1a9d2297593 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/detail/InvestigationDetail.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/detail/InvestigationDetail.tsx @@ -105,7 +105,7 @@ export function InvestigationDetail({ onCancel={readOnly ? undefined : () => void update((api) => api.cancelRun(lens.id))} /> )} - {live && } + {live && } {runNow && ( (null); - const playback = useReviewPlayback(job.reviews, live); - const model = analysisModel([...job.reviews.map((r) => r.model), ...modelsUsed(job.steps), job.settings.model]); - const { review: focused, following } = focusedReview(job.reviews, pinned, playback.current); - const issues = issueCount(job); + const playback = useReviewPlayback(reviews, live); + const withReviews = { ...job, reviews: [...reviews] }; + const model = analysisModel([...reviews.map((r) => r.model), ...modelsUsed(job.steps), job.settings.model]); + const { review: focused, following } = focusedReview(reviews, pinned, playback.current); + const issues = issueCount(withReviews); const reviewed = live ? shownCount(job.reviewed, playback) : job.reviewed; + const decided = decidedReviews(playback, playback.phase.verdict); + const pin = (review: Review) => setPinned(review === playback.current ? null : reviewKey(review)); const open = (review?: Review) => { - setPinned(review && review !== playback.current ? reviewKey(review) : null); + if (review) pin(review); setDrawerOpen(true); }; return ( <> - {stripOpen && ( + {stripOpen ? ( setStripOpen(false)} /> - )} - {!stripOpen && ( + ) : ( setStripOpen(true)} @@ -62,15 +65,17 @@ export function LiveRun({ job, name }: { job: Job; name: string }) { onClose={() => setDrawerOpen(false)} name={name} model={model} - job={job} + status={job.status} + reviewed={reviewed} playback={playback} live={live} focused={focused} following={following} phase={playback.phase} - groups={conclusions(job.reviews, job.settings.checks)} - scope={issues.scope === "findings" ? `from the last ${job.reviews.length} reviews` : issues.scope} - onPick={(review) => setPinned(review === playback.current ? null : reviewKey(review))} + groups={conclusions(decided, job.settings.checks)} + decided={decided.length} + scope={job.reviewed > reviews.length ? `From the latest ${reviews.length} of ${job.reviewed} reviewed traces` : ""} + onPick={pin} onFollow={() => setPinned(null)} /> > 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 d471bfa96be..bdd04b36621 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/live/LiveStrip.tsx +++ b/ui/litellm-dashboard/src/components/lens/investigations/live/LiveStrip.tsx @@ -13,16 +13,17 @@ import { outcome, providerOf, queueRows, reviewKey, shortVerdict, type IssueCoun import type { Playback } from "../../model/live"; import type { Review } from "../../model/types"; -const RECENT = 5; +const RECENT = 3; const MARK = { issue: "●", clear: "✓", unknown: "–" } as const; +const LOGO = { sm: "size-3.5", md: "size-[18px]" } as const; -export function ModelName({ model }: { model: string }) { +export function ModelName({ model, size = "sm" }: { model: string; size?: keyof typeof LOGO }) { if (!model) return null; const provider = providerOf(model); return ( - {provider && } - {model} + {provider && } + {model} ); } @@ -31,7 +32,7 @@ function RecentLine({ review, now, onOpen }: { review: Review; now: number; onOp const result = outcome(review); const issue = result === "issue"; return ( - + onOpen(review)} @@ -40,7 +41,7 @@ function RecentLine({ review, now, onOpen }: { review: Review; now: number; onOp {MARK[result]} - {review.agent || review.name} + {review.agent || review.name} {shortVerdict(review)} {agoLabel(Date.parse(review.at), now)} @@ -80,7 +81,7 @@ export function LiveStrip({ return ( @@ -107,10 +108,10 @@ export function LiveStrip({ )} - - onOpen()} disabled={!recent.length}> + + onOpen()} disabled={!recent.length}> - View live + View run diff --git a/ui/litellm-dashboard/src/components/lens/investigations/live/useLivePanels.ts b/ui/litellm-dashboard/src/components/lens/investigations/live/useLivePanels.ts index 610e588a0f7..f5896b3682d 100644 --- a/ui/litellm-dashboard/src/components/lens/investigations/live/useLivePanels.ts +++ b/ui/litellm-dashboard/src/components/lens/investigations/live/useLivePanels.ts @@ -3,7 +3,6 @@ import { useCallback, useState } from "react"; const STRIP_KEY = "litellm.lens.liveStrip"; -const DRAWER_KEY = "litellm.lens.liveDrawerClosed"; function read(key: string): string | null { try { @@ -29,15 +28,3 @@ export function useStripOpen(): [boolean, (open: boolean) => void] { }, []); return [open, update]; } - -export function useDrawerOpen(jobId: string, live: boolean): [boolean, (open: boolean) => void] { - const [open, setOpen] = useState(() => live && read(DRAWER_KEY) !== jobId); - const update = useCallback( - (next: boolean) => { - setOpen(next); - if (!next) write(DRAWER_KEY, jobId); - }, - [jobId], - ); - return [open, update]; -}