From 67244759c77df7cecdd53e521bffe13989c89adf Mon Sep 17 00:00:00 2001 From: Zamil Majdy Date: Thu, 14 Nov 2024 01:31:22 +0700 Subject: [PATCH] fix(frontend): Fix client-side validation for Agent Executor Block (#8643) * feat(frontend): Center initial canvas & add option to open graph on agent executor blok * Removed unused variable --- .../frontend/src/components/CustomNode.tsx | 18 +++++++++++++++++- .../frontend/src/hooks/useAgentGraph.ts | 19 ++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/autogpt_platform/frontend/src/components/CustomNode.tsx b/autogpt_platform/frontend/src/components/CustomNode.tsx index 3890ad573358..85a38fc911d5 100644 --- a/autogpt_platform/frontend/src/components/CustomNode.tsx +++ b/autogpt_platform/frontend/src/components/CustomNode.tsx @@ -40,7 +40,12 @@ import NodeOutputs from "./NodeOutputs"; import { IconCoin } from "./ui/icons"; import * as Separator from "@radix-ui/react-separator"; import * as ContextMenu from "@radix-ui/react-context-menu"; -import { DotsVerticalIcon, TrashIcon, CopyIcon } from "@radix-ui/react-icons"; +import { + DotsVerticalIcon, + TrashIcon, + CopyIcon, + ExitIcon, +} from "@radix-ui/react-icons"; export type ConnectionData = Array<{ edge_id: string; @@ -96,11 +101,13 @@ export function CustomNode({ >(); const isInitialSetup = useRef(true); const flowContext = useContext(FlowContext); + let nodeFlowId = ""; if (data.uiType === BlockUIType.AGENT) { // Display the graph's schema instead AgentExecutorBlock's schema. data.inputSchema = data.hardcodedValues?.input_schema || {}; data.outputSchema = data.hardcodedValues?.output_schema || {}; + nodeFlowId = data.hardcodedValues?.graph_id || nodeFlowId; } if (!flowContext) { @@ -496,6 +503,15 @@ export function CustomNode({ Copy + {nodeFlowId && ( + window.open(`/build?flowID=${nodeFlowId}`)} + className="flex cursor-pointer items-center rounded-md px-3 py-2 hover:bg-gray-100" + > + + Open agent + + )} { - let isValid = true; + const validateNodes = useCallback((): string | null => { + let errorMessage = null; nodes.forEach((node) => { const validate = ajv.compile(node.data.inputSchema); const errors = {} as { [key: string]: string }; // Validate values against schema using AJV - const valid = validate(node.data.hardcodedValues); + const inputData = + node.data.uiType === BlockUIType.AGENT + ? node.data.hardcodedValues?.data || {} + : node.data.hardcodedValues || {}; + const valid = validate(inputData); if (!valid) { // Populate errors if validation fails validate.errors?.forEach((error) => { @@ -385,7 +389,7 @@ export default function useAgentGraph( return; } console.warn("Error", error); - isValid = false; + errorMessage = error.message || "Invalid input"; if (path && error.message) { const key = path.slice(1); console.log("Error", key, error.message); @@ -417,7 +421,7 @@ export default function useAgentGraph( }); }); - return isValid; + return errorMessage; }, [nodes]); // Handle user requests @@ -471,10 +475,11 @@ export default function useAgentGraph( }); // If run was requested, run the agent } else if (saveRunRequest.request === "run") { - if (!validateNodes()) { + const validationError = validateNodes(); + if (validationError) { console.error("Validation failed; aborting run"); toast({ - title: "Invalid credentials or inputs", + title: `Validation failed: ${validationError}`, variant: "destructive", duration: 2000, });