claude-notification-plugin 1.1.32 → 1.1.35

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.1.32",
3
+ "version": "1.1.35",
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/README.md CHANGED
@@ -75,20 +75,20 @@ Config file: `~/.claude/claude-notify.config.json`
75
75
  "enabled": true
76
76
  },
77
77
  "webhookUrl": "",
78
- "sendUserPromptToWebhook": false,
79
78
  "notifyAfterSeconds": 15,
80
79
  "notifyOnWaiting": false,
81
80
  "debug": false,
82
81
  "listener": {
82
+ "claudeArgs": ["--permission-mode", "auto"],
83
83
  "projects": {
84
84
  "default": {
85
85
  "path": "abs-path-to-project"
86
+ "claudeArgs": ["--permission-mode", "bypassPermissions"]
86
87
  },
87
88
  "alias1": {
88
89
  "path": "abs-path-to-project"
89
90
  }
90
91
  },
91
- "claudeArgs": ["--permission-mode", "auto"],
92
92
  "continueSession": true,
93
93
  "worktreeBaseDir": "abs-path-to-worktrees-root",
94
94
  "autoCreateWorktree": true,
@@ -131,12 +131,9 @@ ENV: `CLAUDE_NOTIFY_VOICE`
131
131
  **notifyOnWaiting** — Notify when Claude is waiting for input. Default: **false**
132
132
  ENV: `CLAUDE_NOTIFY_WAITING`
133
133
 
134
- **webhookUrl** — POST notification JSON to this URL. Payload: `title`, `project`, `branch`, `duration`, `trigger`, `voicePhrase`, `hookEvent`.
134
+ **webhookUrl** — POST notification JSON to this URL. When set, all events (including user prompts) are sent. Set env to empty string (`""`) to disable per-project.
135
135
  ENV: `CLAUDE_NOTIFY_WEBHOOK_URL`
136
136
 
137
- **sendUserPromptToWebhook** — Also send user prompts to the webhook. Requires `webhookUrl`. Default: **false**
138
- ENV: `CLAUDE_NOTIFY_SEND_USER_PROMPT_TO_WEBHOOK`
139
-
140
137
  **notifyAfterSeconds** — Skip notifications for tasks shorter than this. Default: **15**
141
138
  ENV: `CLAUDE_NOTIFY_AFTER_SECONDS`
142
139
 
@@ -163,7 +160,6 @@ Add to `.claude/settings.local.json` in the project root:
163
160
  "CLAUDE_NOTIFY_DEBUG": 0,
164
161
  "CLAUDE_NOTIFY_INCLUDE_LAST_CC_MESSAGE_IN_TELEGRAM": 1,
165
162
  "CLAUDE_NOTIFY_WEBHOOK_URL": "",
166
- "CLAUDE_NOTIFY_SEND_USER_PROMPT_TO_WEBHOOK": 0,
167
163
  "CLAUDE_NOTIFY_AFTER_SECONDS": 15
168
164
  }
169
165
  }
package/bin/install.js CHANGED
@@ -617,7 +617,6 @@ Send any message to your bot in Telegram, then press Enter.\x1b[0m`);
617
617
  enabled: true,
618
618
  },
619
619
  webhookUrl: '',
620
- sendUserPromptToWebhook: false,
621
620
  notifyAfterSeconds: 15,
622
621
  notifyOnWaiting: false,
623
622
  debug: false,
package/commit-sha CHANGED
@@ -1 +1 @@
1
- b65d01cebc9e993e0a3808bcd3715fde0acfa7b4
1
+ 0c61ed57e3d709a6379f00009d55d8f6093f1cbc
@@ -10,6 +10,8 @@ export class TelegramPoller {
10
10
  this.logger = logger;
11
11
  this.baseUrl = `https://api.telegram.org/bot${token}`;
12
12
  this.offset = 0;
13
+ this._errorBackoff = 0; // current backoff in ms (0 = no backoff)
14
+ this._consecutiveErrors = 0;
13
15
  }
14
16
 
15
17
  async flush () {
@@ -26,14 +28,27 @@ export class TelegramPoller {
26
28
  }
27
29
 
28
30
  async getUpdates () {
31
+ // Apply backoff delay if we've had consecutive errors
32
+ if (this._errorBackoff > 0) {
33
+ await new Promise((resolve) => setTimeout(resolve, this._errorBackoff));
34
+ }
35
+
29
36
  try {
30
37
  const url = `${this.baseUrl}/getUpdates?offset=${this.offset}&timeout=${POLL_TIMEOUT}&allowed_updates=["message"]`;
31
38
  const res = await fetch(url, { signal: AbortSignal.timeout((POLL_TIMEOUT + 10) * 1000) });
32
39
  const data = await res.json();
33
40
  if (!data.ok) {
34
41
  this.logger.error(`getUpdates failed: ${JSON.stringify(data)}`);
42
+ this._applyBackoff();
35
43
  return [];
36
44
  }
45
+ // Success — reset backoff
46
+ if (this._consecutiveErrors > 0) {
47
+ this.logger.info('getUpdates recovered after errors');
48
+ }
49
+ this._consecutiveErrors = 0;
50
+ this._errorBackoff = 0;
51
+
37
52
  const messages = [];
38
53
  for (const update of data.result || []) {
39
54
  this.offset = update.update_id + 1;
@@ -55,12 +70,19 @@ export class TelegramPoller {
55
70
  return messages;
56
71
  } catch (err) {
57
72
  if (err.name !== 'TimeoutError' && err.name !== 'AbortError') {
58
- this.logger.error(`getUpdates error: ${err.message}`);
73
+ this._applyBackoff();
74
+ this.logger.error(`getUpdates error: ${err.message} (retry in ${Math.round(this._errorBackoff / 1000)}s)`);
59
75
  }
60
76
  return [];
61
77
  }
62
78
  }
63
79
 
80
+ _applyBackoff () {
81
+ this._consecutiveErrors++;
82
+ // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s (max)
83
+ this._errorBackoff = Math.min(1000 * Math.pow(2, this._consecutiveErrors - 1), 30000);
84
+ }
85
+
64
86
  async sendMessage (text, replyToMessageId) {
65
87
  const chunks = splitMessage(text);
66
88
  let firstMessageId = null;
@@ -61,7 +61,6 @@ function loadConfig () {
61
61
  enabled: true,
62
62
  },
63
63
  webhookUrl: '',
64
- sendUserPromptToWebhook: false,
65
64
  notifyAfterSeconds: 15,
66
65
  notifyOnWaiting: false,
67
66
  debug: false,
@@ -95,9 +94,6 @@ function loadConfig () {
95
94
  if (typeof user.webhookUrl === 'string') {
96
95
  config.webhookUrl = user.webhookUrl;
97
96
  }
98
- if (typeof user.sendUserPromptToWebhook === 'boolean') {
99
- config.sendUserPromptToWebhook = user.sendUserPromptToWebhook;
100
- }
101
97
  } catch {
102
98
  // ignore malformed config
103
99
  }
@@ -132,12 +128,9 @@ function loadConfig () {
132
128
  if (process.env.CLAUDE_NOTIFY_INCLUDE_LAST_CC_MESSAGE_IN_TELEGRAM !== undefined) {
133
129
  config.telegram.includeLastCcMessageInTelegram = process.env.CLAUDE_NOTIFY_INCLUDE_LAST_CC_MESSAGE_IN_TELEGRAM === '1';
134
130
  }
135
- if (process.env.CLAUDE_NOTIFY_WEBHOOK_URL) {
131
+ if (process.env.CLAUDE_NOTIFY_WEBHOOK_URL !== undefined) {
136
132
  config.webhookUrl = process.env.CLAUDE_NOTIFY_WEBHOOK_URL;
137
133
  }
138
- if (process.env.CLAUDE_NOTIFY_SEND_USER_PROMPT_TO_WEBHOOK !== undefined) {
139
- config.sendUserPromptToWebhook = process.env.CLAUDE_NOTIFY_SEND_USER_PROMPT_TO_WEBHOOK === '1';
140
- }
141
134
  if (process.env.CLAUDE_NOTIFY_AFTER_SECONDS !== undefined) {
142
135
  const val = Number(process.env.CLAUDE_NOTIFY_AFTER_SECONDS);
143
136
  if (!Number.isNaN(val)) {
@@ -684,15 +677,13 @@ process.stdin.on('end', async () => {
684
677
  if (eventType === 'UserPromptSubmit') {
685
678
  state.sessions[sessionId] = { start: Date.now() };
686
679
  saveState(state);
687
- if (config.sendUserPromptToWebhook) {
688
- await sendWebhook(config, {
689
- title: 'User prompt submitted',
690
- project,
691
- trigger: eventType,
692
- prompt: event.prompt || '',
693
- hookEvent: event,
694
- });
695
- }
680
+ await sendWebhook(config, {
681
+ title: 'User prompt submitted',
682
+ project,
683
+ trigger: eventType,
684
+ prompt: event.prompt || '',
685
+ hookEvent: event,
686
+ });
696
687
  process.exit(0);
697
688
  }
698
689
 
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.1.32",
4
+ "version": "1.1.35",
5
5
  "description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
6
6
  "type": "module",
7
7
  "engines": {