@wbern/cc-ping 1.12.0 → 1.13.1

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 +47 -15
  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) => {
@@ -1227,7 +1256,7 @@ function resolveExecutable(deps) {
1227
1256
  args: [process.argv[1]]
1228
1257
  };
1229
1258
  }
1230
- function generateLaunchdPlist(options, execInfo, configDir) {
1259
+ function generateLaunchdPlist(options, execInfo, configDir, path) {
1231
1260
  const intervalMs = parseIntervalForService(options.interval);
1232
1261
  const programArgs = [
1233
1262
  ...execInfo.args,
@@ -1251,6 +1280,7 @@ function generateLaunchdPlist(options, execInfo, configDir) {
1251
1280
  const envVars = {};
1252
1281
  if (configDir) envVars.CC_PING_CONFIG = configDir;
1253
1282
  if (execInfo.args.length === 0) envVars.CC_PING_BIN = execInfo.executable;
1283
+ if (path) envVars.PATH = path;
1254
1284
  let envSection = "";
1255
1285
  if (Object.keys(envVars).length > 0) {
1256
1286
  const entries = Object.entries(envVars).map(
@@ -1288,7 +1318,7 @@ ${argsXml}
1288
1318
  </plist>
1289
1319
  `;
1290
1320
  }
1291
- function generateSystemdUnit(options, execInfo, configDir) {
1321
+ function generateSystemdUnit(options, execInfo, configDir, path) {
1292
1322
  const intervalMs = parseIntervalForService(options.interval);
1293
1323
  const programArgs = [
1294
1324
  ...execInfo.args,
@@ -1308,6 +1338,7 @@ function generateSystemdUnit(options, execInfo, configDir) {
1308
1338
  if (configDir) envPairs.push(`CC_PING_CONFIG=${configDir}`);
1309
1339
  if (execInfo.args.length === 0)
1310
1340
  envPairs.push(`CC_PING_BIN=${execInfo.executable}`);
1341
+ if (path) envPairs.push(`PATH=${path}`);
1311
1342
  const envLine = envPairs.map((p) => `
1312
1343
  Environment=${p}`).join("");
1313
1344
  return `[Unit]
@@ -1379,11 +1410,12 @@ async function installService(options, deps) {
1379
1410
  execSync: _execSync
1380
1411
  });
1381
1412
  const configDir = _configDir || void 0;
1413
+ const envPath = process.env.PATH;
1382
1414
  let content;
1383
1415
  if (_platform === "darwin") {
1384
- content = generateLaunchdPlist(options, execInfo, configDir);
1416
+ content = generateLaunchdPlist(options, execInfo, configDir, envPath);
1385
1417
  } else {
1386
- content = generateSystemdUnit(options, execInfo, configDir);
1418
+ content = generateSystemdUnit(options, execInfo, configDir, envPath);
1387
1419
  }
1388
1420
  _mkdirSync(dirname(path), { recursive: true });
1389
1421
  _writeFileSync(path, content);
@@ -1458,18 +1490,18 @@ function escapeXml(str) {
1458
1490
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
1459
1491
  }
1460
1492
  function parseIntervalForService(value) {
1461
- if (!value) return QUOTA_WINDOW_MS2;
1493
+ if (!value) return QUOTA_WINDOW_MS3;
1462
1494
  const minutes = Number(value);
1463
- if (Number.isNaN(minutes) || minutes <= 0) return QUOTA_WINDOW_MS2;
1495
+ if (Number.isNaN(minutes) || minutes <= 0) return QUOTA_WINDOW_MS3;
1464
1496
  return minutes * 60 * 1e3;
1465
1497
  }
1466
- var PLIST_LABEL, SYSTEMD_SERVICE, QUOTA_WINDOW_MS2;
1498
+ var PLIST_LABEL, SYSTEMD_SERVICE, QUOTA_WINDOW_MS3;
1467
1499
  var init_service = __esm({
1468
1500
  "src/service.ts"() {
1469
1501
  "use strict";
1470
1502
  PLIST_LABEL = "com.cc-ping.daemon";
1471
1503
  SYSTEMD_SERVICE = "cc-ping-daemon";
1472
- QUOTA_WINDOW_MS2 = 5 * 60 * 60 * 1e3;
1504
+ QUOTA_WINDOW_MS3 = 5 * 60 * 60 * 1e3;
1473
1505
  }
1474
1506
  });
1475
1507
 
@@ -2063,7 +2095,7 @@ function getDeferredHandles() {
2063
2095
  }
2064
2096
  return deferred;
2065
2097
  }
2066
- var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.12.0").option(
2098
+ var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.13.1").option(
2067
2099
  "--config <path>",
2068
2100
  "Path to config directory (default: ~/.config/cc-ping, env: CC_PING_CONFIG)"
2069
2101
  ).hook("preAction", (thisCommand) => {
@@ -2292,7 +2324,7 @@ daemon.command("start").description("Start the daemon process").option(
2292
2324
  bell: opts.bell,
2293
2325
  notify: opts.notify,
2294
2326
  smartSchedule,
2295
- version: "1.12.0"
2327
+ version: "1.13.1"
2296
2328
  });
2297
2329
  if (!result.success) {
2298
2330
  console.error(result.error);
@@ -2328,7 +2360,7 @@ daemon.command("stop").description("Stop the daemon process").action(async () =>
2328
2360
  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
2361
  const { getServiceStatus: getServiceStatus2 } = await Promise.resolve().then(() => (init_service(), service_exports));
2330
2362
  const svc = getServiceStatus2();
2331
- const status = getDaemonStatus({ currentVersion: "1.12.0" });
2363
+ const status = getDaemonStatus({ currentVersion: "1.13.1" });
2332
2364
  if (opts.json) {
2333
2365
  const serviceInfo = svc.installed ? {
2334
2366
  service: {
@@ -2389,7 +2421,7 @@ daemon.command("status").description("Show daemon status").option("--json", "Out
2389
2421
  if (status.versionMismatch) {
2390
2422
  console.log(
2391
2423
  yellow(
2392
- ` Warning: daemon is running v${status.daemonVersion} but v${"1.12.0"} is installed.`
2424
+ ` Warning: daemon is running v${status.daemonVersion} but v${"1.13.1"} is installed.`
2393
2425
  )
2394
2426
  );
2395
2427
  console.log(
@@ -2457,7 +2489,7 @@ daemon.command("_run", { hidden: true }).option("--interval-ms <ms>", "Ping inte
2457
2489
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2458
2490
  intervalMs,
2459
2491
  configDir: resolveConfigDir2(),
2460
- version: "1.12.0"
2492
+ version: "1.13.1"
2461
2493
  });
2462
2494
  }
2463
2495
  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.1",
4
4
  "description": "Ping Claude Code sessions to trigger quota windows early across multiple accounts",
5
5
  "type": "module",
6
6
  "bin": {