aidp 0.25.0 → 0.27.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -6
  3. data/lib/aidp/analyze/error_handler.rb +11 -0
  4. data/lib/aidp/cli/checkpoint_command.rb +198 -0
  5. data/lib/aidp/cli/config_command.rb +71 -0
  6. data/lib/aidp/cli/enhanced_input.rb +2 -0
  7. data/lib/aidp/cli/first_run_wizard.rb +8 -7
  8. data/lib/aidp/cli/harness_command.rb +102 -0
  9. data/lib/aidp/cli/jobs_command.rb +3 -3
  10. data/lib/aidp/cli/mcp_dashboard.rb +4 -3
  11. data/lib/aidp/cli/models_command.rb +662 -0
  12. data/lib/aidp/cli/providers_command.rb +223 -0
  13. data/lib/aidp/cli.rb +35 -456
  14. data/lib/aidp/daemon/runner.rb +2 -2
  15. data/lib/aidp/debug_mixin.rb +2 -9
  16. data/lib/aidp/execute/async_work_loop_runner.rb +2 -1
  17. data/lib/aidp/execute/checkpoint_display.rb +38 -37
  18. data/lib/aidp/execute/interactive_repl.rb +2 -1
  19. data/lib/aidp/execute/prompt_manager.rb +4 -4
  20. data/lib/aidp/execute/work_loop_runner.rb +253 -56
  21. data/lib/aidp/execute/workflow_selector.rb +2 -2
  22. data/lib/aidp/harness/config_loader.rb +20 -11
  23. data/lib/aidp/harness/config_manager.rb +5 -5
  24. data/lib/aidp/harness/config_schema.rb +30 -8
  25. data/lib/aidp/harness/configuration.rb +105 -4
  26. data/lib/aidp/harness/enhanced_runner.rb +24 -15
  27. data/lib/aidp/harness/error_handler.rb +26 -5
  28. data/lib/aidp/harness/filter_strategy.rb +45 -0
  29. data/lib/aidp/harness/generic_filter_strategy.rb +63 -0
  30. data/lib/aidp/harness/model_cache.rb +269 -0
  31. data/lib/aidp/harness/model_discovery_service.rb +259 -0
  32. data/lib/aidp/harness/model_registry.rb +201 -0
  33. data/lib/aidp/harness/output_filter.rb +136 -0
  34. data/lib/aidp/harness/provider_manager.rb +18 -3
  35. data/lib/aidp/harness/rspec_filter_strategy.rb +82 -0
  36. data/lib/aidp/harness/runner.rb +5 -0
  37. data/lib/aidp/harness/test_runner.rb +165 -27
  38. data/lib/aidp/harness/thinking_depth_manager.rb +223 -7
  39. data/lib/aidp/harness/ui/enhanced_tui.rb +4 -1
  40. data/lib/aidp/logger.rb +35 -5
  41. data/lib/aidp/providers/adapter.rb +2 -4
  42. data/lib/aidp/providers/anthropic.rb +141 -128
  43. data/lib/aidp/providers/base.rb +98 -2
  44. data/lib/aidp/providers/capability_registry.rb +0 -1
  45. data/lib/aidp/providers/codex.rb +49 -67
  46. data/lib/aidp/providers/cursor.rb +71 -59
  47. data/lib/aidp/providers/gemini.rb +44 -60
  48. data/lib/aidp/providers/github_copilot.rb +2 -66
  49. data/lib/aidp/providers/kilocode.rb +24 -80
  50. data/lib/aidp/providers/opencode.rb +24 -80
  51. data/lib/aidp/safe_directory.rb +10 -3
  52. data/lib/aidp/setup/wizard.rb +345 -8
  53. data/lib/aidp/storage/csv_storage.rb +9 -3
  54. data/lib/aidp/storage/file_manager.rb +8 -2
  55. data/lib/aidp/storage/json_storage.rb +9 -3
  56. data/lib/aidp/version.rb +1 -1
  57. data/lib/aidp/watch/build_processor.rb +40 -1
  58. data/lib/aidp/watch/change_request_processor.rb +659 -0
  59. data/lib/aidp/watch/plan_generator.rb +93 -14
  60. data/lib/aidp/watch/plan_processor.rb +71 -8
  61. data/lib/aidp/watch/repository_client.rb +85 -20
  62. data/lib/aidp/watch/review_processor.rb +3 -3
  63. data/lib/aidp/watch/runner.rb +37 -0
  64. data/lib/aidp/watch/state_store.rb +46 -1
  65. data/lib/aidp/workflows/guided_agent.rb +3 -3
  66. data/lib/aidp/workstream_executor.rb +5 -2
  67. data/lib/aidp.rb +4 -0
  68. data/templates/aidp-development.yml.example +2 -2
  69. data/templates/aidp-production.yml.example +3 -3
  70. data/templates/aidp.yml.example +53 -0
  71. metadata +14 -1
@@ -10,10 +10,33 @@ module Aidp
10
10
  class Kilocode < Base
11
11
  include Aidp::DebugMixin
12
12
 
13
+ # Model name pattern for OpenAI models (since Kilocode uses OpenAI)
14
+ MODEL_PATTERN = /^gpt-[\d.o-]+(?:-turbo)?(?:-mini)?$/i
15
+
13
16
  def self.available?
14
17
  !!Aidp::Util.which("kilocode")
15
18
  end
16
19
 
20
+ # Check if this provider supports a given model family
21
+ #
22
+ # @param family_name [String] The model family name
23
+ # @return [Boolean] True if it matches OpenAI model pattern
24
+ def self.supports_model_family?(family_name)
25
+ MODEL_PATTERN.match?(family_name)
26
+ end
27
+
28
+ # Discover available models from registry
29
+ #
30
+ # Note: Kilocode CLI doesn't have a standard model listing command
31
+ # Returns registry-based models that match OpenAI patterns
32
+ #
33
+ # @return [Array<Hash>] Array of discovered models
34
+ def self.discover_models
35
+ return [] unless available?
36
+
37
+ discover_models_from_registry(MODEL_PATTERN, "kilocode")
38
+ end
39
+
17
40
  def name
18
41
  "kilocode"
19
42
  end
@@ -31,12 +54,6 @@ module Aidp
31
54
  debug_provider("kilocode", "Starting execution", {timeout: timeout_seconds})
32
55
  debug_log("📝 Sending prompt to kilocode (length: #{prompt.length})", level: :info)
33
56
 
34
- # Check if streaming mode is enabled
35
- streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
36
- if streaming_enabled
37
- display_message("📺 Display streaming enabled - output buffering reduced", type: :info)
38
- end
39
-
40
57
  # Check if prompt is too large and warn
41
58
  if prompt.length > 3000
42
59
  debug_log("⚠️ Large prompt detected (#{prompt.length} chars) - this may cause rate limiting", level: :warn)
@@ -85,7 +102,7 @@ module Aidp
85
102
  end
86
103
 
87
104
  # Use debug_execute_command for better debugging
88
- result = debug_execute_command("kilocode", args: args, input: prompt, timeout: timeout_seconds, streaming: streaming_enabled, env: env_vars)
105
+ result = debug_execute_command("kilocode", args: args, input: prompt, timeout: timeout_seconds, env: env_vars)
89
106
 
90
107
  # Log the results
91
108
  debug_command("kilocode", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
@@ -112,58 +129,6 @@ module Aidp
112
129
 
113
130
  private
114
131
 
115
- def calculate_timeout
116
- # Priority order for timeout calculation:
117
- # 1. Quick mode (for testing)
118
- # 2. Environment variable override
119
- # 3. Adaptive timeout based on step type
120
- # 4. Default timeout
121
-
122
- if ENV["AIDP_QUICK_MODE"]
123
- display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
124
- return TIMEOUT_QUICK_MODE
125
- end
126
-
127
- if ENV["AIDP_KILOCODE_TIMEOUT"]
128
- return ENV["AIDP_KILOCODE_TIMEOUT"].to_i
129
- end
130
-
131
- if adaptive_timeout
132
- display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
133
- return adaptive_timeout
134
- end
135
-
136
- # Default timeout
137
- display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
138
- TIMEOUT_DEFAULT
139
- end
140
-
141
- def adaptive_timeout
142
- @adaptive_timeout ||= begin
143
- # Timeout recommendations based on step type patterns
144
- step_name = ENV["AIDP_CURRENT_STEP"] || ""
145
-
146
- case step_name
147
- when /REPOSITORY_ANALYSIS/
148
- TIMEOUT_REPOSITORY_ANALYSIS
149
- when /ARCHITECTURE_ANALYSIS/
150
- TIMEOUT_ARCHITECTURE_ANALYSIS
151
- when /TEST_ANALYSIS/
152
- TIMEOUT_TEST_ANALYSIS
153
- when /FUNCTIONALITY_ANALYSIS/
154
- TIMEOUT_FUNCTIONALITY_ANALYSIS
155
- when /DOCUMENTATION_ANALYSIS/
156
- TIMEOUT_DOCUMENTATION_ANALYSIS
157
- when /STATIC_ANALYSIS/
158
- TIMEOUT_STATIC_ANALYSIS
159
- when /REFACTORING_RECOMMENDATIONS/
160
- TIMEOUT_REFACTORING_RECOMMENDATIONS
161
- else
162
- nil # Use default
163
- end
164
- end
165
- end
166
-
167
132
  def activity_callback(state, message, provider)
168
133
  # This is now handled by the animated display thread
169
134
  # Only print static messages for state changes
@@ -176,27 +141,6 @@ module Aidp
176
141
  display_message("❌ kilocode execution failed: #{message}", type: :error)
177
142
  end
178
143
  end
179
-
180
- def setup_activity_monitoring(provider_name, callback)
181
- @activity_callback = callback
182
- @activity_state = :starting
183
- @activity_start_time = Time.now
184
- end
185
-
186
- def record_activity(message)
187
- @activity_state = :running
188
- @activity_callback&.call(:running, message, "kilocode")
189
- end
190
-
191
- def mark_completed
192
- @activity_state = :completed
193
- @activity_callback&.call(:completed, "Execution completed", "kilocode")
194
- end
195
-
196
- def mark_failed(reason)
197
- @activity_state = :failed
198
- @activity_callback&.call(:failed, reason, "kilocode")
199
- end
200
144
  end
201
145
  end
202
146
  end
@@ -10,10 +10,33 @@ module Aidp
10
10
  class Opencode < Base
11
11
  include Aidp::DebugMixin
12
12
 
13
+ # Model name pattern for OpenAI models (since OpenCode uses OpenAI)
14
+ MODEL_PATTERN = /^gpt-[\d.o-]+(?:-turbo)?(?:-mini)?$/i
15
+
13
16
  def self.available?
14
17
  !!Aidp::Util.which("opencode")
15
18
  end
16
19
 
20
+ # Check if this provider supports a given model family
21
+ #
22
+ # @param family_name [String] The model family name
23
+ # @return [Boolean] True if it matches OpenAI model pattern
24
+ def self.supports_model_family?(family_name)
25
+ MODEL_PATTERN.match?(family_name)
26
+ end
27
+
28
+ # Discover available models from registry
29
+ #
30
+ # Note: OpenCode CLI doesn't have a standard model listing command
31
+ # Returns registry-based models that match OpenAI patterns
32
+ #
33
+ # @return [Array<Hash>] Array of discovered models
34
+ def self.discover_models
35
+ return [] unless available?
36
+
37
+ discover_models_from_registry(MODEL_PATTERN, "opencode")
38
+ end
39
+
17
40
  def name
18
41
  "opencode"
19
42
  end
@@ -31,12 +54,6 @@ module Aidp
31
54
  debug_provider("opencode", "Starting execution", {timeout: timeout_seconds})
32
55
  debug_log("📝 Sending prompt to opencode (length: #{prompt.length})", level: :info)
33
56
 
34
- # Check if streaming mode is enabled
35
- streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
36
- if streaming_enabled
37
- display_message("📺 Display streaming enabled - output buffering reduced (opencode does not support true streaming)", type: :info)
38
- end
39
-
40
57
  # Check if prompt is too large and warn
41
58
  if prompt.length > 3000
42
59
  debug_log("⚠️ Large prompt detected (#{prompt.length} chars) - this may cause rate limiting", level: :warn)
@@ -67,7 +84,7 @@ module Aidp
67
84
  # Use debug_execute_command for better debugging
68
85
  # opencode run command with prompt and model
69
86
  model = ENV["OPENCODE_MODEL"] || "github-copilot/claude-3.5-sonnet"
70
- result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds, streaming: streaming_enabled)
87
+ result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds)
71
88
 
72
89
  # Log the results
73
90
  debug_command("opencode", args: ["run", "-m", model, prompt], input: nil, output: result.out, error: result.err, exit_code: result.exit_status)
@@ -94,58 +111,6 @@ module Aidp
94
111
 
95
112
  private
96
113
 
97
- def calculate_timeout
98
- # Priority order for timeout calculation:
99
- # 1. Quick mode (for testing)
100
- # 2. Environment variable override
101
- # 3. Adaptive timeout based on step type
102
- # 4. Default timeout
103
-
104
- if ENV["AIDP_QUICK_MODE"]
105
- display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
106
- return TIMEOUT_QUICK_MODE
107
- end
108
-
109
- if ENV["AIDP_OPENCODE_TIMEOUT"]
110
- return ENV["AIDP_OPENCODE_TIMEOUT"].to_i
111
- end
112
-
113
- if adaptive_timeout
114
- display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
115
- return adaptive_timeout
116
- end
117
-
118
- # Default timeout
119
- display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
120
- TIMEOUT_DEFAULT
121
- end
122
-
123
- def adaptive_timeout
124
- @adaptive_timeout ||= begin
125
- # Timeout recommendations based on step type patterns
126
- step_name = ENV["AIDP_CURRENT_STEP"] || ""
127
-
128
- case step_name
129
- when /REPOSITORY_ANALYSIS/
130
- TIMEOUT_REPOSITORY_ANALYSIS
131
- when /ARCHITECTURE_ANALYSIS/
132
- TIMEOUT_ARCHITECTURE_ANALYSIS
133
- when /TEST_ANALYSIS/
134
- TIMEOUT_TEST_ANALYSIS
135
- when /FUNCTIONALITY_ANALYSIS/
136
- TIMEOUT_FUNCTIONALITY_ANALYSIS
137
- when /DOCUMENTATION_ANALYSIS/
138
- TIMEOUT_DOCUMENTATION_ANALYSIS
139
- when /STATIC_ANALYSIS/
140
- TIMEOUT_STATIC_ANALYSIS
141
- when /REFACTORING_RECOMMENDATIONS/
142
- TIMEOUT_REFACTORING_RECOMMENDATIONS
143
- else
144
- nil # Use default
145
- end
146
- end
147
- end
148
-
149
114
  def activity_callback(state, message, provider)
150
115
  # This is now handled by the animated display thread
151
116
  # Only print static messages for state changes
@@ -158,27 +123,6 @@ module Aidp
158
123
  display_message("❌ opencode execution failed: #{message}", type: :error)
159
124
  end
160
125
  end
161
-
162
- def setup_activity_monitoring(provider_name, callback)
163
- @activity_callback = callback
164
- @activity_state = :starting
165
- @activity_start_time = Time.now
166
- end
167
-
168
- def record_activity(message)
169
- @activity_state = :running
170
- @activity_callback&.call(:running, message, "opencode")
171
- end
172
-
173
- def mark_completed
174
- @activity_state = :completed
175
- @activity_callback&.call(:completed, "Execution completed", "opencode")
176
- end
177
-
178
- def mark_failed(reason)
179
- @activity_state = :failed
180
- @activity_callback&.call(:failed, reason, "opencode")
181
- end
182
126
  end
183
127
  end
184
128
  end
@@ -22,14 +22,21 @@ module Aidp
22
22
  path
23
23
  rescue SystemCallError => e
24
24
  fallback = determine_fallback_path(path)
25
- Kernel.warn "[#{component_name}] Cannot create directory #{path}: #{e.class}: #{e.message}"
26
- Kernel.warn "[#{component_name}] Using fallback directory: #{fallback}"
25
+
26
+ # Suppress permission warnings during tests to reduce noise
27
+ unless ENV["RSPEC_RUNNING"] == "true"
28
+ Kernel.warn "[#{component_name}] Cannot create directory #{path}: #{e.class}: #{e.message}"
29
+ Kernel.warn "[#{component_name}] Using fallback directory: #{fallback}"
30
+ end
27
31
 
28
32
  # Try to create fallback directory
29
33
  begin
30
34
  FileUtils.mkdir_p(fallback) unless Dir.exist?(fallback)
31
35
  rescue SystemCallError => e2
32
- Kernel.warn "[#{component_name}] Fallback directory creation also failed: #{e2.class}: #{e2.message}"
36
+ # Suppress fallback errors during tests too
37
+ unless ENV["RSPEC_RUNNING"] == "true"
38
+ Kernel.warn "[#{component_name}] Fallback directory creation also failed: #{e2.class}: #{e2.message}"
39
+ end
33
40
  end
34
41
 
35
42
  fallback