agentvibes 4.2.0 → 4.4.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.
- package/.agentvibes/bmad/bmad-voices.md +69 -69
- package/.agentvibes/config.json +12 -0
- package/.claude/activation-instructions +54 -54
- package/.claude/audio/tracks/README.md +52 -52
- package/.claude/commands/agent-vibes/add.md +21 -21
- package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
- package/.claude/commands/agent-vibes/agent.md +79 -79
- package/.claude/commands/agent-vibes/background-music.md +111 -111
- package/.claude/commands/agent-vibes/bmad.md +198 -198
- package/.claude/commands/agent-vibes/clean.md +18 -18
- package/.claude/commands/agent-vibes/cleanup.md +18 -18
- package/.claude/commands/agent-vibes/commands.json +145 -145
- package/.claude/commands/agent-vibes/effects.md +97 -97
- package/.claude/commands/agent-vibes/get.md +9 -9
- package/.claude/commands/agent-vibes/hide.md +91 -91
- package/.claude/commands/agent-vibes/language.md +23 -23
- package/.claude/commands/agent-vibes/learn.md +67 -67
- package/.claude/commands/agent-vibes/list.md +13 -13
- package/.claude/commands/agent-vibes/mute.md +37 -37
- package/.claude/commands/agent-vibes/preview.md +17 -17
- package/.claude/commands/agent-vibes/provider.md +68 -68
- package/.claude/commands/agent-vibes/replay-target.md +14 -14
- package/.claude/commands/agent-vibes/sample.md +12 -12
- package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
- package/.claude/commands/agent-vibes/set-pretext.md +65 -65
- package/.claude/commands/agent-vibes/set-speed.md +41 -41
- package/.claude/commands/agent-vibes/show.md +84 -84
- package/.claude/commands/agent-vibes/switch.md +87 -87
- package/.claude/commands/agent-vibes/target-voice.md +26 -26
- package/.claude/commands/agent-vibes/target.md +30 -30
- package/.claude/commands/agent-vibes/translate.md +68 -68
- package/.claude/commands/agent-vibes/unmute.md +45 -45
- package/.claude/commands/agent-vibes/verbosity.md +89 -89
- package/.claude/commands/agent-vibes/whoami.md +7 -7
- package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
- package/.claude/commands/agent-vibes-rdp.md +24 -24
- package/.claude/config/agentvibes.json +1 -0
- package/.claude/config/audio-effects.cfg +2 -2
- package/.claude/config/audio-effects.cfg.sample +52 -52
- package/.claude/config/background-music-volume.txt +1 -0
- package/.claude/config/intro-text.txt +1 -0
- package/.claude/config/piper-speech-rate.txt +4 -0
- package/.claude/config/piper-target-speech-rate.txt +1 -0
- package/.claude/config/reverb-level.txt +1 -0
- package/.claude/config/tts-speech-rate.txt +4 -0
- package/.claude/config/tts-target-speech-rate.txt +1 -0
- package/.claude/docs/TERMUX_SETUP.md +408 -408
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/README-TTS-QUEUE.md +135 -135
- package/.claude/hooks/audio-cache-utils.sh +246 -246
- package/.claude/hooks/audio-processor.sh +433 -433
- package/.claude/hooks/background-music-manager.sh +404 -404
- package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
- package/.claude/hooks/bmad-speak.sh +269 -269
- package/.claude/hooks/bmad-tts-injector.sh +568 -568
- package/.claude/hooks/bmad-voice-manager.sh +928 -928
- package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
- package/.claude/hooks/clawdbot-receiver.sh +107 -107
- package/.claude/hooks/clean-audio-cache.sh +22 -22
- package/.claude/hooks/cleanup-cache.sh +106 -106
- package/.claude/hooks/configure-rdp-mode.sh +137 -137
- package/.claude/hooks/download-extra-voices.sh +244 -244
- package/.claude/hooks/effects-manager.sh +268 -268
- package/.claude/hooks/github-star-reminder.sh +154 -154
- package/.claude/hooks/language-manager.sh +362 -362
- package/.claude/hooks/learn-manager.sh +492 -492
- package/.claude/hooks/macos-voice-manager.sh +205 -205
- package/.claude/hooks/migrate-background-music.sh +125 -125
- package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
- package/.claude/hooks/optimize-background-music.sh +87 -87
- package/.claude/hooks/path-resolver.sh +60 -60
- package/.claude/hooks/personality-manager.sh +448 -448
- package/.claude/hooks/piper-download-voices.sh +225 -225
- package/.claude/hooks/piper-installer.sh +292 -292
- package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
- package/.claude/hooks/piper-voice-manager.sh +24 -3
- package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +90 -90
- package/.claude/hooks/play-tts-enhanced.sh +105 -105
- package/.claude/hooks/play-tts-macos.sh +368 -368
- package/.claude/hooks/play-tts-piper.sh +679 -679
- package/.claude/hooks/play-tts-soprano.sh +356 -356
- package/.claude/hooks/play-tts-ssh-remote.sh +167 -167
- package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
- package/.claude/hooks/play-tts.sh +301 -301
- package/.claude/hooks/prepare-release.sh +54 -54
- package/.claude/hooks/provider-commands.sh +617 -617
- package/.claude/hooks/provider-manager.sh +399 -399
- package/.claude/hooks/replay-target-audio.sh +95 -95
- package/.claude/hooks/requirements.txt +6 -6
- package/.claude/hooks/sentiment-manager.sh +201 -201
- package/.claude/hooks/session-start-tts.sh +81 -81
- package/.claude/hooks/soprano-gradio-synth.py +139 -139
- package/.claude/hooks/speed-manager.sh +291 -291
- package/.claude/hooks/stop-tts.sh +84 -84
- package/.claude/hooks/termux-installer.sh +261 -261
- package/.claude/hooks/translate-manager.sh +341 -341
- package/.claude/hooks/translator.py +237 -237
- package/.claude/hooks/tts-queue-worker.sh +145 -145
- package/.claude/hooks/tts-queue.sh +165 -165
- package/.claude/hooks/verbosity-manager.sh +178 -178
- package/.claude/hooks/voice-manager.sh +548 -548
- package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
- package/.claude/hooks-windows/background-music-manager.ps1 +348 -0
- package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -0
- package/.claude/hooks-windows/download-extra-voices.ps1 +185 -0
- package/.claude/hooks-windows/effects-manager.ps1 +294 -0
- package/.claude/hooks-windows/language-manager.ps1 +193 -0
- package/.claude/hooks-windows/learn-manager.ps1 +241 -0
- package/.claude/hooks-windows/personality-manager.ps1 +266 -0
- package/.claude/hooks-windows/play-tts-piper.ps1 +209 -0
- package/.claude/hooks-windows/play-tts-sapi.ps1 +108 -0
- package/.claude/hooks-windows/play-tts-soprano.ps1 +159 -158
- package/.claude/hooks-windows/play-tts-windows-piper.ps1 +50 -5
- package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -108
- package/.claude/hooks-windows/play-tts.ps1 +344 -266
- package/.claude/hooks-windows/provider-manager.ps1 +29 -10
- package/.claude/hooks-windows/session-start-tts.ps1 +124 -124
- package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
- package/.claude/hooks-windows/speed-manager.ps1 +166 -0
- package/.claude/hooks-windows/verbosity-manager.ps1 +119 -0
- package/.claude/hooks-windows/voice-manager-windows.ps1 +92 -8
- package/.claude/output-styles/agent-vibes.md +202 -202
- package/.claude/personalities/angry.md +14 -14
- package/.claude/personalities/annoying.md +14 -14
- package/.claude/personalities/crass.md +14 -14
- package/.claude/personalities/dramatic.md +14 -14
- package/.claude/personalities/dry-humor.md +50 -50
- package/.claude/personalities/flirty.md +20 -20
- package/.claude/personalities/funny.md +14 -14
- package/.claude/personalities/grandpa.md +32 -32
- package/.claude/personalities/millennial.md +14 -14
- package/.claude/personalities/moody.md +14 -14
- package/.claude/personalities/normal.md +16 -16
- package/.claude/personalities/pirate.md +14 -14
- package/.claude/personalities/poetic.md +14 -14
- package/.claude/personalities/professional.md +14 -14
- package/.claude/personalities/rapper.md +55 -55
- package/.claude/personalities/robot.md +14 -14
- package/.claude/personalities/sarcastic.md +38 -38
- package/.claude/personalities/sassy.md +14 -14
- package/.claude/personalities/surfer-dude.md +14 -14
- package/.claude/personalities/zen.md +14 -14
- package/.claude/settings.json +15 -15
- package/.claude/verbosity.txt +1 -1
- package/.clawdbot/README.md +105 -105
- package/.clawdbot/skill/SKILL.md +241 -241
- package/.mcp.json +12 -0
- package/CLAUDE.md +170 -170
- package/README.md +2029 -2007
- package/RELEASE_NOTES.md +1310 -1203
- package/WINDOWS-SETUP.md +208 -208
- package/bin/agent-vibes +39 -39
- package/bin/agentvibes-voice-browser.js +1840 -1840
- package/bin/agentvibes.js +48 -2
- package/bin/mcp-server.js +121 -121
- package/bin/mcp-server.sh +206 -206
- package/bin/test-bmad-pr +78 -78
- package/mcp-server/QUICK_START.md +203 -203
- package/mcp-server/README.md +345 -345
- package/mcp-server/WINDOWS_SETUP.md +260 -260
- package/mcp-server/docs/troubleshooting-audio.md +313 -313
- package/mcp-server/examples/claude_desktop_config.json +11 -11
- package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
- package/mcp-server/examples/custom_instructions.md +169 -169
- package/mcp-server/install-deps.js +130 -130
- package/mcp-server/pyproject.toml +52 -52
- package/mcp-server/requirements.txt +2 -2
- package/mcp-server/server.py +1465 -1453
- package/mcp-server/test_server.py +395 -395
- package/mcp-server/test_windows_script_parity.py +336 -0
- package/package.json +110 -110
- package/setup-windows.ps1 +815 -815
- package/src/bmad-detector.js +71 -71
- package/src/cli/list-personalities.js +110 -110
- package/src/cli/list-voices.js +114 -114
- package/src/commands/bmad-voices.js +394 -394
- package/src/commands/install-mcp.js +476 -476
- package/src/console/app.js +824 -824
- package/src/console/audio-env.js +20 -1
- package/src/console/brand-colors.js +13 -13
- package/src/console/constants/personalities.js +44 -44
- package/src/console/footer-config.js +50 -50
- package/src/console/modals/modal-overlay.js +247 -247
- package/src/console/navigation.js +62 -62
- package/src/console/tabs/agents-tab.js +1684 -1516
- package/src/console/tabs/help-tab.js +261 -261
- package/src/console/tabs/install-tab.js +1007 -991
- package/src/console/tabs/music-tab.js +22 -8
- package/src/console/tabs/placeholder-tab.js +53 -53
- package/src/console/tabs/readme-tab.js +267 -267
- package/src/console/tabs/receiver-tab.js +1472 -1212
- package/src/console/tabs/settings-tab.js +208 -84
- package/src/console/tabs/voices-tab.js +100 -21
- package/src/console/widgets/destroy-list.js +25 -25
- package/src/console/widgets/format-utils.js +89 -89
- package/src/console/widgets/notice.js +55 -55
- package/src/console/widgets/personality-picker.js +185 -185
- package/src/console/widgets/reverb-picker.js +94 -94
- package/src/console/widgets/track-picker.js +285 -285
- package/src/installer/music-file-input.js +304 -304
- package/src/installer.js +5895 -5829
- package/src/services/agent-voice-store.js +423 -423
- package/src/services/config-service.js +264 -264
- package/src/services/navigation-service.js +123 -123
- package/src/services/provider-service.js +143 -132
- package/src/services/verbosity-service.js +157 -157
- package/src/utils/audio-duration-validator.js +298 -298
- package/src/utils/audio-format-validator.js +277 -277
- package/src/utils/dependency-checker.js +469 -466
- package/src/utils/file-ownership-verifier.js +358 -358
- package/src/utils/list-formatter.js +194 -194
- package/src/utils/music-file-validator.js +285 -285
- package/src/utils/preview-list-prompt.js +136 -136
- package/src/utils/provider-validator.js +96 -12
- package/src/utils/secure-music-storage.js +412 -412
- package/templates/agentvibes-receiver.sh +482 -482
- package/templates/audio/welcome-music.mp3 +0 -0
- package/voice-assignments.json +8244 -8244
- package/.claude/config/background-music-position.txt +0 -1
|
@@ -1,301 +1,301 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# File: .claude/hooks/play-tts.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 TTS Provider Router with Translation and Language Learning Support
|
|
35
|
-
# @context Routes TTS requests to active provider (Piper or macOS) with optional translation
|
|
36
|
-
# @architecture Provider abstraction layer - single entry point for all TTS, handles translation and learning mode
|
|
37
|
-
# @dependencies provider-manager.sh, play-tts-piper.sh, translator.py, translate-manager.sh, learn-manager.sh
|
|
38
|
-
# @entrypoints Called by hooks, slash commands, personality-manager.sh, and all TTS features
|
|
39
|
-
# @patterns Provider pattern - delegates to provider-specific implementations, auto-detects provider from voice name
|
|
40
|
-
# @related provider-manager.sh, play-tts-piper.sh, learn-manager.sh, translate-manager.sh
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
set -euo pipefail
|
|
44
|
-
|
|
45
|
-
# Fix locale warnings
|
|
46
|
-
export LC_ALL=C
|
|
47
|
-
|
|
48
|
-
# Get script directory (needed for mute file check)
|
|
49
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
50
|
-
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
51
|
-
export PROJECT_ROOT # Export for child scripts
|
|
52
|
-
|
|
53
|
-
# Check if muted (persists across sessions)
|
|
54
|
-
# Project settings always override global settings:
|
|
55
|
-
# - .claude/agentvibes-unmuted = project explicitly unmuted (overrides global mute)
|
|
56
|
-
# - .claude/agentvibes-muted = project muted (overrides global unmute)
|
|
57
|
-
# - ~/.agentvibes-muted = global mute (only if no project-level setting)
|
|
58
|
-
GLOBAL_MUTE_FILE="$HOME/.agentvibes-muted"
|
|
59
|
-
PROJECT_MUTE_FILE="$PROJECT_ROOT/.claude/agentvibes-muted"
|
|
60
|
-
PROJECT_UNMUTE_FILE="$PROJECT_ROOT/.claude/agentvibes-unmuted"
|
|
61
|
-
|
|
62
|
-
# Check project-level settings first (project overrides global)
|
|
63
|
-
if [[ -f "$PROJECT_UNMUTE_FILE" ]]; then
|
|
64
|
-
# Project explicitly unmuted - ignore global mute
|
|
65
|
-
: # Continue (do nothing, will not exit)
|
|
66
|
-
elif [[ -f "$PROJECT_MUTE_FILE" ]]; then
|
|
67
|
-
# Project explicitly muted
|
|
68
|
-
if [[ -f "$GLOBAL_MUTE_FILE" ]]; then
|
|
69
|
-
echo "🔇 TTS muted (project + global)" >&2
|
|
70
|
-
else
|
|
71
|
-
echo "🔇 TTS muted (project)" >&2
|
|
72
|
-
fi
|
|
73
|
-
exit 0
|
|
74
|
-
elif [[ -f "$GLOBAL_MUTE_FILE" ]]; then
|
|
75
|
-
# Global mute and no project-level override
|
|
76
|
-
echo "🔇 TTS muted (global)" >&2
|
|
77
|
-
exit 0
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
TEXT="${1:-}"
|
|
81
|
-
VOICE_OVERRIDE="${2:-}" # Optional: voice name or ID
|
|
82
|
-
AGENT_PROFILE_FILE="${3:-}" # Optional: path to per-agent profile JSON (from bmad-speak.sh)
|
|
83
|
-
|
|
84
|
-
# Security: Validate inputs
|
|
85
|
-
if [[ -z "$TEXT" ]]; then
|
|
86
|
-
echo "Error: No text provided" >&2
|
|
87
|
-
exit 1
|
|
88
|
-
fi
|
|
89
|
-
|
|
90
|
-
# Security: Validate voice override doesn't contain dangerous characters
|
|
91
|
-
if [[ -n "$VOICE_OVERRIDE" ]] && [[ "$VOICE_OVERRIDE" =~ [';|&$`<>(){}'] ]]; then
|
|
92
|
-
echo "Error: Invalid characters in voice parameter" >&2
|
|
93
|
-
exit 1
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
# Remove backslash escaping that Claude might add for SAFE special chars only
|
|
97
|
-
# SECURITY: Only unescape punctuation chars that cannot form shell commands (#127)
|
|
98
|
-
# Never unescape $, `, \, or other shell metacharacters
|
|
99
|
-
TEXT="${TEXT//\\!/!}" # Remove \!
|
|
100
|
-
TEXT="${TEXT//\\?/?}" # Remove \?
|
|
101
|
-
TEXT="${TEXT//\\,/,}" # Remove \,
|
|
102
|
-
TEXT="${TEXT//\\./.}" # Remove \. (keep the period)
|
|
103
|
-
|
|
104
|
-
# Prepend intro text (pretext) if configured
|
|
105
|
-
# Check project-local first, then global
|
|
106
|
-
_PRETEXT_FILE="$PROJECT_ROOT/.claude/config/intro-text.txt"
|
|
107
|
-
[[ -f "$_PRETEXT_FILE" ]] || _PRETEXT_FILE="$HOME/.claude/config/intro-text.txt"
|
|
108
|
-
if [[ -f "$_PRETEXT_FILE" ]]; then
|
|
109
|
-
_PRETEXT="$(head -1 "$_PRETEXT_FILE" 2>/dev/null || true)"
|
|
110
|
-
if [[ -n "$_PRETEXT" ]]; then
|
|
111
|
-
TEXT="${_PRETEXT} ${TEXT}"
|
|
112
|
-
fi
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
# Source provider manager to get active provider
|
|
116
|
-
source "$SCRIPT_DIR/provider-manager.sh"
|
|
117
|
-
|
|
118
|
-
# Get active provider
|
|
119
|
-
ACTIVE_PROVIDER=$(get_active_provider)
|
|
120
|
-
|
|
121
|
-
# Show GitHub star reminder (once per day)
|
|
122
|
-
"$SCRIPT_DIR/github-star-reminder.sh" 2>/dev/null || true
|
|
123
|
-
|
|
124
|
-
# @function detect_voice_provider
|
|
125
|
-
# @intent Auto-detect provider from voice name (for mixed-provider support)
|
|
126
|
-
# @why Allow Piper for main language + macOS for target language
|
|
127
|
-
# @param $1 voice name/ID
|
|
128
|
-
# @returns Provider name (piper or macos)
|
|
129
|
-
detect_voice_provider() {
|
|
130
|
-
local voice="$1"
|
|
131
|
-
# Piper voice names contain underscore and dash (e.g., es_ES-davefx-medium)
|
|
132
|
-
if [[ "$voice" == *"_"*"-"* ]]; then
|
|
133
|
-
echo "piper"
|
|
134
|
-
else
|
|
135
|
-
echo "$ACTIVE_PROVIDER"
|
|
136
|
-
fi
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
# Override provider if voice indicates different provider (mixed-provider mode)
|
|
140
|
-
if [[ -n "$VOICE_OVERRIDE" ]]; then
|
|
141
|
-
DETECTED_PROVIDER=$(detect_voice_provider "$VOICE_OVERRIDE")
|
|
142
|
-
if [[ "$DETECTED_PROVIDER" != "$ACTIVE_PROVIDER" ]]; then
|
|
143
|
-
ACTIVE_PROVIDER="$DETECTED_PROVIDER"
|
|
144
|
-
fi
|
|
145
|
-
fi
|
|
146
|
-
|
|
147
|
-
# @function speak_text
|
|
148
|
-
# @intent Route text to appropriate TTS provider
|
|
149
|
-
# @why Reusable function for speaking, used by both single and learning modes
|
|
150
|
-
# @param $1 text to speak
|
|
151
|
-
# @param $2 voice override (optional)
|
|
152
|
-
# @param $3 provider override (optional)
|
|
153
|
-
speak_text() {
|
|
154
|
-
local text="$1"
|
|
155
|
-
local voice="${2:-}"
|
|
156
|
-
local provider="${3:-$ACTIVE_PROVIDER}"
|
|
157
|
-
local profile_file="${4:-$AGENT_PROFILE_FILE}"
|
|
158
|
-
|
|
159
|
-
case "$provider" in
|
|
160
|
-
piper)
|
|
161
|
-
"$SCRIPT_DIR/play-tts-piper.sh" "$text" "$voice" "$profile_file"
|
|
162
|
-
;;
|
|
163
|
-
soprano)
|
|
164
|
-
"$SCRIPT_DIR/play-tts-soprano.sh" "$text" "$voice"
|
|
165
|
-
;;
|
|
166
|
-
macos)
|
|
167
|
-
"$SCRIPT_DIR/play-tts-macos.sh" "$text" "$voice"
|
|
168
|
-
;;
|
|
169
|
-
termux-ssh)
|
|
170
|
-
"$SCRIPT_DIR/play-tts-termux-ssh.sh" "$text" "$voice"
|
|
171
|
-
;;
|
|
172
|
-
*)
|
|
173
|
-
echo "❌ Unknown provider: $provider" >&2
|
|
174
|
-
return 1
|
|
175
|
-
;;
|
|
176
|
-
esac
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
# Note: learn-manager.sh and translate-manager.sh are sourced inside their
|
|
180
|
-
# respective handler functions to avoid triggering their main handlers
|
|
181
|
-
|
|
182
|
-
# @function handle_learning_mode
|
|
183
|
-
# @intent Speak in both main language and target language for learning
|
|
184
|
-
# @why Issue #51 - Auto-translate and speak twice for immersive language learning
|
|
185
|
-
# @returns 0 if learning mode handled, 1 if not in learning mode
|
|
186
|
-
handle_learning_mode() {
|
|
187
|
-
# Source learn-manager for learning mode functions
|
|
188
|
-
source "$SCRIPT_DIR/learn-manager.sh" 2>/dev/null || return 1
|
|
189
|
-
|
|
190
|
-
# Check if learning mode is enabled
|
|
191
|
-
if ! is_learn_mode_enabled 2>/dev/null; then
|
|
192
|
-
return 1
|
|
193
|
-
fi
|
|
194
|
-
|
|
195
|
-
local target_lang
|
|
196
|
-
target_lang=$(get_target_language 2>/dev/null || echo "")
|
|
197
|
-
local target_voice
|
|
198
|
-
target_voice=$(get_target_voice 2>/dev/null || echo "")
|
|
199
|
-
|
|
200
|
-
# Need both target language and voice for learning mode
|
|
201
|
-
if [[ -z "$target_lang" ]] || [[ -z "$target_voice" ]]; then
|
|
202
|
-
return 1
|
|
203
|
-
fi
|
|
204
|
-
|
|
205
|
-
# 1. Speak in main language (current voice)
|
|
206
|
-
speak_text "$TEXT" "$VOICE_OVERRIDE" "$ACTIVE_PROVIDER"
|
|
207
|
-
|
|
208
|
-
# 2. Auto-translate to target language
|
|
209
|
-
local translated
|
|
210
|
-
# SECURITY: Add timeout to prevent hanging (#134)
|
|
211
|
-
translated=$(timeout 5 python3 "$SCRIPT_DIR/translator.py" "$TEXT" "$target_lang" 2>/dev/null) || translated="$TEXT"
|
|
212
|
-
|
|
213
|
-
# Small pause between languages
|
|
214
|
-
sleep 0.5
|
|
215
|
-
|
|
216
|
-
# 3. Speak translated text with target voice
|
|
217
|
-
local target_provider
|
|
218
|
-
target_provider=$(detect_voice_provider "$target_voice")
|
|
219
|
-
speak_text "$translated" "$target_voice" "$target_provider"
|
|
220
|
-
|
|
221
|
-
return 0
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
# @function handle_translation_mode
|
|
225
|
-
# @intent Translate and speak in target language (non-learning mode)
|
|
226
|
-
# @why Issue #50 - BMAD multi-language TTS support
|
|
227
|
-
# @returns 0 if translation handled, 1 if not translating
|
|
228
|
-
handle_translation_mode() {
|
|
229
|
-
# Source translate-manager to get translation settings
|
|
230
|
-
source "$SCRIPT_DIR/translate-manager.sh" 2>/dev/null || return 1
|
|
231
|
-
|
|
232
|
-
# Check if translation is enabled
|
|
233
|
-
if ! is_translation_enabled 2>/dev/null; then
|
|
234
|
-
return 1
|
|
235
|
-
fi
|
|
236
|
-
|
|
237
|
-
local translate_to
|
|
238
|
-
translate_to=$(get_translate_to 2>/dev/null || echo "")
|
|
239
|
-
|
|
240
|
-
if [[ -z "$translate_to" ]] || [[ "$translate_to" == "english" ]]; then
|
|
241
|
-
return 1
|
|
242
|
-
fi
|
|
243
|
-
|
|
244
|
-
# Translate text
|
|
245
|
-
local translated
|
|
246
|
-
# SECURITY: Add timeout to prevent hanging (#134)
|
|
247
|
-
translated=$(timeout 5 python3 "$SCRIPT_DIR/translator.py" "$TEXT" "$translate_to" 2>/dev/null) || translated="$TEXT"
|
|
248
|
-
|
|
249
|
-
# Get voice for target language if no override specified
|
|
250
|
-
local voice_to_use="$VOICE_OVERRIDE"
|
|
251
|
-
if [[ -z "$voice_to_use" ]]; then
|
|
252
|
-
source "$SCRIPT_DIR/language-manager.sh" 2>/dev/null || true
|
|
253
|
-
voice_to_use=$(get_voice_for_language "$translate_to" "$ACTIVE_PROVIDER" 2>/dev/null || echo "")
|
|
254
|
-
fi
|
|
255
|
-
|
|
256
|
-
# Update provider if voice indicates different provider
|
|
257
|
-
local provider_to_use="$ACTIVE_PROVIDER"
|
|
258
|
-
if [[ -n "$voice_to_use" ]]; then
|
|
259
|
-
provider_to_use=$(detect_voice_provider "$voice_to_use")
|
|
260
|
-
fi
|
|
261
|
-
|
|
262
|
-
# Speak translated text
|
|
263
|
-
speak_text "$translated" "$voice_to_use" "$provider_to_use"
|
|
264
|
-
return 0
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
# Mode priority:
|
|
268
|
-
# 1. Learning mode (speaks twice: main + translated)
|
|
269
|
-
# 2. Translation mode (speaks translated only)
|
|
270
|
-
# 3. Normal mode (speaks as-is)
|
|
271
|
-
|
|
272
|
-
# Try learning mode first (Issue #51)
|
|
273
|
-
if handle_learning_mode; then
|
|
274
|
-
exit 0
|
|
275
|
-
fi
|
|
276
|
-
|
|
277
|
-
# Try translation mode (Issue #50)
|
|
278
|
-
if handle_translation_mode; then
|
|
279
|
-
exit 0
|
|
280
|
-
fi
|
|
281
|
-
|
|
282
|
-
# Normal single-language mode - route to appropriate provider implementation
|
|
283
|
-
case "$ACTIVE_PROVIDER" in
|
|
284
|
-
piper)
|
|
285
|
-
exec "$SCRIPT_DIR/play-tts-piper.sh" "$TEXT" "$VOICE_OVERRIDE" "$AGENT_PROFILE_FILE"
|
|
286
|
-
;;
|
|
287
|
-
soprano)
|
|
288
|
-
exec "$SCRIPT_DIR/play-tts-soprano.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
289
|
-
;;
|
|
290
|
-
macos)
|
|
291
|
-
exec "$SCRIPT_DIR/play-tts-macos.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
292
|
-
;;
|
|
293
|
-
termux-ssh)
|
|
294
|
-
exec "$SCRIPT_DIR/play-tts-termux-ssh.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
295
|
-
;;
|
|
296
|
-
*)
|
|
297
|
-
echo "❌ Unknown provider: $ACTIVE_PROVIDER" >&2
|
|
298
|
-
echo " Run: /agent-vibes:provider list" >&2
|
|
299
|
-
exit 1
|
|
300
|
-
;;
|
|
301
|
-
esac
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# File: .claude/hooks/play-tts.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 TTS Provider Router with Translation and Language Learning Support
|
|
35
|
+
# @context Routes TTS requests to active provider (Piper or macOS) with optional translation
|
|
36
|
+
# @architecture Provider abstraction layer - single entry point for all TTS, handles translation and learning mode
|
|
37
|
+
# @dependencies provider-manager.sh, play-tts-piper.sh, translator.py, translate-manager.sh, learn-manager.sh
|
|
38
|
+
# @entrypoints Called by hooks, slash commands, personality-manager.sh, and all TTS features
|
|
39
|
+
# @patterns Provider pattern - delegates to provider-specific implementations, auto-detects provider from voice name
|
|
40
|
+
# @related provider-manager.sh, play-tts-piper.sh, learn-manager.sh, translate-manager.sh
|
|
41
|
+
#
|
|
42
|
+
|
|
43
|
+
set -euo pipefail
|
|
44
|
+
|
|
45
|
+
# Fix locale warnings
|
|
46
|
+
export LC_ALL=C
|
|
47
|
+
|
|
48
|
+
# Get script directory (needed for mute file check)
|
|
49
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
50
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
51
|
+
export PROJECT_ROOT # Export for child scripts
|
|
52
|
+
|
|
53
|
+
# Check if muted (persists across sessions)
|
|
54
|
+
# Project settings always override global settings:
|
|
55
|
+
# - .claude/agentvibes-unmuted = project explicitly unmuted (overrides global mute)
|
|
56
|
+
# - .claude/agentvibes-muted = project muted (overrides global unmute)
|
|
57
|
+
# - ~/.agentvibes-muted = global mute (only if no project-level setting)
|
|
58
|
+
GLOBAL_MUTE_FILE="$HOME/.agentvibes-muted"
|
|
59
|
+
PROJECT_MUTE_FILE="$PROJECT_ROOT/.claude/agentvibes-muted"
|
|
60
|
+
PROJECT_UNMUTE_FILE="$PROJECT_ROOT/.claude/agentvibes-unmuted"
|
|
61
|
+
|
|
62
|
+
# Check project-level settings first (project overrides global)
|
|
63
|
+
if [[ -f "$PROJECT_UNMUTE_FILE" ]]; then
|
|
64
|
+
# Project explicitly unmuted - ignore global mute
|
|
65
|
+
: # Continue (do nothing, will not exit)
|
|
66
|
+
elif [[ -f "$PROJECT_MUTE_FILE" ]]; then
|
|
67
|
+
# Project explicitly muted
|
|
68
|
+
if [[ -f "$GLOBAL_MUTE_FILE" ]]; then
|
|
69
|
+
echo "🔇 TTS muted (project + global)" >&2
|
|
70
|
+
else
|
|
71
|
+
echo "🔇 TTS muted (project)" >&2
|
|
72
|
+
fi
|
|
73
|
+
exit 0
|
|
74
|
+
elif [[ -f "$GLOBAL_MUTE_FILE" ]]; then
|
|
75
|
+
# Global mute and no project-level override
|
|
76
|
+
echo "🔇 TTS muted (global)" >&2
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
TEXT="${1:-}"
|
|
81
|
+
VOICE_OVERRIDE="${2:-}" # Optional: voice name or ID
|
|
82
|
+
AGENT_PROFILE_FILE="${3:-}" # Optional: path to per-agent profile JSON (from bmad-speak.sh)
|
|
83
|
+
|
|
84
|
+
# Security: Validate inputs
|
|
85
|
+
if [[ -z "$TEXT" ]]; then
|
|
86
|
+
echo "Error: No text provided" >&2
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Security: Validate voice override doesn't contain dangerous characters
|
|
91
|
+
if [[ -n "$VOICE_OVERRIDE" ]] && [[ "$VOICE_OVERRIDE" =~ [';|&$`<>(){}'] ]]; then
|
|
92
|
+
echo "Error: Invalid characters in voice parameter" >&2
|
|
93
|
+
exit 1
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# Remove backslash escaping that Claude might add for SAFE special chars only
|
|
97
|
+
# SECURITY: Only unescape punctuation chars that cannot form shell commands (#127)
|
|
98
|
+
# Never unescape $, `, \, or other shell metacharacters
|
|
99
|
+
TEXT="${TEXT//\\!/!}" # Remove \!
|
|
100
|
+
TEXT="${TEXT//\\?/?}" # Remove \?
|
|
101
|
+
TEXT="${TEXT//\\,/,}" # Remove \,
|
|
102
|
+
TEXT="${TEXT//\\./.}" # Remove \. (keep the period)
|
|
103
|
+
|
|
104
|
+
# Prepend intro text (pretext) if configured
|
|
105
|
+
# Check project-local first, then global
|
|
106
|
+
_PRETEXT_FILE="$PROJECT_ROOT/.claude/config/intro-text.txt"
|
|
107
|
+
[[ -f "$_PRETEXT_FILE" ]] || _PRETEXT_FILE="$HOME/.claude/config/intro-text.txt"
|
|
108
|
+
if [[ -f "$_PRETEXT_FILE" ]]; then
|
|
109
|
+
_PRETEXT="$(head -1 "$_PRETEXT_FILE" 2>/dev/null || true)"
|
|
110
|
+
if [[ -n "$_PRETEXT" ]]; then
|
|
111
|
+
TEXT="${_PRETEXT} ${TEXT}"
|
|
112
|
+
fi
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Source provider manager to get active provider
|
|
116
|
+
source "$SCRIPT_DIR/provider-manager.sh"
|
|
117
|
+
|
|
118
|
+
# Get active provider
|
|
119
|
+
ACTIVE_PROVIDER=$(get_active_provider)
|
|
120
|
+
|
|
121
|
+
# Show GitHub star reminder (once per day)
|
|
122
|
+
"$SCRIPT_DIR/github-star-reminder.sh" 2>/dev/null || true
|
|
123
|
+
|
|
124
|
+
# @function detect_voice_provider
|
|
125
|
+
# @intent Auto-detect provider from voice name (for mixed-provider support)
|
|
126
|
+
# @why Allow Piper for main language + macOS for target language
|
|
127
|
+
# @param $1 voice name/ID
|
|
128
|
+
# @returns Provider name (piper or macos)
|
|
129
|
+
detect_voice_provider() {
|
|
130
|
+
local voice="$1"
|
|
131
|
+
# Piper voice names contain underscore and dash (e.g., es_ES-davefx-medium)
|
|
132
|
+
if [[ "$voice" == *"_"*"-"* ]]; then
|
|
133
|
+
echo "piper"
|
|
134
|
+
else
|
|
135
|
+
echo "$ACTIVE_PROVIDER"
|
|
136
|
+
fi
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# Override provider if voice indicates different provider (mixed-provider mode)
|
|
140
|
+
if [[ -n "$VOICE_OVERRIDE" ]]; then
|
|
141
|
+
DETECTED_PROVIDER=$(detect_voice_provider "$VOICE_OVERRIDE")
|
|
142
|
+
if [[ "$DETECTED_PROVIDER" != "$ACTIVE_PROVIDER" ]]; then
|
|
143
|
+
ACTIVE_PROVIDER="$DETECTED_PROVIDER"
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# @function speak_text
|
|
148
|
+
# @intent Route text to appropriate TTS provider
|
|
149
|
+
# @why Reusable function for speaking, used by both single and learning modes
|
|
150
|
+
# @param $1 text to speak
|
|
151
|
+
# @param $2 voice override (optional)
|
|
152
|
+
# @param $3 provider override (optional)
|
|
153
|
+
speak_text() {
|
|
154
|
+
local text="$1"
|
|
155
|
+
local voice="${2:-}"
|
|
156
|
+
local provider="${3:-$ACTIVE_PROVIDER}"
|
|
157
|
+
local profile_file="${4:-$AGENT_PROFILE_FILE}"
|
|
158
|
+
|
|
159
|
+
case "$provider" in
|
|
160
|
+
piper)
|
|
161
|
+
"$SCRIPT_DIR/play-tts-piper.sh" "$text" "$voice" "$profile_file"
|
|
162
|
+
;;
|
|
163
|
+
soprano)
|
|
164
|
+
"$SCRIPT_DIR/play-tts-soprano.sh" "$text" "$voice"
|
|
165
|
+
;;
|
|
166
|
+
macos)
|
|
167
|
+
"$SCRIPT_DIR/play-tts-macos.sh" "$text" "$voice"
|
|
168
|
+
;;
|
|
169
|
+
termux-ssh)
|
|
170
|
+
"$SCRIPT_DIR/play-tts-termux-ssh.sh" "$text" "$voice"
|
|
171
|
+
;;
|
|
172
|
+
*)
|
|
173
|
+
echo "❌ Unknown provider: $provider" >&2
|
|
174
|
+
return 1
|
|
175
|
+
;;
|
|
176
|
+
esac
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# Note: learn-manager.sh and translate-manager.sh are sourced inside their
|
|
180
|
+
# respective handler functions to avoid triggering their main handlers
|
|
181
|
+
|
|
182
|
+
# @function handle_learning_mode
|
|
183
|
+
# @intent Speak in both main language and target language for learning
|
|
184
|
+
# @why Issue #51 - Auto-translate and speak twice for immersive language learning
|
|
185
|
+
# @returns 0 if learning mode handled, 1 if not in learning mode
|
|
186
|
+
handle_learning_mode() {
|
|
187
|
+
# Source learn-manager for learning mode functions
|
|
188
|
+
source "$SCRIPT_DIR/learn-manager.sh" 2>/dev/null || return 1
|
|
189
|
+
|
|
190
|
+
# Check if learning mode is enabled
|
|
191
|
+
if ! is_learn_mode_enabled 2>/dev/null; then
|
|
192
|
+
return 1
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
local target_lang
|
|
196
|
+
target_lang=$(get_target_language 2>/dev/null || echo "")
|
|
197
|
+
local target_voice
|
|
198
|
+
target_voice=$(get_target_voice 2>/dev/null || echo "")
|
|
199
|
+
|
|
200
|
+
# Need both target language and voice for learning mode
|
|
201
|
+
if [[ -z "$target_lang" ]] || [[ -z "$target_voice" ]]; then
|
|
202
|
+
return 1
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
# 1. Speak in main language (current voice)
|
|
206
|
+
speak_text "$TEXT" "$VOICE_OVERRIDE" "$ACTIVE_PROVIDER"
|
|
207
|
+
|
|
208
|
+
# 2. Auto-translate to target language
|
|
209
|
+
local translated
|
|
210
|
+
# SECURITY: Add timeout to prevent hanging (#134)
|
|
211
|
+
translated=$(timeout 5 python3 "$SCRIPT_DIR/translator.py" "$TEXT" "$target_lang" 2>/dev/null) || translated="$TEXT"
|
|
212
|
+
|
|
213
|
+
# Small pause between languages
|
|
214
|
+
sleep 0.5
|
|
215
|
+
|
|
216
|
+
# 3. Speak translated text with target voice
|
|
217
|
+
local target_provider
|
|
218
|
+
target_provider=$(detect_voice_provider "$target_voice")
|
|
219
|
+
speak_text "$translated" "$target_voice" "$target_provider"
|
|
220
|
+
|
|
221
|
+
return 0
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# @function handle_translation_mode
|
|
225
|
+
# @intent Translate and speak in target language (non-learning mode)
|
|
226
|
+
# @why Issue #50 - BMAD multi-language TTS support
|
|
227
|
+
# @returns 0 if translation handled, 1 if not translating
|
|
228
|
+
handle_translation_mode() {
|
|
229
|
+
# Source translate-manager to get translation settings
|
|
230
|
+
source "$SCRIPT_DIR/translate-manager.sh" 2>/dev/null || return 1
|
|
231
|
+
|
|
232
|
+
# Check if translation is enabled
|
|
233
|
+
if ! is_translation_enabled 2>/dev/null; then
|
|
234
|
+
return 1
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
local translate_to
|
|
238
|
+
translate_to=$(get_translate_to 2>/dev/null || echo "")
|
|
239
|
+
|
|
240
|
+
if [[ -z "$translate_to" ]] || [[ "$translate_to" == "english" ]]; then
|
|
241
|
+
return 1
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
# Translate text
|
|
245
|
+
local translated
|
|
246
|
+
# SECURITY: Add timeout to prevent hanging (#134)
|
|
247
|
+
translated=$(timeout 5 python3 "$SCRIPT_DIR/translator.py" "$TEXT" "$translate_to" 2>/dev/null) || translated="$TEXT"
|
|
248
|
+
|
|
249
|
+
# Get voice for target language if no override specified
|
|
250
|
+
local voice_to_use="$VOICE_OVERRIDE"
|
|
251
|
+
if [[ -z "$voice_to_use" ]]; then
|
|
252
|
+
source "$SCRIPT_DIR/language-manager.sh" 2>/dev/null || true
|
|
253
|
+
voice_to_use=$(get_voice_for_language "$translate_to" "$ACTIVE_PROVIDER" 2>/dev/null || echo "")
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
# Update provider if voice indicates different provider
|
|
257
|
+
local provider_to_use="$ACTIVE_PROVIDER"
|
|
258
|
+
if [[ -n "$voice_to_use" ]]; then
|
|
259
|
+
provider_to_use=$(detect_voice_provider "$voice_to_use")
|
|
260
|
+
fi
|
|
261
|
+
|
|
262
|
+
# Speak translated text
|
|
263
|
+
speak_text "$translated" "$voice_to_use" "$provider_to_use"
|
|
264
|
+
return 0
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
# Mode priority:
|
|
268
|
+
# 1. Learning mode (speaks twice: main + translated)
|
|
269
|
+
# 2. Translation mode (speaks translated only)
|
|
270
|
+
# 3. Normal mode (speaks as-is)
|
|
271
|
+
|
|
272
|
+
# Try learning mode first (Issue #51)
|
|
273
|
+
if handle_learning_mode; then
|
|
274
|
+
exit 0
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# Try translation mode (Issue #50)
|
|
278
|
+
if handle_translation_mode; then
|
|
279
|
+
exit 0
|
|
280
|
+
fi
|
|
281
|
+
|
|
282
|
+
# Normal single-language mode - route to appropriate provider implementation
|
|
283
|
+
case "$ACTIVE_PROVIDER" in
|
|
284
|
+
piper)
|
|
285
|
+
exec "$SCRIPT_DIR/play-tts-piper.sh" "$TEXT" "$VOICE_OVERRIDE" "$AGENT_PROFILE_FILE"
|
|
286
|
+
;;
|
|
287
|
+
soprano)
|
|
288
|
+
exec "$SCRIPT_DIR/play-tts-soprano.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
289
|
+
;;
|
|
290
|
+
macos)
|
|
291
|
+
exec "$SCRIPT_DIR/play-tts-macos.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
292
|
+
;;
|
|
293
|
+
termux-ssh)
|
|
294
|
+
exec "$SCRIPT_DIR/play-tts-termux-ssh.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
295
|
+
;;
|
|
296
|
+
*)
|
|
297
|
+
echo "❌ Unknown provider: $ACTIVE_PROVIDER" >&2
|
|
298
|
+
echo " Run: /agent-vibes:provider list" >&2
|
|
299
|
+
exit 1
|
|
300
|
+
;;
|
|
301
|
+
esac
|