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
-
#api_key_env_var_names ⇒ Array<String>
Environment variable names that the provider’s CLI reads for API key authentication.
-
#api_key_unset_vars ⇒ Array<String>
Environment variable names to unset when the caller supplies its own API key, preventing the CLI from reading stale or conflicting proxy/header variables.
-
#cli_env_overrides ⇒ Hash{String => String}
Provider-specific environment variable overrides that the caller should set when invoking the CLI (e.g. feature flags or sandbox controls).
-
#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.
-
#parse_rate_limit_reset(text) ⇒ Time?
Parse rate-limit reset time from provider error output.
-
#parse_test_error(output:, files: {}) ⇒ Hash?
Parse provider-specific error information from test output.
-
#sandboxed_environment? ⇒ Boolean
Whether the provider is running inside a sandboxed (Docker) environment.
-
#send_message(prompt:, **options) ⇒ Response
Main send_message implementation.
-
#subscription_unset_vars ⇒ Array<String>
Environment variable names to unset when the caller uses subscription-based auth, ensuring the CLI does not pick up API-key or proxy variables that would conflict.
-
#test_command_overrides ⇒ Array<String>
Additional CLI flags for health-check/test invocations.
Methods included from Adapter
#auth_lock_config, #auth_type, #build_mcp_flags, #capabilities, #config_file_content, #configuration_schema, #dangerous_mode_flags, #error_classification_patterns, #error_patterns, #execution_semantics, #fetch_mcp_servers, #health_status, included, metadata_package_name, #noisy_error_patterns, normalize_metadata_installation, normalize_metadata_source_type, normalize_metadata_version_requirement, #notify_hook_content, #session_flags, #smoke_test, #smoke_test_contract, #supported_mcp_transports, #supports_dangerous_mode?, #supports_mcp?, #supports_sessions?, #supports_text_mode?, #supports_token_counting?, #supports_tool_control?, #token_usage_from_api_response, #translate_error, #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
#api_key_env_var_names ⇒ Array<String>
Environment variable names that the provider’s CLI reads for API key authentication.
211 |
# File 'lib/agent_harness/providers/base.rb', line 211 def api_key_env_var_names = [] |
#api_key_unset_vars ⇒ Array<String>
Environment variable names to unset when the caller supplies its own API key, preventing the CLI from reading stale or conflicting proxy/header variables.
217 |
# File 'lib/agent_harness/providers/base.rb', line 217 def api_key_unset_vars = [] |
#cli_env_overrides ⇒ Hash{String => String}
Provider-specific environment variable overrides that the caller should set when invoking the CLI (e.g. feature flags or sandbox controls).
229 |
# File 'lib/agent_harness/providers/base.rb', line 229 def cli_env_overrides = {} |
#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
194 195 196 |
# File 'lib/agent_harness/providers/base.rb', line 194 def display_name name.capitalize end |
#name ⇒ String
Provider name for display
187 188 189 |
# File 'lib/agent_harness/providers/base.rb', line 187 def name self.class.provider_name.to_s end |
#parse_rate_limit_reset(text) ⇒ Time?
Parse rate-limit reset time from provider error output.
Providers that emit rate-limit reset times should override this method (or include RateLimitResetParsing for the common format).
260 261 262 |
# File 'lib/agent_harness/providers/base.rb', line 260 def parse_rate_limit_reset(text) nil end |
#parse_test_error(output:, files: {}) ⇒ Hash?
Parse provider-specific error information from test output
Providers override this to extract structured error details from CLI output or sidecar files produced during a test invocation.
249 250 251 |
# File 'lib/agent_harness/providers/base.rb', line 249 def parse_test_error(output:, files: {}) nil 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.
204 205 206 |
# File 'lib/agent_harness/providers/base.rb', line 204 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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/agent_harness/providers/base.rb', line 104 def (prompt:, **) log_debug("send_message_start", prompt_length: prompt.length, options: .keys) # Text mode: fall back to CLI with tools disabled when the provider # does not have an HTTP text transport. Providers that support text # mode (e.g. Anthropic) override send_message to intercept this # before reaching Base. if [:mode] == :text && !supports_text_mode? log_debug("text_mode_cli_fallback", provider: self.class.provider_name) = .except(:mode).merge(tools: :none) end # Warn when tools option is passed to a provider that doesn't support it if [:tools] && !supports_tool_control? log_debug("tools_option_unsupported", provider: self.class.provider_name, tools: [:tools]) @logger&.warn( "[AgentHarness::#{self.class.provider_name}] tools option is not supported " \ "by this provider and will be ignored" ) end # 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 |
#subscription_unset_vars ⇒ Array<String>
Environment variable names to unset when the caller uses subscription-based auth, ensuring the CLI does not pick up API-key or proxy variables that would conflict.
223 |
# File 'lib/agent_harness/providers/base.rb', line 223 def subscription_unset_vars = [] |
#test_command_overrides ⇒ Array<String>
Additional CLI flags for health-check/test invocations
Providers override this to supply flags that should be appended when the CLI is invoked in a test or smoke-test context.
237 238 239 |
# File 'lib/agent_harness/providers/base.rb', line 237 def test_command_overrides [] end |