aidp 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +194 -25
- data/lib/aidp/analyze/kb_inspector.rb +2 -15
- data/lib/aidp/analyze/progress.rb +2 -1
- data/lib/aidp/analyze/ruby_maat_integration.rb +2 -15
- data/lib/aidp/analyze/runner.rb +64 -20
- data/lib/aidp/analyze/steps.rb +10 -8
- data/lib/aidp/analyze/tree_sitter_grammar_loader.rb +2 -13
- data/lib/aidp/analyze/tree_sitter_scan.rb +2 -13
- data/lib/aidp/cli/checkpoint_command.rb +98 -0
- data/lib/aidp/cli/first_run_wizard.rb +65 -94
- data/lib/aidp/cli/jobs_command.rb +249 -34
- data/lib/aidp/cli.rb +312 -38
- data/lib/aidp/config.rb +5 -8
- data/lib/aidp/debug_logger.rb +4 -4
- data/lib/aidp/debug_mixin.rb +11 -4
- data/lib/aidp/execute/checkpoint.rb +282 -0
- data/lib/aidp/execute/checkpoint_display.rb +221 -0
- data/lib/aidp/execute/progress.rb +2 -1
- data/lib/aidp/execute/prompt_manager.rb +62 -0
- data/lib/aidp/execute/runner.rb +53 -24
- data/lib/aidp/execute/steps.rb +36 -27
- data/lib/aidp/execute/work_loop_runner.rb +308 -0
- data/lib/aidp/execute/workflow_selector.rb +26 -17
- data/lib/aidp/harness/condition_detector.rb +4 -4
- data/lib/aidp/harness/config_schema.rb +40 -0
- data/lib/aidp/harness/config_validator.rb +3 -6
- data/lib/aidp/harness/configuration.rb +35 -1
- data/lib/aidp/harness/enhanced_runner.rb +22 -1
- data/lib/aidp/harness/error_handler.rb +103 -28
- data/lib/aidp/harness/provider_factory.rb +4 -1
- data/lib/aidp/harness/provider_manager.rb +250 -15
- data/lib/aidp/harness/runner.rb +3 -14
- data/lib/aidp/harness/simple_user_interface.rb +2 -15
- data/lib/aidp/harness/status_display.rb +12 -17
- data/lib/aidp/harness/test_runner.rb +83 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +2 -0
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +22 -4
- data/lib/aidp/harness/ui/error_handler.rb +4 -0
- data/lib/aidp/harness/ui/frame_manager.rb +10 -8
- data/lib/aidp/harness/ui/job_monitor.rb +2 -0
- data/lib/aidp/harness/ui/navigation/main_menu.rb +4 -2
- data/lib/aidp/harness/ui/navigation/menu_item.rb +1 -0
- data/lib/aidp/harness/ui/navigation/menu_state.rb +1 -0
- data/lib/aidp/harness/ui/navigation/submenu.rb +1 -0
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +2 -0
- data/lib/aidp/harness/ui/progress_display.rb +8 -12
- data/lib/aidp/harness/ui/question_collector.rb +2 -0
- data/lib/aidp/harness/ui/spinner_group.rb +2 -0
- data/lib/aidp/harness/ui/spinner_helper.rb +1 -1
- data/lib/aidp/harness/ui/status_manager.rb +4 -2
- data/lib/aidp/harness/ui/status_widget.rb +3 -1
- data/lib/aidp/harness/ui/workflow_controller.rb +2 -0
- data/lib/aidp/harness/user_interface.rb +12 -17
- data/lib/aidp/jobs/background_runner.rb +278 -0
- data/lib/aidp/message_display.rb +48 -0
- data/lib/aidp/provider_manager.rb +3 -1
- data/lib/aidp/providers/anthropic.rb +100 -17
- data/lib/aidp/providers/base.rb +42 -11
- data/lib/aidp/providers/codex.rb +248 -0
- data/lib/aidp/providers/cursor.rb +35 -42
- data/lib/aidp/providers/gemini.rb +25 -15
- data/lib/aidp/providers/github_copilot.rb +41 -42
- data/lib/aidp/providers/opencode.rb +34 -41
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/workflows/definitions.rb +357 -0
- data/lib/aidp/workflows/selector.rb +171 -0
- data/lib/aidp.rb +12 -0
- data/templates/planning/generate_llm_style_guide.md +119 -0
- metadata +38 -26
- /data/templates/{ANALYZE/02_ARCHITECTURE_ANALYSIS.md → analysis/analyze_architecture.md} +0 -0
- /data/templates/{ANALYZE/05_DOCUMENTATION_ANALYSIS.md → analysis/analyze_documentation.md} +0 -0
- /data/templates/{ANALYZE/04_FUNCTIONALITY_ANALYSIS.md → analysis/analyze_functionality.md} +0 -0
- /data/templates/{ANALYZE/01_REPOSITORY_ANALYSIS.md → analysis/analyze_repository.md} +0 -0
- /data/templates/{ANALYZE/06_STATIC_ANALYSIS.md → analysis/analyze_static_code.md} +0 -0
- /data/templates/{ANALYZE/03_TEST_ANALYSIS.md → analysis/analyze_tests.md} +0 -0
- /data/templates/{ANALYZE/07_REFACTORING_RECOMMENDATIONS.md → analysis/recommend_refactoring.md} +0 -0
- /data/templates/{ANALYZE/06a_tree_sitter_scan.md → analysis/scan_with_tree_sitter.md} +0 -0
- /data/templates/{EXECUTE/11_STATIC_ANALYSIS.md → implementation/configure_static_analysis.md} +0 -0
- /data/templates/{EXECUTE/14_DOCS_PORTAL.md → implementation/create_documentation_portal.md} +0 -0
- /data/templates/{EXECUTE/10_IMPLEMENTATION_AGENT.md → implementation/implement_features.md} +0 -0
- /data/templates/{EXECUTE/13_DELIVERY_ROLLOUT.md → implementation/plan_delivery.md} +0 -0
- /data/templates/{EXECUTE/15_POST_RELEASE.md → implementation/review_post_release.md} +0 -0
- /data/templates/{EXECUTE/09_SCAFFOLDING_DEVEX.md → implementation/setup_scaffolding.md} +0 -0
- /data/templates/{EXECUTE/02A_ARCH_GATE_QUESTIONS.md → planning/ask_architecture_questions.md} +0 -0
- /data/templates/{EXECUTE/00_PRD.md → planning/create_prd.md} +0 -0
- /data/templates/{EXECUTE/08_TASKS.md → planning/create_tasks.md} +0 -0
- /data/templates/{EXECUTE/04_DOMAIN_DECOMPOSITION.md → planning/decompose_domain.md} +0 -0
- /data/templates/{EXECUTE/01_NFRS.md → planning/define_nfrs.md} +0 -0
- /data/templates/{EXECUTE/05_CONTRACTS.md → planning/design_apis.md} +0 -0
- /data/templates/{EXECUTE/02_ARCHITECTURE.md → planning/design_architecture.md} +0 -0
- /data/templates/{EXECUTE/06_THREAT_MODEL.md → planning/design_data_model.md} +0 -0
- /data/templates/{EXECUTE/03_ADR_FACTORY.md → planning/generate_adrs.md} +0 -0
- /data/templates/{EXECUTE/12_OBSERVABILITY_SLOS.md → planning/plan_observability.md} +0 -0
- /data/templates/{EXECUTE/07_TEST_PLAN.md → planning/plan_testing.md} +0 -0
data/lib/aidp/cli.rb
CHANGED
@@ -12,6 +12,8 @@ require_relative "cli/first_run_wizard"
|
|
12
12
|
module Aidp
|
13
13
|
# CLI interface for AIDP
|
14
14
|
class CLI
|
15
|
+
include Aidp::MessageDisplay
|
16
|
+
|
15
17
|
# Simple options holder for instance methods (used in specs)
|
16
18
|
attr_accessor :options
|
17
19
|
|
@@ -20,21 +22,6 @@ module Aidp
|
|
20
22
|
@prompt = prompt
|
21
23
|
end
|
22
24
|
|
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
|
-
|
38
25
|
# Instance version of harness status (used by specs; non-interactive)
|
39
26
|
def harness_status
|
40
27
|
modes = %i[analyze execute]
|
@@ -68,9 +55,9 @@ module Aidp
|
|
68
55
|
status = if options[:expect_error] == true
|
69
56
|
"error"
|
70
57
|
elsif step.nil?
|
71
|
-
"success"
|
58
|
+
"success" # Initial call without step
|
72
59
|
else
|
73
|
-
"completed"
|
60
|
+
"completed" # Subsequent calls with specific step
|
74
61
|
end
|
75
62
|
|
76
63
|
{
|
@@ -154,20 +141,7 @@ module Aidp
|
|
154
141
|
end
|
155
142
|
|
156
143
|
class << self
|
157
|
-
|
158
|
-
def display_message(message, type: :info)
|
159
|
-
prompt = TTY::Prompt.new
|
160
|
-
color = case type
|
161
|
-
when :error then :red
|
162
|
-
when :success then :green
|
163
|
-
when :warning then :yellow
|
164
|
-
when :info then :blue
|
165
|
-
when :highlight then :cyan
|
166
|
-
when :muted then :bright_black
|
167
|
-
else :white
|
168
|
-
end
|
169
|
-
prompt.say(message, color: color)
|
170
|
-
end
|
144
|
+
extend Aidp::MessageDisplay::ClassMethods
|
171
145
|
|
172
146
|
def run(args = ARGV)
|
173
147
|
# Handle subcommands first (status, jobs, kb, harness)
|
@@ -251,15 +225,58 @@ module Aidp
|
|
251
225
|
options = {}
|
252
226
|
|
253
227
|
parser = OptionParser.new do |opts|
|
254
|
-
opts.banner = "Usage: aidp [options]"
|
228
|
+
opts.banner = "Usage: aidp [COMMAND] [options]"
|
229
|
+
opts.separator ""
|
230
|
+
opts.separator "AI Development Pipeline - Autonomous development workflow automation"
|
255
231
|
opts.separator ""
|
256
|
-
opts.separator "
|
232
|
+
opts.separator "Commands:"
|
233
|
+
opts.separator " analyze [--background] Start analyze mode workflow"
|
234
|
+
opts.separator " execute [--background] Start execute mode workflow"
|
235
|
+
opts.separator " status Show current system status"
|
236
|
+
opts.separator " jobs Manage background jobs"
|
237
|
+
opts.separator " list - List all jobs"
|
238
|
+
opts.separator " status <id> [--follow] - Show job status"
|
239
|
+
opts.separator " logs <id> [--tail] - Show job logs"
|
240
|
+
opts.separator " stop <id> - Stop a running job"
|
241
|
+
opts.separator " checkpoint View progress checkpoints and metrics"
|
242
|
+
opts.separator " show - Show latest checkpoint"
|
243
|
+
opts.separator " summary [--watch] - Show progress summary with trends"
|
244
|
+
opts.separator " history [N] - Show last N checkpoints"
|
245
|
+
opts.separator " metrics - Show detailed metrics"
|
246
|
+
opts.separator " clear [--force] - Clear checkpoint data"
|
247
|
+
opts.separator " providers Show provider health dashboard"
|
248
|
+
opts.separator " harness Manage harness state"
|
249
|
+
opts.separator " status - Show harness status"
|
250
|
+
opts.separator " reset - Reset harness state"
|
251
|
+
opts.separator " kb Knowledge base commands"
|
252
|
+
opts.separator " show <topic> - Show knowledge base topic"
|
257
253
|
opts.separator ""
|
258
254
|
opts.separator "Options:"
|
259
255
|
|
260
256
|
opts.on("-h", "--help", "Show this help message") { options[:help] = true }
|
261
257
|
opts.on("-v", "--version", "Show version information") { options[:version] = true }
|
262
|
-
opts.on("--setup-config", "Setup or reconfigure config file
|
258
|
+
opts.on("--setup-config", "Setup or reconfigure config file") { options[:setup_config] = true }
|
259
|
+
|
260
|
+
opts.separator ""
|
261
|
+
opts.separator "Examples:"
|
262
|
+
opts.separator " # Start background execution"
|
263
|
+
opts.separator " aidp execute --background"
|
264
|
+
opts.separator " aidp execute --background --follow # Start and follow logs"
|
265
|
+
opts.separator ""
|
266
|
+
opts.separator " # Monitor background jobs"
|
267
|
+
opts.separator " aidp jobs list # List all jobs"
|
268
|
+
opts.separator " aidp jobs status <job_id> # Show job status"
|
269
|
+
opts.separator " aidp jobs logs <job_id> --tail # Tail job logs"
|
270
|
+
opts.separator ""
|
271
|
+
opts.separator " # Watch progress in real-time"
|
272
|
+
opts.separator " aidp checkpoint summary --watch # Auto-refresh every 5s"
|
273
|
+
opts.separator " aidp checkpoint summary --watch --interval 10"
|
274
|
+
opts.separator ""
|
275
|
+
opts.separator " # Other commands"
|
276
|
+
opts.separator " aidp providers # Check provider health"
|
277
|
+
opts.separator " aidp checkpoint history 20 # Show last 20 checkpoints"
|
278
|
+
opts.separator ""
|
279
|
+
opts.separator "For more information, visit: https://github.com/viamin/aidp"
|
263
280
|
end
|
264
281
|
|
265
282
|
parser.parse!(args)
|
@@ -270,18 +287,20 @@ module Aidp
|
|
270
287
|
# Determine if the invocation is a subcommand style call
|
271
288
|
def subcommand?(args)
|
272
289
|
return false if args.nil? || args.empty?
|
273
|
-
%w[status jobs kb harness execute analyze].include?(args.first)
|
290
|
+
%w[status jobs kb harness execute analyze providers checkpoint].include?(args.first)
|
274
291
|
end
|
275
292
|
|
276
293
|
def run_subcommand(args)
|
277
294
|
cmd = args.shift
|
278
295
|
case cmd
|
279
296
|
when "status" then run_status_command
|
280
|
-
when "jobs" then run_jobs_command
|
297
|
+
when "jobs" then run_jobs_command(args)
|
281
298
|
when "kb" then run_kb_command(args)
|
282
299
|
when "harness" then run_harness_command(args)
|
283
300
|
when "execute" then run_execute_command(args)
|
284
301
|
when "analyze" then run_execute_command(args, mode: :analyze) # symmetry
|
302
|
+
when "providers" then run_providers_command(args)
|
303
|
+
when "checkpoint" then run_checkpoint_command(args)
|
285
304
|
else
|
286
305
|
display_message("Unknown command: #{cmd}", type: :info)
|
287
306
|
return 1
|
@@ -298,10 +317,11 @@ module Aidp
|
|
298
317
|
display_message("Use 'aidp analyze' or 'aidp execute' to start a workflow", type: :info)
|
299
318
|
end
|
300
319
|
|
301
|
-
def run_jobs_command
|
320
|
+
def run_jobs_command(args = [])
|
302
321
|
require_relative "cli/jobs_command"
|
303
322
|
jobs_cmd = Aidp::CLI::JobsCommand.new(prompt: TTY::Prompt.new)
|
304
|
-
|
323
|
+
subcommand = args.shift
|
324
|
+
jobs_cmd.run(subcommand, args)
|
305
325
|
end
|
306
326
|
|
307
327
|
def run_kb_command(args)
|
@@ -336,6 +356,8 @@ module Aidp
|
|
336
356
|
approve_step = nil
|
337
357
|
reset = false
|
338
358
|
no_harness = false
|
359
|
+
background = false
|
360
|
+
follow = false
|
339
361
|
|
340
362
|
until flags.empty?
|
341
363
|
token = flags.shift
|
@@ -343,6 +365,8 @@ module Aidp
|
|
343
365
|
when "--no-harness" then no_harness = true
|
344
366
|
when "--reset" then reset = true
|
345
367
|
when "--approve" then approve_step = flags.shift
|
368
|
+
when "--background" then background = true
|
369
|
+
when "--follow" then follow = true
|
346
370
|
else
|
347
371
|
step ||= token unless token.start_with?("--")
|
348
372
|
end
|
@@ -361,6 +385,35 @@ module Aidp
|
|
361
385
|
display_message("Use 'aidp #{mode}' without arguments", type: :info)
|
362
386
|
return
|
363
387
|
end
|
388
|
+
|
389
|
+
# Handle background execution
|
390
|
+
if background
|
391
|
+
require_relative "jobs/background_runner"
|
392
|
+
runner = Aidp::Jobs::BackgroundRunner.new(Dir.pwd)
|
393
|
+
|
394
|
+
display_message("Starting #{mode} mode in background...", type: :info)
|
395
|
+
job_id = runner.start(mode, {})
|
396
|
+
|
397
|
+
display_message("✓ Started background job: #{job_id}", type: :success)
|
398
|
+
display_message("", type: :info)
|
399
|
+
display_message("Monitor progress:", type: :info)
|
400
|
+
display_message(" aidp jobs status #{job_id}", type: :info)
|
401
|
+
display_message(" aidp jobs logs #{job_id} --tail", type: :info)
|
402
|
+
display_message(" aidp checkpoint summary", type: :info)
|
403
|
+
display_message("", type: :info)
|
404
|
+
display_message("Stop the job:", type: :info)
|
405
|
+
display_message(" aidp jobs stop #{job_id}", type: :info)
|
406
|
+
|
407
|
+
if follow
|
408
|
+
display_message("", type: :info)
|
409
|
+
display_message("Following logs (Ctrl+C to stop following)...", type: :info)
|
410
|
+
sleep 1 # Give daemon time to start writing logs
|
411
|
+
runner.follow_job_logs(job_id)
|
412
|
+
end
|
413
|
+
|
414
|
+
return
|
415
|
+
end
|
416
|
+
|
364
417
|
if step
|
365
418
|
display_message("Running #{mode} step '#{step}' with enhanced TUI harness", type: :highlight)
|
366
419
|
display_message("progress indicators", type: :info)
|
@@ -386,6 +439,227 @@ module Aidp
|
|
386
439
|
display_message("workflow selection options", type: :info)
|
387
440
|
end
|
388
441
|
|
442
|
+
def run_checkpoint_command(args)
|
443
|
+
require_relative "execute/checkpoint"
|
444
|
+
require_relative "execute/checkpoint_display"
|
445
|
+
|
446
|
+
sub = args.shift || "summary"
|
447
|
+
checkpoint = Aidp::Execute::Checkpoint.new(Dir.pwd)
|
448
|
+
display = Aidp::Execute::CheckpointDisplay.new
|
449
|
+
|
450
|
+
case sub
|
451
|
+
when "show"
|
452
|
+
latest = checkpoint.latest_checkpoint
|
453
|
+
if latest
|
454
|
+
display.display_checkpoint(latest, show_details: true)
|
455
|
+
else
|
456
|
+
display_message("No checkpoint data found.", type: :info)
|
457
|
+
end
|
458
|
+
|
459
|
+
when "summary"
|
460
|
+
watch = args.include?("--watch")
|
461
|
+
interval = extract_interval_option(args) || 5
|
462
|
+
|
463
|
+
if watch
|
464
|
+
watch_checkpoint_summary(checkpoint, display, interval)
|
465
|
+
else
|
466
|
+
summary = checkpoint.progress_summary
|
467
|
+
if summary
|
468
|
+
display.display_progress_summary(summary)
|
469
|
+
else
|
470
|
+
display_message("No checkpoint data found.", type: :info)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
when "history"
|
475
|
+
limit = args.shift || "10"
|
476
|
+
history = checkpoint.checkpoint_history(limit: limit.to_i)
|
477
|
+
if history.any?
|
478
|
+
display.display_checkpoint_history(history, limit: limit.to_i)
|
479
|
+
else
|
480
|
+
display_message("No checkpoint history found.", type: :info)
|
481
|
+
end
|
482
|
+
|
483
|
+
when "metrics"
|
484
|
+
latest = checkpoint.latest_checkpoint
|
485
|
+
unless latest
|
486
|
+
display_message("No checkpoint data found.", type: :info)
|
487
|
+
return
|
488
|
+
end
|
489
|
+
|
490
|
+
display_message("", type: :info)
|
491
|
+
display_message("📊 Detailed Metrics", type: :info)
|
492
|
+
display_message("=" * 60, type: :muted)
|
493
|
+
|
494
|
+
metrics = latest[:metrics]
|
495
|
+
display_message("Lines of Code: #{metrics[:lines_of_code]}", type: :info)
|
496
|
+
display_message("File Count: #{metrics[:file_count]}", type: :info)
|
497
|
+
display_message("Test Coverage: #{metrics[:test_coverage]}%", type: :info)
|
498
|
+
display_message("Code Quality: #{metrics[:code_quality]}%", type: :info)
|
499
|
+
display_message("PRD Task Progress: #{metrics[:prd_task_progress]}%", type: :info)
|
500
|
+
|
501
|
+
if metrics[:tests_passing]
|
502
|
+
status = metrics[:tests_passing] ? "✓ Passing" : "✗ Failing"
|
503
|
+
display_message("Tests: #{status}", type: :info)
|
504
|
+
end
|
505
|
+
|
506
|
+
if metrics[:linters_passing]
|
507
|
+
status = metrics[:linters_passing] ? "✓ Passing" : "✗ Failing"
|
508
|
+
display_message("Linters: #{status}", type: :info)
|
509
|
+
end
|
510
|
+
|
511
|
+
display_message("=" * 60, type: :muted)
|
512
|
+
display_message("", type: :info)
|
513
|
+
|
514
|
+
when "clear"
|
515
|
+
force = args.include?("--force")
|
516
|
+
unless force
|
517
|
+
prompt = TTY::Prompt.new
|
518
|
+
confirm = prompt.yes?("Are you sure you want to clear all checkpoint data?")
|
519
|
+
return unless confirm
|
520
|
+
end
|
521
|
+
|
522
|
+
checkpoint.clear
|
523
|
+
display_message("✓ Checkpoint data cleared.", type: :success)
|
524
|
+
|
525
|
+
else
|
526
|
+
display_message("Usage: aidp checkpoint <show|summary|history|metrics|clear>", type: :info)
|
527
|
+
display_message(" show - Show the latest checkpoint data", type: :info)
|
528
|
+
display_message(" summary [--watch] - Show progress summary with trends", type: :info)
|
529
|
+
display_message(" history [N] - Show last N checkpoints", type: :info)
|
530
|
+
display_message(" metrics - Show detailed metrics", type: :info)
|
531
|
+
display_message(" clear [--force] - Clear all checkpoint data", type: :info)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
def watch_checkpoint_summary(checkpoint, display, interval)
|
536
|
+
display_message("Watching checkpoint summary (refresh: #{interval}s, Ctrl+C to exit)...", type: :info)
|
537
|
+
display_message("", type: :info)
|
538
|
+
|
539
|
+
begin
|
540
|
+
loop do
|
541
|
+
# Clear screen
|
542
|
+
print "\e[2J\e[H"
|
543
|
+
|
544
|
+
summary = checkpoint.progress_summary
|
545
|
+
if summary
|
546
|
+
display.display_progress_summary(summary)
|
547
|
+
|
548
|
+
# Show last update time
|
549
|
+
if summary[:current] && summary[:current][:timestamp]
|
550
|
+
last_update = Time.parse(summary[:current][:timestamp])
|
551
|
+
age = Time.now - last_update
|
552
|
+
display_message("", type: :info)
|
553
|
+
display_message("Last update: #{format_time_ago_simple(age)} | Refreshing in #{interval}s...", type: :muted)
|
554
|
+
end
|
555
|
+
else
|
556
|
+
display_message("No checkpoint data found. Waiting for data...", type: :info)
|
557
|
+
end
|
558
|
+
|
559
|
+
sleep interval
|
560
|
+
end
|
561
|
+
rescue Interrupt
|
562
|
+
display_message("\nStopped watching checkpoint summary", type: :info)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
def extract_interval_option(args)
|
567
|
+
args.each_with_index do |arg, i|
|
568
|
+
if arg == "--interval" && args[i + 1]
|
569
|
+
return args[i + 1].to_i
|
570
|
+
elsif arg.start_with?("--interval=")
|
571
|
+
return arg.split("=")[1].to_i
|
572
|
+
end
|
573
|
+
end
|
574
|
+
nil
|
575
|
+
end
|
576
|
+
|
577
|
+
def format_time_ago_simple(seconds)
|
578
|
+
if seconds < 60
|
579
|
+
"#{seconds.to_i}s ago"
|
580
|
+
elsif seconds < 3600
|
581
|
+
"#{(seconds / 60).to_i}m ago"
|
582
|
+
else
|
583
|
+
"#{(seconds / 3600).to_i}h ago"
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
def run_providers_command(args)
|
588
|
+
# Accept flags directly on `aidp providers` now (health is implicit)
|
589
|
+
no_color = false
|
590
|
+
args.reject! do |a|
|
591
|
+
if a == "--no-color"
|
592
|
+
no_color = true
|
593
|
+
true
|
594
|
+
else
|
595
|
+
false
|
596
|
+
end
|
597
|
+
end
|
598
|
+
configuration = Aidp::Harness::Configuration.new(Dir.pwd)
|
599
|
+
pm = Aidp::Harness::ProviderManager.new(configuration, prompt: TTY::Prompt.new)
|
600
|
+
|
601
|
+
# Use TTY::Spinner for progress indication
|
602
|
+
require "tty-spinner"
|
603
|
+
start_time = Time.now
|
604
|
+
spinner = TTY::Spinner.new(":spinner Gathering provider health...", format: :dots)
|
605
|
+
spinner.auto_spin
|
606
|
+
|
607
|
+
begin
|
608
|
+
rows = pm.health_dashboard
|
609
|
+
ensure
|
610
|
+
spinner.stop
|
611
|
+
elapsed = (Time.now - start_time).round(2)
|
612
|
+
display_message("Provider Health Dashboard (#{elapsed}s)", type: :highlight)
|
613
|
+
end
|
614
|
+
require "tty-table"
|
615
|
+
color = ->(text, code) { "\e[#{code}m#{text}\e[0m" }
|
616
|
+
status_color = lambda do |status|
|
617
|
+
case status
|
618
|
+
when /healthy/ then 32
|
619
|
+
when /unhealthy_auth/ then 31
|
620
|
+
when /unhealthy/ then 33
|
621
|
+
when /circuit/ then 35
|
622
|
+
else 37
|
623
|
+
end
|
624
|
+
end
|
625
|
+
availability_color = ->(avail) { (avail == "yes") ? 32 : 31 }
|
626
|
+
rate_color = ->(rl) { rl.start_with?("yes") ? 33 : 36 }
|
627
|
+
circuit_color = lambda do |c|
|
628
|
+
c.start_with?("open") ? 31 : 32
|
629
|
+
end
|
630
|
+
table_rows = rows.map do |r|
|
631
|
+
last_used = r[:last_used] ? r[:last_used].strftime("%H:%M:%S") : "-"
|
632
|
+
cb = r[:circuit_breaker]
|
633
|
+
cb += " (#{r[:circuit_breaker_remaining]}s)" if r[:circuit_breaker_remaining]
|
634
|
+
rl = if r[:rate_limited]
|
635
|
+
r[:rate_limit_reset_in] ? "yes (#{r[:rate_limit_reset_in]}s)" : "yes"
|
636
|
+
else
|
637
|
+
"no"
|
638
|
+
end
|
639
|
+
tokens = (r[:total_tokens].to_i > 0) ? r[:total_tokens].to_s : "0"
|
640
|
+
reason = r[:unhealthy_reason] || "-"
|
641
|
+
if no_color || !$stdout.tty?
|
642
|
+
[r[:provider], r[:status], (r[:available] ? "yes" : "no"), cb, rl, tokens, last_used, reason]
|
643
|
+
else
|
644
|
+
[
|
645
|
+
color.call(r[:provider], "1;97"),
|
646
|
+
color.call(r[:status], status_color.call(r[:status])),
|
647
|
+
color.call(r[:available] ? "yes" : "no", availability_color.call(r[:available] ? "yes" : "no")),
|
648
|
+
color.call(cb, circuit_color.call(cb)),
|
649
|
+
color.call(rl, rate_color.call(rl)),
|
650
|
+
color.call(tokens, 37),
|
651
|
+
color.call(last_used, 90),
|
652
|
+
((reason == "-") ? reason : color.call(reason, 33))
|
653
|
+
]
|
654
|
+
end
|
655
|
+
end
|
656
|
+
header = ["Provider", "Status", "Avail", "Circuit", "RateLimited", "Tokens", "LastUsed", "Reason"]
|
657
|
+
table = TTY::Table.new header, table_rows
|
658
|
+
display_message(table.render(:basic), type: :info)
|
659
|
+
rescue => e
|
660
|
+
display_message("Failed to display provider health: #{e.message}", type: :error)
|
661
|
+
end
|
662
|
+
|
389
663
|
def extract_mode_option(args)
|
390
664
|
mode = nil
|
391
665
|
args.each do |arg|
|
data/lib/aidp/config.rb
CHANGED
@@ -165,14 +165,10 @@ module Aidp
|
|
165
165
|
}.freeze
|
166
166
|
|
167
167
|
def self.load(project_dir = Dir.pwd)
|
168
|
-
|
169
|
-
config_file = File.join(project_dir, "aidp.yml")
|
170
|
-
legacy_config_file = File.join(project_dir, ".aidp.yml")
|
168
|
+
config_file = File.join(project_dir, ".aidp", "aidp.yml")
|
171
169
|
|
172
170
|
if File.exist?(config_file)
|
173
171
|
load_yaml_config(config_file)
|
174
|
-
elsif File.exist?(legacy_config_file)
|
175
|
-
load_yaml_config(legacy_config_file)
|
176
172
|
else
|
177
173
|
{}
|
178
174
|
end
|
@@ -248,15 +244,16 @@ module Aidp
|
|
248
244
|
|
249
245
|
# Check if configuration file exists
|
250
246
|
def self.config_exists?(project_dir = Dir.pwd)
|
251
|
-
File.exist?(File.join(project_dir, "aidp.yml"))
|
252
|
-
File.exist?(File.join(project_dir, ".aidp.yml"))
|
247
|
+
File.exist?(File.join(project_dir, ".aidp", "aidp.yml"))
|
253
248
|
end
|
254
249
|
|
255
250
|
# Create example configuration file
|
256
251
|
def self.create_example_config(project_dir = Dir.pwd)
|
257
|
-
config_path = File.join(project_dir, "aidp.yml")
|
252
|
+
config_path = File.join(project_dir, ".aidp", "aidp.yml")
|
258
253
|
return false if File.exist?(config_path)
|
259
254
|
|
255
|
+
FileUtils.mkdir_p(File.dirname(config_path))
|
256
|
+
|
260
257
|
example_config = {
|
261
258
|
harness: {
|
262
259
|
max_retries: 2,
|
data/lib/aidp/debug_logger.rb
CHANGED
@@ -94,7 +94,7 @@ module Aidp
|
|
94
94
|
|
95
95
|
# Also output to console if debug is enabled
|
96
96
|
if ENV["DEBUG"] && ENV["DEBUG"].to_i > 0
|
97
|
-
puts "\e[36m#{banner}\e[0m"
|
97
|
+
puts "\e[36m#{banner}\e[0m" # Cyan color
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
@@ -127,11 +127,11 @@ module Aidp
|
|
127
127
|
when :error
|
128
128
|
warn message
|
129
129
|
when :warn
|
130
|
-
puts "\e[33m#{message}\e[0m"
|
130
|
+
puts "\e[33m#{message}\e[0m" # Yellow
|
131
131
|
when :info
|
132
|
-
puts "\e[36m#{message}\e[0m"
|
132
|
+
puts "\e[36m#{message}\e[0m" # Cyan
|
133
133
|
when :debug
|
134
|
-
puts "\e[90m#{message}\e[0m"
|
134
|
+
puts "\e[90m#{message}\e[0m" # Gray
|
135
135
|
else
|
136
136
|
puts message
|
137
137
|
end
|
data/lib/aidp/debug_mixin.rb
CHANGED
@@ -7,8 +7,8 @@ module Aidp
|
|
7
7
|
module DebugMixin
|
8
8
|
# Debug levels
|
9
9
|
DEBUG_OFF = 0
|
10
|
-
DEBUG_BASIC = 1
|
11
|
-
DEBUG_VERBOSE = 2
|
10
|
+
DEBUG_BASIC = 1 # Commands and stderr
|
11
|
+
DEBUG_VERBOSE = 2 # Everything including prompts and stdout
|
12
12
|
|
13
13
|
def self.included(base)
|
14
14
|
base.extend(ClassMethods)
|
@@ -145,7 +145,7 @@ module Aidp
|
|
145
145
|
end
|
146
146
|
|
147
147
|
# Execute command with debug logging
|
148
|
-
def debug_execute_command(cmd, args: [], input: nil, timeout: nil, **options)
|
148
|
+
def debug_execute_command(cmd, args: [], input: nil, timeout: nil, streaming: false, **options)
|
149
149
|
require "tty-command"
|
150
150
|
|
151
151
|
command_str = [cmd, *args].join(" ")
|
@@ -154,7 +154,14 @@ module Aidp
|
|
154
154
|
debug_log("🚀 Starting command execution: #{command_str}", level: :info)
|
155
155
|
|
156
156
|
begin
|
157
|
-
|
157
|
+
# Configure printer based on streaming mode
|
158
|
+
if streaming
|
159
|
+
# Use progress printer for real-time output
|
160
|
+
cmd_obj = TTY::Command.new(printer: :progress)
|
161
|
+
debug_log("📺 Streaming mode enabled - showing real-time output", level: :info)
|
162
|
+
else
|
163
|
+
cmd_obj = TTY::Command.new(printer: :null) # Disable TTY::Command's own output
|
164
|
+
end
|
158
165
|
|
159
166
|
# Prepare input
|
160
167
|
input_data = nil
|