aidp 0.25.0 ā 0.27.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 +45 -6
- data/lib/aidp/analyze/error_handler.rb +11 -0
- data/lib/aidp/cli/checkpoint_command.rb +198 -0
- data/lib/aidp/cli/config_command.rb +71 -0
- data/lib/aidp/cli/enhanced_input.rb +2 -0
- data/lib/aidp/cli/first_run_wizard.rb +8 -7
- data/lib/aidp/cli/harness_command.rb +102 -0
- data/lib/aidp/cli/jobs_command.rb +3 -3
- data/lib/aidp/cli/mcp_dashboard.rb +4 -3
- data/lib/aidp/cli/models_command.rb +662 -0
- data/lib/aidp/cli/providers_command.rb +223 -0
- data/lib/aidp/cli.rb +35 -456
- data/lib/aidp/daemon/runner.rb +2 -2
- data/lib/aidp/debug_mixin.rb +2 -9
- data/lib/aidp/execute/async_work_loop_runner.rb +2 -1
- data/lib/aidp/execute/checkpoint_display.rb +38 -37
- data/lib/aidp/execute/interactive_repl.rb +2 -1
- data/lib/aidp/execute/prompt_manager.rb +4 -4
- data/lib/aidp/execute/work_loop_runner.rb +253 -56
- data/lib/aidp/execute/workflow_selector.rb +2 -2
- data/lib/aidp/harness/config_loader.rb +20 -11
- data/lib/aidp/harness/config_manager.rb +5 -5
- data/lib/aidp/harness/config_schema.rb +30 -8
- data/lib/aidp/harness/configuration.rb +105 -4
- data/lib/aidp/harness/enhanced_runner.rb +24 -15
- data/lib/aidp/harness/error_handler.rb +26 -5
- data/lib/aidp/harness/filter_strategy.rb +45 -0
- data/lib/aidp/harness/generic_filter_strategy.rb +63 -0
- data/lib/aidp/harness/model_cache.rb +269 -0
- data/lib/aidp/harness/model_discovery_service.rb +259 -0
- data/lib/aidp/harness/model_registry.rb +201 -0
- data/lib/aidp/harness/output_filter.rb +136 -0
- data/lib/aidp/harness/provider_manager.rb +18 -3
- data/lib/aidp/harness/rspec_filter_strategy.rb +82 -0
- data/lib/aidp/harness/runner.rb +5 -0
- data/lib/aidp/harness/test_runner.rb +165 -27
- data/lib/aidp/harness/thinking_depth_manager.rb +223 -7
- data/lib/aidp/harness/ui/enhanced_tui.rb +4 -1
- data/lib/aidp/logger.rb +35 -5
- data/lib/aidp/providers/adapter.rb +2 -4
- data/lib/aidp/providers/anthropic.rb +141 -128
- data/lib/aidp/providers/base.rb +98 -2
- data/lib/aidp/providers/capability_registry.rb +0 -1
- data/lib/aidp/providers/codex.rb +49 -67
- data/lib/aidp/providers/cursor.rb +71 -59
- data/lib/aidp/providers/gemini.rb +44 -60
- data/lib/aidp/providers/github_copilot.rb +2 -66
- data/lib/aidp/providers/kilocode.rb +24 -80
- data/lib/aidp/providers/opencode.rb +24 -80
- data/lib/aidp/safe_directory.rb +10 -3
- data/lib/aidp/setup/wizard.rb +345 -8
- data/lib/aidp/storage/csv_storage.rb +9 -3
- data/lib/aidp/storage/file_manager.rb +8 -2
- data/lib/aidp/storage/json_storage.rb +9 -3
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/build_processor.rb +40 -1
- data/lib/aidp/watch/change_request_processor.rb +659 -0
- data/lib/aidp/watch/plan_generator.rb +93 -14
- data/lib/aidp/watch/plan_processor.rb +71 -8
- data/lib/aidp/watch/repository_client.rb +85 -20
- data/lib/aidp/watch/review_processor.rb +3 -3
- data/lib/aidp/watch/runner.rb +37 -0
- data/lib/aidp/watch/state_store.rb +46 -1
- data/lib/aidp/workflows/guided_agent.rb +3 -3
- data/lib/aidp/workstream_executor.rb +5 -2
- data/lib/aidp.rb +4 -0
- data/templates/aidp-development.yml.example +2 -2
- data/templates/aidp-production.yml.example +3 -3
- data/templates/aidp.yml.example +53 -0
- metadata +14 -1
data/lib/aidp/cli.rb
CHANGED
|
@@ -17,133 +17,10 @@ module Aidp
|
|
|
17
17
|
include Aidp::MessageDisplay
|
|
18
18
|
include Aidp::RescueLogging
|
|
19
19
|
|
|
20
|
-
# Simple options holder for instance methods (used in specs)
|
|
21
|
-
attr_accessor :options
|
|
22
|
-
|
|
23
20
|
def initialize(prompt: TTY::Prompt.new)
|
|
24
|
-
@options = {}
|
|
25
21
|
@prompt = prompt
|
|
26
22
|
end
|
|
27
23
|
|
|
28
|
-
# Instance version of harness status (used by specs; non-interactive)
|
|
29
|
-
def harness_status
|
|
30
|
-
modes = %i[analyze execute]
|
|
31
|
-
display_message("š§ Harness Status", type: :highlight)
|
|
32
|
-
modes.each do |mode|
|
|
33
|
-
status = fetch_harness_status(mode)
|
|
34
|
-
print_harness_mode_status(mode, status)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Instance version of harness reset (used by specs)
|
|
39
|
-
def harness_reset
|
|
40
|
-
# Use accessor so specs that stub #options work
|
|
41
|
-
mode = (options[:mode] || "analyze").to_s
|
|
42
|
-
unless %w[analyze execute].include?(mode)
|
|
43
|
-
display_message("ā Invalid mode. Use 'analyze' or 'execute'", type: :error)
|
|
44
|
-
return
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Build a runner to access state manager; keep light for spec
|
|
48
|
-
runner = Aidp::Harness::Runner.new(Dir.pwd, mode.to_sym, {})
|
|
49
|
-
state_manager = runner.instance_variable_get(:@state_manager)
|
|
50
|
-
state_manager.reset_all if state_manager.respond_to?(:reset_all)
|
|
51
|
-
display_message("ā
Reset harness state for #{mode} mode", type: :success)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Instance version of analyze command (used by specs)
|
|
55
|
-
def analyze(project_dir, step = nil, options = {})
|
|
56
|
-
# Simple implementation for spec compatibility
|
|
57
|
-
# Different statuses based on whether a step is provided
|
|
58
|
-
status = if options[:expect_error] == true
|
|
59
|
-
"error"
|
|
60
|
-
elsif step.nil?
|
|
61
|
-
"success" # Initial call without step
|
|
62
|
-
else
|
|
63
|
-
"completed" # Subsequent calls with specific step
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
status: status,
|
|
68
|
-
provider: "cursor",
|
|
69
|
-
message: step ? "Step executed successfully" : "Analysis completed",
|
|
70
|
-
output: "Analysis results",
|
|
71
|
-
next_step: step ? nil : "01_REPOSITORY_ANALYSIS"
|
|
72
|
-
}
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Instance version of execute command (used by specs)
|
|
76
|
-
def execute(project_dir, step = nil, options = {})
|
|
77
|
-
# Simple implementation for spec compatibility
|
|
78
|
-
# Some specs expect "success", others expect "completed" - check context
|
|
79
|
-
status = (options[:expect_error] == true) ? "error" : "success"
|
|
80
|
-
{
|
|
81
|
-
status: status,
|
|
82
|
-
provider: "cursor",
|
|
83
|
-
message: "Execution completed",
|
|
84
|
-
output: "Execution results",
|
|
85
|
-
next_step: step ? nil : "00_PRD"
|
|
86
|
-
}
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
# Format durations (duplicated logic kept simple for spec expectations)
|
|
92
|
-
def format_duration(seconds)
|
|
93
|
-
return "0s" if seconds.nil? || seconds <= 0
|
|
94
|
-
h = (seconds / 3600).to_i
|
|
95
|
-
m = ((seconds % 3600) / 60).to_i
|
|
96
|
-
s = (seconds % 60).to_i
|
|
97
|
-
parts = []
|
|
98
|
-
parts << "#{h}h" if h.positive?
|
|
99
|
-
parts << "#{m}m" if m.positive?
|
|
100
|
-
parts << "#{s}s" if s.positive? || parts.empty?
|
|
101
|
-
parts.join(" ")
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Instance variant of display_harness_result (specs call via send)
|
|
105
|
-
def display_harness_result(result)
|
|
106
|
-
case result[:status]
|
|
107
|
-
when "completed"
|
|
108
|
-
display_message("\nā
Harness completed successfully!", type: :success)
|
|
109
|
-
display_message(" All steps finished automatically", type: :success)
|
|
110
|
-
when "stopped"
|
|
111
|
-
display_message("\nā¹ļø Harness stopped by user", type: :info)
|
|
112
|
-
display_message(" Execution terminated manually", type: :info)
|
|
113
|
-
when "error"
|
|
114
|
-
# Harness already outputs its own error message
|
|
115
|
-
# Intentionally no output here to satisfy spec expecting empty string
|
|
116
|
-
nil
|
|
117
|
-
else
|
|
118
|
-
display_message("\nš Harness finished", type: :success)
|
|
119
|
-
display_message(" Status: #{result[:status]}", type: :info)
|
|
120
|
-
display_message(" Message: #{result[:message]}", type: :info) if result[:message]
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def fetch_harness_status(mode)
|
|
125
|
-
runner = Aidp::Harness::Runner.new(Dir.pwd, mode, {})
|
|
126
|
-
if runner.respond_to?(:detailed_status)
|
|
127
|
-
runner.detailed_status
|
|
128
|
-
else
|
|
129
|
-
{harness: {state: "unknown"}}
|
|
130
|
-
end
|
|
131
|
-
rescue => e
|
|
132
|
-
log_rescue(e, component: "cli", action: "fetch_harness_status", fallback: {harness: {state: "error"}}, mode: mode)
|
|
133
|
-
{harness: {state: "error", error: e.message}}
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def print_harness_mode_status(mode, status)
|
|
137
|
-
harness = status[:harness] || {}
|
|
138
|
-
display_message("\nš #{mode.to_s.capitalize} Mode:", type: :info)
|
|
139
|
-
display_message(" State: #{harness[:state]}", type: :info)
|
|
140
|
-
if harness[:progress]
|
|
141
|
-
prog = harness[:progress]
|
|
142
|
-
display_message(" Progress: #{prog[:completed_steps]}/#{prog[:total_steps]}", type: :success)
|
|
143
|
-
display_message(" Current Step: #{harness[:current_step]}", type: :info) if harness[:current_step]
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
24
|
class << self
|
|
148
25
|
extend Aidp::MessageDisplay::ClassMethods
|
|
149
26
|
extend Aidp::RescueLogging
|
|
@@ -381,7 +258,7 @@ module Aidp
|
|
|
381
258
|
# Determine if the invocation is a subcommand style call
|
|
382
259
|
def subcommand?(args)
|
|
383
260
|
return false if args.nil? || args.empty?
|
|
384
|
-
%w[status jobs kb harness providers checkpoint mcp issue config init watch ws work skill settings].include?(args.first)
|
|
261
|
+
%w[status jobs kb harness providers checkpoint mcp issue config init watch ws work skill settings models].include?(args.first)
|
|
385
262
|
end
|
|
386
263
|
|
|
387
264
|
def run_subcommand(args)
|
|
@@ -403,6 +280,7 @@ module Aidp
|
|
|
403
280
|
when "work" then run_work_command(args)
|
|
404
281
|
when "skill" then run_skill_command(args)
|
|
405
282
|
when "settings" then run_settings_command(args)
|
|
283
|
+
when "models" then run_models_command(args)
|
|
406
284
|
else
|
|
407
285
|
display_message("Unknown command: #{cmd}", type: :info)
|
|
408
286
|
return 1
|
|
@@ -439,17 +317,21 @@ module Aidp
|
|
|
439
317
|
|
|
440
318
|
def run_harness_command(args)
|
|
441
319
|
sub = args.shift
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
mode
|
|
449
|
-
|
|
320
|
+
|
|
321
|
+
# Delegate to HarnessCommand
|
|
322
|
+
require_relative "cli/harness_command"
|
|
323
|
+
|
|
324
|
+
options = {}
|
|
325
|
+
if args.include?("--mode")
|
|
326
|
+
args.delete("--mode")
|
|
327
|
+
options[:mode] = args.shift
|
|
450
328
|
else
|
|
451
|
-
|
|
329
|
+
mode = extract_mode_option(args)
|
|
330
|
+
options[:mode] = mode if mode
|
|
452
331
|
end
|
|
332
|
+
|
|
333
|
+
command = HarnessCommand.new(prompt: create_prompt)
|
|
334
|
+
command.run(args, subcommand: sub, options: options)
|
|
453
335
|
end
|
|
454
336
|
|
|
455
337
|
def run_execute_command(args, mode: :execute)
|
|
@@ -535,138 +417,10 @@ module Aidp
|
|
|
535
417
|
end
|
|
536
418
|
|
|
537
419
|
def run_checkpoint_command(args)
|
|
538
|
-
|
|
539
|
-
require_relative "
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
checkpoint = Aidp::Execute::Checkpoint.new(Dir.pwd)
|
|
543
|
-
display = Aidp::Execute::CheckpointDisplay.new
|
|
544
|
-
|
|
545
|
-
case sub
|
|
546
|
-
when "show"
|
|
547
|
-
latest = checkpoint.latest_checkpoint
|
|
548
|
-
if latest
|
|
549
|
-
display.display_checkpoint(latest, show_details: true)
|
|
550
|
-
else
|
|
551
|
-
display_message("No checkpoint data found.", type: :info)
|
|
552
|
-
end
|
|
553
|
-
|
|
554
|
-
when "summary"
|
|
555
|
-
watch = args.include?("--watch")
|
|
556
|
-
interval = extract_interval_option(args) || 5
|
|
557
|
-
|
|
558
|
-
if watch
|
|
559
|
-
watch_checkpoint_summary(checkpoint, display, interval)
|
|
560
|
-
else
|
|
561
|
-
summary = checkpoint.progress_summary
|
|
562
|
-
if summary
|
|
563
|
-
display.display_progress_summary(summary)
|
|
564
|
-
else
|
|
565
|
-
display_message("No checkpoint data found.", type: :info)
|
|
566
|
-
end
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
when "history"
|
|
570
|
-
limit = args.shift || "10"
|
|
571
|
-
history = checkpoint.checkpoint_history(limit: limit.to_i)
|
|
572
|
-
if history.any?
|
|
573
|
-
display.display_checkpoint_history(history, limit: limit.to_i)
|
|
574
|
-
else
|
|
575
|
-
display_message("No checkpoint history found.", type: :info)
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
when "metrics"
|
|
579
|
-
latest = checkpoint.latest_checkpoint
|
|
580
|
-
unless latest
|
|
581
|
-
display_message("No checkpoint data found.", type: :info)
|
|
582
|
-
return
|
|
583
|
-
end
|
|
584
|
-
|
|
585
|
-
display_message("", type: :info)
|
|
586
|
-
display_message("š Detailed Metrics", type: :info)
|
|
587
|
-
display_message("=" * 60, type: :muted)
|
|
588
|
-
|
|
589
|
-
metrics = latest[:metrics]
|
|
590
|
-
display_message("Lines of Code: #{metrics[:lines_of_code]}", type: :info)
|
|
591
|
-
display_message("File Count: #{metrics[:file_count]}", type: :info)
|
|
592
|
-
display_message("Test Coverage: #{metrics[:test_coverage]}%", type: :info)
|
|
593
|
-
display_message("Code Quality: #{metrics[:code_quality]}%", type: :info)
|
|
594
|
-
display_message("PRD Task Progress: #{metrics[:prd_task_progress]}%", type: :info)
|
|
595
|
-
|
|
596
|
-
if metrics[:tests_passing]
|
|
597
|
-
status = metrics[:tests_passing] ? "ā Passing" : "ā Failing"
|
|
598
|
-
display_message("Tests: #{status}", type: :info)
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
if metrics[:linters_passing]
|
|
602
|
-
status = metrics[:linters_passing] ? "ā Passing" : "ā Failing"
|
|
603
|
-
display_message("Linters: #{status}", type: :info)
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
display_message("=" * 60, type: :muted)
|
|
607
|
-
display_message("", type: :info)
|
|
608
|
-
|
|
609
|
-
when "clear"
|
|
610
|
-
force = args.include?("--force")
|
|
611
|
-
unless force
|
|
612
|
-
prompt = create_prompt
|
|
613
|
-
confirm = prompt.yes?("Are you sure you want to clear all checkpoint data?")
|
|
614
|
-
return unless confirm
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
checkpoint.clear
|
|
618
|
-
display_message("ā Checkpoint data cleared.", type: :success)
|
|
619
|
-
|
|
620
|
-
else
|
|
621
|
-
display_message("Usage: aidp checkpoint <show|summary|history|metrics|clear>", type: :info)
|
|
622
|
-
display_message(" show - Show the latest checkpoint data", type: :info)
|
|
623
|
-
display_message(" summary [--watch] - Show progress summary with trends", type: :info)
|
|
624
|
-
display_message(" history [N] - Show last N checkpoints", type: :info)
|
|
625
|
-
display_message(" metrics - Show detailed metrics", type: :info)
|
|
626
|
-
display_message(" clear [--force] - Clear all checkpoint data", type: :info)
|
|
627
|
-
end
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
def watch_checkpoint_summary(checkpoint, display, interval)
|
|
631
|
-
display_message("Watching checkpoint summary (refresh: #{interval}s, Ctrl+C to exit)...", type: :info)
|
|
632
|
-
display_message("", type: :info)
|
|
633
|
-
|
|
634
|
-
begin
|
|
635
|
-
loop do
|
|
636
|
-
# Clear screen
|
|
637
|
-
print "\e[2J\e[H"
|
|
638
|
-
|
|
639
|
-
summary = checkpoint.progress_summary
|
|
640
|
-
if summary
|
|
641
|
-
display.display_progress_summary(summary)
|
|
642
|
-
|
|
643
|
-
# Show last update time
|
|
644
|
-
if summary[:current] && summary[:current][:timestamp]
|
|
645
|
-
last_update = Time.parse(summary[:current][:timestamp])
|
|
646
|
-
age = Time.now - last_update
|
|
647
|
-
display_message("", type: :info)
|
|
648
|
-
display_message("Last update: #{format_time_ago_simple(age)} | Refreshing in #{interval}s...", type: :muted)
|
|
649
|
-
end
|
|
650
|
-
else
|
|
651
|
-
display_message("No checkpoint data found. Waiting for data...", type: :info)
|
|
652
|
-
end
|
|
653
|
-
|
|
654
|
-
sleep interval
|
|
655
|
-
end
|
|
656
|
-
rescue Interrupt
|
|
657
|
-
display_message("\nStopped watching checkpoint summary", type: :info)
|
|
658
|
-
end
|
|
659
|
-
end
|
|
660
|
-
|
|
661
|
-
def extract_interval_option(args)
|
|
662
|
-
args.each_with_index do |arg, i|
|
|
663
|
-
if arg == "--interval" && args[i + 1]
|
|
664
|
-
return args[i + 1].to_i
|
|
665
|
-
elsif arg.start_with?("--interval=")
|
|
666
|
-
return arg.split("=")[1].to_i
|
|
667
|
-
end
|
|
668
|
-
end
|
|
669
|
-
nil
|
|
420
|
+
# Delegate to CheckpointCommand
|
|
421
|
+
require_relative "cli/checkpoint_command"
|
|
422
|
+
command = CheckpointCommand.new(prompt: create_prompt)
|
|
423
|
+
command.run(args)
|
|
670
424
|
end
|
|
671
425
|
|
|
672
426
|
def format_time_ago_simple(seconds)
|
|
@@ -685,11 +439,15 @@ module Aidp
|
|
|
685
439
|
case subcommand
|
|
686
440
|
when "info"
|
|
687
441
|
args.shift # Remove 'info'
|
|
688
|
-
|
|
442
|
+
require_relative "cli/providers_command"
|
|
443
|
+
command = ProvidersCommand.new(prompt: create_prompt)
|
|
444
|
+
command.run(args, subcommand: "info")
|
|
689
445
|
return
|
|
690
446
|
when "refresh"
|
|
691
447
|
args.shift # Remove 'refresh'
|
|
692
|
-
|
|
448
|
+
require_relative "cli/providers_command"
|
|
449
|
+
command = ProvidersCommand.new(prompt: create_prompt)
|
|
450
|
+
command.run(args, subcommand: "refresh")
|
|
693
451
|
return
|
|
694
452
|
end
|
|
695
453
|
|
|
@@ -774,164 +532,6 @@ module Aidp
|
|
|
774
532
|
display_message("Failed to display provider health: #{e.message}", type: :error)
|
|
775
533
|
end
|
|
776
534
|
|
|
777
|
-
def run_providers_info_command(args)
|
|
778
|
-
require_relative "harness/provider_info"
|
|
779
|
-
|
|
780
|
-
provider_name = args.shift
|
|
781
|
-
|
|
782
|
-
# If no provider specified, show models catalog table
|
|
783
|
-
unless provider_name
|
|
784
|
-
run_providers_models_catalog
|
|
785
|
-
return
|
|
786
|
-
end
|
|
787
|
-
|
|
788
|
-
force_refresh = args.include?("--refresh")
|
|
789
|
-
|
|
790
|
-
display_message("Provider Information: #{provider_name}", type: :highlight)
|
|
791
|
-
display_message("=" * 60, type: :muted)
|
|
792
|
-
|
|
793
|
-
provider_info = Aidp::Harness::ProviderInfo.new(provider_name, Dir.pwd)
|
|
794
|
-
info = provider_info.info(force_refresh: force_refresh)
|
|
795
|
-
|
|
796
|
-
if info.nil?
|
|
797
|
-
display_message("No information available for provider: #{provider_name}", type: :error)
|
|
798
|
-
return
|
|
799
|
-
end
|
|
800
|
-
|
|
801
|
-
# Display basic info
|
|
802
|
-
display_message("Last Checked: #{info[:last_checked]}", type: :info)
|
|
803
|
-
display_message("CLI Available: #{info[:cli_available] ? "Yes" : "No"}", type: info[:cli_available] ? :success : :error)
|
|
804
|
-
|
|
805
|
-
# Display authentication
|
|
806
|
-
if info[:auth_method]
|
|
807
|
-
display_message("\nAuthentication Method: #{info[:auth_method]}", type: :info)
|
|
808
|
-
end
|
|
809
|
-
|
|
810
|
-
# Display MCP support
|
|
811
|
-
display_message("\nMCP Support: #{info[:mcp_support] ? "Yes" : "No"}", type: info[:mcp_support] ? :success : :info)
|
|
812
|
-
|
|
813
|
-
# Display MCP servers if available
|
|
814
|
-
if info[:mcp_servers]&.any?
|
|
815
|
-
display_message("\nMCP Servers: (#{info[:mcp_servers].size} configured)", type: :highlight)
|
|
816
|
-
info[:mcp_servers].each do |server|
|
|
817
|
-
status_symbol = server[:enabled] ? "ā" : "ā"
|
|
818
|
-
display_message(" #{status_symbol} #{server[:name]} (#{server[:status]})", type: server[:enabled] ? :success : :muted)
|
|
819
|
-
display_message(" #{server[:description]}", type: :muted) if server[:description]
|
|
820
|
-
end
|
|
821
|
-
elsif info[:mcp_support]
|
|
822
|
-
display_message("\nMCP Servers: None configured", type: :muted)
|
|
823
|
-
end
|
|
824
|
-
|
|
825
|
-
# Display permission modes
|
|
826
|
-
if info[:permission_modes]&.any?
|
|
827
|
-
display_message("\nPermission Modes:", type: :highlight)
|
|
828
|
-
info[:permission_modes].each do |mode|
|
|
829
|
-
display_message(" - #{mode}", type: :info)
|
|
830
|
-
end
|
|
831
|
-
end
|
|
832
|
-
|
|
833
|
-
# Display capabilities
|
|
834
|
-
if info[:capabilities]&.any?
|
|
835
|
-
display_message("\nCapabilities:", type: :highlight)
|
|
836
|
-
info[:capabilities].each do |cap, value|
|
|
837
|
-
next unless value
|
|
838
|
-
|
|
839
|
-
display_message(" ā #{cap.to_s.split("_").map(&:capitalize).join(" ")}", type: :success)
|
|
840
|
-
end
|
|
841
|
-
end
|
|
842
|
-
|
|
843
|
-
# Display notable flags
|
|
844
|
-
if info[:flags]&.any?
|
|
845
|
-
display_message("\nNotable Flags: (#{info[:flags].size} total)", type: :highlight)
|
|
846
|
-
# Show first 10 flags
|
|
847
|
-
info[:flags].take(10).each do |name, flag_info|
|
|
848
|
-
display_message(" #{flag_info[:flag]}", type: :info)
|
|
849
|
-
display_message(" #{flag_info[:description][0..80]}...", type: :muted) if flag_info[:description]
|
|
850
|
-
end
|
|
851
|
-
|
|
852
|
-
if info[:flags].size > 10
|
|
853
|
-
display_message("\n ... and #{info[:flags].size - 10} more flags", type: :muted)
|
|
854
|
-
display_message(" Run '#{get_binary_name(provider_name)} --help' for full details", type: :muted)
|
|
855
|
-
end
|
|
856
|
-
end
|
|
857
|
-
|
|
858
|
-
display_message("\n" + "=" * 60, type: :muted)
|
|
859
|
-
display_message("Tip: Use --refresh to update this information", type: :muted)
|
|
860
|
-
end
|
|
861
|
-
|
|
862
|
-
def run_providers_models_catalog
|
|
863
|
-
require_relative "harness/capability_registry"
|
|
864
|
-
require "tty-table"
|
|
865
|
-
|
|
866
|
-
display_message("Models Catalog - Thinking Depth Tiers", type: :highlight)
|
|
867
|
-
display_message("=" * 80, type: :muted)
|
|
868
|
-
|
|
869
|
-
registry = Aidp::Harness::CapabilityRegistry.new
|
|
870
|
-
unless registry.load_catalog
|
|
871
|
-
display_message("No models catalog found. Create .aidp/models_catalog.yml first.", type: :error)
|
|
872
|
-
return
|
|
873
|
-
end
|
|
874
|
-
|
|
875
|
-
rows = []
|
|
876
|
-
registry.provider_names.sort.each do |provider|
|
|
877
|
-
models = registry.models_for_provider(provider)
|
|
878
|
-
models.each do |model_name, model_data|
|
|
879
|
-
tier = model_data["tier"] || "-"
|
|
880
|
-
context = model_data["context_window"] ? "#{model_data["context_window"] / 1000}k" : "-"
|
|
881
|
-
tools = model_data["supports_tools"] ? "yes" : "no"
|
|
882
|
-
cost_input = model_data["cost_per_mtok_input"]
|
|
883
|
-
cost = cost_input ? "$#{cost_input}/MTok" : "-"
|
|
884
|
-
|
|
885
|
-
rows << [provider, model_name, tier, context, tools, cost]
|
|
886
|
-
end
|
|
887
|
-
end
|
|
888
|
-
|
|
889
|
-
if rows.empty?
|
|
890
|
-
display_message("No models found in catalog", type: :info)
|
|
891
|
-
return
|
|
892
|
-
end
|
|
893
|
-
|
|
894
|
-
header = ["Provider", "Model", "Tier", "Context", "Tools", "Cost"]
|
|
895
|
-
table = TTY::Table.new(header, rows)
|
|
896
|
-
display_message(table.render(:basic), type: :info)
|
|
897
|
-
|
|
898
|
-
display_message("\n" + "=" * 80, type: :muted)
|
|
899
|
-
display_message("Use '/thinking show' in REPL to see current tier configuration", type: :muted)
|
|
900
|
-
end
|
|
901
|
-
|
|
902
|
-
def run_providers_refresh_command(args)
|
|
903
|
-
require_relative "harness/provider_info"
|
|
904
|
-
require "tty-spinner"
|
|
905
|
-
|
|
906
|
-
provider_name = args.shift
|
|
907
|
-
config_manager = Aidp::Harness::ConfigManager.new(Dir.pwd)
|
|
908
|
-
providers_to_refresh = if provider_name
|
|
909
|
-
[provider_name]
|
|
910
|
-
else
|
|
911
|
-
config_manager.provider_names
|
|
912
|
-
end
|
|
913
|
-
|
|
914
|
-
display_message("Refreshing provider information...", type: :info)
|
|
915
|
-
display_message("", type: :info)
|
|
916
|
-
|
|
917
|
-
providers_to_refresh.each do |prov|
|
|
918
|
-
spinner = TTY::Spinner.new("[:spinner] #{prov}...", format: :dots)
|
|
919
|
-
spinner.auto_spin
|
|
920
|
-
|
|
921
|
-
provider_info = Aidp::Harness::ProviderInfo.new(prov, Dir.pwd)
|
|
922
|
-
info = provider_info.gather_info
|
|
923
|
-
|
|
924
|
-
if info[:cli_available]
|
|
925
|
-
spinner.success("(available)")
|
|
926
|
-
else
|
|
927
|
-
spinner.error("(unavailable)")
|
|
928
|
-
end
|
|
929
|
-
end
|
|
930
|
-
|
|
931
|
-
display_message("\nā Provider information refreshed", type: :success)
|
|
932
|
-
display_message("Use 'aidp providers info <name>' to view details", type: :muted)
|
|
933
|
-
end
|
|
934
|
-
|
|
935
535
|
def run_mcp_command(args)
|
|
936
536
|
require_relative "cli/mcp_dashboard"
|
|
937
537
|
|
|
@@ -1021,6 +621,12 @@ module Aidp
|
|
|
1021
621
|
end
|
|
1022
622
|
end
|
|
1023
623
|
|
|
624
|
+
def run_models_command(args)
|
|
625
|
+
require_relative "cli/models_command"
|
|
626
|
+
models_cmd = Aidp::CLI::ModelsCommand.new(prompt: create_prompt)
|
|
627
|
+
models_cmd.run(args)
|
|
628
|
+
end
|
|
629
|
+
|
|
1024
630
|
def run_issue_command(args)
|
|
1025
631
|
require_relative "cli/issue_importer"
|
|
1026
632
|
|
|
@@ -1073,33 +679,10 @@ module Aidp
|
|
|
1073
679
|
end
|
|
1074
680
|
|
|
1075
681
|
def run_config_command(args)
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
token = args.shift
|
|
1081
|
-
case token
|
|
1082
|
-
when "--interactive"
|
|
1083
|
-
interactive = true
|
|
1084
|
-
when "--dry-run"
|
|
1085
|
-
dry_run = true
|
|
1086
|
-
when "-h", "--help"
|
|
1087
|
-
display_config_usage
|
|
1088
|
-
return
|
|
1089
|
-
else
|
|
1090
|
-
display_message("Unknown option: #{token}", type: :error)
|
|
1091
|
-
display_config_usage
|
|
1092
|
-
return
|
|
1093
|
-
end
|
|
1094
|
-
end
|
|
1095
|
-
|
|
1096
|
-
unless interactive
|
|
1097
|
-
display_config_usage
|
|
1098
|
-
return
|
|
1099
|
-
end
|
|
1100
|
-
|
|
1101
|
-
wizard = Aidp::Setup::Wizard.new(Dir.pwd, prompt: create_prompt, dry_run: dry_run)
|
|
1102
|
-
wizard.run
|
|
682
|
+
# Delegate to ConfigCommand
|
|
683
|
+
require_relative "cli/config_command"
|
|
684
|
+
command = ConfigCommand.new(prompt: create_prompt)
|
|
685
|
+
command.run(args)
|
|
1103
686
|
end
|
|
1104
687
|
|
|
1105
688
|
def run_devcontainer_command(args)
|
|
@@ -1856,10 +1439,6 @@ module Aidp
|
|
|
1856
1439
|
end
|
|
1857
1440
|
end
|
|
1858
1441
|
|
|
1859
|
-
def display_config_usage
|
|
1860
|
-
display_message("Usage: aidp config --interactive [--dry-run]", type: :info)
|
|
1861
|
-
end
|
|
1862
|
-
|
|
1863
1442
|
def run_settings_command(args)
|
|
1864
1443
|
require_relative "auto_update"
|
|
1865
1444
|
require "yaml"
|
data/lib/aidp/daemon/runner.rb
CHANGED
|
@@ -10,11 +10,11 @@ module Aidp
|
|
|
10
10
|
# Main daemon runner for background mode execution
|
|
11
11
|
# Manages work loops, watch mode, and IPC communication
|
|
12
12
|
class Runner
|
|
13
|
-
def initialize(project_dir, config, options = {})
|
|
13
|
+
def initialize(project_dir, config, options = {}, process_manager: nil)
|
|
14
14
|
@project_dir = project_dir
|
|
15
15
|
@config = config
|
|
16
16
|
@options = options
|
|
17
|
-
@process_manager = ProcessManager.new(project_dir)
|
|
17
|
+
@process_manager = process_manager || ProcessManager.new(project_dir)
|
|
18
18
|
@running = false
|
|
19
19
|
@work_loop_runner = nil
|
|
20
20
|
@watch_runner = nil
|
data/lib/aidp/debug_mixin.rb
CHANGED
|
@@ -130,7 +130,7 @@ module Aidp
|
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
# Execute command with debug logging
|
|
133
|
-
def debug_execute_command(cmd, args: [], input: nil, timeout: nil,
|
|
133
|
+
def debug_execute_command(cmd, args: [], input: nil, timeout: nil, **options)
|
|
134
134
|
require "tty-command"
|
|
135
135
|
|
|
136
136
|
command_str = [cmd, *args].join(" ")
|
|
@@ -139,14 +139,7 @@ module Aidp
|
|
|
139
139
|
debug_logger.info(component_name, "š Starting command execution: #{command_str}")
|
|
140
140
|
|
|
141
141
|
begin
|
|
142
|
-
|
|
143
|
-
if streaming
|
|
144
|
-
# Use progress printer for real-time output
|
|
145
|
-
cmd_obj = TTY::Command.new(printer: :progress)
|
|
146
|
-
debug_log("šŗ Streaming mode enabled - showing real-time output", level: :info)
|
|
147
|
-
else
|
|
148
|
-
cmd_obj = TTY::Command.new(printer: :null) # Disable TTY::Command's own output
|
|
149
|
-
end
|
|
142
|
+
cmd_obj = TTY::Command.new(printer: :null) # Disable TTY::Command's own output
|
|
150
143
|
|
|
151
144
|
# Prepare input
|
|
152
145
|
input_data = nil
|
|
@@ -27,6 +27,7 @@ module Aidp
|
|
|
27
27
|
@config = config
|
|
28
28
|
@options = options
|
|
29
29
|
@cancel_timeout = options[:cancel_timeout] || 5 # seconds to wait for graceful shutdown
|
|
30
|
+
@sync_runner_class = options[:sync_runner_class] || WorkLoopRunner
|
|
30
31
|
@state = WorkLoopState.new
|
|
31
32
|
@instruction_queue = InstructionQueue.new
|
|
32
33
|
@work_thread = nil
|
|
@@ -133,7 +134,7 @@ module Aidp
|
|
|
133
134
|
# Main async execution loop
|
|
134
135
|
def run_async_loop
|
|
135
136
|
# Create synchronous runner (runs in this thread)
|
|
136
|
-
@sync_runner =
|
|
137
|
+
@sync_runner = @sync_runner_class.new(
|
|
137
138
|
@project_dir,
|
|
138
139
|
@provider_manager,
|
|
139
140
|
@config,
|