@hasna/economy 0.2.25 → 0.2.27
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/index.js +377 -25
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +382 -31
- package/dist/ingest/codex.d.ts.map +1 -1
- package/dist/lib/peer-sync.d.ts +21 -0
- package/dist/lib/peer-sync.d.ts.map +1 -0
- package/dist/mcp/index.js +71 -14
- package/dist/server/index.js +71 -14
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1087,9 +1087,7 @@ function queryAgentBreakdown(db, period = "all") {
|
|
|
1087
1087
|
}
|
|
1088
1088
|
return [...groups.values()].sort((a, b) => b.api_equivalent_usd - a.api_equivalent_usd);
|
|
1089
1089
|
}
|
|
1090
|
-
function
|
|
1091
|
-
if (projectName && projectName.trim() !== "")
|
|
1092
|
-
return projectName;
|
|
1090
|
+
function pathProjectLabel(projectPath) {
|
|
1093
1091
|
if (!projectPath)
|
|
1094
1092
|
return "";
|
|
1095
1093
|
const segments = projectPath.split("/").filter(Boolean);
|
|
@@ -1098,12 +1096,45 @@ function labelForPath(projectPath, projectName) {
|
|
|
1098
1096
|
if (projectPrefix.test(seg))
|
|
1099
1097
|
return seg;
|
|
1100
1098
|
}
|
|
1101
|
-
const generic = new Set([
|
|
1099
|
+
const generic = new Set([
|
|
1100
|
+
"web",
|
|
1101
|
+
"app",
|
|
1102
|
+
"apps",
|
|
1103
|
+
"packages",
|
|
1104
|
+
"src",
|
|
1105
|
+
"lib",
|
|
1106
|
+
"server",
|
|
1107
|
+
"client",
|
|
1108
|
+
"api",
|
|
1109
|
+
"frontend",
|
|
1110
|
+
"backend",
|
|
1111
|
+
"home",
|
|
1112
|
+
"users",
|
|
1113
|
+
"workspace",
|
|
1114
|
+
"workspaces",
|
|
1115
|
+
"hasna"
|
|
1116
|
+
]);
|
|
1102
1117
|
for (let i = segments.length - 1;i >= 0; i--) {
|
|
1103
1118
|
if (!generic.has(segments[i].toLowerCase()))
|
|
1104
1119
|
return segments[i];
|
|
1105
1120
|
}
|
|
1106
|
-
return
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
function isRepoLikeLabel(label) {
|
|
1124
|
+
return /^(open|skill|hook|service|connect|platform|agent|tool|iapp|project|scaffold|capp)-/.test(label) || label.includes("-");
|
|
1125
|
+
}
|
|
1126
|
+
function labelForPath(projectPath, projectName) {
|
|
1127
|
+
const pathLabel = pathProjectLabel(projectPath);
|
|
1128
|
+
if (pathLabel && (!projectName || projectName.trim() === "" || isRepoLikeLabel(pathLabel)))
|
|
1129
|
+
return pathLabel;
|
|
1130
|
+
if (projectName && projectName.trim() !== "")
|
|
1131
|
+
return projectName;
|
|
1132
|
+
if (pathLabel)
|
|
1133
|
+
return pathLabel;
|
|
1134
|
+
return projectPath;
|
|
1135
|
+
}
|
|
1136
|
+
function groupKeyForPath(projectPath, projectName) {
|
|
1137
|
+
return labelForPath(projectPath, projectName).trim().toLowerCase();
|
|
1107
1138
|
}
|
|
1108
1139
|
function queryProjectBreakdown(db, period = "all") {
|
|
1109
1140
|
const requestWhere = requestPeriodWhere(period);
|
|
@@ -1118,14 +1149,15 @@ function queryProjectBreakdown(db, period = "all") {
|
|
|
1118
1149
|
const label = labelForPath(s.project_path, s.project_name);
|
|
1119
1150
|
if (!label)
|
|
1120
1151
|
continue;
|
|
1121
|
-
const
|
|
1152
|
+
const key = groupKeyForPath(s.project_path, s.project_name);
|
|
1153
|
+
const g = groups.get(key) ?? { label, sessionIds: [], samplePath: s.project_path };
|
|
1122
1154
|
g.sessionIds.push(s.id);
|
|
1123
1155
|
if (!g.samplePath)
|
|
1124
1156
|
g.samplePath = s.project_path;
|
|
1125
|
-
groups.set(
|
|
1157
|
+
groups.set(key, g);
|
|
1126
1158
|
}
|
|
1127
1159
|
const result = [];
|
|
1128
|
-
for (const
|
|
1160
|
+
for (const g of groups.values()) {
|
|
1129
1161
|
const placeholders = g.sessionIds.map(() => "?").join(",");
|
|
1130
1162
|
const reqStats = placeholders.length ? db.prepare(`
|
|
1131
1163
|
SELECT
|
|
@@ -1156,7 +1188,7 @@ function queryProjectBreakdown(db, period = "all") {
|
|
|
1156
1188
|
const lastActive = [reqStats.last_active, sessionOnlyStats.last_active].filter(Boolean).sort().at(-1) ?? "";
|
|
1157
1189
|
result.push({
|
|
1158
1190
|
project_path: g.samplePath,
|
|
1159
|
-
project_name: label,
|
|
1191
|
+
project_name: g.label,
|
|
1160
1192
|
sessions: totalSessions,
|
|
1161
1193
|
requests: reqStats.requests + sessionOnlyStats.requests,
|
|
1162
1194
|
total_tokens: reqStats.total_tokens + sessionOnlyStats.total_tokens,
|
|
@@ -1488,17 +1520,21 @@ function listMachineRegistry(db) {
|
|
|
1488
1520
|
}
|
|
1489
1521
|
function dedupeRequests(db) {
|
|
1490
1522
|
const dupes = db.prepare(`
|
|
1491
|
-
SELECT source_request_id, agent, MIN(id) as keep_id, COUNT(*) as cnt
|
|
1523
|
+
SELECT source_request_id, agent, COALESCE(machine_id, '') as machine_id, MIN(id) as keep_id, COUNT(*) as cnt
|
|
1492
1524
|
FROM requests
|
|
1493
1525
|
WHERE source_request_id != '' AND source_request_id IS NOT NULL
|
|
1494
|
-
GROUP BY source_request_id, agent
|
|
1526
|
+
GROUP BY source_request_id, agent, COALESCE(machine_id, '')
|
|
1495
1527
|
HAVING cnt > 1
|
|
1496
1528
|
`).all();
|
|
1497
1529
|
let removed = 0;
|
|
1498
1530
|
for (const row of dupes) {
|
|
1499
1531
|
const result = db.prepare(`
|
|
1500
|
-
DELETE FROM requests
|
|
1501
|
-
|
|
1532
|
+
DELETE FROM requests
|
|
1533
|
+
WHERE source_request_id = ?
|
|
1534
|
+
AND agent = ?
|
|
1535
|
+
AND COALESCE(machine_id, '') = ?
|
|
1536
|
+
AND id != ?
|
|
1537
|
+
`).run(row.source_request_id, row.agent, row.machine_id, row.keep_id);
|
|
1502
1538
|
removed += result.changes;
|
|
1503
1539
|
}
|
|
1504
1540
|
return removed;
|
|
@@ -2642,6 +2678,25 @@ function buildThreadQuery(codexDb) {
|
|
|
2642
2678
|
FROM threads WHERE tokens_used > 0
|
|
2643
2679
|
`;
|
|
2644
2680
|
}
|
|
2681
|
+
function openCodexDb(dbPath, verbose) {
|
|
2682
|
+
let lastError;
|
|
2683
|
+
for (const readonly of [true, false]) {
|
|
2684
|
+
let codexDb = null;
|
|
2685
|
+
try {
|
|
2686
|
+
codexDb = readonly ? new BunDatabase(dbPath, { readonly: true }) : new BunDatabase(dbPath);
|
|
2687
|
+
codexDb.prepare("PRAGMA schema_version").get();
|
|
2688
|
+
return codexDb;
|
|
2689
|
+
} catch (error) {
|
|
2690
|
+
lastError = error;
|
|
2691
|
+
codexDb?.close();
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
if (verbose) {
|
|
2695
|
+
const message = lastError instanceof Error ? lastError.message : String(lastError);
|
|
2696
|
+
console.log("Codex DB unreadable:", dbPath, message);
|
|
2697
|
+
}
|
|
2698
|
+
return null;
|
|
2699
|
+
}
|
|
2645
2700
|
function readTokenEvents(rolloutPath) {
|
|
2646
2701
|
if (!rolloutPath || !existsSync5(rolloutPath))
|
|
2647
2702
|
return [];
|
|
@@ -2731,7 +2786,9 @@ async function ingestCodex(db, verbose = false) {
|
|
|
2731
2786
|
let requests = 0;
|
|
2732
2787
|
const account = await resolveAccountForAgent("codex");
|
|
2733
2788
|
try {
|
|
2734
|
-
codexDb =
|
|
2789
|
+
codexDb = openCodexDb(dbPath, verbose);
|
|
2790
|
+
if (!codexDb)
|
|
2791
|
+
return { sessions: 0, requests: 0 };
|
|
2735
2792
|
const threads = codexDb.prepare(buildThreadQuery(codexDb)).all();
|
|
2736
2793
|
for (const thread of threads) {
|
|
2737
2794
|
const model = thread.model ?? readCodexModel();
|
|
@@ -4007,7 +4064,7 @@ __export(exports_config, {
|
|
|
4007
4064
|
loadConfig: () => loadConfig2,
|
|
4008
4065
|
getConfigValue: () => getConfigValue
|
|
4009
4066
|
});
|
|
4010
|
-
import { existsSync as
|
|
4067
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
4011
4068
|
import { dirname as dirname2, join as join12 } from "path";
|
|
4012
4069
|
function getConfigPath() {
|
|
4013
4070
|
return process.env["HASNA_ECONOMY_CONFIG_PATH"] ?? join12(getDataDir(), "config.json");
|
|
@@ -4015,7 +4072,7 @@ function getConfigPath() {
|
|
|
4015
4072
|
function loadConfig2() {
|
|
4016
4073
|
try {
|
|
4017
4074
|
const configPath = getConfigPath();
|
|
4018
|
-
if (
|
|
4075
|
+
if (existsSync13(configPath)) {
|
|
4019
4076
|
const raw = readFileSync11(configPath, "utf-8");
|
|
4020
4077
|
return { ...DEFAULTS, ...JSON.parse(raw) };
|
|
4021
4078
|
}
|
|
@@ -4025,7 +4082,7 @@ function loadConfig2() {
|
|
|
4025
4082
|
function saveConfig2(config) {
|
|
4026
4083
|
const configPath = getConfigPath();
|
|
4027
4084
|
const dir = dirname2(configPath);
|
|
4028
|
-
if (!
|
|
4085
|
+
if (!existsSync13(dir))
|
|
4029
4086
|
mkdirSync3(dir, { recursive: true });
|
|
4030
4087
|
writeFileSync2(configPath, JSON.stringify(config, null, 2) + `
|
|
4031
4088
|
`);
|
|
@@ -4169,7 +4226,7 @@ var init_webhooks = __esm(() => {
|
|
|
4169
4226
|
});
|
|
4170
4227
|
|
|
4171
4228
|
// src/lib/watch-paths.ts
|
|
4172
|
-
import { existsSync as
|
|
4229
|
+
import { existsSync as existsSync14 } from "fs";
|
|
4173
4230
|
function getWatchPaths() {
|
|
4174
4231
|
const p = agentPaths();
|
|
4175
4232
|
const candidates = [
|
|
@@ -4182,7 +4239,7 @@ function getWatchPaths() {
|
|
|
4182
4239
|
p.piSessions,
|
|
4183
4240
|
p.hermesDir
|
|
4184
4241
|
];
|
|
4185
|
-
return candidates.filter((path) =>
|
|
4242
|
+
return candidates.filter((path) => existsSync14(path));
|
|
4186
4243
|
}
|
|
4187
4244
|
var init_watch_paths = __esm(() => {
|
|
4188
4245
|
init_paths();
|
|
@@ -4352,7 +4409,7 @@ __export(exports_serve, {
|
|
|
4352
4409
|
createHandler: () => createHandler
|
|
4353
4410
|
});
|
|
4354
4411
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4355
|
-
import { existsSync as
|
|
4412
|
+
import { existsSync as existsSync15 } from "fs";
|
|
4356
4413
|
import { resolve, sep } from "path";
|
|
4357
4414
|
function json(data, status = 200) {
|
|
4358
4415
|
return new Response(JSON.stringify(data), {
|
|
@@ -4417,13 +4474,13 @@ function createServerFetch(apiHandler, dashboardDir = DEFAULT_DASHBOARD_DIR) {
|
|
|
4417
4474
|
if (url.pathname.startsWith("/api") || url.pathname === "/health") {
|
|
4418
4475
|
return apiHandler(req);
|
|
4419
4476
|
}
|
|
4420
|
-
if (
|
|
4477
|
+
if (existsSync15(dashboardDir)) {
|
|
4421
4478
|
const filePath = dashboardPath(dashboardDir, url.pathname);
|
|
4422
|
-
if (filePath &&
|
|
4479
|
+
if (filePath && existsSync15(filePath)) {
|
|
4423
4480
|
return new Response(Bun.file(filePath));
|
|
4424
4481
|
}
|
|
4425
4482
|
const indexPath = dashboardPath(dashboardDir, "/");
|
|
4426
|
-
if (indexPath &&
|
|
4483
|
+
if (indexPath && existsSync15(indexPath)) {
|
|
4427
4484
|
return new Response(Bun.file(indexPath));
|
|
4428
4485
|
}
|
|
4429
4486
|
}
|
|
@@ -4820,14 +4877,14 @@ __export(exports_menubar, {
|
|
|
4820
4877
|
});
|
|
4821
4878
|
import chalk6 from "chalk";
|
|
4822
4879
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
4823
|
-
import { cpSync, existsSync as
|
|
4880
|
+
import { cpSync, existsSync as existsSync16, mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
4824
4881
|
import { tmpdir, arch } from "os";
|
|
4825
4882
|
import { join as join13 } from "path";
|
|
4826
4883
|
function getArch() {
|
|
4827
4884
|
return arch() === "arm64" ? "arm64" : "x86_64";
|
|
4828
4885
|
}
|
|
4829
4886
|
function isInstalled() {
|
|
4830
|
-
return
|
|
4887
|
+
return existsSync16(APP_PATH);
|
|
4831
4888
|
}
|
|
4832
4889
|
function isRunning() {
|
|
4833
4890
|
try {
|
|
@@ -6161,6 +6218,7 @@ var TOP_LEVEL = [
|
|
|
6161
6218
|
"init",
|
|
6162
6219
|
"estimate",
|
|
6163
6220
|
"fleet",
|
|
6221
|
+
"merge-db",
|
|
6164
6222
|
"todos",
|
|
6165
6223
|
"serve",
|
|
6166
6224
|
"mcp",
|
|
@@ -6514,6 +6572,285 @@ function registerFleetCommands(program) {
|
|
|
6514
6572
|
init_agents();
|
|
6515
6573
|
init_sync_all();
|
|
6516
6574
|
init_cloud_sync();
|
|
6575
|
+
|
|
6576
|
+
// src/lib/peer-sync.ts
|
|
6577
|
+
init_database();
|
|
6578
|
+
init_package_metadata();
|
|
6579
|
+
import { Database as BunDatabase2 } from "bun:sqlite";
|
|
6580
|
+
import { existsSync as existsSync12 } from "fs";
|
|
6581
|
+
var GENERIC_PEER_TABLES = [
|
|
6582
|
+
"usage_snapshots",
|
|
6583
|
+
"subscriptions",
|
|
6584
|
+
"billing_daily",
|
|
6585
|
+
"savings_daily",
|
|
6586
|
+
"budgets",
|
|
6587
|
+
"goals",
|
|
6588
|
+
"model_pricing",
|
|
6589
|
+
"machines"
|
|
6590
|
+
];
|
|
6591
|
+
function quoteIdent(identifier) {
|
|
6592
|
+
return `"${identifier.replace(/"/g, '""')}"`;
|
|
6593
|
+
}
|
|
6594
|
+
function tableExists(db, table) {
|
|
6595
|
+
const row = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`).get(table);
|
|
6596
|
+
return Boolean(row);
|
|
6597
|
+
}
|
|
6598
|
+
function tableColumns(db, table) {
|
|
6599
|
+
if (!tableExists(db, table))
|
|
6600
|
+
return [];
|
|
6601
|
+
return db.prepare(`PRAGMA table_info(${quoteIdent(table)})`).all();
|
|
6602
|
+
}
|
|
6603
|
+
function commonColumns(source, target, table) {
|
|
6604
|
+
const sourceCols = new Set(tableColumns(source, table).map((c) => c.name));
|
|
6605
|
+
return tableColumns(target, table).map((c) => c.name).filter((c) => sourceCols.has(c));
|
|
6606
|
+
}
|
|
6607
|
+
function primaryKeyColumns(db, table) {
|
|
6608
|
+
return tableColumns(db, table).filter((c) => c.pk > 0).sort((a, b) => a.pk - b.pk).map((c) => c.name);
|
|
6609
|
+
}
|
|
6610
|
+
function selectRows(source, table, columns) {
|
|
6611
|
+
if (columns.length === 0)
|
|
6612
|
+
return [];
|
|
6613
|
+
const select = columns.map(quoteIdent).join(", ");
|
|
6614
|
+
return source.prepare(`SELECT ${select} FROM ${quoteIdent(table)}`).all();
|
|
6615
|
+
}
|
|
6616
|
+
function rowByKey(target, table, keyColumns, row) {
|
|
6617
|
+
if (keyColumns.length === 0)
|
|
6618
|
+
return null;
|
|
6619
|
+
if (keyColumns.some((c) => row[c] == null))
|
|
6620
|
+
return null;
|
|
6621
|
+
const where = keyColumns.map((c) => `${quoteIdent(c)} = ?`).join(" AND ");
|
|
6622
|
+
return target.prepare(`SELECT * FROM ${quoteIdent(table)} WHERE ${where}`).get(...keyColumns.map((c) => row[c]));
|
|
6623
|
+
}
|
|
6624
|
+
function hasId(target, table, id) {
|
|
6625
|
+
return target.prepare(`SELECT id, machine_id FROM ${quoteIdent(table)} WHERE id = ?`).get(id);
|
|
6626
|
+
}
|
|
6627
|
+
function shouldReplace(source, existing) {
|
|
6628
|
+
if (!existing)
|
|
6629
|
+
return true;
|
|
6630
|
+
const sourceUpdated = source["updated_at"];
|
|
6631
|
+
const existingUpdated = existing["updated_at"];
|
|
6632
|
+
if (typeof sourceUpdated === "string" && typeof existingUpdated === "string" && existingUpdated !== "") {
|
|
6633
|
+
return sourceUpdated >= existingUpdated;
|
|
6634
|
+
}
|
|
6635
|
+
return true;
|
|
6636
|
+
}
|
|
6637
|
+
function normalizeRow(row, columns, sourceMachine, now) {
|
|
6638
|
+
const next = { ...row };
|
|
6639
|
+
if (columns.includes("machine_id") && (!next["machine_id"] || next["machine_id"] === "")) {
|
|
6640
|
+
next["machine_id"] = sourceMachine;
|
|
6641
|
+
}
|
|
6642
|
+
if (columns.includes("updated_at") && (!next["updated_at"] || next["updated_at"] === "")) {
|
|
6643
|
+
next["updated_at"] = next["timestamp"] ?? next["started_at"] ?? next["created_at"] ?? now;
|
|
6644
|
+
}
|
|
6645
|
+
if (columns.includes("synced_at") && next["synced_at"] == null)
|
|
6646
|
+
next["synced_at"] = "";
|
|
6647
|
+
if (columns.includes("attribution_tag") && next["attribution_tag"] == null)
|
|
6648
|
+
next["attribution_tag"] = "";
|
|
6649
|
+
return next;
|
|
6650
|
+
}
|
|
6651
|
+
function insertOrReplace(target, table, columns, row) {
|
|
6652
|
+
const colSql = columns.map(quoteIdent).join(", ");
|
|
6653
|
+
const placeholders = columns.map(() => "?").join(", ");
|
|
6654
|
+
target.prepare(`
|
|
6655
|
+
INSERT OR REPLACE INTO ${quoteIdent(table)} (${colSql})
|
|
6656
|
+
VALUES (${placeholders})
|
|
6657
|
+
`).run(...columns.map((c) => row[c] ?? null));
|
|
6658
|
+
}
|
|
6659
|
+
function collisionId(target, table, machine, originalId) {
|
|
6660
|
+
const base = `${machine || "peer"}:${originalId}`;
|
|
6661
|
+
const baseRow = hasId(target, table, base);
|
|
6662
|
+
if (!baseRow || String(baseRow["machine_id"] ?? "") === machine)
|
|
6663
|
+
return base;
|
|
6664
|
+
for (let i = 2;; i++) {
|
|
6665
|
+
const candidate = `${base}:${i}`;
|
|
6666
|
+
const row = hasId(target, table, candidate);
|
|
6667
|
+
if (!row || String(row["machine_id"] ?? "") === machine)
|
|
6668
|
+
return candidate;
|
|
6669
|
+
}
|
|
6670
|
+
}
|
|
6671
|
+
function mergeIdentityTable(target, source, table, sourceMachine, now, sessionIdMap) {
|
|
6672
|
+
const stats = { table, inserted: 0, updated: 0, skipped: 0, collisions: 0 };
|
|
6673
|
+
const columns = commonColumns(source, target, table);
|
|
6674
|
+
const rows = selectRows(source, table, columns);
|
|
6675
|
+
const idMap = new Map;
|
|
6676
|
+
for (const raw of rows) {
|
|
6677
|
+
const row = normalizeRow(raw, columns, sourceMachine, now);
|
|
6678
|
+
const originalId = String(row["id"] ?? "");
|
|
6679
|
+
if (!originalId) {
|
|
6680
|
+
stats.skipped++;
|
|
6681
|
+
continue;
|
|
6682
|
+
}
|
|
6683
|
+
const machine = String(row["machine_id"] ?? "");
|
|
6684
|
+
const directExisting = hasId(target, table, originalId);
|
|
6685
|
+
if (directExisting && String(directExisting["machine_id"] ?? "") !== machine) {
|
|
6686
|
+
row["id"] = collisionId(target, table, machine, originalId);
|
|
6687
|
+
stats.collisions++;
|
|
6688
|
+
}
|
|
6689
|
+
if (table === "requests" && sessionIdMap) {
|
|
6690
|
+
const originalSessionId = String(row["session_id"] ?? "");
|
|
6691
|
+
row["session_id"] = sessionIdMap.get(originalSessionId) ?? originalSessionId;
|
|
6692
|
+
}
|
|
6693
|
+
const existing = hasId(target, table, String(row["id"]));
|
|
6694
|
+
idMap.set(originalId, String(row["id"]));
|
|
6695
|
+
if (existing && !shouldReplace(row, existing)) {
|
|
6696
|
+
stats.skipped++;
|
|
6697
|
+
continue;
|
|
6698
|
+
}
|
|
6699
|
+
insertOrReplace(target, table, columns, row);
|
|
6700
|
+
if (existing)
|
|
6701
|
+
stats.updated++;
|
|
6702
|
+
else
|
|
6703
|
+
stats.inserted++;
|
|
6704
|
+
}
|
|
6705
|
+
return { stats, idMap };
|
|
6706
|
+
}
|
|
6707
|
+
function mergeProjects(target, source) {
|
|
6708
|
+
const table = "projects";
|
|
6709
|
+
const stats = { table, inserted: 0, updated: 0, skipped: 0, collisions: 0 };
|
|
6710
|
+
const columns = commonColumns(source, target, table);
|
|
6711
|
+
const rows = selectRows(source, table, columns);
|
|
6712
|
+
for (const raw of rows) {
|
|
6713
|
+
const row = { ...raw };
|
|
6714
|
+
const path = String(row["path"] ?? "");
|
|
6715
|
+
const id = String(row["id"] ?? "");
|
|
6716
|
+
if (!path || !id) {
|
|
6717
|
+
stats.skipped++;
|
|
6718
|
+
continue;
|
|
6719
|
+
}
|
|
6720
|
+
const existingByPath = target.prepare(`SELECT * FROM projects WHERE path = ?`).get(path);
|
|
6721
|
+
if (existingByPath) {
|
|
6722
|
+
row["id"] = existingByPath["id"] ?? id;
|
|
6723
|
+
insertOrReplace(target, table, columns, row);
|
|
6724
|
+
stats.updated++;
|
|
6725
|
+
continue;
|
|
6726
|
+
}
|
|
6727
|
+
const existingById = target.prepare(`SELECT * FROM projects WHERE id = ?`).get(id);
|
|
6728
|
+
if (existingById && String(existingById["path"] ?? "") !== path) {
|
|
6729
|
+
row["id"] = `peer:${id}`;
|
|
6730
|
+
stats.collisions++;
|
|
6731
|
+
while (target.prepare(`SELECT id FROM projects WHERE id = ?`).get(row["id"])) {
|
|
6732
|
+
row["id"] = `peer:${String(row["id"])}`;
|
|
6733
|
+
}
|
|
6734
|
+
}
|
|
6735
|
+
insertOrReplace(target, table, columns, row);
|
|
6736
|
+
stats.inserted++;
|
|
6737
|
+
}
|
|
6738
|
+
return stats;
|
|
6739
|
+
}
|
|
6740
|
+
function mergeGenericTable(target, source, table, sourceMachine, now) {
|
|
6741
|
+
const stats = { table, inserted: 0, updated: 0, skipped: 0, collisions: 0 };
|
|
6742
|
+
const columns = commonColumns(source, target, table);
|
|
6743
|
+
const keyColumns = primaryKeyColumns(target, table).filter((c) => columns.includes(c));
|
|
6744
|
+
const rows = selectRows(source, table, columns);
|
|
6745
|
+
for (const raw of rows) {
|
|
6746
|
+
const row = normalizeRow(raw, columns, sourceMachine, now);
|
|
6747
|
+
const existing = rowByKey(target, table, keyColumns, row);
|
|
6748
|
+
if (existing && !shouldReplace(row, existing)) {
|
|
6749
|
+
stats.skipped++;
|
|
6750
|
+
continue;
|
|
6751
|
+
}
|
|
6752
|
+
insertOrReplace(target, table, columns, row);
|
|
6753
|
+
if (existing)
|
|
6754
|
+
stats.updated++;
|
|
6755
|
+
else
|
|
6756
|
+
stats.inserted++;
|
|
6757
|
+
}
|
|
6758
|
+
return stats;
|
|
6759
|
+
}
|
|
6760
|
+
function detectSourceMachine(source, fallback) {
|
|
6761
|
+
if (fallback && fallback.trim())
|
|
6762
|
+
return fallback.trim();
|
|
6763
|
+
const counts = new Map;
|
|
6764
|
+
for (const table of ["sessions", "requests", "usage_snapshots"]) {
|
|
6765
|
+
if (!tableExists(source, table))
|
|
6766
|
+
continue;
|
|
6767
|
+
const rows = source.prepare(`
|
|
6768
|
+
SELECT machine_id, COUNT(*) as cnt
|
|
6769
|
+
FROM ${quoteIdent(table)}
|
|
6770
|
+
WHERE machine_id != '' AND machine_id IS NOT NULL
|
|
6771
|
+
GROUP BY machine_id
|
|
6772
|
+
`).all();
|
|
6773
|
+
for (const row of rows) {
|
|
6774
|
+
counts.set(row.machine_id, (counts.get(row.machine_id) ?? 0) + row.cnt);
|
|
6775
|
+
}
|
|
6776
|
+
}
|
|
6777
|
+
let best = "";
|
|
6778
|
+
let bestCount = -1;
|
|
6779
|
+
for (const [machine, count] of counts.entries()) {
|
|
6780
|
+
if (count > bestCount) {
|
|
6781
|
+
best = machine;
|
|
6782
|
+
bestCount = count;
|
|
6783
|
+
}
|
|
6784
|
+
}
|
|
6785
|
+
return best || "peer";
|
|
6786
|
+
}
|
|
6787
|
+
function ensureMachineRegistry(target, machine, now) {
|
|
6788
|
+
if (!machine)
|
|
6789
|
+
return;
|
|
6790
|
+
target.prepare(`
|
|
6791
|
+
INSERT INTO machines (machine_id, hostname, last_seen_at, last_push_at, last_pull_at, economy_version, updated_at)
|
|
6792
|
+
VALUES (?, ?, ?, NULL, ?, ?, ?)
|
|
6793
|
+
ON CONFLICT(machine_id) DO UPDATE SET
|
|
6794
|
+
hostname = COALESCE(NULLIF(machines.hostname, ''), excluded.hostname),
|
|
6795
|
+
last_seen_at = CASE
|
|
6796
|
+
WHEN machines.last_seen_at IS NULL OR machines.last_seen_at < excluded.last_seen_at THEN excluded.last_seen_at
|
|
6797
|
+
ELSE machines.last_seen_at
|
|
6798
|
+
END,
|
|
6799
|
+
last_pull_at = excluded.last_pull_at,
|
|
6800
|
+
economy_version = excluded.economy_version,
|
|
6801
|
+
updated_at = excluded.updated_at
|
|
6802
|
+
`).run(machine, machine, now, now, packageMetadata.version, now);
|
|
6803
|
+
}
|
|
6804
|
+
function openSourceDatabase(path) {
|
|
6805
|
+
try {
|
|
6806
|
+
return new BunDatabase2(path, { readonly: true });
|
|
6807
|
+
} catch {
|
|
6808
|
+
return new BunDatabase2(path);
|
|
6809
|
+
}
|
|
6810
|
+
}
|
|
6811
|
+
function mergePeerDatabase(target, sourcePath, opts = {}) {
|
|
6812
|
+
if (!existsSync12(sourcePath))
|
|
6813
|
+
throw new Error(`source database does not exist: ${sourcePath}`);
|
|
6814
|
+
const source = openSourceDatabase(sourcePath);
|
|
6815
|
+
const now = opts.now ?? new Date().toISOString();
|
|
6816
|
+
const sourceMachine = detectSourceMachine(source, opts.sourceMachine);
|
|
6817
|
+
const tables = [];
|
|
6818
|
+
try {
|
|
6819
|
+
target.exec("PRAGMA foreign_keys = OFF");
|
|
6820
|
+
target.exec("BEGIN IMMEDIATE");
|
|
6821
|
+
try {
|
|
6822
|
+
tables.push(mergeProjects(target, source));
|
|
6823
|
+
const sessionMerge = mergeIdentityTable(target, source, "sessions", sourceMachine, now);
|
|
6824
|
+
tables.push(sessionMerge.stats);
|
|
6825
|
+
tables.push(mergeIdentityTable(target, source, "requests", sourceMachine, now, sessionMerge.idMap).stats);
|
|
6826
|
+
for (const table of GENERIC_PEER_TABLES) {
|
|
6827
|
+
tables.push(mergeGenericTable(target, source, table, sourceMachine, now));
|
|
6828
|
+
}
|
|
6829
|
+
ensureMachineRegistry(target, sourceMachine, now);
|
|
6830
|
+
target.exec("COMMIT");
|
|
6831
|
+
} catch (err) {
|
|
6832
|
+
target.exec("ROLLBACK");
|
|
6833
|
+
throw err;
|
|
6834
|
+
} finally {
|
|
6835
|
+
target.exec("PRAGMA foreign_keys = ON");
|
|
6836
|
+
}
|
|
6837
|
+
} finally {
|
|
6838
|
+
source.close();
|
|
6839
|
+
}
|
|
6840
|
+
const deduped = dedupeRequests(target);
|
|
6841
|
+
const rowsWritten = tables.reduce((sum, table) => sum + table.inserted + table.updated, 0);
|
|
6842
|
+
const collisions = tables.reduce((sum, table) => sum + table.collisions, 0);
|
|
6843
|
+
return {
|
|
6844
|
+
source_path: sourcePath,
|
|
6845
|
+
source_machine: sourceMachine,
|
|
6846
|
+
rows_written: rowsWritten,
|
|
6847
|
+
collisions,
|
|
6848
|
+
deduped,
|
|
6849
|
+
tables: tables.filter((t) => t.inserted || t.updated || t.skipped || t.collisions)
|
|
6850
|
+
};
|
|
6851
|
+
}
|
|
6852
|
+
|
|
6853
|
+
// src/cli/index.ts
|
|
6517
6854
|
init_database();
|
|
6518
6855
|
init_database();
|
|
6519
6856
|
init_billing();
|
|
@@ -7340,6 +7677,21 @@ program.command("machines").description("List all machines that have synced data
|
|
|
7340
7677
|
${chalk7.dim("Current machine:")} ${chalk7.bold(current)}`);
|
|
7341
7678
|
console.log();
|
|
7342
7679
|
});
|
|
7680
|
+
program.command("merge-db <source-db>").description("Merge another Economy SQLite database into this machine").option("--source-machine <id>", "Machine id to use for source rows that do not have one").option("--json", "Output JSON").action((sourceDb, opts) => {
|
|
7681
|
+
const db = openDatabase();
|
|
7682
|
+
const result = mergePeerDatabase(db, sourceDb, { sourceMachine: opts.sourceMachine });
|
|
7683
|
+
if (opts.json) {
|
|
7684
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7685
|
+
return;
|
|
7686
|
+
}
|
|
7687
|
+
console.log();
|
|
7688
|
+
console.log(chalk7.bold.cyan(` Merged Economy DB \u2014 ${result.source_machine}`));
|
|
7689
|
+
console.log(` Rows written: ${fmtCount(result.rows_written)} \xB7 collisions remapped: ${fmtCount(result.collisions)} \xB7 deduped: ${fmtCount(result.deduped)}`);
|
|
7690
|
+
for (const table of result.tables) {
|
|
7691
|
+
console.log(` ${chalk7.white(table.table.padEnd(16))}` + ` inserted ${fmtCount(table.inserted).padStart(6)}` + ` updated ${fmtCount(table.updated).padStart(6)}` + ` skipped ${fmtCount(table.skipped).padStart(6)}` + ` collisions ${fmtCount(table.collisions).padStart(3)}`);
|
|
7692
|
+
}
|
|
7693
|
+
console.log();
|
|
7694
|
+
});
|
|
7343
7695
|
program.command("export").description("Export data as CSV").option("--type <type>", "Data type: sessions or requests", "sessions").option("--period <period>", "Period: today|week|month|all", "month").option("--output <file>", "Output file path (default: stdout)").action(async (opts) => {
|
|
7344
7696
|
await autoSync();
|
|
7345
7697
|
const db = openDatabase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,cAAc,CAAA;AAKxD,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,MAAM,EACN,YAAY,EACZ,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,MAAM,EACN,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAkBnC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,QAAQ,CAgBxE;AAkRD,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAuBrE;AAID,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAkBzE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA2BnE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAE,aAAkB,GAAG,cAAc,EAAE,CAuBxF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAK,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAKvF;AAID,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,WAAW,CA8B7G;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,cAAc,EAAE,CAUlE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAc,GAAG,cAAc,EAAE,CA0E1F;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './lib/pricing.js';
|
|
|
4
4
|
export * from './lib/gatherer.js';
|
|
5
5
|
export * from './lib/model-config.js';
|
|
6
6
|
export * from './lib/open-projects.js';
|
|
7
|
+
export * from './lib/peer-sync.js';
|
|
7
8
|
export * from './ingest/claude.js';
|
|
8
9
|
export * from './ingest/codex.js';
|
|
9
10
|
export * from './ingest/gemini.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
|