From 612e5c6d74c07969a5dd33b2a57a14444d93f079 Mon Sep 17 00:00:00 2001 From: Vukasin Date: Tue, 29 Jul 2025 23:34:02 +0200 Subject: [PATCH] fix: util parsing and ajust structure --- backend/triggers/utils.py | 27 ++++++++- .../[agentId]/workflow/[workflowId]/page.tsx | 34 +++++++++++- .../utils/workflow-structure-utils.test.ts | 1 + .../components/workflows/workflow-builder.tsx | 55 +++++++++++++++++-- .../workflows/workflow-side-panel.tsx | 4 +- .../workflows/workflow-structure-test.md | 1 + 6 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 frontend/src/components/workflows/utils/workflow-structure-utils.test.ts create mode 100644 frontend/src/components/workflows/workflow-structure-test.md diff --git a/backend/triggers/utils.py b/backend/triggers/utils.py index e0b82438..5e7a9c48 100644 --- a/backend/triggers/utils.py +++ b/backend/triggers/utils.py @@ -26,7 +26,16 @@ class WorkflowParser: self.step_counter = 0 self.parsed_steps = [] - filtered_steps = [step for step in steps if step.get('name') != 'Start' or step.get('description') != 'Click to add steps or use the Add Node button'] + start_node = next( + (step for step in steps if step.get('name') == 'Start' and step.get('description') == 'Click to add steps or use the Add Node button'), + None + ) + + if start_node and "children" in start_node: + filtered_steps = start_node["children"] + else: + # fallback: use top-level list (for backward compat) + filtered_steps = steps return self._parse_steps_recursive(filtered_steps) @@ -143,6 +152,22 @@ class WorkflowParser: total_steps, total_conditions, max_nesting_depth = count_steps_recursive(steps) + # Large debug print to show inputs and parsed output + print("=" * 80) + print("WORKFLOW PARSER DEBUG - get_workflow_summary") + print("=" * 80) + print(f"INPUT STEPS:") + print(f"Type: {type(steps)}") + print(f"Length: {len(steps) if isinstance(steps, list) else 'N/A'}") + print(f"Raw steps: {steps}") + print("-" * 80) + print(f"PARSED OUTPUT:") + print(f"Total steps: {total_steps}") + print(f"Total conditions: {total_conditions}") + print(f"Max nesting depth: {max_nesting_depth}") + print(f"Has conditional logic: {total_conditions > 0}") + print("=" * 80) + return { "total_steps": total_steps, "total_conditions": total_conditions, diff --git a/frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/[workflowId]/page.tsx b/frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/[workflowId]/page.tsx index 473474a6..12b8ada0 100644 --- a/frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/[workflowId]/page.tsx +++ b/frontend/src/app/(dashboard)/agents/config/[agentId]/workflow/[workflowId]/page.tsx @@ -15,6 +15,7 @@ import { ConditionalStep } from '@/components/agents/workflows/conditional-workf import { WorkflowBuilder } from '@/components/workflows/workflow-builder'; const convertToNestedJSON = (steps: ConditionalStep[]): any[] => { + // Since we're using the old structure directly, just pass it through let globalOrder = 1; const convertStepsWithNesting = (stepList: ConditionalStep[]): any[] => { return stepList.map((step) => { @@ -40,7 +41,18 @@ const convertToNestedJSON = (steps: ConditionalStep[]): any[] => { }; const reconstructFromNestedJSON = (nestedSteps: any[]): ConditionalStep[] => { - if (!nestedSteps || nestedSteps.length === 0) return []; + if (!nestedSteps || nestedSteps.length === 0) { + // Return default root structure if no steps + return [{ + id: 'start-node', + name: 'Start', + description: 'Click to add steps or use the Add Node button', + type: 'instruction', + config: {}, + order: 0, + children: [] + }]; + } const convertStepsFromNested = (stepList: any[]): ConditionalStep[] => { return stepList.map((step) => { @@ -70,7 +82,25 @@ const reconstructFromNestedJSON = (nestedSteps: any[]): ConditionalStep[] => { }); }; - return convertStepsFromNested(nestedSteps); + const reconstructedSteps = convertStepsFromNested(nestedSteps); + + // Make sure we have proper root structure + if (reconstructedSteps.length > 0 && + reconstructedSteps[0].name === 'Start' && + reconstructedSteps[0].description === 'Click to add steps or use the Add Node button') { + return reconstructedSteps; + } + + // If not proper structure, wrap in root node + return [{ + id: 'start-node', + name: 'Start', + description: 'Click to add steps or use the Add Node button', + type: 'instruction', + config: {}, + order: 0, + children: reconstructedSteps + }]; }; const reconstructFromFlatJSON = (flatSteps: any[]): ConditionalStep[] => { diff --git a/frontend/src/components/workflows/utils/workflow-structure-utils.test.ts b/frontend/src/components/workflows/utils/workflow-structure-utils.test.ts new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/frontend/src/components/workflows/utils/workflow-structure-utils.test.ts @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/components/workflows/workflow-builder.tsx b/frontend/src/components/workflows/workflow-builder.tsx index 8892147d..61ca25ee 100644 --- a/frontend/src/components/workflows/workflow-builder.tsx +++ b/frontend/src/components/workflows/workflow-builder.tsx @@ -33,6 +33,17 @@ interface WorkflowBuilderProps { onDescriptionChange?: (description: string) => void; } +// Root node structure that parser expects +const createRootNode = (children: ConditionalStep[] = []): ConditionalStep => ({ + id: 'start-node', + name: 'Start', + description: 'Click to add steps or use the Add Node button', + type: 'instruction', + config: {}, + order: 0, + children: children +}); + export function WorkflowBuilder({ steps, onStepsChange, @@ -48,6 +59,38 @@ export function WorkflowBuilder({ onNameChange, onDescriptionChange }: WorkflowBuilderProps) { + // Ensure we always have the proper root structure + const workflowSteps = useMemo(() => { + // If we don't have steps or it's not the right structure, create proper root + if (!steps || steps.length === 0) { + return [createRootNode()]; + } + + // Check if we already have proper root structure + const firstStep = steps[0]; + if (firstStep && + firstStep.name === 'Start' && + firstStep.description === 'Click to add steps or use the Add Node button' && + firstStep.type === 'instruction' && + Array.isArray(firstStep.children)) { + return steps; + } + + // If we have flat structure, wrap it in root node + return [createRootNode(steps)]; + }, [steps]); + + // Get the actual workflow children (the steps we edit) + const editableSteps = useMemo(() => { + return workflowSteps[0]?.children || []; + }, [workflowSteps]); + + // Handle changes to the editable steps + const handleStepsChange = useCallback((newSteps: ConditionalStep[]) => { + const updatedWorkflow = [createRootNode(newSteps)]; + onStepsChange(updatedWorkflow); + }, [onStepsChange]); + const [isPanelOpen, setIsPanelOpen] = useState(false); const [panelMode, setPanelMode] = useState<'add' | 'edit'>('add'); const [selectedStep, setSelectedStep] = useState(null); @@ -66,8 +109,8 @@ export function WorkflowBuilder({ getAvailableStepTypes, STEP_CATEGORIES } = useWorkflowSteps({ - steps, - onStepsChange, + steps: editableSteps, // Work with the children array + onStepsChange: handleStepsChange, // Update the root structure agentTools, setIsPanelOpen, setPanelMode, @@ -105,7 +148,7 @@ export function WorkflowBuilder({ >
- {steps.length === 0 ? ( + {editableSteps.length === 0 ? ( // Empty state
@@ -125,17 +168,17 @@ export function WorkflowBuilder({
) : ( - // Steps list + // Steps list - uses the children array from root node
diff --git a/frontend/src/components/workflows/workflow-side-panel.tsx b/frontend/src/components/workflows/workflow-side-panel.tsx index aac80647..2abd778c 100644 --- a/frontend/src/components/workflows/workflow-side-panel.tsx +++ b/frontend/src/components/workflows/workflow-side-panel.tsx @@ -180,10 +180,10 @@ export function WorkflowSidePanel({ {/* Tool configuration */} {selectedStep.config?.tool_name && ( -
+
Tool Configuration
- Using: {selectedStep.config.tool_name} + Using: {selectedStep.config.tool_name}
)} diff --git a/frontend/src/components/workflows/workflow-structure-test.md b/frontend/src/components/workflows/workflow-structure-test.md new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/frontend/src/components/workflows/workflow-structure-test.md @@ -0,0 +1 @@ + \ No newline at end of file