Custom pi-ai routes lose catalog-known modalities — inheritance is keyed by provider route, not model id #1992
Replies: 1 comment
|
Confirmed at source level and implemented as a cherry-pick-ready branch. Source audit (master 47f9438)
Patch: fix/pi-ai-catalog-model-id-inheritancehttps://github.com/zoahdev/deepseek-harness/tree/fix/pi-ai-catalog-model-id-inheritance
Verification
This also unblocks the #1986 family (image sessions switching to custom routes) for pi-ai-backed gateways. Thanks for the precise root cause - the "inheritance keyed by provider route, not model id" framing made the fix one line plus a cache. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Setup
A custom OpenAI-compatible route fronted by a translation proxy (sub2api) that serves genuine upstream model ids. The route key is a private one, so every model entry is hand-declared with just an id:
Symptom
selectModelrefuses with "Model ... does not accept image input, but this session already contains images; select an image-capable model."promptwithMODEL_DOES_NOT_SUPPORT_IMAGES→ "当前模型不支持图片,请切换支持图片的模型".Both gates live in
packages/host/apiproxy/src/api-proxy.tsand callctx.llm.resolveModelInfo(provider, model).Root cause
resolveRouteModelsinpackages/llm/llm-pi-ai/src/catalog.tsresolves input modalities as:where
base = catalogModels(provider).get(entry.id)andcatalogModels(provider)indexes the installed catalog by the provider route key. A hand-declared route key that pi-ai does not ship yields an emptydefaultsmap, so even model ids the installed catalog fully describe inherit nothing and fall through toDEFAULT_INPUT = ['text'](packages/llm/llm-pi-ai/src/config.ts).The part that stings: with pi-ai 0.82.1, the generated catalog already knows these ids —
MODELS['openai']['gpt-5.6-sol'](and every other gpt-5.x) recordsinput: [text, image]withcontextWindow: 272000. The information is present in the very package the adapter imports; only the route-key indirection loses it. Nothing interrogates the gateway, which is a deliberate posture — but here the answer is already local.For contrast: routes whose key happens to match an installed catalog provider inherit modalities per model id, which is why one settings file can work for those routes and break only for the hand-declared key.
Workaround (works today, hot-reloads)
defaultInput: [text, image]covering every undeclared model on the route, orinput: [text, image], oropenaiso it becomes a catalog route (keeps the custombaseURL) — at the cost of the custom display name, and non-catalog entries (e.g.gpt-image-*) still fall back.Suggestion
For hand-declared routes (route key not shipped by the installed catalog), add one model-id-keyed inheritance layer between
base?.inputandroute.defaultInput:input— and possiblycontextWindow/maxTokens/ reasoning capability — as the next resolution layer;This keeps the conservative
['text']floor for genuinely unknown models — under-claiming refuses an image up front and names the model, while over-claiming gets rejected mid-turn after the message is durable — while proxies serving genuine upstream model ids keep the correct modalities for free.Related: #356 covers the same admission gate for hand-declared models in general; this discussion is the narrower case where the installed catalog already knows the exact model id and the route-key indirection is the only thing dropping it.
All reactions