claude-notification-plugin 1.0.107 → 1.0.108

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-notification-plugin",
3
- "version": "1.0.107",
3
+ "version": "1.0.108",
4
4
  "description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
5
5
  "author": {
6
6
  "name": "Viacheslav Makarov",
package/bin/install.js CHANGED
@@ -19,6 +19,112 @@ const installedPluginsPath = path.join(pluginsDir, 'installed_plugins.json');
19
19
  const knownMarketplacesPath = path.join(pluginsDir, 'known_marketplaces.json');
20
20
  const marketplacesDir = path.join(pluginsDir, 'marketplaces');
21
21
  const RESOLVER_PATH = path.join(claudeDir, 'claude-notify-resolve.js');
22
+ const pidFile = path.join(claudeDir, '.listener.pid');
23
+ const installLogPath = path.join(claudeDir, 'install.log');
24
+
25
+ // ──────────────────────────────────────
26
+ // Logging to file
27
+ // ──────────────────────────────────────
28
+
29
+ let logStream;
30
+
31
+ function initLog () {
32
+ fs.mkdirSync(claudeDir, { recursive: true });
33
+ logStream = fs.createWriteStream(installLogPath, { flags: 'w' });
34
+ const origLog = console.log.bind(console);
35
+ const origWarn = console.warn.bind(console);
36
+ const stamp = () => new Date().toISOString();
37
+
38
+ console.log = (...args) => {
39
+ origLog(...args);
40
+ const line = args.map(String).join(' ').replace(/\x1b\[[0-9;]*m/g, '');
41
+ logStream.write(`[${stamp()}] ${line}\n`);
42
+ };
43
+
44
+ console.warn = (...args) => {
45
+ origWarn(...args);
46
+ const line = args.map(String).join(' ').replace(/\x1b\[[0-9;]*m/g, '');
47
+ logStream.write(`[${stamp()}] WARN: ${line}\n`);
48
+ };
49
+ }
50
+
51
+ function closeLog () {
52
+ if (logStream) {
53
+ logStream.end();
54
+ }
55
+ }
56
+
57
+ // ──────────────────────────────────────
58
+ // Stop listener before reinstall
59
+ // ──────────────────────────────────────
60
+
61
+ function isProcessAlive (pid) {
62
+ if (!Number.isInteger(pid) || pid <= 0) {
63
+ return false;
64
+ }
65
+ try {
66
+ if (process.platform === 'win32') {
67
+ const result = execSync(`tasklist /FI "PID eq ${pid}" /NH`, {
68
+ encoding: 'utf-8',
69
+ windowsHide: true,
70
+ stdio: ['pipe', 'pipe', 'ignore'],
71
+ });
72
+ return result.includes(String(pid));
73
+ }
74
+ process.kill(pid, 0);
75
+ return true;
76
+ } catch {
77
+ return false;
78
+ }
79
+ }
80
+
81
+ function killProcessTree (pid) {
82
+ if (!isProcessAlive(pid)) {
83
+ return false;
84
+ }
85
+ try {
86
+ if (process.platform === 'win32') {
87
+ execSync(`taskkill /PID ${pid} /T /F`, { stdio: 'ignore', windowsHide: true });
88
+ console.log(` Listener process ${pid} killed`);
89
+ return true;
90
+ }
91
+ process.kill(pid, 'SIGTERM');
92
+ let tries = 10;
93
+ while (tries-- > 0 && isProcessAlive(pid)) {
94
+ execSync('sleep 0.2', { stdio: 'ignore' });
95
+ }
96
+ if (isProcessAlive(pid)) {
97
+ process.kill(pid, 'SIGKILL');
98
+ }
99
+ console.log(` Listener process ${pid} killed`);
100
+ return true;
101
+ } catch {
102
+ return false;
103
+ }
104
+ }
105
+
106
+ function stopListenerIfRunning () {
107
+ let stopped = false;
108
+ const pidFromFile = (() => {
109
+ try {
110
+ if (!fs.existsSync(pidFile)) return null;
111
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
112
+ return Number.isInteger(pid) && pid > 0 ? pid : null;
113
+ } catch { return null; }
114
+ })();
115
+
116
+ if (pidFromFile && killProcessTree(pidFromFile)) {
117
+ stopped = true;
118
+ }
119
+
120
+ try {
121
+ if (fs.existsSync(pidFile)) {
122
+ fs.unlinkSync(pidFile);
123
+ }
124
+ } catch { /* ignore */ }
125
+
126
+ return stopped;
127
+ }
22
128
 
23
129
  const HOOK_COMMAND = 'claude-notify';
24
130
  const MARKETPLACE_KEY = 'bazilio-plugins';
@@ -313,6 +419,11 @@ function addHook (settings, event) {
313
419
  // ──────────────────────────────────────
314
420
 
315
421
  async function main () {
422
+ initLog();
423
+
424
+ // 0. Stop listener if running (before overwriting files)
425
+ const listenerWasStopped = stopListenerIfRunning();
426
+
316
427
  // 1. Register plugin in Claude Code
317
428
  const version = getVersion();
318
429
 
@@ -514,9 +625,11 @@ Send any message to your bot in Telegram, then press Enter.\x1b[0m`);
514
625
  sudo apt install espeak`;
515
626
  }
516
627
 
628
+ const listenerLine = listenerWasStopped ? '\nListener was stopped (restart manually if needed).' : '';
629
+
517
630
  console.log(`
518
631
  Installed!
519
-
632
+ ${listenerLine}
520
633
  Hooks registered:
521
634
  - UserPromptSubmit (start timer)
522
635
  - Stop (task finished)
@@ -525,9 +638,13 @@ Hooks registered:
525
638
  Config: ${configPath}
526
639
  ${telegramStatus}${platformTip}
527
640
 
641
+ Log: ${installLogPath}
642
+
528
643
  To uninstall: claude-notify uninstall
529
644
 
530
645
  To disable per project, add to .claude/settings.local.json: { "env": { "CLAUDE_NOTIFY_DISABLE": "1" } }`);
646
+
647
+ closeLog();
531
648
  }
532
649
 
533
650
  main().then(() => 0);
package/commit-sha CHANGED
@@ -1 +1 @@
1
- c5e25e27c544bccfb19bcac820c751c4279d3a2e
1
+ 4d9fe96446b31d55ec608eac82a50aaeb12e59b1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-notification-plugin",
3
3
  "productName": "claude-notification-plugin",
4
- "version": "1.0.107",
4
+ "version": "1.0.108",
5
5
  "description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
6
6
  "type": "module",
7
7
  "engines": {