steroids-cli 0.10.30 → 0.10.31
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.
- package/dist/commands/loop-phases.d.ts.map +1 -1
- package/dist/commands/loop-phases.js +111 -22
- package/dist/commands/loop-phases.js.map +1 -1
- package/dist/orchestrator/signal-parser.d.ts +4 -0
- package/dist/orchestrator/signal-parser.d.ts.map +1 -1
- package/dist/orchestrator/signal-parser.js +48 -8
- package/dist/orchestrator/signal-parser.js.map +1 -1
- package/dist/providers/claude.d.ts.map +1 -1
- package/dist/providers/claude.js +4 -1
- package/dist/providers/claude.js.map +1 -1
- package/dist/runners/global-db-backoffs.d.ts +17 -0
- package/dist/runners/global-db-backoffs.d.ts.map +1 -0
- package/dist/runners/global-db-backoffs.js +69 -0
- package/dist/runners/global-db-backoffs.js.map +1 -0
- package/dist/runners/global-db-connection.d.ts +37 -0
- package/dist/runners/global-db-connection.d.ts.map +1 -0
- package/dist/runners/global-db-connection.js +245 -0
- package/dist/runners/global-db-connection.js.map +1 -0
- package/dist/runners/global-db-daemon.d.ts +12 -0
- package/dist/runners/global-db-daemon.d.ts.map +1 -0
- package/dist/runners/global-db-daemon.js +35 -0
- package/dist/runners/global-db-daemon.js.map +1 -0
- package/dist/runners/global-db-schema.d.ts +79 -0
- package/dist/runners/global-db-schema.d.ts.map +1 -0
- package/dist/runners/global-db-schema.js +433 -0
- package/dist/runners/global-db-schema.js.map +1 -0
- package/dist/runners/global-db-sessions.d.ts +13 -0
- package/dist/runners/global-db-sessions.d.ts.map +1 -0
- package/dist/runners/global-db-sessions.js +65 -0
- package/dist/runners/global-db-sessions.js.map +1 -0
- package/dist/runners/global-db-validation.d.ts +27 -0
- package/dist/runners/global-db-validation.d.ts.map +1 -0
- package/dist/runners/global-db-validation.js +43 -0
- package/dist/runners/global-db-validation.js.map +1 -0
- package/dist/runners/global-db.d.ts +10 -87
- package/dist/runners/global-db.d.ts.map +1 -1
- package/dist/runners/global-db.js +61 -809
- package/dist/runners/global-db.js.map +1 -1
- package/dist/runners/orchestrator-loop.d.ts.map +1 -1
- package/dist/runners/orchestrator-loop.js +56 -29
- package/dist/runners/orchestrator-loop.js.map +1 -1
- package/dist/runners/wakeup-checks.d.ts.map +1 -1
- package/dist/runners/wakeup-checks.js +14 -1
- package/dist/runners/wakeup-checks.js.map +1 -1
- package/dist/runners/wakeup-reconcile.d.ts.map +1 -1
- package/dist/runners/wakeup-reconcile.js +14 -0
- package/dist/runners/wakeup-reconcile.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,815 +2,67 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Global database for runner state
|
|
4
4
|
* Located at ~/.steroids/steroids.db (user home, not project)
|
|
5
|
+
*
|
|
6
|
+
* This file re-exports all functionality from focused modules.
|
|
7
|
+
* See individual modules for implementation details.
|
|
5
8
|
*/
|
|
6
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
-
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.getGlobalSteroidsDir =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.
|
|
25
|
-
exports.
|
|
26
|
-
exports.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
69
|
-
path TEXT PRIMARY KEY,
|
|
70
|
-
name TEXT,
|
|
71
|
-
registered_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
72
|
-
last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
73
|
-
enabled INTEGER NOT NULL DEFAULT 1
|
|
74
|
-
);
|
|
75
|
-
`;
|
|
76
|
-
/**
|
|
77
|
-
* Schema upgrade from version 2 to version 3: Add stats columns to projects table
|
|
78
|
-
*/
|
|
79
|
-
const GLOBAL_SCHEMA_V3_SQL = `
|
|
80
|
-
-- Add task stats columns (for API/WebUI display without accessing project DBs)
|
|
81
|
-
ALTER TABLE projects ADD COLUMN pending_count INTEGER DEFAULT 0;
|
|
82
|
-
ALTER TABLE projects ADD COLUMN in_progress_count INTEGER DEFAULT 0;
|
|
83
|
-
ALTER TABLE projects ADD COLUMN review_count INTEGER DEFAULT 0;
|
|
84
|
-
ALTER TABLE projects ADD COLUMN completed_count INTEGER DEFAULT 0;
|
|
85
|
-
ALTER TABLE projects ADD COLUMN stats_updated_at TEXT;
|
|
86
|
-
`;
|
|
87
|
-
/**
|
|
88
|
-
* Schema upgrade from version 3 to version 4: Add section_id to runners table
|
|
89
|
-
*/
|
|
90
|
-
const GLOBAL_SCHEMA_V4_SQL = `
|
|
91
|
-
-- Add section_id column to runners for section focus feature
|
|
92
|
-
ALTER TABLE runners ADD COLUMN section_id TEXT;
|
|
93
|
-
`;
|
|
94
|
-
/**
|
|
95
|
-
* Schema upgrade from version 4 to version 5: Add activity_log table
|
|
96
|
-
*/
|
|
97
|
-
const GLOBAL_SCHEMA_V5_SQL = `
|
|
98
|
-
-- Activity log for tracking task completions across all projects
|
|
99
|
-
CREATE TABLE IF NOT EXISTS activity_log (
|
|
100
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
101
|
-
project_path TEXT NOT NULL,
|
|
102
|
-
runner_id TEXT NOT NULL,
|
|
103
|
-
task_id TEXT NOT NULL,
|
|
104
|
-
task_title TEXT NOT NULL,
|
|
105
|
-
section_name TEXT,
|
|
106
|
-
final_status TEXT NOT NULL,
|
|
107
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
108
|
-
);
|
|
109
|
-
CREATE INDEX IF NOT EXISTS idx_activity_log_created_at ON activity_log(created_at);
|
|
110
|
-
CREATE INDEX IF NOT EXISTS idx_activity_log_project ON activity_log(project_path);
|
|
111
|
-
`;
|
|
112
|
-
/**
|
|
113
|
-
* Schema upgrade from version 5 to version 6: Add commit_message to activity_log
|
|
114
|
-
*/
|
|
115
|
-
const GLOBAL_SCHEMA_V6_SQL = `
|
|
116
|
-
-- Add commit_message column to activity_log for storing coder's final message
|
|
117
|
-
ALTER TABLE activity_log ADD COLUMN commit_message TEXT;
|
|
118
|
-
`;
|
|
119
|
-
/**
|
|
120
|
-
* Schema upgrade from version 6 to version 7: Add commit_sha to activity_log
|
|
121
|
-
*/
|
|
122
|
-
const GLOBAL_SCHEMA_V7_SQL = `
|
|
123
|
-
-- Add commit_sha column to activity_log for GitHub links
|
|
124
|
-
ALTER TABLE activity_log ADD COLUMN commit_sha TEXT;
|
|
125
|
-
`;
|
|
126
|
-
/**
|
|
127
|
-
* Schema upgrade from version 7 to version 8: Add parallel session tracking
|
|
128
|
-
*/
|
|
129
|
-
const GLOBAL_SCHEMA_V8_SQL = `
|
|
130
|
-
-- Parallel run sessions for independent workstreams
|
|
131
|
-
CREATE TABLE IF NOT EXISTS parallel_sessions (
|
|
132
|
-
id TEXT PRIMARY KEY,
|
|
133
|
-
project_path TEXT NOT NULL,
|
|
134
|
-
status TEXT NOT NULL CHECK (
|
|
135
|
-
status IN (
|
|
136
|
-
'running',
|
|
137
|
-
'merging',
|
|
138
|
-
'cleanup_pending',
|
|
139
|
-
'cleanup_draining',
|
|
140
|
-
'blocked_conflict',
|
|
141
|
-
'blocked_recovery',
|
|
142
|
-
'blocked_validation',
|
|
143
|
-
'completed',
|
|
144
|
-
'failed',
|
|
145
|
-
'aborted'
|
|
146
|
-
)
|
|
147
|
-
),
|
|
148
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
149
|
-
completed_at TEXT
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
-- Workstreams within a parallel session
|
|
153
|
-
CREATE TABLE IF NOT EXISTS workstreams (
|
|
154
|
-
id TEXT PRIMARY KEY,
|
|
155
|
-
session_id TEXT NOT NULL REFERENCES parallel_sessions(id),
|
|
156
|
-
branch_name TEXT NOT NULL,
|
|
157
|
-
section_ids TEXT NOT NULL,
|
|
158
|
-
clone_path TEXT,
|
|
159
|
-
status TEXT NOT NULL CHECK (status IN ('running', 'completed', 'failed')),
|
|
160
|
-
runner_id TEXT,
|
|
161
|
-
completed_at TEXT,
|
|
162
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
-- Associate runners with a parallel session
|
|
166
|
-
ALTER TABLE runners ADD COLUMN parallel_session_id TEXT;
|
|
167
|
-
`;
|
|
168
|
-
/**
|
|
169
|
-
* Schema upgrade from version 8 to version 9: add project_repo_id and active-session guards.
|
|
170
|
-
*/
|
|
171
|
-
const GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL = `
|
|
172
|
-
CREATE INDEX IF NOT EXISTS idx_parallel_sessions_project_repo_id
|
|
173
|
-
ON parallel_sessions(project_repo_id);
|
|
174
|
-
|
|
175
|
-
CREATE TRIGGER IF NOT EXISTS trg_parallel_sessions_active_insert
|
|
176
|
-
BEFORE INSERT ON parallel_sessions
|
|
177
|
-
WHEN NEW.project_repo_id IS NOT NULL
|
|
178
|
-
AND NEW.status NOT IN ('completed', 'failed', 'aborted')
|
|
179
|
-
BEGIN
|
|
180
|
-
SELECT RAISE(ABORT, 'active parallel session already exists for project repo')
|
|
181
|
-
WHERE EXISTS (
|
|
182
|
-
SELECT 1
|
|
183
|
-
FROM parallel_sessions
|
|
184
|
-
WHERE project_repo_id = NEW.project_repo_id
|
|
185
|
-
AND status NOT IN ('completed', 'failed', 'aborted')
|
|
186
|
-
);
|
|
187
|
-
END;
|
|
188
|
-
|
|
189
|
-
CREATE TRIGGER IF NOT EXISTS trg_parallel_sessions_active_update
|
|
190
|
-
BEFORE UPDATE OF project_repo_id, status ON parallel_sessions
|
|
191
|
-
WHEN NEW.project_repo_id IS NOT NULL
|
|
192
|
-
AND NEW.status NOT IN ('completed', 'failed', 'aborted')
|
|
193
|
-
BEGIN
|
|
194
|
-
SELECT RAISE(ABORT, 'active parallel session already exists for project repo')
|
|
195
|
-
WHERE EXISTS (
|
|
196
|
-
SELECT 1
|
|
197
|
-
FROM parallel_sessions
|
|
198
|
-
WHERE project_repo_id = NEW.project_repo_id
|
|
199
|
-
AND status NOT IN ('completed', 'failed', 'aborted')
|
|
200
|
-
AND id != NEW.id
|
|
201
|
-
);
|
|
202
|
-
END;
|
|
203
|
-
`;
|
|
204
|
-
/**
|
|
205
|
-
* Schema upgrade from version 9 to version 10: add workstream lease fields.
|
|
206
|
-
*/
|
|
207
|
-
const GLOBAL_SCHEMA_V10_SQL = `
|
|
208
|
-
CREATE INDEX IF NOT EXISTS idx_workstreams_session_status
|
|
209
|
-
ON workstreams(session_id, status);
|
|
210
|
-
`;
|
|
211
|
-
/**
|
|
212
|
-
* Schema upgrade from version 10 to version 11: add sealed merge input fields.
|
|
213
|
-
*/
|
|
214
|
-
const GLOBAL_SCHEMA_V11_SQL = `
|
|
215
|
-
CREATE INDEX IF NOT EXISTS idx_workstreams_completion_order
|
|
216
|
-
ON workstreams(session_id, completion_order);
|
|
217
|
-
`;
|
|
218
|
-
/**
|
|
219
|
-
* Schema upgrade from version 11 to version 12: add reconciliation/backoff fields.
|
|
220
|
-
*/
|
|
221
|
-
const GLOBAL_SCHEMA_V12_SQL = `
|
|
222
|
-
CREATE INDEX IF NOT EXISTS idx_workstreams_next_retry_at
|
|
223
|
-
ON workstreams(next_retry_at);
|
|
224
|
-
`;
|
|
225
|
-
/**
|
|
226
|
-
* Schema upgrade from version 13 to version 14: add conflict attempt tracking.
|
|
227
|
-
*/
|
|
228
|
-
const GLOBAL_SCHEMA_V14_SQL = `
|
|
229
|
-
CREATE INDEX IF NOT EXISTS idx_workstreams_conflict_attempts
|
|
230
|
-
ON workstreams(conflict_attempts);
|
|
231
|
-
`;
|
|
232
|
-
/**
|
|
233
|
-
* Schema upgrade from version 14 to version 15: add validation escalation tracking.
|
|
234
|
-
*/
|
|
235
|
-
const GLOBAL_SCHEMA_V15_SQL = `
|
|
236
|
-
CREATE TABLE IF NOT EXISTS validation_escalations (
|
|
237
|
-
id TEXT PRIMARY KEY,
|
|
238
|
-
session_id TEXT NOT NULL REFERENCES parallel_sessions(id),
|
|
239
|
-
project_path TEXT NOT NULL,
|
|
240
|
-
workspace_path TEXT NOT NULL,
|
|
241
|
-
validation_command TEXT NOT NULL,
|
|
242
|
-
error_message TEXT NOT NULL,
|
|
243
|
-
stdout_snippet TEXT,
|
|
244
|
-
stderr_snippet TEXT,
|
|
245
|
-
status TEXT NOT NULL DEFAULT 'open' CHECK(status IN ('open', 'resolved')),
|
|
246
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
247
|
-
resolved_at TEXT
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
CREATE INDEX IF NOT EXISTS idx_validation_escalations_session
|
|
251
|
-
ON validation_escalations(session_id, status, created_at DESC);
|
|
252
|
-
CREATE INDEX IF NOT EXISTS idx_validation_escalations_project
|
|
253
|
-
ON validation_escalations(project_path, status, created_at DESC);
|
|
254
|
-
`;
|
|
255
|
-
/**
|
|
256
|
-
* Schema upgrade from version 15 to version 16: add provider backoff coordination.
|
|
257
|
-
*/
|
|
258
|
-
const GLOBAL_SCHEMA_V16_SQL = `
|
|
259
|
-
CREATE TABLE IF NOT EXISTS provider_backoffs (
|
|
260
|
-
provider TEXT PRIMARY KEY,
|
|
261
|
-
backoff_until_ms INTEGER NOT NULL,
|
|
262
|
-
retry_count INTEGER NOT NULL DEFAULT 0,
|
|
263
|
-
reason TEXT,
|
|
264
|
-
updated_at INTEGER NOT NULL
|
|
265
|
-
);
|
|
266
|
-
`;
|
|
267
|
-
const GLOBAL_SCHEMA_V17_SQL = `
|
|
268
|
-
-- Add hibernation fields to projects table
|
|
269
|
-
-- Note: These columns are deprecated in V18 but kept here for schema history.
|
|
270
|
-
ALTER TABLE projects ADD COLUMN hibernating_until TEXT;
|
|
271
|
-
ALTER TABLE projects ADD COLUMN hibernation_tier INTEGER DEFAULT 0;
|
|
272
|
-
`;
|
|
273
|
-
const GLOBAL_SCHEMA_V18_SQL = `
|
|
274
|
-
-- Drop project hibernation fields and add provider backoff reason_type
|
|
275
|
-
ALTER TABLE projects DROP COLUMN hibernating_until;
|
|
276
|
-
ALTER TABLE projects DROP COLUMN hibernation_tier;
|
|
277
|
-
ALTER TABLE provider_backoffs ADD COLUMN reason_type TEXT;
|
|
278
|
-
`;
|
|
279
|
-
const GLOBAL_SCHEMA_VERSION = '18';
|
|
280
|
-
function hasColumn(db, tableName, columnName) {
|
|
281
|
-
const columns = db
|
|
282
|
-
.prepare(`PRAGMA table_info(${tableName})`)
|
|
283
|
-
.all();
|
|
284
|
-
return columns.some((column) => column.name === columnName);
|
|
285
|
-
}
|
|
286
|
-
function applyGlobalSchemaV9(db) {
|
|
287
|
-
if (!hasColumn(db, 'parallel_sessions', 'project_repo_id')) {
|
|
288
|
-
db.exec('ALTER TABLE parallel_sessions ADD COLUMN project_repo_id TEXT');
|
|
289
|
-
}
|
|
290
|
-
db.exec("UPDATE parallel_sessions SET project_repo_id = project_path WHERE project_repo_id IS NULL");
|
|
291
|
-
db.exec(GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL);
|
|
292
|
-
}
|
|
293
|
-
function applyGlobalSchemaV10(db) {
|
|
294
|
-
if (!hasColumn(db, 'workstreams', 'claim_generation')) {
|
|
295
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN claim_generation INTEGER NOT NULL DEFAULT 0');
|
|
296
|
-
}
|
|
297
|
-
const leaseColumnMissing = !hasColumn(db, 'workstreams', 'lease_expires_at');
|
|
298
|
-
if (leaseColumnMissing) {
|
|
299
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN lease_expires_at TEXT');
|
|
300
|
-
// Backfill only during the one-time schema upgrade that introduces lease_expires_at.
|
|
301
|
-
// Do NOT run this on every startup, or wakeup reconciliation cannot observe
|
|
302
|
-
// intentionally NULL/expired leases for stale workstreams.
|
|
303
|
-
db.exec("UPDATE workstreams SET lease_expires_at = datetime('now', '+120 seconds') " +
|
|
304
|
-
"WHERE lease_expires_at IS NULL AND status = 'running'");
|
|
305
|
-
}
|
|
306
|
-
db.exec(GLOBAL_SCHEMA_V10_SQL);
|
|
307
|
-
}
|
|
308
|
-
function applyGlobalSchemaV11(db) {
|
|
309
|
-
if (!hasColumn(db, 'workstreams', 'sealed_base_sha')) {
|
|
310
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN sealed_base_sha TEXT');
|
|
311
|
-
}
|
|
312
|
-
if (!hasColumn(db, 'workstreams', 'sealed_head_sha')) {
|
|
313
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN sealed_head_sha TEXT');
|
|
314
|
-
}
|
|
315
|
-
if (!hasColumn(db, 'workstreams', 'sealed_commit_shas')) {
|
|
316
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN sealed_commit_shas TEXT');
|
|
317
|
-
}
|
|
318
|
-
if (!hasColumn(db, 'workstreams', 'completion_order')) {
|
|
319
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN completion_order INTEGER');
|
|
320
|
-
}
|
|
321
|
-
db.exec(GLOBAL_SCHEMA_V11_SQL);
|
|
322
|
-
}
|
|
323
|
-
function applyGlobalSchemaV12(db) {
|
|
324
|
-
if (!hasColumn(db, 'workstreams', 'recovery_attempts')) {
|
|
325
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN recovery_attempts INTEGER NOT NULL DEFAULT 0');
|
|
326
|
-
}
|
|
327
|
-
if (!hasColumn(db, 'workstreams', 'next_retry_at')) {
|
|
328
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN next_retry_at TEXT');
|
|
329
|
-
}
|
|
330
|
-
if (!hasColumn(db, 'workstreams', 'last_reconcile_action')) {
|
|
331
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN last_reconcile_action TEXT');
|
|
332
|
-
}
|
|
333
|
-
if (!hasColumn(db, 'workstreams', 'last_reconciled_at')) {
|
|
334
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN last_reconciled_at TEXT');
|
|
335
|
-
}
|
|
336
|
-
db.exec(GLOBAL_SCHEMA_V12_SQL);
|
|
337
|
-
}
|
|
338
|
-
function supportsBlockedParallelSessionStatuses(db) {
|
|
339
|
-
const row = db
|
|
340
|
-
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'parallel_sessions'")
|
|
341
|
-
.get();
|
|
342
|
-
const sql = row?.sql ?? '';
|
|
343
|
-
return (sql.includes('blocked_conflict') &&
|
|
344
|
-
sql.includes('blocked_recovery') &&
|
|
345
|
-
sql.includes('blocked_validation') &&
|
|
346
|
-
sql.includes('aborted'));
|
|
347
|
-
}
|
|
348
|
-
function applyGlobalSchemaV13(db) {
|
|
349
|
-
if (supportsBlockedParallelSessionStatuses(db)) {
|
|
350
|
-
db.exec(GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
db.exec('PRAGMA foreign_keys = OFF');
|
|
354
|
-
try {
|
|
355
|
-
db.exec('BEGIN IMMEDIATE');
|
|
356
|
-
try {
|
|
357
|
-
db.exec('DROP TABLE IF EXISTS parallel_sessions_new');
|
|
358
|
-
db.exec(`
|
|
359
|
-
CREATE TABLE IF NOT EXISTS parallel_sessions_new (
|
|
360
|
-
id TEXT PRIMARY KEY,
|
|
361
|
-
project_path TEXT NOT NULL,
|
|
362
|
-
project_repo_id TEXT,
|
|
363
|
-
status TEXT NOT NULL CHECK (
|
|
364
|
-
status IN (
|
|
365
|
-
'running',
|
|
366
|
-
'merging',
|
|
367
|
-
'cleanup_pending',
|
|
368
|
-
'cleanup_draining',
|
|
369
|
-
'blocked_conflict',
|
|
370
|
-
'blocked_recovery',
|
|
371
|
-
'blocked_validation',
|
|
372
|
-
'completed',
|
|
373
|
-
'failed',
|
|
374
|
-
'aborted'
|
|
375
|
-
)
|
|
376
|
-
),
|
|
377
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
378
|
-
completed_at TEXT
|
|
379
|
-
);
|
|
380
|
-
`);
|
|
381
|
-
db.exec(`
|
|
382
|
-
INSERT INTO parallel_sessions_new (id, project_path, project_repo_id, status, created_at, completed_at)
|
|
383
|
-
SELECT
|
|
384
|
-
id,
|
|
385
|
-
project_path,
|
|
386
|
-
project_repo_id,
|
|
387
|
-
CASE
|
|
388
|
-
WHEN status IN (
|
|
389
|
-
'running',
|
|
390
|
-
'merging',
|
|
391
|
-
'cleanup_pending',
|
|
392
|
-
'cleanup_draining',
|
|
393
|
-
'blocked_conflict',
|
|
394
|
-
'blocked_recovery',
|
|
395
|
-
'blocked_validation',
|
|
396
|
-
'completed',
|
|
397
|
-
'failed',
|
|
398
|
-
'aborted'
|
|
399
|
-
) THEN status
|
|
400
|
-
ELSE 'running'
|
|
401
|
-
END,
|
|
402
|
-
created_at,
|
|
403
|
-
completed_at
|
|
404
|
-
FROM parallel_sessions;
|
|
405
|
-
`);
|
|
406
|
-
db.exec('DROP TABLE parallel_sessions');
|
|
407
|
-
db.exec('ALTER TABLE parallel_sessions_new RENAME TO parallel_sessions');
|
|
408
|
-
db.exec('COMMIT');
|
|
409
|
-
}
|
|
410
|
-
catch (error) {
|
|
411
|
-
db.exec('ROLLBACK');
|
|
412
|
-
throw error;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
finally {
|
|
416
|
-
db.exec('PRAGMA foreign_keys = ON');
|
|
417
|
-
}
|
|
418
|
-
db.exec(GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL);
|
|
419
|
-
}
|
|
420
|
-
function applyGlobalSchemaV14(db) {
|
|
421
|
-
if (!hasColumn(db, 'workstreams', 'conflict_attempts')) {
|
|
422
|
-
db.exec('ALTER TABLE workstreams ADD COLUMN conflict_attempts INTEGER NOT NULL DEFAULT 0');
|
|
423
|
-
}
|
|
424
|
-
db.exec(GLOBAL_SCHEMA_V14_SQL);
|
|
425
|
-
}
|
|
426
|
-
function applyGlobalSchemaV15(db) {
|
|
427
|
-
db.exec(GLOBAL_SCHEMA_V15_SQL);
|
|
428
|
-
}
|
|
429
|
-
function applyGlobalSchemaV16(db) {
|
|
430
|
-
db.exec(GLOBAL_SCHEMA_V16_SQL);
|
|
431
|
-
}
|
|
432
|
-
function applyGlobalSchemaV17(db) {
|
|
433
|
-
if (!hasColumn(db, 'projects', 'hibernating_until')) {
|
|
434
|
-
db.exec(GLOBAL_SCHEMA_V17_SQL);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
function applyGlobalSchemaV18(db) {
|
|
438
|
-
if (!hasColumn(db, 'provider_backoffs', 'reason_type')) {
|
|
439
|
-
try {
|
|
440
|
-
db.exec(GLOBAL_SCHEMA_V18_SQL);
|
|
441
|
-
}
|
|
442
|
-
catch (e) {
|
|
443
|
-
// Ignore DROP COLUMN errors if sqlite version is too old
|
|
444
|
-
console.warn('V18 schema partial application (sqlite may not support DROP COLUMN). Adding reason_type only.');
|
|
445
|
-
db.exec('ALTER TABLE provider_backoffs ADD COLUMN reason_type TEXT;');
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Get the path to the global steroids directory.
|
|
451
|
-
* Respects STEROIDS_HOME env var for test isolation (Jest's ESM VM context
|
|
452
|
-
* doesn't propagate process.env.HOME changes to CJS os.homedir()).
|
|
453
|
-
*/
|
|
454
|
-
function getGlobalSteroidsDir() {
|
|
455
|
-
const home = process.env.STEROIDS_HOME || (0, node_os_1.homedir)();
|
|
456
|
-
return (0, node_path_1.join)(home, STEROIDS_DIR);
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Get the path to the global database
|
|
460
|
-
*/
|
|
461
|
-
function getGlobalDbPath() {
|
|
462
|
-
return (0, node_path_1.join)(getGlobalSteroidsDir(), DB_NAME);
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Check if global database exists
|
|
466
|
-
*/
|
|
467
|
-
function isGlobalDbInitialized() {
|
|
468
|
-
return (0, node_fs_1.existsSync)(getGlobalDbPath());
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Initialize and open the global database
|
|
472
|
-
* Creates it if it doesn't exist
|
|
473
|
-
*/
|
|
474
|
-
function openGlobalDatabase() {
|
|
475
|
-
const dbPath = getGlobalDbPath();
|
|
476
|
-
const steroidsDir = getGlobalSteroidsDir();
|
|
477
|
-
// Create ~/.steroids directory if it doesn't exist
|
|
478
|
-
if (!(0, node_fs_1.existsSync)(steroidsDir)) {
|
|
479
|
-
(0, node_fs_1.mkdirSync)(steroidsDir, { recursive: true });
|
|
480
|
-
}
|
|
481
|
-
const db = new better_sqlite3_1.default(dbPath);
|
|
482
|
-
// Configure SQLite for optimal performance and safety
|
|
483
|
-
db.pragma('journal_mode = WAL');
|
|
484
|
-
db.pragma('busy_timeout = 5000');
|
|
485
|
-
// Create base schema (IF NOT EXISTS makes this idempotent)
|
|
486
|
-
db.exec(GLOBAL_SCHEMA_SQL);
|
|
487
|
-
// Get current version
|
|
488
|
-
const versionRow = db
|
|
489
|
-
.prepare('SELECT value FROM _global_schema WHERE key = ?')
|
|
490
|
-
.get('version');
|
|
491
|
-
const currentVersion = versionRow?.value;
|
|
492
|
-
if (!currentVersion) {
|
|
493
|
-
// Fresh database - apply all schemas and set to latest version
|
|
494
|
-
db.exec(GLOBAL_SCHEMA_V2_SQL);
|
|
495
|
-
db.exec(GLOBAL_SCHEMA_V3_SQL);
|
|
496
|
-
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
497
|
-
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
498
|
-
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
499
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
500
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
501
|
-
applyGlobalSchemaV9(db);
|
|
502
|
-
applyGlobalSchemaV15(db);
|
|
503
|
-
applyGlobalSchemaV16(db);
|
|
504
|
-
applyGlobalSchemaV17(db);
|
|
505
|
-
applyGlobalSchemaV18(db);
|
|
506
|
-
db.prepare('INSERT OR REPLACE INTO _global_schema (key, value) VALUES (?, ?)')
|
|
507
|
-
.run('version', GLOBAL_SCHEMA_VERSION);
|
|
508
|
-
db.prepare('INSERT INTO _global_schema (key, value) VALUES (?, ?)').run('created_at', new Date().toISOString());
|
|
509
|
-
}
|
|
510
|
-
else if (currentVersion === '1') {
|
|
511
|
-
// Upgrade from version 1 to latest
|
|
512
|
-
db.exec(GLOBAL_SCHEMA_V2_SQL);
|
|
513
|
-
db.exec(GLOBAL_SCHEMA_V3_SQL);
|
|
514
|
-
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
515
|
-
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
516
|
-
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
517
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
518
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
519
|
-
applyGlobalSchemaV9(db);
|
|
520
|
-
applyGlobalSchemaV10(db);
|
|
521
|
-
applyGlobalSchemaV11(db);
|
|
522
|
-
applyGlobalSchemaV12(db);
|
|
523
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
524
|
-
}
|
|
525
|
-
else if (currentVersion === '2') {
|
|
526
|
-
// Upgrade from version 2 to latest
|
|
527
|
-
db.exec(GLOBAL_SCHEMA_V3_SQL);
|
|
528
|
-
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
529
|
-
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
530
|
-
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
531
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
532
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
533
|
-
applyGlobalSchemaV9(db);
|
|
534
|
-
applyGlobalSchemaV10(db);
|
|
535
|
-
applyGlobalSchemaV11(db);
|
|
536
|
-
applyGlobalSchemaV12(db);
|
|
537
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
538
|
-
}
|
|
539
|
-
else if (currentVersion === '3') {
|
|
540
|
-
// Upgrade from version 3 to latest
|
|
541
|
-
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
542
|
-
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
543
|
-
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
544
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
545
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
546
|
-
applyGlobalSchemaV9(db);
|
|
547
|
-
applyGlobalSchemaV10(db);
|
|
548
|
-
applyGlobalSchemaV11(db);
|
|
549
|
-
applyGlobalSchemaV12(db);
|
|
550
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
551
|
-
}
|
|
552
|
-
else if (currentVersion === '4') {
|
|
553
|
-
// Upgrade from version 4 to latest
|
|
554
|
-
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
555
|
-
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
556
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
557
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
558
|
-
applyGlobalSchemaV9(db);
|
|
559
|
-
applyGlobalSchemaV10(db);
|
|
560
|
-
applyGlobalSchemaV11(db);
|
|
561
|
-
applyGlobalSchemaV12(db);
|
|
562
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
563
|
-
}
|
|
564
|
-
else if (currentVersion === '5') {
|
|
565
|
-
// Upgrade from version 5 to latest
|
|
566
|
-
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
567
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
568
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
569
|
-
applyGlobalSchemaV9(db);
|
|
570
|
-
applyGlobalSchemaV10(db);
|
|
571
|
-
applyGlobalSchemaV11(db);
|
|
572
|
-
applyGlobalSchemaV12(db);
|
|
573
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
574
|
-
}
|
|
575
|
-
else if (currentVersion === '6') {
|
|
576
|
-
// Upgrade from version 6 to version 7
|
|
577
|
-
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
578
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
579
|
-
applyGlobalSchemaV9(db);
|
|
580
|
-
applyGlobalSchemaV10(db);
|
|
581
|
-
applyGlobalSchemaV11(db);
|
|
582
|
-
applyGlobalSchemaV12(db);
|
|
583
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
584
|
-
}
|
|
585
|
-
else if (currentVersion === '7') {
|
|
586
|
-
// Upgrade from version 7 to version 8
|
|
587
|
-
db.exec(GLOBAL_SCHEMA_V8_SQL);
|
|
588
|
-
applyGlobalSchemaV9(db);
|
|
589
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
590
|
-
}
|
|
591
|
-
else if (currentVersion === '8') {
|
|
592
|
-
// Upgrade from version 8 to version 9
|
|
593
|
-
applyGlobalSchemaV9(db);
|
|
594
|
-
applyGlobalSchemaV10(db);
|
|
595
|
-
applyGlobalSchemaV11(db);
|
|
596
|
-
applyGlobalSchemaV12(db);
|
|
597
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
598
|
-
}
|
|
599
|
-
else if (currentVersion === '9') {
|
|
600
|
-
// Upgrade from version 9 to version 10
|
|
601
|
-
applyGlobalSchemaV10(db);
|
|
602
|
-
applyGlobalSchemaV11(db);
|
|
603
|
-
applyGlobalSchemaV12(db);
|
|
604
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
605
|
-
}
|
|
606
|
-
else if (currentVersion === '10') {
|
|
607
|
-
// Upgrade from version 10 to version 11
|
|
608
|
-
applyGlobalSchemaV11(db);
|
|
609
|
-
applyGlobalSchemaV12(db);
|
|
610
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
611
|
-
}
|
|
612
|
-
else if (currentVersion === '11') {
|
|
613
|
-
// Upgrade from version 11 to version 12
|
|
614
|
-
applyGlobalSchemaV12(db);
|
|
615
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
616
|
-
}
|
|
617
|
-
else if (currentVersion === '15') {
|
|
618
|
-
applyGlobalSchemaV16(db);
|
|
619
|
-
applyGlobalSchemaV17(db);
|
|
620
|
-
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
621
|
-
}
|
|
622
|
-
// Future upgrades would be handled here with additional conditions
|
|
623
|
-
applyGlobalSchemaV9(db);
|
|
624
|
-
applyGlobalSchemaV10(db);
|
|
625
|
-
applyGlobalSchemaV11(db);
|
|
626
|
-
applyGlobalSchemaV12(db);
|
|
627
|
-
applyGlobalSchemaV13(db);
|
|
628
|
-
applyGlobalSchemaV14(db);
|
|
629
|
-
applyGlobalSchemaV15(db);
|
|
630
|
-
applyGlobalSchemaV16(db);
|
|
631
|
-
applyGlobalSchemaV17(db);
|
|
632
|
-
db.prepare(`INSERT INTO _global_schema (key, value) VALUES (?, ?)
|
|
633
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run('version', GLOBAL_SCHEMA_VERSION);
|
|
634
|
-
return {
|
|
635
|
-
db,
|
|
636
|
-
close: () => db.close(),
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
* Get global schema version
|
|
641
|
-
*/
|
|
642
|
-
function getGlobalSchemaVersion(db) {
|
|
643
|
-
try {
|
|
644
|
-
const row = db
|
|
645
|
-
.prepare('SELECT value FROM _global_schema WHERE key = ?')
|
|
646
|
-
.get('version');
|
|
647
|
-
return row?.value ?? null;
|
|
648
|
-
}
|
|
649
|
-
catch {
|
|
650
|
-
return null;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
/**
|
|
654
|
-
* Get the global daemon active status
|
|
655
|
-
*/
|
|
656
|
-
function getDaemonActiveStatus() {
|
|
657
|
-
try {
|
|
658
|
-
return withGlobalDatabase((db) => {
|
|
659
|
-
const row = db
|
|
660
|
-
.prepare('SELECT value FROM _global_schema WHERE key = ?')
|
|
661
|
-
.get('is_active');
|
|
662
|
-
// Default to true if not explicitly set to 'false'
|
|
663
|
-
return row?.value !== 'false';
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
catch {
|
|
667
|
-
return true; // Default to active on error
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
* Set the global daemon active status
|
|
672
|
-
*/
|
|
673
|
-
function setDaemonActiveStatus(isActive) {
|
|
674
|
-
withGlobalDatabase((db) => {
|
|
675
|
-
db.prepare(`INSERT INTO _global_schema (key, value) VALUES (?, ?)
|
|
676
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run('is_active', isActive ? 'true' : 'false');
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
function updateParallelSessionStatus(sessionId, status, markCompletedAt = false) {
|
|
680
|
-
withGlobalDatabase((db) => {
|
|
681
|
-
db.prepare(`UPDATE parallel_sessions
|
|
682
|
-
SET status = ?,
|
|
683
|
-
completed_at = CASE
|
|
684
|
-
WHEN ? = 1 THEN datetime('now')
|
|
685
|
-
ELSE completed_at
|
|
686
|
-
END
|
|
687
|
-
WHERE id = ?`).run(status, markCompletedAt ? 1 : 0, sessionId);
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
|
-
function revokeWorkstreamLeasesForSession(sessionId) {
|
|
691
|
-
return withGlobalDatabase((db) => {
|
|
692
|
-
const result = db.prepare(`UPDATE workstreams
|
|
693
|
-
SET runner_id = NULL,
|
|
694
|
-
lease_expires_at = datetime('now')
|
|
695
|
-
WHERE session_id = ?`).run(sessionId);
|
|
696
|
-
return result.changes;
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
function listParallelSessionRunners(sessionId) {
|
|
700
|
-
return withGlobalDatabase((db) => {
|
|
701
|
-
return db
|
|
702
|
-
.prepare('SELECT id, pid FROM runners WHERE parallel_session_id = ?')
|
|
703
|
-
.all(sessionId);
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
function removeParallelSessionRunner(runnerId) {
|
|
707
|
-
withGlobalDatabase((db) => {
|
|
708
|
-
db.prepare('DELETE FROM runners WHERE id = ?').run(runnerId);
|
|
709
|
-
});
|
|
710
|
-
}
|
|
711
|
-
function recordValidationEscalation(input) {
|
|
712
|
-
const { db, close } = openGlobalDatabase();
|
|
713
|
-
const id = (0, node_crypto_1.randomUUID)();
|
|
714
|
-
try {
|
|
715
|
-
db.prepare(`INSERT INTO validation_escalations (
|
|
716
|
-
id, session_id, project_path, workspace_path, validation_command,
|
|
717
|
-
error_message, stdout_snippet, stderr_snippet, status
|
|
718
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'open')`).run(id, input.sessionId, input.projectPath, input.workspacePath, input.validationCommand, input.errorMessage, input.stdoutSnippet ?? null, input.stderrSnippet ?? null);
|
|
719
|
-
const row = db
|
|
720
|
-
.prepare(`SELECT id, session_id, project_path, workspace_path, validation_command,
|
|
721
|
-
error_message, stdout_snippet, stderr_snippet, status, created_at, resolved_at
|
|
722
|
-
FROM validation_escalations
|
|
723
|
-
WHERE id = ?`)
|
|
724
|
-
.get(id);
|
|
725
|
-
if (!row) {
|
|
726
|
-
throw new Error(`Failed to read validation escalation record for id ${id}`);
|
|
727
|
-
}
|
|
728
|
-
return row;
|
|
729
|
-
}
|
|
730
|
-
finally {
|
|
731
|
-
close();
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
function resolveValidationEscalationsForSession(sessionId) {
|
|
735
|
-
return withGlobalDatabase((db) => {
|
|
736
|
-
const result = db.prepare(`UPDATE validation_escalations
|
|
737
|
-
SET status = 'resolved',
|
|
738
|
-
resolved_at = datetime('now')
|
|
739
|
-
WHERE session_id = ?
|
|
740
|
-
AND status = 'open'`).run(sessionId);
|
|
741
|
-
return result.changes;
|
|
742
|
-
});
|
|
743
|
-
}
|
|
744
|
-
/**
|
|
745
|
-
* Record a provider rate limit backoff in the global DB.
|
|
746
|
-
* Uses MAX so existing longer backoffs are never shortened.
|
|
747
|
-
*/
|
|
748
|
-
function recordProviderBackoff(provider, backoffUntilMs, reason, reasonType) {
|
|
749
|
-
withGlobalDatabase((db) => {
|
|
750
|
-
// We only update reason_type if the schema has it (V18+)
|
|
751
|
-
if (hasColumn(db, 'provider_backoffs', 'reason_type')) {
|
|
752
|
-
db.prepare(`
|
|
753
|
-
INSERT INTO provider_backoffs (provider, backoff_until_ms, retry_count, reason, reason_type, updated_at)
|
|
754
|
-
VALUES (?, ?, 1, ?, ?, ?)
|
|
755
|
-
ON CONFLICT(provider) DO UPDATE SET
|
|
756
|
-
backoff_until_ms = MAX(backoff_until_ms, excluded.backoff_until_ms),
|
|
757
|
-
retry_count = retry_count + 1,
|
|
758
|
-
reason = excluded.reason,
|
|
759
|
-
reason_type = excluded.reason_type,
|
|
760
|
-
updated_at = excluded.updated_at
|
|
761
|
-
`).run(provider, backoffUntilMs, reason ?? null, reasonType ?? null, Date.now());
|
|
762
|
-
}
|
|
763
|
-
else {
|
|
764
|
-
db.prepare(`
|
|
765
|
-
INSERT INTO provider_backoffs (provider, backoff_until_ms, retry_count, reason, updated_at)
|
|
766
|
-
VALUES (?, ?, 1, ?, ?)
|
|
767
|
-
ON CONFLICT(provider) DO UPDATE SET
|
|
768
|
-
backoff_until_ms = MAX(backoff_until_ms, excluded.backoff_until_ms),
|
|
769
|
-
retry_count = retry_count + 1,
|
|
770
|
-
reason = excluded.reason,
|
|
771
|
-
updated_at = excluded.updated_at
|
|
772
|
-
`).run(provider, backoffUntilMs, reason ?? null, Date.now());
|
|
773
|
-
}
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
/**
|
|
777
|
-
* Get how many ms until the provider's global backoff expires (0 if not backed off).
|
|
778
|
-
*/
|
|
779
|
-
function getProviderBackoffRemainingMs(provider) {
|
|
780
|
-
return withGlobalDatabase((db) => {
|
|
781
|
-
const row = db
|
|
782
|
-
.prepare('SELECT backoff_until_ms FROM provider_backoffs WHERE provider = ?')
|
|
783
|
-
.get(provider);
|
|
784
|
-
if (!row)
|
|
785
|
-
return 0;
|
|
786
|
-
return Math.max(0, row.backoff_until_ms - Date.now());
|
|
787
|
-
});
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Clear a provider's backoff record (called after a successful invocation).
|
|
791
|
-
*/
|
|
792
|
-
function clearProviderBackoff(provider) {
|
|
793
|
-
withGlobalDatabase((db) => {
|
|
794
|
-
db.prepare('DELETE FROM provider_backoffs WHERE provider = ?').run(provider);
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Execute a callback with a managed global database connection.
|
|
799
|
-
* Automatically handles closing the connection when done or if an error occurs.
|
|
800
|
-
*/
|
|
801
|
-
function withGlobalDatabase(callback) {
|
|
802
|
-
const { db, close } = openGlobalDatabase();
|
|
803
|
-
try {
|
|
804
|
-
const result = callback(db);
|
|
805
|
-
if (result instanceof Promise) {
|
|
806
|
-
return result.finally(() => close());
|
|
807
|
-
}
|
|
808
|
-
close();
|
|
809
|
-
return result;
|
|
810
|
-
}
|
|
811
|
-
catch (error) {
|
|
812
|
-
close();
|
|
813
|
-
throw error;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
10
|
+
exports.clearProviderBackoff = exports.getProviderBackoffRemainingMs = exports.recordProviderBackoff = exports.resolveValidationEscalationsForSession = exports.recordValidationEscalation = exports.removeParallelSessionRunner = exports.listParallelSessionRunners = exports.revokeWorkstreamLeasesForSession = exports.updateParallelSessionStatus = exports.setDaemonActiveStatus = exports.getDaemonActiveStatus = exports.withGlobalDatabase = exports.getGlobalSchemaVersion = exports.openGlobalDatabase = exports.isGlobalDbInitialized = exports.getGlobalDbPath = exports.getGlobalSteroidsDir = exports.applyGlobalSchemaV18 = exports.applyGlobalSchemaV17 = exports.applyGlobalSchemaV16 = exports.applyGlobalSchemaV15 = exports.applyGlobalSchemaV14 = exports.applyGlobalSchemaV13 = exports.applyGlobalSchemaV12 = exports.applyGlobalSchemaV11 = exports.applyGlobalSchemaV10 = exports.applyGlobalSchemaV9 = exports.GLOBAL_SCHEMA_VERSION = exports.GLOBAL_SCHEMA_V18_SQL = exports.GLOBAL_SCHEMA_V17_SQL = exports.GLOBAL_SCHEMA_V16_SQL = exports.GLOBAL_SCHEMA_V15_SQL = exports.GLOBAL_SCHEMA_V14_SQL = exports.GLOBAL_SCHEMA_V12_SQL = exports.GLOBAL_SCHEMA_V11_SQL = exports.GLOBAL_SCHEMA_V10_SQL = exports.GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL = exports.GLOBAL_SCHEMA_V8_SQL = exports.GLOBAL_SCHEMA_V7_SQL = exports.GLOBAL_SCHEMA_V6_SQL = exports.GLOBAL_SCHEMA_V5_SQL = exports.GLOBAL_SCHEMA_V4_SQL = exports.GLOBAL_SCHEMA_V3_SQL = exports.GLOBAL_SCHEMA_V2_SQL = exports.GLOBAL_SCHEMA_SQL = void 0;
|
|
11
|
+
// Schema and migrations
|
|
12
|
+
var global_db_schema_1 = require("./global-db-schema");
|
|
13
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_SQL; } });
|
|
14
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V2_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V2_SQL; } });
|
|
15
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V3_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V3_SQL; } });
|
|
16
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V4_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V4_SQL; } });
|
|
17
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V5_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V5_SQL; } });
|
|
18
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V6_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V6_SQL; } });
|
|
19
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V7_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V7_SQL; } });
|
|
20
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V8_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V8_SQL; } });
|
|
21
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V9_INDEX_AND_TRIGGERS_SQL; } });
|
|
22
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V10_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V10_SQL; } });
|
|
23
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V11_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V11_SQL; } });
|
|
24
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V12_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V12_SQL; } });
|
|
25
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V14_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V14_SQL; } });
|
|
26
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V15_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V15_SQL; } });
|
|
27
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V16_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V16_SQL; } });
|
|
28
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V17_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V17_SQL; } });
|
|
29
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_V18_SQL", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_V18_SQL; } });
|
|
30
|
+
Object.defineProperty(exports, "GLOBAL_SCHEMA_VERSION", { enumerable: true, get: function () { return global_db_schema_1.GLOBAL_SCHEMA_VERSION; } });
|
|
31
|
+
Object.defineProperty(exports, "applyGlobalSchemaV9", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV9; } });
|
|
32
|
+
Object.defineProperty(exports, "applyGlobalSchemaV10", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV10; } });
|
|
33
|
+
Object.defineProperty(exports, "applyGlobalSchemaV11", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV11; } });
|
|
34
|
+
Object.defineProperty(exports, "applyGlobalSchemaV12", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV12; } });
|
|
35
|
+
Object.defineProperty(exports, "applyGlobalSchemaV13", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV13; } });
|
|
36
|
+
Object.defineProperty(exports, "applyGlobalSchemaV14", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV14; } });
|
|
37
|
+
Object.defineProperty(exports, "applyGlobalSchemaV15", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV15; } });
|
|
38
|
+
Object.defineProperty(exports, "applyGlobalSchemaV16", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV16; } });
|
|
39
|
+
Object.defineProperty(exports, "applyGlobalSchemaV17", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV17; } });
|
|
40
|
+
Object.defineProperty(exports, "applyGlobalSchemaV18", { enumerable: true, get: function () { return global_db_schema_1.applyGlobalSchemaV18; } });
|
|
41
|
+
// Connection management
|
|
42
|
+
var global_db_connection_1 = require("./global-db-connection");
|
|
43
|
+
Object.defineProperty(exports, "getGlobalSteroidsDir", { enumerable: true, get: function () { return global_db_connection_1.getGlobalSteroidsDir; } });
|
|
44
|
+
Object.defineProperty(exports, "getGlobalDbPath", { enumerable: true, get: function () { return global_db_connection_1.getGlobalDbPath; } });
|
|
45
|
+
Object.defineProperty(exports, "isGlobalDbInitialized", { enumerable: true, get: function () { return global_db_connection_1.isGlobalDbInitialized; } });
|
|
46
|
+
Object.defineProperty(exports, "openGlobalDatabase", { enumerable: true, get: function () { return global_db_connection_1.openGlobalDatabase; } });
|
|
47
|
+
Object.defineProperty(exports, "getGlobalSchemaVersion", { enumerable: true, get: function () { return global_db_connection_1.getGlobalSchemaVersion; } });
|
|
48
|
+
Object.defineProperty(exports, "withGlobalDatabase", { enumerable: true, get: function () { return global_db_connection_1.withGlobalDatabase; } });
|
|
49
|
+
// Daemon status
|
|
50
|
+
var global_db_daemon_1 = require("./global-db-daemon");
|
|
51
|
+
Object.defineProperty(exports, "getDaemonActiveStatus", { enumerable: true, get: function () { return global_db_daemon_1.getDaemonActiveStatus; } });
|
|
52
|
+
Object.defineProperty(exports, "setDaemonActiveStatus", { enumerable: true, get: function () { return global_db_daemon_1.setDaemonActiveStatus; } });
|
|
53
|
+
// Parallel sessions
|
|
54
|
+
var global_db_sessions_1 = require("./global-db-sessions");
|
|
55
|
+
Object.defineProperty(exports, "updateParallelSessionStatus", { enumerable: true, get: function () { return global_db_sessions_1.updateParallelSessionStatus; } });
|
|
56
|
+
Object.defineProperty(exports, "revokeWorkstreamLeasesForSession", { enumerable: true, get: function () { return global_db_sessions_1.revokeWorkstreamLeasesForSession; } });
|
|
57
|
+
Object.defineProperty(exports, "listParallelSessionRunners", { enumerable: true, get: function () { return global_db_sessions_1.listParallelSessionRunners; } });
|
|
58
|
+
Object.defineProperty(exports, "removeParallelSessionRunner", { enumerable: true, get: function () { return global_db_sessions_1.removeParallelSessionRunner; } });
|
|
59
|
+
// Validation escalations
|
|
60
|
+
var global_db_validation_1 = require("./global-db-validation");
|
|
61
|
+
Object.defineProperty(exports, "recordValidationEscalation", { enumerable: true, get: function () { return global_db_validation_1.recordValidationEscalation; } });
|
|
62
|
+
Object.defineProperty(exports, "resolveValidationEscalationsForSession", { enumerable: true, get: function () { return global_db_validation_1.resolveValidationEscalationsForSession; } });
|
|
63
|
+
// Provider backoffs
|
|
64
|
+
var global_db_backoffs_1 = require("./global-db-backoffs");
|
|
65
|
+
Object.defineProperty(exports, "recordProviderBackoff", { enumerable: true, get: function () { return global_db_backoffs_1.recordProviderBackoff; } });
|
|
66
|
+
Object.defineProperty(exports, "getProviderBackoffRemainingMs", { enumerable: true, get: function () { return global_db_backoffs_1.getProviderBackoffRemainingMs; } });
|
|
67
|
+
Object.defineProperty(exports, "clearProviderBackoff", { enumerable: true, get: function () { return global_db_backoffs_1.clearProviderBackoff; } });
|
|
816
68
|
//# sourceMappingURL=global-db.js.map
|