问题现象 链接到标题
Codex 通过 Moon Bridge 使用 DeepSeek V4 Flash 时,任务执行中途突然终止。终端输出类似:
<||DSML||tool_calls> <||DSML||invoke name="exec_command"> <||DSML||parameter name="cmd" string="true">
然后任务就卡住不动了。
问题分析 链接到标题
Moon Bridge 架构 链接到标题
Moon Bridge 是一个 Go 编写的协议转换与模型路由代理,对外暴露 OpenAI Responses API(/v1/responses),对内支持 Anthropic Messages、Google Gemini、OpenAI Chat Completions 等多种上游协议。
当 Codex 发起请求时,Moon Bridge 负责把 OpenAI Responses 格式的请求转换为上游 Provider 需要的格式。
根因:DeepSeek V4 DSML 链接到标题
DeepSeek V4 在工具调用场景下,会将 DSML(DeepSeek Markup Language)标记直接输出到 content 字段,而不是作为结构化的 tool_calls 返回。这违反了 OpenAI API 契约——工具调用应该只在 tool_calls 字段中传递。
当 Moon Bridge 把 DeepSeek 的响应转发给 Codex 时,Codex 期望的结构化 tool_calls 字段为空,于是把 DSML 标记当作普通文本处理,最终导致任务直接中止。
相关 Issue 链接到标题
- moon-bridge#51:Codex 发送空 name 的 Tools 导致 DeepSeek 400 错误
- earendil-works/pi#3712:DeepSeek V4 通过 OpenAI 兼容端点也会原生输出 DSML 到 assistant text
解决方案 链接到标题
根本解决需要在 Moon Bridge 中添加 DSML 解析器,从 content 中提取工具调用并转换为结构化的 tool_calls 格式。
总结 链接到标题
这是典型的 Codex + 非 OpenAI 原生模型的协议兼容性问题。Moon Bridge 完成的是入口协议转换,但在工具调用链路上还需要更深入的协议转换逻辑。