用户在使用工具调用(Tool Use)功能时,AI 会重复调用相同的工具,进入无限循环:
用户: 帮我看一下 index.html 是否提交
AI: 好的我来帮你检查
*tool use: git diff
*tool use: git status
AI: 用户说xxxx,好的我来帮你检查 ← 重复!
*tool use: git diff
*tool use: git status
AI: 用户说xxxx,我马上来检查 ← 又重复!
... 无限循环 ...
代码位置:claude_converter.py 的 process_history() 函数(第290-320行)
问题:合并连续USER消息时,没有区分包含 tool_result 的消息和普通文本消息,导致它们被错误地合并在一起。
具体场景:
# 输入消息
[
USER: "M: 检查文件",
ASSISTANT: [tool_use...],
USER: [tool_result...], # 包含工具执行结果
USER: "用户的跟进问题", # 普通文本(连续的USER消息)
]
# 旧代码输出(错误)
[
USER: "M: 检查文件",
ASSISTANT: [tool_use...],
USER: "用户的跟进问题" + [tool_result...] # ❌ 被合并了!
]
后果:
修改函数以收集并合并所有消息的 toolResults:
def merge_user_messages(messages: List[Dict[str, Any]]) -> Dict[str, Any]:
all_tool_results = [] # 收集所有消息的 toolResults
for msg in messages:
msg_ctx = msg.get("userInputMessageContext", {})
if base_context is None:
base_context = msg_ctx.copy()
# 移除 toolResults,单独合并
if "toolResults" in base_context:
all_tool_results.extend(base_context.pop("toolResults"))
else:
# 从后续消息收集 toolResults
if "toolResults" in msg_ctx:
all_tool_results.extend(msg_ctx["toolResults"])
# 将合并的 toolResults 添加到结果
if all_tool_results:
result["userInputMessageContext"]["toolResults"] = all_tool_results
添加智能检测,只在需要时才进行合并:
# 检测消息是否已正确交替
has_consecutive_same_role = False
for item in raw_history:
current_role = "user" if "userInputMessage" in item else "assistant"
if prev_role == current_role:
has_consecutive_same_role = True
break
prev_role = current_role
# 模式1:快速路径 - 消息已正确交替,跳过合并
if not has_consecutive_same_role:
return raw_history
# 模式2:合并路径 - 检测到连续的同角色消息,应用合并逻辑
# ... 合并逻辑 ...
双模式优势:
# 连续USER消息(包含多个tool_result)
输入: [USER(r1), USER(r2), USER(text)]
# 旧代码(错误)
输出: {toolResults: [r1]} # ❌ r2丢失
# 新代码(正确)
输出: {toolResults: [r1, r2], content: "text"} # ✅ 全部保留
优势:
所有测试通过:
代码质量:
_validate_message_order() 函数_detect_tool_call_loop() 函数DEBUG_MESSAGE_CONVERSION=true如果需要查看详细日志:
# 在 .env 中添加
DEBUG_MESSAGE_CONVERSION=true
# 重启服务后会看到详细的消息转换日志
修复版本: v1.0
修复日期: 2025-12-08
影响范围: 所有使用工具调用的场景