fix(providers): keep reasoning items wire-valid for DeepSeek Responses

convert_messages() emitted reasoning items with ``content`` as a plain
string whenever preserve_reasoning was enabled (the DeepSeek spec).
DeepSeek's Responses gateway rejects that shape with a serde error
("input: invalid type: string ..., expected a sequence"), which surfaced
only after token consolidation cleared provider_state and forced the
full-history conversion path; replayed server items already carry list
content, which is why normal multi-turn requests never failed. Serialize
reasoning content as a list of output_text parts, matching the OpenAI
Responses schema and DeepSeek's accepted wire shape (verified live against
api.deepseek.com/responses).

The serde fallback classifier introduced in the previous commit remains as
a last-resort safeguard for any remaining wire incompatibility.

Tests: extend test_preserves_deepseek_reasoning_content to the array shape;
add a full-history regression with the observed failing item, a
replay/consolidation regression covering both replayed and converted
reasoning items, and provider-level request fixtures for both paths.
Full suite: 5773 passed, 22 skipped (only the known local-only
channels/sms packaging failure remains).
This commit is contained in:
arcdrake22
2026-08-03 18:06:45 +08:00
committed by chengyongru
parent fb2688fd37
commit 6eda67b50c
3 changed files with 189 additions and 2 deletions
@@ -45,7 +45,7 @@ def convert_messages(
if isinstance(reasoning, str) and reasoning:
input_items.append({
"type": "reasoning",
"content": reasoning,
"content": [{"type": "output_text", "text": reasoning}],
})
if isinstance(content, str) and content:
message_id = _unique_item_id(f"msg_{idx}", used_item_ids)