opencode-smart-voice-notify 1.1.1 → 1.1.2

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/README.md CHANGED
@@ -96,86 +96,153 @@ The auto-generated configuration includes all advanced settings, message arrays,
96
96
 
97
97
  If you prefer to create the config manually, add a `smart-voice-notify.jsonc` file in your OpenCode config directory (`~/.config/opencode/`):
98
98
 
99
- ```jsonc
100
- {
101
- // ============================================================
102
- // NOTIFICATION MODE SETTINGS (Smart Notification System)
103
- // ============================================================
104
- // Controls how notifications are delivered:
105
- // 'sound-first' - Play sound immediately, TTS reminder after delay (RECOMMENDED)
106
- // 'tts-first' - Speak TTS immediately, no sound
107
- // 'both' - Play sound AND speak TTS immediately
108
- // 'sound-only' - Only play sound, no TTS at all
109
- "notificationMode": "sound-first",
110
-
111
- // ============================================================
112
- // TTS REMINDER SETTINGS (When user doesn't respond to sound)
113
- // ============================================================
114
-
115
- // Enable TTS reminder if user doesn't respond after sound notification
116
- "enableTTSReminder": true,
117
-
118
- // Delay (in seconds) before TTS reminder fires
119
- "ttsReminderDelaySeconds": 30, // Global default
120
- "idleReminderDelaySeconds": 30, // For task completion notifications
121
- "permissionReminderDelaySeconds": 20, // For permission requests (more urgent)
122
-
99
+ ```jsonc
100
+ {
101
+ // ============================================================
102
+ // OpenCode Smart Voice Notify - Full Configuration Reference
103
+ // ============================================================
104
+ //
105
+ // IMPORTANT: This is a REFERENCE file showing ALL available options.
106
+ //
107
+ // To use this plugin:
108
+ // 1. Copy this file to: ~/.config/opencode/smart-voice-notify.jsonc
109
+ // (On Windows: C:\Users\<YourUser>\.config\opencode\smart-voice-notify.jsonc)
110
+ // 2. Customize the settings below to your preference
111
+ // 3. The plugin auto-creates a minimal config if none exists
112
+ //
113
+ // Sound files are automatically copied to ~/.config/opencode/assets/
114
+ // on first run. You can also use your own custom sound files.
115
+ //
116
+ // ============================================================
117
+
118
+ // ============================================================
119
+ // NOTIFICATION MODE SETTINGS (Smart Notification System)
120
+ // ============================================================
121
+ // Controls how notifications are delivered:
122
+ // 'sound-first' - Play sound immediately, TTS reminder after delay (RECOMMENDED)
123
+ // 'tts-first' - Speak TTS immediately, no sound
124
+ // 'both' - Play sound AND speak TTS immediately
125
+ // 'sound-only' - Only play sound, no TTS at all
126
+ "notificationMode": "sound-first",
127
+
128
+ // ============================================================
129
+ // TTS REMINDER SETTINGS (When user doesn't respond to sound)
130
+ // ============================================================
131
+
132
+ // Enable TTS reminder if user doesn't respond after sound notification
133
+ "enableTTSReminder": true,
134
+
135
+ // Delay (in seconds) before TTS reminder fires
136
+ // Set globally or per-notification type
137
+ "ttsReminderDelaySeconds": 30, // Global default
138
+ "idleReminderDelaySeconds": 30, // For task completion notifications
139
+ "permissionReminderDelaySeconds": 20, // For permission requests (more urgent)
140
+
123
141
  // Follow-up reminders if user STILL doesn't respond after first TTS
124
142
  "enableFollowUpReminders": true,
125
143
  "maxFollowUpReminders": 3, // Max number of follow-up TTS reminders
126
144
  "reminderBackoffMultiplier": 1.5, // Each follow-up waits longer (30s, 45s, 67s...)
127
-
145
+
128
146
  // ============================================================
129
147
  // PERMISSION BATCHING (Multiple permissions at once)
130
148
  // ============================================================
131
- // When multiple permissions arrive simultaneously, batch them into one notification
132
- "permissionBatchWindowMs": 800, // Batch window in milliseconds
133
-
149
+ // When multiple permissions arrive simultaneously (e.g., 5 at once),
150
+ // batch them into a single notification instead of playing 5 overlapping sounds.
151
+ // The notification will say "X permission requests require your attention".
152
+
153
+ // Batch window (ms) - how long to wait for more permissions before notifying
154
+ "permissionBatchWindowMs": 800,
155
+
134
156
  // ============================================================
135
157
  // TTS ENGINE SELECTION
136
158
  // ============================================================
137
- // 'elevenlabs' - Best quality, anime-like voices (requires API key)
159
+ // 'elevenlabs' - Best quality, anime-like voices (requires API key, free tier: 10k chars/month)
138
160
  // 'edge' - Good quality neural voices (Free, Native Node.js implementation)
139
- // 'sapi' - Windows built-in voices (free, offline)
140
- "ttsEngine": "edge",
161
+ // 'sapi' - Windows built-in voices (free, offline, robotic)
162
+ "ttsEngine": "elevenlabs",
163
+
164
+ // Enable TTS for notifications (falls back to sound files if TTS fails)
141
165
  "enableTTS": true,
142
-
143
- // ============================================================
144
- // ELEVENLABS SETTINGS (Best Quality - Anime-like Voices)
145
- // ============================================================
146
- // Get your API key from: https://elevenlabs.io/app/settings/api-keys
147
- // "elevenLabsApiKey": "YOUR_API_KEY_HERE",
148
- "elevenLabsVoiceId": "cgSgspJ2msm6clMCkdW9",
149
- "elevenLabsModel": "eleven_turbo_v2_5",
150
- "elevenLabsStability": 0.5,
151
- "elevenLabsSimilarity": 0.75,
152
- "elevenLabsStyle": 0.5,
153
-
154
- // ============================================================
155
- // EDGE TTS SETTINGS (Free Neural Voices - Default Engine)
156
- // ============================================================
157
- "edgeVoice": "en-US-AnaNeural",
158
- "edgePitch": "+50Hz",
159
- "edgeRate": "+10%",
160
-
161
- // ============================================================
162
- // SAPI SETTINGS (Windows Built-in - Last Resort Fallback)
163
- // ============================================================
164
- "sapiVoice": "Microsoft Zira Desktop",
165
- "sapiRate": -1,
166
- "sapiPitch": "medium",
167
- "sapiVolume": "loud",
168
-
169
- // ============================================================
170
- // INITIAL TTS MESSAGES (Used immediately or after sound)
171
- // ============================================================
172
- "idleTTSMessages": [
173
- "All done! Your task has been completed successfully.",
174
- "Hey there! I finished working on your request.",
175
- "Task complete! Ready for your review whenever you are.",
176
- "Good news! Everything is done and ready for you.",
177
- "Finished! Let me know if you need anything else."
178
- ],
166
+
167
+ // ============================================================
168
+ // ELEVENLABS SETTINGS (Best Quality - Anime-like Voices)
169
+ // ============================================================
170
+ // Get your API key from: https://elevenlabs.io/app/settings/api-keys
171
+ // Free tier: 10,000 characters/month
172
+ "elevenLabsApiKey": "YOUR_API_KEY_HERE",
173
+
174
+ // Voice ID - Recommended cute/anime-like voices:
175
+ // 'cgSgspJ2msm6clMCkdW9' - Jessica (Playful, Bright, Warm) - RECOMMENDED
176
+ // 'FGY2WhTYpPnrIDTdsKH5' - Laura (Enthusiast, Quirky)
177
+ // 'jsCqWAovK2LkecY7zXl4' - Freya (Expressive, Confident)
178
+ // 'EXAVITQu4vr4xnSDxMaL' - Sarah (Soft, Warm)
179
+ // Browse more at: https://elevenlabs.io/voice-library
180
+ "elevenLabsVoiceId": "cgSgspJ2msm6clMCkdW9",
181
+
182
+ // Model: 'eleven_turbo_v2_5' (fast, good), 'eleven_multilingual_v2' (highest quality)
183
+ "elevenLabsModel": "eleven_turbo_v2_5",
184
+
185
+ // Voice tuning (0.0 to 1.0)
186
+ "elevenLabsStability": 0.5, // Lower = more expressive, Higher = more consistent
187
+ "elevenLabsSimilarity": 0.75, // How closely to match the original voice
188
+ "elevenLabsStyle": 0.5, // Style exaggeration (higher = more expressive)
189
+
190
+ // ============================================================
191
+ // EDGE TTS SETTINGS (Free Neural Voices - Fallback)
192
+ // ============================================================
193
+ // Native Node.js implementation (No external dependencies)
194
+
195
+ // Voice options (run 'edge-tts --list-voices' to see all):
196
+ // 'en-US-AnaNeural' - Young, cute, cartoon-like (RECOMMENDED)
197
+ // 'en-US-JennyNeural' - Friendly, warm
198
+ // 'en-US-AriaNeural' - Confident, clear
199
+ // 'en-GB-SoniaNeural' - British, friendly
200
+ // 'en-AU-NatashaNeural' - Australian, warm
201
+ "edgeVoice": "en-US-AnaNeural",
202
+
203
+ // Pitch adjustment: +0Hz to +100Hz (higher = more anime-like)
204
+ "edgePitch": "+50Hz",
205
+
206
+ // Speech rate: -50% to +100%
207
+ "edgeRate": "+10%",
208
+
209
+ // ============================================================
210
+ // SAPI SETTINGS (Windows Built-in - Last Resort Fallback)
211
+ // ============================================================
212
+
213
+ // Voice (run PowerShell to list all installed voices):
214
+ // Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).GetInstalledVoices() | % { $_.VoiceInfo.Name }
215
+ //
216
+ // Common Windows voices:
217
+ // 'Microsoft Zira Desktop' - Female, US English
218
+ // 'Microsoft David Desktop' - Male, US English
219
+ // 'Microsoft Hazel Desktop' - Female, UK English
220
+ "sapiVoice": "Microsoft Zira Desktop",
221
+
222
+ // Speech rate: -10 (slowest) to +10 (fastest), 0 is normal
223
+ "sapiRate": -1,
224
+
225
+ // Pitch: 'x-low', 'low', 'medium', 'high', 'x-high'
226
+ "sapiPitch": "medium",
227
+
228
+ // Volume: 'silent', 'x-soft', 'soft', 'medium', 'loud', 'x-loud'
229
+ "sapiVolume": "loud",
230
+
231
+ // ============================================================
232
+ // INITIAL TTS MESSAGES (Used immediately or after sound)
233
+ // These are randomly selected each time for variety
234
+ // ============================================================
235
+
236
+ // Messages when agent finishes work (task completion)
237
+ "idleTTSMessages": [
238
+ "All done! Your task has been completed successfully.",
239
+ "Hey there! I finished working on your request.",
240
+ "Task complete! Ready for your review whenever you are.",
241
+ "Good news! Everything is done and ready for you.",
242
+ "Finished! Let me know if you need anything else."
243
+ ],
244
+
245
+ // Messages for permission requests
179
246
  "permissionTTSMessages": [
180
247
  "Attention please! I need your permission to continue.",
181
248
  "Hey! Quick approval needed to proceed with the task.",
@@ -183,22 +250,32 @@ If you prefer to create the config manually, add a `smart-voice-notify.jsonc` fi
183
250
  "Excuse me! I need your authorization before I can continue.",
184
251
  "Permission required! Please review and approve when ready."
185
252
  ],
253
+
186
254
  // Messages for MULTIPLE permission requests (use {count} placeholder)
255
+ // Used when several permissions arrive simultaneously
187
256
  "permissionTTSMessagesMultiple": [
188
257
  "Attention please! There are {count} permission requests waiting for your approval.",
189
- "Hey! {count} permissions need your approval to continue."
258
+ "Hey! {count} permissions need your approval to continue.",
259
+ "Heads up! You have {count} pending permission requests.",
260
+ "Excuse me! I need your authorization for {count} different actions.",
261
+ "{count} permissions required! Please review and approve when ready."
190
262
  ],
191
-
192
- // ============================================================
193
- // TTS REMINDER MESSAGES (Used after delay if no response)
194
- // ============================================================
195
- "idleReminderTTSMessages": [
196
- "Hey, are you still there? Your task has been waiting for review.",
197
- "Just a gentle reminder - I finished your request a while ago!",
198
- "Hello? I completed your task. Please take a look when you can.",
199
- "Still waiting for you! The work is done and ready for review.",
200
- "Knock knock! Your completed task is patiently waiting for you."
201
- ],
263
+
264
+ // ============================================================
265
+ // TTS REMINDER MESSAGES (More urgent - used after delay if no response)
266
+ // These are more personalized and urgent to get user attention
267
+ // ============================================================
268
+
269
+ // Reminder messages when agent finished but user hasn't responded
270
+ "idleReminderTTSMessages": [
271
+ "Hey, are you still there? Your task has been waiting for review.",
272
+ "Just a gentle reminder - I finished your request a while ago!",
273
+ "Hello? I completed your task. Please take a look when you can.",
274
+ "Still waiting for you! The work is done and ready for review.",
275
+ "Knock knock! Your completed task is patiently waiting for you."
276
+ ],
277
+
278
+ // Reminder messages when permission still needed
202
279
  "permissionReminderTTSMessages": [
203
280
  "Hey! I still need your permission to continue. Please respond!",
204
281
  "Reminder: There is a pending permission request. I cannot proceed without you.",
@@ -206,30 +283,105 @@ If you prefer to create the config manually, add a `smart-voice-notify.jsonc` fi
206
283
  "Please check your screen! I really need your permission to move forward.",
207
284
  "Still waiting for authorization! The task is on hold until you respond."
208
285
  ],
286
+
209
287
  // Reminder messages for MULTIPLE permissions (use {count} placeholder)
210
288
  "permissionReminderTTSMessagesMultiple": [
211
289
  "Hey! I still need your approval for {count} permissions. Please respond!",
212
- "Reminder: There are {count} pending permission requests."
290
+ "Reminder: There are {count} pending permission requests. I cannot proceed without you.",
291
+ "Hello? I am waiting for your approval on {count} items. This is getting urgent!",
292
+ "Please check your screen! {count} permissions are waiting for your response.",
293
+ "Still waiting for authorization on {count} requests! The task is on hold."
213
294
  ],
214
-
215
- // ============================================================
216
- // SOUND FILES (relative to OpenCode config directory)
217
- // ============================================================
218
- "idleSound": "assets/Soft-high-tech-notification-sound-effect.mp3",
219
- "permissionSound": "assets/Machine-alert-beep-sound-effect.mp3",
220
-
221
- // ============================================================
222
- // GENERAL SETTINGS
223
- // ============================================================
224
- "wakeMonitor": true,
225
- "forceVolume": true,
226
- "volumeThreshold": 50,
227
- "enableToast": true,
228
- "enableSound": true,
229
- "idleThresholdSeconds": 60,
230
- "debugLog": false
231
- }
232
- ```
295
+
296
+ // ============================================================
297
+ // QUESTION TOOL MESSAGES (SDK v1.1.7+ - Agent asking user questions)
298
+ // ============================================================
299
+ // The "question" tool allows the LLM to ask users questions during execution.
300
+ // This is useful for gathering preferences, clarifying instructions, or getting
301
+ // decisions on implementation choices.
302
+
303
+ // Messages when agent asks user a question
304
+ "questionTTSMessages": [
305
+ "Hey! I have a question for you. Please check your screen.",
306
+ "Attention! I need your input to continue.",
307
+ "Quick question! Please take a look when you have a moment.",
308
+ "I need some clarification. Could you please respond?",
309
+ "Question time! Your input is needed to proceed."
310
+ ],
311
+
312
+ // Messages for MULTIPLE questions (use {count} placeholder)
313
+ "questionTTSMessagesMultiple": [
314
+ "Hey! I have {count} questions for you. Please check your screen.",
315
+ "Attention! I need your input on {count} items to continue.",
316
+ "{count} questions need your attention. Please take a look!",
317
+ "I need some clarifications. There are {count} questions waiting for you.",
318
+ "Question time! {count} questions need your response to proceed."
319
+ ],
320
+
321
+ // Reminder messages for questions (more urgent - used after delay)
322
+ "questionReminderTTSMessages": [
323
+ "Hey! I am still waiting for your answer. Please check the questions!",
324
+ "Reminder: There is a question waiting for your response.",
325
+ "Hello? I need your input to continue. Please respond when you can.",
326
+ "Still waiting for your answer! The task is on hold.",
327
+ "Your input is needed! Please check the pending question."
328
+ ],
329
+
330
+ // Reminder messages for MULTIPLE questions (use {count} placeholder)
331
+ "questionReminderTTSMessagesMultiple": [
332
+ "Hey! I am still waiting for answers to {count} questions. Please respond!",
333
+ "Reminder: There are {count} questions waiting for your response.",
334
+ "Hello? I need your input on {count} items. Please respond when you can.",
335
+ "Still waiting for your answers on {count} questions! The task is on hold.",
336
+ "Your input is needed! {count} questions are pending your response."
337
+ ],
338
+
339
+ // Delay (in seconds) before question reminder fires
340
+ "questionReminderDelaySeconds": 25,
341
+
342
+ // Question batch window (ms) - how long to wait for more questions before notifying
343
+ "questionBatchWindowMs": 800,
344
+
345
+ // ============================================================
346
+ // SOUND FILES (For immediate notifications)
347
+ // These are played first before TTS reminder kicks in
348
+ // ============================================================
349
+ // Paths are relative to ~/.config/opencode/ directory
350
+ // The plugin automatically copies bundled sounds to assets/ on first run
351
+ // You can replace with your own custom MP3/WAV files
352
+
353
+ "idleSound": "assets/Soft-high-tech-notification-sound-effect.mp3",
354
+ "permissionSound": "assets/Machine-alert-beep-sound-effect.mp3",
355
+ "questionSound": "assets/Machine-alert-beep-sound-effect.mp3",
356
+
357
+ // ============================================================
358
+ // GENERAL SETTINGS
359
+ // ============================================================
360
+
361
+ // Wake monitor from sleep when notifying (Windows/macOS)
362
+ "wakeMonitor": true,
363
+
364
+ // Force system volume up if below threshold
365
+ "forceVolume": true,
366
+
367
+ // Volume threshold (0-100): force volume if current level is below this
368
+ "volumeThreshold": 50,
369
+
370
+ // Show TUI toast notifications in OpenCode terminal
371
+ "enableToast": true,
372
+
373
+ // Enable audio notifications (sound files and TTS)
374
+ "enableSound": true,
375
+
376
+ // Consider monitor asleep after this many seconds of inactivity (Windows only)
377
+ "idleThresholdSeconds": 60,
378
+
379
+ // Enable debug logging to ~/.config/opencode/logs/smart-voice-notify-debug.log
380
+ // The logs folder is created automatically when debug logging is enabled
381
+ // Useful for troubleshooting notification issues
382
+ "debugLog": false
383
+ }
384
+ ```
233
385
 
234
386
  See `example.config.jsonc` for more details.
235
387
 
@@ -16,6 +16,13 @@
16
16
  //
17
17
  // ============================================================
18
18
 
19
+ // ============================================================
20
+ // PLUGIN ENABLE/DISABLE
21
+ // ============================================================
22
+ // Master switch to enable or disable the entire plugin.
23
+ // Set to false to disable all notifications without uninstalling.
24
+ "enabled": true,
25
+
19
26
  // ============================================================
20
27
  // NOTIFICATION MODE SETTINGS (Smart Notification System)
21
28
  // ============================================================
package/index.js CHANGED
@@ -23,9 +23,28 @@ import { createTTS, getTTSConfig } from './util/tts.js';
23
23
  */
24
24
  export default async function SmartVoiceNotifyPlugin({ project, client, $, directory, worktree }) {
25
25
  const config = getTTSConfig();
26
+
27
+ // Master switch: if plugin is disabled, return empty handlers immediately
28
+ if (config.enabled === false) {
29
+ const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), '.config', 'opencode');
30
+ const logsDir = path.join(configDir, 'logs');
31
+ const logFile = path.join(logsDir, 'smart-voice-notify-debug.log');
32
+ if (config.debugLog) {
33
+ try {
34
+ if (!fs.existsSync(logsDir)) {
35
+ fs.mkdirSync(logsDir, { recursive: true });
36
+ }
37
+ const timestamp = new Date().toISOString();
38
+ fs.appendFileSync(logFile, `[${timestamp}] Plugin disabled via config (enabled: false) - no event handlers registered\n`);
39
+ } catch (e) {}
40
+ }
41
+ return {};
42
+ }
43
+
26
44
  const tts = createTTS({ $, client });
27
45
 
28
46
  const platform = os.platform();
47
+
29
48
  const configDir = process.env.OPENCODE_CONFIG_DIR || path.join(os.homedir(), '.config', 'opencode');
30
49
  const logsDir = path.join(configDir, 'logs');
31
50
  const logFile = path.join(logsDir, 'smart-voice-notify-debug.log');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-smart-voice-notify",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Smart voice notification plugin for OpenCode with multiple TTS engines (ElevenLabs, Edge TTS, Windows SAPI) and intelligent reminder system",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/util/config.js CHANGED
@@ -59,6 +59,13 @@ const generateDefaultConfig = (overrides = {}, version = '1.0.0') => {
59
59
  // Internal version tracking - DO NOT REMOVE
60
60
  "_configVersion": "${version}",
61
61
 
62
+ // ============================================================
63
+ // PLUGIN ENABLE/DISABLE
64
+ // ============================================================
65
+ // Master switch to enable or disable the entire plugin.
66
+ // Set to false to disable all notifications without uninstalling.
67
+ "enabled": ${overrides.enabled !== undefined ? overrides.enabled : true},
68
+
62
69
  // ============================================================
63
70
  // NOTIFICATION MODE SETTINGS (Smart Notification System)
64
71
  // ============================================================