agentvibes 5.6.9 → 5.7.0

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.
Files changed (95) hide show
  1. package/.agentvibes/config.json +3 -38
  2. package/.claude/commands/agent-vibes/provider.md +0 -0
  3. package/.claude/config/audio-effects.cfg +1 -1
  4. package/.claude/config/background-music-position.txt +6 -8
  5. package/.claude/config/reverb-level.txt +0 -0
  6. package/.claude/github-star-reminder.txt +1 -1
  7. package/.claude/hooks/bmad-tts-injector.sh +49 -21
  8. package/.claude/hooks/provider-commands.sh +16 -4
  9. package/.claude/hooks/provider-manager.sh +38 -0
  10. package/.claude/hooks/stop.sh +2 -27
  11. package/.claude/hooks/voice-manager.sh +50 -2
  12. package/.claude/hooks-windows/play-tts.ps1 +34 -1
  13. package/.claude/hooks-windows/tts-watcher.ps1 +122 -0
  14. package/.claude/piper-voices-dir.txt +1 -1
  15. package/.mcp.json +13 -33
  16. package/README.md +6 -8
  17. package/RELEASE_NOTES.md +32 -0
  18. package/bin/agent-vibes +39 -39
  19. package/package.json +1 -1
  20. package/src/bmad-detector.js +85 -71
  21. package/src/cli/list-personalities.js +110 -110
  22. package/src/cli/list-voices.js +114 -114
  23. package/src/commands/bmad-voices.js +394 -394
  24. package/src/commands/install-mcp.js +476 -476
  25. package/src/console/brand-colors.js +13 -13
  26. package/src/console/constants/personalities.js +44 -44
  27. package/src/console/tabs/help-tab.js +314 -314
  28. package/src/console/tabs/readme-tab.js +272 -272
  29. package/src/console/widgets/destroy-list.js +25 -25
  30. package/src/console/widgets/notice.js +55 -55
  31. package/src/console/widgets/personality-picker.js +213 -213
  32. package/src/i18n/de.js +202 -202
  33. package/src/i18n/es.js +202 -202
  34. package/src/i18n/fr.js +202 -202
  35. package/src/i18n/hi.js +202 -202
  36. package/src/i18n/ja.js +202 -202
  37. package/src/i18n/ko.js +202 -202
  38. package/src/i18n/pt.js +202 -202
  39. package/src/i18n/strings.js +54 -54
  40. package/src/i18n/zh-CN.js +202 -202
  41. package/src/installer/language-screen.js +31 -31
  42. package/src/installer/music-file-input.js +304 -304
  43. package/src/installer.js +70 -7
  44. package/src/services/agent-voice-store.js +59 -12
  45. package/src/services/config-service.js +264 -264
  46. package/src/services/language-service.js +47 -47
  47. package/src/services/provider-service.js +143 -143
  48. package/src/utils/audio-duration-validator.js +298 -298
  49. package/src/utils/audio-format-validator.js +277 -277
  50. package/src/utils/dependency-checker.js +469 -469
  51. package/src/utils/file-ownership-verifier.js +358 -358
  52. package/src/utils/list-formatter.js +194 -194
  53. package/src/utils/music-file-validator.js +285 -285
  54. package/src/utils/preview-list-prompt.js +136 -136
  55. package/src/utils/secure-music-storage.js +412 -412
  56. package/.agentvibes/LITE-MODE.md +0 -236
  57. package/.agentvibes/README.md +0 -136
  58. package/.agentvibes/backup/session-start-tts.sh.20251210_212814 +0 -141
  59. package/.agentvibes/backups/agents/analyst_20260204_144958.md +0 -78
  60. package/.agentvibes/backups/agents/architect_20260204_144958.md +0 -72
  61. package/.agentvibes/backups/agents/dev_20260204_144958.md +0 -74
  62. package/.agentvibes/backups/agents/pm_20260204_144958.md +0 -72
  63. package/.agentvibes/backups/agents/quick-flow-solo-dev_20260204_144958.md +0 -64
  64. package/.agentvibes/backups/agents/sm_20260204_144958.md +0 -87
  65. package/.agentvibes/backups/agents/tea_20260204_144958.md +0 -79
  66. package/.agentvibes/backups/agents/tech-writer_20260204_144958.md +0 -82
  67. package/.agentvibes/backups/agents/ux-designer_20260204_144958.md +0 -80
  68. package/.agentvibes/config/README-personality-defaults.md +0 -162
  69. package/.agentvibes/config/agentvibes.json +0 -1
  70. package/.agentvibes/config/mode.txt +0 -1
  71. package/.agentvibes/config/personality-voice-defaults.default.json +0 -21
  72. package/.agentvibes/config/save-audio.txt +0 -1
  73. package/.agentvibes/config/voice-metadata.json +0 -160
  74. package/.agentvibes/hooks/help.sh +0 -191
  75. package/.agentvibes/hooks/post-tool-use-lite.sh +0 -111
  76. package/.agentvibes/hooks/save-audio-manager.sh +0 -162
  77. package/.agentvibes/hooks/session-start-full-optimized.sh +0 -102
  78. package/.agentvibes/hooks/session-start-full.sh +0 -142
  79. package/.agentvibes/hooks/session-start-lite-v2.sh +0 -34
  80. package/.agentvibes/hooks/session-start-lite.sh +0 -29
  81. package/.agentvibes/hooks/stop-lite.sh +0 -115
  82. package/.agentvibes/hooks/switch-mode.sh +0 -215
  83. package/.agentvibes/output-styles/audio-summary.md +0 -30
  84. package/.claude/audio/voice-samples/piper/alan.wav +0 -0
  85. package/.claude/audio/voice-samples/piper/amy.wav +0 -0
  86. package/.claude/audio/voice-samples/piper/charlotte.wav +0 -0
  87. package/.claude/audio/voice-samples/piper/joe.wav +0 -0
  88. package/.claude/audio/voice-samples/piper/john.wav +0 -0
  89. package/.claude/audio/voice-samples/piper/katherine.wav +0 -0
  90. package/.claude/audio/voice-samples/piper/kristin.wav +0 -0
  91. package/.claude/audio/voice-samples/piper/linda.wav +0 -0
  92. package/.claude/audio/voice-samples/piper/marcus.wav +0 -0
  93. package/.claude/audio/voice-samples/piper/ryan.wav +0 -0
  94. package/.claude/hooks/post-response.sh +0 -41
  95. package/bin/ensure-soprano-running.sh +0 -43
package/src/installer.js CHANGED
@@ -4570,9 +4570,8 @@ async function handleMcpConfiguration(targetDir, options) {
4570
4570
  * @param {string} targetDir - Base installation directory to validate bmadPath is within
4571
4571
  */
4572
4572
  async function processBmadTtsInjections(bmadPath, targetDir) {
4573
- // Security: Validate bmadPath is within targetDir (not process.cwd() which may differ
4574
- // when called from BMAD's installer via npx with a different cwd)
4575
- if (!isPathSafe(bmadPath, targetDir)) {
4573
+ // Security: bmadPath must be within targetDir OR home dir (BMAD may be installed globally at ~/_bmad)
4574
+ if (!isPathSafe(bmadPath, targetDir) && !isPathSafe(bmadPath, os.homedir())) {
4576
4575
  console.error(chalk.red('⚠️ Security: Invalid BMAD path detected'));
4577
4576
  return;
4578
4577
  }
@@ -4841,14 +4840,17 @@ async function handleBmadIntegration(targetDir, options = {}) {
4841
4840
  }
4842
4841
 
4843
4842
  // Process TTS_INJECTION markers in BMAD files if they exist
4844
- // This handles the case where BMAD was installed before AgentVibes
4845
- await processBmadTtsInjections(bmadDetection.bmadPath, targetDir);
4843
+ // Skip for global home-dir BMAD installs only inject into project-local BMAD
4844
+ if (!bmadDetection.isGlobal) {
4845
+ await processBmadTtsInjections(bmadDetection.bmadPath, targetDir);
4846
+ }
4846
4847
 
4847
4848
  // Create default voice assignments if they don't exist
4848
4849
  await createDefaultBmadVoiceAssignmentsProactive(targetDir);
4849
4850
 
4850
4851
  // Prompt user to inject TTS into BMAD agents (or auto-inject with --yes flag)
4851
- let enableTtsInjection = options.yes; // Auto-enable with --yes flag
4852
+ // Skip injection prompt for global BMAD modifying shared ~/.bmad files from a project install is wrong
4853
+ let enableTtsInjection = bmadDetection.isGlobal ? false : options.yes;
4852
4854
 
4853
4855
  if (!options.yes) {
4854
4856
  console.log(''); // Add spacing
@@ -5047,7 +5049,7 @@ async function updateCommandFiles(targetDir, spinner) {
5047
5049
  * on every `npx agentvibes update` regardless of target directory.
5048
5050
  */
5049
5051
  const CRITICAL_HOOKS = ['stop-tts.sh', 'stop.sh', 'play-tts.sh', 'play-tts-piper.sh', 'audio-processor.sh', 'session-start-tts.sh', 'bmad-party-speak.sh'];
5050
- const CRITICAL_HOOKS_WINDOWS = ['play-tts.ps1', 'play-tts-piper.ps1', 'audio-processor.ps1', 'session-start-tts.ps1', 'bmad-speak.ps1', 'bmad-party-speak.ps1'];
5052
+ const CRITICAL_HOOKS_WINDOWS = ['play-tts.ps1', 'play-tts-piper.ps1', 'audio-processor.ps1', 'session-start-tts.ps1', 'bmad-speak.ps1', 'bmad-party-speak.ps1', 'tts-watcher.ps1'];
5051
5053
 
5052
5054
  /**
5053
5055
  * Update critical hooks in the global ~/.claude/hooks/ directory if it exists.
@@ -5094,6 +5096,59 @@ async function updateGlobalHooks(srcHooksDir, homeDirOverride) {
5094
5096
  return updated;
5095
5097
  }
5096
5098
 
5099
+ /**
5100
+ * Restart the AgentVibes TTS queue watcher on Windows after an update.
5101
+ * Only runs if the watcher is already installed (~/.agentvibes/tts-watcher.ps1 exists),
5102
+ * meaning the user previously ran setup-ssh-receiver.ps1. Silently skips for users
5103
+ * who don't use the SSH remote receiver.
5104
+ * @param {string} [homeDirOverride] - Override home dir (for testing only)
5105
+ * @returns {Promise<boolean>} true if watcher was restarted, false if skipped
5106
+ */
5107
+ async function restartWatcherIfInstalled(homeDirOverride) {
5108
+ if (!isNativeWindows()) return false;
5109
+
5110
+ const homeDir = homeDirOverride || os.homedir();
5111
+ const watcherDest = path.join(homeDir, '.agentvibes', 'tts-watcher.ps1');
5112
+ const vbsLauncher = path.join(homeDir, '.agentvibes', 'start-watcher.vbs');
5113
+
5114
+ // Only act if the user has the SSH receiver set up
5115
+ try {
5116
+ await fs.access(watcherDest);
5117
+ } catch {
5118
+ return false;
5119
+ }
5120
+
5121
+ const { spawnSync, spawn } = require('child_process');
5122
+
5123
+ // Kill old watcher — use array args to avoid quoting issues
5124
+ spawnSync('powershell.exe', [
5125
+ '-NoProfile', '-Command',
5126
+ 'Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like \'*tts-watcher.ps1*\' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }'
5127
+ ], { stdio: 'ignore', timeout: 8000 });
5128
+
5129
+ // Copy updated watcher from global hooks to the deployed location
5130
+ const watcherSrc = path.join(homeDir, '.claude', 'hooks-windows', 'tts-watcher.ps1');
5131
+ try {
5132
+ await fs.copyFile(watcherSrc, watcherDest);
5133
+ } catch {
5134
+ // src may not exist on a fresh install path — skip copy, the file was already
5135
+ // put there by updateGlobalHooks() earlier in the same run
5136
+ }
5137
+
5138
+ // Restart via VBS launcher (hidden, no console flash) or fall back to direct spawn
5139
+ try {
5140
+ await fs.access(vbsLauncher);
5141
+ spawnSync('wscript.exe', [vbsLauncher], { stdio: 'ignore' });
5142
+ } catch {
5143
+ const ps = spawn('powershell.exe', [
5144
+ '-NoProfile', '-ExecutionPolicy', 'Bypass', '-WindowStyle', 'Hidden', '-File', watcherDest
5145
+ ], { detached: true, stdio: 'ignore' });
5146
+ ps.unref();
5147
+ }
5148
+
5149
+ return true;
5150
+ }
5151
+
5097
5152
  /**
5098
5153
  * Perform all update operations
5099
5154
  * @param {string} targetDir - Target installation directory
@@ -5120,6 +5175,14 @@ async function performUpdateOperations(targetDir, spinner) {
5120
5175
  console.log(chalk.green(`✓ Updated ${globalHooksUpdated} critical scripts in ~/.claude/hooks/`));
5121
5176
  }
5122
5177
 
5178
+ // On Windows: restart the TTS queue watcher if it was previously installed via
5179
+ // setup-ssh-receiver.ps1. This propagates hook updates without requiring the
5180
+ // user to manually run update-watcher.ps1 after every `npx agentvibes update`.
5181
+ const watcherRestarted = await restartWatcherIfInstalled();
5182
+ if (watcherRestarted) {
5183
+ console.log(chalk.green('✓ TTS watcher restarted with updated scripts'));
5184
+ }
5185
+
5123
5186
  // Update personalities
5124
5187
  spinner.text = 'Updating personality templates...';
5125
5188
  const srcPersonalitiesDir = path.join(__dirname, '..', '.claude', 'personalities');
@@ -109,9 +109,17 @@ export function isSingleVoiceProvider(provider) {
109
109
  */
110
110
  export function parseBmadManifest(projectRoot) {
111
111
  const safeRoot = path.resolve(projectRoot ?? process.cwd());
112
- const manifestPath = path.resolve(safeRoot, '_bmad', '_config', 'agent-manifest.csv');
113
-
114
- if (!fs.existsSync(manifestPath)) return [];
112
+ // Check project-local first, then home dir (global BMAD install)
113
+ const roots = [safeRoot];
114
+ const homeDir = os.homedir();
115
+ if (safeRoot !== homeDir) roots.push(homeDir);
116
+
117
+ let manifestPath = null;
118
+ for (const root of roots) {
119
+ const candidate = path.resolve(root, '_bmad', '_config', 'agent-manifest.csv');
120
+ if (fs.existsSync(candidate)) { manifestPath = candidate; break; }
121
+ }
122
+ if (!manifestPath) return [];
115
123
 
116
124
  try {
117
125
  const raw = fs.readFileSync(manifestPath, 'utf8');
@@ -196,11 +204,32 @@ export function scanBmadAgents(projectRoot) {
196
204
  const fromManifest = parseBmadManifest(projectRoot);
197
205
  if (fromManifest.length > 0) return fromManifest;
198
206
 
199
- // Fallback: directory scan
207
+ // Fallback: directory scan — check project-local then home dir
200
208
  const safeRoot = path.resolve(projectRoot ?? process.cwd());
209
+ const homeDir2 = os.homedir();
210
+
211
+ // v6.6+: agents under .claude/skills/*/agents/ — collect all such dirs
212
+ const skillsAgentDirs = [];
213
+ for (const root of (safeRoot !== homeDir2 ? [safeRoot, homeDir2] : [safeRoot])) {
214
+ const skillsDir = path.resolve(root, '.claude', 'skills');
215
+ if (fs.existsSync(skillsDir)) {
216
+ try {
217
+ for (const skill of fs.readdirSync(skillsDir)) {
218
+ const agentsDir = path.resolve(skillsDir, skill, 'agents');
219
+ if (fs.existsSync(agentsDir)) skillsAgentDirs.push(agentsDir);
220
+ }
221
+ } catch { /* skip */ }
222
+ }
223
+ }
224
+
201
225
  const candidateDirs = [
202
226
  path.resolve(safeRoot, '_bmad', 'bmm', 'agents'),
203
227
  path.resolve(safeRoot, '.bmad', 'agents'),
228
+ ...(safeRoot !== homeDir2 ? [
229
+ path.resolve(homeDir2, '_bmad', 'bmm', 'agents'),
230
+ path.resolve(homeDir2, '.bmad', 'agents'),
231
+ ] : []),
232
+ ...skillsAgentDirs,
204
233
  ];
205
234
 
206
235
  for (const dir of candidateDirs) {
@@ -232,15 +261,33 @@ export function scanBmadAgents(projectRoot) {
232
261
  */
233
262
  export function isBmadDetected(projectRoot) {
234
263
  const safeRoot = path.resolve(projectRoot ?? process.cwd());
235
- const manifestPath = path.resolve(safeRoot, '_bmad', '_config', 'agent-manifest.csv');
236
- if (fs.existsSync(manifestPath)) return true;
264
+ const homeDir = os.homedir();
237
265
 
238
- // Fallback checks
239
- const dirs = [
240
- path.resolve(safeRoot, '_bmad', 'bmm', 'agents'),
241
- path.resolve(safeRoot, '.bmad', 'agents'),
242
- ];
243
- return dirs.some(d => fs.existsSync(d));
266
+ // Check project-local first, then home-dir (BMAD can be installed globally at ~/_bmad)
267
+ const roots = safeRoot !== homeDir ? [safeRoot, homeDir] : [safeRoot];
268
+
269
+ for (const root of roots) {
270
+ // v6.x: agent-manifest.csv; v6.6+: manifest.yaml only (no agent-manifest.csv)
271
+ if (fs.existsSync(path.resolve(root, '_bmad', '_config', 'agent-manifest.csv'))) return true;
272
+ if (fs.existsSync(path.resolve(root, '_bmad', '_config', 'manifest.yaml'))) return true;
273
+
274
+ const dirs = [
275
+ path.resolve(root, '_bmad', 'bmm', 'agents'),
276
+ path.resolve(root, '.bmad', 'agents'),
277
+ ];
278
+ if (dirs.some(d => fs.existsSync(d))) return true;
279
+
280
+ // v6.6+: agents live under .claude/skills/*/agents/
281
+ const skillsDir = path.resolve(root, '.claude', 'skills');
282
+ if (fs.existsSync(skillsDir)) {
283
+ try {
284
+ const skills = fs.readdirSync(skillsDir);
285
+ if (skills.some(s => fs.existsSync(path.resolve(skillsDir, s, 'agents')))) return true;
286
+ } catch { /* skip */ }
287
+ }
288
+ }
289
+
290
+ return false;
244
291
  }
245
292
 
246
293
  // ---------------------------------------------------------------------------