feat: raise configurable chat tool call limit

This commit is contained in:
2026-09-26 20:36:05 +08:00
parent 84bb5abb28
commit 47e60187c7
5 changed files with 49 additions and 10 deletions
+34 -3
View File
@@ -218,8 +218,9 @@ def test_sse_persists_messages_and_tool_failure(session_factory, monkeypatch):
def tool_call(self, messages, tools):
calls.append(messages)
if len(calls) == 1:
return {"role": "assistant", "content": None, "tool_calls": [{"id": "call1", "type": "function",
"function": {"name": "list_courses", "arguments": "{}"}}]}
return {"role": "assistant", "content": None, "tool_calls": [
{"id": f"call{index}", "type": "function",
"function": {"name": "list_courses", "arguments": "{}"}} for index in range(9)]}
return {"role": "assistant", "content": "已列出课程版本。", "tool_calls": []}
monkeypatch.setattr(chat_api, "client_for_chat", lambda db: FakeClient())
def override_db():
@@ -231,9 +232,10 @@ def test_sse_persists_messages_and_tool_failure(session_factory, monkeypatch):
created = client.post("/api/conversations", json={"title": "测试对话"}).json()
with client.stream("POST", f"/api/conversations/{created['id']}/messages", json={"content": "列出课程"}) as response:
body = "".join(response.iter_text())
assert "event: tool" in body and "event: message" in body
assert body.count("event: tool") == 9 and "event: message" in body
restored = client.get(f"/api/conversations/{created['id']}").json()
assert [m["role"] for m in restored["messages"]] == ["user", "assistant"]
assert len(restored["messages"][1]["tool_calls"]) == 9
assert restored["runs"][0]["status"] == "completed"
monkeypatch.setattr(chat_api, "client_for_chat", lambda db: (_ for _ in ()).throw(ModelError("不支持工具调用")))
with client.stream("POST", f"/api/conversations/{created['id']}/messages", json={"content": "再试"}) as response:
@@ -251,6 +253,35 @@ def test_sse_persists_messages_and_tool_failure(session_factory, monkeypatch):
app.dependency_overrides.clear()
def test_failed_tool_calls_count_toward_limit(monkeypatch):
class RepeatingClient:
def tool_call(self, messages, tools):
return {"role": "assistant", "content": None, "tool_calls": [
{"id": f"call{len(messages)}", "type": "function",
"function": {"name": "unknown_tool", "arguments": "{}"}}]}
conversation = SimpleNamespace(id=1, course_version_id=None, batch_id=None, project_id=None, updated_at=None)
run = SimpleNamespace(id=1, status="running", error=None, finished_at=None)
class FakeSession:
def __enter__(self):
return self
def __exit__(self, *_args):
pass
def get(self, model, _id):
return conversation if model is Conversation else run
def scalars(self, _query):
return SimpleNamespace(all=lambda: [])
def commit(self):
pass
monkeypatch.setattr(chat_api, "client_for_chat", lambda db: RepeatingClient())
monkeypatch.setattr(chat_api, "get_settings", lambda: SimpleNamespace(chat_max_tool_calls=9))
body = "".join(chat_api._run_agent(FakeSession, 1, 1, "循环调用工具"))
assert body.count("event: tool") == 9
assert "本次消息工具调用超过上限 9 次" in body
assert run.status == "failed"
def test_native_tool_calls_unsupported_endpoint():
transport = httpx.MockTransport(lambda request: httpx.Response(400, json={"error": "unsupported"}))
client = DeepSeekClient(api_key="test-key", transport=transport)