@wbern/cc-ping 1.3.1 → 1.3.2

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 +48 -11
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -387,6 +387,7 @@ function formatExecError(error) {
387
387
  function pingOne(account) {
388
388
  const start = Date.now();
389
389
  return new Promise((resolve) => {
390
+ let resolved = false;
390
391
  const child = execFile(
391
392
  "claude",
392
393
  [
@@ -401,9 +402,13 @@ function pingOne(account) {
401
402
  ],
402
403
  {
403
404
  env: { ...process.env, CLAUDE_CONFIG_DIR: account.configDir },
404
- timeout: 3e4
405
+ timeout: PING_TIMEOUT_MS,
406
+ killSignal: "SIGKILL"
405
407
  },
406
408
  (error, stdout) => {
409
+ if (resolved) return;
410
+ resolved = true;
411
+ clearTimeout(hardKillTimer);
407
412
  const claudeResponse = parseClaudeResponse(stdout) ?? void 0;
408
413
  const isError = claudeResponse?.is_error === true;
409
414
  let errorMsg;
@@ -425,6 +430,21 @@ function pingOne(account) {
425
430
  });
426
431
  }
427
432
  );
433
+ const hardKillTimer = setTimeout(() => {
434
+ if (resolved) return;
435
+ resolved = true;
436
+ try {
437
+ child.kill("SIGKILL");
438
+ } catch {
439
+ }
440
+ resolve({
441
+ handle: account.handle,
442
+ success: false,
443
+ durationMs: Date.now() - start,
444
+ error: "timed out"
445
+ });
446
+ }, PING_TIMEOUT_MS + KILL_GRACE_MS);
447
+ hardKillTimer.unref();
428
448
  child.stdin?.end();
429
449
  });
430
450
  }
@@ -438,11 +458,14 @@ async function pingAccounts(accounts, options = {}) {
438
458
  }
439
459
  return results;
440
460
  }
461
+ var PING_TIMEOUT_MS, KILL_GRACE_MS;
441
462
  var init_ping = __esm({
442
463
  "src/ping.ts"() {
443
464
  "use strict";
444
465
  init_parse();
445
466
  init_prompt();
467
+ PING_TIMEOUT_MS = 3e4;
468
+ KILL_GRACE_MS = 5e3;
446
469
  }
447
470
  });
448
471
 
@@ -517,10 +540,10 @@ async function runPing(accounts, options) {
517
540
  ringBell();
518
541
  }
519
542
  if (failed > 0 && options.notify) {
520
- const failedHandles = results.filter((r) => !r.success).map((r) => r.handle);
543
+ const failedHandles2 = results.filter((r) => !r.success).map((r) => r.handle);
521
544
  await sendNotification(
522
545
  "cc-ping: ping failure",
523
- `${failed} account(s) failed: ${failedHandles.join(", ")}`
546
+ `${failed} account(s) failed: ${failedHandles2.join(", ")}`
524
547
  );
525
548
  }
526
549
  if (options.notify) {
@@ -533,6 +556,7 @@ async function runPing(accounts, options) {
533
556
  await sendNotification("cc-ping: new window", body, { sound: true });
534
557
  }
535
558
  }
559
+ const failedHandles = results.filter((r) => !r.success).map((r) => r.handle);
536
560
  if (options.json) {
537
561
  const jsonResults = results.map((r) => ({
538
562
  handle: r.handle,
@@ -541,11 +565,11 @@ async function runPing(accounts, options) {
541
565
  error: r.error
542
566
  }));
543
567
  stdout(JSON.stringify(jsonResults, null, 2));
544
- return failed > 0 ? 1 : 0;
568
+ return { exitCode: failed > 0 ? 1 : 0, failedHandles };
545
569
  }
546
570
  if (failed > 0) {
547
571
  logger.error(`${failed}/${results.length} failed`);
548
- return 1;
572
+ return { exitCode: 1, failedHandles };
549
573
  }
550
574
  logger.log(`
551
575
  All ${results.length} accounts pinged successfully`);
@@ -558,7 +582,7 @@ All ${results.length} accounts pinged successfully`);
558
582
  );
559
583
  }
560
584
  }
561
- return 0;
585
+ return { exitCode: 0, failedHandles: [] };
562
586
  }
563
587
  var init_run_ping = __esm({
564
588
  "src/run-ping.ts"() {
@@ -716,13 +740,26 @@ async function daemonLoop(intervalMs, options, deps) {
716
740
  deps.log(
717
741
  `[${(/* @__PURE__ */ new Date()).toISOString()}] Pinging ${accounts.length} account(s)...`
718
742
  );
719
- await deps.runPing(accounts, {
743
+ const pingOpts = {
720
744
  parallel: false,
721
745
  quiet: options.quiet ?? true,
722
746
  bell: options.bell,
723
747
  notify: options.notify,
724
748
  wakeDelayMs
725
- });
749
+ };
750
+ const { failedHandles } = await deps.runPing(accounts, pingOpts);
751
+ if (failedHandles.length > 0 && !deps.shouldStop()) {
752
+ const retryAccounts = accounts.filter(
753
+ (a) => failedHandles.includes(a.handle)
754
+ );
755
+ if (retryAccounts.length > 0) {
756
+ deps.log(`Retrying ${retryAccounts.length} account(s)...`);
757
+ const retry = await deps.runPing(retryAccounts, pingOpts);
758
+ if (retry.failedHandles.length > 0) {
759
+ deps.log(`Retry failed for: ${retry.failedHandles.join(", ")}`);
760
+ }
761
+ }
762
+ }
726
763
  deps.updateState?.({ lastPingAt: (/* @__PURE__ */ new Date()).toISOString() });
727
764
  }
728
765
  if (deps.shouldStop()) break;
@@ -889,7 +926,7 @@ var init_daemon = __esm({
889
926
  init_paths();
890
927
  init_state();
891
928
  GRACEFUL_POLL_MS = 500;
892
- GRACEFUL_POLL_ATTEMPTS = 20;
929
+ GRACEFUL_POLL_ATTEMPTS = 120;
893
930
  POST_KILL_DELAY_MS = 1e3;
894
931
  }
895
932
  });
@@ -1691,7 +1728,7 @@ function suggestAccount(accounts, now = /* @__PURE__ */ new Date()) {
1691
1728
  }
1692
1729
 
1693
1730
  // src/cli.ts
1694
- var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.3.1").option(
1731
+ var program = new Command().name("cc-ping").description("Ping Claude Code sessions to trigger quota windows early").version("1.3.2").option(
1695
1732
  "--config <path>",
1696
1733
  "Path to config directory (default: ~/.config/cc-ping, env: CC_PING_CONFIG)"
1697
1734
  ).hook("preAction", (thisCommand) => {
@@ -1724,7 +1761,7 @@ program.command("ping").description("Ping configured accounts to start quota win
1724
1761
  process.exit(0);
1725
1762
  }
1726
1763
  const staggerMs = opts.stagger ? parseStagger(opts.stagger, targets.length) : void 0;
1727
- const exitCode = await runPing(targets, {
1764
+ const { exitCode } = await runPing(targets, {
1728
1765
  parallel: opts.parallel,
1729
1766
  quiet: opts.quiet,
1730
1767
  json: opts.json,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbern/cc-ping",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Ping Claude Code sessions to trigger quota windows early across multiple accounts",
5
5
  "type": "module",
6
6
  "bin": {