diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx index d7ede3fc..36874b1d 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx @@ -42,6 +42,7 @@ type Props = { const workflowParameterTypeOptions = [ { label: "string", value: WorkflowParameterValueType.String }, + { label: "credential", value: "credential" }, { label: "float", value: WorkflowParameterValueType.Float }, { label: "integer", value: WorkflowParameterValueType.Integer }, { label: "boolean", value: WorkflowParameterValueType.Boolean }, @@ -52,6 +53,11 @@ const workflowParameterTypeOptions = [ type CredentialDataType = "password" | "secret" | "creditCard"; type CredentialSource = "bitwarden" | "skyvern" | "onepassword" | "azurevault"; +// When selecting from the Value Type dropdown, "credential" is a special value that triggers +// credential-specific UI. This is separate from WorkflowParameterValueType which only includes +// data types like string, integer, etc. +type ParameterTypeSelection = WorkflowParameterValueType | "credential"; + // Determine available sources based on credential data type function getAvailableSourcesForDataType( dataType: CredentialDataType, @@ -79,12 +85,20 @@ function getAvailableSourcesForDataType( } } -function header(type: WorkflowEditorParameterType, isEdit: boolean) { +function header( + type: WorkflowEditorParameterType, + isEdit: boolean, + isCredentialSelected: boolean, +) { const prefix = isEdit ? "Edit" : "Add"; + if (type === "workflow" && !isEdit) { + // Unified add mode + return `${prefix} Parameter`; + } if (type === "workflow") { return `${prefix} Input Parameter`; } - if (type === "credential") { + if (type === "credential" || (!isEdit && isCredentialSelected)) { return `${prefix} Credential Parameter`; } return `${prefix} Context Parameter`; @@ -103,8 +117,9 @@ function detectInitialCredentialDataType( // Helper to detect initial credential source from existing parameter function detectInitialCredentialSource( initialValues: ParametersState[number] | undefined, + isCloud: boolean, ): CredentialSource { - if (!initialValues) return "bitwarden"; + if (!initialValues) return isCloud ? "skyvern" : "bitwarden"; if (initialValues.parameterType === "secret") return "bitwarden"; if (initialValues.parameterType === "creditCardData") return "bitwarden"; @@ -116,7 +131,7 @@ function detectInitialCredentialSource( if (parameterIsAzureVaultCredential(initialValues)) return "azurevault"; } - return "bitwarden"; + return isCloud ? "skyvern" : "bitwarden"; } function WorkflowParameterEditPanel({ @@ -156,7 +171,7 @@ function WorkflowParameterEditPanel({ detectInitialCredentialDataType(initialValues), ); const [credentialSource, setCredentialSource] = useState( - detectInitialCredentialSource(initialValues), + detectInitialCredentialSource(initialValues, isCloud), ); const [urlParameterKey, setUrlParameterKey] = useState( @@ -172,12 +187,13 @@ function WorkflowParameterEditPanel({ ? initialValues?.collectionId ?? "" : "", ); - const [parameterType, setParameterType] = - useState( - initialValues?.parameterType === "workflow" + const [parameterType, setParameterType] = useState( + type === "credential" + ? "credential" + : initialValues?.parameterType === "workflow" ? initialValues.dataType : "string", - ); + ); const [defaultValueState, setDefaultValueState] = useState<{ hasDefaultValue: boolean; @@ -261,32 +277,38 @@ function WorkflowParameterEditPanel({ isCloud, ); + // Check if we're in unified add mode and credential is selected + const isCredentialSelected = parameterType === "credential"; + const showCredentialFields = + type === "credential" || + (type === "workflow" && !isEditMode && isCredentialSelected); + // Determine what fields to show based on credential data type and source const showBitwardenPasswordFields = - type === "credential" && + showCredentialFields && credentialDataType === "password" && credentialSource === "bitwarden"; const showBitwardenSecretFields = - type === "credential" && + showCredentialFields && credentialDataType === "secret" && credentialSource === "bitwarden"; const showBitwardenCreditCardFields = - type === "credential" && + showCredentialFields && credentialDataType === "creditCard" && credentialSource === "bitwarden"; const showOnePasswordFields = - type === "credential" && credentialSource === "onepassword"; + showCredentialFields && credentialSource === "onepassword"; const showAzureVaultFields = - type === "credential" && credentialSource === "azurevault"; + showCredentialFields && credentialSource === "azurevault"; const showSkyvernCredentialSelector = - type === "credential" && credentialSource === "skyvern" && isCloud; + showCredentialFields && credentialSource === "skyvern" && isCloud; return (
- {header(type, isEditMode)} + {header(type, isEditMode, isCredentialSelected)}
@@ -312,15 +334,42 @@ function WorkflowParameterEditPanel({
-
-
- { - if (!checked) { + {/* Default value section - only for non-credential types */} + {!isCredentialSelected && ( +
+
+ { + if (!checked) { + setDefaultValueState({ + hasDefaultValue: false, + defaultValue: null, + }); + return; + } setDefaultValueState({ - hasDefaultValue: false, - defaultValue: null, + hasDefaultValue: true, + defaultValue: getDefaultValueForParameterType( + parameterType as WorkflowParameterValueType, + ), }); - return; - } - setDefaultValueState({ - hasDefaultValue: true, - defaultValue: - getDefaultValueForParameterType(parameterType), - }); - }} - /> - -
- {defaultValueState.hasDefaultValue && ( - { - if ( - parameterType === "file_url" && - typeof value === "object" && - value && - "s3uri" in value - ) { + }} + /> + +
+ {defaultValueState.hasDefaultValue && ( + { + if ( + parameterType === "file_url" && + typeof value === "object" && + value && + "s3uri" in value + ) { + setDefaultValueState((state) => { + return { + ...state, + defaultValue: value.s3uri, + }; + }); + return; + } setDefaultValueState((state) => { return { ...state, - defaultValue: value.s3uri, + defaultValue: value, }; }); - return; - } - setDefaultValueState((state) => { - return { - ...state, - defaultValue: value, - }; - }); - }} - type={parameterType} - value={defaultValueState.defaultValue} - /> - )} -
+ }} + type={parameterType as WorkflowParameterValueType} + value={defaultValueState.defaultValue} + /> + )} +
+ )} )} {/* Credential Parameter - Unified Flow */} - {type === "credential" && ( + {showCredentialFields && ( <> {/* Step 1: Credential Type */}
@@ -717,8 +778,8 @@ function WorkflowParameterEditPanel({ return; } - // Handle workflow parameters - if (type === "workflow") { + // Handle workflow parameters (non-credential) + if (type === "workflow" && !isCredentialSelected) { if ( parameterType === "json" && typeof defaultValueState.defaultValue === "string" @@ -763,7 +824,7 @@ function WorkflowParameterEditPanel({ onSave({ key, parameterType: "workflow", - dataType: parameterType, + dataType: parameterType as WorkflowParameterValueType, description, defaultValue: defaultValueState.hasDefaultValue ? defaultValue @@ -792,7 +853,7 @@ function WorkflowParameterEditPanel({ } // Handle credential parameters based on type + source combination - if (type === "credential") { + if (type === "credential" || isCredentialSelected) { // Skyvern managed credentials if (credentialSource === "skyvern") { if (!credentialId) { diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx index cc44fd9b..e8c270f9 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx @@ -4,14 +4,6 @@ import { WorkflowParameterEditPanel } from "./WorkflowParameterEditPanel"; import { MixerVerticalIcon, PlusIcon } from "@radix-ui/react-icons"; import { Button } from "@/components/ui/button"; import { GarbageIcon } from "@/components/icons/GarbageIcon"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; import { useNodes, useReactFlow } from "@xyflow/react"; import { useWorkflowHasChangesStore } from "@/store/WorkflowHasChangesStore"; import { useWorkflowParametersStore } from "@/store/WorkflowParametersStore"; @@ -106,40 +98,19 @@ function WorkflowParametersPanel({ onMouseDownCapture }: Props) { prompted to fill them in before running your workflow. - - - - - - Add Parameter - - { - setOperationPanelState({ - active: true, - operation: "add", - type: WorkflowEditorParameterTypes.Workflow, - }); - }} - > - Input Parameter - - { - setOperationPanelState({ - active: true, - operation: "add", - type: WorkflowEditorParameterTypes.Credential, - }); - }} - > - Credential Parameter - - - +