nightshift-mcp 1.1.2 → 2.0.1

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.
@@ -0,0 +1,503 @@
1
+ /**
2
+ * NightShift Database Layer
3
+ *
4
+ * SQLite-backed storage for all NightShift state.
5
+ * Replaces scattered JSON/text files with ACID transactions and indexed queries.
6
+ * Uses better-sqlite3 for synchronous, high-performance access.
7
+ */
8
+ import Database from "better-sqlite3";
9
+ import * as fs from "fs";
10
+ import * as path from "path";
11
+ // ============================================
12
+ // Schema Version & Migrations
13
+ // ============================================
14
+ const SCHEMA_VERSION = 1;
15
+ const SCHEMA_SQL = `
16
+ -- Schema version tracking
17
+ CREATE TABLE IF NOT EXISTS schema_version (
18
+ version INTEGER NOT NULL,
19
+ applied_at TEXT DEFAULT (datetime('now'))
20
+ );
21
+
22
+ -- Chat messages (replaces chat.txt)
23
+ CREATE TABLE IF NOT EXISTS chat_messages (
24
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
25
+ agent TEXT NOT NULL,
26
+ type TEXT NOT NULL,
27
+ content TEXT NOT NULL,
28
+ timestamp TEXT DEFAULT (datetime('now'))
29
+ );
30
+ CREATE INDEX IF NOT EXISTS idx_chat_agent ON chat_messages(agent);
31
+ CREATE INDEX IF NOT EXISTS idx_chat_type ON chat_messages(type);
32
+ CREATE INDEX IF NOT EXISTS idx_chat_timestamp ON chat_messages(timestamp);
33
+
34
+ -- Workflow state (replaces workflow.json)
35
+ CREATE TABLE IF NOT EXISTS workflow (
36
+ id INTEGER PRIMARY KEY CHECK (id = 1), -- singleton row
37
+ phase TEXT NOT NULL DEFAULT 'planning',
38
+ project_goal TEXT,
39
+ data TEXT NOT NULL DEFAULT '{}', -- full workflow JSON for complex nested state
40
+ updated_at TEXT DEFAULT (datetime('now'))
41
+ );
42
+
43
+ -- Story assignments (extracted from workflow for better querying)
44
+ CREATE TABLE IF NOT EXISTS story_assignments (
45
+ story_id TEXT PRIMARY KEY,
46
+ agent TEXT NOT NULL,
47
+ status TEXT NOT NULL DEFAULT 'active', -- active, completed, failed, abandoned
48
+ assigned_at TEXT DEFAULT (datetime('now')),
49
+ completed_at TEXT
50
+ );
51
+ CREATE INDEX IF NOT EXISTS idx_assignments_agent ON story_assignments(agent);
52
+ CREATE INDEX IF NOT EXISTS idx_assignments_status ON story_assignments(status);
53
+
54
+ -- Decisions (extracted from workflow)
55
+ CREATE TABLE IF NOT EXISTS decisions (
56
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
57
+ topic TEXT NOT NULL,
58
+ chosen TEXT NOT NULL,
59
+ rationale TEXT,
60
+ agent TEXT,
61
+ timestamp TEXT DEFAULT (datetime('now'))
62
+ );
63
+
64
+ -- Trace events (replaces trace.json)
65
+ CREATE TABLE IF NOT EXISTS trace_events (
66
+ id TEXT PRIMARY KEY,
67
+ parent_id TEXT,
68
+ type TEXT NOT NULL, -- spawn, complete, fail, failover, decision
69
+ agent TEXT NOT NULL,
70
+ task_id TEXT,
71
+ status TEXT NOT NULL DEFAULT 'active', -- active, completed, failed
72
+ outcome TEXT,
73
+ metadata TEXT, -- JSON
74
+ started_at TEXT DEFAULT (datetime('now')),
75
+ ended_at TEXT,
76
+ duration_ms INTEGER
77
+ );
78
+ CREATE INDEX IF NOT EXISTS idx_trace_parent ON trace_events(parent_id);
79
+ CREATE INDEX IF NOT EXISTS idx_trace_task ON trace_events(task_id);
80
+ CREATE INDEX IF NOT EXISTS idx_trace_agent ON trace_events(agent);
81
+
82
+ -- Context store (replaces context/*.json files)
83
+ CREATE TABLE IF NOT EXISTS context_entries (
84
+ id TEXT PRIMARY KEY,
85
+ topic TEXT NOT NULL,
86
+ content TEXT NOT NULL,
87
+ agent TEXT NOT NULL,
88
+ tags TEXT, -- JSON array
89
+ created_at TEXT DEFAULT (datetime('now')),
90
+ updated_at TEXT DEFAULT (datetime('now'))
91
+ );
92
+ CREATE INDEX IF NOT EXISTS idx_context_topic ON context_entries(topic);
93
+
94
+ -- Agent registry (replaces agent-registry.json)
95
+ CREATE TABLE IF NOT EXISTS agent_registry (
96
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
97
+ agent TEXT NOT NULL,
98
+ pid INTEGER,
99
+ output_file TEXT,
100
+ story_id TEXT,
101
+ prompt_preview TEXT, -- first 500 chars
102
+ started_at TEXT DEFAULT (datetime('now')),
103
+ status TEXT NOT NULL DEFAULT 'running' -- running, completed, failed, killed
104
+ );
105
+ CREATE INDEX IF NOT EXISTS idx_registry_agent ON agent_registry(agent);
106
+ CREATE INDEX IF NOT EXISTS idx_registry_status ON agent_registry(status);
107
+
108
+ -- ============================================
109
+ -- NEW v2 tables
110
+ -- ============================================
111
+
112
+ -- Immutable audit log (append-only)
113
+ CREATE TABLE IF NOT EXISTS audit_log (
114
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
115
+ event_type TEXT NOT NULL, -- spawn, complete, fail, rollback, scope_leak, rate_limit, circuit_break, budget_warning, budget_exceeded
116
+ agent TEXT,
117
+ story_id TEXT,
118
+ data TEXT NOT NULL DEFAULT '{}', -- JSON blob with event-specific details
119
+ timestamp TEXT DEFAULT (datetime('now'))
120
+ );
121
+ CREATE INDEX IF NOT EXISTS idx_audit_type ON audit_log(event_type);
122
+ CREATE INDEX IF NOT EXISTS idx_audit_agent ON audit_log(agent);
123
+ CREATE INDEX IF NOT EXISTS idx_audit_story ON audit_log(story_id);
124
+ CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp);
125
+
126
+ -- Run records (for run-guard and autoresearch)
127
+ CREATE TABLE IF NOT EXISTS run_records (
128
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
129
+ story_id TEXT,
130
+ agent TEXT NOT NULL,
131
+ model TEXT,
132
+ timeout_set_ms INTEGER,
133
+ duration_ms INTEGER,
134
+ status TEXT NOT NULL, -- success, verification_failed, scope_leak, timeout, rate_limited, rollback_failed, quarantined
135
+ files_declared TEXT, -- JSON array
136
+ files_actual TEXT, -- JSON array
137
+ scope_leak INTEGER DEFAULT 0,
138
+ out_of_scope_files TEXT, -- JSON array
139
+ tests_passed INTEGER,
140
+ verification_passed INTEGER,
141
+ rollback_triggered INTEGER DEFAULT 0,
142
+ diff_stats TEXT, -- JSON
143
+ exit_code INTEGER,
144
+ error_message TEXT,
145
+ started_at TEXT DEFAULT (datetime('now')),
146
+ ended_at TEXT
147
+ );
148
+ CREATE INDEX IF NOT EXISTS idx_runs_story ON run_records(story_id);
149
+ CREATE INDEX IF NOT EXISTS idx_runs_agent ON run_records(agent);
150
+ CREATE INDEX IF NOT EXISTS idx_runs_status ON run_records(status);
151
+
152
+ -- Budget tracking
153
+ CREATE TABLE IF NOT EXISTS budget_entries (
154
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
155
+ agent TEXT NOT NULL,
156
+ provider TEXT, -- openrouter, anthropic, google, local, ollama
157
+ tokens_in INTEGER DEFAULT 0,
158
+ tokens_out INTEGER DEFAULT 0,
159
+ estimated_cost_usd REAL DEFAULT 0,
160
+ story_id TEXT,
161
+ run_record_id INTEGER REFERENCES run_records(id),
162
+ timestamp TEXT DEFAULT (datetime('now'))
163
+ );
164
+ CREATE INDEX IF NOT EXISTS idx_budget_agent ON budget_entries(agent);
165
+ CREATE INDEX IF NOT EXISTS idx_budget_provider ON budget_entries(provider);
166
+
167
+ -- Budget limits (configurable per agent)
168
+ CREATE TABLE IF NOT EXISTS budget_limits (
169
+ agent TEXT PRIMARY KEY,
170
+ enabled INTEGER DEFAULT 0,
171
+ max_tokens_per_run INTEGER,
172
+ max_cost_per_day_usd REAL,
173
+ max_cost_per_month_usd REAL,
174
+ warning_threshold_pct REAL DEFAULT 0.8
175
+ );
176
+
177
+ -- Circuit breaker state (persisted across restarts)
178
+ CREATE TABLE IF NOT EXISTS circuit_breaker_state (
179
+ agent TEXT PRIMARY KEY,
180
+ state TEXT NOT NULL DEFAULT 'CLOSED', -- CLOSED, OPEN, HALF_OPEN
181
+ consecutive_failures INTEGER DEFAULT 0,
182
+ broken_since TEXT,
183
+ total_failures INTEGER DEFAULT 0,
184
+ total_successes INTEGER DEFAULT 0,
185
+ updated_at TEXT DEFAULT (datetime('now'))
186
+ );
187
+ `;
188
+ // ============================================
189
+ // Database Manager
190
+ // ============================================
191
+ export class NightShiftDB {
192
+ db;
193
+ dbPath;
194
+ constructor(projectPath) {
195
+ const robotChatDir = path.join(projectPath, ".robot-chat");
196
+ if (!fs.existsSync(robotChatDir)) {
197
+ fs.mkdirSync(robotChatDir, { recursive: true });
198
+ }
199
+ this.dbPath = path.join(robotChatDir, "nightshift.db");
200
+ this.db = new Database(this.dbPath);
201
+ // Performance settings
202
+ this.db.pragma("journal_mode = WAL"); // Concurrent readers
203
+ this.db.pragma("synchronous = NORMAL"); // Good durability/performance balance
204
+ this.db.pragma("foreign_keys = ON");
205
+ this.db.pragma("busy_timeout = 5000"); // Wait up to 5s for locks
206
+ this.initSchema();
207
+ }
208
+ initSchema() {
209
+ const version = this.getSchemaVersion();
210
+ if (version < SCHEMA_VERSION) {
211
+ this.db.exec(SCHEMA_SQL);
212
+ this.setSchemaVersion(SCHEMA_VERSION);
213
+ }
214
+ }
215
+ getSchemaVersion() {
216
+ try {
217
+ const row = this.db.prepare("SELECT version FROM schema_version ORDER BY applied_at DESC LIMIT 1").get();
218
+ return row?.version ?? 0;
219
+ }
220
+ catch {
221
+ return 0; // Table doesn't exist yet
222
+ }
223
+ }
224
+ setSchemaVersion(version) {
225
+ this.db.prepare("INSERT INTO schema_version (version) VALUES (?)").run(version);
226
+ }
227
+ // ============================================
228
+ // Transaction helper
229
+ // ============================================
230
+ transaction(fn) {
231
+ return this.db.transaction(fn)();
232
+ }
233
+ // ============================================
234
+ // Audit Log (immutable, append-only)
235
+ // ============================================
236
+ appendAudit(eventType, data, agent, storyId) {
237
+ const result = this.db.prepare("INSERT INTO audit_log (event_type, agent, story_id, data) VALUES (?, ?, ?, ?)").run(eventType, agent ?? null, storyId ?? null, JSON.stringify(data));
238
+ return result.lastInsertRowid;
239
+ }
240
+ queryAudit(options = {}) {
241
+ let sql = "SELECT * FROM audit_log WHERE 1=1";
242
+ const params = [];
243
+ if (options.eventType) {
244
+ sql += " AND event_type = ?";
245
+ params.push(options.eventType);
246
+ }
247
+ if (options.agent) {
248
+ sql += " AND agent = ?";
249
+ params.push(options.agent);
250
+ }
251
+ if (options.storyId) {
252
+ sql += " AND story_id = ?";
253
+ params.push(options.storyId);
254
+ }
255
+ if (options.since) {
256
+ sql += " AND timestamp >= ?";
257
+ params.push(options.since);
258
+ }
259
+ sql += " ORDER BY id DESC";
260
+ if (options.limit) {
261
+ sql += " LIMIT ?";
262
+ params.push(options.limit);
263
+ }
264
+ const rows = this.db.prepare(sql).all(...params);
265
+ return rows.map(r => ({ ...r, data: JSON.parse(r.data) }));
266
+ }
267
+ // ============================================
268
+ // Run Records
269
+ // ============================================
270
+ insertRunRecord(record) {
271
+ const result = this.db.prepare(`
272
+ INSERT INTO run_records (story_id, agent, model, timeout_set_ms, duration_ms, status,
273
+ files_declared, files_actual, scope_leak, out_of_scope_files, tests_passed,
274
+ verification_passed, rollback_triggered, diff_stats, exit_code, error_message, started_at, ended_at)
275
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
276
+ `).run(record.story_id ?? null, record.agent, record.model ?? null, record.timeout_set_ms ?? null, record.duration_ms ?? null, record.status, JSON.stringify(record.files_declared ?? []), JSON.stringify(record.files_actual ?? []), record.scope_leak ? 1 : 0, JSON.stringify(record.out_of_scope_files ?? []), record.tests_passed != null ? (record.tests_passed ? 1 : 0) : null, record.verification_passed != null ? (record.verification_passed ? 1 : 0) : null, record.rollback_triggered ? 1 : 0, JSON.stringify(record.diff_stats ?? {}), record.exit_code ?? null, record.error_message ?? null, record.started_at ?? new Date().toISOString(), record.ended_at ?? null);
277
+ return result.lastInsertRowid;
278
+ }
279
+ getRunRecords(options = {}) {
280
+ let sql = "SELECT * FROM run_records WHERE 1=1";
281
+ const params = [];
282
+ if (options.storyId) {
283
+ sql += " AND story_id = ?";
284
+ params.push(options.storyId);
285
+ }
286
+ if (options.agent) {
287
+ sql += " AND agent = ?";
288
+ params.push(options.agent);
289
+ }
290
+ if (options.status) {
291
+ sql += " AND status = ?";
292
+ params.push(options.status);
293
+ }
294
+ sql += " ORDER BY id DESC";
295
+ if (options.limit) {
296
+ sql += " LIMIT ?";
297
+ params.push(options.limit);
298
+ }
299
+ const rows = this.db.prepare(sql).all(...params);
300
+ return rows.map(r => ({
301
+ id: r.id,
302
+ story_id: r.story_id ?? undefined,
303
+ agent: r.agent,
304
+ model: r.model ?? undefined,
305
+ timeout_set_ms: r.timeout_set_ms ?? undefined,
306
+ duration_ms: r.duration_ms ?? undefined,
307
+ status: r.status,
308
+ files_declared: r.files_declared ? JSON.parse(r.files_declared) : [],
309
+ files_actual: r.files_actual ? JSON.parse(r.files_actual) : [],
310
+ scope_leak: r.scope_leak === 1,
311
+ out_of_scope_files: r.out_of_scope_files ? JSON.parse(r.out_of_scope_files) : [],
312
+ tests_passed: r.tests_passed != null ? r.tests_passed === 1 : undefined,
313
+ verification_passed: r.verification_passed != null ? r.verification_passed === 1 : undefined,
314
+ rollback_triggered: r.rollback_triggered === 1,
315
+ diff_stats: r.diff_stats ? JSON.parse(r.diff_stats) : {},
316
+ exit_code: r.exit_code ?? undefined,
317
+ error_message: r.error_message ?? undefined,
318
+ started_at: r.started_at,
319
+ ended_at: r.ended_at ?? undefined,
320
+ }));
321
+ }
322
+ // ============================================
323
+ // Budget
324
+ // ============================================
325
+ addBudgetEntry(entry) {
326
+ const result = this.db.prepare(`
327
+ INSERT INTO budget_entries (agent, provider, tokens_in, tokens_out, estimated_cost_usd, story_id, run_record_id)
328
+ VALUES (?, ?, ?, ?, ?, ?, ?)
329
+ `).run(entry.agent, entry.provider ?? null, entry.tokens_in ?? 0, entry.tokens_out ?? 0, entry.estimated_cost_usd ?? 0, entry.story_id ?? null, entry.run_record_id ?? null);
330
+ return result.lastInsertRowid;
331
+ }
332
+ getBudgetStatus(agent) {
333
+ const totalRow = this.db.prepare("SELECT COALESCE(SUM(estimated_cost_usd), 0) as total FROM budget_entries WHERE agent = ?").get(agent);
334
+ const todayRow = this.db.prepare("SELECT COALESCE(SUM(estimated_cost_usd), 0) as total FROM budget_entries WHERE agent = ? AND date(timestamp) = date('now')").get(agent);
335
+ const monthRow = this.db.prepare("SELECT COALESCE(SUM(estimated_cost_usd), 0) as total FROM budget_entries WHERE agent = ? AND strftime('%Y-%m', timestamp) = strftime('%Y-%m', 'now')").get(agent);
336
+ const limit = this.db.prepare("SELECT * FROM budget_limits WHERE agent = ?").get(agent);
337
+ const parsedLimit = limit ? {
338
+ agent: limit.agent,
339
+ enabled: limit.enabled === 1,
340
+ max_tokens_per_run: limit.max_tokens_per_run ?? undefined,
341
+ max_cost_per_day_usd: limit.max_cost_per_day_usd ?? undefined,
342
+ max_cost_per_month_usd: limit.max_cost_per_month_usd ?? undefined,
343
+ warning_threshold_pct: limit.warning_threshold_pct ?? undefined,
344
+ } : null;
345
+ let exceeded = false;
346
+ let exceededReason;
347
+ let warning = false;
348
+ if (parsedLimit?.enabled) {
349
+ const warnPct = parsedLimit.warning_threshold_pct ?? 0.8;
350
+ if (parsedLimit.max_cost_per_day_usd != null) {
351
+ if (todayRow.total >= parsedLimit.max_cost_per_day_usd) {
352
+ exceeded = true;
353
+ exceededReason = `Daily limit $${parsedLimit.max_cost_per_day_usd} exceeded ($${todayRow.total.toFixed(4)})`;
354
+ }
355
+ else if (todayRow.total >= parsedLimit.max_cost_per_day_usd * warnPct) {
356
+ warning = true;
357
+ }
358
+ }
359
+ if (parsedLimit.max_cost_per_month_usd != null) {
360
+ if (monthRow.total >= parsedLimit.max_cost_per_month_usd) {
361
+ exceeded = true;
362
+ exceededReason = `Monthly limit $${parsedLimit.max_cost_per_month_usd} exceeded ($${monthRow.total.toFixed(4)})`;
363
+ }
364
+ else if (monthRow.total >= parsedLimit.max_cost_per_month_usd * warnPct) {
365
+ warning = true;
366
+ }
367
+ }
368
+ }
369
+ return {
370
+ totalCost: totalRow.total,
371
+ todayCost: todayRow.total,
372
+ monthCost: monthRow.total,
373
+ limit: parsedLimit,
374
+ exceeded,
375
+ warning,
376
+ exceededReason,
377
+ };
378
+ }
379
+ setBudgetLimit(agent, limit) {
380
+ // Use null sentinel to distinguish "field omitted" from "field set to null/false"
381
+ const enabled = limit.enabled !== undefined ? (limit.enabled ? 1 : 0) : null;
382
+ const maxTokens = limit.max_tokens_per_run !== undefined ? limit.max_tokens_per_run : null;
383
+ const maxDaily = limit.max_cost_per_day_usd !== undefined ? limit.max_cost_per_day_usd : null;
384
+ const maxMonthly = limit.max_cost_per_month_usd !== undefined ? limit.max_cost_per_month_usd : null;
385
+ const warnPct = limit.warning_threshold_pct !== undefined ? limit.warning_threshold_pct : null;
386
+ this.db.prepare(`
387
+ INSERT INTO budget_limits (agent, enabled, max_tokens_per_run, max_cost_per_day_usd, max_cost_per_month_usd, warning_threshold_pct)
388
+ VALUES (?, COALESCE(?, 0), ?, ?, ?, COALESCE(?, 0.8))
389
+ ON CONFLICT(agent) DO UPDATE SET
390
+ enabled = COALESCE(?, enabled),
391
+ max_tokens_per_run = COALESCE(?, max_tokens_per_run),
392
+ max_cost_per_day_usd = COALESCE(?, max_cost_per_day_usd),
393
+ max_cost_per_month_usd = COALESCE(?, max_cost_per_month_usd),
394
+ warning_threshold_pct = COALESCE(?, warning_threshold_pct)
395
+ `).run(agent, enabled, maxTokens, maxDaily, maxMonthly, warnPct, enabled, maxTokens, maxDaily, maxMonthly, warnPct);
396
+ }
397
+ // ============================================
398
+ // Circuit Breaker Persistence
399
+ // ============================================
400
+ saveCircuitState(agent, state) {
401
+ this.db.prepare(`
402
+ INSERT INTO circuit_breaker_state (agent, state, consecutive_failures, broken_since, total_failures, total_successes, updated_at)
403
+ VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
404
+ ON CONFLICT(agent) DO UPDATE SET
405
+ state = excluded.state,
406
+ consecutive_failures = excluded.consecutive_failures,
407
+ broken_since = excluded.broken_since,
408
+ total_failures = excluded.total_failures,
409
+ total_successes = excluded.total_successes,
410
+ updated_at = excluded.updated_at
411
+ `).run(agent, state.state, state.consecutiveFailures, state.brokenSince ?? null, state.totalFailures, state.totalSuccesses);
412
+ }
413
+ loadCircuitState(agent) {
414
+ const row = this.db.prepare("SELECT * FROM circuit_breaker_state WHERE agent = ?").get(agent);
415
+ if (!row)
416
+ return null;
417
+ return {
418
+ state: row.state,
419
+ consecutiveFailures: row.consecutive_failures,
420
+ brokenSince: row.broken_since ?? undefined,
421
+ totalFailures: row.total_failures,
422
+ totalSuccesses: row.total_successes,
423
+ };
424
+ }
425
+ // ============================================
426
+ // Chat Messages
427
+ // ============================================
428
+ insertChatMessage(agent, type, content) {
429
+ const result = this.db.prepare("INSERT INTO chat_messages (agent, type, content) VALUES (?, ?, ?)").run(agent, type, content);
430
+ return result.lastInsertRowid;
431
+ }
432
+ getChatMessages(options = {}) {
433
+ let sql = "SELECT * FROM chat_messages WHERE 1=1";
434
+ const params = [];
435
+ if (options.agent) {
436
+ sql += " AND agent = ?";
437
+ params.push(options.agent);
438
+ }
439
+ if (options.type) {
440
+ sql += " AND type = ?";
441
+ params.push(options.type);
442
+ }
443
+ if (options.sinceId) {
444
+ sql += " AND id > ?";
445
+ params.push(options.sinceId);
446
+ }
447
+ sql += " ORDER BY id DESC";
448
+ if (options.limit) {
449
+ sql += " LIMIT ?";
450
+ params.push(options.limit);
451
+ }
452
+ return this.db.prepare(sql).all(...params);
453
+ }
454
+ // ============================================
455
+ // Autoresearch Queries
456
+ // ============================================
457
+ getAgentSuccessRate(agent) {
458
+ let sql = `
459
+ SELECT agent, COUNT(*) as total,
460
+ SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as successes,
461
+ ROUND(CAST(SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS REAL) / COUNT(*), 3) as rate
462
+ FROM run_records
463
+ `;
464
+ const params = [];
465
+ if (agent) {
466
+ sql += " WHERE agent = ?";
467
+ params.push(agent);
468
+ }
469
+ sql += " GROUP BY agent ORDER BY rate DESC";
470
+ return this.db.prepare(sql).all(...params);
471
+ }
472
+ getAverageDuration(agent) {
473
+ let sql = `
474
+ SELECT agent, AVG(duration_ms) as avg_duration_ms, COUNT(DISTINCT story_id) as median_stories
475
+ FROM run_records WHERE duration_ms IS NOT NULL
476
+ `;
477
+ const params = [];
478
+ if (agent) {
479
+ sql += " AND agent = ?";
480
+ params.push(agent);
481
+ }
482
+ sql += " GROUP BY agent";
483
+ return this.db.prepare(sql).all(...params);
484
+ }
485
+ getScopeLeakRate() {
486
+ return this.db.prepare(`
487
+ SELECT agent, COUNT(*) as total,
488
+ SUM(CASE WHEN scope_leak = 1 THEN 1 ELSE 0 END) as leaks,
489
+ ROUND(CAST(SUM(CASE WHEN scope_leak = 1 THEN 1 ELSE 0 END) AS REAL) / COUNT(*), 3) as rate
490
+ FROM run_records GROUP BY agent ORDER BY rate DESC
491
+ `).all();
492
+ }
493
+ // ============================================
494
+ // Cleanup
495
+ // ============================================
496
+ close() {
497
+ this.db.close();
498
+ }
499
+ getPath() {
500
+ return this.dbPath;
501
+ }
502
+ }
503
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nightshift-mcp",
3
- "version": "1.1.2",
3
+ "version": "2.0.1",
4
4
  "description": "Agent teams and multi-agent orchestration across AI models via MCP. Coordinate Claude, Codex, Gemini, Vibe, and Goose with delegation, failovers, and autonomous workflows.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,10 +42,12 @@
42
42
  "license": "MIT",
43
43
  "dependencies": {
44
44
  "@modelcontextprotocol/sdk": "^1.0.0",
45
+ "better-sqlite3": "^12.8.0",
45
46
  "proper-lockfile": "^4.1.2",
46
47
  "zod": "^3.25.0"
47
48
  },
48
49
  "devDependencies": {
50
+ "@types/better-sqlite3": "^7.6.13",
49
51
  "@types/node": "^20.0.0",
50
52
  "@types/proper-lockfile": "^4.1.4",
51
53
  "typescript": "^5.0.0",