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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +3 -7
- package/bin/install.js +0 -1
- package/commit-sha +1 -1
- package/listener/telegram-poller.js +23 -1
- package/notifier/notifier.js +8 -17
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-notification-plugin",
|
|
3
|
-
"version": "1.1.
|
|
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.
|
|
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
package/commit-sha
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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.
|
|
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;
|
package/notifier/notifier.js
CHANGED
|
@@ -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
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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.
|
|
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": {
|