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: :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.



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

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



121
122
123
124
# File 'lib/agent_harness/providers/registry.rb', line 121

def all
  ensure_builtin_providers_registered
  @providers.keys
end

#availableArray<Symbol>

List available providers (CLI installed)

Returns:

  • (Array<Symbol>)

    available provider names



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

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



113
114
115
116
# File 'lib/agent_harness/providers/registry.rb', line 113

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:



93
94
95
96
97
# File 'lib/agent_harness/providers/registry.rb', line 93

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:



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

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:



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

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



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

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

#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:



214
215
216
217
218
219
220
221
222
223
224
# File 'lib/agent_harness/providers/registry.rb', line 214

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



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/agent_harness/providers/registry.rb', line 231

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



54
55
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
# File 'lib/agent_harness/providers/registry.rb', line 54

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



103
104
105
106
107
# File 'lib/agent_harness/providers/registry.rb', line 103

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

#reset!Object



255
256
257
258
259
260
261
262
263
264
# File 'lib/agent_harness/providers/registry.rb', line 255

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:



188
189
190
191
192
193
# File 'lib/agent_harness/providers/registry.rb', line 188

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



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

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