Skip to content

Commit

Permalink
Merge pull request #154 from PySpur-Dev/fix/routerNodeUI
Browse files Browse the repository at this point in the history
fix/ Router Node, Coalesce Node and Output Schemas
  • Loading branch information
srijanpatel authored Feb 12, 2025
2 parents 828c6b0 + 7e2a27c commit 47f6c6b
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 278 deletions.
5 changes: 5 additions & 0 deletions backend/app/execution/workflow_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ async def _execute_node(self, node_id: str) -> Optional[BaseNodeOutput]:
):
self._outputs[node_id] = None
return None
elif node.node_type == "CoalesceNode" and all(
[v is None for v in node_input.values()]
):
self._outputs[node_id] = None
return None

# Remove None values from input
node_input = {k: v for k, v in node_input.items() if v is not None}
Expand Down
22 changes: 13 additions & 9 deletions frontend/src/components/nodes/logic/CoalesceNode.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React, { useState, useRef, useEffect, useMemo } from 'react'
import NodeErrorDisplay from '@/components/nodes/NodeErrorDisplay'
import { FlowWorkflowNode } from '@/types/api_types/nodeTypeSchemas'
import { Button, Card, Divider, Select, SelectItem } from '@heroui/react'
import { Icon } from '@iconify/react'
import { Handle, Position, useConnection } from '@xyflow/react'
import BaseNode from '../BaseNode'
import { Input, Card, Divider, Button, Select, SelectItem } from '@heroui/react'
import isEqual from 'lodash/isEqual'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { updateNodeConfigOnly } from '../../../store/flowSlice'
import styles from '../DynamicNode.module.css'
import { Icon } from '@iconify/react'
import { RootState } from '../../../store/store'
import BaseNode from '../BaseNode'
import styles from '../DynamicNode.module.css'
import NodeOutputDisplay from '../NodeOutputDisplay'
import isEqual from 'lodash/isEqual'
import { FlowWorkflowNodeConfig } from '@/types/api_types/nodeTypeSchemas'
import { FlowWorkflowNode } from '@/types/api_types/nodeTypeSchemas'

interface CoalesceNodeProps {
id: string
Expand Down Expand Up @@ -38,6 +38,7 @@ export const CoalesceNode: React.FC<CoalesceNodeProps> = ({ id, data }) => {

// Node's output for display
const nodeOutput = useSelector((state: RootState) => state.flow.nodes.find((node) => node.id === id)?.data?.run)
const nodeError = useSelector((state: RootState) => state.flow.nodes.find((node) => node.id === id)?.data?.error)

// Node's config
const nodeConfig = useSelector((state: RootState) => state.flow.nodeConfigs[id])
Expand Down Expand Up @@ -357,6 +358,9 @@ export const CoalesceNode: React.FC<CoalesceNodeProps> = ({ id, data }) => {
key={variable.value}
value={variable.value}
textValue={variable.label}
classNames={{
title: 'w-full whitespace-normal break-words',
}}
>
<div className="whitespace-normal">
<span>{variable.label}</span>
Expand All @@ -382,7 +386,7 @@ export const CoalesceNode: React.FC<CoalesceNodeProps> = ({ id, data }) => {
</>
)}
</div>

{nodeError && <NodeErrorDisplay error={nodeError} />}
{/* Display node's output if it exists */}
<NodeOutputDisplay output={nodeOutput} />
</BaseNode>
Expand Down
33 changes: 23 additions & 10 deletions frontend/src/components/nodes/logic/RouterNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,21 @@ export const RouterNode: React.FC<RouterNodeProps> = ({ id, data, readOnly = fal

const predNodeConfig = nodeConfigs[node.id]
const nodeTitle = predNodeConfig?.title || node.id
const outputSchema = predNodeConfig?.output_schema || {}

return Object.entries(outputSchema).map(([key, type]) => ({
value: `${nodeTitle}.${key}`,
label: `${nodeTitle}.${key} (${type})`,
}))
const outputSchema = predNodeConfig?.output_json_schema || '{}'

try {
const schema = JSON.parse(outputSchema)
// Extract properties from JSON schema
const properties = schema.properties || {}

return Object.entries(properties).map(([key, value]: [string, any]) => ({
value: `${nodeTitle}.${key}`,
label: `${nodeTitle}.${key} (${value.type || 'any'})`,
}))
} catch (error) {
console.error('Failed to parse output schema:', error)
return []
}
})
}, [predecessorNodes, nodeConfigs])

Expand Down Expand Up @@ -511,8 +520,7 @@ export const RouterNode: React.FC<RouterNodeProps> = ({ id, data, readOnly = fal
variant="flat"
classNames={{
trigger: 'dark:bg-default-50/10',
base: 'dark:bg-default-50/10',
popoverContent: 'dark:bg-default-50/10',
popoverContent: 'dark:bg-default-50',
}}
renderValue={(items) => {
return items.map((item) => (
Expand All @@ -532,6 +540,9 @@ export const RouterNode: React.FC<RouterNodeProps> = ({ id, data, readOnly = fal
value={variable.value}
textValue={variable.label}
className="text-default-700 dark:text-default-300"
classNames={{
title: 'w-full whitespace-normal break-words',
}}
>
<div className="whitespace-normal">
<span>{variable.label}</span>
Expand Down Expand Up @@ -570,8 +581,7 @@ export const RouterNode: React.FC<RouterNodeProps> = ({ id, data, readOnly = fal
variant="flat"
classNames={{
trigger: 'dark:bg-default-50/10',
base: 'dark:bg-default-50/10',
popoverContent: 'dark:bg-default-50/10',
popoverContent: 'dark:bg-default-50',
}}
renderValue={(items) => {
return items.map((item) => (
Expand All @@ -590,6 +600,9 @@ export const RouterNode: React.FC<RouterNodeProps> = ({ id, data, readOnly = fal
value={op.value}
textValue={op.label}
className="text-default-700 dark:text-default-300"
classNames={{
title: 'w-full whitespace-normal break-words',
}}
>
{op.label}
</SelectItem>
Expand Down
Loading

0 comments on commit 47f6c6b

Please sign in to comment.