Skip to content

fix(llm-pi-ai): 目录路由的模型发现改为合并线上清单 - #309

Open
FudanSE-Nick wants to merge 1 commit into
dataelement:mainfrom
FudanSE-Nick:fix/opencode-go-model-discovery
Open

fix(llm-pi-ai): 目录路由的模型发现改为合并线上清单#309
FudanSE-Nick wants to merge 1 commit into
dataelement:mainfrom
FudanSE-Nick:fix/opencode-go-model-discovery

Conversation

@FudanSE-Nick

Copy link
Copy Markdown

问题

设置页「获取可用模型」对 pi-ai 内置目录路由(如 OpenCode Go)永远不发网络请求,只回放打包时烤死的静态快照。订阅网关在 pi-ai 两次发版之间新增的模型因此永远无法出现 —— 而这正是用户点这个按钮的目的。

实测对比(本机 pi-ai 0.84.3,快照生成于 2026-08-24):

来源 模型数
内置快照 23
https://opencode.ai/zen/go/v1/models 实时 35

glm-5.3-flashgrok-4.6omen-alphaqwen3.8-flashmuse-spark-1.3-contributor 等 13 个,同时还保留着线上已下架的 ox-alpha-free

升级 pi-ai 治不了根:0.84.4 是 25 个、0.85.0 是 27 个,仍落后线上。静态快照跟 npm 发版走,而网关随时上新,结构上追不上。

第二层问题更隐蔽:即便用户手动把新模型写进 settings.yaml 也用不了。 resolveRouteModels 依赖 sharedCatalogApi 的「全体一致」判断为快照外模型补 api,而 opencode-go 横跨三种协议(Completions 19 / Responses 3 / Anthropic Messages 1),该判断返回 undefined,整条路由解析失败:

llm-pi-ai: provider "opencode-go" model "omen-alpha" needs an api;
the installed catalog does not describe it, so set the route's api to ...

唯一出路是设路由级 api,但它覆盖所有同级模型,反而弄坏另外两种协议的。

改动

两层一起修,均在 patches/@deepseek-ai+dsh-llm-pi-ai+0.1.2-rc.1.patch(沿用仓库既有的 patch-package 约定,与原有的 401/403 分类 hunk 合并在同一文件)。

发现discoverModels):目录路由现在同时读快照与自身端点并合并。快照携带清单不披露的容量,因此两边都描述某模型时快照优先;端点顺序决定新模型的位置。端点不可达、凭据被拒、协议无可读清单时仍回落到快照 —— 离线可用是这个动作原有的能力。调用方主动取消(ABORTED)不会被回落成陈旧列表。

解析resolveRouteModels):sharedCatalogApi 换成 catalogEndpoint,按多数而非全体一致得出协议及其配套 baseUrl。多数协议下的新模型自动继承端点;少数协议的同级模型仍各自保留自己的 api/baseUrl

一处需要评审关注的取舍

按多数推断协议有猜错的可能。但备选方案是「路由无法添加任何新模型,除非设路由级 api 弄坏同级模型」。猜错的代价是该模型首次使用时被端点明确拒绝、有名有姓、可恢复;两害相权取其轻。如果维护者倾向别的方案(例如给 models 条目增加 per-model api 字段),我乐意改。

草稿值、路由级 api/baseURL、以及目录未描述的自定义路由行为均保持不变。

测试

修改前先在未改动的源码上验证 bug 真实存在(发现返回 5 个 / 0 次网络调用 / 0 个线上新模型;解析抛 needs an api),确认修复后行为反转。

新增 test/model-discovery-catalog-patch.test.ts(4 项,已精简至只覆盖核心行为与上述取舍的护栏):

  • 能报出快照外的网关模型,且快照容量优先
  • 端点不可达时回落到快照
  • 快照外的模型可被解析(原本直接失败)
  • 少数协议的同级模型不被拖到多数协议上

验证结果:

  • npx vitest run85 文件 / 704 项全通过
  • npx tsc --noEmit -p tsconfig.node.json → 通过
  • npx patch-package → 20 个补丁全部干净应用
  • 本地打包 dev dmg(arm64)并挂载核验,产物内 catalogEndpoint/listEndpointModels 就位、sharedCatalogApi 已移除

备注

未改动 package.jsonoverridespackage-lock.json 把 pi-ai 锁在 0.84.4,钉版本只能把差距从 13 个缩到 8 个,本 PR 之后版本落差已不再影响此功能。

#284(0.7.1 后点击无反应)不是同一问题,未做关联。

「获取可用模型」对 pi-ai 内置目录路由(如 OpenCode Go)永远不发网络请求,
只回放打包时的静态快照,因此订阅网关在 pi-ai 两次发版之间新增的模型永远
无法出现——而这正是用户点这个按钮的目的。实测 opencode-go 快照为 23 个模型
(pi-ai 0.84.3,生成于 2026-08-24),而 https://opencode.ai/zen/go/v1/models
实时返回 35 个,缺 glm-5.3-flash、grok-4.6、omen-alpha、qwen3.8-flash 等
13 个,同时还保留了线上已下架的 ox-alpha-free。

即便手动把新模型写进 settings.yaml 也无法使用:resolveRouteModels 依赖
sharedCatalogApi 的「全体一致」判断来为快照外的模型补 api,而 opencode-go
横跨三种协议,该判断返回 undefined,于是整条路由解析失败并报
「model "…" needs an api」。唯一的出路是设置路由级 api,但它会覆盖所有同级
模型,反而弄坏另外两种协议的模型。

两层一起修:

- 目录路由现在同时读取快照与自身端点,二者合并。快照携带清单不披露的容量,
  因此在两边都描述某模型时快照优先;端点顺序决定新模型的位置。端点不可达、
  凭据被拒、协议无可读清单时仍回落到快照——离线可用是这个动作原有的能力。
  调用方主动取消(ABORTED)不会被回落成陈旧列表。
- sharedCatalogApi 换成 catalogEndpoint,按「多数」而非「全体一致」得出协议
  及其配套 baseUrl。多数协议下的新模型因此能自动继承端点,而少数协议的同级
  模型仍各自保留自己的 api/baseUrl,不会被拖到多数协议上。

按多数推断有猜错的可能,但备选是路由无法添加任何新模型,除非设路由级 api
弄坏同级模型;猜错的代价是该模型首次使用时被端点明确拒绝、有名有姓、可恢复。

草稿值、路由级 api/baseURL、以及目录未描述的自定义路由行为均保持不变。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant