Skip to content

Define Goose model discovery without relying on interactive configure #728

Description

@dcellison

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions