modelstat 0.0.43 → 0.0.45

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.mjs CHANGED
@@ -4550,6 +4550,8 @@ function sourceEventId(deviceId, sourceOrFilePath, byteOffsetMaybe) {
4550
4550
  key = `fs::${sourceOrFilePath}::${byteOffset}`;
4551
4551
  } else if ("file" in sourceOrFilePath) {
4552
4552
  key = `fs::${sourceOrFilePath.file}::${sourceOrFilePath.byteOffset}`;
4553
+ } else if ("lineUuid" in sourceOrFilePath) {
4554
+ key = `uuid::${sourceOrFilePath.lineUuid}`;
4553
4555
  } else {
4554
4556
  key = `web::${sourceOrFilePath.host}::${sourceOrFilePath.conversationId}::${sourceOrFilePath.messageId}`;
4555
4557
  }
@@ -4682,9 +4684,20 @@ var init_src = __esm({
4682
4684
 
4683
4685
  // ../../packages/parsers/src/claude-code/index.ts
4684
4686
  import { createHash } from "crypto";
4685
- import { createReadStream } from "fs";
4687
+ import { createReadStream, existsSync as existsSync2, readdirSync } from "fs";
4686
4688
  import { stat } from "fs/promises";
4689
+ import { dirname as dirname2, join } from "path";
4687
4690
  import { createInterface } from "readline";
4691
+ function countToolCalls(content) {
4692
+ const counts = {};
4693
+ if (!Array.isArray(content)) return counts;
4694
+ for (const block of content) {
4695
+ if (block && block.type === "tool_use" && typeof block.name === "string" && block.name) {
4696
+ counts[block.name] = (counts[block.name] ?? 0) + 1;
4697
+ }
4698
+ }
4699
+ return counts;
4700
+ }
4688
4701
  function extractExcerpt(content) {
4689
4702
  if (!content) return void 0;
4690
4703
  let text = "";
@@ -4722,6 +4735,37 @@ async function parseClaudeCodeJsonl(ctx) {
4722
4735
  let cwd = null;
4723
4736
  let gitBranch = null;
4724
4737
  let lastModel = null;
4738
+ const filenameSessionId = deriveSessionIdFromFilename(ctx.sourceFile);
4739
+ const ancestorExistsCache = /* @__PURE__ */ new Map();
4740
+ function ancestorFileExists(sid) {
4741
+ const cached2 = ancestorExistsCache.get(sid);
4742
+ if (cached2 !== void 0) return cached2;
4743
+ let found = false;
4744
+ const dir = dirname2(ctx.sourceFile);
4745
+ try {
4746
+ if (existsSync2(join(dir, `${sid}.jsonl`))) {
4747
+ found = true;
4748
+ } else {
4749
+ const root = dirname2(dir);
4750
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
4751
+ if (!entry.isDirectory()) continue;
4752
+ if (existsSync2(join(root, entry.name, `${sid}.jsonl`))) {
4753
+ found = true;
4754
+ break;
4755
+ }
4756
+ }
4757
+ }
4758
+ } catch {
4759
+ }
4760
+ ancestorExistsCache.set(sid, found);
4761
+ return found;
4762
+ }
4763
+ function dedupeIdFor(lineUuid, byteOffset) {
4764
+ const isResumeCopy = filenameSessionId !== null && sessionId !== filenameSessionId;
4765
+ if (!isResumeCopy) return sourceEventId(ctx.deviceId, ctx.sourceFile, byteOffset);
4766
+ if (ancestorFileExists(sessionId)) return null;
4767
+ return sourceEventId(ctx.deviceId, { lineUuid });
4768
+ }
4725
4769
  for await (const line of rl) {
4726
4770
  const byteLen = Buffer.byteLength(line, "utf8") + 1;
4727
4771
  const offsetAtLineStart = startOffset + bytePos;
@@ -4758,10 +4802,15 @@ async function parseClaudeCodeJsonl(ctx) {
4758
4802
  skipped += 1;
4759
4803
  continue;
4760
4804
  }
4805
+ const eventId = dedupeIdFor(a.uuid, offsetAtLineStart);
4806
+ if (eventId === null) {
4807
+ skipped += 1;
4808
+ continue;
4809
+ }
4761
4810
  const slug = guessRepoSlugFromPath(cwd);
4762
4811
  const excerpt = extractExcerpt(a.message?.content);
4763
4812
  events.push({
4764
- source_event_id: sourceEventId(ctx.deviceId, ctx.sourceFile, offsetAtLineStart),
4813
+ source_event_id: eventId,
4765
4814
  ts: a.timestamp,
4766
4815
  kind: "assistant_message",
4767
4816
  tool: "claude_code",
@@ -4786,7 +4835,7 @@ async function parseClaudeCodeJsonl(ctx) {
4786
4835
  reasoning: 0
4787
4836
  },
4788
4837
  duration_ms: null,
4789
- tool_calls: {},
4838
+ tool_calls: countToolCalls(a.message?.content),
4790
4839
  files_touched: [],
4791
4840
  ...excerpt ? { content_excerpt: excerpt } : {},
4792
4841
  source_file: ctx.sourceFile,
@@ -4803,9 +4852,14 @@ async function parseClaudeCodeJsonl(ctx) {
4803
4852
  skipped += 1;
4804
4853
  continue;
4805
4854
  }
4855
+ const eventId = dedupeIdFor(u.uuid, offsetAtLineStart);
4856
+ if (eventId === null) {
4857
+ skipped += 1;
4858
+ continue;
4859
+ }
4806
4860
  const excerpt = extractExcerpt(u.message?.content);
4807
4861
  events.push({
4808
- source_event_id: sourceEventId(ctx.deviceId, ctx.sourceFile, offsetAtLineStart),
4862
+ source_event_id: eventId,
4809
4863
  ts: u.timestamp,
4810
4864
  kind: "user_message",
4811
4865
  tool: "claude_code",
@@ -4835,6 +4889,10 @@ async function parseClaudeCodeJsonl(ctx) {
4835
4889
  sourceFile: ctx.sourceFile
4836
4890
  };
4837
4891
  }
4892
+ function deriveSessionIdFromFilename(path5) {
4893
+ const m = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/.exec(path5);
4894
+ return m ? m[1] ?? null : null;
4895
+ }
4838
4896
  async function quickChecksum(path5) {
4839
4897
  const st = await stat(path5);
4840
4898
  const stream = createReadStream(path5, {
@@ -7155,9 +7213,9 @@ var init_cursor = __esm({
7155
7213
 
7156
7214
  // ../../packages/parsers/src/discovery/index.ts
7157
7215
  import { execFile as execFile2, execSync } from "child_process";
7158
- import { existsSync as existsSync2, statSync } from "fs";
7216
+ import { existsSync as existsSync3, statSync } from "fs";
7159
7217
  import { homedir, platform } from "os";
7160
- import { join, resolve as resolve2 } from "path";
7218
+ import { join as join2, resolve as resolve2 } from "path";
7161
7219
  import { promisify as promisify2 } from "util";
7162
7220
  async function discover(options = {}) {
7163
7221
  const os2 = platform() === "darwin" ? "macos" : "linux";
@@ -7173,7 +7231,7 @@ async function discover(options = {}) {
7173
7231
  }
7174
7232
  for (const extra of options.extraDataDirs?.[spec.tool] ?? []) candidates.add(expandPath(extra));
7175
7233
  for (const p of candidates) {
7176
- if (existsSync2(p) && statSync(p).isDirectory()) {
7234
+ if (existsSync3(p) && statSync(p).isDirectory()) {
7177
7235
  installations.push({
7178
7236
  tool: spec.tool,
7179
7237
  install_method: "manual",
@@ -7190,8 +7248,8 @@ async function discover(options = {}) {
7190
7248
  for (const spec of SOURCES) {
7191
7249
  for (const bin of spec.binaries ?? []) {
7192
7250
  for (const dir of binDirs) {
7193
- const p = join(dir, bin);
7194
- if (existsSync2(p)) {
7251
+ const p = join2(dir, bin);
7252
+ if (existsSync3(p)) {
7195
7253
  const version = await safeVersionProbe(p);
7196
7254
  installations.push({
7197
7255
  tool: spec.tool,
@@ -7341,7 +7399,7 @@ async function probeIdentities(os2) {
7341
7399
  `${homedir()}/.codex/auth.json`,
7342
7400
  `${homedir()}/.config/codex/auth.json`
7343
7401
  ]) {
7344
- if (!existsSync2(candidate)) continue;
7402
+ if (!existsSync3(candidate)) continue;
7345
7403
  try {
7346
7404
  const data = await fs4.promises.readFile(candidate, "utf8");
7347
7405
  const obj = JSON.parse(data);
@@ -7389,7 +7447,7 @@ async function probeIdentities(os2) {
7389
7447
  `${homedir()}/.gemini/oauth_creds.json`,
7390
7448
  `${homedir()}/.config/gemini/oauth_creds.json`
7391
7449
  ]) {
7392
- if (!existsSync2(candidate)) continue;
7450
+ if (!existsSync3(candidate)) continue;
7393
7451
  try {
7394
7452
  const data = await fs4.promises.readFile(candidate, "utf8");
7395
7453
  const obj = JSON.parse(data);
@@ -7411,7 +7469,7 @@ async function probeIdentities(os2) {
7411
7469
  `${homedir()}/Library/Application Support/Cursor/User/globalStorage/storage.json`,
7412
7470
  `${homedir()}/.config/Cursor/User/globalStorage/storage.json`
7413
7471
  ]) {
7414
- if (!existsSync2(candidate)) continue;
7472
+ if (!existsSync3(candidate)) continue;
7415
7473
  try {
7416
7474
  const data = await fs4.promises.readFile(candidate, "utf8");
7417
7475
  const obj = JSON.parse(data);
@@ -7571,10 +7629,10 @@ import {
7571
7629
  readFileSync as readFileSync2,
7572
7630
  renameSync,
7573
7631
  writeFileSync,
7574
- existsSync as existsSync3
7632
+ existsSync as existsSync4
7575
7633
  } from "fs";
7576
7634
  import { homedir as homedir2, hostname as osHostname } from "os";
7577
- import { join as join2 } from "path";
7635
+ import { join as join3 } from "path";
7578
7636
  function ensureRoot() {
7579
7637
  mkdirSync(ROOT, { recursive: true, mode: 448 });
7580
7638
  }
@@ -7592,7 +7650,7 @@ function identityPath() {
7592
7650
  return IDENTITY_FILE;
7593
7651
  }
7594
7652
  function hasIdentityFile() {
7595
- return existsSync3(IDENTITY_FILE);
7653
+ return existsSync4(IDENTITY_FILE);
7596
7654
  }
7597
7655
  function parseFile() {
7598
7656
  try {
@@ -7643,7 +7701,7 @@ function saveIdentity(meta) {
7643
7701
  writeAtomic(meta);
7644
7702
  }
7645
7703
  function backupIdentity() {
7646
- if (!existsSync3(IDENTITY_FILE)) return null;
7704
+ if (!existsSync4(IDENTITY_FILE)) return null;
7647
7705
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7648
7706
  const dest = `${IDENTITY_FILE}.bak-${stamp}`;
7649
7707
  renameSync(IDENTITY_FILE, dest);
@@ -7660,8 +7718,8 @@ var ROOT, IDENTITY_FILE;
7660
7718
  var init_identity = __esm({
7661
7719
  "src/identity.ts"() {
7662
7720
  "use strict";
7663
- ROOT = join2(homedir2(), ".modelstat");
7664
- IDENTITY_FILE = join2(ROOT, "identity.json");
7721
+ ROOT = join3(homedir2(), ".modelstat");
7722
+ IDENTITY_FILE = join3(ROOT, "identity.json");
7665
7723
  }
7666
7724
  });
7667
7725
 
@@ -21162,7 +21220,7 @@ var require_snapshot_recorder = __commonJS({
21162
21220
  "../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
21163
21221
  "use strict";
21164
21222
  var { writeFile, readFile, mkdir: mkdir2 } = __require("fs/promises");
21165
- var { dirname: dirname8, resolve: resolve6 } = __require("path");
21223
+ var { dirname: dirname9, resolve: resolve6 } = __require("path");
21166
21224
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("timers");
21167
21225
  var { InvalidArgumentError, UndiciError } = require_errors();
21168
21226
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -21393,7 +21451,7 @@ var require_snapshot_recorder = __commonJS({
21393
21451
  throw new InvalidArgumentError("Snapshot path is required");
21394
21452
  }
21395
21453
  const resolvedPath = resolve6(path5);
21396
- await mkdir2(dirname8(resolvedPath), { recursive: true });
21454
+ await mkdir2(dirname9(resolvedPath), { recursive: true });
21397
21455
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
21398
21456
  hash,
21399
21457
  snapshot
@@ -43947,9 +44005,9 @@ var init_source = __esm({
43947
44005
  });
43948
44006
 
43949
44007
  // src/config.ts
43950
- import { existsSync as existsSync4 } from "fs";
44008
+ import { existsSync as existsSync5 } from "fs";
43951
44009
  import { hostname } from "os";
43952
- import { dirname as dirname2, resolve as resolve3 } from "path";
44010
+ import { dirname as dirname3, resolve as resolve3 } from "path";
43953
44011
  import { fileURLToPath } from "url";
43954
44012
  function migrateFromConf() {
43955
44013
  const bearer = store.get("bearerToken");
@@ -43989,10 +44047,10 @@ var init_config2 = __esm({
43989
44047
  import_dotenv = __toESM(require_main(), 1);
43990
44048
  init_source();
43991
44049
  init_identity();
43992
- here = dirname2(fileURLToPath(import.meta.url));
44050
+ here = dirname3(fileURLToPath(import.meta.url));
43993
44051
  for (let d = here, i = 0; i < 8; i++, d = resolve3(d, "..")) {
43994
44052
  const candidate = resolve3(d, ".env");
43995
- if (existsSync4(candidate)) {
44053
+ if (existsSync5(candidate)) {
43996
44054
  (0, import_dotenv.config)({ path: candidate });
43997
44055
  break;
43998
44056
  }
@@ -44801,7 +44859,7 @@ var init_src3 = __esm({
44801
44859
 
44802
44860
  // ../../packages/companion-core/src/node/file-queue-store.ts
44803
44861
  import { promises as fs3 } from "fs";
44804
- import { dirname as dirname3 } from "path";
44862
+ import { dirname as dirname4 } from "path";
44805
44863
  var SENT_TTL_MS, FileQueueStore;
44806
44864
  var init_file_queue_store = __esm({
44807
44865
  "../../packages/companion-core/src/node/file-queue-store.ts"() {
@@ -44857,7 +44915,7 @@ var init_file_queue_store = __esm({
44857
44915
  items: Object.fromEntries(this.items.entries())
44858
44916
  };
44859
44917
  const tmp = `${this.filePath}.tmp`;
44860
- await fs3.mkdir(dirname3(this.filePath), { recursive: true });
44918
+ await fs3.mkdir(dirname4(this.filePath), { recursive: true });
44861
44919
  await fs3.writeFile(tmp, JSON.stringify(snap), "utf8");
44862
44920
  try {
44863
44921
  await fs3.rename(this.filePath, `${this.filePath}.bak`);
@@ -45034,14 +45092,14 @@ var init_ollama = __esm({
45034
45092
 
45035
45093
  // ../../packages/companion-core/src/node/llama.ts
45036
45094
  import { mkdir } from "fs/promises";
45037
- import { existsSync as existsSync5 } from "fs";
45095
+ import { existsSync as existsSync6 } from "fs";
45038
45096
  import { homedir as homedir4 } from "os";
45039
- import { dirname as dirname4, join as join3 } from "path";
45097
+ import { dirname as dirname5, join as join4 } from "path";
45040
45098
  function defaultLlamaConfig() {
45041
45099
  const env2 = globalThis.process?.env ?? {};
45042
- const modelsDir = env2.MODELSTAT_MODELS_DIR ?? join3(homedir4(), ".modelstat", "models");
45100
+ const modelsDir = env2.MODELSTAT_MODELS_DIR ?? join4(homedir4(), ".modelstat", "models");
45043
45101
  const modelUrl = env2.MODELSTAT_LLAMA_MODEL_URL ?? DEFAULT_LLAMA_MODEL_URL;
45044
- const modelPath = env2.MODELSTAT_LLAMA_MODEL_PATH ?? join3(modelsDir, basenameFromUrl(modelUrl));
45102
+ const modelPath = env2.MODELSTAT_LLAMA_MODEL_PATH ?? join4(modelsDir, basenameFromUrl(modelUrl));
45045
45103
  return {
45046
45104
  modelPath,
45047
45105
  modelUrl,
@@ -45062,8 +45120,8 @@ function basenameFromUrl(url) {
45062
45120
  return parts[parts.length - 1] || "model.gguf";
45063
45121
  }
45064
45122
  async function ensureLlamaModel(cfg = defaultLlamaConfig()) {
45065
- if (existsSync5(cfg.modelPath)) return cfg.modelPath;
45066
- await mkdir(dirname4(cfg.modelPath), { recursive: true });
45123
+ if (existsSync6(cfg.modelPath)) return cfg.modelPath;
45124
+ await mkdir(dirname5(cfg.modelPath), { recursive: true });
45067
45125
  const res = await fetch(cfg.modelUrl);
45068
45126
  if (!res.ok || !res.body) {
45069
45127
  throw new Error(
@@ -45534,7 +45592,7 @@ var init_pipeline2 = __esm({
45534
45592
  // src/scan.ts
45535
45593
  import { readdir, stat as stat2 } from "fs/promises";
45536
45594
  import { homedir as homedir5 } from "os";
45537
- import { join as join4 } from "path";
45595
+ import { join as join5 } from "path";
45538
45596
  function withNonNullTokens(e) {
45539
45597
  return e.tokens ? e : { ...e, tokens: { ...ZERO_TOKENS } };
45540
45598
  }
@@ -45543,16 +45601,16 @@ async function scanAll(cb = {}) {
45543
45601
  if (!deviceId) throw new Error("agent not enrolled \u2014 run `register` first");
45544
45602
  const jobs = [];
45545
45603
  try {
45546
- const base = join4(homedir5(), ".claude/projects");
45604
+ const base = join5(homedir5(), ".claude/projects");
45547
45605
  const projects = await readdir(base).catch(() => []);
45548
45606
  for (const p of projects) {
45549
- const dir = join4(base, p);
45607
+ const dir = join5(base, p);
45550
45608
  const ds = await stat2(dir).catch(() => null);
45551
45609
  if (!ds?.isDirectory()) continue;
45552
45610
  const files = await readdir(dir);
45553
45611
  for (const f of files) {
45554
45612
  if (!f.endsWith(".jsonl")) continue;
45555
- const full = join4(dir, f);
45613
+ const full = join5(dir, f);
45556
45614
  jobs.push({
45557
45615
  path: full,
45558
45616
  parse: async () => {
@@ -45566,17 +45624,17 @@ async function scanAll(cb = {}) {
45566
45624
  console.warn("claude scan skipped:", e.message);
45567
45625
  }
45568
45626
  try {
45569
- const base = join4(homedir5(), ".codex/sessions");
45627
+ const base = join5(homedir5(), ".codex/sessions");
45570
45628
  const years = await readdir(base).catch(() => []);
45571
45629
  for (const y of years) {
45572
- const months = await readdir(join4(base, y)).catch(() => []);
45630
+ const months = await readdir(join5(base, y)).catch(() => []);
45573
45631
  for (const m of months) {
45574
- const days = await readdir(join4(base, y, m)).catch(() => []);
45632
+ const days = await readdir(join5(base, y, m)).catch(() => []);
45575
45633
  for (const d of days) {
45576
- const files = await readdir(join4(base, y, m, d)).catch(() => []);
45634
+ const files = await readdir(join5(base, y, m, d)).catch(() => []);
45577
45635
  for (const f of files) {
45578
45636
  if (!f.startsWith("rollout-") || !f.endsWith(".jsonl")) continue;
45579
- const full = join4(base, y, m, d, f);
45637
+ const full = join5(base, y, m, d, f);
45580
45638
  jobs.push({
45581
45639
  path: full,
45582
45640
  parse: async () => {
@@ -45671,7 +45729,7 @@ var init_scan = __esm({
45671
45729
  init_pipeline2();
45672
45730
  init_config2();
45673
45731
  init_api();
45674
- AGENT_VERSION = true ? "agent-0.0.43" : "agent-dev";
45732
+ AGENT_VERSION = true ? "agent-0.0.45" : "agent-dev";
45675
45733
  BATCH_MAX_EVENTS = 2e3;
45676
45734
  ZERO_TOKENS = {
45677
45735
  input: 0,
@@ -45686,7 +45744,7 @@ var init_scan = __esm({
45686
45744
  // src/lock.ts
45687
45745
  import {
45688
45746
  closeSync,
45689
- existsSync as existsSync7,
45747
+ existsSync as existsSync8,
45690
45748
  mkdirSync as mkdirSync3,
45691
45749
  openSync,
45692
45750
  readFileSync as readFileSync4,
@@ -45696,7 +45754,7 @@ import {
45696
45754
  writeSync
45697
45755
  } from "fs";
45698
45756
  import { homedir as homedir7 } from "os";
45699
- import { join as join6 } from "path";
45757
+ import { join as join7 } from "path";
45700
45758
  function isProcessAlive(pid) {
45701
45759
  if (!pid || pid <= 0) return false;
45702
45760
  try {
@@ -45797,8 +45855,8 @@ var LOCK_DIR, LOCK_FILE;
45797
45855
  var init_lock = __esm({
45798
45856
  "src/lock.ts"() {
45799
45857
  "use strict";
45800
- LOCK_DIR = join6(homedir7(), ".modelstat");
45801
- LOCK_FILE = join6(LOCK_DIR, "daemon.lock");
45858
+ LOCK_DIR = join7(homedir7(), ".modelstat");
45859
+ LOCK_FILE = join7(LOCK_DIR, "daemon.lock");
45802
45860
  }
45803
45861
  });
45804
45862
 
@@ -46599,9 +46657,9 @@ var init_handler = __esm({
46599
46657
  if (this.fsw.closed) {
46600
46658
  return;
46601
46659
  }
46602
- const dirname8 = sysPath.dirname(file);
46660
+ const dirname9 = sysPath.dirname(file);
46603
46661
  const basename4 = sysPath.basename(file);
46604
- const parent = this.fsw._getWatchedDir(dirname8);
46662
+ const parent = this.fsw._getWatchedDir(dirname9);
46605
46663
  let prevStats = stats;
46606
46664
  if (parent.has(basename4))
46607
46665
  return;
@@ -46628,7 +46686,7 @@ var init_handler = __esm({
46628
46686
  prevStats = newStats2;
46629
46687
  }
46630
46688
  } catch (error) {
46631
- this.fsw._remove(dirname8, basename4);
46689
+ this.fsw._remove(dirname9, basename4);
46632
46690
  }
46633
46691
  } else if (parent.has(basename4)) {
46634
46692
  const at = newStats.atimeMs;
@@ -47594,7 +47652,7 @@ __export(daemon_exports, {
47594
47652
  setQueue: () => setQueue,
47595
47653
  setStat: () => setStat
47596
47654
  });
47597
- import { existsSync as existsSync8, statSync as statSync2 } from "fs";
47655
+ import { existsSync as existsSync9, statSync as statSync2 } from "fs";
47598
47656
  function setPhase(phase, message) {
47599
47657
  status.phase = phase;
47600
47658
  status.message = message ?? null;
@@ -47674,15 +47732,15 @@ async function sendHeartbeat() {
47674
47732
  }
47675
47733
  async function writeLocalStatus(snapshot) {
47676
47734
  const { homedir: homedir9 } = await import("os");
47677
- const { join: join10 } = await import("path");
47735
+ const { join: join11 } = await import("path");
47678
47736
  const { writeFile, mkdir: mkdir2, rename } = await import("fs/promises");
47679
47737
  if (!lastStatusPath) {
47680
- const dir = join10(homedir9(), ".modelstat");
47738
+ const dir = join11(homedir9(), ".modelstat");
47681
47739
  try {
47682
47740
  await mkdir2(dir, { recursive: true });
47683
47741
  } catch {
47684
47742
  }
47685
- lastStatusPath = join10(dir, "last-status.json");
47743
+ lastStatusPath = join11(dir, "last-status.json");
47686
47744
  }
47687
47745
  const tmp = `${lastStatusPath}.tmp`;
47688
47746
  try {
@@ -47805,20 +47863,20 @@ async function runDaemon(opts = {}) {
47805
47863
  await requestScan("startup");
47806
47864
  const chokidar = (await Promise.resolve().then(() => (init_esm2(), esm_exports))).default;
47807
47865
  const { homedir: homedir9, platform: platform5 } = await import("os");
47808
- const { join: join10 } = await import("path");
47866
+ const { join: join11 } = await import("path");
47809
47867
  const home2 = homedir9();
47810
47868
  const dirs = [
47811
- join10(home2, ".claude/projects"),
47812
- join10(home2, ".codex/sessions"),
47813
- join10(home2, ".cursor/ai-tracking"),
47814
- join10(home2, ".gemini"),
47869
+ join11(home2, ".claude/projects"),
47870
+ join11(home2, ".codex/sessions"),
47871
+ join11(home2, ".cursor/ai-tracking"),
47872
+ join11(home2, ".gemini"),
47815
47873
  ...platform5() === "darwin" ? [
47816
- join10(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
47817
- join10(home2, "Library/Application Support/Claude")
47874
+ join11(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
47875
+ join11(home2, "Library/Application Support/Claude")
47818
47876
  ] : [
47819
- join10(home2, ".config/Cursor/User/workspaceStorage")
47877
+ join11(home2, ".config/Cursor/User/workspaceStorage")
47820
47878
  ]
47821
- ].filter((p) => existsSync8(p) && statSync2(p).isDirectory());
47879
+ ].filter((p) => existsSync9(p) && statSync2(p).isDirectory());
47822
47880
  setPhase("watching", `Watching ${dirs.length} directories`);
47823
47881
  const watcher = chokidar.watch(dirs, {
47824
47882
  persistent: true,
@@ -47871,7 +47929,7 @@ var init_daemon = __esm({
47871
47929
  init_lock();
47872
47930
  init_scan();
47873
47931
  init_single_flight();
47874
- AGENT_VERSION2 = true ? "agent-0.0.43" : "agent-dev";
47932
+ AGENT_VERSION2 = true ? "agent-0.0.45" : "agent-dev";
47875
47933
  HEARTBEAT_INTERVAL_MS = 1e4;
47876
47934
  SCAN_INTERVAL_MS = 5 * 60 * 1e3;
47877
47935
  DISCOVERY_INTERVAL_MS = 6e4;
@@ -47897,37 +47955,37 @@ var watch_exports = {};
47897
47955
  __export(watch_exports, {
47898
47956
  watchForever: () => watchForever
47899
47957
  });
47900
- import { existsSync as existsSync9 } from "fs";
47958
+ import { existsSync as existsSync10 } from "fs";
47901
47959
  import { homedir as homedir8, platform as platform3 } from "os";
47902
- import { join as join9 } from "path";
47960
+ import { join as join10 } from "path";
47903
47961
  function resolveWatchDirs() {
47904
47962
  const home2 = homedir8();
47905
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join9(home2, ".config");
47906
- const xdgData = process.env.XDG_DATA_HOME ?? join9(home2, ".local/share");
47963
+ const xdgConfig = process.env.XDG_CONFIG_HOME ?? join10(home2, ".config");
47964
+ const xdgData = process.env.XDG_DATA_HOME ?? join10(home2, ".local/share");
47907
47965
  const candidates = [
47908
47966
  // universal (default HOME-rooted CLI data dirs)
47909
- join9(home2, ".claude/projects"),
47910
- join9(home2, ".codex/sessions"),
47911
- join9(home2, ".cursor/ai-tracking"),
47912
- join9(home2, ".gemini"),
47913
- join9(home2, ".aider"),
47967
+ join10(home2, ".claude/projects"),
47968
+ join10(home2, ".codex/sessions"),
47969
+ join10(home2, ".cursor/ai-tracking"),
47970
+ join10(home2, ".gemini"),
47971
+ join10(home2, ".aider"),
47914
47972
  // XDG / Linux
47915
- join9(xdgConfig, "claude/projects"),
47916
- join9(xdgConfig, "codex/sessions"),
47917
- join9(xdgConfig, "Cursor/User/workspaceStorage"),
47918
- join9(xdgConfig, "Code/User/workspaceStorage"),
47919
- join9(xdgConfig, "Code - Insiders/User/workspaceStorage"),
47920
- join9(xdgData, "claude/projects"),
47973
+ join10(xdgConfig, "claude/projects"),
47974
+ join10(xdgConfig, "codex/sessions"),
47975
+ join10(xdgConfig, "Cursor/User/workspaceStorage"),
47976
+ join10(xdgConfig, "Code/User/workspaceStorage"),
47977
+ join10(xdgConfig, "Code - Insiders/User/workspaceStorage"),
47978
+ join10(xdgData, "claude/projects"),
47921
47979
  // macOS
47922
47980
  ...platform3() === "darwin" ? [
47923
- join9(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
47924
- join9(home2, "Library/Application Support/Claude"),
47925
- join9(home2, "Library/Application Support/Code/User/workspaceStorage"),
47926
- join9(home2, "Library/Application Support/Windsurf/User/workspaceStorage"),
47927
- join9(home2, "Library/Application Support/Zed")
47981
+ join10(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
47982
+ join10(home2, "Library/Application Support/Claude"),
47983
+ join10(home2, "Library/Application Support/Code/User/workspaceStorage"),
47984
+ join10(home2, "Library/Application Support/Windsurf/User/workspaceStorage"),
47985
+ join10(home2, "Library/Application Support/Zed")
47928
47986
  ] : []
47929
47987
  ];
47930
- return Array.from(new Set(candidates)).filter((p) => existsSync9(p));
47988
+ return Array.from(new Set(candidates)).filter((p) => existsSync10(p));
47931
47989
  }
47932
47990
  async function safeScan(reason) {
47933
47991
  if (scanning) {
@@ -48002,7 +48060,7 @@ import { createInterface as createInterface3 } from "readline";
48002
48060
  import { spawnSync } from "child_process";
48003
48061
  import {
48004
48062
  copyFileSync,
48005
- existsSync as existsSync6,
48063
+ existsSync as existsSync7,
48006
48064
  mkdirSync as mkdirSync2,
48007
48065
  readFileSync as readFileSync3,
48008
48066
  realpathSync,
@@ -48011,7 +48069,7 @@ import {
48011
48069
  } from "fs";
48012
48070
  import { createRequire } from "module";
48013
48071
  import { homedir as homedir6, platform as platform2, userInfo } from "os";
48014
- import { dirname as dirname5, join as join5 } from "path";
48072
+ import { dirname as dirname6, join as join6 } from "path";
48015
48073
  import { fileURLToPath as fileURLToPath2 } from "url";
48016
48074
  var SERVICE_LABEL = "ai.modelstat.agent";
48017
48075
  var SYSTEMD_UNIT = "modelstat";
@@ -48019,16 +48077,16 @@ function home() {
48019
48077
  return homedir6();
48020
48078
  }
48021
48079
  function stateDir() {
48022
- return join5(home(), ".modelstat");
48080
+ return join6(home(), ".modelstat");
48023
48081
  }
48024
48082
  function binDir() {
48025
- return join5(stateDir(), "bin");
48083
+ return join6(stateDir(), "bin");
48026
48084
  }
48027
48085
  function logDir() {
48028
- return join5(stateDir(), "logs");
48086
+ return join6(stateDir(), "logs");
48029
48087
  }
48030
48088
  function installedCliPath() {
48031
- return join5(binDir(), "modelstat.mjs");
48089
+ return join6(binDir(), "modelstat.mjs");
48032
48090
  }
48033
48091
  function runningCliPath() {
48034
48092
  return fileURLToPath2(import.meta.url).replace(/service\.(mjs|js|ts)$/, "cli.mjs");
@@ -48038,7 +48096,7 @@ function installBundle() {
48038
48096
  mkdirSync2(logDir(), { recursive: true });
48039
48097
  const src = runningCliPath();
48040
48098
  const dest = installedCliPath();
48041
- if (!existsSync6(src)) {
48099
+ if (!existsSync7(src)) {
48042
48100
  throw new Error(
48043
48101
  `Can't find the CLI bundle to install from (${src}). Are you running a local dev build?`
48044
48102
  );
@@ -48054,14 +48112,14 @@ var NODE_LLAMA_CPP_FALLBACK_VERSION = "3.18.1";
48054
48112
  function sourceLlamaVersion(sourceCli) {
48055
48113
  try {
48056
48114
  const req = createRequire(sourceCli);
48057
- let d = dirname5(realpathSync(req.resolve("node-llama-cpp")));
48115
+ let d = dirname6(realpathSync(req.resolve("node-llama-cpp")));
48058
48116
  for (let i = 0; i < 10; i++) {
48059
- const pj = join5(d, "package.json");
48060
- if (existsSync6(pj)) {
48117
+ const pj = join6(d, "package.json");
48118
+ if (existsSync7(pj)) {
48061
48119
  const p = JSON.parse(readFileSync3(pj, "utf8"));
48062
48120
  if (p.name === "node-llama-cpp" && p.version) return p.version;
48063
48121
  }
48064
- const up = dirname5(d);
48122
+ const up = dirname6(d);
48065
48123
  if (up === d) break;
48066
48124
  d = up;
48067
48125
  }
@@ -48075,7 +48133,7 @@ function installNativeRuntime(sourceCli) {
48075
48133
  try {
48076
48134
  const have = JSON.parse(
48077
48135
  readFileSync3(
48078
- join5(dest, "node_modules", "node-llama-cpp", "package.json"),
48136
+ join6(dest, "node_modules", "node-llama-cpp", "package.json"),
48079
48137
  "utf8"
48080
48138
  )
48081
48139
  );
@@ -48116,21 +48174,21 @@ function nodeBinary() {
48116
48174
  return process.execPath;
48117
48175
  }
48118
48176
  function plistPath() {
48119
- return join5(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
48177
+ return join6(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
48120
48178
  }
48121
48179
  function locateTrayExecutable() {
48122
48180
  const candidates = [
48123
- join5(home(), "Applications", "ModelstatTray.app", "Contents", "MacOS", "modelstat-tray"),
48181
+ join6(home(), "Applications", "ModelstatTray.app", "Contents", "MacOS", "modelstat-tray"),
48124
48182
  "/Applications/ModelstatTray.app/Contents/MacOS/modelstat-tray"
48125
48183
  ];
48126
48184
  for (const p of candidates) {
48127
- if (existsSync6(p)) return p;
48185
+ if (existsSync7(p)) return p;
48128
48186
  }
48129
48187
  return null;
48130
48188
  }
48131
48189
  function writePlist(cliPath) {
48132
48190
  const p = plistPath();
48133
- mkdirSync2(dirname5(p), { recursive: true });
48191
+ mkdirSync2(dirname6(p), { recursive: true });
48134
48192
  const tray = locateTrayExecutable();
48135
48193
  const programArgs = tray ? ` <string>${tray}</string>` : [
48136
48194
  ` <string>${nodeBinary()}</string>`,
@@ -48150,8 +48208,8 @@ ${programArgs}
48150
48208
  <key>KeepAlive</key>
48151
48209
  <dict><key>SuccessfulExit</key><false/></dict>
48152
48210
  <key>ThrottleInterval</key><integer>30</integer>
48153
- <key>StandardOutPath</key><string>${join5(logDir(), "out.log")}</string>
48154
- <key>StandardErrorPath</key><string>${join5(logDir(), "err.log")}</string>
48211
+ <key>StandardOutPath</key><string>${join6(logDir(), "out.log")}</string>
48212
+ <key>StandardErrorPath</key><string>${join6(logDir(), "err.log")}</string>
48155
48213
  <key>EnvironmentVariables</key>
48156
48214
  <dict>
48157
48215
  <key>PATH</key><string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
@@ -48196,7 +48254,7 @@ function macUninstall() {
48196
48254
  const target = `gui/${uid}/${SERVICE_LABEL}`;
48197
48255
  launchctl(["bootout", target]);
48198
48256
  const plist = plistPath();
48199
- if (existsSync6(plist)) {
48257
+ if (existsSync7(plist)) {
48200
48258
  try {
48201
48259
  unlinkSync(plist);
48202
48260
  } catch {
@@ -48209,12 +48267,12 @@ function macStatus() {
48209
48267
  return { running: r.ok, hint: r.ok ? "launchd managed" : "not installed" };
48210
48268
  }
48211
48269
  function systemdUnitPath() {
48212
- const xdg = process.env.XDG_CONFIG_HOME ?? join5(home(), ".config");
48213
- return join5(xdg, "systemd", "user", `${SYSTEMD_UNIT}.service`);
48270
+ const xdg = process.env.XDG_CONFIG_HOME ?? join6(home(), ".config");
48271
+ return join6(xdg, "systemd", "user", `${SYSTEMD_UNIT}.service`);
48214
48272
  }
48215
48273
  function writeSystemdUnit(cliPath) {
48216
48274
  const unitPath = systemdUnitPath();
48217
- mkdirSync2(dirname5(unitPath), { recursive: true });
48275
+ mkdirSync2(dirname6(unitPath), { recursive: true });
48218
48276
  const unit = `[Unit]
48219
48277
  Description=modelstat agent
48220
48278
  Documentation=https://modelstat.ai
@@ -48233,8 +48291,8 @@ RestartSec=10
48233
48291
  # Don't restart-storm if the service is persistently unreachable.
48234
48292
  StartLimitIntervalSec=300
48235
48293
  StartLimitBurst=10
48236
- StandardOutput=append:${join5(logDir(), "out.log")}
48237
- StandardError=append:${join5(logDir(), "err.log")}
48294
+ StandardOutput=append:${join6(logDir(), "out.log")}
48295
+ StandardError=append:${join6(logDir(), "err.log")}
48238
48296
 
48239
48297
  [Install]
48240
48298
  WantedBy=default.target
@@ -48259,7 +48317,7 @@ function linuxInstall() {
48259
48317
  function linuxUninstall() {
48260
48318
  systemctl(["disable", "--now", `${SYSTEMD_UNIT}.service`]);
48261
48319
  const unit = systemdUnitPath();
48262
- if (existsSync6(unit)) {
48320
+ if (existsSync7(unit)) {
48263
48321
  try {
48264
48322
  unlinkSync(unit);
48265
48323
  } catch {
@@ -48303,9 +48361,9 @@ function logsDir() {
48303
48361
  }
48304
48362
  function installTrayApp(sourceAppPath) {
48305
48363
  if (platform2() !== "darwin") return null;
48306
- if (!existsSync6(sourceAppPath)) return null;
48307
- const dest = join5(home(), "Applications", "ModelstatTray.app");
48308
- mkdirSync2(dirname5(dest), { recursive: true });
48364
+ if (!existsSync7(sourceAppPath)) return null;
48365
+ const dest = join6(home(), "Applications", "ModelstatTray.app");
48366
+ mkdirSync2(dirname6(dest), { recursive: true });
48309
48367
  spawnSync("rm", ["-rf", dest]);
48310
48368
  const r = spawnSync("cp", ["-R", sourceAppPath, dest], { encoding: "utf8" });
48311
48369
  if (r.status !== 0) {
@@ -48315,28 +48373,28 @@ function installTrayApp(sourceAppPath) {
48315
48373
  }
48316
48374
  function bundledTrayAppPath() {
48317
48375
  if (platform2() !== "darwin") return null;
48318
- const here2 = dirname5(fileURLToPath2(import.meta.url));
48376
+ const here2 = dirname6(fileURLToPath2(import.meta.url));
48319
48377
  const candidates = [
48320
48378
  // Pre-built .app — CI with codesigning drops one here.
48321
- join5(here2, "..", "vendor", "ModelstatTray.app"),
48379
+ join6(here2, "..", "vendor", "ModelstatTray.app"),
48322
48380
  // Local dev layout: apps/agent-dev/src/service.ts → ../../tray-mac/build/ModelstatTray.app
48323
- join5(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
48381
+ join6(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
48324
48382
  ];
48325
48383
  for (const c of candidates) {
48326
- if (existsSync6(c)) return c;
48384
+ if (existsSync7(c)) return c;
48327
48385
  }
48328
48386
  const sourceDirs = [
48329
- join5(here2, "..", "vendor", "tray-mac"),
48330
- join5(here2, "..", "..", "tray-mac")
48387
+ join6(here2, "..", "vendor", "tray-mac"),
48388
+ join6(here2, "..", "..", "tray-mac")
48331
48389
  ];
48332
48390
  for (const src of sourceDirs) {
48333
- const build = join5(src, "build-app.sh");
48334
- if (!existsSync6(build)) continue;
48391
+ const build = join6(src, "build-app.sh");
48392
+ if (!existsSync7(build)) continue;
48335
48393
  if (!hasSwift()) return null;
48336
48394
  const r = spawnSync("bash", [build], { cwd: src, encoding: "utf8" });
48337
48395
  if (r.status === 0) {
48338
- const app = join5(src, "build", "ModelstatTray.app");
48339
- if (existsSync6(app)) return app;
48396
+ const app = join6(src, "build", "ModelstatTray.app");
48397
+ if (existsSync7(app)) return app;
48340
48398
  }
48341
48399
  }
48342
48400
  return null;
@@ -48381,7 +48439,7 @@ function tryOpenBrowser(url) {
48381
48439
  return false;
48382
48440
  }
48383
48441
  }
48384
- var AGENT_VERSION3 = true ? "agent-0.0.43" : "agent-dev";
48442
+ var AGENT_VERSION3 = true ? "agent-0.0.45" : "agent-dev";
48385
48443
  function osFamily() {
48386
48444
  const p = platform4();
48387
48445
  if (p === "darwin") return "macos";
@@ -48776,9 +48834,9 @@ function fmtTokens(v) {
48776
48834
  async function readLocalStatus() {
48777
48835
  try {
48778
48836
  const { homedir: homedir9 } = await import("os");
48779
- const { join: join10 } = await import("path");
48837
+ const { join: join11 } = await import("path");
48780
48838
  const { readFile } = await import("fs/promises");
48781
- const p = join10(homedir9(), ".modelstat", "last-status.json");
48839
+ const p = join11(homedir9(), ".modelstat", "last-status.json");
48782
48840
  const txt = await readFile(p, "utf8");
48783
48841
  return JSON.parse(txt);
48784
48842
  } catch {
@@ -48911,6 +48969,22 @@ function cmdPaths(args) {
48911
48969
  console.log(`${k.padEnd(8)} ${String(v)}`);
48912
48970
  }
48913
48971
  }
48972
+ function cmdToken(args) {
48973
+ if (!state.bearer) {
48974
+ console.error("not paired \u2014 run `npx modelstat@latest` first");
48975
+ process.exit(1);
48976
+ }
48977
+ if (args.includes("--json")) {
48978
+ process.stdout.write(`${JSON.stringify({ token: state.bearer, api: state.apiUrl })}
48979
+ `);
48980
+ return;
48981
+ }
48982
+ process.stdout.write(`${state.bearer}
48983
+ `);
48984
+ if (process.stderr.isTTY) {
48985
+ console.error("(device token \u2014 treat it like a password; rotate via the dashboard if leaked)");
48986
+ }
48987
+ }
48914
48988
  function parseConnectOpts(argv) {
48915
48989
  return {
48916
48990
  json: argv.includes("--json"),
@@ -48951,6 +49025,9 @@ async function main() {
48951
49025
  case "paths":
48952
49026
  cmdPaths(rest);
48953
49027
  return;
49028
+ case "token":
49029
+ cmdToken(rest);
49030
+ return;
48954
49031
  case "discover":
48955
49032
  return cmdDiscover();
48956
49033
  case "scan":
@@ -48975,6 +49052,7 @@ async function main() {
48975
49052
  console.log(" npx modelstat@latest stats \u2014 live device summary: sessions \xB7 tokens \xB7 cost (--json)");
48976
49053
  console.log(" npx modelstat@latest jobs \u2014 pipeline queue + recent processing ledger (--json)");
48977
49054
  console.log(" npx modelstat@latest paths \u2014 print state file + log dir + api URL (--json)");
49055
+ console.log(" npx modelstat@latest token \u2014 print the device token for hosted MCP / API access (--json)");
48978
49056
  console.log();
48979
49057
  console.log("Dev / one-shots:");
48980
49058
  console.log(" npx modelstat@latest scan \u2014 one-shot parse + upload of local JSONL");