Adds sanitize_tool_message_pairing() called from build_chat_completion_request() after translate_message() runs. Drops any role:"tool" message whose immediately-preceding non-tool message is role:"assistant" but has no tool_calls entry matching the tool_call_id. This is the second layer of the tool-pairing invariant defense: - 6e301c8: compaction boundary fix (producer layer) - this commit: request-builder sanitizer (sender layer) Together these close the 400-error loop for resumed/compacted multi-turn tool sessions on OpenAI-compatible backends. Sanitization only fires when preceding message is role:assistant (not user/system) to avoid dropping valid translation artifacts from mixed user-message content blocks. Regression tests: sanitize_drops_orphaned_tool_messages covers valid pair, orphaned tool (no tool_calls in preceding assistant), mismatched id, and two tool results both referencing the same assistant turn. 116 api + 159 CLI + 431 runtime tests pass. Fmt clean. |
||
|---|---|---|
| .. | ||
| api | ||
| commands | ||
| compat-harness | ||
| mock-anthropic-service | ||
| plugins | ||
| runtime | ||
| rusty-claude-cli | ||
| telemetry | ||
| tools | ||