``omit_defaults`` dropped the block's defaulted discriminator, and a request
that carried thinking was answered with 422 "thinking: missing field ``type``" —
which is what the compat sent for any configured ``reasoning_effort``. The field
has no default now, so it always encodes (both call sites pass it).
DeepSeek's Anthropic compat runs a hosted ``web_search`` itself and answers with
the blocks that search produced — ``thinking``, ``server_tool_use`` (the query)
and ``web_search_tool_result`` — so the content union that knew only text and
tool_use could not decode a live search turn. It carries them now, ``tools``
accepts the opaque server-tool dicts the surface declares, and
``web_search_tool_result.content`` stays loose on purpose: its
``web_search_result`` entries hold an ``encrypted_content`` the API demands back
unchanged (a trimmed result is answered with 422 "missing field
``encrypted_content``").
``provider_tools`` reached only the Responses surface, and the Anthropic one
wants its own definition of the same intent: a bare ``web_search`` becomes
``{type="web_search_20250305", name="web_search"}`` (the server tool Claude
declares and DeepSeek's compat reads, keeping a ``max_uses`` cap or any other
key), merged after the local function tools.
Such a tool is the server's: it streams ``input_json_delta`` fragments like a
call, and reading them as one asked the registry for a tool the server had
already run. Block types are now tracked, so only a ``tool_use`` block becomes a
tool call; the search blocks and ``thinking`` are skipped by the response
mapping (the answer the model wrote already used them) and never executed.
Thinking mode checks the field per round, not per call: an answer whose message
carried no `reasoning_content` came back 400 with the wording a call gets ("the
`reasoning_content` … must be passed back to the API"), while an empty string
satisfies the check. The injection now touches every assistant message instead
of only the ones carrying `tool_calls`.
DeepSeek dropped the `v4` prefix from its flash model, and the old id stays
valid only as a compatibility alias. Seed the default catalog with the current
name so a provider that omits `models` no longer offers a deprecated id, and
follow the rename in the wire fixtures and the minimal config template. An
explicit `deepseek-v4-flash` in TOML still passes through unchanged.
niquests exposes content as an async property; reading it without await
left a coroutine warning and skipped the body. Only load body on HTTP
errors for streams so SSE is not consumed early.
Previously DONE was skipped with continue, so keep-alive connections
could hang forever after the model finished. Also fail fast on HTTP
error statuses for stream and non-stream completions.