@wbern/cc-ping 1.12.0 → 1.13.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +40 -11
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -618,14 +618,30 @@ var init_run_ping = __esm({
618
618
  var schedule_exports = {};
619
619
  __export(schedule_exports, {
620
620
  buildHourHistogram: () => buildHourHistogram,
621
+ checkRecentActivity: () => checkRecentActivity,
621
622
  findOptimalPingHour: () => findOptimalPingHour,
622
623
  getAccountSchedule: () => getAccountSchedule,
624
+ isRecentlyActive: () => isRecentlyActive,
623
625
  parseSmartSchedule: () => parseSmartSchedule,
624
626
  readAccountSchedule: () => readAccountSchedule,
625
627
  shouldDefer: () => shouldDefer
626
628
  });
627
629
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
628
630
  import { join as join6 } from "path";
631
+ function isRecentlyActive(historyLines, now) {
632
+ let latest = 0;
633
+ for (const line of historyLines) {
634
+ try {
635
+ const entry = JSON.parse(line);
636
+ if (typeof entry.timestamp === "number" && entry.timestamp > latest) {
637
+ latest = entry.timestamp;
638
+ }
639
+ } catch {
640
+ }
641
+ }
642
+ if (latest === 0) return false;
643
+ return now.getTime() - latest < QUOTA_WINDOW_MS2;
644
+ }
629
645
  function buildHourHistogram(timestamps) {
630
646
  const bins = new Array(24).fill(0);
631
647
  for (const ts of timestamps) {
@@ -697,6 +713,13 @@ function readAccountSchedule(configDir, now = /* @__PURE__ */ new Date(), resetA
697
713
  const lines = content.split("\n").filter((l) => l.trim());
698
714
  return getAccountSchedule(lines, now, resetAt);
699
715
  }
716
+ function checkRecentActivity(configDir, now = /* @__PURE__ */ new Date()) {
717
+ const historyPath = join6(configDir, "history.jsonl");
718
+ if (!existsSync5(historyPath)) return false;
719
+ const content = readFileSync5(historyPath, "utf-8");
720
+ const lines = content.split("\n").filter((l) => l.trim());
721
+ return isRecentlyActive(lines, now);
722
+ }
700
723
  function parseSmartSchedule(value) {
701
724
  const lower = value.toLowerCase();
702
725
  if (TRUTHY.has(lower)) return true;
@@ -705,11 +728,12 @@ function parseSmartSchedule(value) {
705
728
  `Invalid smart-schedule value: "${value}". Use true/false, on/off, or 1/0`
706
729
  );
707
730
  }
708
- var QUOTA_WINDOW_HOURS, MIN_DAYS, HISTORY_WINDOW_MS, TRUTHY, FALSY;
731
+ var QUOTA_WINDOW_HOURS, QUOTA_WINDOW_MS2, MIN_DAYS, HISTORY_WINDOW_MS, TRUTHY, FALSY;
709
732
  var init_schedule = __esm({
710
733
  "src/schedule.ts"() {
711
734
  "use strict";
712
735
  QUOTA_WINDOW_HOURS = 5;
736
+ QUOTA_WINDOW_MS2 = QUOTA_WINDOW_HOURS * 60 * 60 * 1e3;
713
737
  MIN_DAYS = 7;
714
738
  HISTORY_WINDOW_MS = 14 * 24 * 60 * 60 * 1e3;
715
739
  TRUTHY = /* @__PURE__ */ new Set(["true", "on", "1"]);
@@ -1109,6 +1133,7 @@ async function runDaemonWithDefaults(intervalMs, options) {
1109
1133
  const { runPing: runPing2 } = await Promise.resolve().then(() => (init_run_ping(), run_ping_exports));
1110
1134
  const { listAccounts: listAccounts2 } = await Promise.resolve().then(() => (init_config(), config_exports));
1111
1135
  const { getWindowReset: getWindowReset2 } = await Promise.resolve().then(() => (init_state(), state_exports));
1136
+ const { checkRecentActivity: checkRecentActivity2 } = await Promise.resolve().then(() => (init_schedule(), schedule_exports));
1112
1137
  const smartScheduleEnabled = options.smartSchedule !== false;
1113
1138
  let shouldDeferPing;
1114
1139
  if (smartScheduleEnabled) {
@@ -1167,7 +1192,11 @@ async function runDaemonWithDefaults(intervalMs, options) {
1167
1192
  sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)),
1168
1193
  shouldStop: () => existsSync6(stopPath),
1169
1194
  log: (msg) => console.log(msg),
1170
- isWindowActive: (handle) => getWindowReset2(handle) !== null,
1195
+ isWindowActive: (handle) => {
1196
+ if (getWindowReset2(handle) !== null) return true;
1197
+ const account = listAccounts2().find((a) => a.handle === handle);
1198
+ return account ? checkRecentActivity2(account.configDir) : false;
1199
+ },
1171
1200
  shouldDeferPing,
1172
1201
  hasUpgraded,
1173
1202
  updateState: (patch) => {
@@ -1458,18 +1487,18 @@ function escapeXml(str) {
1458
1487
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
1459
1488
  }
1460
1489
  function parseIntervalForService(value) {
1461
- if (!value) return QUOTA_WINDOW_MS2;
1490
+ if (!value) return QUOTA_WINDOW_MS3;
1462
1491
  const minutes = Number(value);
1463
- if (Number.isNaN(minutes) || minutes <= 0) return QUOTA_WINDOW_MS2;
1492
+ if (Number.isNaN(minutes) || minutes <= 0) return QUOTA_WINDOW_MS3;
1464
1493
  return minutes * 60 * 1e3;
1465
1494
  }
1466
- var PLIST_LABEL, SYSTEMD_SERVICE, QUOTA_WINDOW_MS2;
1495
+ var PLIST_LABEL, SYSTEMD_SERVICE, QUOTA_WINDOW_MS3;
1467
1496
  var init_service = __esm({
1468
1497
  "src/service.ts"() {
1469
1498
  "use strict";
1470
1499
  PLIST_LABEL = "com.cc-ping.daemon";
1471
1500
  SYSTEMD_SERVICE = "cc-ping-daemon";
1472
- QUOTA_WINDOW_MS2 = 5 * 60 * 60 * 1e3;
1501
+ QUOTA_WINDOW_MS3 = 5 * 60 * 60 * 1e3;
1473
1502
  }
1474
1503
  });
1475
1504
 
@@ -2063,7 +2092,7 @@ function getDeferredHandles() {
2063
2092
  }
2064
2093
  return deferred;
2065
2094
  }
2066
- var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.12.0").option(
2095
+ var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.13.0").option(
2067
2096
  "--config <path>",
2068
2097
  "Path to config directory (default: ~/.config/cc-ping, env: CC_PING_CONFIG)"
2069
2098
  ).hook("preAction", (thisCommand) => {
@@ -2292,7 +2321,7 @@ daemon.command("start").description("Start the daemon process").option(
2292
2321
  bell: opts.bell,
2293
2322
  notify: opts.notify,
2294
2323
  smartSchedule,
2295
- version: "1.12.0"
2324
+ version: "1.13.0"
2296
2325
  });
2297
2326
  if (!result.success) {
2298
2327
  console.error(result.error);
@@ -2328,7 +2357,7 @@ daemon.command("stop").description("Stop the daemon process").action(async () =>
2328
2357
  daemon.command("status").description("Show daemon status").option("--json", "Output as JSON", false).option("--censor", "Mask account handles in output (for screenshots)").action(async (opts) => {
2329
2358
  const { getServiceStatus: getServiceStatus2 } = await Promise.resolve().then(() => (init_service(), service_exports));
2330
2359
  const svc = getServiceStatus2();
2331
- const status = getDaemonStatus({ currentVersion: "1.12.0" });
2360
+ const status = getDaemonStatus({ currentVersion: "1.13.0" });
2332
2361
  if (opts.json) {
2333
2362
  const serviceInfo = svc.installed ? {
2334
2363
  service: {
@@ -2389,7 +2418,7 @@ daemon.command("status").description("Show daemon status").option("--json", "Out
2389
2418
  if (status.versionMismatch) {
2390
2419
  console.log(
2391
2420
  yellow(
2392
- ` Warning: daemon is running v${status.daemonVersion} but v${"1.12.0"} is installed.`
2421
+ ` Warning: daemon is running v${status.daemonVersion} but v${"1.13.0"} is installed.`
2393
2422
  )
2394
2423
  );
2395
2424
  console.log(
@@ -2457,7 +2486,7 @@ daemon.command("_run", { hidden: true }).option("--interval-ms <ms>", "Ping inte
2457
2486
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2458
2487
  intervalMs,
2459
2488
  configDir: resolveConfigDir2(),
2460
- version: "1.12.0"
2489
+ version: "1.13.0"
2461
2490
  });
2462
2491
  }
2463
2492
  await runDaemonWithDefaults(intervalMs, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbern/cc-ping",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "description": "Ping Claude Code sessions to trigger quota windows early across multiple accounts",
5
5
  "type": "module",
6
6
  "bin": {