mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-21 00:21:49 +00:00
fix(ui): keep recorded order when an untimed guardrail shares a phase
This commit is contained in:
parent
8bb496154a
commit
d67c7894dd
2 changed files with 30 additions and 3 deletions
|
|
@ -33,6 +33,15 @@ const untimedPreCall: Partial<GuardrailInformation> = {
|
|||
duration: null,
|
||||
};
|
||||
|
||||
const timedPreCall: Partial<GuardrailInformation> = {
|
||||
guardrail_name: "timed-pre-rail",
|
||||
guardrail_status: "success",
|
||||
guardrail_mode: "pre_call",
|
||||
start_time: 1_700_000_000,
|
||||
end_time: 1_700_000_000.1,
|
||||
duration: 0.1,
|
||||
};
|
||||
|
||||
const ranPostCall: Partial<GuardrailInformation> = {
|
||||
guardrail_name: "ran-rail",
|
||||
guardrail_status: "success",
|
||||
|
|
@ -117,6 +126,21 @@ describe("GuardrailViewer", () => {
|
|||
expect(screen.queryByText(/^T\+/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("keeps an untimed guardrail ahead of a timed one recorded after it in the same phase", () => {
|
||||
const untimed = makeGuardrailInformation(untimedPreCall);
|
||||
const timedPre = makeGuardrailInformation(timedPreCall);
|
||||
renderWithProviders(<GuardrailViewer data={[untimed, timedPre]} />);
|
||||
|
||||
const rows = screen.getAllByTestId("lifecycle-row");
|
||||
const rowIndex = (label: RegExp): number => rows.findIndex((r) => within(r).queryByText(label) !== null);
|
||||
const untimedIndex = rowIndex(/Pre-call guardrail: conduct/);
|
||||
const timedIndex = rowIndex(/Pre-call guardrail: timed-pre-rail/);
|
||||
|
||||
expect(untimedIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(timedIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(untimedIndex).toBeLessThan(timedIndex);
|
||||
});
|
||||
|
||||
it("anchors offsets on the timed entries and gives the untimed one no fabricated offset", () => {
|
||||
const untimed = makeGuardrailInformation(untimedPreCall);
|
||||
const ran = makeGuardrailInformation(ranPostCall);
|
||||
|
|
|
|||
|
|
@ -375,15 +375,18 @@ const belongsOnLifecycle = (e: GuardrailInformation): boolean => isTimed(e) || g
|
|||
const RequestLifecycle = ({ entries }: { entries: GuardrailInformation[] }) => {
|
||||
const sorted = useMemo(() => {
|
||||
const onLifecycle = entries.filter(belongsOnLifecycle);
|
||||
const timed = onLifecycle.filter(isTimed).sort((a, b) => a.start_time - b.start_time);
|
||||
return [...timed, ...onLifecycle.filter((e) => !isTimed(e))];
|
||||
const byStart = onLifecycle.filter(isTimed).sort((a, b) => a.start_time - b.start_time);
|
||||
const timedSlots = new Map(
|
||||
onLifecycle.flatMap((e, i) => (isTimed(e) ? [i] : [])).map((slot, k) => [slot, byStart[k]]),
|
||||
);
|
||||
return onLifecycle.map((e, i) => timedSlots.get(i) ?? e);
|
||||
}, [entries]);
|
||||
|
||||
const timeline = useMemo(() => {
|
||||
if (sorted.length === 0) return [];
|
||||
|
||||
const timed = sorted.filter(isTimed);
|
||||
const baseTime = timed.length > 0 ? timed[0].start_time : null;
|
||||
const baseTime = timed.length > 0 ? Math.min(...timed.map((e) => e.start_time)) : null;
|
||||
const offsetOf = (e: GuardrailInformation): number | null =>
|
||||
baseTime === null || !isTimed(e) ? null : Math.round((e.end_time - baseTime) * 1000);
|
||||
const items: TimelineEntry[] = [];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue