import { formatDateTime } from "./utils"; type RetryAwareRun = { status: string; retryOfRunId?: string | null; scheduledRetryAt?: string | Date | null; scheduledRetryAttempt?: number | null; scheduledRetryReason?: string | null; retryExhaustedReason?: string | null; }; export type RunRetryStateSummary = { kind: "scheduled" | "exhausted" | "attempted"; badgeLabel: string; tone: string; detail: string | null; secondary: string | null; retryOfRunId: string | null; }; const RETRY_REASON_LABELS: Record = { transient_failure: "Transient failure", missing_issue_comment: "Missing issue comment", process_lost: "Process lost", assignment_recovery: "Assignment recovery", issue_continuation_needed: "Continuation needed", max_turns_continuation: "Max-turn continuation", }; function readNonEmptyString(value: unknown) { return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; } function joinFragments(parts: Array) { const filtered = parts.filter((part): part is string => Boolean(part)); return filtered.length > 0 ? filtered.join(" ยท ") : null; } export function formatRetryReason(reason: string | null | undefined) { const normalized = readNonEmptyString(reason); if (!normalized) return null; return RETRY_REASON_LABELS[normalized] ?? normalized.replace(/_/g, " "); } export function describeRunRetryState(run: RetryAwareRun): RunRetryStateSummary | null { const attempt = typeof run.scheduledRetryAttempt === "number" && Number.isFinite(run.scheduledRetryAttempt) && run.scheduledRetryAttempt > 0 ? run.scheduledRetryAttempt : null; const attemptLabel = attempt ? `Attempt ${attempt}` : null; const reasonLabel = formatRetryReason(run.scheduledRetryReason); const retryOfRunId = readNonEmptyString(run.retryOfRunId); const exhaustedReason = readNonEmptyString(run.retryExhaustedReason); const dueAt = run.scheduledRetryAt ? formatDateTime(run.scheduledRetryAt) : null; const isMaxTurnContinuation = run.scheduledRetryReason === "max_turns_continuation"; const hasRetryMetadata = Boolean(retryOfRunId) || Boolean(reasonLabel) || Boolean(dueAt) || Boolean(attemptLabel) || Boolean(exhaustedReason); if (!hasRetryMetadata) return null; if (run.status === "scheduled_retry") { return { kind: "scheduled", badgeLabel: isMaxTurnContinuation ? "Continuation scheduled" : "Retry scheduled", tone: "border-cyan-500/30 bg-cyan-500/10 text-cyan-700 dark:text-cyan-300", detail: joinFragments([attemptLabel, reasonLabel]), secondary: dueAt ? `${isMaxTurnContinuation ? "Next continuation" : "Next retry"} ${dueAt}` : `${isMaxTurnContinuation ? "Next continuation" : "Next retry"} pending schedule`, retryOfRunId, }; } if (exhaustedReason) { return { kind: "exhausted", badgeLabel: isMaxTurnContinuation ? "Continuation exhausted" : "Retry exhausted", tone: "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300", detail: joinFragments([attemptLabel, reasonLabel, "Automatic retries exhausted"]), secondary: exhaustedReason.includes("Manual intervention required") ? exhaustedReason : `${exhaustedReason} Manual intervention required.`, retryOfRunId, }; } return { kind: "attempted", badgeLabel: isMaxTurnContinuation ? "Continued run" : "Retried run", tone: "border-slate-500/20 bg-slate-500/10 text-slate-700 dark:text-slate-300", detail: joinFragments([attemptLabel, reasonLabel]), secondary: null, retryOfRunId, }; }