"use client"; import { makeAssistantToolUI } from "@assistant-ui/react"; import { AlertTriangleIcon, CheckIcon, InfoIcon, Loader2Icon, RefreshCwIcon, Trash2Icon, XIcon, } from "lucide-react"; import { useParams } from "next/navigation"; import { useState } from "react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { authenticatedFetch } from "@/lib/auth-utils"; interface GoogleDriveAccount { id: number; name: string; } interface GoogleDriveFile { file_id: string; name: string; mime_type: string; web_view_link: string; } interface InterruptResult { __interrupt__: true; __decided__?: "approve" | "reject"; action_requests: Array<{ name: string; args: Record; }>; review_configs: Array<{ action_name: string; allowed_decisions: Array<"approve" | "reject">; }>; context?: { account?: GoogleDriveAccount; file?: GoogleDriveFile; error?: string; }; } interface SuccessResult { status: "success"; file_id: string; message?: string; deleted_from_kb?: boolean; } interface WarningResult { status: "success"; warning: string; file_id?: string; message?: string; } interface ErrorResult { status: "error"; message: string; } interface NotFoundResult { status: "not_found"; message: string; } interface InsufficientPermissionsResult { status: "insufficient_permissions"; connector_id: number; message: string; } type DeleteGoogleDriveFileResult = | InterruptResult | SuccessResult | WarningResult | ErrorResult | NotFoundResult | InsufficientPermissionsResult; function isInterruptResult(result: unknown): result is InterruptResult { return ( typeof result === "object" && result !== null && "__interrupt__" in result && (result as InterruptResult).__interrupt__ === true ); } function isErrorResult(result: unknown): result is ErrorResult { return ( typeof result === "object" && result !== null && "status" in result && (result as ErrorResult).status === "error" ); } function isNotFoundResult(result: unknown): result is NotFoundResult { return ( typeof result === "object" && result !== null && "status" in result && (result as NotFoundResult).status === "not_found" ); } function isWarningResult(result: unknown): result is WarningResult { return ( typeof result === "object" && result !== null && "status" in result && (result as WarningResult).status === "success" && "warning" in result && typeof (result as WarningResult).warning === "string" ); } function isInsufficientPermissionsResult(result: unknown): result is InsufficientPermissionsResult { return ( typeof result === "object" && result !== null && "status" in result && (result as InsufficientPermissionsResult).status === "insufficient_permissions" ); } const MIME_TYPE_LABELS: Record = { "application/vnd.google-apps.document": "Google Doc", "application/vnd.google-apps.spreadsheet": "Google Sheet", "application/vnd.google-apps.presentation": "Google Slides", }; function ApprovalCard({ interruptData, onDecision, }: { interruptData: InterruptResult; onDecision: (decision: { type: "approve" | "reject"; message?: string; edited_action?: { name: string; args: Record }; }) => void; }) { const [decided, setDecided] = useState<"approve" | "reject" | null>( interruptData.__decided__ ?? null ); const [deleteFromKb, setDeleteFromKb] = useState(false); const account = interruptData.context?.account; const file = interruptData.context?.file; const fileLabel = file?.mime_type ? (MIME_TYPE_LABELS[file.mime_type] ?? "File") : "File"; return (
{/* Header */}

Delete Google Drive File

Requires your approval to proceed

{/* Context — read-only file details */} {!decided && interruptData.context && (
{interruptData.context.error ? (

{interruptData.context.error}

) : ( <> {account && (
Google Drive Account
{account.name}
)} {file && (
File to Trash
{file.name}
{fileLabel}
{file.web_view_link && ( Open in Drive )}
)} )}
)} {/* Trash warning */} {!decided && (

⚠️ The file will be moved to Google Drive trash. You can restore it from trash within 30 days.

)} {/* Checkbox for deleting from knowledge base */} {!decided && (
)} {/* Action buttons */}
{decided ? (

{decided === "approve" ? ( <> Approved ) : ( <> Rejected )}

) : ( <> )}
); } function InsufficientPermissionsCard({ result }: { result: InsufficientPermissionsResult }) { const params = useParams(); const searchSpaceId = params.search_space_id as string; const [loading, setLoading] = useState(false); async function handleReauth() { setLoading(true); try { const backendUrl = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "http://localhost:8000"; const url = new URL(`${backendUrl}/api/v1/auth/google/drive/connector/reauth`); url.searchParams.set("connector_id", String(result.connector_id)); url.searchParams.set("space_id", searchSpaceId); url.searchParams.set("return_url", window.location.pathname); const response = await authenticatedFetch(url.toString()); if (!response.ok) { const data = await response.json().catch(() => ({})); toast.error(data.detail ?? "Failed to initiate re-authentication. Please try again."); return; } const data = await response.json(); if (data.auth_url) { window.location.href = data.auth_url; } } catch { toast.error("Failed to initiate re-authentication. Please try again."); } finally { setLoading(false); } } return (

Additional permissions required

{result.message}

); } function WarningCard({ result }: { result: WarningResult }) { return (

Partial success

{result.message &&

{result.message}

}

{result.warning}

); } function ErrorCard({ result }: { result: ErrorResult }) { return (

Failed to delete file

{result.message}

); } function NotFoundCard({ result }: { result: NotFoundResult }) { return (

{result.message}

); } function SuccessCard({ result }: { result: SuccessResult }) { return (

{result.message || "File moved to trash successfully"}

{result.deleted_from_kb && (
✓ Also removed from knowledge base
)}
); } export const DeleteGoogleDriveFileToolUI = makeAssistantToolUI< { file_name: string; delete_from_kb?: boolean }, DeleteGoogleDriveFileResult >({ toolName: "delete_google_drive_file", render: function DeleteGoogleDriveFileUI({ result, status }) { if (status.type === "running") { return (

Looking up file in Google Drive...

); } if (!result) return null; if (isInterruptResult(result)) { return ( { window.dispatchEvent( new CustomEvent("hitl-decision", { detail: { decisions: [decision] } }) ); }} /> ); } if ( typeof result === "object" && result !== null && "status" in result && (result as { status: string }).status === "rejected" ) { return null; } if (isInsufficientPermissionsResult(result)) return ; if (isNotFoundResult(result)) return ; if (isWarningResult(result)) return ; if (isErrorResult(result)) return ; return ; }, });