@swestash/agent-lens 0.11.0 → 0.11.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.
- package/README.md +5 -3
- package/dist/agent-lens.js +217 -175
- package/dist/agent-lens.js.map +1 -1
- package/package.json +1 -2
- package/web/404.html +1 -1
- package/web/assets/{AboutView-B6r8WJKS.js → AboutView-ttDCxp0d.js} +1 -1
- package/web/assets/{Dashboard-C0axgFBI.js → Dashboard-CdjRQBg_.js} +1 -1
- package/web/assets/{FileView-D3OB1c3e.js → FileView-0gYNqeF8.js} +1 -1
- package/web/assets/{FilesView-DYSJHOfO.js → FilesView-CMwzNpYU.js} +1 -1
- package/web/assets/{SecurityView-Dl5rRtT4.js → SecurityView-B8QFRIOR.js} +1 -1
- package/web/assets/{SessionView-77dXiwzp.js → SessionView-C3NBGoRm.js} +1 -1
- package/web/assets/{SkillView-Bkwf24pB.js → SkillView-ChrzRaaf.js} +1 -1
- package/web/assets/{SkillsView-CAGiD59V.js → SkillsView-BS-Hhx-l.js} +1 -1
- package/web/assets/{WorkflowView-CR2GzUdU.js → WorkflowView-BohpjfRN.js} +1 -1
- package/web/assets/{index-BxbXFMQG.js → index-0iQ2t2WR.js} +2 -2
- package/web/assets/{index-BnVRCFL6.js → index-DWa5WNaY.js} +1 -1
- package/web/assets/{jsonish-B3QCD4cU.js → jsonish-Bvk9aoZ9.js} +1 -1
- package/web/assets/{severity-DTzxtVJn.js → severity-FT-qpBVJ.js} +1 -1
- package/web/index.html +1 -1
package/dist/agent-lens.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { existsSync as existsSync10, writeFileSync as writeFileSync3 } from "fs";
|
|
5
|
-
import { join as join12 } from "path";
|
|
6
|
-
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
4
|
+
import { existsSync as existsSync10, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5
|
+
import { join as join12 } from "node:path";
|
|
6
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
7
7
|
|
|
8
8
|
// ../../node_modules/.pnpm/cac@6.7.14/node_modules/cac/dist/index.mjs
|
|
9
9
|
import { EventEmitter } from "events";
|
|
@@ -921,6 +921,29 @@ END;
|
|
|
921
921
|
`
|
|
922
922
|
);
|
|
923
923
|
|
|
924
|
+
// ../core/dist/sqlite.js
|
|
925
|
+
function runNamed(stmt, row) {
|
|
926
|
+
return stmt.run(row);
|
|
927
|
+
}
|
|
928
|
+
var savepointSeq = 0;
|
|
929
|
+
function transaction(db, fn) {
|
|
930
|
+
return (...args) => {
|
|
931
|
+
const savepoint = db.isTransaction ? `agent_lens_sp_${savepointSeq++}` : "";
|
|
932
|
+
db.exec(savepoint ? `SAVEPOINT ${savepoint}` : "BEGIN");
|
|
933
|
+
try {
|
|
934
|
+
const result = fn(...args);
|
|
935
|
+
db.exec(savepoint ? `RELEASE ${savepoint}` : "COMMIT");
|
|
936
|
+
return result;
|
|
937
|
+
} catch (err) {
|
|
938
|
+
try {
|
|
939
|
+
db.exec(savepoint ? `ROLLBACK TO ${savepoint}; RELEASE ${savepoint}` : "ROLLBACK");
|
|
940
|
+
} catch {
|
|
941
|
+
}
|
|
942
|
+
throw err;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
|
|
924
947
|
// ../core/dist/security.js
|
|
925
948
|
var SEVERITY_ORDER = ["info", "low", "medium", "high", "critical"];
|
|
926
949
|
function severityRank(s) {
|
|
@@ -1076,7 +1099,7 @@ function scrubUsernames(text, users) {
|
|
|
1076
1099
|
}
|
|
1077
1100
|
|
|
1078
1101
|
// ../core/dist/redact-export.js
|
|
1079
|
-
import { createHash } from "crypto";
|
|
1102
|
+
import { createHash } from "node:crypto";
|
|
1080
1103
|
|
|
1081
1104
|
// ../core/dist/markdown.js
|
|
1082
1105
|
function truncate(s) {
|
|
@@ -1313,6 +1336,9 @@ var activeTable = PRICE_TABLE;
|
|
|
1313
1336
|
function usePricing(table) {
|
|
1314
1337
|
activeTable = table;
|
|
1315
1338
|
}
|
|
1339
|
+
function activePricing() {
|
|
1340
|
+
return activeTable;
|
|
1341
|
+
}
|
|
1316
1342
|
function rateForModel(model) {
|
|
1317
1343
|
if (!model)
|
|
1318
1344
|
return null;
|
|
@@ -1333,25 +1359,24 @@ function costForUsage(model, u) {
|
|
|
1333
1359
|
}
|
|
1334
1360
|
|
|
1335
1361
|
// ../core/dist/rawjson.js
|
|
1336
|
-
import { gzipSync, gunzipSync } from "zlib";
|
|
1362
|
+
import { gzipSync, gunzipSync } from "node:zlib";
|
|
1337
1363
|
function packRaw(json) {
|
|
1338
1364
|
return gzipSync(Buffer.from(json, "utf8"));
|
|
1339
1365
|
}
|
|
1340
1366
|
function unpackRaw(value) {
|
|
1341
|
-
if (
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
return value.toString("utf8");
|
|
1367
|
+
if (typeof value === "string")
|
|
1368
|
+
return value;
|
|
1369
|
+
if (value.length >= 2 && value[0] === 31 && value[1] === 139) {
|
|
1370
|
+
return gunzipSync(value).toString("utf8");
|
|
1346
1371
|
}
|
|
1347
|
-
return value;
|
|
1372
|
+
return Buffer.from(value).toString("utf8");
|
|
1348
1373
|
}
|
|
1349
1374
|
|
|
1350
1375
|
// ../core/dist/paths.js
|
|
1351
|
-
import { existsSync, readFileSync } from "fs";
|
|
1352
|
-
import { dirname, join, resolve } from "path";
|
|
1353
|
-
import { fileURLToPath } from "url";
|
|
1354
|
-
import { homedir, platform } from "os";
|
|
1376
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1377
|
+
import { dirname, join, resolve } from "node:path";
|
|
1378
|
+
import { fileURLToPath } from "node:url";
|
|
1379
|
+
import { homedir, platform } from "node:os";
|
|
1355
1380
|
function expandPath(p) {
|
|
1356
1381
|
if (!p)
|
|
1357
1382
|
return p;
|
|
@@ -1429,8 +1454,8 @@ function resolveWebDist(fromDir, repoRoot = findRepoRoot(fromDir)) {
|
|
|
1429
1454
|
}
|
|
1430
1455
|
|
|
1431
1456
|
// ../core/dist/config.js
|
|
1432
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
1433
|
-
import { join as join2 } from "path";
|
|
1457
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
1458
|
+
import { join as join2 } from "node:path";
|
|
1434
1459
|
var DEFAULT_PORT = 4477;
|
|
1435
1460
|
var DEFAULT_HOST = "127.0.0.1";
|
|
1436
1461
|
var DEFAULT_DB_NAME = "agent-lens.db";
|
|
@@ -1512,10 +1537,10 @@ function resolveServerConfig(overrides = {}, cfg = readConfigFile()) {
|
|
|
1512
1537
|
}
|
|
1513
1538
|
|
|
1514
1539
|
// ../core/dist/version.js
|
|
1515
|
-
import { spawnSync } from "child_process";
|
|
1516
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
1517
|
-
import { dirname as dirname2, join as join3, parse } from "path";
|
|
1518
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1540
|
+
import { spawnSync } from "node:child_process";
|
|
1541
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
1542
|
+
import { dirname as dirname2, join as join3, parse } from "node:path";
|
|
1543
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
1519
1544
|
var moduleDir2 = dirname2(fileURLToPath2(import.meta.url));
|
|
1520
1545
|
function isPlaceholder(v) {
|
|
1521
1546
|
return v.startsWith("0.0.0");
|
|
@@ -1617,9 +1642,9 @@ function encodeProjectPath(p) {
|
|
|
1617
1642
|
}
|
|
1618
1643
|
|
|
1619
1644
|
// ../core/dist/collect.js
|
|
1620
|
-
import { appendFileSync, closeSync, copyFileSync, existsSync as existsSync2, mkdirSync, openSync, readSync, readdirSync, statSync, unlinkSync, utimesSync, writeSync, chmodSync } from "fs";
|
|
1621
|
-
import { basename, dirname as dirname3, join as join4, relative, sep } from "path";
|
|
1622
|
-
import { platform as platform2 } from "os";
|
|
1645
|
+
import { appendFileSync, closeSync, copyFileSync, existsSync as existsSync2, mkdirSync, openSync, readSync, readdirSync, statSync, unlinkSync, utimesSync, writeSync, chmodSync } from "node:fs";
|
|
1646
|
+
import { basename, dirname as dirname3, join as join4, relative, sep } from "node:path";
|
|
1647
|
+
import { platform as platform2 } from "node:os";
|
|
1623
1648
|
var POSIX = platform2() !== "win32";
|
|
1624
1649
|
var DIR_MODE = 448;
|
|
1625
1650
|
var FILE_MODE = 384;
|
|
@@ -1838,9 +1863,9 @@ function collectAll(opts = {}) {
|
|
|
1838
1863
|
}
|
|
1839
1864
|
|
|
1840
1865
|
// ../core/dist/lock.js
|
|
1841
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
1842
|
-
import { dirname as dirname4 } from "path";
|
|
1843
|
-
import { hostname } from "os";
|
|
1866
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
|
|
1867
|
+
import { dirname as dirname4 } from "node:path";
|
|
1868
|
+
import { hostname } from "node:os";
|
|
1844
1869
|
function isAlive(pid) {
|
|
1845
1870
|
if (!pid)
|
|
1846
1871
|
return false;
|
|
@@ -1880,10 +1905,10 @@ function acquireLock(lockPath, staleMs = 6 * 60 * 60 * 1e3) {
|
|
|
1880
1905
|
}
|
|
1881
1906
|
|
|
1882
1907
|
// ../core/dist/service.js
|
|
1883
|
-
import { spawnSync as spawnSync2 } from "child_process";
|
|
1884
|
-
import { mkdirSync as mkdirSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1885
|
-
import { homedir as homedir2, platform as platform3, userInfo } from "os";
|
|
1886
|
-
import { join as join5 } from "path";
|
|
1908
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1909
|
+
import { mkdirSync as mkdirSync3, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1910
|
+
import { homedir as homedir2, platform as platform3, userInfo } from "node:os";
|
|
1911
|
+
import { join as join5 } from "node:path";
|
|
1887
1912
|
var DEFAULT_HOURS = [9, 13, 17, 21];
|
|
1888
1913
|
function currentUser() {
|
|
1889
1914
|
try {
|
|
@@ -2208,15 +2233,15 @@ function runService(action, params) {
|
|
|
2208
2233
|
}
|
|
2209
2234
|
|
|
2210
2235
|
// ../ingest/dist/run.js
|
|
2211
|
-
import { readFileSync as readFileSync6, statSync as statSync3, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
|
|
2212
|
-
import { dirname as dirname6, join as join9 } from "path";
|
|
2236
|
+
import { readFileSync as readFileSync6, statSync as statSync3, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "node:fs";
|
|
2237
|
+
import { dirname as dirname6, join as join9 } from "node:path";
|
|
2213
2238
|
|
|
2214
2239
|
// ../ingest/dist/db.js
|
|
2215
|
-
import
|
|
2240
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2216
2241
|
function openRaw(file) {
|
|
2217
|
-
const db = new
|
|
2218
|
-
db.
|
|
2219
|
-
db.
|
|
2242
|
+
const db = new DatabaseSync(file);
|
|
2243
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
2244
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
2220
2245
|
return db;
|
|
2221
2246
|
}
|
|
2222
2247
|
function readSchemaVersion(db) {
|
|
@@ -2236,37 +2261,40 @@ function openDb(file) {
|
|
|
2236
2261
|
return db;
|
|
2237
2262
|
}
|
|
2238
2263
|
function resetSchema(db) {
|
|
2239
|
-
db.
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2264
|
+
db.exec("PRAGMA foreign_keys = OFF");
|
|
2265
|
+
try {
|
|
2266
|
+
db.exec(`
|
|
2267
|
+
DROP TRIGGER IF EXISTS events_au;
|
|
2268
|
+
DROP TRIGGER IF EXISTS events_ad;
|
|
2269
|
+
DROP TRIGGER IF EXISTS events_ai;
|
|
2270
|
+
DROP TABLE IF EXISTS events_fts;
|
|
2271
|
+
DROP TABLE IF EXISTS file_changes;
|
|
2272
|
+
DROP TABLE IF EXISTS findings;
|
|
2273
|
+
DROP TABLE IF EXISTS classifications;
|
|
2274
|
+
DROP TABLE IF EXISTS token_usage;
|
|
2275
|
+
DROP TABLE IF EXISTS tool_calls;
|
|
2276
|
+
DROP TABLE IF EXISTS skills;
|
|
2277
|
+
DROP TABLE IF EXISTS events;
|
|
2278
|
+
DROP TABLE IF EXISTS turns;
|
|
2279
|
+
DROP TABLE IF EXISTS sessions;
|
|
2280
|
+
DROP TABLE IF EXISTS projects;
|
|
2281
|
+
DROP TABLE IF EXISTS sources;
|
|
2282
|
+
DROP TABLE IF EXISTS agents;
|
|
2283
|
+
DROP TABLE IF EXISTS workflow_results;
|
|
2284
|
+
DROP TABLE IF EXISTS session_meta;
|
|
2285
|
+
DROP TABLE IF EXISTS tool_results;
|
|
2286
|
+
DROP TABLE IF EXISTS ingest_state;
|
|
2287
|
+
DROP TABLE IF EXISTS meta;
|
|
2288
|
+
`);
|
|
2289
|
+
applySchema(db);
|
|
2290
|
+
} finally {
|
|
2291
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
2292
|
+
}
|
|
2265
2293
|
}
|
|
2266
2294
|
|
|
2267
2295
|
// ../ingest/dist/adapters/claude-code.js
|
|
2268
|
-
import { readdirSync as readdirSync2 } from "fs";
|
|
2269
|
-
import { basename as basename2, join as join6 } from "path";
|
|
2296
|
+
import { readdirSync as readdirSync2 } from "node:fs";
|
|
2297
|
+
import { basename as basename2, join as join6 } from "node:path";
|
|
2270
2298
|
function flattenText(content) {
|
|
2271
2299
|
if (content == null)
|
|
2272
2300
|
return null;
|
|
@@ -2527,7 +2555,7 @@ function createDirtySet(db, name, ids) {
|
|
|
2527
2555
|
db.exec(`DROP TABLE IF EXISTS ${name}`);
|
|
2528
2556
|
db.exec(`CREATE TEMP TABLE ${name} (id TEXT PRIMARY KEY)`);
|
|
2529
2557
|
const ins = db.prepare(`INSERT OR IGNORE INTO ${name} (id) VALUES (?)`);
|
|
2530
|
-
|
|
2558
|
+
transaction(db, (xs) => {
|
|
2531
2559
|
for (const id of xs)
|
|
2532
2560
|
ins.run(id);
|
|
2533
2561
|
})(ids);
|
|
@@ -2727,7 +2755,7 @@ function classify(db, dirty) {
|
|
|
2727
2755
|
category=excluded.category, complexity_score=excluded.complexity_score,
|
|
2728
2756
|
complexity_band=excluded.complexity_band, signals_json=excluded.signals_json,
|
|
2729
2757
|
classifier_version=excluded.classifier_version`);
|
|
2730
|
-
const tx =
|
|
2758
|
+
const tx = transaction(db, () => {
|
|
2731
2759
|
for (const sess of sessions) {
|
|
2732
2760
|
const toolCounts = toolMix.get(sess.id) ?? {};
|
|
2733
2761
|
const skills = skillMix.get(sess.id) ?? {};
|
|
@@ -2798,8 +2826,8 @@ function classify(db, dirty) {
|
|
|
2798
2826
|
}
|
|
2799
2827
|
|
|
2800
2828
|
// ../ingest/dist/detect.js
|
|
2801
|
-
import { createHash as createHash2 } from "crypto";
|
|
2802
|
-
import { posix as path } from "path";
|
|
2829
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
2830
|
+
import { posix as path } from "node:path";
|
|
2803
2831
|
var DETECTOR_VERSION = 8;
|
|
2804
2832
|
function evidence(s, max = 200) {
|
|
2805
2833
|
const one = s.replace(/\s+/g, " ").trim();
|
|
@@ -3264,7 +3292,7 @@ function detect(db, dirty) {
|
|
|
3264
3292
|
VALUES (@id, @session_id, @tool_call_id, @event_uuid, @turn_id, @rule_id, @category, @framework_ref, @severity, @title, @evidence, @signals_json, @detector_version)
|
|
3265
3293
|
ON CONFLICT(id) DO NOTHING`);
|
|
3266
3294
|
const delScope = incremental ? "DELETE FROM findings WHERE session_id IN (SELECT id FROM _dirty_sec)" : "DELETE FROM findings";
|
|
3267
|
-
const tx =
|
|
3295
|
+
const tx = transaction(db, () => {
|
|
3268
3296
|
db.exec(delScope);
|
|
3269
3297
|
for (const row of rows) {
|
|
3270
3298
|
const ctx = buildContext(row, projPath.get(row.session_id) ?? null, ownedConfigDirs);
|
|
@@ -3324,7 +3352,7 @@ function classifyErrors(db, dirty) {
|
|
|
3324
3352
|
createDirtySet(db, "_dirty_err", dirty);
|
|
3325
3353
|
const rows = db.prepare(`SELECT id, result_summary FROM tool_calls WHERE status = 'error'${scope}`).all();
|
|
3326
3354
|
const update = db.prepare("UPDATE tool_calls SET error_type = ? WHERE id = ?");
|
|
3327
|
-
const tx =
|
|
3355
|
+
const tx = transaction(db, () => {
|
|
3328
3356
|
db.exec(`UPDATE tool_calls SET error_type = NULL WHERE error_type IS NOT NULL${scope}`);
|
|
3329
3357
|
for (const r of rows)
|
|
3330
3358
|
update.run(classifyToolError(r.result_summary).type, r.id);
|
|
@@ -3337,8 +3365,8 @@ function classifyErrors(db, dirty) {
|
|
|
3337
3365
|
}
|
|
3338
3366
|
|
|
3339
3367
|
// ../ingest/dist/filechanges.js
|
|
3340
|
-
import { createHash as createHash3 } from "crypto";
|
|
3341
|
-
import { posix as path2 } from "path";
|
|
3368
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
3369
|
+
import { posix as path2 } from "node:path";
|
|
3342
3370
|
var FILECHANGES_VERSION = 1;
|
|
3343
3371
|
var FILE_TOOLS = ["Edit", "Write", "NotebookEdit"];
|
|
3344
3372
|
function fileChangeId(toolCallId, filePath) {
|
|
@@ -3370,7 +3398,7 @@ function deriveFileChanges(db, dirty) {
|
|
|
3370
3398
|
db.exec("DROP TABLE IF EXISTS _dirty_fc");
|
|
3371
3399
|
db.exec("CREATE TEMP TABLE _dirty_fc (id TEXT PRIMARY KEY)");
|
|
3372
3400
|
const ins = db.prepare("INSERT OR IGNORE INTO _dirty_fc (id) VALUES (?)");
|
|
3373
|
-
|
|
3401
|
+
transaction(db, (ids) => {
|
|
3374
3402
|
for (const id of ids)
|
|
3375
3403
|
ins.run(id);
|
|
3376
3404
|
})(dirty);
|
|
@@ -3387,7 +3415,7 @@ function deriveFileChanges(db, dirty) {
|
|
|
3387
3415
|
VALUES (@id, @tool_call_id, @session_id, @turn_id, @event_uuid, @project_id, @file_path, @tool_name, @lines_added, @lines_removed, @timestamp, @derive_version)
|
|
3388
3416
|
ON CONFLICT(id) DO NOTHING`);
|
|
3389
3417
|
const delScope = incremental ? "DELETE FROM file_changes WHERE session_id IN (SELECT id FROM _dirty_fc)" : "DELETE FROM file_changes";
|
|
3390
|
-
const tx =
|
|
3418
|
+
const tx = transaction(db, () => {
|
|
3391
3419
|
db.exec(delScope);
|
|
3392
3420
|
for (const row of rows) {
|
|
3393
3421
|
if (row.status === "error")
|
|
@@ -3436,10 +3464,10 @@ function deriveFileChanges(db, dirty) {
|
|
|
3436
3464
|
}
|
|
3437
3465
|
|
|
3438
3466
|
// ../ingest/dist/canonicalize.js
|
|
3439
|
-
import { existsSync as existsSync4 } from "fs";
|
|
3440
|
-
import { homedir as homedir3 } from "os";
|
|
3441
|
-
import { createHash as createHash4 } from "crypto";
|
|
3442
|
-
import { dirname as dirname5, join as join7 } from "path";
|
|
3467
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
3468
|
+
import { homedir as homedir3 } from "node:os";
|
|
3469
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
3470
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
3443
3471
|
function projectId(agentId, path3) {
|
|
3444
3472
|
return createHash4("sha1").update(`${agentId}\0${path3}`).digest("hex").slice(0, 16);
|
|
3445
3473
|
}
|
|
@@ -3495,7 +3523,7 @@ function canonicalizeProjects(db, opts = {}) {
|
|
|
3495
3523
|
const repointSessions = db.prepare("UPDATE sessions SET project_id = ? WHERE project_id = ?");
|
|
3496
3524
|
const repointFileChanges = db.prepare("UPDATE file_changes SET project_id = ? WHERE project_id = ?");
|
|
3497
3525
|
const touched = /* @__PURE__ */ new Set();
|
|
3498
|
-
|
|
3526
|
+
transaction(db, () => {
|
|
3499
3527
|
for (const r of rows) {
|
|
3500
3528
|
const target = canon(r.path);
|
|
3501
3529
|
if (target === strip(r.path))
|
|
@@ -3519,12 +3547,12 @@ function canonicalizeProjects(db, opts = {}) {
|
|
|
3519
3547
|
for (const id of touched)
|
|
3520
3548
|
refresh.run(id);
|
|
3521
3549
|
})();
|
|
3522
|
-
const removed = db.prepare("DELETE FROM projects WHERE id NOT IN (SELECT DISTINCT project_id FROM sessions WHERE project_id IS NOT NULL)").run().changes;
|
|
3550
|
+
const removed = Number(db.prepare("DELETE FROM projects WHERE id NOT IN (SELECT DISTINCT project_id FROM sessions WHERE project_id IS NOT NULL)").run().changes);
|
|
3523
3551
|
return { merged, removed };
|
|
3524
3552
|
}
|
|
3525
3553
|
|
|
3526
3554
|
// ../ingest/dist/pipeline.js
|
|
3527
|
-
import { createHash as createHash5 } from "crypto";
|
|
3555
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
3528
3556
|
function newStats() {
|
|
3529
3557
|
return { files: 0, skipped: 0, malformed: 0, newEvents: 0 };
|
|
3530
3558
|
}
|
|
@@ -3588,20 +3616,23 @@ function pruneExcluded(db, excludedPaths) {
|
|
|
3588
3616
|
return 0;
|
|
3589
3617
|
}
|
|
3590
3618
|
const files = db.prepare("SELECT DISTINCT source_file f FROM events WHERE session_id IN (SELECT id FROM _prune) AND source_file IS NOT NULL").all().map((r) => r.f);
|
|
3591
|
-
db.
|
|
3592
|
-
|
|
3593
|
-
db
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3619
|
+
db.exec("PRAGMA foreign_keys = OFF");
|
|
3620
|
+
try {
|
|
3621
|
+
transaction(db, () => {
|
|
3622
|
+
db.exec("DELETE FROM findings WHERE session_id IN (SELECT id FROM _prune)");
|
|
3623
|
+
db.exec("DELETE FROM file_changes WHERE session_id IN (SELECT id FROM _prune)");
|
|
3624
|
+
for (const t of ["token_usage", "tool_calls", "turns", "events"])
|
|
3625
|
+
db.exec(`DELETE FROM ${t} WHERE session_id IN (SELECT id FROM _prune)`);
|
|
3626
|
+
db.exec("DELETE FROM classifications WHERE scope = 'session' AND target_id IN (SELECT id FROM _prune)");
|
|
3627
|
+
db.exec("DELETE FROM sessions WHERE id IN (SELECT id FROM _prune)");
|
|
3628
|
+
const delState = db.prepare("DELETE FROM ingest_state WHERE file_path = ?");
|
|
3629
|
+
for (const f of files)
|
|
3630
|
+
delState.run(f);
|
|
3631
|
+
db.exec("DELETE FROM projects WHERE id NOT IN (SELECT DISTINCT project_id FROM sessions WHERE project_id IS NOT NULL)");
|
|
3632
|
+
})();
|
|
3633
|
+
} finally {
|
|
3634
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
3635
|
+
}
|
|
3605
3636
|
db.exec("DROP TABLE IF EXISTS _prune");
|
|
3606
3637
|
return total;
|
|
3607
3638
|
}
|
|
@@ -3683,12 +3714,12 @@ function rebuildTurns(db, scope, sessionIds) {
|
|
|
3683
3714
|
const insTurn = db.prepare(`INSERT INTO turns (id, session_id, seq, user_event_uuid, prompt_preview, model, started_at, ended_at, duration_ms)
|
|
3684
3715
|
VALUES (@id, @session_id, @seq, @user_event_uuid, @prompt_preview, @model, @started_at, @ended_at, @duration_ms)`);
|
|
3685
3716
|
const updEventTurn = db.prepare("UPDATE events SET turn_id = ? WHERE uuid = ?");
|
|
3686
|
-
const tx =
|
|
3717
|
+
const tx = transaction(db, () => {
|
|
3687
3718
|
for (const { id } of sessionIds) {
|
|
3688
3719
|
const rows = selEvents.all(id);
|
|
3689
3720
|
const { turns, eventTurn } = buildTurns(id, rows);
|
|
3690
3721
|
for (const t of turns)
|
|
3691
|
-
insTurn
|
|
3722
|
+
runNamed(insTurn, t);
|
|
3692
3723
|
for (const [uuid, turnId] of eventTurn)
|
|
3693
3724
|
updEventTurn.run(turnId, uuid);
|
|
3694
3725
|
}
|
|
@@ -3707,7 +3738,7 @@ function linkSkillVersions(db, sessionIds) {
|
|
|
3707
3738
|
first_seen = MIN(first_seen, excluded.first_seen),
|
|
3708
3739
|
base_dir = excluded.base_dir`);
|
|
3709
3740
|
const linkCall = db.prepare("UPDATE tool_calls SET skill_id = ? WHERE id = ?");
|
|
3710
|
-
const linkTx =
|
|
3741
|
+
const linkTx = transaction(db, () => {
|
|
3711
3742
|
for (const { id: sid } of sessionIds) {
|
|
3712
3743
|
const calls = selSkillCalls.all(sid);
|
|
3713
3744
|
if (!calls.length)
|
|
@@ -3905,7 +3936,7 @@ function prepareStatements(db) {
|
|
|
3905
3936
|
function ingestFile(db, stmts, adapter, file, lines, meta, now2, stats) {
|
|
3906
3937
|
const sessionMeta = {};
|
|
3907
3938
|
let eventsInFile = 0;
|
|
3908
|
-
const tx =
|
|
3939
|
+
const tx = transaction(db, () => {
|
|
3909
3940
|
stmts.insSessionStub.run(file.sessionId, adapter.agentId, file.sourceId);
|
|
3910
3941
|
let seq = 0;
|
|
3911
3942
|
for (const line of lines) {
|
|
@@ -3929,10 +3960,10 @@ function ingestFile(db, stmts, adapter, file, lines, meta, now2, stats) {
|
|
|
3929
3960
|
}
|
|
3930
3961
|
}
|
|
3931
3962
|
if (parsed.tokenUsage)
|
|
3932
|
-
stmts.insTokens
|
|
3963
|
+
runNamed(stmts.insTokens, parsed.tokenUsage);
|
|
3933
3964
|
if (parsed.toolCalls)
|
|
3934
3965
|
for (const tc of parsed.toolCalls)
|
|
3935
|
-
stmts.insTool
|
|
3966
|
+
runNamed(stmts.insTool, tc);
|
|
3936
3967
|
if (parsed.toolResults)
|
|
3937
3968
|
for (const tr of parsed.toolResults)
|
|
3938
3969
|
stmts.patchTool.run({
|
|
@@ -3986,14 +4017,13 @@ function ingestFile(db, stmts, adapter, file, lines, meta, now2, stats) {
|
|
|
3986
4017
|
}
|
|
3987
4018
|
|
|
3988
4019
|
// ../ingest/dist/workflows.js
|
|
3989
|
-
import { basename as basename3 } from "path";
|
|
4020
|
+
import { basename as basename3 } from "node:path";
|
|
3990
4021
|
|
|
3991
4022
|
// ../ingest/dist/sidecar.js
|
|
3992
|
-
import { readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
3993
|
-
import { join as join8 } from "path";
|
|
4023
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
|
|
4024
|
+
import { join as join8 } from "node:path";
|
|
3994
4025
|
|
|
3995
4026
|
// ../ingest/dist/redact.js
|
|
3996
|
-
import { createHash as createHash6, randomBytes } from "crypto";
|
|
3997
4027
|
function parseExcludes(csv) {
|
|
3998
4028
|
return (csv ?? "").split(",").map((s) => s.trim()).filter(Boolean).map(encodeProjectPath);
|
|
3999
4029
|
}
|
|
@@ -4002,17 +4032,17 @@ function isExcludedArchivePath(filePath, excluded) {
|
|
|
4002
4032
|
}
|
|
4003
4033
|
|
|
4004
4034
|
// ../ingest/dist/fileread.js
|
|
4005
|
-
import { createHash as
|
|
4006
|
-
import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
|
|
4007
|
-
import { StringDecoder } from "string_decoder";
|
|
4035
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
4036
|
+
import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "node:fs";
|
|
4037
|
+
import { StringDecoder } from "node:string_decoder";
|
|
4008
4038
|
var STREAM_THRESHOLD = 8 * 1024 * 1024;
|
|
4009
4039
|
var CHUNK2 = 64 * 1024;
|
|
4010
4040
|
function sha256(buf) {
|
|
4011
|
-
return
|
|
4041
|
+
return createHash6("sha256").update(buf).digest("hex");
|
|
4012
4042
|
}
|
|
4013
4043
|
function sha256File(path3) {
|
|
4014
4044
|
const fd = openSync2(path3, "r");
|
|
4015
|
-
const h =
|
|
4045
|
+
const h = createHash6("sha256");
|
|
4016
4046
|
const buf = Buffer.allocUnsafe(CHUNK2);
|
|
4017
4047
|
try {
|
|
4018
4048
|
let n;
|
|
@@ -4205,7 +4235,7 @@ function ingestWorkflowResults(db, sourceArchiveDir, sourceId, excludedDirs, now
|
|
|
4205
4235
|
}
|
|
4206
4236
|
|
|
4207
4237
|
// ../ingest/dist/meta.js
|
|
4208
|
-
import { basename as basename4 } from "path";
|
|
4238
|
+
import { basename as basename4 } from "node:path";
|
|
4209
4239
|
var newMetaStats = newSidecarStats;
|
|
4210
4240
|
function ingestSubagentMeta(db, sourceArchiveDir, sourceId, excludedDirs, now2, stats, full) {
|
|
4211
4241
|
const upsert = db.prepare(`INSERT INTO session_meta
|
|
@@ -4244,7 +4274,7 @@ function ingestSubagentMeta(db, sourceArchiveDir, sourceId, excludedDirs, now2,
|
|
|
4244
4274
|
}
|
|
4245
4275
|
|
|
4246
4276
|
// ../ingest/dist/toolResults.js
|
|
4247
|
-
import { basename as basename5 } from "path";
|
|
4277
|
+
import { basename as basename5 } from "node:path";
|
|
4248
4278
|
var newToolResultStats = newSidecarStats;
|
|
4249
4279
|
function ingestToolResults(db, sourceArchiveDir, excludedDirs, now2, stats, full) {
|
|
4250
4280
|
const upsert = db.prepare(`INSERT INTO tool_results (session_id, name, path, bytes, text, ingested_at)
|
|
@@ -4435,22 +4465,23 @@ function runMetrics(argv = process.argv.slice(2)) {
|
|
|
4435
4465
|
}
|
|
4436
4466
|
|
|
4437
4467
|
// ../server/dist/run.js
|
|
4438
|
-
import { existsSync as existsSync8 } from "fs";
|
|
4439
|
-
import { dirname as dirname7 } from "path";
|
|
4440
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4468
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
4469
|
+
import { dirname as dirname7 } from "node:path";
|
|
4470
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
4441
4471
|
|
|
4442
4472
|
// ../server/dist/db.js
|
|
4443
|
-
import
|
|
4473
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
4444
4474
|
|
|
4445
4475
|
// ../server/dist/sql-util.js
|
|
4476
|
+
var bind = (params) => params;
|
|
4446
4477
|
function tableExists(db, name) {
|
|
4447
4478
|
return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?").get(name);
|
|
4448
4479
|
}
|
|
4449
4480
|
function queryAll(db, sql, ...params) {
|
|
4450
|
-
return db.prepare(sql).all(...params);
|
|
4481
|
+
return db.prepare(sql).all(...bind(params));
|
|
4451
4482
|
}
|
|
4452
4483
|
function queryGet(db, sql, ...params) {
|
|
4453
|
-
return db.prepare(sql).get(...params);
|
|
4484
|
+
return db.prepare(sql).get(...bind(params));
|
|
4454
4485
|
}
|
|
4455
4486
|
function pushDateRange(clauses, params, col, from, to) {
|
|
4456
4487
|
if (from) {
|
|
@@ -4526,8 +4557,8 @@ function costOf(rows) {
|
|
|
4526
4557
|
|
|
4527
4558
|
// ../server/dist/db.js
|
|
4528
4559
|
function openReadonly(file) {
|
|
4529
|
-
const db = new
|
|
4530
|
-
db.
|
|
4560
|
+
const db = new DatabaseSync2(file, { readOnly: true });
|
|
4561
|
+
db.exec("PRAGMA query_only = ON");
|
|
4531
4562
|
return db;
|
|
4532
4563
|
}
|
|
4533
4564
|
function schemaStatus(db) {
|
|
@@ -4575,6 +4606,32 @@ function listModels(db) {
|
|
|
4575
4606
|
function toFtsQuery(raw) {
|
|
4576
4607
|
return raw.trim().split(/\s+/).filter(Boolean).map((t) => `"${t.replace(/"/g, '""')}"`).join(" ");
|
|
4577
4608
|
}
|
|
4609
|
+
var TOKENS_SORT_SQL = `(SELECT COALESCE(SUM(t.input_tokens + t.output_tokens
|
|
4610
|
+
+ t.cache_creation_input_tokens + t.cache_read_input_tokens), 0)
|
|
4611
|
+
FROM token_usage t WHERE t.session_id = s.id)`;
|
|
4612
|
+
var SECURITY_SORT_SQL = `(CASE worst_severity
|
|
4613
|
+
WHEN 'critical' THEN 5 WHEN 'high' THEN 4 WHEN 'medium' THEN 3 WHEN 'low' THEN 2 WHEN 'info' THEN 1
|
|
4614
|
+
ELSE 0 END) * 1000000 + finding_count`;
|
|
4615
|
+
var COST_SORT_SQL = `(SELECT COALESCE(SUM((tu.input_tokens * mr.i_rate + tu.output_tokens * mr.o_rate
|
|
4616
|
+
+ tu.cache_creation_input_tokens * mr.cw_rate + tu.cache_read_input_tokens * mr.cr_rate) / 1000000.0), 0)
|
|
4617
|
+
FROM token_usage tu LEFT JOIN model_rate mr ON mr.model IS tu.model
|
|
4618
|
+
WHERE tu.session_id = s.id)`;
|
|
4619
|
+
function ratesCte() {
|
|
4620
|
+
const entries = Object.entries(activePricing());
|
|
4621
|
+
return {
|
|
4622
|
+
// `model_rate` resolves the prefix match ONCE per distinct model id, not once per token_usage row.
|
|
4623
|
+
// Inlining the lookup into the cost expression instead re-ran it for every usage row of every
|
|
4624
|
+
// candidate session — ~35× slower on a real corpus, which would have made this "fix" a regression.
|
|
4625
|
+
sql: `WITH rates(prefix, i_rate, o_rate, cw_rate, cr_rate) AS (VALUES ${entries.map(() => "(?,?,?,?,?)").join(",")}),
|
|
4626
|
+
model_rate AS (
|
|
4627
|
+
SELECT m.model, r.i_rate, r.o_rate, r.cw_rate, r.cr_rate
|
|
4628
|
+
FROM (SELECT DISTINCT model FROM token_usage) m
|
|
4629
|
+
LEFT JOIN rates r ON r.prefix = (
|
|
4630
|
+
SELECT p.prefix FROM rates p WHERE substr(m.model, 1, length(p.prefix)) = p.prefix
|
|
4631
|
+
ORDER BY length(p.prefix) DESC LIMIT 1)) `,
|
|
4632
|
+
params: entries.flatMap(([prefix, r]) => [prefix, r.input, r.output, r.cacheWrite, r.cacheRead])
|
|
4633
|
+
};
|
|
4634
|
+
}
|
|
4578
4635
|
function listSessions(db, f) {
|
|
4579
4636
|
const where = [];
|
|
4580
4637
|
const params = [];
|
|
@@ -4619,41 +4676,19 @@ function listSessions(db, f) {
|
|
|
4619
4676
|
LIMIT 1) AS worst_severity
|
|
4620
4677
|
FROM sessions s LEFT JOIN projects p ON p.id = s.project_id
|
|
4621
4678
|
${whereSql}`;
|
|
4622
|
-
const
|
|
4679
|
+
const ORDER = {
|
|
4623
4680
|
started: "s.started_at",
|
|
4624
4681
|
title: "COALESCE(s.ai_title, s.slug)",
|
|
4625
4682
|
turns: "s.turn_count",
|
|
4626
|
-
duration: "s.duration_ms"
|
|
4683
|
+
duration: "s.duration_ms",
|
|
4684
|
+
errors: "tool_error_count",
|
|
4685
|
+
tokens: TOKENS_SORT_SQL,
|
|
4686
|
+
cost: COST_SORT_SQL,
|
|
4687
|
+
security: SECURITY_SORT_SQL
|
|
4627
4688
|
};
|
|
4628
4689
|
const sortKey = f.sort ?? "started";
|
|
4629
|
-
const
|
|
4630
|
-
|
|
4631
|
-
if (JS_SORT.has(sortKey)) {
|
|
4632
|
-
const all = attachSessionCost(db, queryAll(db, baseSelect, ...params));
|
|
4633
|
-
const sign = f.dir === "asc" ? 1 : -1;
|
|
4634
|
-
const metric = (r) => {
|
|
4635
|
-
switch (sortKey) {
|
|
4636
|
-
case "tokens":
|
|
4637
|
-
return r.tokens;
|
|
4638
|
-
case "cost":
|
|
4639
|
-
return r.cost;
|
|
4640
|
-
case "errors":
|
|
4641
|
-
return r.tool_error_count ?? 0;
|
|
4642
|
-
// Security: rank by worst severity (info=0 … critical=4; none = -1), finding count as tiebreak.
|
|
4643
|
-
case "security":
|
|
4644
|
-
return (severityRank(r.worst_severity ?? "") + 1) * 1e6 + (r.finding_count ?? 0);
|
|
4645
|
-
default:
|
|
4646
|
-
return 0;
|
|
4647
|
-
}
|
|
4648
|
-
};
|
|
4649
|
-
all.sort((a, b) => {
|
|
4650
|
-
const c = (metric(a) - metric(b)) * sign;
|
|
4651
|
-
return c !== 0 ? c : String(a.id).localeCompare(String(b.id));
|
|
4652
|
-
});
|
|
4653
|
-
sessions = all.slice(f.offset, f.offset + f.limit);
|
|
4654
|
-
} else {
|
|
4655
|
-
sessions = attachSessionCost(db, queryAll(db, `${baseSelect} ORDER BY ${orderBy(NATIVE_ORDER, sortKey, "started", f.dir)}, s.id ASC LIMIT ? OFFSET ?`, ...params, f.limit, f.offset));
|
|
4656
|
-
}
|
|
4690
|
+
const rates = sortKey === "cost" ? ratesCte() : null;
|
|
4691
|
+
const sessions = attachSessionCost(db, queryAll(db, `${rates?.sql ?? ""}${baseSelect} ORDER BY ${orderBy(ORDER, sortKey, "started", f.dir)}, s.id ASC LIMIT ? OFFSET ?`, ...rates?.params ?? [], ...params, f.limit, f.offset));
|
|
4657
4692
|
return { total, sessions };
|
|
4658
4693
|
}
|
|
4659
4694
|
function attachSessionCost(db, rows) {
|
|
@@ -5216,7 +5251,7 @@ function securitySummary(db) {
|
|
|
5216
5251
|
}
|
|
5217
5252
|
|
|
5218
5253
|
// ../server/dist/app.js
|
|
5219
|
-
import { existsSync as existsSync7 } from "fs";
|
|
5254
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
5220
5255
|
import Fastify from "fastify";
|
|
5221
5256
|
import fastifyStatic from "@fastify/static";
|
|
5222
5257
|
|
|
@@ -5274,11 +5309,18 @@ var usageForCost = (u) => ({
|
|
|
5274
5309
|
cache_creation_input_tokens: u.cw ?? 0,
|
|
5275
5310
|
cache_read_input_tokens: u.cr ?? 0
|
|
5276
5311
|
});
|
|
5277
|
-
function
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
const
|
|
5281
|
-
|
|
5312
|
+
function percentiles(db, values, params) {
|
|
5313
|
+
const at = (p) => `(SELECT COALESCE((SELECT v FROM vals ORDER BY v
|
|
5314
|
+
LIMIT 1 OFFSET MAX(0, CAST(ceil(${p} / 100.0 * (SELECT c FROM n)) AS INTEGER) - 1)), 0))`;
|
|
5315
|
+
const row = queryGet(
|
|
5316
|
+
db,
|
|
5317
|
+
// MATERIALIZED matters: the three selects below each reference `vals`, and without the hint
|
|
5318
|
+
// SQLite inlines the CTE and re-runs the underlying scan once per percentile.
|
|
5319
|
+
`WITH vals AS MATERIALIZED (${values}), n AS (SELECT COUNT(*) c FROM vals)
|
|
5320
|
+
SELECT ${at(50)} AS p50, ${at(95)} AS p95, (SELECT c FROM n) AS count`,
|
|
5321
|
+
...params
|
|
5322
|
+
);
|
|
5323
|
+
return row ?? { p50: 0, p95: 0, count: 0 };
|
|
5282
5324
|
}
|
|
5283
5325
|
function workflowWhere(f) {
|
|
5284
5326
|
const where = [];
|
|
@@ -5345,10 +5387,10 @@ function dashboardOverview(db, f) {
|
|
|
5345
5387
|
unpriced2.push(u.model);
|
|
5346
5388
|
}
|
|
5347
5389
|
const totalTokens = tokens.input + tokens.output + tokens.cache_creation + tokens.cache_read;
|
|
5348
|
-
const
|
|
5349
|
-
${w.sql ? w.sql + " AND" : "WHERE"} tn.duration_ms IS NOT NULL
|
|
5350
|
-
const
|
|
5351
|
-
${w.sql ? w.sql + " AND" : "WHERE"} s.is_sidechain = 0 AND s.duration_ms IS NOT NULL
|
|
5390
|
+
const turnDur = percentiles(db, `SELECT tn.duration_ms v FROM turns tn JOIN sessions s ON s.id = tn.session_id
|
|
5391
|
+
${w.sql ? w.sql + " AND" : "WHERE"} tn.duration_ms IS NOT NULL`, w.params);
|
|
5392
|
+
const sessDur = percentiles(db, `SELECT s.duration_ms v FROM sessions s
|
|
5393
|
+
${w.sql ? w.sql + " AND" : "WHERE"} s.is_sidechain = 0 AND s.duration_ms IS NOT NULL`, w.params);
|
|
5352
5394
|
return {
|
|
5353
5395
|
range: { from: f.from ?? null, to: f.to ?? null, source: f.source ?? null },
|
|
5354
5396
|
sessions: counts.sessions ?? 0,
|
|
@@ -5363,8 +5405,8 @@ function dashboardOverview(db, f) {
|
|
|
5363
5405
|
cache_read_ratio: totalTokens ? tokens.cache_read / totalTokens : 0,
|
|
5364
5406
|
cost: Number(cost.toFixed(4)),
|
|
5365
5407
|
unpriced_models: [...new Set(unpriced2)].sort(),
|
|
5366
|
-
turn_duration_ms:
|
|
5367
|
-
session_duration_ms:
|
|
5408
|
+
turn_duration_ms: turnDur,
|
|
5409
|
+
session_duration_ms: sessDur,
|
|
5368
5410
|
workflows: workflowAgg(db, f)
|
|
5369
5411
|
};
|
|
5370
5412
|
}
|
|
@@ -5529,8 +5571,8 @@ function dashboardBreakdowns(db, f) {
|
|
|
5529
5571
|
}
|
|
5530
5572
|
|
|
5531
5573
|
// ../server/dist/refresh.js
|
|
5532
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync5 } from "fs";
|
|
5533
|
-
import { join as join10 } from "path";
|
|
5574
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5 } from "node:fs";
|
|
5575
|
+
import { join as join10 } from "node:path";
|
|
5534
5576
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
5535
5577
|
function originAllowed(origin) {
|
|
5536
5578
|
if (!origin)
|
|
@@ -5567,7 +5609,7 @@ function runRefresh() {
|
|
|
5567
5609
|
}
|
|
5568
5610
|
|
|
5569
5611
|
// ../server/dist/triage.js
|
|
5570
|
-
import
|
|
5612
|
+
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
5571
5613
|
var TRIAGE_SCHEMA_SQL = (
|
|
5572
5614
|
/* sql */
|
|
5573
5615
|
`
|
|
@@ -5595,8 +5637,8 @@ CREATE TABLE IF NOT EXISTS muted_rules (
|
|
|
5595
5637
|
`
|
|
5596
5638
|
);
|
|
5597
5639
|
function openTriage(file) {
|
|
5598
|
-
const db = new
|
|
5599
|
-
db.
|
|
5640
|
+
const db = new DatabaseSync3(file);
|
|
5641
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
5600
5642
|
db.exec(TRIAGE_SCHEMA_SQL);
|
|
5601
5643
|
return db;
|
|
5602
5644
|
}
|
|
@@ -5605,7 +5647,7 @@ function dismiss(db, ids, note) {
|
|
|
5605
5647
|
const stmt = db.prepare(`INSERT INTO dismissed_findings (finding_id, note, dismissed_at) VALUES (?, ?, ?)
|
|
5606
5648
|
ON CONFLICT(finding_id) DO UPDATE SET note = excluded.note, dismissed_at = excluded.dismissed_at`);
|
|
5607
5649
|
const ts = now();
|
|
5608
|
-
const tx =
|
|
5650
|
+
const tx = transaction(db, (list) => {
|
|
5609
5651
|
for (const id of list)
|
|
5610
5652
|
stmt.run(id, note ?? null, ts);
|
|
5611
5653
|
});
|
|
@@ -5615,9 +5657,9 @@ function dismiss(db, ids, note) {
|
|
|
5615
5657
|
function reopen(db, ids) {
|
|
5616
5658
|
const stmt = db.prepare("DELETE FROM dismissed_findings WHERE finding_id = ?");
|
|
5617
5659
|
let n = 0;
|
|
5618
|
-
const tx =
|
|
5660
|
+
const tx = transaction(db, (list) => {
|
|
5619
5661
|
for (const id of list)
|
|
5620
|
-
n += stmt.run(id).changes;
|
|
5662
|
+
n += Number(stmt.run(id).changes);
|
|
5621
5663
|
});
|
|
5622
5664
|
tx(ids);
|
|
5623
5665
|
return n;
|
|
@@ -5627,14 +5669,14 @@ function muteRule(db, ruleId, scope = "global", scopeId = "", note) {
|
|
|
5627
5669
|
ON CONFLICT(rule_id, scope, scope_id) DO UPDATE SET note = excluded.note, muted_at = excluded.muted_at`).run(ruleId, scope, scope === "global" ? "" : scopeId, note ?? null, now());
|
|
5628
5670
|
}
|
|
5629
5671
|
function unmute(db, ruleId, scope = "global", scopeId = "") {
|
|
5630
|
-
return db.prepare("DELETE FROM muted_rules WHERE rule_id = ? AND scope = ? AND scope_id = ?").run(ruleId, scope, scope === "global" ? "" : scopeId).changes;
|
|
5672
|
+
return Number(db.prepare("DELETE FROM muted_rules WHERE rule_id = ? AND scope = ? AND scope_id = ?").run(ruleId, scope, scope === "global" ? "" : scopeId).changes);
|
|
5631
5673
|
}
|
|
5632
5674
|
function listMutes(db) {
|
|
5633
5675
|
return db.prepare("SELECT rule_id, scope, scope_id, note, muted_at FROM muted_rules ORDER BY muted_at DESC").all();
|
|
5634
5676
|
}
|
|
5635
5677
|
|
|
5636
5678
|
// ../server/dist/about.js
|
|
5637
|
-
import { statSync as statSync4 } from "fs";
|
|
5679
|
+
import { statSync as statSync4 } from "node:fs";
|
|
5638
5680
|
function storage(db, dbPath) {
|
|
5639
5681
|
const row = tableExists(db, "ingest_state") ? queryGet(db, "SELECT COUNT(*) files, SUM(size) bytes, MAX(ingested_at) last FROM ingest_state") : void 0;
|
|
5640
5682
|
let db_bytes = null;
|
|
@@ -6018,8 +6060,8 @@ async function startServer(overrides = {}) {
|
|
|
6018
6060
|
}
|
|
6019
6061
|
|
|
6020
6062
|
// src/watch.ts
|
|
6021
|
-
import { existsSync as existsSync9 } from "fs";
|
|
6022
|
-
import { join as join11 } from "path";
|
|
6063
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
6064
|
+
import { join as join11 } from "node:path";
|
|
6023
6065
|
import chokidar from "chokidar";
|
|
6024
6066
|
async function runWatch(opts = {}) {
|
|
6025
6067
|
const sources = loadSources();
|