diff --git a/surfsense_web/components/tool-ui/dropbox/create-file.tsx b/surfsense_web/components/tool-ui/dropbox/create-file.tsx index ac45f1f5b..70daf491c 100644 --- a/surfsense_web/components/tool-ui/dropbox/create-file.tsx +++ b/surfsense_web/components/tool-ui/dropbox/create-file.tsx @@ -16,6 +16,8 @@ import { SelectValue, } from "@/components/ui/select"; import { useHitlPhase } from "@/hooks/use-hitl-phase"; +import { isInterruptResult, useHitlDecision } from "@/lib/hitl"; +import type { InterruptResult, HitlDecision } from "@/lib/hitl"; interface DropboxAccount { id: number; @@ -29,21 +31,11 @@ interface SupportedType { label: string; } -interface InterruptResult { - __interrupt__: true; - __decided__?: "approve" | "reject" | "edit"; - __completed__?: boolean; - action_requests: Array<{ name: string; args: Record }>; - review_configs: Array<{ - action_name: string; - allowed_decisions: Array<"approve" | "edit" | "reject">; - }>; - context?: { - accounts?: DropboxAccount[]; - parent_folders?: Record>; - supported_types?: SupportedType[]; - error?: string; - }; +interface DropboxCreateFileContext { + accounts?: DropboxAccount[]; + parent_folders?: Record>; + supported_types?: SupportedType[]; + error?: string; } interface SuccessResult { @@ -65,16 +57,7 @@ interface AuthErrorResult { connector_type?: string; } -type CreateDropboxFileResult = InterruptResult | SuccessResult | ErrorResult | AuthErrorResult; - -function isInterruptResult(result: unknown): result is InterruptResult { - return ( - typeof result === "object" && - result !== null && - "__interrupt__" in result && - (result as InterruptResult).__interrupt__ === true - ); -} +type CreateDropboxFileResult = InterruptResult | SuccessResult | ErrorResult | AuthErrorResult; function isErrorResult(result: unknown): result is ErrorResult { return ( @@ -100,12 +83,8 @@ function ApprovalCard({ onDecision, }: { args: { name: string; file_type?: string; content?: string }; - interruptData: InterruptResult; - onDecision: (decision: { - type: "approve" | "reject" | "edit"; - message?: string; - edited_action?: { name: string; args: Record }; - }) => void; + interruptData: InterruptResult; + onDecision: (decision: HitlDecision) => void; }) { const { phase, setProcessing, setRejected } = useHitlPhase(interruptData); const [isPanelOpen, setIsPanelOpen] = useState(false); @@ -455,17 +434,14 @@ export const CreateDropboxFileToolUI = ({ { name: string; file_type?: string; content?: string }, CreateDropboxFileResult >) => { + const { dispatch } = useHitlDecision(); if (!result) return null; if (isInterruptResult(result)) { return ( { - window.dispatchEvent( - new CustomEvent("hitl-decision", { detail: { decisions: [decision] } }) - ); - }} + interruptData={result as InterruptResult} + onDecision={(decision) => dispatch([decision])} /> ); } diff --git a/surfsense_web/components/tool-ui/dropbox/trash-file.tsx b/surfsense_web/components/tool-ui/dropbox/trash-file.tsx index 0b38777c1..3d4ad8a94 100644 --- a/surfsense_web/components/tool-ui/dropbox/trash-file.tsx +++ b/surfsense_web/components/tool-ui/dropbox/trash-file.tsx @@ -7,6 +7,8 @@ import { TextShimmerLoader } from "@/components/prompt-kit/loader"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { useHitlPhase } from "@/hooks/use-hitl-phase"; +import { isInterruptResult, useHitlDecision } from "@/lib/hitl"; +import type { InterruptResult, HitlDecision } from "@/lib/hitl"; interface DropboxAccount { id: number; @@ -22,13 +24,10 @@ interface DropboxFile { document_id?: number; } -interface InterruptResult { - __interrupt__: true; - __decided__?: "approve" | "reject"; - __completed__?: boolean; - action_requests: Array<{ name: string; args: Record }>; - review_configs: Array<{ action_name: string; allowed_decisions: Array<"approve" | "reject"> }>; - context?: { account?: DropboxAccount; file?: DropboxFile; error?: string }; +interface DropboxTrashFileContext { + account?: DropboxAccount; + file?: DropboxFile; + error?: string; } interface SuccessResult { @@ -52,20 +51,12 @@ interface AuthErrorResult { } type DeleteDropboxFileResult = - | InterruptResult + | InterruptResult | SuccessResult | ErrorResult | NotFoundResult | AuthErrorResult; -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" && @@ -95,12 +86,8 @@ function ApprovalCard({ interruptData, onDecision, }: { - interruptData: InterruptResult; - onDecision: (decision: { - type: "approve" | "reject"; - message?: string; - edited_action?: { name: string; args: Record }; - }) => void; + interruptData: InterruptResult; + onDecision: (decision: HitlDecision) => void; }) { const { phase, setProcessing, setRejected } = useHitlPhase(interruptData); const [deleteFromKb, setDeleteFromKb] = useState(false); @@ -308,16 +295,13 @@ export const DeleteDropboxFileToolUI = ({ { file_name: string; delete_from_kb?: boolean }, DeleteDropboxFileResult >) => { + const { dispatch } = useHitlDecision(); if (!result) return null; if (isInterruptResult(result)) { return ( { - window.dispatchEvent( - new CustomEvent("hitl-decision", { detail: { decisions: [decision] } }) - ); - }} + interruptData={result as InterruptResult} + onDecision={(decision) => dispatch([decision])} /> ); } diff --git a/surfsense_web/components/tool-ui/google-drive/create-file.tsx b/surfsense_web/components/tool-ui/google-drive/create-file.tsx index af263032d..2b77d5028 100644 --- a/surfsense_web/components/tool-ui/google-drive/create-file.tsx +++ b/surfsense_web/components/tool-ui/google-drive/create-file.tsx @@ -16,6 +16,8 @@ import { SelectValue, } from "@/components/ui/select"; import { useHitlPhase } from "@/hooks/use-hitl-phase"; +import { isInterruptResult, useHitlDecision } from "@/lib/hitl"; +import type { InterruptResult, HitlDecision } from "@/lib/hitl"; interface GoogleDriveAccount { id: number; @@ -23,24 +25,11 @@ interface GoogleDriveAccount { auth_expired?: boolean; } -interface InterruptResult { - __interrupt__: true; - __decided__?: "approve" | "reject" | "edit"; - __completed__?: boolean; - action_requests: Array<{ - name: string; - args: Record; - }>; - review_configs: Array<{ - action_name: string; - allowed_decisions: Array<"approve" | "edit" | "reject">; - }>; - context?: { - accounts?: GoogleDriveAccount[]; - supported_types?: string[]; - parent_folders?: Record>; - error?: string; - }; +interface DriveCreateFileContext { + accounts?: GoogleDriveAccount[]; + supported_types?: string[]; + parent_folders?: Record>; + error?: string; } interface SuccessResult { @@ -69,21 +58,12 @@ interface AuthErrorResult { } type CreateGoogleDriveFileResult = - | InterruptResult + | InterruptResult | SuccessResult | ErrorResult | InsufficientPermissionsResult | AuthErrorResult; -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" && @@ -122,12 +102,8 @@ function ApprovalCard({ onDecision, }: { args: { name: string; file_type: string; content?: string }; - interruptData: InterruptResult; - onDecision: (decision: { - type: "approve" | "reject" | "edit"; - message?: string; - edited_action?: { name: string; args: Record }; - }) => void; + interruptData: InterruptResult; + onDecision: (decision: HitlDecision) => void; }) { const { phase, setProcessing, setRejected } = useHitlPhase(interruptData); const [isPanelOpen, setIsPanelOpen] = useState(false); @@ -499,18 +475,15 @@ export const CreateGoogleDriveFileToolUI = ({ { name: string; file_type: string; content?: string }, CreateGoogleDriveFileResult >) => { + const { dispatch } = useHitlDecision(); if (!result) return null; if (isInterruptResult(result)) { return ( { - window.dispatchEvent( - new CustomEvent("hitl-decision", { detail: { decisions: [decision] } }) - ); - }} + interruptData={result as InterruptResult} + onDecision={(decision) => dispatch([decision])} /> ); } diff --git a/surfsense_web/components/tool-ui/google-drive/trash-file.tsx b/surfsense_web/components/tool-ui/google-drive/trash-file.tsx index f5ac11a3c..fa0bfc3bd 100644 --- a/surfsense_web/components/tool-ui/google-drive/trash-file.tsx +++ b/surfsense_web/components/tool-ui/google-drive/trash-file.tsx @@ -7,6 +7,8 @@ import { TextShimmerLoader } from "@/components/prompt-kit/loader"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { useHitlPhase } from "@/hooks/use-hitl-phase"; +import { isInterruptResult, useHitlDecision } from "@/lib/hitl"; +import type { InterruptResult, HitlDecision } from "@/lib/hitl"; interface GoogleDriveAccount { id: number; @@ -21,23 +23,10 @@ interface GoogleDriveFile { web_view_link: string; } -interface InterruptResult { - __interrupt__: true; - __decided__?: "approve" | "reject"; - __completed__?: boolean; - 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 DriveTrashFileContext { + account?: GoogleDriveAccount; + file?: GoogleDriveFile; + error?: string; } interface SuccessResult { @@ -77,7 +66,7 @@ interface AuthErrorResult { } type DeleteGoogleDriveFileResult = - | InterruptResult + | InterruptResult | SuccessResult | WarningResult | ErrorResult @@ -85,15 +74,6 @@ type DeleteGoogleDriveFileResult = | InsufficientPermissionsResult | AuthErrorResult; -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" && @@ -151,12 +131,8 @@ function ApprovalCard({ interruptData, onDecision, }: { - interruptData: InterruptResult; - onDecision: (decision: { - type: "approve" | "reject"; - message?: string; - edited_action?: { name: string; args: Record }; - }) => void; + interruptData: InterruptResult; + onDecision: (decision: HitlDecision) => void; }) { const { phase, setProcessing, setRejected } = useHitlPhase(interruptData); const [deleteFromKb, setDeleteFromKb] = useState(false); @@ -416,18 +392,14 @@ export const DeleteGoogleDriveFileToolUI = ({ { file_name: string; delete_from_kb?: boolean }, DeleteGoogleDriveFileResult >) => { + const { dispatch } = useHitlDecision(); if (!result) return null; if (isInterruptResult(result)) { return ( { - const event = new CustomEvent("hitl-decision", { - detail: { decisions: [decision] }, - }); - window.dispatchEvent(event); - }} + interruptData={result as InterruptResult} + onDecision={(decision) => dispatch([decision])} /> ); }