From f98793704638e42220bdc72c002a1e5ead968769 Mon Sep 17 00:00:00 2001 From: Abhimanyu Yadav <122007096+Abhi1992002@users.noreply.github.com> Date: Tue, 2 Dec 2025 18:17:12 +0530 Subject: [PATCH] fix(frontend): prune empty values from node inputs and fix object editor connection detection (#11507) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR addresses two issues: 1. **Empty values being sent to backend**: Node inputs were including empty strings, null, and undefined values when converting to backend format, causing unnecessary data to be sent. 2. **Incorrect connection detection in ObjectEditor**: The component was checking if the parent field was connected instead of checking individual key-value pairs, causing incorrect UI state for dynamic properties. ### Changes 🏗️ - **nodeStore.ts**: Added `pruneEmptyValues` utility to remove empty/null/undefined values from `hardcodedValues` before converting nodes to backend format. This ensures only meaningful input values are sent to the backend API. - **ObjectEditorWidget.tsx**: - Removed unused `fieldKey` prop from component interface - Fixed connection detection logic to check individual key-value handle IDs instead of the parent field key, ensuring correct connection state for each dynamic property in object editors ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Create a node with object input fields and verify empty values are not sent to backend - [x] Add multiple key-value pairs to an object editor widget - [x] Connect individual key-value pairs via handles and verify connection state is correctly displayed - [x] Disconnect a key-value pair and verify the input field becomes editable - [x] Save and reload an agent with object inputs to verify empty values are pruned correctly - [x] Verify that non-empty values are still correctly preserved and sent to backend --- .../frontend/src/app/(platform)/build/stores/nodeStore.ts | 3 ++- .../widgets/ObjectEditorWidget/ObjectEditorWidget.tsx | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts b/autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts index a8101434f4..dc9963194a 100644 --- a/autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts +++ b/autogpt_platform/frontend/src/app/(platform)/build/stores/nodeStore.ts @@ -12,6 +12,7 @@ import { NodeExecutionResult } from "@/app/api/__generated__/models/nodeExecutio import { useHistoryStore } from "./historyStore"; import { useEdgeStore } from "./edgeStore"; import { BlockUIType } from "../components/types"; +import { pruneEmptyValues } from "@/lib/utils"; // Minimum movement (in pixels) required before logging position change to history // Prevents spamming history with small movements when clicking on inputs inside blocks @@ -201,7 +202,7 @@ export const useNodeStore = create((set, get) => ({ return { id: node.id, block_id: node.data.block_id, - input_default: node.data.hardcodedValues, + input_default: pruneEmptyValues(node.data.hardcodedValues), metadata: { position: node.position, ...(node.data.metadata?.customized_name !== undefined && { diff --git a/autogpt_platform/frontend/src/components/renderers/input-renderer/widgets/ObjectEditorWidget/ObjectEditorWidget.tsx b/autogpt_platform/frontend/src/components/renderers/input-renderer/widgets/ObjectEditorWidget/ObjectEditorWidget.tsx index 97f8afb31c..80d504421d 100644 --- a/autogpt_platform/frontend/src/components/renderers/input-renderer/widgets/ObjectEditorWidget/ObjectEditorWidget.tsx +++ b/autogpt_platform/frontend/src/components/renderers/input-renderer/widgets/ObjectEditorWidget/ObjectEditorWidget.tsx @@ -34,7 +34,6 @@ export const ObjectEditor = React.forwardRef( disabled = false, className, nodeId, - fieldKey, }, ref, ) => { @@ -101,12 +100,12 @@ export const ObjectEditor = React.forwardRef( id={parentFieldId} > {Object.entries(value).map(([key, propertyValue], idx) => { - const isDynamicPropertyConnected = isInputConnected(nodeId, fieldKey); const handleId = generateHandleId( parentFieldId, [key], HandleIdType.KEY_VALUE, ); + const isDynamicPropertyConnected = isInputConnected(nodeId, handleId); return (