aidp 0.26.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/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 +661 -0
- data/lib/aidp/cli/providers_command.rb +223 -0
- data/lib/aidp/cli.rb +45 -464
- data/lib/aidp/config.rb +54 -0
- data/lib/aidp/daemon/runner.rb +2 -2
- data/lib/aidp/debug_mixin.rb +25 -10
- data/lib/aidp/execute/agent_signal_parser.rb +22 -0
- 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/repl_macros.rb +2 -2
- data/lib/aidp/execute/steps.rb +94 -1
- data/lib/aidp/execute/work_loop_runner.rb +238 -19
- data/lib/aidp/execute/workflow_selector.rb +4 -27
- 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 +5 -10
- data/lib/aidp/harness/config_schema.rb +8 -0
- data/lib/aidp/harness/configuration.rb +40 -2
- data/lib/aidp/harness/enhanced_runner.rb +25 -19
- data/lib/aidp/harness/error_handler.rb +23 -73
- 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/provider_factory.rb +11 -2
- data/lib/aidp/harness/runner.rb +5 -0
- data/lib/aidp/harness/state_manager.rb +0 -7
- data/lib/aidp/harness/thinking_depth_manager.rb +202 -7
- 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/message_display.rb +0 -46
- 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/adapter.rb +2 -4
- data/lib/aidp/providers/aider.rb +264 -0
- data/lib/aidp/providers/anthropic.rb +206 -121
- data/lib/aidp/providers/base.rb +123 -3
- data/lib/aidp/providers/capability_registry.rb +0 -1
- data/lib/aidp/providers/codex.rb +75 -70
- data/lib/aidp/providers/cursor.rb +87 -59
- data/lib/aidp/providers/gemini.rb +57 -60
- data/lib/aidp/providers/github_copilot.rb +19 -66
- data/lib/aidp/providers/kilocode.rb +35 -80
- data/lib/aidp/providers/opencode.rb +35 -80
- data/lib/aidp/setup/wizard.rb +555 -8
- 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 +95 -52
- 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 +100 -19
- 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/workflows/guided_agent.rb +3 -3
- data/lib/aidp/workstream_cleanup.rb +245 -0
- data/lib/aidp/worktree.rb +19 -0
- data/templates/aidp-development.yml.example +2 -2
- data/templates/aidp-production.yml.example +3 -3
- 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 +47 -1
data/lib/aidp/providers/base.rb
CHANGED
|
@@ -37,7 +37,7 @@ module Aidp
|
|
|
37
37
|
TIMEOUT_REFACTORING_RECOMMENDATIONS = 600 # 10 minutes - refactoring
|
|
38
38
|
TIMEOUT_IMPLEMENTATION = 900 # 15 minutes - implementation (write files, run tests, fix issues)
|
|
39
39
|
|
|
40
|
-
attr_reader :activity_state, :last_activity_time, :start_time, :step_name
|
|
40
|
+
attr_reader :activity_state, :last_activity_time, :start_time, :step_name, :model
|
|
41
41
|
|
|
42
42
|
def initialize(output: nil, prompt: TTY::Prompt.new)
|
|
43
43
|
@activity_state = :idle
|
|
@@ -52,6 +52,7 @@ module Aidp
|
|
|
52
52
|
@harness_context = nil
|
|
53
53
|
@output = output
|
|
54
54
|
@prompt = prompt
|
|
55
|
+
@model = nil
|
|
55
56
|
@harness_metrics = {
|
|
56
57
|
total_requests: 0,
|
|
57
58
|
successful_requests: 0,
|
|
@@ -74,6 +75,12 @@ module Aidp
|
|
|
74
75
|
name
|
|
75
76
|
end
|
|
76
77
|
|
|
78
|
+
# Configure the provider with options
|
|
79
|
+
# @param config [Hash] Configuration options, may include :model
|
|
80
|
+
def configure(config)
|
|
81
|
+
@model = config[:model] if config[:model]
|
|
82
|
+
end
|
|
83
|
+
|
|
77
84
|
def send_message(prompt:, session: nil)
|
|
78
85
|
raise NotImplementedError, "#{self.class} must implement #send_message"
|
|
79
86
|
end
|
|
@@ -324,6 +331,59 @@ module Aidp
|
|
|
324
331
|
end
|
|
325
332
|
end
|
|
326
333
|
|
|
334
|
+
# Helper method for registry-based model discovery
|
|
335
|
+
#
|
|
336
|
+
# Providers that use the model registry can call this method to discover models
|
|
337
|
+
# based on a model family pattern.
|
|
338
|
+
#
|
|
339
|
+
# @param model_pattern [Regexp] Pattern to match model families
|
|
340
|
+
# @param provider_name [String] Name of the provider
|
|
341
|
+
# @return [Array<Hash>] Array of discovered models
|
|
342
|
+
def self.discover_models_from_registry(model_pattern, provider_name)
|
|
343
|
+
require_relative "../harness/model_registry"
|
|
344
|
+
registry = Aidp::Harness::ModelRegistry.new
|
|
345
|
+
|
|
346
|
+
# Get all models from registry that match the pattern
|
|
347
|
+
models = registry.all_families.filter_map do |family|
|
|
348
|
+
next unless model_pattern.match?(family)
|
|
349
|
+
|
|
350
|
+
info = registry.get_model_info(family)
|
|
351
|
+
next unless info
|
|
352
|
+
|
|
353
|
+
{
|
|
354
|
+
name: family,
|
|
355
|
+
family: family,
|
|
356
|
+
tier: info["tier"],
|
|
357
|
+
capabilities: info["capabilities"] || [],
|
|
358
|
+
context_window: info["context_window"],
|
|
359
|
+
provider: provider_name
|
|
360
|
+
}
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
Aidp.log_info("#{provider_name}_provider", "using registry models", count: models.size)
|
|
364
|
+
models
|
|
365
|
+
rescue => e
|
|
366
|
+
Aidp.log_debug("#{provider_name}_provider", "discovery failed", error: e.message)
|
|
367
|
+
[]
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Get firewall requirements for this provider
|
|
371
|
+
#
|
|
372
|
+
# Returns domains and IP ranges that need to be accessible for this provider
|
|
373
|
+
# to function properly. Used by devcontainer firewall configuration.
|
|
374
|
+
#
|
|
375
|
+
# @return [Hash] Firewall requirements with :domains and :ip_ranges keys
|
|
376
|
+
# - domains: Array of domain strings
|
|
377
|
+
# - ip_ranges: Array of CIDR strings
|
|
378
|
+
#
|
|
379
|
+
# Override in subclasses to provide provider-specific requirements
|
|
380
|
+
def self.firewall_requirements
|
|
381
|
+
{
|
|
382
|
+
domains: [],
|
|
383
|
+
ip_ranges: []
|
|
384
|
+
}
|
|
385
|
+
end
|
|
386
|
+
|
|
327
387
|
protected
|
|
328
388
|
|
|
329
389
|
# Log message to job if in background mode
|
|
@@ -371,8 +431,6 @@ module Aidp
|
|
|
371
431
|
(success_rate * 50) + ((1 - rate_limit_ratio) * 30) + (response_time_score * 0.2)
|
|
372
432
|
end
|
|
373
433
|
|
|
374
|
-
protected
|
|
375
|
-
|
|
376
434
|
# Update spinner status with elapsed time
|
|
377
435
|
# This is a shared method used by all providers to display progress
|
|
378
436
|
def update_spinner_status(spinner, elapsed, provider_name)
|
|
@@ -419,6 +477,68 @@ module Aidp
|
|
|
419
477
|
false # Base implementation returns false, subclasses should override
|
|
420
478
|
end
|
|
421
479
|
|
|
480
|
+
# Calculate timeout for provider operations
|
|
481
|
+
#
|
|
482
|
+
# Priority order:
|
|
483
|
+
# 1. Quick mode (for testing)
|
|
484
|
+
# 2. Provider-specific environment variable override
|
|
485
|
+
# 3. Adaptive timeout based on step type
|
|
486
|
+
# 4. Default timeout
|
|
487
|
+
#
|
|
488
|
+
# Override provider_env_var to customize the environment variable name
|
|
489
|
+
def calculate_timeout
|
|
490
|
+
if ENV["AIDP_QUICK_MODE"]
|
|
491
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
492
|
+
return TIMEOUT_QUICK_MODE
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
provider_env_var = "AIDP_#{name.upcase}_TIMEOUT"
|
|
496
|
+
return ENV[provider_env_var].to_i if ENV[provider_env_var]
|
|
497
|
+
|
|
498
|
+
step_timeout = adaptive_timeout
|
|
499
|
+
if step_timeout
|
|
500
|
+
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
501
|
+
return step_timeout
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
# Default timeout
|
|
505
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
506
|
+
TIMEOUT_DEFAULT
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# Get adaptive timeout based on step type
|
|
510
|
+
#
|
|
511
|
+
# This method returns different timeout values based on the type of operation
|
|
512
|
+
# being performed, as indicated by the AIDP_CURRENT_STEP environment variable.
|
|
513
|
+
# Returns nil for unknown steps to allow calculate_timeout to use the default.
|
|
514
|
+
def adaptive_timeout
|
|
515
|
+
@adaptive_timeout ||= begin
|
|
516
|
+
# Timeout recommendations based on step type patterns
|
|
517
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
518
|
+
|
|
519
|
+
case step_name
|
|
520
|
+
when /REPOSITORY_ANALYSIS/
|
|
521
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
|
522
|
+
when /ARCHITECTURE_ANALYSIS/
|
|
523
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
524
|
+
when /TEST_ANALYSIS/
|
|
525
|
+
TIMEOUT_TEST_ANALYSIS
|
|
526
|
+
when /FUNCTIONALITY_ANALYSIS/
|
|
527
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
528
|
+
when /DOCUMENTATION_ANALYSIS/
|
|
529
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
530
|
+
when /STATIC_ANALYSIS/
|
|
531
|
+
TIMEOUT_STATIC_ANALYSIS
|
|
532
|
+
when /REFACTORING_RECOMMENDATIONS/
|
|
533
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
534
|
+
when /IMPLEMENTATION/
|
|
535
|
+
TIMEOUT_IMPLEMENTATION
|
|
536
|
+
else
|
|
537
|
+
nil # Return nil for unknown steps
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
|
|
422
542
|
private
|
|
423
543
|
end
|
|
424
544
|
end
|
|
@@ -16,7 +16,6 @@ module Aidp
|
|
|
16
16
|
:supports_tool_use, # Boolean: supports tool/function calling
|
|
17
17
|
:supports_vision, # Boolean: supports image/vision inputs
|
|
18
18
|
:supports_file_upload, # Boolean: supports file uploads
|
|
19
|
-
:streaming, # Boolean: supports streaming responses
|
|
20
19
|
:supports_mcp, # Boolean: supports Model Context Protocol
|
|
21
20
|
:max_tokens, # Maximum tokens per response
|
|
22
21
|
:supports_dangerous_mode # Boolean: supports elevated permissions mode
|
data/lib/aidp/providers/codex.rb
CHANGED
|
@@ -10,10 +10,52 @@ module Aidp
|
|
|
10
10
|
class Codex < Base
|
|
11
11
|
include Aidp::DebugMixin
|
|
12
12
|
|
|
13
|
+
# Model name pattern for OpenAI models (since Codex uses OpenAI)
|
|
14
|
+
MODEL_PATTERN = /^gpt-[\d.o-]+(?:-turbo)?(?:-mini)?$/i
|
|
15
|
+
LONG_PROMPT_THRESHOLD = 8000
|
|
16
|
+
LONG_PROMPT_TIMEOUT = 900 # 15 minutes for large prompts
|
|
17
|
+
|
|
13
18
|
def self.available?
|
|
14
19
|
!!Aidp::Util.which("codex")
|
|
15
20
|
end
|
|
16
21
|
|
|
22
|
+
# Check if this provider supports a given model family
|
|
23
|
+
#
|
|
24
|
+
# @param family_name [String] The model family name
|
|
25
|
+
# @return [Boolean] True if it matches OpenAI model pattern
|
|
26
|
+
def self.supports_model_family?(family_name)
|
|
27
|
+
MODEL_PATTERN.match?(family_name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Discover available models from registry
|
|
31
|
+
#
|
|
32
|
+
# Note: Codex CLI doesn't have a standard model listing command
|
|
33
|
+
# Returns registry-based models that match OpenAI patterns
|
|
34
|
+
#
|
|
35
|
+
# @return [Array<Hash>] Array of discovered models
|
|
36
|
+
def self.discover_models
|
|
37
|
+
return [] unless available?
|
|
38
|
+
|
|
39
|
+
discover_models_from_registry(MODEL_PATTERN, "codex")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Get firewall requirements for Codex provider
|
|
43
|
+
# Codex uses OpenAI APIs
|
|
44
|
+
def self.firewall_requirements
|
|
45
|
+
{
|
|
46
|
+
domains: [
|
|
47
|
+
"api.openai.com",
|
|
48
|
+
"auth.openai.com",
|
|
49
|
+
"openai.com",
|
|
50
|
+
"chat.openai.com",
|
|
51
|
+
"chatgpt.com",
|
|
52
|
+
"cdn.openai.com",
|
|
53
|
+
"oaiusercontent.com"
|
|
54
|
+
],
|
|
55
|
+
ip_ranges: []
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
17
59
|
def name
|
|
18
60
|
"codex"
|
|
19
61
|
end
|
|
@@ -37,18 +79,13 @@ module Aidp
|
|
|
37
79
|
def send_message(prompt:, session: nil)
|
|
38
80
|
raise "codex CLI not available" unless self.class.available?
|
|
39
81
|
|
|
40
|
-
# Smart timeout calculation
|
|
82
|
+
# Smart timeout calculation (store prompt length for adaptive logic)
|
|
83
|
+
@current_codex_prompt_length = prompt.length
|
|
41
84
|
timeout_seconds = calculate_timeout
|
|
42
85
|
|
|
43
86
|
debug_provider("codex", "Starting execution", {timeout: timeout_seconds})
|
|
44
87
|
debug_log("📝 Sending prompt to codex (length: #{prompt.length})", level: :info)
|
|
45
88
|
|
|
46
|
-
# Check if streaming mode is enabled
|
|
47
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
48
|
-
if streaming_enabled
|
|
49
|
-
display_message("📺 Streaming mode enabled - output will appear in real-time", type: :info)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
89
|
# Set up activity monitoring
|
|
53
90
|
setup_activity_monitoring("codex", method(:activity_callback))
|
|
54
91
|
record_activity("Starting codex execution")
|
|
@@ -74,6 +111,11 @@ module Aidp
|
|
|
74
111
|
# Use non-interactive mode (exec) for automation
|
|
75
112
|
args = ["exec", prompt]
|
|
76
113
|
|
|
114
|
+
# Add model if configured
|
|
115
|
+
if @model && !@model.empty?
|
|
116
|
+
args += ["--model", @model]
|
|
117
|
+
end
|
|
118
|
+
|
|
77
119
|
# Add session support if provided (codex may support session/thread continuation)
|
|
78
120
|
if session && !session.empty?
|
|
79
121
|
args += ["--session", session]
|
|
@@ -94,7 +136,7 @@ module Aidp
|
|
|
94
136
|
end
|
|
95
137
|
|
|
96
138
|
# Use debug_execute_command for better debugging
|
|
97
|
-
result = debug_execute_command("codex", args: args, timeout: timeout_seconds
|
|
139
|
+
result = debug_execute_command("codex", args: args, timeout: timeout_seconds)
|
|
98
140
|
|
|
99
141
|
# Log the results
|
|
100
142
|
debug_command("codex", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
@@ -116,6 +158,7 @@ module Aidp
|
|
|
116
158
|
raise
|
|
117
159
|
ensure
|
|
118
160
|
cleanup_activity_display(activity_display_thread, spinner)
|
|
161
|
+
@current_codex_prompt_length = nil
|
|
119
162
|
end
|
|
120
163
|
end
|
|
121
164
|
|
|
@@ -128,9 +171,10 @@ module Aidp
|
|
|
128
171
|
args += ["--session", session]
|
|
129
172
|
end
|
|
130
173
|
|
|
131
|
-
# Add model selection
|
|
132
|
-
|
|
133
|
-
|
|
174
|
+
# Add model selection (from parameter or configured model)
|
|
175
|
+
model_to_use = model || @model
|
|
176
|
+
if model_to_use
|
|
177
|
+
args += ["--model", model_to_use]
|
|
134
178
|
end
|
|
135
179
|
|
|
136
180
|
# Add approval flag - but warn about interactive behavior
|
|
@@ -161,22 +205,17 @@ module Aidp
|
|
|
161
205
|
|
|
162
206
|
# Internal helper for send_with_options - executes with custom arguments
|
|
163
207
|
def send_with_custom_args(prompt:, args:)
|
|
208
|
+
@current_codex_prompt_length = prompt.length
|
|
164
209
|
timeout_seconds = calculate_timeout
|
|
165
210
|
|
|
166
211
|
debug_provider("codex", "Starting execution", {timeout: timeout_seconds, args: args})
|
|
167
212
|
debug_log("📝 Sending prompt to codex with custom args", level: :info)
|
|
168
213
|
|
|
169
|
-
# Check if streaming mode is enabled
|
|
170
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
171
|
-
if streaming_enabled
|
|
172
|
-
display_message("📺 Display streaming enabled - output buffering reduced (codex CLI does not support true streaming)", type: :info)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
214
|
setup_activity_monitoring("codex", method(:activity_callback))
|
|
176
215
|
record_activity("Starting codex execution with custom args")
|
|
177
216
|
|
|
178
217
|
begin
|
|
179
|
-
result = debug_execute_command("codex", args: args, timeout: timeout_seconds
|
|
218
|
+
result = debug_execute_command("codex", args: args, timeout: timeout_seconds)
|
|
180
219
|
debug_command("codex", args: args, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
181
220
|
|
|
182
221
|
if result.exit_status == 0
|
|
@@ -191,58 +230,8 @@ module Aidp
|
|
|
191
230
|
mark_failed("codex execution failed: #{e.message}")
|
|
192
231
|
debug_error(e, {provider: "codex", prompt_length: prompt.length})
|
|
193
232
|
raise
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
def calculate_timeout
|
|
198
|
-
# Priority order for timeout calculation:
|
|
199
|
-
# 1. Quick mode (for testing)
|
|
200
|
-
# 2. Environment variable override
|
|
201
|
-
# 3. Adaptive timeout based on step type
|
|
202
|
-
# 4. Default timeout
|
|
203
|
-
|
|
204
|
-
if ENV["AIDP_QUICK_MODE"]
|
|
205
|
-
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
206
|
-
return TIMEOUT_QUICK_MODE
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
if ENV["AIDP_CODEX_TIMEOUT"]
|
|
210
|
-
return ENV["AIDP_CODEX_TIMEOUT"].to_i
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
if adaptive_timeout
|
|
214
|
-
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
|
215
|
-
return adaptive_timeout
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
# Default timeout
|
|
219
|
-
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
220
|
-
TIMEOUT_DEFAULT
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def adaptive_timeout
|
|
224
|
-
@adaptive_timeout ||= begin
|
|
225
|
-
# Timeout recommendations based on step type patterns
|
|
226
|
-
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
227
|
-
|
|
228
|
-
case step_name
|
|
229
|
-
when /REPOSITORY_ANALYSIS/
|
|
230
|
-
TIMEOUT_REPOSITORY_ANALYSIS
|
|
231
|
-
when /ARCHITECTURE_ANALYSIS/
|
|
232
|
-
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
233
|
-
when /TEST_ANALYSIS/
|
|
234
|
-
TIMEOUT_TEST_ANALYSIS
|
|
235
|
-
when /FUNCTIONALITY_ANALYSIS/
|
|
236
|
-
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
237
|
-
when /DOCUMENTATION_ANALYSIS/
|
|
238
|
-
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
239
|
-
when /STATIC_ANALYSIS/
|
|
240
|
-
TIMEOUT_STATIC_ANALYSIS
|
|
241
|
-
when /REFACTORING_RECOMMENDATIONS/
|
|
242
|
-
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
243
|
-
else
|
|
244
|
-
nil # Use default
|
|
245
|
-
end
|
|
233
|
+
ensure
|
|
234
|
+
@current_codex_prompt_length = nil
|
|
246
235
|
end
|
|
247
236
|
end
|
|
248
237
|
|
|
@@ -257,6 +246,22 @@ module Aidp
|
|
|
257
246
|
display_message("\n❌ Codex CLI failed: #{message}", type: :error)
|
|
258
247
|
end
|
|
259
248
|
end
|
|
249
|
+
|
|
250
|
+
def calculate_timeout
|
|
251
|
+
env_override = ENV["AIDP_CODEX_TIMEOUT"]
|
|
252
|
+
return env_override.to_i if env_override&.match?(/^\d+$/)
|
|
253
|
+
|
|
254
|
+
base_timeout = super
|
|
255
|
+
|
|
256
|
+
prompt_length = @current_codex_prompt_length
|
|
257
|
+
return base_timeout unless prompt_length && prompt_length >= LONG_PROMPT_THRESHOLD
|
|
258
|
+
|
|
259
|
+
extended_timeout = [base_timeout, LONG_PROMPT_TIMEOUT].max
|
|
260
|
+
if extended_timeout > base_timeout
|
|
261
|
+
display_message("⏱️ Codex prompt length #{prompt_length} detected - extending timeout to #{extended_timeout} seconds", type: :info)
|
|
262
|
+
end
|
|
263
|
+
extended_timeout
|
|
264
|
+
end
|
|
260
265
|
end
|
|
261
266
|
end
|
|
262
267
|
end
|
|
@@ -14,6 +14,92 @@ module Aidp
|
|
|
14
14
|
!!Aidp::Util.which("cursor-agent")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
# Normalize Cursor's model name to family name
|
|
18
|
+
#
|
|
19
|
+
# Cursor may use different naming conventions (e.g., dots vs hyphens)
|
|
20
|
+
#
|
|
21
|
+
# @param provider_model_name [String] Cursor's model name
|
|
22
|
+
# @return [String] The normalized family name
|
|
23
|
+
def self.model_family(provider_model_name)
|
|
24
|
+
# Normalize cursor naming to standard family names
|
|
25
|
+
# cursor uses dots: "claude-3.5-sonnet" -> "claude-3-5-sonnet"
|
|
26
|
+
provider_model_name.gsub(/(\d)\.(\d)/, '\1-\2')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Convert family name to Cursor's naming convention
|
|
30
|
+
#
|
|
31
|
+
# @param family_name [String] The model family name
|
|
32
|
+
# @return [String] Cursor's model name
|
|
33
|
+
def self.provider_model_name(family_name)
|
|
34
|
+
# Cursor uses dots for version numbers
|
|
35
|
+
# "claude-3-5-sonnet" -> "claude-3.5-sonnet"
|
|
36
|
+
family_name.gsub(/(\d)-(\d)/, '\1.\2')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Check if this provider supports a given model family
|
|
40
|
+
#
|
|
41
|
+
# Cursor supports Claude, GPT, and Cursor-specific models
|
|
42
|
+
#
|
|
43
|
+
# @param family_name [String] The model family name
|
|
44
|
+
# @return [Boolean] True if likely supported
|
|
45
|
+
def self.supports_model_family?(family_name)
|
|
46
|
+
family_name.match?(/^(claude|gpt|cursor)-/)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Get firewall requirements for Cursor provider
|
|
50
|
+
def self.firewall_requirements
|
|
51
|
+
{
|
|
52
|
+
domains: [
|
|
53
|
+
"cursor.com",
|
|
54
|
+
"www.cursor.com",
|
|
55
|
+
"downloads.cursor.com",
|
|
56
|
+
"api.cursor.sh",
|
|
57
|
+
"cursor.sh",
|
|
58
|
+
"app.cursor.sh",
|
|
59
|
+
"www.cursor.sh"
|
|
60
|
+
],
|
|
61
|
+
ip_ranges: []
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Discover available models from Cursor
|
|
66
|
+
#
|
|
67
|
+
# Note: Cursor doesn't have a public model listing API
|
|
68
|
+
# Returns registry-based models that match Cursor patterns
|
|
69
|
+
#
|
|
70
|
+
# @return [Array<Hash>] Array of discovered models
|
|
71
|
+
def self.discover_models
|
|
72
|
+
return [] unless available?
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
require_relative "../harness/model_registry"
|
|
76
|
+
registry = Aidp::Harness::ModelRegistry.new
|
|
77
|
+
|
|
78
|
+
# Get all models from registry that Cursor might support
|
|
79
|
+
models = registry.all_families.filter_map do |family|
|
|
80
|
+
next unless supports_model_family?(family)
|
|
81
|
+
|
|
82
|
+
info = registry.get_model_info(family)
|
|
83
|
+
next unless info
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
name: provider_model_name(family),
|
|
87
|
+
family: family,
|
|
88
|
+
tier: info["tier"],
|
|
89
|
+
capabilities: info["capabilities"] || [],
|
|
90
|
+
context_window: info["context_window"],
|
|
91
|
+
provider: "cursor"
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
Aidp.log_info("cursor_provider", "using registry models", count: models.size)
|
|
96
|
+
models
|
|
97
|
+
rescue => e
|
|
98
|
+
Aidp.log_debug("cursor_provider", "discovery failed", error: e.message)
|
|
99
|
+
[]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
17
103
|
def name
|
|
18
104
|
"cursor"
|
|
19
105
|
end
|
|
@@ -40,12 +126,6 @@ module Aidp
|
|
|
40
126
|
debug_provider("cursor", "Starting execution", {timeout: timeout_seconds})
|
|
41
127
|
debug_log("📝 Sending prompt to cursor-agent (length: #{prompt.length})", level: :info)
|
|
42
128
|
|
|
43
|
-
# Check if streaming mode is enabled
|
|
44
|
-
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
|
45
|
-
if streaming_enabled
|
|
46
|
-
display_message("📺 Display streaming enabled - output buffering reduced (cursor-agent does not support true streaming)", type: :info)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
129
|
# Set up activity monitoring
|
|
50
130
|
setup_activity_monitoring("cursor-agent", method(:activity_callback))
|
|
51
131
|
record_activity("Starting cursor-agent execution")
|
|
@@ -71,7 +151,7 @@ module Aidp
|
|
|
71
151
|
# Use debug_execute_command for better debugging
|
|
72
152
|
# Use -p mode (designed for non-interactive/script use)
|
|
73
153
|
# No fallback to interactive modes - they would hang AIDP's automation workflow
|
|
74
|
-
result = debug_execute_command("cursor-agent", args: ["-p"], input: prompt, timeout: timeout_seconds
|
|
154
|
+
result = debug_execute_command("cursor-agent", args: ["-p"], input: prompt, timeout: timeout_seconds)
|
|
75
155
|
|
|
76
156
|
# Log the results
|
|
77
157
|
debug_command("cursor-agent", args: ["-p"], input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
@@ -98,58 +178,6 @@ module Aidp
|
|
|
98
178
|
|
|
99
179
|
private
|
|
100
180
|
|
|
101
|
-
def calculate_timeout
|
|
102
|
-
# Priority order for timeout calculation:
|
|
103
|
-
# 1. Quick mode (for testing)
|
|
104
|
-
# 2. Environment variable override
|
|
105
|
-
# 3. Adaptive timeout based on step type
|
|
106
|
-
# 4. Default timeout
|
|
107
|
-
|
|
108
|
-
if ENV["AIDP_QUICK_MODE"]
|
|
109
|
-
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
|
110
|
-
return TIMEOUT_QUICK_MODE
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
if ENV["AIDP_CURSOR_TIMEOUT"]
|
|
114
|
-
return ENV["AIDP_CURSOR_TIMEOUT"].to_i
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
if adaptive_timeout
|
|
118
|
-
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
|
119
|
-
return adaptive_timeout
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Default timeout
|
|
123
|
-
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
|
124
|
-
TIMEOUT_DEFAULT
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def adaptive_timeout
|
|
128
|
-
@adaptive_timeout ||= begin
|
|
129
|
-
# Timeout recommendations based on step type patterns
|
|
130
|
-
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
131
|
-
|
|
132
|
-
case step_name
|
|
133
|
-
when /REPOSITORY_ANALYSIS/
|
|
134
|
-
TIMEOUT_REPOSITORY_ANALYSIS
|
|
135
|
-
when /ARCHITECTURE_ANALYSIS/
|
|
136
|
-
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
137
|
-
when /TEST_ANALYSIS/
|
|
138
|
-
TIMEOUT_TEST_ANALYSIS
|
|
139
|
-
when /FUNCTIONALITY_ANALYSIS/
|
|
140
|
-
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
141
|
-
when /DOCUMENTATION_ANALYSIS/
|
|
142
|
-
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
143
|
-
when /STATIC_ANALYSIS/
|
|
144
|
-
TIMEOUT_STATIC_ANALYSIS
|
|
145
|
-
when /REFACTORING_RECOMMENDATIONS/
|
|
146
|
-
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
147
|
-
else
|
|
148
|
-
nil # Use default
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
181
|
def activity_callback(state, message, provider)
|
|
154
182
|
# This is now handled by the animated display thread
|
|
155
183
|
# Only print static messages for state changes
|