Class: AgentHarness::Providers::Base
- Inherits:
-
Object
- Object
- AgentHarness::Providers::Base
- Includes:
- Adapter
- Defined in:
- lib/agent_harness/providers/base.rb
Overview
Base class for all providers
Provides common functionality for provider implementations including command execution, error handling, and response parsing.
Direct Known Subclasses
Aider, Anthropic, Codex, Cursor, Gemini, GithubCopilot, Kilocode, MistralVibe, Opencode
Constant Summary collapse
- DEFAULT_SMOKE_TEST_CONTRACT =
{ prompt: "Reply with exactly OK.", expected_output: "OK", timeout: 30, require_output: true, success_message: "Smoke test passed" }.freeze
- COMMON_ERROR_PATTERNS =
Common error patterns shared across providers that use standard HTTP-style error responses. Providers with unique patterns (e.g. Anthropic, GitHub Copilot) override error_patterns entirely.
{ rate_limited: [ /rate.?limit/i, /too.?many.?requests/i, /\b429\b/ ], auth_expired: [ /invalid.*api.*key/i, /unauthorized/i, /authentication/i ], quota_exceeded: [ /quota.*exceeded/i, /insufficient.*quota/i, /billing/i ], transient: [ /timeout/i, /connection.*error/i, /service.*unavailable/i, /\b503\b/, /\b502\b/ ] }.tap { |patterns| patterns.each_value(&:freeze) }.freeze
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#executor ⇒ Object
Returns the value of attribute executor.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
Class Method Summary collapse
Instance Method Summary collapse
-
#configure(options = {}) ⇒ self
Configure the provider instance.
-
#display_name ⇒ String
Human-friendly display name.
-
#initialize(config: nil, executor: nil, logger: nil) ⇒ Base
constructor
Initialize the provider.
-
#name ⇒ String
Provider name for display.
-
#sandboxed_environment? ⇒ Boolean
Whether the provider is running inside a sandboxed (Docker) environment.
-
#send_message(prompt:, **options) ⇒ Response
Main send_message implementation.
Methods included from Adapter
#auth_type, #build_mcp_flags, #capabilities, #configuration_schema, #dangerous_mode_flags, #error_patterns, #execution_semantics, #fetch_mcp_servers, #health_status, included, metadata_package_name, normalize_metadata_installation, normalize_metadata_source_type, normalize_metadata_version_requirement, #parse_rate_limit_reset, #session_flags, #smoke_test, #smoke_test_contract, #supported_mcp_transports, #supports_dangerous_mode?, #supports_mcp?, #supports_sessions?, #validate_config, #validate_mcp_servers!
Constructor Details
#initialize(config: nil, executor: nil, logger: nil) ⇒ Base
Initialize the provider
79 80 81 82 83 |
# File 'lib/agent_harness/providers/base.rb', line 79 def initialize(config: nil, executor: nil, logger: nil) @config = config || ProviderConfig.new(self.class.provider_name) @executor = executor || AgentHarness.configuration.command_executor @logger = logger || AgentHarness.logger end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
65 66 67 |
# File 'lib/agent_harness/providers/base.rb', line 65 def config @config end |
#executor ⇒ Object
Returns the value of attribute executor.
66 67 68 |
# File 'lib/agent_harness/providers/base.rb', line 66 def executor @executor end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
65 66 67 |
# File 'lib/agent_harness/providers/base.rb', line 65 def logger @logger end |
Class Method Details
.smoke_test_contract ⇒ Object
69 70 71 |
# File 'lib/agent_harness/providers/base.rb', line 69 def smoke_test_contract nil end |
Instance Method Details
#configure(options = {}) ⇒ self
Configure the provider instance
89 90 91 92 |
# File 'lib/agent_harness/providers/base.rb', line 89 def configure( = {}) @config.merge!() self end |
#display_name ⇒ String
Human-friendly display name
174 175 176 |
# File 'lib/agent_harness/providers/base.rb', line 174 def display_name name.capitalize end |
#name ⇒ String
Provider name for display
167 168 169 |
# File 'lib/agent_harness/providers/base.rb', line 167 def name self.class.provider_name.to_s end |
#sandboxed_environment? ⇒ Boolean
Whether the provider is running inside a sandboxed (Docker) environment
Providers can use this to adjust execution flags, e.g. skipping nested sandboxing when already inside a container.
184 185 186 |
# File 'lib/agent_harness/providers/base.rb', line 184 def sandboxed_environment? @executor.is_a?(DockerCommandExecutor) end |
#send_message(prompt:, **options) ⇒ Response
Main send_message implementation
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/agent_harness/providers/base.rb', line 104 def (prompt:, **) log_debug("send_message_start", prompt_length: prompt.length, options: .keys) # Coerce provider_runtime from Hash if needed = normalize_provider_runtime() # Normalize and validate MCP servers = normalize_mcp_servers() validate_mcp_servers!([:mcp_servers]) if [:mcp_servers]&.any? # Build command command = build_command(prompt, ) preparation = build_execution_preparation() # Calculate timeout timeout = [:timeout] || @config.timeout || default_timeout # Execute command start_time = Time.now result = execute_with_timeout( command, timeout: timeout, env: build_env(), preparation: preparation, **() ) duration = Time.now - start_time # Parse response response = parse_response(result, duration: duration) runtime = [:provider_runtime] # Runtime model is a per-request override and always takes precedence # over both the config-level model and whatever parse_response returned. # This is intentional: callers use runtime overrides to route a single # provider instance through different backends on each request. if runtime&.model response = Response.new( output: response.output, exit_code: response.exit_code, duration: response.duration, provider: response.provider, model: runtime.model, tokens: response.tokens, metadata: response., error: response.error ) end # Track tokens track_tokens(response) if response.tokens log_debug("send_message_complete", duration: duration, tokens: response.tokens) response rescue McpConfigurationError, McpUnsupportedError, McpTransportUnsupportedError raise rescue => e handle_error(e, prompt: prompt, options: ) end |