agentvibes 4.0.1 → 4.4.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 (219) hide show
  1. package/.agentvibes/bmad/bmad-voices.md +69 -69
  2. package/.agentvibes/config.json +12 -0
  3. package/.claude/activation-instructions +54 -54
  4. package/.claude/audio/tracks/README.md +52 -52
  5. package/.claude/commands/agent-vibes/add.md +21 -21
  6. package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
  7. package/.claude/commands/agent-vibes/agent.md +79 -79
  8. package/.claude/commands/agent-vibes/background-music.md +111 -111
  9. package/.claude/commands/agent-vibes/bmad.md +198 -198
  10. package/.claude/commands/agent-vibes/clean.md +18 -18
  11. package/.claude/commands/agent-vibes/cleanup.md +18 -18
  12. package/.claude/commands/agent-vibes/commands.json +145 -145
  13. package/.claude/commands/agent-vibes/effects.md +97 -97
  14. package/.claude/commands/agent-vibes/get.md +9 -9
  15. package/.claude/commands/agent-vibes/hide.md +91 -91
  16. package/.claude/commands/agent-vibes/language.md +23 -23
  17. package/.claude/commands/agent-vibes/learn.md +67 -67
  18. package/.claude/commands/agent-vibes/list.md +13 -13
  19. package/.claude/commands/agent-vibes/mute.md +37 -37
  20. package/.claude/commands/agent-vibes/preview.md +17 -17
  21. package/.claude/commands/agent-vibes/provider.md +68 -68
  22. package/.claude/commands/agent-vibes/replay-target.md +14 -14
  23. package/.claude/commands/agent-vibes/sample.md +12 -12
  24. package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
  25. package/.claude/commands/agent-vibes/set-pretext.md +65 -65
  26. package/.claude/commands/agent-vibes/set-speed.md +41 -41
  27. package/.claude/commands/agent-vibes/show.md +84 -84
  28. package/.claude/commands/agent-vibes/switch.md +87 -87
  29. package/.claude/commands/agent-vibes/target-voice.md +26 -26
  30. package/.claude/commands/agent-vibes/target.md +30 -30
  31. package/.claude/commands/agent-vibes/translate.md +68 -68
  32. package/.claude/commands/agent-vibes/unmute.md +45 -45
  33. package/.claude/commands/agent-vibes/verbosity.md +89 -89
  34. package/.claude/commands/agent-vibes/whoami.md +7 -7
  35. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  36. package/.claude/commands/agent-vibes-rdp.md +24 -24
  37. package/.claude/config/agentvibes.json +1 -0
  38. package/.claude/config/audio-effects.cfg +3 -2
  39. package/.claude/config/audio-effects.cfg.sample +52 -52
  40. package/.claude/config/background-music-volume.txt +1 -0
  41. package/.claude/config/intro-text.txt +1 -0
  42. package/.claude/config/piper-speech-rate.txt +4 -0
  43. package/.claude/config/piper-target-speech-rate.txt +1 -0
  44. package/.claude/config/reverb-level.txt +1 -0
  45. package/.claude/config/tts-speech-rate.txt +4 -0
  46. package/.claude/config/tts-target-speech-rate.txt +1 -0
  47. package/.claude/docs/TERMUX_SETUP.md +408 -408
  48. package/.claude/github-star-reminder.txt +1 -1
  49. package/.claude/hooks/README-TTS-QUEUE.md +135 -135
  50. package/.claude/hooks/audio-cache-utils.sh +246 -246
  51. package/.claude/hooks/audio-processor.sh +433 -389
  52. package/.claude/hooks/background-music-manager.sh +404 -404
  53. package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
  54. package/.claude/hooks/bmad-speak.sh +269 -112
  55. package/.claude/hooks/bmad-tts-injector.sh +568 -568
  56. package/.claude/hooks/bmad-voice-manager.sh +928 -928
  57. package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
  58. package/.claude/hooks/clawdbot-receiver.sh +107 -107
  59. package/.claude/hooks/clean-audio-cache.sh +22 -22
  60. package/.claude/hooks/cleanup-cache.sh +106 -106
  61. package/.claude/hooks/configure-rdp-mode.sh +137 -137
  62. package/.claude/hooks/download-extra-voices.sh +244 -244
  63. package/.claude/hooks/effects-manager.sh +268 -268
  64. package/.claude/hooks/github-star-reminder.sh +154 -154
  65. package/.claude/hooks/language-manager.sh +362 -362
  66. package/.claude/hooks/learn-manager.sh +492 -492
  67. package/.claude/hooks/macos-voice-manager.sh +205 -205
  68. package/.claude/hooks/migrate-background-music.sh +125 -125
  69. package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
  70. package/.claude/hooks/optimize-background-music.sh +87 -87
  71. package/.claude/hooks/path-resolver.sh +60 -60
  72. package/.claude/hooks/personality-manager.sh +448 -448
  73. package/.claude/hooks/piper-download-voices.sh +225 -225
  74. package/.claude/hooks/piper-installer.sh +292 -292
  75. package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
  76. package/.claude/hooks/piper-voice-manager.sh +24 -3
  77. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +90 -90
  78. package/.claude/hooks/play-tts-enhanced.sh +105 -70
  79. package/.claude/hooks/play-tts-macos.sh +368 -345
  80. package/.claude/hooks/play-tts-piper.sh +679 -578
  81. package/.claude/hooks/play-tts-soprano.sh +356 -320
  82. package/.claude/hooks/play-tts-ssh-remote.sh +167 -88
  83. package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
  84. package/.claude/hooks/play-tts.sh +301 -298
  85. package/.claude/hooks/prepare-release.sh +54 -54
  86. package/.claude/hooks/provider-commands.sh +617 -617
  87. package/.claude/hooks/provider-manager.sh +399 -399
  88. package/.claude/hooks/replay-target-audio.sh +95 -95
  89. package/.claude/hooks/requirements.txt +6 -6
  90. package/.claude/hooks/sentiment-manager.sh +201 -201
  91. package/.claude/hooks/session-start-tts.sh +81 -71
  92. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  93. package/.claude/hooks/speed-manager.sh +291 -291
  94. package/.claude/hooks/stop-tts.sh +84 -0
  95. package/.claude/hooks/termux-installer.sh +261 -261
  96. package/.claude/hooks/translate-manager.sh +341 -341
  97. package/.claude/hooks/translator.py +237 -237
  98. package/.claude/hooks/tts-queue-worker.sh +145 -114
  99. package/.claude/hooks/tts-queue.sh +165 -136
  100. package/.claude/hooks/verbosity-manager.sh +178 -178
  101. package/.claude/hooks/voice-manager.sh +548 -544
  102. package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
  103. package/.claude/hooks-windows/background-music-manager.ps1 +348 -0
  104. package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -0
  105. package/.claude/hooks-windows/download-extra-voices.ps1 +185 -0
  106. package/.claude/hooks-windows/effects-manager.ps1 +294 -0
  107. package/.claude/hooks-windows/language-manager.ps1 +193 -0
  108. package/.claude/hooks-windows/learn-manager.ps1 +241 -0
  109. package/.claude/hooks-windows/personality-manager.ps1 +266 -0
  110. package/.claude/hooks-windows/play-tts-piper.ps1 +209 -0
  111. package/.claude/hooks-windows/play-tts-sapi.ps1 +108 -0
  112. package/.claude/hooks-windows/play-tts-soprano.ps1 +159 -158
  113. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +50 -5
  114. package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -108
  115. package/.claude/hooks-windows/play-tts.ps1 +344 -266
  116. package/.claude/hooks-windows/provider-manager.ps1 +29 -10
  117. package/.claude/hooks-windows/session-start-tts.ps1 +124 -124
  118. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  119. package/.claude/hooks-windows/speed-manager.ps1 +166 -0
  120. package/.claude/hooks-windows/verbosity-manager.ps1 +119 -0
  121. package/.claude/hooks-windows/voice-manager-windows.ps1 +92 -8
  122. package/.claude/output-styles/agent-vibes.md +202 -202
  123. package/.claude/personalities/angry.md +14 -14
  124. package/.claude/personalities/annoying.md +14 -14
  125. package/.claude/personalities/crass.md +14 -14
  126. package/.claude/personalities/dramatic.md +14 -14
  127. package/.claude/personalities/dry-humor.md +50 -50
  128. package/.claude/personalities/flirty.md +20 -20
  129. package/.claude/personalities/funny.md +14 -14
  130. package/.claude/personalities/grandpa.md +32 -32
  131. package/.claude/personalities/millennial.md +14 -14
  132. package/.claude/personalities/moody.md +14 -14
  133. package/.claude/personalities/normal.md +16 -16
  134. package/.claude/personalities/pirate.md +14 -14
  135. package/.claude/personalities/poetic.md +14 -14
  136. package/.claude/personalities/professional.md +14 -14
  137. package/.claude/personalities/rapper.md +55 -55
  138. package/.claude/personalities/robot.md +14 -14
  139. package/.claude/personalities/sarcastic.md +38 -38
  140. package/.claude/personalities/sassy.md +14 -14
  141. package/.claude/personalities/surfer-dude.md +14 -14
  142. package/.claude/personalities/zen.md +14 -14
  143. package/.claude/settings.json +15 -15
  144. package/.claude/verbosity.txt +1 -1
  145. package/.clawdbot/README.md +105 -105
  146. package/.clawdbot/skill/SKILL.md +241 -241
  147. package/.mcp.json +12 -0
  148. package/CLAUDE.md +170 -181
  149. package/README.md +2029 -1909
  150. package/RELEASE_NOTES.md +1310 -66
  151. package/WINDOWS-SETUP.md +208 -208
  152. package/bin/agent-vibes +39 -39
  153. package/bin/agentvibes-voice-browser.js +1840 -1826
  154. package/bin/agentvibes.js +48 -2
  155. package/bin/mcp-server.js +121 -121
  156. package/bin/mcp-server.sh +206 -206
  157. package/bin/test-bmad-pr +78 -78
  158. package/mcp-server/QUICK_START.md +203 -203
  159. package/mcp-server/README.md +345 -345
  160. package/mcp-server/WINDOWS_SETUP.md +260 -260
  161. package/mcp-server/docs/troubleshooting-audio.md +313 -313
  162. package/mcp-server/examples/claude_desktop_config.json +11 -11
  163. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  164. package/mcp-server/examples/custom_instructions.md +169 -169
  165. package/mcp-server/install-deps.js +130 -130
  166. package/mcp-server/pyproject.toml +52 -52
  167. package/mcp-server/requirements.txt +2 -2
  168. package/mcp-server/server.py +1465 -1417
  169. package/mcp-server/test_server.py +395 -395
  170. package/mcp-server/test_windows_script_parity.py +336 -0
  171. package/package.json +110 -112
  172. package/setup-windows.ps1 +815 -815
  173. package/src/bmad-detector.js +71 -71
  174. package/src/cli/list-personalities.js +110 -110
  175. package/src/cli/list-voices.js +114 -114
  176. package/src/commands/bmad-voices.js +394 -394
  177. package/src/commands/install-mcp.js +476 -476
  178. package/src/console/app.js +824 -806
  179. package/src/console/audio-env.js +20 -1
  180. package/src/console/brand-colors.js +13 -13
  181. package/src/console/constants/personalities.js +44 -0
  182. package/src/console/footer-config.js +50 -46
  183. package/src/console/modals/modal-overlay.js +247 -247
  184. package/src/console/navigation.js +62 -61
  185. package/src/console/tabs/agents-tab.js +1684 -369
  186. package/src/console/tabs/help-tab.js +261 -261
  187. package/src/console/tabs/install-tab.js +1007 -991
  188. package/src/console/tabs/music-tab.js +22 -8
  189. package/src/console/tabs/placeholder-tab.js +53 -46
  190. package/src/console/tabs/readme-tab.js +267 -267
  191. package/src/console/tabs/receiver-tab.js +1472 -0
  192. package/src/console/tabs/settings-tab.js +185 -402
  193. package/src/console/tabs/voices-tab.js +100 -21
  194. package/src/console/widgets/destroy-list.js +25 -0
  195. package/src/console/widgets/format-utils.js +89 -0
  196. package/src/console/widgets/notice.js +55 -0
  197. package/src/console/widgets/personality-picker.js +185 -0
  198. package/src/console/widgets/reverb-picker.js +94 -0
  199. package/src/console/widgets/track-picker.js +285 -0
  200. package/src/installer/music-file-input.js +304 -304
  201. package/src/installer.js +5882 -5777
  202. package/src/services/agent-voice-store.js +423 -163
  203. package/src/services/config-service.js +264 -264
  204. package/src/services/navigation-service.js +123 -123
  205. package/src/services/provider-service.js +132 -132
  206. package/src/services/verbosity-service.js +157 -157
  207. package/src/utils/audio-duration-validator.js +298 -298
  208. package/src/utils/audio-format-validator.js +277 -277
  209. package/src/utils/dependency-checker.js +469 -466
  210. package/src/utils/file-ownership-verifier.js +358 -358
  211. package/src/utils/list-formatter.js +194 -194
  212. package/src/utils/music-file-validator.js +285 -275
  213. package/src/utils/preview-list-prompt.js +136 -136
  214. package/src/utils/provider-validator.js +96 -12
  215. package/src/utils/secure-music-storage.js +412 -412
  216. package/templates/agentvibes-receiver.sh +482 -162
  217. package/templates/audio/welcome-music.mp3 +0 -0
  218. package/voice-assignments.json +8244 -8244
  219. package/.claude/config/background-music-position.txt +0 -1
@@ -1,617 +1,617 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/provider-commands.sh
4
- #
5
- # AgentVibes - Finally, your AI Agents can Talk Back! Text-to-Speech WITH personality for AI Assistants!
6
- # Website: https://agentvibes.org
7
- # Repository: https://github.com/paulpreibisch/AgentVibes
8
- #
9
- # Co-created by Paul Preibisch with Claude AI
10
- # Copyright (c) 2025 Paul Preibisch
11
- #
12
- # Licensed under the Apache License, Version 2.0 (the "License");
13
- # you may not use this file except in compliance with the License.
14
- # You may obtain a copy of the License at
15
- #
16
- # http://www.apache.org/licenses/LICENSE-2.0
17
- #
18
- # Unless required by applicable law or agreed to in writing, software
19
- # distributed under the License is distributed on an "AS IS" BASIS,
20
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
- # See the License for the specific language governing permissions and
22
- # limitations under the License.
23
- #
24
- # DISCLAIMER: This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
- # express or implied, including but not limited to the warranties of
26
- # merchantability, fitness for a particular purpose and noninfringement.
27
- # In no event shall the authors or copyright holders be liable for any claim,
28
- # damages or other liability, whether in an action of contract, tort or
29
- # otherwise, arising from, out of or in connection with the software or the
30
- # use or other dealings in the software.
31
- #
32
- # ---
33
- #
34
- # @fileoverview Provider management slash commands
35
- # @context User-facing commands for switching and managing TTS providers
36
- # @architecture Part of /agent-vibes:* command system with language compatibility checking
37
- # @dependencies provider-manager.sh, language-manager.sh, voice-manager.sh, piper-voice-manager.sh
38
- # @entrypoints Called by /agent-vibes:provider slash commands (list, switch, info, test, get, preview)
39
- # @patterns Interactive confirmations, platform detection, language compatibility validation
40
- # @related provider-manager.sh, play-tts.sh, voice-manager.sh, piper-voice-manager.sh
41
- #
42
-
43
- # Get script directory
44
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
45
- source "$SCRIPT_DIR/provider-manager.sh"
46
- source "$SCRIPT_DIR/language-manager.sh"
47
-
48
- COMMAND="${1:-help}"
49
-
50
- # @function is_language_supported
51
- # @intent Check if a language is supported by a provider
52
- # @param $1 {string} language - Language code (e.g., "spanish", "french")
53
- # @param $2 {string} provider - Provider name (e.g., "piper", "macos")
54
- # @returns 0 if supported, 1 if not
55
- is_language_supported() {
56
- local language="$1"
57
- local provider="$2"
58
-
59
- # English is always supported
60
- if [[ "$language" == "english" ]] || [[ "$language" == "en" ]]; then
61
- return 0
62
- fi
63
-
64
- case "$provider" in
65
- piper)
66
- # Piper only supports English natively
67
- return 1
68
- ;;
69
- macos)
70
- # macOS has voices for 40+ languages built-in
71
- return 0
72
- ;;
73
- *)
74
- return 1
75
- ;;
76
- esac
77
- }
78
-
79
- # @function provider_list
80
- # @intent Display all available providers with status
81
- provider_list() {
82
- local current_provider
83
- current_provider=$(get_active_provider)
84
-
85
- # Check if running on macOS
86
- local is_macos=false
87
- if [[ "$(uname -s)" == "Darwin" ]]; then
88
- is_macos=true
89
- fi
90
-
91
- echo "┌────────────────────────────────────────────────────────────┐"
92
- echo "│ Available TTS Providers │"
93
- echo "├────────────────────────────────────────────────────────────┤"
94
-
95
- # macOS Say (show first on macOS systems)
96
- if [[ "$is_macos" == true ]]; then
97
- if [[ "$current_provider" == "macos" ]]; then
98
- echo "│ ✓ macOS Say Built-in, free ⭐⭐⭐⭐ [ACTIVE] │"
99
- else
100
- echo "│ macOS Say Built-in, free ⭐⭐⭐⭐ [RECOMMENDED] │"
101
- fi
102
- echo "│ Cost: Free (built-in) │"
103
- echo "│ Platform: macOS only │"
104
- echo "│ Offline: Yes │"
105
- echo "│ │"
106
- fi
107
-
108
- # Piper
109
- if [[ "$current_provider" == "piper" ]]; then
110
- echo "│ ✓ Piper TTS Free, offline ⭐⭐⭐⭐ [ACTIVE] │"
111
- else
112
- echo "│ Piper TTS Free, offline ⭐⭐⭐⭐ │"
113
- fi
114
- echo "│ Cost: Free forever │"
115
- echo "│ Platform: WSL, Linux only │"
116
- echo "│ Offline: Yes │"
117
-
118
- # macOS Say (show at end for non-macOS systems)
119
- if [[ "$is_macos" != true ]]; then
120
- echo "│ │"
121
- if [[ "$current_provider" == "macos" ]]; then
122
- echo "│ ✓ macOS Say Built-in, free ⭐⭐⭐⭐ [ACTIVE] │"
123
- else
124
- echo "│ macOS Say Built-in, free ⭐⭐⭐⭐ (macOS only) │"
125
- fi
126
- echo "│ Cost: Free (built-in) │"
127
- echo "│ Platform: macOS only │"
128
- echo "│ Offline: Yes │"
129
- fi
130
-
131
- echo "└────────────────────────────────────────────────────────────┘"
132
- echo ""
133
- echo "Learn more: agentvibes.org/providers"
134
- }
135
-
136
- # @function provider_switch
137
- # @intent Switch to a different TTS provider
138
- provider_switch() {
139
- local new_provider="$1"
140
- local force_mode=false
141
-
142
- # Check for --force or --yes flag
143
- if [[ "$2" == "--force" ]] || [[ "$2" == "--yes" ]] || [[ "$2" == "-y" ]]; then
144
- force_mode=true
145
- fi
146
-
147
- # Auto-enable force mode if running non-interactively (e.g., from MCP)
148
- # Check multiple conditions for MCP/non-interactive context
149
- if [[ ! -t 0 ]] || [[ -n "$CLAUDE_PROJECT_DIR" ]] || [[ -n "$MCP_SERVER" ]]; then
150
- force_mode=true
151
- fi
152
-
153
- if [[ -z "$new_provider" ]]; then
154
- echo "❌ Error: Provider name required"
155
- echo "Usage: /agent-vibes:provider switch <provider> [--force]"
156
- echo "Available: piper, macos"
157
- return 1
158
- fi
159
-
160
- # Validate provider
161
- if ! validate_provider "$new_provider"; then
162
- echo "❌ Invalid provider: $new_provider"
163
- echo ""
164
- echo "Available providers:"
165
- list_providers
166
- return 1
167
- fi
168
-
169
- local current_provider
170
- current_provider=$(get_active_provider)
171
-
172
- if [[ "$current_provider" == "$new_provider" ]]; then
173
- echo "✓ Already using $new_provider"
174
- return 0
175
- fi
176
-
177
- # Platform check for Piper
178
- if [[ "$new_provider" == "piper" ]]; then
179
- if ! grep -qi microsoft /proc/version 2>/dev/null && [[ "$(uname -s)" != "Linux" ]]; then
180
- echo "❌ Piper is only supported on WSL and Linux"
181
- echo "Your platform: $(uname -s)"
182
- echo "See: agentvibes.org/platform-support"
183
- return 1
184
- fi
185
-
186
- # Check if Piper is installed
187
- if ! command -v piper &> /dev/null; then
188
- echo "❌ Piper TTS is not installed"
189
- echo ""
190
- echo "Install with: pipx install piper-tts"
191
- echo "Or run: .claude/hooks/piper-installer.sh"
192
- echo ""
193
- echo "Visit: agentvibes.org/install-piper"
194
- return 1
195
- fi
196
- fi
197
-
198
- # Platform check for macOS
199
- if [[ "$new_provider" == "macos" ]]; then
200
- if [[ "$(uname -s)" != "Darwin" ]]; then
201
- echo "❌ macOS Say provider is only supported on macOS"
202
- echo "Your platform: $(uname -s)"
203
- echo ""
204
- echo "Alternative providers:"
205
- echo " • Piper TTS (free, offline) - for Linux/WSL"
206
- echo ""
207
- echo "See: agentvibes.org/platform-support"
208
- return 1
209
- fi
210
- fi
211
-
212
- # Check language compatibility
213
- local current_language
214
- current_language=$(get_language_code)
215
-
216
- if [[ "$current_language" != "english" ]]; then
217
- if ! is_language_supported "$current_language" "$new_provider" 2>/dev/null; then
218
- echo "⚠️ Language Compatibility Warning"
219
- echo ""
220
- echo "Current language: $current_language"
221
- echo "Target provider: $new_provider"
222
- echo ""
223
- echo "❌ Language '$current_language' is not natively supported by $new_provider"
224
- echo " Will fall back to English when using $new_provider"
225
- echo ""
226
- echo "Options:"
227
- echo " 1. Continue anyway (will use English)"
228
- echo " 2. Switch language to English"
229
- echo " 3. Cancel provider switch"
230
- echo ""
231
-
232
- # Skip prompt in force mode
233
- if [[ "$force_mode" == true ]]; then
234
- echo "⏩ Force mode: Continuing with fallback to English..."
235
- else
236
- read -p "Choose option [1-3]: " -n 1 -r
237
- echo
238
-
239
- case $REPLY in
240
- 1)
241
- echo "⏩ Continuing with fallback to English..."
242
- ;;
243
- 2)
244
- echo "🔄 Switching language to English..."
245
- "$SCRIPT_DIR/language-manager.sh" set english
246
- ;;
247
- 3)
248
- echo "❌ Provider switch cancelled"
249
- return 1
250
- ;;
251
- *)
252
- echo "❌ Invalid option, cancelling"
253
- return 1
254
- ;;
255
- esac
256
- fi
257
- fi
258
- fi
259
-
260
- # Confirm switch (skip in force mode)
261
- if [[ "$force_mode" != true ]]; then
262
- echo ""
263
- echo "⚠️ Switch to $(echo $new_provider | tr '[:lower:]' '[:upper:]')?"
264
- echo ""
265
- echo "Current: $current_provider"
266
- echo "New: $new_provider"
267
- if [[ "$current_language" != "english" ]]; then
268
- echo "Language: $current_language"
269
- fi
270
- echo ""
271
- read -p "Continue? [y/N]: " -n 1 -r
272
- echo
273
-
274
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
275
- echo "❌ Switch cancelled"
276
- return 1
277
- fi
278
- else
279
- echo "⏩ Force mode: Switching to $new_provider..."
280
- fi
281
-
282
- # Perform switch
283
- set_active_provider "$new_provider"
284
-
285
- # Update target voice if language learning mode is active
286
- local target_lang_file=""
287
- local target_voice_file=""
288
-
289
- # Check project-local first, then global
290
- if [[ -d "$SCRIPT_DIR/../.." ]]; then
291
- local project_dir="$SCRIPT_DIR/../.."
292
- if [[ -f "$project_dir/.claude/tts-target-language.txt" ]]; then
293
- target_lang_file="$project_dir/.claude/tts-target-language.txt"
294
- target_voice_file="$project_dir/.claude/tts-target-voice.txt"
295
- fi
296
- fi
297
-
298
- # Fallback to global
299
- if [[ -z "$target_lang_file" ]]; then
300
- if [[ -f "$HOME/.claude/tts-target-language.txt" ]]; then
301
- target_lang_file="$HOME/.claude/tts-target-language.txt"
302
- target_voice_file="$HOME/.claude/tts-target-voice.txt"
303
- fi
304
- fi
305
-
306
- # If target language is set, update voice for new provider
307
- if [[ -n "$target_lang_file" ]] && [[ -f "$target_lang_file" ]]; then
308
- local target_lang
309
- target_lang=$(cat "$target_lang_file")
310
-
311
- if [[ -n "$target_lang" ]]; then
312
- # Get the recommended voice for this language with new provider
313
- local new_target_voice
314
- new_target_voice=$(get_voice_for_language "$target_lang" "$new_provider")
315
-
316
- if [[ -n "$new_target_voice" ]]; then
317
- echo "$new_target_voice" > "$target_voice_file"
318
- echo ""
319
- echo "🔄 Updated target language voice:"
320
- echo " Language: $target_lang"
321
- echo " Voice: $new_target_voice (for $new_provider)"
322
- fi
323
- fi
324
- fi
325
-
326
- # Test new provider
327
- echo ""
328
- echo "🔊 Testing provider..."
329
- "$SCRIPT_DIR/play-tts.sh" "Provider switched to $new_provider successfully" 2>/dev/null
330
-
331
- echo ""
332
- echo "✓ Provider switch complete!"
333
- echo "Visit agentvibes.org for tips and tricks"
334
- }
335
-
336
- # @function provider_info
337
- # @intent Show detailed information about a provider
338
- provider_info() {
339
- local provider_name="$1"
340
-
341
- if [[ -z "$provider_name" ]]; then
342
- echo "❌ Error: Provider name required"
343
- echo "Usage: /agent-vibes:provider info <provider>"
344
- return 1
345
- fi
346
-
347
- case "$provider_name" in
348
- piper)
349
- echo "┌────────────────────────────────────────────────────────────┐"
350
- echo "│ Piper TTS - Free Offline Provider │"
351
- echo "├────────────────────────────────────────────────────────────┤"
352
- echo "│ Quality: ⭐⭐⭐⭐ (Very good) │"
353
- echo "│ Cost: Free forever │"
354
- echo "│ Platform: WSL, Linux only │"
355
- echo "│ Offline: Yes (fully local) │"
356
- echo "│ │"
357
- echo "│ Trade-offs: │"
358
- echo "│ + Completely free, no API costs │"
359
- echo "│ + Works offline, no internet needed │"
360
- echo "│ + Fast synthesis (local processing) │"
361
- echo "│ - WSL/Linux only (no macOS/Windows) │"
362
- echo "│ │"
363
- echo "│ Best for: Budget-conscious, offline use, privacy │"
364
- echo "└────────────────────────────────────────────────────────────┘"
365
- echo ""
366
- echo "Full comparison: agentvibes.org/providers"
367
- ;;
368
-
369
- macos)
370
- echo "┌────────────────────────────────────────────────────────────┐"
371
- echo "│ macOS Say - Native macOS TTS Provider │"
372
- echo "├────────────────────────────────────────────────────────────┤"
373
- echo "│ Quality: ⭐⭐⭐⭐ (Very good, Siri-quality on Mojave+) │"
374
- echo "│ Cost: Free (built-in) │"
375
- echo "│ Platform: macOS only (all versions since 10.0) │"
376
- echo "│ Offline: Yes (fully local) │"
377
- echo "│ │"
378
- echo "│ Trade-offs: │"
379
- echo "│ + Zero setup - built into every Mac │"
380
- echo "│ + 100+ voices in 40+ languages │"
381
- echo "│ + Completely free, no API costs │"
382
- echo "│ + Works offline, no internet needed │"
383
- echo "│ - macOS only (no Windows/Linux) │"
384
- echo "│ │"
385
- echo "│ Popular voices: Samantha, Alex, Daniel, Victoria │"
386
- echo "│ │"
387
- echo "│ Best for: Mac users wanting free, zero-setup TTS │"
388
- echo "└────────────────────────────────────────────────────────────┘"
389
- echo ""
390
- echo "Full comparison: agentvibes.org/providers"
391
- ;;
392
-
393
- *)
394
- echo "❌ Unknown provider: $provider_name"
395
- echo "Available: piper, macos"
396
- ;;
397
- esac
398
- }
399
-
400
- # @function provider_test
401
- # @intent Test current provider with sample audio
402
- provider_test() {
403
- local current_provider
404
- current_provider=$(get_active_provider)
405
-
406
- echo "🔊 Testing provider: $current_provider"
407
- echo ""
408
-
409
- "$SCRIPT_DIR/play-tts.sh" "Provider test successful. Audio is working correctly with $current_provider."
410
-
411
- echo ""
412
- echo "✓ Test complete"
413
- }
414
-
415
- # @function provider_get
416
- # @intent Show currently active provider
417
- provider_get() {
418
- local current_provider
419
- current_provider=$(get_active_provider)
420
-
421
- echo "🎤 Current Provider: $current_provider"
422
- echo ""
423
-
424
- # Show brief info
425
- case "$current_provider" in
426
- piper)
427
- echo "Quality: ⭐⭐⭐⭐"
428
- echo "Cost: Free forever"
429
- echo "Offline: Yes"
430
- ;;
431
- macos)
432
- echo "Quality: ⭐⭐⭐⭐"
433
- echo "Cost: Free (built-in)"
434
- echo "Offline: Yes"
435
- ;;
436
- esac
437
-
438
- echo ""
439
- echo "Use /agent-vibes:provider info $current_provider for details"
440
- }
441
-
442
- # @function provider_preview
443
- # @intent Preview voices for the currently active provider
444
- # @architecture Delegates to provider-specific voice managers
445
- provider_preview() {
446
- local current_provider
447
- current_provider=$(get_active_provider)
448
-
449
- echo "🎤 Voice Preview ($current_provider)"
450
- echo ""
451
-
452
- case "$current_provider" in
453
- piper)
454
- # Use the Piper voice manager's list functionality
455
- source "$SCRIPT_DIR/piper-voice-manager.sh"
456
-
457
- # Check if a specific voice was requested
458
- local voice_arg="$1"
459
-
460
- if [[ -n "$voice_arg" ]]; then
461
- # User requested a specific voice - check if it's a valid Piper voice
462
- # Piper voice names are like: en_US-lessac-medium
463
- # Try to find a matching voice model
464
-
465
- # Check if the voice arg looks like a Piper model name (contains underscores/hyphens)
466
- if [[ "$voice_arg" =~ ^[a-z]{2}_[A-Z]{2}- ]]; then
467
- # Looks like a Piper voice model name
468
- if verify_voice "$voice_arg"; then
469
- echo "🎤 Previewing Piper voice: $voice_arg"
470
- echo ""
471
- "$SCRIPT_DIR/play-tts.sh" "Hello, this is the $voice_arg voice. How do you like it?" "$voice_arg"
472
- else
473
- echo "❌ Voice model not found: $voice_arg"
474
- echo ""
475
- echo "💡 Piper voice names look like: en_US-lessac-medium"
476
- echo " Run /agent-vibes:list to see available Piper voices"
477
- fi
478
- else
479
- # Invalid voice format
480
- echo "❌ Invalid voice format: '$voice_arg'"
481
- echo ""
482
- echo "💡 Piper voice names look like: en_US-lessac-medium"
483
- echo " Run /agent-vibes:list to see available Piper voices"
484
- echo ""
485
- echo "Popular Piper voices to try:"
486
- echo " • en_US-lessac-medium (clear, professional)"
487
- echo " • en_US-amy-medium (warm, friendly)"
488
- echo " • en_US-joe-medium (casual, natural)"
489
- fi
490
- return
491
- fi
492
-
493
- # No specific voice - preview first 3 voices
494
- echo "🎤 Piper Preview of 3 people"
495
- echo ""
496
-
497
- # Play first 3 Piper voices as samples
498
- local sample_voices=(
499
- "en_US-lessac-medium:Lessac"
500
- "en_US-amy-medium:Amy"
501
- "en_US-joe-medium:Joe"
502
- )
503
-
504
- for voice_entry in "${sample_voices[@]}"; do
505
- local voice_name="${voice_entry%%:*}"
506
- local display_name="${voice_entry##*:}"
507
-
508
- echo "🔊 ${display_name}..."
509
- "$SCRIPT_DIR/play-tts.sh" "Hi, my name is ${display_name}" "$voice_name"
510
-
511
- # Wait for the voice to finish playing before starting next one
512
- sleep 3
513
- done
514
-
515
- echo ""
516
- echo "✓ Preview complete"
517
- echo "💡 Use /agent-vibes:list to see all available Piper voices"
518
- ;;
519
- macos)
520
- # Check if running on macOS
521
- if [[ "$(uname -s)" != "Darwin" ]]; then
522
- echo "❌ macOS voices only available on macOS"
523
- echo "Your platform: $(uname -s)"
524
- return 1
525
- fi
526
-
527
- # Check if a specific voice was requested
528
- local voice_arg="$1"
529
-
530
- if [[ -n "$voice_arg" ]]; then
531
- # User requested a specific voice - check if it's valid
532
- if say -v ? 2>/dev/null | grep -qi "^${voice_arg} "; then
533
- echo "🎤 Previewing macOS voice: $voice_arg"
534
- echo ""
535
- "$SCRIPT_DIR/play-tts.sh" "Hello, this is ${voice_arg}. How do you like my voice?" "$voice_arg"
536
- else
537
- echo "❌ Voice not found: $voice_arg"
538
- echo ""
539
- echo "Available macOS voices (showing English):"
540
- say -v ? 2>/dev/null | grep -i "en_" | head -10
541
- echo ""
542
- echo "Run /agent-vibes:list to see all available voices"
543
- fi
544
- return
545
- fi
546
-
547
- # No specific voice - preview first 3 English voices
548
- echo "🎤 macOS Preview of 3 voices"
549
- echo ""
550
-
551
- # Preview common English voices
552
- local sample_voices=("Samantha" "Alex" "Daniel")
553
-
554
- for voice in "${sample_voices[@]}"; do
555
- if say -v ? 2>/dev/null | grep -qi "^${voice} "; then
556
- echo "🔊 ${voice}..."
557
- "$SCRIPT_DIR/play-tts.sh" "Hi, my name is ${voice}" "$voice"
558
- sleep 3
559
- fi
560
- done
561
-
562
- echo ""
563
- echo "✓ Preview complete"
564
- echo "💡 Use /agent-vibes:list to see all available macOS voices"
565
- ;;
566
-
567
- *)
568
- echo "❌ Unknown provider: $current_provider"
569
- ;;
570
- esac
571
- }
572
-
573
- # @function provider_help
574
- # @intent Show help for provider commands
575
- provider_help() {
576
- echo "Provider Management Commands"
577
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
578
- echo ""
579
- echo "Usage:"
580
- echo " /agent-vibes:provider list # Show all providers"
581
- echo " /agent-vibes:provider switch <name> # Switch provider"
582
- echo " /agent-vibes:provider info <name> # Provider details"
583
- echo " /agent-vibes:provider test # Test current provider"
584
- echo " /agent-vibes:provider get # Show active provider"
585
- echo ""
586
- echo "Examples:"
587
- echo " /agent-vibes:provider switch piper"
588
- echo " /agent-vibes:provider info piper"
589
- echo ""
590
- echo "Learn more: agentvibes.org/docs/providers"
591
- }
592
-
593
- # Route to appropriate function
594
- case "$COMMAND" in
595
- list)
596
- provider_list
597
- ;;
598
- switch)
599
- provider_switch "$2" "$3"
600
- ;;
601
- info)
602
- provider_info "$2"
603
- ;;
604
- test)
605
- provider_test
606
- ;;
607
- get)
608
- provider_get
609
- ;;
610
- preview)
611
- shift # Remove 'preview' from args
612
- provider_preview "$@"
613
- ;;
614
- help|*)
615
- provider_help
616
- ;;
617
- esac
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/provider-commands.sh
4
+ #
5
+ # AgentVibes - Finally, your AI Agents can Talk Back! Text-to-Speech WITH personality for AI Assistants!
6
+ # Website: https://agentvibes.org
7
+ # Repository: https://github.com/paulpreibisch/AgentVibes
8
+ #
9
+ # Co-created by Paul Preibisch with Claude AI
10
+ # Copyright (c) 2025 Paul Preibisch
11
+ #
12
+ # Licensed under the Apache License, Version 2.0 (the "License");
13
+ # you may not use this file except in compliance with the License.
14
+ # You may obtain a copy of the License at
15
+ #
16
+ # http://www.apache.org/licenses/LICENSE-2.0
17
+ #
18
+ # Unless required by applicable law or agreed to in writing, software
19
+ # distributed under the License is distributed on an "AS IS" BASIS,
20
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ # See the License for the specific language governing permissions and
22
+ # limitations under the License.
23
+ #
24
+ # DISCLAIMER: This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # express or implied, including but not limited to the warranties of
26
+ # merchantability, fitness for a particular purpose and noninfringement.
27
+ # In no event shall the authors or copyright holders be liable for any claim,
28
+ # damages or other liability, whether in an action of contract, tort or
29
+ # otherwise, arising from, out of or in connection with the software or the
30
+ # use or other dealings in the software.
31
+ #
32
+ # ---
33
+ #
34
+ # @fileoverview Provider management slash commands
35
+ # @context User-facing commands for switching and managing TTS providers
36
+ # @architecture Part of /agent-vibes:* command system with language compatibility checking
37
+ # @dependencies provider-manager.sh, language-manager.sh, voice-manager.sh, piper-voice-manager.sh
38
+ # @entrypoints Called by /agent-vibes:provider slash commands (list, switch, info, test, get, preview)
39
+ # @patterns Interactive confirmations, platform detection, language compatibility validation
40
+ # @related provider-manager.sh, play-tts.sh, voice-manager.sh, piper-voice-manager.sh
41
+ #
42
+
43
+ # Get script directory
44
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
45
+ source "$SCRIPT_DIR/provider-manager.sh"
46
+ source "$SCRIPT_DIR/language-manager.sh"
47
+
48
+ COMMAND="${1:-help}"
49
+
50
+ # @function is_language_supported
51
+ # @intent Check if a language is supported by a provider
52
+ # @param $1 {string} language - Language code (e.g., "spanish", "french")
53
+ # @param $2 {string} provider - Provider name (e.g., "piper", "macos")
54
+ # @returns 0 if supported, 1 if not
55
+ is_language_supported() {
56
+ local language="$1"
57
+ local provider="$2"
58
+
59
+ # English is always supported
60
+ if [[ "$language" == "english" ]] || [[ "$language" == "en" ]]; then
61
+ return 0
62
+ fi
63
+
64
+ case "$provider" in
65
+ piper)
66
+ # Piper only supports English natively
67
+ return 1
68
+ ;;
69
+ macos)
70
+ # macOS has voices for 40+ languages built-in
71
+ return 0
72
+ ;;
73
+ *)
74
+ return 1
75
+ ;;
76
+ esac
77
+ }
78
+
79
+ # @function provider_list
80
+ # @intent Display all available providers with status
81
+ provider_list() {
82
+ local current_provider
83
+ current_provider=$(get_active_provider)
84
+
85
+ # Check if running on macOS
86
+ local is_macos=false
87
+ if [[ "$(uname -s)" == "Darwin" ]]; then
88
+ is_macos=true
89
+ fi
90
+
91
+ echo "┌────────────────────────────────────────────────────────────┐"
92
+ echo "│ Available TTS Providers │"
93
+ echo "├────────────────────────────────────────────────────────────┤"
94
+
95
+ # macOS Say (show first on macOS systems)
96
+ if [[ "$is_macos" == true ]]; then
97
+ if [[ "$current_provider" == "macos" ]]; then
98
+ echo "│ ✓ macOS Say Built-in, free ⭐⭐⭐⭐ [ACTIVE] │"
99
+ else
100
+ echo "│ macOS Say Built-in, free ⭐⭐⭐⭐ [RECOMMENDED] │"
101
+ fi
102
+ echo "│ Cost: Free (built-in) │"
103
+ echo "│ Platform: macOS only │"
104
+ echo "│ Offline: Yes │"
105
+ echo "│ │"
106
+ fi
107
+
108
+ # Piper
109
+ if [[ "$current_provider" == "piper" ]]; then
110
+ echo "│ ✓ Piper TTS Free, offline ⭐⭐⭐⭐ [ACTIVE] │"
111
+ else
112
+ echo "│ Piper TTS Free, offline ⭐⭐⭐⭐ │"
113
+ fi
114
+ echo "│ Cost: Free forever │"
115
+ echo "│ Platform: WSL, Linux only │"
116
+ echo "│ Offline: Yes │"
117
+
118
+ # macOS Say (show at end for non-macOS systems)
119
+ if [[ "$is_macos" != true ]]; then
120
+ echo "│ │"
121
+ if [[ "$current_provider" == "macos" ]]; then
122
+ echo "│ ✓ macOS Say Built-in, free ⭐⭐⭐⭐ [ACTIVE] │"
123
+ else
124
+ echo "│ macOS Say Built-in, free ⭐⭐⭐⭐ (macOS only) │"
125
+ fi
126
+ echo "│ Cost: Free (built-in) │"
127
+ echo "│ Platform: macOS only │"
128
+ echo "│ Offline: Yes │"
129
+ fi
130
+
131
+ echo "└────────────────────────────────────────────────────────────┘"
132
+ echo ""
133
+ echo "Learn more: agentvibes.org/providers"
134
+ }
135
+
136
+ # @function provider_switch
137
+ # @intent Switch to a different TTS provider
138
+ provider_switch() {
139
+ local new_provider="$1"
140
+ local force_mode=false
141
+
142
+ # Check for --force or --yes flag
143
+ if [[ "$2" == "--force" ]] || [[ "$2" == "--yes" ]] || [[ "$2" == "-y" ]]; then
144
+ force_mode=true
145
+ fi
146
+
147
+ # Auto-enable force mode if running non-interactively (e.g., from MCP)
148
+ # Check multiple conditions for MCP/non-interactive context
149
+ if [[ ! -t 0 ]] || [[ -n "$CLAUDE_PROJECT_DIR" ]] || [[ -n "$MCP_SERVER" ]]; then
150
+ force_mode=true
151
+ fi
152
+
153
+ if [[ -z "$new_provider" ]]; then
154
+ echo "❌ Error: Provider name required"
155
+ echo "Usage: /agent-vibes:provider switch <provider> [--force]"
156
+ echo "Available: piper, macos"
157
+ return 1
158
+ fi
159
+
160
+ # Validate provider
161
+ if ! validate_provider "$new_provider"; then
162
+ echo "❌ Invalid provider: $new_provider"
163
+ echo ""
164
+ echo "Available providers:"
165
+ list_providers
166
+ return 1
167
+ fi
168
+
169
+ local current_provider
170
+ current_provider=$(get_active_provider)
171
+
172
+ if [[ "$current_provider" == "$new_provider" ]]; then
173
+ echo "✓ Already using $new_provider"
174
+ return 0
175
+ fi
176
+
177
+ # Platform check for Piper
178
+ if [[ "$new_provider" == "piper" ]]; then
179
+ if ! grep -qi microsoft /proc/version 2>/dev/null && [[ "$(uname -s)" != "Linux" ]]; then
180
+ echo "❌ Piper is only supported on WSL and Linux"
181
+ echo "Your platform: $(uname -s)"
182
+ echo "See: agentvibes.org/platform-support"
183
+ return 1
184
+ fi
185
+
186
+ # Check if Piper is installed
187
+ if ! command -v piper &> /dev/null; then
188
+ echo "❌ Piper TTS is not installed"
189
+ echo ""
190
+ echo "Install with: pipx install piper-tts"
191
+ echo "Or run: .claude/hooks/piper-installer.sh"
192
+ echo ""
193
+ echo "Visit: agentvibes.org/install-piper"
194
+ return 1
195
+ fi
196
+ fi
197
+
198
+ # Platform check for macOS
199
+ if [[ "$new_provider" == "macos" ]]; then
200
+ if [[ "$(uname -s)" != "Darwin" ]]; then
201
+ echo "❌ macOS Say provider is only supported on macOS"
202
+ echo "Your platform: $(uname -s)"
203
+ echo ""
204
+ echo "Alternative providers:"
205
+ echo " • Piper TTS (free, offline) - for Linux/WSL"
206
+ echo ""
207
+ echo "See: agentvibes.org/platform-support"
208
+ return 1
209
+ fi
210
+ fi
211
+
212
+ # Check language compatibility
213
+ local current_language
214
+ current_language=$(get_language_code)
215
+
216
+ if [[ "$current_language" != "english" ]]; then
217
+ if ! is_language_supported "$current_language" "$new_provider" 2>/dev/null; then
218
+ echo "⚠️ Language Compatibility Warning"
219
+ echo ""
220
+ echo "Current language: $current_language"
221
+ echo "Target provider: $new_provider"
222
+ echo ""
223
+ echo "❌ Language '$current_language' is not natively supported by $new_provider"
224
+ echo " Will fall back to English when using $new_provider"
225
+ echo ""
226
+ echo "Options:"
227
+ echo " 1. Continue anyway (will use English)"
228
+ echo " 2. Switch language to English"
229
+ echo " 3. Cancel provider switch"
230
+ echo ""
231
+
232
+ # Skip prompt in force mode
233
+ if [[ "$force_mode" == true ]]; then
234
+ echo "⏩ Force mode: Continuing with fallback to English..."
235
+ else
236
+ read -p "Choose option [1-3]: " -n 1 -r
237
+ echo
238
+
239
+ case $REPLY in
240
+ 1)
241
+ echo "⏩ Continuing with fallback to English..."
242
+ ;;
243
+ 2)
244
+ echo "🔄 Switching language to English..."
245
+ "$SCRIPT_DIR/language-manager.sh" set english
246
+ ;;
247
+ 3)
248
+ echo "❌ Provider switch cancelled"
249
+ return 1
250
+ ;;
251
+ *)
252
+ echo "❌ Invalid option, cancelling"
253
+ return 1
254
+ ;;
255
+ esac
256
+ fi
257
+ fi
258
+ fi
259
+
260
+ # Confirm switch (skip in force mode)
261
+ if [[ "$force_mode" != true ]]; then
262
+ echo ""
263
+ echo "⚠️ Switch to $(echo $new_provider | tr '[:lower:]' '[:upper:]')?"
264
+ echo ""
265
+ echo "Current: $current_provider"
266
+ echo "New: $new_provider"
267
+ if [[ "$current_language" != "english" ]]; then
268
+ echo "Language: $current_language"
269
+ fi
270
+ echo ""
271
+ read -p "Continue? [y/N]: " -n 1 -r
272
+ echo
273
+
274
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
275
+ echo "❌ Switch cancelled"
276
+ return 1
277
+ fi
278
+ else
279
+ echo "⏩ Force mode: Switching to $new_provider..."
280
+ fi
281
+
282
+ # Perform switch
283
+ set_active_provider "$new_provider"
284
+
285
+ # Update target voice if language learning mode is active
286
+ local target_lang_file=""
287
+ local target_voice_file=""
288
+
289
+ # Check project-local first, then global
290
+ if [[ -d "$SCRIPT_DIR/../.." ]]; then
291
+ local project_dir="$SCRIPT_DIR/../.."
292
+ if [[ -f "$project_dir/.claude/tts-target-language.txt" ]]; then
293
+ target_lang_file="$project_dir/.claude/tts-target-language.txt"
294
+ target_voice_file="$project_dir/.claude/tts-target-voice.txt"
295
+ fi
296
+ fi
297
+
298
+ # Fallback to global
299
+ if [[ -z "$target_lang_file" ]]; then
300
+ if [[ -f "$HOME/.claude/tts-target-language.txt" ]]; then
301
+ target_lang_file="$HOME/.claude/tts-target-language.txt"
302
+ target_voice_file="$HOME/.claude/tts-target-voice.txt"
303
+ fi
304
+ fi
305
+
306
+ # If target language is set, update voice for new provider
307
+ if [[ -n "$target_lang_file" ]] && [[ -f "$target_lang_file" ]]; then
308
+ local target_lang
309
+ target_lang=$(cat "$target_lang_file")
310
+
311
+ if [[ -n "$target_lang" ]]; then
312
+ # Get the recommended voice for this language with new provider
313
+ local new_target_voice
314
+ new_target_voice=$(get_voice_for_language "$target_lang" "$new_provider")
315
+
316
+ if [[ -n "$new_target_voice" ]]; then
317
+ echo "$new_target_voice" > "$target_voice_file"
318
+ echo ""
319
+ echo "🔄 Updated target language voice:"
320
+ echo " Language: $target_lang"
321
+ echo " Voice: $new_target_voice (for $new_provider)"
322
+ fi
323
+ fi
324
+ fi
325
+
326
+ # Test new provider
327
+ echo ""
328
+ echo "🔊 Testing provider..."
329
+ "$SCRIPT_DIR/play-tts.sh" "Provider switched to $new_provider successfully" 2>/dev/null
330
+
331
+ echo ""
332
+ echo "✓ Provider switch complete!"
333
+ echo "Visit agentvibes.org for tips and tricks"
334
+ }
335
+
336
+ # @function provider_info
337
+ # @intent Show detailed information about a provider
338
+ provider_info() {
339
+ local provider_name="$1"
340
+
341
+ if [[ -z "$provider_name" ]]; then
342
+ echo "❌ Error: Provider name required"
343
+ echo "Usage: /agent-vibes:provider info <provider>"
344
+ return 1
345
+ fi
346
+
347
+ case "$provider_name" in
348
+ piper)
349
+ echo "┌────────────────────────────────────────────────────────────┐"
350
+ echo "│ Piper TTS - Free Offline Provider │"
351
+ echo "├────────────────────────────────────────────────────────────┤"
352
+ echo "│ Quality: ⭐⭐⭐⭐ (Very good) │"
353
+ echo "│ Cost: Free forever │"
354
+ echo "│ Platform: WSL, Linux only │"
355
+ echo "│ Offline: Yes (fully local) │"
356
+ echo "│ │"
357
+ echo "│ Trade-offs: │"
358
+ echo "│ + Completely free, no API costs │"
359
+ echo "│ + Works offline, no internet needed │"
360
+ echo "│ + Fast synthesis (local processing) │"
361
+ echo "│ - WSL/Linux only (no macOS/Windows) │"
362
+ echo "│ │"
363
+ echo "│ Best for: Budget-conscious, offline use, privacy │"
364
+ echo "└────────────────────────────────────────────────────────────┘"
365
+ echo ""
366
+ echo "Full comparison: agentvibes.org/providers"
367
+ ;;
368
+
369
+ macos)
370
+ echo "┌────────────────────────────────────────────────────────────┐"
371
+ echo "│ macOS Say - Native macOS TTS Provider │"
372
+ echo "├────────────────────────────────────────────────────────────┤"
373
+ echo "│ Quality: ⭐⭐⭐⭐ (Very good, Siri-quality on Mojave+) │"
374
+ echo "│ Cost: Free (built-in) │"
375
+ echo "│ Platform: macOS only (all versions since 10.0) │"
376
+ echo "│ Offline: Yes (fully local) │"
377
+ echo "│ │"
378
+ echo "│ Trade-offs: │"
379
+ echo "│ + Zero setup - built into every Mac │"
380
+ echo "│ + 100+ voices in 40+ languages │"
381
+ echo "│ + Completely free, no API costs │"
382
+ echo "│ + Works offline, no internet needed │"
383
+ echo "│ - macOS only (no Windows/Linux) │"
384
+ echo "│ │"
385
+ echo "│ Popular voices: Samantha, Alex, Daniel, Victoria │"
386
+ echo "│ │"
387
+ echo "│ Best for: Mac users wanting free, zero-setup TTS │"
388
+ echo "└────────────────────────────────────────────────────────────┘"
389
+ echo ""
390
+ echo "Full comparison: agentvibes.org/providers"
391
+ ;;
392
+
393
+ *)
394
+ echo "❌ Unknown provider: $provider_name"
395
+ echo "Available: piper, macos"
396
+ ;;
397
+ esac
398
+ }
399
+
400
+ # @function provider_test
401
+ # @intent Test current provider with sample audio
402
+ provider_test() {
403
+ local current_provider
404
+ current_provider=$(get_active_provider)
405
+
406
+ echo "🔊 Testing provider: $current_provider"
407
+ echo ""
408
+
409
+ "$SCRIPT_DIR/play-tts.sh" "Provider test successful. Audio is working correctly with $current_provider."
410
+
411
+ echo ""
412
+ echo "✓ Test complete"
413
+ }
414
+
415
+ # @function provider_get
416
+ # @intent Show currently active provider
417
+ provider_get() {
418
+ local current_provider
419
+ current_provider=$(get_active_provider)
420
+
421
+ echo "🎤 Current Provider: $current_provider"
422
+ echo ""
423
+
424
+ # Show brief info
425
+ case "$current_provider" in
426
+ piper)
427
+ echo "Quality: ⭐⭐⭐⭐"
428
+ echo "Cost: Free forever"
429
+ echo "Offline: Yes"
430
+ ;;
431
+ macos)
432
+ echo "Quality: ⭐⭐⭐⭐"
433
+ echo "Cost: Free (built-in)"
434
+ echo "Offline: Yes"
435
+ ;;
436
+ esac
437
+
438
+ echo ""
439
+ echo "Use /agent-vibes:provider info $current_provider for details"
440
+ }
441
+
442
+ # @function provider_preview
443
+ # @intent Preview voices for the currently active provider
444
+ # @architecture Delegates to provider-specific voice managers
445
+ provider_preview() {
446
+ local current_provider
447
+ current_provider=$(get_active_provider)
448
+
449
+ echo "🎤 Voice Preview ($current_provider)"
450
+ echo ""
451
+
452
+ case "$current_provider" in
453
+ piper)
454
+ # Use the Piper voice manager's list functionality
455
+ source "$SCRIPT_DIR/piper-voice-manager.sh"
456
+
457
+ # Check if a specific voice was requested
458
+ local voice_arg="$1"
459
+
460
+ if [[ -n "$voice_arg" ]]; then
461
+ # User requested a specific voice - check if it's a valid Piper voice
462
+ # Piper voice names are like: en_US-lessac-medium
463
+ # Try to find a matching voice model
464
+
465
+ # Check if the voice arg looks like a Piper model name (contains underscores/hyphens)
466
+ if [[ "$voice_arg" =~ ^[a-z]{2}_[A-Z]{2}- ]]; then
467
+ # Looks like a Piper voice model name
468
+ if verify_voice "$voice_arg"; then
469
+ echo "🎤 Previewing Piper voice: $voice_arg"
470
+ echo ""
471
+ "$SCRIPT_DIR/play-tts.sh" "Hello, this is the $voice_arg voice. How do you like it?" "$voice_arg"
472
+ else
473
+ echo "❌ Voice model not found: $voice_arg"
474
+ echo ""
475
+ echo "💡 Piper voice names look like: en_US-lessac-medium"
476
+ echo " Run /agent-vibes:list to see available Piper voices"
477
+ fi
478
+ else
479
+ # Invalid voice format
480
+ echo "❌ Invalid voice format: '$voice_arg'"
481
+ echo ""
482
+ echo "💡 Piper voice names look like: en_US-lessac-medium"
483
+ echo " Run /agent-vibes:list to see available Piper voices"
484
+ echo ""
485
+ echo "Popular Piper voices to try:"
486
+ echo " • en_US-lessac-medium (clear, professional)"
487
+ echo " • en_US-amy-medium (warm, friendly)"
488
+ echo " • en_US-joe-medium (casual, natural)"
489
+ fi
490
+ return
491
+ fi
492
+
493
+ # No specific voice - preview first 3 voices
494
+ echo "🎤 Piper Preview of 3 people"
495
+ echo ""
496
+
497
+ # Play first 3 Piper voices as samples
498
+ local sample_voices=(
499
+ "en_US-lessac-medium:Lessac"
500
+ "en_US-amy-medium:Amy"
501
+ "en_US-joe-medium:Joe"
502
+ )
503
+
504
+ for voice_entry in "${sample_voices[@]}"; do
505
+ local voice_name="${voice_entry%%:*}"
506
+ local display_name="${voice_entry##*:}"
507
+
508
+ echo "🔊 ${display_name}..."
509
+ "$SCRIPT_DIR/play-tts.sh" "Hi, my name is ${display_name}" "$voice_name"
510
+
511
+ # Wait for the voice to finish playing before starting next one
512
+ sleep 3
513
+ done
514
+
515
+ echo ""
516
+ echo "✓ Preview complete"
517
+ echo "💡 Use /agent-vibes:list to see all available Piper voices"
518
+ ;;
519
+ macos)
520
+ # Check if running on macOS
521
+ if [[ "$(uname -s)" != "Darwin" ]]; then
522
+ echo "❌ macOS voices only available on macOS"
523
+ echo "Your platform: $(uname -s)"
524
+ return 1
525
+ fi
526
+
527
+ # Check if a specific voice was requested
528
+ local voice_arg="$1"
529
+
530
+ if [[ -n "$voice_arg" ]]; then
531
+ # User requested a specific voice - check if it's valid
532
+ if say -v ? 2>/dev/null | grep -qi "^${voice_arg} "; then
533
+ echo "🎤 Previewing macOS voice: $voice_arg"
534
+ echo ""
535
+ "$SCRIPT_DIR/play-tts.sh" "Hello, this is ${voice_arg}. How do you like my voice?" "$voice_arg"
536
+ else
537
+ echo "❌ Voice not found: $voice_arg"
538
+ echo ""
539
+ echo "Available macOS voices (showing English):"
540
+ say -v ? 2>/dev/null | grep -i "en_" | head -10
541
+ echo ""
542
+ echo "Run /agent-vibes:list to see all available voices"
543
+ fi
544
+ return
545
+ fi
546
+
547
+ # No specific voice - preview first 3 English voices
548
+ echo "🎤 macOS Preview of 3 voices"
549
+ echo ""
550
+
551
+ # Preview common English voices
552
+ local sample_voices=("Samantha" "Alex" "Daniel")
553
+
554
+ for voice in "${sample_voices[@]}"; do
555
+ if say -v ? 2>/dev/null | grep -qi "^${voice} "; then
556
+ echo "🔊 ${voice}..."
557
+ "$SCRIPT_DIR/play-tts.sh" "Hi, my name is ${voice}" "$voice"
558
+ sleep 3
559
+ fi
560
+ done
561
+
562
+ echo ""
563
+ echo "✓ Preview complete"
564
+ echo "💡 Use /agent-vibes:list to see all available macOS voices"
565
+ ;;
566
+
567
+ *)
568
+ echo "❌ Unknown provider: $current_provider"
569
+ ;;
570
+ esac
571
+ }
572
+
573
+ # @function provider_help
574
+ # @intent Show help for provider commands
575
+ provider_help() {
576
+ echo "Provider Management Commands"
577
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
578
+ echo ""
579
+ echo "Usage:"
580
+ echo " /agent-vibes:provider list # Show all providers"
581
+ echo " /agent-vibes:provider switch <name> # Switch provider"
582
+ echo " /agent-vibes:provider info <name> # Provider details"
583
+ echo " /agent-vibes:provider test # Test current provider"
584
+ echo " /agent-vibes:provider get # Show active provider"
585
+ echo ""
586
+ echo "Examples:"
587
+ echo " /agent-vibes:provider switch piper"
588
+ echo " /agent-vibes:provider info piper"
589
+ echo ""
590
+ echo "Learn more: agentvibes.org/docs/providers"
591
+ }
592
+
593
+ # Route to appropriate function
594
+ case "$COMMAND" in
595
+ list)
596
+ provider_list
597
+ ;;
598
+ switch)
599
+ provider_switch "$2" "$3"
600
+ ;;
601
+ info)
602
+ provider_info "$2"
603
+ ;;
604
+ test)
605
+ provider_test
606
+ ;;
607
+ get)
608
+ provider_get
609
+ ;;
610
+ preview)
611
+ shift # Remove 'preview' from args
612
+ provider_preview "$@"
613
+ ;;
614
+ help|*)
615
+ provider_help
616
+ ;;
617
+ esac