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,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,61 +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
|
-
$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_CURSOR_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 :stuck
|
|
164
|
-
|
|
155
|
+
display_message("\n⚠️ cursor appears stuck: #{message}", type: :warning)
|
|
165
156
|
when :completed
|
|
166
|
-
|
|
157
|
+
display_message("\n✅ cursor completed: #{message}", type: :success)
|
|
167
158
|
when :failed
|
|
168
|
-
|
|
159
|
+
display_message("\n❌ cursor failed: #{message}", type: :error)
|
|
169
160
|
end
|
|
170
161
|
end
|
|
171
162
|
end
|
|
@@ -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
|
-
|
|
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"]
|
|
@@ -65,13 +75,13 @@ module Aidp
|
|
|
65
75
|
# Adaptive timeout based on step type
|
|
66
76
|
step_timeout = get_adaptive_timeout
|
|
67
77
|
if step_timeout
|
|
68
|
-
|
|
78
|
+
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
69
79
|
return step_timeout
|
|
70
80
|
end
|
|
71
81
|
|
|
72
|
-
# Default timeout
|
|
73
|
-
|
|
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
|