diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java index 078353bb..7b3fba58 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java @@ -1,5 +1,6 @@ package vip.mate.agent.graph; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.Message; @@ -320,6 +321,8 @@ public class NodeStreamingChatHelper { private static final long BACKOFF_BASE_MS = 3000; private static final long BACKOFF_CAP_MS = 60_000; + private static final ObjectMapper TOOL_ARG_JSON_MAPPER = new ObjectMapper(); + /** * 判断错误是否可重试(基于状态码/异常类型) */ @@ -1841,11 +1844,49 @@ public class NodeStreamingChatHelper { acc.id, acc.type != null ? acc.type : "function", acc.name, - acc.arguments.toString())); + sanitizeToolCallArguments(acc.name, acc.arguments.toString()))); } return result; } + /** + * Ensure {@code function.arguments} is always a well-formed JSON string. + *
+ * Some providers (e.g. aliyun-codingplan) reject the entire follow-up + * request with HTTP 400 when the assistant message in history carries a + * tool call whose {@code arguments} is not parseable JSON. Streaming + * accumulation can produce such payloads when: + *