aidp 0.10.0 → 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/kb_inspector.rb +2 -15
- data/lib/aidp/analyze/progress.rb +2 -1
- data/lib/aidp/analyze/ruby_maat_integration.rb +2 -15
- data/lib/aidp/analyze/runner.rb +64 -20
- data/lib/aidp/analyze/steps.rb +10 -8
- data/lib/aidp/analyze/tree_sitter_grammar_loader.rb +2 -13
- data/lib/aidp/analyze/tree_sitter_scan.rb +2 -13
- data/lib/aidp/cli/checkpoint_command.rb +98 -0
- data/lib/aidp/cli/first_run_wizard.rb +65 -94
- data/lib/aidp/cli/jobs_command.rb +249 -34
- data/lib/aidp/cli.rb +312 -38
- 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 +53 -24
- 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 +26 -17
- 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 +22 -1
- data/lib/aidp/harness/error_handler.rb +103 -28
- data/lib/aidp/harness/provider_factory.rb +4 -1
- data/lib/aidp/harness/provider_manager.rb +250 -15
- data/lib/aidp/harness/runner.rb +3 -14
- data/lib/aidp/harness/simple_user_interface.rb +2 -15
- data/lib/aidp/harness/status_display.rb +12 -17
- data/lib/aidp/harness/test_runner.rb +83 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +2 -0
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +22 -4
- data/lib/aidp/harness/ui/error_handler.rb +4 -0
- data/lib/aidp/harness/ui/frame_manager.rb +10 -8
- data/lib/aidp/harness/ui/job_monitor.rb +2 -0
- data/lib/aidp/harness/ui/navigation/main_menu.rb +4 -2
- 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 +8 -12
- 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 +3 -1
- data/lib/aidp/harness/ui/workflow_controller.rb +2 -0
- data/lib/aidp/harness/user_interface.rb +12 -17
- data/lib/aidp/jobs/background_runner.rb +278 -0
- data/lib/aidp/message_display.rb +48 -0
- data/lib/aidp/provider_manager.rb +3 -1
- data/lib/aidp/providers/anthropic.rb +100 -17
- data/lib/aidp/providers/base.rb +42 -11
- data/lib/aidp/providers/codex.rb +248 -0
- data/lib/aidp/providers/cursor.rb +35 -42
- data/lib/aidp/providers/gemini.rb +25 -15
- data/lib/aidp/providers/github_copilot.rb +41 -42
- data/lib/aidp/providers/opencode.rb +34 -41
- 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 +12 -0
- data/templates/planning/generate_llm_style_guide.md +119 -0
- metadata +38 -26
- /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,248 @@
|
|
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 Codex < Base
|
11
|
+
include Aidp::DebugMixin
|
12
|
+
|
13
|
+
def self.available?
|
14
|
+
!!Aidp::Util.which("codex")
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
"codex"
|
19
|
+
end
|
20
|
+
|
21
|
+
def display_name
|
22
|
+
"Codex 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("codex", ["--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 "codex CLI not available" unless self.class.available?
|
39
|
+
|
40
|
+
# Smart timeout calculation
|
41
|
+
timeout_seconds = calculate_timeout
|
42
|
+
|
43
|
+
debug_provider("codex", "Starting execution", {timeout: timeout_seconds})
|
44
|
+
debug_log("📝 Sending prompt to codex (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("📺 Streaming mode enabled - output will appear in real-time", type: :info)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Set up activity monitoring
|
53
|
+
setup_activity_monitoring("codex", method(:activity_callback))
|
54
|
+
record_activity("Starting codex 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, "🤖 Codex CLI")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
begin
|
75
|
+
# Use non-interactive mode (exec) for automation
|
76
|
+
args = ["exec", prompt]
|
77
|
+
|
78
|
+
# Add session support if provided (codex may support session/thread continuation)
|
79
|
+
if session && !session.empty?
|
80
|
+
args += ["--session", session]
|
81
|
+
end
|
82
|
+
|
83
|
+
# Use debug_execute_command for better debugging
|
84
|
+
result = debug_execute_command("codex", args: args, timeout: timeout_seconds, streaming: streaming_enabled)
|
85
|
+
|
86
|
+
# Log the results
|
87
|
+
debug_command("codex", 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("codex failed with exit code #{result.exit_status}")
|
96
|
+
debug_error(StandardError.new("codex failed"), {exit_code: result.exit_status, stderr: result.err})
|
97
|
+
raise "codex failed with exit code #{result.exit_status}: #{result.err}"
|
98
|
+
end
|
99
|
+
rescue => e
|
100
|
+
spinner&.error("✗")
|
101
|
+
mark_failed("codex execution failed: #{e.message}")
|
102
|
+
debug_error(e, {provider: "codex", 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, model: nil, ask_for_approval: false)
|
111
|
+
args = ["exec", prompt]
|
112
|
+
|
113
|
+
# Add session support
|
114
|
+
if session && !session.empty?
|
115
|
+
args += ["--session", session]
|
116
|
+
end
|
117
|
+
|
118
|
+
# Add model selection
|
119
|
+
if model
|
120
|
+
args += ["--model", model]
|
121
|
+
end
|
122
|
+
|
123
|
+
# Add approval flag
|
124
|
+
if ask_for_approval
|
125
|
+
args += ["--ask-for-approval"]
|
126
|
+
end
|
127
|
+
|
128
|
+
# Use the enhanced version of send
|
129
|
+
send_with_custom_args(prompt: prompt, args: args)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Override health check for Codex specific considerations
|
133
|
+
def harness_healthy?
|
134
|
+
return false unless super
|
135
|
+
|
136
|
+
# Additional health checks specific to Codex CLI
|
137
|
+
# Check if we can access the CLI (basic connectivity test)
|
138
|
+
begin
|
139
|
+
result = Aidp::Util.execute_command("codex", ["--help"], timeout: 5)
|
140
|
+
result.exit_status == 0
|
141
|
+
rescue
|
142
|
+
false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
# Internal helper for send_with_options - executes with custom arguments
|
149
|
+
def send_with_custom_args(prompt:, args:)
|
150
|
+
timeout_seconds = calculate_timeout
|
151
|
+
|
152
|
+
debug_provider("codex", "Starting execution", {timeout: timeout_seconds, args: args})
|
153
|
+
debug_log("📝 Sending prompt to codex with custom args", level: :info)
|
154
|
+
|
155
|
+
# Check if streaming mode is enabled
|
156
|
+
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
157
|
+
if streaming_enabled
|
158
|
+
display_message("📺 Display streaming enabled - output buffering reduced (codex CLI does not support true streaming)", type: :info)
|
159
|
+
end
|
160
|
+
|
161
|
+
setup_activity_monitoring("codex", method(:activity_callback))
|
162
|
+
record_activity("Starting codex execution with custom args")
|
163
|
+
|
164
|
+
begin
|
165
|
+
result = debug_execute_command("codex", args: args, timeout: timeout_seconds, streaming: streaming_enabled)
|
166
|
+
debug_command("codex", args: args, output: result.out, error: result.err, exit_code: result.exit_status)
|
167
|
+
|
168
|
+
if result.exit_status == 0
|
169
|
+
mark_completed
|
170
|
+
result.out
|
171
|
+
else
|
172
|
+
mark_failed("codex failed with exit code #{result.exit_status}")
|
173
|
+
debug_error(StandardError.new("codex failed"), {exit_code: result.exit_status, stderr: result.err})
|
174
|
+
raise "codex failed with exit code #{result.exit_status}: #{result.err}"
|
175
|
+
end
|
176
|
+
rescue => e
|
177
|
+
mark_failed("codex execution failed: #{e.message}")
|
178
|
+
debug_error(e, {provider: "codex", prompt_length: prompt.length})
|
179
|
+
raise
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def calculate_timeout
|
184
|
+
# Priority order for timeout calculation:
|
185
|
+
# 1. Quick mode (for testing)
|
186
|
+
# 2. Environment variable override
|
187
|
+
# 3. Adaptive timeout based on step type
|
188
|
+
# 4. Default timeout
|
189
|
+
|
190
|
+
if ENV["AIDP_QUICK_MODE"]
|
191
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
192
|
+
return TIMEOUT_QUICK_MODE
|
193
|
+
end
|
194
|
+
|
195
|
+
if ENV["AIDP_CODEX_TIMEOUT"]
|
196
|
+
return ENV["AIDP_CODEX_TIMEOUT"].to_i
|
197
|
+
end
|
198
|
+
|
199
|
+
# Adaptive timeout based on step type
|
200
|
+
step_timeout = get_adaptive_timeout
|
201
|
+
if step_timeout
|
202
|
+
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
203
|
+
return step_timeout
|
204
|
+
end
|
205
|
+
|
206
|
+
# Default timeout
|
207
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
208
|
+
TIMEOUT_DEFAULT
|
209
|
+
end
|
210
|
+
|
211
|
+
def get_adaptive_timeout
|
212
|
+
# Timeout recommendations based on step type patterns
|
213
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
214
|
+
|
215
|
+
case step_name
|
216
|
+
when /REPOSITORY_ANALYSIS/
|
217
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
218
|
+
when /ARCHITECTURE_ANALYSIS/
|
219
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
220
|
+
when /TEST_ANALYSIS/
|
221
|
+
TIMEOUT_TEST_ANALYSIS
|
222
|
+
when /FUNCTIONALITY_ANALYSIS/
|
223
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
224
|
+
when /DOCUMENTATION_ANALYSIS/
|
225
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
226
|
+
when /STATIC_ANALYSIS/
|
227
|
+
TIMEOUT_STATIC_ANALYSIS
|
228
|
+
when /REFACTORING_RECOMMENDATIONS/
|
229
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
230
|
+
else
|
231
|
+
nil # Use default
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def activity_callback(state, message, provider)
|
236
|
+
# Handle activity state changes
|
237
|
+
case state
|
238
|
+
when :stuck
|
239
|
+
display_message("\n⚠️ Codex CLI appears stuck: #{message}", type: :warning)
|
240
|
+
when :completed
|
241
|
+
display_message("\n✅ Codex CLI completed: #{message}", type: :success)
|
242
|
+
when :failed
|
243
|
+
display_message("\n❌ Codex CLI failed: #{message}", type: :error)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
@@ -18,6 +18,10 @@ module Aidp
|
|
18
18
|
"cursor"
|
19
19
|
end
|
20
20
|
|
21
|
+
def display_name
|
22
|
+
"Cursor AI"
|
23
|
+
end
|
24
|
+
|
21
25
|
def send(prompt:, session: nil)
|
22
26
|
raise "cursor-agent not available" unless self.class.available?
|
23
27
|
|
@@ -27,10 +31,20 @@ module Aidp
|
|
27
31
|
debug_provider("cursor", "Starting execution", {timeout: timeout_seconds})
|
28
32
|
debug_log("📝 Sending prompt to cursor-agent (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 (cursor-agent does not support true streaming)", type: :info)
|
38
|
+
end
|
39
|
+
|
30
40
|
# Set up activity monitoring
|
31
41
|
setup_activity_monitoring("cursor-agent", method(:activity_callback))
|
32
42
|
record_activity("Starting cursor-agent execution")
|
33
43
|
|
44
|
+
# Create a spinner for activity display
|
45
|
+
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
46
|
+
spinner.auto_spin
|
47
|
+
|
34
48
|
# Start activity display thread with timeout
|
35
49
|
activity_display_thread = Thread.new do
|
36
50
|
start_time = Time.now
|
@@ -41,7 +55,7 @@ module Aidp
|
|
41
55
|
# Break if we've been running too long or state changed
|
42
56
|
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
43
57
|
|
44
|
-
|
58
|
+
update_spinner_status(spinner, elapsed, "🔄 cursor-agent")
|
45
59
|
end
|
46
60
|
end
|
47
61
|
|
@@ -49,59 +63,38 @@ module Aidp
|
|
49
63
|
# Use debug_execute_command for better debugging
|
50
64
|
# Try agent command first (better for large prompts), fallback to -p mode
|
51
65
|
begin
|
52
|
-
result = debug_execute_command("cursor-agent", args: ["agent"], input: prompt, timeout: timeout_seconds)
|
66
|
+
result = debug_execute_command("cursor-agent", args: ["agent"], input: prompt, timeout: timeout_seconds, streaming: streaming_enabled)
|
53
67
|
rescue => e
|
54
68
|
# Fallback to -p mode if agent command fails
|
55
69
|
debug_log("🔄 Falling back to -p mode: #{e.message}", level: :warn)
|
56
|
-
result = debug_execute_command("cursor-agent", args: ["-p"], input: prompt, timeout: timeout_seconds)
|
70
|
+
result = debug_execute_command("cursor-agent", args: ["-p"], input: prompt, timeout: timeout_seconds, streaming: streaming_enabled)
|
57
71
|
end
|
58
72
|
|
59
73
|
# Log the results
|
60
74
|
debug_command("cursor-agent", args: ["-p"], input: prompt, 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("cursor-agent failed with exit code #{result.exit_status}")
|
72
83
|
debug_error(StandardError.new("cursor-agent failed"), {exit_code: result.exit_status, stderr: result.err})
|
73
84
|
raise "cursor-agent 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("cursor-agent execution failed: #{e.message}")
|
81
89
|
debug_error(e, {provider: "cursor", 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 cursor execution with elapsed time
|
90
|
-
minutes = (elapsed / 60).to_i
|
91
|
-
seconds = (elapsed % 60).to_i
|
92
|
-
|
93
|
-
if minutes > 0
|
94
|
-
print "\r🔄 cursor-agent is running... (#{minutes}m #{seconds}s)"
|
95
|
-
else
|
96
|
-
print "\r🔄 cursor-agent is running... (#{seconds}s)"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def clear_activity_status
|
101
|
-
# Clear the activity status line
|
102
|
-
print "\r" + " " * 50 + "\r"
|
103
|
-
end
|
104
|
-
|
105
98
|
def calculate_timeout
|
106
99
|
# Priority order for timeout calculation:
|
107
100
|
# 1. Quick mode (for testing)
|
@@ -110,8 +103,8 @@ module Aidp
|
|
110
103
|
# 4. Default timeout
|
111
104
|
|
112
105
|
if ENV["AIDP_QUICK_MODE"]
|
113
|
-
display_message("⚡ Quick mode enabled -
|
114
|
-
return
|
106
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
107
|
+
return TIMEOUT_QUICK_MODE
|
115
108
|
end
|
116
109
|
|
117
110
|
if ENV["AIDP_CURSOR_TIMEOUT"]
|
@@ -125,9 +118,9 @@ module Aidp
|
|
125
118
|
return step_timeout
|
126
119
|
end
|
127
120
|
|
128
|
-
# Default timeout
|
129
|
-
display_message("📋 Using default timeout:
|
130
|
-
|
121
|
+
# Default timeout
|
122
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
123
|
+
TIMEOUT_DEFAULT
|
131
124
|
end
|
132
125
|
|
133
126
|
def get_adaptive_timeout
|
@@ -136,21 +129,21 @@ module Aidp
|
|
136
129
|
|
137
130
|
case step_name
|
138
131
|
when /REPOSITORY_ANALYSIS/
|
139
|
-
|
132
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
140
133
|
when /ARCHITECTURE_ANALYSIS/
|
141
|
-
|
134
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
142
135
|
when /TEST_ANALYSIS/
|
143
|
-
|
136
|
+
TIMEOUT_TEST_ANALYSIS
|
144
137
|
when /FUNCTIONALITY_ANALYSIS/
|
145
|
-
|
138
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
146
139
|
when /DOCUMENTATION_ANALYSIS/
|
147
|
-
|
140
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
148
141
|
when /STATIC_ANALYSIS/
|
149
|
-
|
142
|
+
TIMEOUT_STATIC_ANALYSIS
|
150
143
|
when /REFACTORING_RECOMMENDATIONS/
|
151
|
-
|
144
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
152
145
|
else
|
153
|
-
nil
|
146
|
+
nil # Use default
|
154
147
|
end
|
155
148
|
end
|
156
149
|
|
@@ -16,6 +16,10 @@ module Aidp
|
|
16
16
|
"gemini"
|
17
17
|
end
|
18
18
|
|
19
|
+
def display_name
|
20
|
+
"Google Gemini"
|
21
|
+
end
|
22
|
+
|
19
23
|
def send(prompt:, session: nil)
|
20
24
|
raise "gemini CLI not available" unless self.class.available?
|
21
25
|
|
@@ -25,9 +29,15 @@ module Aidp
|
|
25
29
|
debug_provider("gemini", "Starting execution", {timeout: timeout_seconds})
|
26
30
|
debug_log("📝 Sending prompt to gemini...", level: :info)
|
27
31
|
|
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
|
+
|
28
38
|
begin
|
29
|
-
# Use debug_execute_command
|
30
|
-
result = debug_execute_command("gemini", args: ["--print"], input: prompt, timeout: timeout_seconds)
|
39
|
+
# Use debug_execute_command with streaming support
|
40
|
+
result = debug_execute_command("gemini", args: ["--print"], input: prompt, timeout: timeout_seconds, streaming: streaming_enabled)
|
31
41
|
|
32
42
|
# Log the results
|
33
43
|
debug_command("gemini", args: ["--print"], input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
@@ -54,8 +64,8 @@ module Aidp
|
|
54
64
|
# 4. Default timeout
|
55
65
|
|
56
66
|
if ENV["AIDP_QUICK_MODE"]
|
57
|
-
display_message("⚡ Quick mode enabled -
|
58
|
-
return
|
67
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
68
|
+
return TIMEOUT_QUICK_MODE
|
59
69
|
end
|
60
70
|
|
61
71
|
if ENV["AIDP_GEMINI_TIMEOUT"]
|
@@ -69,9 +79,9 @@ module Aidp
|
|
69
79
|
return step_timeout
|
70
80
|
end
|
71
81
|
|
72
|
-
# Default timeout
|
73
|
-
display_message("📋 Using default timeout:
|
74
|
-
|
82
|
+
# Default timeout
|
83
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
84
|
+
TIMEOUT_DEFAULT
|
75
85
|
end
|
76
86
|
|
77
87
|
def get_adaptive_timeout
|
@@ -80,21 +90,21 @@ module Aidp
|
|
80
90
|
|
81
91
|
case step_name
|
82
92
|
when /REPOSITORY_ANALYSIS/
|
83
|
-
|
93
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
84
94
|
when /ARCHITECTURE_ANALYSIS/
|
85
|
-
|
95
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
86
96
|
when /TEST_ANALYSIS/
|
87
|
-
|
97
|
+
TIMEOUT_TEST_ANALYSIS
|
88
98
|
when /FUNCTIONALITY_ANALYSIS/
|
89
|
-
|
99
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
90
100
|
when /DOCUMENTATION_ANALYSIS/
|
91
|
-
|
101
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
92
102
|
when /STATIC_ANALYSIS/
|
93
|
-
|
103
|
+
TIMEOUT_STATIC_ANALYSIS
|
94
104
|
when /REFACTORING_RECOMMENDATIONS/
|
95
|
-
|
105
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
96
106
|
else
|
97
|
-
nil
|
107
|
+
nil # Use default
|
98
108
|
end
|
99
109
|
end
|
100
110
|
end
|
@@ -18,6 +18,10 @@ module Aidp
|
|
18
18
|
"github_copilot"
|
19
19
|
end
|
20
20
|
|
21
|
+
def display_name
|
22
|
+
"GitHub Copilot CLI"
|
23
|
+
end
|
24
|
+
|
21
25
|
def available?
|
22
26
|
return false unless self.class.available?
|
23
27
|
|
@@ -39,10 +43,20 @@ module Aidp
|
|
39
43
|
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds})
|
40
44
|
debug_log("📝 Sending prompt to copilot (length: #{prompt.length})", level: :info)
|
41
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
|
+
|
42
52
|
# Set up activity monitoring
|
43
53
|
setup_activity_monitoring("copilot", method(:activity_callback))
|
44
54
|
record_activity("Starting copilot execution")
|
45
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
|
+
|
46
60
|
# Start activity display thread with timeout
|
47
61
|
activity_display_thread = Thread.new do
|
48
62
|
start_time = Time.now
|
@@ -53,7 +67,7 @@ module Aidp
|
|
53
67
|
# Break if we've been running too long or state changed
|
54
68
|
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
55
69
|
|
56
|
-
|
70
|
+
update_spinner_status(spinner, elapsed, "🤖 GitHub Copilot CLI")
|
57
71
|
end
|
58
72
|
end
|
59
73
|
|
@@ -67,32 +81,28 @@ module Aidp
|
|
67
81
|
end
|
68
82
|
|
69
83
|
# Use debug_execute_command for better debugging (no input since prompt is in args)
|
70
|
-
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds)
|
84
|
+
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds, streaming: streaming_enabled)
|
71
85
|
|
72
86
|
# Log the results
|
73
87
|
debug_command("copilot", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
74
88
|
|
75
|
-
# Stop activity display
|
76
|
-
activity_display_thread.kill if activity_display_thread.alive?
|
77
|
-
activity_display_thread.join(0.1) # Give it 100ms to finish
|
78
|
-
clear_activity_status
|
79
|
-
|
80
89
|
if result.exit_status == 0
|
90
|
+
spinner.success("✓")
|
81
91
|
mark_completed
|
82
92
|
result.out
|
83
93
|
else
|
94
|
+
spinner.error("✗")
|
84
95
|
mark_failed("copilot failed with exit code #{result.exit_status}")
|
85
96
|
debug_error(StandardError.new("copilot failed"), {exit_code: result.exit_status, stderr: result.err})
|
86
97
|
raise "copilot failed with exit code #{result.exit_status}: #{result.err}"
|
87
98
|
end
|
88
99
|
rescue => e
|
89
|
-
|
90
|
-
activity_display_thread.kill if activity_display_thread.alive?
|
91
|
-
activity_display_thread.join(0.1) # Give it 100ms to finish
|
92
|
-
clear_activity_status
|
100
|
+
spinner&.error("✗")
|
93
101
|
mark_failed("copilot execution failed: #{e.message}")
|
94
102
|
debug_error(e, {provider: "github_copilot", prompt_length: prompt.length})
|
95
103
|
raise
|
104
|
+
ensure
|
105
|
+
cleanup_activity_display(activity_display_thread, spinner)
|
96
106
|
end
|
97
107
|
end
|
98
108
|
|
@@ -157,11 +167,17 @@ module Aidp
|
|
157
167
|
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds, args: args})
|
158
168
|
debug_log("📝 Sending prompt to copilot with custom args", level: :info)
|
159
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
|
+
|
160
176
|
setup_activity_monitoring("copilot", method(:activity_callback))
|
161
177
|
record_activity("Starting copilot execution with custom args")
|
162
178
|
|
163
179
|
begin
|
164
|
-
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds)
|
180
|
+
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds, streaming: streaming_enabled)
|
165
181
|
debug_command("copilot", args: args, output: result.out, error: result.err, exit_code: result.exit_status)
|
166
182
|
|
167
183
|
if result.exit_status == 0
|
@@ -179,23 +195,6 @@ module Aidp
|
|
179
195
|
end
|
180
196
|
end
|
181
197
|
|
182
|
-
def print_activity_status(elapsed)
|
183
|
-
# Print activity status during execution with elapsed time
|
184
|
-
minutes = (elapsed / 60).to_i
|
185
|
-
seconds = (elapsed % 60).to_i
|
186
|
-
|
187
|
-
if minutes > 0
|
188
|
-
print "\r🤖 GitHub Copilot CLI is running... (#{minutes}m #{seconds}s)"
|
189
|
-
else
|
190
|
-
print "\r🤖 GitHub Copilot CLI is running... (#{seconds}s)"
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def clear_activity_status
|
195
|
-
# Clear the activity status line
|
196
|
-
print "\r" + " " * 60 + "\r"
|
197
|
-
end
|
198
|
-
|
199
198
|
def calculate_timeout
|
200
199
|
# Priority order for timeout calculation:
|
201
200
|
# 1. Quick mode (for testing)
|
@@ -204,8 +203,8 @@ module Aidp
|
|
204
203
|
# 4. Default timeout
|
205
204
|
|
206
205
|
if ENV["AIDP_QUICK_MODE"]
|
207
|
-
display_message("⚡ Quick mode enabled -
|
208
|
-
return
|
206
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
207
|
+
return TIMEOUT_QUICK_MODE
|
209
208
|
end
|
210
209
|
|
211
210
|
if ENV["AIDP_GITHUB_COPILOT_TIMEOUT"]
|
@@ -219,9 +218,9 @@ module Aidp
|
|
219
218
|
return step_timeout
|
220
219
|
end
|
221
220
|
|
222
|
-
# Default timeout
|
223
|
-
display_message("📋 Using default timeout:
|
224
|
-
|
221
|
+
# Default timeout
|
222
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
223
|
+
TIMEOUT_DEFAULT
|
225
224
|
end
|
226
225
|
|
227
226
|
def get_adaptive_timeout
|
@@ -230,21 +229,21 @@ module Aidp
|
|
230
229
|
|
231
230
|
case step_name
|
232
231
|
when /REPOSITORY_ANALYSIS/
|
233
|
-
|
232
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
234
233
|
when /ARCHITECTURE_ANALYSIS/
|
235
|
-
|
234
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
236
235
|
when /TEST_ANALYSIS/
|
237
|
-
|
236
|
+
TIMEOUT_TEST_ANALYSIS
|
238
237
|
when /FUNCTIONALITY_ANALYSIS/
|
239
|
-
|
238
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
240
239
|
when /DOCUMENTATION_ANALYSIS/
|
241
|
-
|
240
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
242
241
|
when /STATIC_ANALYSIS/
|
243
|
-
|
242
|
+
TIMEOUT_STATIC_ANALYSIS
|
244
243
|
when /REFACTORING_RECOMMENDATIONS/
|
245
|
-
|
244
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
246
245
|
else
|
247
|
-
nil
|
246
|
+
nil # Use default
|
248
247
|
end
|
249
248
|
end
|
250
249
|
|