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
pull/8632/head^2
Zamil Majdy 2024-11-14 01:31:22 +07:00 committed by GitHub
parent a3655b8a85
commit 67244759c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 8 deletions

View File

@ -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({
<CopyIcon className="mr-2 h-5 w-5" />
<span>Copy</span>
</ContextMenu.Item>
{nodeFlowId && (
<ContextMenu.Item
onSelect={() => window.open(`/build?flowID=${nodeFlowId}`)}
className="flex cursor-pointer items-center rounded-md px-3 py-2 hover:bg-gray-100"
>
<ExitIcon className="mr-2 h-5 w-5" />
<span>Open agent</span>
</ContextMenu.Item>
)}
<ContextMenu.Separator className="my-1 h-px bg-gray-300" />
<ContextMenu.Item
onSelect={deleteNode}

View File

@ -359,15 +359,19 @@ export default function useAgentGraph(
});
}, [updateQueue, nodesSyncedWithSavedAgent, updateNodesWithExecutionData]);
const validateNodes = useCallback((): boolean => {
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,
});