aidp 0.27.0 ā 0.28.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 +89 -0
- data/lib/aidp/cli/models_command.rb +5 -6
- data/lib/aidp/cli.rb +10 -8
- data/lib/aidp/config.rb +54 -0
- data/lib/aidp/debug_mixin.rb +23 -1
- data/lib/aidp/execute/agent_signal_parser.rb +22 -0
- data/lib/aidp/execute/repl_macros.rb +2 -2
- data/lib/aidp/execute/steps.rb +94 -1
- data/lib/aidp/execute/work_loop_runner.rb +209 -17
- data/lib/aidp/execute/workflow_selector.rb +2 -25
- data/lib/aidp/firewall/provider_requirements_collector.rb +262 -0
- data/lib/aidp/harness/ai_decision_engine.rb +35 -2
- data/lib/aidp/harness/config_manager.rb +0 -5
- data/lib/aidp/harness/config_schema.rb +8 -0
- data/lib/aidp/harness/configuration.rb +27 -19
- data/lib/aidp/harness/enhanced_runner.rb +1 -4
- data/lib/aidp/harness/error_handler.rb +1 -72
- data/lib/aidp/harness/provider_factory.rb +11 -2
- data/lib/aidp/harness/state_manager.rb +0 -7
- data/lib/aidp/harness/thinking_depth_manager.rb +47 -68
- data/lib/aidp/harness/ui/enhanced_tui.rb +8 -18
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +0 -18
- data/lib/aidp/harness/ui/progress_display.rb +6 -2
- data/lib/aidp/harness/user_interface.rb +0 -58
- data/lib/aidp/init/runner.rb +7 -2
- data/lib/aidp/planning/analyzers/feedback_analyzer.rb +365 -0
- data/lib/aidp/planning/builders/agile_plan_builder.rb +387 -0
- data/lib/aidp/planning/builders/project_plan_builder.rb +193 -0
- data/lib/aidp/planning/generators/gantt_generator.rb +190 -0
- data/lib/aidp/planning/generators/iteration_plan_generator.rb +392 -0
- data/lib/aidp/planning/generators/legacy_research_planner.rb +473 -0
- data/lib/aidp/planning/generators/marketing_report_generator.rb +348 -0
- data/lib/aidp/planning/generators/mvp_scope_generator.rb +310 -0
- data/lib/aidp/planning/generators/user_test_plan_generator.rb +373 -0
- data/lib/aidp/planning/generators/wbs_generator.rb +259 -0
- data/lib/aidp/planning/mappers/persona_mapper.rb +163 -0
- data/lib/aidp/planning/parsers/document_parser.rb +141 -0
- data/lib/aidp/planning/parsers/feedback_data_parser.rb +252 -0
- data/lib/aidp/provider_manager.rb +8 -32
- data/lib/aidp/providers/aider.rb +264 -0
- data/lib/aidp/providers/anthropic.rb +74 -2
- data/lib/aidp/providers/base.rb +25 -1
- data/lib/aidp/providers/codex.rb +26 -3
- data/lib/aidp/providers/cursor.rb +16 -0
- data/lib/aidp/providers/gemini.rb +13 -0
- data/lib/aidp/providers/github_copilot.rb +17 -0
- data/lib/aidp/providers/kilocode.rb +11 -0
- data/lib/aidp/providers/opencode.rb +11 -0
- data/lib/aidp/setup/wizard.rb +249 -39
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/build_processor.rb +211 -30
- data/lib/aidp/watch/change_request_processor.rb +128 -14
- data/lib/aidp/watch/ci_fix_processor.rb +103 -37
- data/lib/aidp/watch/ci_log_extractor.rb +258 -0
- data/lib/aidp/watch/github_state_extractor.rb +177 -0
- data/lib/aidp/watch/implementation_verifier.rb +284 -0
- data/lib/aidp/watch/plan_generator.rb +7 -43
- data/lib/aidp/watch/plan_processor.rb +7 -6
- data/lib/aidp/watch/repository_client.rb +245 -17
- data/lib/aidp/watch/review_processor.rb +98 -17
- data/lib/aidp/watch/reviewers/base_reviewer.rb +1 -1
- data/lib/aidp/watch/runner.rb +181 -29
- data/lib/aidp/watch/state_store.rb +22 -1
- data/lib/aidp/workflows/definitions.rb +147 -0
- data/lib/aidp/workstream_cleanup.rb +245 -0
- data/lib/aidp/worktree.rb +19 -0
- data/templates/aidp.yml.example +57 -0
- data/templates/implementation/generate_tdd_specs.md +213 -0
- data/templates/implementation/iterative_implementation.md +122 -0
- data/templates/planning/agile/analyze_feedback.md +183 -0
- data/templates/planning/agile/generate_iteration_plan.md +179 -0
- data/templates/planning/agile/generate_legacy_research_plan.md +171 -0
- data/templates/planning/agile/generate_marketing_report.md +162 -0
- data/templates/planning/agile/generate_mvp_scope.md +127 -0
- data/templates/planning/agile/generate_user_test_plan.md +143 -0
- data/templates/planning/agile/ingest_feedback.md +174 -0
- data/templates/planning/assemble_project_plan.md +113 -0
- data/templates/planning/assign_personas.md +108 -0
- data/templates/planning/create_tasks.md +52 -6
- data/templates/planning/generate_gantt.md +86 -0
- data/templates/planning/generate_wbs.md +85 -0
- data/templates/planning/initialize_planning_mode.md +70 -0
- data/templates/skills/README.md +2 -2
- data/templates/skills/marketing_strategist/SKILL.md +279 -0
- data/templates/skills/product_manager/SKILL.md +177 -0
- data/templates/skills/ruby_aidp_planning/SKILL.md +497 -0
- data/templates/skills/ruby_rspec_tdd/SKILL.md +514 -0
- data/templates/skills/ux_researcher/SKILL.md +222 -0
- metadata +39 -1
|
@@ -166,6 +166,11 @@ module Aidp
|
|
|
166
166
|
work_loop_config[:max_iterations]
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
# Check if task completion is required for work loop completion
|
|
170
|
+
def task_completion_required?
|
|
171
|
+
work_loop_config.fetch(:task_completion_required, true)
|
|
172
|
+
end
|
|
173
|
+
|
|
169
174
|
# Get test commands
|
|
170
175
|
def test_commands
|
|
171
176
|
normalize_commands(work_loop_config[:test_commands] || [])
|
|
@@ -432,34 +437,37 @@ module Aidp
|
|
|
432
437
|
thinking_overrides[key] || thinking_overrides[key.to_sym]
|
|
433
438
|
end
|
|
434
439
|
|
|
435
|
-
# Get tiers configuration
|
|
436
|
-
|
|
437
|
-
|
|
440
|
+
# Get thinking tiers configuration for a specific provider
|
|
441
|
+
# @param provider_name [String] The provider name
|
|
442
|
+
# @return [Hash] The thinking tiers configuration for the provider
|
|
443
|
+
def provider_thinking_tiers(provider_name)
|
|
444
|
+
provider_cfg = provider_config(provider_name)
|
|
445
|
+
provider_cfg[:thinking_tiers] || provider_cfg["thinking_tiers"] || {}
|
|
438
446
|
end
|
|
439
447
|
|
|
440
|
-
# Get models configured for a specific tier
|
|
441
|
-
#
|
|
442
|
-
|
|
443
|
-
|
|
448
|
+
# Get models configured for a specific tier and provider
|
|
449
|
+
# @param tier [String, Symbol] The tier name (mini, standard, thinking, pro, max)
|
|
450
|
+
# @param provider_name [String] The provider name (required)
|
|
451
|
+
# @return [Array<String>] Array of model names for the tier
|
|
452
|
+
def models_for_tier(tier, provider_name)
|
|
453
|
+
return [] unless provider_name
|
|
454
|
+
|
|
455
|
+
tier_config = provider_thinking_tiers(provider_name)[tier] ||
|
|
456
|
+
provider_thinking_tiers(provider_name)[tier.to_sym]
|
|
444
457
|
return [] unless tier_config
|
|
445
458
|
|
|
446
459
|
models = tier_config[:models] || tier_config["models"]
|
|
447
460
|
return [] unless models
|
|
448
461
|
|
|
449
|
-
#
|
|
450
|
-
Array(models).map
|
|
451
|
-
if model_entry.is_a?(Hash)
|
|
452
|
-
{
|
|
453
|
-
provider: (model_entry[:provider] || model_entry["provider"]).to_s,
|
|
454
|
-
model: (model_entry[:model] || model_entry["model"]).to_s
|
|
455
|
-
}
|
|
456
|
-
end
|
|
457
|
-
end.compact
|
|
462
|
+
# Return simple array of model name strings
|
|
463
|
+
Array(models).map(&:to_s).compact
|
|
458
464
|
end
|
|
459
465
|
|
|
460
|
-
# Get all configured tiers
|
|
461
|
-
|
|
462
|
-
|
|
466
|
+
# Get all configured tiers for a provider
|
|
467
|
+
# @param provider_name [String] The provider name
|
|
468
|
+
# @return [Array<String>] Array of tier names
|
|
469
|
+
def configured_tiers(provider_name)
|
|
470
|
+
provider_thinking_tiers(provider_name).keys.map(&:to_s)
|
|
463
471
|
end
|
|
464
472
|
|
|
465
473
|
# Get fallback configuration
|
|
@@ -106,9 +106,6 @@ module Aidp
|
|
|
106
106
|
@tui.show_message("š Starting #{@mode.to_s.capitalize} Mode", :info)
|
|
107
107
|
|
|
108
108
|
begin
|
|
109
|
-
# Start TUI display loop
|
|
110
|
-
@tui.start_display_loop
|
|
111
|
-
|
|
112
109
|
# Load existing state if resuming
|
|
113
110
|
# Temporarily disabled to test
|
|
114
111
|
# load_state if @state_manager.has_state?
|
|
@@ -174,7 +171,7 @@ module Aidp
|
|
|
174
171
|
ensure
|
|
175
172
|
# Save state before exiting
|
|
176
173
|
save_state
|
|
177
|
-
@tui.
|
|
174
|
+
@tui.restore_screen
|
|
178
175
|
cleanup
|
|
179
176
|
end
|
|
180
177
|
|
|
@@ -81,7 +81,7 @@ module Aidp
|
|
|
81
81
|
error_type: error_info[:error_type],
|
|
82
82
|
reason: "Retry not applicable or exhausted"
|
|
83
83
|
})
|
|
84
|
-
if
|
|
84
|
+
if error_info[:error_type].to_sym == :auth_expired
|
|
85
85
|
# Mark provider unhealthy to avoid immediate re-selection
|
|
86
86
|
begin
|
|
87
87
|
if @provider_manager.respond_to?(:mark_provider_auth_failure)
|
|
@@ -399,43 +399,6 @@ module Aidp
|
|
|
399
399
|
jitter: false
|
|
400
400
|
},
|
|
401
401
|
|
|
402
|
-
# Legacy aliases for backward compatibility
|
|
403
|
-
network_error: {
|
|
404
|
-
name: "network_error",
|
|
405
|
-
enabled: true,
|
|
406
|
-
max_retries: 3,
|
|
407
|
-
backoff_strategy: :exponential,
|
|
408
|
-
base_delay: 1.0,
|
|
409
|
-
max_delay: 30.0,
|
|
410
|
-
jitter: true
|
|
411
|
-
},
|
|
412
|
-
server_error: {
|
|
413
|
-
name: "server_error",
|
|
414
|
-
enabled: true,
|
|
415
|
-
max_retries: 2,
|
|
416
|
-
backoff_strategy: :linear,
|
|
417
|
-
base_delay: 2.0,
|
|
418
|
-
max_delay: 10.0,
|
|
419
|
-
jitter: true
|
|
420
|
-
},
|
|
421
|
-
timeout: {
|
|
422
|
-
name: "timeout",
|
|
423
|
-
enabled: true,
|
|
424
|
-
max_retries: 2,
|
|
425
|
-
backoff_strategy: :exponential,
|
|
426
|
-
base_delay: 1.0,
|
|
427
|
-
max_delay: 15.0,
|
|
428
|
-
jitter: true
|
|
429
|
-
},
|
|
430
|
-
rate_limit: {
|
|
431
|
-
name: "rate_limit",
|
|
432
|
-
enabled: false,
|
|
433
|
-
max_retries: 0,
|
|
434
|
-
backoff_strategy: :none,
|
|
435
|
-
base_delay: 0.0,
|
|
436
|
-
max_delay: 0.0,
|
|
437
|
-
jitter: false
|
|
438
|
-
},
|
|
439
402
|
authentication: {
|
|
440
403
|
name: "authentication",
|
|
441
404
|
enabled: false,
|
|
@@ -723,40 +686,6 @@ module Aidp
|
|
|
723
686
|
reason: "Permanent error, requires manual intervention",
|
|
724
687
|
priority: :critical
|
|
725
688
|
}
|
|
726
|
-
# Legacy error type mappings for backward compatibility
|
|
727
|
-
when :timeout
|
|
728
|
-
{
|
|
729
|
-
action: :switch_model,
|
|
730
|
-
reason: "Timeout error, trying faster model",
|
|
731
|
-
priority: :medium
|
|
732
|
-
}
|
|
733
|
-
when :network_error
|
|
734
|
-
{
|
|
735
|
-
action: :switch_provider,
|
|
736
|
-
reason: "Network error, switching provider",
|
|
737
|
-
priority: :medium
|
|
738
|
-
}
|
|
739
|
-
when :server_error
|
|
740
|
-
{
|
|
741
|
-
action: :switch_provider,
|
|
742
|
-
reason: "Server error, switching provider",
|
|
743
|
-
priority: :medium
|
|
744
|
-
}
|
|
745
|
-
when :authentication, :permission_denied
|
|
746
|
-
# Try to switch to another provider. If no providers available, this will
|
|
747
|
-
# be detected in attempt_recovery and we'll crash (crash-early principle)
|
|
748
|
-
{
|
|
749
|
-
action: :switch_provider,
|
|
750
|
-
reason: "Authentication/permission issue ā switching provider to continue",
|
|
751
|
-
priority: :critical,
|
|
752
|
-
crash_if_no_fallback: true
|
|
753
|
-
}
|
|
754
|
-
when :rate_limit
|
|
755
|
-
{
|
|
756
|
-
action: :switch_provider,
|
|
757
|
-
reason: "Rate limit reached, switching provider",
|
|
758
|
-
priority: :high
|
|
759
|
-
}
|
|
760
689
|
else
|
|
761
690
|
{
|
|
762
691
|
action: :switch_provider,
|
|
@@ -9,6 +9,7 @@ require_relative "../providers/opencode"
|
|
|
9
9
|
require_relative "../providers/kilocode"
|
|
10
10
|
require_relative "../providers/github_copilot"
|
|
11
11
|
require_relative "../providers/codex"
|
|
12
|
+
require_relative "../providers/aider"
|
|
12
13
|
|
|
13
14
|
module Aidp
|
|
14
15
|
module Harness
|
|
@@ -22,7 +23,8 @@ module Aidp
|
|
|
22
23
|
"opencode" => Aidp::Providers::Opencode,
|
|
23
24
|
"kilocode" => Aidp::Providers::Kilocode,
|
|
24
25
|
"github_copilot" => Aidp::Providers::GithubCopilot,
|
|
25
|
-
"codex" => Aidp::Providers::Codex
|
|
26
|
+
"codex" => Aidp::Providers::Codex,
|
|
27
|
+
"aider" => Aidp::Providers::Aider
|
|
26
28
|
}.freeze
|
|
27
29
|
|
|
28
30
|
def initialize(config_manager = nil)
|
|
@@ -240,8 +242,15 @@ module Aidp
|
|
|
240
242
|
|
|
241
243
|
def configure_provider(provider_instance, provider_config, options)
|
|
242
244
|
# Set basic configuration
|
|
245
|
+
config_hash = provider_config.config(options).dup
|
|
246
|
+
|
|
247
|
+
# Add model to config if specified in options
|
|
248
|
+
if options[:model]
|
|
249
|
+
config_hash[:model] = options[:model]
|
|
250
|
+
end
|
|
251
|
+
|
|
243
252
|
if provider_instance.respond_to?(:configure)
|
|
244
|
-
provider_instance.configure(
|
|
253
|
+
provider_instance.configure(config_hash)
|
|
245
254
|
end
|
|
246
255
|
|
|
247
256
|
# Set harness context if available
|
|
@@ -103,13 +103,6 @@ module Aidp
|
|
|
103
103
|
save_state(updated_state)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
# Get current step from state (legacy method - use progress tracker integration instead)
|
|
107
|
-
def current_step_from_state
|
|
108
|
-
state = load_state
|
|
109
|
-
return nil unless state
|
|
110
|
-
state[:current_step]
|
|
111
|
-
end
|
|
112
|
-
|
|
113
106
|
# Set current step
|
|
114
107
|
def set_current_step(step_name)
|
|
115
108
|
update_state(current_step: step_name, last_updated: Time.now)
|
|
@@ -153,40 +153,32 @@ module Aidp
|
|
|
153
153
|
tier ||= current_tier
|
|
154
154
|
validate_tier!(tier)
|
|
155
155
|
|
|
156
|
-
# First, try to get models from user's configuration for this tier
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if configured_models.any?
|
|
160
|
-
# If provider specified, try to find model for that provider in config
|
|
161
|
-
if provider
|
|
162
|
-
matching_model = configured_models.find { |m| m[:provider] == provider }
|
|
163
|
-
if matching_model
|
|
164
|
-
Aidp.log_debug("thinking_depth_manager", "Selected model from user config",
|
|
165
|
-
tier: tier,
|
|
166
|
-
provider: provider,
|
|
167
|
-
model: matching_model[:model])
|
|
168
|
-
return [matching_model[:provider], matching_model[:model], {}]
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# If provider doesn't support tier and switching allowed, try other providers in config
|
|
172
|
-
unless configuration.allow_provider_switch_for_tier?
|
|
173
|
-
Aidp.log_warn("thinking_depth_manager", "Provider lacks tier in config, switching disabled",
|
|
174
|
-
tier: tier,
|
|
175
|
-
provider: provider)
|
|
176
|
-
return nil
|
|
177
|
-
end
|
|
178
|
-
end
|
|
156
|
+
# First, try to get models from user's configuration for this tier and provider
|
|
157
|
+
if provider
|
|
158
|
+
configured_models = configuration.models_for_tier(tier, provider)
|
|
179
159
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
Aidp.
|
|
160
|
+
if configured_models.any?
|
|
161
|
+
# Use first configured model for this provider and tier
|
|
162
|
+
model_name = configured_models.first
|
|
163
|
+
Aidp.log_debug("thinking_depth_manager", "Selected model from user config",
|
|
184
164
|
tier: tier,
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return [first_model[:provider], first_model[:model], {}]
|
|
165
|
+
provider: provider,
|
|
166
|
+
model: model_name)
|
|
167
|
+
return [provider, model_name, {}]
|
|
189
168
|
end
|
|
169
|
+
|
|
170
|
+
# Provider specified but has no models for this tier in config
|
|
171
|
+
# Try catalog for the specified provider before switching providers
|
|
172
|
+
Aidp.log_debug("thinking_depth_manager", "Provider has no configured models for tier, trying catalog",
|
|
173
|
+
tier: tier,
|
|
174
|
+
provider: provider)
|
|
175
|
+
|
|
176
|
+
# Continue to catalog-based selection below (will try specified provider first)
|
|
177
|
+
else
|
|
178
|
+
# No provider specified - this should not happen in normal flow
|
|
179
|
+
# Log warning and fall through to catalog-based selection
|
|
180
|
+
Aidp.log_warn("thinking_depth_manager", "select_model_for_tier called without provider",
|
|
181
|
+
tier: tier)
|
|
190
182
|
end
|
|
191
183
|
|
|
192
184
|
# Fall back to catalog-based selection if no models in user config
|
|
@@ -396,37 +388,22 @@ module Aidp
|
|
|
396
388
|
fallback_tiers = generate_fallback_tier_order(requested_tier)
|
|
397
389
|
|
|
398
390
|
fallback_tiers.each do |fallback_tier|
|
|
399
|
-
# First, try user's configuration for this fallback tier
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if configured_models.any?
|
|
403
|
-
# Try specified provider first if given
|
|
404
|
-
if provider
|
|
405
|
-
matching_model = configured_models.find { |m| m[:provider] == provider }
|
|
406
|
-
if matching_model
|
|
407
|
-
Aidp.log_warn("thinking_depth_manager", "Falling back to different tier (from config)",
|
|
408
|
-
requested_tier: requested_tier,
|
|
409
|
-
fallback_tier: fallback_tier,
|
|
410
|
-
provider: provider,
|
|
411
|
-
model: matching_model[:model])
|
|
412
|
-
return [matching_model[:provider], matching_model[:model], {}]
|
|
413
|
-
end
|
|
414
|
-
end
|
|
391
|
+
# First, try user's configuration for this fallback tier and provider
|
|
392
|
+
if provider
|
|
393
|
+
configured_models = configuration.models_for_tier(fallback_tier, provider)
|
|
415
394
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
Aidp.log_warn("thinking_depth_manager", "Falling back to different tier and provider (from config)",
|
|
395
|
+
if configured_models.any?
|
|
396
|
+
model_name = configured_models.first
|
|
397
|
+
Aidp.log_warn("thinking_depth_manager", "Falling back to different tier (from config)",
|
|
420
398
|
requested_tier: requested_tier,
|
|
421
399
|
fallback_tier: fallback_tier,
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
return [first_model[:provider], first_model[:model], {}]
|
|
400
|
+
provider: provider,
|
|
401
|
+
model: model_name)
|
|
402
|
+
return [provider, model_name, {}]
|
|
426
403
|
end
|
|
427
404
|
end
|
|
428
405
|
|
|
429
|
-
# Fall back to catalog if no models in config
|
|
406
|
+
# Fall back to catalog if no models in config for the provider
|
|
430
407
|
# Try specified provider first if given
|
|
431
408
|
if provider
|
|
432
409
|
model_name, model_data = @registry.best_model_for_tier(fallback_tier, provider)
|
|
@@ -440,19 +417,21 @@ module Aidp
|
|
|
440
417
|
end
|
|
441
418
|
end
|
|
442
419
|
|
|
443
|
-
# Try all available providers in catalog
|
|
444
|
-
|
|
445
|
-
|
|
420
|
+
# Try all available providers in catalog if switching allowed
|
|
421
|
+
if configuration.allow_provider_switch_for_tier?
|
|
422
|
+
@registry.provider_names.each do |prov_name|
|
|
423
|
+
next if prov_name == provider # Skip if already tried above
|
|
446
424
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
425
|
+
model_name, model_data = @registry.best_model_for_tier(fallback_tier, prov_name)
|
|
426
|
+
if model_name
|
|
427
|
+
Aidp.log_warn("thinking_depth_manager", "Falling back to different tier and provider (from catalog)",
|
|
428
|
+
requested_tier: requested_tier,
|
|
429
|
+
fallback_tier: fallback_tier,
|
|
430
|
+
requested_provider: provider,
|
|
431
|
+
fallback_provider: prov_name,
|
|
432
|
+
model: model_name)
|
|
433
|
+
return [prov_name, model_name, model_data]
|
|
434
|
+
end
|
|
456
435
|
end
|
|
457
436
|
end
|
|
458
437
|
end
|
|
@@ -43,16 +43,6 @@ module Aidp
|
|
|
43
43
|
setup_signal_handlers
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
# Simple display initialization - no background threads
|
|
47
|
-
def start_display_loop
|
|
48
|
-
# Display loop is now just a no-op for compatibility
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def stop_display_loop
|
|
52
|
-
# Simple cleanup - no background threads to stop
|
|
53
|
-
restore_screen
|
|
54
|
-
end
|
|
55
|
-
|
|
56
46
|
# Input methods using TTY::Prompt only - no background threads
|
|
57
47
|
def get_user_input(prompt = "š¬ You: ")
|
|
58
48
|
@prompt.ask(prompt)
|
|
@@ -258,6 +248,12 @@ module Aidp
|
|
|
258
248
|
@prompt.say("š #{message}", color: :cyan)
|
|
259
249
|
end
|
|
260
250
|
|
|
251
|
+
def restore_screen
|
|
252
|
+
@cursor.show
|
|
253
|
+
@cursor.clear_screen
|
|
254
|
+
@cursor.move_to(1, 1)
|
|
255
|
+
end
|
|
256
|
+
|
|
261
257
|
private
|
|
262
258
|
|
|
263
259
|
def extract_questions_for_step(step_name)
|
|
@@ -284,20 +280,14 @@ module Aidp
|
|
|
284
280
|
[]
|
|
285
281
|
end
|
|
286
282
|
|
|
287
|
-
def restore_screen
|
|
288
|
-
@cursor.show
|
|
289
|
-
@cursor.clear_screen
|
|
290
|
-
@cursor.move_to(1, 1)
|
|
291
|
-
end
|
|
292
|
-
|
|
293
283
|
def setup_signal_handlers
|
|
294
284
|
Signal.trap("INT") do
|
|
295
|
-
|
|
285
|
+
restore_screen
|
|
296
286
|
exit(1)
|
|
297
287
|
end
|
|
298
288
|
|
|
299
289
|
Signal.trap("TERM") do
|
|
300
|
-
|
|
290
|
+
restore_screen
|
|
301
291
|
exit(0)
|
|
302
292
|
end
|
|
303
293
|
end
|
|
@@ -86,24 +86,6 @@ module Aidp
|
|
|
86
86
|
}
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
# Legacy method - kept for backward compatibility if needed
|
|
90
|
-
def select_execute_workflow_interactive
|
|
91
|
-
# Step 1: Collect project information
|
|
92
|
-
collect_project_info_interactive
|
|
93
|
-
|
|
94
|
-
# Step 2: Choose workflow type
|
|
95
|
-
workflow_type = choose_workflow_type_interactive
|
|
96
|
-
|
|
97
|
-
# Step 3: Generate workflow steps
|
|
98
|
-
steps = generate_workflow_steps_interactive(workflow_type)
|
|
99
|
-
|
|
100
|
-
{
|
|
101
|
-
workflow_type: workflow_type,
|
|
102
|
-
steps: steps,
|
|
103
|
-
user_input: @user_input
|
|
104
|
-
}
|
|
105
|
-
end
|
|
106
|
-
|
|
107
89
|
def select_analyze_workflow_defaults
|
|
108
90
|
@tui.show_message("š Starting analyze mode with default configuration...", :info)
|
|
109
91
|
|
|
@@ -22,14 +22,18 @@ module Aidp
|
|
|
22
22
|
|
|
23
23
|
def initialize(ui_components = {})
|
|
24
24
|
super()
|
|
25
|
+
@output = ui_components[:output]
|
|
25
26
|
@progress = ui_components[:progress] || TTY::ProgressBar
|
|
26
|
-
@pastel =
|
|
27
|
+
@pastel = if @output&.respond_to?(:tty?) && @output.tty?
|
|
28
|
+
Pastel.new(enabled: true)
|
|
29
|
+
else
|
|
30
|
+
Pastel.new(enabled: false)
|
|
31
|
+
end
|
|
27
32
|
@formatter = ui_components[:formatter] || ProgressFormatter.new
|
|
28
33
|
@display_history = []
|
|
29
34
|
@auto_refresh_enabled = false
|
|
30
35
|
@refresh_interval = 1.0
|
|
31
36
|
@refresh_thread = nil
|
|
32
|
-
@output = ui_components[:output]
|
|
33
37
|
@prompt = ui_components[:prompt] || TTY::Prompt.new
|
|
34
38
|
@spinner_class = begin
|
|
35
39
|
ui_components[:spinner] || TTY::Spinner
|
|
@@ -425,48 +425,6 @@ module Aidp
|
|
|
425
425
|
display_message("\nš Continuing execution...", type: :success)
|
|
426
426
|
end
|
|
427
427
|
|
|
428
|
-
# Display question information (legacy method for compatibility)
|
|
429
|
-
def display_question_info(question_type, expected_input, options, default_value, required)
|
|
430
|
-
info_parts = []
|
|
431
|
-
|
|
432
|
-
# Question type
|
|
433
|
-
type_emojis = {
|
|
434
|
-
"text" => "š",
|
|
435
|
-
"choice" => "š",
|
|
436
|
-
"confirmation" => "ā
",
|
|
437
|
-
"file" => "š",
|
|
438
|
-
"number" => "š¢",
|
|
439
|
-
"email" => "š§",
|
|
440
|
-
"url" => "š"
|
|
441
|
-
}
|
|
442
|
-
type_emoji = type_emojis[question_type] || "ā"
|
|
443
|
-
info_parts << "#{type_emoji} #{question_type.capitalize}"
|
|
444
|
-
|
|
445
|
-
# Expected input type
|
|
446
|
-
if expected_input != "text"
|
|
447
|
-
info_parts << "Expected: #{expected_input}"
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
# Options
|
|
451
|
-
if options && !options.empty?
|
|
452
|
-
info_parts << "Options: #{options.join(", ")}"
|
|
453
|
-
end
|
|
454
|
-
|
|
455
|
-
# Default value
|
|
456
|
-
if default_value
|
|
457
|
-
info_parts << "Default: #{default_value}"
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
# Required status
|
|
461
|
-
info_parts << if required
|
|
462
|
-
"Required: Yes"
|
|
463
|
-
else
|
|
464
|
-
"Required: No"
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
display_message(" #{info_parts.join(" | ")}", type: :info)
|
|
468
|
-
end
|
|
469
|
-
|
|
470
428
|
# Get response for a specific question with enhanced validation
|
|
471
429
|
def question_response(question_data, _question_number)
|
|
472
430
|
question_type = question_data[:type] || "text"
|
|
@@ -1576,12 +1534,6 @@ module Aidp
|
|
|
1576
1534
|
end
|
|
1577
1535
|
end
|
|
1578
1536
|
|
|
1579
|
-
# Find files matching search term (legacy method for compatibility)
|
|
1580
|
-
def find_files(search_term)
|
|
1581
|
-
search_options = parse_file_search_options(search_term)
|
|
1582
|
-
find_files_advanced(search_options)
|
|
1583
|
-
end
|
|
1584
|
-
|
|
1585
1537
|
# Display advanced file selection menu
|
|
1586
1538
|
def display_advanced_file_menu(files, search_options)
|
|
1587
1539
|
display_message("\nš Available files:", type: :info)
|
|
@@ -1659,11 +1611,6 @@ module Aidp
|
|
|
1659
1611
|
end
|
|
1660
1612
|
end
|
|
1661
1613
|
|
|
1662
|
-
# Display file selection menu (legacy method for compatibility)
|
|
1663
|
-
def display_file_menu(files)
|
|
1664
|
-
display_advanced_file_menu(files, {term: "", extensions: [], directories: []})
|
|
1665
|
-
end
|
|
1666
|
-
|
|
1667
1614
|
# Get advanced file selection from user
|
|
1668
1615
|
def advanced_file_selection(max_files, _search_options)
|
|
1669
1616
|
loop do
|
|
@@ -1763,11 +1710,6 @@ module Aidp
|
|
|
1763
1710
|
@prompt.keypress("Press any key to continue...")
|
|
1764
1711
|
end
|
|
1765
1712
|
|
|
1766
|
-
# Get file selection from user (legacy method for compatibility)
|
|
1767
|
-
def file_selection(max_files)
|
|
1768
|
-
advanced_file_selection(max_files, {term: "", extensions: [], directories: []})
|
|
1769
|
-
end
|
|
1770
|
-
|
|
1771
1713
|
# Get confirmation from user
|
|
1772
1714
|
def confirmation(message, default: true)
|
|
1773
1715
|
default_text = default ? "Y/n" : "y/N"
|
data/lib/aidp/init/runner.rb
CHANGED
|
@@ -337,8 +337,13 @@ module Aidp
|
|
|
337
337
|
next unless tool_command
|
|
338
338
|
|
|
339
339
|
# Check if command exists
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
begin
|
|
341
|
+
unless system("which #{tool_command} > /dev/null 2>&1")
|
|
342
|
+
warnings << " ā ļø #{format_tool(tool_data[:tool])} detected but command '#{tool_command}' not found in PATH"
|
|
343
|
+
end
|
|
344
|
+
rescue IOError
|
|
345
|
+
# Streams may be closed in test environment - skip validation
|
|
346
|
+
Aidp.log_debug("init_runner", "skipping_tool_validation", tool: tool_command, reason: "closed_stream")
|
|
342
347
|
end
|
|
343
348
|
end
|
|
344
349
|
|