myagent-ai 1.15.43 → 1.15.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -462,6 +462,8 @@ class MainAgent(BaseAgent):
462
462
  _v2_reasoning_collected: List[str] = []
463
463
  # XML 解析失败时的 LLM 修正重试计数
464
464
  _xml_correction_retries: int = 0
465
+ # 连续无工具调用计数(防止模型一直不调用工具导致死循环)
466
+ _consecutive_no_tool_count: int = 0
465
467
 
466
468
  conversation_history = list(context.conversation_history or [])
467
469
 
@@ -905,27 +907,68 @@ class MainAgent(BaseAgent):
905
907
  )
906
908
  break
907
909
 
908
- # Step 10: 执行工具调用(无论 finish 值如何,先执行工具)
910
+ # Step 10: 执行工具调用
909
911
  if not parsed.tools_to_call:
910
- # 无工具调用: 优先使用已收集的 reasoning 文本(包含 parsed.response),避免丢失第一轮输出
911
- if _v2_reasoning_collected:
912
- final_text = "\n".join(_v2_reasoning_collected)
912
+ _consecutive_no_tool_count += 1
913
+ # 如果 finish=true 且无工具,任务完成
914
+ if parsed.finish:
915
+ logger.info(f"[{task_id}] finish=true 且无工具调用,任务完成")
916
+ if _v2_reasoning_collected:
917
+ final_text = "\n".join(_v2_reasoning_collected)
918
+ else:
919
+ before, after = extract_surrounding_text(llm_raw)
920
+ final_text = (before + "\n" + after).strip() if (before.strip() or after.strip()) else "已完成所有操作。"
921
+ context.working_memory["final_response"] = final_text
922
+ if not _emitted_reasoning_this_iter:
923
+ await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
924
+ if self.memory:
925
+ self.memory.add_session(
926
+ session_id=context.session_id,
927
+ role="assistant",
928
+ content=final_text,
929
+ )
930
+ break
931
+ elif _consecutive_no_tool_count >= 2:
932
+ # 连续 2 轮无工具调用,视为模型无意继续执行任务
933
+ logger.warning(
934
+ f"[{task_id}] 连续 {_consecutive_no_tool_count} 轮无工具调用且未 finish,"
935
+ f"视为任务结束"
936
+ )
937
+ if _v2_reasoning_collected:
938
+ final_text = "\n".join(_v2_reasoning_collected)
939
+ else:
940
+ before, after = extract_surrounding_text(llm_raw)
941
+ final_text = (before + "\n" + after).strip() if (before.strip() or after.strip()) else "任务已完成。"
942
+ context.working_memory["final_response"] = final_text
943
+ if not _emitted_reasoning_this_iter:
944
+ await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
945
+ if self.memory:
946
+ self.memory.add_session(
947
+ session_id=context.session_id,
948
+ role="assistant",
949
+ content=final_text,
950
+ )
951
+ break
913
952
  else:
914
- before, after = extract_surrounding_text(llm_raw)
915
- final_text = (before + "\n" + after).strip() if (before.strip() or after.strip()) else "任务已完成。"
916
- context.working_memory["final_response"] = final_text
917
- # [v1.15.8] 跳过已发送的 reasoning 文本,避免 TTS 重复播报
918
- if not _emitted_reasoning_this_iter:
919
- await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
920
- if self.memory:
921
- self.memory.add_session(
922
- session_id=context.session_id,
923
- role="assistant",
924
- content=final_text,
953
+ # finish 且未达到连续无工具阈值,继续回调 LLM
954
+ # 模型可能只是在中间步骤输出说明文字,下一轮才调用工具
955
+ logger.info(
956
+ f"[{task_id}] 无工具调用且未 finish(连续第 {_consecutive_no_tool_count} 轮),"
957
+ f"继续回调 LLM"
925
958
  )
926
- break
959
+ # 将当前输出作为对话历史,回调 LLM 继续执行
960
+ if llm_raw.strip():
961
+ conversation_history.append(Message(role="assistant", content=llm_raw))
962
+ conversation_history.append(Message(
963
+ role="user",
964
+ content="[系统提示] 你上一轮输出没有包含任何工具调用,也没有设置 finish=true。"
965
+ "如果任务尚未完成,请继续执行必要的工具调用。"
966
+ "如果任务已完成,请在输出中设置 <finish>true</finish>。",
967
+ ))
968
+ continue
927
969
 
928
970
  # Step 11: 有工具调用 — 先执行所有工具,再根据 finish 决定回调
971
+ _consecutive_no_tool_count = 0 # 有工具调用,重置计数器
929
972
  need_callback = False
930
973
  tool_outputs_parts = []
931
974
  _reasoning_len_before_round = len(_v2_reasoning_collected) # 记录本轮开始时的长度
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.15.43",
3
+ "version": "1.15.44",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {