aidp 0.9.3 → 0.9.5
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 +3 -3
- data/lib/aidp/cli/first_run_wizard.rb +56 -33
- data/lib/aidp/execute/workflow_selector.rb +2 -2
- data/lib/aidp/harness/configuration.rb +1 -1
- data/lib/aidp/harness/simple_user_interface.rb +2 -2
- data/lib/aidp/harness/ui/enhanced_tui.rb +4 -28
- data/lib/aidp/harness/ui/job_monitor.rb +2 -2
- data/lib/aidp/harness/ui/navigation/main_menu.rb +2 -2
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +2 -2
- data/lib/aidp/harness/ui/question_collector.rb +2 -2
- data/lib/aidp/harness/user_interface.rb +2 -2
- data/lib/aidp/version.rb +1 -1
- data/templates/README.md +3 -3
- data/templates/aidp-development.yml.example +2 -2
- data/templates/aidp-production.yml.example +2 -2
- data/templates/aidp.yml.example +4 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12e70b298f80b189c33c7db0a67027086a8441a4fdd5c0ae45045b491c5ca825
|
4
|
+
data.tar.gz: 1f6445fd7ed137c78e4c6000aac0418d15d00856beea9db9afd4d843aad11b4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fab5f97f7874314f0991cd75260175b7aab803d199bb25ab1223fae0d280a7b6a97a11ff160d90b5bc263fc312bc64bb3c95c32e34e31d960c8ab7a403a8778
|
7
|
+
data.tar.gz: 9bf30d28286d09e7d25bb23bd3109e422e91518f7e46113949ed27a87cc722046dc8cfd881f00279c6f849173a6a9f4c503d07b519d7cd7ca53d7cd53a71cf67
|
data/README.md
CHANGED
@@ -76,15 +76,15 @@ The TUI automatically switches providers when:
|
|
76
76
|
# aidp.yml
|
77
77
|
providers:
|
78
78
|
claude:
|
79
|
-
type: "
|
79
|
+
type: "usage_based"
|
80
80
|
api_key: "${AIDP_CLAUDE_API_KEY}"
|
81
81
|
max_tokens: 100000
|
82
82
|
gemini:
|
83
|
-
type: "
|
83
|
+
type: "usage_based"
|
84
84
|
api_key: "${AIDP_GEMINI_API_KEY}"
|
85
85
|
max_tokens: 50000
|
86
86
|
cursor:
|
87
|
-
type: "
|
87
|
+
type: "subscription"
|
88
88
|
```
|
89
89
|
|
90
90
|
### Environment Variables
|
@@ -10,10 +10,10 @@ module Aidp
|
|
10
10
|
class FirstRunWizard
|
11
11
|
TEMPLATES_DIR = File.expand_path(File.join(__dir__, "..", "..", "..", "templates"))
|
12
12
|
|
13
|
-
def self.ensure_config(project_dir, input: $stdin, output: $stdout, non_interactive: false)
|
13
|
+
def self.ensure_config(project_dir, input: $stdin, output: $stdout, non_interactive: false, prompt: TTY::Prompt.new)
|
14
14
|
return true if Aidp::Config.config_exists?(project_dir)
|
15
15
|
|
16
|
-
wizard = new(project_dir, input: input, output: output)
|
16
|
+
wizard = new(project_dir, input: input, output: output, prompt: prompt)
|
17
17
|
|
18
18
|
if non_interactive || !input.tty? || !output.tty?
|
19
19
|
# Non-interactive environment - create minimal config silently
|
@@ -25,8 +25,8 @@ module Aidp
|
|
25
25
|
wizard.run
|
26
26
|
end
|
27
27
|
|
28
|
-
def self.setup_config(project_dir, input: $stdin, output: $stdout, non_interactive: false)
|
29
|
-
wizard = new(project_dir, input: input, output: output)
|
28
|
+
def self.setup_config(project_dir, input: $stdin, output: $stdout, non_interactive: false, prompt: TTY::Prompt.new)
|
29
|
+
wizard = new(project_dir, input: input, output: output, prompt: prompt)
|
30
30
|
|
31
31
|
if non_interactive || !input.tty? || !output.tty?
|
32
32
|
# Non-interactive environment - skip setup
|
@@ -37,11 +37,11 @@ module Aidp
|
|
37
37
|
wizard.run_setup_config
|
38
38
|
end
|
39
39
|
|
40
|
-
def initialize(project_dir, input: $stdin, output: $stdout)
|
40
|
+
def initialize(project_dir, input: $stdin, output: $stdout, prompt: TTY::Prompt.new)
|
41
41
|
@project_dir = project_dir
|
42
42
|
@input = input
|
43
43
|
@output = output
|
44
|
-
@prompt =
|
44
|
+
@prompt = prompt
|
45
45
|
end
|
46
46
|
|
47
47
|
def run
|
@@ -49,11 +49,8 @@ module Aidp
|
|
49
49
|
loop do
|
50
50
|
choice = ask_choice
|
51
51
|
case choice
|
52
|
-
when "1" then return finish(
|
53
|
-
when "2" then return finish(
|
54
|
-
when "3" then return finish(copy_template("aidp-production.yml.example"))
|
55
|
-
when "4" then return finish(write_example_config(@project_dir))
|
56
|
-
when "5" then return finish(run_custom)
|
52
|
+
when "1" then return finish(write_quick_config(@project_dir))
|
53
|
+
when "2" then return finish(run_custom)
|
57
54
|
when "q", "Q" then @output.puts("Exiting without creating configuration.")
|
58
55
|
return false
|
59
56
|
else
|
@@ -92,19 +89,14 @@ module Aidp
|
|
92
89
|
|
93
90
|
def ask_choice
|
94
91
|
@output.puts "Choose a configuration style:" unless @asking
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
@output.print "Enter choice [1]: "
|
104
|
-
@output.flush
|
105
|
-
ans = @input.gets&.strip
|
106
|
-
ans = "1" if ans.nil? || ans.empty?
|
107
|
-
ans
|
92
|
+
|
93
|
+
options = {
|
94
|
+
"Quick setup (cursor + macos, no API keys needed)" => "1",
|
95
|
+
"Custom setup (choose your own providers and settings)" => "2",
|
96
|
+
"Quit" => "q"
|
97
|
+
}
|
98
|
+
|
99
|
+
@prompt.select("Select an option:", options, default: "Quick setup (cursor + macos, no API keys needed)")
|
108
100
|
end
|
109
101
|
|
110
102
|
def finish(path)
|
@@ -133,16 +125,41 @@ module Aidp
|
|
133
125
|
dest = File.join(project_dir, "aidp.yml")
|
134
126
|
return dest if File.exist?(dest)
|
135
127
|
data = {
|
136
|
-
harness
|
137
|
-
max_retries
|
138
|
-
default_provider
|
139
|
-
fallback_providers
|
140
|
-
no_api_keys_required
|
128
|
+
"harness" => {
|
129
|
+
"max_retries" => 2,
|
130
|
+
"default_provider" => "cursor",
|
131
|
+
"fallback_providers" => ["cursor"],
|
132
|
+
"no_api_keys_required" => false
|
133
|
+
},
|
134
|
+
"providers" => {
|
135
|
+
"cursor" => {
|
136
|
+
"type" => "subscription",
|
137
|
+
"default_flags" => []
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
File.write(dest, YAML.dump(data))
|
142
|
+
dest
|
143
|
+
end
|
144
|
+
|
145
|
+
def write_quick_config(project_dir)
|
146
|
+
dest = File.join(project_dir, "aidp.yml")
|
147
|
+
return dest if File.exist?(dest)
|
148
|
+
data = {
|
149
|
+
"harness" => {
|
150
|
+
"max_retries" => 2,
|
151
|
+
"default_provider" => "cursor",
|
152
|
+
"fallback_providers" => ["macos"],
|
153
|
+
"no_api_keys_required" => true
|
141
154
|
},
|
142
|
-
providers
|
143
|
-
cursor
|
144
|
-
type
|
145
|
-
default_flags
|
155
|
+
"providers" => {
|
156
|
+
"cursor" => {
|
157
|
+
"type" => "subscription",
|
158
|
+
"default_flags" => []
|
159
|
+
},
|
160
|
+
"macos" => {
|
161
|
+
"type" => "usage_based",
|
162
|
+
"default_flags" => []
|
146
163
|
}
|
147
164
|
}
|
148
165
|
}
|
@@ -252,6 +269,12 @@ module Aidp
|
|
252
269
|
# Convert existing provider config to string keys
|
253
270
|
converted_provider = {}
|
254
271
|
existing_provider.each { |k, v| converted_provider[k.to_s] = v }
|
272
|
+
# Ensure the type is correct (fix old "package" and "api" types)
|
273
|
+
if converted_provider["type"] == "package"
|
274
|
+
converted_provider["type"] = "subscription"
|
275
|
+
elsif converted_provider["type"] == "api"
|
276
|
+
converted_provider["type"] = "usage_based"
|
277
|
+
end
|
255
278
|
provider_section[prov] = converted_provider
|
256
279
|
else
|
257
280
|
provider_section[prov] = {"type" => (prov == "cursor") ? "subscription" : "usage_based", "default_flags" => []}
|
@@ -6,9 +6,9 @@ module Aidp
|
|
6
6
|
module Execute
|
7
7
|
# Handles interactive workflow selection and project setup
|
8
8
|
class WorkflowSelector
|
9
|
-
def initialize
|
9
|
+
def initialize(prompt: TTY::Prompt.new)
|
10
10
|
@user_input = {}
|
11
|
-
@prompt =
|
11
|
+
@prompt = prompt
|
12
12
|
end
|
13
13
|
|
14
14
|
# Main entry point for interactive workflow selection
|
@@ -47,7 +47,7 @@ module Aidp
|
|
47
47
|
harness_config[:no_api_keys_required]
|
48
48
|
end
|
49
49
|
|
50
|
-
# Get provider type (
|
50
|
+
# Get provider type (usage_based, subscription, etc.)
|
51
51
|
def provider_type(provider_name)
|
52
52
|
provider_config(provider_name)[:type] || "unknown"
|
53
53
|
end
|
@@ -7,8 +7,8 @@ module Aidp
|
|
7
7
|
# Simple, focused user interface for collecting feedback
|
8
8
|
# Replaces the bloated UserInterface with minimal, clean code
|
9
9
|
class SimpleUserInterface
|
10
|
-
def initialize
|
11
|
-
@prompt =
|
10
|
+
def initialize(prompt: TTY::Prompt.new)
|
11
|
+
@prompt = prompt
|
12
12
|
end
|
13
13
|
|
14
14
|
# Main method - collect responses for questions
|
@@ -18,15 +18,17 @@ module Aidp
|
|
18
18
|
class InputError < TUIError; end
|
19
19
|
class DisplayError < TUIError; end
|
20
20
|
|
21
|
-
def initialize
|
21
|
+
def initialize(prompt: TTY::Prompt.new)
|
22
22
|
@cursor = TTY::Cursor
|
23
23
|
@screen = TTY::Screen
|
24
24
|
@pastel = Pastel.new
|
25
|
-
@prompt =
|
25
|
+
@prompt = prompt
|
26
|
+
|
26
27
|
# Headless (non-interactive) detection for test/CI environments:
|
27
28
|
# - RSpec defined or RSPEC_RUNNING env set
|
28
29
|
# - STDIN not a TTY (captured by PTY/tmux harness)
|
29
30
|
@headless = !!(defined?(RSpec) || ENV["RSPEC_RUNNING"] || $stdin.nil? || !$stdin.tty?)
|
31
|
+
|
30
32
|
@current_mode = nil
|
31
33
|
@workflow_active = false
|
32
34
|
@current_step = nil
|
@@ -47,32 +49,6 @@ module Aidp
|
|
47
49
|
restore_screen
|
48
50
|
end
|
49
51
|
|
50
|
-
# Job monitoring methods
|
51
|
-
def add_job(job_id, job_data)
|
52
|
-
@jobs[job_id] = {
|
53
|
-
id: job_id,
|
54
|
-
name: job_data[:name] || job_id,
|
55
|
-
status: job_data[:status] || :pending,
|
56
|
-
progress: job_data[:progress] || 0,
|
57
|
-
started_at: Time.now,
|
58
|
-
message: job_data[:message] || "",
|
59
|
-
provider: job_data[:provider] || "unknown"
|
60
|
-
}
|
61
|
-
@jobs_visible = true
|
62
|
-
end
|
63
|
-
|
64
|
-
def update_job(job_id, updates)
|
65
|
-
return unless @jobs[job_id]
|
66
|
-
|
67
|
-
@jobs[job_id].merge!(updates)
|
68
|
-
@jobs[job_id][:updated_at] = Time.now
|
69
|
-
end
|
70
|
-
|
71
|
-
def remove_job(job_id)
|
72
|
-
@jobs.delete(job_id)
|
73
|
-
@jobs_visible = @jobs.any?
|
74
|
-
end
|
75
|
-
|
76
52
|
# Input methods using TTY::Prompt only - no background threads
|
77
53
|
def get_user_input(prompt = "💬 You: ")
|
78
54
|
@prompt.ask(prompt)
|
@@ -31,9 +31,9 @@ module Aidp
|
|
31
31
|
urgent: "Urgent"
|
32
32
|
}.freeze
|
33
33
|
|
34
|
-
def initialize(ui_components = {})
|
34
|
+
def initialize(ui_components = {}, prompt: TTY::Prompt.new)
|
35
35
|
super()
|
36
|
-
@prompt =
|
36
|
+
@prompt = prompt
|
37
37
|
@pastel = Pastel.new
|
38
38
|
@status_manager = ui_components[:status_manager] || StatusManager.new
|
39
39
|
@frame_manager = ui_components[:frame_manager] || FrameManager.new
|
@@ -17,9 +17,9 @@ module Aidp
|
|
17
17
|
class InvalidMenuError < MenuError; end
|
18
18
|
class NavigationError < MenuError; end
|
19
19
|
|
20
|
-
def initialize(ui_components = {})
|
20
|
+
def initialize(ui_components = {}, prompt: nil)
|
21
21
|
super()
|
22
|
-
@prompt = ui_components[:prompt] || TTY::Prompt.new
|
22
|
+
@prompt = prompt || ui_components[:prompt] || TTY::Prompt.new
|
23
23
|
@pastel = Pastel.new
|
24
24
|
@formatter = ui_components[:formatter] || MenuFormatter.new
|
25
25
|
@state_manager = ui_components[:state_manager] || MenuState.new
|
@@ -28,9 +28,9 @@ module Aidp
|
|
28
28
|
}
|
29
29
|
}.freeze
|
30
30
|
|
31
|
-
def initialize(ui_components = {})
|
31
|
+
def initialize(ui_components = {}, prompt: nil)
|
32
32
|
super()
|
33
|
-
@prompt = ui_components[:prompt] || TTY::Prompt.new
|
33
|
+
@prompt = prompt || ui_components[:prompt] || TTY::Prompt.new
|
34
34
|
@pastel = Pastel.new
|
35
35
|
@formatter = ui_components[:formatter] || WorkflowFormatter.new
|
36
36
|
@state_manager = ui_components[:state_manager]
|
@@ -12,9 +12,9 @@ module Aidp
|
|
12
12
|
class ValidationError < QuestionError; end
|
13
13
|
class CollectionError < QuestionError; end
|
14
14
|
|
15
|
-
def initialize(ui_components = {})
|
15
|
+
def initialize(ui_components = {}, prompt: nil)
|
16
16
|
super()
|
17
|
-
@prompt = ui_components[:prompt] || TTY::Prompt.new
|
17
|
+
@prompt = prompt || ui_components[:prompt] || TTY::Prompt.new
|
18
18
|
@validator = ui_components[:validator] || QuestionValidator.new
|
19
19
|
end
|
20
20
|
|
@@ -6,10 +6,10 @@ module Aidp
|
|
6
6
|
module Harness
|
7
7
|
# Handles user interaction and feedback collection
|
8
8
|
class UserInterface
|
9
|
-
def initialize
|
9
|
+
def initialize(prompt: TTY::Prompt.new)
|
10
10
|
@input_history = []
|
11
11
|
@file_selection_enabled = false
|
12
|
-
@prompt =
|
12
|
+
@prompt = prompt
|
13
13
|
@control_mutex = Mutex.new
|
14
14
|
@pause_requested = false
|
15
15
|
@stop_requested = false
|
data/lib/aidp/version.rb
CHANGED
data/templates/README.md
CHANGED
@@ -102,7 +102,7 @@ The `harness` section controls the overall behavior of the harness system:
|
|
102
102
|
|
103
103
|
The `providers` section defines individual provider settings:
|
104
104
|
|
105
|
-
- `type`: Provider type (
|
105
|
+
- `type`: Provider type (subscription, usage_based, passthrough)
|
106
106
|
- `priority`: Provider priority (higher = more preferred)
|
107
107
|
- `models`: Available models for the provider
|
108
108
|
- `features`: Provider capabilities
|
@@ -172,9 +172,9 @@ time_based:
|
|
172
172
|
|
173
173
|
## Provider Types
|
174
174
|
|
175
|
-
###
|
175
|
+
### Subscription Providers
|
176
176
|
|
177
|
-
- **Type**: `
|
177
|
+
- **Type**: `subscription`
|
178
178
|
- **Pricing**: Fixed monthly/yearly subscription
|
179
179
|
- **Examples**: Cursor Pro
|
180
180
|
- **Configuration**: No API keys needed
|
data/templates/aidp.yml.example
CHANGED
@@ -125,7 +125,7 @@ harness:
|
|
125
125
|
|
126
126
|
# Provider configurations
|
127
127
|
providers:
|
128
|
-
# Cursor provider (
|
128
|
+
# Cursor provider (subscription-based)
|
129
129
|
cursor:
|
130
130
|
type: "subscription" # subscription, usage_based, or passthrough
|
131
131
|
priority: 1 # Provider priority (higher = more preferred)
|
@@ -188,7 +188,7 @@ providers:
|
|
188
188
|
|
189
189
|
# Cost tracking
|
190
190
|
cost:
|
191
|
-
input_cost_per_token: 0.0 #
|
191
|
+
input_cost_per_token: 0.0 # Subscription-based pricing
|
192
192
|
output_cost_per_token: 0.0
|
193
193
|
fixed_cost_per_request: 0.0
|
194
194
|
currency: "USD"
|
@@ -426,8 +426,8 @@ providers:
|
|
426
426
|
# metrics_interval: 60
|
427
427
|
|
428
428
|
# Provider types explained:
|
429
|
-
# - "
|
430
|
-
# - "
|
429
|
+
# - "subscription": Uses subscription-based pricing (e.g., Cursor Pro)
|
430
|
+
# - "usage_based": Uses API-based pricing with token limits
|
431
431
|
# - "passthrough": Uses underlying service (user manages API keys)
|
432
432
|
|
433
433
|
# Environment-specific configurations
|