Module: OllamaAgent::Providers::Registry

Defined in:
lib/ollama_agent/providers/registry.rb

Overview

Central registry for model providers. Resolves a provider by name string or symbol and builds the Router. Also builds CredentialRouter instances from a credentials config array.

Examples:

Single-provider usage (unchanged)

provider = OllamaAgent::Providers::Registry.resolve("openai")

Multi-credential pool

router = OllamaAgent::Providers::Registry.from_credentials([
  { id: "key-1", provider: "openai", api_key: ENV["OPENAI_KEY_1"], weight: 2,
    limits: { rpm: 60, tpm: 90_000, daily_tokens: 10_000_000 } },
  { id: "key-2", provider: "openai", api_key: ENV["OPENAI_KEY_2"], weight: 1 },
  { id: "groq",  provider: "groq",   api_key: ENV["GROQ_KEY"],
    base_url: "https://api.groq.com/openai/v1" }
])

Constant Summary collapse

BUILT_IN =
{
  "ollama" => Ollama,
  "ollama_cloud" => Ollama,
  "openai" => OpenAI,
  "anthropic" => Anthropic,
  # OpenAI-compatible aliases — use openai provider with custom base_url
  "groq" => OpenAI,
  "together" => OpenAI,
  "openrouter" => OpenAI
}.freeze
COMPATIBLE_URLS =

Default base URLs for external providers

{
  "groq" => "https://api.groq.com/openai/v1",
  "together" => "https://api.together.xyz/v1",
  "openrouter" => "https://openrouter.ai/api/v1",
  "ollama_cloud" => "https://api.ollama.com"
}.freeze

Class Method Summary collapse

Class Method Details

.auto_providerObject

Returns a provider that is available right now. Checks Ollama first (free/local), then OpenAI, then Anthropic.



115
116
117
118
119
120
121
122
123
# File 'lib/ollama_agent/providers/registry.rb', line 115

def auto_provider(**)
  candidates = [
    BUILT_IN["ollama"].new(**),
    (BUILT_IN["openai"].new(**)    if ENV["OPENAI_API_KEY"]),
    (BUILT_IN["anthropic"].new(**) if ENV["ANTHROPIC_API_KEY"])
  ].compact

  Router.new(providers: candidates, strategy: :first_available)
end

.from_credentials(credentials, hooks: nil) ⇒ CredentialRouter

Build a CredentialRouter from an array of credential configuration hashes. This is the primary entry point for multi-key / multi-provider setups.

Parameters:

  • credentials (Array<Hash>)

    each hash: :id [String] (required) unique name :provider [String] (required) “openai” | “anthropic” | “groq” | “ollama” | …:api_key [String] :base_url [String] override for OpenAI-compatible endpoints :weight [Integer] routing weight (default 1) :limits [Hash] { rpm:, tpm:, daily_tokens:, daily_requests: }

  • hooks (Streaming::Hooks, nil) (defaults to: nil)

Returns:



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ollama_agent/providers/registry.rb', line 101

def from_credentials(credentials, hooks: nil)
  creds = credentials.map { |cfg| build_credential(cfg) }
  pool  = CredentialPool.new(credentials: creds)
  mon   = HealthMonitor.new(hooks: hooks)

  CredentialRouter.new(
    pool: pool,
    provider_builder: method(:build_provider_for_credential),
    health_monitor: mon
  )
end

.known_namesObject



125
126
127
# File 'lib/ollama_agent/providers/registry.rb', line 125

def known_names
  (BUILT_IN.keys + @custom.keys).uniq
end

.register(name, klass) ⇒ Object

Register a custom provider class.

Raises:

  • (ArgumentError)


59
60
61
62
63
# File 'lib/ollama_agent/providers/registry.rb', line 59

def register(name, klass)
  raise ArgumentError, "#{klass} must inherit from Providers::Base" unless klass <= Base

  @custom[name.to_s] = klass
end

.reset_custom!Object



129
130
131
# File 'lib/ollama_agent/providers/registry.rb', line 129

def reset_custom!
  @custom = {}
end

.resolve(name, **opts) ⇒ Base

Resolve a provider instance by name.

Parameters:

  • name (String, Symbol)

    provider name or “auto”

  • opts (Hash)

    forwarded to the provider constructor

Returns:

  • (Base)

    provider instance

Raises:

  • (ArgumentError)


69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ollama_agent/providers/registry.rb', line 69

def resolve(name, **opts)
  return auto_provider(**opts) if name.to_s == "auto"

  n     = name.to_s
  klass = @custom[n] || BUILT_IN[n]
  raise ArgumentError, "Unknown provider: #{name}. Known: #{known_names.join(", ")}" unless klass

  # Inject default base_url for OpenAI-compatible aliases
  opts[:base_url] ||= COMPATIBLE_URLS[n] if COMPATIBLE_URLS.key?(n)

  klass.new(**opts)
end

.router(names, strategy: :first_available, **shared_opts) ⇒ Object

Build a router from a priority list of provider names.

Parameters:

  • names (Array<String>)

    provider names in fallback order



84
85
86
87
# File 'lib/ollama_agent/providers/registry.rb', line 84

def router(names, strategy: :first_available, **shared_opts)
  providers = names.map { |n| resolve(n, **shared_opts) }
  Router.new(providers: providers, strategy: strategy)
end