({ call, result, status = "requested", isError = false, isDecided = false, subagentName, onApprove, onReject, tokenStats }: ToolDisplayProps)
| 28 | } |
| 29 | |
| 30 | const ToolDisplay = ({ call, result, status = "requested", isError = false, isDecided = false, subagentName, onApprove, onReject, tokenStats }: ToolDisplayProps) => { |
| 31 | const [areArgumentsExpanded, setAreArgumentsExpanded] = useState(status === "pending_approval"); |
| 32 | const [areResultsExpanded, setAreResultsExpanded] = useState(false); |
| 33 | const [isCopied, setIsCopied] = useState(false); |
| 34 | const [isSubmitting, setIsSubmitting] = useState(false); |
| 35 | const [showRejectForm, setShowRejectForm] = useState(false); |
| 36 | const [rejectionReason, setRejectionReason] = useState(""); |
| 37 | |
| 38 | const hasResult = result !== undefined; |
| 39 | |
| 40 | const handleCopy = async () => { |
| 41 | try { |
| 42 | await navigator.clipboard.writeText(result?.content || ""); |
| 43 | setIsCopied(true); |
| 44 | setTimeout(() => setIsCopied(false), 2000); |
| 45 | } catch (err) { |
| 46 | console.error("Failed to copy text:", err); |
| 47 | } |
| 48 | }; |
| 49 | |
| 50 | const handleApprove = async () => { |
| 51 | if (!onApprove) { |
| 52 | return; |
| 53 | } |
| 54 | setIsSubmitting(true); |
| 55 | onApprove(); |
| 56 | }; |
| 57 | |
| 58 | /** Show the rejection reason form instead of immediately rejecting. */ |
| 59 | const handleRejectClick = () => { |
| 60 | setShowRejectForm(true); |
| 61 | }; |
| 62 | |
| 63 | /** Confirm rejection — submits with optional reason. */ |
| 64 | const handleRejectConfirm = async () => { |
| 65 | if (!onReject) { |
| 66 | return; |
| 67 | } |
| 68 | setShowRejectForm(false); |
| 69 | setIsSubmitting(true); |
| 70 | onReject(rejectionReason.trim() || undefined); |
| 71 | }; |
| 72 | |
| 73 | /** Cancel the rejection form — go back to Approve/Reject buttons. */ |
| 74 | const handleRejectCancel = () => { |
| 75 | setShowRejectForm(false); |
| 76 | setRejectionReason(""); |
| 77 | }; |
| 78 | |
| 79 | // Define UI elements based on status |
| 80 | const getStatusDisplay = () => { |
| 81 | if (isError && status === "executing") { |
| 82 | return ( |
| 83 | <> |
| 84 | <AlertCircle className="w-3 h-3 inline-block mr-2 text-red-500" /> |
| 85 | Error |
| 86 | </> |
| 87 | ); |
nothing calls this directly
no test coverage detected