mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-06-15 07:14:08 +00:00
fix: drop tool results missing call ids
maintainer edit: treat tool messages without tool_call_id as orphaned during session persistence so malformed results cannot survive into history.
This commit is contained in:
parent
eb25df9b49
commit
33e6da14d8
@ -1592,13 +1592,13 @@ class AgentLoop:
|
|||||||
continue # skip empty assistant messages — they poison session context
|
continue # skip empty assistant messages — they poison session context
|
||||||
if role == "tool":
|
if role == "tool":
|
||||||
tool_call_id = entry.get("tool_call_id")
|
tool_call_id = entry.get("tool_call_id")
|
||||||
if tool_call_id and str(tool_call_id) not in declared_tool_call_ids:
|
if not tool_call_id or str(tool_call_id) not in declared_tool_call_ids:
|
||||||
# A tool result without a declared call violates the
|
# A tool result without a declared call violates the
|
||||||
# OpenAI/Anthropic pairing contract and would poison
|
# OpenAI/Anthropic pairing contract and would poison
|
||||||
# every future request built from this session (#4006).
|
# every future request built from this session (#4006).
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Dropping orphaned tool result {} from session {} during persistence",
|
"Dropping orphaned tool result {} from session {} during persistence",
|
||||||
tool_call_id,
|
tool_call_id or "(missing id)",
|
||||||
session.key,
|
session.key,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -1406,6 +1406,23 @@ def test_save_turn_drops_orphaned_tool_results() -> None:
|
|||||||
assert [m["role"] for m in session.messages] == ["user", "assistant"]
|
assert [m["role"] for m in session.messages] == ["user", "assistant"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_turn_drops_tool_results_without_tool_call_id() -> None:
|
||||||
|
loop = _mk_loop()
|
||||||
|
session = Session(key="test:missing-tool-call-id")
|
||||||
|
session.add_message("user", "hi")
|
||||||
|
|
||||||
|
loop._save_turn(
|
||||||
|
session,
|
||||||
|
[
|
||||||
|
{"role": "tool", "name": "exec", "content": "missing id"},
|
||||||
|
{"role": "assistant", "content": "done"},
|
||||||
|
],
|
||||||
|
skip=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert [m["role"] for m in session.messages] == ["user", "assistant"]
|
||||||
|
|
||||||
|
|
||||||
def test_save_turn_keeps_tool_results_declared_in_prior_history() -> None:
|
def test_save_turn_keeps_tool_results_declared_in_prior_history() -> None:
|
||||||
# Declarations may live in already-persisted history (e.g. a restored
|
# Declarations may live in already-persisted history (e.g. a restored
|
||||||
# runtime checkpoint), not only in the new-turn slice.
|
# runtime checkpoint), not only in the new-turn slice.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user