agentvibes 5.10.1 → 5.11.1

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 (160) hide show
  1. package/.agentvibes/config.json +15 -1
  2. package/.agentvibes/install-manifest.json +342 -0
  3. package/.claude/audio/ui/CREDITS.txt +16 -0
  4. package/.claude/audio/ui/bling-success.wav +0 -0
  5. package/.claude/commands/agent-vibes/receiver.md +64 -0
  6. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  7. package/.claude/commands/agent-vibes-rdp.md +24 -24
  8. package/.claude/config/audio-effects.cfg +5 -4
  9. package/.claude/config/audio-effects.cfg.sample +52 -52
  10. package/.claude/config/background-music-enabled.txt +1 -1
  11. package/.claude/config/background-music-position.txt +27 -0
  12. package/.claude/config/background-music-volume.txt +1 -0
  13. package/.claude/config/background-music.cfg +1 -0
  14. package/.claude/config/background-music.txt +1 -0
  15. package/.claude/config/language.txt +1 -0
  16. package/.claude/config/personality.txt +1 -0
  17. package/.claude/config/reverb-level.txt +1 -0
  18. package/.claude/config/tts-speech-rate.txt +1 -0
  19. package/.claude/config/tts-verbosity.txt +1 -0
  20. package/.claude/docs/TERMUX_SETUP.md +408 -408
  21. package/.claude/github-star-reminder.txt +1 -1
  22. package/.claude/hooks/audio-cache-utils.sh +0 -0
  23. package/.claude/hooks/audio-processor.sh +57 -18
  24. package/.claude/hooks/background-music-manager.sh +0 -0
  25. package/.claude/hooks/bmad-party-speak.sh +0 -0
  26. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  27. package/.claude/hooks/bmad-speak.sh +0 -0
  28. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  29. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  30. package/.claude/hooks/clawdbot-receiver-SECURE.sh +0 -0
  31. package/.claude/hooks/clawdbot-receiver.sh +0 -0
  32. package/.claude/hooks/clean-audio-cache.sh +0 -0
  33. package/.claude/hooks/cleanup-cache.sh +0 -0
  34. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  35. package/.claude/hooks/download-extra-voices.sh +0 -0
  36. package/.claude/hooks/effects-manager.sh +0 -0
  37. package/.claude/hooks/github-star-reminder.sh +0 -0
  38. package/.claude/hooks/kokoro-installer.sh +117 -0
  39. package/.claude/hooks/kokoro-server.py +219 -0
  40. package/.claude/hooks/kokoro-tts.py +141 -0
  41. package/.claude/hooks/language-manager.sh +0 -0
  42. package/.claude/hooks/learn-manager.sh +0 -0
  43. package/.claude/hooks/macos-voice-manager.sh +0 -0
  44. package/.claude/hooks/migrate-background-music.sh +0 -0
  45. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  46. package/.claude/hooks/optimize-background-music.sh +0 -0
  47. package/.claude/hooks/path-resolver.sh +0 -0
  48. package/.claude/hooks/personality-manager.sh +0 -0
  49. package/.claude/hooks/piper-download-voices.sh +39 -16
  50. package/.claude/hooks/piper-installer.sh +11 -6
  51. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  52. package/.claude/hooks/piper-voice-manager.sh +6 -6
  53. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +3 -1
  54. package/.claude/hooks/play-tts-agentvibes-receiver.sh +1 -0
  55. package/.claude/hooks/play-tts-elevenlabs.sh +360 -0
  56. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  57. package/.claude/hooks/play-tts-kokoro.sh +127 -0
  58. package/.claude/hooks/play-tts-macos.sh +0 -0
  59. package/.claude/hooks/play-tts-piper.sh +0 -0
  60. package/.claude/hooks/play-tts-soprano.sh +0 -0
  61. package/.claude/hooks/play-tts-ssh-remote.sh +9 -2
  62. package/.claude/hooks/play-tts-termux-ssh.sh +3 -1
  63. package/.claude/hooks/play-tts-windows-receiver.sh +0 -0
  64. package/.claude/hooks/play-tts.sh +78 -2
  65. package/.claude/hooks/prepare-release.sh +0 -0
  66. package/.claude/hooks/provider-commands.sh +71 -22
  67. package/.claude/hooks/provider-manager.sh +15 -7
  68. package/.claude/hooks/replay-target-audio.sh +0 -0
  69. package/.claude/hooks/requirements.txt +6 -6
  70. package/.claude/hooks/sentiment-manager.sh +0 -0
  71. package/.claude/hooks/session-start-tts.sh +0 -0
  72. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  73. package/.claude/hooks/speed-manager.sh +0 -0
  74. package/.claude/hooks/stop-tts.sh +0 -0
  75. package/.claude/hooks/termux-installer.sh +0 -0
  76. package/.claude/hooks/translate-manager.sh +0 -0
  77. package/.claude/hooks/translator.py +237 -237
  78. package/.claude/hooks/tts-queue-worker.sh +0 -0
  79. package/.claude/hooks/tts-queue.sh +0 -0
  80. package/.claude/hooks/verbosity-manager.sh +0 -0
  81. package/.claude/hooks/voice-manager.sh +0 -0
  82. package/.claude/hooks-windows/audio-cache-utils.ps1.user.bak +119 -0
  83. package/.claude/hooks-windows/kokoro-server.py +219 -0
  84. package/.claude/hooks-windows/kokoro-tts.py +107 -0
  85. package/.claude/hooks-windows/play-tts-kokoro.ps1 +191 -0
  86. package/.claude/hooks-windows/play-tts.ps1 +29 -1
  87. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  88. package/.claude/hooks-windows/soprano-gradio-synth.py.user.bak +153 -0
  89. package/.claude/piper-voices-dir.txt +1 -0
  90. package/.claude/verbosity.txt +1 -1
  91. package/.clawdbot/README.md +105 -105
  92. package/.mcp.json +6 -19
  93. package/README.md +127 -2116
  94. package/RELEASE_NOTES.md +73 -0
  95. package/WINDOWS-SETUP.md +208 -208
  96. package/bin/agent-vibes +39 -39
  97. package/bin/agentvibes-voice-browser.js +0 -0
  98. package/bin/agentvibes.js +0 -0
  99. package/bin/mcp-server.js +121 -121
  100. package/bin/mcp-server.sh +0 -0
  101. package/bin/test-bmad-pr +78 -78
  102. package/mcp-server/QUICK_START.md +203 -203
  103. package/mcp-server/README.md +345 -345
  104. package/mcp-server/WINDOWS_SETUP.md +0 -0
  105. package/mcp-server/examples/claude_desktop_config.json +11 -11
  106. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  107. package/mcp-server/examples/custom_instructions.md +169 -169
  108. package/mcp-server/install-deps.js +0 -0
  109. package/mcp-server/server.py +1807 -1807
  110. package/mcp-server/test_server.py +0 -0
  111. package/package.json +4 -3
  112. package/src/cli/list-personalities.js +110 -110
  113. package/src/cli/list-voices.js +114 -114
  114. package/src/commands/bmad-voices.js +394 -394
  115. package/src/commands/install-mcp.js +3 -3
  116. package/src/console/app.js +25 -9
  117. package/src/console/audio-env.js +85 -1
  118. package/src/console/brand-colors.js +13 -13
  119. package/src/console/constants/personalities.js +44 -44
  120. package/src/console/navigation.js +4 -0
  121. package/src/console/tabs/agents-tab.js +12 -6
  122. package/src/console/tabs/help-tab.js +314 -314
  123. package/src/console/tabs/music-tab.js +7 -25
  124. package/src/console/tabs/readme-tab.js +272 -272
  125. package/src/console/tabs/setup-tab.js +1704 -120
  126. package/src/console/tabs/voices-tab.js +72 -88
  127. package/src/console/widgets/destroy-list.js +25 -25
  128. package/src/console/widgets/format-utils.js +14 -2
  129. package/src/console/widgets/help-bar.js +55 -0
  130. package/src/console/widgets/notice.js +55 -55
  131. package/src/console/widgets/reverb-picker.js +429 -41
  132. package/src/console/widgets/track-picker.js +60 -51
  133. package/src/i18n/de.js +2 -1
  134. package/src/i18n/en.js +1 -0
  135. package/src/i18n/es.js +2 -1
  136. package/src/i18n/fr.js +2 -1
  137. package/src/i18n/hi.js +2 -1
  138. package/src/i18n/ja.js +2 -1
  139. package/src/i18n/ko.js +2 -1
  140. package/src/i18n/pt.js +2 -1
  141. package/src/i18n/strings.js +9 -9
  142. package/src/i18n/zh-CN.js +2 -1
  143. package/src/installer/language-screen.js +31 -31
  144. package/src/installer/music-file-input.js +304 -304
  145. package/src/installer.js +95 -7
  146. package/src/services/config-service.js +264 -264
  147. package/src/services/language-service.js +47 -47
  148. package/src/services/provider-service.js +35 -0
  149. package/src/services/provider-voice-catalog.js +126 -0
  150. package/src/services/tts-engine-service.js +51 -2
  151. package/src/utils/audio-duration-validator.js +53 -10
  152. package/src/utils/audio-format-validator.js +277 -277
  153. package/src/utils/dependency-checker.js +469 -469
  154. package/src/utils/file-ownership-verifier.js +358 -358
  155. package/src/utils/music-file-validator.js +285 -285
  156. package/src/utils/preview-list-prompt.js +144 -136
  157. package/src/utils/provider-validator.js +70 -0
  158. package/src/utils/secure-music-storage.js +412 -412
  159. package/templates/agentvibes-receiver.sh +235 -231
  160. package/templates/audio/welcome-music.mp3 +0 -0
package/src/installer.js CHANGED
@@ -3190,7 +3190,9 @@ function execScript(scriptPath, options = {}) {
3190
3190
  // Instead, directly execute the script file without sourcing shell config
3191
3191
  // The script itself will be executed in a clean environment
3192
3192
  // Note: This means shell aliases/functions won't be available, but that's safer
3193
- return execFileSync(scriptFile, args, {
3193
+ // S8701: scriptFile is validated to live under .claude/hooks (above), args are
3194
+ // passed as an array and shell:false disables shell interpretation. Risk handled.
3195
+ return execFileSync(scriptFile, args, { // NOSONAR
3194
3196
  ...options,
3195
3197
  shell: false // Don't use shell to avoid injection risks
3196
3198
  });
@@ -3598,7 +3600,7 @@ function shouldIncludeHookFile(file, stat) {
3598
3600
  !file.startsWith('.');
3599
3601
  }
3600
3602
  return stat.isFile() &&
3601
- (file.endsWith('.sh') || file === 'hooks.json') &&
3603
+ (file.endsWith('.sh') || file.endsWith('.py') || file === 'hooks.json') &&
3602
3604
  !file.includes('prepare-release') &&
3603
3605
  !file.startsWith('.');
3604
3606
  }
@@ -4349,6 +4351,47 @@ async function installPluginManifest(targetDir, spinner) {
4349
4351
  }
4350
4352
  }
4351
4353
 
4354
+ /**
4355
+ * Prompt the user to optionally download the LibriTTS 900+ voice library.
4356
+ * Skipped silently if: options.yes, libritts already downloaded, or script missing.
4357
+ */
4358
+ async function offerLibriTTSDownload(piperDownloadPath, options) {
4359
+ if (options.yes) return;
4360
+ if (!fsSync.existsSync(piperDownloadPath)) return;
4361
+
4362
+ const voicesDir = path.join(process.env.HOME || process.env.USERPROFILE, '.claude', 'piper-voices');
4363
+ const librittsAlreadyInstalled = fsSync.existsSync(path.join(voicesDir, 'en_US-libritts-high.onnx'));
4364
+ if (librittsAlreadyInstalled) return;
4365
+
4366
+ console.log(chalk.cyan('\nšŸŽ™ļø Want 900+ voice variations?\n'));
4367
+ console.log(chalk.gray(' The LibriTTS model includes 904 named speakers (Ryan, Sarah, Joe, and more).'));
4368
+ console.log(chalk.gray(' Browse them with /agent-vibes:list after install.'));
4369
+ console.log(chalk.gray(' Download size: ~114MB\n'));
4370
+
4371
+ const { installLibriTTS } = await inquirer.prompt([{
4372
+ type: 'confirm',
4373
+ name: 'installLibriTTS',
4374
+ message: 'Download LibriTTS voice library? (optional)',
4375
+ default: false,
4376
+ }]);
4377
+
4378
+ if (!installLibriTTS) {
4379
+ console.log(chalk.gray(' Skipped. Run later: ~/.claude/hooks/piper-download-voices.sh --libritts\n'));
4380
+ return;
4381
+ }
4382
+
4383
+ try {
4384
+ execScript(`${piperDownloadPath} --libritts --yes`, {
4385
+ stdio: 'inherit',
4386
+ env: process.env
4387
+ });
4388
+ console.log(chalk.green('\nāœ… LibriTTS voices downloaded! Browse with /agent-vibes:list\n'));
4389
+ } catch {
4390
+ console.log(chalk.yellow('\nāš ļø LibriTTS download failed.'));
4391
+ console.log(chalk.gray(' Run later: ~/.claude/hooks/piper-download-voices.sh --libritts\n'));
4392
+ }
4393
+ }
4394
+
4352
4395
  /**
4353
4396
  * Check if Piper is installed and optionally install it
4354
4397
  * @param {string} targetDir - Target installation directory
@@ -4374,6 +4417,8 @@ async function checkAndInstallPiper(targetDir, options) {
4374
4417
 
4375
4418
  if (hasVoices) {
4376
4419
  console.log(chalk.green(` Found ${voiceFiles.length} voice model(s)\n`));
4420
+ const piperDownloadPathEarly = path.join(targetDir, '.claude', 'hooks', 'piper-download-voices.sh');
4421
+ await offerLibriTTSDownload(piperDownloadPathEarly, options);
4377
4422
  return;
4378
4423
  }
4379
4424
  }
@@ -4402,6 +4447,7 @@ async function checkAndInstallPiper(targetDir, options) {
4402
4447
  console.log(chalk.cyan(` ${piperDownloadPath}\n`));
4403
4448
  }
4404
4449
 
4450
+ await offerLibriTTSDownload(piperDownloadPath, options);
4405
4451
  return;
4406
4452
  } catch {
4407
4453
  console.log(chalk.yellow('āš ļø Piper TTS binary not detected\n'));
@@ -4591,6 +4637,43 @@ async function checkAndInstallPiperWindows(targetDir, options) {
4591
4637
  console.log(chalk.yellow('You can download voices manually later.\n'));
4592
4638
  }
4593
4639
  }
4640
+
4641
+ // Offer LibriTTS 900+ voices (Windows — downloaded via Node directly)
4642
+ if (!options.yes && !fsSync.existsSync(path.join(voicesDir, 'en_US-libritts-high.onnx'))) {
4643
+ console.log(chalk.cyan('\nšŸŽ™ļø Want 900+ voice variations?\n'));
4644
+ console.log(chalk.gray(' The LibriTTS model includes 904 named speakers (Ryan, Sarah, Joe, and more).'));
4645
+ console.log(chalk.gray(' Browse them with /agent-vibes:list after install.'));
4646
+ console.log(chalk.gray(' Download size: ~114MB\n'));
4647
+
4648
+ const { installLibriTTSWin } = await inquirer.prompt([{
4649
+ type: 'confirm',
4650
+ name: 'installLibriTTSWin',
4651
+ message: 'Download LibriTTS voice library? (optional)',
4652
+ default: false,
4653
+ }]);
4654
+
4655
+ if (installLibriTTSWin) {
4656
+ const librittsVoices = [
4657
+ { name: 'en_US-libritts-high', path: 'en/en_US/libritts/high' },
4658
+ { name: 'en_US-libritts_r-medium', path: 'en/en_US/libritts_r/medium' },
4659
+ ];
4660
+ const piperBase = 'https://huggingface.co/rhasspy/piper-voices/resolve/main';
4661
+ await fs.mkdir(voicesDir, { recursive: true });
4662
+ for (const v of librittsVoices) {
4663
+ spinner.start(`Downloading ${v.name}...`);
4664
+ try {
4665
+ await downloadFile(`${piperBase}/${v.path}/${v.name}.onnx`, path.join(voicesDir, `${v.name}.onnx`));
4666
+ await downloadFile(`${piperBase}/${v.path}/${v.name}.onnx.json`, path.join(voicesDir, `${v.name}.onnx.json`));
4667
+ spinner.succeed(chalk.green(`Downloaded ${v.name}`));
4668
+ } catch (err) {
4669
+ spinner.fail(chalk.yellow(`Failed to download ${v.name}: ${err.message}`));
4670
+ }
4671
+ }
4672
+ console.log(chalk.green('\nāœ… LibriTTS voices ready! Browse with /agent-vibes:list\n'));
4673
+ } else {
4674
+ console.log(chalk.gray(' Skipped. Download later via: npx agentvibes → Voices tab → Install BMAD Voices\n'));
4675
+ }
4676
+ }
4594
4677
  }
4595
4678
 
4596
4679
  /**
@@ -5793,17 +5876,22 @@ Troubleshooting:
5793
5876
  if (userConfig.hermes?.enabled) {
5794
5877
  try {
5795
5878
  const hermesHooksDir = path.join(userConfig.hermes.hermesHome, 'hooks', 'agentvibes-tts');
5796
- // Validate that hermesHome stays within expected bounds (no path traversal)
5879
+ // Validate that hermesHome stays within expected bounds (no path traversal).
5880
+ // Use a trailing path.sep so a sibling like ".../hermes-evil" can't satisfy
5881
+ // the prefix check against ".../hermes".
5797
5882
  const resolvedHermesHome = path.resolve(userConfig.hermes.hermesHome);
5798
5883
  const resolvedHooksDir = path.resolve(hermesHooksDir);
5799
- if (!resolvedHooksDir.startsWith(resolvedHermesHome)) {
5884
+ if (resolvedHooksDir !== resolvedHermesHome &&
5885
+ !resolvedHooksDir.startsWith(resolvedHermesHome + path.sep)) {
5800
5886
  throw new Error('Invalid Hermes hooks path — possible path traversal');
5801
5887
  }
5802
- await fs.mkdir(hermesHooksDir, { recursive: true, mode: 0o700 });
5888
+ // S8707: writes target resolvedHooksDir, validated above to stay within
5889
+ // the user-configured hermesHome. Risk handled.
5890
+ await fs.mkdir(hermesHooksDir, { recursive: true, mode: 0o700 }); // NOSONAR
5803
5891
 
5804
5892
  // HOOK.yaml
5805
5893
  const hookYaml = `name: agentvibes-tts\ndescription: Send agent responses to AgentVibes TTS remotely\nevents:\n - agent:end\n`;
5806
- await fs.writeFile(path.join(hermesHooksDir, 'HOOK.yaml'), hookYaml, { mode: 0o600 });
5894
+ await fs.writeFile(path.join(hermesHooksDir, 'HOOK.yaml'), hookYaml, { mode: 0o600 }); // NOSONAR — see S8707 note above
5807
5895
 
5808
5896
  // handler.py — substitute config values; use JSON.stringify for safe string embedding
5809
5897
  const safeKeyPath = JSON.stringify(userConfig.hermes.sshKeyPath);
@@ -5940,7 +6028,7 @@ def _strip_markdown(text: str) -> str:
5940
6028
  text = re.sub(r"\\s+", " ", text).strip()
5941
6029
  return text
5942
6030
  `;
5943
- await fs.writeFile(path.join(hermesHooksDir, 'handler.py'), handlerPy, { mode: 0o600 });
6031
+ await fs.writeFile(path.join(hermesHooksDir, 'handler.py'), handlerPy, { mode: 0o600 }); // NOSONAR — see S8707 note above
5944
6032
  spinner.succeed(chalk.green('Hermes integration installed!'));
5945
6033
  console.log(chalk.gray(` Hooks written to: ${hermesHooksDir}`));
5946
6034
  console.log(chalk.gray(' Run: hermes gateway restart'));