@wbern/cc-ping 1.6.0 → 1.8.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 +78 -35
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -9,6 +9,27 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // src/color.ts
13
+ function isColorEnabled() {
14
+ if (process.env.NO_COLOR) return false;
15
+ if (process.env.FORCE_COLOR === "1") return true;
16
+ if (process.env.FORCE_COLOR === "0") return false;
17
+ return process.stdout.isTTY ?? false;
18
+ }
19
+ function wrap(code, text) {
20
+ return isColorEnabled() ? `\x1B[${code}m${text}\x1B[0m` : text;
21
+ }
22
+ var green, red, yellow, blue;
23
+ var init_color = __esm({
24
+ "src/color.ts"() {
25
+ "use strict";
26
+ green = (text) => wrap("32", text);
27
+ red = (text) => wrap("31", text);
28
+ yellow = (text) => wrap("33", text);
29
+ blue = (text) => wrap("34", text);
30
+ }
31
+ });
32
+
12
33
  // src/paths.ts
13
34
  var paths_exports = {};
14
35
  __export(paths_exports, {
@@ -186,27 +207,6 @@ var init_bell = __esm({
186
207
  }
187
208
  });
188
209
 
189
- // src/color.ts
190
- function isColorEnabled() {
191
- if (process.env.NO_COLOR) return false;
192
- if (process.env.FORCE_COLOR === "1") return true;
193
- if (process.env.FORCE_COLOR === "0") return false;
194
- return process.stdout.isTTY ?? false;
195
- }
196
- function wrap(code, text) {
197
- return isColorEnabled() ? `\x1B[${code}m${text}\x1B[0m` : text;
198
- }
199
- var green, red, yellow, blue;
200
- var init_color = __esm({
201
- "src/color.ts"() {
202
- "use strict";
203
- green = (text) => wrap("32", text);
204
- red = (text) => wrap("31", text);
205
- yellow = (text) => wrap("33", text);
206
- blue = (text) => wrap("34", text);
207
- }
208
- });
209
-
210
210
  // src/history.ts
211
211
  import { appendFileSync, existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4 } from "fs";
212
212
  import { join as join5 } from "path";
@@ -1070,7 +1070,15 @@ async function runDaemon(intervalMs, options, deps) {
1070
1070
  cleanup();
1071
1071
  }
1072
1072
  if (exitReason === "upgrade") {
1073
- deps.exit(75);
1073
+ if (deps.restart) {
1074
+ try {
1075
+ deps.restart();
1076
+ } catch {
1077
+ deps.exit(75);
1078
+ }
1079
+ } else {
1080
+ deps.exit(75);
1081
+ }
1074
1082
  }
1075
1083
  }
1076
1084
  async function runDaemonWithDefaults(intervalMs, options) {
@@ -1123,7 +1131,23 @@ async function runDaemonWithDefaults(intervalMs, options) {
1123
1131
  },
1124
1132
  onSignal: (signal, handler) => process.on(signal, handler),
1125
1133
  removeSignal: (signal, handler) => process.removeListener(signal, handler),
1126
- exit: (code) => process.exit(code)
1134
+ exit: (code) => process.exit(code),
1135
+ restart: () => {
1136
+ console.log("Restarting daemon with updated binary...");
1137
+ const result = startDaemon({
1138
+ interval: `${intervalMs / 6e4}m`,
1139
+ quiet: options.quiet,
1140
+ bell: options.bell,
1141
+ notify: options.notify,
1142
+ smartSchedule: options.smartSchedule
1143
+ });
1144
+ if (result.success) {
1145
+ console.log(`Daemon restarted (PID: ${result.pid})`);
1146
+ } else {
1147
+ console.log(`Failed to restart: ${result.error}`);
1148
+ process.exit(75);
1149
+ }
1150
+ }
1127
1151
  });
1128
1152
  }
1129
1153
  var GRACEFUL_POLL_MS, GRACEFUL_POLL_ATTEMPTS, POST_KILL_DELAY_MS;
@@ -1466,6 +1490,9 @@ function checkAccounts(accounts) {
1466
1490
  return accounts.map((a) => checkAccount(a));
1467
1491
  }
1468
1492
 
1493
+ // src/cli.ts
1494
+ init_color();
1495
+
1469
1496
  // src/completions.ts
1470
1497
  var COMMANDS = "ping scan add remove list status next-reset history suggest check completions moo daemon";
1471
1498
  function bashCompletion() {
@@ -1740,10 +1767,20 @@ function colorizeStatus(windowStatus) {
1740
1767
  }
1741
1768
  }
1742
1769
  function formatStatusLine(status) {
1743
- const ping = status.lastPing === null ? "never" : status.lastPing.replace("T", " ").replace(/\.\d+Z$/, "Z");
1744
- const reset = status.timeUntilReset !== null ? ` (resets in ${status.timeUntilReset})` : "";
1770
+ const lines = [];
1745
1771
  const dup = status.duplicateOf ? ` [duplicate of ${status.duplicateOf}]` : "";
1746
- return ` ${status.handle}: ${colorizeStatus(status.windowStatus)} last ping: ${ping}${reset}${dup}`;
1772
+ lines.push(
1773
+ ` ${status.handle}: ${colorizeStatus(status.windowStatus)}${dup}`
1774
+ );
1775
+ const ping = status.lastPing === null ? "never" : status.lastPing.replace("T", " ").replace(/\.\d+Z$/, "Z");
1776
+ lines.push(` - last ping: ${ping}`);
1777
+ if (status.timeUntilReset !== null) {
1778
+ lines.push(` - resets in ${status.timeUntilReset}`);
1779
+ }
1780
+ if (status.deferUntilUtcHour !== void 0) {
1781
+ lines.push(` - scheduled ping at ${status.deferUntilUtcHour}:00 UTC`);
1782
+ }
1783
+ return lines.join("\n");
1747
1784
  }
1748
1785
  function getAccountStatuses(accounts, now = /* @__PURE__ */ new Date(), duplicates, deferredHandles) {
1749
1786
  const dupLookup = /* @__PURE__ */ new Map();
@@ -1775,6 +1812,7 @@ function getAccountStatuses(accounts, now = /* @__PURE__ */ new Date(), duplicat
1775
1812
  }
1776
1813
  const window = getWindowReset(account.handle, now);
1777
1814
  const isDeferred = !window && deferredHandles?.has(account.handle);
1815
+ const deferUntilUtcHour = isDeferred ? deferredHandles?.get(account.handle) : void 0;
1778
1816
  return {
1779
1817
  handle: account.handle,
1780
1818
  configDir: account.configDir,
@@ -1783,7 +1821,8 @@ function getAccountStatuses(accounts, now = /* @__PURE__ */ new Date(), duplicat
1783
1821
  timeUntilReset: window ? formatTimeRemaining(window.remainingMs) : null,
1784
1822
  lastCostUsd,
1785
1823
  lastTokens,
1786
- duplicateOf
1824
+ duplicateOf,
1825
+ deferUntilUtcHour
1787
1826
  };
1788
1827
  });
1789
1828
  }
@@ -1946,17 +1985,17 @@ function suggestAccount(accounts, now = /* @__PURE__ */ new Date()) {
1946
1985
 
1947
1986
  // src/cli.ts
1948
1987
  function getDeferredHandles() {
1949
- const deferred = /* @__PURE__ */ new Set();
1988
+ const deferred = /* @__PURE__ */ new Map();
1950
1989
  const now = /* @__PURE__ */ new Date();
1951
1990
  for (const account of listAccounts()) {
1952
1991
  const schedule = readAccountSchedule(account.configDir);
1953
1992
  if (schedule && shouldDefer(now, schedule.optimalPingHour).defer) {
1954
- deferred.add(account.handle);
1993
+ deferred.set(account.handle, schedule.optimalPingHour);
1955
1994
  }
1956
1995
  }
1957
1996
  return deferred;
1958
1997
  }
1959
- var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.6.0").option(
1998
+ var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.8.0").option(
1960
1999
  "--config <path>",
1961
2000
  "Path to config directory (default: ~/.config/cc-ping, env: CC_PING_CONFIG)"
1962
2001
  ).hook("preAction", (thisCommand) => {
@@ -2183,7 +2222,7 @@ daemon.command("start").description("Start the daemon process").option(
2183
2222
  bell: opts.bell,
2184
2223
  notify: opts.notify,
2185
2224
  smartSchedule,
2186
- version: "1.6.0"
2225
+ version: "1.8.0"
2187
2226
  });
2188
2227
  if (!result.success) {
2189
2228
  console.error(result.error);
@@ -2217,7 +2256,7 @@ daemon.command("stop").description("Stop the daemon process").action(async () =>
2217
2256
  daemon.command("status").description("Show daemon status").option("--json", "Output as JSON", false).action(async (opts) => {
2218
2257
  const { getServiceStatus: getServiceStatus2 } = await Promise.resolve().then(() => (init_service(), service_exports));
2219
2258
  const svc = getServiceStatus2();
2220
- const status = getDaemonStatus({ currentVersion: "1.6.0" });
2259
+ const status = getDaemonStatus({ currentVersion: "1.8.0" });
2221
2260
  if (opts.json) {
2222
2261
  const serviceInfo = svc.installed ? {
2223
2262
  service: {
@@ -2277,10 +2316,14 @@ daemon.command("status").description("Show daemon status").option("--json", "Out
2277
2316
  }
2278
2317
  if (status.versionMismatch) {
2279
2318
  console.log(
2280
- ` Warning: daemon is running v${status.daemonVersion} but v${"1.6.0"} is installed.`
2319
+ yellow(
2320
+ ` Warning: daemon is running v${status.daemonVersion} but v${"1.8.0"} is installed.`
2321
+ )
2281
2322
  );
2282
2323
  console.log(
2283
- " Restart to pick up the new version: cc-ping daemon stop && cc-ping daemon start"
2324
+ yellow(
2325
+ " Restart to pick up the new version: cc-ping daemon stop && cc-ping daemon start"
2326
+ )
2284
2327
  );
2285
2328
  }
2286
2329
  console.log("");
@@ -2340,7 +2383,7 @@ daemon.command("_run", { hidden: true }).option("--interval-ms <ms>", "Ping inte
2340
2383
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2341
2384
  intervalMs,
2342
2385
  configDir: resolveConfigDir2(),
2343
- version: "1.6.0"
2386
+ version: "1.8.0"
2344
2387
  });
2345
2388
  }
2346
2389
  await runDaemonWithDefaults(intervalMs, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbern/cc-ping",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "Ping Claude Code sessions to trigger quota windows early across multiple accounts",
5
5
  "type": "module",
6
6
  "bin": {