chore: format, extract failure banner, sync dashboard api types

This commit is contained in:
Tin Chi Lo 2026-08-11 00:58:15 -07:00
parent c0fb7188eb
commit ec32f70b56
4 changed files with 26 additions and 16 deletions

View file

@ -605,8 +605,10 @@ class ShadowEvalLogger(CustomLogger):
# attributed to, and budget-checked against, the key whose traffic it copies.
# The router's pre-routing hook also writes its routing decision into this dict;
# read it back after the call for tier attribution.
shadow_metadata: Final[dict[str, object]] = sanitized_forwardable_call_metadata( # mutable-ok: router writes back
parent_metadata, SHADOW_EVAL_ROUTER_CALL_ORIGIN
shadow_metadata: Final[dict[str, object]] = (
sanitized_forwardable_call_metadata( # mutable-ok: router writes back
parent_metadata, SHADOW_EVAL_ROUTER_CALL_ORIGIN
)
)
shadow_params: Final = { # mutable-ok: splatted as kwargs
k: v for k, v in model_parameters.items() if k not in ("stream", "metadata")

View file

@ -3,11 +3,14 @@ import { describe, expect, it, vi } from "vitest";
const mockUserDailyActivityCall = vi.fn();
vi.mock("@/components/networking", () => ({
userDailyActivityCall: (...args: unknown[]) => mockUserDailyActivityCall(...args),
getToolSpend: vi.fn().mockResolvedValue({ by_tool: [], daily: [], start_date: null, end_date: null }),
getGeneralSettingsCall: vi.fn().mockResolvedValue([]),
}));
vi.mock("@/components/networking", () => {
const emptyToolSpend = { by_tool: [], daily: [], start_date: null, end_date: null };
return {
userDailyActivityCall: (...args: unknown[]) => mockUserDailyActivityCall(...args),
getToolSpend: vi.fn().mockResolvedValue(emptyToolSpend),
getGeneralSettingsCall: vi.fn().mockResolvedValue([]),
};
});
vi.mock("@/components/shared/advanced_date_picker", () => ({
__esModule: true,

View file

@ -265,6 +265,15 @@ const VerdictBar: React.FC<{ results: NonNullable<ShadowEvalJob["results"]> }> =
);
};
const JobFailureBanner: React.FC<{ job: ShadowEvalJob }> = ({ job }) => {
if (job.failed_count === 0 || !job.last_error) return null;
return (
<p className="border-b bg-red-50 px-6 py-2 text-xs text-destructive">
Last failure: <span className="font-mono">{job.last_error}</span>
</p>
);
};
const JobResults: React.FC<{
job: ShadowEvalJob;
onStop: () => void;
@ -298,11 +307,7 @@ const JobResults: React.FC<{
) : null}
</div>
{job.failed_count > 0 && job.last_error ? (
<p className="border-b bg-red-50 px-6 py-2 text-xs text-destructive">
Last failure: <span className="font-mono">{job.last_error}</span>
</p>
) : null}
<JobFailureBanner job={job} />
{results && results.groups.length > 0 ? (
<>
@ -633,6 +638,8 @@ const ShadowEvalSection: React.FC<ShadowEvalSectionProps> = ({ accessToken }) =>
const latest = useMemo(() => jobs?.[0] ?? null, [jobs]);
const previous = useMemo(() => jobs?.slice(1) ?? [], [jobs]);
const { data: latestDetail } = useShadowEvalJob(accessToken, latest?.job_id ?? null);
const latestJobIsFinished =
latestDetail != null && latestDetail.status !== "pending" && latestDetail.status !== "running";
if (error instanceof ApiError && error.status === 403) return null; // admin-only section
@ -657,9 +664,7 @@ const ShadowEvalSection: React.FC<ShadowEvalSectionProps> = ({ accessToken }) =>
/>
) : null}
{!latest || (latestDetail && latestDetail.status !== "pending" && latestDetail.status !== "running") ? (
<StartForm accessToken={accessToken} />
) : null}
{!latest || latestJobIsFinished ? <StartForm accessToken={accessToken} /> : null}
<PreviousJobs accessToken={accessToken} jobs={previous} />
</div>

View file

@ -886,7 +886,7 @@ export interface paths {
put?: never;
/**
* Stop Shadow Eval Job
* @description Stop an active shadow eval job. Existing verdicts are kept; sampling halts within ~30s.
* @description Stop an active shadow eval job. Existing verdicts are kept; sampling halts within ~10s.
*/
post: operations["stop_shadow_eval_job_auto_router_shadow_eval__job_id__stop_post"];
delete?: never;