What happens
DeepSeek Responses reasoning now arrives and is stored after #2328, but a later tool-loop request tries to replay that plaintext reasoning through the OpenAI encrypted-reasoning shape.
With store: false, @ai-sdk/openai rejects that shape when it has no reasoningEncryptedContent, removes the reasoning item from the request, and prints this process warning:
AI SDK Warning (openai.responses / deepseek-v4-flash): Reasoning parts without encrypted content are not supported when store is false. Skipping reasoning parts.
This is not only noisy terminal output: the warning says the request projection is lossy.
The asymmetric round trip
Response direction (provider -> Maka) works today:
DeepSeek response.reasoning_text.delta
-> plaintext Responses transport added in #2328
-> AI SDK reasoning delta
-> Maka ThinkingItem { text, itemId, no encrypted content }
-> event log / UI
Request direction (Maka -> provider) does not:
stored ThinkingItem
-> AiSdkBackend reasoning part
-> @ai-sdk/openai Responses input converter
-> store=false + encrypted_content missing
-> warning + reasoning item removed
-> provider receives function_call / function_call_output without the plaintext reasoning
For example, after DeepSeek reasons and calls a tool, the desired second request is conceptually:
message, reasoning, function_call, function_call_output
The current request is:
message, function_call, function_call_output
DeepSeek can mask this in ordinary runs by recovering reasoning from its own call_id, but that is provider-specific behavior rather than a complete replay contract. The provider-free serialization gap is tracked upstream in vercel/ai#18511, with a proposed @ai-sdk/open-responses fix in vercel/ai#18546.
Why encrypted_content is involved
Maka sends Responses requests with store: false. The native OpenAI provider in the AI SDK therefore treats a replayable reasoning item as OpenAI's encrypted-content contract. DeepSeek's Open Responses dialect instead returns and consumes plaintext content[].reasoning_text; it cannot satisfy the OpenAI serializer merely by having an itemId.
The current replay capability is too broad: openai-responses-item says that a Responses reasoning item can be replayed, but does not say which wire dialect can encode it.
Proposed direction
I think this should be resolved at the ModelAdapter/request-projection seam, not by suppressing AI SDK warnings globally.
- Do not project plaintext Responses reasoning as an OpenAI encrypted reasoning item when
reasoningEncryptedContent is absent. This preserves today's actual wire body while removing the misleading attempted replay and process warning.
- Keep replaying genuine encrypted reasoning unchanged.
- Once the upstream
@ai-sdk/open-responses request-side fix is released, evaluate routing measured Open Responses providers such as DeepSeek through a dialect-specific codec/provider so plaintext reasoning is really serialized in the correct order.
The short-term containment and the full plaintext round trip can be separate PRs. I’m happy to implement this; before I start, I’d like to confirm whether maintainers prefer that split or want to wait for the upstream provider fix.
Acceptance checks
- A DeepSeek tool-loop request emits no plaintext-as-encrypted warning.
- A fake-fetch assertion checks the actual request body, not only Maka's intermediate model messages.
- Encrypted OpenAI Responses reasoning still replays.
- The request preserves
message, reasoning, function_call, function_call_output ordering once plaintext replay is enabled.
- No global warning suppression is introduced.
Related: #2328, vercel/ai#18511, vercel/ai#18546
中文说明
现象
#2328 已经修复了响应方向:DeepSeek 返回的明文 reasoning_text 能进入 Maka 的事件日志和界面。但是下一次工具回合组装请求时,Maka 又把这段明文 reasoning 当成 OpenAI 的加密 reasoning item 重放。
因为当前请求使用 store: false,@ai-sdk/openai 要求这种 reasoning item 携带 encrypted_content。DeepSeek 返回的是明文 reasoning_text,没有加密内容,所以 SDK 打印 warning 并在真正发请求前删除 reasoning item。
因此这不是单纯的日志噪音,而是说明请求投影发生了有损丢弃。
两个方向
- 响应方向:Provider 返回内容给 Maka。这个方向已经能把 DeepSeek 的明文 reasoning 转换、保存并显示。
- 请求方向:Maka 在工具调用后的下一轮,把历史消息重新发送给 Provider。这个方向目前尝试使用错误的 OpenAI 加密格式,随后被 SDK 丢弃。
普通运行有时仍然成功,是因为 DeepSeek 可以根据自己签发的 call_id 在服务端找回 reasoning;这不代表 Maka 已经正确发送了它。
建议
短期在 ModelAdapter/请求投影位置停止把缺少 reasoningEncryptedContent 的明文 reasoning 伪装成加密 item;真实的加密 reasoning 继续正常重放。长期等 @ai-sdk/open-responses 的请求侧修复发布后,再让 DeepSeek 使用能真正编码 reasoning_text 的 provider/codec。
不建议全局关闭 AI SDK warning,因为那只会隐藏有损请求。
我愿意实现这个修复;开始前想先确认维护者更希望拆成“短期止损 + 完整明文重放”两个 PR,还是等待上游 provider 修复。
What happens
DeepSeek Responses reasoning now arrives and is stored after #2328, but a later tool-loop request tries to replay that plaintext reasoning through the OpenAI encrypted-reasoning shape.
With
store: false,@ai-sdk/openairejects that shape when it has noreasoningEncryptedContent, removes the reasoning item from the request, and prints this process warning:This is not only noisy terminal output: the warning says the request projection is lossy.
The asymmetric round trip
Response direction (provider -> Maka) works today:
Request direction (Maka -> provider) does not:
For example, after DeepSeek reasons and calls a tool, the desired second request is conceptually:
The current request is:
DeepSeek can mask this in ordinary runs by recovering reasoning from its own
call_id, but that is provider-specific behavior rather than a complete replay contract. The provider-free serialization gap is tracked upstream in vercel/ai#18511, with a proposed@ai-sdk/open-responsesfix in vercel/ai#18546.Why
encrypted_contentis involvedMaka sends Responses requests with
store: false. The native OpenAI provider in the AI SDK therefore treats a replayable reasoning item as OpenAI's encrypted-content contract. DeepSeek's Open Responses dialect instead returns and consumes plaintextcontent[].reasoning_text; it cannot satisfy the OpenAI serializer merely by having anitemId.The current replay capability is too broad:
openai-responses-itemsays that a Responses reasoning item can be replayed, but does not say which wire dialect can encode it.Proposed direction
I think this should be resolved at the ModelAdapter/request-projection seam, not by suppressing AI SDK warnings globally.
reasoningEncryptedContentis absent. This preserves today's actual wire body while removing the misleading attempted replay and process warning.@ai-sdk/open-responsesrequest-side fix is released, evaluate routing measured Open Responses providers such as DeepSeek through a dialect-specific codec/provider so plaintext reasoning is really serialized in the correct order.The short-term containment and the full plaintext round trip can be separate PRs. I’m happy to implement this; before I start, I’d like to confirm whether maintainers prefer that split or want to wait for the upstream provider fix.
Acceptance checks
message, reasoning, function_call, function_call_outputordering once plaintext replay is enabled.Related: #2328, vercel/ai#18511, vercel/ai#18546
中文说明
现象
#2328 已经修复了响应方向:DeepSeek 返回的明文
reasoning_text能进入 Maka 的事件日志和界面。但是下一次工具回合组装请求时,Maka 又把这段明文 reasoning 当成 OpenAI 的加密 reasoning item 重放。因为当前请求使用
store: false,@ai-sdk/openai要求这种 reasoning item 携带encrypted_content。DeepSeek 返回的是明文reasoning_text,没有加密内容,所以 SDK 打印 warning 并在真正发请求前删除 reasoning item。因此这不是单纯的日志噪音,而是说明请求投影发生了有损丢弃。
两个方向
普通运行有时仍然成功,是因为 DeepSeek 可以根据自己签发的
call_id在服务端找回 reasoning;这不代表 Maka 已经正确发送了它。建议
短期在 ModelAdapter/请求投影位置停止把缺少
reasoningEncryptedContent的明文 reasoning 伪装成加密 item;真实的加密 reasoning 继续正常重放。长期等@ai-sdk/open-responses的请求侧修复发布后,再让 DeepSeek 使用能真正编码reasoning_text的 provider/codec。不建议全局关闭 AI SDK warning,因为那只会隐藏有损请求。
我愿意实现这个修复;开始前想先确认维护者更希望拆成“短期止损 + 完整明文重放”两个 PR,还是等待上游 provider 修复。