Add continue on failure as passthrough and cache_actions property (#983)

This commit is contained in:
Shuchang Zheng
2024-10-15 13:41:54 -07:00
committed by GitHub
parent 575dd356fe
commit ec2217a3fe
12 changed files with 74 additions and 52 deletions

View File

@@ -1,9 +1,9 @@
import type { Node } from "@xyflow/react";
import { NodeBaseData } from "../types";
export type CodeBlockNodeData = {
export type CodeBlockNodeData = NodeBaseData & {
code: string;
editable: boolean;
label: string;
};
export type CodeBlockNode = Node<CodeBlockNodeData, "codeBlock">;
@@ -12,4 +12,5 @@ export const codeBlockNodeDefaultData: CodeBlockNodeData = {
editable: true,
label: "",
code: `# To assign a value to the output of this block,\n# assign the value to the variable 'result'\n# The final value of 'result' will be used as the output of this block\n\nresult = 5`,
continueOnFailure: false,
} as const;

View File

@@ -1,10 +1,10 @@
import type { Node } from "@xyflow/react";
import { SKYVERN_DOWNLOAD_DIRECTORY } from "../../constants";
import { NodeBaseData } from "../types";
export type DownloadNodeData = {
export type DownloadNodeData = NodeBaseData & {
url: string;
editable: boolean;
label: string;
};
export type DownloadNode = Node<DownloadNodeData, "download">;
@@ -13,6 +13,7 @@ export const downloadNodeDefaultData: DownloadNodeData = {
editable: true,
label: "",
url: SKYVERN_DOWNLOAD_DIRECTORY,
continueOnFailure: false,
} as const;
export const helpTooltipContent = {

View File

@@ -1,9 +1,9 @@
import type { Node } from "@xyflow/react";
import { NodeBaseData } from "../types";
export type FileParserNodeData = {
export type FileParserNodeData = NodeBaseData & {
fileUrl: string;
editable: boolean;
label: string;
};
export type FileParserNode = Node<FileParserNodeData, "fileParser">;
@@ -12,6 +12,7 @@ export const fileParserNodeDefaultData: FileParserNodeData = {
editable: true,
label: "",
fileUrl: "",
continueOnFailure: false,
} as const;
export const helpTooltipContent = {

View File

@@ -1,9 +1,9 @@
import type { Node } from "@xyflow/react";
import { NodeBaseData } from "../types";
export type LoopNodeData = {
export type LoopNodeData = NodeBaseData & {
loopValue: string;
editable: boolean;
label: string;
};
export type LoopNode = Node<LoopNodeData, "loop">;
@@ -12,6 +12,7 @@ export const loopNodeDefaultData: LoopNodeData = {
editable: true,
label: "",
loopValue: "",
continueOnFailure: false,
} as const;
export function isLoopNode(node: Node): node is LoopNode {

View File

@@ -7,14 +7,14 @@ import {
SMTP_PORT_PARAMETER_KEY,
SMTP_USERNAME_PARAMETER_KEY,
} from "../../constants";
import { NodeBaseData } from "../types";
export type SendEmailNodeData = {
export type SendEmailNodeData = NodeBaseData & {
recipients: string;
subject: string;
body: string;
fileAttachments: string;
editable: boolean;
label: string;
sender: string;
smtpHostSecretParameterKey?: string;
smtpPortSecretParameterKey?: string;
@@ -36,6 +36,7 @@ export const sendEmailNodeDefaultData: SendEmailNodeData = {
smtpPortSecretParameterKey: SMTP_PORT_PARAMETER_KEY,
smtpUsernameSecretParameterKey: SMTP_USERNAME_PARAMETER_KEY,
smtpPasswordSecretParameterKey: SMTP_PASSWORD_PARAMETER_KEY,
continueOnFailure: false,
} as const;
export const helpTooltipContent = {

View File

@@ -1,6 +1,7 @@
import type { Node } from "@xyflow/react";
import { NodeBaseData } from "../types";
export type TaskNodeData = {
export type TaskNodeData = NodeBaseData & {
url: string;
navigationGoal: string;
dataExtractionGoal: string;
@@ -11,11 +12,10 @@ export type TaskNodeData = {
allowDownloads: boolean;
downloadSuffix: string | null;
editable: boolean;
label: string;
parameterKeys: Array<string>;
totpVerificationUrl: string | null;
totpIdentifier: string | null;
continueOnFailure: boolean;
cacheActions: boolean;
};
export type TaskNode = Node<TaskNodeData, "task">;
@@ -38,6 +38,7 @@ export const taskNodeDefaultData: TaskNodeData = {
totpVerificationUrl: null,
totpIdentifier: null,
continueOnFailure: false,
cacheActions: false,
} as const;
export function isTaskNode(node: Node): node is TaskNode {

View File

@@ -1,6 +1,7 @@
import type { Node } from "@xyflow/react";
import { NodeBaseData } from "../types";
export type TextPromptNodeData = {
export type TextPromptNodeData = NodeBaseData & {
prompt: string;
jsonSchema: string;
editable: boolean;
@@ -14,6 +15,7 @@ export const textPromptNodeDefaultData: TextPromptNodeData = {
label: "",
prompt: "",
jsonSchema: "null",
continueOnFailure: false,
} as const;
export const helpTooltipContent = {

View File

@@ -1,10 +1,10 @@
import type { Node } from "@xyflow/react";
import { SKYVERN_DOWNLOAD_DIRECTORY } from "../../constants";
import { NodeBaseData } from "../types";
export type UploadNodeData = {
export type UploadNodeData = NodeBaseData & {
path: string;
editable: boolean;
label: string;
};
export type UploadNode = Node<UploadNodeData, "upload">;
@@ -13,6 +13,7 @@ export const uploadNodeDefaultData: UploadNodeData = {
editable: true,
label: "",
path: SKYVERN_DOWNLOAD_DIRECTORY,
continueOnFailure: false,
} as const;
export const helpTooltipContent = {

View File

@@ -0,0 +1,4 @@
export type NodeBaseData = {
label: string;
continueOnFailure: boolean;
};

View File

@@ -1,7 +1,11 @@
import Dagre from "@dagrejs/dagre";
import type { Node } from "@xyflow/react";
import { Edge } from "@xyflow/react";
import { nanoid } from "nanoid";
import type {
AWSSecretParameter,
BitwardenSensitiveInformationParameter,
ContextParameter,
OutputParameter,
Parameter,
WorkflowApiResponse,
@@ -33,6 +37,7 @@ import {
SMTP_USERNAME_AWS_KEY,
SMTP_USERNAME_PARAMETER_KEY,
} from "./constants";
import { ParametersState } from "./FlowRenderer";
import { AppNode, nodeTypes } from "./nodes";
import { codeBlockNodeDefaultData } from "./nodes/CodeBlockNode/types";
import { downloadNodeDefaultData } from "./nodes/DownloadNode/types";
@@ -42,8 +47,8 @@ import { NodeAdderNode } from "./nodes/NodeAdderNode/types";
import { sendEmailNodeDefaultData } from "./nodes/SendEmailNode/types";
import { taskNodeDefaultData } from "./nodes/TaskNode/types";
import { textPromptNodeDefaultData } from "./nodes/TextPromptNode/types";
import { NodeBaseData } from "./nodes/types";
import { uploadNodeDefaultData } from "./nodes/UploadNode/types";
import type { Node } from "@xyflow/react";
export const NEW_NODE_LABEL_PREFIX = "block_";
@@ -126,6 +131,10 @@ function convertToNode(
position: { x: 0, y: 0 },
connectable: false,
};
const commonData: NodeBaseData = {
label: block.label,
continueOnFailure: block.continue_on_failure,
};
switch (block.block_type) {
case "task": {
return {
@@ -133,7 +142,7 @@ function convertToNode(
...common,
type: "task",
data: {
label: block.label,
...commonData,
editable: true,
url: block.url ?? "",
navigationGoal: block.navigation_goal ?? "",
@@ -147,7 +156,7 @@ function convertToNode(
parameterKeys: block.parameters.map((p) => p.key),
totpIdentifier: block.totp_identifier ?? null,
totpVerificationUrl: block.totp_verification_url ?? null,
continueOnFailure: block.continue_on_failure,
cacheActions: block.cache_actions,
},
};
}
@@ -157,7 +166,7 @@ function convertToNode(
...common,
type: "codeBlock",
data: {
label: block.label,
...commonData,
editable: true,
code: block.code,
},
@@ -169,7 +178,7 @@ function convertToNode(
...common,
type: "sendEmail",
data: {
label: block.label,
...commonData,
editable: true,
body: block.body,
fileAttachments: block.file_attachments.join(", "),
@@ -189,7 +198,7 @@ function convertToNode(
...common,
type: "textPrompt",
data: {
label: block.label,
...commonData,
editable: true,
prompt: block.prompt,
jsonSchema: JSON.stringify(block.json_schema, null, 2),
@@ -202,7 +211,7 @@ function convertToNode(
...common,
type: "loop",
data: {
label: block.label,
...commonData,
editable: true,
loopValue: block.loop_over.key,
},
@@ -214,7 +223,7 @@ function convertToNode(
...common,
type: "fileParser",
data: {
label: block.label,
...commonData,
editable: true,
fileUrl: block.file_url,
},
@@ -227,7 +236,7 @@ function convertToNode(
...common,
type: "download",
data: {
label: block.label,
...commonData,
editable: true,
url: block.url,
},
@@ -240,7 +249,7 @@ function convertToNode(
...common,
type: "upload",
data: {
label: block.label,
...commonData,
editable: true,
path: block.path,
},
@@ -497,11 +506,15 @@ function JSONParseSafe(json: string): Record<string, unknown> | null {
function getWorkflowBlock(
node: Exclude<AppNode, LoopNode | NodeAdderNode>,
): BlockYAML {
const base = {
label: node.data.label,
continue_on_failure: node.data.continueOnFailure,
};
switch (node.type) {
case "task": {
return {
...base,
block_type: "task",
label: node.data.label,
url: node.data.url,
navigation_goal: node.data.navigationGoal,
data_extraction_goal: node.data.dataExtractionGoal,
@@ -519,13 +532,13 @@ function getWorkflowBlock(
parameter_keys: node.data.parameterKeys,
totp_identifier: node.data.totpIdentifier,
totp_verification_url: node.data.totpVerificationUrl,
continue_on_failure: node.data.continueOnFailure,
cache_actions: node.data.cacheActions,
};
}
case "sendEmail": {
return {
...base,
block_type: "send_email",
label: node.data.label,
body: node.data.body,
file_attachments: node.data.fileAttachments
.split(",")
@@ -545,37 +558,37 @@ function getWorkflowBlock(
}
case "codeBlock": {
return {
...base,
block_type: "code",
label: node.data.label,
code: node.data.code,
};
}
case "download": {
return {
...base,
block_type: "download_to_s3",
label: node.data.label,
url: node.data.url,
};
}
case "upload": {
return {
...base,
block_type: "upload_to_s3",
label: node.data.label,
path: node.data.path,
};
}
case "fileParser": {
return {
...base,
block_type: "file_url_parser",
label: node.data.label,
file_url: node.data.fileUrl,
file_type: "csv",
};
}
case "textPrompt": {
return {
...base,
block_type: "text_prompt",
label: node.data.label,
llm_key: "",
prompt: node.data.prompt,
json_schema: JSONParseSafe(node.data.jsonSchema),
@@ -630,13 +643,6 @@ function generateNodeLabel(existingLabels: Array<string>) {
throw new Error("Failed to generate a new node label");
}
import type {
AWSSecretParameter,
BitwardenSensitiveInformationParameter,
ContextParameter,
} from "../types/workflowTypes";
import { ParametersState } from "./FlowRenderer";
/**
* If a parameter is not displayed in the editor, we should echo its value back when saved.
*/
@@ -980,6 +986,7 @@ function convertBlocks(blocks: Array<WorkflowBlock>): Array<BlockYAML> {
parameter_keys: block.parameters.map((p) => p.key),
totp_identifier: block.totp_identifier,
totp_verification_url: block.totp_verification_url,
cache_actions: block.cache_actions,
};
return blockYaml;
}
@@ -1076,22 +1083,22 @@ function convert(workflow: WorkflowApiResponse): WorkflowCreateYAMLRequest {
}
export {
convert,
convertEchoParameters,
createNode,
generateNodeData,
getElements,
getWorkflowBlocks,
layout,
generateNodeLabel,
convertEchoParameters,
getOutputParameterKey,
getUpdatedNodesAfterLabelUpdateForParameterKeys,
getAdditionalParametersForEmailBlock,
getUniqueLabelForExistingNode,
isOutputParameterKey,
getAvailableOutputParameterKeys,
getBlockNameOfOutputParameterKey,
getDefaultValueForParameterType,
getUpdatedParametersAfterLabelUpdateForSourceParameterKey,
getElements,
getOutputParameterKey,
getPreviousNodeIds,
getAvailableOutputParameterKeys,
convert,
getUniqueLabelForExistingNode,
getUpdatedNodesAfterLabelUpdateForParameterKeys,
getUpdatedParametersAfterLabelUpdateForSourceParameterKey,
getWorkflowBlocks,
isOutputParameterKey,
layout,
};

View File

@@ -137,6 +137,7 @@ export type TaskBlock = WorkflowBlockBase & {
download_suffix?: string | null;
totp_verification_url?: string | null;
totp_identifier?: string | null;
cache_actions: boolean;
};
export type ForLoopBlock = WorkflowBlockBase & {

View File

@@ -110,6 +110,7 @@ export type TaskBlockYAML = BlockYAMLBase & {
download_suffix?: string | null;
totp_verification_url?: string | null;
totp_identifier?: string | null;
cache_actions: boolean;
};
export type CodeBlockYAML = BlockYAMLBase & {