From 4242c776ed44424846028342ae81b44e303125a1 Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:35:21 +0800 Subject: [PATCH] fix: Infinite loop increases maximum loop count limit (#4088) --- .../flow/step_node/loop_node/impl/base_loop_node.py | 7 +++++++ installer/Dockerfile | 1 + ui/src/workflow/common/validate.ts | 4 ++-- ui/src/workflow/nodes/loop-body-node/index.vue | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/application/flow/step_node/loop_node/impl/base_loop_node.py b/apps/application/flow/step_node/loop_node/impl/base_loop_node.py index f0b57421f..9e83ad4da 100644 --- a/apps/application/flow/step_node/loop_node/impl/base_loop_node.py +++ b/apps/application/flow/step_node/loop_node/impl/base_loop_node.py @@ -15,6 +15,10 @@ from application.flow.step_node.loop_node.i_loop_node import ILoopNode from application.flow.tools import Reasoning from application.models import ChatRecord from common.handle.impl.response.loop_to_response import LoopToResponse +from maxkb.const import CONFIG +from django.utils.translation import gettext as _ + +max_loop_count = (CONFIG.get("MAX_LOOP_COUNT") or 1000) def _is_interrupt_exec(node, node_variable: Dict, workflow_variable: Dict): @@ -127,6 +131,7 @@ def loop(workflow_manage_new_instance, node: INode, generate_loop): current_index = node.context.get("current_index") or 0 node_params = node.node_params start_node_id = node_params.get('child_node', {}).get('runtime_node_id') + loop_type = node_params.get('loop_type') start_node_data = None chat_record = None child_node = None @@ -138,6 +143,8 @@ def loop(workflow_manage_new_instance, node: INode, generate_loop): details=loop_node_data[current_index]) for item, index in generate_loop(current_index): + if 0 < max_loop_count <= index - current_index and loop_type == 'LOOP': + raise Exception(_('Exceeding the maximum number of cycles')) """ 指定次数循环 @return: diff --git a/installer/Dockerfile b/installer/Dockerfile index c5ba2e5e3..3455c0ab8 100644 --- a/installer/Dockerfile +++ b/installer/Dockerfile @@ -44,6 +44,7 @@ ENV MAXKB_VERSION="${DOCKER_IMAGE_TAG} (build at ${BUILD_AT}, commit: ${GITHUB_C MAXKB_LOCAL_MODEL_HOST=127.0.0.1 \ MAXKB_LOCAL_MODEL_PORT=11636 \ MAXKB_LOCAL_MODEL_PROTOCOL=http \ + MAXKB_MAX_LOOP_COUNT=1000 \ PIP_TARGET=/opt/maxkb/python-packages diff --git a/ui/src/workflow/common/validate.ts b/ui/src/workflow/common/validate.ts index 1254e6d68..b1ccef27e 100644 --- a/ui/src/workflow/common/validate.ts +++ b/ui/src/workflow/common/validate.ts @@ -85,8 +85,8 @@ export class WorkFlowInstance { const base_node_list = this.nodes.filter((item) => item.id === WorkflowType.Base) return base_node_list[0] } - extis_break_node() { - return this.nodes.some((item) => item.id === WorkflowType.LoopBreakNode) + exist_break_node() { + return this.nodes.some((item) => item.type === WorkflowType.LoopBreakNode) } /** * 校验工作流 diff --git a/ui/src/workflow/nodes/loop-body-node/index.vue b/ui/src/workflow/nodes/loop-body-node/index.vue index d2bcfd39d..1f4dfe2f4 100644 --- a/ui/src/workflow/nodes/loop-body-node/index.vue +++ b/ui/src/workflow/nodes/loop-body-node/index.vue @@ -26,7 +26,7 @@ const validate = () => { const loop_node = props.nodeModel.graphModel.getNodeModelById(loop_node_id) try { workflow.is_loop_valid() - if (loop_node.properties.node_data.loop_type == 'LOOP' && !workflow.extis_break_node()) { + if (loop_node.properties.node_data.loop_type == 'LOOP' && !workflow.exist_break_node()) { return Promise.reject({ node: loop_node, errMessage: t('views.applicationWorkflow.validate.loopNodeBreakNodeRequired'),