Module: Aidp::Providers::Adapter
- Included in:
- Base
- Defined in:
- lib/aidp/providers/adapter.rb
Overview
ProviderAdapter defines the standardized interface that all provider implementations must conform to. This ensures consistent behavior across different AI model providers while allowing for provider-specific implementations.
Design Philosophy:
-
Adapters are stateless; delegate throttling, retries, and escalation to coordinator
-
Store provider-specific regex matchers adjacent to adapters for maintainability
-
Single semantic flags map to provider-specific equivalents
Instance Method Summary collapse
-
#available? ⇒ Boolean
Check if the provider is available on this system.
-
#capabilities ⇒ Hash
Declare provider capabilities.
-
#classify_error(error) ⇒ Symbol
Classify an error into the standardized error taxonomy.
-
#dangerous_mode=(enabled) ⇒ void
Enable or disable dangerous mode.
-
#dangerous_mode_enabled? ⇒ Boolean
Check if dangerous mode is currently enabled.
-
#dangerous_mode_flags ⇒ Array<String>
Get the provider-specific flag(s) for enabling dangerous mode Maps the semantic ‘dangerous: true` flag to provider-specific equivalents.
-
#display_name ⇒ String
Human-friendly display name for UI.
-
#error_metadata(error) ⇒ Hash
Get normalized error metadata.
-
#error_patterns ⇒ Hash<Symbol, Array<Regexp>>
Get error classification regex patterns for this provider.
-
#fetch_mcp_servers ⇒ Array<Hash>
Fetch MCP servers configured for this provider.
-
#health_status ⇒ Hash
Check provider health.
-
#logging_metadata ⇒ Hash
Get logging metadata for this provider.
-
#name ⇒ String
Provider identifier (e.g., “anthropic”, “cursor”, “gemini”).
-
#redact_secrets(message) ⇒ String
Redact secrets from log messages.
-
#retryable_error?(error) ⇒ Boolean
Check if an error is retryable.
-
#send_message(prompt:, session: nil, **options) ⇒ Hash, String
Send a message to the provider and get a response.
-
#supports_dangerous_mode? ⇒ Boolean
Check if the provider supports dangerous/elevated permissions mode.
-
#supports_mcp? ⇒ Boolean
Check if the provider supports Model Context Protocol.
-
#validate_config(config) ⇒ Hash
Validate provider configuration.
Instance Method Details
#available? ⇒ Boolean
Check if the provider is available on this system
55 56 57 |
# File 'lib/aidp/providers/adapter.rb', line 55 def available? true end |
#capabilities ⇒ Hash
Declare provider capabilities
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/aidp/providers/adapter.rb', line 70 def capabilities { reasoning_tiers: [], context_window: 100_000, supports_json_mode: false, supports_tool_use: false, supports_vision: false, supports_file_upload: false } end |
#classify_error(error) ⇒ Symbol
Classify an error into the standardized error taxonomy
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/aidp/providers/adapter.rb', line 132 def classify_error(error) = error..to_s # First check provider-specific patterns error_patterns.each do |category, patterns| patterns.each do |pattern| return category if .match?(pattern) end end # Fall back to ErrorTaxonomy for classification require_relative "error_taxonomy" Aidp::Providers::ErrorTaxonomy.() end |
#dangerous_mode=(enabled) ⇒ void
This method returns an undefined value.
Enable or disable dangerous mode
109 110 111 |
# File 'lib/aidp/providers/adapter.rb', line 109 def dangerous_mode=(enabled) @dangerous_mode_enabled = enabled end |
#dangerous_mode_enabled? ⇒ Boolean
Check if dangerous mode is currently enabled
102 103 104 |
# File 'lib/aidp/providers/adapter.rb', line 102 def dangerous_mode_enabled? @dangerous_mode_enabled ||= false end |
#dangerous_mode_flags ⇒ Array<String>
Get the provider-specific flag(s) for enabling dangerous mode Maps the semantic ‘dangerous: true` flag to provider-specific equivalents
96 97 98 |
# File 'lib/aidp/providers/adapter.rb', line 96 def dangerous_mode_flags [] end |
#display_name ⇒ String
Human-friendly display name for UI
26 27 28 |
# File 'lib/aidp/providers/adapter.rb', line 26 def display_name name end |
#error_metadata(error) ⇒ Hash
Get normalized error metadata
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/aidp/providers/adapter.rb', line 150 def (error) { provider: name, error_category: classify_error(error), error_class: error.class.name, message: redact_secrets(error.), timestamp: Time.now.iso8601, retryable: retryable_error?(error) } end |
#error_patterns ⇒ Hash<Symbol, Array<Regexp>>
Get error classification regex patterns for this provider
125 126 127 |
# File 'lib/aidp/providers/adapter.rb', line 125 def error_patterns {} end |
#fetch_mcp_servers ⇒ Array<Hash>
Fetch MCP servers configured for this provider
49 50 51 |
# File 'lib/aidp/providers/adapter.rb', line 49 def fetch_mcp_servers [] end |
#health_status ⇒ Hash
Check provider health
229 230 231 232 233 234 235 236 |
# File 'lib/aidp/providers/adapter.rb', line 229 def health_status { provider: name, available: available?, healthy: available?, timestamp: Time.now.iso8601 } end |
#logging_metadata ⇒ Hash
Get logging metadata for this provider
173 174 175 176 177 178 179 180 181 |
# File 'lib/aidp/providers/adapter.rb', line 173 def { provider: name, display_name: display_name, supports_mcp: supports_mcp?, available: available?, dangerous_mode: dangerous_mode_enabled? } end |
#name ⇒ String
Provider identifier (e.g., “anthropic”, “cursor”, “gemini”)
20 21 22 |
# File 'lib/aidp/providers/adapter.rb', line 20 def name raise NotImplementedError, "#{self.class} must implement #name" end |
#redact_secrets(message) ⇒ String
Redact secrets from log messages
186 187 188 189 190 191 192 193 |
# File 'lib/aidp/providers/adapter.rb', line 186 def redact_secrets() # Redact common secret patterns = .gsub(/api[_-]?key[:\s=]+[^\s&]+/i, "api_key=[REDACTED]") = .gsub(/token[:\s=]+[^\s&]+/i, "token=[REDACTED]") = .gsub(/password[:\s=]+[^\s&]+/i, "password=[REDACTED]") = .gsub(/bearer\s+[^\s&]+/i, "bearer [REDACTED]") .gsub(/sk-[a-zA-Z0-9_-]{20,}/i, "sk-[REDACTED]") end |
#retryable_error?(error) ⇒ Boolean
Check if an error is retryable
164 165 166 167 |
# File 'lib/aidp/providers/adapter.rb', line 164 def retryable_error?(error) category = classify_error(error) [:transient].include?(category) end |
#send_message(prompt:, session: nil, **options) ⇒ Hash, String
Send a message to the provider and get a response
35 36 37 |
# File 'lib/aidp/providers/adapter.rb', line 35 def (prompt:, session: nil, **) raise NotImplementedError, "#{self.class} must implement #send_message" end |
#supports_dangerous_mode? ⇒ Boolean
Check if the provider supports dangerous/elevated permissions mode
85 86 87 |
# File 'lib/aidp/providers/adapter.rb', line 85 def supports_dangerous_mode? false end |
#supports_mcp? ⇒ Boolean
Check if the provider supports Model Context Protocol
43 44 45 |
# File 'lib/aidp/providers/adapter.rb', line 43 def supports_mcp? false end |
#validate_config(config) ⇒ Hash
Validate provider configuration
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/aidp/providers/adapter.rb', line 200 def validate_config(config) errors = [] warnings = [] # Validate required fields unless config[:type] errors << "Provider type is required" end unless ["usage_based", "subscription", "passthrough"].include?(config[:type]) errors << "Provider type must be one of: usage_based, subscription, passthrough" end # Validate models if present if config[:models] && !config[:models].is_a?(Array) errors << "Models must be an array" end { valid: errors.empty?, errors: errors, warnings: warnings } end |