Conversation
added 2 commits
September 7, 2026 00:06
GET /provider always builds the full models.dev catalog, which is what the model picker needs and nothing else does. A client that only renders the currently selected model pays for the whole snapshot on every call. Add an optional `connected` query parameter. With `connected=true` the handler answers from `Provider.list()` alone and never touches the catalog or the config filter. The parameter is optional and defaults to the existing behavior, so current clients are unaffected.
The bootstrap fetched the full provider list on every start, for the global scope and once more per project directory. Only the model picker needs the models.dev catalog, and it is identical for every directory. Request the connected providers during bootstrap and pull the catalog once, a few seconds later, into the same cache entry. `loadProvidersQuery` defaults to connected-only because every consumer shares its key: one that mounts before the bootstrap has written its result would otherwise fetch the full catalog on its own and undo the saving. The catalog is written through `setQueryData` rather than `fetchQuery`, which would rewrite the stored query options and leave the entry permanently stale.
Contributor
|
The following comment was made by an LLM, it may be inaccurate: I found one potentially related PR: Related PR:
The current PR (#47678) takes a more targeted approach by adding a No other duplicate PRs found addressing the same feature. |
This branch has not been deployed
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.
Issue for this PR
Closes #47677
Type of change
What does this PR do?
GET /provideralways builds the full models.dev catalog. In the HTTP API test harness oncurrent
devthat response is 4,168,456 bytes and takes ~1.5 s; the connected providers in thesame instance are 4,468 bytes. The catalog is 99.9% of the payload, and only the model picker
needs it.
The app bootstrap asks for it anyway, once globally and once per project directory, and
loadProvidersQueryhas nostaleTime, so any consumer mounting before the bootstrap result iswritten fetches it again.
Two commits:
Server. An optional
connectedquery parameter onGET /provider. Withconnected=truethehandler answers from
Provider.list()and never reads the models.dev snapshot or the configfilter, so none of the expensive work happens. The parameter is optional and the default path is
untouched, so existing clients see no change. One deliberate difference in the connected view: the
full response also reports catalog providers that only have stored credentials, which cannot be
resolved without the catalog; they appear once the caller fetches it.
Client. The bootstrap requests the connected providers, then pulls the catalog once, three
seconds later, into the same cache entry.
loadProvidersQuerydefaults to connected-only onpurpose — every consumer shares the query key, so leaving the full catalog as the default means a
single early consumer pulls all of it and the saving is gone. The catalog is written with
setQueryDatarather thanfetchQuery, becausefetchQueryrewrites the stored query optionsand a
staleTimeoverride there leaves the entry permanently stale, making every consumer refetch.Only the global entry warms the catalog; it is identical for every directory, so warming per
directory would pull the same payload once per project.
How did you verify your code works?
Measured in the HTTP API test harness, same instance, both endpoints:
New regression test in
packages/opencode/test/server/httpapi-provider.test.ts: the connected viewis non-empty, strictly smaller than the catalog, a subset of it, and lists exactly the providers it
returns. Verified that it fails without the change — with the early return disabled the catalog and
the connected view both return 159 providers and the size assertion fails.
New regression test in
packages/app/src/context/global-sync/bootstrap.test.ts: the query asks for{ connected: true }by default and for the full catalog only when explicitly requested.bun test test/server/httpapi-provider.test.tsinpackages/opencode: 6 pass, 1 skip, 0 failbun test --conditions=solid --preload ./happydom.ts src/context/global-sync/bootstrap.test.tsinpackages/app: 11 pass, 0 failtsgo --noEmitinpackages/opencode: cleantsgo -binpackages/app: cleanprettier --checkon all changed files: cleanoxlinton the changed files: 5 warnings, all present ondevbefore this changeThe SDK and OpenAPI changes are the output of
bun ./script/generate.ts.Not measured: startup wall-clock in a packaged desktop build. The numbers above are payload size
and handler time from the test harness.
Screenshots / recordings
Not a UI change.
Checklist