Skip to content

feat(models): reload model discovery from the /models dialog - #3374

Open
joestump-agent wants to merge 1 commit into
charmbracelet:mainfrom
joestump-agent:upstream/model-reload
Open

feat(models): reload model discovery from the /models dialog#3374
joestump-agent wants to merge 1 commit into
charmbracelet:mainfrom
joestump-agent:upstream/model-reload

Conversation

@joestump-agent

Copy link
Copy Markdown
Contributor

Posted by @joestump-agent at @joestump's direction.

What & why

There's currently no way to reload model discovery without restarting Crush. Local providers — Ollama, LM Studio, llama.cpp, LiteLLM, etc. — can gain models at runtime (an ollama pull mid-session), but discovery only runs at startup, so newly pulled models stay invisible until you quit and relaunch.

This adds a ctrl+r "reload" action to the /models dialog that re-runs model discovery for custom providers, merges any newly found models into the in-memory config, refreshes the list in place (preserving whatever you've typed as a filter), and reports how many models turned up.

How it works

  • Shared discovery helper. The concurrent discovery loop is factored out of configureProviders into discoverProviderModels (internal/config/discovery.go) so load-time discovery and interactive reload stay in lockstep. Load keeps its original trigger semantics; reload forces discovery for every custom provider that hasn't opted out via discover_models: false.
  • ConfigStore.ReloadModelDiscovery(ctx) (int, error) re-runs discovery (10s timeout), merges results, and returns the count of newly added models. Like startup discovery, results are ephemeral — recomputed each time, never persisted to disk.
  • Dialog UX. ctrl+rActionReloadModelDiscovery → background reload → the list rebuilds via a new Models.ReloadItems() that re-applies the active filter. A toast reports Discovered N new models / No new models found. The dialog stays open throughout.
  • Both runtime modes. Wired through the Workspace interface: AppWorkspace calls the store directly; ClientWorkspace proxies to a new POST /v1/workspaces/{id}/config/reload-discovery endpoint and then refreshes its cached config so the client's dialog sees the new models.

Scope

This reloads custom/local provider discovery (the discover package) — the case where models genuinely appear at runtime. It does not re-fetch the known/catwalk (models.dev) provider list, which is memoized per-process and is a separate concern.

Testing

  • New internal/config/discovery_test.go: providerWantsDiscovery trigger matrix (load vs. force/reload), an end-to-end reload against an httptest server whose model list grows between passes (verifies the new model is picked up, added count is correct, and user-specified model metadata is preserved), and an opt-out (discover_models: false) test asserting the provider is never queried.
  • New internal/ui/dialog/models_test.go covering ReloadItems() filter preservation.
  • go build ./..., go vet, and gofmt clean; internal/config, discover, ui/dialog, workspace, server, and client package tests pass.

💘 Generated with Crush

Assisted-by: Claude Fable 5

Local providers (Ollama, LM Studio, llama.cpp, LiteLLM, …) can gain
models at runtime — an `ollama pull` mid-session — but discovery only
ran at startup, so the new models were invisible until Crush restarted.

Add a `ctrl+r` "reload" action to the /models dialog that re-runs model
discovery for custom providers and merges any newly found models into
the in-memory config, then refreshes the list in place (preserving the
active filter) and reports how many models were discovered.

The concurrent discovery loop is factored out of configureProviders into
a shared helper (discoverProviderModels) so load and reload stay in
lockstep; reload forces discovery for every custom provider that hasn't
opted out via `discover_models: false`. Discovered models remain
ephemeral — recomputed each load/reload, never persisted.

Wired through the Workspace interface, so it works in both in-process
(AppWorkspace) and client/server (ClientWorkspace, via a new
/config/reload-discovery endpoint that refreshes the client's cached
config) modes.

Assisted-by: Claude Fable 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant