Repository navigation
Conversation
There was a problem hiding this comment.
The server side of the fix works. Run from source, the base rejects a providers-only config patch with 400 (Missing key ["shell"]), and the form always throws provider.custom.unavailable. With this change the same credential + config patch writes the provider to the global JSONC (comments and other keys kept, no key in the file), and the provider and model show up as enabled in /api/provider and /api/model within a few seconds. The credentials tests and the server config test pass, and app, core, schema and client typecheck. I didn't drive the desktop/web form itself, so the UI part relies on your screenshots and the unit tests.
Public API impact, all backwards compatible:
Config.Patch/PATCH /api/experimental/config:shellgoes from required to optional. A new optionalprovidersrecord (ConfigProvider.Infoby ID) replaces each named entry in the global document.@opencode/client:config.update(input)becomesconfig.update(input?), andConfigUpdateInputgainsproviders. The effect client now exportsConfigProvidertypes.- Existing callers that send
{ shell }keep working.
Concerns are inline: the 10s polling loop in the form, duplicate credentials when retrying after a 'saved but not loaded' result, and the size and timing dependence of the new server test. For maintainers: #52653 took the same approach (native provider config plus a separate credential) and was closed without a comment, so whether this design is wanted is worth confirming.
| return output.result | ||
| } | ||
|
|
||
| const refresh = async (providerID: string, modelIDs: string[]) => { |
There was a problem hiding this comment.
The form re-reads the catalog every 250 ms for up to 10s, waiting for the server's debounced reload after the write. This ties the UI to server reload timing: a slow or large config reload shows 'saved, but its models could not be loaded' even though nothing is wrong. Could Config.update wait for the reload it requests (or the endpoint answer only once the new config is applied)? Then the form could refresh once instead of polling.
| */ | ||
| export async function saveCustomProvider(api: ServerApi, provider: CustomProvider) { | ||
| const credential = provider.key | ||
| ? await api.credential.create({ |
There was a problem hiding this comment.
When the write succeeds but the models never load, the dialog closes and the provider is not in data.location.provider.list(). If the user opens the form again with the same ID, the duplicate check passes, a second credential is created for the same integration and the config entry is overwritten. Could the save reuse or replace an existing credential for providerID, or the duplicate check also look at the config/integration?
| ) | ||
|
|
||
| it.live( | ||
| "saves a custom provider that becomes a selectable provider and model", |
There was a problem hiding this comment.
This test is about 160 lines, runs the real file watcher and polls for up to 15s across several endpoints, so it is slow and timing-dependent. The core behaviour is "a providers patch keeps unrelated JSONC and replaces just the named entry", which could be a short test like the existing shell one. The catalog/integration round-trip could be dropped or cut down to one check.
Issue for this PR
Closes #50650
Type of change
What does this PR do?
Restore custom OpenAI-compatible provider setup in the current integration picker and fix the failed submission reported in #50650. Save the provider definition in global JSONC while preserving other settings. Store literal API keys through the credential API and clean them up if the config write fails.
Wait for the configured models to load before reporting a connection. Rejected writes keep the form available to retry; saved configurations whose models do not load get a separate message.
How did you verify your code works?
bun run check: lint and all 35 package checks passed. App and clientbun run typecheck:tscalso passed.bun run check:generated: regeneration produces no diff.The fully parallel settings suite passed 46/53. All seven shortcut/activity-layout failures also reproduced on unmodified
devat86ce19d96e.Visual
Screenshots / recordings
Captured with local test fixtures. The before image shows the reported failure; the after image shows the saved model in the current picker.
Checklist
Added by the opencode bot (AI-generated).
Related: #51527, #57365, #51031, #57325
Public API: makes
shelloptional and addsprovidersto thePATCH /api/experimental/configpatch (andconfig.updatein @opencode/client); backwards compatible