diff --git a/skyvern-frontend/src/components/WorkflowBlockInputSet.tsx b/skyvern-frontend/src/components/WorkflowBlockInputSet.tsx index 875a3e6c..3e417cc8 100644 --- a/skyvern-frontend/src/components/WorkflowBlockInputSet.tsx +++ b/skyvern-frontend/src/components/WorkflowBlockInputSet.tsx @@ -11,6 +11,14 @@ type Props = { values: Set; }; +function areSetsEqual(a: Set, b: Set): boolean { + if (a.size !== b.size) return false; + for (const item of a) { + if (!b.has(item)) return false; + } + return true; +} + function WorkflowBlockInputSet(props: Props) { const { nodeId, onChange, values } = props; const [parameterKeys, setParameterKeys] = useState>(values); @@ -20,6 +28,13 @@ function WorkflowBlockInputSet(props: Props) { workflowParameters.map((parameter) => parameter.key), ); + // Sync local state when values prop changes (e.g., parameter renamed externally) + useEffect(() => { + if (!areSetsEqual(parameterKeys, values)) { + setParameterKeys(values); + } + }, [values, parameterKeys]); + useEffect(() => { onChange(new Set(parameterKeys)); // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx index 8ed57202..a244d36b 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParametersPanel.tsx @@ -196,20 +196,29 @@ function WorkflowParametersPanel({ onMouseDownCapture }: Props) { setHasChanges(true); setNodes((nodes) => { return nodes.map((node) => { + // All node types that have parameterKeys if ( node.type === "task" || - node.type === "textPrompt" + node.type === "textPrompt" || + node.type === "login" || + node.type === "navigation" || + node.type === "extraction" || + node.type === "fileDownload" || + node.type === "action" || + node.type === "http_request" || + node.type === "validation" || + node.type === "codeBlock" ) { + const parameterKeys = node.data + .parameterKeys as Array | null; return { ...node, data: { ...node.data, - parameterKeys: ( - node.data - .parameterKeys as Array - ).filter( - (key) => key !== parameter.key, - ), + parameterKeys: + parameterKeys?.filter( + (key) => key !== parameter.key, + ) ?? null, }, }; } @@ -293,24 +302,34 @@ function WorkflowParametersPanel({ onMouseDownCapture }: Props) { ); setNodes((nodes) => { return nodes.map((node) => { + // All node types that have parameterKeys if ( node.type === "task" || - node.type === "textPrompt" + node.type === "textPrompt" || + node.type === "login" || + node.type === "navigation" || + node.type === "extraction" || + node.type === "fileDownload" || + node.type === "action" || + node.type === "http_request" || + node.type === "validation" || + node.type === "codeBlock" ) { + const parameterKeys = node.data + .parameterKeys as Array | null; return { ...node, data: { ...node.data, - parameterKeys: ( - node.data.parameterKeys as Array - ).map((key) => { - if ( - key === operationPanelState.parameter?.key - ) { - return editedParameter.key; - } - return key; - }), + parameterKeys: + parameterKeys?.map((key) => { + if ( + key === operationPanelState.parameter?.key + ) { + return editedParameter.key; + } + return key; + }) ?? null, }, }; }