fix: ask each backend for its own model list - #12
DevMortimer merged 3 commits into
Conversation
listModels() requested the SDK's own /v1/models against the backend's host. Only the judgment path was rewritten, so an OpenRouter client asked for a path that host does not serve: openrouter.ai answers it with its app page and the SDK rejects the body. listModels() could never verify a key on that backend, which is the budget-free way to prove one. The transport wrapper now rewrites the model-list path too, and renames the list to the field the SDK reads when the registry declares another. Both are registry data, so the SDK stays untouched and the TypeSafe backend keeps the caller's fetch exactly as before. Closes DevMortimer#11
DevMortimer
left a comment
There was a problem hiding this comment.
Thanks, the path rewrite and field rename look right, and the TypeSafe backend is untouched. Two things to fix in this branch before merge:
-
A bad OpenRouter key now gets recorded as verified. OpenRouter's
/api/v1/modelsis public, solistModels()succeeds with any key, and the success path callsrecordAuthVerified(). After this PRauthState({ backend: "openrouter" })reportsverified: truefor a missing or garbage key. Before, that path was unreachable for OpenRouter. Please skip the verified write when the backend's models endpoint does not check the key, for example an optional flag onBackendConfig, and narrow the "listModels()verifies the key" line indocs/api.mdto match. An offline test that OpenRouterlistModels()leaves the auth state unverified would cover it. -
Return model ids, not display names. Please handle the limitation you noted here rather than separately: OpenRouter entries carry
id, which is whatmodel:accepts, whilenameis a label. HavelistModels()return usable ids for OpenRouter, and keep the TypeSafe backend's output unchanged.
Review feedback on the model-list change. openrouter.ai serves /api/v1/models to anyone, so a success there says nothing about the key. Recording it as verified would report a missing or garbage OpenRouter key as good, which the unreachable path never did. The registry now says whether a list checks the key, and only a list that does writes the verification record. OpenRouter entries carry the id that `model:` accepts and a display name, so the entry's id is promoted to the name listModels() returns. The TypeSafe backend declares neither and is unchanged.
|
Both fixed in 1. A public list no longer records verification. 2.
|
DevMortimer
left a comment
There was a problem hiding this comment.
Both points addressed. Verified locally on 94273b5: build, typecheck, 100 tests pass; OpenRouter listModels() leaves the auth state unverified and returns ids.
What and why
Closes #11.
listModels()asked every backend for the SDK's own/v1/models, because the transport wrapper only rewrote the judgment path. An OpenRouter client therefore requestedhttps://openrouter.ai/v1/models, which answers with the app's HTML page, and the SDK rejected the body. SolistModels()could never verify a key on that backend — the documented way to prove one without spending the request budget.Change
BackendConfiggainsmodelsPath?andmodelsField?;DECISIONS_BACKENDS.openrouterdeclares/api/v1/modelsanddata.modelsfield the SDK reads. A body without the declared field is passed through unchanged, so the SDK still reports its own shape error rather than a masked one.fetchexactly as before.docs/api.mddocuments the two fields.Verification
npm ciandnpm run checkpass: build, typecheck, 99 offline tests, three of them new.fetch: the URL each backend is asked for, the renamed envelope, the pass-through when the declared field is absent, and that a TypeSafe response is never renamed.docs/api.mdupdated.Live testing: this touches the transport, so I checked the changed path against the real endpoint. With
backend: "openrouter",listModels()returns 454 models fromhttps://openrouter.ai/api/v1/models. That endpoint is public, so the check sent no key. I did not runnpm run test:live: it bills a request against a TypeSafe key and I do not have one.Compatibility and release notes
BackendConfig, both documented. No export added or removed, and no behavior change forbackend: "typesafe"or for a caller that omitsbackend.Xiaomi: MiMo-V2.6-Pro-UltraSpeed), not the model ids thatmodel:accepts. Every entry carries anameand the longest is 56 characters, so the existing 100-character filter drops none.