fix(desktop): onboarding can configure a local/custom endpoint without an API key - #38572
Merged
Conversation
The runtime resolver reads model.base_url from config and ignores the OPENAI_BASE_URL env var, so a self-hosted endpoint could not be configured from the GUI. Two changes enable it: - POST /api/model/set accepts an optional base_url and persists it as model.base_url when provider=custom (still clearing stale base_url for hosted providers). - POST /api/providers/validate now returns the model ids a custom endpoint advertises at /v1/models, so the GUI can auto-pick a default without asking the user to type a model name. Refs desktop onboarding "Local / custom endpoint" bug.
…I changes Onboarding's "Local / custom endpoint" only wrote the OPENAI_BASE_URL env var, which runtime resolution ignores — so a self-hosted endpoint was never wired in and setup failed with "No usable credentials found for custom" even though local servers need no key. Route the local option through saveOnboardingLocalEndpoint: probe the endpoint, auto-discover a model from /v1/models, persist provider=custom + base_url + model via /api/model/set, then verify the runtime directly (not via completeWithModelConfirm, which would re-assign the model without base_url and wipe it). No onboarding form/UI changes — the existing single URL field is enough.
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-attribute |
1 |
First entries
tests/hermes_cli/test_web_server.py:1128: [unresolved-attribute] unresolved-attribute: Attribute `get` is not defined on `None` in union `Any | None`
✅ Fixed issues: none
Unchanged: 5050 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
1 task
This was referenced Jun 8, 2026
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.
Summary
Desktop onboarding's "Local / custom endpoint" option now actually works, including the common no-API-key case (vLLM, llama.cpp, Ollama). No onboarding UI changes — the existing single URL field is reused.
Root cause: the local option only wrote the
OPENAI_BASE_URLenv var, but runtime resolution deliberately ignores it —model.base_urlin config.yaml is the single source of truth. And/api/model/setactively clearedbase_url, so the GUI had no way to persist it. Resolution fell through to the default provider and reported "No usable credentials found for custom".Changes
hermes_cli/web_server.py:POST /api/model/setaccepts an optionalbase_urland persistsmodel.base_urlforprovider=custom(clears it for hosted providers, unchanged).POST /api/providers/validatereturns the model ids advertised at/v1/models(tolerant_parse_model_idsfor OpenAI/vLLM/llama.cpp shapes) so the GUI auto-picks a default.apps/desktop/src/store/onboarding.ts: local option routes throughsaveOnboardingLocalEndpoint— probe endpoint, auto-discover model, persistprovider=custom+base_url+model, verify runtime. AvoidscompleteWithModelConfirm, which would re-assign the model without a base_url and wipe it._parse_model_ids/ base_url persistence; frontend onboarding store).Validation
provider=custom+ base_url, no keyapi_key=no-key-required,api_mode=chat_completionsset_model/parse_model_ids)E2E verified with a fake no-key OpenAI-compatible endpoint in an isolated HERMES_HOME with all credential env vars unset. Negative control (no base_url) reproduces the exact pre-PR error.
Salvage of #38265 by @xxxigm — both commits cherry-picked onto current main with authorship preserved. Closes #38265.
Infographic