Class: Aidp::Config
- Inherits:
-
Object
- Object
- Aidp::Config
- Defined in:
- lib/aidp/config.rb
Overview
Configuration management for both execute and analyze modes
Constant Summary collapse
- DEFAULT_HARNESS_CONFIG =
Default configuration for harness
{ harness: { max_retries: 2, default_provider: "cursor", fallback_providers: ["cursor"], no_api_keys_required: false, provider_weights: { "cursor" => 3, "anthropic" => 2 }, circuit_breaker: { enabled: true, failure_threshold: 5, timeout: 300, half_open_max_calls: 3 }, retry: { enabled: true, max_attempts: 3, base_delay: 1.0, max_delay: 60.0, exponential_base: 2.0, jitter: true }, rate_limit: { enabled: true, default_reset_time: 3600, burst_limit: 10, sustained_limit: 5 }, load_balancing: { enabled: true, strategy: "weighted_round_robin", health_check_interval: 30, unhealthy_threshold: 3 }, model_switching: { enabled: true, auto_switch_on_error: true, auto_switch_on_rate_limit: true, fallback_strategy: "sequential" }, health_check: { enabled: true, interval: 60, timeout: 10, failure_threshold: 3, success_threshold: 2 }, metrics: { enabled: true, retention_days: 30, aggregation_interval: 300, export_interval: 3600 }, session: { enabled: true, timeout: 1800, sticky_sessions: true, session_affinity: "provider_model" } }, providers: { cursor: { type: "subscription", priority: 1, model_family: "auto", default_flags: [], models: ["cursor-default", "cursor-fast", "cursor-precise"], model_weights: { "cursor-default" => 3, "cursor-fast" => 2, "cursor-precise" => 1 }, models_config: { "cursor-default" => { flags: [], timeout: 600 }, "cursor-fast" => { flags: ["--fast"], timeout: 300 }, "cursor-precise" => { flags: ["--precise"], timeout: 900 } }, features: { file_upload: true, code_generation: true, analysis: true }, monitoring: { enabled: true, metrics_interval: 60 } }, anthropic: { type: "usage_based", priority: 2, model_family: "claude", max_tokens: 100_000, default_flags: ["--dangerously-skip-permissions"], models: ["claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022"], model_weights: { "claude-3-5-sonnet-20241022" => 3, "claude-3-5-haiku-20241022" => 2 }, models_config: { "claude-3-5-sonnet-20241022" => { flags: ["--dangerously-skip-permissions"], max_tokens: 200_000, timeout: 300 }, "claude-3-5-haiku-20241022" => { flags: ["--dangerously-skip-permissions"], max_tokens: 200_000, timeout: 180 } }, auth: { api_key_env: "ANTHROPIC_API_KEY" }, endpoints: { default: "https://api.anthropic.com/v1/messages" }, features: { file_upload: true, code_generation: true, analysis: true, vision: true }, monitoring: { enabled: true, metrics_interval: 60 } } }, skills: { search_paths: [], default_provider_filter: true, enable_custom_skills: true }, waterfall: { enabled: true, docs_directory: ".aidp/docs", generate_decisions_md: true, gantt_format: "mermaid", wbs_phases: [ "Requirements", "Design", "Implementation", "Testing", "Deployment" ], effort_estimation: { method: "llm_relative", units: "story_points" }, persona_assignment: { method: "zfc_automatic", allow_parallel: true } } }.freeze
Class Method Summary collapse
-
.agile_config(project_dir = Dir.pwd) ⇒ Object
Get agile configuration.
- .aidp_dir(project_dir = Dir.pwd) ⇒ Object
- .config_dir(project_dir = Dir.pwd) ⇒ Object
-
.config_exists?(project_dir = Dir.pwd) ⇒ Boolean
Check if configuration file exists.
-
.config_file(project_dir = Dir.pwd) ⇒ Object
Expose path methods for convenience.
-
.configured_providers(project_dir = Dir.pwd) ⇒ Object
Get all configured providers.
-
.create_example_config(project_dir = Dir.pwd) ⇒ Object
Create example configuration file.
-
.harness_config(project_dir = Dir.pwd) ⇒ Object
Get harness configuration.
- .load(project_dir = Dir.pwd) ⇒ Object
-
.load_harness_config(project_dir = Dir.pwd) ⇒ Object
Load harness configuration with defaults.
-
.provider_config(provider_name, project_dir = Dir.pwd) ⇒ Object
Get provider configuration.
-
.skills_config(project_dir = Dir.pwd) ⇒ Object
Get skills configuration.
-
.tool_metadata_config(project_dir = Dir.pwd) ⇒ Object
Get tool metadata configuration.
-
.validate_harness_config(config, project_dir = Dir.pwd) ⇒ Object
Validate harness configuration.
-
.waterfall_config(project_dir = Dir.pwd) ⇒ Object
Get waterfall configuration.
Class Method Details
.agile_config(project_dir = Dir.pwd) ⇒ Object
Get agile configuration
274 275 276 277 278 279 280 |
# File 'lib/aidp/config.rb', line 274 def self.agile_config(project_dir = Dir.pwd) config = load_harness_config(project_dir) agile_section = config[:agile] || config["agile"] || {} # Convert string keys to symbols for consistency symbolize_keys(agile_section) end |
.aidp_dir(project_dir = Dir.pwd) ⇒ Object
350 351 352 |
# File 'lib/aidp/config.rb', line 350 def self.aidp_dir(project_dir = Dir.pwd) ConfigPaths.aidp_dir(project_dir) end |
.config_dir(project_dir = Dir.pwd) ⇒ Object
346 347 348 |
# File 'lib/aidp/config.rb', line 346 def self.config_dir(project_dir = Dir.pwd) ConfigPaths.config_dir(project_dir) end |
.config_exists?(project_dir = Dir.pwd) ⇒ Boolean
Check if configuration file exists
292 293 294 |
# File 'lib/aidp/config.rb', line 292 def self.config_exists?(project_dir = Dir.pwd) ConfigPaths.config_exists?(project_dir) end |
.config_file(project_dir = Dir.pwd) ⇒ Object
Expose path methods for convenience
342 343 344 |
# File 'lib/aidp/config.rb', line 342 def self.config_file(project_dir = Dir.pwd) ConfigPaths.config_file(project_dir) end |
.configured_providers(project_dir = Dir.pwd) ⇒ Object
Get all configured providers
249 250 251 252 253 |
# File 'lib/aidp/config.rb', line 249 def self.configured_providers(project_dir = Dir.pwd) config = load_harness_config(project_dir) providers_section = config[:providers] || config["providers"] || {} providers_section.keys.map(&:to_s) end |
.create_example_config(project_dir = Dir.pwd) ⇒ Object
Create example configuration file
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/aidp/config.rb', line 297 def self.create_example_config(project_dir = Dir.pwd) config_path = ConfigPaths.config_file(project_dir) return false if File.exist?(config_path) ConfigPaths.ensure_config_dir(project_dir) example_config = { harness: { max_retries: 2, default_provider: "cursor", fallback_providers: ["cursor"], no_api_keys_required: false }, providers: { cursor: { type: "subscription", default_flags: [] }, claude: { type: "usage_based", max_tokens: 100_000, default_flags: ["--dangerously-skip-permissions"] }, gemini: { type: "usage_based", max_tokens: 50_000, default_flags: [] } }, agile: { mvp_first: true, feedback_loops: true, auto_iteration: false, research_enabled: true, marketing_enabled: true, legacy_analysis: true, personas: ["product_manager", "ux_researcher", "architect", "senior_developer", "qa_engineer", "devops_engineer", "tech_writer", "marketing_strategist"] } } File.write(config_path, YAML.dump(example_config)) true end |
.harness_config(project_dir = Dir.pwd) ⇒ Object
Get harness configuration
231 232 233 234 235 236 237 |
# File 'lib/aidp/config.rb', line 231 def self.harness_config(project_dir = Dir.pwd) config = load_harness_config(project_dir) harness_section = config[:harness] || config["harness"] || {} # Convert string keys to symbols for consistency symbolize_keys(harness_section) end |
.load(project_dir = Dir.pwd) ⇒ Object
177 178 179 180 181 182 183 184 185 |
# File 'lib/aidp/config.rb', line 177 def self.load(project_dir = Dir.pwd) config_file = ConfigPaths.config_file(project_dir) if File.exist?(config_file) load_yaml_config(config_file) else {} end end |
.load_harness_config(project_dir = Dir.pwd) ⇒ Object
Load harness configuration with defaults
188 189 190 191 |
# File 'lib/aidp/config.rb', line 188 def self.load_harness_config(project_dir = Dir.pwd) config = load(project_dir) merge_harness_defaults(config) end |
.provider_config(provider_name, project_dir = Dir.pwd) ⇒ Object
Get provider configuration
240 241 242 243 244 245 246 |
# File 'lib/aidp/config.rb', line 240 def self.provider_config(provider_name, project_dir = Dir.pwd) config = load_harness_config(project_dir) providers_section = config[:providers] || config["providers"] || {} provider_config = providers_section[provider_name.to_s] || providers_section[provider_name.to_sym] || {} symbolize_keys(provider_config) end |
.skills_config(project_dir = Dir.pwd) ⇒ Object
Get skills configuration
256 257 258 259 260 261 262 |
# File 'lib/aidp/config.rb', line 256 def self.skills_config(project_dir = Dir.pwd) config = load_harness_config(project_dir) skills_section = config[:skills] || config["skills"] || {} # Convert string keys to symbols for consistency symbolize_keys(skills_section) end |
.tool_metadata_config(project_dir = Dir.pwd) ⇒ Object
Get tool metadata configuration
283 284 285 286 287 288 289 |
# File 'lib/aidp/config.rb', line 283 def self.(project_dir = Dir.pwd) config = load_harness_config(project_dir) = config[:tool_metadata] || config["tool_metadata"] || {} # Convert string keys to symbols for consistency symbolize_keys() end |
.validate_harness_config(config, project_dir = Dir.pwd) ⇒ Object
Validate harness configuration
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/aidp/config.rb', line 194 def self.validate_harness_config(config, project_dir = Dir.pwd) errors = [] # Validate harness section (check the merged config, not original) harness_config = config[:harness] || config["harness"] if harness_config unless harness_config[:default_provider] || harness_config["default_provider"] errors << "Default provider not specified in harness config" end end # Validate providers section using config_validator # Only validate providers that exist in the original YAML file, not merged defaults original_config = load(project_dir) original_providers = original_config[:providers] || original_config["providers"] if original_providers&.any? require_relative "harness/config_validator" validator = Aidp::Harness::ConfigValidator.new(project_dir) # Only validate if the config file exists # Skip validation if we're validating a simple test config (no project_dir specified or simple config) should_validate = validator.config_exists? && (project_dir != Dir.pwd || config[:harness]&.keys&.size.to_i > 2) if should_validate original_providers.each do |provider_name, _provider_config| validation_result = validator.validate_provider(provider_name) unless validation_result[:valid] errors.concat(validation_result[:errors]) end end end end errors end |
.waterfall_config(project_dir = Dir.pwd) ⇒ Object
Get waterfall configuration
265 266 267 268 269 270 271 |
# File 'lib/aidp/config.rb', line 265 def self.waterfall_config(project_dir = Dir.pwd) config = load_harness_config(project_dir) waterfall_section = config[:waterfall] || config["waterfall"] || {} # Convert string keys to symbols for consistency symbolize_keys(waterfall_section) end |