opencastle 0.11.0 → 0.13.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.
- package/dist/cli/convoy/events.d.ts +10 -0
- package/dist/cli/convoy/events.d.ts.map +1 -0
- package/dist/cli/convoy/events.js +27 -0
- package/dist/cli/convoy/events.js.map +1 -0
- package/dist/cli/convoy/events.test.d.ts +2 -0
- package/dist/cli/convoy/events.test.d.ts.map +1 -0
- package/dist/cli/convoy/events.test.js +94 -0
- package/dist/cli/convoy/events.test.js.map +1 -0
- package/dist/cli/convoy/merge.d.ts +15 -0
- package/dist/cli/convoy/merge.d.ts.map +1 -0
- package/dist/cli/convoy/merge.js +62 -0
- package/dist/cli/convoy/merge.js.map +1 -0
- package/dist/cli/convoy/merge.test.d.ts +2 -0
- package/dist/cli/convoy/merge.test.d.ts.map +1 -0
- package/dist/cli/convoy/merge.test.js +134 -0
- package/dist/cli/convoy/merge.test.js.map +1 -0
- package/dist/cli/convoy/store.d.ts +23 -0
- package/dist/cli/convoy/store.d.ts.map +1 -0
- package/dist/cli/convoy/store.js +210 -0
- package/dist/cli/convoy/store.js.map +1 -0
- package/dist/cli/convoy/store.test.d.ts +2 -0
- package/dist/cli/convoy/store.test.d.ts.map +1 -0
- package/dist/cli/convoy/store.test.js +387 -0
- package/dist/cli/convoy/store.test.js.map +1 -0
- package/dist/cli/convoy/types.d.ts +56 -0
- package/dist/cli/convoy/types.d.ts.map +1 -0
- package/dist/cli/convoy/types.js +2 -0
- package/dist/cli/convoy/types.js.map +1 -0
- package/dist/cli/convoy/worktree.d.ts +13 -0
- package/dist/cli/convoy/worktree.d.ts.map +1 -0
- package/dist/cli/convoy/worktree.js +90 -0
- package/dist/cli/convoy/worktree.js.map +1 -0
- package/dist/cli/convoy/worktree.test.d.ts +2 -0
- package/dist/cli/convoy/worktree.test.d.ts.map +1 -0
- package/dist/cli/convoy/worktree.test.js +146 -0
- package/dist/cli/convoy/worktree.test.js.map +1 -0
- package/dist/cli/run/adapters/claude-code.js +1 -1
- package/dist/cli/run/adapters/claude-code.js.map +1 -1
- package/dist/cli/run/adapters/copilot.d.ts.map +1 -1
- package/dist/cli/run/adapters/copilot.js +5 -0
- package/dist/cli/run/adapters/copilot.js.map +1 -1
- package/dist/cli/run/adapters/cursor.js +1 -1
- package/dist/cli/run/adapters/cursor.js.map +1 -1
- package/dist/cli/run/executor.test.js +1 -0
- package/dist/cli/run/executor.test.js.map +1 -1
- package/dist/cli/run/loop-executor.d.ts.map +1 -1
- package/dist/cli/run/loop-executor.js +1 -0
- package/dist/cli/run/loop-executor.js.map +1 -1
- package/dist/cli/run/schema.d.ts +4 -0
- package/dist/cli/run/schema.d.ts.map +1 -1
- package/dist/cli/run/schema.js +78 -2
- package/dist/cli/run/schema.js.map +1 -1
- package/dist/cli/run/schema.test.js +384 -1
- package/dist/cli/run/schema.test.js.map +1 -1
- package/dist/cli/types.d.ts +21 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/cli/convoy/events.test.ts +118 -0
- package/src/cli/convoy/events.ts +41 -0
- package/src/cli/convoy/merge.test.ts +184 -0
- package/src/cli/convoy/merge.ts +89 -0
- package/src/cli/convoy/store.test.ts +446 -0
- package/src/cli/convoy/store.ts +308 -0
- package/src/cli/convoy/types.ts +68 -0
- package/src/cli/convoy/worktree.test.ts +177 -0
- package/src/cli/convoy/worktree.ts +116 -0
- package/src/cli/run/adapters/claude-code.ts +1 -1
- package/src/cli/run/adapters/copilot.ts +5 -0
- package/src/cli/run/adapters/cursor.ts +1 -1
- package/src/cli/run/executor.test.ts +1 -0
- package/src/cli/run/loop-executor.ts +1 -0
- package/src/cli/run/schema.test.ts +462 -1
- package/src/cli/run/schema.ts +96 -2
- package/src/cli/types.ts +22 -0
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
const SCHEMA_VERSION = 1;
|
|
3
|
+
class ConvoyStoreImpl {
|
|
4
|
+
db;
|
|
5
|
+
constructor(dbPath) {
|
|
6
|
+
this.db = new DatabaseSync(dbPath);
|
|
7
|
+
this.db.exec('PRAGMA journal_mode = WAL');
|
|
8
|
+
this.db.exec('PRAGMA synchronous = NORMAL');
|
|
9
|
+
this.initSchema();
|
|
10
|
+
}
|
|
11
|
+
initSchema() {
|
|
12
|
+
const row = this.db.prepare('PRAGMA user_version').get();
|
|
13
|
+
if (row.user_version === 0) {
|
|
14
|
+
this.db.exec(`
|
|
15
|
+
CREATE TABLE IF NOT EXISTS convoy (
|
|
16
|
+
id TEXT PRIMARY KEY,
|
|
17
|
+
name TEXT NOT NULL,
|
|
18
|
+
spec_hash TEXT NOT NULL,
|
|
19
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
20
|
+
branch TEXT,
|
|
21
|
+
created_at TEXT NOT NULL,
|
|
22
|
+
started_at TEXT,
|
|
23
|
+
finished_at TEXT,
|
|
24
|
+
spec_yaml TEXT NOT NULL
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE IF NOT EXISTS task (
|
|
28
|
+
id TEXT PRIMARY KEY,
|
|
29
|
+
convoy_id TEXT NOT NULL REFERENCES convoy(id),
|
|
30
|
+
phase INTEGER NOT NULL,
|
|
31
|
+
prompt TEXT NOT NULL,
|
|
32
|
+
agent TEXT NOT NULL DEFAULT 'developer',
|
|
33
|
+
model TEXT,
|
|
34
|
+
timeout_ms INTEGER NOT NULL DEFAULT 1800000,
|
|
35
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
36
|
+
worker_id TEXT,
|
|
37
|
+
worktree TEXT,
|
|
38
|
+
output TEXT,
|
|
39
|
+
exit_code INTEGER,
|
|
40
|
+
started_at TEXT,
|
|
41
|
+
finished_at TEXT,
|
|
42
|
+
retries INTEGER NOT NULL DEFAULT 0,
|
|
43
|
+
max_retries INTEGER NOT NULL DEFAULT 1,
|
|
44
|
+
files TEXT,
|
|
45
|
+
depends_on TEXT
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
CREATE TABLE IF NOT EXISTS worker (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
task_id TEXT REFERENCES task(id),
|
|
51
|
+
adapter TEXT NOT NULL,
|
|
52
|
+
pid INTEGER,
|
|
53
|
+
session_id TEXT,
|
|
54
|
+
status TEXT NOT NULL DEFAULT 'spawned',
|
|
55
|
+
worktree TEXT,
|
|
56
|
+
created_at TEXT NOT NULL,
|
|
57
|
+
finished_at TEXT,
|
|
58
|
+
last_heartbeat TEXT
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE TABLE IF NOT EXISTS event (
|
|
62
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
63
|
+
convoy_id TEXT REFERENCES convoy(id),
|
|
64
|
+
task_id TEXT,
|
|
65
|
+
worker_id TEXT,
|
|
66
|
+
type TEXT NOT NULL,
|
|
67
|
+
data TEXT,
|
|
68
|
+
created_at TEXT NOT NULL
|
|
69
|
+
);
|
|
70
|
+
`);
|
|
71
|
+
this.db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
insertConvoy(record) {
|
|
75
|
+
this.db
|
|
76
|
+
.prepare(`INSERT INTO convoy (id, name, spec_hash, status, branch, created_at, started_at, finished_at, spec_yaml)
|
|
77
|
+
VALUES (:id, :name, :spec_hash, :status, :branch, :created_at, NULL, NULL, :spec_yaml)`)
|
|
78
|
+
.run(record);
|
|
79
|
+
}
|
|
80
|
+
getConvoy(id) {
|
|
81
|
+
return this.db
|
|
82
|
+
.prepare('SELECT * FROM convoy WHERE id = :id')
|
|
83
|
+
.get({ id });
|
|
84
|
+
}
|
|
85
|
+
updateConvoyStatus(id, status, extra) {
|
|
86
|
+
const sets = ['status = :status'];
|
|
87
|
+
const params = { id, status };
|
|
88
|
+
if (extra?.started_at !== undefined) {
|
|
89
|
+
sets.push('started_at = :started_at');
|
|
90
|
+
params.started_at = extra.started_at;
|
|
91
|
+
}
|
|
92
|
+
if (extra?.finished_at !== undefined) {
|
|
93
|
+
sets.push('finished_at = :finished_at');
|
|
94
|
+
params.finished_at = extra.finished_at;
|
|
95
|
+
}
|
|
96
|
+
this.db.prepare(`UPDATE convoy SET ${sets.join(', ')} WHERE id = :id`).run(params);
|
|
97
|
+
}
|
|
98
|
+
insertTask(record) {
|
|
99
|
+
this.db
|
|
100
|
+
.prepare(`INSERT INTO task
|
|
101
|
+
(id, convoy_id, phase, prompt, agent, model, timeout_ms, status,
|
|
102
|
+
worker_id, worktree, output, exit_code, started_at, finished_at,
|
|
103
|
+
retries, max_retries, files, depends_on)
|
|
104
|
+
VALUES
|
|
105
|
+
(:id, :convoy_id, :phase, :prompt, :agent, :model, :timeout_ms, :status,
|
|
106
|
+
NULL, NULL, NULL, NULL, NULL, NULL,
|
|
107
|
+
:retries, :max_retries, :files, :depends_on)`)
|
|
108
|
+
.run(record);
|
|
109
|
+
}
|
|
110
|
+
getTask(id, convoyId) {
|
|
111
|
+
return this.db
|
|
112
|
+
.prepare('SELECT * FROM task WHERE id = :id AND convoy_id = :convoy_id')
|
|
113
|
+
.get({ id, convoy_id: convoyId });
|
|
114
|
+
}
|
|
115
|
+
getTasksByConvoy(convoyId) {
|
|
116
|
+
return this.db
|
|
117
|
+
.prepare('SELECT * FROM task WHERE convoy_id = :convoy_id ORDER BY phase, id')
|
|
118
|
+
.all({ convoy_id: convoyId });
|
|
119
|
+
}
|
|
120
|
+
updateTaskStatus(id, convoyId, status, extra) {
|
|
121
|
+
const sets = ['status = :status'];
|
|
122
|
+
const params = { id, convoy_id: convoyId, status };
|
|
123
|
+
const extraFields = ['worker_id', 'worktree', 'output', 'exit_code', 'started_at', 'finished_at', 'retries'];
|
|
124
|
+
if (extra) {
|
|
125
|
+
for (const field of extraFields) {
|
|
126
|
+
if (field in extra && extra[field] !== undefined) {
|
|
127
|
+
sets.push(`${field} = :${field}`);
|
|
128
|
+
params[field] = extra[field];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
this.db
|
|
133
|
+
.prepare(`UPDATE task SET ${sets.join(', ')} WHERE id = :id AND convoy_id = :convoy_id`)
|
|
134
|
+
.run(params);
|
|
135
|
+
}
|
|
136
|
+
getReadyTasks(convoyId) {
|
|
137
|
+
const allTasks = this.getTasksByConvoy(convoyId);
|
|
138
|
+
const doneTaskIds = new Set(allTasks.filter(t => t.status === 'done').map(t => t.id));
|
|
139
|
+
return allTasks.filter(task => {
|
|
140
|
+
if (task.status !== 'pending')
|
|
141
|
+
return false;
|
|
142
|
+
if (!task.depends_on)
|
|
143
|
+
return true;
|
|
144
|
+
const deps = JSON.parse(task.depends_on);
|
|
145
|
+
return deps.length === 0 || deps.every(depId => doneTaskIds.has(depId));
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
insertWorker(record) {
|
|
149
|
+
this.db
|
|
150
|
+
.prepare(`INSERT INTO worker
|
|
151
|
+
(id, task_id, adapter, pid, session_id, status, worktree, created_at,
|
|
152
|
+
finished_at, last_heartbeat)
|
|
153
|
+
VALUES
|
|
154
|
+
(:id, :task_id, :adapter, :pid, :session_id, :status, :worktree, :created_at,
|
|
155
|
+
NULL, NULL)`)
|
|
156
|
+
.run(record);
|
|
157
|
+
}
|
|
158
|
+
getWorker(id) {
|
|
159
|
+
return this.db
|
|
160
|
+
.prepare('SELECT * FROM worker WHERE id = :id')
|
|
161
|
+
.get({ id });
|
|
162
|
+
}
|
|
163
|
+
updateWorkerStatus(id, status, extra) {
|
|
164
|
+
const sets = ['status = :status'];
|
|
165
|
+
const params = { id, status };
|
|
166
|
+
if (extra?.finished_at !== undefined) {
|
|
167
|
+
sets.push('finished_at = :finished_at');
|
|
168
|
+
params.finished_at = extra.finished_at;
|
|
169
|
+
}
|
|
170
|
+
if (extra?.last_heartbeat !== undefined) {
|
|
171
|
+
sets.push('last_heartbeat = :last_heartbeat');
|
|
172
|
+
params.last_heartbeat = extra.last_heartbeat;
|
|
173
|
+
}
|
|
174
|
+
if (extra?.pid !== undefined) {
|
|
175
|
+
sets.push('pid = :pid');
|
|
176
|
+
params.pid = extra.pid;
|
|
177
|
+
}
|
|
178
|
+
this.db.prepare(`UPDATE worker SET ${sets.join(', ')} WHERE id = :id`).run(params);
|
|
179
|
+
}
|
|
180
|
+
insertEvent(record) {
|
|
181
|
+
this.db
|
|
182
|
+
.prepare(`INSERT INTO event (convoy_id, task_id, worker_id, type, data, created_at)
|
|
183
|
+
VALUES (:convoy_id, :task_id, :worker_id, :type, :data, :created_at)`)
|
|
184
|
+
.run(record);
|
|
185
|
+
}
|
|
186
|
+
getEvents(convoyId) {
|
|
187
|
+
return this.db
|
|
188
|
+
.prepare('SELECT * FROM event WHERE convoy_id = :convoy_id ORDER BY id')
|
|
189
|
+
.all({ convoy_id: convoyId });
|
|
190
|
+
}
|
|
191
|
+
withTransaction(fn) {
|
|
192
|
+
this.db.exec('BEGIN');
|
|
193
|
+
try {
|
|
194
|
+
const result = fn();
|
|
195
|
+
this.db.exec('COMMIT');
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
this.db.exec('ROLLBACK');
|
|
200
|
+
throw err;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
close() {
|
|
204
|
+
this.db.close();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
export function createConvoyStore(dbPath) {
|
|
208
|
+
return new ConvoyStoreImpl(dbPath);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/cli/convoy/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../../src/cli/convoy/store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import { createConvoyStore } from './store.js';
|
|
7
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
8
|
+
let tmpDir;
|
|
9
|
+
let dbPath;
|
|
10
|
+
let store;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'convoy-test-'));
|
|
13
|
+
dbPath = join(tmpDir, 'test.db');
|
|
14
|
+
store = createConvoyStore(dbPath);
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
store.close();
|
|
18
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
function makeConvoy(overrides = {}) {
|
|
21
|
+
return {
|
|
22
|
+
id: 'convoy-1',
|
|
23
|
+
name: 'Test Convoy',
|
|
24
|
+
spec_hash: 'abc123',
|
|
25
|
+
status: 'pending',
|
|
26
|
+
branch: null,
|
|
27
|
+
created_at: new Date().toISOString(),
|
|
28
|
+
spec_yaml: 'name: test',
|
|
29
|
+
...overrides,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function makeTask(overrides = {}) {
|
|
33
|
+
return {
|
|
34
|
+
id: 'task-1',
|
|
35
|
+
convoy_id: 'convoy-1',
|
|
36
|
+
phase: 0,
|
|
37
|
+
prompt: 'Do something',
|
|
38
|
+
agent: 'developer',
|
|
39
|
+
model: null,
|
|
40
|
+
timeout_ms: 1_800_000,
|
|
41
|
+
status: 'pending',
|
|
42
|
+
retries: 0,
|
|
43
|
+
max_retries: 1,
|
|
44
|
+
files: null,
|
|
45
|
+
depends_on: null,
|
|
46
|
+
...overrides,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function makeWorker(overrides = {}) {
|
|
50
|
+
return {
|
|
51
|
+
id: 'worker-1',
|
|
52
|
+
task_id: null,
|
|
53
|
+
adapter: 'copilot',
|
|
54
|
+
pid: null,
|
|
55
|
+
session_id: null,
|
|
56
|
+
status: 'spawned',
|
|
57
|
+
worktree: null,
|
|
58
|
+
created_at: new Date().toISOString(),
|
|
59
|
+
...overrides,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// ── DB creation and WAL mode ──────────────────────────────────────────────────
|
|
63
|
+
describe('DB creation', () => {
|
|
64
|
+
it('creates the database file at the given path', async () => {
|
|
65
|
+
const { existsSync } = await import('node:fs');
|
|
66
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
it('sets WAL journal mode', () => {
|
|
69
|
+
const db = new DatabaseSync(dbPath);
|
|
70
|
+
const row = db.prepare('PRAGMA journal_mode').get();
|
|
71
|
+
db.close();
|
|
72
|
+
expect(row.journal_mode).toBe('wal');
|
|
73
|
+
});
|
|
74
|
+
it('sets schema version to 1', () => {
|
|
75
|
+
const db = new DatabaseSync(dbPath);
|
|
76
|
+
const row = db.prepare('PRAGMA user_version').get();
|
|
77
|
+
db.close();
|
|
78
|
+
expect(row.user_version).toBe(1);
|
|
79
|
+
});
|
|
80
|
+
it('creates all required tables', () => {
|
|
81
|
+
const db = new DatabaseSync(dbPath);
|
|
82
|
+
const tables = db
|
|
83
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
|
|
84
|
+
.all();
|
|
85
|
+
db.close();
|
|
86
|
+
const names = tables.map(t => t.name).sort();
|
|
87
|
+
expect(names).toContain('convoy');
|
|
88
|
+
expect(names).toContain('task');
|
|
89
|
+
expect(names).toContain('worker');
|
|
90
|
+
expect(names).toContain('event');
|
|
91
|
+
});
|
|
92
|
+
it('reopening an existing DB does not reset schema version', () => {
|
|
93
|
+
store.close();
|
|
94
|
+
const store2 = createConvoyStore(dbPath);
|
|
95
|
+
const db = new DatabaseSync(dbPath);
|
|
96
|
+
const row = db.prepare('PRAGMA user_version').get();
|
|
97
|
+
db.close();
|
|
98
|
+
store2.close();
|
|
99
|
+
// Reassign so afterEach does not double-close
|
|
100
|
+
store = createConvoyStore(dbPath);
|
|
101
|
+
expect(row.user_version).toBe(1);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
// ── convoy CRUD ───────────────────────────────────────────────────────────────
|
|
105
|
+
describe('convoy CRUD', () => {
|
|
106
|
+
it('inserts and retrieves a convoy record', () => {
|
|
107
|
+
const record = makeConvoy();
|
|
108
|
+
store.insertConvoy(record);
|
|
109
|
+
const retrieved = store.getConvoy('convoy-1');
|
|
110
|
+
expect(retrieved).toBeDefined();
|
|
111
|
+
expect(retrieved.id).toBe('convoy-1');
|
|
112
|
+
expect(retrieved.name).toBe('Test Convoy');
|
|
113
|
+
expect(retrieved.status).toBe('pending');
|
|
114
|
+
expect(retrieved.started_at).toBeNull();
|
|
115
|
+
expect(retrieved.finished_at).toBeNull();
|
|
116
|
+
});
|
|
117
|
+
it('returns undefined for missing convoy', () => {
|
|
118
|
+
expect(store.getConvoy('does-not-exist')).toBeUndefined();
|
|
119
|
+
});
|
|
120
|
+
it('updates convoy status', () => {
|
|
121
|
+
store.insertConvoy(makeConvoy());
|
|
122
|
+
store.updateConvoyStatus('convoy-1', 'running');
|
|
123
|
+
expect(store.getConvoy('convoy-1').status).toBe('running');
|
|
124
|
+
});
|
|
125
|
+
it('updates convoy status with started_at', () => {
|
|
126
|
+
const ts = '2026-01-01T00:00:00.000Z';
|
|
127
|
+
store.insertConvoy(makeConvoy());
|
|
128
|
+
store.updateConvoyStatus('convoy-1', 'running', { started_at: ts });
|
|
129
|
+
const retrieved = store.getConvoy('convoy-1');
|
|
130
|
+
expect(retrieved.status).toBe('running');
|
|
131
|
+
expect(retrieved.started_at).toBe(ts);
|
|
132
|
+
});
|
|
133
|
+
it('updates convoy status with finished_at', () => {
|
|
134
|
+
const ts = '2026-01-01T01:00:00.000Z';
|
|
135
|
+
store.insertConvoy(makeConvoy());
|
|
136
|
+
store.updateConvoyStatus('convoy-1', 'done', { finished_at: ts });
|
|
137
|
+
const retrieved = store.getConvoy('convoy-1');
|
|
138
|
+
expect(retrieved.status).toBe('done');
|
|
139
|
+
expect(retrieved.finished_at).toBe(ts);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
// ── task CRUD ─────────────────────────────────────────────────────────────────
|
|
143
|
+
describe('task CRUD', () => {
|
|
144
|
+
beforeEach(() => {
|
|
145
|
+
store.insertConvoy(makeConvoy());
|
|
146
|
+
});
|
|
147
|
+
it('inserts and retrieves a task record', () => {
|
|
148
|
+
store.insertTask(makeTask());
|
|
149
|
+
const retrieved = store.getTask('task-1', 'convoy-1');
|
|
150
|
+
expect(retrieved).toBeDefined();
|
|
151
|
+
expect(retrieved.id).toBe('task-1');
|
|
152
|
+
expect(retrieved.convoy_id).toBe('convoy-1');
|
|
153
|
+
expect(retrieved.status).toBe('pending');
|
|
154
|
+
expect(retrieved.worker_id).toBeNull();
|
|
155
|
+
expect(retrieved.output).toBeNull();
|
|
156
|
+
});
|
|
157
|
+
it('returns undefined for missing task', () => {
|
|
158
|
+
expect(store.getTask('does-not-exist', 'convoy-1')).toBeUndefined();
|
|
159
|
+
});
|
|
160
|
+
it('stores JSON fields as strings', () => {
|
|
161
|
+
const task = makeTask({
|
|
162
|
+
id: 'task-json',
|
|
163
|
+
files: JSON.stringify(['src/a.ts', 'src/b.ts']),
|
|
164
|
+
depends_on: JSON.stringify(['task-prev']),
|
|
165
|
+
});
|
|
166
|
+
store.insertTask(task);
|
|
167
|
+
const retrieved = store.getTask('task-json', 'convoy-1');
|
|
168
|
+
expect(JSON.parse(retrieved.files)).toEqual(['src/a.ts', 'src/b.ts']);
|
|
169
|
+
expect(JSON.parse(retrieved.depends_on)).toEqual(['task-prev']);
|
|
170
|
+
});
|
|
171
|
+
it('retrieves all tasks for a convoy ordered by phase', () => {
|
|
172
|
+
store.insertTask(makeTask({ id: 'task-2', phase: 1 }));
|
|
173
|
+
store.insertTask(makeTask({ id: 'task-1', phase: 0 }));
|
|
174
|
+
const tasks = store.getTasksByConvoy('convoy-1');
|
|
175
|
+
expect(tasks).toHaveLength(2);
|
|
176
|
+
expect(tasks[0].phase).toBe(0);
|
|
177
|
+
expect(tasks[1].phase).toBe(1);
|
|
178
|
+
});
|
|
179
|
+
it('updates task status', () => {
|
|
180
|
+
store.insertTask(makeTask());
|
|
181
|
+
store.updateTaskStatus('task-1', 'convoy-1', 'running');
|
|
182
|
+
expect(store.getTask('task-1', 'convoy-1').status).toBe('running');
|
|
183
|
+
});
|
|
184
|
+
it('updates task status with extra fields', () => {
|
|
185
|
+
const ts = '2026-01-01T00:00:00.000Z';
|
|
186
|
+
store.insertTask(makeTask());
|
|
187
|
+
store.updateTaskStatus('task-1', 'convoy-1', 'done', {
|
|
188
|
+
output: 'Task complete',
|
|
189
|
+
exit_code: 0,
|
|
190
|
+
finished_at: ts,
|
|
191
|
+
retries: 1,
|
|
192
|
+
});
|
|
193
|
+
const task = store.getTask('task-1', 'convoy-1');
|
|
194
|
+
expect(task.status).toBe('done');
|
|
195
|
+
expect(task.output).toBe('Task complete');
|
|
196
|
+
expect(task.exit_code).toBe(0);
|
|
197
|
+
expect(task.finished_at).toBe(ts);
|
|
198
|
+
expect(task.retries).toBe(1);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
// ── getReadyTasks ─────────────────────────────────────────────────────────────
|
|
202
|
+
describe('getReadyTasks', () => {
|
|
203
|
+
beforeEach(() => {
|
|
204
|
+
store.insertConvoy(makeConvoy());
|
|
205
|
+
});
|
|
206
|
+
it('returns a pending task with no dependencies', () => {
|
|
207
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: null }));
|
|
208
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
209
|
+
expect(ready.map(t => t.id)).toContain('task-a');
|
|
210
|
+
});
|
|
211
|
+
it('returns a pending task with empty depends_on array', () => {
|
|
212
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: JSON.stringify([]) }));
|
|
213
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
214
|
+
expect(ready.map(t => t.id)).toContain('task-a');
|
|
215
|
+
});
|
|
216
|
+
it('returns a task when its single dependency is done', () => {
|
|
217
|
+
store.insertTask(makeTask({ id: 'task-dep', depends_on: null }));
|
|
218
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: JSON.stringify(['task-dep']) }));
|
|
219
|
+
store.updateTaskStatus('task-dep', 'convoy-1', 'done');
|
|
220
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
221
|
+
expect(ready.map(t => t.id)).toContain('task-a');
|
|
222
|
+
});
|
|
223
|
+
it('does not return a task when its single dependency is not done', () => {
|
|
224
|
+
store.insertTask(makeTask({ id: 'task-dep', depends_on: null }));
|
|
225
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: JSON.stringify(['task-dep']) }));
|
|
226
|
+
// task-dep stays pending
|
|
227
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
228
|
+
expect(ready.map(t => t.id)).not.toContain('task-a');
|
|
229
|
+
});
|
|
230
|
+
it('returns a task when all multiple dependencies are done', () => {
|
|
231
|
+
store.insertTask(makeTask({ id: 'dep-1', depends_on: null }));
|
|
232
|
+
store.insertTask(makeTask({ id: 'dep-2', depends_on: null }));
|
|
233
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: JSON.stringify(['dep-1', 'dep-2']) }));
|
|
234
|
+
store.updateTaskStatus('dep-1', 'convoy-1', 'done');
|
|
235
|
+
store.updateTaskStatus('dep-2', 'convoy-1', 'done');
|
|
236
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
237
|
+
expect(ready.map(t => t.id)).toContain('task-a');
|
|
238
|
+
});
|
|
239
|
+
it('does not return a task when only some of multiple dependencies are done', () => {
|
|
240
|
+
store.insertTask(makeTask({ id: 'dep-1', depends_on: null }));
|
|
241
|
+
store.insertTask(makeTask({ id: 'dep-2', depends_on: null }));
|
|
242
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: JSON.stringify(['dep-1', 'dep-2']) }));
|
|
243
|
+
store.updateTaskStatus('dep-1', 'convoy-1', 'done');
|
|
244
|
+
// dep-2 stays pending
|
|
245
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
246
|
+
expect(ready.map(t => t.id)).not.toContain('task-a');
|
|
247
|
+
});
|
|
248
|
+
it('does not return tasks that are already running', () => {
|
|
249
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: null }));
|
|
250
|
+
store.updateTaskStatus('task-a', 'convoy-1', 'running');
|
|
251
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
252
|
+
expect(ready.map(t => t.id)).not.toContain('task-a');
|
|
253
|
+
});
|
|
254
|
+
it('does not return tasks that are already done', () => {
|
|
255
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: null }));
|
|
256
|
+
store.updateTaskStatus('task-a', 'convoy-1', 'done');
|
|
257
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
258
|
+
expect(ready.map(t => t.id)).not.toContain('task-a');
|
|
259
|
+
});
|
|
260
|
+
it('returns empty array when no tasks are ready', () => {
|
|
261
|
+
store.insertTask(makeTask({ id: 'dep-1', depends_on: null, status: 'running' }));
|
|
262
|
+
store.insertTask(makeTask({ id: 'task-a', depends_on: JSON.stringify(['dep-1']) }));
|
|
263
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
264
|
+
expect(ready.map(t => t.id)).not.toContain('task-a');
|
|
265
|
+
});
|
|
266
|
+
it('returns empty array for a convoy with no tasks', () => {
|
|
267
|
+
const ready = store.getReadyTasks('convoy-1');
|
|
268
|
+
expect(ready).toHaveLength(0);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
// ── worker CRUD ───────────────────────────────────────────────────────────────
|
|
272
|
+
describe('worker CRUD', () => {
|
|
273
|
+
it('inserts and retrieves a worker record', () => {
|
|
274
|
+
store.insertWorker(makeWorker());
|
|
275
|
+
const retrieved = store.getWorker('worker-1');
|
|
276
|
+
expect(retrieved).toBeDefined();
|
|
277
|
+
expect(retrieved.id).toBe('worker-1');
|
|
278
|
+
expect(retrieved.adapter).toBe('copilot');
|
|
279
|
+
expect(retrieved.status).toBe('spawned');
|
|
280
|
+
expect(retrieved.finished_at).toBeNull();
|
|
281
|
+
expect(retrieved.last_heartbeat).toBeNull();
|
|
282
|
+
});
|
|
283
|
+
it('returns undefined for missing worker', () => {
|
|
284
|
+
expect(store.getWorker('does-not-exist')).toBeUndefined();
|
|
285
|
+
});
|
|
286
|
+
it('updates worker status', () => {
|
|
287
|
+
store.insertWorker(makeWorker());
|
|
288
|
+
store.updateWorkerStatus('worker-1', 'running');
|
|
289
|
+
expect(store.getWorker('worker-1').status).toBe('running');
|
|
290
|
+
});
|
|
291
|
+
it('updates worker status with finished_at and pid', () => {
|
|
292
|
+
const ts = '2026-01-01T01:00:00.000Z';
|
|
293
|
+
store.insertWorker(makeWorker());
|
|
294
|
+
store.updateWorkerStatus('worker-1', 'done', { finished_at: ts, pid: 12345 });
|
|
295
|
+
const worker = store.getWorker('worker-1');
|
|
296
|
+
expect(worker.status).toBe('done');
|
|
297
|
+
expect(worker.finished_at).toBe(ts);
|
|
298
|
+
expect(worker.pid).toBe(12345);
|
|
299
|
+
});
|
|
300
|
+
it('updates worker last_heartbeat', () => {
|
|
301
|
+
const ts = '2026-01-01T00:30:00.000Z';
|
|
302
|
+
store.insertWorker(makeWorker());
|
|
303
|
+
store.updateWorkerStatus('worker-1', 'running', { last_heartbeat: ts });
|
|
304
|
+
expect(store.getWorker('worker-1').last_heartbeat).toBe(ts);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
// ── event CRUD ────────────────────────────────────────────────────────────────
|
|
308
|
+
describe('event CRUD', () => {
|
|
309
|
+
beforeEach(() => {
|
|
310
|
+
store.insertConvoy(makeConvoy());
|
|
311
|
+
});
|
|
312
|
+
it('inserts and retrieves events for a convoy', () => {
|
|
313
|
+
store.insertEvent({
|
|
314
|
+
convoy_id: 'convoy-1',
|
|
315
|
+
task_id: null,
|
|
316
|
+
worker_id: null,
|
|
317
|
+
type: 'convoy_started',
|
|
318
|
+
data: JSON.stringify({ msg: 'hello' }),
|
|
319
|
+
created_at: new Date().toISOString(),
|
|
320
|
+
});
|
|
321
|
+
const events = store.getEvents('convoy-1');
|
|
322
|
+
expect(events).toHaveLength(1);
|
|
323
|
+
expect(events[0].type).toBe('convoy_started');
|
|
324
|
+
expect(events[0].convoy_id).toBe('convoy-1');
|
|
325
|
+
expect(JSON.parse(events[0].data)).toEqual({ msg: 'hello' });
|
|
326
|
+
});
|
|
327
|
+
it('returns events ordered by id (insertion order)', () => {
|
|
328
|
+
const now = new Date().toISOString();
|
|
329
|
+
store.insertEvent({ convoy_id: 'convoy-1', task_id: null, worker_id: null, type: 'first', data: null, created_at: now });
|
|
330
|
+
store.insertEvent({ convoy_id: 'convoy-1', task_id: null, worker_id: null, type: 'second', data: null, created_at: now });
|
|
331
|
+
store.insertEvent({ convoy_id: 'convoy-1', task_id: null, worker_id: null, type: 'third', data: null, created_at: now });
|
|
332
|
+
const events = store.getEvents('convoy-1');
|
|
333
|
+
expect(events.map(e => e.type)).toEqual(['first', 'second', 'third']);
|
|
334
|
+
});
|
|
335
|
+
it('returns empty array for convoy with no events', () => {
|
|
336
|
+
expect(store.getEvents('convoy-1')).toHaveLength(0);
|
|
337
|
+
});
|
|
338
|
+
it('assigns autoincrement id', () => {
|
|
339
|
+
const now = new Date().toISOString();
|
|
340
|
+
store.insertEvent({ convoy_id: 'convoy-1', task_id: null, worker_id: null, type: 'ev', data: null, created_at: now });
|
|
341
|
+
store.insertEvent({ convoy_id: 'convoy-1', task_id: null, worker_id: null, type: 'ev2', data: null, created_at: now });
|
|
342
|
+
const events = store.getEvents('convoy-1');
|
|
343
|
+
expect(typeof events[0].id).toBe('number');
|
|
344
|
+
expect(events[1].id).toBeGreaterThan(events[0].id);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
// ── withTransaction ───────────────────────────────────────────────────────────
|
|
348
|
+
describe('withTransaction', () => {
|
|
349
|
+
beforeEach(() => {
|
|
350
|
+
store.insertConvoy(makeConvoy());
|
|
351
|
+
});
|
|
352
|
+
it('commits on success and returns the result', () => {
|
|
353
|
+
const result = store.withTransaction(() => {
|
|
354
|
+
store.insertTask(makeTask());
|
|
355
|
+
return 'done';
|
|
356
|
+
});
|
|
357
|
+
expect(result).toBe('done');
|
|
358
|
+
expect(store.getTask('task-1', 'convoy-1')).toBeDefined();
|
|
359
|
+
});
|
|
360
|
+
it('rolls back on error and re-throws', () => {
|
|
361
|
+
expect(() => {
|
|
362
|
+
store.withTransaction(() => {
|
|
363
|
+
store.insertTask(makeTask());
|
|
364
|
+
throw new Error('forced error');
|
|
365
|
+
});
|
|
366
|
+
}).toThrow('forced error');
|
|
367
|
+
expect(store.getTask('task-1', 'convoy-1')).toBeUndefined();
|
|
368
|
+
});
|
|
369
|
+
it('supports nested data operations inside transaction', () => {
|
|
370
|
+
const ts = new Date().toISOString();
|
|
371
|
+
store.withTransaction(() => {
|
|
372
|
+
store.insertTask(makeTask({ id: 'task-alpha' }));
|
|
373
|
+
store.updateTaskStatus('task-alpha', 'convoy-1', 'running', { started_at: ts });
|
|
374
|
+
});
|
|
375
|
+
const task = store.getTask('task-alpha', 'convoy-1');
|
|
376
|
+
expect(task.status).toBe('running');
|
|
377
|
+
expect(task.started_at).toBe(ts);
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
// ── close ─────────────────────────────────────────────────────────────────────
|
|
381
|
+
describe('close', () => {
|
|
382
|
+
it('closes without error when DB is open', () => {
|
|
383
|
+
const freshStore = createConvoyStore(join(tmpDir, 'fresh.db'));
|
|
384
|
+
expect(() => freshStore.close()).not.toThrow();
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
//# sourceMappingURL=store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../../src/cli/convoy/store.test.ts"],"names":[],"mappings":"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"}
|