fix(agent): close tool-call sequence on interrupt to prevent role alternation violation (#48879)

This commit is contained in:
kyssta-exe 2026-06-19 07:25:57 +00:00 committed by Teknium
parent 53f8386587
commit 81d2dc5d0f

View file

@ -166,6 +166,29 @@ def finalize_turn(
# same empty-response loop again.
try:
agent._drop_trailing_empty_response_scaffolding(messages)
# When the turn was interrupted and the last message is a tool
# result, append a synthetic assistant message to close the
# tool-call sequence. Without this, the session persists a
# ``tool → user`` alternation that strict providers (Gemini,
# Claude) reject, causing them to hallucinate a continuation of
# the user's message on the next turn (#48879).
#
# ``_drop_trailing_empty_response_scaffolding`` only rewinds the
# tool tail when an empty-response scaffolding flag is present; a
# clean ``/stop`` interrupt after a successful tool sets no such
# flag, so the tool result survives as the tail and we close it
# here instead. On an interrupt ``final_response`` is typically
# empty, so fall back to an explicit placeholder rather than
# persisting an empty-content assistant turn.
if interrupted and messages and messages[-1].get("role") == "tool":
messages.append(
{
"role": "assistant",
"content": (final_response or "").strip() or "Operation interrupted.",
}
)
agent._persist_session(messages, conversation_history)
except Exception as _persist_err:
_cleanup_errors.append(f"persist_session: {_persist_err}")