aidp 0.9.6 → 0.11.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/README.md +194 -25
- data/lib/aidp/analyze/error_handler.rb +4 -2
- data/lib/aidp/{analysis → analyze}/kb_inspector.rb +93 -89
- data/lib/aidp/analyze/prioritizer.rb +3 -2
- data/lib/aidp/analyze/progress.rb +2 -1
- data/lib/aidp/analyze/ruby_maat_integration.rb +7 -3
- data/lib/aidp/analyze/runner.rb +73 -11
- data/lib/aidp/{analysis → analyze}/seams.rb +1 -1
- data/lib/aidp/analyze/steps.rb +10 -8
- data/lib/aidp/{analysis → analyze}/tree_sitter_grammar_loader.rb +11 -5
- data/lib/aidp/{analysis → analyze}/tree_sitter_scan.rb +21 -15
- data/lib/aidp/cli/checkpoint_command.rb +98 -0
- data/lib/aidp/cli/first_run_wizard.rb +83 -103
- data/lib/aidp/cli/jobs_command.rb +270 -36
- data/lib/aidp/cli/terminal_io.rb +3 -3
- data/lib/aidp/cli.rb +411 -69
- data/lib/aidp/config.rb +5 -8
- data/lib/aidp/debug_logger.rb +4 -4
- data/lib/aidp/debug_mixin.rb +11 -4
- data/lib/aidp/execute/checkpoint.rb +282 -0
- data/lib/aidp/execute/checkpoint_display.rb +221 -0
- data/lib/aidp/execute/progress.rb +2 -1
- data/lib/aidp/execute/prompt_manager.rb +62 -0
- data/lib/aidp/execute/runner.rb +67 -20
- data/lib/aidp/execute/steps.rb +36 -27
- data/lib/aidp/execute/work_loop_runner.rb +308 -0
- data/lib/aidp/execute/workflow_selector.rb +50 -26
- data/lib/aidp/harness/condition_detector.rb +4 -4
- data/lib/aidp/harness/config_schema.rb +40 -0
- data/lib/aidp/harness/config_validator.rb +3 -6
- data/lib/aidp/harness/configuration.rb +35 -1
- data/lib/aidp/harness/enhanced_runner.rb +25 -4
- data/lib/aidp/harness/error_handler.rb +103 -28
- data/lib/aidp/harness/provider_factory.rb +6 -1
- data/lib/aidp/harness/provider_manager.rb +273 -19
- data/lib/aidp/harness/runner.rb +14 -6
- data/lib/aidp/harness/simple_user_interface.rb +6 -4
- data/lib/aidp/harness/status_display.rb +118 -106
- data/lib/aidp/harness/test_runner.rb +83 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +7 -5
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +22 -4
- data/lib/aidp/harness/ui/error_handler.rb +7 -2
- data/lib/aidp/harness/ui/frame_manager.rb +61 -39
- data/lib/aidp/harness/ui/job_monitor.rb +2 -0
- data/lib/aidp/harness/ui/navigation/main_menu.rb +27 -16
- data/lib/aidp/harness/ui/navigation/menu_item.rb +1 -0
- data/lib/aidp/harness/ui/navigation/menu_state.rb +1 -0
- data/lib/aidp/harness/ui/navigation/submenu.rb +1 -0
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +2 -0
- data/lib/aidp/harness/ui/progress_display.rb +26 -7
- data/lib/aidp/harness/ui/question_collector.rb +2 -0
- data/lib/aidp/harness/ui/spinner_group.rb +2 -0
- data/lib/aidp/harness/ui/spinner_helper.rb +1 -1
- data/lib/aidp/harness/ui/status_manager.rb +4 -2
- data/lib/aidp/harness/ui/status_widget.rb +20 -9
- data/lib/aidp/harness/ui/workflow_controller.rb +27 -9
- data/lib/aidp/harness/user_interface.rb +338 -330
- data/lib/aidp/jobs/background_runner.rb +278 -0
- data/lib/aidp/message_display.rb +48 -0
- data/lib/aidp/provider_manager.rb +13 -7
- data/lib/aidp/providers/anthropic.rb +101 -18
- data/lib/aidp/providers/base.rb +51 -1
- data/lib/aidp/providers/codex.rb +248 -0
- data/lib/aidp/providers/cursor.rb +39 -48
- data/lib/aidp/providers/gemini.rb +26 -16
- data/lib/aidp/providers/github_copilot.rb +263 -0
- data/lib/aidp/providers/opencode.rb +38 -47
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/workflows/definitions.rb +357 -0
- data/lib/aidp/workflows/selector.rb +171 -0
- data/lib/aidp.rb +16 -4
- data/templates/planning/generate_llm_style_guide.md +119 -0
- metadata +43 -31
- data/lib/aidp/analyze/progress_visualizer.rb +0 -314
- /data/templates/{ANALYZE/02_ARCHITECTURE_ANALYSIS.md → analysis/analyze_architecture.md} +0 -0
- /data/templates/{ANALYZE/05_DOCUMENTATION_ANALYSIS.md → analysis/analyze_documentation.md} +0 -0
- /data/templates/{ANALYZE/04_FUNCTIONALITY_ANALYSIS.md → analysis/analyze_functionality.md} +0 -0
- /data/templates/{ANALYZE/01_REPOSITORY_ANALYSIS.md → analysis/analyze_repository.md} +0 -0
- /data/templates/{ANALYZE/06_STATIC_ANALYSIS.md → analysis/analyze_static_code.md} +0 -0
- /data/templates/{ANALYZE/03_TEST_ANALYSIS.md → analysis/analyze_tests.md} +0 -0
- /data/templates/{ANALYZE/07_REFACTORING_RECOMMENDATIONS.md → analysis/recommend_refactoring.md} +0 -0
- /data/templates/{ANALYZE/06a_tree_sitter_scan.md → analysis/scan_with_tree_sitter.md} +0 -0
- /data/templates/{EXECUTE/11_STATIC_ANALYSIS.md → implementation/configure_static_analysis.md} +0 -0
- /data/templates/{EXECUTE/14_DOCS_PORTAL.md → implementation/create_documentation_portal.md} +0 -0
- /data/templates/{EXECUTE/10_IMPLEMENTATION_AGENT.md → implementation/implement_features.md} +0 -0
- /data/templates/{EXECUTE/13_DELIVERY_ROLLOUT.md → implementation/plan_delivery.md} +0 -0
- /data/templates/{EXECUTE/15_POST_RELEASE.md → implementation/review_post_release.md} +0 -0
- /data/templates/{EXECUTE/09_SCAFFOLDING_DEVEX.md → implementation/setup_scaffolding.md} +0 -0
- /data/templates/{EXECUTE/02A_ARCH_GATE_QUESTIONS.md → planning/ask_architecture_questions.md} +0 -0
- /data/templates/{EXECUTE/00_PRD.md → planning/create_prd.md} +0 -0
- /data/templates/{EXECUTE/08_TASKS.md → planning/create_tasks.md} +0 -0
- /data/templates/{EXECUTE/04_DOMAIN_DECOMPOSITION.md → planning/decompose_domain.md} +0 -0
- /data/templates/{EXECUTE/01_NFRS.md → planning/define_nfrs.md} +0 -0
- /data/templates/{EXECUTE/05_CONTRACTS.md → planning/design_apis.md} +0 -0
- /data/templates/{EXECUTE/02_ARCHITECTURE.md → planning/design_architecture.md} +0 -0
- /data/templates/{EXECUTE/06_THREAT_MODEL.md → planning/design_data_model.md} +0 -0
- /data/templates/{EXECUTE/03_ADR_FACTORY.md → planning/generate_adrs.md} +0 -0
- /data/templates/{EXECUTE/12_OBSERVABILITY_SLOS.md → planning/plan_observability.md} +0 -0
- /data/templates/{EXECUTE/07_TEST_PLAN.md → planning/plan_testing.md} +0 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "timeout"
|
|
4
|
+
require_relative "base"
|
|
5
|
+
require_relative "../util"
|
|
6
|
+
require_relative "../debug_mixin"
|
|
7
|
+
|
|
8
|
+
module Aidp
|
|
9
|
+
module Providers
|
|
10
|
+
class GithubCopilot < Base
|
|
11
|
+
include Aidp::DebugMixin
|
|
12
|
+
|
|
13
|
+
def self.available?
|
|
14
|
+
!!Aidp::Util.which("copilot")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def name
|
|
18
|
+
"github_copilot"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def display_name
|
|
22
|
+
"GitHub Copilot CLI"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def available?
|
|
26
|
+
return false unless self.class.available?
|
|
27
|
+
|
|
28
|
+
# Additional check to ensure the CLI is properly configured
|
|
29
|
+
begin
|
|
30
|
+
result = Aidp::Util.execute_command("copilot", ["--version"], timeout: 10)
|
|
31
|
+
result.exit_status == 0
|
|
32
|
+
rescue
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def send(prompt:, session: nil)
|
|
38
|
+
raise "copilot CLI not available" unless self.class.available?
|
|
39
|
+
|
|
40
|
+
# Smart timeout calculation
|
|
41
|
+
timeout_seconds = calculate_timeout
|
|
42
|
+
|
|
43
|
+
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds})
|
|
44
|
+
debug_log("📝 Sending prompt to copilot (length: #{prompt.length})", level: :info)
|
|
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
|
+
# Set up activity monitoring
|
|
53
|
+
setup_activity_monitoring("copilot", method(:activity_callback))
|
|
54
|
+
record_activity("Starting copilot execution")
|
|
55
|
+
|
|
56
|
+
# Create a spinner for activity display
|
|
57
|
+
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
|
58
|
+
spinner.auto_spin
|
|
59
|
+
|
|
60
|
+
# Start activity display thread with timeout
|
|
61
|
+
activity_display_thread = Thread.new do
|
|
62
|
+
start_time = Time.now
|
|
63
|
+
loop do
|
|
64
|
+
sleep 0.5 # Update every 500ms to reduce spam
|
|
65
|
+
elapsed = Time.now - start_time
|
|
66
|
+
|
|
67
|
+
# Break if we've been running too long or state changed
|
|
68
|
+
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
|
69
|
+
|
|
70
|
+
update_spinner_status(spinner, elapsed, "🤖 GitHub Copilot CLI")
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
# Use non-interactive mode for automation
|
|
76
|
+
args = ["-p", prompt, "--allow-all-tools"]
|
|
77
|
+
|
|
78
|
+
# Add session support if provided
|
|
79
|
+
if session && !session.empty?
|
|
80
|
+
args += ["--resume", session]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Use debug_execute_command for better debugging (no input since prompt is in args)
|
|
84
|
+
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds, streaming: streaming_enabled)
|
|
85
|
+
|
|
86
|
+
# Log the results
|
|
87
|
+
debug_command("copilot", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
88
|
+
|
|
89
|
+
if result.exit_status == 0
|
|
90
|
+
spinner.success("✓")
|
|
91
|
+
mark_completed
|
|
92
|
+
result.out
|
|
93
|
+
else
|
|
94
|
+
spinner.error("✗")
|
|
95
|
+
mark_failed("copilot failed with exit code #{result.exit_status}")
|
|
96
|
+
debug_error(StandardError.new("copilot failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
97
|
+
raise "copilot failed with exit code #{result.exit_status}: #{result.err}"
|
|
98
|
+
end
|
|
99
|
+
rescue => e
|
|
100
|
+
spinner&.error("✗")
|
|
101
|
+
mark_failed("copilot execution failed: #{e.message}")
|
|
102
|
+
debug_error(e, {provider: "github_copilot", prompt_length: prompt.length})
|
|
103
|
+
raise
|
|
104
|
+
ensure
|
|
105
|
+
cleanup_activity_display(activity_display_thread, spinner)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Enhanced send method with additional options
|
|
110
|
+
def send_with_options(prompt:, session: nil, tools: nil, log_level: nil, config_file: nil, directories: nil)
|
|
111
|
+
args = ["-p", prompt]
|
|
112
|
+
|
|
113
|
+
# Add session support
|
|
114
|
+
if session && !session.empty?
|
|
115
|
+
args += ["--resume", session]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Add tool permissions
|
|
119
|
+
if tools && !tools.empty?
|
|
120
|
+
if tools.include?("all")
|
|
121
|
+
args += ["--allow-all-tools"]
|
|
122
|
+
else
|
|
123
|
+
tools.each do |tool|
|
|
124
|
+
args += ["--allow-tool", tool]
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
else
|
|
128
|
+
# Default to allowing all tools for automation
|
|
129
|
+
args += ["--allow-all-tools"]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Add logging level
|
|
133
|
+
if log_level
|
|
134
|
+
args += ["--log-level", log_level]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Add allowed directories
|
|
138
|
+
if directories && !directories.empty?
|
|
139
|
+
directories.each do |dir|
|
|
140
|
+
args += ["--add-dir", dir]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Use the enhanced version of send
|
|
145
|
+
send_with_custom_args(prompt: prompt, args: args)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Override health check for GitHub Copilot specific considerations
|
|
149
|
+
def harness_healthy?
|
|
150
|
+
return false unless super
|
|
151
|
+
|
|
152
|
+
# Additional health checks specific to GitHub Copilot CLI
|
|
153
|
+
# Check if we can access GitHub (basic connectivity test)
|
|
154
|
+
begin
|
|
155
|
+
result = Aidp::Util.execute_command("copilot", ["--help"], timeout: 5)
|
|
156
|
+
result.exit_status == 0
|
|
157
|
+
rescue
|
|
158
|
+
false
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
private
|
|
163
|
+
|
|
164
|
+
def send_with_custom_args(prompt:, args:)
|
|
165
|
+
timeout_seconds = calculate_timeout
|
|
166
|
+
|
|
167
|
+
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds, args: args})
|
|
168
|
+
debug_log("📝 Sending prompt to copilot with custom args", level: :info)
|
|
169
|
+
|
|
170
|
+
# Check if streaming mode is enabled
|
|
171
|
+
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
172
|
+
if streaming_enabled
|
|
173
|
+
display_message("📺 Display streaming enabled - output buffering reduced (copilot CLI does not support true streaming)", type: :info)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
setup_activity_monitoring("copilot", method(:activity_callback))
|
|
177
|
+
record_activity("Starting copilot execution with custom args")
|
|
178
|
+
|
|
179
|
+
begin
|
|
180
|
+
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds, streaming: streaming_enabled)
|
|
181
|
+
debug_command("copilot", args: args, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
182
|
+
|
|
183
|
+
if result.exit_status == 0
|
|
184
|
+
mark_completed
|
|
185
|
+
result.out
|
|
186
|
+
else
|
|
187
|
+
mark_failed("copilot failed with exit code #{result.exit_status}")
|
|
188
|
+
debug_error(StandardError.new("copilot failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
189
|
+
raise "copilot failed with exit code #{result.exit_status}: #{result.err}"
|
|
190
|
+
end
|
|
191
|
+
rescue => e
|
|
192
|
+
mark_failed("copilot execution failed: #{e.message}")
|
|
193
|
+
debug_error(e, {provider: "github_copilot", prompt_length: prompt.length})
|
|
194
|
+
raise
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def calculate_timeout
|
|
199
|
+
# Priority order for timeout calculation:
|
|
200
|
+
# 1. Quick mode (for testing)
|
|
201
|
+
# 2. Environment variable override
|
|
202
|
+
# 3. Adaptive timeout based on step type
|
|
203
|
+
# 4. Default timeout
|
|
204
|
+
|
|
205
|
+
if ENV["AIDP_QUICK_MODE"]
|
|
206
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
207
|
+
return TIMEOUT_QUICK_MODE
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if ENV["AIDP_GITHUB_COPILOT_TIMEOUT"]
|
|
211
|
+
return ENV["AIDP_GITHUB_COPILOT_TIMEOUT"].to_i
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Adaptive timeout based on step type
|
|
215
|
+
step_timeout = get_adaptive_timeout
|
|
216
|
+
if step_timeout
|
|
217
|
+
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
218
|
+
return step_timeout
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Default timeout
|
|
222
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
223
|
+
TIMEOUT_DEFAULT
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def get_adaptive_timeout
|
|
227
|
+
# Timeout recommendations based on step type patterns
|
|
228
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
229
|
+
|
|
230
|
+
case step_name
|
|
231
|
+
when /REPOSITORY_ANALYSIS/
|
|
232
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
|
233
|
+
when /ARCHITECTURE_ANALYSIS/
|
|
234
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
235
|
+
when /TEST_ANALYSIS/
|
|
236
|
+
TIMEOUT_TEST_ANALYSIS
|
|
237
|
+
when /FUNCTIONALITY_ANALYSIS/
|
|
238
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
239
|
+
when /DOCUMENTATION_ANALYSIS/
|
|
240
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
241
|
+
when /STATIC_ANALYSIS/
|
|
242
|
+
TIMEOUT_STATIC_ANALYSIS
|
|
243
|
+
when /REFACTORING_RECOMMENDATIONS/
|
|
244
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
245
|
+
else
|
|
246
|
+
nil # Use default
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def activity_callback(state, message, provider)
|
|
251
|
+
# Handle activity state changes
|
|
252
|
+
case state
|
|
253
|
+
when :stuck
|
|
254
|
+
display_message("\n⚠️ GitHub Copilot CLI appears stuck: #{message}", type: :warning)
|
|
255
|
+
when :completed
|
|
256
|
+
display_message("\n✅ GitHub Copilot CLI completed: #{message}", type: :success)
|
|
257
|
+
when :failed
|
|
258
|
+
display_message("\n❌ GitHub Copilot CLI failed: #{message}", type: :error)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
@@ -18,6 +18,10 @@ module Aidp
|
|
|
18
18
|
"opencode"
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
def display_name
|
|
22
|
+
"OpenCode"
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def send(prompt:, session: nil)
|
|
22
26
|
raise "opencode not available" unless self.class.available?
|
|
23
27
|
|
|
@@ -27,6 +31,12 @@ module Aidp
|
|
|
27
31
|
debug_provider("opencode", "Starting execution", {timeout: timeout_seconds})
|
|
28
32
|
debug_log("📝 Sending prompt to opencode (length: #{prompt.length})", level: :info)
|
|
29
33
|
|
|
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
|
+
|
|
30
40
|
# Check if prompt is too large and warn
|
|
31
41
|
if prompt.length > 3000
|
|
32
42
|
debug_log("⚠️ Large prompt detected (#{prompt.length} chars) - this may cause rate limiting", level: :warn)
|
|
@@ -36,6 +46,10 @@ module Aidp
|
|
|
36
46
|
setup_activity_monitoring("opencode", method(:activity_callback))
|
|
37
47
|
record_activity("Starting opencode execution")
|
|
38
48
|
|
|
49
|
+
# Create a spinner for activity display
|
|
50
|
+
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
|
51
|
+
spinner.auto_spin
|
|
52
|
+
|
|
39
53
|
# Start activity display thread with timeout
|
|
40
54
|
activity_display_thread = Thread.new do
|
|
41
55
|
start_time = Time.now
|
|
@@ -46,7 +60,7 @@ module Aidp
|
|
|
46
60
|
# Break if we've been running too long or state changed
|
|
47
61
|
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
|
48
62
|
|
|
49
|
-
|
|
63
|
+
update_spinner_status(spinner, elapsed, "🔄 opencode")
|
|
50
64
|
end
|
|
51
65
|
end
|
|
52
66
|
|
|
@@ -54,56 +68,33 @@ module Aidp
|
|
|
54
68
|
# Use debug_execute_command for better debugging
|
|
55
69
|
# opencode run command with prompt and model
|
|
56
70
|
model = ENV["OPENCODE_MODEL"] || "github-copilot/claude-3.5-sonnet"
|
|
57
|
-
result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds)
|
|
71
|
+
result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds, streaming: streaming_enabled)
|
|
58
72
|
|
|
59
73
|
# Log the results
|
|
60
74
|
debug_command("opencode", args: ["run", "-m", model, prompt], input: nil, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
61
75
|
|
|
62
|
-
# Stop activity display
|
|
63
|
-
activity_display_thread.kill if activity_display_thread.alive?
|
|
64
|
-
activity_display_thread.join(0.1) # Give it 100ms to finish
|
|
65
|
-
clear_activity_status
|
|
66
|
-
|
|
67
76
|
if result.exit_status == 0
|
|
77
|
+
spinner.success("✓")
|
|
68
78
|
mark_completed
|
|
69
79
|
result.out
|
|
70
80
|
else
|
|
81
|
+
spinner.error("✗")
|
|
71
82
|
mark_failed("opencode failed with exit code #{result.exit_status}")
|
|
72
83
|
debug_error(StandardError.new("opencode failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
73
84
|
raise "opencode failed with exit code #{result.exit_status}: #{result.err}"
|
|
74
85
|
end
|
|
75
86
|
rescue => e
|
|
76
|
-
|
|
77
|
-
activity_display_thread.kill if activity_display_thread.alive?
|
|
78
|
-
activity_display_thread.join(0.1) # Give it 100ms to finish
|
|
79
|
-
clear_activity_status
|
|
87
|
+
spinner&.error("✗")
|
|
80
88
|
mark_failed("opencode execution failed: #{e.message}")
|
|
81
89
|
debug_error(e, {provider: "opencode", prompt_length: prompt.length})
|
|
82
90
|
raise
|
|
91
|
+
ensure
|
|
92
|
+
cleanup_activity_display(activity_display_thread, spinner)
|
|
83
93
|
end
|
|
84
94
|
end
|
|
85
95
|
|
|
86
96
|
private
|
|
87
97
|
|
|
88
|
-
def print_activity_status(elapsed)
|
|
89
|
-
# Print activity status during opencode execution with elapsed time
|
|
90
|
-
minutes = (elapsed / 60).to_i
|
|
91
|
-
seconds = (elapsed % 60).to_i
|
|
92
|
-
|
|
93
|
-
if minutes > 0
|
|
94
|
-
print "\r🔄 opencode is running... (#{minutes}m #{seconds}s)"
|
|
95
|
-
else
|
|
96
|
-
print "\r🔄 opencode is running... (#{seconds}s)"
|
|
97
|
-
end
|
|
98
|
-
$stdout.flush
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def clear_activity_status
|
|
102
|
-
# Clear the activity status line
|
|
103
|
-
print "\r" + " " * 50 + "\r"
|
|
104
|
-
$stdout.flush
|
|
105
|
-
end
|
|
106
|
-
|
|
107
98
|
def calculate_timeout
|
|
108
99
|
# Priority order for timeout calculation:
|
|
109
100
|
# 1. Quick mode (for testing)
|
|
@@ -112,8 +103,8 @@ module Aidp
|
|
|
112
103
|
# 4. Default timeout
|
|
113
104
|
|
|
114
105
|
if ENV["AIDP_QUICK_MODE"]
|
|
115
|
-
|
|
116
|
-
return
|
|
106
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
107
|
+
return TIMEOUT_QUICK_MODE
|
|
117
108
|
end
|
|
118
109
|
|
|
119
110
|
if ENV["AIDP_OPENCODE_TIMEOUT"]
|
|
@@ -123,13 +114,13 @@ module Aidp
|
|
|
123
114
|
# Adaptive timeout based on step type
|
|
124
115
|
step_timeout = get_adaptive_timeout
|
|
125
116
|
if step_timeout
|
|
126
|
-
|
|
117
|
+
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
127
118
|
return step_timeout
|
|
128
119
|
end
|
|
129
120
|
|
|
130
|
-
# Default timeout
|
|
131
|
-
|
|
132
|
-
|
|
121
|
+
# Default timeout
|
|
122
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
123
|
+
TIMEOUT_DEFAULT
|
|
133
124
|
end
|
|
134
125
|
|
|
135
126
|
def get_adaptive_timeout
|
|
@@ -138,21 +129,21 @@ module Aidp
|
|
|
138
129
|
|
|
139
130
|
case step_name
|
|
140
131
|
when /REPOSITORY_ANALYSIS/
|
|
141
|
-
|
|
132
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
|
142
133
|
when /ARCHITECTURE_ANALYSIS/
|
|
143
|
-
|
|
134
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
144
135
|
when /TEST_ANALYSIS/
|
|
145
|
-
|
|
136
|
+
TIMEOUT_TEST_ANALYSIS
|
|
146
137
|
when /FUNCTIONALITY_ANALYSIS/
|
|
147
|
-
|
|
138
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
148
139
|
when /DOCUMENTATION_ANALYSIS/
|
|
149
|
-
|
|
140
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
150
141
|
when /STATIC_ANALYSIS/
|
|
151
|
-
|
|
142
|
+
TIMEOUT_STATIC_ANALYSIS
|
|
152
143
|
when /REFACTORING_RECOMMENDATIONS/
|
|
153
|
-
|
|
144
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
154
145
|
else
|
|
155
|
-
nil
|
|
146
|
+
nil # Use default
|
|
156
147
|
end
|
|
157
148
|
end
|
|
158
149
|
|
|
@@ -161,11 +152,11 @@ module Aidp
|
|
|
161
152
|
# Only print static messages for state changes
|
|
162
153
|
case state
|
|
163
154
|
when :starting
|
|
164
|
-
|
|
155
|
+
display_message("🚀 Starting opencode execution...", type: :info)
|
|
165
156
|
when :completed
|
|
166
|
-
|
|
157
|
+
display_message("✅ opencode execution completed", type: :success)
|
|
167
158
|
when :failed
|
|
168
|
-
|
|
159
|
+
display_message("❌ opencode execution failed: #{message}", type: :error)
|
|
169
160
|
end
|
|
170
161
|
end
|
|
171
162
|
|
data/lib/aidp/version.rb
CHANGED