diff --git a/surfsense_web/components/tool-ui/google-drive/index.ts b/surfsense_web/components/tool-ui/google-drive/index.ts
index a01c781a7..8a4225469 100644
--- a/surfsense_web/components/tool-ui/google-drive/index.ts
+++ b/surfsense_web/components/tool-ui/google-drive/index.ts
@@ -1 +1,2 @@
export { CreateGoogleDriveFileToolUI } from "./create-file";
+export { TrashGoogleDriveFileToolUI } from "./trash-file";
diff --git a/surfsense_web/components/tool-ui/google-drive/trash-file.tsx b/surfsense_web/components/tool-ui/google-drive/trash-file.tsx
new file mode 100644
index 000000000..39cd9cadd
--- /dev/null
+++ b/surfsense_web/components/tool-ui/google-drive/trash-file.tsx
@@ -0,0 +1,359 @@
+"use client";
+
+import { makeAssistantToolUI } from "@assistant-ui/react";
+import {
+ AlertTriangleIcon,
+ CheckIcon,
+ InfoIcon,
+ Loader2Icon,
+ Trash2Icon,
+ XIcon,
+} from "lucide-react";
+import { useState } from "react";
+import { Button } from "@/components/ui/button";
+
+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;
+}
+
+interface ErrorResult {
+ status: "error";
+ message: string;
+}
+
+interface NotFoundResult {
+ status: "not_found";
+ message: string;
+}
+
+type TrashGoogleDriveFileResult =
+ | InterruptResult
+ | SuccessResult
+ | ErrorResult
+ | NotFoundResult;
+
+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"
+ );
+}
+
+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 account = interruptData.context?.account;
+ const file = interruptData.context?.file;
+ const fileLabel = file?.mime_type
+ ? (MIME_TYPE_LABELS[file.mime_type] ?? "File")
+ : "File";
+
+ return (
+
+ {/* Header */}
+
+
+
+
Trash 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 && (
+
+ )}
+ >
+ )}
+
+ )}
+
+ {/* Trash warning */}
+ {!decided && (
+
+
+ ⚠️ The file will be moved to Google Drive trash. You can restore it from trash within 30 days.
+
+
+ )}
+
+ {/* Action buttons */}
+
+ {decided ? (
+
+ {decided === "approve" ? (
+ <>
+
+ Approved
+ >
+ ) : (
+ <>
+
+ Rejected
+ >
+ )}
+
+ ) : (
+ <>
+
+
+ >
+ )}
+
+
+ );
+}
+
+function ErrorCard({ result }: { result: ErrorResult }) {
+ return (
+
+ );
+}
+
+function NotFoundCard({ result }: { result: NotFoundResult }) {
+ return (
+
+ );
+}
+
+function SuccessCard({ result }: { result: SuccessResult }) {
+ return (
+
+
+
+
+
+
+
+ {result.message || "File moved to trash successfully"}
+
+
+
+
+ );
+}
+
+export const TrashGoogleDriveFileToolUI = makeAssistantToolUI<
+ { file_name: string },
+ TrashGoogleDriveFileResult
+>({
+ toolName: "trash_google_drive_file",
+ render: function TrashGoogleDriveFileUI({ 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 (isNotFoundResult(result)) return ;
+ if (isErrorResult(result)) return ;
+
+ return ;
+ },
+});
diff --git a/surfsense_web/components/tool-ui/index.ts b/surfsense_web/components/tool-ui/index.ts
index 8fab309d2..0af026dac 100644
--- a/surfsense_web/components/tool-ui/index.ts
+++ b/surfsense_web/components/tool-ui/index.ts
@@ -32,7 +32,7 @@ export {
} from "./display-image";
export { GeneratePodcastToolUI } from "./generate-podcast";
export { GenerateReportToolUI } from "./generate-report";
-export { CreateGoogleDriveFileToolUI } from "./google-drive";
+export { CreateGoogleDriveFileToolUI, TrashGoogleDriveFileToolUI } from "./google-drive";
export {
Image,
ImageErrorBoundary,