import { useState } from "react"; import type { Interrupt } from "@copilotkit/react-core/v2"; export interface InterruptCardProps { interrupt: Interrupt; index?: number; total?: number; onResolve: (payload: unknown) => void; onCancel: () => void; } type Addressed = "approved" | "rejected" | "cancelled"; /** * Default reusable interrupt UI for one AG-UI Interrupt. * * With multiple interrupts open, `useInterrupt` accumulates responses and only * resumes once EVERY interrupt is addressed — so a single card's click won't * re-render the set. This component therefore tracks its own "addressed" state * to give immediate per-card feedback (and disable its buttons) while the rest * are still pending. When the run resumes, the whole set unmounts. */ export function InterruptCard({ interrupt, index, total, onResolve, onCancel, }: InterruptCardProps) { const [addressed, setAddressed] = useState(null); const multi = typeof total === "number" && total > 1; const act = (kind: Addressed, fn: () => void) => { if (addressed) return; setAddressed(kind); fn(); }; if (addressed) { const label = addressed === "approved" ? "✓ Approved" : addressed === "rejected" ? "✗ Rejected" : "Cancelled"; return (
{label} {" — "} {interrupt.message ?? interrupt.reason} {multi && ( (waiting for the others…) )}
); } return (
{interrupt.reason} {multi && typeof index === "number" && ( {index + 1} / {total} )}

{interrupt.message ?? "Action requires your confirmation."}

); }