exe-watcher 0.2.4 → 0.2.6

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.js CHANGED
@@ -3395,17 +3395,13 @@ async function scanProjectDirs(dirs, seenMsgIds, dateRange) {
3395
3395
  }
3396
3396
  }
3397
3397
  }
3398
- const projects = [];
3399
- for (const [dirName, sessions] of projectMap) {
3400
- projects.push({
3401
- project: dirName,
3402
- projectPath: unsanitizePath(dirName),
3403
- sessions,
3404
- totalCostUSD: sessions.reduce((s, sess) => s + sess.totalCostUSD, 0),
3405
- totalApiCalls: sessions.reduce((s, sess) => s + sess.apiCalls, 0)
3406
- });
3407
- }
3408
- return projects;
3398
+ return Array.from(projectMap.entries()).map(([dirName, sessions]) => ({
3399
+ project: dirName,
3400
+ projectPath: unsanitizePath(dirName),
3401
+ sessions,
3402
+ totalCostUSD: sessions.reduce((s, sess) => s + sess.totalCostUSD, 0),
3403
+ totalApiCalls: sessions.reduce((s, sess) => s + sess.apiCalls, 0)
3404
+ }));
3409
3405
  }
3410
3406
  function providerCallToTurn(call) {
3411
3407
  const tools = call.tools;
@@ -3511,32 +3507,14 @@ function cacheKey(dateRange, providerFilter, sourceFingerprint = "static") {
3511
3507
  const s = dateRange ? `${dateRange.start.getTime()}:${dateRange.end.getTime()}` : "none";
3512
3508
  return `${s}:${providerFilter ?? "all"}:${sourceFingerprint}`;
3513
3509
  }
3514
- async function buildSourceFingerprint(path) {
3515
- try {
3516
- const fp = await stat10(path);
3517
- if (!fp.isDirectory()) return `f:${Math.round(fp.mtimeMs)}:${fp.size}`;
3518
- const entries = await readdir8(path);
3519
- const children = await Promise.all(entries.map(async (entry) => stat10(join15(path, entry)).catch(() => null)));
3520
- let childCount = 0;
3521
- let childSizeBytes = 0;
3522
- let newestChildMtimeMs = 0;
3523
- for (const child of children) {
3524
- if (!child) continue;
3525
- childCount += 1;
3526
- childSizeBytes += child.size;
3527
- newestChildMtimeMs = Math.max(newestChildMtimeMs, child.mtimeMs);
3528
- }
3529
- return `d:${Math.round(fp.mtimeMs)}:${fp.size}:${childCount}:${Math.round(newestChildMtimeMs)}:${childSizeBytes}`;
3530
- } catch {
3531
- return "missing";
3510
+ function buildCacheFingerprint(sources) {
3511
+ let hash = sources.length;
3512
+ for (const s of sources) {
3513
+ for (let i = 0; i < s.path.length; i++) {
3514
+ hash = (hash << 5) + hash + s.path.charCodeAt(i) | 0;
3515
+ }
3532
3516
  }
3533
- }
3534
- async function buildCacheFingerprint(sources) {
3535
- const parts = await Promise.all(sources.map(async (source) => {
3536
- const fingerprint = await buildSourceFingerprint(source.path);
3537
- return `${source.provider}:${source.project}:${source.path}:${fingerprint}`;
3538
- }));
3539
- return parts.sort().join("|");
3517
+ return `${sources.length}:${hash >>> 0}`;
3540
3518
  }
3541
3519
  async function getSourceContext(providerFilter) {
3542
3520
  const key = sourceContextCacheKey(providerFilter);
@@ -3546,7 +3524,7 @@ async function getSourceContext(providerFilter) {
3546
3524
  }
3547
3525
  const promise = (async () => {
3548
3526
  const sources = await discoverAllSessions(providerFilter);
3549
- const fingerprint = await buildCacheFingerprint(sources);
3527
+ const fingerprint = buildCacheFingerprint(sources);
3550
3528
  return { sources, fingerprint };
3551
3529
  })();
3552
3530
  inFlightSourceContexts.set(key, promise);
@@ -7050,13 +7028,17 @@ program.command("status").description("Compact status output (today + week + mon
7050
7028
  const latestFresh = freshDays.length > 0 ? freshDays[freshDays.length - 1].date : null;
7051
7029
  c = { ...c, days: freshDays, lastComputedDate: latestFresh };
7052
7030
  }
7031
+ const PROGRESSIVE_CHUNK_DAYS = 30;
7032
+ const isColdStart = !c.lastComputedDate;
7053
7033
  const gapStart = c.lastComputedDate ? new Date(
7054
7034
  parseInt(c.lastComputedDate.slice(0, 4)),
7055
7035
  parseInt(c.lastComputedDate.slice(5, 7)) - 1,
7056
7036
  parseInt(c.lastComputedDate.slice(8, 10)) + 1
7057
7037
  ) : new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY3);
7058
- if (gapStart.getTime() <= yesterdayEnd.getTime()) {
7059
- const gapRange = { start: gapStart, end: yesterdayEnd };
7038
+ const fullBackfillStart = new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY3);
7039
+ const effectiveGapStart = isColdStart ? todayStart : gapStart < fullBackfillStart ? fullBackfillStart : yesterdayEnd.getTime() - gapStart.getTime() > PROGRESSIVE_CHUNK_DAYS * MS_PER_DAY3 ? new Date(yesterdayEnd.getTime() - PROGRESSIVE_CHUNK_DAYS * MS_PER_DAY3) : gapStart;
7040
+ if (!isColdStart && effectiveGapStart.getTime() <= yesterdayEnd.getTime()) {
7041
+ const gapRange = { start: effectiveGapStart, end: yesterdayEnd };
7060
7042
  const gapProjects = filterProjectsByName(await parseAllSessions(gapRange, "all"), opts.project, opts.exclude);
7061
7043
  const gapDays = fillMissingDays(gapRange.start, gapRange.end, aggregateProjectsIntoDays(gapProjects));
7062
7044
  c = addNewDays(c, gapDays, yesterdayStr, { coveredThrough: yesterdayStr });
@@ -7218,11 +7200,22 @@ program.command("status").description("Compact status output (today + week + mon
7218
7200
  if (agentStats) {
7219
7201
  agentStats = estimateAgentCosts(agentStats);
7220
7202
  }
7221
- const [proj7d, proj30d] = await Promise.all([
7222
- parseAllSessions(getDateRange2("week").range, "all"),
7223
- parseAllSessions(getDateRange2("30days").range, "all")
7224
- ]);
7225
- const projectSpend = buildProjectSpend(allTodayProjects, proj7d, proj30d);
7203
+ let projectSpend = null;
7204
+ try {
7205
+ const [proj7d, proj30d] = await Promise.all([
7206
+ Promise.race([
7207
+ parseAllSessions(getDateRange2("week").range, "all"),
7208
+ new Promise((r) => setTimeout(() => r([]), 3e3))
7209
+ ]),
7210
+ Promise.race([
7211
+ parseAllSessions(getDateRange2("30days").range, "all"),
7212
+ new Promise((r) => setTimeout(() => r([]), 3e3))
7213
+ ])
7214
+ ]);
7215
+ projectSpend = buildProjectSpend(allTodayProjects, proj7d, proj30d);
7216
+ } catch {
7217
+ projectSpend = buildProjectSpend(allTodayProjects, [], []);
7218
+ }
7226
7219
  const diagnostics = { daysCount, parseTimeMs, warnings };
7227
7220
  console.log(JSON.stringify(buildMenubarPayload(currentData, providers, optimize, dailyHistory, agentStats, projectSpend, exeOsDetected, statsFileAge, diagnostics)));
7228
7221
  return;