PR #947 fixed the consumer side (context.py) but the root cause is at
the provider level — getattr returns "" (empty string) instead of None
when reasoning_content is empty. This causes DeepSeek API to reject the
request with "Missing reasoning_content field" error.
`"" or None` evaluates to None, preventing empty strings from
propagating downstream.
Fixes#946
When MCP tools return empty content, messages may contain empty-string
text blocks. OpenAI-compatible providers reject these with HTTP 400.
Changes:
- Add _prevent_empty_text_blocks() to filter empty text items from
content lists and handle empty string content
- For assistant messages with tool_calls, set content to None (valid)
- For other messages, replace with '(empty)' placeholder
- Only copy message dict when modification is needed (zero-copy path
for normal messages)
Co-Authored-By: nanobot <noreply@anthropic.com>