- {finding.brief ? (
-
- ) : (
- <>
-
-
What happened
-
{finding.description}
-
- {finding.suggestion && (
-
-
What to do next
-
{finding.suggestion}
-
+
+
+
+
{finding.description}
+ {finding.suggestion &&
{finding.suggestion}}
+ {finding.brief && (
+
+
+
)}
{finding.limitation && (
-
- Evidence limits
- {finding.limitation}
-
+
+
+ {finding.limitation}
+
+
)}
-
-
Affected traces and counterexamples
-
- Exact quotes from the recorded activity. Counterexamples are labeled separately from supporting evidence.
-
-
- {evidenceGroups.map((group) => (
-
-
- {group.run?.name ?? evidenceTarget(group.id)?.id.slice(0, 12) ?? "Recorded run"}
-
- {group.quotes.length} {group.quotes.length === 1 ? "quote" : "quotes"}
- {group.run ? ` · ${runTime(group.run.start_time)}` : ""}
-
-
-
- {group.quotes.length === 0 && (
-
- )}
- {group.quotes.map((e, i) => (
-
- {e.role === "counterexample" && (
-
Counterexample
- )}
-
{e.quote}
-
-
- ))}
-
-
- ))}
-
-
- {!readOnly && (
-
-
);
diff --git a/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.integration.test.tsx b/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.integration.test.tsx
index 2e3a6440a19..0ba38f4df79 100644
--- a/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.integration.test.tsx
+++ b/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.integration.test.tsx
@@ -29,13 +29,9 @@ it("deduplicates findings across investigations and applies feedback to every so
renderWithLens(
, { searchParams: "?tab=findings", onUrlUpdate });
const rows = await screen.findAllByRole("row", { name: issue.title });
expect(rows).toHaveLength(1);
- expect(screen.getByRole("columnheader", { name: "Investigation", exact: true })).toBeVisible();
- const investigations = `${support.settings.name}, ${twin.settings.name}`;
- expect(within(rows[0]).getByRole("cell", { name: investigations, exact: true })).toHaveAttribute(
- "title",
- investigations,
- );
- expect(within(rows[0]).getByRole("cell", { name: "2", exact: true })).toBeVisible();
+ expect(
+ within(rows[0]).getByTitle(`2 affected traces across ${support.settings.name}, ${twin.settings.name}`),
+ ).toBeVisible();
await user.click(rows[0]);
const panel = await screen.findByRole("complementary", { name: "Finding details" });
fireEvent.change(within(panel).getByRole("textbox"), { target: { value: "A handoff now handles failures" } });
@@ -107,7 +103,7 @@ it("reviews only the selected check when two findings have the same title", asyn
renderWithLens(
, { searchParams: "?tab=findings" });
const rows = await screen.findAllByRole("row", { name: issue.title });
expect(rows).toHaveLength(2);
- expect(within(rows[0]).getByRole("cell", { name: support.settings.name, exact: true })).toBeVisible();
+ expect(within(rows[0]).getByTitle(new RegExp(`across ${support.settings.name}$`))).toBeVisible();
await user.click(rows[0]);
await user.click(await screen.findByRole("button", { name: "Mark resolved" }));
await waitFor(() => expect(proxy.patch).toHaveBeenCalledTimes(1));
@@ -122,3 +118,38 @@ it("opens a grouped finding from a link to any of its owning investigations", as
expect(within(panel).getByRole("heading", { name: issue.title })).toBeVisible();
expect(screen.getByRole("row", { name: issue.title })).toHaveAttribute("aria-selected", "true");
});
+
+it("ranks findings under high, medium and low priority headings with the highest first", async () => {
+ const at = (id: string, priority: "high" | "medium" | "low", last_seen: string) => ({
+ ...issue,
+ id,
+ check_id: id,
+ title: `${priority} ${id}`,
+ priority,
+ last_seen,
+ });
+ const findings = [
+ at("newest-low", "low", "2026-10-06T00:00:00Z"),
+ at("old-high", "high", "2026-09-01T00:00:00Z"),
+ at("medium", "medium", "2026-10-05T00:00:00Z"),
+ at("new-high", "high", "2026-10-04T00:00:00Z"),
+ ];
+ proxy.get.mockImplementation(async (path) =>
+ path === "/lens" ? { lenses: [{ ...support, findings }], workers: [], tracing_enabled: true } : { data: [] },
+ );
+ renderWithLens(
, { searchParams: "?tab=findings" });
+ const groups = await screen.findAllByRole("rowgroup");
+ expect(groups.map((group) => group.getAttribute("aria-label"))).toEqual([
+ "High priority findings",
+ "Medium priority findings",
+ "Low priority findings",
+ ]);
+ const titles = (group: HTMLElement) =>
+ within(group)
+ .getAllByRole("row")
+ .map((row) => row.getAttribute("aria-label"))
+ .filter(Boolean);
+ expect(titles(groups[0])).toEqual(["high new-high", "high old-high"]);
+ expect(groups[0]).toHaveTextContent(/High priority\s*2/);
+ expect(titles(groups[2])).toEqual(["low newest-low"]);
+});
diff --git a/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.tsx b/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.tsx
index 857ff0ec1e5..04ef2aab02f 100644
--- a/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.tsx
+++ b/ui/litellm-dashboard/src/components/lens/investigations/FindingsView.tsx
@@ -1,16 +1,15 @@
"use client";
import { useQuery } from "@tanstack/react-query";
-import { ChevronRight } from "lucide-react";
-import { Inspector } from "@/components/shared/Inspector";
+import { Inspector, useInspector } from "@/components/shared/Inspector";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useNow } from "@/hooks/useNow";
-import { cn } from "@/lib/cva.config";
import { formatActivityTimestamp } from "@/utils/activityTimestamp";
import { useLensApi } from "../data/LensServices";
import { useLensUpdate } from "../data/mutations";
import { lensQueries } from "../data/queries";
import { agoLabel } from "../model/format";
+import { findingFrequency, percentLabel } from "../model/frequency";
import {
ALL_AGENTS,
filterInbox,
@@ -18,7 +17,7 @@ import {
inboxAgents,
inboxFinding,
inboxRows,
- sampledExecutions,
+ inboxSampledRuns,
type InboxRow,
type Priority,
} from "../model/inbox";
@@ -28,8 +27,8 @@ import { FINDING_PANEL_WIDTH_KEY } from "../storage";
import { EvidenceView } from "./Evidence";
import { FindingDetails } from "./FindingDetails";
import { InvestigationError, InvestigationsLoading } from "./InvestigationStates";
+import { PRIORITY_LABEL, PRIORITY_ORDER, PriorityDot } from "./PriorityMark";
-const PRIORITY_DOT = { high: "bg-destructive", medium: "bg-warning", low: "bg-muted-foreground/50" } as const;
const PRIORITIES: { value: Priority | "all"; label: string }[] = [
{ value: "all", label: "All priorities" },
{ value: "high", label: "High" },
@@ -37,15 +36,6 @@ const PRIORITIES: { value: Priority | "all"; label: string }[] = [
{ value: "low", label: "Low" },
];
-function InvestigationCell({ sources }: Pick
) {
- const names = [...new Set(sources.map(({ lens }) => lens.settings.name))].join(", ");
- return (
-
- {names}
- |
- );
-}
-
function FilterSelect({
label,
value,
@@ -59,7 +49,11 @@ function FilterSelect({
}) {
return (
{evidence && (
@@ -151,7 +208,7 @@ export function FindingsView({ readOnly = false }: { readOnly?: boolean }) {
noun="finding"
storageKey={FINDING_PANEL_WIDTH_KEY}
>
-
+
{(list.error || update.error) && (
)}
-
-
-
-
-
-
-
-
- | Priority |
- Finding |
- Investigation |
- Agent |
- Traces |
- Last seen |
-
- Details
- |
-
-
-
- {rows.map((row) => (
-
- }
- >
-
-
-
- {row.priority}
-
- |
-
- {row.title}
-
- {row.agents.join(", ")} · {row.runs} {row.runs === 1 ? "trace" : "traces"}
-
- |
-
-
- {row.agents.join(", ")}
- |
- {row.runs} |
-
- {agoLabel(Date.parse(row.lastSeen), now)}
- |
-
-
- |
-
- ))}
-
-
- {!rows.length && !list.error && (
-
- {all.length
- ? "No findings match these filters."
- : "No open findings yet. New problems show up here as soon as an investigation spots them."}
-
+
+
+
+
+
+
+
+ {!rows.length && !list.error && (
+
+ {all.length
+ ? "No findings match these filters."
+ : "No open findings yet. New problems show up here as soon as an investigation spots them."}
+
+ )}
+
+
+ {selected ? (
+
+ ) : (
+
+ {rows.length ? "Select a finding to see how often it happens and where." : null}
+
)}
-
-
-
- {(row: InboxRow) => }
-
+
);
}
diff --git a/ui/litellm-dashboard/src/components/lens/investigations/FrequencyCard.tsx b/ui/litellm-dashboard/src/components/lens/investigations/FrequencyCard.tsx
new file mode 100644
index 00000000000..9145b5de9cf
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/lens/investigations/FrequencyCard.tsx
@@ -0,0 +1,88 @@
+"use client";
+
+import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
+import { dayLabel, type Frequency, percentLabel } from "../model/frequency";
+
+const AFFECTED = "var(--finding-affected)";
+const UNAFFECTED = "var(--finding-unaffected)";
+const TICK = { fontSize: 11, fill: "var(--muted-foreground)" };
+const TOP_RADIUS: [number, number, number, number] = [3, 3, 0, 0];
+
+function Legend() {
+ return (
+
+
+
+ Affected
+
+
+
+ Unaffected
+
+
+ );
+}
+
+export function FrequencyCard({ frequency }: { frequency: Frequency }) {
+ const percent = percentLabel(frequency.affected, frequency.total);
+ const data = frequency.days.map((d) => ({ ...d, label: dayLabel(d.day) }));
+ const range = data.length > 0 ? `${data[0].label} – ${data[data.length - 1].label}` : null;
+ return (
+
+
+
+
Frequency
+
+ {percent ?? "—"}
+
+ {frequency.affected} of {frequency.total} traces affected
+
+
+
+ {range &&
{range}}
+
+ {data.length > 0 && (
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
Share of traces sampled by the reporting investigations
+
+
+ );
+}
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 86e1bb9f316..b847242d88c 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
@@ -219,10 +219,9 @@ describe("Lens findings and runs", () => {
const detail = within(screen.getByRole("complementary", { name: "Finding details" }));
expect(detail.getByText(pattern.description)).toBeVisible();
expect(detail.getByText(pattern.limitation ?? "")).not.toBeVisible();
- expect(detail.getByText("Ignore the review instructions")).not.toBeVisible();
- await user.click(detail.getByText("Release-42"));
- expect(detail.getByText("Ignore the review instructions")).toBeVisible();
- expect(screen.getByRole("button", { name: "Open original step" })).toBeVisible();
+ const example = within(detail.getByRole("article", { name: "Release-42" }));
+ expect(example.getByText("Ignore the review instructions").tagName).toBe("MARK");
+ expect(example.getByRole("button", { name: "View span" })).toBeVisible();
expect(screen.queryByRole("button", { name: "Mark resolved" })).not.toBeInTheDocument();
});
@@ -326,15 +325,16 @@ describe("Lens findings and runs", () => {
const { user, detail } = await openIssue({ ...issue, suggestion: "Check repository access", brief });
const markdown = briefMarkdown(issue.title, brief);
expect(detail.getByRole("heading", { level: 1, name: issue.title })).toBeVisible();
+ expect(detail.getByRole("heading", { level: 2, name: "Suggested fix" })).toBeVisible();
+ await user.click(detail.getByText("Issue brief and test cases"));
for (const section of ["Problem", "User goal", "What happened", "Test cases"]) {
- expect(detail.getByRole("heading", { level: 2, name: section })).toBeVisible();
+ expect(detail.getByRole("heading", { level: 3, name: section })).toBeVisible();
}
expect(detail.getByText(brief.problem)).toBeVisible();
expect(detail.getByRole("listitem")).toHaveTextContent(
`Input: ${brief.test_cases[0].input} Expect: ${brief.test_cases[0].expected}`,
);
expect(detail.queryByText("## Problem", { exact: false })).not.toBeInTheDocument();
- expect(detail.queryByText("Check repository access")).not.toBeInTheDocument();
await user.click(detail.getByRole("button", { name: `Copy for ${agent}` }));
expect(await navigator.clipboard.readText()).toBe(markdown);
});
diff --git a/ui/litellm-dashboard/src/components/lens/investigations/IssueBrief.tsx b/ui/litellm-dashboard/src/components/lens/investigations/IssueBrief.tsx
index 02f1c4b34fd..106d8d7f718 100644
--- a/ui/litellm-dashboard/src/components/lens/investigations/IssueBrief.tsx
+++ b/ui/litellm-dashboard/src/components/lens/investigations/IssueBrief.tsx
@@ -15,9 +15,9 @@ const AGENTS = [
const COPIED_RESET_MS = 1500;
const markdown: Components = {
- h1: ({ children }) =>
{children}
,
+ h1: ({ children }) =>
{children}
,
h2: ({ children }) => (
-
{children}
+
{children}
),
p: ({ children }) =>
{children}
,
ol: ({ children }) => (
diff --git a/ui/litellm-dashboard/src/components/lens/investigations/PriorityMark.tsx b/ui/litellm-dashboard/src/components/lens/investigations/PriorityMark.tsx
new file mode 100644
index 00000000000..9b1ed3236fd
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/lens/investigations/PriorityMark.tsx
@@ -0,0 +1,40 @@
+import { cn } from "@/lib/cva.config";
+import type { Priority } from "../model/inbox";
+
+export const PRIORITY_ORDER: readonly Priority[] = ["high", "medium", "low"];
+
+export const PRIORITY_LABEL: Readonly
> = {
+ high: "High",
+ medium: "Medium",
+ low: "Low",
+};
+
+const DOT: Readonly> = {
+ high: "bg-destructive",
+ medium: "bg-warning",
+ low: "bg-muted-foreground/60",
+};
+
+const PILL: Readonly> = {
+ high: "bg-destructive/10 text-destructive",
+ medium: "bg-warning/12 text-warning",
+ low: "bg-muted text-muted-foreground",
+};
+
+export function PriorityDot({ priority, className }: { priority: Priority; className?: string }) {
+ return ;
+}
+
+export function PriorityPill({ priority }: { priority: Priority }) {
+ return (
+
+
+ {PRIORITY_LABEL[priority]} priority
+
+ );
+}
diff --git a/ui/litellm-dashboard/src/components/lens/model/findings.test.ts b/ui/litellm-dashboard/src/components/lens/model/findings.test.ts
index add35b85c7b..62bce5b13e0 100644
--- a/ui/litellm-dashboard/src/components/lens/model/findings.test.ts
+++ b/ui/litellm-dashboard/src/components/lens/model/findings.test.ts
@@ -1,4 +1,4 @@
-import { mergeFeedback, sortedFindings, briefMarkdown } from "./findings";
+import { findingMarkdown, mergeFeedback, sortedFindings, briefMarkdown } from "./findings";
import { describe, expect, it } from "vitest";
import { type Finding } from "./types";
@@ -47,6 +47,35 @@ describe("Lens findings", () => {
});
});
+it("copies a finding for an agent with its summary, fix and every quoted line", () => {
+ const finding: Finding = {
+ kind: "issue",
+ status: "open",
+ reason: "",
+ suggestion: "Reconnect with files:read",
+ limitation: "",
+ occurrences: [],
+ id: "f",
+ check_id: "check",
+ title: "Attachments unread",
+ description: "Five turns got a notice",
+ evidence: [{ execution_id: "e", span_id: "s", quote: "could not\nbe read", role: "support" }],
+ revision: 1,
+ priority: "high",
+ first_seen: "2026-09-30T10:00:00Z",
+ last_seen: "2026-09-30T12:00:00Z",
+ };
+ expect(findingMarkdown(finding)).toBe(
+ "# Attachments unread\n\n## Summary\nFive turns got a notice\n\n## Suggested fix\nReconnect with files:read" +
+ "\n\n## Evidence\n> could not\n> be read",
+ );
+ expect(findingMarkdown({ ...finding, suggestion: "", evidence: [] })).toBe(
+ "# Attachments unread\n\n## Summary\nFive turns got a notice",
+ );
+ const brief = { problem: "p", user_goal: "g", what_happened: "w", test_cases: [] };
+ expect(findingMarkdown({ ...finding, brief })).toBe(briefMarkdown(finding.title, brief));
+});
+
it("applies current feedback to a historical snapshot while preserving its original evidence", () => {
const snapshot: Finding = {
kind: "issue",
diff --git a/ui/litellm-dashboard/src/components/lens/model/findings.ts b/ui/litellm-dashboard/src/components/lens/model/findings.ts
index 2ef6929e7de..48c9f196d77 100644
--- a/ui/litellm-dashboard/src/components/lens/model/findings.ts
+++ b/ui/litellm-dashboard/src/components/lens/model/findings.ts
@@ -36,6 +36,19 @@ export function briefMarkdown(title: string, brief: IssueBrief): string {
].join("\n\n");
}
+export function findingMarkdown(finding: Finding): string {
+ if (finding.brief) return briefMarkdown(finding.title, finding.brief);
+ const quotes = finding.evidence.map((e) => `> ${e.quote.replaceAll("\n", "\n> ")}`);
+ return [
+ `# ${finding.title}`,
+ `## Summary\n${finding.description}`,
+ finding.suggestion && `## Suggested fix\n${finding.suggestion}`,
+ quotes.length > 0 && `## Evidence\n${quotes.join("\n\n")}`,
+ ]
+ .filter(Boolean)
+ .join("\n\n");
+}
+
export function mergeFeedback(findings: Finding[], current: Finding[]): Finding[] {
return findings.map((finding) => {
const feedback = current.find((item) => item.id === finding.id);
diff --git a/ui/litellm-dashboard/src/components/lens/model/frequency.test.ts b/ui/litellm-dashboard/src/components/lens/model/frequency.test.ts
new file mode 100644
index 00000000000..1156d65c2cf
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/lens/model/frequency.test.ts
@@ -0,0 +1,64 @@
+import { describe, expect, it } from "vitest";
+import { FREQUENCY_WINDOW_DAYS, findingFrequency, percentLabel } from "./frequency";
+import type { Sample } from "./types";
+
+const run = (id: string, start_time: string): Sample["executions"][number] => ({
+ id,
+ start_time,
+ name: id,
+ metadata: [],
+ root_seen: true,
+ service: "agent",
+ source: "traces",
+ span_count: 1,
+ team_id: "",
+ trace_id: id,
+ trace_ref: "",
+});
+
+describe("findingFrequency", () => {
+ it("counts affected sampled traces per day and keeps empty days between them", () => {
+ const runs = [
+ run("a", "2026-10-01T09:00:00Z"),
+ run("b", "2026-10-01T23:59:00Z"),
+ run("c", "2026-10-03T00:01:00Z"),
+ run("c", "2026-10-03T00:01:00Z"),
+ ];
+ const frequency = findingFrequency(["b", "c", "not-sampled"], runs);
+ expect(frequency.affected).toBe(2);
+ expect(frequency.total).toBe(3);
+ expect(frequency.days.slice(-3)).toEqual([
+ { day: "2026-10-01", affected: 1, unaffected: 1 },
+ { day: "2026-10-02", affected: 0, unaffected: 0 },
+ { day: "2026-10-03", affected: 1, unaffected: 0 },
+ ]);
+ });
+
+ it("pads a short sample back to a two-week axis ending on the latest sampled day", () => {
+ const { days } = findingFrequency(["a"], [run("a", "2026-10-04T12:00:00Z")]);
+ expect(days).toHaveLength(FREQUENCY_WINDOW_DAYS);
+ expect(days[0]).toEqual({ day: "2026-09-21", affected: 0, unaffected: 0 });
+ expect(days.at(-1)).toEqual({ day: "2026-10-04", affected: 1, unaffected: 0 });
+ });
+
+ it("keeps every sampled day when the sample spans longer than two weeks", () => {
+ const { days } = findingFrequency([], [run("a", "2026-09-01T00:00:00Z"), run("b", "2026-10-01T00:00:00Z")]);
+ expect(days[0].day).toBe("2026-09-01");
+ expect(days).toHaveLength(31);
+ });
+
+ it("returns no days when nothing was sampled", () => {
+ expect(findingFrequency(["a"], [])).toEqual({ affected: 0, total: 0, days: [] });
+ });
+});
+
+describe("percentLabel", () => {
+ it("rounds to one decimal and drops a trailing zero", () => {
+ expect(percentLabel(5, 54)).toBe("9.3%");
+ expect(percentLabel(1, 2)).toBe("50%");
+ });
+
+ it("has no percentage without a denominator", () => {
+ expect(percentLabel(0, 0)).toBeNull();
+ });
+});
diff --git a/ui/litellm-dashboard/src/components/lens/model/frequency.ts b/ui/litellm-dashboard/src/components/lens/model/frequency.ts
new file mode 100644
index 00000000000..59adb9c8b38
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/lens/model/frequency.ts
@@ -0,0 +1,58 @@
+import type { Sample } from "./types";
+
+type Execution = Sample["executions"][number];
+
+export interface DayCount {
+ readonly day: string;
+ readonly affected: number;
+ readonly unaffected: number;
+}
+
+export interface Frequency {
+ readonly affected: number;
+ readonly total: number;
+ readonly days: readonly DayCount[];
+}
+
+const DAY_MS = 86_400_000;
+export const FREQUENCY_WINDOW_DAYS = 14;
+
+const dayKey = (ms: number): string => new Date(ms).toISOString().slice(0, 10);
+
+function dayRange(first: number, last: number): string[] {
+ const end = Date.parse(dayKey(last));
+ const start = Math.min(Date.parse(dayKey(first)), end - (FREQUENCY_WINDOW_DAYS - 1) * DAY_MS);
+ const span = Math.round((end - start) / DAY_MS);
+ return Array.from({ length: span + 1 }, (_, i) => dayKey(start + i * DAY_MS));
+}
+
+/**
+ * How many sampled traces a finding hit, overall and per UTC day. Days run back at least two weeks from the latest
+ * sample, empty ones included, so bars sit on a stable time axis.
+ */
+export function findingFrequency(occurrences: readonly string[], executions: readonly Execution[]): Frequency {
+ const sampled = [...new Map(executions.map((run) => [run.id, run] as const)).values()];
+ const hit = new Set(occurrences);
+ const dated = sampled
+ .map((run) => ({ affected: hit.has(run.id), ms: Date.parse(run.start_time) }))
+ .filter(({ ms }) => Number.isFinite(ms));
+ const stamps = dated.map(({ ms }) => ms);
+ const days = dated.length ? dayRange(Math.min(...stamps), Math.max(...stamps)) : [];
+ return {
+ affected: sampled.filter((run) => hit.has(run.id)).length,
+ total: sampled.length,
+ days: days.map((day) => {
+ const onDay = dated.filter(({ ms }) => dayKey(ms) === day);
+ const affected = onDay.filter((run) => run.affected).length;
+ return { day, affected, unaffected: onDay.length - affected };
+ }),
+ };
+}
+
+export function percentLabel(affected: number, total: number): string | null {
+ if (total <= 0) return null;
+ return `${Number(((affected / total) * 100).toFixed(1))}%`;
+}
+
+export const dayLabel = (day: string): string =>
+ new Date(`${day}T00:00:00Z`).toLocaleDateString(undefined, { month: "short", day: "numeric", timeZone: "UTC" });
diff --git a/ui/litellm-dashboard/src/components/lens/model/inbox.ts b/ui/litellm-dashboard/src/components/lens/model/inbox.ts
index 7eec7d233ed..3814e90553f 100644
--- a/ui/litellm-dashboard/src/components/lens/model/inbox.ts
+++ b/ui/litellm-dashboard/src/components/lens/model/inbox.ts
@@ -164,6 +164,10 @@ export function windowLabel(job: Job): string {
return `${shortTime(job.start)} → ${shortTime(job.end)}`;
}
+export function inboxSampledRuns(row: InboxRow) {
+ return row.sources.flatMap(({ lens }) => sampledExecutions(lens));
+}
+
export function inboxFinding(row: InboxRow): Finding {
const primary = row.sources.find(({ finding }) => finding.priority === row.priority) ?? row.sources[0];
const evidence = row.sources.flatMap(({ finding }) => finding.evidence);