|
|
|
|
@@ -44,6 +44,25 @@ interface AuditLogResponse {
|
|
|
|
|
total: number;
|
|
|
|
|
page: number;
|
|
|
|
|
pages: number;
|
|
|
|
|
notice?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createEmptyAuditLogResponse(page: number, notice?: string): AuditLogResponse {
|
|
|
|
|
return {
|
|
|
|
|
items: [],
|
|
|
|
|
total: 0,
|
|
|
|
|
page,
|
|
|
|
|
pages: 0,
|
|
|
|
|
...(notice !== undefined ? { notice } : {}),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isRateLimitError(error: unknown): boolean {
|
|
|
|
|
if (!(error instanceof Error)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return /429|rate limit|too many requests/i.test(error.message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
|
|
@@ -138,7 +157,15 @@ async function fetchAuditLog(
|
|
|
|
|
params.set("sessionId", normalizedSessionId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return apiGet<AuditLogResponse>(`/api/mission-control/audit-log?${params.toString()}`);
|
|
|
|
|
try {
|
|
|
|
|
return await apiGet<AuditLogResponse>(`/api/mission-control/audit-log?${params.toString()}`);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
if (isRateLimitError(error)) {
|
|
|
|
|
return createEmptyAuditLogResponse(page, "Rate limited - retrying...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return createEmptyAuditLogResponse(page);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function AuditLogDrawer({ sessionId, trigger }: AuditLogDrawerProps): React.JSX.Element {
|
|
|
|
|
@@ -180,11 +207,10 @@ export function AuditLogDrawer({ sessionId, trigger }: AuditLogDrawerProps): Rea
|
|
|
|
|
const totalItems = auditLogQuery.data?.total ?? 0;
|
|
|
|
|
const totalPages = auditLogQuery.data?.pages ?? 0;
|
|
|
|
|
const items = auditLogQuery.data?.items ?? [];
|
|
|
|
|
const notice = auditLogQuery.data?.notice;
|
|
|
|
|
|
|
|
|
|
const canGoPrevious = page > 1;
|
|
|
|
|
const canGoNext = totalPages > 0 && page < totalPages;
|
|
|
|
|
const errorMessage =
|
|
|
|
|
auditLogQuery.error instanceof Error ? auditLogQuery.error.message : "Failed to load audit log";
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Sheet open={open} onOpenChange={setOpen}>
|
|
|
|
|
@@ -237,10 +263,10 @@ export function AuditLogDrawer({ sessionId, trigger }: AuditLogDrawerProps): Rea
|
|
|
|
|
Loading audit log...
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
) : auditLogQuery.error ? (
|
|
|
|
|
) : notice ? (
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={5} className="px-3 py-6 text-center text-sm text-red-500">
|
|
|
|
|
{errorMessage}
|
|
|
|
|
<td colSpan={5} className="px-3 py-6 text-center text-sm text-muted-foreground">
|
|
|
|
|
{notice}
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
) : items.length === 0 ? (
|
|
|
|
|
|