opencode-interrupt-plugin 0.4.1 → 0.4.4

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.
@@ -13,6 +13,7 @@ export class AudioMonitor extends EventEmitter {
13
13
  start() {
14
14
  if (this.isRunning)
15
15
  return;
16
+ console.log('[interrupt-monitor] Starting audio monitor');
16
17
  this.isRunning = true;
17
18
  this.emit('started');
18
19
  this.poll();
@@ -28,18 +29,26 @@ export class AudioMonitor extends EventEmitter {
28
29
  ], { stdio: ['ignore', 'ignore', 'pipe'] });
29
30
  let out = '';
30
31
  proc.stderr?.on('data', (d) => { out += d.toString(); });
31
- proc.on('exit', () => {
32
+ proc.on('exit', (code) => {
32
33
  if (!this.isRunning)
33
34
  return;
35
+ if (code !== 0) {
36
+ console.log(`[interrupt-monitor] sox exited with code ${code}`);
37
+ }
34
38
  const rms = parseRMSFromStat(out);
35
39
  if (rms !== null) {
40
+ console.log(`[interrupt-monitor] RMS: ${rms.toFixed(6)} (threshold: ${this.threshold})`);
36
41
  this.handleRMS(rms);
37
42
  }
43
+ else {
44
+ console.log(`[interrupt-monitor] Failed to parse RMS from stderr (${out.length} chars)`);
45
+ }
38
46
  this.pollTimer = setTimeout(() => this.poll(), this.pollMs);
39
47
  });
40
- proc.on('error', () => {
48
+ proc.on('error', (err) => {
41
49
  if (!this.isRunning)
42
50
  return;
51
+ console.log(`[interrupt-monitor] sox spawn error: ${err.message}`);
43
52
  this.emit('error', new Error('sox not found. Install it: brew install sox (macOS) or apt install sox (Linux)'));
44
53
  this.isRunning = false;
45
54
  });
@@ -65,7 +74,7 @@ export class AudioMonitor extends EventEmitter {
65
74
  }
66
75
  }
67
76
  function parseRMSLine(line) {
68
- const match = line.match(/RMS amplitude:\s+([\d.]+)/);
77
+ const match = line.match(/RMS\s+amplitude:\s+([\d.]+)/);
69
78
  if (match)
70
79
  return parseFloat(match[1]);
71
80
  return null;
@@ -35,13 +35,19 @@ export class VoiceOverlapDetector extends EventEmitter {
35
35
  this.monitor.setThreshold(threshold);
36
36
  }
37
37
  handleVoiceDetected(rms) {
38
- if (!this.getIsTTSPlaying())
38
+ const ttsPlaying = this.getIsTTSPlaying();
39
+ if (!ttsPlaying) {
40
+ console.log(`[interrupt-overlap] Voice detected (RMS=${rms.toFixed(6)}) but TTS not playing, ignoring`);
39
41
  return;
40
- if (Date.now() < this.cooldownUntil)
42
+ }
43
+ if (Date.now() < this.cooldownUntil) {
44
+ console.log(`[interrupt-overlap] In cooldown (${this.cooldownUntil - Date.now()}ms remaining), ignoring`);
41
45
  return;
46
+ }
42
47
  const now = Date.now();
43
48
  this.cooldownUntil = now + this.COOLDOWN_MS;
44
49
  const partialContent = this.getPartialContent();
50
+ console.log(`[interrupt-overlap] OVERLAP! RMS=${rms.toFixed(6)}, stopping TTS, partial=${partialContent.slice(0, 80)}`);
45
51
  this.stopTTS();
46
52
  const event = {
47
53
  partialTTSContent: partialContent,
package/dist/index.js CHANGED
@@ -49,11 +49,11 @@ export const InterruptPlugin = (userConfig = {}) => {
49
49
  onTTSEnd();
50
50
  }, () => ttsStreamer.getPartialContent());
51
51
  overlapDetector.on('voice-overlap', (event) => {
52
- if (!activeSessionId)
52
+ if (!activeSessionId) {
53
+ console.log(`[interrupt] Voice overlap event but no active session, ignoring`);
53
54
  return;
54
- if (config.debug) {
55
- console.log(`[interrupt] Voice overlap detected (RMS: ${event.rmsLevel.toFixed(4)})`);
56
55
  }
56
+ console.log(`[interrupt] Voice overlap detected (RMS: ${event.rmsLevel.toFixed(4)})`);
57
57
  updateSessionState(activeSessionId, {
58
58
  wasInterrupted: true,
59
59
  partialContentAtInterrupt: event.partialTTSContent,
@@ -78,6 +78,7 @@ export class TTSEngine extends EventEmitter {
78
78
  });
79
79
  }
80
80
  stop() {
81
+ console.log(`[interrupt-engine] stop() called, playing=${this.playing}`);
81
82
  if (this.generator) {
82
83
  this.generator.kill("SIGTERM");
83
84
  this.generator = null;
package/dist/tts/index.js CHANGED
@@ -104,6 +104,7 @@ export class TTSStreamer extends EventEmitter {
104
104
  }
105
105
  }
106
106
  stop() {
107
+ console.log(`[interrupt-tts] stop() called, playing=${this.engine.isPlaying}, queue=${this.queue.length}, processing=${this.processing}`);
107
108
  this.stopped = true;
108
109
  this.queue = [];
109
110
  this.engine.stop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-interrupt-plugin",
3
- "version": "0.4.1",
3
+ "version": "0.4.4",
4
4
  "description": "Streaming TTS + voice interruption for OpenCode. Speaks responses as they arrive and detects when you talk over it.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",