Parent
Part of #705.
Summary
Goose model availability should not be kept current by scraping goose configure. Goose has provider-aware model discovery internally, but the installed CLI does not expose a stable non-interactive model-list command equivalent to opencode models [provider]. Kai should define a Goose-specific discovery strategy that respects Goose's provider-native model names, keeps direct /model <id> available, and avoids expanding provider scope just because Goose documents many providers.
Current state
Kai's Goose backend runs goose acp --with-builtin developer for conversational sessions and injects model selection through GOOSE_MODEL and provider selection through GOOSE_PROVIDER.
Goose one-shot calls use goose run -i - with --provider <provider> and --model <model> overrides. Kai translates its deepseek provider key to Goose's wire-level custom_deepseek provider name.
For /models, Goose currently delegates to Kai's provider model surface. Curated providers get PROVIDER_MODELS; open-ended providers fall back to text entry. This means Goose inherits static provider lists even though Goose itself has provider internals that can fetch or enumerate models.
Goose model names are provider-native bare model IDs, not OpenCode-style provider/model strings. For example, Goose-on-DeepSeek uses deepseek-v4-pro, while OpenCode-on-DeepSeek uses deepseek/deepseek-v4-pro.
Problem
Goose is similar to OpenCode in that providers sit under the backend, but the available discovery surface is different. OpenCode exposes opencode models [provider]; Goose does not currently expose a comparable non-interactive goose models [provider] command.
Goose's interactive configure flow does fetch models, but that flow is not a runtime API. Scraping or driving goose configure from Kai would couple Telegram model selection to terminal UI prompts, spinner output, and configure-side persistence behavior. That is brittle and would be unpleasant to debug. The technical term is "no."
Using Goose's bundled provider catalogs as the only source of truth is also unsafe. Some Goose providers fetch live endpoints, while declarative providers can fall back to bundled static lists. For DeepSeek, the bundled declarative provider still lists legacy aliases such as deepseek-chat and deepseek-reasoner, which are exactly the kind of stale names Kai should avoid presenting as the current picker surface.
Research notes
Local verification against Goose 1.38.0 showed no top-level model catalog command. The available CLI surfaces include configure, info, run, acp, serve, session, and other operational commands.
goose run --help documents --provider <PROVIDER> and --model <MODEL>, with the model required to be supported by the specified provider. This matches Kai's current one-shot integration shape.
goose info --check reads provider configuration from Goose config or GOOSE_PROVIDER; it reports provider status but does not list supported models.
Goose source shows configure.rs creating a temporary provider and calling fetch_recommended_models(...) before presenting an interactive model selector. That confirms model discovery exists inside Goose, but not as a stable non-interactive CLI contract.
Provider source differs by provider. Anthropic and OpenAI provider implementations fetch live model endpoints. Ollama fetches local tags. Declarative providers can carry static model lists and may fall back to those lists when dynamic fetching is disabled or unavailable.
Relevant sources:
Desired behavior
Kai should treat Goose model discovery as Goose-specific, not as a copy of OpenCode discovery.
If Goose later exposes a stable non-interactive model catalog command, Kai should prefer that command and run it under the same effective OS user and environment used for Goose execution.
Until that exists, Kai should use provider-native discovery for active Goose provider surfaces where reliable provider APIs exist, while preserving Goose's model-name shape. OpenAI models remain bare OpenAI model IDs, Anthropic models remain Claude IDs or accepted aliases, Google models remain Gemini IDs, and DeepSeek models remain bare DeepSeek model IDs.
Direct /model <id> should remain available for Goose even when a model is not present in the picker, because Goose can validate support at runtime and operators may need to pin a model before Kai's discovery path has refreshed.
Discovery failure should not break Goose model selection. Kai should keep the previous static or text-entry behavior available and surface a clear message about the failed discovery source.
Scope
- Define a Goose model discovery adapter that does not call or scrape
goose configure.
- Preserve Goose's provider-native model ID shape for every discovered model.
- Evaluate provider-native discovery for active Goose provider surfaces, using the provider source of truth rather than Goose's bundled static catalog when the bundled catalog is known to be stale or incomplete.
- Keep structural or pass-through validation for direct Goose
/model <id> input where the provider can reject invalid names at runtime.
- Cache discovered results with freshness metadata scoped to the effective Kai user, provider, and discovery source.
- Add tests for successful discovery, discovery failure, stale fallback, unsupported provider discovery, and direct manual model entry.
- Document the distinction between OpenCode
provider/model IDs and Goose provider-native model IDs.
Out of scope
- Scraping, automating, or parsing
goose configure.
- Treating Goose's bundled static provider catalogs as authoritative when a more current provider source exists.
- Expanding Kai's supported Goose providers solely because Goose documents or ships a provider.
- Adding or expanding OpenRouter or Ollama discovery in this issue unless they are separately declared active Kai targets.
- Changing Goose defaults automatically when a new model appears.
- Removing direct
/model <id> entry for Goose.
- Changing Goose provider authentication, key collection, or
GOOSE_PROVIDER wiring.
Acceptance criteria
- The implementation does not invoke
goose configure from Kai runtime, install-time validation, /models, or refresh paths.
- Goose
/models uses a documented discovery source for each active Goose provider, or explicitly falls back to the existing static or text-entry behavior when no reliable source exists.
- Discovered Goose model IDs are displayed and stored in the exact form Goose expects for
GOOSE_MODEL or goose run --model.
- OpenCode-style
provider/model IDs are not introduced into Goose model selection unless the selected Goose provider itself expects that shape.
- Direct
/model <id> remains available for Goose and is not capped to the discovered picker list.
- Discovery caches are scoped so one user's provider availability cannot leak into another user's Goose picker.
- Discovery failures produce clear user-facing feedback and do not make Goose model selection unusable.
- Defaults and
MODEL_REGISTRY choices remain curated. Newly discovered models become selectable but do not automatically become defaults.
- Tests cover provider-specific success, provider-specific discovery failure, fallback behavior, stale bundled catalog avoidance, manual model entry, and the DeepSeek
deepseek to custom_deepseek provider-name translation boundary.
- Documentation explains why Goose cannot currently use the same mechanism as OpenCode and names the condition that would allow that to change: a stable non-interactive Goose model catalog command.
Parent
Part of #705.
Summary
Goose model availability should not be kept current by scraping
goose configure. Goose has provider-aware model discovery internally, but the installed CLI does not expose a stable non-interactive model-list command equivalent toopencode models [provider]. Kai should define a Goose-specific discovery strategy that respects Goose's provider-native model names, keeps direct/model <id>available, and avoids expanding provider scope just because Goose documents many providers.Current state
Kai's Goose backend runs
goose acp --with-builtin developerfor conversational sessions and injects model selection throughGOOSE_MODELand provider selection throughGOOSE_PROVIDER.Goose one-shot calls use
goose run -i -with--provider <provider>and--model <model>overrides. Kai translates itsdeepseekprovider key to Goose's wire-levelcustom_deepseekprovider name.For
/models, Goose currently delegates to Kai's provider model surface. Curated providers getPROVIDER_MODELS; open-ended providers fall back to text entry. This means Goose inherits static provider lists even though Goose itself has provider internals that can fetch or enumerate models.Goose model names are provider-native bare model IDs, not OpenCode-style
provider/modelstrings. For example, Goose-on-DeepSeek usesdeepseek-v4-pro, while OpenCode-on-DeepSeek usesdeepseek/deepseek-v4-pro.Problem
Goose is similar to OpenCode in that providers sit under the backend, but the available discovery surface is different. OpenCode exposes
opencode models [provider]; Goose does not currently expose a comparable non-interactivegoose models [provider]command.Goose's interactive configure flow does fetch models, but that flow is not a runtime API. Scraping or driving
goose configurefrom Kai would couple Telegram model selection to terminal UI prompts, spinner output, and configure-side persistence behavior. That is brittle and would be unpleasant to debug. The technical term is "no."Using Goose's bundled provider catalogs as the only source of truth is also unsafe. Some Goose providers fetch live endpoints, while declarative providers can fall back to bundled static lists. For DeepSeek, the bundled declarative provider still lists legacy aliases such as
deepseek-chatanddeepseek-reasoner, which are exactly the kind of stale names Kai should avoid presenting as the current picker surface.Research notes
Local verification against Goose
1.38.0showed no top-level model catalog command. The available CLI surfaces includeconfigure,info,run,acp,serve,session, and other operational commands.goose run --helpdocuments--provider <PROVIDER>and--model <MODEL>, with the model required to be supported by the specified provider. This matches Kai's current one-shot integration shape.goose info --checkreads provider configuration from Goose config orGOOSE_PROVIDER; it reports provider status but does not list supported models.Goose source shows
configure.rscreating a temporary provider and callingfetch_recommended_models(...)before presenting an interactive model selector. That confirms model discovery exists inside Goose, but not as a stable non-interactive CLI contract.Provider source differs by provider. Anthropic and OpenAI provider implementations fetch live model endpoints. Ollama fetches local tags. Declarative providers can carry static model lists and may fall back to those lists when dynamic fetching is disabled or unavailable.
Relevant sources:
Desired behavior
Kai should treat Goose model discovery as Goose-specific, not as a copy of OpenCode discovery.
If Goose later exposes a stable non-interactive model catalog command, Kai should prefer that command and run it under the same effective OS user and environment used for Goose execution.
Until that exists, Kai should use provider-native discovery for active Goose provider surfaces where reliable provider APIs exist, while preserving Goose's model-name shape. OpenAI models remain bare OpenAI model IDs, Anthropic models remain Claude IDs or accepted aliases, Google models remain Gemini IDs, and DeepSeek models remain bare DeepSeek model IDs.
Direct
/model <id>should remain available for Goose even when a model is not present in the picker, because Goose can validate support at runtime and operators may need to pin a model before Kai's discovery path has refreshed.Discovery failure should not break Goose model selection. Kai should keep the previous static or text-entry behavior available and surface a clear message about the failed discovery source.
Scope
goose configure./model <id>input where the provider can reject invalid names at runtime.provider/modelIDs and Goose provider-native model IDs.Out of scope
goose configure./model <id>entry for Goose.GOOSE_PROVIDERwiring.Acceptance criteria
goose configurefrom Kai runtime, install-time validation,/models, or refresh paths./modelsuses a documented discovery source for each active Goose provider, or explicitly falls back to the existing static or text-entry behavior when no reliable source exists.GOOSE_MODELorgoose run --model.provider/modelIDs are not introduced into Goose model selection unless the selected Goose provider itself expects that shape./model <id>remains available for Goose and is not capped to the discovered picker list.MODEL_REGISTRYchoices remain curated. Newly discovered models become selectable but do not automatically become defaults.deepseektocustom_deepseekprovider-name translation boundary.