Class: AgentHarness::Providers::Registry

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/agent_harness/providers/registry.rb

Overview

Registry for provider classes

Manages registration and lookup of provider classes. Supports dynamic registration of custom providers and aliasing of provider names.

Examples:

Registering a custom provider

AgentHarness::Providers::Registry.instance.register(:my_provider, MyProviderClass)

Looking up a provider

klass = AgentHarness::Providers::Registry.instance.get(:claude)

Constant Summary collapse

BUILTIN_PROVIDER_DEFINITIONS =
[
  {name: :claude, require_path: "agent_harness/providers/anthropic", class_name: :Anthropic, aliases: [:anthropic]},
  {name: :cursor, require_path: "agent_harness/providers/cursor", class_name: :Cursor, aliases: []},
  {name: :gemini, require_path: "agent_harness/providers/gemini", class_name: :Gemini, aliases: []},
  {
    name: :github_copilot,
    require_path: "agent_harness/providers/github_copilot",
    class_name: :GithubCopilot,
    aliases: [:copilot]
  },
  {name: :pi, require_path: "agent_harness/providers/pi", class_name: :Pi, aliases: []},
  {name: :omp, require_path: "agent_harness/providers/omp", class_name: :OhMyPi, aliases: []},
  {name: :codex, require_path: "agent_harness/providers/codex", class_name: :Codex, aliases: []},
  {name: :opencode, require_path: "agent_harness/providers/opencode", class_name: :Opencode, aliases: []},
  {name: :kilocode, require_path: "agent_harness/providers/kilocode", class_name: :Kilocode, aliases: []},
  {name: :aider, require_path: "agent_harness/providers/aider", class_name: :Aider, aliases: []},
  {name: :mistral_vibe, require_path: "agent_harness/providers/mistral_vibe", class_name: :MistralVibe, aliases: []}
].freeze

Instance Method Summary collapse

Constructor Details

#initializeRegistry

Returns a new instance of Registry.



39
40
41
42
43
44
45
46
47
48
# File 'lib/agent_harness/providers/registry.rb', line 39

def initialize
  @providers = {}
  @aliases = {}
  @provider_aliases = Hash.new { |hash, key| hash[key] = [] }
  @metadata_runtime_available = {}
  @provider_metadata_cache = {}
  @provider_metadata_catalog_cache = nil
  @builtin_registered = false
  @builtin_registration_in_progress = false
end

Instance Method Details

#allArray<Symbol>

List all registered provider names

Returns:

  • (Array<Symbol>)

    provider names



123
124
125
126
# File 'lib/agent_harness/providers/registry.rb', line 123

def all
  ensure_builtin_providers_registered
  @providers.keys
end

#availableArray<Symbol>

List available providers (CLI installed)

Returns:

  • (Array<Symbol>)

    available provider names



131
132
133
134
# File 'lib/agent_harness/providers/registry.rb', line 131

def available
  ensure_builtin_providers_registered
  @providers.select { |_, klass| klass.available? }.keys
end

#canonical_name(name) ⇒ Symbol

Resolve a provider lookup key to its canonical registered name.

Parameters:

  • name (Symbol, String)

    the provider name or alias

Returns:

  • (Symbol)

    canonical provider name



115
116
117
118
# File 'lib/agent_harness/providers/registry.rb', line 115

def canonical_name(name)
  ensure_builtin_providers_registered
  resolve_alias(name.to_sym)
end

#get(name) ⇒ Class

Get provider class by name

Parameters:

  • name (Symbol, String)

    the provider name

Returns:

  • (Class)

    the provider class

Raises:



95
96
97
98
99
# File 'lib/agent_harness/providers/registry.rb', line 95

def get(name)
  ensure_builtin_providers_registered
  name = resolve_alias(name.to_sym)
  @providers[name] || raise(ConfigurationError, "Unknown provider: #{name}")
end

#install_contract(name) ⇒ Hash

Fetch install contract metadata for a provider.

Parameters:

  • name (Symbol, String)

    the provider name

Returns:

  • (Hash)

    the provider install contract

Raises:



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/agent_harness/providers/registry.rb', line 142

def install_contract(name)
  provider_class = get(name)

  unless provider_class.respond_to?(:install_contract)
    raise ConfigurationError, "Provider #{provider_class} does not implement .install_contract"
  end

  contract = provider_class.install_contract
  unless contract
    raise ConfigurationError, "Provider #{provider_class} does not expose an install contract"
  end

  contract
end

#installation_contract(name, **options) ⇒ Hash?

Fetch installation metadata for a provider.

Parameters:

  • name (Symbol, String)

    the provider name

  • options (Hash)

    optional target selection (for example, version:)

Returns:

  • (Hash, nil)

    provider installation contract, or nil when the registered provider class does not define .installation_contract

Raises:



164
165
166
167
168
169
# File 'lib/agent_harness/providers/registry.rb', line 164

def installation_contract(name, **options)
  provider_class = get(name)
  return nil unless provider_class.respond_to?(:installation_contract)

  provider_class.installation_contract(**options)
end

#installation_contractsHash<Symbol, Hash>

Get installation metadata for all providers that expose it.

Returns:

  • (Hash<Symbol, Hash>)

    installation contracts keyed by provider



174
175
176
177
178
179
180
181
182
183
# File 'lib/agent_harness/providers/registry.rb', line 174

def installation_contracts
  ensure_builtin_providers_registered

  @providers.each_with_object({}) do |(name, klass), contracts|
    next unless klass.respond_to?(:installation_contract)

    contract = klass.installation_contract
    contracts[name] = contract if contract
  end
end

#model_compatibility(name, model_id:, auth_mode: nil, cli_version: nil) ⇒ AgentHarness::ModelCompatibility::Result

Query runner/model compatibility contract for a provider.

Delegates to the provider class's .model_compatibility method, which returns a structured ModelCompatibility::Result. The default implementation in Adapter returns :unknown for providers that have not opted in to a static contract.

Parameters:

  • name (Symbol, String)

    the provider name or alias

  • model_id (String, Symbol)

    requested model identifier

  • auth_mode (Symbol, nil) (defaults to: nil)

    caller's auth mode

  • cli_version (String, Gem::Version, nil) (defaults to: nil)

    installed CLI version

Returns:

Raises:



199
200
201
202
203
204
205
206
# File 'lib/agent_harness/providers/registry.rb', line 199

def model_compatibility(name, model_id:, auth_mode: nil, cli_version: nil)
  klass = get(name)
  klass.model_compatibility(
    model_id: model_id,
    auth_mode: auth_mode,
    cli_version: cli_version
  )
end

#provider_metadata(name, refresh: false) ⇒ Hash

Fetch consolidated provider metadata for a provider.

Parameters:

  • name (Symbol, String)

    the provider name or alias

Returns:

  • (Hash)

    provider metadata

Raises:



239
240
241
242
243
244
245
246
247
248
249
# File 'lib/agent_harness/providers/registry.rb', line 239

def (name, refresh: false)
  ensure_builtin_providers_registered

  requested_name = name.to_sym
  canonical_name = resolve_alias(requested_name)
  cache_key = [requested_name, canonical_name]

  return (@provider_metadata_cache[cache_key]) if !refresh && @provider_metadata_cache.key?(cache_key)

  (requested_name, canonical_name, refresh: refresh)
end

#provider_metadata_catalog(refresh: false) ⇒ Hash<Symbol, Hash>

Get consolidated metadata for all registered providers.

Parameters:

  • refresh (Boolean) (defaults to: false)

    when true, refresh live runtime metadata such as CLI availability instead of reusing cached values

Returns:

  • (Hash<Symbol, Hash>)

    provider metadata keyed by canonical provider



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/agent_harness/providers/registry.rb', line 256

def (refresh: false)
  ensure_builtin_providers_registered

  return (@provider_metadata_catalog_cache) if !refresh && @provider_metadata_catalog_cache

  if refresh
    
    
  end

  catalog = @providers.keys.each_with_object({}) do |name, result|
    result[name] = (
      name,
      name,
      refresh: refresh,
      invalidate_provider_cache: false,
      invalidate_catalog: false
    )
  end

  @provider_metadata_catalog_cache = (catalog)
  (catalog)
end

#register(name, klass, aliases: []) ⇒ void

This method returns an undefined value.

Register a provider class

Parameters:

  • name (Symbol, String)

    the provider name

  • klass (Class)

    the provider class

  • aliases (Array<Symbol, String>) (defaults to: [])

    alternative names



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/agent_harness/providers/registry.rb', line 56

def register(name, klass, aliases: [])
  name = name.to_sym
  validate_provider_class!(klass)
  normalized_aliases = aliases
    .filter_map do |alias_name|
      normalized_alias = alias_name.to_s.strip
      next if normalized_alias.empty?

      normalized_alias.to_sym
    end
    .uniq - [name]

  validate_provider_name!(name)
  validate_aliases!(name, normalized_aliases)
  unregister_aliases_for(name)

  @providers[name] = klass
  @provider_aliases[name] = normalized_aliases
  @metadata_runtime_available.delete(name)
  
  (klass)

  normalized_aliases.each do |alias_name|
    previous_owner = @aliases[alias_name]
    if previous_owner && previous_owner != name
      @provider_aliases[previous_owner] = @provider_aliases[previous_owner] - [alias_name]
    end

    @aliases[alias_name] = name
  end

  AgentHarness.logger&.debug("[AgentHarness::Registry] Registered provider: #{name}")
end

#registered?(name) ⇒ Boolean

Check if provider is registered

Parameters:

  • name (Symbol, String)

    the provider name

Returns:

  • (Boolean)

    true if registered



105
106
107
108
109
# File 'lib/agent_harness/providers/registry.rb', line 105

def registered?(name)
  ensure_builtin_providers_registered
  name = resolve_alias(name.to_sym)
  @providers.key?(name)
end

#reset!Object



280
281
282
283
284
285
286
287
288
289
# File 'lib/agent_harness/providers/registry.rb', line 280

def reset!
  @providers.each_value { |klass| (klass) }
  @providers.clear
  @aliases.clear
  @provider_aliases.clear
  @metadata_runtime_available.clear
  
  @builtin_registered = false
  @builtin_registration_in_progress = false
end

#smoke_test_contract(name) ⇒ Hash?

Get smoke-test metadata for a provider.

Parameters:

  • name (Symbol, String)

    the provider name

Returns:

  • (Hash, nil)

    smoke-test contract

Raises:



213
214
215
216
217
218
# File 'lib/agent_harness/providers/registry.rb', line 213

def smoke_test_contract(name)
  klass = get(name)
  return nil unless klass.respond_to?(:smoke_test_contract)

  klass.smoke_test_contract
end

#smoke_test_contractsHash<Symbol, Hash>

Get smoke-test metadata for all providers that expose it.

Returns:

  • (Hash<Symbol, Hash>)

    smoke-test contracts keyed by provider



223
224
225
226
227
228
229
230
231
232
# File 'lib/agent_harness/providers/registry.rb', line 223

def smoke_test_contracts
  ensure_builtin_providers_registered

  @providers.each_with_object({}) do |(name, klass), contracts|
    next unless klass.respond_to?(:smoke_test_contract)

    contract = klass.smoke_test_contract
    contracts[name] = contract if contract
  end
end