claude-notification-plugin 1.1.49 → 1.1.52
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/commit-sha +1 -1
- package/listener/pty-runner.js +63 -5
- 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.52",
|
|
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/commit-sha
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
0a1e42c292641f978dba9e382f7ff36af09b1ea8
|
package/listener/pty-runner.js
CHANGED
|
@@ -261,28 +261,57 @@ export class PtyRunner extends EventEmitter {
|
|
|
261
261
|
writeLines();
|
|
262
262
|
this.logger.info(`PTY task sent to ${workDir}: ${task.text.slice(0, 100)}`);
|
|
263
263
|
|
|
264
|
-
// Monitor PTY output for fatal errors that prevent task completion
|
|
264
|
+
// Monitor PTY output for fatal errors that prevent task completion.
|
|
265
|
+
// Some patterns (e.g. "auto mode temporarily unavailable") can appear in the
|
|
266
|
+
// Claude CLI status bar while Claude is still actively working. To avoid false
|
|
267
|
+
// positives we require the buffer to stop growing for two consecutive checks
|
|
268
|
+
// before treating the match as a real error.
|
|
265
269
|
const errorPatterns = [
|
|
266
270
|
{ pattern: 'auto mode temporarily unavailable', msg: 'Claude auto mode temporarily unavailable — retry later' },
|
|
267
271
|
{ pattern: 'Session expired', msg: 'Claude session expired' },
|
|
268
272
|
{ pattern: 'Authentication required', msg: 'Claude authentication required' },
|
|
269
273
|
];
|
|
274
|
+
let errorCandidate = null; // { msg, bufLen } — suspected error awaiting confirmation
|
|
275
|
+
let checkedUpTo = 0; // buffer offset already scanned — avoids re-matching the same text
|
|
270
276
|
const errorCheckInterval = setInterval(() => {
|
|
271
277
|
const buf = session._buffer || '';
|
|
272
|
-
|
|
273
|
-
|
|
278
|
+
const bufLen = buf.length;
|
|
279
|
+
|
|
280
|
+
// If we have a candidate from the previous cycle, confirm it
|
|
281
|
+
if (errorCandidate) {
|
|
282
|
+
if (bufLen === errorCandidate.bufLen) {
|
|
283
|
+
// Buffer did not grow — Claude stopped, treat as real error
|
|
274
284
|
clearInterval(errorCheckInterval);
|
|
275
|
-
this.logger.error(`PTY fatal: ${msg} in ${workDir}`);
|
|
285
|
+
this.logger.error(`PTY fatal: ${errorCandidate.msg} in ${workDir}`);
|
|
276
286
|
if (session._pendingId && this.pendingMarkers.has(session._pendingId)) {
|
|
277
287
|
this.pendingMarkers.delete(session._pendingId);
|
|
278
288
|
}
|
|
279
289
|
session.state = 'idle';
|
|
280
290
|
session.currentTask = null;
|
|
281
291
|
this._destroyPty(workDir);
|
|
282
|
-
this.emit('error', workDir, task, msg);
|
|
292
|
+
this.emit('error', workDir, task, errorCandidate.msg);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
// Buffer grew — Claude is still working, false positive
|
|
296
|
+
this.logger.info(`PTY error candidate dismissed (buffer grew) in ${workDir}`);
|
|
297
|
+
errorCandidate = null;
|
|
298
|
+
checkedUpTo = bufLen;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Scan only new buffer content for pattern matches
|
|
303
|
+
if (bufLen <= checkedUpTo) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const fresh = buf.slice(checkedUpTo);
|
|
307
|
+
for (const { pattern, msg } of errorPatterns) {
|
|
308
|
+
if (fresh.includes(pattern)) {
|
|
309
|
+
this.logger.warn(`PTY error candidate detected: "${pattern}" in ${workDir}, waiting to confirm…`);
|
|
310
|
+
errorCandidate = { msg, bufLen };
|
|
283
311
|
return;
|
|
284
312
|
}
|
|
285
313
|
}
|
|
314
|
+
checkedUpTo = bufLen;
|
|
286
315
|
}, 3000);
|
|
287
316
|
|
|
288
317
|
// Clean up error monitor when task completes normally
|
|
@@ -389,15 +418,44 @@ export class PtyRunner extends EventEmitter {
|
|
|
389
418
|
_buffer: '',
|
|
390
419
|
};
|
|
391
420
|
|
|
421
|
+
// Auto-answer permission prompts: track buffer position and cooldown to
|
|
422
|
+
// prevent double-fire when Claude re-renders the same prompt on screen.
|
|
423
|
+
let lastPermissionAnswerAt = 0;
|
|
424
|
+
let lastPermissionAnswerTime = 0;
|
|
425
|
+
const PERMISSION_COOLDOWN_MS = 5000;
|
|
426
|
+
|
|
392
427
|
ptyProcess.onData((data) => {
|
|
393
428
|
session._buffer += data;
|
|
394
429
|
// Keep buffer reasonable size
|
|
395
430
|
if (session._buffer.length > 50000) {
|
|
396
431
|
session._buffer = session._buffer.slice(-25000);
|
|
432
|
+
lastPermissionAnswerAt = Math.max(0, lastPermissionAnswerAt - 25000);
|
|
397
433
|
}
|
|
398
434
|
if (session._logStream) {
|
|
399
435
|
session._logStream.write(data);
|
|
400
436
|
}
|
|
437
|
+
|
|
438
|
+
// Auto-answer interactive permission prompts that appear when
|
|
439
|
+
// "auto mode temporarily unavailable". The prompt looks like:
|
|
440
|
+
// Do you want to proceed?
|
|
441
|
+
// ❯ 1. Yes
|
|
442
|
+
// 2. Yes, and always allow …
|
|
443
|
+
// 3. No
|
|
444
|
+
// We send Enter to approve (cursor ❯ is already on "1. Yes").
|
|
445
|
+
// Cooldown prevents double-fire from screen redraws.
|
|
446
|
+
const now = Date.now();
|
|
447
|
+
if (session.state === 'busy'
|
|
448
|
+
&& session._buffer.length - lastPermissionAnswerAt > 50
|
|
449
|
+
&& now - lastPermissionAnswerTime > PERMISSION_COOLDOWN_MS) {
|
|
450
|
+
const tail = session._buffer.slice(lastPermissionAnswerAt);
|
|
451
|
+
const clean = tail.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '').replace(/\s/g, '');
|
|
452
|
+
if (clean.includes('Doyouwanttoproceed') && clean.includes('1.Yes')) {
|
|
453
|
+
lastPermissionAnswerAt = session._buffer.length;
|
|
454
|
+
lastPermissionAnswerTime = now;
|
|
455
|
+
this.logger.info(`Auto-answering permission prompt in ${session.workDir}`);
|
|
456
|
+
session.pty.write('\r');
|
|
457
|
+
}
|
|
458
|
+
}
|
|
401
459
|
});
|
|
402
460
|
|
|
403
461
|
ptyProcess.onExit(({ exitCode }) => {
|
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.52",
|
|
5
5
|
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|