@wbern/cc-ping 1.10.1 → 1.11.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 (3) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +17 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -192,8 +192,8 @@ Smart scheduling -- ping timed so window expires at peak:
192
192
 
193
193
  1. Reads `<configDir>/history.jsonl` from each account's config directory (Claude Code's prompt timestamps)
194
194
  2. Builds an hour-of-day histogram from the last 14 days
195
- 3. Finds the weighted midpoint of your activity
196
- 4. Schedules pings at `midpoint - 5h` so the window expires at your peak
195
+ 3. Slides a 5-hour window across the histogram to find the densest period
196
+ 4. Schedules pings so the window expires at the midpoint of peak activity
197
197
 
198
198
  **Defer zone:** When smart scheduling is active, pings that would fire in the 5 hours before the optimal time are deferred. Pings outside this zone proceed normally for continuous coverage.
199
199
 
package/dist/cli.js CHANGED
@@ -620,16 +620,19 @@ function buildHourHistogram(timestamps) {
620
620
  function findOptimalPingHour(histogram) {
621
621
  const total = histogram.reduce((sum, v) => sum + v, 0);
622
622
  if (total === 0) return -1;
623
- const HOUR_TO_RAD = 2 * Math.PI / 24;
624
- let sinSum = 0;
625
- let cosSum = 0;
623
+ let bestStart = 0;
624
+ let bestSum = 0;
626
625
  for (let h = 0; h < 24; h++) {
627
- const angle = h * HOUR_TO_RAD;
628
- sinSum += histogram[h] * Math.sin(angle);
629
- cosSum += histogram[h] * Math.cos(angle);
626
+ let windowSum = 0;
627
+ for (let offset = 0; offset < QUOTA_WINDOW_HOURS; offset++) {
628
+ windowSum += histogram[(h + offset) % 24];
629
+ }
630
+ if (windowSum > bestSum) {
631
+ bestSum = windowSum;
632
+ bestStart = h;
633
+ }
630
634
  }
631
- const meanAngle = Math.atan2(sinSum, cosSum);
632
- const midpoint = Math.round((meanAngle / HOUR_TO_RAD + 24) % 24);
635
+ const midpoint = (bestStart + Math.floor(QUOTA_WINDOW_HOURS / 2)) % 24;
633
636
  return (midpoint - QUOTA_WINDOW_HOURS + 24) % 24;
634
637
  }
635
638
  function shouldDefer(now, optimalPingHour) {
@@ -1783,7 +1786,7 @@ function censorHandle(handle) {
1783
1786
  }
1784
1787
  function censorPart(part) {
1785
1788
  if (part.length <= 1) return part;
1786
- return part[0] + "*".repeat(part.length - 1);
1789
+ return part[0] + "\xB7".repeat(part.length - 1);
1787
1790
  }
1788
1791
  function censorDomain(domain) {
1789
1792
  const lastDot = domain.lastIndexOf(".");
@@ -2020,7 +2023,7 @@ function getDeferredHandles() {
2020
2023
  }
2021
2024
  return deferred;
2022
2025
  }
2023
- var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.10.1").option(
2026
+ var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.11.0").option(
2024
2027
  "--config <path>",
2025
2028
  "Path to config directory (default: ~/.config/cc-ping, env: CC_PING_CONFIG)"
2026
2029
  ).hook("preAction", (thisCommand) => {
@@ -2249,7 +2252,7 @@ daemon.command("start").description("Start the daemon process").option(
2249
2252
  bell: opts.bell,
2250
2253
  notify: opts.notify,
2251
2254
  smartSchedule,
2252
- version: "1.10.1"
2255
+ version: "1.11.0"
2253
2256
  });
2254
2257
  if (!result.success) {
2255
2258
  console.error(result.error);
@@ -2285,7 +2288,7 @@ daemon.command("stop").description("Stop the daemon process").action(async () =>
2285
2288
  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) => {
2286
2289
  const { getServiceStatus: getServiceStatus2 } = await Promise.resolve().then(() => (init_service(), service_exports));
2287
2290
  const svc = getServiceStatus2();
2288
- const status = getDaemonStatus({ currentVersion: "1.10.1" });
2291
+ const status = getDaemonStatus({ currentVersion: "1.11.0" });
2289
2292
  if (opts.json) {
2290
2293
  const serviceInfo = svc.installed ? {
2291
2294
  service: {
@@ -2346,7 +2349,7 @@ daemon.command("status").description("Show daemon status").option("--json", "Out
2346
2349
  if (status.versionMismatch) {
2347
2350
  console.log(
2348
2351
  yellow(
2349
- ` Warning: daemon is running v${status.daemonVersion} but v${"1.10.1"} is installed.`
2352
+ ` Warning: daemon is running v${status.daemonVersion} but v${"1.11.0"} is installed.`
2350
2353
  )
2351
2354
  );
2352
2355
  console.log(
@@ -2414,7 +2417,7 @@ daemon.command("_run", { hidden: true }).option("--interval-ms <ms>", "Ping inte
2414
2417
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2415
2418
  intervalMs,
2416
2419
  configDir: resolveConfigDir2(),
2417
- version: "1.10.1"
2420
+ version: "1.11.0"
2418
2421
  });
2419
2422
  }
2420
2423
  await runDaemonWithDefaults(intervalMs, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbern/cc-ping",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "description": "Ping Claude Code sessions to trigger quota windows early across multiple accounts",
5
5
  "type": "module",
6
6
  "bin": {