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.
@@ -165,13 +165,13 @@ module Aidp
165
165
  end
166
166
 
167
167
  # Set display mode
168
- def set_display_mode(mode)
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 set_update_interval(interval)
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 get_status_data
251
+ def status_data
252
252
  {
253
- basic_info: get_basic_status,
254
- provider_info: get_provider_status,
255
- performance_info: get_performance_status,
256
- error_info: get_error_status,
257
- circuit_breaker_info: get_circuit_breaker_status,
258
- token_info: get_token_status,
259
- rate_limit_info: get_rate_limit_status,
260
- recovery_info: get_recovery_status,
261
- user_feedback_info: get_user_feedback_status,
262
- work_completion_info: get_work_completion_status,
263
- alerts: get_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(get_status_data)
271
+ JSON.pretty_generate(status_data)
272
272
  when :yaml
273
- get_status_data.to_yaml
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, :get_available_providers) || [],
314
- provider_health: safe_manager_call(@provider_manager, :get_provider_health_status) || {}
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.get_all_states
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.get_realtime_metrics
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 get_basic_status
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
- def get_provider_status
688
- @provider_status
689
- end
686
+ attr_reader :provider_status
690
687
 
691
- def get_performance_status
688
+ def performance_status
692
689
  @performance_metrics
693
690
  end
694
691
 
695
- def get_error_status
692
+ def error_status
696
693
  @error_summary
697
694
  end
698
695
 
699
- def get_circuit_breaker_status
700
- @circuit_breaker_status
701
- end
696
+ attr_reader :circuit_breaker_status
702
697
 
703
- def get_token_status
698
+ def token_status
704
699
  @token_usage
705
700
  end
706
701
 
707
- def get_rate_limit_status
708
- @rate_limit_status
709
- end
702
+ attr_reader :rate_limit_status
710
703
 
711
- def get_recovery_status
712
- @recovery_status
713
- end
704
+ attr_reader :recovery_status
714
705
 
715
- def get_user_feedback_status
716
- @user_feedback_status
717
- end
706
+ attr_reader :user_feedback_status
718
707
 
719
- def get_work_completion_status
720
- @work_completion_status
721
- end
708
+ attr_reader :work_completion_status
722
709
 
723
- def get_alerts
724
- @alert_manager.get_active_alerts
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 get_active_alerts
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
- guided_agent = Aidp::Workflows::GuidedAgent.new(@project_dir, prompt: @tui.instance_variable_get(:@prompt))
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 get_job_status(job_id)
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 get_all_jobs
103
+ def all_jobs
104
104
  @monitor_mutex.synchronize { @jobs.dup }
105
105
  end
106
106
 
107
- def get_jobs_by_status(status)
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 get_jobs_by_priority(priority)
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 get_monitoring_summary
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 = get_job_status(job_id)
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 = get_jobs_by_status(status)
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 get_input_with_prompt(message, required: false, default: nil)
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 = get_question_response(question_data, question_number)
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 get_question_response(question_data, _question_number)
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
- get_text_response(expected_input, default_value, required, validation_options)
481
+ text_response(expected_input, default_value, required, validation_options)
482
482
  when "choice"
483
- get_choice_response(options, default_value, required)
483
+ choice_response(options, default_value, required)
484
484
  when "confirmation"
485
- get_confirmation_response(default_value, required)
485
+ confirmation_response(default_value, required)
486
486
  when "file"
487
- get_file_response(expected_input, default_value, required, validation_options)
487
+ file_response(expected_input, default_value, required, validation_options)
488
488
  when "number"
489
- get_number_response(expected_input, default_value, required, validation_options)
489
+ number_response(expected_input, default_value, required, validation_options)
490
490
  when "email"
491
- get_email_response(default_value, required, validation_options)
491
+ email_response(default_value, required, validation_options)
492
492
  when "url"
493
- get_url_response(default_value, required, validation_options)
493
+ url_response(default_value, required, validation_options)
494
494
  else
495
- get_text_response(expected_input, default_value, required, validation_options)
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 get_text_response(expected_input, default_value, required, options = {})
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 = get_input_with_prompt(prompt_text, required: required, default: default_value)
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 get_choice_response(options, default_value, required)
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 get_confirmation_response(default_value, required)
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 get_file_response(_expected_input, default_value, required, options = {})
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 get_number_response(expected_input, default_value, required, options = {})
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 get_email_response(default_value, required, options = {})
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 get_url_response(default_value, required, options = {})
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 get_user_input(prompt)
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 = get_advanced_file_selection(available_files.size, search_options)
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 get_file_info(file)
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: get_file_type(file)
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 get_file_type(file)
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 get_advanced_file_selection(max_files, _search_options)
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: #{get_file_type(file_path)}", type: :info)
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 get_file_selection(max_files)
1768
- get_advanced_file_selection(max_files, {term: "", extensions: [], directories: []})
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 get_confirmation(message, default: true)
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 get_choice(message, options, default: nil)
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 get_user_preferences
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] = get_confirmation(
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] = get_confirmation(
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] = get_confirmation(
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] = get_confirmation(
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 get_quick_feedback(question, options = {})
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
- get_text_response("text", default_value, required)
2010
+ text_response("text", default_value, required)
2011
2011
  when "confirmation"
2012
- get_confirmation_response(default_value, required)
2012
+ confirmation_response(default_value, required)
2013
2013
  when "choice"
2014
- get_choice_response(options[:options], default_value, required)
2014
+ choice_response(options[:options], default_value, required)
2015
2015
  else
2016
- get_text_response("text", default_value, required)
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 = get_quick_feedback(question_text, {
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 get_control_status
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 = get_control_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
- # Adaptive timeout based on step type
105
- step_timeout = get_adaptive_timeout
106
- if step_timeout
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 get_adaptive_timeout
117
- # Timeout recommendations based on step type patterns
118
- step_name = ENV["AIDP_CURRENT_STEP"] || ""
119
-
120
- case step_name
121
- when /REPOSITORY_ANALYSIS/
122
- TIMEOUT_REPOSITORY_ANALYSIS
123
- when /ARCHITECTURE_ANALYSIS/
124
- TIMEOUT_ARCHITECTURE_ANALYSIS
125
- when /TEST_ANALYSIS/
126
- TIMEOUT_TEST_ANALYSIS
127
- when /FUNCTIONALITY_ANALYSIS/
128
- TIMEOUT_FUNCTIONALITY_ANALYSIS
129
- when /DOCUMENTATION_ANALYSIS/
130
- TIMEOUT_DOCUMENTATION_ANALYSIS
131
- when /STATIC_ANALYSIS/
132
- TIMEOUT_STATIC_ANALYSIS
133
- when /REFACTORING_RECOMMENDATIONS/
134
- TIMEOUT_REFACTORING_RECOMMENDATIONS
135
- else
136
- nil # Use default
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