"use client";
import { formatRelativeTime } from "@/lib/formatters";
import type { UsageStats } from "@/lib/types";
import {
DataRow,
ExpandText,
GroupRow,
HeadCell,
LeadCell,
TableFrame,
TableNotice,
} from "@/features/recipes/recipes-content/catalog-table-shell";
type ErrorRow = {
key: string;
createdAt: string;
source: string;
method: string | null;
status: number | null;
errorClass: string | null;
message: string | null;
};
const byNewest = (a: ErrorRow, b: ErrorRow): number => b.createdAt.localeCompare(a.createdAt);
/**
* The failures, with their messages.
*
* A success rate tells you something is wrong; it never tells you what. These
* rows are the only place in the product where the controller's own error text
* is legible, so the message column is the widest one and the timestamps are
* relative — "4 min ago" is what you need when you are deciding whether the
* thing you just did caused this.
*/
export function UsageErrorsTab({ stats }: { stats: UsageStats }) {
const controller = stats.controller;
const requestErrors: ErrorRow[] = (controller?.recent_errors ?? [])
.map((error, index) => ({
key: `request-${index}-${error.created_at}`,
createdAt: error.created_at,
source: error.path,
method: error.method || null,
status: error.status || null,
errorClass: error.error_class,
message: error.error_message,
}))
.sort(byNewest);
const toolErrors: ErrorRow[] = (controller?.function_calls?.recent_errors ?? [])
.map((error, index) => ({
key: `tool-${index}-${error.created_at}`,
createdAt: error.created_at,
source: error.function_name,
method: null,
status: null,
errorClass: error.error_class,
message: error.error_message,
}))
.sort(byNewest);
if (requestErrors.length === 0 && toolErrors.length === 0) {
return (
);
}
const groups = [
{
label: "Request errors",
blurb: "HTTP requests the controller could not serve",
rows: requestErrors,
},
{
label: "Tool-call errors",
blurb: "tools the agent runtime invoked that threw",
rows: toolErrors,
},
].filter((group) => group.rows.length > 0);
return (