agentvibes 2.0.6 → 2.0.8
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/.claude/commands/agent-vibes/preview.md +5 -4
- package/.claude/commands/agent-vibes/whoami.md +2 -2
- package/.claude/hooks/check-output-style.sh +60 -0
- package/.claude/hooks/language-manager.sh +50 -48
- package/.claude/hooks/personality-manager.sh +34 -2
- package/.claude/hooks/play-tts-piper.sh +27 -9
- package/.claude/hooks/play-tts.sh +29 -127
- package/.claude/hooks/provider-commands.sh +41 -2
- package/.claude/hooks/voice-manager.sh +85 -36
- package/.claude/personalities/angry.md +2 -1
- package/.claude/personalities/annoying.md +2 -1
- package/.claude/personalities/crass.md +2 -1
- package/.claude/personalities/dramatic.md +2 -1
- package/.claude/personalities/dry-humor.md +2 -1
- package/.claude/personalities/flirty.md +2 -1
- package/.claude/personalities/funny.md +2 -1
- package/.claude/personalities/grandpa.md +2 -1
- package/.claude/personalities/millennial.md +2 -1
- package/.claude/personalities/moody.md +2 -1
- package/.claude/personalities/normal.md +2 -1
- package/.claude/personalities/pirate.md +2 -1
- package/.claude/personalities/poetic.md +2 -1
- package/.claude/personalities/professional.md +2 -1
- package/.claude/personalities/robot.md +2 -1
- package/.claude/personalities/sarcastic.md +2 -1
- package/.claude/personalities/sassy.md +2 -1
- package/.claude/personalities/surfer-dude.md +2 -1
- package/.claude/personalities/zen.md +2 -1
- package/.claude/piper-voices-dir.txt +1 -0
- package/README.md +2 -2
- package/RELEASE_NOTES.md +277 -0
- package/agentvibes.org/.claude/commands/agent-vibes/add.md +21 -0
- package/agentvibes.org/.claude/commands/agent-vibes/agent-vibes.md +68 -0
- package/agentvibes.org/.claude/commands/agent-vibes/commands.json +53 -0
- package/agentvibes.org/.claude/commands/agent-vibes/get.md +9 -0
- package/agentvibes.org/.claude/commands/agent-vibes/list.md +13 -0
- package/agentvibes.org/.claude/commands/agent-vibes/personality.md +79 -0
- package/agentvibes.org/.claude/commands/agent-vibes/preview.md +16 -0
- package/agentvibes.org/.claude/commands/agent-vibes/provider.md +54 -0
- package/agentvibes.org/.claude/commands/agent-vibes/replay.md +19 -0
- package/agentvibes.org/.claude/commands/agent-vibes/sample.md +12 -0
- package/agentvibes.org/.claude/commands/agent-vibes/sentiment.md +52 -0
- package/agentvibes.org/.claude/commands/agent-vibes/set-language.md +47 -0
- package/agentvibes.org/.claude/commands/agent-vibes/set-pretext.md +65 -0
- package/agentvibes.org/.claude/commands/agent-vibes/switch.md +53 -0
- package/agentvibes.org/.claude/commands/agent-vibes/update.md +20 -0
- package/agentvibes.org/.claude/commands/agent-vibes/version.md +10 -0
- package/agentvibes.org/.claude/commands/agent-vibes/whoami.md +7 -0
- package/agentvibes.org/.claude/hooks/bmad-voice-manager.sh +278 -0
- package/agentvibes.org/.claude/hooks/language-manager.sh +190 -0
- package/agentvibes.org/.claude/hooks/personality-manager.sh +279 -0
- package/agentvibes.org/.claude/hooks/piper-download-voices.sh +133 -0
- package/agentvibes.org/.claude/hooks/piper-voice-manager.sh +227 -0
- package/agentvibes.org/.claude/hooks/play-tts-elevenlabs.sh +201 -0
- package/agentvibes.org/.claude/hooks/play-tts-piper.sh +175 -0
- package/agentvibes.org/.claude/hooks/play-tts.sh +138 -0
- package/agentvibes.org/.claude/hooks/provider-commands.sh +374 -0
- package/agentvibes.org/.claude/hooks/provider-manager.sh +196 -0
- package/agentvibes.org/.claude/hooks/sentiment-manager.sh +163 -0
- package/agentvibes.org/.claude/hooks/voice-manager.sh +349 -0
- package/agentvibes.org/.claude/hooks/voices-config.sh +33 -0
- package/agentvibes.org/.claude/journal/2025-10-07.html +373 -0
- package/agentvibes.org/.claude/journal/index.html +91 -0
- package/agentvibes.org/.claude/output-styles/agent-vibes.md +203 -0
- package/agentvibes.org/.claude/personalities/angry.md +16 -0
- package/agentvibes.org/.claude/personalities/annoying.md +16 -0
- package/agentvibes.org/.claude/personalities/crass.md +16 -0
- package/agentvibes.org/.claude/personalities/dramatic.md +16 -0
- package/agentvibes.org/.claude/personalities/dry-humor.md +52 -0
- package/agentvibes.org/.claude/personalities/flirty.md +22 -0
- package/agentvibes.org/.claude/personalities/funny.md +16 -0
- package/agentvibes.org/.claude/personalities/grandpa.md +34 -0
- package/agentvibes.org/.claude/personalities/millennial.md +16 -0
- package/agentvibes.org/.claude/personalities/moody.md +16 -0
- package/agentvibes.org/.claude/personalities/normal.md +18 -0
- package/agentvibes.org/.claude/personalities/pirate.md +16 -0
- package/agentvibes.org/.claude/personalities/poetic.md +16 -0
- package/agentvibes.org/.claude/personalities/professional.md +16 -0
- package/agentvibes.org/.claude/personalities/robot.md +16 -0
- package/agentvibes.org/.claude/personalities/sarcastic.md +40 -0
- package/agentvibes.org/.claude/personalities/sassy.md +16 -0
- package/agentvibes.org/.claude/personalities/surfer-dude.md +16 -0
- package/agentvibes.org/.claude/personalities/zen.md +16 -0
- package/agentvibes.org/.mcp-minimal.json +60 -0
- package/agentvibes.org/CHANGELOG.md +56 -0
- package/agentvibes.org/README.md +93 -0
- package/agentvibes.org/app/(auth)/layout.tsx +15 -0
- package/agentvibes.org/app/(auth)/reset-password/page.tsx +45 -0
- package/agentvibes.org/app/(auth)/signin/page.tsx +82 -0
- package/agentvibes.org/app/(auth)/signup/page.tsx +104 -0
- package/agentvibes.org/app/(default)/layout.tsx +31 -0
- package/agentvibes.org/app/(default)/page.tsx +20 -0
- package/agentvibes.org/app/api/hello/route.ts +3 -0
- package/agentvibes.org/app/css/additional-styles/theme.css +82 -0
- package/agentvibes.org/app/css/additional-styles/utility-patterns.css +55 -0
- package/agentvibes.org/app/css/style.css +100 -0
- package/agentvibes.org/app/layout.tsx +63 -0
- package/agentvibes.org/components/cta.tsx +58 -0
- package/agentvibes.org/components/features.tsx +256 -0
- package/agentvibes.org/components/hero-home.tsx +133 -0
- package/agentvibes.org/components/modal-video.tsx +137 -0
- package/agentvibes.org/components/page-illustration.tsx +55 -0
- package/agentvibes.org/components/spotlight.tsx +77 -0
- package/agentvibes.org/components/testimonials.tsx +282 -0
- package/agentvibes.org/components/ui/footer.tsx +82 -0
- package/agentvibes.org/components/ui/header.tsx +53 -0
- package/agentvibes.org/components/ui/logo.tsx +10 -0
- package/agentvibes.org/components/workflows.tsx +176 -0
- package/agentvibes.org/next.config.js +4 -0
- package/agentvibes.org/package-lock.json +1974 -0
- package/agentvibes.org/package.json +30 -0
- package/agentvibes.org/pnpm-lock.yaml +1141 -0
- package/agentvibes.org/postcss.config.js +5 -0
- package/agentvibes.org/public/audio/02-sarcastic.mp3 +0 -0
- package/agentvibes.org/public/audio/03-angry.mp3 +0 -0
- package/agentvibes.org/public/audio/04-grandpa.mp3 +0 -0
- package/agentvibes.org/public/audio/05-sarcastic-example2.mp3 +0 -0
- package/agentvibes.org/public/audio/french-rachel.mp3 +0 -0
- package/agentvibes.org/public/audio/spanish-antoni.mp3 +0 -0
- package/agentvibes.org/public/favicon.ico +0 -0
- package/agentvibes.org/public/fonts/nacelle-italic.woff2 +0 -0
- package/agentvibes.org/public/fonts/nacelle-regular.woff2 +0 -0
- package/agentvibes.org/public/fonts/nacelle-semibold.woff2 +0 -0
- package/agentvibes.org/public/fonts/nacelle-semibolditalic.woff2 +0 -0
- package/agentvibes.org/public/images/blurred-shape-gray.svg +1 -0
- package/agentvibes.org/public/images/blurred-shape.svg +1 -0
- package/agentvibes.org/public/images/client-logo-01.svg +1 -0
- package/agentvibes.org/public/images/client-logo-02.svg +1 -0
- package/agentvibes.org/public/images/client-logo-03.svg +1 -0
- package/agentvibes.org/public/images/client-logo-04.svg +1 -0
- package/agentvibes.org/public/images/client-logo-05.svg +1 -0
- package/agentvibes.org/public/images/client-logo-06.svg +1 -0
- package/agentvibes.org/public/images/client-logo-07.svg +1 -0
- package/agentvibes.org/public/images/client-logo-08.svg +1 -0
- package/agentvibes.org/public/images/client-logo-09.svg +1 -0
- package/agentvibes.org/public/images/features.png +0 -0
- package/agentvibes.org/public/images/footer-illustration.svg +1 -0
- package/agentvibes.org/public/images/hero-image-01.jpg +0 -0
- package/agentvibes.org/public/images/logo.svg +1 -0
- package/agentvibes.org/public/images/page-illustration.svg +1 -0
- package/agentvibes.org/public/images/secondary-illustration.svg +1 -0
- package/agentvibes.org/public/images/testimonial-01.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-02.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-03.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-04.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-05.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-06.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-07.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-08.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-09.jpg +0 -0
- package/agentvibes.org/public/images/workflow-01.png +0 -0
- package/agentvibes.org/public/images/workflow-02.png +0 -0
- package/agentvibes.org/public/images/workflow-03.png +0 -0
- package/agentvibes.org/public/videos/video.mp4 +0 -0
- package/agentvibes.org/tsconfig.json +28 -0
- package/agentvibes.org/utils/useMasonry.tsx +67 -0
- package/agentvibes.org/utils/useMousePosition.tsx +27 -0
- package/package.json +1 -1
- package/src/installer.js +145 -171
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Preview
|
|
2
|
+
description: Preview TTS voices by playing audio samples (provider-aware)
|
|
3
3
|
argument-hint: [voice_name|first|last] [N]
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Preview
|
|
6
|
+
Preview TTS voices by playing audio samples from your active provider.
|
|
7
7
|
|
|
8
8
|
Usage examples:
|
|
9
9
|
- `/agent-vibes:preview` - Preview first 3 voices (default)
|
|
10
10
|
- `/agent-vibes:preview 5` - Preview first 5 voices
|
|
11
|
-
- `/agent-vibes:preview Jessica` - Preview Jessica Anne Bogart voice
|
|
11
|
+
- `/agent-vibes:preview Jessica` - Preview Jessica Anne Bogart voice (ElevenLabs)
|
|
12
|
+
- `/agent-vibes:preview lessac` - Preview Lessac voice (Piper)
|
|
12
13
|
- `/agent-vibes:preview "Northern Terry"` - Preview Northern Terry voice
|
|
13
14
|
- `/agent-vibes:preview first 10` - Preview first 10 voices
|
|
14
15
|
- `/agent-vibes:preview last 5` - Preview last 5 voices
|
|
15
16
|
|
|
16
|
-
!bash .claude/hooks/
|
|
17
|
+
!bash .claude/hooks/provider-commands.sh preview $ARGUMENTS
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Show the current active voice
|
|
2
|
+
description: Show the current active voice and TTS provider
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Display the currently selected ElevenLabs
|
|
5
|
+
Display the currently selected TTS voice and active provider (ElevenLabs or Piper).
|
|
6
6
|
|
|
7
7
|
!bash .claude/hooks/voice-manager.sh whoami
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# @fileoverview Output Style Detection for AgentVibes
|
|
4
|
+
# @context Detects if agent-vibes output style is active
|
|
5
|
+
# @architecture Helper for slash commands to warn users
|
|
6
|
+
# @why Voice commands won't work without agent-vibes output style
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
# Check if we're in a Claude Code session with agent-vibes output style
|
|
10
|
+
# This is a heuristic check - we can't directly detect the output style,
|
|
11
|
+
# but we can check if TTS commands would work
|
|
12
|
+
|
|
13
|
+
check_output_style() {
|
|
14
|
+
# Strategy: Check if this script is being called from within a Claude response
|
|
15
|
+
# If CLAUDECODE env var is set, we're in Claude Code
|
|
16
|
+
# If not, we're running standalone (not in a Claude Code session)
|
|
17
|
+
|
|
18
|
+
if [[ -z "$CLAUDECODE" ]]; then
|
|
19
|
+
# Not in Claude Code at all
|
|
20
|
+
return 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# We're in Claude Code, but we can't directly detect output style
|
|
24
|
+
# The agent-vibes output style calls our TTS hooks automatically
|
|
25
|
+
# So if this function is called, it means a slash command was invoked
|
|
26
|
+
|
|
27
|
+
# Check if we have the necessary TTS setup
|
|
28
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
29
|
+
|
|
30
|
+
# Check if agent-vibes output style is installed
|
|
31
|
+
if [[ ! -f "$SCRIPT_DIR/../output-styles/agent-vibes.md" ]]; then
|
|
32
|
+
return 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# All checks passed - likely using agent-vibes output style
|
|
36
|
+
return 0
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Show warning if output style is not agent-vibes
|
|
40
|
+
show_output_style_warning() {
|
|
41
|
+
echo ""
|
|
42
|
+
echo "⚠️ Voice commands require the agent-vibes output style"
|
|
43
|
+
echo ""
|
|
44
|
+
echo "To enable voice narration, run:"
|
|
45
|
+
echo " /output-style agent-vibes"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "This will make Claude speak with TTS for all responses."
|
|
48
|
+
echo "You can still use voice commands manually with agent-vibes disabled,"
|
|
49
|
+
echo "but you won't hear automatic TTS narration."
|
|
50
|
+
echo ""
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Main execution when called directly
|
|
54
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
55
|
+
if ! check_output_style; then
|
|
56
|
+
show_output_style_warning
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
@@ -139,52 +139,54 @@ get_best_voice_for_language() {
|
|
|
139
139
|
echo "${LANGUAGE_VOICES[$lang]}"
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
# Main command handler
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
# Main command handler - only run if script is executed directly, not sourced
|
|
143
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
144
|
+
case "${1:-}" in
|
|
145
|
+
set)
|
|
146
|
+
if [[ -z "$2" ]]; then
|
|
147
|
+
echo "Usage: language-manager.sh set <language>"
|
|
148
|
+
exit 1
|
|
149
|
+
fi
|
|
150
|
+
set_language "$2"
|
|
151
|
+
;;
|
|
152
|
+
get)
|
|
153
|
+
get_language
|
|
154
|
+
;;
|
|
155
|
+
code)
|
|
156
|
+
get_language_code
|
|
157
|
+
;;
|
|
158
|
+
check-voice)
|
|
159
|
+
if [[ -z "$2" ]]; then
|
|
160
|
+
echo "Usage: language-manager.sh check-voice <voice-name>"
|
|
161
|
+
exit 1
|
|
162
|
+
fi
|
|
163
|
+
if is_voice_multilingual "$2"; then
|
|
164
|
+
echo "yes"
|
|
165
|
+
else
|
|
166
|
+
echo "no"
|
|
167
|
+
fi
|
|
168
|
+
;;
|
|
169
|
+
best-voice)
|
|
170
|
+
get_best_voice_for_language
|
|
171
|
+
;;
|
|
172
|
+
list)
|
|
173
|
+
echo "Supported languages and recommended voices:"
|
|
174
|
+
echo ""
|
|
175
|
+
for lang in "${!LANGUAGE_VOICES[@]}"; do
|
|
176
|
+
printf "%-15s → %s\n" "$lang" "${LANGUAGE_VOICES[$lang]}"
|
|
177
|
+
done | sort
|
|
178
|
+
;;
|
|
179
|
+
*)
|
|
180
|
+
echo "AgentVibes Language Manager"
|
|
181
|
+
echo ""
|
|
182
|
+
echo "Usage:"
|
|
183
|
+
echo " language-manager.sh set <language> Set language"
|
|
184
|
+
echo " language-manager.sh get Get current language"
|
|
185
|
+
echo " language-manager.sh code Get language code only"
|
|
186
|
+
echo " language-manager.sh check-voice <name> Check if voice is multilingual"
|
|
187
|
+
echo " language-manager.sh best-voice Get best voice for current language"
|
|
188
|
+
echo " language-manager.sh list List all supported languages"
|
|
147
189
|
exit 1
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
get)
|
|
152
|
-
get_language
|
|
153
|
-
;;
|
|
154
|
-
code)
|
|
155
|
-
get_language_code
|
|
156
|
-
;;
|
|
157
|
-
check-voice)
|
|
158
|
-
if [[ -z "$2" ]]; then
|
|
159
|
-
echo "Usage: language-manager.sh check-voice <voice-name>"
|
|
160
|
-
exit 1
|
|
161
|
-
fi
|
|
162
|
-
if is_voice_multilingual "$2"; then
|
|
163
|
-
echo "yes"
|
|
164
|
-
else
|
|
165
|
-
echo "no"
|
|
166
|
-
fi
|
|
167
|
-
;;
|
|
168
|
-
best-voice)
|
|
169
|
-
get_best_voice_for_language
|
|
170
|
-
;;
|
|
171
|
-
list)
|
|
172
|
-
echo "Supported languages and recommended voices:"
|
|
173
|
-
echo ""
|
|
174
|
-
for lang in "${!LANGUAGE_VOICES[@]}"; do
|
|
175
|
-
printf "%-15s → %s\n" "$lang" "${LANGUAGE_VOICES[$lang]}"
|
|
176
|
-
done | sort
|
|
177
|
-
;;
|
|
178
|
-
*)
|
|
179
|
-
echo "AgentVibes Language Manager"
|
|
180
|
-
echo ""
|
|
181
|
-
echo "Usage:"
|
|
182
|
-
echo " language-manager.sh set <language> Set language"
|
|
183
|
-
echo " language-manager.sh get Get current language"
|
|
184
|
-
echo " language-manager.sh code Get language code only"
|
|
185
|
-
echo " language-manager.sh check-voice <name> Check if voice is multilingual"
|
|
186
|
-
echo " language-manager.sh best-voice Get best voice for current language"
|
|
187
|
-
echo " language-manager.sh list List all supported languages"
|
|
188
|
-
exit 1
|
|
189
|
-
;;
|
|
190
|
-
esac
|
|
190
|
+
;;
|
|
191
|
+
esac
|
|
192
|
+
fi
|
|
@@ -37,7 +37,10 @@ get_personality_data() {
|
|
|
37
37
|
grep "^description:" "$file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
|
38
38
|
;;
|
|
39
39
|
voice)
|
|
40
|
-
grep "^
|
|
40
|
+
grep "^elevenlabs_voice:" "$file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
|
41
|
+
;;
|
|
42
|
+
piper_voice)
|
|
43
|
+
grep "^piper_voice:" "$file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
|
41
44
|
;;
|
|
42
45
|
instructions)
|
|
43
46
|
sed -n '/^## AI Instructions/,/^##/p' "$file" | sed '1d;$d'
|
|
@@ -122,7 +125,33 @@ case "$1" in
|
|
|
122
125
|
echo "🎭 Personality set to: $PERSONALITY"
|
|
123
126
|
|
|
124
127
|
# Check if personality has an assigned voice
|
|
125
|
-
|
|
128
|
+
# Detect active TTS provider
|
|
129
|
+
PROVIDER_FILE=""
|
|
130
|
+
if [[ -f "$CLAUDE_DIR/tts-provider.txt" ]]; then
|
|
131
|
+
PROVIDER_FILE="$CLAUDE_DIR/tts-provider.txt"
|
|
132
|
+
elif [[ -f "$HOME/.claude/tts-provider.txt" ]]; then
|
|
133
|
+
PROVIDER_FILE="$HOME/.claude/tts-provider.txt"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
ACTIVE_PROVIDER="elevenlabs" # default
|
|
137
|
+
if [[ -n "$PROVIDER_FILE" ]]; then
|
|
138
|
+
ACTIVE_PROVIDER=$(cat "$PROVIDER_FILE")
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# Get the appropriate voice based on provider
|
|
142
|
+
ASSIGNED_VOICE=""
|
|
143
|
+
if [[ "$ACTIVE_PROVIDER" == "piper" ]]; then
|
|
144
|
+
# Try to get Piper-specific voice first
|
|
145
|
+
ASSIGNED_VOICE=$(get_personality_data "$PERSONALITY" "piper_voice")
|
|
146
|
+
if [[ -z "$ASSIGNED_VOICE" ]]; then
|
|
147
|
+
# Fallback to default Piper voice
|
|
148
|
+
ASSIGNED_VOICE="en_US-lessac-medium"
|
|
149
|
+
fi
|
|
150
|
+
else
|
|
151
|
+
# Use ElevenLabs voice (reads from elevenlabs_voice: field)
|
|
152
|
+
ASSIGNED_VOICE=$(get_personality_data "$PERSONALITY" "voice")
|
|
153
|
+
fi
|
|
154
|
+
|
|
126
155
|
if [[ -n "$ASSIGNED_VOICE" ]]; then
|
|
127
156
|
# Switch to the assigned voice (silently - personality will do the talking)
|
|
128
157
|
VOICE_MANAGER="$SCRIPT_DIR/voice-manager.sh"
|
|
@@ -163,6 +192,9 @@ case "$1" in
|
|
|
163
192
|
|
|
164
193
|
echo ""
|
|
165
194
|
echo "Note: AI will generate unique ${PERSONALITY} responses - no fixed templates!"
|
|
195
|
+
echo ""
|
|
196
|
+
echo "💡 Tip: To hear automatic TTS narration, enable the agent-vibes output style:"
|
|
197
|
+
echo " /output-style agent-vibes"
|
|
166
198
|
fi
|
|
167
199
|
;;
|
|
168
200
|
|
|
@@ -32,22 +32,40 @@ DEFAULT_VOICE="en_US-lessac-medium"
|
|
|
32
32
|
VOICE_MODEL=""
|
|
33
33
|
|
|
34
34
|
# Get current language setting
|
|
35
|
-
CURRENT_LANGUAGE=$(
|
|
35
|
+
CURRENT_LANGUAGE=$(get_language_code)
|
|
36
36
|
|
|
37
37
|
if [[ -n "$VOICE_OVERRIDE" ]]; then
|
|
38
38
|
# Use override if provided
|
|
39
39
|
VOICE_MODEL="$VOICE_OVERRIDE"
|
|
40
40
|
echo "🎤 Using voice: $VOICE_OVERRIDE (session-specific)"
|
|
41
41
|
else
|
|
42
|
-
# Try to get
|
|
43
|
-
|
|
42
|
+
# Try to get voice from voice file (project-local first, then global)
|
|
43
|
+
VOICE_FILE=""
|
|
44
|
+
if [[ -f "$SCRIPT_DIR/../tts-voice.txt" ]]; then
|
|
45
|
+
VOICE_FILE="$SCRIPT_DIR/../tts-voice.txt"
|
|
46
|
+
elif [[ -f "$HOME/.claude/tts-voice.txt" ]]; then
|
|
47
|
+
VOICE_FILE="$HOME/.claude/tts-voice.txt"
|
|
48
|
+
fi
|
|
44
49
|
|
|
45
|
-
if [[ -n "$
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
if [[ -n "$VOICE_FILE" ]]; then
|
|
51
|
+
FILE_VOICE=$(cat "$VOICE_FILE" 2>/dev/null)
|
|
52
|
+
# Check if it's a Piper model name (contains underscore and dash)
|
|
53
|
+
if [[ "$FILE_VOICE" == *"_"*"-"* ]]; then
|
|
54
|
+
VOICE_MODEL="$FILE_VOICE"
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# If no Piper voice from file, try language-specific voice
|
|
59
|
+
if [[ -z "$VOICE_MODEL" ]]; then
|
|
60
|
+
LANG_VOICE=$(get_voice_for_language "$CURRENT_LANGUAGE" "piper" 2>/dev/null)
|
|
61
|
+
|
|
62
|
+
if [[ -n "$LANG_VOICE" ]]; then
|
|
63
|
+
VOICE_MODEL="$LANG_VOICE"
|
|
64
|
+
echo "🌍 Using $CURRENT_LANGUAGE voice: $LANG_VOICE (Piper)"
|
|
65
|
+
else
|
|
66
|
+
# Use default voice
|
|
67
|
+
VOICE_MODEL="$DEFAULT_VOICE"
|
|
68
|
+
fi
|
|
51
69
|
fi
|
|
52
70
|
fi
|
|
53
71
|
|
|
@@ -1,138 +1,40 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Quick TTS playback script with session-specific voice support
|
|
3
|
-
# Usage: play-tts.sh "Text to speak" [voice_name_or_id]
|
|
4
2
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
3
|
+
# @fileoverview TTS Provider Router
|
|
4
|
+
# @context Routes TTS requests to active provider (ElevenLabs or Piper)
|
|
5
|
+
# @architecture Provider abstraction layer - single entry point for all TTS
|
|
6
|
+
# @dependencies provider-manager.sh, play-tts-elevenlabs.sh, play-tts-piper.sh
|
|
7
|
+
# @entrypoints Called by hooks, slash commands, and personality-manager.sh
|
|
8
|
+
# @patterns Provider pattern - delegates to provider-specific implementations
|
|
9
|
+
# @related provider-manager.sh, play-tts-elevenlabs.sh, play-tts-piper.sh
|
|
9
10
|
#
|
|
10
|
-
# This allows different sessions to use different voices for easy identification!
|
|
11
11
|
|
|
12
12
|
# Fix locale warnings
|
|
13
13
|
export LC_ALL=C
|
|
14
14
|
|
|
15
15
|
TEXT="$1"
|
|
16
|
-
VOICE_OVERRIDE="$2" # Optional: voice name or
|
|
17
|
-
API_KEY="${ELEVENLABS_API_KEY}"
|
|
16
|
+
VOICE_OVERRIDE="$2" # Optional: voice name or ID
|
|
18
17
|
|
|
19
|
-
#
|
|
20
|
-
CONFIG_DIR="${CLAUDE_PROJECT_DIR:-.}/.claude/config"
|
|
21
|
-
CONFIG_FILE="$CONFIG_DIR/agentvibes.json"
|
|
22
|
-
|
|
23
|
-
if [[ -f "$CONFIG_FILE" ]] && command -v jq &> /dev/null; then
|
|
24
|
-
PRETEXT=$(jq -r '.pretext // empty' "$CONFIG_FILE" 2>/dev/null)
|
|
25
|
-
if [[ -n "$PRETEXT" ]]; then
|
|
26
|
-
TEXT="$PRETEXT: $TEXT"
|
|
27
|
-
fi
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Limit text length to prevent API issues (max 500 chars for safety)
|
|
31
|
-
if [ ${#TEXT} -gt 500 ]; then
|
|
32
|
-
TEXT="${TEXT:0:497}..."
|
|
33
|
-
echo "⚠️ Text truncated to 500 characters for API safety"
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Source the single voice configuration file
|
|
18
|
+
# Get script directory
|
|
37
19
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
38
|
-
source "$SCRIPT_DIR/voices-config.sh"
|
|
39
|
-
|
|
40
|
-
# Determine which voice to use
|
|
41
|
-
VOICE_ID=""
|
|
42
|
-
|
|
43
|
-
if [[ -n "$VOICE_OVERRIDE" ]]; then
|
|
44
|
-
# Check if override is a voice name (lookup in mapping)
|
|
45
|
-
if [[ -n "${VOICES[$VOICE_OVERRIDE]}" ]]; then
|
|
46
|
-
VOICE_ID="${VOICES[$VOICE_OVERRIDE]}"
|
|
47
|
-
echo "🎤 Using voice: $VOICE_OVERRIDE (session-specific)"
|
|
48
|
-
# Check if override looks like a voice ID (alphanumeric string ~20 chars)
|
|
49
|
-
elif [[ "$VOICE_OVERRIDE" =~ ^[a-zA-Z0-9]{15,30}$ ]]; then
|
|
50
|
-
VOICE_ID="$VOICE_OVERRIDE"
|
|
51
|
-
echo "🎤 Using custom voice ID (session-specific)"
|
|
52
|
-
else
|
|
53
|
-
echo "⚠️ Unknown voice '$VOICE_OVERRIDE', using default"
|
|
54
|
-
fi
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
# If no override or invalid override, use default from voice manager
|
|
58
|
-
if [[ -z "$VOICE_ID" ]]; then
|
|
59
|
-
VOICE_MANAGER_SCRIPT="$(dirname "$0")/voice-manager.sh"
|
|
60
|
-
if [[ -f "$VOICE_MANAGER_SCRIPT" ]]; then
|
|
61
|
-
VOICE_NAME=$("$VOICE_MANAGER_SCRIPT" get)
|
|
62
|
-
VOICE_ID="${VOICES[$VOICE_NAME]}"
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
# Final fallback to Cowboy Bob default
|
|
66
|
-
if [[ -z "$VOICE_ID" ]]; then
|
|
67
|
-
echo "⚠️ No voice configured, using Cowboy Bob default"
|
|
68
|
-
VOICE_ID="${VOICES[Cowboy Bob]}"
|
|
69
|
-
fi
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
if [ -z "$TEXT" ]; then
|
|
73
|
-
echo "Usage: $0 \"text to speak\""
|
|
74
|
-
exit 1
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
if [ -z "$API_KEY" ]; then
|
|
78
|
-
echo "Error: ELEVENLABS_API_KEY not set"
|
|
79
|
-
exit 1
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
# Create audio file in project-local storage
|
|
83
|
-
# Use project directory if available, otherwise fall back to global
|
|
84
|
-
if [[ -n "$CLAUDE_PROJECT_DIR" ]]; then
|
|
85
|
-
AUDIO_DIR="$CLAUDE_PROJECT_DIR/.claude/audio"
|
|
86
|
-
else
|
|
87
|
-
# Fallback: try to find .claude directory in current path
|
|
88
|
-
CURRENT_DIR="$PWD"
|
|
89
|
-
while [[ "$CURRENT_DIR" != "/" ]]; do
|
|
90
|
-
if [[ -d "$CURRENT_DIR/.claude" ]]; then
|
|
91
|
-
AUDIO_DIR="$CURRENT_DIR/.claude/audio"
|
|
92
|
-
break
|
|
93
|
-
fi
|
|
94
|
-
CURRENT_DIR=$(dirname "$CURRENT_DIR")
|
|
95
|
-
done
|
|
96
|
-
# Final fallback to global if no project .claude found
|
|
97
|
-
if [[ -z "$AUDIO_DIR" ]]; then
|
|
98
|
-
AUDIO_DIR="$HOME/.claude/audio"
|
|
99
|
-
fi
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
mkdir -p "$AUDIO_DIR"
|
|
103
|
-
TEMP_FILE="$AUDIO_DIR/tts-$(date +%s).mp3"
|
|
104
|
-
|
|
105
|
-
# Generate audio
|
|
106
|
-
curl -s -X POST "https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}" \
|
|
107
|
-
-H "xi-api-key: ${API_KEY}" \
|
|
108
|
-
-H "Content-Type: application/json" \
|
|
109
|
-
-d "{\"text\":\"${TEXT}\",\"model_id\":\"eleven_monolingual_v1\",\"voice_settings\":{\"stability\":0.5,\"similarity_boost\":0.75}}" \
|
|
110
|
-
-o "${TEMP_FILE}"
|
|
111
|
-
|
|
112
|
-
# Add silence padding to prevent WSL audio static
|
|
113
|
-
if [ -f "${TEMP_FILE}" ]; then
|
|
114
|
-
# Check if ffmpeg is available for adding padding
|
|
115
|
-
if command -v ffmpeg &> /dev/null; then
|
|
116
|
-
PADDED_FILE="$AUDIO_DIR/tts-padded-$(date +%s).mp3"
|
|
117
|
-
# Add 200ms of silence at the beginning to prevent static
|
|
118
|
-
ffmpeg -f lavfi -i anullsrc=r=44100:cl=stereo:d=0.2 -i "${TEMP_FILE}" \
|
|
119
|
-
-filter_complex "[0:a][1:a]concat=n=2:v=0:a=1[out]" \
|
|
120
|
-
-map "[out]" -y "${PADDED_FILE}" 2>/dev/null
|
|
121
|
-
|
|
122
|
-
if [ -f "${PADDED_FILE}" ]; then
|
|
123
|
-
# Use padded file and clean up original
|
|
124
|
-
rm -f "${TEMP_FILE}"
|
|
125
|
-
TEMP_FILE="${PADDED_FILE}"
|
|
126
|
-
fi
|
|
127
|
-
# If padding failed, just use original file
|
|
128
|
-
fi
|
|
129
20
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
21
|
+
# Source provider manager to get active provider
|
|
22
|
+
source "$SCRIPT_DIR/provider-manager.sh"
|
|
23
|
+
|
|
24
|
+
# Get active provider
|
|
25
|
+
ACTIVE_PROVIDER=$(get_active_provider)
|
|
26
|
+
|
|
27
|
+
# Route to appropriate provider implementation
|
|
28
|
+
case "$ACTIVE_PROVIDER" in
|
|
29
|
+
elevenlabs)
|
|
30
|
+
exec "$SCRIPT_DIR/play-tts-elevenlabs.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
31
|
+
;;
|
|
32
|
+
piper)
|
|
33
|
+
exec "$SCRIPT_DIR/play-tts-piper.sh" "$TEXT" "$VOICE_OVERRIDE"
|
|
34
|
+
;;
|
|
35
|
+
*)
|
|
36
|
+
echo "❌ Unknown provider: $ACTIVE_PROVIDER"
|
|
37
|
+
echo " Run: /agent-vibes:provider list"
|
|
38
|
+
exit 1
|
|
39
|
+
;;
|
|
40
|
+
esac
|
|
@@ -292,10 +292,49 @@ provider_preview() {
|
|
|
292
292
|
;;
|
|
293
293
|
piper)
|
|
294
294
|
# Use the Piper voice manager's list functionality
|
|
295
|
-
# For Piper, we'll list and play sample from available voices
|
|
296
295
|
source "$SCRIPT_DIR/piper-voice-manager.sh"
|
|
297
296
|
|
|
298
|
-
#
|
|
297
|
+
# Check if a specific voice was requested
|
|
298
|
+
local voice_arg="$1"
|
|
299
|
+
|
|
300
|
+
if [[ -n "$voice_arg" ]]; then
|
|
301
|
+
# User requested a specific voice - check if it's a valid Piper voice
|
|
302
|
+
# Piper voice names are like: en_US-lessac-medium
|
|
303
|
+
# Try to find a matching voice model
|
|
304
|
+
|
|
305
|
+
# Check if the voice arg looks like a Piper model name (contains underscores/hyphens)
|
|
306
|
+
if [[ "$voice_arg" =~ ^[a-z]{2}_[A-Z]{2}- ]]; then
|
|
307
|
+
# Looks like a Piper voice model name
|
|
308
|
+
if verify_voice "$voice_arg"; then
|
|
309
|
+
echo "🎤 Previewing Piper voice: $voice_arg"
|
|
310
|
+
echo ""
|
|
311
|
+
"$SCRIPT_DIR/play-tts.sh" "Hello, this is the $voice_arg voice. How do you like it?" "$voice_arg"
|
|
312
|
+
else
|
|
313
|
+
echo "❌ Voice model not found: $voice_arg"
|
|
314
|
+
echo ""
|
|
315
|
+
echo "💡 Piper voice names look like: en_US-lessac-medium"
|
|
316
|
+
echo " Run /agent-vibes:list to see available Piper voices"
|
|
317
|
+
fi
|
|
318
|
+
else
|
|
319
|
+
# Looks like an ElevenLabs voice name (like "Antoni", "Jessica")
|
|
320
|
+
echo "❌ '$voice_arg' appears to be an ElevenLabs voice"
|
|
321
|
+
echo ""
|
|
322
|
+
echo "You're currently using Piper TTS (free provider)."
|
|
323
|
+
echo "Piper has different voices than ElevenLabs."
|
|
324
|
+
echo ""
|
|
325
|
+
echo "Options:"
|
|
326
|
+
echo " 1. Run /agent-vibes:list to see available Piper voices"
|
|
327
|
+
echo " 2. Switch to ElevenLabs: /agent-vibes:provider switch elevenlabs"
|
|
328
|
+
echo ""
|
|
329
|
+
echo "Popular Piper voices to try:"
|
|
330
|
+
echo " • en_US-lessac-medium (clear, professional)"
|
|
331
|
+
echo " • en_US-amy-medium (warm, friendly)"
|
|
332
|
+
echo " • en_US-joe-medium (casual, natural)"
|
|
333
|
+
fi
|
|
334
|
+
return
|
|
335
|
+
fi
|
|
336
|
+
|
|
337
|
+
# No specific voice - preview first 3 voices
|
|
299
338
|
echo "🎤 Piper Preview of 3 people"
|
|
300
339
|
echo ""
|
|
301
340
|
|
|
@@ -163,52 +163,77 @@ case "$1" in
|
|
|
163
163
|
exit 0
|
|
164
164
|
fi
|
|
165
165
|
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
# Detect active TTS provider
|
|
167
|
+
PROVIDER_FILE=""
|
|
168
|
+
if [[ -f "$CLAUDE_DIR/tts-provider.txt" ]]; then
|
|
169
|
+
PROVIDER_FILE="$CLAUDE_DIR/tts-provider.txt"
|
|
170
|
+
elif [[ -f "$HOME/.claude/tts-provider.txt" ]]; then
|
|
171
|
+
PROVIDER_FILE="$HOME/.claude/tts-provider.txt"
|
|
172
|
+
fi
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
ACTIVE_PROVIDER="elevenlabs" # default
|
|
175
|
+
if [[ -n "$PROVIDER_FILE" ]]; then
|
|
176
|
+
ACTIVE_PROVIDER=$(cat "$PROVIDER_FILE")
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
# If using Piper and voice name looks like a Piper model (contains underscore and dash)
|
|
180
|
+
# then skip ElevenLabs voice validation
|
|
181
|
+
if [[ "$ACTIVE_PROVIDER" == "piper" ]] && [[ "$VOICE_NAME" == *"_"*"-"* ]]; then
|
|
182
|
+
# This is a Piper model name, use it directly
|
|
183
|
+
FOUND="$VOICE_NAME"
|
|
184
|
+
else
|
|
185
|
+
# ElevenLabs voice lookup
|
|
186
|
+
# Check if input is a number
|
|
187
|
+
if [[ "$VOICE_NAME" =~ ^[0-9]+$ ]]; then
|
|
188
|
+
# Get voice array
|
|
189
|
+
VOICE_ARRAY=()
|
|
190
|
+
for voice in "${!VOICES[@]}"; do
|
|
191
|
+
VOICE_ARRAY+=("$voice")
|
|
192
|
+
done
|
|
193
|
+
|
|
194
|
+
# Sort the array
|
|
195
|
+
IFS=$'\n' SORTED_VOICES=($(sort <<<"${VOICE_ARRAY[*]}"))
|
|
196
|
+
unset IFS
|
|
177
197
|
|
|
178
|
-
|
|
179
|
-
|
|
198
|
+
# Get voice by number (adjust for 0-based index)
|
|
199
|
+
INDEX=$((VOICE_NAME - 1))
|
|
180
200
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
201
|
+
if [[ $INDEX -ge 0 && $INDEX -lt ${#SORTED_VOICES[@]} ]]; then
|
|
202
|
+
VOICE_NAME="${SORTED_VOICES[$INDEX]}"
|
|
203
|
+
FOUND="${SORTED_VOICES[$INDEX]}"
|
|
204
|
+
else
|
|
205
|
+
echo "❌ Invalid number. Please choose between 1 and ${#SORTED_VOICES[@]}"
|
|
206
|
+
exit 1
|
|
207
|
+
fi
|
|
184
208
|
else
|
|
185
|
-
|
|
186
|
-
|
|
209
|
+
# Check if voice exists (case-insensitive)
|
|
210
|
+
FOUND=""
|
|
211
|
+
for voice in "${!VOICES[@]}"; do
|
|
212
|
+
if [[ "${voice,,}" == "${VOICE_NAME,,}" ]]; then
|
|
213
|
+
FOUND="$voice"
|
|
214
|
+
break
|
|
215
|
+
fi
|
|
216
|
+
done
|
|
187
217
|
fi
|
|
188
|
-
else
|
|
189
|
-
# Check if voice exists (case-insensitive)
|
|
190
|
-
FOUND=""
|
|
191
|
-
for voice in "${!VOICES[@]}"; do
|
|
192
|
-
if [[ "${voice,,}" == "${VOICE_NAME,,}" ]]; then
|
|
193
|
-
FOUND="$voice"
|
|
194
|
-
break
|
|
195
|
-
fi
|
|
196
|
-
done
|
|
197
|
-
fi
|
|
198
218
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
219
|
+
if [[ -z "$FOUND" ]]; then
|
|
220
|
+
echo "❌ Unknown voice: $VOICE_NAME"
|
|
221
|
+
echo ""
|
|
222
|
+
echo "Available voices:"
|
|
223
|
+
for voice in "${!VOICES[@]}"; do
|
|
224
|
+
echo " - $voice"
|
|
225
|
+
done | sort
|
|
226
|
+
exit 1
|
|
227
|
+
fi
|
|
207
228
|
fi
|
|
208
229
|
|
|
209
230
|
echo "$FOUND" > "$VOICE_FILE"
|
|
210
231
|
echo "✅ Voice switched to: $FOUND"
|
|
211
|
-
|
|
232
|
+
|
|
233
|
+
# Show voice ID only for ElevenLabs voices
|
|
234
|
+
if [[ "$ACTIVE_PROVIDER" != "piper" ]] && [[ -n "${VOICES[$FOUND]}" ]]; then
|
|
235
|
+
echo "🎤 Voice ID: ${VOICES[$FOUND]}"
|
|
236
|
+
fi
|
|
212
237
|
|
|
213
238
|
# Have the new voice introduce itself (unless silent mode)
|
|
214
239
|
if [[ "$SILENT_MODE" != "true" ]]; then
|
|
@@ -217,6 +242,10 @@ case "$1" in
|
|
|
217
242
|
if [ -x "$PLAY_TTS" ]; then
|
|
218
243
|
"$PLAY_TTS" "Hi, I'm $FOUND. I'll be your voice assistant moving forward." "$FOUND" > /dev/null 2>&1 &
|
|
219
244
|
fi
|
|
245
|
+
|
|
246
|
+
echo ""
|
|
247
|
+
echo "💡 Tip: To hear automatic TTS narration, enable the agent-vibes output style:"
|
|
248
|
+
echo " /output-style agent-vibes"
|
|
220
249
|
fi
|
|
221
250
|
;;
|
|
222
251
|
|
|
@@ -232,6 +261,26 @@ case "$1" in
|
|
|
232
261
|
echo "🎤 Current Voice Configuration"
|
|
233
262
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
234
263
|
|
|
264
|
+
# Get active TTS provider
|
|
265
|
+
PROVIDER_FILE="$CLAUDE_DIR/tts-provider.txt"
|
|
266
|
+
if [[ ! -f "$PROVIDER_FILE" ]]; then
|
|
267
|
+
PROVIDER_FILE="$HOME/.claude/tts-provider.txt"
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
if [ -f "$PROVIDER_FILE" ]; then
|
|
271
|
+
ACTIVE_PROVIDER=$(cat "$PROVIDER_FILE")
|
|
272
|
+
if [[ "$ACTIVE_PROVIDER" == "elevenlabs" ]]; then
|
|
273
|
+
echo "Provider: ElevenLabs (Premium AI)"
|
|
274
|
+
elif [[ "$ACTIVE_PROVIDER" == "piper" ]]; then
|
|
275
|
+
echo "Provider: Piper TTS (Free, Offline)"
|
|
276
|
+
else
|
|
277
|
+
echo "Provider: $ACTIVE_PROVIDER"
|
|
278
|
+
fi
|
|
279
|
+
else
|
|
280
|
+
# Default to ElevenLabs if no provider file
|
|
281
|
+
echo "Provider: ElevenLabs (Premium AI)"
|
|
282
|
+
fi
|
|
283
|
+
|
|
235
284
|
# Get current voice
|
|
236
285
|
if [ -f "$VOICE_FILE" ]; then
|
|
237
286
|
CURRENT_VOICE=$(cat "$VOICE_FILE")
|