Skip to content

feat(config): live model fetching for Copilot and Venice#3103

Open
taoeffect wants to merge 16 commits into
charmbracelet:mainfrom
taoeffect:issue-2740
Open

feat(config): live model fetching for Copilot and Venice#3103
taoeffect wants to merge 16 commits into
charmbracelet:mainfrom
taoeffect:issue-2740

Conversation

@taoeffect

@taoeffect taoeffect commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Closes #2740

Motivation

Crush's model list for GitHub Copilot and Venice comes from Catwalk, a static community-maintained database. When these providers add, remove, or change models, users have to wait for a Catwalk update — even though both providers expose a /models API with the current list. This led to stale model pickers, missing new models, and outdated metadata (context windows, pricing, reasoning support).

Also, per #2740, some of the models that are in Catwalk could be different from the actual models the user has access to, depending on their subscription/plan.

Approach

When you're signed in to Copilot (OAuth, with expired tokens refreshed just for the fetch) or Venice (API key), Crush fetches the model list directly from the provider at startup:

  • Catwalk stays as the seed and fallback. It provides the provider's name, default model IDs, and the model list for unauthenticated users (model browsing still works). Live models are merged onto the Catwalk seed: live data wins for the model list and metadata, Catwalk fills in what the provider APIs don't supply, and if a Catwalk default model no longer exists live, the first live model takes its place. Any fetch failure falls back to the cached result or the Catwalk seed.
  • At most one fetch per startup. Models are fetched once per process start, gated by a 60-second disk cache shared across processes — warm restarts are instant and hit no network. Failures (network, disk, empty responses) are always non-fatal; startup never blocks on the live overlay.
  • Manual refresh. crush update-providers also refreshes authenticated live providers; --source=venice / --source=copilot refresh them directly, bypassing the cache.
  • Capability-based filtering. Copilot's response includes non-chat models (embeddings, routers); these are filtered via the API's capabilities.type field rather than ID guesswork.

Respects disable_provider_auto_update and works offline, same as the existing Catwalk/Hyper sync.

AI Disclosure

Assisted with: Fable 5 (max), GPT-5.5 (xhigh), and Opus 4.8

I had Opus 4.8 create the plan files, GPT-5.5 implement them, and finally Fable 5 review and fix bugs.

Three rounds of reviews were used (two local, one Copilot).

  • I have read CONTRIBUTING.md.
  • I have created a discussion that was approved by a maintainer (for new features).

Copilot AI review requested due to automatic review settings June 10, 2026 16:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds authenticated “live” provider model syncing for Venice and Copilot (with caching), and changes UI model-related actions to persist at workspace scope to avoid being overridden.

Changes:

  • Persist selected models + thinking/reasoning settings at ScopeWorkspace (and add regression tests).
  • Introduce live provider model clients/syncing for Venice and Copilot, including CLI support (update-providers --source=venice|copilot) and best-effort refresh on default updates.
  • Add unit/integration tests covering live provider overlays, caching/TTL behavior, and CLI help/examples.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
internal/ui/model/ui_test.go Adds tests ensuring workspace-scoped persistence for model selection/thinking/reasoning.
internal/ui/model/ui.go Persists model selection/thinking/reasoning at workspace scope and factors logic into helpers.
internal/server/recover_test.go Updates tests to use context-aware HTTP requests.
internal/config/venice_models_test.go Tests Venice live models client mapping/filtering and auth header behavior.
internal/config/venice_models.go Implements Venice /models live client + response-to-catwalk mapping.
internal/config/provider_test.go Adds integration tests for live overlay behavior, credentials, and cache updates.
internal/config/provider.go Adds live overlay plumbing, Venice/Copilot update entrypoints, and credential detection helpers.
internal/config/live_provider_test.go Adds comprehensive tests for live provider sync behavior (cache, TTL, errors).
internal/config/live_provider.go Implements generic live provider sync w/ cache + TTL merge behavior.
internal/config/copilot_models_test.go Tests Copilot live models client mapping and OAuth refresh behavior.
internal/config/copilot_models.go Implements Copilot /models live client + filtering/deduping logic.
internal/cmd/update_providers_test.go Ensures CLI flags/examples mention the new live providers.
internal/cmd/update_providers.go Adds `--source=venice
README.md Documents that update-providers also refreshes live providers when authenticated.
AGENTS.md Documents provider update/live overlay behavior and TTL concept.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/config/live_provider.go
Comment thread internal/config/live_provider.go
Comment thread internal/config/provider.go
Comment thread internal/config/provider.go
Comment thread internal/ui/model/ui.go Outdated
Comment thread internal/ui/model/ui.go
…ffort toggles

Assisted-by: Claude Opus 4.6 (via Crush)
@ehiggs

ehiggs commented Jun 10, 2026

Copy link
Copy Markdown

If we have a manual update command and these things only change every few months, does there need to be a request happening every minute?

I've got 8-15 instances of crush running on my machine, mostly idling in different work trees. Do they all need to check every minute?

I would say remove them or check once or twice a day.

@taoeffect

taoeffect commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

The check isn't happening once per minute, it's once at startup (and then at most, once per minute), so your 8-15 instances won't be checking at all while they're idling. I don't think users will be starting crush up that frequently...

EDIT: Edited PR description to make this clearer.

Make live provider model refresh non-blocking on startup and propagate
completed refreshes into the running session. The TUI now starts with the
catwalk seed or warm cache immediately while stale/missing live caches
refresh in the background.

A syncer completion callback updates a lock-guarded provider list and
publishes a ProvidersUpdatedEvent over a config pubsub broker, which the UI
uses to repopulate an open model dialog without restarting Crush.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copilot: User-oriented list of models based on their subscription

3 participants