Skip to content

同一任务从 DeepSeek 切换到 GPT 后,明文 reasoning_text 历史导致请求持续 400 #17

Description

@LEILEI0628

现象

在同一个 Codex 任务中先使用 DSCodex 的 DeepSeek V4 Flash/Pro,再切换到 GPT 模型(例如 gpt-5.6-sol),下一次 GPT 请求会立即失败:

Invalid 'input[7].content': array too long.
Expected an array with maximum length 0, but got an array with length 1 instead.

任务切回 DeepSeek 后可以继续运行;再次切换到 GPT 仍会触发相同错误。

这不是 Responses-Lite 请求头缺失导致的。补齐 Responses-Lite 请求头只会让请求正确到达 ChatGPT 后端,随后暴露已有的跨 provider 历史格式不兼容。

根因分析

DeepSeek Responses API 返回的 reasoning item 形状类似:

{
  "type": "reasoning",
  "content": [
    {
      "type": "reasoning_text",
      "text": "<omitted>"
    }
  ],
  "encrypted_content": null,
  "summary": []
}

Codex 将这个 item 写入任务历史。

切换到 GPT 后,DSCodex v1.0.0 对 GPT 请求执行透明旁路:

let outgoingBody = raw;

因此 DeepSeek 生成的明文 reasoning_text item 会被原样发送到 ChatGPT Responses 后端。

ChatGPT 后端接受的 reasoning 历史使用空 content 和 opaque/encrypted reasoning 数据,不接受上述带一个 reasoning_text content item 的 DeepSeek 形状,于是返回:

{
  "error": {
    "message": "Invalid 'input[7].content': array too long. Expected an array with maximum length 0, but got an array with length 1 instead.",
    "param": "input[7].content",
    "code": "array_above_max_length"
  }
}

官方 OpenAI Responses 文档建议在同一模型的无状态多轮请求中重放完整 output,包括加密 reasoning item;但这里重放的是另一 provider 生成的非 OpenAI reasoning 格式,二者不兼容。

复现步骤

  1. 安装并启动 DSCodex v1.0.0。

  2. 新建 Codex 任务,选择 deepseek/deepseek-v4-pro

  3. 让模型完成至少一个响应,使任务历史中产生 reasoning item。

  4. 在同一任务内切换到 gpt-5.6-sol

  5. 发送任意消息。

  6. GPT 请求返回 HTTP 400:

    Invalid 'input[N].content': array too long.
    Expected an array with maximum length 0, but got an array with length 1 instead.
    
  7. 切回 V4 Pro 后任务恢复运行。

复现证据

该问题已在两个独立任务中出现:

  • DSCodex v1.0.0、Codex CLI 0.147.0-alpha.6.5:V4 Pro → GPT-5.6 Sol 后报 input[7].content
  • 较长的旧任务在直通 ChatGPT remote compact 时:报 input[316].content

两个位置对应的历史 item 均为:

  • type: "reasoning"
  • content.length: 1
  • content 类型为 reasoning_text
  • encrypted_content: null

未在 issue 中包含任何 reasoning 正文、OAuth 信息或真实账户标识。

影响

  • 在同一任务内从 DeepSeek 切回 GPT 无法继续工作;
  • 错误 item 已保存在任务历史中,所以每次 GPT 请求都会重复失败;
  • 用户只能切回 DeepSeek 或新建任务,现有任务无法正常使用 GPT 接续;
  • remote compaction 也可能在请求头问题修复后继续被该历史 item 阻塞。

期望行为

DSCodex 应允许同一任务在 DeepSeek 与 GPT 之间安全切换。

发送 GPT-bound 请求前,应识别并处理 DeepSeek 特有的明文 reasoning item,避免将 GPT 不接受的 reasoning_text 形状直接发送给 ChatGPT。

处理过程必须保留用户消息、assistant 可见输出、工具调用及工具输出的相对顺序,不应修改用户的 rollout JSONL 文件。

建议修复方向

可考虑在 GPT-bound 请求中识别:

  • type === "reasoning"
  • content 包含 reasoning_text
  • encrypted_content == null

并在转发前安全移除这类 DeepSeek-only reasoning item。

由于 GPT 请求可能使用 zstd 压缩,只有实际发生迁移时才应解码、修改并以正确编码重新构造请求;不含 DeepSeek reasoning 的普通 GPT 流量仍应保持透明字节旁路。

另一种方案是在 provider 切换时生成可跨 provider 使用的 compact summary,但不应把明文 reasoning 内容转换成普通消息或直接泄露给另一 provider。

环境

  • DSCodex:v1.0.0(45e9f84
  • Codex Desktop,底层 CLI:0.147.0-alpha.6.5
  • OS:macOS 26.4.1
  • 切换方向:DeepSeek V4 Pro → GPT-5.6 Sol

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions