aidp 0.8.1 → 0.8.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a295d267b134bc6f1c28aef126969254203d4f07f98d39e686c85c4479954eca
4
- data.tar.gz: 23b7bef369a2d423d3e141492f857da0d66640c337d4cd530befa52d6f3c9392
3
+ metadata.gz: b9c14dc26b8cedb7e1beb09f9799dcbbcedf3e6aeb33b908256d7c67bd864b22
4
+ data.tar.gz: 3af751e93b47bf20566796c4ebf7519aa425e9851531b954be059b7bf649fc7d
5
5
  SHA512:
6
- metadata.gz: 2544ee1a9ba91033d2b8b9eee057df06c2a15aa3d90725028f72a839c09d3d3f1b95545b937cc9206e360bb8f137174cb495b591ae9890fc26ef5e58e235c0d2
7
- data.tar.gz: 4e634535c9cfdcae56400ac073b79334e5a0311342f53e26d6a9b1ace929c5bae5210ae92467e0c47cca3afa902935857d315886bdbc1a6dd07880b55878dd07
6
+ metadata.gz: 3991a8477fc0f4293473a06083b734f7ea544d46847747688cda8c0c7d9b59e4dde2bbb41faaa92a9edaad88e920a0d6faca939c11d3a32c4da6f9b3740c62fe
7
+ data.tar.gz: b11ab471251fd86f4d9ff2acbd8c3c8fb0e9bf360292dc51e6a9697ba97b0e520dbcf9dc115331e1eb6800268dc08055b0e7fd4584f5af9e7a6609a7d3fac058
@@ -4,7 +4,6 @@ require "tty-spinner"
4
4
  require "tty-progressbar"
5
5
  require "tty-table"
6
6
  require "pastel"
7
- require "colorize"
8
7
 
9
8
  module Aidp
10
9
  class ProgressVisualizer
@@ -295,21 +294,21 @@ module Aidp
295
294
  end
296
295
 
297
296
  def colorize(text, color)
298
- return text unless defined?((+"").colorize)
297
+ return text unless @pastel
299
298
 
300
- text.to_s.colorize(color)
299
+ @pastel.decorate(text.to_s, color)
301
300
  end
302
301
 
303
302
  def coverage_colorize(percentage, color)
304
- return percentage unless defined?((+"").colorize)
303
+ return percentage unless @pastel
305
304
 
306
- percentage.to_s.colorize(color)
305
+ @pastel.decorate(percentage.to_s, color)
307
306
  end
308
307
 
309
308
  def priority_colorize(text, color)
310
- return text unless defined?((+"").colorize)
309
+ return text unless @pastel
311
310
 
312
- text.to_s.colorize(color)
311
+ @pastel.decorate(text.to_s, color)
313
312
  end
314
313
  end
315
314
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "readline"
3
+ require "tty-prompt"
4
4
 
5
5
  module Aidp
6
6
  module Execute
@@ -8,6 +8,7 @@ module Aidp
8
8
  class WorkflowSelector
9
9
  def initialize
10
10
  @user_input = {}
11
+ @prompt = TTY::Prompt.new
11
12
  end
12
13
 
13
14
  # Main entry point for interactive workflow selection
@@ -189,22 +190,23 @@ module Aidp
189
190
 
190
191
  def prompt_required(question)
191
192
  loop do
192
- response = Readline.readline("#{question}: ", true)&.strip
193
- return response unless response.nil? || response.empty?
194
- puts "This field is required. Please provide an answer."
193
+ input = @prompt.ask("#{question}:")
194
+
195
+ if input.nil? || input.strip.empty?
196
+ puts "❌ This field is required. Please provide an answer."
197
+ next
198
+ end
199
+
200
+ return input.strip
195
201
  end
196
202
  end
197
203
 
198
204
  def prompt_optional(question)
199
- Readline.readline("#{question} (optional): ", true)&.strip
205
+ @prompt.ask("#{question} (optional):")
200
206
  end
201
207
 
202
208
  def prompt_choice(question, valid_choices)
203
- loop do
204
- response = Readline.readline("#{question} (#{valid_choices.join("/")}): ", true)&.strip&.downcase
205
- return response if valid_choices.map(&:downcase).include?(response)
206
- puts "Please choose one of: #{valid_choices.join(", ")}"
207
- end
209
+ @prompt.select("#{question}:", valid_choices, per_page: valid_choices.length)
208
210
  end
209
211
  end
210
212
  end
@@ -28,7 +28,7 @@ module Aidp
28
28
  # Headless (non-interactive) detection for test/CI environments:
29
29
  # - RSpec defined or RSPEC_RUNNING env set
30
30
  # - STDIN not a TTY (captured by PTY/tmux harness)
31
- @headless = !!(defined?(RSpec) || ENV["RSPEC_RUNNING"] || !$stdin.tty?)
31
+ @headless = !!(defined?(RSpec) || ENV["RSPEC_RUNNING"] || $stdin.nil? || !$stdin.tty?)
32
32
  @current_mode = nil
33
33
  @workflow_active = false
34
34
  @current_step = nil
@@ -382,7 +382,7 @@ module Aidp
382
382
  # Very lightweight key listener just for spec expectations (F1 help, Ctrl shortcuts)
383
383
  def start_key_listener
384
384
  return if @key_thread
385
- return unless $stdin.tty? || @headless
385
+ return unless $stdin&.tty? || @headless
386
386
 
387
387
  @key_thread = Thread.new do
388
388
  while @display_active
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "readline"
3
+ require "tty-prompt"
4
4
 
5
5
  module Aidp
6
6
  module Harness
@@ -9,6 +9,47 @@ module Aidp
9
9
  def initialize
10
10
  @input_history = []
11
11
  @file_selection_enabled = false
12
+ @prompt = TTY::Prompt.new
13
+ @control_mutex = Mutex.new
14
+ @pause_requested = false
15
+ @stop_requested = false
16
+ @resume_requested = false
17
+ @control_interface_enabled = false
18
+ @control_thread = nil
19
+ end
20
+
21
+ private
22
+
23
+ # Helper method to handle input consistently with TTY::Prompt
24
+ # Fixed to avoid keystroke loss issues with TTY::Prompt's required validation
25
+ def get_input_with_prompt(message, required: false, default: nil)
26
+ loop do
27
+ # Always use simple ask without built-in validation to avoid echo issues
28
+ input = if default
29
+ @prompt.ask("#{message} (default: #{default}): ")
30
+ else
31
+ @prompt.ask("#{message}: ")
32
+ end
33
+
34
+ # Handle empty input
35
+ if input.nil? || input.strip.empty?
36
+ if default
37
+ return default
38
+ elsif required
39
+ puts "❌ This field is required. Please provide a response."
40
+ next
41
+ else
42
+ return nil
43
+ end
44
+ end
45
+
46
+ return input.strip
47
+ end
48
+ end
49
+
50
+ public
51
+
52
+ def setup_control_interface
12
53
  @control_interface_enabled = true
13
54
  @pause_requested = false
14
55
  @stop_requested = false
@@ -465,9 +506,14 @@ module Aidp
465
506
  puts " 3. Get help"
466
507
  puts " 4. Cancel all questions"
467
508
 
468
- choice = Readline.readline("Your choice (1-4): ", true)
509
+ choice = @prompt.select("Choose an option:", {
510
+ "Try again" => "1",
511
+ "Skip this question" => "2",
512
+ "Get help" => "3",
513
+ "Cancel all questions" => "4"
514
+ })
469
515
 
470
- case choice&.strip
516
+ case choice
471
517
  when "1"
472
518
  puts "🔄 Retrying..."
473
519
  :retry
@@ -529,7 +575,7 @@ module Aidp
529
575
  end
530
576
 
531
577
  puts "\nPress Enter to continue..."
532
- Readline.readline
578
+ @prompt.keypress("Press any key to continue...")
533
579
  end
534
580
 
535
581
  # Enhanced error handling and validation display
@@ -563,7 +609,7 @@ module Aidp
563
609
  end
564
610
  puts "\nPress Enter to continue or type 'fix' to correct..."
565
611
 
566
- input = Readline.readline("", true)
612
+ input = @prompt.ask("")
567
613
  return input&.strip&.downcase == "fix"
568
614
  end
569
615
  false
@@ -573,21 +619,16 @@ module Aidp
573
619
  def get_text_response(expected_input, default_value, required, options = {})
574
620
  prompt = "Your response"
575
621
  prompt += " (default: #{default_value})" if default_value
576
- prompt += required ? ": " : " (optional): "
622
+ prompt_text = prompt + (required ? "" : " (optional)")
577
623
 
578
624
  loop do
579
- input = Readline.readline(prompt, true)
625
+ input = get_input_with_prompt(prompt_text, required: required, default: default_value)
580
626
 
581
- # Handle empty input
582
- if input.nil? || input.strip.empty?
583
- if default_value
584
- return default_value
585
- elsif required
586
- puts "❌ This field is required. Please provide a response."
587
- next
588
- else
589
- return nil
590
- end
627
+ # get_input_with_prompt already handles required validation and returns non-empty input
628
+ # Only validate the type/format if we got input
629
+ if input.nil?
630
+ # This should only happen for non-required fields
631
+ return nil
591
632
  end
592
633
 
593
634
  # Enhanced validation
@@ -622,7 +663,7 @@ module Aidp
622
663
  prompt += " (default: #{default_value})" if default_value
623
664
  prompt += required ? ": " : " (optional): "
624
665
 
625
- input = Readline.readline(prompt, true)
666
+ input = @prompt.ask(prompt)
626
667
 
627
668
  if input.nil? || input.strip.empty?
628
669
  if default_value
@@ -666,7 +707,7 @@ module Aidp
666
707
  prompt += required ? ": " : " (optional): "
667
708
 
668
709
  loop do
669
- input = Readline.readline(prompt, true)
710
+ input = @prompt.ask(prompt)
670
711
 
671
712
  if input.nil? || input.strip.empty?
672
713
  return default
@@ -702,7 +743,7 @@ module Aidp
702
743
  prompt += required ? ": " : " (optional): "
703
744
 
704
745
  loop do
705
- input = Readline.readline(prompt, true)
746
+ input = @prompt.ask(prompt)
706
747
 
707
748
  if input.nil? || input.strip.empty?
708
749
  if default_value
@@ -745,7 +786,7 @@ module Aidp
745
786
  prompt += required ? ": " : " (optional): "
746
787
 
747
788
  loop do
748
- input = Readline.readline(prompt, true)
789
+ input = @prompt.ask(prompt)
749
790
 
750
791
  if input.nil? || input.strip.empty?
751
792
  if default_value
@@ -792,7 +833,7 @@ module Aidp
792
833
  prompt += required ? ": " : " (optional): "
793
834
 
794
835
  loop do
795
- input = Readline.readline(prompt, true)
836
+ input = @prompt.ask(prompt)
796
837
 
797
838
  if input.nil? || input.strip.empty?
798
839
  if default_value
@@ -829,7 +870,7 @@ module Aidp
829
870
  prompt += required ? ": " : " (optional): "
830
871
 
831
872
  loop do
832
- input = Readline.readline(prompt, true)
873
+ input = @prompt.ask(prompt)
833
874
 
834
875
  if input.nil? || input.strip.empty?
835
876
  if default_value
@@ -1278,7 +1319,7 @@ module Aidp
1278
1319
  # Get user input with support for file selection
1279
1320
  def get_user_input(prompt)
1280
1321
  loop do
1281
- input = Readline.readline(prompt, true)
1322
+ input = @prompt.ask(prompt)
1282
1323
 
1283
1324
  # Handle empty input
1284
1325
  if input.nil? || input.strip.empty?
@@ -1622,7 +1663,7 @@ module Aidp
1622
1663
  # Get advanced file selection from user
1623
1664
  def get_advanced_file_selection(max_files, _search_options)
1624
1665
  loop do
1625
- input = Readline.readline("Select file (0-#{max_files}, -1=refine, p=preview, h=help): ", true)
1666
+ input = @prompt.ask("Select file (0-#{max_files}, -1=refine, p=preview, h=help): ")
1626
1667
 
1627
1668
  if input.nil? || input.strip.empty?
1628
1669
  puts "Please enter a selection."
@@ -1715,7 +1756,7 @@ module Aidp
1715
1756
  end
1716
1757
 
1717
1758
  puts "\nPress Enter to continue..."
1718
- Readline.readline
1759
+ @prompt.keypress("Press any key to continue...")
1719
1760
  end
1720
1761
 
1721
1762
  # Get file selection from user (legacy method for compatibility)
@@ -1729,7 +1770,7 @@ module Aidp
1729
1770
  prompt = "#{message} [#{default_text}]: "
1730
1771
 
1731
1772
  loop do
1732
- input = Readline.readline(prompt, true)
1773
+ input = @prompt.ask(prompt)
1733
1774
 
1734
1775
  if input.nil? || input.strip.empty?
1735
1776
  return default
@@ -1756,7 +1797,7 @@ module Aidp
1756
1797
  end
1757
1798
 
1758
1799
  loop do
1759
- input = Readline.readline("Your choice (1-#{options.size}): ", true)
1800
+ input = @prompt.ask("Your choice (1-#{options.size}): ")
1760
1801
 
1761
1802
  if input.nil? || input.strip.empty?
1762
1803
  return default if default
@@ -1927,14 +1968,14 @@ module Aidp
1927
1968
  if should_show_help?(questions.first&.dig(:type), seen_types)
1928
1969
  show_help
1929
1970
  puts "\nPress Enter to continue..."
1930
- Readline.readline
1971
+ @prompt.keypress("Press any key to continue...")
1931
1972
  end
1932
1973
 
1933
1974
  # Display question summary if verbose
1934
1975
  if @verbose_mode
1935
1976
  display_question_summary(questions)
1936
1977
  puts "\nPress Enter to start answering questions..."
1937
- Readline.readline
1978
+ @prompt.keypress("Press any key to continue...")
1938
1979
  end
1939
1980
 
1940
1981
  # Collect feedback
@@ -2041,17 +2082,17 @@ module Aidp
2041
2082
 
2042
2083
  # Check if pause is requested
2043
2084
  def pause_requested?
2044
- @control_mutex.synchronize { @pause_requested }
2085
+ @control_mutex.synchronize { !!@pause_requested }
2045
2086
  end
2046
2087
 
2047
2088
  # Check if stop is requested
2048
2089
  def stop_requested?
2049
- @control_mutex.synchronize { @stop_requested }
2090
+ @control_mutex.synchronize { !!@stop_requested }
2050
2091
  end
2051
2092
 
2052
2093
  # Check if resume is requested
2053
2094
  def resume_requested?
2054
- @control_mutex.synchronize { @resume_requested }
2095
+ @control_mutex.synchronize { !!@resume_requested }
2055
2096
  end
2056
2097
 
2057
2098
  # Request pause
@@ -2124,7 +2165,7 @@ module Aidp
2124
2165
  puts "=" * 50
2125
2166
 
2126
2167
  loop do
2127
- input = Readline.readline("Paused> ", true)
2168
+ input = @prompt.ask("Paused>")
2128
2169
 
2129
2170
  case input&.strip&.downcase
2130
2171
  when "r", "resume"
@@ -2189,7 +2230,7 @@ module Aidp
2189
2230
  # Control interface main loop
2190
2231
  def control_interface_loop
2191
2232
  loop do
2192
- input = Readline.readline("Control> ", true)
2233
+ input = @prompt.ask("Control> ")
2193
2234
 
2194
2235
  case input&.strip&.downcase
2195
2236
  when "p", "pause"
@@ -2253,11 +2294,11 @@ module Aidp
2253
2294
  def get_control_status
2254
2295
  @control_mutex.synchronize do
2255
2296
  {
2256
- enabled: @control_interface_enabled,
2257
- pause_requested: @pause_requested,
2258
- stop_requested: @stop_requested,
2259
- resume_requested: @resume_requested,
2260
- control_thread_alive: @control_thread&.alive? || false
2297
+ enabled: !!@control_interface_enabled,
2298
+ pause_requested: !!@pause_requested,
2299
+ stop_requested: !!@stop_requested,
2300
+ resume_requested: !!@resume_requested,
2301
+ control_thread_alive: !!@control_thread&.alive?
2261
2302
  }
2262
2303
  end
2263
2304
  end
@@ -2291,7 +2332,7 @@ module Aidp
2291
2332
  puts "=" * 50
2292
2333
 
2293
2334
  loop do
2294
- choice = Readline.readline("Select option (1-8): ", true)
2335
+ choice = @prompt.ask("Select option (1-8): ")
2295
2336
 
2296
2337
  case choice&.strip
2297
2338
  when "1"
data/lib/aidp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aidp
4
- VERSION = "0.8.1"
4
+ VERSION = "0.8.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aidp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bart Agapinan
@@ -23,20 +23,6 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0.11'
26
- - !ruby/object:Gem::Dependency
27
- name: colorize
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: '1.1'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '1.1'
40
26
  - !ruby/object:Gem::Dependency
41
27
  name: csv
42
28
  requirement: !ruby/object:Gem::Requirement