feat: show all block parameters including advanced settings in WR UI (#SKY-6813) (#4807)

This commit is contained in:
Celal Zamanoğlu
2026-02-19 18:58:30 +03:00
committed by GitHub
parent e051f2ce01
commit c43ec25d22
11 changed files with 1019 additions and 8 deletions

View File

@@ -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() {
</div>
</div>
) : null}
{activeBlock && activeBlock.block_type === WorkflowBlockTypes.Wait ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-sm font-bold">Wait Block Parameters</h1>
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Wait Duration</h1>
<HelpTooltip content="Seconds to wait before proceeding." />
</div>
<Input
value={
typeof activeBlock.wait_sec === "number"
? `${activeBlock.wait_sec}s`
: "N/A"
}
readOnly
/>
</div>
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.HumanInteraction ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-sm font-bold">
Human Interaction Block Parameters
</h1>
{activeBlock.instructions ? (
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Instructions</h1>
<HelpTooltip content="Instructions for the human interaction." />
</div>
<AutoResizingTextarea
value={activeBlock.instructions}
readOnly
/>
</div>
) : null}
{activeBlock.positive_descriptor ? (
<div className="flex flex-col gap-2">
<h1 className="text-sm">Positive Descriptor</h1>
<Input value={activeBlock.positive_descriptor} readOnly />
</div>
) : null}
{activeBlock.negative_descriptor ? (
<div className="flex flex-col gap-2">
<h1 className="text-sm">Negative Descriptor</h1>
<Input value={activeBlock.negative_descriptor} readOnly />
</div>
) : null}
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.Conditional ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-sm font-bold">Conditional Block Parameters</h1>
{activeBlock.executed_branch_expression ? (
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Executed Expression</h1>
<HelpTooltip content="The branch expression that was evaluated." />
</div>
<AutoResizingTextarea
value={activeBlock.executed_branch_expression}
readOnly
/>
</div>
) : null}
{typeof activeBlock.executed_branch_result === "boolean" ? (
<div className="flex flex-col gap-2">
<h1 className="text-sm">Branch Result</h1>
<div className="flex items-center gap-3">
<Switch
checked={activeBlock.executed_branch_result}
disabled
/>
<span className="text-sm text-slate-400">
{activeBlock.executed_branch_result ? "True" : "False"}
</span>
</div>
</div>
) : null}
{activeBlock.executed_branch_next_block ? (
<div className="flex flex-col gap-2">
<h1 className="text-sm">Next Block</h1>
<Input
value={activeBlock.executed_branch_next_block}
readOnly
/>
</div>
) : null}
{activeBlock.executed_branch_id ? (
<div className="flex flex-col gap-2">
<h1 className="text-sm">Executed Branch ID</h1>
<Input value={activeBlock.executed_branch_id} readOnly />
</div>
) : null}
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.TextPrompt ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-sm font-bold">Text Prompt Block Parameters</h1>
{activeBlock.prompt ? (
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Prompt</h1>
<HelpTooltip content="Instructions passed to the selected LLM." />
</div>
<AutoResizingTextarea value={activeBlock.prompt} readOnly />
</div>
) : null}
</div>
</div>
) : null}
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-sm font-bold">Workflow Parameters</h1>
@@ -171,6 +293,27 @@ function DebuggerPostRunParameters() {
/>
</div>
</div>
{workflowRun.browser_session_id ? (
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Browser Session ID</h1>
<HelpTooltip content="The browser session ID used for this run." />
</div>
<Input value={workflowRun.browser_session_id} readOnly />
</div>
) : null}
{workflowRun.max_screenshot_scrolls != null ? (
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Max Screenshot Scrolls</h1>
<HelpTooltip content="Maximum number of screenshot scrolls." />
</div>
<Input
value={workflowRun.max_screenshot_scrolls.toString()}
readOnly
/>
</div>
) : null}
</div>
</div>
{workflowRun.task_v2 ? (
@@ -187,10 +330,6 @@ function DebuggerPostRunParameters() {
readOnly
/>
</div>
<AutoResizingTextarea
value={workflowRun.task_v2?.prompt ?? ""}
readOnly
/>
</div>
</div>
) : null}

View File

@@ -140,6 +140,29 @@ function DebuggerTaskBlockParameters({ block }: Props) {
</div>
</div>
) : null}
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Continue on Failure</h1>
<HelpTooltip content="Whether to continue the workflow if this block fails" />
</div>
<div className="flex items-center gap-3">
<Switch checked={block.continue_on_failure} disabled />
<span className="text-sm text-slate-400">
{block.continue_on_failure ? "Enabled" : "Disabled"}
</span>
</div>
</div>
{block.engine ? (
<div className="flex flex-col gap-2">
<div className="flex w-full items-center justify-start gap-2">
<h1 className="text-sm">Engine</h1>
<HelpTooltip content="The execution engine used for this block" />
</div>
<Input value={block.engine} readOnly />
</div>
) : null}
</>
);
}

View File

@@ -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<ActionsApiResponse> | null;
recipients?: Array<string> | null;
attachments?: Array<string> | null;

View File

@@ -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 (
<>
<div className="flex gap-16">
@@ -151,6 +216,131 @@ function TaskBlockParameters({ block }: Props) {
</div>
</div>
) : null}
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Continue on Failure</h1>
<h2 className="text-base text-slate-400">
Whether to continue the workflow if this block fails
</h2>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={block.continue_on_failure} disabled />
<span className="text-sm text-slate-400">
{block.continue_on_failure ? "Enabled" : "Disabled"}
</span>
</div>
</div>
{hasAdvancedSettings ? (
<>
<h2 className="text-base font-semibold text-slate-300">
Advanced Settings
</h2>
{engine ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Engine</h1>
<h2 className="text-base text-slate-400">
The execution engine used for this block
</h2>
</div>
<Input value={engine} readOnly />
</div>
) : null}
{errorCodeMapping ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Error Code Mapping</h1>
<h2 className="text-base text-slate-400">
Custom error codes and their descriptions
</h2>
</div>
<CodeEditor
className="w-full"
language="json"
value={JSON.stringify(errorCodeMapping, null, 2)}
readOnly
minHeight="96px"
maxHeight="200px"
/>
</div>
) : null}
{typeof maxRetries === "number" ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Max Retries</h1>
</div>
<Input value={maxRetries.toString()} readOnly />
</div>
) : null}
{typeof maxStepsPerRun === "number" ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Max Steps Per Run</h1>
</div>
<Input value={maxStepsPerRun.toString()} readOnly />
</div>
) : null}
{totpVerificationUrl ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">TOTP Verification URL</h1>
</div>
<Input value={totpVerificationUrl} readOnly />
</div>
) : null}
{totpIdentifier ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">TOTP Identifier</h1>
</div>
<Input value={totpIdentifier} readOnly />
</div>
) : null}
{completeOnDownload === true ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Complete on Download</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={true} disabled />
<span className="text-sm text-slate-400">Enabled</span>
</div>
</div>
) : null}
{downloadSuffix ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Download Suffix</h1>
</div>
<Input value={downloadSuffix} readOnly />
</div>
) : null}
{disableCache === true ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Cache Disabled</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={true} disabled />
<span className="text-sm text-slate-400">
Cache is disabled for this block
</span>
</div>
</div>
) : null}
</>
) : null}
</>
);
}

View File

@@ -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() {
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Block Parameters</h1>
<TaskBlockParameters block={activeBlock} />
<TaskBlockParameters
block={activeBlock}
definitionBlock={definitionBlock}
/>
</div>
</div>
) : null}
@@ -191,6 +200,142 @@ function WorkflowPostRunParameters() {
</div>
</div>
) : null}
{activeBlock && activeBlock.block_type === WorkflowBlockTypes.Wait ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Wait Block</h1>
<WaitBlockParameters
waitSec={
activeBlock.wait_sec ??
(isBlockOfType(definitionBlock, WorkflowBlockTypes.Wait)
? definitionBlock.wait_sec ?? null
: null)
}
/>
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.HttpRequest &&
isBlockOfType(definitionBlock, WorkflowBlockTypes.HttpRequest) ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">HTTP Request Block</h1>
<HttpRequestBlockParameters
method={definitionBlock.method}
url={definitionBlock.url}
headers={definitionBlock.headers}
body={definitionBlock.body}
files={definitionBlock.files}
timeout={definitionBlock.timeout}
followRedirects={definitionBlock.follow_redirects}
downloadFilename={definitionBlock.download_filename}
saveResponseAsFile={definitionBlock.save_response_as_file}
/>
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.PrintPage &&
isBlockOfType(definitionBlock, WorkflowBlockTypes.PrintPage) ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Print Page Block</h1>
<PrintPageBlockParameters
format={definitionBlock.format}
landscape={definitionBlock.landscape}
printBackground={definitionBlock.print_background}
includeTimestamp={definitionBlock.include_timestamp}
customFilename={definitionBlock.custom_filename}
/>
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.HumanInteraction ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Human Interaction Block</h1>
<HumanInteractionBlockParameters
instructions={
activeBlock.instructions ??
(isBlockOfType(
definitionBlock,
WorkflowBlockTypes.HumanInteraction,
)
? definitionBlock.instructions
: null)
}
positiveDescriptor={
activeBlock.positive_descriptor ??
(isBlockOfType(
definitionBlock,
WorkflowBlockTypes.HumanInteraction,
)
? definitionBlock.positive_descriptor
: null)
}
negativeDescriptor={
activeBlock.negative_descriptor ??
(isBlockOfType(
definitionBlock,
WorkflowBlockTypes.HumanInteraction,
)
? definitionBlock.negative_descriptor
: null)
}
timeoutSeconds={
isBlockOfType(
definitionBlock,
WorkflowBlockTypes.HumanInteraction,
)
? definitionBlock.timeout_seconds
: null
}
/>
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.Conditional ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Conditional Block</h1>
<ConditionalBlockParameters
branchConditions={
isBlockOfType(definitionBlock, WorkflowBlockTypes.Conditional)
? definitionBlock.branch_conditions
: null
}
executedBranchId={activeBlock.executed_branch_id ?? null}
executedBranchExpression={
activeBlock.executed_branch_expression ?? null
}
executedBranchResult={activeBlock.executed_branch_result ?? null}
executedBranchNextBlock={
activeBlock.executed_branch_next_block ?? null
}
/>
</div>
</div>
) : null}
{activeBlock &&
activeBlock.block_type === WorkflowBlockTypes.Taskv2 &&
isBlockOfType(definitionBlock, WorkflowBlockTypes.Taskv2) ? (
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Task v2 Block</h1>
<Taskv2BlockParameters
prompt={activeBlock.prompt ?? definitionBlock.prompt ?? ""}
url={activeBlock.url ?? definitionBlock.url}
maxSteps={definitionBlock.max_steps}
totpVerificationUrl={definitionBlock.totp_verification_url}
totpIdentifier={definitionBlock.totp_identifier}
disableCache={definitionBlock.disable_cache}
/>
</div>
</div>
) : null}
<div className="rounded bg-slate-elevation2 p-6">
<div className="space-y-4">
<h1 className="text-lg font-bold">Workflow Input Parameters</h1>
@@ -252,6 +397,36 @@ function WorkflowPostRunParameters() {
/>
</div>
</div>
{workflowRun.browser_session_id ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Browser Session ID</h1>
</div>
<Input value={workflowRun.browser_session_id} readOnly />
</div>
) : null}
{workflow?.run_with ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Run With</h1>
<h2 className="text-base text-slate-400">
Execution mode for this workflow
</h2>
</div>
<Input value={workflow.run_with} readOnly />
</div>
) : null}
{workflowRun.max_screenshot_scrolls != null ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Max Screenshot Scrolls</h1>
</div>
<Input
value={workflowRun.max_screenshot_scrolls.toString()}
readOnly
/>
</div>
) : null}
</div>
</div>
{workflowRun.task_v2 ? (

View File

@@ -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<BranchCondition> | null;
executedBranchId: string | null;
executedBranchExpression: string | null;
executedBranchResult: boolean | null;
executedBranchNextBlock: string | null;
};
function ConditionalBlockParameters({
branchConditions,
executedBranchId,
executedBranchExpression,
executedBranchResult,
executedBranchNextBlock,
}: Props) {
return (
<div className="space-y-4">
{executedBranchExpression ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Executed Expression</h1>
<h2 className="text-base text-slate-400">
The branch expression that was evaluated
</h2>
</div>
<AutoResizingTextarea value={executedBranchExpression} readOnly />
</div>
) : null}
{typeof executedBranchResult === "boolean" ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Branch Result</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={executedBranchResult} disabled />
<span className="text-sm text-slate-400">
{executedBranchResult ? "True" : "False"}
</span>
</div>
</div>
) : null}
{executedBranchNextBlock ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Next Block</h1>
<h2 className="text-base text-slate-400">
The block that was executed after the condition
</h2>
</div>
<Input value={executedBranchNextBlock} readOnly />
</div>
) : null}
{executedBranchId ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Executed Branch ID</h1>
</div>
<Input value={executedBranchId} readOnly />
</div>
) : null}
{branchConditions && branchConditions.length > 0 ? (
<div className="space-y-3">
<h2 className="text-base font-semibold text-slate-300">
Branch Conditions
</h2>
{branchConditions.map((condition) => (
<div
key={condition.id}
className="space-y-2 rounded border border-slate-700/40 bg-slate-elevation3 p-3"
>
{condition.description ? (
<p className="text-sm text-slate-400">
{condition.description}
</p>
) : null}
{condition.criteria?.expression ? (
<div className="flex items-center gap-2">
<span className="text-sm font-medium">Expression:</span>
<code className="text-sm text-slate-300">
{condition.criteria.expression}
</code>
</div>
) : null}
{condition.next_block_label ? (
<div className="flex items-center gap-2">
<span className="text-sm font-medium">Next Block:</span>
<span className="text-sm text-slate-300">
{condition.next_block_label}
</span>
</div>
) : null}
{condition.is_default ? (
<span className="inline-block rounded bg-slate-700 px-2 py-0.5 text-xs">
Default
</span>
) : null}
</div>
))}
</div>
) : null}
</div>
);
}
export { ConditionalBlockParameters };

View File

@@ -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<string, string> | null;
body: Record<string, unknown> | null;
files: Record<string, string> | null;
timeout: number;
followRedirects: boolean;
downloadFilename: string | null;
saveResponseAsFile: boolean;
};
function HttpRequestBlockParameters({
method,
url,
headers,
body,
files,
timeout,
followRedirects,
downloadFilename,
saveResponseAsFile,
}: Props) {
return (
<div className="space-y-4">
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Method</h1>
</div>
<Input value={method} readOnly />
</div>
{url ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">URL</h1>
</div>
<AutoResizingTextarea value={url} readOnly />
</div>
) : null}
{headers && Object.keys(headers).length > 0 ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Headers</h1>
</div>
<CodeEditor
className="w-full"
language="json"
value={JSON.stringify(headers, null, 2)}
readOnly
minHeight="96px"
maxHeight="200px"
/>
</div>
) : null}
{body && Object.keys(body).length > 0 ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Body</h1>
</div>
<CodeEditor
className="w-full"
language="json"
value={JSON.stringify(body, null, 2)}
readOnly
minHeight="96px"
maxHeight="200px"
/>
</div>
) : null}
{files && Object.keys(files).length > 0 ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Files</h1>
<h2 className="text-base text-slate-400">
File fields and their paths/URLs
</h2>
</div>
<CodeEditor
className="w-full"
language="json"
value={JSON.stringify(files, null, 2)}
readOnly
minHeight="96px"
maxHeight="200px"
/>
</div>
) : null}
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Timeout</h1>
<h2 className="text-base text-slate-400">In seconds</h2>
</div>
<Input value={timeout.toString()} readOnly />
</div>
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Follow Redirects</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={followRedirects} disabled />
<span className="text-sm text-slate-400">
{followRedirects ? "Enabled" : "Disabled"}
</span>
</div>
</div>
{downloadFilename ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Download Filename</h1>
</div>
<Input value={downloadFilename} readOnly />
</div>
) : null}
{saveResponseAsFile ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Save Response as File</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={true} disabled />
<span className="text-sm text-slate-400">Enabled</span>
</div>
</div>
) : null}
</div>
);
}
export { HttpRequestBlockParameters };

View File

@@ -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 (
<div className="space-y-4">
{instructions ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Instructions</h1>
<h2 className="text-base text-slate-400">
Instructions for the human interaction
</h2>
</div>
<AutoResizingTextarea value={instructions} readOnly />
</div>
) : null}
{positiveDescriptor ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Positive Descriptor</h1>
</div>
<Input value={positiveDescriptor} readOnly />
</div>
) : null}
{negativeDescriptor ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Negative Descriptor</h1>
</div>
<Input value={negativeDescriptor} readOnly />
</div>
) : null}
{typeof timeoutSeconds === "number" ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Timeout</h1>
<h2 className="text-base text-slate-400">In seconds</h2>
</div>
<Input value={timeoutSeconds.toString()} readOnly />
</div>
) : null}
</div>
);
}
export { HumanInteractionBlockParameters };

View File

@@ -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 (
<div className="space-y-4">
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Format</h1>
</div>
<Input value={format} readOnly />
</div>
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Landscape</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={landscape} disabled />
<span className="text-sm text-slate-400">
{landscape ? "Enabled" : "Disabled"}
</span>
</div>
</div>
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Print Background</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={printBackground} disabled />
<span className="text-sm text-slate-400">
{printBackground ? "Enabled" : "Disabled"}
</span>
</div>
</div>
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Include Timestamp</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={includeTimestamp} disabled />
<span className="text-sm text-slate-400">
{includeTimestamp ? "Enabled" : "Disabled"}
</span>
</div>
</div>
{customFilename ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Custom Filename</h1>
</div>
<Input value={customFilename} readOnly />
</div>
) : null}
</div>
);
}
export { PrintPageBlockParameters };

View File

@@ -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 (
<div className="space-y-4">
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Prompt</h1>
<h2 className="text-base text-slate-400">
The instructions for this task
</h2>
</div>
<AutoResizingTextarea value={prompt} readOnly />
</div>
{url ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">URL</h1>
</div>
<Input value={url} readOnly />
</div>
) : null}
{typeof maxSteps === "number" ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Max Steps</h1>
</div>
<Input value={maxSteps.toString()} readOnly />
</div>
) : null}
{totpVerificationUrl ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">TOTP Verification URL</h1>
</div>
<Input value={totpVerificationUrl} readOnly />
</div>
) : null}
{totpIdentifier ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">TOTP Identifier</h1>
</div>
<Input value={totpIdentifier} readOnly />
</div>
) : null}
{disableCache ? (
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Cache Disabled</h1>
</div>
<div className="flex w-full items-center gap-3">
<Switch checked={true} disabled />
<span className="text-sm text-slate-400">
Cache is disabled for this block
</span>
</div>
</div>
) : null}
</div>
);
}
export { Taskv2BlockParameters };

View File

@@ -0,0 +1,26 @@
import { Input } from "@/components/ui/input";
type Props = {
waitSec: number | null | undefined;
};
function WaitBlockParameters({ waitSec }: Props) {
return (
<div className="space-y-4">
<div className="flex gap-16">
<div className="w-80">
<h1 className="text-lg">Wait Duration</h1>
<h2 className="text-base text-slate-400">
Seconds to wait before proceeding
</h2>
</div>
<Input
value={typeof waitSec === "number" ? `${waitSec}s` : "N/A"}
readOnly
/>
</div>
</div>
);
}
export { WaitBlockParameters };