fix(routes): 修复 count_tokens 路由对 target_vendor.name 的错误属性访问;#235
Merged
ThreeFish-AI merged 1 commit intoMay 11, 2026
Merged
Conversation
根因: BaseVendor 仅暴露抽象方法 get_name(), 所有 Vendor 子类均无 name 实例属性. routes.py:153/160 错误访问 target_vendor.name 导致 AttributeError 返回 500. 间歇性原因: 仅当 infer_source_vendor_from_body() 从请求体推断出非空 source (含 zhipu 私有产物 srvtoolu_* / server_tool_use) 时才走错误分支, 因此日志中 200/500 共存. 变更要点: - routes.py 两处 .name 改为 .get_name() 并提取局部变量 target_name 复用, 避免重复方法调用与日志/调用点不一致风险 - 新增回归测试 test_count_tokens_triggers_zhipu_to_target_channel: 注入 server_tool_use + srvtoolu_* 触发 zhipu→anthropic 通道, 断言 200 且 debug 日志含 channel adaptation, 弥补此前 6 个 count_tokens 测试均未触达该分支的盲区 - docs/issue.md 追加档案, 总结根因/防范/同类问题影响 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题概述
后台日志反复出现
POST /v1/messages/count_tokens?beta=true 500 Internal Server Error,伴随AttributeError: 'ZhipuVendor' object has no attribute 'name'。同一时间窗口内大量请求 200 OK、少量 500,呈"间歇性"故障特征。根因分析
src/coding/proxy/server/routes.py:153,160在count_tokens路由中访问target_vendor.name,触发AttributeError返回 500。BaseVendor仅暴露抽象方法get_name() -> str(src/coding/proxy/vendors/base.py:75-77),所有派生类(ZhipuVendor、AnthropicVendor、CopilotVendor、MinimaxVendor、DoubaoVendor、KimiVendor等)均通过_vendor_name类属性配合get_name()返回名称 —— 并无name实例属性。if source:是守卫;source由infer_source_vendor_from_body()启发式推断,仅当请求体出现 zhipu 私有产物(srvtoolu_*id 或server_tool_use块)时返回"zhipu",否则None。纯净的首轮 count_tokens 请求自然绕过 153 行,因此 200/500 共存。变更内容
src/coding/proxy/server/routes.py:将target_vendor.name改为target_vendor.get_name(),并提取局部变量target_name避免重复方法调用、保障日志/调用点一致。tests/test_app_routes.py:新增回归测试test_count_tokens_triggers_zhipu_to_target_channel,通过注入server_tool_use+srvtoolu_*让infer_source_vendor_from_body返回"zhipu",断言返回 200 且 debug 日志含count_tokens channel zhipu → anthropic,反向验证通道被实际触发(避免"未触达分支即通过"的盲点)。docs/issue.md:补充完整 Issue 档案(表因 / 根因 / 处理方式 / 后续防范 / 同类问题影响),沉淀同类问题的处理范式。防范与启示
BaseVendor暴露的方法(get_name()、map_model()等),避免直接访问派生类未定义的"假属性"。grep -rn "vendor\.name\b" src/全仓扫描,确认误用仅 routes.py 的这两处,已一并消除。/v1/messages主链路调用的tier.name是Tier对象的合法 dataclass 属性,不受影响。BaseVendor增加@property name指向get_name(),将契约前移到类型系统由 mypy / pyright 拦截 —— 属"演进式设计"范畴,不在本次最小干预范围内。验证
tests/test_app_routes.py全部 34 用例通过(含新增 1 例)。grep -rn "vendor\.name\b" src/零匹配。