import { useId, useState } from "react"; import { useMutation } from "@tanstack/react-query"; import type { ExecutionBlocker, Issue } from "@paperclipai/shared"; import { issuesApi } from "../api/issues"; import { Button } from "./ui/button"; import { Checkbox } from "./ui/checkbox"; import { Label } from "./ui/label"; import { Textarea } from "./ui/textarea"; export function WorkspaceFileRecovery({ issueId, issueStatus, blocker, canManage, onRecorded }: { issueId: string; issueStatus: Issue["status"]; blocker: ExecutionBlocker; canManage: boolean; onRecorded: () => void; }) { const noteId = useId(); const confirmationId = useId(); const [evidence, setEvidence] = useState(""); const [confirmed, setConfirmed] = useState(false); const record = useMutation({ mutationFn: () => issuesApi.resolveRecoveryAction(issueId, { actionId: blocker.recoveryActionId!, outcome: "restored", sourceIssueStatus: issueStatus, resolutionNote: evidence.trim(), executionReconciliation: { runId: blocker.runId!, providerStopped: true, actionOutcome: "mixed", outcomeEvidence: "This request records recovered workspace files only. It does not replay the source run or certify its external action outcomes.", workspaceRepairEvidence: evidence.trim(), }, }), onSuccess: onRecorded, }); if (!blocker.workspaceRepairRequired || !blocker.canRecordWorkspaceRepair || !["legacy_execution_requires_reconciliation", "native_continuation_requires_reconciliation"].includes(blocker.cause) || !blocker.recoveryActionId || !blocker.runId) return null; return
{record.isSuccess ?

File recovery recorded. The task status is unchanged. Continue the task when it is ready.

: canManage ? <>