Enumerates the models a backend can serve, normalised to ExAthena.Model.
This is the single place that knows how each family of backend answers "what
models do you have?". It exists as its own module rather than inside
ExAthena.Providers.ReqLLM because listing shares nothing with inference: it
speaks different endpoints, on different paths, with different failure
tolerances.
Why the transport is hand-rolled
Neither req_llm nor llm_db can enumerate a live server. req_llm ships no
discovery callback and no adapter that issues GET /v1/models; its
ReqLLM.available_models/1 is a catalog query (llm_db candidates filtered by
which credentials happen to resolve), and llm_db is a build-time snapshot with
no runtime HTTP at all. Neither has any notion of a local Ollama daemon — the
catalog carries ollama_cloud, never localhost:11434. So live enumeration is
ours to do, and the catalog is used for what it is genuinely good at: metadata.
Dispatch
| Backend | Source |
|---|---|
:ollama | GET /api/tags on the bare host, optionally plus the cloud catalogue |
:llamacpp | GET /v1/models |
:exo | GET /v1/models?status=downloaded |
any other tag with a base_url | GET /v1/models (OpenAI wire format) |
| any other tag | the llm_db catalog for that provider |
Local backends are matched on :openai_compatible_backend rather than on
:req_llm_provider_tag, because every OpenAI-wire backend — Ollama and
llama.cpp included — carries the tag "openai"; the tag cannot tell them apart.
Summary
Functions
Reduce a listing result to the bare sorted ids / error atoms that the
deprecated ExAthena.Chat.* helpers promised.
List the models available for the backend described by opts.
Functions
@spec legacy_result({:ok, [ExAthena.Model.t()]} | {:error, ExAthena.Error.t()}) :: {:ok, [String.t()]} | {:error, atom() | {:http, integer()}}
Reduce a listing result to the bare sorted ids / error atoms that the
deprecated ExAthena.Chat.* helpers promised.
Lives here, next to the errors it decodes, so the three shims share one
translation instead of re-deriving it — the canonical ExAthena.Error keeps
the original atom in :raw for exactly this purpose.
@spec list(keyword()) :: {:ok, [ExAthena.Model.t()]} | {:error, ExAthena.Error.t()}
List the models available for the backend described by opts.
opts are the provider opts ExAthena.Config already threads for a call —
:base_url, :api_key, :req_llm_provider_tag, :openai_compatible_backend,
:extra_headers — plus:
:timeout_ms— per-request receive timeout (default 2_000). Listing backs a UI picker, so it fails fast rather than hanging the interface.:include_cloud— Ollama only; also fetch theollama.comcatalogue.:cloud_base_url— Ollama cloud host override (defaulthttps://ollama.com).