aidp 0.3.0 → 0.7.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 +191 -5
- data/lib/aidp/analysis/kb_inspector.rb +456 -0
- data/lib/aidp/analysis/seams.rb +188 -0
- data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +493 -0
- data/lib/aidp/analysis/tree_sitter_scan.rb +703 -0
- data/lib/aidp/analyze/agent_personas.rb +1 -1
- data/lib/aidp/analyze/agent_tool_executor.rb +5 -11
- data/lib/aidp/analyze/data_retention_manager.rb +0 -5
- data/lib/aidp/analyze/database.rb +99 -82
- data/lib/aidp/analyze/error_handler.rb +12 -79
- data/lib/aidp/analyze/export_manager.rb +0 -7
- data/lib/aidp/analyze/focus_guidance.rb +2 -2
- data/lib/aidp/analyze/incremental_analyzer.rb +1 -11
- data/lib/aidp/analyze/large_analysis_progress.rb +0 -5
- data/lib/aidp/analyze/memory_manager.rb +34 -60
- data/lib/aidp/analyze/metrics_storage.rb +336 -0
- data/lib/aidp/analyze/parallel_processor.rb +0 -6
- data/lib/aidp/analyze/performance_optimizer.rb +0 -3
- data/lib/aidp/analyze/prioritizer.rb +2 -2
- data/lib/aidp/analyze/repository_chunker.rb +14 -21
- data/lib/aidp/analyze/ruby_maat_integration.rb +6 -102
- data/lib/aidp/analyze/runner.rb +107 -191
- data/lib/aidp/analyze/steps.rb +35 -30
- data/lib/aidp/analyze/storage.rb +233 -178
- data/lib/aidp/analyze/tool_configuration.rb +21 -36
- data/lib/aidp/cli/jobs_command.rb +489 -0
- data/lib/aidp/cli/terminal_io.rb +52 -0
- data/lib/aidp/cli.rb +160 -45
- data/lib/aidp/core_ext/class_attribute.rb +36 -0
- data/lib/aidp/database/pg_adapter.rb +148 -0
- data/lib/aidp/database_config.rb +69 -0
- data/lib/aidp/database_connection.rb +72 -0
- data/lib/aidp/execute/runner.rb +65 -92
- data/lib/aidp/execute/steps.rb +81 -82
- data/lib/aidp/job_manager.rb +41 -0
- data/lib/aidp/jobs/base_job.rb +45 -0
- data/lib/aidp/jobs/provider_execution_job.rb +83 -0
- data/lib/aidp/provider_manager.rb +25 -0
- data/lib/aidp/providers/agent_supervisor.rb +348 -0
- data/lib/aidp/providers/anthropic.rb +160 -3
- data/lib/aidp/providers/base.rb +153 -6
- data/lib/aidp/providers/cursor.rb +245 -43
- data/lib/aidp/providers/gemini.rb +164 -3
- data/lib/aidp/providers/supervised_base.rb +317 -0
- data/lib/aidp/providers/supervised_cursor.rb +22 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp.rb +31 -34
- data/templates/ANALYZE/01_REPOSITORY_ANALYSIS.md +4 -4
- data/templates/ANALYZE/06a_tree_sitter_scan.md +217 -0
- metadata +91 -36
data/lib/aidp/analyze/storage.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "pg"
|
4
4
|
require "json"
|
5
5
|
require "yaml"
|
6
6
|
|
@@ -12,7 +12,6 @@ module Aidp
|
|
12
12
|
def initialize(project_dir = Dir.pwd, config = {})
|
13
13
|
@project_dir = project_dir
|
14
14
|
@config = config
|
15
|
-
@db_path = config[:db_path] || File.join(project_dir, ".aidp-analysis.db")
|
16
15
|
@db = nil
|
17
16
|
|
18
17
|
ensure_database_exists
|
@@ -36,14 +35,24 @@ module Aidp
|
|
36
35
|
}
|
37
36
|
|
38
37
|
# Insert or update analysis result
|
39
|
-
@db.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
@db.exec_params(
|
39
|
+
<<~SQL,
|
40
|
+
INSERT INTO analysis_results (execution_id, step_name, data, metadata, created_at, updated_at)
|
41
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
42
|
+
ON CONFLICT (execution_id, step_name)
|
43
|
+
DO UPDATE SET
|
44
|
+
data = EXCLUDED.data,
|
45
|
+
metadata = EXCLUDED.metadata,
|
46
|
+
updated_at = EXCLUDED.updated_at
|
47
|
+
SQL
|
48
|
+
[
|
49
|
+
execution_id,
|
50
|
+
step_name,
|
51
|
+
data.to_json,
|
52
|
+
analysis_data[:metadata].to_json,
|
53
|
+
timestamp,
|
54
|
+
timestamp
|
55
|
+
]
|
47
56
|
)
|
48
57
|
|
49
58
|
# Store metrics with indefinite retention
|
@@ -55,13 +64,6 @@ module Aidp
|
|
55
64
|
stored_at: timestamp,
|
56
65
|
success: true
|
57
66
|
}
|
58
|
-
rescue => e
|
59
|
-
{
|
60
|
-
success: false,
|
61
|
-
error: e.message,
|
62
|
-
execution_id: execution_id,
|
63
|
-
step_name: step_name
|
64
|
-
}
|
65
67
|
end
|
66
68
|
|
67
69
|
# Store metrics with indefinite retention
|
@@ -72,14 +74,19 @@ module Aidp
|
|
72
74
|
metrics = extract_metrics(data)
|
73
75
|
|
74
76
|
metrics.each do |metric_name, metric_value|
|
75
|
-
@db.
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
@db.exec_params(
|
78
|
+
<<~SQL,
|
79
|
+
INSERT INTO metrics (execution_id, step_name, metric_name, metric_value, metric_type, created_at)
|
80
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
81
|
+
SQL
|
82
|
+
[
|
83
|
+
execution_id,
|
84
|
+
step_name,
|
85
|
+
metric_name,
|
86
|
+
metric_value.to_s,
|
87
|
+
metric_value.class.name,
|
88
|
+
timestamp
|
89
|
+
]
|
83
90
|
)
|
84
91
|
end
|
85
92
|
|
@@ -93,28 +100,35 @@ module Aidp
|
|
93
100
|
|
94
101
|
result = if step_name
|
95
102
|
# Get specific step result
|
96
|
-
@db.
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
103
|
+
@db.exec_params(
|
104
|
+
<<~SQL,
|
105
|
+
SELECT * FROM analysis_results
|
106
|
+
WHERE execution_id = $1 AND step_name = $2
|
107
|
+
ORDER BY updated_at DESC
|
108
|
+
LIMIT 1
|
109
|
+
SQL
|
110
|
+
[execution_id, step_name]
|
111
|
+
)
|
101
112
|
else
|
102
113
|
# Get all results for execution
|
103
|
-
@db.
|
104
|
-
|
105
|
-
|
114
|
+
@db.exec_params(
|
115
|
+
<<~SQL,
|
116
|
+
SELECT * FROM analysis_results
|
117
|
+
WHERE execution_id = $1
|
118
|
+
ORDER BY updated_at DESC
|
119
|
+
SQL
|
120
|
+
[execution_id]
|
106
121
|
)
|
107
122
|
end
|
108
123
|
|
109
|
-
return nil
|
124
|
+
return nil if result.ntuples.zero?
|
110
125
|
|
111
|
-
if result.
|
126
|
+
if result.ntuples > 1
|
112
127
|
# Multiple results
|
113
128
|
result.map { |row| parse_analysis_result(row) }
|
114
129
|
else
|
115
130
|
# Single result
|
116
|
-
|
117
|
-
parse_analysis_result(row)
|
131
|
+
parse_analysis_result(result[0])
|
118
132
|
end
|
119
133
|
end
|
120
134
|
|
@@ -124,26 +138,31 @@ module Aidp
|
|
124
138
|
|
125
139
|
query = "SELECT * FROM metrics WHERE 1=1"
|
126
140
|
params = []
|
141
|
+
param_index = 1
|
127
142
|
|
128
143
|
if execution_id
|
129
|
-
query += " AND execution_id =
|
144
|
+
query += " AND execution_id = $#{param_index}"
|
130
145
|
params << execution_id
|
146
|
+
param_index += 1
|
131
147
|
end
|
132
148
|
|
133
149
|
if step_name
|
134
|
-
query += " AND step_name =
|
150
|
+
query += " AND step_name = $#{param_index}"
|
135
151
|
params << step_name
|
152
|
+
param_index += 1
|
136
153
|
end
|
137
154
|
|
138
155
|
if metric_name
|
139
|
-
query += " AND metric_name =
|
156
|
+
query += " AND metric_name = $#{param_index}"
|
140
157
|
params << metric_name
|
158
|
+
param_index += 1
|
141
159
|
end
|
142
160
|
|
143
|
-
query += " ORDER BY created_at DESC
|
161
|
+
query += " ORDER BY created_at DESC"
|
162
|
+
query += " LIMIT $#{param_index}"
|
144
163
|
params << limit
|
145
164
|
|
146
|
-
results = @db.
|
165
|
+
results = @db.exec_params(query, params)
|
147
166
|
results.map { |row| parse_metric(row) }
|
148
167
|
end
|
149
168
|
|
@@ -153,25 +172,29 @@ module Aidp
|
|
153
172
|
|
154
173
|
query = "SELECT * FROM aggregated_metrics WHERE 1=1"
|
155
174
|
params = []
|
175
|
+
param_index = 1
|
156
176
|
|
157
177
|
if execution_id
|
158
|
-
query += " AND execution_id =
|
178
|
+
query += " AND execution_id = $#{param_index}"
|
159
179
|
params << execution_id
|
180
|
+
param_index += 1
|
160
181
|
end
|
161
182
|
|
162
183
|
if step_name
|
163
|
-
query += " AND step_name =
|
184
|
+
query += " AND step_name = $#{param_index}"
|
164
185
|
params << step_name
|
186
|
+
param_index += 1
|
165
187
|
end
|
166
188
|
|
167
189
|
if metric_name
|
168
|
-
query += " AND metric_name =
|
190
|
+
query += " AND metric_name = $#{param_index}"
|
169
191
|
params << metric_name
|
192
|
+
param_index + 1
|
170
193
|
end
|
171
194
|
|
172
195
|
query += " ORDER BY created_at DESC"
|
173
196
|
|
174
|
-
results = @db.
|
197
|
+
results = @db.exec_params(query, params)
|
175
198
|
results.map { |row| parse_aggregated_metric(row) }
|
176
199
|
end
|
177
200
|
|
@@ -179,9 +202,14 @@ module Aidp
|
|
179
202
|
def get_execution_history(limit = 50)
|
180
203
|
ensure_connection
|
181
204
|
|
182
|
-
results = @db.
|
183
|
-
|
184
|
-
|
205
|
+
results = @db.exec_params(
|
206
|
+
<<~SQL,
|
207
|
+
SELECT DISTINCT execution_id, step_name, created_at, updated_at
|
208
|
+
FROM analysis_results
|
209
|
+
ORDER BY created_at DESC
|
210
|
+
LIMIT $1
|
211
|
+
SQL
|
212
|
+
[limit]
|
185
213
|
)
|
186
214
|
|
187
215
|
results.map { |row| parse_execution_history(row) }
|
@@ -194,30 +222,34 @@ module Aidp
|
|
194
222
|
stats = {}
|
195
223
|
|
196
224
|
# Total executions
|
197
|
-
total_executions = @db.
|
225
|
+
total_executions = @db.exec("SELECT COUNT(DISTINCT execution_id) FROM analysis_results").first["count"].to_i
|
198
226
|
stats[:total_executions] = total_executions
|
199
227
|
|
200
228
|
# Total steps
|
201
|
-
total_steps = @db.
|
229
|
+
total_steps = @db.exec("SELECT COUNT(*) FROM analysis_results").first["count"].to_i
|
202
230
|
stats[:total_steps] = total_steps
|
203
231
|
|
204
232
|
# Steps by type
|
205
|
-
steps_by_type = @db.
|
206
|
-
stats[:steps_by_type] = steps_by_type.
|
233
|
+
steps_by_type = @db.exec("SELECT step_name, COUNT(*) FROM analysis_results GROUP BY step_name")
|
234
|
+
stats[:steps_by_type] = steps_by_type.each_with_object({}) do |row, hash|
|
235
|
+
hash[row["step_name"]] = row["count"].to_i
|
236
|
+
end
|
207
237
|
|
208
238
|
# Total metrics
|
209
|
-
total_metrics = @db.
|
239
|
+
total_metrics = @db.exec("SELECT COUNT(*) FROM metrics").first["count"].to_i
|
210
240
|
stats[:total_metrics] = total_metrics
|
211
241
|
|
212
242
|
# Metrics by type
|
213
|
-
metrics_by_type = @db.
|
214
|
-
stats[:metrics_by_type] = metrics_by_type.
|
243
|
+
metrics_by_type = @db.exec("SELECT metric_name, COUNT(*) FROM metrics GROUP BY metric_name")
|
244
|
+
stats[:metrics_by_type] = metrics_by_type.each_with_object({}) do |row, hash|
|
245
|
+
hash[row["metric_name"]] = row["count"].to_i
|
246
|
+
end
|
215
247
|
|
216
248
|
# Date range
|
217
|
-
date_range = @db.
|
249
|
+
date_range = @db.exec("SELECT MIN(created_at), MAX(created_at) FROM analysis_results").first
|
218
250
|
stats[:date_range] = {
|
219
|
-
earliest: date_range[
|
220
|
-
latest: date_range[
|
251
|
+
earliest: date_range["min"] ? Time.parse(date_range["min"]) : nil,
|
252
|
+
latest: date_range["max"] ? Time.parse(date_range["max"]) : nil
|
221
253
|
}
|
222
254
|
|
223
255
|
stats
|
@@ -228,10 +260,9 @@ module Aidp
|
|
228
260
|
ensure_connection
|
229
261
|
|
230
262
|
# Delete existing analysis result
|
231
|
-
@db.
|
232
|
-
"DELETE FROM analysis_results WHERE execution_id =
|
233
|
-
execution_id,
|
234
|
-
step_name
|
263
|
+
@db.exec_params(
|
264
|
+
"DELETE FROM analysis_results WHERE execution_id = $1 AND step_name = $2",
|
265
|
+
[execution_id, step_name]
|
235
266
|
)
|
236
267
|
|
237
268
|
# Store new analysis result
|
@@ -243,17 +274,16 @@ module Aidp
|
|
243
274
|
ensure_connection
|
244
275
|
|
245
276
|
if execution_id && step_name
|
246
|
-
@db.
|
247
|
-
"DELETE FROM analysis_results WHERE execution_id =
|
248
|
-
execution_id,
|
249
|
-
step_name
|
277
|
+
@db.exec_params(
|
278
|
+
"DELETE FROM analysis_results WHERE execution_id = $1 AND step_name = $2",
|
279
|
+
[execution_id, step_name]
|
250
280
|
)
|
251
281
|
elsif execution_id
|
252
|
-
@db.
|
282
|
+
@db.exec_params("DELETE FROM analysis_results WHERE execution_id = $1", [execution_id])
|
253
283
|
elsif step_name
|
254
|
-
@db.
|
284
|
+
@db.exec_params("DELETE FROM analysis_results WHERE step_name = $1", [step_name])
|
255
285
|
else
|
256
|
-
@db.
|
286
|
+
@db.exec("DELETE FROM analysis_results")
|
257
287
|
end
|
258
288
|
|
259
289
|
{success: true, deleted_execution_id: execution_id, deleted_step_name: step_name}
|
@@ -295,27 +325,43 @@ module Aidp
|
|
295
325
|
|
296
326
|
# Import analysis results
|
297
327
|
parsed_data["analysis_results"]&.each do |result|
|
298
|
-
@db.
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
328
|
+
@db.exec_params(
|
329
|
+
<<~SQL,
|
330
|
+
INSERT INTO analysis_results (execution_id, step_name, data, metadata, created_at, updated_at)
|
331
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
332
|
+
ON CONFLICT (execution_id, step_name)
|
333
|
+
DO UPDATE SET
|
334
|
+
data = EXCLUDED.data,
|
335
|
+
metadata = EXCLUDED.metadata,
|
336
|
+
updated_at = EXCLUDED.updated_at
|
337
|
+
SQL
|
338
|
+
[
|
339
|
+
result["execution_id"],
|
340
|
+
result["step_name"],
|
341
|
+
result["data"],
|
342
|
+
result["metadata"],
|
343
|
+
result["created_at"],
|
344
|
+
result["updated_at"]
|
345
|
+
]
|
306
346
|
)
|
307
347
|
end
|
308
348
|
|
309
349
|
# Import metrics
|
310
350
|
parsed_data["metrics"]&.each do |metric|
|
311
|
-
@db.
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
351
|
+
@db.exec_params(
|
352
|
+
<<~SQL,
|
353
|
+
INSERT INTO metrics (execution_id, step_name, metric_name, metric_value, metric_type, created_at)
|
354
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
355
|
+
ON CONFLICT DO NOTHING
|
356
|
+
SQL
|
357
|
+
[
|
358
|
+
metric["execution_id"],
|
359
|
+
metric["step_name"],
|
360
|
+
metric["metric_name"],
|
361
|
+
metric["metric_value"],
|
362
|
+
metric["metric_type"],
|
363
|
+
metric["created_at"]
|
364
|
+
]
|
319
365
|
)
|
320
366
|
end
|
321
367
|
|
@@ -331,71 +377,78 @@ module Aidp
|
|
331
377
|
private
|
332
378
|
|
333
379
|
def ensure_database_exists
|
334
|
-
|
335
|
-
|
336
|
-
@db = SQLite3::Database.new(@db_path)
|
380
|
+
ensure_connection
|
337
381
|
create_schema
|
338
382
|
end
|
339
383
|
|
340
384
|
def ensure_connection
|
341
|
-
|
385
|
+
return if @db
|
386
|
+
|
387
|
+
@db = PG.connect(
|
388
|
+
host: ENV["AIDP_DB_HOST"] || "localhost",
|
389
|
+
port: ENV["AIDP_DB_PORT"] || 5432,
|
390
|
+
dbname: ENV["AIDP_DB_NAME"] || "aidp",
|
391
|
+
user: ENV["AIDP_DB_USER"] || ENV["USER"],
|
392
|
+
password: ENV["AIDP_DB_PASSWORD"]
|
393
|
+
)
|
394
|
+
@db.type_map_for_results = PG::BasicTypeMapForResults.new(@db)
|
342
395
|
end
|
343
396
|
|
344
397
|
def create_schema
|
345
398
|
# Create analysis_results table
|
346
|
-
@db.
|
399
|
+
@db.exec(<<~SQL)
|
347
400
|
CREATE TABLE IF NOT EXISTS analysis_results (
|
348
|
-
id
|
401
|
+
id SERIAL PRIMARY KEY,
|
349
402
|
execution_id TEXT NOT NULL,
|
350
403
|
step_name TEXT NOT NULL,
|
351
|
-
data
|
352
|
-
metadata
|
353
|
-
created_at
|
354
|
-
updated_at
|
404
|
+
data JSONB NOT NULL,
|
405
|
+
metadata JSONB,
|
406
|
+
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
407
|
+
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
355
408
|
UNIQUE(execution_id, step_name)
|
356
409
|
)
|
357
410
|
SQL
|
358
411
|
|
359
412
|
# Create metrics table (indefinite retention)
|
360
|
-
@db.
|
413
|
+
@db.exec(<<~SQL)
|
361
414
|
CREATE TABLE IF NOT EXISTS metrics (
|
362
|
-
id
|
415
|
+
id SERIAL PRIMARY KEY,
|
363
416
|
execution_id TEXT NOT NULL,
|
364
417
|
step_name TEXT NOT NULL,
|
365
418
|
metric_name TEXT NOT NULL,
|
366
419
|
metric_value TEXT NOT NULL,
|
367
420
|
metric_type TEXT NOT NULL,
|
368
|
-
created_at
|
421
|
+
created_at TIMESTAMP WITH TIME ZONE NOT NULL
|
369
422
|
)
|
370
423
|
SQL
|
371
424
|
|
372
425
|
# Create aggregated_metrics table
|
373
|
-
@db.
|
426
|
+
@db.exec(<<~SQL)
|
374
427
|
CREATE TABLE IF NOT EXISTS aggregated_metrics (
|
375
|
-
id
|
428
|
+
id SERIAL PRIMARY KEY,
|
376
429
|
execution_id TEXT NOT NULL,
|
377
430
|
step_name TEXT NOT NULL,
|
378
431
|
metric_name TEXT NOT NULL,
|
379
|
-
min_value
|
380
|
-
max_value
|
381
|
-
avg_value
|
432
|
+
min_value DOUBLE PRECISION,
|
433
|
+
max_value DOUBLE PRECISION,
|
434
|
+
avg_value DOUBLE PRECISION,
|
382
435
|
count INTEGER NOT NULL,
|
383
|
-
created_at
|
436
|
+
created_at TIMESTAMP WITH TIME ZONE NOT NULL
|
384
437
|
)
|
385
438
|
SQL
|
386
439
|
|
387
440
|
# Create indexes
|
388
|
-
@db.
|
389
|
-
@db.
|
390
|
-
@db.
|
391
|
-
@db.
|
392
|
-
@db.
|
393
|
-
@db.
|
394
|
-
@db.
|
441
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_analysis_results_execution_id ON analysis_results(execution_id)")
|
442
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_analysis_results_step_name ON analysis_results(step_name)")
|
443
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_analysis_results_created_at ON analysis_results(created_at)")
|
444
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_execution_id ON metrics(execution_id)")
|
445
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_step_name ON metrics(step_name)")
|
446
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_metric_name ON metrics(metric_name)")
|
447
|
+
@db.exec("CREATE INDEX IF NOT EXISTS idx_metrics_created_at ON metrics(created_at)")
|
395
448
|
|
396
449
|
# Store schema version
|
397
|
-
@db.
|
398
|
-
@db.
|
450
|
+
@db.exec("CREATE TABLE IF NOT EXISTS schema_version (version INTEGER NOT NULL)")
|
451
|
+
@db.exec_params("INSERT INTO schema_version (version) VALUES ($1) ON CONFLICT DO NOTHING", [SCHEMA_VERSION])
|
399
452
|
end
|
400
453
|
|
401
454
|
def generate_execution_id
|
@@ -436,41 +489,37 @@ module Aidp
|
|
436
489
|
next unless metric_value.is_a?(Numeric)
|
437
490
|
|
438
491
|
# Get existing aggregated metric
|
439
|
-
existing = @db.
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
492
|
+
existing = @db.exec_params(
|
493
|
+
<<~SQL,
|
494
|
+
SELECT * FROM aggregated_metrics
|
495
|
+
WHERE execution_id = $1 AND step_name = $2 AND metric_name = $3
|
496
|
+
SQL
|
497
|
+
[execution_id, step_name, metric_name]
|
444
498
|
).first
|
445
499
|
|
446
500
|
if existing
|
447
501
|
# Update existing aggregated metric
|
448
|
-
count = existing[
|
449
|
-
min_value = [existing[
|
450
|
-
max_value = [existing[
|
451
|
-
avg_value = ((existing[
|
452
|
-
|
453
|
-
@db.
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
timestamp
|
460
|
-
existing[0]
|
502
|
+
count = existing["count"].to_i + 1
|
503
|
+
min_value = [existing["min_value"].to_f, metric_value].min
|
504
|
+
max_value = [existing["max_value"].to_f, metric_value].max
|
505
|
+
avg_value = ((existing["avg_value"].to_f * existing["count"].to_i) + metric_value) / count
|
506
|
+
|
507
|
+
@db.exec_params(
|
508
|
+
<<~SQL,
|
509
|
+
UPDATE aggregated_metrics
|
510
|
+
SET min_value = $1, max_value = $2, avg_value = $3, count = $4, created_at = $5
|
511
|
+
WHERE id = $6
|
512
|
+
SQL
|
513
|
+
[min_value, max_value, avg_value, count, timestamp, existing["id"]]
|
461
514
|
)
|
462
515
|
else
|
463
516
|
# Create new aggregated metric
|
464
|
-
@db.
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
metric_value,
|
470
|
-
metric_value,
|
471
|
-
metric_value,
|
472
|
-
1,
|
473
|
-
timestamp.to_i
|
517
|
+
@db.exec_params(
|
518
|
+
<<~SQL,
|
519
|
+
INSERT INTO aggregated_metrics (execution_id, step_name, metric_name, min_value, max_value, avg_value, count, created_at)
|
520
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
521
|
+
SQL
|
522
|
+
[execution_id, step_name, metric_name, metric_value, metric_value, metric_value, 1, timestamp]
|
474
523
|
)
|
475
524
|
end
|
476
525
|
end
|
@@ -480,13 +529,13 @@ module Aidp
|
|
480
529
|
return nil unless row
|
481
530
|
|
482
531
|
{
|
483
|
-
id: row[
|
484
|
-
execution_id: row[
|
485
|
-
step_name: row[
|
486
|
-
data: JSON.parse(row[
|
487
|
-
metadata: JSON.parse(row[
|
488
|
-
created_at: Time.
|
489
|
-
updated_at: Time.
|
532
|
+
id: row["id"].to_i,
|
533
|
+
execution_id: row["execution_id"],
|
534
|
+
step_name: row["step_name"],
|
535
|
+
data: JSON.parse(row["data"]),
|
536
|
+
metadata: JSON.parse(row["metadata"] || "{}"),
|
537
|
+
created_at: Time.parse(row["created_at"]),
|
538
|
+
updated_at: Time.parse(row["updated_at"])
|
490
539
|
}
|
491
540
|
end
|
492
541
|
|
@@ -494,13 +543,13 @@ module Aidp
|
|
494
543
|
return nil unless row
|
495
544
|
|
496
545
|
{
|
497
|
-
id: row[
|
498
|
-
execution_id: row[
|
499
|
-
step_name: row[
|
500
|
-
metric_name: row[
|
501
|
-
metric_value: row[
|
502
|
-
metric_type: row[
|
503
|
-
created_at: Time.
|
546
|
+
id: row["id"].to_i,
|
547
|
+
execution_id: row["execution_id"],
|
548
|
+
step_name: row["step_name"],
|
549
|
+
metric_name: row["metric_name"],
|
550
|
+
metric_value: row["metric_value"],
|
551
|
+
metric_type: row["metric_type"],
|
552
|
+
created_at: Time.parse(row["created_at"])
|
504
553
|
}
|
505
554
|
end
|
506
555
|
|
@@ -508,15 +557,15 @@ module Aidp
|
|
508
557
|
return nil unless row
|
509
558
|
|
510
559
|
{
|
511
|
-
id: row[
|
512
|
-
execution_id: row[
|
513
|
-
step_name: row[
|
514
|
-
metric_name: row[
|
515
|
-
min_value: row[
|
516
|
-
max_value: row[
|
517
|
-
avg_value: row[
|
518
|
-
count: row[
|
519
|
-
created_at: Time.
|
560
|
+
id: row["id"].to_i,
|
561
|
+
execution_id: row["execution_id"],
|
562
|
+
step_name: row["step_name"],
|
563
|
+
metric_name: row["metric_name"],
|
564
|
+
min_value: row["min_value"].to_f,
|
565
|
+
max_value: row["max_value"].to_f,
|
566
|
+
avg_value: row["avg_value"].to_f,
|
567
|
+
count: row["count"].to_i,
|
568
|
+
created_at: Time.parse(row["created_at"])
|
520
569
|
}
|
521
570
|
end
|
522
571
|
|
@@ -524,10 +573,10 @@ module Aidp
|
|
524
573
|
return nil unless row
|
525
574
|
|
526
575
|
{
|
527
|
-
execution_id: row[
|
528
|
-
step_name: row[
|
529
|
-
created_at: Time.
|
530
|
-
updated_at: Time.
|
576
|
+
execution_id: row["execution_id"],
|
577
|
+
step_name: row["step_name"],
|
578
|
+
created_at: Time.parse(row["created_at"]),
|
579
|
+
updated_at: Time.parse(row["updated_at"])
|
531
580
|
}
|
532
581
|
end
|
533
582
|
|
@@ -536,20 +585,22 @@ module Aidp
|
|
536
585
|
|
537
586
|
query = "SELECT * FROM analysis_results"
|
538
587
|
params = []
|
588
|
+
param_index = 1
|
539
589
|
|
540
590
|
if options[:execution_id]
|
541
|
-
query += " WHERE execution_id =
|
591
|
+
query += " WHERE execution_id = $#{param_index}"
|
542
592
|
params << options[:execution_id]
|
593
|
+
param_index += 1
|
543
594
|
end
|
544
595
|
|
545
596
|
query += " ORDER BY created_at DESC"
|
546
597
|
|
547
598
|
if options[:limit]
|
548
|
-
query += " LIMIT
|
599
|
+
query += " LIMIT $#{param_index}"
|
549
600
|
params << options[:limit]
|
550
601
|
end
|
551
602
|
|
552
|
-
results = @db.
|
603
|
+
results = @db.exec_params(query, params)
|
553
604
|
results.map { |row| parse_analysis_result(row) }
|
554
605
|
end
|
555
606
|
|
@@ -558,20 +609,22 @@ module Aidp
|
|
558
609
|
|
559
610
|
query = "SELECT * FROM metrics"
|
560
611
|
params = []
|
612
|
+
param_index = 1
|
561
613
|
|
562
614
|
if options[:execution_id]
|
563
|
-
query += " WHERE execution_id =
|
615
|
+
query += " WHERE execution_id = $#{param_index}"
|
564
616
|
params << options[:execution_id]
|
617
|
+
param_index += 1
|
565
618
|
end
|
566
619
|
|
567
620
|
query += " ORDER BY created_at DESC"
|
568
621
|
|
569
622
|
if options[:limit]
|
570
|
-
query += " LIMIT
|
623
|
+
query += " LIMIT $#{param_index}"
|
571
624
|
params << options[:limit]
|
572
625
|
end
|
573
626
|
|
574
|
-
results = @db.
|
627
|
+
results = @db.exec_params(query, params)
|
575
628
|
results.map { |row| parse_metric(row) }
|
576
629
|
end
|
577
630
|
|
@@ -580,20 +633,22 @@ module Aidp
|
|
580
633
|
|
581
634
|
query = "SELECT * FROM aggregated_metrics"
|
582
635
|
params = []
|
636
|
+
param_index = 1
|
583
637
|
|
584
638
|
if options[:execution_id]
|
585
|
-
query += " WHERE execution_id =
|
639
|
+
query += " WHERE execution_id = $#{param_index}"
|
586
640
|
params << options[:execution_id]
|
641
|
+
param_index += 1
|
587
642
|
end
|
588
643
|
|
589
644
|
query += " ORDER BY created_at DESC"
|
590
645
|
|
591
646
|
if options[:limit]
|
592
|
-
query += " LIMIT
|
647
|
+
query += " LIMIT $#{param_index}"
|
593
648
|
params << options[:limit]
|
594
649
|
end
|
595
650
|
|
596
|
-
results = @db.
|
651
|
+
results = @db.exec_params(query, params)
|
597
652
|
results.map { |row| parse_aggregated_metric(row) }
|
598
653
|
end
|
599
654
|
end
|