From 2438bcacbf40d73118b01a85d09ea0c740ad4261 Mon Sep 17 00:00:00 2001 From: Shuchang Zheng Date: Mon, 26 May 2025 08:19:42 -0700 Subject: [PATCH] add engine to more blocks (#2457) --- skyvern-frontend/src/api/types.ts | 9 ++++++ .../src/components/EngineSelector.tsx | 31 +++++++++++++++++++ .../editor/nodes/ActionNode/ActionNode.tsx | 16 ++++++++++ .../editor/nodes/ActionNode/types.ts | 3 ++ .../nodes/ExtractionNode/ExtractionNode.tsx | 16 ++++++++++ .../editor/nodes/ExtractionNode/types.ts | 3 ++ .../FileDownloadNode/FileDownloadNode.tsx | 16 ++++++++++ .../editor/nodes/FileDownloadNode/types.ts | 3 ++ .../editor/nodes/LoginNode/LoginNode.tsx | 16 ++++++++++ .../workflows/editor/nodes/LoginNode/types.ts | 3 ++ .../nodes/NavigationNode/NavigationNode.tsx | 28 ++++------------- .../editor/nodes/NavigationNode/types.ts | 5 +-- .../editor/nodes/TaskNode/TaskNode.tsx | 16 ++++++++++ .../workflows/editor/nodes/TaskNode/types.ts | 3 ++ .../workflows/editor/workflowEditorUtils.ts | 19 ++++++++++-- .../routes/workflows/types/workflowTypes.ts | 9 ++++-- .../workflows/types/workflowYamlTypes.ts | 8 ++++- skyvern/forge/sdk/workflow/models/yaml.py | 5 +++ skyvern/forge/sdk/workflow/service.py | 5 +++ 19 files changed, 185 insertions(+), 29 deletions(-) create mode 100644 skyvern-frontend/src/components/EngineSelector.tsx diff --git a/skyvern-frontend/src/api/types.ts b/skyvern-frontend/src/api/types.ts index 3926383c..4c471056 100644 --- a/skyvern-frontend/src/api/types.ts +++ b/skyvern-frontend/src/api/types.ts @@ -391,3 +391,12 @@ export type CreditCardCredential = { card_brand: string; card_holder_name: string; }; + +export const RunEngine = { + SkyvernV1: "skyvern-1.0", + SkyvernV2: "skyvern-2.0", + OpenaiCua: "openai-cua", + AnthropicCua: "anthropic-cua", +} as const; + +export type RunEngine = (typeof RunEngine)[keyof typeof RunEngine]; diff --git a/skyvern-frontend/src/components/EngineSelector.tsx b/skyvern-frontend/src/components/EngineSelector.tsx new file mode 100644 index 00000000..b0a8024a --- /dev/null +++ b/skyvern-frontend/src/components/EngineSelector.tsx @@ -0,0 +1,31 @@ +import { RunEngine } from "@/api/types"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; + +type Props = { + value: RunEngine | null; + onChange: (value: RunEngine) => void; + className?: string; +}; + +function RunEngineSelector({ value, onChange, className }: Props) { + return ( + + ); +} + +export { RunEngineSelector }; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx index 113b4afd..a9699c0f 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx @@ -34,6 +34,7 @@ import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; +import { RunEngineSelector } from "@/components/EngineSelector"; const urlTooltip = "The URL Skyvern is navigating to. Leave this field blank to pick up from where the last block left off."; @@ -59,6 +60,7 @@ function ActionNode({ id, data }: NodeProps) { downloadSuffix: data.downloadSuffix, totpVerificationUrl: data.totpVerificationUrl, totpIdentifier: data.totpIdentifier, + engine: data.engine, }); const deleteNodeCallback = useDeleteNodeCallback(); @@ -181,6 +183,20 @@ function ActionNode({ id, data }: NodeProps) { }} /> +
+
+ +
+ { + handleChange("engine", value); + }} + className="nopan w-52 text-xs" + /> +
diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/types.ts index 71cef107..e05711de 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/types.ts @@ -1,5 +1,6 @@ import type { Node } from "@xyflow/react"; import { NodeBaseData } from "../types"; +import { RunEngine } from "@/api/types"; export type ActionNodeData = NodeBaseData & { url: string; @@ -12,6 +13,7 @@ export type ActionNodeData = NodeBaseData & { totpVerificationUrl: string | null; totpIdentifier: string | null; cacheActions: boolean; + engine: RunEngine | null; }; export type ActionNode = Node; @@ -30,6 +32,7 @@ export const actionNodeDefaultData: ActionNodeData = { totpIdentifier: null, continueOnFailure: false, cacheActions: false, + engine: RunEngine.SkyvernV1, } as const; export function isActionNode(node: Node): node is ActionNode { diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx index b46c4615..75552ba6 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx @@ -33,6 +33,7 @@ import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; import { WorkflowDataSchemaInputGroup } from "@/components/DataSchemaInputGroup/WorkflowDataSchemaInputGroup"; import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; +import { RunEngineSelector } from "@/components/EngineSelector"; function ExtractionNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -48,6 +49,7 @@ function ExtractionNode({ id, data }: NodeProps) { maxStepsOverride: data.maxStepsOverride, continueOnFailure: data.continueOnFailure, cacheActions: data.cacheActions, + engine: data.engine, }); const deleteNodeCallback = useDeleteNodeCallback(); const nodes = useNodes(); @@ -159,6 +161,20 @@ function ExtractionNode({ id, data }: NodeProps) { }} />
+
+
+ +
+ { + handleChange("engine", value); + }} + className="nopan w-52 text-xs" + /> +
+
+
+ +
+ { + handleChange("engine", value); + }} + className="nopan w-52 text-xs" + /> +
+
+
+ +
+ { + handleChange("engine", value); + }} + className="nopan w-52 text-xs" + /> +
- + className="nopan w-52 text-xs" + />
diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/types.ts index c90165ce..79694135 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/types.ts @@ -1,5 +1,6 @@ import type { Node } from "@xyflow/react"; import { NodeBaseData } from "../types"; +import { RunEngine } from "@/api/types"; export type NavigationNodeData = NodeBaseData & { url: string; @@ -7,7 +8,7 @@ export type NavigationNodeData = NodeBaseData & { errorCodeMapping: string; completeCriterion: string; terminateCriterion: string; - engine: string | null; + engine: RunEngine | null; maxRetries: number | null; maxStepsOverride: number | null; allowDownloads: boolean; @@ -28,7 +29,7 @@ export const navigationNodeDefaultData: NavigationNodeData = { completeCriterion: "", terminateCriterion: "", errorCodeMapping: "null", - engine: "skyvern-1.0", + engine: RunEngine.SkyvernV1, maxRetries: null, maxStepsOverride: null, allowDownloads: false, diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx index 54b7af96..2a29db9d 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx @@ -36,6 +36,7 @@ import { ParametersMultiSelect } from "./ParametersMultiSelect"; import type { TaskNode } from "./types"; import { WorkflowDataSchemaInputGroup } from "@/components/DataSchemaInputGroup/WorkflowDataSchemaInputGroup"; import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; +import { RunEngineSelector } from "@/components/EngineSelector"; function TaskNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -67,6 +68,7 @@ function TaskNode({ id, data }: NodeProps) { totpVerificationUrl: data.totpVerificationUrl, totpIdentifier: data.totpIdentifier, includeActionHistoryInVerification: data.includeActionHistoryInVerification, + engine: data.engine, }); function handleChange(key: string, value: unknown) { @@ -229,6 +231,20 @@ function TaskNode({ id, data }: NodeProps) { />
+
+
+ +
+ { + handleChange("engine", value); + }} + className="nopan w-52 text-xs" + /> +