aidp 0.12.1 → 0.14.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 +7 -0
- data/lib/aidp/analyze/json_file_storage.rb +21 -21
- data/lib/aidp/cli/enhanced_input.rb +114 -0
- data/lib/aidp/cli/first_run_wizard.rb +28 -309
- data/lib/aidp/cli/issue_importer.rb +359 -0
- data/lib/aidp/cli/mcp_dashboard.rb +3 -3
- data/lib/aidp/cli/terminal_io.rb +26 -0
- data/lib/aidp/cli.rb +155 -7
- data/lib/aidp/daemon/process_manager.rb +146 -0
- data/lib/aidp/daemon/runner.rb +232 -0
- data/lib/aidp/execute/async_work_loop_runner.rb +216 -0
- data/lib/aidp/execute/future_work_backlog.rb +411 -0
- data/lib/aidp/execute/guard_policy.rb +246 -0
- data/lib/aidp/execute/instruction_queue.rb +131 -0
- data/lib/aidp/execute/interactive_repl.rb +335 -0
- data/lib/aidp/execute/repl_macros.rb +651 -0
- data/lib/aidp/execute/steps.rb +8 -0
- data/lib/aidp/execute/work_loop_runner.rb +322 -36
- data/lib/aidp/execute/work_loop_state.rb +162 -0
- data/lib/aidp/harness/condition_detector.rb +6 -6
- data/lib/aidp/harness/config_loader.rb +23 -23
- data/lib/aidp/harness/config_manager.rb +61 -61
- data/lib/aidp/harness/config_schema.rb +88 -0
- data/lib/aidp/harness/config_validator.rb +9 -9
- data/lib/aidp/harness/configuration.rb +76 -29
- data/lib/aidp/harness/error_handler.rb +13 -13
- data/lib/aidp/harness/provider_config.rb +79 -79
- data/lib/aidp/harness/provider_factory.rb +40 -40
- data/lib/aidp/harness/provider_info.rb +37 -20
- data/lib/aidp/harness/provider_manager.rb +58 -53
- data/lib/aidp/harness/provider_type_checker.rb +6 -6
- data/lib/aidp/harness/runner.rb +7 -7
- data/lib/aidp/harness/status_display.rb +33 -46
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +4 -1
- data/lib/aidp/harness/ui/job_monitor.rb +7 -7
- data/lib/aidp/harness/user_interface.rb +43 -43
- data/lib/aidp/init/doc_generator.rb +256 -0
- data/lib/aidp/init/project_analyzer.rb +343 -0
- data/lib/aidp/init/runner.rb +83 -0
- data/lib/aidp/init.rb +5 -0
- data/lib/aidp/logger.rb +279 -0
- data/lib/aidp/providers/anthropic.rb +100 -26
- data/lib/aidp/providers/base.rb +13 -0
- data/lib/aidp/providers/codex.rb +28 -27
- data/lib/aidp/providers/cursor.rb +141 -34
- data/lib/aidp/providers/github_copilot.rb +26 -26
- data/lib/aidp/providers/macos_ui.rb +2 -18
- data/lib/aidp/providers/opencode.rb +26 -26
- data/lib/aidp/setup/wizard.rb +777 -0
- data/lib/aidp/tooling_detector.rb +115 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/build_processor.rb +282 -0
- data/lib/aidp/watch/plan_generator.rb +166 -0
- data/lib/aidp/watch/plan_processor.rb +83 -0
- data/lib/aidp/watch/repository_client.rb +243 -0
- data/lib/aidp/watch/runner.rb +93 -0
- data/lib/aidp/watch/state_store.rb +105 -0
- data/lib/aidp/watch.rb +9 -0
- data/lib/aidp/workflows/guided_agent.rb +344 -23
- data/lib/aidp.rb +14 -0
- data/templates/implementation/simple_task.md +36 -0
- metadata +27 -1
data/lib/aidp/logger.rb
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "logger"
|
|
4
|
+
require "json"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
|
|
7
|
+
module Aidp
|
|
8
|
+
# Unified structured logger for all AIDP operations
|
|
9
|
+
# Supports:
|
|
10
|
+
# - Multiple log levels (info, error, debug)
|
|
11
|
+
# - Text and JSONL formats
|
|
12
|
+
# - Automatic rotation
|
|
13
|
+
# - Redaction of secrets
|
|
14
|
+
# - Consistent file layout in .aidp/logs/
|
|
15
|
+
#
|
|
16
|
+
# Usage:
|
|
17
|
+
# Aidp.setup_logger(project_dir, config)
|
|
18
|
+
# Aidp.logger.info("component", "message", key: "value")
|
|
19
|
+
class AidpLogger
|
|
20
|
+
LEVELS = {
|
|
21
|
+
debug: ::Logger::DEBUG,
|
|
22
|
+
info: ::Logger::INFO,
|
|
23
|
+
warn: ::Logger::WARN,
|
|
24
|
+
error: ::Logger::ERROR
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
LOG_DIR = ".aidp/logs"
|
|
28
|
+
INFO_LOG = "#{LOG_DIR}/aidp.log"
|
|
29
|
+
DEBUG_LOG = "#{LOG_DIR}/aidp_debug.log"
|
|
30
|
+
|
|
31
|
+
DEFAULT_MAX_SIZE = 10 * 1024 * 1024 # 10MB
|
|
32
|
+
DEFAULT_MAX_FILES = 5
|
|
33
|
+
|
|
34
|
+
attr_reader :level, :json_format
|
|
35
|
+
|
|
36
|
+
def initialize(project_dir = Dir.pwd, config = {})
|
|
37
|
+
@project_dir = project_dir
|
|
38
|
+
@config = config
|
|
39
|
+
@level = determine_log_level
|
|
40
|
+
@json_format = config[:json] || false
|
|
41
|
+
@max_size = config[:max_size_mb] ? config[:max_size_mb] * 1024 * 1024 : DEFAULT_MAX_SIZE
|
|
42
|
+
@max_files = config[:max_backups] || DEFAULT_MAX_FILES
|
|
43
|
+
|
|
44
|
+
ensure_log_directory
|
|
45
|
+
migrate_old_logs if should_migrate?
|
|
46
|
+
setup_loggers
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Log info level message
|
|
50
|
+
def info(component, message, **metadata)
|
|
51
|
+
log(:info, component, message, **metadata)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Log error level message
|
|
55
|
+
def error(component, message, **metadata)
|
|
56
|
+
log(:error, component, message, **metadata)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Log warn level message
|
|
60
|
+
def warn(component, message, **metadata)
|
|
61
|
+
log(:warn, component, message, **metadata)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Log debug level message
|
|
65
|
+
def debug(component, message, **metadata)
|
|
66
|
+
log(:debug, component, message, **metadata)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Log at specified level
|
|
70
|
+
def log(level, component, message, **metadata)
|
|
71
|
+
return unless should_log?(level)
|
|
72
|
+
|
|
73
|
+
# Redact sensitive data
|
|
74
|
+
safe_message = redact(message)
|
|
75
|
+
safe_metadata = redact_hash(metadata)
|
|
76
|
+
|
|
77
|
+
# Log to appropriate file(s)
|
|
78
|
+
if level == :debug
|
|
79
|
+
write_to_debug(level, component, safe_message, safe_metadata)
|
|
80
|
+
else
|
|
81
|
+
write_to_info(level, component, safe_message, safe_metadata)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Always log errors to both files
|
|
85
|
+
if level == :error
|
|
86
|
+
write_to_debug(level, component, safe_message, safe_metadata)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Close all loggers
|
|
91
|
+
def close
|
|
92
|
+
@info_logger&.close
|
|
93
|
+
@debug_logger&.close
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def determine_log_level
|
|
99
|
+
# Priority: ENV > config > default
|
|
100
|
+
level_str = ENV["AIDP_LOG_LEVEL"] || @config[:level] || "info"
|
|
101
|
+
level_sym = level_str.to_sym
|
|
102
|
+
LEVELS.key?(level_sym) ? level_sym : :info
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def should_log?(level)
|
|
106
|
+
LEVELS[level] >= LEVELS[@level]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def ensure_log_directory
|
|
110
|
+
log_dir = File.join(@project_dir, LOG_DIR)
|
|
111
|
+
FileUtils.mkdir_p(log_dir) unless Dir.exist?(log_dir)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def setup_loggers
|
|
115
|
+
info_path = File.join(@project_dir, INFO_LOG)
|
|
116
|
+
debug_path = File.join(@project_dir, DEBUG_LOG)
|
|
117
|
+
|
|
118
|
+
@info_logger = create_logger(info_path)
|
|
119
|
+
@debug_logger = create_logger(debug_path)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def create_logger(path)
|
|
123
|
+
logger = ::Logger.new(path, @max_files, @max_size)
|
|
124
|
+
logger.level = ::Logger::DEBUG # Control at write level instead
|
|
125
|
+
logger.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" }
|
|
126
|
+
logger
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def write_to_info(level, component, message, metadata)
|
|
130
|
+
entry = format_entry(level, component, message, metadata)
|
|
131
|
+
@info_logger.send(logger_method(level), entry)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def write_to_debug(level, component, message, metadata)
|
|
135
|
+
entry = format_entry(level, component, message, metadata)
|
|
136
|
+
@debug_logger.send(logger_method(level), entry)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def logger_method(level)
|
|
140
|
+
case level
|
|
141
|
+
when :debug then :debug
|
|
142
|
+
when :info then :info
|
|
143
|
+
when :warn then :warn
|
|
144
|
+
when :error then :error
|
|
145
|
+
else :info
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def format_entry(level, component, message, metadata)
|
|
150
|
+
if @json_format
|
|
151
|
+
format_json(level, component, message, metadata)
|
|
152
|
+
else
|
|
153
|
+
format_text(level, component, message, metadata)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def format_text(level, component, message, metadata)
|
|
158
|
+
timestamp = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ")
|
|
159
|
+
level_str = level.to_s.upcase
|
|
160
|
+
parts = ["#{timestamp} #{level_str} #{component} #{message}"]
|
|
161
|
+
|
|
162
|
+
unless metadata.empty?
|
|
163
|
+
metadata_str = metadata.map { |k, v| "#{k}=#{redact(v.to_s)}" }.join(" ")
|
|
164
|
+
parts << "(#{metadata_str})"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
parts.join(" ")
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def format_json(level, component, message, metadata)
|
|
171
|
+
entry = {
|
|
172
|
+
ts: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ"),
|
|
173
|
+
level: level.to_s,
|
|
174
|
+
component: component,
|
|
175
|
+
msg: message
|
|
176
|
+
}.merge(metadata)
|
|
177
|
+
|
|
178
|
+
JSON.generate(entry)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Redaction patterns for common secrets
|
|
182
|
+
REDACTION_PATTERNS = [
|
|
183
|
+
# API keys and tokens (with capture groups)
|
|
184
|
+
[/\b(api[_-]?key|token|secret|password|passwd|pwd)[=:]\s*['"]?([^\s'")]+)['"]?/i, '\1=<REDACTED>'],
|
|
185
|
+
# Bearer tokens
|
|
186
|
+
[/Bearer\s+[A-Za-z0-9\-._~+\/]+=*/, "<REDACTED>"],
|
|
187
|
+
# GitHub tokens
|
|
188
|
+
[/\bgh[ps]_[A-Za-z0-9_]{36,}/, "<REDACTED>"],
|
|
189
|
+
# AWS keys
|
|
190
|
+
[/\bAKIA[0-9A-Z]{16}/, "<REDACTED>"],
|
|
191
|
+
# Generic secrets in key=value format
|
|
192
|
+
[/\b(secret|credentials?|auth)[=:]\s*['"]?([^\s'")]{8,})['"]?/i, '\1=<REDACTED>']
|
|
193
|
+
].freeze
|
|
194
|
+
|
|
195
|
+
def redact(text)
|
|
196
|
+
return text unless text.is_a?(String)
|
|
197
|
+
|
|
198
|
+
redacted = text.dup
|
|
199
|
+
REDACTION_PATTERNS.each do |pattern, replacement|
|
|
200
|
+
redacted.gsub!(pattern, replacement)
|
|
201
|
+
end
|
|
202
|
+
redacted
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def redact_hash(hash)
|
|
206
|
+
hash.transform_values { |v| v.is_a?(String) ? redact(v) : v }
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Migration from old debug_logs location
|
|
210
|
+
OLD_DEBUG_DIR = ".aidp/debug_logs"
|
|
211
|
+
OLD_DEBUG_LOG = "#{OLD_DEBUG_DIR}/aidp_debug.log"
|
|
212
|
+
|
|
213
|
+
def should_migrate?
|
|
214
|
+
old_path = File.join(@project_dir, OLD_DEBUG_LOG)
|
|
215
|
+
new_path = File.join(@project_dir, DEBUG_LOG)
|
|
216
|
+
|
|
217
|
+
# Migrate if old exists and new doesn't
|
|
218
|
+
File.exist?(old_path) && !File.exist?(new_path)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def migrate_old_logs
|
|
222
|
+
old_path = File.join(@project_dir, OLD_DEBUG_LOG)
|
|
223
|
+
new_path = File.join(@project_dir, DEBUG_LOG)
|
|
224
|
+
|
|
225
|
+
begin
|
|
226
|
+
FileUtils.mv(old_path, new_path)
|
|
227
|
+
log_migration_notice
|
|
228
|
+
rescue => e
|
|
229
|
+
# If migration fails, just continue (new logs will be created)
|
|
230
|
+
warn "Failed to migrate old logs: #{e.message}"
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def log_migration_notice
|
|
235
|
+
notice = format_text(
|
|
236
|
+
:info,
|
|
237
|
+
"migration",
|
|
238
|
+
"Logs migrated from .aidp/debug_logs/ to .aidp/logs/",
|
|
239
|
+
timestamp: Time.now.utc.iso8601
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# Write directly to avoid recursion
|
|
243
|
+
info_path = File.join(@project_dir, INFO_LOG)
|
|
244
|
+
File.open(info_path, "a") do |f|
|
|
245
|
+
f.puts notice
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Module-level logger accessor
|
|
251
|
+
class << self
|
|
252
|
+
# Set up global logger instance
|
|
253
|
+
def setup_logger(project_dir = Dir.pwd, config = {})
|
|
254
|
+
@logger = AidpLogger.new(project_dir, config)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Get current logger instance (creates default if not set up)
|
|
258
|
+
def logger
|
|
259
|
+
@logger ||= AidpLogger.new
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Convenience logging methods
|
|
263
|
+
def log_info(component, message, **metadata)
|
|
264
|
+
logger.info(component, message, **metadata)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def log_error(component, message, **metadata)
|
|
268
|
+
logger.error(component, message, **metadata)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def log_warn(component, message, **metadata)
|
|
272
|
+
logger.warn(component, message, **metadata)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def log_debug(component, message, **metadata)
|
|
276
|
+
logger.debug(component, message, **metadata)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
@@ -21,6 +21,25 @@ module Aidp
|
|
|
21
21
|
"Anthropic Claude CLI"
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def supports_mcp?
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def fetch_mcp_servers
|
|
29
|
+
return [] unless self.class.available?
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
# Use claude mcp list command
|
|
33
|
+
result = debug_execute_command("claude", args: ["mcp", "list"], timeout: 5)
|
|
34
|
+
return [] unless result.exit_status == 0
|
|
35
|
+
|
|
36
|
+
parse_claude_mcp_output(result.out)
|
|
37
|
+
rescue => e
|
|
38
|
+
debug_log("Failed to fetch MCP servers via Claude CLI: #{e.message}", level: :debug)
|
|
39
|
+
[]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
24
43
|
def available?
|
|
25
44
|
self.class.available?
|
|
26
45
|
end
|
|
@@ -101,11 +120,9 @@ module Aidp
|
|
|
101
120
|
return ENV["AIDP_ANTHROPIC_TIMEOUT"].to_i
|
|
102
121
|
end
|
|
103
122
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
108
|
-
return step_timeout
|
|
123
|
+
if adaptive_timeout
|
|
124
|
+
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
|
125
|
+
return adaptive_timeout
|
|
109
126
|
end
|
|
110
127
|
|
|
111
128
|
# Default timeout
|
|
@@ -113,27 +130,29 @@ module Aidp
|
|
|
113
130
|
TIMEOUT_DEFAULT
|
|
114
131
|
end
|
|
115
132
|
|
|
116
|
-
def
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
def adaptive_timeout
|
|
134
|
+
@adaptive_timeout ||= begin
|
|
135
|
+
# Timeout recommendations based on step type patterns
|
|
136
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
137
|
+
|
|
138
|
+
case step_name
|
|
139
|
+
when /REPOSITORY_ANALYSIS/
|
|
140
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
|
141
|
+
when /ARCHITECTURE_ANALYSIS/
|
|
142
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
143
|
+
when /TEST_ANALYSIS/
|
|
144
|
+
TIMEOUT_TEST_ANALYSIS
|
|
145
|
+
when /FUNCTIONALITY_ANALYSIS/
|
|
146
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
147
|
+
when /DOCUMENTATION_ANALYSIS/
|
|
148
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
149
|
+
when /STATIC_ANALYSIS/
|
|
150
|
+
TIMEOUT_STATIC_ANALYSIS
|
|
151
|
+
when /REFACTORING_RECOMMENDATIONS/
|
|
152
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
153
|
+
else
|
|
154
|
+
nil # Use default
|
|
155
|
+
end
|
|
137
156
|
end
|
|
138
157
|
end
|
|
139
158
|
|
|
@@ -184,6 +203,61 @@ module Aidp
|
|
|
184
203
|
# Return original output if parsing fails
|
|
185
204
|
output
|
|
186
205
|
end
|
|
206
|
+
|
|
207
|
+
# Parse Claude MCP server list output
|
|
208
|
+
def parse_claude_mcp_output(output)
|
|
209
|
+
servers = []
|
|
210
|
+
return servers unless output
|
|
211
|
+
|
|
212
|
+
lines = output.lines
|
|
213
|
+
lines.reject! { |line| /checking mcp server health/i.match?(line) }
|
|
214
|
+
|
|
215
|
+
lines.each do |line|
|
|
216
|
+
line = line.strip
|
|
217
|
+
next if line.empty?
|
|
218
|
+
|
|
219
|
+
# Try to parse Claude format: "name: command - ✓ Connected"
|
|
220
|
+
if line =~ /^([^:]+):\s*(.+?)\s*-\s*(✓|✗)\s*(.+)$/
|
|
221
|
+
name = Regexp.last_match(1).strip
|
|
222
|
+
command = Regexp.last_match(2).strip
|
|
223
|
+
status_symbol = Regexp.last_match(3)
|
|
224
|
+
status_text = Regexp.last_match(4).strip
|
|
225
|
+
|
|
226
|
+
servers << {
|
|
227
|
+
name: name,
|
|
228
|
+
status: (status_symbol == "✓") ? "connected" : "error",
|
|
229
|
+
description: command,
|
|
230
|
+
enabled: status_symbol == "✓",
|
|
231
|
+
error: (status_symbol == "✗") ? status_text : nil,
|
|
232
|
+
source: "claude_cli"
|
|
233
|
+
}
|
|
234
|
+
next
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Try to parse legacy table format
|
|
238
|
+
next if /Name.*Status/i.match?(line)
|
|
239
|
+
next if /^[-=]+$/.match?(line)
|
|
240
|
+
|
|
241
|
+
parts = line.split(/\s{2,}/)
|
|
242
|
+
next if parts.size < 2
|
|
243
|
+
|
|
244
|
+
name = parts[0]&.strip
|
|
245
|
+
status = parts[1]&.strip
|
|
246
|
+
description = parts[2..]&.join(" ")&.strip
|
|
247
|
+
|
|
248
|
+
next unless name && !name.empty?
|
|
249
|
+
|
|
250
|
+
servers << {
|
|
251
|
+
name: name,
|
|
252
|
+
status: status || "unknown",
|
|
253
|
+
description: description,
|
|
254
|
+
enabled: status&.downcase == "enabled" || status&.downcase == "connected",
|
|
255
|
+
source: "claude_cli"
|
|
256
|
+
}
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
servers
|
|
260
|
+
end
|
|
187
261
|
end
|
|
188
262
|
end
|
|
189
263
|
end
|
data/lib/aidp/providers/base.rb
CHANGED
|
@@ -73,6 +73,19 @@ module Aidp
|
|
|
73
73
|
raise NotImplementedError, "#{self.class} must implement #send"
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
# Fetch MCP servers configured for this provider
|
|
77
|
+
# Returns an array of server hashes with keys: :name, :status, :description, :enabled
|
|
78
|
+
# Override in subclasses to provide provider-specific MCP server detection
|
|
79
|
+
def fetch_mcp_servers
|
|
80
|
+
[]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Check if this provider supports MCP servers
|
|
84
|
+
# Override in subclasses to provide accurate MCP support detection
|
|
85
|
+
def supports_mcp?
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
|
|
76
89
|
# Set job context for background execution
|
|
77
90
|
def set_job_context(job_id:, execution_id:, job_manager:)
|
|
78
91
|
@job_context = {
|
data/lib/aidp/providers/codex.rb
CHANGED
|
@@ -120,8 +120,9 @@ module Aidp
|
|
|
120
120
|
args += ["--model", model]
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
-
# Add approval flag
|
|
123
|
+
# Add approval flag - but warn about interactive behavior
|
|
124
124
|
if ask_for_approval
|
|
125
|
+
debug_log("⚠️ WARNING: --ask-for-approval flag may cause interactive prompts that could hang AIDP", level: :warn)
|
|
125
126
|
args += ["--ask-for-approval"]
|
|
126
127
|
end
|
|
127
128
|
|
|
@@ -196,11 +197,9 @@ module Aidp
|
|
|
196
197
|
return ENV["AIDP_CODEX_TIMEOUT"].to_i
|
|
197
198
|
end
|
|
198
199
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
display_message("🧠 Using adaptive timeout: #{step_timeout} seconds", type: :info)
|
|
203
|
-
return step_timeout
|
|
200
|
+
if adaptive_timeout
|
|
201
|
+
display_message("🧠 Using adaptive timeout: #{adaptive_timeout} seconds", type: :info)
|
|
202
|
+
return adaptive_timeout
|
|
204
203
|
end
|
|
205
204
|
|
|
206
205
|
# Default timeout
|
|
@@ -208,27 +207,29 @@ module Aidp
|
|
|
208
207
|
TIMEOUT_DEFAULT
|
|
209
208
|
end
|
|
210
209
|
|
|
211
|
-
def
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
210
|
+
def adaptive_timeout
|
|
211
|
+
@adaptive_timeout ||= begin
|
|
212
|
+
# Timeout recommendations based on step type patterns
|
|
213
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
|
214
|
+
|
|
215
|
+
case step_name
|
|
216
|
+
when /REPOSITORY_ANALYSIS/
|
|
217
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
|
218
|
+
when /ARCHITECTURE_ANALYSIS/
|
|
219
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
|
220
|
+
when /TEST_ANALYSIS/
|
|
221
|
+
TIMEOUT_TEST_ANALYSIS
|
|
222
|
+
when /FUNCTIONALITY_ANALYSIS/
|
|
223
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
|
224
|
+
when /DOCUMENTATION_ANALYSIS/
|
|
225
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
|
226
|
+
when /STATIC_ANALYSIS/
|
|
227
|
+
TIMEOUT_STATIC_ANALYSIS
|
|
228
|
+
when /REFACTORING_RECOMMENDATIONS/
|
|
229
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
|
230
|
+
else
|
|
231
|
+
nil # Use default
|
|
232
|
+
end
|
|
232
233
|
end
|
|
233
234
|
end
|
|
234
235
|
|