
Devin 把一句工具描述里的措辞当成 MCP 配置错误回 403,中转把一个坏请求重试了十六次;Antigravity 把上游的安全拦截译成正常结束,客户端拿到空回答还以为成功。两处修复今早进了 dev,v8.0.52 都还没有——本期给出今天就能改的两条配置和一条自查。
6e6afab9,dev 领先四笔2。窗口内四个仓库都没有发新版。| 你看到的 | 属于哪一类 | 现在能做什么 |
|---|---|---|
Devin 回 403 permission_denied 加 MCP configuration issue,一条请求在日志里重试十几次 | 请求内容触发,不是凭证问题 | 加一条请求过错规则让它停下,或改工具描述 |
Antigravity 转 Claude 的路径上 stop_reason=end_turn 且输出 0 token | 上游安全拦截被译成正常结束 | v8.0.52 没有配置项,只能等新版 |
OpenAI 兼容上游回 422、说 developer 角色不认识 | 角色语义不兼容 | 用 payload.override 改写成 system |
Codex 经 Antigravity 分组带 apply_patch 时报错、回程只出 function_call | custom 工具被降级成空 schema | 等 sub2api 合 #8489 |
exec 的自定义工具,Devin 侧收到的名字是 functions__exec。这个工具的描述约一万七千字符,里面嵌着 exec_command 的一句话3。403 devin upstream error (permission_denied): Unable to process request due to an MCP configuration issue.。它把工具描述里的措辞当成了 MCP 配置错误,与账号状态无关3。| 工具名 | 描述里那句话 | 结果 |
|---|---|---|
exec_command | 原句 | 200 |
probe_tool | 原句 | 403 |
functions__exec | 原句 | 403 |
functions__exec | 改一个词(an session ID) | 200 |
probe_tool | 把 PTY 换成 pseudo-terminal | 200 |
SanitizeDevinToolDescription(_ string, desc string),第一个参数直接不用,两个替换无条件执行4。returning output or an session ID for ongoing interaction。这样上游那条匹配串就不再命中4。
internal/translator/common/devin_tools.go 第 36–63 行:第一个参数写成下划线,第 60–61 行两个替换不看工具名、无条件执行4(toolName, desc string),只有 exec_command 或以 __exec_command 结尾的才替换,write_stdin 同理5。functions__exec 名字对不上,整段描述原样发了出去。
return desc,描述原样出站5request-retry: 3,这次 403 又被当成可以换号的失败。于是一个注定失败两次的请求,把候选凭证逐个试过去。oauth:
providers:
devin:
request-scoped-errors:
- status: 403
match:
- "Unable to process request due to an MCP configuration issue"
action: "stop"payload.override 加一条 protocol: "devin" 的规则,改 tools.#(name=="functions__exec").description。permission_denied 与那两句文案之一8。
internal/clienterror/client_error.go 第 179–210 行:IsDevinRequestPermissionDenied 要求 403 加 permission_denied,再命中 MCP 配置或内容政策两句文案之一,然后被 IsRequestFault 调用8resolveAntigravityClaudeStopReason,先判有没有工具调用9。tool_use;MAX_TOKENS 给 max_tokens;SAFETY、RECITATION、PROHIBITED_CONTENT、SPII、BLOCKLIST、IMAGE_SAFETY、MALFORMED_RESPONSE、MALFORMED_FUNCTION_CALL 八个给 refusal9。STOP、FINISH_REASON_UNSPECIFIED、UNKNOWN 和空串才是 end_turn,其余落默认分支也归 end_turn。
internal/translator/antigravity/claude/antigravity_claude_response.go 第 591–610 行:hasToolUse 优先,八个安全类 finishReason 一起映射为 refusal9
MAX_TOKENS 与 STOP 一族有分支,第 606 行的 default 兜底成 end_turn10end_turn 当正常完成。客户端不重试、不提示,用户看到一个空回答;这次调用照样记账。stop_reason=end_turn 且输出 token 为 0 的响应,逐条对一下上游的 finishReason。v8.0.52 上这类响应是静默的。git ls-remote https://github.com/router-for-me/CLIProxyAPI \
HEAD refs/heads/main refs/heads/dev 'refs/tags/v8.0.52*'developer 发上来(见 #7174)。无条件降成 system 会回退那些本来就支持 developer 的上游,还剥掉中段指令的权威性11。system|user|assistant|tool 的上游,他给的写法是:payload:
override:
- models:
- name: "deepseek-*"
protocol: "openai"
params:
'messages.#(role=="developer")#.role': "system"# 表示改写所有匹配项,漏掉就只改第一条。没有 developer 消息时这条规则不动任何东西11。ForwardAsResponses 没像 Anthropic 路径那样调 AdaptResponsesClientTools。于是 apply_patch 这类 freeform 工具被转成空 schema,模型没地方放补丁,回程只出 function_call12。File uploads 组件降级,API 侧全绿——产品侧问题,不影响中转13。MCP configuration issue 的,先加那条 request-scoped-errors,把重试风暴停掉。payload.override 改 functions__exec 的描述,或者在源码模式里加规则。stop_reason=end_turn 且 0 输出的,按被拦截处理,别当模型没话说。github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
status.openai.com
status.anthropic.com
status.cloud.google.com
codex-reset.com
reddit.com
community.openai.com
This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.