From c43ec25d22e40282575914c58197ea8479a4ed35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Celal=20Zamano=C4=9Flu?= <95054566+celalzamanoglu@users.noreply.github.com> Date: Thu, 19 Feb 2026 18:58:30 +0300 Subject: [PATCH] feat: show all block parameters including advanced settings in WR UI (#SKY-6813) (#4807) --- .../debugger/DebuggerPostRunParameters.tsx | 147 ++++++++++++- .../debugger/DebuggerTaskBlockParameters.tsx | 23 +++ .../workflows/types/workflowRunTypes.ts | 3 +- .../workflowRun/TaskBlockParameters.tsx | 194 +++++++++++++++++- .../workflowRun/WorkflowPostRunParameters.tsx | 177 +++++++++++++++- .../blockInfo/ConditionalBlockParameters.tsx | 110 ++++++++++ .../blockInfo/HttpRequestBlockParameters.tsx | 134 ++++++++++++ .../HumanInteractionBlockParameters.tsx | 59 ++++++ .../blockInfo/PrintPageBlockParameters.tsx | 72 +++++++ .../blockInfo/Taskv2BlockParameters.tsx | 82 ++++++++ .../blockInfo/WaitBlockParameters.tsx | 26 +++ 11 files changed, 1019 insertions(+), 8 deletions(-) create mode 100644 skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/ConditionalBlockParameters.tsx create mode 100644 skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HttpRequestBlockParameters.tsx create mode 100644 skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HumanInteractionBlockParameters.tsx create mode 100644 skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/PrintPageBlockParameters.tsx create mode 100644 skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/Taskv2BlockParameters.tsx create mode 100644 skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/WaitBlockParameters.tsx diff --git a/skyvern-frontend/src/routes/workflows/debugger/DebuggerPostRunParameters.tsx b/skyvern-frontend/src/routes/workflows/debugger/DebuggerPostRunParameters.tsx index 3196f55b..b45163c4 100644 --- a/skyvern-frontend/src/routes/workflows/debugger/DebuggerPostRunParameters.tsx +++ b/skyvern-frontend/src/routes/workflows/debugger/DebuggerPostRunParameters.tsx @@ -13,6 +13,7 @@ import { DebuggerSendEmailBlockParameters } from "./DebuggerSendEmailBlockInfo"; import { ProxyLocation } from "@/api/types"; import { KeyValueInput } from "@/components/KeyValueInput"; import { HelpTooltip } from "@/components/HelpTooltip"; +import { Switch } from "@/components/ui/switch"; function DebuggerPostRunParameters() { const { data: workflowRunTimeline, isLoading: workflowRunTimelineIsLoading } = @@ -104,6 +105,127 @@ function DebuggerPostRunParameters() { ) : null} + {activeBlock && activeBlock.block_type === WorkflowBlockTypes.Wait ? ( +
+
+

Wait Block Parameters

+
+
+

Wait Duration

+ +
+ +
+
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.HumanInteraction ? ( +
+
+

+ Human Interaction Block Parameters +

+ {activeBlock.instructions ? ( +
+
+

Instructions

+ +
+ +
+ ) : null} + {activeBlock.positive_descriptor ? ( +
+

Positive Descriptor

+ +
+ ) : null} + {activeBlock.negative_descriptor ? ( +
+

Negative Descriptor

+ +
+ ) : null} +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.Conditional ? ( +
+
+

Conditional Block Parameters

+ {activeBlock.executed_branch_expression ? ( +
+
+

Executed Expression

+ +
+ +
+ ) : null} + {typeof activeBlock.executed_branch_result === "boolean" ? ( +
+

Branch Result

+
+ + + {activeBlock.executed_branch_result ? "True" : "False"} + +
+
+ ) : null} + {activeBlock.executed_branch_next_block ? ( +
+

Next Block

+ +
+ ) : null} + {activeBlock.executed_branch_id ? ( +
+

Executed Branch ID

+ +
+ ) : null} +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.TextPrompt ? ( +
+
+

Text Prompt Block Parameters

+ {activeBlock.prompt ? ( +
+
+

Prompt

+ +
+ +
+ ) : null} +
+
+ ) : null}

Workflow Parameters

@@ -171,6 +293,27 @@ function DebuggerPostRunParameters() { />
+ {workflowRun.browser_session_id ? ( +
+
+

Browser Session ID

+ +
+ +
+ ) : null} + {workflowRun.max_screenshot_scrolls != null ? ( +
+
+

Max Screenshot Scrolls

+ +
+ +
+ ) : null} {workflowRun.task_v2 ? ( @@ -187,10 +330,6 @@ function DebuggerPostRunParameters() { readOnly /> - ) : null} diff --git a/skyvern-frontend/src/routes/workflows/debugger/DebuggerTaskBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/debugger/DebuggerTaskBlockParameters.tsx index 1252aa6c..24f21d09 100644 --- a/skyvern-frontend/src/routes/workflows/debugger/DebuggerTaskBlockParameters.tsx +++ b/skyvern-frontend/src/routes/workflows/debugger/DebuggerTaskBlockParameters.tsx @@ -140,6 +140,29 @@ function DebuggerTaskBlockParameters({ block }: Props) { ) : null} + +
+
+

Continue on Failure

+ +
+
+ + + {block.continue_on_failure ? "Enabled" : "Disabled"} + +
+
+ + {block.engine ? ( +
+
+

Engine

+ +
+ +
+ ) : null} ); } diff --git a/skyvern-frontend/src/routes/workflows/types/workflowRunTypes.ts b/skyvern-frontend/src/routes/workflows/types/workflowRunTypes.ts index 6937ed4c..9dc68b11 100644 --- a/skyvern-frontend/src/routes/workflows/types/workflowRunTypes.ts +++ b/skyvern-frontend/src/routes/workflows/types/workflowRunTypes.ts @@ -1,4 +1,4 @@ -import { ActionsApiResponse, Status } from "@/api/types"; +import { ActionsApiResponse, RunEngine, Status } from "@/api/types"; import { isTaskVariantBlock, WorkflowBlockType } from "./workflowTypes"; import { ActionItem } from "../workflowRun/WorkflowRunOverview"; @@ -41,6 +41,7 @@ export type WorkflowRunBlock = { terminate_criterion: string | null; complete_criterion: string | null; include_action_history_in_verification: boolean | null; + engine: RunEngine | null; actions: Array | null; recipients?: Array | null; attachments?: Array | null; diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/TaskBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/TaskBlockParameters.tsx index af367640..5ab12d38 100644 --- a/skyvern-frontend/src/routes/workflows/workflowRun/TaskBlockParameters.tsx +++ b/skyvern-frontend/src/routes/workflows/workflowRun/TaskBlockParameters.tsx @@ -2,14 +2,19 @@ import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResi import { Input } from "@/components/ui/input"; import { CodeEditor } from "@/routes/workflows/components/CodeEditor"; import { WorkflowRunBlock } from "../types/workflowRunTypes"; -import { isTaskVariantBlock, WorkflowBlockTypes } from "../types/workflowTypes"; +import { + isTaskVariantBlock, + WorkflowBlockTypes, + type WorkflowBlock, +} from "../types/workflowTypes"; import { Switch } from "@/components/ui/switch"; type Props = { block: WorkflowRunBlock; + definitionBlock?: WorkflowBlock | null; }; -function TaskBlockParameters({ block }: Props) { +function TaskBlockParameters({ block, definitionBlock }: Props) { const isTaskVariant = isTaskVariantBlock(block); if (!isTaskVariant) { return null; @@ -32,6 +37,66 @@ function TaskBlockParameters({ block }: Props) { block.block_type === WorkflowBlockTypes.Task || block.block_type === WorkflowBlockTypes.Navigation; + // Advanced settings from definition block + const errorCodeMapping = + definitionBlock && + "error_code_mapping" in definitionBlock && + definitionBlock.error_code_mapping + ? definitionBlock.error_code_mapping + : null; + + const maxRetries = + definitionBlock && "max_retries" in definitionBlock + ? definitionBlock.max_retries + : undefined; + + const maxStepsPerRun = + definitionBlock && "max_steps_per_run" in definitionBlock + ? definitionBlock.max_steps_per_run + : undefined; + + const totpVerificationUrl = + definitionBlock && "totp_verification_url" in definitionBlock + ? definitionBlock.totp_verification_url + : null; + + const totpIdentifier = + definitionBlock && "totp_identifier" in definitionBlock + ? definitionBlock.totp_identifier + : null; + + const completeOnDownload = + definitionBlock && "complete_on_download" in definitionBlock + ? definitionBlock.complete_on_download + : undefined; + + const downloadSuffix = + definitionBlock && "download_suffix" in definitionBlock + ? definitionBlock.download_suffix + : null; + + const disableCache = + definitionBlock && "disable_cache" in definitionBlock + ? definitionBlock.disable_cache + : undefined; + + const engine = + block.engine ?? + (definitionBlock && "engine" in definitionBlock + ? definitionBlock.engine + : null); + + const hasAdvancedSettings = + errorCodeMapping !== null || + typeof maxRetries === "number" || + typeof maxStepsPerRun === "number" || + Boolean(totpVerificationUrl) || + Boolean(totpIdentifier) || + completeOnDownload === true || + Boolean(downloadSuffix) || + disableCache === true || + engine !== null; + return ( <>
@@ -151,6 +216,131 @@ function TaskBlockParameters({ block }: Props) {
) : null} + +
+
+

Continue on Failure

+

+ Whether to continue the workflow if this block fails +

+
+
+ + + {block.continue_on_failure ? "Enabled" : "Disabled"} + +
+
+ + {hasAdvancedSettings ? ( + <> +

+ Advanced Settings +

+ + {engine ? ( +
+
+

Engine

+

+ The execution engine used for this block +

+
+ +
+ ) : null} + + {errorCodeMapping ? ( +
+
+

Error Code Mapping

+

+ Custom error codes and their descriptions +

+
+ +
+ ) : null} + + {typeof maxRetries === "number" ? ( +
+
+

Max Retries

+
+ +
+ ) : null} + + {typeof maxStepsPerRun === "number" ? ( +
+
+

Max Steps Per Run

+
+ +
+ ) : null} + + {totpVerificationUrl ? ( +
+
+

TOTP Verification URL

+
+ +
+ ) : null} + + {totpIdentifier ? ( +
+
+

TOTP Identifier

+
+ +
+ ) : null} + + {completeOnDownload === true ? ( +
+
+

Complete on Download

+
+
+ + Enabled +
+
+ ) : null} + + {downloadSuffix ? ( +
+
+

Download Suffix

+
+ +
+ ) : null} + + {disableCache === true ? ( +
+
+

Cache Disabled

+
+
+ + + Cache is disabled for this block + +
+
+ ) : null} + + ) : null} ); } diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/WorkflowPostRunParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/WorkflowPostRunParameters.tsx index 1a272186..0f2defb9 100644 --- a/skyvern-frontend/src/routes/workflows/workflowRun/WorkflowPostRunParameters.tsx +++ b/skyvern-frontend/src/routes/workflows/workflowRun/WorkflowPostRunParameters.tsx @@ -22,6 +22,12 @@ import { CodeBlockParameters } from "./blockInfo/CodeBlockParameters"; import { TextPromptBlockParameters } from "./blockInfo/TextPromptBlockParameters"; import { GotoUrlBlockParameters } from "./blockInfo/GotoUrlBlockParameters"; import { FileDownloadBlockParameters } from "./blockInfo/FileDownloadBlockParameters"; +import { WaitBlockParameters } from "./blockInfo/WaitBlockParameters"; +import { HttpRequestBlockParameters } from "./blockInfo/HttpRequestBlockParameters"; +import { PrintPageBlockParameters } from "./blockInfo/PrintPageBlockParameters"; +import { HumanInteractionBlockParameters } from "./blockInfo/HumanInteractionBlockParameters"; +import { ConditionalBlockParameters } from "./blockInfo/ConditionalBlockParameters"; +import { Taskv2BlockParameters } from "./blockInfo/Taskv2BlockParameters"; function WorkflowPostRunParameters() { const { data: workflowRunTimeline, isLoading: workflowRunTimelineIsLoading } = @@ -86,7 +92,10 @@ function WorkflowPostRunParameters() {

Block Parameters

- +
) : null} @@ -191,6 +200,142 @@ function WorkflowPostRunParameters() { ) : null} + {activeBlock && activeBlock.block_type === WorkflowBlockTypes.Wait ? ( +
+
+

Wait Block

+ +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.HttpRequest && + isBlockOfType(definitionBlock, WorkflowBlockTypes.HttpRequest) ? ( +
+
+

HTTP Request Block

+ +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.PrintPage && + isBlockOfType(definitionBlock, WorkflowBlockTypes.PrintPage) ? ( +
+
+

Print Page Block

+ +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.HumanInteraction ? ( +
+
+

Human Interaction Block

+ +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.Conditional ? ( +
+
+

Conditional Block

+ +
+
+ ) : null} + {activeBlock && + activeBlock.block_type === WorkflowBlockTypes.Taskv2 && + isBlockOfType(definitionBlock, WorkflowBlockTypes.Taskv2) ? ( +
+
+

Task v2 Block

+ +
+
+ ) : null}

Workflow Input Parameters

@@ -252,6 +397,36 @@ function WorkflowPostRunParameters() { />
+ {workflowRun.browser_session_id ? ( +
+
+

Browser Session ID

+
+ +
+ ) : null} + {workflow?.run_with ? ( +
+
+

Run With

+

+ Execution mode for this workflow +

+
+ +
+ ) : null} + {workflowRun.max_screenshot_scrolls != null ? ( +
+
+

Max Screenshot Scrolls

+
+ +
+ ) : null} {workflowRun.task_v2 ? ( diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/ConditionalBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/ConditionalBlockParameters.tsx new file mode 100644 index 00000000..2a0aa5ee --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/ConditionalBlockParameters.tsx @@ -0,0 +1,110 @@ +import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea"; +import { Input } from "@/components/ui/input"; +import { Switch } from "@/components/ui/switch"; +import type { BranchCondition } from "@/routes/workflows/types/workflowTypes"; + +type Props = { + branchConditions: Array | null; + executedBranchId: string | null; + executedBranchExpression: string | null; + executedBranchResult: boolean | null; + executedBranchNextBlock: string | null; +}; + +function ConditionalBlockParameters({ + branchConditions, + executedBranchId, + executedBranchExpression, + executedBranchResult, + executedBranchNextBlock, +}: Props) { + return ( +
+ {executedBranchExpression ? ( +
+
+

Executed Expression

+

+ The branch expression that was evaluated +

+
+ +
+ ) : null} + {typeof executedBranchResult === "boolean" ? ( +
+
+

Branch Result

+
+
+ + + {executedBranchResult ? "True" : "False"} + +
+
+ ) : null} + {executedBranchNextBlock ? ( +
+
+

Next Block

+

+ The block that was executed after the condition +

+
+ +
+ ) : null} + {executedBranchId ? ( +
+
+

Executed Branch ID

+
+ +
+ ) : null} + {branchConditions && branchConditions.length > 0 ? ( +
+

+ Branch Conditions +

+ {branchConditions.map((condition) => ( +
+ {condition.description ? ( +

+ {condition.description} +

+ ) : null} + {condition.criteria?.expression ? ( +
+ Expression: + + {condition.criteria.expression} + +
+ ) : null} + {condition.next_block_label ? ( +
+ Next Block: + + {condition.next_block_label} + +
+ ) : null} + {condition.is_default ? ( + + Default + + ) : null} +
+ ))} +
+ ) : null} +
+ ); +} + +export { ConditionalBlockParameters }; diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HttpRequestBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HttpRequestBlockParameters.tsx new file mode 100644 index 00000000..0f7e8db9 --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HttpRequestBlockParameters.tsx @@ -0,0 +1,134 @@ +import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea"; +import { Input } from "@/components/ui/input"; +import { Switch } from "@/components/ui/switch"; +import { CodeEditor } from "@/routes/workflows/components/CodeEditor"; + +type Props = { + method: string; + url: string | null; + headers: Record | null; + body: Record | null; + files: Record | null; + timeout: number; + followRedirects: boolean; + downloadFilename: string | null; + saveResponseAsFile: boolean; +}; + +function HttpRequestBlockParameters({ + method, + url, + headers, + body, + files, + timeout, + followRedirects, + downloadFilename, + saveResponseAsFile, +}: Props) { + return ( +
+
+
+

Method

+
+ +
+ {url ? ( +
+
+

URL

+
+ +
+ ) : null} + {headers && Object.keys(headers).length > 0 ? ( +
+
+

Headers

+
+ +
+ ) : null} + {body && Object.keys(body).length > 0 ? ( +
+
+

Body

+
+ +
+ ) : null} + {files && Object.keys(files).length > 0 ? ( +
+
+

Files

+

+ File fields and their paths/URLs +

+
+ +
+ ) : null} +
+
+

Timeout

+

In seconds

+
+ +
+
+
+

Follow Redirects

+
+
+ + + {followRedirects ? "Enabled" : "Disabled"} + +
+
+ {downloadFilename ? ( +
+
+

Download Filename

+
+ +
+ ) : null} + {saveResponseAsFile ? ( +
+
+

Save Response as File

+
+
+ + Enabled +
+
+ ) : null} +
+ ); +} + +export { HttpRequestBlockParameters }; diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HumanInteractionBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HumanInteractionBlockParameters.tsx new file mode 100644 index 00000000..b7bb7d01 --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/HumanInteractionBlockParameters.tsx @@ -0,0 +1,59 @@ +import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea"; +import { Input } from "@/components/ui/input"; + +type Props = { + instructions: string | null; + positiveDescriptor: string | null; + negativeDescriptor: string | null; + timeoutSeconds: number | null; +}; + +function HumanInteractionBlockParameters({ + instructions, + positiveDescriptor, + negativeDescriptor, + timeoutSeconds, +}: Props) { + return ( +
+ {instructions ? ( +
+
+

Instructions

+

+ Instructions for the human interaction +

+
+ +
+ ) : null} + {positiveDescriptor ? ( +
+
+

Positive Descriptor

+
+ +
+ ) : null} + {negativeDescriptor ? ( +
+
+

Negative Descriptor

+
+ +
+ ) : null} + {typeof timeoutSeconds === "number" ? ( +
+
+

Timeout

+

In seconds

+
+ +
+ ) : null} +
+ ); +} + +export { HumanInteractionBlockParameters }; diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/PrintPageBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/PrintPageBlockParameters.tsx new file mode 100644 index 00000000..5e0f2719 --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/PrintPageBlockParameters.tsx @@ -0,0 +1,72 @@ +import { Input } from "@/components/ui/input"; +import { Switch } from "@/components/ui/switch"; + +type Props = { + format: string; + landscape: boolean; + printBackground: boolean; + includeTimestamp: boolean; + customFilename: string | null; +}; + +function PrintPageBlockParameters({ + format, + landscape, + printBackground, + includeTimestamp, + customFilename, +}: Props) { + return ( +
+
+
+

Format

+
+ +
+
+
+

Landscape

+
+
+ + + {landscape ? "Enabled" : "Disabled"} + +
+
+
+
+

Print Background

+
+
+ + + {printBackground ? "Enabled" : "Disabled"} + +
+
+
+
+

Include Timestamp

+
+
+ + + {includeTimestamp ? "Enabled" : "Disabled"} + +
+
+ {customFilename ? ( +
+
+

Custom Filename

+
+ +
+ ) : null} +
+ ); +} + +export { PrintPageBlockParameters }; diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/Taskv2BlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/Taskv2BlockParameters.tsx new file mode 100644 index 00000000..7be05482 --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/Taskv2BlockParameters.tsx @@ -0,0 +1,82 @@ +import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea"; +import { Input } from "@/components/ui/input"; +import { Switch } from "@/components/ui/switch"; + +type Props = { + prompt: string; + url: string | null; + maxSteps: number | null; + totpVerificationUrl: string | null; + totpIdentifier: string | null; + disableCache: boolean; +}; + +function Taskv2BlockParameters({ + prompt, + url, + maxSteps, + totpVerificationUrl, + totpIdentifier, + disableCache, +}: Props) { + return ( +
+
+
+

Prompt

+

+ The instructions for this task +

+
+ +
+ {url ? ( +
+
+

URL

+
+ +
+ ) : null} + {typeof maxSteps === "number" ? ( +
+
+

Max Steps

+
+ +
+ ) : null} + {totpVerificationUrl ? ( +
+
+

TOTP Verification URL

+
+ +
+ ) : null} + {totpIdentifier ? ( +
+
+

TOTP Identifier

+
+ +
+ ) : null} + {disableCache ? ( +
+
+

Cache Disabled

+
+
+ + + Cache is disabled for this block + +
+
+ ) : null} +
+ ); +} + +export { Taskv2BlockParameters }; diff --git a/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/WaitBlockParameters.tsx b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/WaitBlockParameters.tsx new file mode 100644 index 00000000..f9694fb8 --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/workflowRun/blockInfo/WaitBlockParameters.tsx @@ -0,0 +1,26 @@ +import { Input } from "@/components/ui/input"; + +type Props = { + waitSec: number | null | undefined; +}; + +function WaitBlockParameters({ waitSec }: Props) { + return ( +
+
+
+

Wait Duration

+

+ Seconds to wait before proceeding +

+
+ +
+
+ ); +} + +export { WaitBlockParameters };