claude-notification-plugin 1.1.43 → 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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-notification-plugin",
3
- "version": "1.1.43",
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
- b460aaa05a941c411fb010c938655a256ff5ad57
1
+ 0a1e42c292641f978dba9e382f7ff36af09b1ea8
@@ -6,6 +6,9 @@ const COMMANDS = [
6
6
  '/history', '/stop', '/help',
7
7
  ];
8
8
 
9
+ // Telegram bot commands to silently ignore (not tasks, not our commands)
10
+ const IGNORED_COMMANDS = ['/start'];
11
+
9
12
  /**
10
13
  * Parse a Telegram message into a command or task.
11
14
  *
@@ -32,6 +35,11 @@ export function parseMessage (text) {
32
35
  const parts = trimmed.split(/\s+/);
33
36
  const cmd = parts[0].toLowerCase().replace(/@\w+$/, ''); // strip @botname
34
37
 
38
+ // Telegram built-in commands — silently ignore
39
+ if (IGNORED_COMMANDS.includes(cmd)) {
40
+ return null;
41
+ }
42
+
35
43
  // Known command
36
44
  if (COMMANDS.includes(cmd)) {
37
45
  return {
@@ -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
- for (const { pattern, msg } of errorPatterns) {
273
- if (buf.includes(pattern)) {
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);
283
293
  return;
284
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;
285
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 };
311
+ return;
312
+ }
313
+ }
314
+ checkedUpTo = bufLen;
286
315
  }, 3000);
287
316
 
288
317
  // Clean up error monitor when task completes normally
@@ -349,6 +378,17 @@ export class PtyRunner extends EventEmitter {
349
378
  args.push('--permission-mode', 'auto');
350
379
  }
351
380
 
381
+ // Reduce PTY output noise: disable animations, progress bar, tips
382
+ if (!args.includes('--settings')) {
383
+ args.push('--settings', JSON.stringify({
384
+ prefersReducedMotion: true,
385
+ outputStyle: 'plain',
386
+ terminalProgressBarEnabled: false,
387
+ spinnerTipsEnabled: false,
388
+ showTurnDuration: false,
389
+ }));
390
+ }
391
+
352
392
  this.logger.info(`Creating PTY session in ${workDir} with args: ${JSON.stringify(args)}`);
353
393
 
354
394
  const shell = process.platform === 'win32' ? 'cmd.exe' : '/bin/bash';
@@ -378,15 +418,44 @@ export class PtyRunner extends EventEmitter {
378
418
  _buffer: '',
379
419
  };
380
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
+
381
427
  ptyProcess.onData((data) => {
382
428
  session._buffer += data;
383
429
  // Keep buffer reasonable size
384
430
  if (session._buffer.length > 50000) {
385
431
  session._buffer = session._buffer.slice(-25000);
432
+ lastPermissionAnswerAt = Math.max(0, lastPermissionAnswerAt - 25000);
386
433
  }
387
434
  if (session._logStream) {
388
435
  session._logStream.write(data);
389
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
+ }
390
459
  });
391
460
 
392
461
  ptyProcess.onExit(({ exitCode }) => {
@@ -423,14 +492,26 @@ export class PtyRunner extends EventEmitter {
423
492
 
424
493
  /**
425
494
  * Wait for PTY output to stabilize (Claude has loaded).
495
+ * Automatically answers the workspace trust prompt if it appears.
426
496
  */
427
497
  _waitForReady (session, timeoutMs) {
428
498
  return new Promise((resolve) => {
429
499
  let lastLength = 0;
430
500
  let stableCount = 0;
501
+ let trustAnswered = false;
431
502
  const checkInterval = 500;
432
503
 
433
504
  const timer = setInterval(() => {
505
+ // Detect and auto-answer workspace trust prompt
506
+ if (!trustAnswered) {
507
+ const buf = (session._buffer || '').replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '').replace(/\s/g, '');
508
+ if (buf.includes('trustthisfolder') || buf.includes('Yesiproceed')) {
509
+ trustAnswered = true;
510
+ this.logger.info('Auto-answering workspace trust prompt');
511
+ session.pty.write('\r');
512
+ }
513
+ }
514
+
434
515
  const currentLength = session._buffer.length;
435
516
  if (currentLength > 0 && currentLength === lastLength) {
436
517
  stableCount++;
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.43",
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": {