agentvibes 2.0.20 → 2.0.22

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 (233) hide show
  1. package/.claude/agents/health-coach.md +154 -0
  2. package/.claude/agents/motivator.md +171 -0
  3. package/.claude/agents/negotiator.md +97 -0
  4. package/.claude/commands/agent-vibes/agent-health-coach.md +15 -0
  5. package/.claude/commands/agent-vibes/agent-motivator.md +15 -0
  6. package/.claude/commands/agent-vibes/agent-negotiator.md +15 -0
  7. package/.claude/commands/agent-vibes/agent.md +79 -0
  8. package/.claude/commands/agent-vibes/commands.json +4 -0
  9. package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -0
  10. package/.claude/github-star-reminder.txt +1 -1
  11. package/.claude/hooks/download-extra-voices.sh +244 -0
  12. package/.claude/hooks/personality-manager.sh +81 -0
  13. package/.claude/hooks/piper-download-voices.sh +3 -93
  14. package/.claude/hooks/piper-multispeaker-registry.sh +165 -0
  15. package/.claude/hooks/play-tts-elevenlabs.sh +5 -3
  16. package/.claude/hooks/play-tts-piper.sh +27 -44
  17. package/.claude/hooks/provider-manager.sh +24 -5
  18. package/.claude/hooks/speed-manager.sh +10 -12
  19. package/.claude/hooks/voice-manager.sh +94 -56
  20. package/README.md +0 -3
  21. package/RELEASE_NOTES.md +40 -247
  22. package/docs/agents.md +485 -0
  23. package/docs/commands.md +1 -21
  24. package/docs/extra-voices-implementation-summary.md +235 -0
  25. package/docs/voice-registration-fix.md +254 -0
  26. package/fix-vscode-colors.sh +88 -0
  27. package/fixcolors +88 -0
  28. package/generate-all-agent-voices.sh +174 -0
  29. package/generate-missing-elevenlabs-complete.sh +236 -0
  30. package/generate-missing-elevenlabs.sh +110 -0
  31. package/generate-new-voices.sh +108 -0
  32. package/generate-piper-agent-intros.sh +85 -0
  33. package/generate-provider-and-agent-intros.sh +136 -0
  34. package/logo/fav_icon_128x128.png +0 -0
  35. package/logo/fav_icon_128x128.png:Zone.Identifier +4 -0
  36. package/logo/logo1.webp +0 -0
  37. package/logo/logo1.webp:Zone.Identifier +4 -0
  38. package/logo/social.png +0 -0
  39. package/logo/social.png:Zone.Identifier +4 -0
  40. package/mcp-server/agentvibes.db +0 -0
  41. package/mcp-server/server.py +47 -14
  42. package/package.json +3 -3
  43. package/regenerate-agent-voices.sh +79 -0
  44. package/test/unit/provider-manager.bats +8 -5
  45. package/test/unit/speed-manager.bats +4 -4
  46. package/agentvibes.org/.claude/audio/tts-padded-1760744118.mp3 +0 -0
  47. package/agentvibes.org/.claude/audio/tts-padded-1760748535.mp3 +0 -0
  48. package/agentvibes.org/.claude/audio/tts-padded-1760748676.mp3 +0 -0
  49. package/agentvibes.org/.claude/audio/tts-padded-1760750748.mp3 +0 -0
  50. package/agentvibes.org/.claude/audio/tts-padded-1760750947.mp3 +0 -0
  51. package/agentvibes.org/.claude/audio/tts-padded-1760752718.mp3 +0 -0
  52. package/agentvibes.org/.claude/audio/tts-padded-1760752907.mp3 +0 -0
  53. package/agentvibes.org/.claude/audio/tts-padded-1760753017.mp3 +0 -0
  54. package/agentvibes.org/.claude/audio/tts-padded-1760753045.mp3 +0 -0
  55. package/agentvibes.org/.claude/audio/tts-padded-1760753241.mp3 +0 -0
  56. package/agentvibes.org/.claude/audio/tts-padded-1760753315.mp3 +0 -0
  57. package/agentvibes.org/.claude/audio/tts-padded-1760753382.mp3 +0 -0
  58. package/agentvibes.org/.claude/audio/tts-padded-1760753408.mp3 +0 -0
  59. package/agentvibes.org/.claude/audio/tts-padded-1760753426.mp3 +0 -0
  60. package/agentvibes.org/.claude/audio/tts-padded-1760753446.mp3 +0 -0
  61. package/agentvibes.org/.claude/audio/tts-padded-1760753541.mp3 +0 -0
  62. package/agentvibes.org/.claude/audio/tts-padded-1760753553.mp3 +0 -0
  63. package/agentvibes.org/.claude/audio/tts-padded-1760753577.mp3 +0 -0
  64. package/agentvibes.org/.claude/commands/agent-vibes/add.md +0 -21
  65. package/agentvibes.org/.claude/commands/agent-vibes/agent-vibes.md +0 -68
  66. package/agentvibes.org/.claude/commands/agent-vibes/bmad.md +0 -196
  67. package/agentvibes.org/.claude/commands/agent-vibes/commands.json +0 -77
  68. package/agentvibes.org/.claude/commands/agent-vibes/get.md +0 -9
  69. package/agentvibes.org/.claude/commands/agent-vibes/language.md +0 -23
  70. package/agentvibes.org/.claude/commands/agent-vibes/learn.md +0 -67
  71. package/agentvibes.org/.claude/commands/agent-vibes/list.md +0 -13
  72. package/agentvibes.org/.claude/commands/agent-vibes/personality.md +0 -79
  73. package/agentvibes.org/.claude/commands/agent-vibes/preview.md +0 -17
  74. package/agentvibes.org/.claude/commands/agent-vibes/provider.md +0 -54
  75. package/agentvibes.org/.claude/commands/agent-vibes/replay-target.md +0 -14
  76. package/agentvibes.org/.claude/commands/agent-vibes/replay.md +0 -19
  77. package/agentvibes.org/.claude/commands/agent-vibes/sample.md +0 -12
  78. package/agentvibes.org/.claude/commands/agent-vibes/sentiment.md +0 -52
  79. package/agentvibes.org/.claude/commands/agent-vibes/set-language.md +0 -47
  80. package/agentvibes.org/.claude/commands/agent-vibes/set-pretext.md +0 -65
  81. package/agentvibes.org/.claude/commands/agent-vibes/set-speed.md +0 -41
  82. package/agentvibes.org/.claude/commands/agent-vibes/switch.md +0 -53
  83. package/agentvibes.org/.claude/commands/agent-vibes/target-voice.md +0 -26
  84. package/agentvibes.org/.claude/commands/agent-vibes/target.md +0 -30
  85. package/agentvibes.org/.claude/commands/agent-vibes/update.md +0 -20
  86. package/agentvibes.org/.claude/commands/agent-vibes/version.md +0 -10
  87. package/agentvibes.org/.claude/commands/agent-vibes/whoami.md +0 -7
  88. package/agentvibes.org/.claude/hooks/bmad-tts-injector.sh +0 -386
  89. package/agentvibes.org/.claude/hooks/bmad-voice-manager.sh +0 -375
  90. package/agentvibes.org/.claude/hooks/check-output-style.sh +0 -60
  91. package/agentvibes.org/.claude/hooks/github-star-reminder.sh +0 -94
  92. package/agentvibes.org/.claude/hooks/language-manager.sh +0 -360
  93. package/agentvibes.org/.claude/hooks/learn-manager.sh +0 -443
  94. package/agentvibes.org/.claude/hooks/personality-manager.sh +0 -324
  95. package/agentvibes.org/.claude/hooks/piper-download-voices.sh +0 -133
  96. package/agentvibes.org/.claude/hooks/piper-installer.sh +0 -144
  97. package/agentvibes.org/.claude/hooks/piper-voice-manager.sh +0 -227
  98. package/agentvibes.org/.claude/hooks/play-tts-elevenlabs.sh +0 -376
  99. package/agentvibes.org/.claude/hooks/play-tts-piper.sh +0 -281
  100. package/agentvibes.org/.claude/hooks/play-tts.sh +0 -69
  101. package/agentvibes.org/.claude/hooks/provider-commands.sh +0 -505
  102. package/agentvibes.org/.claude/hooks/provider-manager.sh +0 -248
  103. package/agentvibes.org/.claude/hooks/replay-target-audio.sh +0 -64
  104. package/agentvibes.org/.claude/hooks/sentiment-manager.sh +0 -163
  105. package/agentvibes.org/.claude/hooks/speed-manager.sh +0 -259
  106. package/agentvibes.org/.claude/hooks/voice-manager.sh +0 -477
  107. package/agentvibes.org/.claude/hooks/voices-config.sh +0 -33
  108. package/agentvibes.org/.claude/journal/2025-10-07.html +0 -373
  109. package/agentvibes.org/.claude/journal/index.html +0 -91
  110. package/agentvibes.org/.claude/output-styles/agent-vibes.md +0 -203
  111. package/agentvibes.org/.claude/personalities/angry.md +0 -17
  112. package/agentvibes.org/.claude/personalities/annoying.md +0 -17
  113. package/agentvibes.org/.claude/personalities/crass.md +0 -17
  114. package/agentvibes.org/.claude/personalities/dramatic.md +0 -17
  115. package/agentvibes.org/.claude/personalities/dry-humor.md +0 -53
  116. package/agentvibes.org/.claude/personalities/flirty.md +0 -23
  117. package/agentvibes.org/.claude/personalities/funny.md +0 -17
  118. package/agentvibes.org/.claude/personalities/grandpa.md +0 -35
  119. package/agentvibes.org/.claude/personalities/millennial.md +0 -17
  120. package/agentvibes.org/.claude/personalities/moody.md +0 -17
  121. package/agentvibes.org/.claude/personalities/normal.md +0 -19
  122. package/agentvibes.org/.claude/personalities/pirate.md +0 -17
  123. package/agentvibes.org/.claude/personalities/poetic.md +0 -17
  124. package/agentvibes.org/.claude/personalities/professional.md +0 -17
  125. package/agentvibes.org/.claude/personalities/robot.md +0 -17
  126. package/agentvibes.org/.claude/personalities/sarcastic.md +0 -41
  127. package/agentvibes.org/.claude/personalities/sassy.md +0 -17
  128. package/agentvibes.org/.claude/personalities/surfer-dude.md +0 -17
  129. package/agentvibes.org/.claude/personalities/zen.md +0 -17
  130. package/agentvibes.org/.claude/piper-voices-dir.txt +0 -1
  131. package/agentvibes.org/.claude/plugins/bmad-voices.md +0 -42
  132. package/agentvibes.org/.claude/tts-provider.txt +0 -1
  133. package/agentvibes.org/.mcp-minimal.json +0 -60
  134. package/agentvibes.org/CHANGELOG.md +0 -56
  135. package/agentvibes.org/README.md +0 -93
  136. package/agentvibes.org/app/(auth)/layout.tsx +0 -15
  137. package/agentvibes.org/app/(auth)/reset-password/page.tsx +0 -45
  138. package/agentvibes.org/app/(auth)/signin/page.tsx +0 -82
  139. package/agentvibes.org/app/(auth)/signup/page.tsx +0 -104
  140. package/agentvibes.org/app/(default)/blog/[slug]/page.tsx +0 -128
  141. package/agentvibes.org/app/(default)/blog/page.tsx +0 -95
  142. package/agentvibes.org/app/(default)/layout.tsx +0 -31
  143. package/agentvibes.org/app/(default)/page.tsx +0 -20
  144. package/agentvibes.org/app/api/hello/route.ts +0 -3
  145. package/agentvibes.org/app/css/additional-styles/theme.css +0 -82
  146. package/agentvibes.org/app/css/additional-styles/utility-patterns.css +0 -55
  147. package/agentvibes.org/app/css/style.css +0 -100
  148. package/agentvibes.org/app/layout.tsx +0 -63
  149. package/agentvibes.org/components/code-block.tsx +0 -27
  150. package/agentvibes.org/components/cta.tsx +0 -58
  151. package/agentvibes.org/components/features.tsx +0 -256
  152. package/agentvibes.org/components/hero-home.tsx +0 -133
  153. package/agentvibes.org/components/mdx-components.tsx +0 -128
  154. package/agentvibes.org/components/modal-video.tsx +0 -137
  155. package/agentvibes.org/components/page-illustration.tsx +0 -55
  156. package/agentvibes.org/components/spotlight.tsx +0 -77
  157. package/agentvibes.org/components/testimonials.tsx +0 -282
  158. package/agentvibes.org/components/ui/footer.tsx +0 -82
  159. package/agentvibes.org/components/ui/header.tsx +0 -68
  160. package/agentvibes.org/components/ui/logo.tsx +0 -10
  161. package/agentvibes.org/components/workflows.tsx +0 -176
  162. package/agentvibes.org/content/blog/discovering-new-piper-voices.mdx +0 -253
  163. package/agentvibes.org/content/blog/getting-started-agentvibes.mdx +0 -228
  164. package/agentvibes.org/content/blog/introducing-agentvibes-v2.mdx +0 -250
  165. package/agentvibes.org/content/blog/language-learning-with-agentvibes.mdx +0 -142
  166. package/agentvibes.org/content/blog/voice-personalities-guide.mdx +0 -119
  167. package/agentvibes.org/lib/blog.ts +0 -73
  168. package/agentvibes.org/next.config.js +0 -6
  169. package/agentvibes.org/package-lock.json +0 -4285
  170. package/agentvibes.org/package.json +0 -40
  171. package/agentvibes.org/pnpm-lock.yaml +0 -1141
  172. package/agentvibes.org/postcss.config.js +0 -5
  173. package/agentvibes.org/public/audio/02-sarcastic.mp3 +0 -0
  174. package/agentvibes.org/public/audio/03-angry.mp3 +0 -0
  175. package/agentvibes.org/public/audio/04-grandpa.mp3 +0 -0
  176. package/agentvibes.org/public/audio/05-sarcastic-example2.mp3 +0 -0
  177. package/agentvibes.org/public/audio/french-rachel.mp3 +0 -0
  178. package/agentvibes.org/public/audio/piper-voices/speaker_0_Cori_Samuel.wav +0 -0
  179. package/agentvibes.org/public/audio/piper-voices/speaker_10_Steve_C.wav +0 -0
  180. package/agentvibes.org/public/audio/piper-voices/speaker_11_Owlivia.wav +0 -0
  181. package/agentvibes.org/public/audio/piper-voices/speaker_12_Paul_Hampton.wav +0 -0
  182. package/agentvibes.org/public/audio/piper-voices/speaker_13_Jennifer_Dorr.wav +0 -0
  183. package/agentvibes.org/public/audio/piper-voices/speaker_14_Emily_Cripps.wav +0 -0
  184. package/agentvibes.org/public/audio/piper-voices/speaker_15_Martin_Clifton.wav +0 -0
  185. package/agentvibes.org/public/audio/piper-voices/speaker_1_Kara_Shallenberg.wav +0 -0
  186. package/agentvibes.org/public/audio/piper-voices/speaker_2_Kristin_Hughes.wav +0 -0
  187. package/agentvibes.org/public/audio/piper-voices/speaker_3_Maria_Kasper.wav +0 -0
  188. package/agentvibes.org/public/audio/piper-voices/speaker_4_Mike_Pelton.wav +0 -0
  189. package/agentvibes.org/public/audio/piper-voices/speaker_5_Mark_Nelson.wav +0 -0
  190. package/agentvibes.org/public/audio/piper-voices/speaker_6_Michael_Scherer.wav +0 -0
  191. package/agentvibes.org/public/audio/piper-voices/speaker_7_James_K_White.wav +0 -0
  192. package/agentvibes.org/public/audio/piper-voices/speaker_8_Rose_Ibex.wav +0 -0
  193. package/agentvibes.org/public/audio/piper-voices/speaker_9_progressingamerica.wav +0 -0
  194. package/agentvibes.org/public/audio/spanish-antoni.mp3 +0 -0
  195. package/agentvibes.org/public/favicon.ico +0 -0
  196. package/agentvibes.org/public/fonts/nacelle-italic.woff2 +0 -0
  197. package/agentvibes.org/public/fonts/nacelle-regular.woff2 +0 -0
  198. package/agentvibes.org/public/fonts/nacelle-semibold.woff2 +0 -0
  199. package/agentvibes.org/public/fonts/nacelle-semibolditalic.woff2 +0 -0
  200. package/agentvibes.org/public/images/blurred-shape-gray.svg +0 -1
  201. package/agentvibes.org/public/images/blurred-shape.svg +0 -1
  202. package/agentvibes.org/public/images/client-logo-01.svg +0 -1
  203. package/agentvibes.org/public/images/client-logo-02.svg +0 -1
  204. package/agentvibes.org/public/images/client-logo-03.svg +0 -1
  205. package/agentvibes.org/public/images/client-logo-04.svg +0 -1
  206. package/agentvibes.org/public/images/client-logo-05.svg +0 -1
  207. package/agentvibes.org/public/images/client-logo-06.svg +0 -1
  208. package/agentvibes.org/public/images/client-logo-07.svg +0 -1
  209. package/agentvibes.org/public/images/client-logo-08.svg +0 -1
  210. package/agentvibes.org/public/images/client-logo-09.svg +0 -1
  211. package/agentvibes.org/public/images/features.png +0 -0
  212. package/agentvibes.org/public/images/footer-illustration.svg +0 -1
  213. package/agentvibes.org/public/images/hero-image-01.jpg +0 -0
  214. package/agentvibes.org/public/images/logo.svg +0 -1
  215. package/agentvibes.org/public/images/page-illustration.svg +0 -1
  216. package/agentvibes.org/public/images/secondary-illustration.svg +0 -1
  217. package/agentvibes.org/public/images/testimonial-01.jpg +0 -0
  218. package/agentvibes.org/public/images/testimonial-02.jpg +0 -0
  219. package/agentvibes.org/public/images/testimonial-03.jpg +0 -0
  220. package/agentvibes.org/public/images/testimonial-04.jpg +0 -0
  221. package/agentvibes.org/public/images/testimonial-05.jpg +0 -0
  222. package/agentvibes.org/public/images/testimonial-06.jpg +0 -0
  223. package/agentvibes.org/public/images/testimonial-07.jpg +0 -0
  224. package/agentvibes.org/public/images/testimonial-08.jpg +0 -0
  225. package/agentvibes.org/public/images/testimonial-09.jpg +0 -0
  226. package/agentvibes.org/public/images/workflow-01.png +0 -0
  227. package/agentvibes.org/public/images/workflow-02.png +0 -0
  228. package/agentvibes.org/public/images/workflow-03.png +0 -0
  229. package/agentvibes.org/public/videos/video.mp4 +0 -0
  230. package/agentvibes.org/tsconfig.json +0 -28
  231. package/agentvibes.org/utils/useMasonry.tsx +0 -67
  232. package/agentvibes.org/utils/useMousePosition.tsx +0 -27
  233. package/docs/bryce-beattie-voice-licensing.md +0 -131
@@ -75,8 +75,18 @@ else
75
75
 
76
76
  if [[ -n "$VOICE_FILE" ]]; then
77
77
  FILE_VOICE=$(cat "$VOICE_FILE" 2>/dev/null)
78
- # Check if it's a Piper model name (contains underscore and dash, or speaker ID with #)
79
- if [[ "$FILE_VOICE" == *"_"*"-"* ]] || [[ "$FILE_VOICE" == *"#"* ]]; then
78
+
79
+ # Check for multi-speaker voice (model + speaker ID stored separately)
80
+ MODEL_FILE="$SCRIPT_DIR/../tts-piper-model.txt"
81
+ SPEAKER_ID_FILE="$SCRIPT_DIR/../tts-piper-speaker-id.txt"
82
+
83
+ if [[ -f "$MODEL_FILE" ]] && [[ -f "$SPEAKER_ID_FILE" ]]; then
84
+ # Multi-speaker voice
85
+ VOICE_MODEL=$(cat "$MODEL_FILE" 2>/dev/null)
86
+ SPEAKER_ID=$(cat "$SPEAKER_ID_FILE" 2>/dev/null)
87
+ echo "🎭 Using multi-speaker voice: $FILE_VOICE (Model: $VOICE_MODEL, Speaker ID: $SPEAKER_ID)"
88
+ # Check if it's a standard Piper model name or custom voice (just use as-is)
89
+ elif [[ -n "$FILE_VOICE" ]]; then
80
90
  VOICE_MODEL="$FILE_VOICE"
81
91
  fi
82
92
  fi
@@ -118,21 +128,7 @@ fi
118
128
  # @param Uses global: $VOICE_MODEL
119
129
  # @sideeffects Downloads voice model files
120
130
  # @edgecases Prompts user for consent before downloading
121
-
122
- # Strip speaker ID for verification/download (speaker ID is after #)
123
- VOICE_MODEL_BASE="$VOICE_MODEL"
124
- if [[ "$VOICE_MODEL" == *"#"* ]]; then
125
- VOICE_MODEL_BASE="${VOICE_MODEL%%#*}"
126
- fi
127
-
128
- # Check if custom voice exists (bypass verification for custom voices)
129
- CUSTOM_VOICE_PATH="$HOME/.local/share/piper/voices/$VOICE_MODEL_BASE.onnx"
130
- IS_CUSTOM_VOICE=false
131
- if [[ -f "$CUSTOM_VOICE_PATH" ]]; then
132
- IS_CUSTOM_VOICE=true
133
- fi
134
-
135
- if [[ "$IS_CUSTOM_VOICE" == "false" ]] && ! verify_voice "$VOICE_MODEL_BASE"; then
131
+ if ! verify_voice "$VOICE_MODEL"; then
136
132
  echo "📥 Voice model not found: $VOICE_MODEL"
137
133
  echo " File size: ~25MB"
138
134
  echo " Preview: https://huggingface.co/rhasspy/piper-voices"
@@ -141,7 +137,7 @@ if [[ "$IS_CUSTOM_VOICE" == "false" ]] && ! verify_voice "$VOICE_MODEL_BASE"; th
141
137
  echo
142
138
 
143
139
  if [[ $REPLY =~ ^[Yy]$ ]]; then
144
- if ! download_voice "$VOICE_MODEL_BASE"; then
140
+ if ! download_voice "$VOICE_MODEL"; then
145
141
  echo "❌ Failed to download voice model"
146
142
  echo "Fix: Download manually or choose different voice"
147
143
  exit 3
@@ -152,19 +148,11 @@ if [[ "$IS_CUSTOM_VOICE" == "false" ]] && ! verify_voice "$VOICE_MODEL_BASE"; th
152
148
  fi
153
149
  fi
154
150
 
155
- # Get voice model path (use base model without speaker ID)
156
- # Suppress stderr from get_voice_path since we have custom voice fallback
157
- VOICE_PATH=$(get_voice_path "$VOICE_MODEL_BASE" 2>/dev/null)
151
+ # Get voice model path
152
+ VOICE_PATH=$(get_voice_path "$VOICE_MODEL")
158
153
  if [[ $? -ne 0 ]]; then
159
- # Try custom voice in piper voices directory
160
- CUSTOM_PATH="$HOME/.local/share/piper/voices/$VOICE_MODEL_BASE.onnx"
161
- if [[ -f "$CUSTOM_PATH" ]]; then
162
- VOICE_PATH="$CUSTOM_PATH"
163
- echo "🎤 Using custom voice: $VOICE_MODEL_BASE"
164
- else
165
- echo "❌ Voice model path not found: $VOICE_MODEL"
166
- exit 3
167
- fi
154
+ echo "❌ Voice model path not found: $VOICE_MODEL"
155
+ exit 3
168
156
  fi
169
157
 
170
158
  # @function determine_audio_directory
@@ -254,23 +242,16 @@ SPEECH_RATE=$(get_speech_rate)
254
242
  # @function synthesize_with_piper
255
243
  # @intent Generate speech using Piper TTS
256
244
  # @why Provides free, offline TTS alternative
257
- # @param Uses globals: $TEXT, $VOICE_PATH, $SPEECH_RATE, $VOICE_MODEL
245
+ # @param Uses globals: $TEXT, $VOICE_PATH, $SPEECH_RATE, $SPEAKER_ID (optional)
258
246
  # @returns Creates WAV file at $TEMP_FILE
259
247
  # @exitcode 0=success, 4=synthesis error
260
248
  # @sideeffects Creates audio file
261
- # @edgecases Handles piper errors, invalid models, speaker IDs
262
-
263
- # Check if voice model includes speaker ID (format: modelname#speakerID)
264
- SPEAKER_ID=""
265
- if [[ "$VOICE_MODEL" == *"#"* ]]; then
266
- SPEAKER_ID="${VOICE_MODEL##*#}"
267
- VOICE_MODEL="${VOICE_MODEL%%#*}"
268
- fi
269
-
270
- # Build piper command with optional speaker parameter
249
+ # @edgecases Handles piper errors, invalid models, multi-speaker voices
271
250
  if [[ -n "$SPEAKER_ID" ]]; then
251
+ # Multi-speaker voice: Pass speaker ID
272
252
  echo "$TEXT" | piper --model "$VOICE_PATH" --speaker "$SPEAKER_ID" --length-scale "$SPEECH_RATE" --output_file "$TEMP_FILE" 2>/dev/null
273
253
  else
254
+ # Single-speaker voice
274
255
  echo "$TEXT" | piper --model "$VOICE_PATH" --length-scale "$SPEECH_RATE" --output_file "$TEMP_FILE" 2>/dev/null
275
256
  fi
276
257
 
@@ -330,9 +311,11 @@ DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wr
330
311
  DURATION=${DURATION%.*} # Round to integer
331
312
  DURATION=${DURATION:-1} # Default to 1 second if detection fails
332
313
 
333
- # Play audio in background
334
- (mpv "$TEMP_FILE" || aplay "$TEMP_FILE" || paplay "$TEMP_FILE") >/dev/null 2>&1 &
335
- PLAYER_PID=$!
314
+ # Play audio in background (skip if in test mode)
315
+ if [[ "${AGENTVIBES_TEST_MODE:-false}" != "true" ]]; then
316
+ (mpv "$TEMP_FILE" || aplay "$TEMP_FILE" || paplay "$TEMP_FILE") >/dev/null 2>&1 &
317
+ PLAYER_PID=$!
318
+ fi
336
319
 
337
320
  # Wait for audio to finish, then release lock
338
321
  (sleep $DURATION; rm -f "$LOCK_FILE") &
@@ -141,12 +141,31 @@ set_active_provider() {
141
141
  voice_file="$HOME/.claude/tts-voice.txt"
142
142
  fi
143
143
 
144
- # Remove voice file to force default voice for new provider
145
- if [[ -f "$voice_file" ]]; then
146
- rm -f "$voice_file"
147
- fi
144
+ # Set default voice for the new provider
145
+ local default_voice
146
+ case "$provider" in
147
+ piper)
148
+ # Default Piper voice
149
+ default_voice="en_US-lessac-medium"
150
+ ;;
151
+ elevenlabs)
152
+ # Default ElevenLabs voice (first in alphabetical order from voices-config.sh)
153
+ default_voice="Amy"
154
+ ;;
155
+ *)
156
+ # Unknown provider - remove voice file
157
+ if [[ -f "$voice_file" ]]; then
158
+ rm -f "$voice_file"
159
+ fi
160
+ echo "✓ Active provider set to: $provider (voice reset)"
161
+ return 0
162
+ ;;
163
+ esac
164
+
165
+ # Write default voice to file
166
+ echo "$default_voice" > "$voice_file"
148
167
 
149
- echo "✓ Active provider set to: $provider (voice reset to default)"
168
+ echo "✓ Active provider set to: $provider (voice set to: $default_voice)"
150
169
  }
151
170
 
152
171
  # @function list_providers
@@ -191,20 +191,18 @@ set_speed() {
191
191
  echo ""
192
192
  echo "Note: Speed control works with both Piper and ElevenLabs providers"
193
193
 
194
- # Array of tongue twisters to demonstrate speed
195
- local tongue_twisters=(
196
- "Peter Piper picked a peck of pickled peppers"
197
- "She sells seashells by the seashore"
198
- "How much wood would a woodchuck chuck if a woodchuck could chuck wood"
199
- "Fuzzy Wuzzy was a bear, Fuzzy Wuzzy had no hair"
200
- "I scream, you scream, we all scream for ice cream"
201
- "Red lorry, yellow lorry, red lorry, yellow lorry"
202
- "Six slippery snails slid slowly seaward"
194
+ # Array of simple test messages to demonstrate speed
195
+ local test_messages=(
196
+ "Testing speed change"
197
+ "Speed test in progress"
198
+ "Checking audio speed"
199
+ "Speed configuration test"
200
+ "Audio speed test"
203
201
  )
204
202
 
205
- # Pick a random tongue twister
206
- local random_index=$((RANDOM % ${#tongue_twisters[@]}))
207
- local test_msg="${tongue_twisters[$random_index]}"
203
+ # Pick a random test message
204
+ local random_index=$((RANDOM % ${#test_messages[@]}))
205
+ local test_msg="${test_messages[$random_index]}"
208
206
 
209
207
  echo ""
210
208
  echo "🔊 Testing new speed with: \"$test_msg\""
@@ -87,64 +87,17 @@ case "$1" in
87
87
  source "$SCRIPT_DIR/piper-voice-manager.sh"
88
88
  VOICE_DIR=$(get_voice_storage_dir)
89
89
  VOICE_COUNT=0
90
-
91
- # Extract base voice name and speaker ID from current voice if it has # format
92
- CURRENT_BASE_VOICE="$CURRENT_VOICE"
93
- CURRENT_SPEAKER_ID=""
94
- if [[ "$CURRENT_VOICE" == *"#"* ]]; then
95
- CURRENT_BASE_VOICE="${CURRENT_VOICE%%#*}"
96
- CURRENT_SPEAKER_ID="${CURRENT_VOICE##*#}"
97
- fi
98
-
99
90
  for onnx_file in "$VOICE_DIR"/*.onnx; do
100
91
  if [[ -f "$onnx_file" ]]; then
101
92
  voice=$(basename "$onnx_file" .onnx)
102
- json_file="${onnx_file}.json"
103
-
104
- # Check if this is a multi-speaker voice
105
- if [[ -f "$json_file" ]] && command -v jq &> /dev/null; then
106
- NUM_SPEAKERS=$(jq -r '.num_speakers // 1' "$json_file" 2>/dev/null)
107
-
108
- if [[ "$NUM_SPEAKERS" -gt 1 ]]; then
109
- # Multi-speaker voice - list all speakers
110
- echo ""
111
- echo " 📢 $voice (Multi-speaker: $NUM_SPEAKERS voices)"
112
-
113
- # Read speaker names from JSON
114
- jq -r '.speaker_id_map | to_entries[] | " \(.value)️. \(.key) → \(.value|tostring)#\(.value)"' "$json_file" 2>/dev/null | while read -r speaker_line; do
115
- # Extract speaker ID from the line
116
- speaker_id=$(echo "$speaker_line" | sed -E 's/.*→ ([0-9]+)#[0-9]+$/\1/')
117
-
118
- # Check if this speaker is current
119
- if [[ "$voice" == "$CURRENT_BASE_VOICE" ]] && [[ "$speaker_id" == "$CURRENT_SPEAKER_ID" ]]; then
120
- # Remove the → ID#ID suffix and add current marker
121
- speaker_display=$(echo "$speaker_line" | sed -E 's/ → [0-9]+#[0-9]+$//')
122
- echo " ▶ $speaker_display (current)"
123
- else
124
- # Remove the → ID#ID suffix
125
- speaker_display=$(echo "$speaker_line" | sed -E 's/ → [0-9]+#[0-9]+$//')
126
- echo " $speaker_display"
127
- fi
128
- done
129
- else
130
- # Single-speaker voice
131
- if [ "$voice" = "$CURRENT_VOICE" ] || [ "$voice" = "$CURRENT_BASE_VOICE" ]; then
132
- echo " ▶ $voice (current)"
133
- else
134
- echo " $voice"
135
- fi
136
- fi
93
+ if [ "$voice" = "$CURRENT_VOICE" ]; then
94
+ echo " ▶ $voice (current)"
137
95
  else
138
- # No JSON file or jq not available - show as single voice
139
- if [ "$voice" = "$CURRENT_VOICE" ] || [ "$voice" = "$CURRENT_BASE_VOICE" ]; then
140
- echo " ▶ $voice (current)"
141
- else
142
- echo " $voice"
143
- fi
96
+ echo " $voice"
144
97
  fi
145
98
  ((VOICE_COUNT++))
146
99
  fi
147
- done
100
+ done | sort
148
101
 
149
102
  if [[ $VOICE_COUNT -eq 0 ]]; then
150
103
  echo " (No Piper voices downloaded yet)"
@@ -309,11 +262,96 @@ case "$1" in
309
262
  ACTIVE_PROVIDER=$(cat "$PROVIDER_FILE")
310
263
  fi
311
264
 
312
- # If using Piper and voice name looks like a Piper model (contains underscore and dash)
313
- # then skip ElevenLabs voice validation
314
- if [[ "$ACTIVE_PROVIDER" == "piper" ]] && [[ "$VOICE_NAME" == *"_"*"-"* ]]; then
315
- # This is a Piper model name, use it directly
316
- FOUND="$VOICE_NAME"
265
+ # Voice lookup strategy depends on active provider
266
+ if [[ "$ACTIVE_PROVIDER" == "piper" ]]; then
267
+ # Piper voice lookup: Scan voice directory for .onnx files
268
+ source "$SCRIPT_DIR/piper-voice-manager.sh"
269
+ VOICE_DIR=$(get_voice_storage_dir)
270
+
271
+ # Check if voice file exists (case-insensitive)
272
+ FOUND=""
273
+ shopt -s nullglob
274
+ for onnx_file in "$VOICE_DIR"/*.onnx; do
275
+ if [[ -f "$onnx_file" ]]; then
276
+ voice=$(basename "$onnx_file" .onnx)
277
+ if [[ "${voice,,}" == "${VOICE_NAME,,}" ]]; then
278
+ FOUND="$voice"
279
+ break
280
+ fi
281
+ fi
282
+ done
283
+ shopt -u nullglob
284
+
285
+ # If not found, check multi-speaker registry
286
+ if [[ -z "$FOUND" ]] && [[ -f "$SCRIPT_DIR/piper-multispeaker-registry.sh" ]]; then
287
+ source "$SCRIPT_DIR/piper-multispeaker-registry.sh"
288
+
289
+ MULTISPEAKER_INFO=$(get_multispeaker_info "$VOICE_NAME")
290
+ if [[ -n "$MULTISPEAKER_INFO" ]]; then
291
+ MODEL="${MULTISPEAKER_INFO%%:*}"
292
+ SPEAKER_ID="${MULTISPEAKER_INFO#*:}"
293
+
294
+ # Verify the model file exists
295
+ if [[ -f "$VOICE_DIR/${MODEL}.onnx" ]]; then
296
+ # Store speaker name in tts-voice.txt
297
+ echo "$VOICE_NAME" > "$VOICE_FILE"
298
+
299
+ # Store model and speaker ID separately for play-tts-piper.sh
300
+ echo "$MODEL" > "$CLAUDE_DIR/tts-piper-model.txt"
301
+ echo "$SPEAKER_ID" > "$CLAUDE_DIR/tts-piper-speaker-id.txt"
302
+
303
+ DESCRIPTION=$(get_multispeaker_description "$VOICE_NAME")
304
+ echo "✅ Multi-speaker voice switched to: $VOICE_NAME"
305
+ echo "🎤 Model: $MODEL.onnx (Speaker ID: $SPEAKER_ID)"
306
+ if [[ -n "$DESCRIPTION" ]]; then
307
+ echo "📝 Description: $DESCRIPTION"
308
+ fi
309
+
310
+ # Have the new voice introduce itself (unless silent mode)
311
+ if [[ "$SILENT_MODE" != "true" ]]; then
312
+ PLAY_TTS="$SCRIPT_DIR/play-tts.sh"
313
+ if [ -x "$PLAY_TTS" ]; then
314
+ "$PLAY_TTS" "Hi, I'm $VOICE_NAME. I'll be your voice assistant moving forward." > /dev/null 2>&1 &
315
+ fi
316
+
317
+ echo ""
318
+ echo "💡 Tip: To hear automatic TTS narration, enable the Agent Vibes output style:"
319
+ echo " /output-style Agent Vibes"
320
+ fi
321
+ exit 0
322
+ else
323
+ echo "❌ Multi-speaker model not found: $MODEL.onnx"
324
+ echo ""
325
+ echo "Download it with: /agent-vibes:provider download"
326
+ exit 1
327
+ fi
328
+ fi
329
+ fi
330
+
331
+ if [[ -z "$FOUND" ]]; then
332
+ echo "❌ Piper voice not found: $VOICE_NAME"
333
+ echo ""
334
+ echo "Available Piper voices:"
335
+ shopt -s nullglob
336
+ for onnx_file in "$VOICE_DIR"/*.onnx; do
337
+ if [[ -f "$onnx_file" ]]; then
338
+ echo " - $(basename "$onnx_file" .onnx)"
339
+ fi
340
+ done | sort
341
+ shopt -u nullglob
342
+ echo ""
343
+ if [[ -f "$SCRIPT_DIR/piper-multispeaker-registry.sh" ]]; then
344
+ echo "Multi-speaker voices (requires 16Speakers.onnx):"
345
+ source "$SCRIPT_DIR/piper-multispeaker-registry.sh"
346
+ for entry in "${MULTISPEAKER_VOICES[@]}"; do
347
+ name="${entry%%:*}"
348
+ echo " - $name"
349
+ done | sort
350
+ echo ""
351
+ fi
352
+ echo "Download extra voices with: /agent-vibes:provider download"
353
+ exit 1
354
+ fi
317
355
  else
318
356
  # ElevenLabs voice lookup
319
357
  # Check if input is a number
package/README.md CHANGED
@@ -311,8 +311,6 @@ AgentVibes supports **custom personalities**, **custom voices**, and **integrati
311
311
  - 🗣️ **[OpenWhisper (Azure)](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/whisper-overview)** - Microsoft's speech-to-text service
312
312
  - 🎙️ **[ElevenLabs](https://elevenlabs.io/)** - Premium AI voice synthesis
313
313
  - 🆓 **[Piper TTS](https://github.com/rhasspy/piper)** - Free offline neural TTS
314
- - 🎨 **[Custom Piper Voices by Bryce Beattie](https://brycebeattie.com/files/tts/)** - High-quality community Piper voices (Kristin, Jenny)
315
- - 🛠️ **[Create Custom Piper TTS Voice](https://ssamjh.nz/create-custom-piper-tts-voice/)** - Tutorial for training your own Piper voices
316
314
  - 🤖 **[Claude Code](https://claude.com/claude-code)** - AI coding assistant
317
315
  - 🎭 **[BMAD METHOD](https://github.com/bmad-code-org/BMAD-METHOD)** - Multi-agent framework
318
316
 
@@ -420,7 +418,6 @@ npm update -g agentvibes && agentvibes update --yes
420
418
  **Special Thanks:**
421
419
  - 💡 [Claude Code Hooks Mastery](https://github.com/disler/claude-code-hooks-mastery) by [@disler](https://github.com/disler) - Hooks inspiration
422
420
  - 🤖 [BMAD METHOD](https://github.com/bmad-code-org/BMAD-METHOD) - Multi-agent framework with auto voice switching integration
423
- - 🎨 [Bryce Beattie](https://brycebeattie.com/files/tts/) - Custom high-quality Piper voices (Kristin, Jenny)
424
421
 
425
422
  [↑ Back to top](#-table-of-contents)
426
423