aidp 0.12.1 → 0.13.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/analyze/json_file_storage.rb +21 -21
- data/lib/aidp/cli/enhanced_input.rb +114 -0
- data/lib/aidp/cli/first_run_wizard.rb +1 -7
- data/lib/aidp/cli/mcp_dashboard.rb +3 -3
- data/lib/aidp/cli/terminal_io.rb +26 -0
- data/lib/aidp/cli.rb +4 -4
- data/lib/aidp/harness/condition_detector.rb +6 -6
- data/lib/aidp/harness/config_loader.rb +23 -23
- data/lib/aidp/harness/config_manager.rb +61 -61
- data/lib/aidp/harness/config_validator.rb +9 -9
- data/lib/aidp/harness/configuration.rb +28 -28
- data/lib/aidp/harness/error_handler.rb +13 -13
- data/lib/aidp/harness/provider_config.rb +79 -79
- data/lib/aidp/harness/provider_factory.rb +40 -40
- data/lib/aidp/harness/provider_info.rb +37 -20
- data/lib/aidp/harness/provider_manager.rb +58 -53
- data/lib/aidp/harness/provider_type_checker.rb +6 -6
- data/lib/aidp/harness/runner.rb +7 -7
- data/lib/aidp/harness/status_display.rb +33 -46
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +2 -1
- data/lib/aidp/harness/ui/job_monitor.rb +7 -7
- data/lib/aidp/harness/user_interface.rb +43 -43
- data/lib/aidp/providers/anthropic.rb +100 -26
- data/lib/aidp/providers/base.rb +13 -0
- data/lib/aidp/providers/codex.rb +28 -27
- data/lib/aidp/providers/cursor.rb +141 -34
- data/lib/aidp/providers/github_copilot.rb +26 -26
- data/lib/aidp/providers/macos_ui.rb +2 -18
- data/lib/aidp/providers/opencode.rb +26 -26
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/workflows/guided_agent.rb +344 -23
- metadata +2 -1
@@ -165,13 +165,13 @@ module Aidp
|
|
165
165
|
end
|
166
166
|
|
167
167
|
# Set display mode
|
168
|
-
def
|
168
|
+
def display_mode(mode)
|
169
169
|
@display_mode = mode
|
170
170
|
@display_config[:mode] = mode
|
171
171
|
end
|
172
172
|
|
173
173
|
# Set update interval
|
174
|
-
def
|
174
|
+
def update_interval(interval)
|
175
175
|
@update_interval = interval
|
176
176
|
@display_config[:update_interval] = interval
|
177
177
|
end
|
@@ -248,19 +248,19 @@ module Aidp
|
|
248
248
|
end
|
249
249
|
|
250
250
|
# Get comprehensive status data
|
251
|
-
def
|
251
|
+
def status_data
|
252
252
|
{
|
253
|
-
basic_info:
|
254
|
-
provider_info:
|
255
|
-
performance_info:
|
256
|
-
error_info:
|
257
|
-
circuit_breaker_info:
|
258
|
-
token_info:
|
259
|
-
rate_limit_info:
|
260
|
-
recovery_info:
|
261
|
-
user_feedback_info:
|
262
|
-
work_completion_info:
|
263
|
-
alerts:
|
253
|
+
basic_info: basic_status,
|
254
|
+
provider_info: provider_status,
|
255
|
+
performance_info: performance_status,
|
256
|
+
error_info: error_status,
|
257
|
+
circuit_breaker_info: circuit_breaker_status,
|
258
|
+
token_info: token_status,
|
259
|
+
rate_limit_info: rate_limit_status,
|
260
|
+
recovery_info: recovery_status,
|
261
|
+
user_feedback_info: user_feedback_status,
|
262
|
+
work_completion_info: work_completion_status,
|
263
|
+
alerts: alerts
|
264
264
|
}
|
265
265
|
end
|
266
266
|
|
@@ -268,9 +268,9 @@ module Aidp
|
|
268
268
|
def export_status_data(format = :json)
|
269
269
|
case format
|
270
270
|
when :json
|
271
|
-
JSON.pretty_generate(
|
271
|
+
JSON.pretty_generate(status_data)
|
272
272
|
when :yaml
|
273
|
-
|
273
|
+
status_data.to_yaml
|
274
274
|
when :text
|
275
275
|
format_status_as_text
|
276
276
|
else
|
@@ -310,8 +310,8 @@ module Aidp
|
|
310
310
|
@provider_status = {
|
311
311
|
current_provider: safe_manager_call(@provider_manager, :current_provider),
|
312
312
|
current_model: safe_manager_call(@provider_manager, :current_model),
|
313
|
-
available_providers: safe_manager_call(@provider_manager, :
|
314
|
-
provider_health: safe_manager_call(@provider_manager, :
|
313
|
+
available_providers: safe_manager_call(@provider_manager, :available_providers) || [],
|
314
|
+
provider_health: safe_manager_call(@provider_manager, :provider_health_status) || {}
|
315
315
|
}
|
316
316
|
rescue => e
|
317
317
|
# Log minimal info without breaking display; keep previous provider_status if available
|
@@ -330,13 +330,13 @@ module Aidp
|
|
330
330
|
def collect_circuit_breaker_status
|
331
331
|
return unless @circuit_breaker_manager
|
332
332
|
|
333
|
-
@circuit_breaker_status = @circuit_breaker_manager.
|
333
|
+
@circuit_breaker_status = @circuit_breaker_manager.all_states
|
334
334
|
end
|
335
335
|
|
336
336
|
def collect_metrics_data
|
337
337
|
return unless @metrics_manager
|
338
338
|
|
339
|
-
@performance_metrics = @metrics_manager.
|
339
|
+
@performance_metrics = @metrics_manager.realtime_metrics
|
340
340
|
end
|
341
341
|
|
342
342
|
def collect_error_data
|
@@ -616,7 +616,6 @@ module Aidp
|
|
616
616
|
end
|
617
617
|
|
618
618
|
def display_alerts
|
619
|
-
alerts = get_alerts
|
620
619
|
return unless alerts.any?
|
621
620
|
|
622
621
|
display_message("\n🚨 ALERTS", type: :warning)
|
@@ -672,7 +671,7 @@ module Aidp
|
|
672
671
|
display_message(" Continuing with status updates...", type: :info)
|
673
672
|
end
|
674
673
|
|
675
|
-
def
|
674
|
+
def basic_status
|
676
675
|
{
|
677
676
|
duration: @start_time ? Time.now - @start_time : 0,
|
678
677
|
current_step: @current_step,
|
@@ -684,44 +683,32 @@ module Aidp
|
|
684
683
|
}
|
685
684
|
end
|
686
685
|
|
687
|
-
|
688
|
-
@provider_status
|
689
|
-
end
|
686
|
+
attr_reader :provider_status
|
690
687
|
|
691
|
-
def
|
688
|
+
def performance_status
|
692
689
|
@performance_metrics
|
693
690
|
end
|
694
691
|
|
695
|
-
def
|
692
|
+
def error_status
|
696
693
|
@error_summary
|
697
694
|
end
|
698
695
|
|
699
|
-
|
700
|
-
@circuit_breaker_status
|
701
|
-
end
|
696
|
+
attr_reader :circuit_breaker_status
|
702
697
|
|
703
|
-
def
|
698
|
+
def token_status
|
704
699
|
@token_usage
|
705
700
|
end
|
706
701
|
|
707
|
-
|
708
|
-
@rate_limit_status
|
709
|
-
end
|
702
|
+
attr_reader :rate_limit_status
|
710
703
|
|
711
|
-
|
712
|
-
@recovery_status
|
713
|
-
end
|
704
|
+
attr_reader :recovery_status
|
714
705
|
|
715
|
-
|
716
|
-
@user_feedback_status
|
717
|
-
end
|
706
|
+
attr_reader :user_feedback_status
|
718
707
|
|
719
|
-
|
720
|
-
@work_completion_status
|
721
|
-
end
|
708
|
+
attr_reader :work_completion_status
|
722
709
|
|
723
|
-
def
|
724
|
-
@alert_manager.
|
710
|
+
def alerts
|
711
|
+
@alert_manager.active_alerts
|
725
712
|
end
|
726
713
|
|
727
714
|
def calculate_step_duration
|
@@ -854,7 +841,7 @@ module Aidp
|
|
854
841
|
end
|
855
842
|
end
|
856
843
|
|
857
|
-
def
|
844
|
+
def active_alerts
|
858
845
|
@alerts
|
859
846
|
end
|
860
847
|
|
@@ -250,7 +250,8 @@ module Aidp
|
|
250
250
|
|
251
251
|
def select_guided_workflow
|
252
252
|
# Use the guided agent to help user select workflow
|
253
|
-
|
253
|
+
# Don't pass prompt so it uses EnhancedInput with full readline support
|
254
|
+
guided_agent = Aidp::Workflows::GuidedAgent.new(@project_dir)
|
254
255
|
result = guided_agent.select_workflow
|
255
256
|
|
256
257
|
# Store user input for later use
|
@@ -85,7 +85,7 @@ module Aidp
|
|
85
85
|
raise MonitorError, "Failed to update job status: #{e.message}"
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
88
|
+
def job_status(job_id)
|
89
89
|
validate_job_id(job_id)
|
90
90
|
|
91
91
|
@monitor_mutex.synchronize do
|
@@ -100,11 +100,11 @@ module Aidp
|
|
100
100
|
@monitor_mutex.synchronize { @jobs.key?(job_id) }
|
101
101
|
end
|
102
102
|
|
103
|
-
def
|
103
|
+
def all_jobs
|
104
104
|
@monitor_mutex.synchronize { @jobs.dup }
|
105
105
|
end
|
106
106
|
|
107
|
-
def
|
107
|
+
def jobs_by_status(status)
|
108
108
|
validate_job_status(status)
|
109
109
|
|
110
110
|
@monitor_mutex.synchronize do
|
@@ -114,7 +114,7 @@ module Aidp
|
|
114
114
|
raise MonitorError, "Failed to get jobs by status: #{e.message}"
|
115
115
|
end
|
116
116
|
|
117
|
-
def
|
117
|
+
def jobs_by_priority(priority)
|
118
118
|
validate_job_priority(priority)
|
119
119
|
|
120
120
|
@monitor_mutex.synchronize do
|
@@ -162,7 +162,7 @@ module Aidp
|
|
162
162
|
@update_callbacks.delete(callback)
|
163
163
|
end
|
164
164
|
|
165
|
-
def
|
165
|
+
def monitoring_summary
|
166
166
|
@monitor_mutex.synchronize do
|
167
167
|
{
|
168
168
|
total_jobs: @jobs.size,
|
@@ -176,7 +176,7 @@ module Aidp
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def display_job_status(job_id)
|
179
|
-
job =
|
179
|
+
job = job_status(job_id)
|
180
180
|
@frame_manager.section("Job Status: #{job_id}") do
|
181
181
|
display_job_details(job)
|
182
182
|
end
|
@@ -189,7 +189,7 @@ module Aidp
|
|
189
189
|
end
|
190
190
|
|
191
191
|
def display_jobs_by_status(status)
|
192
|
-
jobs =
|
192
|
+
jobs = jobs_by_status(status)
|
193
193
|
@frame_manager.section("Jobs with Status: #{status}") do
|
194
194
|
display_jobs_table(jobs)
|
195
195
|
end
|
@@ -26,7 +26,7 @@ module Aidp
|
|
26
26
|
|
27
27
|
# Helper method to handle input consistently with TTY::Prompt
|
28
28
|
# Fixed to avoid keystroke loss issues with TTY::Prompt's required validation
|
29
|
-
def
|
29
|
+
def input_with_prompt(message, required: false, default: nil)
|
30
30
|
loop do
|
31
31
|
# Always use simple ask without built-in validation to avoid echo issues
|
32
32
|
input = if default
|
@@ -82,7 +82,7 @@ module Aidp
|
|
82
82
|
display_numbered_question(question_data, question_number, index + 1, questions.length)
|
83
83
|
|
84
84
|
# Get user response based on question type
|
85
|
-
response =
|
85
|
+
response = question_response(question_data, question_number)
|
86
86
|
|
87
87
|
# Validate response if required
|
88
88
|
if question_data[:required] != false && (response.nil? || response.to_s.strip.empty?)
|
@@ -468,7 +468,7 @@ module Aidp
|
|
468
468
|
end
|
469
469
|
|
470
470
|
# Get response for a specific question with enhanced validation
|
471
|
-
def
|
471
|
+
def question_response(question_data, _question_number)
|
472
472
|
question_type = question_data[:type] || "text"
|
473
473
|
expected_input = question_data[:expected_input] || "text"
|
474
474
|
options = question_data[:options]
|
@@ -478,21 +478,21 @@ module Aidp
|
|
478
478
|
|
479
479
|
case question_type
|
480
480
|
when "text"
|
481
|
-
|
481
|
+
text_response(expected_input, default_value, required, validation_options)
|
482
482
|
when "choice"
|
483
|
-
|
483
|
+
choice_response(options, default_value, required)
|
484
484
|
when "confirmation"
|
485
|
-
|
485
|
+
confirmation_response(default_value, required)
|
486
486
|
when "file"
|
487
|
-
|
487
|
+
file_response(expected_input, default_value, required, validation_options)
|
488
488
|
when "number"
|
489
|
-
|
489
|
+
number_response(expected_input, default_value, required, validation_options)
|
490
490
|
when "email"
|
491
|
-
|
491
|
+
email_response(default_value, required, validation_options)
|
492
492
|
when "url"
|
493
|
-
|
493
|
+
url_response(default_value, required, validation_options)
|
494
494
|
else
|
495
|
-
|
495
|
+
text_response(expected_input, default_value, required, validation_options)
|
496
496
|
end
|
497
497
|
end
|
498
498
|
|
@@ -620,13 +620,13 @@ module Aidp
|
|
620
620
|
end
|
621
621
|
|
622
622
|
# Get text response with enhanced validation
|
623
|
-
def
|
623
|
+
def text_response(expected_input, default_value, required, options = {})
|
624
624
|
prompt = "Your response"
|
625
625
|
prompt += " (default: #{default_value})" if default_value
|
626
626
|
prompt_text = prompt + (required ? "" : " (optional)")
|
627
627
|
|
628
628
|
loop do
|
629
|
-
input =
|
629
|
+
input = input_with_prompt(prompt_text, required: required, default: default_value)
|
630
630
|
|
631
631
|
# get_input_with_prompt already handles required validation and returns non-empty input
|
632
632
|
# Only validate the type/format if we got input
|
@@ -653,7 +653,7 @@ module Aidp
|
|
653
653
|
end
|
654
654
|
|
655
655
|
# Get choice response with enhanced validation
|
656
|
-
def
|
656
|
+
def choice_response(options, default_value, required)
|
657
657
|
return nil if options.nil? || options.empty?
|
658
658
|
|
659
659
|
display_message("\n Available options:", type: :info)
|
@@ -704,7 +704,7 @@ module Aidp
|
|
704
704
|
end
|
705
705
|
|
706
706
|
# Get confirmation response with enhanced validation
|
707
|
-
def
|
707
|
+
def confirmation_response(default_value, required)
|
708
708
|
default = default_value.nil? || default_value
|
709
709
|
default_text = default ? "Y/n" : "y/N"
|
710
710
|
prompt = "Your response [#{default_text}]"
|
@@ -741,7 +741,7 @@ module Aidp
|
|
741
741
|
end
|
742
742
|
|
743
743
|
# Get file response with enhanced validation
|
744
|
-
def
|
744
|
+
def file_response(_expected_input, default_value, required, options = {})
|
745
745
|
prompt = "File path"
|
746
746
|
prompt += " (default: #{default_value})" if default_value
|
747
747
|
prompt += required ? ": " : " (optional): "
|
@@ -784,7 +784,7 @@ module Aidp
|
|
784
784
|
end
|
785
785
|
|
786
786
|
# Get number response with enhanced validation
|
787
|
-
def
|
787
|
+
def number_response(expected_input, default_value, required, options = {})
|
788
788
|
prompt = "Number"
|
789
789
|
prompt += " (default: #{default_value})" if default_value
|
790
790
|
prompt += required ? ": " : " (optional): "
|
@@ -831,7 +831,7 @@ module Aidp
|
|
831
831
|
end
|
832
832
|
|
833
833
|
# Get email response with enhanced validation
|
834
|
-
def
|
834
|
+
def email_response(default_value, required, options = {})
|
835
835
|
prompt = "Email address"
|
836
836
|
prompt += " (default: #{default_value})" if default_value
|
837
837
|
prompt += required ? ": " : " (optional): "
|
@@ -868,7 +868,7 @@ module Aidp
|
|
868
868
|
end
|
869
869
|
|
870
870
|
# Get URL response with enhanced validation
|
871
|
-
def
|
871
|
+
def url_response(default_value, required, options = {})
|
872
872
|
prompt = "URL"
|
873
873
|
prompt += " (default: #{default_value})" if default_value
|
874
874
|
prompt += required ? ": " : " (optional): "
|
@@ -1321,7 +1321,7 @@ module Aidp
|
|
1321
1321
|
end
|
1322
1322
|
|
1323
1323
|
# Get user input with support for file selection
|
1324
|
-
def
|
1324
|
+
def user_input(prompt)
|
1325
1325
|
loop do
|
1326
1326
|
input = @prompt.ask(prompt)
|
1327
1327
|
|
@@ -1364,7 +1364,7 @@ module Aidp
|
|
1364
1364
|
display_advanced_file_menu(available_files, search_options)
|
1365
1365
|
|
1366
1366
|
# Get user selection with advanced options
|
1367
|
-
selection =
|
1367
|
+
selection = advanced_file_selection(available_files.size, search_options)
|
1368
1368
|
|
1369
1369
|
if selection && selection >= 0 && selection < available_files.size
|
1370
1370
|
selected_file = available_files[selection]
|
@@ -1602,12 +1602,12 @@ module Aidp
|
|
1602
1602
|
end
|
1603
1603
|
|
1604
1604
|
# Get file information for display
|
1605
|
-
def
|
1605
|
+
def file_info(file)
|
1606
1606
|
{
|
1607
1607
|
display_name: file,
|
1608
1608
|
size: format_file_size(File.size(file)),
|
1609
1609
|
modified: File.mtime(file).strftime("%Y-%m-%d %H:%M"),
|
1610
|
-
type:
|
1610
|
+
type: file_type(file)
|
1611
1611
|
}
|
1612
1612
|
end
|
1613
1613
|
|
@@ -1623,7 +1623,7 @@ module Aidp
|
|
1623
1623
|
end
|
1624
1624
|
|
1625
1625
|
# Get file type for display
|
1626
|
-
def
|
1626
|
+
def file_type(file)
|
1627
1627
|
ext = File.extname(file)
|
1628
1628
|
case ext
|
1629
1629
|
when ".rb"
|
@@ -1665,7 +1665,7 @@ module Aidp
|
|
1665
1665
|
end
|
1666
1666
|
|
1667
1667
|
# Get advanced file selection from user
|
1668
|
-
def
|
1668
|
+
def advanced_file_selection(max_files, _search_options)
|
1669
1669
|
loop do
|
1670
1670
|
input = @prompt.ask("Select file (0-#{max_files}, -1=refine, p=preview, h=help): ")
|
1671
1671
|
|
@@ -1743,7 +1743,7 @@ module Aidp
|
|
1743
1743
|
display_message(" Size: #{format_file_size(File.size(file_path))}", type: :info)
|
1744
1744
|
display_message(" Lines: #{lines.count}", type: :info)
|
1745
1745
|
display_message(" Modified: #{File.mtime(file_path).strftime("%Y-%m-%d %H:%M:%S")}", type: :info)
|
1746
|
-
display_message(" Type: #{
|
1746
|
+
display_message(" Type: #{file_type(file_path)}", type: :info)
|
1747
1747
|
|
1748
1748
|
display_message("\n📝 Content Preview (first 20 lines):", type: :info)
|
1749
1749
|
display_message("-" * 40, type: :muted)
|
@@ -1764,12 +1764,12 @@ module Aidp
|
|
1764
1764
|
end
|
1765
1765
|
|
1766
1766
|
# Get file selection from user (legacy method for compatibility)
|
1767
|
-
def
|
1768
|
-
|
1767
|
+
def file_selection(max_files)
|
1768
|
+
advanced_file_selection(max_files, {term: "", extensions: [], directories: []})
|
1769
1769
|
end
|
1770
1770
|
|
1771
1771
|
# Get confirmation from user
|
1772
|
-
def
|
1772
|
+
def confirmation(message, default: true)
|
1773
1773
|
default_text = default ? "Y/n" : "y/N"
|
1774
1774
|
prompt = "#{message} [#{default_text}]: "
|
1775
1775
|
|
@@ -1793,7 +1793,7 @@ module Aidp
|
|
1793
1793
|
end
|
1794
1794
|
|
1795
1795
|
# Get choice from multiple options
|
1796
|
-
def
|
1796
|
+
def choice(message, options, default: nil)
|
1797
1797
|
display_message("\n#{message}", type: :info)
|
1798
1798
|
options.each_with_index do |option, index|
|
1799
1799
|
marker = (default && index == default) ? " (default)" : ""
|
@@ -1911,32 +1911,32 @@ module Aidp
|
|
1911
1911
|
end
|
1912
1912
|
|
1913
1913
|
# Get user preferences for feedback collection
|
1914
|
-
def
|
1914
|
+
def user_preferences
|
1915
1915
|
display_message("\n⚙️ User Preferences:", type: :info)
|
1916
1916
|
display_message("-" * 25, type: :muted)
|
1917
1917
|
|
1918
1918
|
preferences = {}
|
1919
1919
|
|
1920
1920
|
# Auto-confirm defaults
|
1921
|
-
preferences[:auto_confirm_defaults] =
|
1921
|
+
preferences[:auto_confirm_defaults] = confirmation(
|
1922
1922
|
"Auto-confirm default values without prompting?",
|
1923
1923
|
default: false
|
1924
1924
|
)
|
1925
1925
|
|
1926
1926
|
# Show help automatically
|
1927
|
-
preferences[:show_help_automatically] =
|
1927
|
+
preferences[:show_help_automatically] = confirmation(
|
1928
1928
|
"Show help automatically for new question types?",
|
1929
1929
|
default: false
|
1930
1930
|
)
|
1931
1931
|
|
1932
1932
|
# Verbose mode
|
1933
|
-
preferences[:verbose_mode] =
|
1933
|
+
preferences[:verbose_mode] = confirmation(
|
1934
1934
|
"Enable verbose mode with detailed information?",
|
1935
1935
|
default: true
|
1936
1936
|
)
|
1937
1937
|
|
1938
1938
|
# File browsing enabled
|
1939
|
-
preferences[:file_browsing_enabled] =
|
1939
|
+
preferences[:file_browsing_enabled] = confirmation(
|
1940
1940
|
"Enable file browsing with @ character?",
|
1941
1941
|
default: true
|
1942
1942
|
)
|
@@ -1998,7 +1998,7 @@ module Aidp
|
|
1998
1998
|
end
|
1999
1999
|
|
2000
2000
|
# Get quick feedback for simple questions
|
2001
|
-
def
|
2001
|
+
def quick_feedback(question, options = {})
|
2002
2002
|
question_type = options[:type] || "text"
|
2003
2003
|
default_value = options[:default]
|
2004
2004
|
required = options[:required] != false
|
@@ -2007,13 +2007,13 @@ module Aidp
|
|
2007
2007
|
|
2008
2008
|
case question_type
|
2009
2009
|
when "text"
|
2010
|
-
|
2010
|
+
text_response("text", default_value, required)
|
2011
2011
|
when "confirmation"
|
2012
|
-
|
2012
|
+
confirmation_response(default_value, required)
|
2013
2013
|
when "choice"
|
2014
|
-
|
2014
|
+
choice_response(options[:options], default_value, required)
|
2015
2015
|
else
|
2016
|
-
|
2016
|
+
text_response("text", default_value, required)
|
2017
2017
|
end
|
2018
2018
|
end
|
2019
2019
|
|
@@ -2033,7 +2033,7 @@ module Aidp
|
|
2033
2033
|
|
2034
2034
|
display_message("\n#{question_number}. #{question_text}", type: :info)
|
2035
2035
|
|
2036
|
-
response =
|
2036
|
+
response = quick_feedback(question_text, {
|
2037
2037
|
type: question_type,
|
2038
2038
|
default: default_value,
|
2039
2039
|
required: required,
|
@@ -2299,7 +2299,7 @@ module Aidp
|
|
2299
2299
|
end
|
2300
2300
|
|
2301
2301
|
# Get control status
|
2302
|
-
def
|
2302
|
+
def control_status
|
2303
2303
|
@control_mutex.synchronize do
|
2304
2304
|
{
|
2305
2305
|
enabled: !!@control_interface_enabled,
|
@@ -2313,7 +2313,7 @@ module Aidp
|
|
2313
2313
|
|
2314
2314
|
# Display control status
|
2315
2315
|
def display_control_status
|
2316
|
-
status =
|
2316
|
+
status = control_status
|
2317
2317
|
|
2318
2318
|
display_message("\n🎮 Control Interface Status", type: :info)
|
2319
2319
|
display_message("=" * 40, type: :muted)
|
@@ -21,6 +21,25 @@ module Aidp
|
|
21
21
|
"Anthropic Claude CLI"
|
22
22
|
end
|
23
23
|
|
24
|
+
def supports_mcp?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch_mcp_servers
|
29
|
+
return [] unless self.class.available?
|
30
|
+
|
31
|
+
begin
|
32
|
+
# Use claude mcp list command
|
33
|
+
result = debug_execute_command("claude", args: ["mcp", "list"], timeout: 5)
|
34
|
+
return [] unless result.exit_status == 0
|
35
|
+
|
36
|
+
parse_claude_mcp_output(result.out)
|
37
|
+
rescue => e
|
38
|
+
debug_log("Failed to fetch MCP servers via Claude CLI: #{e.message}", level: :debug)
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
24
43
|
def available?
|
25
44
|
self.class.available?
|
26
45
|
end
|
@@ -101,11 +120,9 @@ module Aidp
|
|
101
120
|
return ENV["AIDP_ANTHROPIC_TIMEOUT"].to_i
|
102
121
|
end
|
103
122
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
108
|
-
return step_timeout
|
123
|
+
if adaptive_timeout
|
124
|
+
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
125
|
+
return adaptive_timeout
|
109
126
|
end
|
110
127
|
|
111
128
|
# Default timeout
|
@@ -113,27 +130,29 @@ module Aidp
|
|
113
130
|
TIMEOUT_DEFAULT
|
114
131
|
end
|
115
132
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
def adaptive_timeout
|
134
|
+
@adaptive_timeout ||= begin
|
135
|
+
# Timeout recommendations based on step type patterns
|
136
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
137
|
+
|
138
|
+
case step_name
|
139
|
+
when /REPOSITORY_ANALYSIS/
|
140
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
141
|
+
when /ARCHITECTURE_ANALYSIS/
|
142
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
143
|
+
when /TEST_ANALYSIS/
|
144
|
+
TIMEOUT_TEST_ANALYSIS
|
145
|
+
when /FUNCTIONALITY_ANALYSIS/
|
146
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
147
|
+
when /DOCUMENTATION_ANALYSIS/
|
148
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
149
|
+
when /STATIC_ANALYSIS/
|
150
|
+
TIMEOUT_STATIC_ANALYSIS
|
151
|
+
when /REFACTORING_RECOMMENDATIONS/
|
152
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
153
|
+
else
|
154
|
+
nil # Use default
|
155
|
+
end
|
137
156
|
end
|
138
157
|
end
|
139
158
|
|
@@ -184,6 +203,61 @@ module Aidp
|
|
184
203
|
# Return original output if parsing fails
|
185
204
|
output
|
186
205
|
end
|
206
|
+
|
207
|
+
# Parse Claude MCP server list output
|
208
|
+
def parse_claude_mcp_output(output)
|
209
|
+
servers = []
|
210
|
+
return servers unless output
|
211
|
+
|
212
|
+
lines = output.lines
|
213
|
+
lines.reject! { |line| /checking mcp server health/i.match?(line) }
|
214
|
+
|
215
|
+
lines.each do |line|
|
216
|
+
line = line.strip
|
217
|
+
next if line.empty?
|
218
|
+
|
219
|
+
# Try to parse Claude format: "name: command - ✓ Connected"
|
220
|
+
if line =~ /^([^:]+):\s*(.+?)\s*-\s*(✓|✗)\s*(.+)$/
|
221
|
+
name = Regexp.last_match(1).strip
|
222
|
+
command = Regexp.last_match(2).strip
|
223
|
+
status_symbol = Regexp.last_match(3)
|
224
|
+
status_text = Regexp.last_match(4).strip
|
225
|
+
|
226
|
+
servers << {
|
227
|
+
name: name,
|
228
|
+
status: (status_symbol == "✓") ? "connected" : "error",
|
229
|
+
description: command,
|
230
|
+
enabled: status_symbol == "✓",
|
231
|
+
error: (status_symbol == "✗") ? status_text : nil,
|
232
|
+
source: "claude_cli"
|
233
|
+
}
|
234
|
+
next
|
235
|
+
end
|
236
|
+
|
237
|
+
# Try to parse legacy table format
|
238
|
+
next if /Name.*Status/i.match?(line)
|
239
|
+
next if /^[-=]+$/.match?(line)
|
240
|
+
|
241
|
+
parts = line.split(/\s{2,}/)
|
242
|
+
next if parts.size < 2
|
243
|
+
|
244
|
+
name = parts[0]&.strip
|
245
|
+
status = parts[1]&.strip
|
246
|
+
description = parts[2..]&.join(" ")&.strip
|
247
|
+
|
248
|
+
next unless name && !name.empty?
|
249
|
+
|
250
|
+
servers << {
|
251
|
+
name: name,
|
252
|
+
status: status || "unknown",
|
253
|
+
description: description,
|
254
|
+
enabled: status&.downcase == "enabled" || status&.downcase == "connected",
|
255
|
+
source: "claude_cli"
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
259
|
+
servers
|
260
|
+
end
|
187
261
|
end
|
188
262
|
end
|
189
263
|
end
|