@hasna/economy 0.2.26 → 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 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 labelForPath(projectPath, projectName) {
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(["web", "app", "apps", "packages", "src", "lib", "server", "client", "api", "frontend", "backend"]);
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 segments[segments.length - 1] ?? projectPath;
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 g = groups.get(label) ?? { sessionIds: [], samplePath: s.project_path };
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(label, g);
1157
+ groups.set(key, g);
1126
1158
  }
1127
1159
  const result = [];
1128
- for (const [label, g] of groups.entries()) {
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 WHERE source_request_id = ? AND agent = ? AND id != ?
1501
- `).run(row.source_request_id, row.agent, row.keep_id);
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;
@@ -4028,7 +4064,7 @@ __export(exports_config, {
4028
4064
  loadConfig: () => loadConfig2,
4029
4065
  getConfigValue: () => getConfigValue
4030
4066
  });
4031
- import { existsSync as existsSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
4067
+ import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
4032
4068
  import { dirname as dirname2, join as join12 } from "path";
4033
4069
  function getConfigPath() {
4034
4070
  return process.env["HASNA_ECONOMY_CONFIG_PATH"] ?? join12(getDataDir(), "config.json");
@@ -4036,7 +4072,7 @@ function getConfigPath() {
4036
4072
  function loadConfig2() {
4037
4073
  try {
4038
4074
  const configPath = getConfigPath();
4039
- if (existsSync12(configPath)) {
4075
+ if (existsSync13(configPath)) {
4040
4076
  const raw = readFileSync11(configPath, "utf-8");
4041
4077
  return { ...DEFAULTS, ...JSON.parse(raw) };
4042
4078
  }
@@ -4046,7 +4082,7 @@ function loadConfig2() {
4046
4082
  function saveConfig2(config) {
4047
4083
  const configPath = getConfigPath();
4048
4084
  const dir = dirname2(configPath);
4049
- if (!existsSync12(dir))
4085
+ if (!existsSync13(dir))
4050
4086
  mkdirSync3(dir, { recursive: true });
4051
4087
  writeFileSync2(configPath, JSON.stringify(config, null, 2) + `
4052
4088
  `);
@@ -4190,7 +4226,7 @@ var init_webhooks = __esm(() => {
4190
4226
  });
4191
4227
 
4192
4228
  // src/lib/watch-paths.ts
4193
- import { existsSync as existsSync13 } from "fs";
4229
+ import { existsSync as existsSync14 } from "fs";
4194
4230
  function getWatchPaths() {
4195
4231
  const p = agentPaths();
4196
4232
  const candidates = [
@@ -4203,7 +4239,7 @@ function getWatchPaths() {
4203
4239
  p.piSessions,
4204
4240
  p.hermesDir
4205
4241
  ];
4206
- return candidates.filter((path) => existsSync13(path));
4242
+ return candidates.filter((path) => existsSync14(path));
4207
4243
  }
4208
4244
  var init_watch_paths = __esm(() => {
4209
4245
  init_paths();
@@ -4373,7 +4409,7 @@ __export(exports_serve, {
4373
4409
  createHandler: () => createHandler
4374
4410
  });
4375
4411
  import { randomUUID as randomUUID2 } from "crypto";
4376
- import { existsSync as existsSync14 } from "fs";
4412
+ import { existsSync as existsSync15 } from "fs";
4377
4413
  import { resolve, sep } from "path";
4378
4414
  function json(data, status = 200) {
4379
4415
  return new Response(JSON.stringify(data), {
@@ -4438,13 +4474,13 @@ function createServerFetch(apiHandler, dashboardDir = DEFAULT_DASHBOARD_DIR) {
4438
4474
  if (url.pathname.startsWith("/api") || url.pathname === "/health") {
4439
4475
  return apiHandler(req);
4440
4476
  }
4441
- if (existsSync14(dashboardDir)) {
4477
+ if (existsSync15(dashboardDir)) {
4442
4478
  const filePath = dashboardPath(dashboardDir, url.pathname);
4443
- if (filePath && existsSync14(filePath)) {
4479
+ if (filePath && existsSync15(filePath)) {
4444
4480
  return new Response(Bun.file(filePath));
4445
4481
  }
4446
4482
  const indexPath = dashboardPath(dashboardDir, "/");
4447
- if (indexPath && existsSync14(indexPath)) {
4483
+ if (indexPath && existsSync15(indexPath)) {
4448
4484
  return new Response(Bun.file(indexPath));
4449
4485
  }
4450
4486
  }
@@ -4841,14 +4877,14 @@ __export(exports_menubar, {
4841
4877
  });
4842
4878
  import chalk6 from "chalk";
4843
4879
  import { execFileSync as execFileSync2 } from "child_process";
4844
- import { cpSync, existsSync as existsSync15, mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync3 } from "fs";
4880
+ import { cpSync, existsSync as existsSync16, mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync3 } from "fs";
4845
4881
  import { tmpdir, arch } from "os";
4846
4882
  import { join as join13 } from "path";
4847
4883
  function getArch() {
4848
4884
  return arch() === "arm64" ? "arm64" : "x86_64";
4849
4885
  }
4850
4886
  function isInstalled() {
4851
- return existsSync15(APP_PATH);
4887
+ return existsSync16(APP_PATH);
4852
4888
  }
4853
4889
  function isRunning() {
4854
4890
  try {
@@ -6182,6 +6218,7 @@ var TOP_LEVEL = [
6182
6218
  "init",
6183
6219
  "estimate",
6184
6220
  "fleet",
6221
+ "merge-db",
6185
6222
  "todos",
6186
6223
  "serve",
6187
6224
  "mcp",
@@ -6535,6 +6572,285 @@ function registerFleetCommands(program) {
6535
6572
  init_agents();
6536
6573
  init_sync_all();
6537
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
6538
6854
  init_database();
6539
6855
  init_database();
6540
6856
  init_billing();
@@ -7361,6 +7677,21 @@ program.command("machines").description("List all machines that have synced data
7361
7677
  ${chalk7.dim("Current machine:")} ${chalk7.bold(current)}`);
7362
7678
  console.log();
7363
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
+ });
7364
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) => {
7365
7696
  await autoSync();
7366
7697
  const db = openDatabase();
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"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"}
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;AA2CD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAc,GAAG,gBAAgB,EAAE,CAsE9F;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAE,MAAc,GAAG,gBAAgB,EAAE,CAgI9F;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,SAAK,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAQrH;AAID,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAKzE;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAI5E;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,cAAc,EAAE,CAG3D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE9D;AAID,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAU/D;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,EAAE,CAElD;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,YAAY,EAAE,CA2B9D;AAID,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAA;IACzC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI;IACtC,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,OAAO,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CASzD;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,EAAE,CAE9C;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,EAAE,CA6B1D;AAID,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGvF;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7F;AAID,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,EAAE,CAEhF;AAID,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAA;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CAKxE;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAExG;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAY5H;AAID,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,WAAW,EAAE,CAaxD;AAID,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,cAAc,GAAG,IAAI,CAexE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAElF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,cAAc,EAAE,CAE/D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAEpE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAkBvO;AAID,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,mBAAmB,EAAE,YAAY,GAAG,IAAI,CASpG;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,mBAAmB,EAAE,YAAY,EAAE,CAE1F;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjE;AAID,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,EAAE,aAAa,EAAE,IAAI,GAAG,YAAY,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChH,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3D,OAAO,mBAAmB,EAAE,aAAa,EAAE,CAQ7C;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,mBAAmB,EAAE,eAAe,EAAE,CAE/F;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAqBnD"}
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';
@@ -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"}