Repository navigation
Conversation
…ve catalog For a custom OpenAI/Anthropic-compatible node PROVIDER_MODELS is empty, so rawModelIds came out empty and /v1/models fetched the upstream's entire catalogue and merged it into the listing. The user's own model list, managed in the dashboard and stored as customModels, was only merged afterwards — so deleting a model there had no effect: the live fetch put it straight back. Compute customModelIds before the fallback and skip the fetch when the provider already has curated models. Providers with nothing configured still fall back to the live catalogue, and skipDynamicFetch is unaffected. Fixes decolua#3115
…olua#3486) Individual models carry context_length and max_completion_tokens; combo entries were built as bare { id, object, owned_by } and skipped them. A client that sizes its context window off /v1/models therefore fell back to guessing from the model name, and guessed against a pool whose members can be far wider - a 1M pool read as deepseek 128k, compacting at ~96k. Emit the same two snake_case fields on combo entries. A request routed to a combo can land on any member, so the pool can only promise what its smallest member accepts: take the minimum across members. A member that reports no usable number is skipped rather than read as zero, and when no member reports one the field is omitted entirely - an absent field lets the client fall back, a wrong one does not. Web-search and web-fetch combos are untouched: they are not chat models and carry no window. The alias-to-provider map the DB-unavailable branch already built is hoisted so the combo loop can share it, rather than building a second.
…ecolua#3467) The three self-hosted providers read their endpoint from providerSpecificData.baseUrl, and their own registry entries tell the user to set it: text: "Set providerSpecificData.baseUrl to the server root, e.g. http://host:8080 — /v1/audio/speech is appended." The dashboard never rendered a field for it. Every connection created through the UI was therefore saved without one and fell back to the built-in localhost default — which inside Docker is the 9router container itself, so a separately hosted server is unreachable and nothing says why. The modal did have such a field, but it was hardcoded to one provider: const isOllamaLocal = provider === "ollama-local"; {isOllamaLocal && <Input label="Ollama Host URL" ... />} Make it declarative instead. A provider whose endpoint is per-connection now says so in its registry entry: baseUrlField: { label, placeholder, help } and the modal renders whatever the registry declares. ollama-local moves onto the same mechanism rather than keeping a second one beside it, with its label and placeholder preserved exactly. The placeholders are each provider's real fallback, so the box shows what the connection would otherwise use. buildProviderSpecificData moves into src/shared/utils so the saved shape can be tested without rendering. An empty box still saves nothing: it means "keep the default", not "save an empty endpoint".
23c9a8a to
ed8069b
Compare
|
Rebased onto One commit came out of the bundle: Three commits remain:
The conflict in
|
Four provider/model-catalog fixes that were sitting in separate PRs (#3330, #3252, #3529, #3539), rebased onto current
master. Independent commits.fix(auth)(#3262)fix(models)(#3115)/modelsfetch, so the catalog came back with the provider's full list instead of the operator's selectionfeat(models)(#3486)/v1/modelsreported no token limits, so clients sizing a request against a combo had nothing to readfix(providers)(#3467)The
#3115commit reads as larger than it is: most of it is one block moved earlier inbuildModelsListso thatcustomModelIdsexists before the dynamic-fetch decision. The behavioural change is the added&& customModelIds.length === 0on that condition.Verification
Run with vitest 3 and the repo config — both parts matter:
Without
--configthe@/alias does not resolve (Failed to load url @/lib/dataDir.js). And vitest 2.x cannot run anything that reachesopen-sse/translator/index.js: it throwsTypeError: register is not a functionat the top-levelregister(...)calls, becauseindex.jsdeliberately relies on function-declaration hoisting to survive the import cycle while Vite 5's SSR transform turns the named import into a call-time property access. I confirmed that failure on cleanmasterand onmasteras of 15 Aug, so it is not caused by these changes.Every fix was checked by reverting it and confirming which test dies. No claim here rests on a test that passes for another reason.