aidp 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -214
  3. data/bin/aidp +1 -1
  4. data/lib/aidp/analysis/kb_inspector.rb +38 -23
  5. data/lib/aidp/analysis/seams.rb +2 -31
  6. data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +0 -13
  7. data/lib/aidp/analysis/tree_sitter_scan.rb +3 -20
  8. data/lib/aidp/analyze/error_handler.rb +2 -75
  9. data/lib/aidp/analyze/json_file_storage.rb +292 -0
  10. data/lib/aidp/analyze/progress.rb +12 -0
  11. data/lib/aidp/analyze/progress_visualizer.rb +12 -17
  12. data/lib/aidp/analyze/ruby_maat_integration.rb +13 -31
  13. data/lib/aidp/analyze/runner.rb +256 -87
  14. data/lib/aidp/cli/jobs_command.rb +100 -432
  15. data/lib/aidp/cli.rb +309 -239
  16. data/lib/aidp/config.rb +298 -10
  17. data/lib/aidp/debug_logger.rb +195 -0
  18. data/lib/aidp/debug_mixin.rb +187 -0
  19. data/lib/aidp/execute/progress.rb +9 -0
  20. data/lib/aidp/execute/runner.rb +221 -40
  21. data/lib/aidp/execute/steps.rb +17 -7
  22. data/lib/aidp/execute/workflow_selector.rb +211 -0
  23. data/lib/aidp/harness/completion_checker.rb +268 -0
  24. data/lib/aidp/harness/condition_detector.rb +1526 -0
  25. data/lib/aidp/harness/config_loader.rb +373 -0
  26. data/lib/aidp/harness/config_manager.rb +382 -0
  27. data/lib/aidp/harness/config_schema.rb +1006 -0
  28. data/lib/aidp/harness/config_validator.rb +355 -0
  29. data/lib/aidp/harness/configuration.rb +477 -0
  30. data/lib/aidp/harness/enhanced_runner.rb +494 -0
  31. data/lib/aidp/harness/error_handler.rb +616 -0
  32. data/lib/aidp/harness/provider_config.rb +423 -0
  33. data/lib/aidp/harness/provider_factory.rb +306 -0
  34. data/lib/aidp/harness/provider_manager.rb +1269 -0
  35. data/lib/aidp/harness/provider_type_checker.rb +88 -0
  36. data/lib/aidp/harness/runner.rb +411 -0
  37. data/lib/aidp/harness/state/errors.rb +28 -0
  38. data/lib/aidp/harness/state/metrics.rb +219 -0
  39. data/lib/aidp/harness/state/persistence.rb +128 -0
  40. data/lib/aidp/harness/state/provider_state.rb +132 -0
  41. data/lib/aidp/harness/state/ui_state.rb +68 -0
  42. data/lib/aidp/harness/state/workflow_state.rb +123 -0
  43. data/lib/aidp/harness/state_manager.rb +586 -0
  44. data/lib/aidp/harness/status_display.rb +888 -0
  45. data/lib/aidp/harness/ui/base.rb +16 -0
  46. data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
  47. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
  48. data/lib/aidp/harness/ui/error_handler.rb +132 -0
  49. data/lib/aidp/harness/ui/frame_manager.rb +361 -0
  50. data/lib/aidp/harness/ui/job_monitor.rb +500 -0
  51. data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
  52. data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
  53. data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
  54. data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
  55. data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
  56. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
  57. data/lib/aidp/harness/ui/progress_display.rb +280 -0
  58. data/lib/aidp/harness/ui/question_collector.rb +141 -0
  59. data/lib/aidp/harness/ui/spinner_group.rb +184 -0
  60. data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
  61. data/lib/aidp/harness/ui/status_manager.rb +312 -0
  62. data/lib/aidp/harness/ui/status_widget.rb +280 -0
  63. data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
  64. data/lib/aidp/harness/user_interface.rb +2381 -0
  65. data/lib/aidp/provider_manager.rb +131 -7
  66. data/lib/aidp/providers/anthropic.rb +28 -103
  67. data/lib/aidp/providers/base.rb +170 -0
  68. data/lib/aidp/providers/cursor.rb +52 -181
  69. data/lib/aidp/providers/gemini.rb +24 -107
  70. data/lib/aidp/providers/macos_ui.rb +99 -5
  71. data/lib/aidp/providers/opencode.rb +194 -0
  72. data/lib/aidp/storage/csv_storage.rb +172 -0
  73. data/lib/aidp/storage/file_manager.rb +214 -0
  74. data/lib/aidp/storage/json_storage.rb +140 -0
  75. data/lib/aidp/version.rb +1 -1
  76. data/lib/aidp.rb +54 -39
  77. data/templates/COMMON/AGENT_BASE.md +11 -0
  78. data/templates/EXECUTE/00_PRD.md +4 -4
  79. data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
  80. data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
  81. data/templates/EXECUTE/08_TASKS.md +4 -4
  82. data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
  83. data/templates/README.md +279 -0
  84. data/templates/aidp-development.yml.example +373 -0
  85. data/templates/aidp-minimal.yml.example +48 -0
  86. data/templates/aidp-production.yml.example +475 -0
  87. data/templates/aidp.yml.example +598 -0
  88. metadata +93 -69
  89. data/lib/aidp/analyze/agent_personas.rb +0 -71
  90. data/lib/aidp/analyze/agent_tool_executor.rb +0 -439
  91. data/lib/aidp/analyze/data_retention_manager.rb +0 -421
  92. data/lib/aidp/analyze/database.rb +0 -260
  93. data/lib/aidp/analyze/dependencies.rb +0 -335
  94. data/lib/aidp/analyze/export_manager.rb +0 -418
  95. data/lib/aidp/analyze/focus_guidance.rb +0 -517
  96. data/lib/aidp/analyze/incremental_analyzer.rb +0 -533
  97. data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
  98. data/lib/aidp/analyze/large_analysis_progress.rb +0 -499
  99. data/lib/aidp/analyze/memory_manager.rb +0 -339
  100. data/lib/aidp/analyze/metrics_storage.rb +0 -336
  101. data/lib/aidp/analyze/parallel_processor.rb +0 -454
  102. data/lib/aidp/analyze/performance_optimizer.rb +0 -691
  103. data/lib/aidp/analyze/repository_chunker.rb +0 -697
  104. data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
  105. data/lib/aidp/analyze/storage.rb +0 -655
  106. data/lib/aidp/analyze/tool_configuration.rb +0 -441
  107. data/lib/aidp/analyze/tool_modernization.rb +0 -750
  108. data/lib/aidp/database/pg_adapter.rb +0 -148
  109. data/lib/aidp/database_config.rb +0 -69
  110. data/lib/aidp/database_connection.rb +0 -72
  111. data/lib/aidp/job_manager.rb +0 -41
  112. data/lib/aidp/jobs/base_job.rb +0 -45
  113. data/lib/aidp/jobs/provider_execution_job.rb +0 -83
  114. data/lib/aidp/project_detector.rb +0 -117
  115. data/lib/aidp/providers/agent_supervisor.rb +0 -348
  116. data/lib/aidp/providers/supervised_base.rb +0 -317
  117. data/lib/aidp/providers/supervised_cursor.rb +0 -22
  118. data/lib/aidp/sync.rb +0 -13
  119. data/lib/aidp/workspace.rb +0 -19
@@ -0,0 +1,423 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "config_manager"
4
+ require_relative "provider_type_checker"
5
+
6
+ module Aidp
7
+ module Harness
8
+ # Provider-specific configuration management
9
+ class ProviderConfig
10
+ include ProviderTypeChecker
11
+
12
+ def initialize(provider_name, config_manager = nil)
13
+ @provider_name = provider_name.to_s
14
+ @config_manager = config_manager || ConfigManager.new
15
+ @provider_config = nil
16
+ @harness_config = nil
17
+ @cache_timestamp = nil
18
+ end
19
+
20
+ # Get complete provider configuration
21
+ def get_config(options = {})
22
+ return @provider_config if @provider_config && !options[:force_reload] && cache_valid?
23
+
24
+ @provider_config = @config_manager.get_provider_config(@provider_name, options)
25
+ @harness_config = @config_manager.get_harness_config(options)
26
+ @cache_timestamp = Time.now
27
+
28
+ @provider_config || {}
29
+ end
30
+
31
+ # Get provider type (usage_based, subscription)
32
+ def get_type(options = {})
33
+ config = get_config(options)
34
+ config[:type] || config["type"] || "subscription"
35
+ end
36
+
37
+ # Provider type checking methods are now provided by ProviderTypeChecker module
38
+
39
+ # Get provider priority
40
+ def get_priority(options = {})
41
+ config = get_config(options)
42
+ config[:priority] || config["priority"] || 1
43
+ end
44
+
45
+ # Get provider models
46
+ def get_models(options = {})
47
+ config = get_config(options)
48
+ models = config[:models] || config["models"] || []
49
+ models.map(&:to_s)
50
+ end
51
+
52
+ # Get default model
53
+ def get_default_model(options = {})
54
+ models = get_models(options)
55
+ models.first
56
+ end
57
+
58
+ # Get model weights
59
+ def get_model_weights(options = {})
60
+ config = get_config(options)
61
+ weights = config[:model_weights] || config["model_weights"] || {}
62
+ weights.transform_values { |weight| [weight.to_i, 1].max }
63
+ end
64
+
65
+ # Get model configuration
66
+ def get_model_config(model_name, options = {})
67
+ config = get_config(options)
68
+ models_config = config[:models_config] || config["models_config"] || {}
69
+ model_config = models_config[model_name.to_sym] || models_config[model_name.to_s] || {}
70
+
71
+ {
72
+ flags: model_config[:flags] || model_config["flags"] || [],
73
+ max_tokens: model_config[:max_tokens] || model_config["max_tokens"],
74
+ timeout: model_config[:timeout] || model_config["timeout"],
75
+ temperature: model_config[:temperature] || model_config["temperature"],
76
+ max_retries: model_config[:max_retries] || model_config["max_retries"]
77
+ }
78
+ end
79
+
80
+ # Get provider features
81
+ def get_features(options = {})
82
+ config = get_config(options)
83
+ features = config[:features] || config["features"] || {}
84
+
85
+ {
86
+ file_upload: features[:file_upload] == true,
87
+ code_generation: features[:code_generation] != false,
88
+ analysis: features[:analysis] != false,
89
+ vision: features[:vision] == true,
90
+ streaming: features[:streaming] != false,
91
+ function_calling: features[:function_calling] == true,
92
+ tool_use: features[:tool_use] == true
93
+ }
94
+ end
95
+
96
+ # Check if provider supports feature
97
+ def supports_feature?(feature, options = {})
98
+ features = get_features(options)
99
+ features[feature.to_sym] == true
100
+ end
101
+
102
+ # Get provider capabilities
103
+ def get_capabilities(options = {})
104
+ features = get_features(options)
105
+ capabilities = []
106
+
107
+ capabilities << "file_upload" if features[:file_upload]
108
+ capabilities << "code_generation" if features[:code_generation]
109
+ capabilities << "analysis" if features[:analysis]
110
+ capabilities << "vision" if features[:vision]
111
+ capabilities << "streaming" if features[:streaming]
112
+ capabilities << "function_calling" if features[:function_calling]
113
+ capabilities << "tool_use" if features[:tool_use]
114
+
115
+ capabilities
116
+ end
117
+
118
+ # Get provider max tokens
119
+ def get_max_tokens(options = {})
120
+ config = get_config(options)
121
+ config[:max_tokens] || config["max_tokens"]
122
+ end
123
+
124
+ # Get provider timeout
125
+ def get_timeout(options = {})
126
+ config = get_config(options)
127
+ config[:timeout] || config["timeout"] || 300
128
+ end
129
+
130
+ # Get provider default flags
131
+ def get_default_flags(options = {})
132
+ config = get_config(options)
133
+ flags = config[:default_flags] || config["default_flags"] || []
134
+ flags.map(&:to_s)
135
+ end
136
+
137
+ # Get model-specific flags
138
+ def get_model_flags(model_name, options = {})
139
+ model_config = get_model_config(model_name, options)
140
+ model_config[:flags] || []
141
+ end
142
+
143
+ # Get combined flags (default + model-specific)
144
+ def get_combined_flags(model_name = nil, options = {})
145
+ default_flags = get_default_flags(options)
146
+ model_flags = model_name ? get_model_flags(model_name, options) : []
147
+
148
+ (default_flags + model_flags).uniq
149
+ end
150
+
151
+ # Get authentication configuration
152
+ def get_auth_config(options = {})
153
+ config = get_config(options)
154
+ auth = config[:auth] || config["auth"] || {}
155
+
156
+ {
157
+ api_key_env: auth[:api_key_env] || auth["api_key_env"],
158
+ api_key: auth[:api_key] || auth["api_key"],
159
+ api_key_file: auth[:api_key_file] || auth["api_key_file"],
160
+ username: auth[:username] || auth["username"],
161
+ password: auth[:password] || auth["password"],
162
+ token: auth[:token] || auth["token"],
163
+ credentials_file: auth[:credentials_file] || auth["credentials_file"]
164
+ }
165
+ end
166
+
167
+ # Get API key from environment or config
168
+ def get_api_key(options = {})
169
+ auth_config = get_auth_config(options)
170
+
171
+ # Try environment variable first
172
+ if auth_config[:api_key_env]
173
+ api_key = ENV[auth_config[:api_key_env]]
174
+ return api_key if api_key && !api_key.empty?
175
+ end
176
+
177
+ # Try direct config
178
+ auth_config[:api_key]
179
+ end
180
+
181
+ # Get endpoints configuration
182
+ def get_endpoints(options = {})
183
+ config = get_config(options)
184
+ endpoints = config[:endpoints] || config["endpoints"] || {}
185
+
186
+ {
187
+ default: endpoints[:default] || endpoints["default"],
188
+ chat: endpoints[:chat] || endpoints["chat"],
189
+ completion: endpoints[:completion] || endpoints["completion"],
190
+ embedding: endpoints[:embedding] || endpoints["embedding"],
191
+ vision: endpoints[:vision] || endpoints["vision"]
192
+ }
193
+ end
194
+
195
+ # Get default endpoint
196
+ def get_default_endpoint(options = {})
197
+ endpoints = get_endpoints(options)
198
+ endpoints[:default]
199
+ end
200
+
201
+ # Get monitoring configuration
202
+ def get_monitoring_config(options = {})
203
+ config = get_config(options)
204
+ monitoring = config[:monitoring] || config["monitoring"] || {}
205
+
206
+ {
207
+ enabled: monitoring[:enabled] != false,
208
+ metrics_interval: monitoring[:metrics_interval] || 60,
209
+ health_check_interval: monitoring[:health_check_interval] || 300,
210
+ log_level: monitoring[:log_level] || "info",
211
+ log_requests: monitoring[:log_requests] != false,
212
+ log_responses: monitoring[:log_responses] == true
213
+ }
214
+ end
215
+
216
+ # Get rate limiting configuration
217
+ def get_rate_limit_config(options = {})
218
+ config = get_config(options)
219
+ rate_limit = config[:rate_limit] || config["rate_limit"] || {}
220
+
221
+ {
222
+ enabled: rate_limit[:enabled] != false,
223
+ requests_per_minute: rate_limit[:requests_per_minute] || 60,
224
+ requests_per_hour: rate_limit[:requests_per_hour] || 1000,
225
+ tokens_per_minute: rate_limit[:tokens_per_minute],
226
+ tokens_per_hour: rate_limit[:tokens_per_hour],
227
+ burst_limit: rate_limit[:burst_limit] || 10,
228
+ reset_time: rate_limit[:reset_time] || 3600
229
+ }
230
+ end
231
+
232
+ # Get retry configuration
233
+ def get_retry_config(options = {})
234
+ config = get_config(options)
235
+ retry_config = config[:retry] || config["retry"] || {}
236
+
237
+ {
238
+ enabled: retry_config[:enabled] != false,
239
+ max_attempts: retry_config[:max_attempts] || 3,
240
+ base_delay: retry_config[:base_delay] || 1.0,
241
+ max_delay: retry_config[:max_delay] || 60.0,
242
+ exponential_base: retry_config[:exponential_base] || 2.0,
243
+ jitter: retry_config[:jitter] != false,
244
+ retry_on_rate_limit: retry_config[:retry_on_rate_limit] == true
245
+ }
246
+ end
247
+
248
+ # Get circuit breaker configuration
249
+ def get_circuit_breaker_config(options = {})
250
+ config = get_config(options)
251
+ cb_config = config[:circuit_breaker] || config["circuit_breaker"] || {}
252
+
253
+ {
254
+ enabled: cb_config[:enabled] != false,
255
+ failure_threshold: cb_config[:failure_threshold] || 5,
256
+ timeout: cb_config[:timeout] || 300,
257
+ half_open_max_calls: cb_config[:half_open_max_calls] || 3,
258
+ success_threshold: cb_config[:success_threshold] || 2
259
+ }
260
+ end
261
+
262
+ # Get cost configuration
263
+ def get_cost_config(options = {})
264
+ config = get_config(options)
265
+ cost = config[:cost] || config["cost"] || {}
266
+
267
+ {
268
+ input_cost_per_token: cost[:input_cost_per_token] || cost["input_cost_per_token"],
269
+ output_cost_per_token: cost[:output_cost_per_token] || cost["output_cost_per_token"],
270
+ fixed_cost_per_request: cost[:fixed_cost_per_request] || cost["fixed_cost_per_request"],
271
+ currency: cost[:currency] || cost["currency"] || "USD"
272
+ }
273
+ end
274
+
275
+ # Get provider-specific harness configuration
276
+ def get_harness_config(options = {})
277
+ config = get_config(options)
278
+ harness_config = config[:harness] || config["harness"] || {}
279
+
280
+ {
281
+ enabled: harness_config[:enabled] != false,
282
+ auto_switch_on_error: harness_config[:auto_switch_on_error] != false,
283
+ auto_switch_on_rate_limit: harness_config[:auto_switch_on_rate_limit] != false,
284
+ priority: harness_config[:priority] || get_priority(options),
285
+ weight: harness_config[:weight] || 1,
286
+ max_concurrent_requests: harness_config[:max_concurrent_requests] || 5
287
+ }
288
+ end
289
+
290
+ # Get provider health check configuration
291
+ def get_health_check_config(options = {})
292
+ config = get_config(options)
293
+ health_check = config[:health_check] || config["health_check"] || {}
294
+
295
+ {
296
+ enabled: health_check[:enabled] != false,
297
+ interval: health_check[:interval] || 60,
298
+ timeout: health_check[:timeout] || 10,
299
+ failure_threshold: health_check[:failure_threshold] || 3,
300
+ success_threshold: health_check[:success_threshold] || 2,
301
+ check_url: health_check[:check_url] || health_check["check_url"],
302
+ check_prompt: health_check[:check_prompt] || health_check["check_prompt"]
303
+ }
304
+ end
305
+
306
+ # Get provider-specific environment variables
307
+ def get_env_vars(options = {})
308
+ config = get_config(options)
309
+ env_vars = config[:env_vars] || config["env_vars"] || {}
310
+
311
+ # Convert to string keys for environment variable access
312
+ env_vars.transform_keys(&:to_s)
313
+ end
314
+
315
+ # Get provider-specific command line arguments
316
+ def get_cmd_args(options = {})
317
+ config = get_config(options)
318
+ cmd_args = config[:cmd_args] || config["cmd_args"] || []
319
+ cmd_args.map(&:to_s)
320
+ end
321
+
322
+ # Get provider-specific working directory
323
+ def get_working_directory(options = {})
324
+ config = get_config(options)
325
+ config[:working_directory] || config["working_directory"] || Dir.pwd
326
+ end
327
+
328
+ # Get provider-specific log configuration
329
+ def get_log_config(options = {})
330
+ config = get_config(options)
331
+ log_config = config[:log] || config["log"] || {}
332
+
333
+ {
334
+ enabled: log_config[:enabled] != false,
335
+ level: log_config[:level] || "info",
336
+ file: log_config[:file] || log_config["file"],
337
+ max_size: log_config[:max_size] || 10_485_760, # 10MB
338
+ max_files: log_config[:max_files] || 5,
339
+ format: log_config[:format] || "json"
340
+ }
341
+ end
342
+
343
+ # Get provider-specific cache configuration
344
+ def get_cache_config(options = {})
345
+ config = get_config(options)
346
+ cache_config = config[:cache] || config["cache"] || {}
347
+
348
+ {
349
+ enabled: cache_config[:enabled] != false,
350
+ ttl: cache_config[:ttl] || 3600,
351
+ max_size: cache_config[:max_size] || 100,
352
+ strategy: cache_config[:strategy] || "lru"
353
+ }
354
+ end
355
+
356
+ # Get provider-specific security configuration
357
+ def get_security_config(options = {})
358
+ config = get_config(options)
359
+ security = config[:security] || config["security"] || {}
360
+
361
+ {
362
+ ssl_verify: security[:ssl_verify] != false,
363
+ allowed_hosts: security[:allowed_hosts] || security["allowed_hosts"] || [],
364
+ blocked_hosts: security[:blocked_hosts] || security["blocked_hosts"] || [],
365
+ timeout: security[:timeout] || 30,
366
+ max_redirects: security[:max_redirects] || 5
367
+ }
368
+ end
369
+
370
+ # Check if provider is configured
371
+ def configured?(options = {})
372
+ config = get_config(options)
373
+ !config.empty?
374
+ end
375
+
376
+ # Check if provider is enabled
377
+ def enabled?(options = {})
378
+ harness_config = get_harness_config(options)
379
+ harness_config[:enabled] != false
380
+ end
381
+
382
+ # Get provider status
383
+ def get_status(options = {})
384
+ return :not_configured unless configured?(options)
385
+ return :disabled unless enabled?(options)
386
+
387
+ :enabled
388
+ end
389
+
390
+ # Get provider summary
391
+ def get_summary(options = {})
392
+ config = get_config(options)
393
+ return {} if config.empty?
394
+
395
+ {
396
+ name: @provider_name,
397
+ type: get_type(options),
398
+ priority: get_priority(options),
399
+ models: get_models(options),
400
+ features: get_capabilities(options),
401
+ status: get_status(options),
402
+ configured: configured?(options),
403
+ enabled: enabled?(options)
404
+ }
405
+ end
406
+
407
+ # Reload configuration
408
+ def reload_config
409
+ @provider_config = nil
410
+ @harness_config = nil
411
+ @cache_timestamp = nil
412
+ @config_manager.reload_config
413
+ end
414
+
415
+ private
416
+
417
+ def cache_valid?
418
+ return false unless @cache_timestamp
419
+ Time.now - @cache_timestamp < 300 # 5 minutes
420
+ end
421
+ end
422
+ end
423
+ end