Class: Aidp::Harness::AgentHarnessProviderManager

Inherits:
Object
  • Object
show all
Includes:
MessageDisplay
Defined in:
lib/aidp/harness/agent_harness_provider_manager.rb

Overview

Provider manager that delegates to AgentHarness gem

This class implements the same interface as ProviderManager but delegates provider management to the AgentHarness gem's conductor. It allows AIDP to use AgentHarness for provider orchestration while maintaining compatibility with existing Runner and ErrorHandler code.

Examples:

Usage in Runner

@provider_manager = AgentHarnessProviderManager.new(@configuration)

Constant Summary

Constants included from MessageDisplay

MessageDisplay::COLOR_MAP, MessageDisplay::CRITICAL_TYPES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from MessageDisplay

#display_message, included, #message_display_prompt, #quiet_mode?

Constructor Details

#initialize(configuration, prompt: nil, binary_checker: nil) ⇒ AgentHarnessProviderManager

Returns a new instance of AgentHarnessProviderManager.



23
24
25
26
27
28
29
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 23

def initialize(configuration, prompt: nil, binary_checker: nil)
  @configuration = configuration
  @adapter = AgentHarnessAdapter.new(configuration, logger: Aidp.logger)
  @current_model = nil
  @rate_limit_info = {}
  @provider_history = []
end

Instance Attribute Details

#adapterObject (readonly)

Returns the value of attribute adapter.



20
21
22
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 20

def adapter
  @adapter
end

#current_modelString?

Get current model for provider

Returns:

  • (String, nil)

    current model name



41
42
43
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 41

def current_model
  @current_model ||= default_model(current_provider)
end

Instance Method Details

#available_providersArray<Symbol>

Get list of available (healthy) providers

Returns:

  • (Array<Symbol>)

    available provider names



76
77
78
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 76

def available_providers
  @adapter.conductor.provider_manager.available_providers
end

#circuit_open?(provider) ⇒ Boolean

Check if circuit is open for provider

Parameters:

  • provider (Symbol, String)

    provider name

Returns:

  • (Boolean)

    true if circuit is open



208
209
210
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 208

def circuit_open?(provider)
  @adapter.conductor.provider_manager.circuit_open?(provider.to_sym)
end

#configured_providersArray<Symbol>

Get list of configured providers

Returns:

  • (Array<Symbol>)

    provider names



69
70
71
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 69

def configured_providers
  AgentHarness.configuration.providers.keys
end

#current_providerSymbol

Get current provider name

Returns:

  • (Symbol)

    current provider name



34
35
36
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 34

def current_provider
  @adapter.conductor.provider_manager.current_provider
end

#current_provider_modelString

Get current provider and model combination

Returns:

  • (String)

    provider:model string



48
49
50
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 48

def current_provider_model
  "#{current_provider}:#{current_model}"
end

#get_provider(provider = nil) ⇒ AgentHarness::Providers::Base

Get provider instance

Parameters:

  • provider (Symbol, String) (defaults to: nil)

    provider name

Returns:

  • (AgentHarness::Providers::Base)

    provider instance



216
217
218
219
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 216

def get_provider(provider = nil)
  provider ||= current_provider
  @adapter.conductor.provider_manager.get_provider(provider.to_sym)
end

#healthy?(provider) ⇒ Boolean

Check if provider is healthy

Parameters:

  • provider (Symbol, String)

    provider name

Returns:

  • (Boolean)

    true if healthy



200
201
202
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 200

def healthy?(provider)
  @adapter.conductor.provider_manager.healthy?(provider.to_sym)
end

#is_rate_limited?(provider) ⇒ Boolean Also known as: rate_limited?

Check if provider is rate limited

Parameters:

  • provider (Symbol, String)

    provider name

Returns:

  • (Boolean)

    true if rate limited



141
142
143
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 141

def is_rate_limited?(provider)
  @adapter.conductor.provider_manager.rate_limited?(provider.to_sym)
end

#mark_provider_auth_failure(provider) ⇒ void

This method returns an undefined value.

Mark provider as having auth failure

Parameters:

  • provider (Symbol, String)

    provider name



161
162
163
164
165
166
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 161

def mark_provider_auth_failure(provider)
  provider = provider.to_sym
  @adapter.conductor.provider_manager.record_failure(provider)
  Aidp.logger.warn("agent_harness_provider_manager", "Provider auth failure recorded",
    provider: provider)
end

#mark_provider_failure_exhausted(provider) ⇒ void

This method returns an undefined value.

Mark provider as having exhausted failures

Parameters:

  • provider (Symbol, String)

    provider name



172
173
174
175
176
177
178
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 172

def mark_provider_failure_exhausted(provider)
  provider = provider.to_sym
  # Record multiple failures to trigger circuit breaker
  5.times { @adapter.conductor.provider_manager.record_failure(provider) }
  Aidp.logger.warn("agent_harness_provider_manager", "Provider failures exhausted",
    provider: provider)
end

#mark_rate_limited(provider, reset_time = nil) ⇒ void

This method returns an undefined value.

Mark provider as rate limited

Parameters:

  • provider (Symbol, String)

    provider name

  • reset_time (Time, nil) (defaults to: nil)

    when rate limit resets



126
127
128
129
130
131
132
133
134
135
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 126

def mark_rate_limited(provider, reset_time = nil)
  provider = provider.to_sym
  @rate_limit_info[provider] = {
    limited_at: Time.now,
    reset_time: reset_time
  }
  @adapter.conductor.provider_manager.mark_rate_limited(provider, reset_at: reset_time)
  Aidp.logger.info("agent_harness_provider_manager", "Provider marked rate limited",
    provider: provider, reset_time: reset_time)
end

#next_reset_timeTime?

Get next rate limit reset time across all providers

Returns:

  • (Time, nil)

    earliest reset time



149
150
151
152
153
154
155
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 149

def next_reset_time
  reset_times = @rate_limit_info.values
    .map { |info| info[:reset_time] }
    .compact
    .select { |t| t > Time.now }
  reset_times.min
end

#record_failure(provider) ⇒ void

This method returns an undefined value.

Record failed request

Parameters:

  • provider (Symbol, String)

    provider name



192
193
194
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 192

def record_failure(provider)
  @adapter.conductor.provider_manager.record_failure(provider.to_sym)
end

#record_success(provider) ⇒ void

This method returns an undefined value.

Record successful request

Parameters:

  • provider (Symbol, String)

    provider name



184
185
186
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 184

def record_success(provider)
  @adapter.conductor.provider_manager.record_success(provider.to_sym)
end

#reset!void

This method returns an undefined value.

Reset all state



243
244
245
246
247
248
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 243

def reset!
  @adapter.reset!
  @rate_limit_info.clear
  @provider_history.clear
  @current_model = nil
end

#statusHash

Get status information

Returns:

  • (Hash)

    status hash



55
56
57
58
59
60
61
62
63
64
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 55

def status
  harness_status = @adapter.status
  {
    current_provider: current_provider,
    current_model: current_model,
    available_providers: available_providers,
    health_status: harness_status[:health_status],
    metrics: harness_status[:metrics]
  }
end

#switch_modelString?

Switch to next model within provider

Returns:

  • (String, nil)

    new model name or nil



224
225
226
227
228
229
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 224

def switch_model
  # AgentHarness doesn't support per-provider model switching yet
  # This is a no-op for now
  Aidp.logger.debug("agent_harness_provider_manager", "Model switching not yet supported via AgentHarness")
  nil
end

#switch_model_for_error(error_type, context = {}) ⇒ String?

Switch model based on error type

Parameters:

  • error_type (Symbol)

    type of error

  • context (Hash) (defaults to: {})

    additional context

Returns:

  • (String, nil)

    new model name or nil



236
237
238
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 236

def switch_model_for_error(error_type, context = {})
  switch_model
end

#switch_provider(reason = "manual_switch", context = {}) ⇒ Symbol?

Switch to next available provider

Parameters:

  • reason (String) (defaults to: "manual_switch")

    reason for switch

  • context (Hash) (defaults to: {})

    additional context

Returns:

  • (Symbol, nil)

    new provider name or nil



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 85

def switch_provider(reason = "manual_switch", context = {})
  old_provider = current_provider

  begin
    new_provider_instance = @adapter.conductor.provider_manager.switch_provider(
      reason: reason.to_sym,
      context: context
    )

    if new_provider_instance
      new_provider = new_provider_instance.class.provider_name
      log_provider_switch(old_provider, new_provider, reason, context)
      Aidp.logger.info("agent_harness_provider_manager", "Provider switched",
        from: old_provider, to: new_provider, reason: reason)
      new_provider
    else
      Aidp.logger.warn("agent_harness_provider_manager", "No provider available for switch",
        reason: reason, current: old_provider)
      nil
    end
  rescue AgentHarness::NoProvidersAvailableError => e
    Aidp.logger.error("agent_harness_provider_manager", "No providers available",
      reason: reason, attempted: e.attempted_providers)
    nil
  end
end

#switch_provider_for_error(error_type, context = {}) ⇒ Symbol?

Switch provider based on error type

Parameters:

  • error_type (Symbol)

    type of error

  • context (Hash) (defaults to: {})

    additional context

Returns:

  • (Symbol, nil)

    new provider name or nil



117
118
119
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 117

def switch_provider_for_error(error_type, context = {})
  switch_provider(error_type.to_s, context)
end

#token_summaryHash

Get token usage summary

Returns:

  • (Hash)

    token usage



253
254
255
# File 'lib/aidp/harness/agent_harness_provider_manager.rb', line 253

def token_summary
  @adapter.token_summary
end