4.8.13 test (#3102)

* fix: loop index;edge parent check

* perf: reference invalid check

* fix: ts
This commit is contained in:
Archer
2024-11-08 20:53:58 +08:00
committed by GitHub
parent 7537330a3b
commit d58cf44778
17 changed files with 117 additions and 62 deletions

View File

@@ -201,6 +201,7 @@ export enum NodeInputKeyEnum {
nodeHeight = 'nodeHeight',
// loop start
loopStartInput = 'loopStartInput',
loopStartIndex = 'loopStartIndex',
// loop end
loopEndInput = 'loopEndInput',
@@ -258,7 +259,7 @@ export enum NodeOutputKeyEnum {
loopArray = 'loopArray',
// loop start
loopStartInput = 'loopStartInput',
loopArrayIndex = 'loopArrayIndex',
loopStartIndex = 'loopStartIndex',
// form input
formInputResult = 'formInputResult'

View File

@@ -239,7 +239,7 @@ export const getReferenceVariableValue = ({
nodes: RuntimeNodeItemType[];
variables: Record<string, any>;
}) => {
if (!value) return undefined;
if (!value) return value;
// handle single reference value
if (isValidReferenceValueFormat(value)) {
@@ -253,7 +253,7 @@ export const getReferenceVariableValue = ({
const node = nodes.find((node) => node.nodeId === sourceNodeId);
if (!node) {
return undefined;
return value;
}
return node.outputs.find((output) => output.id === outputId)?.value;

View File

@@ -33,12 +33,18 @@ export const LoopStartNode: FlowNodeTemplateType = {
label: '',
required: true,
value: ''
},
{
key: NodeInputKeyEnum.loopStartIndex,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.number,
label: i18nT('workflow:Array_element_index')
}
],
outputs: [
{
id: NodeOutputKeyEnum.loopArrayIndex,
key: NodeOutputKeyEnum.loopArrayIndex,
id: NodeOutputKeyEnum.loopStartIndex,
key: NodeOutputKeyEnum.loopStartIndex,
label: i18nT('workflow:Array_element_index'),
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.number

View File

@@ -387,6 +387,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
node,
runtimeEdges
});
const nodeRunResult = await (() => {
if (status === 'run') {
nodeRunBeforeHook(node);
@@ -482,8 +483,16 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
: {};
node.inputs.forEach((input) => {
// Special input, not format
if (input.key === dynamicInput?.key) return;
// Skip some special key
if (input.key === NodeInputKeyEnum.childrenNodeIdList) {
params[input.key] = input.value;
return;
}
// replace {{xx}} variables
let value = replaceVariable(input.value, variables);
@@ -506,7 +515,6 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
if (input.canEdit && dynamicInput && params[dynamicInput.key]) {
params[dynamicInput.key][input.key] = valueTypeFormat(value, input.valueType);
}
params[input.key] = valueTypeFormat(value, input.valueType);
});

View File

@@ -51,23 +51,16 @@ export const dispatchLoop = async (props: Props): Promise<Response> => {
node.flowNodeType === FlowNodeTypeEnum.loopStart
) {
node.isEntry = true;
node.inputs = node.inputs.map((input) => {
node.inputs.forEach((input) => {
if (input.key === NodeInputKeyEnum.loopStartInput) {
return {
...input,
value: item
};
} else if (input.key === NodeInputKeyEnum.loopStartInput) {
return {
...input,
value: index++
};
} else {
return input;
input.value = item;
} else if (input.key === NodeInputKeyEnum.loopStartIndex) {
input.value = index++;
}
});
}
});
const response = await dispatchWorkFlow({
...props,
runtimeEdges: cloneDeep(runtimeEdges)
@@ -77,11 +70,13 @@ export const dispatchLoop = async (props: Props): Promise<Response> => {
(res) => res.moduleType === FlowNodeTypeEnum.loopEnd
)?.loopOutputValue;
// Concat runtime response
outputValueArr.push(loopOutputValue);
loopDetail.push(...response.flowResponses);
assistantResponses.push(...response.assistantResponses);
totalPoints += response.flowUsages.reduce((acc, usage) => acc + usage.totalPoints, 0);
totalPoints = response.flowUsages.reduce((acc, usage) => acc + usage.totalPoints, 0);
// Concat new variables
newVariables = {
...newVariables,
...response.newVariables

View File

@@ -7,9 +7,11 @@ import {
type Props = ModuleDispatchProps<{
[NodeInputKeyEnum.loopStartInput]: any;
[NodeInputKeyEnum.loopStartIndex]: number;
}>;
type Response = DispatchNodeResultType<{
[NodeOutputKeyEnum.loopStartInput]: any;
[NodeOutputKeyEnum.loopStartIndex]: number;
}>;
export const dispatchLoopStart = async (props: Props): Promise<Response> => {
@@ -18,6 +20,7 @@ export const dispatchLoopStart = async (props: Props): Promise<Response> => {
[DispatchNodeResponseKeyEnum.nodeResponse]: {
loopInputValue: params.loopStartInput
},
[NodeOutputKeyEnum.loopStartInput]: params.loopStartInput
[NodeOutputKeyEnum.loopStartInput]: params.loopStartInput,
[NodeOutputKeyEnum.loopStartIndex]: params.loopStartIndex
};
};

View File

@@ -17,6 +17,8 @@ export const dispatchPluginInput = (props: PluginInputProps) => {
* 插件单独运行时,这里会是一个特殊的数组
* 插件调用的话,这个参数是一个 string[] 不会进行处理
* 硬性要求API 单独调用插件时,要避免这种特殊类型冲突
TODO: 需要 filter max files
*/
for (const key in params) {
const val = params[key];

View File

@@ -130,7 +130,7 @@
"type.Simple bot": "Simple App",
"type.Workflow bot": "Workflow",
"upload_file_max_amount": "Maximum File Quantity",
"upload_file_max_amount_tip": "1. The maximum number of files that can be uploaded at one time.\n2. The maximum number of files remembered by the chat window: each round of dialogue will automatically retrieve files from history, files beyond the range will be forgotten.",
"upload_file_max_amount_tip": "Maximum number of files uploaded in a single round of conversation",
"variable.select type_desc": "You can define a global variable that does not need to be filled in by the user.\n\nThe value of this variable can come from the API interface, the Query of the shared link, or assigned through the [Variable Update] module.",
"variable.textarea_type_desc": "Allows users to input up to 4000 characters in the dialogue box.",
"version.Revert success": "Revert Successful",
@@ -154,7 +154,7 @@
"workflow.read_files": "Document Parsing",
"workflow.read_files_result": "Document Parsing Result",
"workflow.read_files_result_desc": "Original document text, consisting of file names and document content, separated by hyphens between multiple files.",
"workflow.read_files_tip": "Parse all uploaded documents in the dialogue and return the corresponding document content.",
"workflow.read_files_tip": "Parse the documents uploaded in this round of dialogue and return the corresponding document content",
"workflow.select_description": "Description Text",
"workflow.select_description_placeholder": "For example: \nAre there tomatoes in the fridge?",
"workflow.select_description_tip": "You can add a description text to explain the meaning of each option to the user.",

View File

@@ -131,7 +131,7 @@
"type.Simple bot": "简易应用",
"type.Workflow bot": "工作流",
"upload_file_max_amount": "最大文件数量",
"upload_file_max_amount_tip": "1.单次上传文件的最大数量。\n2.对话窗口记忆的最大文件数量:每轮对话会自动获取历史中的文件,超出范围的文件会被遗忘。",
"upload_file_max_amount_tip": "单轮对话中最大上传文件数量",
"variable.select type_desc": "可以为工作流定义全局变量,常用临时缓存。赋值的方式包括:\n1. 从对话页面的 query 参数获取。\n2. 通过 API 的 variables 对象传递。\n3. 通过【变量更新】节点进行赋值。",
"variable.textarea_type_desc": "允许用户最多输入4000字的对话框。",
"version.Revert success": "回滚成功",
@@ -155,7 +155,7 @@
"workflow.read_files": "文档解析",
"workflow.read_files_result": "文档解析结果",
"workflow.read_files_result_desc": "文档原文,由文件名和文档内容组成,多个文件之间通过横线隔开。",
"workflow.read_files_tip": "解析对话中所有上传的文档,并返回对应文档内容",
"workflow.read_files_tip": "解析本轮对话上传的文档,并返回对应文档内容",
"workflow.select_description": "说明文字",
"workflow.select_description_placeholder": "例如: \n冰箱里是否有西红柿",
"workflow.select_description_tip": "你可以添加一段说明文字,用以向用户说明每个选项代表的含义。",