aidp 0.9.5 → 0.10.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/error_handler.rb +4 -2
- data/lib/aidp/{analysis → analyze}/kb_inspector.rb +106 -89
- data/lib/aidp/analyze/prioritizer.rb +3 -2
- data/lib/aidp/analyze/ruby_maat_integration.rb +20 -3
- data/lib/aidp/analyze/runner.rb +27 -9
- data/lib/aidp/{analysis → analyze}/seams.rb +1 -1
- data/lib/aidp/analyze/steps.rb +7 -7
- data/lib/aidp/{analysis → analyze}/tree_sitter_grammar_loader.rb +22 -5
- data/lib/aidp/{analysis → analyze}/tree_sitter_scan.rb +32 -15
- data/lib/aidp/cli/first_run_wizard.rb +37 -28
- data/lib/aidp/cli/jobs_command.rb +37 -18
- data/lib/aidp/cli/terminal_io.rb +3 -3
- data/lib/aidp/cli.rb +131 -63
- data/lib/aidp/execute/runner.rb +27 -9
- data/lib/aidp/execute/steps.rb +18 -18
- data/lib/aidp/execute/workflow_selector.rb +36 -21
- data/lib/aidp/harness/enhanced_runner.rb +3 -3
- data/lib/aidp/harness/provider_factory.rb +3 -1
- data/lib/aidp/harness/provider_manager.rb +34 -15
- data/lib/aidp/harness/runner.rb +24 -5
- data/lib/aidp/harness/simple_user_interface.rb +19 -4
- data/lib/aidp/harness/status_display.rb +121 -104
- data/lib/aidp/harness/ui/enhanced_tui.rb +33 -5
- data/lib/aidp/harness/ui/error_handler.rb +3 -2
- data/lib/aidp/harness/ui/frame_manager.rb +52 -32
- data/lib/aidp/harness/ui/navigation/main_menu.rb +23 -14
- data/lib/aidp/harness/ui/progress_display.rb +28 -5
- data/lib/aidp/harness/ui/status_widget.rb +17 -8
- data/lib/aidp/harness/ui/workflow_controller.rb +25 -9
- data/lib/aidp/harness/user_interface.rb +341 -328
- data/lib/aidp/provider_manager.rb +10 -6
- data/lib/aidp/providers/anthropic.rb +3 -3
- data/lib/aidp/providers/base.rb +20 -1
- data/lib/aidp/providers/cursor.rb +6 -8
- data/lib/aidp/providers/gemini.rb +3 -3
- data/lib/aidp/providers/github_copilot.rb +264 -0
- data/lib/aidp/providers/opencode.rb +6 -8
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp.rb +4 -4
- metadata +6 -6
- data/lib/aidp/analyze/progress_visualizer.rb +0 -314
@@ -20,6 +20,21 @@ module Aidp
|
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
+
# Helper method for consistent message display using TTY::Prompt
|
24
|
+
def display_message(message, type: :info)
|
25
|
+
color = case type
|
26
|
+
when :error then :red
|
27
|
+
when :success then :green
|
28
|
+
when :warning then :yellow
|
29
|
+
when :info then :blue
|
30
|
+
when :highlight then :cyan
|
31
|
+
when :muted then :bright_black
|
32
|
+
else :white
|
33
|
+
end
|
34
|
+
|
35
|
+
@prompt.say(message, color: color)
|
36
|
+
end
|
37
|
+
|
23
38
|
# Helper method to handle input consistently with TTY::Prompt
|
24
39
|
# Fixed to avoid keystroke loss issues with TTY::Prompt's required validation
|
25
40
|
def get_input_with_prompt(message, required: false, default: nil)
|
@@ -36,7 +51,7 @@ module Aidp
|
|
36
51
|
if default
|
37
52
|
return default
|
38
53
|
elsif required
|
39
|
-
|
54
|
+
display_message("❌ This field is required. Please provide a response.", type: :error)
|
40
55
|
next
|
41
56
|
else
|
42
57
|
return nil
|
@@ -82,7 +97,7 @@ module Aidp
|
|
82
97
|
|
83
98
|
# Validate response if required
|
84
99
|
if question_data[:required] != false && (response.nil? || response.to_s.strip.empty?)
|
85
|
-
|
100
|
+
display_message("❌ This question is required. Please provide a response.", type: :error)
|
86
101
|
redo
|
87
102
|
end
|
88
103
|
|
@@ -99,11 +114,11 @@ module Aidp
|
|
99
114
|
|
100
115
|
# Display feedback context
|
101
116
|
def display_feedback_context(context)
|
102
|
-
|
103
|
-
|
117
|
+
display_message("\n📋 Context:", type: :highlight)
|
118
|
+
display_message("-" * 30, type: :muted)
|
104
119
|
|
105
120
|
if context[:type]
|
106
|
-
|
121
|
+
display_message("Type: #{context[:type]}", type: :info)
|
107
122
|
end
|
108
123
|
|
109
124
|
if context[:urgency]
|
@@ -113,23 +128,23 @@ module Aidp
|
|
113
128
|
"low" => "🟢"
|
114
129
|
}
|
115
130
|
urgency_emoji = urgency_emojis[context[:urgency]] || "ℹ️"
|
116
|
-
|
131
|
+
display_message("Urgency: #{urgency_emoji} #{context[:urgency].capitalize}", type: :info)
|
117
132
|
end
|
118
133
|
|
119
134
|
if context[:description]
|
120
|
-
|
135
|
+
display_message("Description: #{context[:description]}", type: :info)
|
121
136
|
end
|
122
137
|
|
123
138
|
if context[:agent_output]
|
124
|
-
|
125
|
-
|
139
|
+
display_message("\nAgent Output:", type: :info)
|
140
|
+
display_message(context[:agent_output], type: :info)
|
126
141
|
end
|
127
142
|
end
|
128
143
|
|
129
144
|
# Display question presentation header
|
130
145
|
def display_question_presentation_header(questions, context)
|
131
|
-
|
132
|
-
|
146
|
+
display_message("\n🤖 Agent needs your feedback:", type: :highlight)
|
147
|
+
display_message("=" * 60, type: :muted)
|
133
148
|
|
134
149
|
# Display question overview
|
135
150
|
display_question_overview(questions)
|
@@ -139,8 +154,8 @@ module Aidp
|
|
139
154
|
display_context_summary(context)
|
140
155
|
end
|
141
156
|
|
142
|
-
|
143
|
-
|
157
|
+
display_message("\n📝 Questions to answer:", type: :info)
|
158
|
+
display_message("-" * 40, type: :muted)
|
144
159
|
end
|
145
160
|
|
146
161
|
# Display question overview
|
@@ -151,23 +166,23 @@ module Aidp
|
|
151
166
|
|
152
167
|
question_types = questions.map { |q| q[:type] || "text" }.uniq
|
153
168
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
169
|
+
display_message("📊 Overview:", type: :info)
|
170
|
+
display_message(" Total questions: #{total_questions}", type: :info)
|
171
|
+
display_message(" Required: #{required_questions}", type: :info)
|
172
|
+
display_message(" Optional: #{optional_questions}", type: :info)
|
173
|
+
display_message(" Question types: #{question_types.join(", ")}", type: :info)
|
159
174
|
|
160
175
|
# Estimate completion time
|
161
176
|
estimated_time = estimate_completion_time(questions)
|
162
|
-
|
177
|
+
display_message(" Estimated time: #{estimated_time}", type: :info)
|
163
178
|
end
|
164
179
|
|
165
180
|
# Display context summary
|
166
181
|
def display_context_summary(context)
|
167
|
-
|
182
|
+
display_message("\n📋 Context Summary:", type: :info)
|
168
183
|
|
169
184
|
if context[:type]
|
170
|
-
|
185
|
+
display_message(" Type: #{context[:type]}", type: :info)
|
171
186
|
end
|
172
187
|
|
173
188
|
if context[:urgency]
|
@@ -177,11 +192,11 @@ module Aidp
|
|
177
192
|
"low" => "🟢"
|
178
193
|
}
|
179
194
|
urgency_emoji = urgency_emojis[context[:urgency]] || "ℹ️"
|
180
|
-
|
195
|
+
display_message(" Urgency: #{urgency_emoji} #{context[:urgency].capitalize}", type: :info)
|
181
196
|
end
|
182
197
|
|
183
198
|
if context[:description]
|
184
|
-
|
199
|
+
display_message(" Description: #{context[:description]}", type: :info)
|
185
200
|
end
|
186
201
|
end
|
187
202
|
|
@@ -230,9 +245,9 @@ module Aidp
|
|
230
245
|
required = question_data[:required] != false
|
231
246
|
|
232
247
|
# Display question header
|
233
|
-
|
234
|
-
|
235
|
-
|
248
|
+
display_message("\n" + "=" * 60, type: :muted)
|
249
|
+
display_message("📝 Question #{question_number} of #{total_questions}", type: :highlight)
|
250
|
+
display_message("=" * 60, type: :muted)
|
236
251
|
|
237
252
|
# Display question text with formatting
|
238
253
|
display_question_text(question_text, question_type)
|
@@ -243,7 +258,7 @@ module Aidp
|
|
243
258
|
# Display question instructions
|
244
259
|
display_question_instructions(question_type, options, default_value, required)
|
245
260
|
|
246
|
-
|
261
|
+
display_message("\n" + "-" * 60, type: :muted)
|
247
262
|
end
|
248
263
|
|
249
264
|
# Display question text with formatting
|
@@ -260,96 +275,96 @@ module Aidp
|
|
260
275
|
}
|
261
276
|
type_emoji = type_emojis[question_type] || "❓"
|
262
277
|
|
263
|
-
|
278
|
+
display_message("#{type_emoji} #{question_text}", type: :info)
|
264
279
|
end
|
265
280
|
|
266
281
|
# Display question metadata
|
267
282
|
def display_question_metadata(question_type, expected_input, options, default_value, required)
|
268
|
-
|
283
|
+
display_message("\n📋 Question Details:", type: :info)
|
269
284
|
|
270
285
|
# Question type
|
271
|
-
|
286
|
+
display_message(" Type: #{question_type.capitalize}", type: :info)
|
272
287
|
|
273
288
|
# Expected input
|
274
289
|
if expected_input != "text"
|
275
|
-
|
290
|
+
display_message(" Expected input: #{expected_input}", type: :info)
|
276
291
|
end
|
277
292
|
|
278
293
|
# Options
|
279
294
|
if options && !options.empty?
|
280
|
-
|
295
|
+
display_message(" Options: #{options.length} available", type: :info)
|
281
296
|
end
|
282
297
|
|
283
298
|
# Default value
|
284
299
|
if default_value
|
285
|
-
|
300
|
+
display_message(" Default: #{default_value}", type: :info)
|
286
301
|
end
|
287
302
|
|
288
303
|
# Required status
|
289
304
|
status = required ? "Required" : "Optional"
|
290
305
|
status_emoji = required ? "🔴" : "🟢"
|
291
|
-
|
306
|
+
display_message(" Status: #{status_emoji} #{status}", type: :info)
|
292
307
|
end
|
293
308
|
|
294
309
|
# Display question instructions
|
295
310
|
def display_question_instructions(question_type, options, default_value, required)
|
296
|
-
|
311
|
+
display_message("\n💡 Instructions:", type: :info)
|
297
312
|
|
298
313
|
case question_type
|
299
314
|
when "text"
|
300
|
-
|
301
|
-
|
302
|
-
|
315
|
+
display_message(" • Enter your text response", type: :info)
|
316
|
+
display_message(" • Use @ for file selection if needed", type: :info)
|
317
|
+
display_message(" • Press Enter when done", type: :info)
|
303
318
|
when "choice"
|
304
|
-
|
305
|
-
|
306
|
-
|
319
|
+
display_message(" • Select from the numbered options below", type: :info)
|
320
|
+
display_message(" • Enter the number of your choice", type: :info)
|
321
|
+
display_message(" • Press Enter to confirm", type: :info)
|
307
322
|
when "confirmation"
|
308
|
-
|
309
|
-
|
310
|
-
|
323
|
+
display_message(" • Enter 'y' or 'yes' for Yes", type: :info)
|
324
|
+
display_message(" • Enter 'n' or 'no' for No", type: :info)
|
325
|
+
display_message(" • Press Enter for default", type: :info)
|
311
326
|
when "file"
|
312
|
-
|
313
|
-
|
314
|
-
|
327
|
+
display_message(" • Enter file path directly", type: :info)
|
328
|
+
display_message(" • Use @ to browse and select files", type: :info)
|
329
|
+
display_message(" • File must exist and be readable", type: :info)
|
315
330
|
when "number"
|
316
|
-
|
317
|
-
|
318
|
-
|
331
|
+
display_message(" • Enter a valid number", type: :info)
|
332
|
+
display_message(" • Use decimal point for decimals", type: :info)
|
333
|
+
display_message(" • Press Enter when done", type: :info)
|
319
334
|
when "email"
|
320
|
-
|
321
|
-
|
322
|
-
|
335
|
+
display_message(" • Enter a valid email address", type: :info)
|
336
|
+
display_message(" • Format: user@domain.com", type: :info)
|
337
|
+
display_message(" • Press Enter when done", type: :info)
|
323
338
|
when "url"
|
324
|
-
|
325
|
-
|
326
|
-
|
339
|
+
display_message(" • Enter a valid URL", type: :info)
|
340
|
+
display_message(" • Format: https://example.com", type: :info)
|
341
|
+
display_message(" • Press Enter when done", type: :info)
|
327
342
|
end
|
328
343
|
|
329
344
|
# Additional instructions based on options
|
330
345
|
if options && !options.empty?
|
331
|
-
|
346
|
+
display_message("\n📋 Available Options:", type: :info)
|
332
347
|
options.each_with_index do |option, index|
|
333
348
|
marker = (default_value && option == default_value) ? " (default)" : ""
|
334
|
-
|
349
|
+
display_message(" #{index + 1}. #{option}#{marker}", type: :info)
|
335
350
|
end
|
336
351
|
end
|
337
352
|
|
338
353
|
# Default value instructions
|
339
354
|
if default_value
|
340
|
-
|
341
|
-
|
355
|
+
display_message("\n⚡ Quick Answer:", type: :info)
|
356
|
+
display_message(" • Press Enter to use default: #{default_value}", type: :info)
|
342
357
|
end
|
343
358
|
|
344
359
|
# Required field instructions
|
345
360
|
if required
|
346
|
-
|
347
|
-
|
348
|
-
|
361
|
+
display_message("\n⚠️ Required Field:", type: :info)
|
362
|
+
display_message(" • This question must be answered", type: :info)
|
363
|
+
display_message(" • Cannot be left blank", type: :info)
|
349
364
|
else
|
350
|
-
|
351
|
-
|
352
|
-
|
365
|
+
display_message("\n✅ Optional Field:", type: :info)
|
366
|
+
display_message(" • This question can be skipped", type: :info)
|
367
|
+
display_message(" • Press Enter to leave blank", type: :info)
|
353
368
|
end
|
354
369
|
end
|
355
370
|
|
@@ -358,13 +373,13 @@ module Aidp
|
|
358
373
|
progress_percentage = (current_index.to_f / total_questions * 100).round(1)
|
359
374
|
progress_bar = generate_progress_bar(progress_percentage)
|
360
375
|
|
361
|
-
|
376
|
+
display_message("\n📊 Progress: #{progress_bar} #{progress_percentage}% (#{current_index}/#{total_questions})", type: :info)
|
362
377
|
|
363
378
|
# Show estimated time remaining
|
364
379
|
if current_index < total_questions
|
365
380
|
remaining_questions = total_questions - current_index
|
366
381
|
estimated_remaining = estimate_remaining_time(remaining_questions)
|
367
|
-
|
382
|
+
display_message("⏱️ Estimated time remaining: #{estimated_remaining}", type: :info)
|
368
383
|
end
|
369
384
|
end
|
370
385
|
|
@@ -391,34 +406,34 @@ module Aidp
|
|
391
406
|
|
392
407
|
# Display question completion summary
|
393
408
|
def display_question_completion_summary(responses, questions)
|
394
|
-
|
395
|
-
|
396
|
-
|
409
|
+
display_message("\n" + "=" * 60, type: :muted)
|
410
|
+
display_message("✅ Question Completion Summary", type: :success)
|
411
|
+
display_message("=" * 60, type: :muted)
|
397
412
|
|
398
413
|
# Show completion statistics
|
399
414
|
total_questions = questions.length
|
400
415
|
answered_questions = responses.values.count { |v| !v.nil? && !v.to_s.strip.empty? }
|
401
416
|
skipped_questions = total_questions - answered_questions
|
402
417
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
418
|
+
display_message("📊 Statistics:", type: :info)
|
419
|
+
display_message(" Total questions: #{total_questions}", type: :info)
|
420
|
+
display_message(" Answered: #{answered_questions}", type: :info)
|
421
|
+
display_message(" Skipped: #{skipped_questions}", type: :info)
|
422
|
+
display_message(" Completion rate: #{(answered_questions.to_f / total_questions * 100).round(1)}%", type: :info)
|
408
423
|
|
409
424
|
# Show response summary
|
410
|
-
|
425
|
+
display_message("\n📝 Response Summary:", type: :info)
|
411
426
|
responses.each do |key, value|
|
412
427
|
question_number = key.gsub("question_", "")
|
413
428
|
if value.nil? || value.to_s.strip.empty?
|
414
|
-
|
429
|
+
display_message(" #{question_number}. [Skipped]", type: :muted)
|
415
430
|
else
|
416
431
|
display_value = (value.to_s.length > 50) ? "#{value.to_s[0..47]}..." : value.to_s
|
417
|
-
|
432
|
+
display_message(" #{question_number}. #{display_value}", type: :info)
|
418
433
|
end
|
419
434
|
end
|
420
435
|
|
421
|
-
|
436
|
+
display_message("\n🚀 Continuing execution...", type: :success)
|
422
437
|
end
|
423
438
|
|
424
439
|
# Display question information (legacy method for compatibility)
|
@@ -460,7 +475,7 @@ module Aidp
|
|
460
475
|
"Required: No"
|
461
476
|
end
|
462
477
|
|
463
|
-
|
478
|
+
display_message(" #{info_parts.join(" | ")}", type: :info)
|
464
479
|
end
|
465
480
|
|
466
481
|
# Get response for a specific question with enhanced validation
|
@@ -496,15 +511,15 @@ module Aidp
|
|
496
511
|
def handle_input_error(error, question_data, retry_count = 0)
|
497
512
|
max_retries = 3
|
498
513
|
|
499
|
-
|
500
|
-
|
514
|
+
display_message("\n🚨 Input Error:", type: :error)
|
515
|
+
display_message(" #{error.message}", type: :error)
|
501
516
|
|
502
517
|
if retry_count < max_retries
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
518
|
+
display_message("\n🔄 Retry Options:", type: :info)
|
519
|
+
display_message(" 1. Try again", type: :info)
|
520
|
+
display_message(" 2. Skip this question", type: :info)
|
521
|
+
display_message(" 3. Get help", type: :info)
|
522
|
+
display_message(" 4. Cancel all questions", type: :info)
|
508
523
|
|
509
524
|
choice = @prompt.select("Choose an option:", {
|
510
525
|
"Try again" => "1",
|
@@ -515,23 +530,23 @@ module Aidp
|
|
515
530
|
|
516
531
|
case choice
|
517
532
|
when "1"
|
518
|
-
|
533
|
+
display_message("🔄 Retrying...", type: :info)
|
519
534
|
:retry
|
520
535
|
when "2"
|
521
|
-
|
536
|
+
display_message("⏭️ Skipping question...", type: :warning)
|
522
537
|
:skip
|
523
538
|
when "3"
|
524
539
|
show_question_help(question_data)
|
525
540
|
:retry
|
526
541
|
when "4"
|
527
|
-
|
542
|
+
display_message("❌ Cancelling all questions...", type: :error)
|
528
543
|
:cancel
|
529
544
|
else
|
530
|
-
|
545
|
+
display_message("❌ Invalid choice. Retrying...", type: :error)
|
531
546
|
:retry
|
532
547
|
end
|
533
548
|
else
|
534
|
-
|
549
|
+
display_message("\n❌ Maximum retries exceeded. Skipping question...", type: :error)
|
535
550
|
:skip
|
536
551
|
end
|
537
552
|
end
|
@@ -540,74 +555,74 @@ module Aidp
|
|
540
555
|
def show_question_help(question_data)
|
541
556
|
question_type = question_data[:type] || "text"
|
542
557
|
|
543
|
-
|
544
|
-
|
558
|
+
display_message("\n📖 Help for #{question_type.capitalize} Question:", type: :info)
|
559
|
+
display_message("=" * 50, type: :muted)
|
545
560
|
|
546
561
|
case question_type
|
547
562
|
when "text"
|
548
|
-
|
549
|
-
|
550
|
-
|
563
|
+
display_message("• Enter any text response", type: :info)
|
564
|
+
display_message("• Use @ for file selection if needed", type: :info)
|
565
|
+
display_message("• Press Enter when done", type: :info)
|
551
566
|
when "choice"
|
552
|
-
|
553
|
-
|
554
|
-
|
567
|
+
display_message("• Select from the numbered options", type: :info)
|
568
|
+
display_message("• Enter the number of your choice", type: :info)
|
569
|
+
display_message("• Or type the option text directly", type: :info)
|
555
570
|
when "confirmation"
|
556
|
-
|
557
|
-
|
558
|
-
|
571
|
+
display_message("• Enter 'y' or 'yes' for Yes", type: :info)
|
572
|
+
display_message("• Enter 'n' or 'no' for No", type: :info)
|
573
|
+
display_message("• Press Enter for default", type: :info)
|
559
574
|
when "file"
|
560
|
-
|
561
|
-
|
562
|
-
|
575
|
+
display_message("• Enter file path directly", type: :info)
|
576
|
+
display_message("• Use @ to browse and select files", type: :info)
|
577
|
+
display_message("• File must exist and be readable", type: :info)
|
563
578
|
when "number"
|
564
|
-
|
565
|
-
|
566
|
-
|
579
|
+
display_message("• Enter a valid number", type: :info)
|
580
|
+
display_message("• Use decimal point for decimals", type: :info)
|
581
|
+
display_message("• Check range requirements", type: :info)
|
567
582
|
when "email"
|
568
|
-
|
569
|
-
|
570
|
-
|
583
|
+
display_message("• Enter a valid email address", type: :info)
|
584
|
+
display_message("• Format: user@domain.com", type: :info)
|
585
|
+
display_message("• Check for typos", type: :info)
|
571
586
|
when "url"
|
572
|
-
|
573
|
-
|
574
|
-
|
587
|
+
display_message("• Enter a valid URL", type: :info)
|
588
|
+
display_message("• Format: https://example.com", type: :info)
|
589
|
+
display_message("• Include protocol (http:// or https://)", type: :info)
|
575
590
|
end
|
576
591
|
|
577
|
-
|
592
|
+
display_message("\nPress Enter to continue...", type: :info)
|
578
593
|
@prompt.keypress("Press any key to continue...")
|
579
594
|
end
|
580
595
|
|
581
596
|
# Enhanced error handling and validation display
|
582
597
|
def display_validation_error(validation_result, _input_type)
|
583
|
-
|
584
|
-
|
598
|
+
display_message("\n❌ Validation Error:", type: :error)
|
599
|
+
display_message(" #{validation_result[:error_message]}", type: :error)
|
585
600
|
|
586
601
|
if validation_result[:suggestions].any?
|
587
|
-
|
602
|
+
display_message("\n💡 Suggestions:", type: :info)
|
588
603
|
validation_result[:suggestions].each do |suggestion|
|
589
|
-
|
604
|
+
display_message(" • #{suggestion}", type: :info)
|
590
605
|
end
|
591
606
|
end
|
592
607
|
|
593
608
|
if validation_result[:warnings].any?
|
594
|
-
|
609
|
+
display_message("\n⚠️ Warnings:", type: :warning)
|
595
610
|
validation_result[:warnings].each do |warning|
|
596
|
-
|
611
|
+
display_message(" • #{warning}", type: :warning)
|
597
612
|
end
|
598
613
|
end
|
599
614
|
|
600
|
-
|
615
|
+
display_message("\n🔄 Please try again...", type: :info)
|
601
616
|
end
|
602
617
|
|
603
618
|
# Display validation warnings
|
604
619
|
def display_validation_warnings(validation_result)
|
605
620
|
if validation_result[:warnings].any?
|
606
|
-
|
621
|
+
display_message("\n⚠️ Warnings:", type: :warning)
|
607
622
|
validation_result[:warnings].each do |warning|
|
608
|
-
|
623
|
+
display_message(" • #{warning}", type: :warning)
|
609
624
|
end
|
610
|
-
|
625
|
+
display_message("\nPress Enter to continue or type 'fix' to correct...", type: :info)
|
611
626
|
|
612
627
|
input = @prompt.ask("")
|
613
628
|
return input&.strip&.downcase == "fix"
|
@@ -652,10 +667,10 @@ module Aidp
|
|
652
667
|
def get_choice_response(options, default_value, required)
|
653
668
|
return nil if options.nil? || options.empty?
|
654
669
|
|
655
|
-
|
670
|
+
display_message("\n Available options:", type: :info)
|
656
671
|
options.each_with_index do |option, index|
|
657
672
|
marker = (default_value && option == default_value) ? " (default)" : ""
|
658
|
-
|
673
|
+
display_message(" #{index + 1}. #{option}#{marker}", type: :info)
|
659
674
|
end
|
660
675
|
|
661
676
|
loop do
|
@@ -669,7 +684,7 @@ module Aidp
|
|
669
684
|
if default_value
|
670
685
|
return default_value
|
671
686
|
elsif required
|
672
|
-
|
687
|
+
display_message("❌ Please make a selection.", type: :error)
|
673
688
|
next
|
674
689
|
else
|
675
690
|
return nil
|
@@ -749,7 +764,7 @@ module Aidp
|
|
749
764
|
if default_value
|
750
765
|
return default_value
|
751
766
|
elsif required
|
752
|
-
|
767
|
+
display_message("❌ Please provide a file path.", type: :error)
|
753
768
|
next
|
754
769
|
else
|
755
770
|
return nil
|
@@ -792,7 +807,7 @@ module Aidp
|
|
792
807
|
if default_value
|
793
808
|
return default_value
|
794
809
|
elsif required
|
795
|
-
|
810
|
+
display_message("❌ Please provide a number.", type: :error)
|
796
811
|
next
|
797
812
|
else
|
798
813
|
return nil
|
@@ -820,7 +835,7 @@ module Aidp
|
|
820
835
|
return Float(input.strip)
|
821
836
|
end
|
822
837
|
rescue ArgumentError
|
823
|
-
|
838
|
+
display_message("❌ Please enter a valid #{expected_input}.", type: :error)
|
824
839
|
next
|
825
840
|
end
|
826
841
|
end
|
@@ -839,7 +854,7 @@ module Aidp
|
|
839
854
|
if default_value
|
840
855
|
return default_value
|
841
856
|
elsif required
|
842
|
-
|
857
|
+
display_message("❌ Please provide an email address.", type: :error)
|
843
858
|
next
|
844
859
|
else
|
845
860
|
return nil
|
@@ -876,7 +891,7 @@ module Aidp
|
|
876
891
|
if default_value
|
877
892
|
return default_value
|
878
893
|
elsif required
|
879
|
-
|
894
|
+
display_message("❌ Please provide a URL.", type: :error)
|
880
895
|
next
|
881
896
|
else
|
882
897
|
return nil
|
@@ -1323,7 +1338,7 @@ module Aidp
|
|
1323
1338
|
|
1324
1339
|
# Handle empty input
|
1325
1340
|
if input.nil? || input.strip.empty?
|
1326
|
-
|
1341
|
+
display_message("Please provide a response.", type: :error)
|
1327
1342
|
next
|
1328
1343
|
end
|
1329
1344
|
|
@@ -1351,8 +1366,8 @@ module Aidp
|
|
1351
1366
|
available_files = find_files_advanced(search_options)
|
1352
1367
|
|
1353
1368
|
if available_files.empty?
|
1354
|
-
|
1355
|
-
|
1369
|
+
display_message("No files found matching '#{search_options[:term]}'. Please try again.", type: :warning)
|
1370
|
+
display_message("💡 Try: @ (all files), @.rb (Ruby files), @config (files with 'config'), @lib/ (files in lib directory)", type: :info)
|
1356
1371
|
return nil
|
1357
1372
|
end
|
1358
1373
|
|
@@ -1364,7 +1379,7 @@ module Aidp
|
|
1364
1379
|
|
1365
1380
|
if selection && selection >= 0 && selection < available_files.size
|
1366
1381
|
selected_file = available_files[selection]
|
1367
|
-
|
1382
|
+
display_message("✅ Selected: #{selected_file}", type: :success)
|
1368
1383
|
|
1369
1384
|
# Show file preview if requested
|
1370
1385
|
if search_options[:preview]
|
@@ -1376,7 +1391,7 @@ module Aidp
|
|
1376
1391
|
# User wants to refine search
|
1377
1392
|
handle_file_selection("@#{search_term}")
|
1378
1393
|
else
|
1379
|
-
|
1394
|
+
display_message("❌ Invalid selection. Please try again.", type: :error)
|
1380
1395
|
nil
|
1381
1396
|
end
|
1382
1397
|
end
|
@@ -1580,21 +1595,21 @@ module Aidp
|
|
1580
1595
|
|
1581
1596
|
# Display advanced file selection menu
|
1582
1597
|
def display_advanced_file_menu(files, search_options)
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1598
|
+
display_message("\n📁 Available files:", type: :info)
|
1599
|
+
display_message("Search: #{search_options[:term]} | Extensions: #{search_options[:extensions].join(", ")} | Directories: #{search_options[:directories].join(", ")}", type: :info)
|
1600
|
+
display_message("-" * 80, type: :muted)
|
1586
1601
|
|
1587
1602
|
files.each_with_index do |file, index|
|
1588
1603
|
file_info = get_file_info(file)
|
1589
|
-
|
1590
|
-
|
1604
|
+
display_message(" #{index + 1}. #{file_info[:display_name]}", type: :info)
|
1605
|
+
display_message(" 📄 #{file_info[:size]} | 📅 #{file_info[:modified]} | 🏷️ #{file_info[:type]}", type: :muted)
|
1591
1606
|
end
|
1592
1607
|
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1608
|
+
display_message("\nOptions:", type: :info)
|
1609
|
+
display_message(" 0. Cancel", type: :info)
|
1610
|
+
display_message(" -1. Refine search", type: :info)
|
1611
|
+
display_message(" p. Preview selected file", type: :info)
|
1612
|
+
display_message(" h. Show help", type: :info)
|
1598
1613
|
end
|
1599
1614
|
|
1600
1615
|
# Get file information for display
|
@@ -1666,7 +1681,7 @@ module Aidp
|
|
1666
1681
|
input = @prompt.ask("Select file (0-#{max_files}, -1=refine, p=preview, h=help): ")
|
1667
1682
|
|
1668
1683
|
if input.nil? || input.strip.empty?
|
1669
|
-
|
1684
|
+
display_message("Please enter a selection.", type: :error)
|
1670
1685
|
next
|
1671
1686
|
end
|
1672
1687
|
|
@@ -1678,7 +1693,7 @@ module Aidp
|
|
1678
1693
|
show_file_selection_help
|
1679
1694
|
next
|
1680
1695
|
when "p", "preview"
|
1681
|
-
|
1696
|
+
display_message("💡 Select a file number first, then use 'p' to preview it.", type: :info)
|
1682
1697
|
next
|
1683
1698
|
end
|
1684
1699
|
|
@@ -1691,71 +1706,71 @@ module Aidp
|
|
1691
1706
|
elsif selection.between?(1, max_files)
|
1692
1707
|
return selection - 1 # Convert to 0-based index
|
1693
1708
|
else
|
1694
|
-
|
1709
|
+
display_message("Please enter a number between 0 and #{max_files}, or use -1, p, h.", type: :error)
|
1695
1710
|
end
|
1696
1711
|
rescue ArgumentError
|
1697
|
-
|
1712
|
+
display_message("Please enter a valid number or command (0-#{max_files}, -1, p, h).", type: :error)
|
1698
1713
|
end
|
1699
1714
|
end
|
1700
1715
|
end
|
1701
1716
|
|
1702
1717
|
# Show file selection help
|
1703
1718
|
def show_file_selection_help
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1719
|
+
display_message("\n📖 File Selection Help:", type: :info)
|
1720
|
+
display_message("=" * 40, type: :muted)
|
1721
|
+
|
1722
|
+
display_message("\n🔍 Search Examples:", type: :info)
|
1723
|
+
display_message(" @ - Show all files", type: :info)
|
1724
|
+
display_message(" @.rb - Show Ruby files only", type: :info)
|
1725
|
+
display_message(" @config - Show files with 'config' in name", type: :info)
|
1726
|
+
display_message(" @lib/ - Show files in lib directory", type: :info)
|
1727
|
+
display_message(" @spec preview - Show spec files with preview option", type: :info)
|
1728
|
+
display_message(" @.js case - Show JavaScript files (case sensitive)", type: :info)
|
1729
|
+
|
1730
|
+
display_message("\n⌨️ Selection Commands:", type: :info)
|
1731
|
+
display_message(" 1-50 - Select file by number", type: :info)
|
1732
|
+
display_message(" 0 - Cancel selection", type: :info)
|
1733
|
+
display_message(" -1 - Refine search", type: :info)
|
1734
|
+
display_message(" p - Preview selected file", type: :info)
|
1735
|
+
display_message(" h - Show this help", type: :info)
|
1736
|
+
|
1737
|
+
display_message("\n💡 Tips:", type: :info)
|
1738
|
+
display_message(" • Files are sorted by relevance and type", type: :info)
|
1739
|
+
display_message(" • Use extension filters for specific file types", type: :info)
|
1740
|
+
display_message(" • Use directory filters to limit search scope", type: :info)
|
1741
|
+
display_message(" • Preview option shows file content before selection", type: :info)
|
1727
1742
|
end
|
1728
1743
|
|
1729
1744
|
# Show file preview
|
1730
1745
|
def show_file_preview(file_path)
|
1731
|
-
|
1732
|
-
|
1746
|
+
display_message("\n📄 File Preview: #{file_path}", type: :highlight)
|
1747
|
+
display_message("=" * 60, type: :muted)
|
1733
1748
|
|
1734
1749
|
begin
|
1735
1750
|
content = File.read(file_path)
|
1736
1751
|
lines = content.lines
|
1737
1752
|
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1753
|
+
display_message("📊 File Info:", type: :info)
|
1754
|
+
display_message(" Size: #{format_file_size(File.size(file_path))}", type: :info)
|
1755
|
+
display_message(" Lines: #{lines.count}", type: :info)
|
1756
|
+
display_message(" Modified: #{File.mtime(file_path).strftime("%Y-%m-%d %H:%M:%S")}", type: :info)
|
1757
|
+
display_message(" Type: #{get_file_type(file_path)}", type: :info)
|
1743
1758
|
|
1744
|
-
|
1745
|
-
|
1759
|
+
display_message("\n📝 Content Preview (first 20 lines):", type: :info)
|
1760
|
+
display_message("-" * 40, type: :muted)
|
1746
1761
|
|
1747
1762
|
lines.first(20).each_with_index do |line, index|
|
1748
|
-
|
1763
|
+
display_message("#{(index + 1).to_s.rjust(3)}: #{line.chomp}", type: :info)
|
1749
1764
|
end
|
1750
1765
|
|
1751
1766
|
if lines.count > 20
|
1752
|
-
|
1767
|
+
display_message("... (#{lines.count - 20} more lines)", type: :muted)
|
1753
1768
|
end
|
1754
1769
|
rescue => e
|
1755
|
-
|
1770
|
+
display_message("❌ Error reading file: #{e.message}", type: :error)
|
1756
1771
|
end
|
1757
1772
|
|
1758
|
-
|
1773
|
+
display_message("\nPress Enter to continue...", type: :info)
|
1759
1774
|
@prompt.keypress("Press any key to continue...")
|
1760
1775
|
end
|
1761
1776
|
|
@@ -1783,17 +1798,17 @@ module Aidp
|
|
1783
1798
|
when "n", "no"
|
1784
1799
|
return false
|
1785
1800
|
else
|
1786
|
-
|
1801
|
+
display_message("Please enter 'y' or 'n'.", type: :error)
|
1787
1802
|
end
|
1788
1803
|
end
|
1789
1804
|
end
|
1790
1805
|
|
1791
1806
|
# Get choice from multiple options
|
1792
1807
|
def get_choice(message, options, default: nil)
|
1793
|
-
|
1808
|
+
display_message("\n#{message}", type: :info)
|
1794
1809
|
options.each_with_index do |option, index|
|
1795
1810
|
marker = (default && index == default) ? " (default)" : ""
|
1796
|
-
|
1811
|
+
display_message(" #{index + 1}. #{option}#{marker}", type: :info)
|
1797
1812
|
end
|
1798
1813
|
|
1799
1814
|
loop do
|
@@ -1801,7 +1816,7 @@ module Aidp
|
|
1801
1816
|
|
1802
1817
|
if input.nil? || input.strip.empty?
|
1803
1818
|
return default if default
|
1804
|
-
|
1819
|
+
display_message("Please make a selection.", type: :error)
|
1805
1820
|
next
|
1806
1821
|
end
|
1807
1822
|
|
@@ -1810,10 +1825,10 @@ module Aidp
|
|
1810
1825
|
if choice.between?(1, options.size)
|
1811
1826
|
return choice - 1 # Convert to 0-based index
|
1812
1827
|
else
|
1813
|
-
|
1828
|
+
display_message("Please enter a number between 1 and #{options.size}.", type: :error)
|
1814
1829
|
end
|
1815
1830
|
rescue ArgumentError
|
1816
|
-
|
1831
|
+
display_message("Please enter a valid number.", type: :error)
|
1817
1832
|
end
|
1818
1833
|
end
|
1819
1834
|
end
|
@@ -1821,13 +1836,11 @@ module Aidp
|
|
1821
1836
|
# Display progress message
|
1822
1837
|
def show_progress(message)
|
1823
1838
|
print "\r#{message}".ljust(80)
|
1824
|
-
$stdout.flush
|
1825
1839
|
end
|
1826
1840
|
|
1827
1841
|
# Clear progress message
|
1828
1842
|
def clear_progress
|
1829
1843
|
print "\r" + " " * 80 + "\r"
|
1830
|
-
$stdout.flush
|
1831
1844
|
end
|
1832
1845
|
|
1833
1846
|
# Get input history
|
@@ -1842,43 +1855,43 @@ module Aidp
|
|
1842
1855
|
|
1843
1856
|
# Display interactive help
|
1844
1857
|
def show_help
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1858
|
+
display_message("\n📖 Interactive Prompt Help:", type: :info)
|
1859
|
+
display_message("=" * 40, type: :info)
|
1860
|
+
|
1861
|
+
display_message("\n🔤 Input Types:", type: :info)
|
1862
|
+
display_message(" • Text: Free-form text input", type: :info)
|
1863
|
+
display_message(" • Choice: Select from predefined options", type: :info)
|
1864
|
+
display_message(" • Confirmation: Yes/No questions", type: :info)
|
1865
|
+
display_message(" • File: File path with @ browsing", type: :info)
|
1866
|
+
display_message(" • Number: Integer or decimal numbers", type: :info)
|
1867
|
+
display_message(" • Email: Email address format", type: :info)
|
1868
|
+
display_message(" • URL: Web URL format", type: :info)
|
1869
|
+
|
1870
|
+
display_message("\n⌨️ Special Commands:", type: :info)
|
1871
|
+
display_message(" • @: Browse and select files", type: :info)
|
1872
|
+
display_message(" • Enter: Use default value (if available)", type: :info)
|
1873
|
+
display_message(" • Ctrl+C: Cancel operation", type: :info)
|
1874
|
+
|
1875
|
+
display_message("\n📁 File Selection:", type: :info)
|
1876
|
+
display_message(" • Type @ to browse files", type: :info)
|
1877
|
+
display_message(" • Type @search to filter files", type: :info)
|
1878
|
+
display_message(" • Select by number or type 0 to cancel", type: :info)
|
1879
|
+
|
1880
|
+
display_message("\n✅ Validation:", type: :info)
|
1881
|
+
display_message(" • Required fields must be filled", type: :info)
|
1882
|
+
display_message(" • Input format is validated automatically", type: :info)
|
1883
|
+
display_message(" • Invalid input shows error and retries", type: :info)
|
1884
|
+
|
1885
|
+
display_message("\n💡 Tips:", type: :info)
|
1886
|
+
display_message(" • Use Tab for auto-completion", type: :info)
|
1887
|
+
display_message(" • Arrow keys for history navigation", type: :info)
|
1888
|
+
display_message(" • Default values are shown in prompts", type: :info)
|
1876
1889
|
end
|
1877
1890
|
|
1878
1891
|
# Display question summary
|
1879
1892
|
def display_question_summary(questions)
|
1880
|
-
|
1881
|
-
|
1893
|
+
display_message("\n📋 Question Summary:", type: :info)
|
1894
|
+
display_message("-" * 30, type: :info)
|
1882
1895
|
|
1883
1896
|
questions.each_with_index do |question_data, index|
|
1884
1897
|
question_number = question_data[:number] || (index + 1)
|
@@ -1898,14 +1911,14 @@ module Aidp
|
|
1898
1911
|
}
|
1899
1912
|
type_emoji = type_emojis[question_type] || "❓"
|
1900
1913
|
|
1901
|
-
|
1914
|
+
display_message(" #{question_number}. #{type_emoji} #{question_text} (#{status})", type: :info)
|
1902
1915
|
end
|
1903
1916
|
end
|
1904
1917
|
|
1905
1918
|
# Get user preferences for feedback collection
|
1906
1919
|
def get_user_preferences
|
1907
|
-
|
1908
|
-
|
1920
|
+
display_message("\n⚙️ User Preferences:", type: :info)
|
1921
|
+
display_message("-" * 25, type: :muted)
|
1909
1922
|
|
1910
1923
|
preferences = {}
|
1911
1924
|
|
@@ -1967,14 +1980,14 @@ module Aidp
|
|
1967
1980
|
# Show help if needed
|
1968
1981
|
if should_show_help?(questions.first&.dig(:type), seen_types)
|
1969
1982
|
show_help
|
1970
|
-
|
1983
|
+
display_message("\nPress Enter to continue...", type: :info)
|
1971
1984
|
@prompt.keypress("Press any key to continue...")
|
1972
1985
|
end
|
1973
1986
|
|
1974
1987
|
# Display question summary if verbose
|
1975
1988
|
if @verbose_mode
|
1976
1989
|
display_question_summary(questions)
|
1977
|
-
|
1990
|
+
display_message("\nPress Enter to start answering questions...", type: :info)
|
1978
1991
|
@prompt.keypress("Press any key to continue...")
|
1979
1992
|
end
|
1980
1993
|
|
@@ -1995,7 +2008,7 @@ module Aidp
|
|
1995
2008
|
default_value = options[:default]
|
1996
2009
|
required = options[:required] != false
|
1997
2010
|
|
1998
|
-
|
2011
|
+
display_message("\n❓ #{question}", type: :info)
|
1999
2012
|
|
2000
2013
|
case question_type
|
2001
2014
|
when "text"
|
@@ -2013,8 +2026,8 @@ module Aidp
|
|
2013
2026
|
def collect_batch_feedback(questions)
|
2014
2027
|
responses = {}
|
2015
2028
|
|
2016
|
-
|
2017
|
-
|
2029
|
+
display_message("\n📝 Quick Feedback Collection:", type: :info)
|
2030
|
+
display_message("=" * 35, type: :muted)
|
2018
2031
|
|
2019
2032
|
questions.each_with_index do |question_data, index|
|
2020
2033
|
question_number = index + 1
|
@@ -2023,7 +2036,7 @@ module Aidp
|
|
2023
2036
|
default_value = question_data[:default]
|
2024
2037
|
required = question_data[:required] != false
|
2025
2038
|
|
2026
|
-
|
2039
|
+
display_message("\n#{question_number}. #{question_text}", type: :info)
|
2027
2040
|
|
2028
2041
|
response = get_quick_feedback(question_text, {
|
2029
2042
|
type: question_type,
|
@@ -2035,7 +2048,7 @@ module Aidp
|
|
2035
2048
|
responses["question_#{question_number}"] = response
|
2036
2049
|
end
|
2037
2050
|
|
2038
|
-
|
2051
|
+
display_message("\n✅ Batch feedback collected.", type: :success)
|
2039
2052
|
responses
|
2040
2053
|
end
|
2041
2054
|
|
@@ -2059,13 +2072,13 @@ module Aidp
|
|
2059
2072
|
end
|
2060
2073
|
end
|
2061
2074
|
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2075
|
+
display_message("\n🎮 Control Interface Started", type: :success)
|
2076
|
+
display_message(" Press 'p' + Enter to pause", type: :info)
|
2077
|
+
display_message(" Press 'r' + Enter to resume", type: :info)
|
2078
|
+
display_message(" Press 's' + Enter to stop", type: :info)
|
2079
|
+
display_message(" Press 'h' + Enter for help", type: :info)
|
2080
|
+
display_message(" Press 'q' + Enter to quit control interface", type: :info)
|
2081
|
+
display_message("=" * 50, type: :muted)
|
2069
2082
|
end
|
2070
2083
|
|
2071
2084
|
# Stop the control interface
|
@@ -2077,7 +2090,7 @@ module Aidp
|
|
2077
2090
|
end
|
2078
2091
|
end
|
2079
2092
|
|
2080
|
-
|
2093
|
+
display_message("\n🛑 Control Interface Stopped", type: :info)
|
2081
2094
|
end
|
2082
2095
|
|
2083
2096
|
# Check if pause is requested
|
@@ -2101,7 +2114,7 @@ module Aidp
|
|
2101
2114
|
@pause_requested = true
|
2102
2115
|
@resume_requested = false
|
2103
2116
|
end
|
2104
|
-
|
2117
|
+
display_message("\n⏸️ Pause requested...", type: :warning)
|
2105
2118
|
end
|
2106
2119
|
|
2107
2120
|
# Request stop
|
@@ -2111,7 +2124,7 @@ module Aidp
|
|
2111
2124
|
@pause_requested = false
|
2112
2125
|
@resume_requested = false
|
2113
2126
|
end
|
2114
|
-
|
2127
|
+
display_message("\n🛑 Stop requested...", type: :error)
|
2115
2128
|
end
|
2116
2129
|
|
2117
2130
|
# Request resume
|
@@ -2120,7 +2133,7 @@ module Aidp
|
|
2120
2133
|
@resume_requested = true
|
2121
2134
|
@pause_requested = false
|
2122
2135
|
end
|
2123
|
-
|
2136
|
+
display_message("\n▶️ Resume requested...", type: :success)
|
2124
2137
|
end
|
2125
2138
|
|
2126
2139
|
# Clear all control requests
|
@@ -2155,14 +2168,14 @@ module Aidp
|
|
2155
2168
|
|
2156
2169
|
# Handle pause state
|
2157
2170
|
def handle_pause_state
|
2158
|
-
|
2159
|
-
|
2160
|
-
|
2161
|
-
|
2162
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2171
|
+
display_message("\n⏸️ HARNESS PAUSED", type: :warning)
|
2172
|
+
display_message("=" * 50, type: :muted)
|
2173
|
+
display_message("🎮 Control Options:", type: :info)
|
2174
|
+
display_message(" 'r' + Enter: Resume execution", type: :info)
|
2175
|
+
display_message(" 's' + Enter: Stop execution", type: :info)
|
2176
|
+
display_message(" 'h' + Enter: Show help", type: :info)
|
2177
|
+
display_message(" 'q' + Enter: Quit control interface", type: :info)
|
2178
|
+
display_message("=" * 50, type: :muted)
|
2166
2179
|
|
2167
2180
|
loop do
|
2168
2181
|
input = @prompt.ask("Paused>")
|
@@ -2180,51 +2193,51 @@ module Aidp
|
|
2180
2193
|
stop_control_interface
|
2181
2194
|
break
|
2182
2195
|
else
|
2183
|
-
|
2196
|
+
display_message("❌ Invalid command. Type 'h' for help.", type: :error)
|
2184
2197
|
end
|
2185
2198
|
end
|
2186
2199
|
end
|
2187
2200
|
|
2188
2201
|
# Handle stop state
|
2189
2202
|
def handle_stop_state
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
2193
|
-
|
2194
|
-
|
2203
|
+
display_message("\n🛑 HARNESS STOPPED", type: :error)
|
2204
|
+
display_message("=" * 50, type: :muted)
|
2205
|
+
display_message("Execution has been stopped by user request.", type: :info)
|
2206
|
+
display_message("You can restart the harness from where it left off.", type: :info)
|
2207
|
+
display_message("=" * 50, type: :muted)
|
2195
2208
|
end
|
2196
2209
|
|
2197
2210
|
# Handle resume state
|
2198
2211
|
def handle_resume_state
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2212
|
+
display_message("\n▶️ HARNESS RESUMED", type: :success)
|
2213
|
+
display_message("=" * 50, type: :muted)
|
2214
|
+
display_message("Execution has been resumed.", type: :info)
|
2215
|
+
display_message("=" * 50, type: :muted)
|
2203
2216
|
end
|
2204
2217
|
|
2205
2218
|
# Show control help
|
2206
2219
|
def show_control_help
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2220
|
+
display_message("\n📖 Control Interface Help", type: :info)
|
2221
|
+
display_message("=" * 50, type: :muted)
|
2222
|
+
display_message("🎮 Available Commands:", type: :info)
|
2223
|
+
display_message(" 'p' or 'pause' - Pause the harness execution", type: :info)
|
2224
|
+
display_message(" 'r' or 'resume' - Resume the harness execution", type: :info)
|
2225
|
+
display_message(" 's' or 'stop' - Stop the harness execution", type: :info)
|
2226
|
+
display_message(" 'h' or 'help' - Show this help message", type: :info)
|
2227
|
+
display_message(" 'q' or 'quit' - Quit the control interface", type: :info)
|
2228
|
+
display_message("", type: :info)
|
2229
|
+
display_message("📋 Control States:", type: :info)
|
2230
|
+
display_message(" Running - Harness is executing normally", type: :info)
|
2231
|
+
display_message(" Paused - Harness is paused, waiting for resume", type: :info)
|
2232
|
+
display_message(" Stopped - Harness has been stopped by user", type: :info)
|
2233
|
+
display_message(" Resumed - Harness has been resumed from pause", type: :info)
|
2234
|
+
display_message("", type: :info)
|
2235
|
+
display_message("💡 Tips:", type: :info)
|
2236
|
+
display_message(" • You can pause/resume/stop at any time during execution", type: :info)
|
2237
|
+
display_message(" • The harness will save its state when paused/stopped", type: :info)
|
2238
|
+
display_message(" • You can restart from where you left off", type: :info)
|
2239
|
+
display_message(" • Use 'h' for help at any time", type: :info)
|
2240
|
+
display_message("=" * 50, type: :muted)
|
2228
2241
|
end
|
2229
2242
|
|
2230
2243
|
# Control interface main loop
|
@@ -2248,15 +2261,15 @@ module Aidp
|
|
2248
2261
|
# Empty input, continue
|
2249
2262
|
next
|
2250
2263
|
else
|
2251
|
-
|
2264
|
+
display_message("❌ Invalid command. Type 'h' for help.", type: :error)
|
2252
2265
|
end
|
2253
2266
|
rescue Interrupt
|
2254
|
-
|
2267
|
+
display_message("\n🛑 Control interface interrupted. Stopping...", type: :error)
|
2255
2268
|
request_stop
|
2256
2269
|
break
|
2257
2270
|
rescue => e
|
2258
|
-
|
2259
|
-
|
2271
|
+
display_message("❌ Control interface error: #{e.message}", type: :error)
|
2272
|
+
display_message(" Type 'h' for help or 'q' to quit.", type: :info)
|
2260
2273
|
end
|
2261
2274
|
end
|
2262
2275
|
|
@@ -2280,14 +2293,14 @@ module Aidp
|
|
2280
2293
|
# Enable control interface
|
2281
2294
|
def enable_control_interface
|
2282
2295
|
@control_interface_enabled = true
|
2283
|
-
|
2296
|
+
display_message("🎮 Control interface enabled", type: :success)
|
2284
2297
|
end
|
2285
2298
|
|
2286
2299
|
# Disable control interface
|
2287
2300
|
def disable_control_interface
|
2288
2301
|
@control_interface_enabled = false
|
2289
2302
|
stop_control_interface
|
2290
|
-
|
2303
|
+
display_message("🎮 Control interface disabled", type: :info)
|
2291
2304
|
end
|
2292
2305
|
|
2293
2306
|
# Get control status
|
@@ -2307,29 +2320,29 @@ module Aidp
|
|
2307
2320
|
def display_control_status
|
2308
2321
|
status = get_control_status
|
2309
2322
|
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2323
|
+
display_message("\n🎮 Control Interface Status", type: :info)
|
2324
|
+
display_message("=" * 40, type: :muted)
|
2325
|
+
display_message("Enabled: #{status[:enabled] ? "✅ Yes" : "❌ No"}", type: :info)
|
2326
|
+
display_message("Pause Requested: #{status[:pause_requested] ? "⏸️ Yes" : "▶️ No"}", type: :info)
|
2327
|
+
display_message("Stop Requested: #{status[:stop_requested] ? "🛑 Yes" : "▶️ No"}", type: :info)
|
2328
|
+
display_message("Resume Requested: #{status[:resume_requested] ? "▶️ Yes" : "⏸️ No"}", type: :info)
|
2329
|
+
display_message("Control Thread: #{status[:control_thread_alive] ? "🟢 Active" : "🔴 Inactive"}", type: :info)
|
2330
|
+
display_message("=" * 40, type: :muted)
|
2318
2331
|
end
|
2319
2332
|
|
2320
2333
|
# Interactive control menu
|
2321
2334
|
def show_control_menu
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2335
|
+
display_message("\n🎮 Harness Control Menu", type: :info)
|
2336
|
+
display_message("=" * 50, type: :muted)
|
2337
|
+
display_message("1. Start Control Interface", type: :info)
|
2338
|
+
display_message("2. Stop Control Interface", type: :info)
|
2339
|
+
display_message("3. Pause Harness", type: :info)
|
2340
|
+
display_message("4. Resume Harness", type: :info)
|
2341
|
+
display_message("5. Stop Harness", type: :info)
|
2342
|
+
display_message("6. Show Control Status", type: :info)
|
2343
|
+
display_message("7. Show Help", type: :info)
|
2344
|
+
display_message("8. Exit Menu", type: :info)
|
2345
|
+
display_message("=" * 50, type: :muted)
|
2333
2346
|
|
2334
2347
|
loop do
|
2335
2348
|
choice = @prompt.ask("Select option (1-8): ")
|
@@ -2350,10 +2363,10 @@ module Aidp
|
|
2350
2363
|
when "7"
|
2351
2364
|
show_control_help
|
2352
2365
|
when "8"
|
2353
|
-
|
2366
|
+
display_message("👋 Exiting control menu...", type: :info)
|
2354
2367
|
break
|
2355
2368
|
else
|
2356
|
-
|
2369
|
+
display_message("❌ Invalid option. Please select 1-8.", type: :error)
|
2357
2370
|
end
|
2358
2371
|
end
|
2359
2372
|
end
|
@@ -2361,17 +2374,17 @@ module Aidp
|
|
2361
2374
|
# Quick control commands
|
2362
2375
|
def quick_pause
|
2363
2376
|
request_pause
|
2364
|
-
|
2377
|
+
display_message("⏸️ Quick pause requested. Use 'r' to resume.", type: :warning)
|
2365
2378
|
end
|
2366
2379
|
|
2367
2380
|
def quick_resume
|
2368
2381
|
request_resume
|
2369
|
-
|
2382
|
+
display_message("▶️ Quick resume requested.", type: :success)
|
2370
2383
|
end
|
2371
2384
|
|
2372
2385
|
def quick_stop
|
2373
2386
|
request_stop
|
2374
|
-
|
2387
|
+
display_message("🛑 Quick stop requested.", type: :error)
|
2375
2388
|
end
|
2376
2389
|
|
2377
2390
|
# Control interface with timeout
|
@@ -2390,7 +2403,7 @@ module Aidp
|
|
2390
2403
|
handle_resume_state
|
2391
2404
|
break
|
2392
2405
|
elsif Time.now - start_time > timeout_seconds
|
2393
|
-
|
2406
|
+
display_message("\n⏰ Control interface timeout reached. Continuing execution...", type: :warning)
|
2394
2407
|
break
|
2395
2408
|
elsif ENV["RACK_ENV"] == "test" || defined?(RSpec)
|
2396
2409
|
sleep(0.1)
|
@@ -2402,11 +2415,11 @@ module Aidp
|
|
2402
2415
|
|
2403
2416
|
# Emergency stop
|
2404
2417
|
def emergency_stop
|
2405
|
-
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
|
2418
|
+
display_message("\n🚨 EMERGENCY STOP INITIATED", type: :error)
|
2419
|
+
display_message("=" * 50, type: :muted)
|
2420
|
+
display_message("All execution will be halted immediately.", type: :error)
|
2421
|
+
display_message("This action cannot be undone.", type: :error)
|
2422
|
+
display_message("=" * 50, type: :muted)
|
2410
2423
|
|
2411
2424
|
@control_mutex.synchronize do
|
2412
2425
|
@stop_requested = true
|
@@ -2415,7 +2428,7 @@ module Aidp
|
|
2415
2428
|
end
|
2416
2429
|
|
2417
2430
|
stop_control_interface
|
2418
|
-
|
2431
|
+
display_message("🛑 Emergency stop completed.", type: :error)
|
2419
2432
|
end
|
2420
2433
|
end
|
2421
2434
|
end
|