diff --git a/packages/agentflow/src/atoms/ConditionBuilder.test.tsx b/packages/agentflow/src/atoms/ConditionBuilder.test.tsx
index f0c7acddb..90f2f2bda 100644
--- a/packages/agentflow/src/atoms/ConditionBuilder.test.tsx
+++ b/packages/agentflow/src/atoms/ConditionBuilder.test.tsx
@@ -3,6 +3,7 @@ import { fireEvent, render, screen } from '@testing-library/react'
import type { InputParam, NodeData } from '@/core/types'
import { ConditionBuilder } from './ConditionBuilder'
+import type { VariableItem } from './VariablePicker'
// --- Mocks ---
const mockOnDataChange = jest.fn()
@@ -10,13 +11,15 @@ const mockOnDataChange = jest.fn()
jest.mock('./NodeInputHandler', () => ({
NodeInputHandler: ({
inputParam,
- onDataChange
+ onDataChange,
+ variableItems
}: {
inputParam: InputParam
data: NodeData
onDataChange: (args: { inputParam: InputParam; newValue: unknown }) => void
+ variableItems?: unknown[]
}) => (
-
+
onDataChange({ inputParam, newValue: e.target.value })} />
@@ -146,6 +149,25 @@ describe('ConditionBuilder', () => {
})
})
+ it('should clear value1 and value2 when operation changes', () => {
+ const data: NodeData = {
+ ...mockNodeData,
+ inputs: {
+ conditions: [{ type: 'string', value1: 'hello', operation: 'equal', value2: 'world' }]
+ }
+ } as NodeData
+
+ render(
)
+
+ const operationInput = screen.getByTestId('input-operation')
+ fireEvent.change(operationInput, { target: { value: 'contains' } })
+
+ expect(mockOnDataChange).toHaveBeenCalledWith({
+ inputParam: conditionInputParam,
+ newValue: [{ type: 'string', value1: '', operation: 'contains', value2: '' }]
+ })
+ })
+
it('should disable buttons when disabled prop is true', () => {
const data: NodeData = {
...mockNodeData,
@@ -207,6 +229,35 @@ describe('ConditionBuilder', () => {
expect(screen.queryByTestId('input-handler-value2')).not.toBeInTheDocument()
})
+ it('should forward variableItems to NodeInputHandler only for params with acceptVariable', () => {
+ const inputParamWithAcceptVariable: InputParam = {
+ ...conditionInputParam,
+ array: [
+ { id: 'type', name: 'type', label: 'Type', type: 'options', default: 'string' } as InputParam,
+ { id: 'value1', name: 'value1', label: 'Value 1', type: 'string', default: '', acceptVariable: true } as InputParam,
+ { id: 'value2', name: 'value2', label: 'Value 2', type: 'string', default: '', acceptVariable: true } as InputParam
+ ]
+ }
+ const data: NodeData = {
+ ...mockNodeData,
+ inputs: { conditions: [{ type: 'string', value1: '', value2: '' }] }
+ } as NodeData
+ const variableItems: VariableItem[] = [{ label: 'question', value: '{{question}}', category: 'Chat Context' }]
+
+ render(
+
+ )
+
+ expect(screen.getByTestId('input-handler-type')).toHaveAttribute('data-has-variables', 'false')
+ expect(screen.getByTestId('input-handler-value1')).toHaveAttribute('data-has-variables', 'true')
+ expect(screen.getByTestId('input-handler-value2')).toHaveAttribute('data-has-variables', 'true')
+ })
+
it('should render fields for each condition item', () => {
const data: NodeData = {
...mockNodeData,
diff --git a/packages/agentflow/src/atoms/ConditionBuilder.tsx b/packages/agentflow/src/atoms/ConditionBuilder.tsx
index 633a7e1f0..c63472c5c 100644
--- a/packages/agentflow/src/atoms/ConditionBuilder.tsx
+++ b/packages/agentflow/src/atoms/ConditionBuilder.tsx
@@ -9,6 +9,7 @@ import type { InputParam, NodeData } from '@/core/types'
import { NodeInputHandler } from './NodeInputHandler'
import { useStableKeys } from './useStableKeys'
+import type { VariableItem } from './VariablePicker'
export interface ConditionBuilderProps {
inputParam: InputParam
@@ -16,6 +17,7 @@ export interface ConditionBuilderProps {
disabled?: boolean
onDataChange?: (params: { inputParam: InputParam; newValue: unknown }) => void
itemParameters?: InputParam[][]
+ variableItems?: VariableItem[]
}
/**
@@ -28,7 +30,8 @@ export function ConditionBuilder({
data,
disabled = false,
onDataChange,
- itemParameters: itemParametersProp
+ itemParameters: itemParametersProp,
+ variableItems
}: ConditionBuilderProps) {
const theme = useTheme()
@@ -49,6 +52,10 @@ export function ConditionBuilder({
const updatedArrayItems = [...arrayItems]
const updatedItem = { ...updatedArrayItems[itemIndex] }
updatedItem[changedParam.name] = newValue
+ if (changedParam.name === 'operation') {
+ updatedItem.value1 = ''
+ updatedItem.value2 = ''
+ }
updatedArrayItems[itemIndex] = updatedItem
onDataChange?.({ inputParam, newValue: updatedArrayItems })
},
@@ -137,6 +144,7 @@ export function ConditionBuilder({
isAdditionalParams={true}
disablePadding={false}
onDataChange={itemHandlers[index]}
+ variableItems={param.acceptVariable ? variableItems : undefined}
/>
))}
diff --git a/packages/agentflow/src/atoms/NodeInputHandler.test.tsx b/packages/agentflow/src/atoms/NodeInputHandler.test.tsx
index 8e41ddbf5..82f55b877 100644
--- a/packages/agentflow/src/atoms/NodeInputHandler.test.tsx
+++ b/packages/agentflow/src/atoms/NodeInputHandler.test.tsx
@@ -379,17 +379,18 @@ describe('NodeInputHandler – json type', () => {
expect(screen.queryByTestId('json-input')).toBeNull()
})
- it('renders inline JsonInput for json with acceptVariable but no variableItems', () => {
+ it('renders a button for json with acceptVariable even when no variableItems are provided', () => {
render(
)
- expect(screen.getByTestId('json-input')).toBeTruthy()
+ expect(screen.getByRole('button', { name: 'My Field' })).toBeTruthy()
+ expect(screen.queryByTestId('json-input')).toBeNull()
})
})
diff --git a/packages/agentflow/src/atoms/NodeInputHandler.tsx b/packages/agentflow/src/atoms/NodeInputHandler.tsx
index eec1a57ca..ee0f06ff6 100644
--- a/packages/agentflow/src/atoms/NodeInputHandler.tsx
+++ b/packages/agentflow/src/atoms/NodeInputHandler.tsx
@@ -48,6 +48,7 @@ export interface AsyncInputProps {
disabled: boolean
onChange: (newValue: string) => void
nodeName?: string
+ nodeId?: string
inputValues?: Record
}
@@ -303,7 +304,7 @@ export function NodeInputHandler({
case 'json': {
const jsonStr = typeof value === 'string' ? value : JSON.stringify(value || {})
- if (inputParam.acceptVariable && variableItems && variableItems.length > 0) {
+ if (inputParam.acceptVariable) {
// acceptVariable: show a button that opens a dialog with JsonInput + variable support
return (