repospend 0.0.3 → 0.0.4
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/CHANGELOG.md +4 -0
- package/dist/cli.js +71 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to RepoSpend will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.0.4
|
|
6
|
+
|
|
7
|
+
- Automatically retry Codex SQLite access after attempting to rebuild `better-sqlite3` when an `npx` or local install has a Node native module ABI mismatch.
|
|
8
|
+
|
|
5
9
|
## 0.0.3
|
|
6
10
|
|
|
7
11
|
- Add initial Claude Code support for local JSONL session transcripts, including projects, timestamps, models, token usage when available, and source status.
|
package/dist/cli.js
CHANGED
|
@@ -936,9 +936,11 @@ function parseBranch(head) {
|
|
|
936
936
|
}
|
|
937
937
|
|
|
938
938
|
// packages/core/src/sources/codex.ts
|
|
939
|
+
import { spawnSync } from "node:child_process";
|
|
939
940
|
import fs4 from "node:fs";
|
|
940
941
|
import os2 from "node:os";
|
|
941
942
|
import path4 from "node:path";
|
|
943
|
+
import { fileURLToPath } from "node:url";
|
|
942
944
|
import Database from "better-sqlite3";
|
|
943
945
|
|
|
944
946
|
// packages/core/src/sources/agent-friction.ts
|
|
@@ -1268,6 +1270,7 @@ function numberFromKeys(object, keys) {
|
|
|
1268
1270
|
}
|
|
1269
1271
|
|
|
1270
1272
|
// packages/core/src/sources/codex.ts
|
|
1273
|
+
var nativeSqliteRebuildAttempted = false;
|
|
1271
1274
|
function scanCodex(options) {
|
|
1272
1275
|
const codexHome = options.codexHome ?? path4.join(os2.homedir(), ".codex");
|
|
1273
1276
|
const statePath = path4.join(codexHome, "state_5.sqlite");
|
|
@@ -1322,7 +1325,7 @@ function scanCodex(options) {
|
|
|
1322
1325
|
function readThreads(statePath, sessionFiles, options, warnings) {
|
|
1323
1326
|
let db;
|
|
1324
1327
|
try {
|
|
1325
|
-
db =
|
|
1328
|
+
db = openCodexStateDatabase(statePath, warnings);
|
|
1326
1329
|
const tableNames = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
|
|
1327
1330
|
if (!tableNames.some((table) => table.name === "threads")) {
|
|
1328
1331
|
warnings.push("Codex SQLite state does not contain a threads table.");
|
|
@@ -1343,6 +1346,70 @@ function readThreads(statePath, sessionFiles, options, warnings) {
|
|
|
1343
1346
|
db?.close();
|
|
1344
1347
|
}
|
|
1345
1348
|
}
|
|
1349
|
+
function openCodexStateDatabase(statePath, warnings) {
|
|
1350
|
+
try {
|
|
1351
|
+
return new Database(statePath, { readonly: true, fileMustExist: true });
|
|
1352
|
+
} catch (error) {
|
|
1353
|
+
if (isNativeSqliteMismatch(error) && attemptNativeSqliteRebuild(warnings)) {
|
|
1354
|
+
return new Database(statePath, { readonly: true, fileMustExist: true });
|
|
1355
|
+
}
|
|
1356
|
+
throw error;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
function attemptNativeSqliteRebuild(warnings) {
|
|
1360
|
+
if (nativeSqliteRebuildAttempted || process.env.REPOSPEND_SKIP_NATIVE_REBUILD === "1") return false;
|
|
1361
|
+
nativeSqliteRebuildAttempted = true;
|
|
1362
|
+
const packageRoot = findRepoSpendPackageRoot();
|
|
1363
|
+
if (!packageRoot) {
|
|
1364
|
+
warnings.push("Codex SQLite native module mismatch detected, but RepoSpend could not locate its package root for an automatic rebuild.");
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
const packageManager = fs4.existsSync(path4.join(packageRoot, "pnpm-lock.yaml")) ? "pnpm" : "npm";
|
|
1368
|
+
const result = spawnSync(packageManager, ["rebuild", "better-sqlite3"], {
|
|
1369
|
+
cwd: packageRoot,
|
|
1370
|
+
encoding: "utf8",
|
|
1371
|
+
stdio: "pipe",
|
|
1372
|
+
timeout: 12e4
|
|
1373
|
+
});
|
|
1374
|
+
if (result.status === 0) return true;
|
|
1375
|
+
const detail = [result.stderr, result.stdout].filter(Boolean).join("\n").split("\n").map((line) => line.trim()).filter(Boolean).slice(-3).join(" ");
|
|
1376
|
+
warnings.push(`Codex SQLite native module mismatch detected. RepoSpend tried to rebuild better-sqlite3 automatically with ${packageManager}, but it failed${exitLabel(result.status)}.${detail ? ` ${detail}` : ""}`);
|
|
1377
|
+
return false;
|
|
1378
|
+
}
|
|
1379
|
+
function findRepoSpendPackageRoot() {
|
|
1380
|
+
const starts = [
|
|
1381
|
+
process.argv[1] ? path4.dirname(fs4.realpathSync(process.argv[1])) : void 0,
|
|
1382
|
+
path4.dirname(fileURLToPath(import.meta.url)),
|
|
1383
|
+
process.cwd()
|
|
1384
|
+
].filter((item) => Boolean(item));
|
|
1385
|
+
for (const start of starts) {
|
|
1386
|
+
const root = findPackageRootNamedRepoSpend(start);
|
|
1387
|
+
if (root) return root;
|
|
1388
|
+
}
|
|
1389
|
+
return void 0;
|
|
1390
|
+
}
|
|
1391
|
+
function findPackageRootNamedRepoSpend(start) {
|
|
1392
|
+
let current = path4.resolve(start);
|
|
1393
|
+
while (true) {
|
|
1394
|
+
const packagePath = path4.join(current, "package.json");
|
|
1395
|
+
if (fs4.existsSync(packagePath)) {
|
|
1396
|
+
try {
|
|
1397
|
+
const packageJson = JSON.parse(fs4.readFileSync(packagePath, "utf8"));
|
|
1398
|
+
if (packageJson.name === "repospend") return current;
|
|
1399
|
+
} catch {
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
const parent = path4.dirname(current);
|
|
1403
|
+
if (parent === current) return void 0;
|
|
1404
|
+
current = parent;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
function isNativeSqliteMismatch(error) {
|
|
1408
|
+
return errorMessage(error).includes("NODE_MODULE_VERSION");
|
|
1409
|
+
}
|
|
1410
|
+
function exitLabel(status) {
|
|
1411
|
+
return status === null ? "" : ` with exit code ${status}`;
|
|
1412
|
+
}
|
|
1346
1413
|
function threadToUsage(row, index, sessionFiles, options) {
|
|
1347
1414
|
const sourcePath = stringValue2(row.rollout_path) ?? matchSessionPath(stringValue2(row.id), sessionFiles) ?? "";
|
|
1348
1415
|
const sessionBreakdown = sourcePath ? readSessionBreakdown(sourcePath) : emptyBreakdown();
|
|
@@ -2311,7 +2378,7 @@ function runtimeCwd() {
|
|
|
2311
2378
|
// apps/server/src/server.ts
|
|
2312
2379
|
import fs7 from "node:fs";
|
|
2313
2380
|
import path6 from "node:path";
|
|
2314
|
-
import { fileURLToPath } from "node:url";
|
|
2381
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
2315
2382
|
import fastifyStatic from "@fastify/static";
|
|
2316
2383
|
import Fastify from "fastify";
|
|
2317
2384
|
|
|
@@ -3147,7 +3214,7 @@ function createServer(options = {}) {
|
|
|
3147
3214
|
return exportCsv();
|
|
3148
3215
|
});
|
|
3149
3216
|
if (options.serveWeb !== false) {
|
|
3150
|
-
const serverDist = path6.dirname(
|
|
3217
|
+
const serverDist = path6.dirname(fileURLToPath2(import.meta.url));
|
|
3151
3218
|
const packagedWebDist = path6.resolve(serverDist, "../web-dist");
|
|
3152
3219
|
const workspaceWebDist = path6.resolve(serverDist, "../../web/dist");
|
|
3153
3220
|
const webDist = fsExists(packagedWebDist) ? packagedWebDist : workspaceWebDist;
|
|
@@ -3173,7 +3240,7 @@ function fsExists(inputPath) {
|
|
|
3173
3240
|
return Boolean(inputPath) && path6.isAbsolute(inputPath) && fs7.existsSync(inputPath);
|
|
3174
3241
|
}
|
|
3175
3242
|
function readPackageVersion() {
|
|
3176
|
-
const serverDist = path6.dirname(
|
|
3243
|
+
const serverDist = path6.dirname(fileURLToPath2(import.meta.url));
|
|
3177
3244
|
const packagePath = path6.resolve(serverDist, "../package.json");
|
|
3178
3245
|
try {
|
|
3179
3246
|
const parsed = JSON.parse(fs7.readFileSync(packagePath, "utf8"));
|
package/package.json
CHANGED