aidp 0.5.0 → 0.8.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 +128 -151
- data/bin/aidp +1 -1
- data/lib/aidp/analysis/kb_inspector.rb +471 -0
- data/lib/aidp/analysis/seams.rb +159 -0
- data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +480 -0
- data/lib/aidp/analysis/tree_sitter_scan.rb +686 -0
- data/lib/aidp/analyze/error_handler.rb +2 -78
- data/lib/aidp/analyze/json_file_storage.rb +292 -0
- data/lib/aidp/analyze/progress.rb +12 -0
- data/lib/aidp/analyze/progress_visualizer.rb +12 -17
- data/lib/aidp/analyze/ruby_maat_integration.rb +13 -31
- data/lib/aidp/analyze/runner.rb +256 -87
- data/lib/aidp/analyze/steps.rb +6 -0
- data/lib/aidp/cli/jobs_command.rb +103 -435
- data/lib/aidp/cli.rb +317 -191
- data/lib/aidp/config.rb +298 -10
- data/lib/aidp/debug_logger.rb +195 -0
- data/lib/aidp/debug_mixin.rb +187 -0
- data/lib/aidp/execute/progress.rb +9 -0
- data/lib/aidp/execute/runner.rb +221 -40
- data/lib/aidp/execute/steps.rb +17 -7
- data/lib/aidp/execute/workflow_selector.rb +211 -0
- data/lib/aidp/harness/completion_checker.rb +268 -0
- data/lib/aidp/harness/condition_detector.rb +1526 -0
- data/lib/aidp/harness/config_loader.rb +373 -0
- data/lib/aidp/harness/config_manager.rb +382 -0
- data/lib/aidp/harness/config_schema.rb +1006 -0
- data/lib/aidp/harness/config_validator.rb +355 -0
- data/lib/aidp/harness/configuration.rb +477 -0
- data/lib/aidp/harness/enhanced_runner.rb +494 -0
- data/lib/aidp/harness/error_handler.rb +616 -0
- data/lib/aidp/harness/provider_config.rb +423 -0
- data/lib/aidp/harness/provider_factory.rb +306 -0
- data/lib/aidp/harness/provider_manager.rb +1269 -0
- data/lib/aidp/harness/provider_type_checker.rb +88 -0
- data/lib/aidp/harness/runner.rb +411 -0
- data/lib/aidp/harness/state/errors.rb +28 -0
- data/lib/aidp/harness/state/metrics.rb +219 -0
- data/lib/aidp/harness/state/persistence.rb +128 -0
- data/lib/aidp/harness/state/provider_state.rb +132 -0
- data/lib/aidp/harness/state/ui_state.rb +68 -0
- data/lib/aidp/harness/state/workflow_state.rb +123 -0
- data/lib/aidp/harness/state_manager.rb +586 -0
- data/lib/aidp/harness/status_display.rb +888 -0
- data/lib/aidp/harness/ui/base.rb +16 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
- data/lib/aidp/harness/ui/error_handler.rb +132 -0
- data/lib/aidp/harness/ui/frame_manager.rb +361 -0
- data/lib/aidp/harness/ui/job_monitor.rb +500 -0
- data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
- data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
- data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
- data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
- data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
- data/lib/aidp/harness/ui/progress_display.rb +280 -0
- data/lib/aidp/harness/ui/question_collector.rb +141 -0
- data/lib/aidp/harness/ui/spinner_group.rb +184 -0
- data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
- data/lib/aidp/harness/ui/status_manager.rb +312 -0
- data/lib/aidp/harness/ui/status_widget.rb +280 -0
- data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
- data/lib/aidp/harness/user_interface.rb +2381 -0
- data/lib/aidp/provider_manager.rb +131 -7
- data/lib/aidp/providers/anthropic.rb +28 -109
- data/lib/aidp/providers/base.rb +170 -0
- data/lib/aidp/providers/cursor.rb +52 -183
- data/lib/aidp/providers/gemini.rb +24 -109
- data/lib/aidp/providers/macos_ui.rb +99 -5
- data/lib/aidp/providers/opencode.rb +194 -0
- data/lib/aidp/storage/csv_storage.rb +172 -0
- data/lib/aidp/storage/file_manager.rb +214 -0
- data/lib/aidp/storage/json_storage.rb +140 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp.rb +56 -35
- data/templates/ANALYZE/06a_tree_sitter_scan.md +217 -0
- data/templates/COMMON/AGENT_BASE.md +11 -0
- data/templates/EXECUTE/00_PRD.md +4 -4
- data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
- data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
- data/templates/EXECUTE/08_TASKS.md +4 -4
- data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
- data/templates/README.md +279 -0
- data/templates/aidp-development.yml.example +373 -0
- data/templates/aidp-minimal.yml.example +48 -0
- data/templates/aidp-production.yml.example +475 -0
- data/templates/aidp.yml.example +598 -0
- metadata +106 -64
- data/lib/aidp/analyze/agent_personas.rb +0 -71
- data/lib/aidp/analyze/agent_tool_executor.rb +0 -445
- data/lib/aidp/analyze/data_retention_manager.rb +0 -426
- data/lib/aidp/analyze/database.rb +0 -260
- data/lib/aidp/analyze/dependencies.rb +0 -335
- data/lib/aidp/analyze/export_manager.rb +0 -425
- data/lib/aidp/analyze/focus_guidance.rb +0 -517
- data/lib/aidp/analyze/incremental_analyzer.rb +0 -543
- data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
- data/lib/aidp/analyze/large_analysis_progress.rb +0 -504
- data/lib/aidp/analyze/memory_manager.rb +0 -365
- data/lib/aidp/analyze/metrics_storage.rb +0 -336
- data/lib/aidp/analyze/parallel_processor.rb +0 -460
- data/lib/aidp/analyze/performance_optimizer.rb +0 -694
- data/lib/aidp/analyze/repository_chunker.rb +0 -704
- data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
- data/lib/aidp/analyze/storage.rb +0 -662
- data/lib/aidp/analyze/tool_configuration.rb +0 -456
- data/lib/aidp/analyze/tool_modernization.rb +0 -750
- data/lib/aidp/database/pg_adapter.rb +0 -148
- data/lib/aidp/database_config.rb +0 -69
- data/lib/aidp/database_connection.rb +0 -72
- data/lib/aidp/database_migration.rb +0 -158
- data/lib/aidp/job_manager.rb +0 -41
- data/lib/aidp/jobs/base_job.rb +0 -47
- data/lib/aidp/jobs/provider_execution_job.rb +0 -96
- data/lib/aidp/project_detector.rb +0 -117
- data/lib/aidp/providers/agent_supervisor.rb +0 -348
- data/lib/aidp/providers/supervised_base.rb +0 -317
- data/lib/aidp/providers/supervised_cursor.rb +0 -22
- data/lib/aidp/sync.rb +0 -13
- data/lib/aidp/workspace.rb +0 -19
@@ -1,148 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Aidp
|
4
|
-
module Database
|
5
|
-
class PgAdapter
|
6
|
-
def initialize(connection)
|
7
|
-
@connection = connection
|
8
|
-
end
|
9
|
-
|
10
|
-
def execute(sql, params = [])
|
11
|
-
result = @connection.exec_params(sql, params)
|
12
|
-
result.to_a.map { |row| row.transform_keys(&:to_sym) }
|
13
|
-
end
|
14
|
-
|
15
|
-
def in_transaction?
|
16
|
-
@connection.transaction_status != PG::PQTRANS_IDLE
|
17
|
-
end
|
18
|
-
|
19
|
-
def checkout
|
20
|
-
yield self
|
21
|
-
end
|
22
|
-
|
23
|
-
def after_commit
|
24
|
-
yield
|
25
|
-
end
|
26
|
-
|
27
|
-
def server_version
|
28
|
-
@connection.server_version
|
29
|
-
end
|
30
|
-
|
31
|
-
def transaction_status
|
32
|
-
@connection.transaction_status
|
33
|
-
end
|
34
|
-
|
35
|
-
def transaction
|
36
|
-
@connection.transaction do
|
37
|
-
yield
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def quote_table_name(name)
|
42
|
-
"\"#{name}\""
|
43
|
-
end
|
44
|
-
|
45
|
-
def quote_identifier(name)
|
46
|
-
"\"#{name}\""
|
47
|
-
end
|
48
|
-
|
49
|
-
def quote_string(string)
|
50
|
-
"'#{string.gsub("'", "''")}'"
|
51
|
-
end
|
52
|
-
|
53
|
-
def quote_date(date)
|
54
|
-
date.strftime("%Y-%m-%d")
|
55
|
-
end
|
56
|
-
|
57
|
-
def quote_time(time)
|
58
|
-
time.strftime("%Y-%m-%d %H:%M:%S.%6N %z")
|
59
|
-
end
|
60
|
-
|
61
|
-
# Additional methods required by Que
|
62
|
-
def async_connection
|
63
|
-
self
|
64
|
-
end
|
65
|
-
|
66
|
-
def wait_for_notify(timeout = nil)
|
67
|
-
@connection.wait_for_notify(timeout)
|
68
|
-
end
|
69
|
-
|
70
|
-
def listen(channel)
|
71
|
-
@connection.exec("LISTEN #{quote_identifier(channel)}")
|
72
|
-
end
|
73
|
-
|
74
|
-
def unlisten(channel)
|
75
|
-
@connection.exec("UNLISTEN #{quote_identifier(channel)}")
|
76
|
-
end
|
77
|
-
|
78
|
-
def unlisten_all
|
79
|
-
@connection.exec("UNLISTEN *")
|
80
|
-
end
|
81
|
-
|
82
|
-
def notifications
|
83
|
-
@connection.notifications
|
84
|
-
end
|
85
|
-
|
86
|
-
def reset
|
87
|
-
@connection.reset
|
88
|
-
end
|
89
|
-
|
90
|
-
def type_map_for_queries
|
91
|
-
@connection.type_map_for_queries
|
92
|
-
end
|
93
|
-
|
94
|
-
def type_map_for_results
|
95
|
-
@connection.type_map_for_results
|
96
|
-
end
|
97
|
-
|
98
|
-
# Additional methods for Que compatibility
|
99
|
-
def adapter_name
|
100
|
-
"pg"
|
101
|
-
end
|
102
|
-
|
103
|
-
def active?
|
104
|
-
@connection.status == PG::CONNECTION_OK
|
105
|
-
end
|
106
|
-
|
107
|
-
def disconnect!
|
108
|
-
@connection.close
|
109
|
-
end
|
110
|
-
|
111
|
-
def reconnect!
|
112
|
-
@connection.reset
|
113
|
-
end
|
114
|
-
|
115
|
-
def raw_connection
|
116
|
-
@connection
|
117
|
-
end
|
118
|
-
|
119
|
-
def schema_search_path
|
120
|
-
execute("SHOW search_path")[0][:search_path]
|
121
|
-
end
|
122
|
-
|
123
|
-
def schema_search_path=(path)
|
124
|
-
execute("SET search_path TO #{path}")
|
125
|
-
end
|
126
|
-
|
127
|
-
def table_exists?(name)
|
128
|
-
execute(<<~SQL, [name]).any?
|
129
|
-
SELECT 1
|
130
|
-
FROM pg_tables
|
131
|
-
WHERE tablename = $1
|
132
|
-
SQL
|
133
|
-
end
|
134
|
-
|
135
|
-
def advisory_lock(id)
|
136
|
-
execute("SELECT pg_advisory_lock($1)", [id])
|
137
|
-
end
|
138
|
-
|
139
|
-
def advisory_unlock(id)
|
140
|
-
execute("SELECT pg_advisory_unlock($1)", [id])
|
141
|
-
end
|
142
|
-
|
143
|
-
def advisory_unlock_all
|
144
|
-
execute("SELECT pg_advisory_unlock_all()")
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
data/lib/aidp/database_config.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "yaml"
|
4
|
-
require "fileutils"
|
5
|
-
|
6
|
-
module Aidp
|
7
|
-
class DatabaseConfig
|
8
|
-
DEFAULT_CONFIG = {
|
9
|
-
"database" => {
|
10
|
-
"adapter" => "postgresql",
|
11
|
-
"host" => "localhost",
|
12
|
-
"port" => 5432,
|
13
|
-
"database" => "aidp",
|
14
|
-
"username" => ENV["USER"],
|
15
|
-
"password" => nil,
|
16
|
-
"pool" => 5,
|
17
|
-
"timeout" => 5000
|
18
|
-
}
|
19
|
-
}.freeze
|
20
|
-
|
21
|
-
def self.load(project_dir = Dir.pwd)
|
22
|
-
new(project_dir).load
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize(project_dir)
|
26
|
-
@project_dir = project_dir
|
27
|
-
@config_file = File.join(project_dir, ".aidp-config.yml")
|
28
|
-
end
|
29
|
-
|
30
|
-
def load
|
31
|
-
ensure_config_exists
|
32
|
-
config = YAML.load_file(@config_file)
|
33
|
-
validate_config(config)
|
34
|
-
config["database"]
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def ensure_config_exists
|
40
|
-
return if File.exist?(@config_file)
|
41
|
-
|
42
|
-
# Create config directory if it doesn't exist
|
43
|
-
FileUtils.mkdir_p(File.dirname(@config_file))
|
44
|
-
|
45
|
-
# Write default config
|
46
|
-
File.write(@config_file, YAML.dump(DEFAULT_CONFIG))
|
47
|
-
|
48
|
-
puts "Created default database configuration at #{@config_file}"
|
49
|
-
puts "Please update the configuration with your database settings"
|
50
|
-
end
|
51
|
-
|
52
|
-
def validate_config(config)
|
53
|
-
unless config.is_a?(Hash) && config["database"].is_a?(Hash)
|
54
|
-
raise "Invalid configuration format in #{@config_file}"
|
55
|
-
end
|
56
|
-
|
57
|
-
required_keys = %w[adapter host port database username]
|
58
|
-
missing_keys = required_keys - config["database"].keys
|
59
|
-
|
60
|
-
unless missing_keys.empty?
|
61
|
-
raise "Missing required configuration keys: #{missing_keys.join(", ")}"
|
62
|
-
end
|
63
|
-
|
64
|
-
unless config["database"]["adapter"] == "postgresql"
|
65
|
-
raise "Only PostgreSQL is supported as a database adapter"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pg"
|
4
|
-
require "que"
|
5
|
-
require "sequel"
|
6
|
-
|
7
|
-
module Aidp
|
8
|
-
class DatabaseConnection
|
9
|
-
class << self
|
10
|
-
def initialize_mutex
|
11
|
-
@mutex ||= Mutex.new
|
12
|
-
end
|
13
|
-
|
14
|
-
def establish_connection
|
15
|
-
initialize_mutex
|
16
|
-
@mutex.synchronize do
|
17
|
-
# Return existing connection if already established
|
18
|
-
return @connection if @connection && !@connection.finished?
|
19
|
-
@connection = PG.connect(connection_params)
|
20
|
-
@sequel_db = Sequel.connect(
|
21
|
-
adapter: "postgres",
|
22
|
-
host: ENV["AIDP_DB_HOST"] || "localhost",
|
23
|
-
port: (ENV["AIDP_DB_PORT"] || 5432).to_i,
|
24
|
-
database: ENV["AIDP_DB_NAME"] || "aidp",
|
25
|
-
user: ENV["AIDP_DB_USER"] || ENV["USER"],
|
26
|
-
password: ENV["AIDP_DB_PASSWORD"]
|
27
|
-
)
|
28
|
-
Que.connection = @sequel_db
|
29
|
-
Que.migrate!(version: Que::Migrations::CURRENT_VERSION)
|
30
|
-
@connection
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def connection
|
35
|
-
return @connection if @connection && !@connection.finished?
|
36
|
-
establish_connection
|
37
|
-
end
|
38
|
-
|
39
|
-
def disconnect
|
40
|
-
initialize_mutex
|
41
|
-
@mutex.synchronize do
|
42
|
-
return unless @connection
|
43
|
-
|
44
|
-
# Safely disconnect in reverse order
|
45
|
-
begin
|
46
|
-
Que.connection = nil
|
47
|
-
rescue => e
|
48
|
-
# Log but don't fail on Que disconnection issues
|
49
|
-
puts "Warning: Error setting Que.connection to nil: #{e.message}" if ENV["AIDP_DEBUG"]
|
50
|
-
end
|
51
|
-
|
52
|
-
@sequel_db&.disconnect
|
53
|
-
@connection&.close
|
54
|
-
@connection = nil
|
55
|
-
@sequel_db = nil
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def connection_params
|
62
|
-
{
|
63
|
-
host: ENV["AIDP_DB_HOST"] || "localhost",
|
64
|
-
port: (ENV["AIDP_DB_PORT"] || 5432).to_i,
|
65
|
-
dbname: ENV["AIDP_DB_NAME"] || "aidp",
|
66
|
-
user: ENV["AIDP_DB_USER"] || ENV["USER"],
|
67
|
-
password: ENV["AIDP_DB_PASSWORD"]
|
68
|
-
}
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,158 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "sqlite3"
|
4
|
-
require "fileutils"
|
5
|
-
|
6
|
-
module Aidp
|
7
|
-
# Handles database migrations for AIDP
|
8
|
-
class DatabaseMigration
|
9
|
-
def initialize(project_dir = Dir.pwd)
|
10
|
-
@project_dir = project_dir
|
11
|
-
@old_db_path = File.join(project_dir, ".aidp-analysis.db")
|
12
|
-
@new_db_path = File.join(project_dir, ".aidp.db")
|
13
|
-
end
|
14
|
-
|
15
|
-
# Migrate database from old to new format
|
16
|
-
def migrate
|
17
|
-
# If neither database exists, create new one directly
|
18
|
-
if !File.exist?(@old_db_path) && !File.exist?(@new_db_path)
|
19
|
-
create_new_database
|
20
|
-
return true
|
21
|
-
end
|
22
|
-
|
23
|
-
# If new database already exists, skip migration
|
24
|
-
if File.exist?(@new_db_path)
|
25
|
-
puts "Database .aidp.db already exists, skipping migration"
|
26
|
-
return false
|
27
|
-
end
|
28
|
-
|
29
|
-
# Rename old database to new name
|
30
|
-
FileUtils.mv(@old_db_path, @new_db_path)
|
31
|
-
|
32
|
-
# Open database connection
|
33
|
-
db = SQLite3::Database.new(@new_db_path)
|
34
|
-
|
35
|
-
# Create new tables for job management
|
36
|
-
create_job_tables(db)
|
37
|
-
|
38
|
-
# Close connection
|
39
|
-
db.close
|
40
|
-
|
41
|
-
true
|
42
|
-
rescue => e
|
43
|
-
puts "Error during database migration: #{e.message}"
|
44
|
-
# Try to restore old database if something went wrong
|
45
|
-
if File.exist?(@new_db_path) && !File.exist?(@old_db_path)
|
46
|
-
FileUtils.mv(@new_db_path, @old_db_path)
|
47
|
-
end
|
48
|
-
false
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def create_new_database
|
54
|
-
db = SQLite3::Database.new(@new_db_path)
|
55
|
-
|
56
|
-
# Create original tables
|
57
|
-
create_original_tables(db)
|
58
|
-
|
59
|
-
# Create new job tables
|
60
|
-
create_job_tables(db)
|
61
|
-
|
62
|
-
db.close
|
63
|
-
end
|
64
|
-
|
65
|
-
def create_original_tables(db)
|
66
|
-
# Create analysis_results table
|
67
|
-
db.execute(<<~SQL)
|
68
|
-
CREATE TABLE analysis_results (
|
69
|
-
step_name TEXT PRIMARY KEY,
|
70
|
-
data TEXT NOT NULL,
|
71
|
-
metadata TEXT,
|
72
|
-
created_at TEXT NOT NULL,
|
73
|
-
updated_at TEXT NOT NULL
|
74
|
-
)
|
75
|
-
SQL
|
76
|
-
|
77
|
-
# Create analysis_metrics table
|
78
|
-
db.execute(<<~SQL)
|
79
|
-
CREATE TABLE analysis_metrics (
|
80
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
81
|
-
step_name TEXT NOT NULL,
|
82
|
-
metric_name TEXT NOT NULL,
|
83
|
-
value TEXT NOT NULL,
|
84
|
-
recorded_at TEXT NOT NULL,
|
85
|
-
UNIQUE(step_name, metric_name, recorded_at)
|
86
|
-
)
|
87
|
-
SQL
|
88
|
-
|
89
|
-
# Create embeddings table
|
90
|
-
db.execute(<<~SQL)
|
91
|
-
CREATE TABLE embeddings (
|
92
|
-
step_name TEXT PRIMARY KEY,
|
93
|
-
embeddings_data TEXT NOT NULL,
|
94
|
-
created_at TEXT NOT NULL
|
95
|
-
)
|
96
|
-
SQL
|
97
|
-
|
98
|
-
# Create indexes
|
99
|
-
db.execute("CREATE INDEX idx_analysis_metrics_step_name ON analysis_metrics(step_name)")
|
100
|
-
db.execute("CREATE INDEX idx_analysis_metrics_recorded_at ON analysis_metrics(recorded_at)")
|
101
|
-
db.execute("CREATE INDEX idx_analysis_results_updated_at ON analysis_results(updated_at)")
|
102
|
-
end
|
103
|
-
|
104
|
-
def create_job_tables(db)
|
105
|
-
# Create jobs table
|
106
|
-
db.execute(<<~SQL)
|
107
|
-
CREATE TABLE jobs (
|
108
|
-
id INTEGER PRIMARY KEY,
|
109
|
-
job_type TEXT NOT NULL,
|
110
|
-
provider TEXT NOT NULL,
|
111
|
-
status TEXT NOT NULL,
|
112
|
-
created_at INTEGER NOT NULL,
|
113
|
-
started_at INTEGER,
|
114
|
-
completed_at INTEGER,
|
115
|
-
error TEXT,
|
116
|
-
metadata TEXT
|
117
|
-
)
|
118
|
-
SQL
|
119
|
-
|
120
|
-
# Create job_executions table
|
121
|
-
db.execute(<<~SQL)
|
122
|
-
CREATE TABLE job_executions (
|
123
|
-
id INTEGER PRIMARY KEY,
|
124
|
-
job_id INTEGER NOT NULL,
|
125
|
-
attempt INTEGER NOT NULL,
|
126
|
-
status TEXT NOT NULL,
|
127
|
-
started_at INTEGER NOT NULL,
|
128
|
-
completed_at INTEGER,
|
129
|
-
error TEXT,
|
130
|
-
FOREIGN KEY (job_id) REFERENCES jobs(id)
|
131
|
-
)
|
132
|
-
SQL
|
133
|
-
|
134
|
-
# Create job_logs table
|
135
|
-
db.execute(<<~SQL)
|
136
|
-
CREATE TABLE job_logs (
|
137
|
-
id INTEGER PRIMARY KEY,
|
138
|
-
job_id INTEGER NOT NULL,
|
139
|
-
execution_id INTEGER NOT NULL,
|
140
|
-
timestamp INTEGER NOT NULL,
|
141
|
-
message TEXT NOT NULL,
|
142
|
-
level TEXT NOT NULL,
|
143
|
-
metadata TEXT,
|
144
|
-
FOREIGN KEY (job_id) REFERENCES jobs(id),
|
145
|
-
FOREIGN KEY (execution_id) REFERENCES job_executions(id)
|
146
|
-
)
|
147
|
-
SQL
|
148
|
-
|
149
|
-
# Create indexes for job tables
|
150
|
-
db.execute("CREATE INDEX idx_jobs_status ON jobs(status)")
|
151
|
-
db.execute("CREATE INDEX idx_jobs_provider ON jobs(provider)")
|
152
|
-
db.execute("CREATE INDEX idx_job_executions_job_id ON job_executions(job_id)")
|
153
|
-
db.execute("CREATE INDEX idx_job_logs_job_id ON job_logs(job_id)")
|
154
|
-
db.execute("CREATE INDEX idx_job_logs_execution_id ON job_logs(execution_id)")
|
155
|
-
db.execute("CREATE INDEX idx_job_logs_timestamp ON job_logs(timestamp)")
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
data/lib/aidp/job_manager.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Aidp
|
4
|
-
class JobManager
|
5
|
-
def initialize(project_dir)
|
6
|
-
@project_dir = project_dir
|
7
|
-
end
|
8
|
-
|
9
|
-
def create_job(job_class, args = {})
|
10
|
-
# Create a new job and return job ID
|
11
|
-
# This is a placeholder implementation
|
12
|
-
job_id = rand(1000..9999)
|
13
|
-
|
14
|
-
# Store job metadata for testing
|
15
|
-
@jobs ||= {}
|
16
|
-
@jobs[job_id] = {
|
17
|
-
id: job_id,
|
18
|
-
job_class: job_class,
|
19
|
-
args: args,
|
20
|
-
status: "queued",
|
21
|
-
created_at: Time.now
|
22
|
-
}
|
23
|
-
|
24
|
-
job_id
|
25
|
-
end
|
26
|
-
|
27
|
-
def get_job(job_id)
|
28
|
-
@jobs ||= {}
|
29
|
-
@jobs[job_id]
|
30
|
-
end
|
31
|
-
|
32
|
-
def update_job_status(job_id, status, error: nil)
|
33
|
-
@jobs ||= {}
|
34
|
-
return unless @jobs[job_id]
|
35
|
-
|
36
|
-
@jobs[job_id][:status] = status
|
37
|
-
@jobs[job_id][:error] = error if error
|
38
|
-
@jobs[job_id][:updated_at] = Time.now
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/aidp/jobs/base_job.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "que"
|
4
|
-
|
5
|
-
module Aidp
|
6
|
-
module Jobs
|
7
|
-
class BaseJob < Que::Job
|
8
|
-
# Default settings
|
9
|
-
self.retry_interval = 30.0 # 30 seconds between retries
|
10
|
-
self.maximum_retry_count = 3
|
11
|
-
|
12
|
-
# Error tracking
|
13
|
-
class_attribute :error_handlers
|
14
|
-
self.error_handlers = []
|
15
|
-
|
16
|
-
def self.on_error(&block)
|
17
|
-
error_handlers << block
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def log_info(message)
|
23
|
-
Que.logger.info "[#{self.class.name}] #{message}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def log_error(message)
|
27
|
-
Que.logger.error "[#{self.class.name}] #{message}"
|
28
|
-
end
|
29
|
-
|
30
|
-
def handle_error(error)
|
31
|
-
self.class.error_handlers.each do |handler|
|
32
|
-
handler.call(error, self)
|
33
|
-
rescue => e
|
34
|
-
log_error "Error handler failed: #{e.message}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Override run to add error handling
|
39
|
-
def run(*args)
|
40
|
-
raise NotImplementedError, "#{self.class} must implement #run"
|
41
|
-
rescue => error
|
42
|
-
handle_error(error)
|
43
|
-
raise # Re-raise to trigger Que's retry mechanism
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Aidp
|
4
|
-
module Jobs
|
5
|
-
class ProviderExecutionJob < BaseJob
|
6
|
-
def self.enqueue(provider_type:, prompt:, session: nil, metadata: {})
|
7
|
-
job = super
|
8
|
-
# Extract job ID explicitly for better readability and debugging
|
9
|
-
job_id = job.que_attrs[:job_id]
|
10
|
-
raise "Failed to enqueue job: no job ID returned" unless job_id
|
11
|
-
job_id
|
12
|
-
end
|
13
|
-
|
14
|
-
def run(provider_type:, prompt:, session: nil, metadata: {})
|
15
|
-
start_time = Time.now
|
16
|
-
|
17
|
-
# Get provider instance
|
18
|
-
provider = Aidp::ProviderManager.get_provider(provider_type)
|
19
|
-
raise "Provider #{provider_type} not available" unless provider
|
20
|
-
|
21
|
-
begin
|
22
|
-
# Execute provider
|
23
|
-
result = provider.send(prompt: prompt, session: session)
|
24
|
-
|
25
|
-
# Store result
|
26
|
-
store_result(result, metadata)
|
27
|
-
|
28
|
-
# Record metrics
|
29
|
-
record_metrics(
|
30
|
-
provider_type: provider_type,
|
31
|
-
duration: Time.now - start_time,
|
32
|
-
success: true,
|
33
|
-
error: nil
|
34
|
-
)
|
35
|
-
rescue => error
|
36
|
-
# Record metrics
|
37
|
-
record_metrics(
|
38
|
-
provider_type: provider_type,
|
39
|
-
duration: Time.now - start_time,
|
40
|
-
success: false,
|
41
|
-
error: error.message
|
42
|
-
)
|
43
|
-
|
44
|
-
# Re-raise error to trigger Que's retry mechanism
|
45
|
-
raise
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def store_result(result, metadata)
|
52
|
-
return unless metadata[:step_name]
|
53
|
-
|
54
|
-
Aidp::DatabaseConnection.connection.exec_params(
|
55
|
-
<<~SQL,
|
56
|
-
INSERT INTO analysis_results (step_name, data, metadata, created_at, updated_at)
|
57
|
-
VALUES ($1, $2, $3, $4, $5)
|
58
|
-
ON CONFLICT (step_name)
|
59
|
-
DO UPDATE SET
|
60
|
-
data = EXCLUDED.data,
|
61
|
-
metadata = EXCLUDED.metadata,
|
62
|
-
updated_at = EXCLUDED.updated_at
|
63
|
-
SQL
|
64
|
-
[
|
65
|
-
metadata[:step_name],
|
66
|
-
result.to_json,
|
67
|
-
metadata.to_json,
|
68
|
-
Time.now,
|
69
|
-
Time.now
|
70
|
-
]
|
71
|
-
)
|
72
|
-
end
|
73
|
-
|
74
|
-
def record_metrics(provider_type:, duration:, success:, error: nil)
|
75
|
-
Aidp::DatabaseConnection.connection.exec_params(
|
76
|
-
<<~SQL,
|
77
|
-
INSERT INTO provider_metrics (
|
78
|
-
provider_type, duration, success, error,
|
79
|
-
job_id, attempt, created_at
|
80
|
-
)
|
81
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
82
|
-
SQL
|
83
|
-
[
|
84
|
-
provider_type,
|
85
|
-
duration,
|
86
|
-
success,
|
87
|
-
error,
|
88
|
-
que_attrs[:job_id],
|
89
|
-
que_attrs[:error_count] + 1,
|
90
|
-
Time.now
|
91
|
-
]
|
92
|
-
)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|