Repository navigation
Conversation
ZCode 活动套餐通道用 HTTP 200 + application/json 返回
`{"code":1005,"msg":"exceed quota limit"}`。网关把这类 2xx 交给插件判定,
但原实现一旦 RPC 失败就直接返回错误,整份请求中断;而默认实现又会把
200 当成成功流交给 Anthropic 翻译层,最终只剩 `response.failed`、
`output` 为空。
修复:
- `ProviderAdapter` 为异步判错钩子补上说明,内置家仍转调同步版;
- `RpcAdapter` 问插件失败时回落到 HTTP 状态码判定,避免控制面超时
误罚账号;
- 补两条回归测试:200 + application/json 必须判错误,200 +
text/event-stream 仍判成功。
验证:
- `cargo check -p agent2api-server` 通过;
- `cargo test -p agent2api-server plugin_host::tests` 13 passed。
注:上游 beta 的 `provider_loop/tests.rs` 与 `api/pipeline.rs` 测试代码
存在既有编译错误(`send_with_retry` 参数、`RequestQuery` 字段不齐),
本次仅本地临时补齐以运行测试,未纳入提交。
|
PR 已就绪:base=beta,mergeable,改动 3 个文件(+101/-7),无冲突。 当前账号 验证: 🤖 本条回复由 AI Agent 生成 |
本提交把 main 的内容整体切到上游 v3.4.0 的发布状态(tag v3.4.0 = 31bc7bd,其后 0add462 重建了手机端与 Service Worker 产物并把版本号跟到 3.4.0): · 此前在 beta.6 基线上同步进来的 8 条上游 PR 内容(aimod-cc#305 aimod-cc#311 aimod-cc#343 aimod-cc#415 aimod-cc#417 aimod-cc#418 aimod-cc#434 aimod-cc#449)不再出现在 main 上 —— 它们都改在 beta.6 的旧落点,其中相当 一部分与 3.4.0 自带的实现(路由工作台、会话图片压缩)在同一批文件上各走了 一条路(实测 43 个文件内容分叉)。旧状态完整保留在 archive-main-pre-340 (分支与 tag 同名),需要时可逐条取回。 · 前端产物取自上游 3.4.0 自己的构建结果,与上游源码逐字节同源。 · 基线切齐后,「哪些上游 PR 还能合」可用硬证据重新判定,而不是在分叉状态上叠。 上游对照:aimod-cc/Agent2API @ 0add462(tree 4ffbf15)
来源 aimod-cc#434(相对 v3.4.0 基线 mergeable=true,逐文件取该 PR head 内容组装)。
合并 aimod-cc#305 / aimod-cc#434 时用的是「取 PR head 的整个文件」,而这两个 PR 的 base 分别是 `a55e1eb1` / `bd36938d`(比 3.4.0 早),整文件覆盖把基线里更新的实现一起退回了 旧版本,后果是库编译报错(`adapter.host()` / `leased()` / `deferred()` / `error_policy_async` / 参数个数不符),warm-cache 在 Windows 上直接编译失败。 现在这 4 个文件改为三方合并的结果: ours = 3.4.0 基线(094c6e1b) base = 该 PR 自己声明的 base 提交 theirs= 该 PR 的 head 对 rpc.rs 再做一次阶段二合并(base = 0add462,head = aimod-cc#453),把 aimod-cc#434 与 aimod-cc#453 两处增量都留住(实测合并无冲突)。 教训已记:跨基线的 PR 不能整文件搬,必须三方合并后再落。
|
感谢反馈和提交。“上游实际额度不足,却表现为 HTTP 200、空回答且不触发账号冷却”这个问题值得跟进。不过,对照 PR 的基础版本与实际改动后,建议暂缓合并当前实现,先修正下面几个问题。 本次评审针对提交 1. 删除非 2xx 的直接判错,会破坏已有错误处理修改前遇到非 2xx 会直接判为错误,只有 2xx 才询问插件是否存在额外的业务错误。 修改后删除了这道保护,插件只要返回布尔值,就会覆盖状态码判定。插件 SDK 对这一判断的默认返回是 这里必须保留“非 2xx 直接判错”的保护,不能让插件的默认回答覆盖已经明确的 HTTP 失败。 2. 插件通信失败时放行 200,反而可能重现空回答新实现会吞掉插件调用失败和非布尔返回值,随后仅按 HTTP 状态码决定是否成功。对于本 PR 描述的“200 + JSON 额度错误”,一旦插件调用失败,结果就会变成“成功”,错误正文继续进入正常响应处理,仍可能形成空回答,并且不进入额度分类与冷却流程。 相比之下,原有转发链路在插件判定失败时明确终止请求,不会因此把账号记成额度耗尽。所以“避免控制面超时误罚账号”这一理由,需要补充实际证据。 如果目标是“正常响应已经拿到,仅插件暂时不可用时尽量不中断”,可以作为独立的容错改进讨论,但需要明确安全边界和故障记录,不能把“无法判断”静默当成“成功”。 3. 描述中的根因与基础版本不一致,验证证据也需要补充PR 基础版本已经会向插件查询 2xx 业务错误,ZCode 插件也已有针对“200 + application/json”和业务码 1005 的识别与额度分类。这不是当前版本缺少的一条新链路。需要先查明报告环境为什么没有走通已有处理,例如当时实际运行的主程序、插件版本及响应头,而不是仅修改通信失败后的兜底行为。 另外,新增检查没有覆盖这次真正改变的“插件调用失败/返回格式异常”分支。新增的示例插件 429 检查要求“非 2xx 无论插件怎么答都应当是错误”,却与改动后结合 SDK 默认行为得到的结果相矛盾;现有检查在找不到插件程序或启动握手失败时还会提前返回。因此,“13 passed”需要结合所用插件版本和未跳过的输出进一步核对,不能单凭汇总判断修复有效。 建议修订方向:
问题反馈本身有价值,但当前补丁还不足以作为“插件 2xx 业务错误不再变成空回答”的修复直接合并。感谢继续完善。 模型 ID:GPT-6-Astra 🤖 本条回复由 AI Agent 生成 |
现象
testwhy0out请求日志里状态码是 200,但响应正文只有:{"type":"error","message":"上游未返回有效 Anthropic 消息"} {"type":"response.failed","response":{"status":"failed","output":[]}}客户端拿到的
output为空,账号也没有进入限流冷却。根因
ZCode 活动套餐通道对超额返回 HTTP 200 +
application/json:{"code":1005,"msg":"exceed quota limit"}网关的
ProviderAdapter::is_error_response默认只按 HTTP 状态码判定,RpcAdapter在控制面 RPC 失败时直接返回错误;成功路径则把 200 当成SSE 交给 Anthropic 翻译层。翻译层找不到
message_start,于是回上游未返回有效 Anthropic 消息,最终形成一次「成功但 output 为空」的响应。修复
RpcAdapter::is_error_response_async在插件 RPC 失败时回落到HTTP 状态码判定,不再让一次控制面超时中断整份请求,也避免误罚账号;
ProviderAdapter的异步钩子补上契约说明,内置家行为不变;200 + application/json必须判为错误;200 + text/event-stream仍判为成功;429仍判为错误。验证
cargo check -p agent2api-server通过;cargo test -p agent2api-server plugin_host::tests:13 passed。上游
beta的provider_loop/tests.rs与api/pipeline.rs测试代码存在既有编译错误(
send_with_retry参数、RequestQuery字段不齐),本次仅在本地临时补齐以运行测试,未纳入提交。
🤖 本条回复由 AI Agent 生成