From e27ba8d457daa4f10041ee70c7de106330ef0af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=AD=90=E9=BB=98?= <925456043@qq.com> Date: Tue, 24 Feb 2026 13:06:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dbot=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=90=8Ejsonschema=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E4=B8=8D=E5=8F=AF=E7=94=A8=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listener/ChatStreamListener.java | 8 +- .../ai/easyagents/tool/WorkflowTool.java | 90 ++++++++++++++++--- 2 files changed, 84 insertions(+), 14 deletions(-) diff --git a/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/listener/ChatStreamListener.java b/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/listener/ChatStreamListener.java index edb61fc..e5f838e 100644 --- a/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/listener/ChatStreamListener.java +++ b/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/listener/ChatStreamListener.java @@ -8,7 +8,6 @@ import com.easyagents.core.model.chat.StreamResponseListener; import com.easyagents.core.model.chat.response.AiMessageResponse; import com.easyagents.core.model.client.StreamContext; import com.easyagents.core.prompt.MemoryPrompt; -import org.apache.catalina.connector.ClientAbortException; import tech.easyflow.core.chat.protocol.ChatDomain; import tech.easyflow.core.chat.protocol.ChatEnvelope; import tech.easyflow.core.chat.protocol.ChatType; @@ -20,6 +19,7 @@ import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; public class ChatStreamListener implements StreamResponseListener { @@ -32,6 +32,8 @@ public class ChatStreamListener implements StreamResponseListener { private boolean canStop = true; // 辅助标记:是否进入过工具调用(避免重复递归判断) private boolean hasToolCall = false; + // 流式响应只能结束一次,避免重复发送导致 IllegalStateException + private final AtomicBoolean completed = new AtomicBoolean(false); public ChatStreamListener(String conversationId, ChatModel chatModel, MemoryPrompt memoryPrompt, ChatSseEmitter sseEmitter, ChatOptions chatOptions) { this.conversationId = conversationId; @@ -86,7 +88,7 @@ public class ChatStreamListener implements StreamResponseListener { @Override public void onStop(StreamContext context) { // 仅当canStop为true(最后一次无后续工具调用的响应)时,执行业务逻辑 - if (this.canStop) { + if (this.canStop && completed.compareAndSet(false, true)) { System.out.println("onStop"); if (context.getThrowable() != null) { sendSystemError(sseEmitter, context.getThrowable().getMessage()); @@ -103,7 +105,7 @@ public class ChatStreamListener implements StreamResponseListener { @Override public void onFailure(StreamContext context, Throwable throwable) { - if (throwable != null) { + if (throwable != null && completed.compareAndSet(false, true)) { throwable.printStackTrace(); sendSystemError(sseEmitter, throwable.getMessage()); } diff --git a/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/tool/WorkflowTool.java b/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/tool/WorkflowTool.java index 777db7a..8076aa6 100644 --- a/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/tool/WorkflowTool.java +++ b/easyflow-modules/easyflow-module-ai/src/main/java/tech/easyflow/ai/easyagents/tool/WorkflowTool.java @@ -9,9 +9,7 @@ import tech.easyflow.ai.entity.Workflow; import tech.easyflow.common.util.SpringContextUtil; import java.math.BigInteger; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; public class WorkflowTool extends BaseTool { @@ -43,18 +41,88 @@ public class WorkflowTool extends BaseTool { Parameter[] parameters = new Parameter[parameterDefs.size()]; for (int i = 0; i < parameterDefs.size(); i++) { com.easyagents.flow.core.chain.Parameter parameterDef = parameterDefs.get(i); - Parameter parameter = new Parameter(); - parameter.setName(parameterDef.getName()); - parameter.setDescription(parameterDef.getDescription()); - DataType dataType = parameterDef.getDataType(); - if (dataType == null) dataType = DataType.String; - parameter.setType(dataType.toString()); - parameter.setRequired(parameterDef.isRequired()); - parameters[i] = parameter; + parameters[i] = toToolParameter(parameterDef); } return parameters; } + private static Parameter toToolParameter(com.easyagents.flow.core.chain.Parameter parameterDef) { + Parameter parameter = new Parameter(); + parameter.setName(parameterDef.getName()); + parameter.setDescription(parameterDef.getDescription()); + parameter.setRequired(parameterDef.isRequired()); + + DataType dataType = parameterDef.getDataType(); + if (dataType == null) { + dataType = DataType.String; + } + + switch (dataType) { + case Object: + parameter.setType("object"); + parameter.setChildren(toToolChildren(parameterDef.getChildren())); + break; + case Array: + parameter.setType("array"); + parameter.setChildren(toToolChildren(parameterDef.getChildren())); + break; + case Array_Object: + parameter.setType("array"); + parameter.setChildren(Collections.singletonList(buildArrayItem("object", parameterDef.getChildren()))); + break; + case Array_String: + parameter.setType("array"); + parameter.setChildren(Collections.singletonList(buildArrayItem("string", null))); + break; + case Array_Number: + parameter.setType("array"); + parameter.setChildren(Collections.singletonList(buildArrayItem("number", null))); + break; + case Array_Boolean: + parameter.setType("array"); + parameter.setChildren(Collections.singletonList(buildArrayItem("boolean", null))); + break; + case Array_File: + parameter.setType("array"); + parameter.setChildren(Collections.singletonList(buildArrayItem("string", null))); + break; + case Number: + parameter.setType("number"); + break; + case Boolean: + parameter.setType("boolean"); + break; + case File: + parameter.setType("string"); + break; + case String: + default: + parameter.setType("string"); + break; + } + + return parameter; + } + + private static List toToolChildren(List parameterDefs) { + if (parameterDefs == null || parameterDefs.isEmpty()) { + return null; + } + List children = new ArrayList<>(parameterDefs.size()); + for (com.easyagents.flow.core.chain.Parameter childDef : parameterDefs) { + children.add(toToolParameter(childDef)); + } + return children; + } + + private static Parameter buildArrayItem(String itemType, List childrenDefs) { + Parameter item = new Parameter(); + item.setName(null); + item.setType(itemType); + item.setChildren(toToolChildren(childrenDefs)); + return item; + } + public BigInteger getWorkflowId() { return workflowId; }