aidp 0.26.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.
- checksums.yaml +4 -4
- data/lib/aidp/cli/checkpoint_command.rb +198 -0
- data/lib/aidp/cli/config_command.rb +71 -0
- data/lib/aidp/cli/enhanced_input.rb +2 -0
- data/lib/aidp/cli/first_run_wizard.rb +8 -7
- data/lib/aidp/cli/harness_command.rb +102 -0
- data/lib/aidp/cli/jobs_command.rb +3 -3
- data/lib/aidp/cli/mcp_dashboard.rb +4 -3
- data/lib/aidp/cli/models_command.rb +662 -0
- data/lib/aidp/cli/providers_command.rb +223 -0
- data/lib/aidp/cli.rb +35 -456
- data/lib/aidp/daemon/runner.rb +2 -2
- data/lib/aidp/debug_mixin.rb +2 -9
- data/lib/aidp/execute/async_work_loop_runner.rb +2 -1
- data/lib/aidp/execute/checkpoint_display.rb +38 -37
- data/lib/aidp/execute/interactive_repl.rb +2 -1
- data/lib/aidp/execute/prompt_manager.rb +4 -4
- data/lib/aidp/execute/work_loop_runner.rb +29 -2
- data/lib/aidp/execute/workflow_selector.rb +2 -2
- data/lib/aidp/harness/config_manager.rb +5 -5
- data/lib/aidp/harness/configuration.rb +32 -2
- data/lib/aidp/harness/enhanced_runner.rb +24 -15
- data/lib/aidp/harness/error_handler.rb +26 -5
- data/lib/aidp/harness/model_cache.rb +269 -0
- data/lib/aidp/harness/model_discovery_service.rb +259 -0
- data/lib/aidp/harness/model_registry.rb +201 -0
- data/lib/aidp/harness/runner.rb +5 -0
- data/lib/aidp/harness/thinking_depth_manager.rb +223 -7
- data/lib/aidp/message_display.rb +0 -46
- data/lib/aidp/providers/adapter.rb +2 -4
- data/lib/aidp/providers/anthropic.rb +141 -128
- data/lib/aidp/providers/base.rb +98 -2
- data/lib/aidp/providers/capability_registry.rb +0 -1
- data/lib/aidp/providers/codex.rb +49 -67
- data/lib/aidp/providers/cursor.rb +71 -59
- data/lib/aidp/providers/gemini.rb +44 -60
- data/lib/aidp/providers/github_copilot.rb +2 -66
- data/lib/aidp/providers/kilocode.rb +24 -80
- data/lib/aidp/providers/opencode.rb +24 -80
- data/lib/aidp/setup/wizard.rb +345 -8
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/plan_generator.rb +93 -14
- data/lib/aidp/watch/review_processor.rb +3 -3
- data/lib/aidp/workflows/guided_agent.rb +3 -3
- data/templates/aidp-development.yml.example +2 -2
- data/templates/aidp-production.yml.example +3 -3
- metadata +9 -1
|
@@ -14,6 +14,76 @@ module Aidp
|
|
|
14
14
|
!!Aidp::Util.which("cursor-agent")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
# Normalize Cursor's model name to family name
|
|
18
|
+
#
|
|
19
|
+
# Cursor may use different naming conventions (e.g., dots vs hyphens)
|
|
20
|
+
#
|
|
21
|
+
# @param provider_model_name [String] Cursor's model name
|
|
22
|
+
# @return [String] The normalized family name
|
|
23
|
+
def self.model_family(provider_model_name)
|
|
24
|
+
# Normalize cursor naming to standard family names
|
|
25
|
+
# cursor uses dots: "claude-3.5-sonnet" -> "claude-3-5-sonnet"
|
|
26
|
+
provider_model_name.gsub(/(\d)\.(\d)/, '\1-\2')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Convert family name to Cursor's naming convention
|
|
30
|
+
#
|
|
31
|
+
# @param family_name [String] The model family name
|
|
32
|
+
# @return [String] Cursor's model name
|
|
33
|
+
def self.provider_model_name(family_name)
|
|
34
|
+
# Cursor uses dots for version numbers
|
|
35
|
+
# "claude-3-5-sonnet" -> "claude-3.5-sonnet"
|
|
36
|
+
family_name.gsub(/(\d)-(\d)/, '\1.\2')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Check if this provider supports a given model family
|
|
40
|
+
#
|
|
41
|
+
# Cursor supports Claude, GPT, and Cursor-specific models
|
|
42
|
+
#
|
|
43
|
+
# @param family_name [String] The model family name
|
|
44
|
+
# @return [Boolean] True if likely supported
|
|
45
|
+
def self.supports_model_family?(family_name)
|
|
46
|
+
family_name.match?(/^(claude|gpt|cursor)-/)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Discover available models from Cursor
|
|
50
|
+
#
|
|
51
|
+
# Note: Cursor doesn't have a public model listing API
|
|
52
|
+
# Returns registry-based models that match Cursor patterns
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<Hash>] Array of discovered models
|
|
55
|
+
def self.discover_models
|
|
56
|
+
return [] unless available?
|
|
57
|
+
|
|
58
|
+
begin
|
|
59
|
+
require_relative "../harness/model_registry"
|
|
60
|
+
registry = Aidp::Harness::ModelRegistry.new
|
|
61
|
+
|
|
62
|
+
# Get all models from registry that Cursor might support
|
|
63
|
+
models = registry.all_families.filter_map do |family|
|
|
64
|
+
next unless supports_model_family?(family)
|
|
65
|
+
|
|
66
|
+
info = registry.get_model_info(family)
|
|
67
|
+
next unless info
|
|
68
|
+
|
|
69
|
+
{
|
|
70
|
+
name: provider_model_name(family),
|
|
71
|
+
family: family,
|
|
72
|
+
tier: info["tier"],
|
|
73
|
+
capabilities: info["capabilities"] || [],
|
|
74
|
+
context_window: info["context_window"],
|
|
75
|
+
provider: "cursor"
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
Aidp.log_info("cursor_provider", "using registry models", count: models.size)
|
|
80
|
+
models
|
|
81
|
+
rescue => e
|
|
82
|
+
Aidp.log_debug("cursor_provider", "discovery failed", error: e.message)
|
|
83
|
+
[]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
17
87
|
def name
|
|
18
88
|
"cursor"
|
|
19
89
|
end
|
|
@@ -40,12 +110,6 @@ module Aidp
|
|
|
40
110
|
debug_provider("cursor", "Starting execution", {timeout: timeout_seconds})
|
|
41
111
|
debug_log("📝 Sending prompt to cursor-agent (length: #{prompt.length})", level: :info)
|
|
42
112
|
|
|
43
|
-
# Check if streaming mode is enabled
|
|
44
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
45
|
-
if streaming_enabled
|
|
46
|
-
display_message("📺 Display streaming enabled - output buffering reduced (cursor-agent does not support true streaming)", type: :info)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
113
|
# Set up activity monitoring
|
|
50
114
|
setup_activity_monitoring("cursor-agent", method(:activity_callback))
|
|
51
115
|
record_activity("Starting cursor-agent execution")
|
|
@@ -71,7 +135,7 @@ module Aidp
|
|
|
71
135
|
# Use debug_execute_command for better debugging
|
|
72
136
|
# Use -p mode (designed for non-interactive/script use)
|
|
73
137
|
# No fallback to interactive modes - they would hang AIDP's automation workflow
|
|
74
|
-
result = debug_execute_command("cursor-agent", args: ["-p"], input: prompt, timeout: timeout_seconds
|
|
138
|
+
result = debug_execute_command("cursor-agent", args: ["-p"], input: prompt, timeout: timeout_seconds)
|
|
75
139
|
|
|
76
140
|
# Log the results
|
|
77
141
|
debug_command("cursor-agent", args: ["-p"], input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
@@ -98,58 +162,6 @@ module Aidp
|
|
|
98
162
|
|
|
99
163
|
private
|
|
100
164
|
|
|
101
|
-
def calculate_timeout
|
|
102
|
-
# Priority order for timeout calculation:
|
|
103
|
-
# 1. Quick mode (for testing)
|
|
104
|
-
# 2. Environment variable override
|
|
105
|
-
# 3. Adaptive timeout based on step type
|
|
106
|
-
# 4. Default timeout
|
|
107
|
-
|
|
108
|
-
if ENV["AIDP_QUICK_MODE"]
|
|
109
|
-
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
110
|
-
return TIMEOUT_QUICK_MODE
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
if ENV["AIDP_CURSOR_TIMEOUT"]
|
|
114
|
-
return ENV["AIDP_CURSOR_TIMEOUT"].to_i
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
if adaptive_timeout
|
|
118
|
-
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
|
119
|
-
return adaptive_timeout
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Default timeout
|
|
123
|
-
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
124
|
-
TIMEOUT_DEFAULT
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def adaptive_timeout
|
|
128
|
-
@adaptive_timeout ||= begin
|
|
129
|
-
# Timeout recommendations based on step type patterns
|
|
130
|
-
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
131
|
-
|
|
132
|
-
case step_name
|
|
133
|
-
when /REPOSITORY_ANALYSIS/
|
|
134
|
-
TIMEOUT_REPOSITORY_ANALYSIS
|
|
135
|
-
when /ARCHITECTURE_ANALYSIS/
|
|
136
|
-
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
137
|
-
when /TEST_ANALYSIS/
|
|
138
|
-
TIMEOUT_TEST_ANALYSIS
|
|
139
|
-
when /FUNCTIONALITY_ANALYSIS/
|
|
140
|
-
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
141
|
-
when /DOCUMENTATION_ANALYSIS/
|
|
142
|
-
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
143
|
-
when /STATIC_ANALYSIS/
|
|
144
|
-
TIMEOUT_STATIC_ANALYSIS
|
|
145
|
-
when /REFACTORING_RECOMMENDATIONS/
|
|
146
|
-
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
147
|
-
else
|
|
148
|
-
nil # Use default
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
165
|
def activity_callback(state, message, provider)
|
|
154
166
|
# This is now handled by the animated display thread
|
|
155
167
|
# Only print static messages for state changes
|
|
@@ -8,10 +8,53 @@ module Aidp
|
|
|
8
8
|
class Gemini < Base
|
|
9
9
|
include Aidp::DebugMixin
|
|
10
10
|
|
|
11
|
+
# Model name pattern for Gemini models
|
|
12
|
+
MODEL_PATTERN = /^gemini-[\d.]+-(?:pro|flash|ultra)(?:-\d+)?$/i
|
|
13
|
+
|
|
11
14
|
def self.available?
|
|
12
15
|
!!Aidp::Util.which("gemini")
|
|
13
16
|
end
|
|
14
17
|
|
|
18
|
+
# Normalize a provider-specific model name to its model family
|
|
19
|
+
#
|
|
20
|
+
# Gemini may use version suffixes (e.g., "gemini-1.5-pro-001").
|
|
21
|
+
# This method strips version suffixes to get the family name.
|
|
22
|
+
#
|
|
23
|
+
# @param provider_model_name [String] The model name
|
|
24
|
+
# @return [String] The model family name
|
|
25
|
+
def self.model_family(provider_model_name)
|
|
26
|
+
# Strip version suffix: "gemini-1.5-pro-001" → "gemini-1.5-pro"
|
|
27
|
+
provider_model_name.sub(/-\d+$/, "")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Convert a model family name to the provider's preferred model name
|
|
31
|
+
#
|
|
32
|
+
# @param family_name [String] The model family name
|
|
33
|
+
# @return [String] The provider-specific model name (same as family)
|
|
34
|
+
def self.provider_model_name(family_name)
|
|
35
|
+
family_name
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Check if this provider supports a given model family
|
|
39
|
+
#
|
|
40
|
+
# @param family_name [String] The model family name
|
|
41
|
+
# @return [Boolean] True if it matches Gemini model pattern
|
|
42
|
+
def self.supports_model_family?(family_name)
|
|
43
|
+
MODEL_PATTERN.match?(family_name)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Discover available models from Gemini
|
|
47
|
+
#
|
|
48
|
+
# Note: Gemini CLI doesn't have a standard model listing command
|
|
49
|
+
# Returns registry-based models that match Gemini patterns
|
|
50
|
+
#
|
|
51
|
+
# @return [Array<Hash>] Array of discovered models
|
|
52
|
+
def self.discover_models
|
|
53
|
+
return [] unless available?
|
|
54
|
+
|
|
55
|
+
discover_models_from_registry(MODEL_PATTERN, "gemini")
|
|
56
|
+
end
|
|
57
|
+
|
|
15
58
|
def name
|
|
16
59
|
"gemini"
|
|
17
60
|
end
|
|
@@ -29,16 +72,9 @@ module Aidp
|
|
|
29
72
|
debug_provider("gemini", "Starting execution", {timeout: timeout_seconds})
|
|
30
73
|
debug_log("📝 Sending prompt to gemini...", level: :info)
|
|
31
74
|
|
|
32
|
-
# Check if streaming mode is enabled
|
|
33
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
34
|
-
if streaming_enabled
|
|
35
|
-
display_message("📺 Display streaming enabled - output buffering reduced (gemini CLI does not support true streaming)", type: :info)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
75
|
begin
|
|
39
76
|
command_args = ["--prompt", prompt]
|
|
40
|
-
|
|
41
|
-
result = debug_execute_command("gemini", args: command_args, timeout: timeout_seconds, streaming: streaming_enabled)
|
|
77
|
+
result = debug_execute_command("gemini", args: command_args, timeout: timeout_seconds)
|
|
42
78
|
|
|
43
79
|
# Log the results
|
|
44
80
|
debug_command("gemini", args: command_args, input: nil, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
@@ -56,58 +92,6 @@ module Aidp
|
|
|
56
92
|
end
|
|
57
93
|
|
|
58
94
|
private
|
|
59
|
-
|
|
60
|
-
def calculate_timeout
|
|
61
|
-
# Priority order for timeout calculation:
|
|
62
|
-
# 1. Quick mode (for testing)
|
|
63
|
-
# 2. Environment variable override
|
|
64
|
-
# 3. Adaptive timeout based on step type
|
|
65
|
-
# 4. Default timeout
|
|
66
|
-
|
|
67
|
-
if ENV["AIDP_QUICK_MODE"]
|
|
68
|
-
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
69
|
-
return TIMEOUT_QUICK_MODE
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
if ENV["AIDP_GEMINI_TIMEOUT"]
|
|
73
|
-
return ENV["AIDP_GEMINI_TIMEOUT"].to_i
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Adaptive timeout based on step type
|
|
77
|
-
step_timeout = get_adaptive_timeout
|
|
78
|
-
if step_timeout
|
|
79
|
-
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
80
|
-
return step_timeout
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Default timeout
|
|
84
|
-
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
85
|
-
TIMEOUT_DEFAULT
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def get_adaptive_timeout
|
|
89
|
-
# Timeout recommendations based on step type patterns
|
|
90
|
-
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
91
|
-
|
|
92
|
-
case step_name
|
|
93
|
-
when /REPOSITORY_ANALYSIS/
|
|
94
|
-
TIMEOUT_REPOSITORY_ANALYSIS
|
|
95
|
-
when /ARCHITECTURE_ANALYSIS/
|
|
96
|
-
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
97
|
-
when /TEST_ANALYSIS/
|
|
98
|
-
TIMEOUT_TEST_ANALYSIS
|
|
99
|
-
when /FUNCTIONALITY_ANALYSIS/
|
|
100
|
-
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
101
|
-
when /DOCUMENTATION_ANALYSIS/
|
|
102
|
-
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
103
|
-
when /STATIC_ANALYSIS/
|
|
104
|
-
TIMEOUT_STATIC_ANALYSIS
|
|
105
|
-
when /REFACTORING_RECOMMENDATIONS/
|
|
106
|
-
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
107
|
-
else
|
|
108
|
-
nil # Use default
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
95
|
end
|
|
112
96
|
end
|
|
113
97
|
end
|
|
@@ -43,12 +43,6 @@ module Aidp
|
|
|
43
43
|
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds})
|
|
44
44
|
debug_log("📝 Sending prompt to copilot (length: #{prompt.length})", level: :info)
|
|
45
45
|
|
|
46
|
-
# Check if streaming mode is enabled
|
|
47
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
48
|
-
if streaming_enabled
|
|
49
|
-
display_message("📺 Display streaming enabled - output buffering reduced (copilot CLI does not support true streaming)", type: :info)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
46
|
# Set up activity monitoring
|
|
53
47
|
setup_activity_monitoring("copilot", method(:activity_callback))
|
|
54
48
|
record_activity("Starting copilot execution")
|
|
@@ -80,7 +74,7 @@ module Aidp
|
|
|
80
74
|
end
|
|
81
75
|
|
|
82
76
|
# Use debug_execute_command for better debugging (no input since prompt is in args)
|
|
83
|
-
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds
|
|
77
|
+
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds)
|
|
84
78
|
|
|
85
79
|
# Log the results
|
|
86
80
|
debug_command("copilot", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
@@ -178,17 +172,11 @@ module Aidp
|
|
|
178
172
|
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds, args: args})
|
|
179
173
|
debug_log("📝 Sending prompt to copilot with custom args", level: :info)
|
|
180
174
|
|
|
181
|
-
# Check if streaming mode is enabled
|
|
182
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
183
|
-
if streaming_enabled
|
|
184
|
-
display_message("📺 Display streaming enabled - output buffering reduced (copilot CLI does not support true streaming)", type: :info)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
175
|
setup_activity_monitoring("copilot", method(:activity_callback))
|
|
188
176
|
record_activity("Starting copilot execution with custom args")
|
|
189
177
|
|
|
190
178
|
begin
|
|
191
|
-
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds
|
|
179
|
+
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds)
|
|
192
180
|
debug_command("copilot", args: args, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
193
181
|
|
|
194
182
|
if result.exit_status == 0
|
|
@@ -206,58 +194,6 @@ module Aidp
|
|
|
206
194
|
end
|
|
207
195
|
end
|
|
208
196
|
|
|
209
|
-
def calculate_timeout
|
|
210
|
-
# Priority order for timeout calculation:
|
|
211
|
-
# 1. Quick mode (for testing)
|
|
212
|
-
# 2. Environment variable override
|
|
213
|
-
# 3. Adaptive timeout based on step type
|
|
214
|
-
# 4. Default timeout
|
|
215
|
-
|
|
216
|
-
if ENV["AIDP_QUICK_MODE"]
|
|
217
|
-
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
218
|
-
return TIMEOUT_QUICK_MODE
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
if ENV["AIDP_GITHUB_COPILOT_TIMEOUT"]
|
|
222
|
-
return ENV["AIDP_GITHUB_COPILOT_TIMEOUT"].to_i
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
if adaptive_timeout
|
|
226
|
-
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
|
227
|
-
return adaptive_timeout
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
# Default timeout
|
|
231
|
-
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
232
|
-
TIMEOUT_DEFAULT
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def adaptive_timeout
|
|
236
|
-
@adaptive_timeout ||= begin
|
|
237
|
-
# Timeout recommendations based on step type patterns
|
|
238
|
-
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
239
|
-
|
|
240
|
-
case step_name
|
|
241
|
-
when /REPOSITORY_ANALYSIS/
|
|
242
|
-
TIMEOUT_REPOSITORY_ANALYSIS
|
|
243
|
-
when /ARCHITECTURE_ANALYSIS/
|
|
244
|
-
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
245
|
-
when /TEST_ANALYSIS/
|
|
246
|
-
TIMEOUT_TEST_ANALYSIS
|
|
247
|
-
when /FUNCTIONALITY_ANALYSIS/
|
|
248
|
-
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
249
|
-
when /DOCUMENTATION_ANALYSIS/
|
|
250
|
-
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
251
|
-
when /STATIC_ANALYSIS/
|
|
252
|
-
TIMEOUT_STATIC_ANALYSIS
|
|
253
|
-
when /REFACTORING_RECOMMENDATIONS/
|
|
254
|
-
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
255
|
-
else
|
|
256
|
-
nil # Use default
|
|
257
|
-
end
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
|
|
261
197
|
def activity_callback(state, message, provider)
|
|
262
198
|
# Handle activity state changes
|
|
263
199
|
case state
|
|
@@ -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,
|
|
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
|
|
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
|