exe-watcher 0.2.3 → 0.2.5

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
@@ -2479,6 +2479,10 @@ function createParser(source, seenKeys) {
2479
2479
  sessionModel = entry.payload?.model;
2480
2480
  continue;
2481
2481
  }
2482
+ if (entry.type === "turn_context" && entry.payload?.model) {
2483
+ sessionModel = entry.payload.model;
2484
+ continue;
2485
+ }
2482
2486
  if (entry.type === "response_item" && entry.payload?.type === "function_call") {
2483
2487
  const rawName = entry.payload.name ?? "";
2484
2488
  pendingTools.push(toolNameMap[rawName] ?? rawName);
@@ -3391,17 +3395,13 @@ async function scanProjectDirs(dirs, seenMsgIds, dateRange) {
3391
3395
  }
3392
3396
  }
3393
3397
  }
3394
- const projects = [];
3395
- for (const [dirName, sessions] of projectMap) {
3396
- projects.push({
3397
- project: dirName,
3398
- projectPath: unsanitizePath(dirName),
3399
- sessions,
3400
- totalCostUSD: sessions.reduce((s, sess) => s + sess.totalCostUSD, 0),
3401
- totalApiCalls: sessions.reduce((s, sess) => s + sess.apiCalls, 0)
3402
- });
3403
- }
3404
- 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
+ }));
3405
3405
  }
3406
3406
  function providerCallToTurn(call) {
3407
3407
  const tools = call.tools;
@@ -3507,32 +3507,14 @@ function cacheKey(dateRange, providerFilter, sourceFingerprint = "static") {
3507
3507
  const s = dateRange ? `${dateRange.start.getTime()}:${dateRange.end.getTime()}` : "none";
3508
3508
  return `${s}:${providerFilter ?? "all"}:${sourceFingerprint}`;
3509
3509
  }
3510
- async function buildSourceFingerprint(path) {
3511
- try {
3512
- const fp = await stat10(path);
3513
- if (!fp.isDirectory()) return `f:${Math.round(fp.mtimeMs)}:${fp.size}`;
3514
- const entries = await readdir8(path);
3515
- const children = await Promise.all(entries.map(async (entry) => stat10(join15(path, entry)).catch(() => null)));
3516
- let childCount = 0;
3517
- let childSizeBytes = 0;
3518
- let newestChildMtimeMs = 0;
3519
- for (const child of children) {
3520
- if (!child) continue;
3521
- childCount += 1;
3522
- childSizeBytes += child.size;
3523
- newestChildMtimeMs = Math.max(newestChildMtimeMs, child.mtimeMs);
3524
- }
3525
- return `d:${Math.round(fp.mtimeMs)}:${fp.size}:${childCount}:${Math.round(newestChildMtimeMs)}:${childSizeBytes}`;
3526
- } catch {
3527
- 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
+ }
3528
3516
  }
3529
- }
3530
- async function buildCacheFingerprint(sources) {
3531
- const parts = await Promise.all(sources.map(async (source) => {
3532
- const fingerprint = await buildSourceFingerprint(source.path);
3533
- return `${source.provider}:${source.project}:${source.path}:${fingerprint}`;
3534
- }));
3535
- return parts.sort().join("|");
3517
+ return `${sources.length}:${hash >>> 0}`;
3536
3518
  }
3537
3519
  async function getSourceContext(providerFilter) {
3538
3520
  const key = sourceContextCacheKey(providerFilter);
@@ -3542,7 +3524,7 @@ async function getSourceContext(providerFilter) {
3542
3524
  }
3543
3525
  const promise = (async () => {
3544
3526
  const sources = await discoverAllSessions(providerFilter);
3545
- const fingerprint = await buildCacheFingerprint(sources);
3527
+ const fingerprint = buildCacheFingerprint(sources);
3546
3528
  return { sources, fingerprint };
3547
3529
  })();
3548
3530
  inFlightSourceContexts.set(key, promise);
@@ -7046,13 +7028,17 @@ program.command("status").description("Compact status output (today + week + mon
7046
7028
  const latestFresh = freshDays.length > 0 ? freshDays[freshDays.length - 1].date : null;
7047
7029
  c = { ...c, days: freshDays, lastComputedDate: latestFresh };
7048
7030
  }
7031
+ const PROGRESSIVE_CHUNK_DAYS = 30;
7032
+ const isColdStart = !c.lastComputedDate;
7049
7033
  const gapStart = c.lastComputedDate ? new Date(
7050
7034
  parseInt(c.lastComputedDate.slice(0, 4)),
7051
7035
  parseInt(c.lastComputedDate.slice(5, 7)) - 1,
7052
7036
  parseInt(c.lastComputedDate.slice(8, 10)) + 1
7053
7037
  ) : new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY3);
7054
- if (gapStart.getTime() <= yesterdayEnd.getTime()) {
7055
- 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 };
7056
7042
  const gapProjects = filterProjectsByName(await parseAllSessions(gapRange, "all"), opts.project, opts.exclude);
7057
7043
  const gapDays = fillMissingDays(gapRange.start, gapRange.end, aggregateProjectsIntoDays(gapProjects));
7058
7044
  c = addNewDays(c, gapDays, yesterdayStr, { coveredThrough: yesterdayStr });
@@ -7214,11 +7200,22 @@ program.command("status").description("Compact status output (today + week + mon
7214
7200
  if (agentStats) {
7215
7201
  agentStats = estimateAgentCosts(agentStats);
7216
7202
  }
7217
- const [proj7d, proj30d] = await Promise.all([
7218
- parseAllSessions(getDateRange2("week").range, "all"),
7219
- parseAllSessions(getDateRange2("30days").range, "all")
7220
- ]);
7221
- 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
+ }
7222
7219
  const diagnostics = { daysCount, parseTimeMs, warnings };
7223
7220
  console.log(JSON.stringify(buildMenubarPayload(currentData, providers, optimize, dailyHistory, agentStats, projectSpend, exeOsDetected, statsFileAge, diagnostics)));
7224
7221
  return;