Repository navigation
Conversation
- Fetch models from OpenAI-compatible providers with baseURL in config - Support plugin-registered discovery loaders (e.g., GitLab) - Discovery runs synchronously during bootstrap init - Remove providers with no models after successful discovery - Add tests for discovery and model registration
- Extract discoverProviderModels() helper from inline 110-line Effect.gen - Replace globalThis.fetch with HttpClient layer (FetchHttpClient) - Add Effect.timeout(10s) to HTTP discovery requests - Replace Exit._tag with Exit.isSuccess/IsFailure - Remove redundant config.get() in init() (use captured s.cfg) - Remove unnecessary 'as any' casts - Fix indentation to consistent 2-space - Set family: 'discovered' on discovered models - Update discovery tests to use HttpClient layer mocks
|
The following comment was made by an LLM, it may be inaccurate: Potential Duplicate PRs FoundBased on my search, I found several related PRs that may be addressing similar or overlapping functionality:
These PRs should be reviewed to determine if they:
I recommend checking PR #27554, #19959, #28973, and #29392 in particular, as they appear most directly related to auto-discovering models from providers. |
Here's how this PR differs from each referenced PR: #27554 (#27554) (androidand) — Solves a broader problem: LAN-level provider discovery (mDNS, subnet scanning, TCP probing) plus model discovery. This PR is scoped specifically to config-file-driven model discovery for already-configured providers, using the Effect HttpClient layer instead of raw Promise.all/fetch. The discoverModels: false opt-out and warning logs for config-vs-discovered limit mismatches are not present in that PR. #32170 (#32170) (MohammadMD1383) — Adds a single hardcoded OmniRoute provider with its own auth plugin. It doesn't apply to arbitrary user-configured OpenAI-compatible endpoints, doesn't parse context/output limits, and has no opt-out mechanism. #19959 (#19959) (hmblair) — A ~50-line proof-of-concept for a single hardcoded "local" provider with an autoload boolean return. Doesn't support multiple providers, doesn't parse limits, doesn't filter Models.dev, and has no opt-out or warning logs. #28973 (#28973) (Thibaultjaigu) — Specific to Requesty only (hardcoded URL). Solves the user-specific routing policies problem, not general OpenAI-compatible endpoint discovery. #29392 (#29392) (dasdkslkd) — Closest in concept but orthogonal: adds a runtime UI flow for adding/removing custom providers through the app. Doesn't parse limits, doesn't filter Models.dev, has no opt-out, and doesn't use the Effect HttpClient layer. This PR's differentiating aspects are:
|
…nai-compatible schemas - Log warning and continue when provider disappears between discovery snapshot and apply - Add @ai-sdk/openai-compatible to schema sanitization check - Add test case for openai-compatible schema sanitization
|
@sethjones anyway we can add this? We have now had over 445 users complain about this issue. |
I'm not sure how to get the team to prioritize / respond versus what I've done already with making sure it's ready and linked. |
…anomalyco#32731) Merge PR anomalyco#32731 by sethjones into dev branch. Auto-discovers available models from OpenAI-compatible providers that have a baseURL configured. opencode now calls GET /v1/models at startup and populates the model list from the provider API. Features: - discoverModels: false opt-out per-provider - Parses context_length and max_output_tokens from API - Warning logs for discovery failures and config limits exceeding discovered limits
…roviders (anomalyco#32731)" This reverts commit aad7116, reversing changes made to dfeb1b5.
…viders
A configured provider can opt in (discover: true, or the v1 config's
discoverModels: true) to have opencode call GET {baseURL}/models and
add whatever the endpoint reports to the catalog, instead of
requiring every model to be hand-listed -- useful for LM Studio,
vLLM, llama.cpp/llama-swap, or any generic OpenAI-compatible
self-hosted endpoint.
Ported from upstream anomalyco#6231 (247 reactions/57
comments -- the second-highest reaction count found across a full
survey of this repo's open issues). Three substantial PRs sat open
and unmerged for 3+ months despite that reaction count. PR anomalyco#32731 (8
files, tightly scoped) is the primary source: this fork reuses its
discoverModels field name, which limit fields to read from the
response, the discovered-model shape, and the "configured/models.dev
wins" merge rule. Deliberately changed from anomalyco#32731: discovery is
opt-in per provider here, not automatic for every provider with a
baseURL -- always-on would fire a startup network request at every
existing custom provider. Unknown limits are left at 0 rather than
anomalyco#32731's guessed 128k default. PR anomalyco#42660's URL-with-existing-path
handling was reused, rewritten with this repo's own HttpClient/Schema
idioms instead of raw fetch in a try/catch; its UI and endpoint
weren't ported. PR anomalyco#27554 (100+ files) had nothing usable beyond
confirming scope overlap. New, since none of the three PRs target it:
a v2 Catalog.Service plugin (this repo didn't have a plugin/catalog
system when those PRs were written).
Runs in both of this repo's provider surfaces: the legacy provider
service (inline before the filter pass, what the TUI model picker
reads) and a new v2 Catalog plugin (packages/core/src/config/plugin/
provider-discovery.ts, once at startup then hourly, same schedule as
the models.dev refresh).
Known gaps: the legacy provider service has no periodic refresh (a
newly-loaded local model appears only after restart/reload); stale
models aren't hidden; discovered capabilities are guesses (no
vision/reasoning detection); only the standard OpenAI models response
shape is understood, not Ollama's native /api/tags; no settings UI or
HTTP endpoint; legacy auth only checks a stored credential or
options.apiKey, not plugin OAuth loaders.
New packages/core/test/provider-discovery.test.ts + config/
provider-discovery.test.ts (unit-level) and packages/opencode/test/
provider/discovery.test.ts (against a real local Bun.serve server,
not a mock). Verified against this fork's current dev, not just the
agent's own stale worktree base: bun typecheck clean across all 30
packages; packages/core 1187 pass (only the pre-existing pty flake);
packages/opencode 3617 pass, only the 4 pre-existing cf-ai-gateway
failures. bun run generate from packages/client correctly produced
no changes -- this is a config-only field, not a Protocol/HttpApi
schema change.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Issue for this PR
Closes #6231
Type of change
What does this PR do?
Auto-discovers available models from OpenAI-compatible providers that have a
baseURLconfigured inopencode.json. Instead of requiring users to list every model manually, opencode now callsGET /v1/modelsat startup and populates the model list.Models come from three sources: Models.dev (metadata), config file (overrides), and the provider API (actual availability). A model is visible only if the provider API returns it or it is declared in config. Metadata is merged with API > config > Models.dev precedence.
This means providers like LM Studio, Ollama, and self-hosted OpenAI-compatible servers automatically show their loaded models without any per-model configuration.
New in this iteration:
discoverModels: falseopt-out — SetdiscoverModels: falseat the provider top level to skip discovery entirely. Useful when you want to manage models exclusively through config or Models.dev.{ "provider": { "my-local": { "npm": "@ai-sdk/openai-compatible", "discoverModels": false, "options": { "baseURL": "http://localhost:8080/v1" } } } }Context & output limits from API — Discovery now parses
context_length(ormax_context_length) andmax_output_tokensfrom the provider API response and applies them to discovered models. Config-defined limits always take precedence.Warning logs — Discovery failures (timeout, network error, non-2xx status, JSON parse failure) now emit
Effect.logWarningwith provider ID and reason. Additionally, when config-defined limits exceed the discovered limits, a warning is logged so users know their config may cause runtime failures.How did you verify your code works?
baseURL/modelslist without manual per-model configbun typecheckfrompackages/opencode— passesChecklist