mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-19 06:14:42 +00:00
fix: minor issue fixes
This commit is contained in:
1 parent
99484e02c8
commit
75e07af78f
16 files changed
+950
-43
No files matched your search
@@ -759,6 +759,66 @@ class TestHandleToolCalls:
|
||||
assistant_ids = {tc["id"] for tc in assistant_msg["tool_calls"]}
|
||||
assert tool_msg["tool_call_id"] in assistant_ids
|
||||
|
||||
def test_create_tool_message_failure_no_duplicate_assistant(self):
|
||||
"""A tool that succeeds but returns an unserializable result makes
|
||||
create_tool_message raise *after* the success path appended the
|
||||
assistant tool_calls message. The except branch must reuse that
|
||||
message, not append a second one — exactly one assistant(tool_calls)
|
||||
precedes the role:"tool" error, or the next completion 400s."""
|
||||
|
||||
class _SerializingHandler(ConcreteHandler):
|
||||
def create_tool_message(
|
||||
self, tool_call: ToolCall, result: Any
|
||||
) -> Dict:
|
||||
# Mirror real handlers: JSON-encode non-str results, which
|
||||
# raises on a value the encoder can't serialize. The error
|
||||
# path passes a plain string, so only the success path trips.
|
||||
import json as _json
|
||||
|
||||
content = (
|
||||
result
|
||||
if isinstance(result, str)
|
||||
else _json.dumps(result)
|
||||
)
|
||||
return {
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_call.id,
|
||||
"content": content,
|
||||
}
|
||||
|
||||
handler = _SerializingHandler()
|
||||
agent = self._make_agent()
|
||||
agent.tool_executor._name_to_tool = {}
|
||||
|
||||
# Tool runs fine but returns a value json.dumps can't encode.
|
||||
def fake_execute(tools_dict, call):
|
||||
yield {"type": "tool_call", "data": {"status": "pending"}}
|
||||
return (object(), call.id)
|
||||
|
||||
agent._execute_tool_action = Mock(side_effect=fake_execute)
|
||||
|
||||
call = ToolCall(id="c1", name="action_1", arguments="{}")
|
||||
gen = handler.handle_tool_calls(agent, [call], {"1": {"name": "t"}}, [])
|
||||
try:
|
||||
while True:
|
||||
next(gen)
|
||||
except StopIteration as e:
|
||||
messages, _pending = e.value
|
||||
|
||||
# Exactly one assistant(tool_calls) for c1, then the tool error — the
|
||||
# buggy path produced [assistant, assistant, tool].
|
||||
assert [m["role"] for m in messages] == ["assistant", "tool"]
|
||||
assistant_msgs = [
|
||||
m for m in messages
|
||||
if m.get("role") == "assistant"
|
||||
and any(tc["id"] == "c1" for tc in m.get("tool_calls", []))
|
||||
]
|
||||
assert len(assistant_msgs) == 1
|
||||
tool_msg = messages[-1]
|
||||
assert tool_msg["role"] == "tool"
|
||||
assert tool_msg["tool_call_id"] == "c1"
|
||||
assert "Error executing tool" in tool_msg["content"]
|
||||
|
||||
def test_partial_batch_failure_answers_every_tool_call(self):
|
||||
"""One tool raises, others succeed: every assistant tool_call must
|
||||
get a matching role:"tool" reply (OpenAI rejects unanswered ids)."""
|
||||
|
||||
Reference in new issue
Block a user