@open-code-review/cli 1.8.4 → 1.10.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/dashboard/server.js +409 -213
- package/dist/index.js +251 -121
- package/dist/lib/db/index.js +128 -17
- package/package.json +2 -2
package/dist/lib/db/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createRequire as _cjsReq } from "module"; const require = _cjsReq(import.meta.url);
|
|
2
2
|
|
|
3
3
|
// src/lib/db/index.ts
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
5
|
-
import { dirname, join } from "node:path";
|
|
4
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
5
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import initSqlJs from "sql.js";
|
|
8
8
|
|
|
@@ -253,6 +253,14 @@ var MIGRATIONS = [
|
|
|
253
253
|
ALTER TABLE map_runs ADD COLUMN source TEXT DEFAULT NULL;
|
|
254
254
|
ALTER TABLE map_runs ADD COLUMN section_count INTEGER DEFAULT 0;
|
|
255
255
|
`
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
version: 9,
|
|
259
|
+
description: "Add uid column to command_executions for JSONL-backed recovery",
|
|
260
|
+
sql: `
|
|
261
|
+
ALTER TABLE command_executions ADD COLUMN uid TEXT;
|
|
262
|
+
CREATE UNIQUE INDEX idx_command_executions_uid ON command_executions(uid);
|
|
263
|
+
`
|
|
256
264
|
}
|
|
257
265
|
];
|
|
258
266
|
function ensureSchemaVersionTable(db) {
|
|
@@ -424,12 +432,109 @@ function getLatestEventId(db) {
|
|
|
424
432
|
return typeof val === "number" ? val : 0;
|
|
425
433
|
}
|
|
426
434
|
|
|
435
|
+
// src/lib/db/command-log.ts
|
|
436
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
437
|
+
import { dirname, join } from "node:path";
|
|
438
|
+
import { randomUUID } from "node:crypto";
|
|
439
|
+
var CACHE_DIR = ".cache";
|
|
440
|
+
var FILENAME = "command-history.jsonl";
|
|
441
|
+
var MAX_LINES = 5e3;
|
|
442
|
+
var KEEP_LINES = 4e3;
|
|
443
|
+
var approxLineCount = -1;
|
|
444
|
+
function generateCommandUid() {
|
|
445
|
+
return randomUUID();
|
|
446
|
+
}
|
|
447
|
+
function cacheDir(ocrDir) {
|
|
448
|
+
return join(ocrDir, "data", CACHE_DIR);
|
|
449
|
+
}
|
|
450
|
+
function commandLogPath(ocrDir) {
|
|
451
|
+
return join(cacheDir(ocrDir), FILENAME);
|
|
452
|
+
}
|
|
453
|
+
function appendCommandLog(ocrDir, entry) {
|
|
454
|
+
try {
|
|
455
|
+
const filePath = commandLogPath(ocrDir);
|
|
456
|
+
const dir = dirname(filePath);
|
|
457
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
458
|
+
const line = JSON.stringify(entry) + "\n";
|
|
459
|
+
appendFileSync(filePath, line, { encoding: "utf-8" });
|
|
460
|
+
if (approxLineCount >= 0) approxLineCount++;
|
|
461
|
+
rotateIfNeeded(filePath);
|
|
462
|
+
} catch {
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function readCommandLog(ocrDir) {
|
|
466
|
+
const filePath = commandLogPath(ocrDir);
|
|
467
|
+
if (!existsSync(filePath)) return [];
|
|
468
|
+
const content = readFileSync(filePath, "utf-8");
|
|
469
|
+
const entries = [];
|
|
470
|
+
for (const line of content.split("\n")) {
|
|
471
|
+
if (!line.trim()) continue;
|
|
472
|
+
try {
|
|
473
|
+
entries.push(JSON.parse(line));
|
|
474
|
+
} catch {
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return entries;
|
|
478
|
+
}
|
|
479
|
+
function replayCommandLog(db, ocrDir) {
|
|
480
|
+
const entries = readCommandLog(ocrDir);
|
|
481
|
+
if (entries.length === 0) return 0;
|
|
482
|
+
const latest = /* @__PURE__ */ new Map();
|
|
483
|
+
for (const entry of entries) {
|
|
484
|
+
if (!entry.uid || !entry.command || !entry.started_at) continue;
|
|
485
|
+
const existing = latest.get(entry.uid);
|
|
486
|
+
if (!existing || entry.event !== "start") {
|
|
487
|
+
latest.set(entry.uid, entry);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
let imported = 0;
|
|
491
|
+
for (const entry of latest.values()) {
|
|
492
|
+
if (entry.event === "start" && !entry.finished_at) continue;
|
|
493
|
+
const existing = db.exec(
|
|
494
|
+
"SELECT COUNT(*) as c FROM command_executions WHERE uid = ?",
|
|
495
|
+
[entry.uid]
|
|
496
|
+
);
|
|
497
|
+
if ((existing[0]?.values[0]?.[0] ?? 0) > 0) continue;
|
|
498
|
+
db.run(
|
|
499
|
+
`INSERT INTO command_executions
|
|
500
|
+
(uid, command, args, exit_code, started_at, finished_at, pid, is_detached)
|
|
501
|
+
VALUES (?, ?, ?, ?, ?, ?, NULL, ?)`,
|
|
502
|
+
[
|
|
503
|
+
entry.uid,
|
|
504
|
+
entry.command,
|
|
505
|
+
entry.args,
|
|
506
|
+
entry.exit_code,
|
|
507
|
+
entry.started_at,
|
|
508
|
+
entry.finished_at,
|
|
509
|
+
entry.is_detached
|
|
510
|
+
]
|
|
511
|
+
);
|
|
512
|
+
imported++;
|
|
513
|
+
}
|
|
514
|
+
return imported;
|
|
515
|
+
}
|
|
516
|
+
function rotateIfNeeded(filePath) {
|
|
517
|
+
try {
|
|
518
|
+
if (approxLineCount >= 0 && approxLineCount <= MAX_LINES) return;
|
|
519
|
+
const content = readFileSync(filePath, "utf-8");
|
|
520
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
521
|
+
approxLineCount = lines.length;
|
|
522
|
+
if (approxLineCount <= MAX_LINES) return;
|
|
523
|
+
const kept = lines.slice(lines.length - KEEP_LINES);
|
|
524
|
+
const tmpPath = `${filePath}.${process.pid}.tmp`;
|
|
525
|
+
writeFileSync(tmpPath, kept.join("\n") + "\n", { encoding: "utf-8" });
|
|
526
|
+
renameSync(tmpPath, filePath);
|
|
527
|
+
approxLineCount = KEEP_LINES;
|
|
528
|
+
} catch {
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
427
532
|
// src/lib/db/index.ts
|
|
428
533
|
var connections = /* @__PURE__ */ new Map();
|
|
429
534
|
function locateWasm() {
|
|
430
535
|
const require2 = createRequire(import.meta.url);
|
|
431
536
|
const sqlJsPath = require2.resolve("sql.js");
|
|
432
|
-
return
|
|
537
|
+
return join2(dirname2(sqlJsPath), "sql-wasm.wasm");
|
|
433
538
|
}
|
|
434
539
|
function applyPragmas(db) {
|
|
435
540
|
db.run("PRAGMA foreign_keys = ON;");
|
|
@@ -441,7 +546,7 @@ async function openDatabase(dbPath) {
|
|
|
441
546
|
if (cached) {
|
|
442
547
|
return cached;
|
|
443
548
|
}
|
|
444
|
-
const wasmBuffer =
|
|
549
|
+
const wasmBuffer = readFileSync2(locateWasm());
|
|
445
550
|
const wasmBinary = wasmBuffer.buffer.slice(
|
|
446
551
|
wasmBuffer.byteOffset,
|
|
447
552
|
wasmBuffer.byteOffset + wasmBuffer.byteLength
|
|
@@ -450,8 +555,8 @@ async function openDatabase(dbPath) {
|
|
|
450
555
|
wasmBinary
|
|
451
556
|
});
|
|
452
557
|
let db;
|
|
453
|
-
if (
|
|
454
|
-
const fileBuffer =
|
|
558
|
+
if (existsSync2(dbPath)) {
|
|
559
|
+
const fileBuffer = readFileSync2(dbPath);
|
|
455
560
|
db = new SQL.Database(fileBuffer);
|
|
456
561
|
} else {
|
|
457
562
|
db = new SQL.Database();
|
|
@@ -462,24 +567,24 @@ async function openDatabase(dbPath) {
|
|
|
462
567
|
}
|
|
463
568
|
function saveDatabase(db, dbPath) {
|
|
464
569
|
const data = db.export();
|
|
465
|
-
const dir =
|
|
466
|
-
if (!
|
|
467
|
-
|
|
570
|
+
const dir = dirname2(dbPath);
|
|
571
|
+
if (!existsSync2(dir)) {
|
|
572
|
+
mkdirSync2(dir, { recursive: true });
|
|
468
573
|
}
|
|
469
|
-
const tmpPath = dbPath
|
|
470
|
-
|
|
471
|
-
|
|
574
|
+
const tmpPath = `${dbPath}.${process.pid}.tmp`;
|
|
575
|
+
writeFileSync2(tmpPath, Buffer.from(data));
|
|
576
|
+
renameSync2(tmpPath, dbPath);
|
|
472
577
|
}
|
|
473
578
|
async function getDb(ocrDir) {
|
|
474
|
-
const dbPath =
|
|
579
|
+
const dbPath = join2(ocrDir, "data", "ocr.db");
|
|
475
580
|
return openDatabase(dbPath);
|
|
476
581
|
}
|
|
477
582
|
async function ensureDatabase(ocrDir) {
|
|
478
|
-
const dataDir =
|
|
479
|
-
if (!
|
|
480
|
-
|
|
583
|
+
const dataDir = join2(ocrDir, "data");
|
|
584
|
+
if (!existsSync2(dataDir)) {
|
|
585
|
+
mkdirSync2(dataDir, { recursive: true });
|
|
481
586
|
}
|
|
482
|
-
const dbPath =
|
|
587
|
+
const dbPath = join2(dataDir, "ocr.db");
|
|
483
588
|
const db = await openDatabase(dbPath);
|
|
484
589
|
runMigrations(db);
|
|
485
590
|
saveDatabase(db, dbPath);
|
|
@@ -500,10 +605,14 @@ function closeAllDatabases() {
|
|
|
500
605
|
}
|
|
501
606
|
export {
|
|
502
607
|
MIGRATIONS,
|
|
608
|
+
appendCommandLog,
|
|
503
609
|
applyPragmas,
|
|
610
|
+
cacheDir,
|
|
504
611
|
closeAllDatabases,
|
|
505
612
|
closeDatabase,
|
|
613
|
+
commandLogPath,
|
|
506
614
|
ensureDatabase,
|
|
615
|
+
generateCommandUid,
|
|
507
616
|
getAllSessions,
|
|
508
617
|
getDb,
|
|
509
618
|
getEventsForSession,
|
|
@@ -514,6 +623,8 @@ export {
|
|
|
514
623
|
insertSession,
|
|
515
624
|
locateWasm,
|
|
516
625
|
openDatabase,
|
|
626
|
+
readCommandLog,
|
|
627
|
+
replayCommandLog,
|
|
517
628
|
resultToRow,
|
|
518
629
|
resultToRows,
|
|
519
630
|
runMigrations,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-code-review/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "CLI for Open Code Review - Multi-environment setup and progress tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"ora": "^8.1.1",
|
|
51
51
|
"socket.io": "^4.8",
|
|
52
52
|
"sql.js": "^1.14.1",
|
|
53
|
-
"@open-code-review/agents": "1.
|
|
53
|
+
"@open-code-review/agents": "1.10.0"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|