Pre-flight Checklist
🔍 Affected Area
Agent Detection
💡 Problem Statement
The model picker screen (model_picker.go) loads providers exclusively from ~/.cache/opencode/models.json via LoadModels() and then filters them with DetectAvailableProviders(). This cache only contains OpenCode's built-in providers (Google, Anthropic, OpenCode Zen, etc.).
Custom providers defined in ~/.config/opencode/opencode.json under the "provider" key are completely ignored. This affects any user who has configured a custom provider — whether it's an OpenAI-compatible proxy, a self-hosted model, a LiteLLM gateway, or any third-party aggregator. For example:
{
"provider": {
"my-provider": {
"name": "My Custom Provider",
"npm": "@ai-sdk/openai-compatible",
"options": { "baseURL": "https://my-api.example.com/v1" },
"models": {
"model-a": { "name": "Model A" },
"model-b": { "name": "Model B" }
}
}
}
}
When this user runs gentle-ai to configure SDD agents, the model picker only shows the built-in providers. None of the models from "my-provider" appear. This forces users to manually edit opencode.json after running gentle-ai to point agents to their custom provider's models, which defeats the purpose of having an interactive installer.
📦 Proposed Solution
In internal/opencode/models.go, after loading providers from the cache (LoadModels()), also parse the "provider" section from opencode.json (using DefaultSettingsPath()) and merge those custom providers into the map before calling DetectAvailableProviders().
Key changes:
-
New function LoadCustomProviders(settingsPath string) (map[string]Provider, error) — reads opencode.json, extracts the "provider" object, and converts each entry to a Provider struct. Since custom providers use the @ai-sdk/openai-compatible format (with npm, options.baseURL, and a models map), the model entries typically only have name — so tool_call should default to true for all custom models (or be inferred).
-
Merge step in LoadModels() or in the caller (model_picker.go / NewModelPickerState): combine cache providers + custom providers, with custom providers taking precedence on ID collision.
-
Detection logic: For custom providers, since they don't have env vars defined in the same way as built-in providers, they should be considered "available" if they exist in opencode.json (the user has explicitly configured them, so they're authenticated by definition).
Expected behavior after the fix:
gentle-ai shows both built-in providers AND any custom providers from opencode.json
- Users can select models from their custom provider directly in the TUI
- No manual editing needed after running
gentle-ai
🔄 Alternatives Considered
-
Manual config only — current workaround: users run gentle-ai, then manually edit opencode.json to change model values to <custom-provider>/<model-id>. This defeats the purpose of having an interactive installer.
-
CLI flag — add --provider flag to specify a custom provider ID. This adds friction and doesn't solve the discovery problem (users still need to know the exact model IDs).
-
Read OpenCode's runtime model list — hook into OpenCode's internal model resolution instead of the cache file. This would be more accurate but requires deeper integration with OpenCode's internals.
📎 Additional Context
Relevant files:
internal/opencode/models.go — LoadModels(), DetectAvailableProviders() (lines 69-157)
internal/tui/screens/model_picker.go — NewModelPickerState() (line 58 calls LoadModels)
internal/opencode/models.go:20-27 — DefaultSettingsPath() already exists but is unused for provider loading
The DefaultSettingsPath() function already points to ~/.config/opencode/opencode.json, so the infrastructure to read the file is partially there — it just needs to be wired up for provider discovery.
Pre-flight Checklist
status:approved🔍 Affected Area
Agent Detection
💡 Problem Statement
The model picker screen (
model_picker.go) loads providers exclusively from~/.cache/opencode/models.jsonviaLoadModels()and then filters them withDetectAvailableProviders(). This cache only contains OpenCode's built-in providers (Google, Anthropic, OpenCode Zen, etc.).Custom providers defined in
~/.config/opencode/opencode.jsonunder the"provider"key are completely ignored. This affects any user who has configured a custom provider — whether it's an OpenAI-compatible proxy, a self-hosted model, a LiteLLM gateway, or any third-party aggregator. For example:{ "provider": { "my-provider": { "name": "My Custom Provider", "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "https://my-api.example.com/v1" }, "models": { "model-a": { "name": "Model A" }, "model-b": { "name": "Model B" } } } } }When this user runs
gentle-aito configure SDD agents, the model picker only shows the built-in providers. None of the models from"my-provider"appear. This forces users to manually editopencode.jsonafter runninggentle-aito point agents to their custom provider's models, which defeats the purpose of having an interactive installer.📦 Proposed Solution
In
internal/opencode/models.go, after loading providers from the cache (LoadModels()), also parse the"provider"section fromopencode.json(usingDefaultSettingsPath()) and merge those custom providers into the map before callingDetectAvailableProviders().Key changes:
New function
LoadCustomProviders(settingsPath string) (map[string]Provider, error)— readsopencode.json, extracts the"provider"object, and converts each entry to aProviderstruct. Since custom providers use the@ai-sdk/openai-compatibleformat (withnpm,options.baseURL, and amodelsmap), the model entries typically only havename— sotool_callshould default totruefor all custom models (or be inferred).Merge step in
LoadModels()or in the caller (model_picker.go/NewModelPickerState): combine cache providers + custom providers, with custom providers taking precedence on ID collision.Detection logic: For custom providers, since they don't have
envvars defined in the same way as built-in providers, they should be considered "available" if they exist inopencode.json(the user has explicitly configured them, so they're authenticated by definition).Expected behavior after the fix:
gentle-aishows both built-in providers AND any custom providers fromopencode.jsongentle-ai🔄 Alternatives Considered
Manual config only — current workaround: users run
gentle-ai, then manually editopencode.jsonto changemodelvalues to<custom-provider>/<model-id>. This defeats the purpose of having an interactive installer.CLI flag — add
--providerflag to specify a custom provider ID. This adds friction and doesn't solve the discovery problem (users still need to know the exact model IDs).Read OpenCode's runtime model list — hook into OpenCode's internal model resolution instead of the cache file. This would be more accurate but requires deeper integration with OpenCode's internals.
📎 Additional Context
Relevant files:
internal/opencode/models.go—LoadModels(),DetectAvailableProviders()(lines 69-157)internal/tui/screens/model_picker.go—NewModelPickerState()(line 58 callsLoadModels)internal/opencode/models.go:20-27—DefaultSettingsPath()already exists but is unused for provider loadingThe
DefaultSettingsPath()function already points to~/.config/opencode/opencode.json, so the infrastructure to read the file is partially there — it just needs to be wired up for provider discovery.