| | |
| | | import { NodeType, nodeTypeMap } from './vueFlowEnum'; |
| | | import { HandleType, useNode, useVueFlow } from '@vue-flow/core'; |
| | | import { v4 as uuid } from 'uuid'; |
| | | import { VueFlowConstant } from './VueFlowConstant'; |
| | | import { CompareOperation, ConditionOperator, NodeType, VarType, nodeTypeMap } from './vueFlowEnum'; |
| | | import { get } from 'lodash'; |
| | | |
| | | export class VueFlowHelper { |
| | | static genId() { |
| | | return uuid().slice(0, 8); |
| | | } |
| | | |
| | | static genGeometryId() { |
| | | return uuid().slice(0, 12); |
| | | } |
| | | |
| | | static getDefaultData = (type: NodeType) => { |
| | | let data: any = { |
| | | title: nodeTypeMap[type], |
| | | }; |
| | | switch (type) { |
| | | case NodeType.Start: |
| | | data = { |
| | | ...data, |
| | | description: '工作流运行的起始节点。', |
| | | }; |
| | | data[VueFlowConstant.GROUP_PARAMS_KEY] = [ |
| | | { |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'var_list', |
| | | label: '', |
| | | type: 'var_list', |
| | | value: [], |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | break; |
| | | case NodeType.End: |
| | | data = { |
| | | ...data, |
| | | description: '工作流运行到此结束。', |
| | | }; |
| | | break; |
| | | case NodeType.Condition: |
| | | data = { |
| | | ...data, |
| | | description: '根据条件表达式执行不同的分支。', |
| | | }; |
| | | data[VueFlowConstant.GROUP_PARAMS_KEY] = [ |
| | | { |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'condition', |
| | | label: '', |
| | | type: 'condition', |
| | | value: [ConditionHelper.getDefaultConditionGroup(), ConditionHelper.getDefaultConditionGroup(true)], |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | break; |
| | | case NodeType.LLM: |
| | | data = { |
| | | ...data, |
| | | description: '调用大模型回答用户问题或者处理任务。', |
| | | }; |
| | | data[VueFlowConstant.GROUP_PARAMS_KEY] = [ |
| | | { |
| | | name: '模型设置', |
| | | |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'llm_model', |
| | | label: '模型', |
| | | type: 'llm_model', |
| | | value: '', |
| | | required: true, |
| | | placeholder: '请选择模型', |
| | | }, |
| | | { key: 'temperature', label: '温度', type: 'slide', scope: [0, 2], step: 0.1, value: 0.6 }, |
| | | ], |
| | | }, |
| | | { |
| | | name: '提示词', |
| | | [VueFlowConstant.PARAMS_KEY]: [{ key: 'prompt', label: '', type: 'textarea', value: '' }], |
| | | }, |
| | | ]; |
| | | break; |
| | | case NodeType.Code: |
| | | data = { |
| | | ...data, |
| | | description: '自定义需要执行的代码。', |
| | | [VueFlowConstant.GROUP_PARAMS_KEY]: [ |
| | | { |
| | | name: '入参', |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'code_input', |
| | | type: 'code_input', |
| | | required: true, |
| | | value: [ |
| | | { key: 'arg1', type: 'input', label: '', value: '' }, |
| | | { key: 'arg2', type: 'input', label: '', value: '' }, |
| | | ], |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | name: '执行代码', |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'code', |
| | | type: 'code', |
| | | required: true, |
| | | value: 'const main = (arg1, arg2) =>{\n return {\n result1: arg1,\n result2: arg2\n }\n}', |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | name: '出参', |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'code_output', |
| | | type: 'code_output', |
| | | // global: 'code:value.map(el => ({ label: el.key, value: el.key }))', |
| | | required: true, |
| | | value: [ |
| | | { key: 'result1', type: 'string' }, |
| | | { key: 'result2', type: 'string' }, |
| | | ], |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | }; |
| | | break; |
| | | case NodeType.Agent: |
| | | data[VueFlowConstant.GROUP_PARAMS_KEY] = [ |
| | | { |
| | | name: '代理名称', |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'agent', |
| | | label: '', |
| | | type: 'agent_select', |
| | | value: '', |
| | | // value_label:'', |
| | | required: true, |
| | | placeholder: '代理名称', |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | break; |
| | | |
| | | case NodeType.Func: |
| | | data[VueFlowConstant.GROUP_PARAMS_KEY] = [ |
| | | { |
| | | name: '函数名称', |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'func_name', |
| | | label: '', |
| | | type: 'func_name_select', |
| | | value: '', |
| | | // value_label:'', |
| | | required: true, |
| | | placeholder: '函数名称', |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | break; |
| | | case NodeType.Output: |
| | | data = { |
| | | ...data, |
| | | description: |
| | | '可向用户发送消息,并且支持进行更丰富的交互,例如请求用户批准进行某项敏感操作、允许用户在模型输出内容的基础上直接修改并提交。', |
| | | }; |
| | | data[VueFlowConstant.GROUP_PARAMS_KEY] = [ |
| | | { |
| | | [VueFlowConstant.PARAMS_KEY]: [ |
| | | { |
| | | key: 'output_msg', |
| | | label: '消息内容', |
| | | type: 'var_textarea_file', |
| | | required: true, |
| | | placeholder: |
| | | '输入需要发送给用户的消息,例如“接下来我将执行 XX 操作,请您确认”,“以下是我的初版草稿,您可以在其基础上进行修改”', |
| | | value: { msg: '', files: [] }, |
| | | }, |
| | | { |
| | | key: 'output_result', |
| | | label: '交互类型', |
| | | global: 'value.type=input', |
| | | type: 'output_form', |
| | | required: true, |
| | | value: { type: 'none', value: '' }, |
| | | options: [], |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | return data; |
| | | }; |
| | | |
| | | /** |
| | | * 强制写入到配置信息中,用于 patch 过去版本中没有的字段,或字段名称已经修改 |
| | | * |
| | | * 版本稳定后可删除此方法 |
| | | * @param obj |
| | | * @param key |
| | | * @param val |
| | | */ |
| | | static getConfigValue = (obj: any, key: string, val: string) => { |
| | | const value = obj[key]; |
| | | if (!value || value !== val) { |
| | | obj[key] = val; |
| | | } |
| | | return val; |
| | | }; |
| | | |
| | | static getHandleId = (node: any, handleType: HandleType, order?: number) => { |
| | | const orderSuffix = order == undefined ? '' : `__${order + ''}`; |
| | | return `${node.id}__handle-${handleType}${orderSuffix}`; |
| | | }; |
| | | |
| | | static getFieldValue = (data, key, index = 0) => { |
| | | let varList = []; |
| | | const group = data?.[VueFlowConstant.GROUP_PARAMS_KEY]; |
| | | if (group && group.length > 0) { |
| | | if (index !== null) { |
| | | const val = group?.[index]?.[VueFlowConstant.PARAMS_KEY]?.find((item) => item.key === key)?.value; |
| | | if (val) { |
| | | varList.push(val); |
| | | } |
| | | } else { |
| | | for (const item of group) { |
| | | if (item[VueFlowConstant.PARAMS_KEY].key === key) { |
| | | varList.push(item[VueFlowConstant.PARAMS_KEY].value); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (varList.length === 0) { |
| | | return null; |
| | | } else if (varList.length === 1) { |
| | | return varList[0]; |
| | | } else { |
| | | return varList; |
| | | } |
| | | }; |
| | | |
| | | static getGroupParam = (data, index = 0) => { |
| | | const group = data?.[VueFlowConstant.GROUP_PARAMS_KEY]?.[index]; |
| | | return group; |
| | | }; |
| | | |
| | | static getParams = (group, key) => { |
| | | return group?.[VueFlowConstant.PARAMS_KEY]?.find((item) => item.key === key); |
| | | }; |
| | | } |
| | | |
| | | export class StartNodeHelper { |
| | | // static getDefaultData = () => { |
| | | // return { |
| | | // title: nodeTypeMap[NodeType.Start], |
| | | // }; |
| | | // }; |
| | | |
| | | static getVarList = (data) => { |
| | | const varList = data[VueFlowConstant.GROUP_PARAMS_KEY][0][VueFlowConstant.PARAMS_KEY].find( |
| | | (item) => item.key === 'condition' |
| | | ).value; |
| | | return varList; |
| | | }; |
| | | } |
| | | |
| | | export class ConditionHelper { |
| | | static getConditionItem = ( |
| | | left?: { |
| | | var: string; |
| | | label: string; |
| | | value: string; |
| | | }, |
| | | right?: { |
| | | type: VarType; |
| | | value: string; |
| | | label: string; |
| | | }, |
| | | operation?: CompareOperation |
| | | ) => { |
| | | return { |
| | | id: VueFlowHelper.genId(), |
| | | left_var: left?.var ?? '', |
| | | left_label: left?.label ?? '', |
| | | left_value: left?.var ?? '', |
| | | comparison_operation: operation ?? '', |
| | | // right_value_type: right?.type ?? VarType.Input, |
| | | // 固定选择 input |
| | | right_value_type: VarType.Input, |
| | | |
| | | right_value: right?.value ?? '', |
| | | right_label: right?.label ?? '', |
| | | }; |
| | | }; |
| | | |
| | | static getDefaultConditionGroup = (isElse = false) => { |
| | | return isElse |
| | | ? { |
| | | id: VueFlowHelper.genId(), |
| | | } |
| | | : { |
| | | id: VueFlowHelper.genId(), |
| | | operator: ConditionOperator.And, |
| | | conditions: [ConditionHelper.getConditionItem()], |
| | | }; |
| | | }; |
| | | } |