# requires: pydantic, pytest import tool_loop as tl def setup_function(): tl.REFUNDS.clear() def test_happy_path_with_self_correction(): out = tl.run_agent(tl.ScriptedModel(tl.demo_script()), "退款", {"user_id": "u1"}, lambda n, a: True) assert out["answer"].startswith("已为订单") and tl.REFUNDS == {"A1001": 199.0} def test_user_rejects_refund(): out = tl.run_agent(tl.ScriptedModel(tl.demo_script()), "退款", {"user_id": "u1"}, lambda n, a: False) assert tl.REFUNDS == {} and out["trace"][2][2] == {"error": "用户拒绝执行该操作"} def test_other_users_order_hidden(): script = [{"role": "assistant", "tool_calls": [tl.call("c1", "get_order", {"order_id": "A1001"})]}, {"role": "assistant", "content": "没有找到订单"}] out = tl.run_agent(tl.ScriptedModel(script), "查订单", {"user_id": "u2"}, lambda n, a: True) assert out["trace"][0][2] == {"error": "订单不存在"} def test_amount_over_paid_rejected_and_unknown_tool(): script = [{"role": "assistant", "tool_calls": [ tl.call("c1", "refund", {"order_id": "A1001", "amount": 500}), tl.call("c2", "drop_table", {})]}, {"role": "assistant", "content": "无法退款"}] model = tl.ScriptedModel(script) out = tl.run_agent(model, "退 500", {"user_id": "u1"}, lambda n, a: True) assert "不能超过" in out["trace"][0][2]["error"] and "未知工具" in out["trace"][1][2]["error"] # 两个工具结果都回传给了模型,并且 tool_call_id 对应 last = model.seen[-1] assert [m["tool_call_id"] for m in last if m["role"] == "tool"] == ["c1", "c2"] def test_max_steps(): script = [{"role": "assistant", "tool_calls": [tl.call(f"c{i}", "get_order", {"order_id": "A1001"})]} for i in range(10)] out = tl.run_agent(tl.ScriptedModel(script), "x", {"user_id": "u1"}, lambda n, a: True, max_steps=3) assert out["steps"] == 3 and "转人工" in out["answer"]