diff --git a/agent_loop.py b/agent_loop.py index a744f0d26..5c19d5fcf 100644 --- a/agent_loop.py +++ b/agent_loop.py @@ -24,6 +24,7 @@ def dispatch(self, tool_name, args, response, index=0, tool_num=1): _hook('tool_after', locals()) return ret elif tool_name == 'bad_json': return StepOutcome(None, next_prompt=args.get('msg', 'bad_json'), should_exit=False) + elif tool_name == 'no_tool': return StepOutcome(response.content, next_prompt=None, should_exit=False) else: yield f"未知工具: {tool_name}\n" return StepOutcome(None, next_prompt=f"未知工具 {tool_name}", should_exit=False) diff --git a/tests/test_agent_loop_no_tool.py b/tests/test_agent_loop_no_tool.py new file mode 100644 index 000000000..92b036c5a --- /dev/null +++ b/tests/test_agent_loop_no_tool.py @@ -0,0 +1,58 @@ +import unittest +from types import SimpleNamespace + +from agent_loop import BaseHandler, exhaust, agent_runner_loop + + +class StubClient: + def __init__(self): + self.last_tools = "" + + def chat(self, messages, tools): + response = SimpleNamespace(content="final answer", tool_calls=[]) + + def gen(): + if False: + yield None + return response + + return gen() + + +class StubHandler(BaseHandler): + def __init__(self): + self.parent = SimpleNamespace(task_dir=None) + self._done_hooks = [] + self.turns = [] + + def turn_end_callback(self, response, tool_calls, tool_results, turn, next_prompt, exit_reason): + self.turns.append({ + "tool_calls": tool_calls, + "next_prompt": next_prompt, + "exit_reason": exit_reason, + }) + return next_prompt + + +class AgentLoopNoToolTests(unittest.TestCase): + def test_direct_answer_completes_without_fake_unknown_tool_retry(self): + handler = StubHandler() + result = exhaust(agent_runner_loop( + StubClient(), + "system", + "user", + handler, + tools_schema=[], + max_turns=1, + verbose=False, + )) + + self.assertEqual(result["result"], "CURRENT_TASK_DONE") + self.assertEqual(len(handler.turns), 1) + self.assertEqual(handler.turns[0]["tool_calls"][0]["tool_name"], "no_tool") + self.assertEqual(handler.turns[0]["next_prompt"], "") + self.assertNotIn("未知工具", handler.turns[0]["next_prompt"]) + + +if __name__ == "__main__": + unittest.main()