Documentation
¶
Overview ¶
Package providers handles LLM provider model listing and management.
Package providers handles LLM provider capabilities and model management.
Index ¶
- Variables
- func CatalogToolSupport(provider, modelID string) (supported, known bool)
- func CleanBaseURL(baseURL string) string
- func DetectProvider(baseURL string) string
- func EndpointID(provider, baseURL, apiKey string) string
- func ForgetCatalogsForTest()
- func GetPerModelToolProviders() []string
- func GetToolCallingProviders() []string
- func HasCatalog(provider string) bool
- func HasModelEndpoint(provider string) bool
- func IsAnthropicURL(baseURL string) bool
- func IsGeminiURL(baseURL string) bool
- func IsGoogleURL(baseURL string) bool
- func IsLocalEndpoint(baseURL string) bool
- func IsLocalHost(baseURL string) bool
- func IsVertexURL(baseURL string) bool
- func IsXAIURL(baseURL string) bool
- func ListProviders() []string
- func OrchestratesServerSide(provider, modelID string) bool
- func PrepareModels(ctx context.Context, provider, baseURL, apiKey string, models ...string)
- func ResolveFromMemory(provider, baseURL, apiKey, configured string) (model, note string, pending bool)
- func ResolveModel(provider, configured string, cat []CatalogModel, ok bool) (model, note string)
- func SetCatalogFetchForTest(...) (restore func())
- func SetCatalogForTest(provider string, models []CatalogModel) (restore func())
- func ToolsEnabledForModel(provider, modelID string) bool
- type CatalogModel
- func CachedCatalog(provider, baseURL, apiKey string) (models []CatalogModel, stale, ok bool)
- func CatalogFor(provider string) ([]CatalogModel, bool)
- func FindServed(cat []CatalogModel, modelID string) (CatalogModel, bool)
- func LoadCatalog(ctx context.Context, provider, baseURL, apiKey string) ([]CatalogModel, bool)
- func MemoryCatalog(provider, baseURL, apiKey string) (models []CatalogModel, stale, ok bool)
- func RefreshCatalog(ctx context.Context, provider, baseURL, apiKey string) ([]CatalogModel, error)
- type ModelDetection
- type ModelInfo
- type ModelService
- type ProviderCapabilities
Constants ¶
This section is empty.
Variables ¶
var DeprecatedModels = map[string]string{
"grok-4-1-fast": "grok-4.20-0309-non-reasoning",
"grok-4-1-fast-reasoning": "grok-4.20-0309-non-reasoning",
"grok-4-1-fast-non-reasoning": "grok-4.20-0309-non-reasoning",
"grok-4-1-reasoning": "grok-4.20-0309-non-reasoning",
"grok-4-1": "grok-4.20-0309-non-reasoning",
}
DeprecatedModels maps Grok models that xAI silently ROUTES to the cost-prohibitive grok-4.3 (the grok-4-1-* family) to a safe replacement (#51). config's reconcileModel migrates them; ResolveModel never picks one.
var Registry = map[string]ProviderCapabilities{ "openai": { Name: "OpenAI", BaseURL: "https://api.openai.com/v1", SupportsFunctionCalling: true, SupportsModelListing: true, SupportsTokenTracking: true, DefaultModel: "gpt-4.1-nano", PreferredToolModel: "gpt-4.1-nano", RequiresAPIKey: true, IsOpenAICompatible: true, SupportsResponses: true, Notes: "Native function calling support. Gold standard implementation.", }, "grok": { Name: "xAI Grok", BaseURL: "https://api.x.ai/v1", SupportsFunctionCalling: true, SupportsModelListing: true, SupportsTokenTracking: true, DefaultModel: "grok-4.20-0309-non-reasoning", PreferredToolModel: "grok-4.20-0309-non-reasoning", RequiresAPIKey: true, IsOpenAICompatible: true, Notes: "Default grok-4.20-0309-non-reasoning: reliable tool calling, no reasoning-token burn, never routes to the cost-prohibitive grok-4.3. Avoid grok-4-1-* (they route to grok-4.3).", }, "venice": { Name: "Venice.ai", BaseURL: "https://api.venice.ai/api/v1", SupportsFunctionCalling: false, SupportsModelListing: true, SupportsTokenTracking: true, DefaultModel: "venice-uncensored-1-2", PreferredToolModel: "", RequiresAPIKey: true, IsOpenAICompatible: true, ToolsPerModel: true, Notes: "NSFW mode uses Venice. No function calling in uncensored mode. Image generation available.", }, "anthropic": { Name: "Anthropic Claude", BaseURL: "https://api.anthropic.com", SupportsFunctionCalling: true, SupportsModelListing: true, SupportsTokenTracking: true, DefaultModel: "claude-sonnet-4-5-20250929", PreferredToolModel: "claude-sonnet-4-5-20250929", RequiresAPIKey: true, IsOpenAICompatible: false, Notes: "Advanced tool use features. OpenAI SDK compatibility is for testing only. Native API recommended.", }, "gemini": { Name: "Google Gemini AI (AI Studio)", BaseURL: "https://generativelanguage.googleapis.com/v1beta", SupportsFunctionCalling: true, SupportsModelListing: false, SupportsTokenTracking: true, DefaultModel: "gemini-flash-latest", PreferredToolModel: "gemini-flash-latest", RequiresAPIKey: true, IsOpenAICompatible: false, Notes: "RECOMMENDED: Native Google GenAI SDK with automatic authentication. Simple API keys (AIza...), free tier available. Full function calling support with streaming. Get key: https://aistudio.google.com/apikey", }, "vertex": { Name: "Google Vertex AI (Cloud)", BaseURL: "https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION", SupportsFunctionCalling: true, SupportsModelListing: false, SupportsTokenTracking: true, DefaultModel: "gemini-2.0-flash", PreferredToolModel: "gemini-2.0-flash", DefaultModelUnverified: true, RequiresAPIKey: false, IsOpenAICompatible: false, Notes: "ENTERPRISE: Native Google GenAI SDK with automatic authentication. No manual token refresh! Use: (1) gcloud auth application-default login OR (2) Service account JSON. Tokens auto-refresh indefinitely. Requires GCP project + billing.", }, "local": { Name: "Local (OpenAI-compatible)", BaseURL: "", SupportsFunctionCalling: true, SupportsModelListing: false, SupportsTokenTracking: true, DefaultModel: "", PreferredToolModel: "", RequiresAPIKey: false, IsOpenAICompatible: true, ExampleBaseURL: "http://127.0.0.1:8080/v1", Notes: "Any OpenAI-compatible server on this machine or the LAN: loopback, private IPs, single-label names, .local/.lan/.internal/.home.arpa (mlx-vlm, Ollama, LM Studio, llama.cpp). Set the model to whatever the server expects — mlx-vlm wants the full filesystem path. No API key required.", }, "openrouter": { Name: "OpenRouter", BaseURL: "https://openrouter.ai/api/v1", SupportsFunctionCalling: true, SupportsModelListing: true, SupportsTokenTracking: true, DefaultModel: "openai/gpt-4.1-nano", PreferredToolModel: "openai/gpt-4.1-nano", RequiresAPIKey: true, IsOpenAICompatible: true, Notes: "Aggregator for multiple providers. Full OpenAI compatibility. Parallel function calling supported.", }, "sakana": { Name: "Sakana AI", BaseURL: "https://api.sakana.ai/v1", SupportsFunctionCalling: true, SupportsModelListing: true, SupportsTokenTracking: true, DefaultModel: "fugu", PreferredToolModel: "fugu", RequiresAPIKey: true, IsOpenAICompatible: true, Notes: "Fugu / Fugu Ultra (1M context, deep reasoning). Fugu Ultra routes 1-3 expert agents. OpenAI-compatible chat completions. Install: curl -fsSL https://sakana.ai/fugu/install | bash", }, "digitalocean": { Name: "DigitalOcean Gradient", BaseURL: "", ExampleBaseURL: "https://your-agent.ondigitalocean.app/api/v1", SupportsFunctionCalling: false, SupportsModelListing: false, SupportsTokenTracking: true, DefaultModel: "gpt-4.1-nano", PreferredToolModel: "", RequiresAPIKey: true, IsOpenAICompatible: true, Notes: "Agent API with RAG capabilities. Token tracking supported via stream_options. Function calling requires cloud-hosted functions.", }, "elevenlabs": { Name: "ElevenLabs", BaseURL: "https://api.elevenlabs.io/v1", SupportsFunctionCalling: false, SupportsModelListing: false, SupportsTokenTracking: false, DefaultModel: "", PreferredToolModel: "", RequiresAPIKey: true, IsOpenAICompatible: false, Notes: "Voice AI provider. Function calling support unknown.", }, }
Registry holds all supported provider configurations. Ordered by priority: Popular/Tested → OpenAI-Compatible → Untested
Functions ¶
func CatalogToolSupport ¶
CatalogToolSupport reports what the provider's own catalog says about a model's tool calling. known is false when no catalog is loaded, the model isn't listed, or the listing doesn't say. An OpenRouter ":variant" suffix falls back to the base id.
func CleanBaseURL ¶
CleanBaseURL is a base URL safe to log: no userinfo, query or fragment.
func DetectProvider ¶
DetectProvider attempts to detect provider from base URL.
func EndpointID ¶
EndpointID names one endpoint's catalog (provider, base URL, key hash) without the key, so callers can tell whether two lookups share one.
func ForgetCatalogsForTest ¶
func ForgetCatalogsForTest()
ForgetCatalogsForTest is for tests only: it drops every catalog loaded in this process, so a test that fetched one doesn't leak it into the next.
func GetPerModelToolProviders ¶
func GetPerModelToolProviders() []string
GetPerModelToolProviders returns the providers with no default tool support whose tool support is decided per model (ToolsPerModel), sorted.
func GetToolCallingProviders ¶
func GetToolCallingProviders() []string
GetToolCallingProviders returns only providers that support function calling.
func HasCatalog ¶
HasCatalog reports whether celeste can list the models a provider serves. Gemini, Vertex, DigitalOcean, local servers and ElevenLabs have none.
func HasModelEndpoint ¶
HasModelEndpoint reports whether the provider answers GET /models/{id}.
func IsAnthropicURL ¶
IsAnthropicURL reports whether baseURL points at Anthropic: its host is anthropic.com or a subdomain of it, in any case, with or without a trailing dot or port. It is the one rule both DetectProvider (the header, capabilities, context windows) and the llm backend choice use (#372). A URL without a scheme is read as https.
func IsGeminiURL ¶
IsGeminiURL reports whether baseURL's host is Google AI Studio's generativelanguage.googleapis.com.
func IsGoogleURL ¶
IsGoogleURL reports whether baseURL is Gemini (AI Studio) or Vertex AI: the endpoints the native Google backend serves.
func IsLocalEndpoint ¶
IsLocalEndpoint reports whether baseURL is a server on this machine or the local network. It is IsLocalHost: one rule for the timeouts, the window probe and fallback, and the "local" provider (#377).
func IsLocalHost ¶
IsLocalHost reports whether baseURL's parsed host is this machine or the local network: localhost, a loopback, private, link-local or unspecified IP, a single-label host, or a .local, .lan, .internal or .home.arpa name. A hosted URL that merely contains "localhost" in its path is not local. Such a server runs the model on the user's own hardware, which can take minutes before the first byte.
func IsVertexURL ¶
IsVertexURL reports whether baseURL's host is Vertex AI's aiplatform.googleapis.com, global or regional (REGION-aiplatform...).
func IsXAIURL ¶
IsXAIURL reports whether baseURL's host is x.ai or a subdomain of it. It is the one rule DetectProvider ("grok") and the llm backend choice use.
func OrchestratesServerSide ¶
OrchestratesServerSide reports whether the model does its own task decomposition, delegation and verification server-side, which makes celeste-cli's local planning phase redundant. Fugu is a trained conductor: it either answers directly or coordinates several frontier models and synthesises the result. Running our planner on top of it means two planners that cannot see each other.
This is deliberately a rule rather than a lookup against the static model list. Sakana ships version-bumped fugu IDs faster than that list is updated, and an unrecognised ID must not silently re-enable local planning against a conductor. The provider is checked too: Sakana serves an OpenAI-compatible API and could host a plain model, which still needs local planning.
func PrepareModels ¶
PrepareModels loads an endpoint's catalog (the cache, or one fetch bounded by the timeout; a fetch that failed in the last five minutes is not retried) and, for providers that answer GET /models/{id}, checks each given model the catalog doesn't list. The answers stay in memory for ResolveFromMemory. It may block on the network: never call it from a Bubble Tea Update.
func ResolveFromMemory ¶
func ResolveFromMemory(provider, baseURL, apiKey, configured string) (model, note string, pending bool)
ResolveFromMemory resolves configured against what this process knows the endpoint serves, with no I/O. A model is replaced only when celeste is sure it's gone: the catalog doesn't list it and, where the provider can say, GET /models/{id} answered 404. pending is true when PrepareModels would know more (no catalog loaded yet, a stale one, or an unchecked miss); until then the configured model is kept. A miss in a list older than the TTL is not proof either.
func ResolveModel ¶
func ResolveModel(provider, configured string, cat []CatalogModel, ok bool) (model, note string)
ResolveModel picks the model a session uses from what the provider serves now, so a retired model is never sent. Pure; ok is false when there is no catalog (offline, no key, a provider without one).
- No catalog: the configured model, unchanged (the registry default when nothing is configured).
- The configured model is served: keep it.
- Otherwise, in order: the provider-flagged default; the newest served version of the configured model (its ID plus "-", "." or ":" and more); the registry default or preferred tool model, if served; the first tool-capable served model; the first served model.
Among ties (several flagged defaults or versions) a tool-capable model wins. The note says what happened; it is empty when nothing was replaced.
func SetCatalogFetchForTest ¶
func SetCatalogFetchForTest(fetch func(ctx context.Context, provider, baseURL, apiKey string) ([]CatalogModel, error)) (restore func())
SetCatalogFetchForTest is for tests only: it replaces the /models fetch, so tests in other packages can see what a fetch was asked (its context, endpoint) without the network. Call the returned func to restore.
func SetCatalogForTest ¶
func SetCatalogForTest(provider string, models []CatalogModel) (restore func())
SetCatalogForTest is for tests only. It makes provider's catalog the given models in every lookup (CachedCatalog, CatalogFor, LoadCatalog, RefreshCatalog), so no test reaches the network or the disk cache. A nil or empty list means "no catalog". Call the returned func to restore. It lives outside a _test.go file because tests in other packages (tui, main) need it.
func ToolsEnabledForModel ¶
ToolsEnabledForModel reports whether celeste should offer tool calling for this provider/model pair. Most providers decide at the provider level (SupportsFunctionCalling); a ToolsPerModel provider (Venice) decides per model instead, since most of its models have no tool support but some do (#151). The chat's skillsEnabled gate calls this instead of reading SupportsFunctionCalling directly, so Venice stops being "no tools" for every model.
Types ¶
type CatalogModel ¶
type CatalogModel struct {
ID string `json:"id"`
// Tools is the provider's own word on tool calling; nil when the listing
// doesn't say (most OpenAI-compatible APIs).
Tools *bool `json:"tools,omitempty"`
// Default marks the model the provider itself flags as its default
// (Venice's "default" trait).
Default bool `json:"default,omitempty"`
}
CatalogModel is one model a provider serves now, from its /models listing.
func CachedCatalog ¶
func CachedCatalog(provider, baseURL, apiKey string) (models []CatalogModel, stale, ok bool)
CachedCatalog returns the cached catalog for an endpoint, from memory or the disk cache, without touching the network. stale is true when it is older than the TTL; the caller decides whether to refresh it.
func CatalogFor ¶
func CatalogFor(provider string) ([]CatalogModel, bool)
CatalogFor returns the catalog most recently loaded in this process for a provider, whatever its endpoint. It never reads disk or the network: the tool gate calls it from the TUI's Update.
func FindServed ¶
func FindServed(cat []CatalogModel, modelID string) (CatalogModel, bool)
FindServed looks a model up in a catalog the way resolution does (case ignored, OpenRouter :variant rules).
func LoadCatalog ¶
func LoadCatalog(ctx context.Context, provider, baseURL, apiKey string) ([]CatalogModel, bool)
LoadCatalog returns the endpoint's catalog: the cached one when there is one (a stale cache is refreshed in the background), else a synchronous fetch bounded by catalogFetchTimeout. A fetch that failed less than five minutes ago is not retried. ok is false when there is no catalog. Never call it from a Bubble Tea Update.
func MemoryCatalog ¶
func MemoryCatalog(provider, baseURL, apiKey string) (models []CatalogModel, stale, ok bool)
MemoryCatalog is CachedCatalog without the disk: it only sees catalogs already loaded in this process, so the TUI's Update can call it.
func RefreshCatalog ¶
func RefreshCatalog(ctx context.Context, provider, baseURL, apiKey string) ([]CatalogModel, error)
RefreshCatalog fetches the endpoint's catalog and caches it. A failed fetch leaves the existing cache alone and is remembered for the negative window.
type ModelDetection ¶
type ModelDetection struct {
// contains filtered or unexported fields
}
ModelDetection provides heuristics for detecting model capabilities.
func NewModelDetection ¶
func NewModelDetection(provider string) *ModelDetection
NewModelDetection creates a model detection helper.
func (*ModelDetection) SupportsTools ¶
func (d *ModelDetection) SupportsTools(modelID string) bool
SupportsTools determines if a model supports function calling.
type ModelInfo ¶
type ModelInfo struct {
ID string
Name string
SupportsTools bool
ContextWindow int
Description string
Provider string
// OrchestratesServerSide mirrors OrchestratesServerSide(Provider, ID) so
// display surfaces (/config, the model picker) can show it without
// recomputing. The function stays the single source of truth.
OrchestratesServerSide bool
}
ModelInfo represents metadata about a model.
func ModelInfosFromCatalog ¶
func ModelInfosFromCatalog(provider string, cat []CatalogModel) []ModelInfo
ModelInfosFromCatalog turns a catalog into display rows, tool-capable models first. Tool support comes from the catalog when it says, else from the name heuristic.
func StaticModels ¶
StaticModels is the offline model list for a provider, used when no catalog is loaded.
type ModelService ¶
type ModelService struct {
// contains filtered or unexported fields
}
ModelService handles model listing and metadata.
func NewModelService ¶
func NewModelService(apiKey, baseURL, provider string) *ModelService
NewModelService creates a new model service for a provider.
type ProviderCapabilities ¶
type ProviderCapabilities struct {
Name string
BaseURL string
SupportsFunctionCalling bool
SupportsModelListing bool
SupportsTokenTracking bool // Returns usage data with stream_options
DefaultModel string
PreferredToolModel string // Best model for function calling
RequiresAPIKey bool
IsOpenAICompatible bool
Notes string
// ToolsPerModel marks a provider with no tool support by default whose
// catalogue has some tool-capable models (checked live per model, see
// ModelDetection.SupportsTools). SupportsFunctionCalling stays false: it
// drives the TUI's skill gate for the provider's default model.
ToolsPerModel bool
// DefaultModelUnverified marks a shipped default model nobody has
// checked against the live service.
DefaultModelUnverified bool
// ExampleBaseURL is shown by `providers info` when BaseURL is empty
// because the endpoint is the user's own (a local server, a DO agent).
ExampleBaseURL string
// SupportsResponses marks an OpenAI-compatible provider whose endpoint
// serves the OpenAI Responses API; celeste then talks to it through
// /v1/responses instead of Chat Completions (2.0 W8).
SupportsResponses bool
}
ProviderCapabilities defines what a provider supports.
func GetProvider ¶
func GetProvider(name string) (ProviderCapabilities, bool)
GetProvider returns provider capabilities by name.