Flowise/packages/components/nodes/agentflow/Condition/Condition.ts

351 lines
14 KiB
TypeScript

import { CommonType, ICommonObject, ICondition, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
class Condition_Agentflow implements INode {
label: string
name: string
version: number
description: string
type: string
icon: string
category: string
color: string
tags: string[]
baseClasses: string[]
inputs: INodeParams[]
outputs: INodeOutputsValue[]
constructor() {
this.label = 'Condition'
this.name = 'conditionAgentflow'
this.version = 1.0
this.type = 'Condition'
this.category = 'Agent Flows'
this.description = `Split flows based on If Else conditions`
this.baseClasses = [this.type]
this.color = '#FFB938'
this.inputs = [
{
label: 'Conditions',
name: 'conditions',
type: 'array',
description: 'Values to compare',
acceptVariable: true,
default: [
{
type: 'string',
value1: '',
operation: 'equal',
value2: ''
}
],
array: [
{
label: 'Type',
name: 'type',
type: 'options',
options: [
{
label: 'String',
name: 'string'
},
{
label: 'Number',
name: 'number'
},
{
label: 'Boolean',
name: 'boolean'
}
],
default: 'string'
},
/////////////////////////////////////// STRING ////////////////////////////////////////
{
label: 'Value 1',
name: 'value1',
type: 'string',
default: '',
description: 'First value to be compared with',
acceptVariable: true,
show: {
'conditions[$index].type': 'string'
}
},
{
label: 'Operation',
name: 'operation',
type: 'options',
options: [
{
label: 'Contains',
name: 'contains'
},
{
label: 'Ends With',
name: 'endsWith'
},
{
label: 'Equal',
name: 'equal'
},
{
label: 'Not Contains',
name: 'notContains'
},
{
label: 'Not Equal',
name: 'notEqual'
},
{
label: 'Regex',
name: 'regex'
},
{
label: 'Starts With',
name: 'startsWith'
},
{
label: 'Is Empty',
name: 'isEmpty'
},
{
label: 'Not Empty',
name: 'notEmpty'
}
],
default: 'equal',
description: 'Type of operation',
show: {
'conditions[$index].type': 'string'
}
},
{
label: 'Value 2',
name: 'value2',
type: 'string',
default: '',
description: 'Second value to be compared with',
acceptVariable: true,
show: {
'conditions[$index].type': 'string'
},
hide: {
'conditions[$index].operation': ['isEmpty', 'notEmpty']
}
},
/////////////////////////////////////// NUMBER ////////////////////////////////////////
{
label: 'Value 1',
name: 'value1',
type: 'number',
default: '',
description: 'First value to be compared with',
acceptVariable: true,
show: {
'conditions[$index].type': 'number'
}
},
{
label: 'Operation',
name: 'operation',
type: 'options',
options: [
{
label: 'Smaller',
name: 'smaller'
},
{
label: 'Smaller Equal',
name: 'smallerEqual'
},
{
label: 'Equal',
name: 'equal'
},
{
label: 'Not Equal',
name: 'notEqual'
},
{
label: 'Larger',
name: 'larger'
},
{
label: 'Larger Equal',
name: 'largerEqual'
},
{
label: 'Is Empty',
name: 'isEmpty'
},
{
label: 'Not Empty',
name: 'notEmpty'
}
],
default: 'equal',
description: 'Type of operation',
show: {
'conditions[$index].type': 'number'
}
},
{
label: 'Value 2',
name: 'value2',
type: 'number',
default: 0,
description: 'Second value to be compared with',
acceptVariable: true,
show: {
'conditions[$index].type': 'number'
}
},
/////////////////////////////////////// BOOLEAN ////////////////////////////////////////
{
label: 'Value 1',
name: 'value1',
type: 'boolean',
default: false,
description: 'First value to be compared with',
show: {
'conditions[$index].type': 'boolean'
}
},
{
label: 'Operation',
name: 'operation',
type: 'options',
options: [
{
label: 'Equal',
name: 'equal'
},
{
label: 'Not Equal',
name: 'notEqual'
}
],
default: 'equal',
description: 'Type of operation',
show: {
'conditions[$index].type': 'boolean'
}
},
{
label: 'Value 2',
name: 'value2',
type: 'boolean',
default: false,
description: 'Second value to be compared with',
show: {
'conditions[$index].type': 'boolean'
}
}
]
}
]
this.outputs = [
{
label: '0',
name: '0',
description: 'Condition 0'
},
{
label: '1',
name: '1',
description: 'Else'
}
]
}
async run(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
const state = options.agentflowRuntime?.state as ICommonObject
const compareOperationFunctions: {
[key: string]: (value1: CommonType, value2: CommonType) => boolean
} = {
contains: (value1: CommonType, value2: CommonType) => (value1 || '').toString().includes((value2 || '').toString()),
notContains: (value1: CommonType, value2: CommonType) => !(value1 || '').toString().includes((value2 || '').toString()),
endsWith: (value1: CommonType, value2: CommonType) => (value1 as string).endsWith(value2 as string),
equal: (value1: CommonType, value2: CommonType) => value1 === value2,
notEqual: (value1: CommonType, value2: CommonType) => value1 !== value2,
larger: (value1: CommonType, value2: CommonType) => (Number(value1) || 0) > (Number(value2) || 0),
largerEqual: (value1: CommonType, value2: CommonType) => (Number(value1) || 0) >= (Number(value2) || 0),
smaller: (value1: CommonType, value2: CommonType) => (Number(value1) || 0) < (Number(value2) || 0),
smallerEqual: (value1: CommonType, value2: CommonType) => (Number(value1) || 0) <= (Number(value2) || 0),
startsWith: (value1: CommonType, value2: CommonType) => (value1 as string).startsWith(value2 as string),
isEmpty: (value1: CommonType) => [undefined, null, ''].includes(value1 as string),
notEmpty: (value1: CommonType) => ![undefined, null, ''].includes(value1 as string)
}
const _conditions = nodeData.inputs?.conditions
const conditions: ICondition[] = typeof _conditions === 'string' ? JSON.parse(_conditions) : _conditions
const initialConditions = { ...conditions }
for (const condition of conditions) {
const _value1 = condition.value1
const _value2 = condition.value2
const operation = condition.operation
let value1: CommonType
let value2: CommonType
switch (condition.type) {
case 'boolean':
value1 = _value1
value2 = _value2
break
case 'number':
value1 = parseFloat(_value1 as string) || 0
value2 = parseFloat(_value2 as string) || 0
break
default: // string
value1 = _value1 as string
value2 = _value2 as string
}
const compareOperationResult = compareOperationFunctions[operation](value1, value2)
if (compareOperationResult) {
// find the matching condition
const conditionIndex = conditions.findIndex((c) => JSON.stringify(c) === JSON.stringify(condition))
// add isFulfilled to the condition
if (conditionIndex > -1) {
conditions[conditionIndex] = { ...condition, isFulfilled: true }
}
break
}
}
// If no condition is fullfilled, add isFulfilled to the ELSE condition
const dummyElseConditionData = {
type: 'string',
value1: '',
operation: 'equal',
value2: ''
}
if (!conditions.some((c) => c.isFulfilled)) {
conditions.push({
...dummyElseConditionData,
isFulfilled: true
})
} else {
conditions.push({
...dummyElseConditionData,
isFulfilled: false
})
}
const returnOutput = {
id: nodeData.id,
name: this.name,
input: { conditions: initialConditions },
output: { conditions },
state
}
return returnOutput
}
}
module.exports = { nodeClass: Condition_Agentflow }