agentvibes 2.0.8 → 2.0.9

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 (130) hide show
  1. package/README.md +2 -2
  2. package/RELEASE_NOTES.md +23 -0
  3. package/package.json +1 -1
  4. package/src/installer.js +57 -31
  5. package/agentvibes.org/.claude/commands/agent-vibes/add.md +0 -21
  6. package/agentvibes.org/.claude/commands/agent-vibes/agent-vibes.md +0 -68
  7. package/agentvibes.org/.claude/commands/agent-vibes/commands.json +0 -53
  8. package/agentvibes.org/.claude/commands/agent-vibes/get.md +0 -9
  9. package/agentvibes.org/.claude/commands/agent-vibes/list.md +0 -13
  10. package/agentvibes.org/.claude/commands/agent-vibes/personality.md +0 -79
  11. package/agentvibes.org/.claude/commands/agent-vibes/preview.md +0 -16
  12. package/agentvibes.org/.claude/commands/agent-vibes/provider.md +0 -54
  13. package/agentvibes.org/.claude/commands/agent-vibes/replay.md +0 -19
  14. package/agentvibes.org/.claude/commands/agent-vibes/sample.md +0 -12
  15. package/agentvibes.org/.claude/commands/agent-vibes/sentiment.md +0 -52
  16. package/agentvibes.org/.claude/commands/agent-vibes/set-language.md +0 -47
  17. package/agentvibes.org/.claude/commands/agent-vibes/set-pretext.md +0 -65
  18. package/agentvibes.org/.claude/commands/agent-vibes/switch.md +0 -53
  19. package/agentvibes.org/.claude/commands/agent-vibes/update.md +0 -20
  20. package/agentvibes.org/.claude/commands/agent-vibes/version.md +0 -10
  21. package/agentvibes.org/.claude/commands/agent-vibes/whoami.md +0 -7
  22. package/agentvibes.org/.claude/hooks/bmad-voice-manager.sh +0 -278
  23. package/agentvibes.org/.claude/hooks/language-manager.sh +0 -190
  24. package/agentvibes.org/.claude/hooks/personality-manager.sh +0 -279
  25. package/agentvibes.org/.claude/hooks/piper-download-voices.sh +0 -133
  26. package/agentvibes.org/.claude/hooks/piper-voice-manager.sh +0 -227
  27. package/agentvibes.org/.claude/hooks/play-tts-elevenlabs.sh +0 -201
  28. package/agentvibes.org/.claude/hooks/play-tts-piper.sh +0 -175
  29. package/agentvibes.org/.claude/hooks/play-tts.sh +0 -138
  30. package/agentvibes.org/.claude/hooks/provider-commands.sh +0 -374
  31. package/agentvibes.org/.claude/hooks/provider-manager.sh +0 -196
  32. package/agentvibes.org/.claude/hooks/sentiment-manager.sh +0 -163
  33. package/agentvibes.org/.claude/hooks/voice-manager.sh +0 -349
  34. package/agentvibes.org/.claude/hooks/voices-config.sh +0 -33
  35. package/agentvibes.org/.claude/journal/2025-10-07.html +0 -373
  36. package/agentvibes.org/.claude/journal/index.html +0 -91
  37. package/agentvibes.org/.claude/output-styles/agent-vibes.md +0 -203
  38. package/agentvibes.org/.claude/personalities/angry.md +0 -16
  39. package/agentvibes.org/.claude/personalities/annoying.md +0 -16
  40. package/agentvibes.org/.claude/personalities/crass.md +0 -16
  41. package/agentvibes.org/.claude/personalities/dramatic.md +0 -16
  42. package/agentvibes.org/.claude/personalities/dry-humor.md +0 -52
  43. package/agentvibes.org/.claude/personalities/flirty.md +0 -22
  44. package/agentvibes.org/.claude/personalities/funny.md +0 -16
  45. package/agentvibes.org/.claude/personalities/grandpa.md +0 -34
  46. package/agentvibes.org/.claude/personalities/millennial.md +0 -16
  47. package/agentvibes.org/.claude/personalities/moody.md +0 -16
  48. package/agentvibes.org/.claude/personalities/normal.md +0 -18
  49. package/agentvibes.org/.claude/personalities/pirate.md +0 -16
  50. package/agentvibes.org/.claude/personalities/poetic.md +0 -16
  51. package/agentvibes.org/.claude/personalities/professional.md +0 -16
  52. package/agentvibes.org/.claude/personalities/robot.md +0 -16
  53. package/agentvibes.org/.claude/personalities/sarcastic.md +0 -40
  54. package/agentvibes.org/.claude/personalities/sassy.md +0 -16
  55. package/agentvibes.org/.claude/personalities/surfer-dude.md +0 -16
  56. package/agentvibes.org/.claude/personalities/zen.md +0 -16
  57. package/agentvibes.org/.mcp-minimal.json +0 -60
  58. package/agentvibes.org/CHANGELOG.md +0 -56
  59. package/agentvibes.org/README.md +0 -93
  60. package/agentvibes.org/app/(auth)/layout.tsx +0 -15
  61. package/agentvibes.org/app/(auth)/reset-password/page.tsx +0 -45
  62. package/agentvibes.org/app/(auth)/signin/page.tsx +0 -82
  63. package/agentvibes.org/app/(auth)/signup/page.tsx +0 -104
  64. package/agentvibes.org/app/(default)/layout.tsx +0 -31
  65. package/agentvibes.org/app/(default)/page.tsx +0 -20
  66. package/agentvibes.org/app/api/hello/route.ts +0 -3
  67. package/agentvibes.org/app/css/additional-styles/theme.css +0 -82
  68. package/agentvibes.org/app/css/additional-styles/utility-patterns.css +0 -55
  69. package/agentvibes.org/app/css/style.css +0 -100
  70. package/agentvibes.org/app/layout.tsx +0 -63
  71. package/agentvibes.org/components/cta.tsx +0 -58
  72. package/agentvibes.org/components/features.tsx +0 -256
  73. package/agentvibes.org/components/hero-home.tsx +0 -133
  74. package/agentvibes.org/components/modal-video.tsx +0 -137
  75. package/agentvibes.org/components/page-illustration.tsx +0 -55
  76. package/agentvibes.org/components/spotlight.tsx +0 -77
  77. package/agentvibes.org/components/testimonials.tsx +0 -282
  78. package/agentvibes.org/components/ui/footer.tsx +0 -82
  79. package/agentvibes.org/components/ui/header.tsx +0 -53
  80. package/agentvibes.org/components/ui/logo.tsx +0 -10
  81. package/agentvibes.org/components/workflows.tsx +0 -176
  82. package/agentvibes.org/next.config.js +0 -4
  83. package/agentvibes.org/package-lock.json +0 -1974
  84. package/agentvibes.org/package.json +0 -30
  85. package/agentvibes.org/pnpm-lock.yaml +0 -1141
  86. package/agentvibes.org/postcss.config.js +0 -5
  87. package/agentvibes.org/public/audio/02-sarcastic.mp3 +0 -0
  88. package/agentvibes.org/public/audio/03-angry.mp3 +0 -0
  89. package/agentvibes.org/public/audio/04-grandpa.mp3 +0 -0
  90. package/agentvibes.org/public/audio/05-sarcastic-example2.mp3 +0 -0
  91. package/agentvibes.org/public/audio/french-rachel.mp3 +0 -0
  92. package/agentvibes.org/public/audio/spanish-antoni.mp3 +0 -0
  93. package/agentvibes.org/public/favicon.ico +0 -0
  94. package/agentvibes.org/public/fonts/nacelle-italic.woff2 +0 -0
  95. package/agentvibes.org/public/fonts/nacelle-regular.woff2 +0 -0
  96. package/agentvibes.org/public/fonts/nacelle-semibold.woff2 +0 -0
  97. package/agentvibes.org/public/fonts/nacelle-semibolditalic.woff2 +0 -0
  98. package/agentvibes.org/public/images/blurred-shape-gray.svg +0 -1
  99. package/agentvibes.org/public/images/blurred-shape.svg +0 -1
  100. package/agentvibes.org/public/images/client-logo-01.svg +0 -1
  101. package/agentvibes.org/public/images/client-logo-02.svg +0 -1
  102. package/agentvibes.org/public/images/client-logo-03.svg +0 -1
  103. package/agentvibes.org/public/images/client-logo-04.svg +0 -1
  104. package/agentvibes.org/public/images/client-logo-05.svg +0 -1
  105. package/agentvibes.org/public/images/client-logo-06.svg +0 -1
  106. package/agentvibes.org/public/images/client-logo-07.svg +0 -1
  107. package/agentvibes.org/public/images/client-logo-08.svg +0 -1
  108. package/agentvibes.org/public/images/client-logo-09.svg +0 -1
  109. package/agentvibes.org/public/images/features.png +0 -0
  110. package/agentvibes.org/public/images/footer-illustration.svg +0 -1
  111. package/agentvibes.org/public/images/hero-image-01.jpg +0 -0
  112. package/agentvibes.org/public/images/logo.svg +0 -1
  113. package/agentvibes.org/public/images/page-illustration.svg +0 -1
  114. package/agentvibes.org/public/images/secondary-illustration.svg +0 -1
  115. package/agentvibes.org/public/images/testimonial-01.jpg +0 -0
  116. package/agentvibes.org/public/images/testimonial-02.jpg +0 -0
  117. package/agentvibes.org/public/images/testimonial-03.jpg +0 -0
  118. package/agentvibes.org/public/images/testimonial-04.jpg +0 -0
  119. package/agentvibes.org/public/images/testimonial-05.jpg +0 -0
  120. package/agentvibes.org/public/images/testimonial-06.jpg +0 -0
  121. package/agentvibes.org/public/images/testimonial-07.jpg +0 -0
  122. package/agentvibes.org/public/images/testimonial-08.jpg +0 -0
  123. package/agentvibes.org/public/images/testimonial-09.jpg +0 -0
  124. package/agentvibes.org/public/images/workflow-01.png +0 -0
  125. package/agentvibes.org/public/images/workflow-02.png +0 -0
  126. package/agentvibes.org/public/images/workflow-03.png +0 -0
  127. package/agentvibes.org/public/videos/video.mp4 +0 -0
  128. package/agentvibes.org/tsconfig.json +0 -28
  129. package/agentvibes.org/utils/useMasonry.tsx +0 -67
  130. package/agentvibes.org/utils/useMousePosition.tsx +0 -27
@@ -1,279 +0,0 @@
1
- #!/bin/bash
2
- # Personality manager for AgentVibes - adds character to TTS messages
3
-
4
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- PERSONALITIES_DIR="$SCRIPT_DIR/../personalities"
6
-
7
- # Project-local file first, global fallback
8
- # Use logical path (not physical) to handle symlinked .claude directories
9
- # Script is at .claude/hooks/personality-manager.sh, so .claude is ..
10
- CLAUDE_DIR="$(cd "$SCRIPT_DIR/.." 2>/dev/null && pwd)"
11
-
12
- # Check if we have a project-local .claude directory
13
- if [[ -d "$CLAUDE_DIR" ]] && [[ "$CLAUDE_DIR" != "$HOME/.claude" ]]; then
14
- PERSONALITY_FILE="$CLAUDE_DIR/tts-personality.txt"
15
- else
16
- PERSONALITY_FILE="$HOME/.claude/tts-personality.txt"
17
- fi
18
-
19
- # Function to get personality data from markdown file
20
- get_personality_data() {
21
- local personality="$1"
22
- local field="$2"
23
- local file="$PERSONALITIES_DIR/${personality}.md"
24
-
25
- if [[ ! -f "$file" ]]; then
26
- return 1
27
- fi
28
-
29
- case "$field" in
30
- prefix)
31
- sed -n '/^## Prefix/,/^##/p' "$file" | sed '1d;$d' | tr -d '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
32
- ;;
33
- suffix)
34
- sed -n '/^## Suffix/,/^##/p' "$file" | sed '1d;$d' | tr -d '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
35
- ;;
36
- description)
37
- grep "^description:" "$file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
38
- ;;
39
- voice)
40
- grep "^voice:" "$file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
41
- ;;
42
- instructions)
43
- sed -n '/^## AI Instructions/,/^##/p' "$file" | sed '1d;$d'
44
- ;;
45
- esac
46
- }
47
-
48
- # Function to list all available personalities
49
- list_personalities() {
50
- local personalities=()
51
-
52
- # Find all .md files in personalities directory
53
- if [[ -d "$PERSONALITIES_DIR" ]]; then
54
- for file in "$PERSONALITIES_DIR"/*.md; do
55
- if [[ -f "$file" ]]; then
56
- basename "$file" .md
57
- fi
58
- done
59
- fi
60
- }
61
-
62
- case "$1" in
63
- list)
64
- echo "🎭 Available Personalities:"
65
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
66
-
67
- # Get current personality
68
- CURRENT="normal"
69
- if [ -f "$PERSONALITY_FILE" ]; then
70
- CURRENT=$(cat "$PERSONALITY_FILE")
71
- fi
72
-
73
- # List personalities from markdown files
74
- echo "Built-in personalities:"
75
- for personality in $(list_personalities | sort); do
76
- desc=$(get_personality_data "$personality" "description")
77
- if [[ "$personality" == "$CURRENT" ]]; then
78
- echo " ✓ $personality - $desc (current)"
79
- else
80
- echo " - $personality - $desc"
81
- fi
82
- done
83
-
84
- # Add random option
85
- if [[ "$CURRENT" == "random" ]]; then
86
- echo " ✓ random - Picks randomly each time (current)"
87
- else
88
- echo " - random - Picks randomly each time"
89
- fi
90
-
91
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
92
- echo ""
93
- echo "Usage: /agent-vibes:personality <name>"
94
- echo " /agent-vibes:personality add <name>"
95
- echo " /agent-vibes:personality edit <name>"
96
- ;;
97
-
98
- set|switch)
99
- PERSONALITY="$2"
100
-
101
- if [[ -z "$PERSONALITY" ]]; then
102
- echo "❌ Please specify a personality name"
103
- echo "Usage: $0 set <personality>"
104
- exit 1
105
- fi
106
-
107
- # Check if personality file exists (unless it's random)
108
- if [[ "$PERSONALITY" != "random" ]]; then
109
- if [[ ! -f "$PERSONALITIES_DIR/${PERSONALITY}.md" ]]; then
110
- echo "❌ Personality not found: $PERSONALITY"
111
- echo ""
112
- echo "Available personalities:"
113
- for p in $(list_personalities | sort); do
114
- echo " • $p"
115
- done
116
- exit 1
117
- fi
118
- fi
119
-
120
- # Save the personality
121
- echo "$PERSONALITY" > "$PERSONALITY_FILE"
122
- echo "🎭 Personality set to: $PERSONALITY"
123
-
124
- # Check if personality has an assigned voice
125
- ASSIGNED_VOICE=$(get_personality_data "$PERSONALITY" "voice")
126
- if [[ -n "$ASSIGNED_VOICE" ]]; then
127
- # Switch to the assigned voice (silently - personality will do the talking)
128
- VOICE_MANAGER="$SCRIPT_DIR/voice-manager.sh"
129
- if [[ -x "$VOICE_MANAGER" ]]; then
130
- echo "🎤 Switching to assigned voice: $ASSIGNED_VOICE"
131
- "$VOICE_MANAGER" switch "$ASSIGNED_VOICE" --silent >/dev/null 2>&1
132
- fi
133
- fi
134
-
135
- # Make a personality-appropriate remark with TTS
136
- if [[ "$PERSONALITY" != "random" ]]; then
137
- echo ""
138
-
139
- # Get TTS script path
140
- TTS_SCRIPT="$SCRIPT_DIR/play-tts.sh"
141
-
142
- # Try to get acknowledgment from personality file
143
- PERSONALITY_FILE_PATH="$PERSONALITIES_DIR/${PERSONALITY}.md"
144
- REMARK=""
145
-
146
- if [[ -f "$PERSONALITY_FILE_PATH" ]]; then
147
- # Extract example responses from personality file (lines starting with "- ")
148
- mapfile -t EXAMPLES < <(grep '^- "' "$PERSONALITY_FILE_PATH" | sed 's/^- "//; s/"$//')
149
-
150
- if [[ ${#EXAMPLES[@]} -gt 0 ]]; then
151
- # Pick a random example
152
- REMARK="${EXAMPLES[$RANDOM % ${#EXAMPLES[@]}]}"
153
- fi
154
- fi
155
-
156
- # Fallback if no examples found
157
- if [[ -z "$REMARK" ]]; then
158
- REMARK="Personality set to ${PERSONALITY}!"
159
- fi
160
-
161
- echo "💬 $REMARK"
162
- "$TTS_SCRIPT" "$REMARK"
163
-
164
- echo ""
165
- echo "Note: AI will generate unique ${PERSONALITY} responses - no fixed templates!"
166
- fi
167
- ;;
168
-
169
- get)
170
- if [ -f "$PERSONALITY_FILE" ]; then
171
- CURRENT=$(cat "$PERSONALITY_FILE")
172
- echo "Current personality: $CURRENT"
173
-
174
- if [[ "$CURRENT" != "random" ]]; then
175
- desc=$(get_personality_data "$CURRENT" "description")
176
- [[ -n "$desc" ]] && echo "Description: $desc"
177
- fi
178
- else
179
- echo "Current personality: normal (default)"
180
- fi
181
- ;;
182
-
183
- add)
184
- NAME="$2"
185
- if [[ -z "$NAME" ]]; then
186
- echo "❌ Please specify a personality name"
187
- echo "Usage: $0 add <name>"
188
- exit 1
189
- fi
190
-
191
- FILE="$PERSONALITIES_DIR/${NAME}.md"
192
- if [[ -f "$FILE" ]]; then
193
- echo "❌ Personality '$NAME' already exists"
194
- echo "Use 'edit' to modify it"
195
- exit 1
196
- fi
197
-
198
- # Create new personality file
199
- cat > "$FILE" << 'EOF'
200
- ---
201
- name: NAME
202
- description: Custom personality
203
- ---
204
-
205
- # NAME Personality
206
-
207
- ## Prefix
208
-
209
-
210
- ## Suffix
211
-
212
-
213
- ## AI Instructions
214
- Describe how the AI should generate messages for this personality.
215
-
216
- ## Example Responses
217
- - "Example response 1"
218
- - "Example response 2"
219
- EOF
220
-
221
- # Replace NAME with actual name
222
- sed -i "s/NAME/$NAME/g" "$FILE"
223
-
224
- echo "✅ Created new personality: $NAME"
225
- echo "📝 Edit the file: $FILE"
226
- echo ""
227
- echo "You can now customize:"
228
- echo " • Prefix: Text before messages"
229
- echo " • Suffix: Text after messages"
230
- echo " • AI Instructions: How AI should speak"
231
- echo " • Example Responses: Sample messages"
232
- ;;
233
-
234
- edit)
235
- NAME="$2"
236
- if [[ -z "$NAME" ]]; then
237
- echo "❌ Please specify a personality name"
238
- echo "Usage: $0 edit <name>"
239
- exit 1
240
- fi
241
-
242
- FILE="$PERSONALITIES_DIR/${NAME}.md"
243
- if [[ ! -f "$FILE" ]]; then
244
- echo "❌ Personality '$NAME' not found"
245
- echo "Use 'add' to create it first"
246
- exit 1
247
- fi
248
-
249
- echo "📝 Edit this file to customize the personality:"
250
- echo "$FILE"
251
- ;;
252
-
253
- reset)
254
- echo "normal" > "$PERSONALITY_FILE"
255
- echo "🎭 Personality reset to: normal"
256
- ;;
257
-
258
- *)
259
- # If a single argument is provided and it's not a command, treat it as "set <personality>"
260
- if [[ -n "$1" ]] && [[ -f "$PERSONALITIES_DIR/${1}.md" || "$1" == "random" ]]; then
261
- # Call set with the personality name
262
- exec "$0" set "$1"
263
- else
264
- echo "AgentVibes Personality Manager"
265
- echo ""
266
- echo "Commands:"
267
- echo " list - List all personalities"
268
- echo " set/switch <name> - Set personality"
269
- echo " add <name> - Create new personality"
270
- echo " edit <name> - Show path to edit personality"
271
- echo " get - Show current personality"
272
- echo " reset - Reset to normal"
273
- echo ""
274
- echo "Examples:"
275
- echo " /agent-vibes:personality flirty"
276
- echo " /agent-vibes:personality add cowboy"
277
- fi
278
- ;;
279
- esac
@@ -1,133 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # @fileoverview Piper Voice Model Downloader
4
- # @context Downloads Piper TTS voice models from HuggingFace
5
- # @purpose Batch download popular voices after installation
6
- # @dependencies piper-voice-manager.sh, piper binary
7
- # @usage ./piper-download-voices.sh [--yes|-y]
8
- # --yes|-y: Skip confirmation prompt (auto-download)
9
- #
10
-
11
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
- source "$SCRIPT_DIR/piper-voice-manager.sh"
13
-
14
- # Parse command line arguments
15
- AUTO_YES=false
16
- if [[ "$1" == "--yes" ]] || [[ "$1" == "-y" ]]; then
17
- AUTO_YES=true
18
- fi
19
-
20
- # Common voice models to download
21
- COMMON_VOICES=(
22
- "en_US-lessac-medium" # Default, clear male
23
- "en_US-amy-medium" # Warm female
24
- "en_US-joe-medium" # Professional male
25
- "en_US-ryan-high" # Expressive male
26
- "en_US-libritts-high" # Premium quality
27
- )
28
-
29
- echo "🎙️ Piper Voice Model Downloader"
30
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
31
- echo ""
32
- echo "This will download the most commonly used Piper voice models."
33
- echo "Each voice is approximately 25MB."
34
- echo ""
35
-
36
- # Check if piper is installed
37
- if ! command -v piper &> /dev/null; then
38
- echo "❌ Error: Piper TTS not installed"
39
- echo "Install with: pipx install piper-tts"
40
- exit 1
41
- fi
42
-
43
- # Get storage directory
44
- VOICE_DIR=$(get_voice_storage_dir)
45
-
46
- echo "📂 Storage location: $VOICE_DIR"
47
- echo ""
48
-
49
- # Count already downloaded
50
- ALREADY_DOWNLOADED=0
51
- ALREADY_DOWNLOADED_LIST=()
52
- NEED_DOWNLOAD=()
53
-
54
- for voice in "${COMMON_VOICES[@]}"; do
55
- if verify_voice "$voice" 2>/dev/null; then
56
- ((ALREADY_DOWNLOADED++))
57
- ALREADY_DOWNLOADED_LIST+=("$voice")
58
- else
59
- NEED_DOWNLOAD+=("$voice")
60
- fi
61
- done
62
-
63
- echo "📊 Status:"
64
- echo " Already downloaded: $ALREADY_DOWNLOADED voice(s)"
65
- echo " Need to download: ${#NEED_DOWNLOAD[@]} voice(s)"
66
- echo ""
67
-
68
- # Show already downloaded voices
69
- if [[ $ALREADY_DOWNLOADED -gt 0 ]]; then
70
- echo "✅ Already downloaded (skipped):"
71
- for voice in "${ALREADY_DOWNLOADED_LIST[@]}"; do
72
- echo " ✓ $voice"
73
- done
74
- echo ""
75
- fi
76
-
77
- if [[ ${#NEED_DOWNLOAD[@]} -eq 0 ]]; then
78
- echo "🎉 All common voices ready to use!"
79
- exit 0
80
- fi
81
-
82
- echo "Voices to download:"
83
- for voice in "${NEED_DOWNLOAD[@]}"; do
84
- echo " • $voice (~25MB)"
85
- done
86
- echo ""
87
-
88
- # Ask for confirmation (skip if --yes flag provided)
89
- if [[ "$AUTO_YES" == "false" ]]; then
90
- read -p "Download ${#NEED_DOWNLOAD[@]} voice model(s)? [Y/n]: " -n 1 -r
91
- echo
92
-
93
- if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ -n $REPLY ]]; then
94
- echo "❌ Download cancelled"
95
- exit 0
96
- fi
97
- else
98
- echo "Auto-downloading ${#NEED_DOWNLOAD[@]} voice model(s)..."
99
- echo ""
100
- fi
101
-
102
- # Download each voice
103
- DOWNLOADED=0
104
- FAILED=0
105
-
106
- for voice in "${NEED_DOWNLOAD[@]}"; do
107
- echo ""
108
- echo "📥 Downloading: $voice..."
109
-
110
- if download_voice "$voice"; then
111
- ((DOWNLOADED++))
112
- echo "✅ Downloaded: $voice"
113
- else
114
- ((FAILED++))
115
- echo "❌ Failed: $voice"
116
- fi
117
- done
118
-
119
- echo ""
120
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
121
- echo "📊 Download Summary:"
122
- echo " ✅ Successfully downloaded: $DOWNLOADED"
123
- echo " ❌ Failed: $FAILED"
124
- echo " 📦 Total voices available: $((ALREADY_DOWNLOADED + DOWNLOADED))"
125
- echo ""
126
-
127
- if [[ $DOWNLOADED -gt 0 ]]; then
128
- echo "✨ Ready to use Piper TTS with downloaded voices!"
129
- echo ""
130
- echo "Try it:"
131
- echo " /agent-vibes:provider switch piper"
132
- echo " /agent-vibes:preview"
133
- fi
@@ -1,227 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # @fileoverview Piper Voice Model Management
4
- # @context Manages downloading, caching, and validating Piper ONNX voice models
5
- # @architecture Voice model lifecycle management for Piper provider
6
- # @dependencies curl, piper binary
7
- # @entrypoints Sourced by play-tts-piper.sh and provider management commands
8
- # @patterns HuggingFace model repository integration, file-based caching
9
- # @related play-tts-piper.sh, provider-manager.sh, GitHub Issue #25
10
- #
11
-
12
- # Base URL for Piper voice models on HuggingFace
13
- PIPER_VOICES_BASE_URL="https://huggingface.co/rhasspy/piper-voices/resolve/main"
14
-
15
- # @function get_voice_storage_dir
16
- # @intent Determine directory for storing Piper voice models
17
- # @why Voice models are large (~25MB each) and should be shared globally across all projects
18
- # @returns Echoes path to voice storage directory (~/.claude/piper-voices)
19
- # @sideeffects Creates directory if it doesn't exist
20
- # @architecture Supports custom path via PIPER_VOICES_DIR env var, defaults to global storage
21
- get_voice_storage_dir() {
22
- local voice_dir
23
-
24
- # Check for custom path in environment or config file
25
- if [[ -n "$PIPER_VOICES_DIR" ]]; then
26
- voice_dir="$PIPER_VOICES_DIR"
27
- else
28
- # Check for config file (project-local first, then global)
29
- local config_file
30
- if [[ -n "$CLAUDE_PROJECT_DIR" ]] && [[ -f "$CLAUDE_PROJECT_DIR/.claude/piper-voices-dir.txt" ]]; then
31
- config_file="$CLAUDE_PROJECT_DIR/.claude/piper-voices-dir.txt"
32
- else
33
- # Search up directory tree for .claude/
34
- local current_dir="$PWD"
35
- while [[ "$current_dir" != "/" ]]; do
36
- if [[ -f "$current_dir/.claude/piper-voices-dir.txt" ]]; then
37
- config_file="$current_dir/.claude/piper-voices-dir.txt"
38
- break
39
- fi
40
- current_dir=$(dirname "$current_dir")
41
- done
42
-
43
- # Check global config
44
- if [[ -z "$config_file" ]] && [[ -f "$HOME/.claude/piper-voices-dir.txt" ]]; then
45
- config_file="$HOME/.claude/piper-voices-dir.txt"
46
- fi
47
- fi
48
-
49
- if [[ -n "$config_file" ]]; then
50
- voice_dir=$(cat "$config_file" | tr -d '[:space:]')
51
- fi
52
- fi
53
-
54
- # Fallback to default global storage
55
- if [[ -z "$voice_dir" ]]; then
56
- voice_dir="$HOME/.claude/piper-voices"
57
- fi
58
-
59
- mkdir -p "$voice_dir"
60
- echo "$voice_dir"
61
- }
62
-
63
- # @function verify_voice
64
- # @intent Check if voice model files exist locally
65
- # @why Avoid redundant downloads, detect missing models
66
- # @param $1 {string} voice_name - Voice model name (e.g., en_US-lessac-medium)
67
- # @returns None
68
- # @exitcode 0=voice exists, 1=voice missing
69
- # @sideeffects None
70
- verify_voice() {
71
- local voice_name="$1"
72
- local voice_dir
73
- voice_dir=$(get_voice_storage_dir)
74
-
75
- local onnx_file="$voice_dir/${voice_name}.onnx"
76
- local json_file="$voice_dir/${voice_name}.onnx.json"
77
-
78
- [[ -f "$onnx_file" ]] && [[ -f "$json_file" ]]
79
- }
80
-
81
- # @function get_voice_path
82
- # @intent Get absolute path to voice model ONNX file
83
- # @why Piper binary requires full path to model file
84
- # @param $1 {string} voice_name - Voice model name
85
- # @returns Echoes path to .onnx file
86
- # @exitcode 0=success, 1=voice not found
87
- # @sideeffects None
88
- get_voice_path() {
89
- local voice_name="$1"
90
- local voice_dir
91
- voice_dir=$(get_voice_storage_dir)
92
-
93
- local onnx_file="$voice_dir/${voice_name}.onnx"
94
-
95
- if [[ ! -f "$onnx_file" ]]; then
96
- echo "❌ Voice model not found: $voice_name" >&2
97
- return 1
98
- fi
99
-
100
- echo "$onnx_file"
101
- }
102
-
103
- # @function parse_voice_components
104
- # @intent Extract language, locale, speaker, quality from voice name
105
- # @why HuggingFace uses directory structure: lang/locale/speaker/quality
106
- # @param $1 {string} voice_name - Voice name (e.g., en_US-lessac-medium)
107
- # @returns Sets global variables: LANG, LOCALE, SPEAKER, QUALITY
108
- # @sideeffects Sets global variables
109
- # AI NOTE: Voice name format is: lang_LOCALE-speaker-quality
110
- parse_voice_components() {
111
- local voice_name="$1"
112
-
113
- # Extract components from voice name
114
- # Format: en_US-lessac-medium
115
- # lang_LOCALE-speaker-quality
116
-
117
- local lang_locale="${voice_name%%-*}" # en_US
118
- local speaker_quality="${voice_name#*-}" # lessac-medium
119
-
120
- LANG="${lang_locale%%_*}" # en
121
- LOCALE="${lang_locale#*_}" # US
122
- SPEAKER="${speaker_quality%%-*}" # lessac
123
- QUALITY="${speaker_quality#*-}" # medium
124
- }
125
-
126
- # @function download_voice
127
- # @intent Download Piper voice model from HuggingFace
128
- # @why Provide free offline TTS voices
129
- # @param $1 {string} voice_name - Voice model name
130
- # @param $2 {string} lang_code - Language code (optional, inferred from voice_name)
131
- # @returns None
132
- # @exitcode 0=success, 1=download failed
133
- # @sideeffects Downloads .onnx and .onnx.json files
134
- # @edgecases Handles network failures, validates file integrity
135
- download_voice() {
136
- local voice_name="$1"
137
- local lang_code="${2:-}"
138
-
139
- local voice_dir
140
- voice_dir=$(get_voice_storage_dir)
141
-
142
- # Check if already downloaded
143
- if verify_voice "$voice_name"; then
144
- echo "✅ Voice already downloaded: $voice_name"
145
- return 0
146
- fi
147
-
148
- # Parse voice components
149
- parse_voice_components "$voice_name"
150
-
151
- # Construct download URLs
152
- # Path format: {language}/{language}_{locale}/{speaker}/{quality}/{speaker}-{quality}.onnx
153
- local model_path="${LANG}/${LANG}_${LOCALE}/${SPEAKER}/${QUALITY}/${voice_name}"
154
- local onnx_url="${PIPER_VOICES_BASE_URL}/${model_path}.onnx"
155
- local json_url="${PIPER_VOICES_BASE_URL}/${model_path}.onnx.json"
156
-
157
- echo "📥 Downloading Piper voice: $voice_name"
158
- echo " Source: HuggingFace (rhasspy/piper-voices)"
159
- echo " Size: ~25MB"
160
- echo ""
161
-
162
- # Download ONNX model
163
- echo " Downloading model file..."
164
- if ! curl -L --progress-bar -o "$voice_dir/${voice_name}.onnx" "$onnx_url"; then
165
- echo "❌ Failed to download voice model"
166
- rm -f "$voice_dir/${voice_name}.onnx"
167
- return 1
168
- fi
169
-
170
- # Download JSON config
171
- echo " Downloading config file..."
172
- if ! curl -L -s -o "$voice_dir/${voice_name}.onnx.json" "$json_url"; then
173
- echo "❌ Failed to download voice config"
174
- rm -f "$voice_dir/${voice_name}.onnx" "$voice_dir/${voice_name}.onnx.json"
175
- return 1
176
- fi
177
-
178
- # Verify file integrity (basic check - file size > 0)
179
- if [[ ! -s "$voice_dir/${voice_name}.onnx" ]]; then
180
- echo "❌ Downloaded file is empty or corrupt"
181
- rm -f "$voice_dir/${voice_name}.onnx" "$voice_dir/${voice_name}.onnx.json"
182
- return 1
183
- fi
184
-
185
- echo "✅ Voice downloaded successfully: $voice_name"
186
- echo " Location: $voice_dir/${voice_name}.onnx"
187
- }
188
-
189
- # @function list_downloaded_voices
190
- # @intent Show all locally cached voice models
191
- # @why Help users see what voices they have available
192
- # @returns Echoes voice names (one per line)
193
- # @exitcode 0=success
194
- # @sideeffects None
195
- list_downloaded_voices() {
196
- local voice_dir
197
- voice_dir=$(get_voice_storage_dir)
198
-
199
- echo "📦 Downloaded Piper Voices:"
200
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
201
-
202
- local count=0
203
- shopt -s nullglob
204
- for onnx_file in "$voice_dir"/*.onnx; do
205
- if [[ -f "$onnx_file" ]]; then
206
- local voice_name
207
- voice_name=$(basename "$onnx_file" .onnx)
208
- local file_size
209
- file_size=$(du -h "$onnx_file" | cut -f1)
210
- echo " • $voice_name ($file_size)"
211
- ((count++))
212
- fi
213
- done
214
- shopt -u nullglob
215
-
216
- if [[ $count -eq 0 ]]; then
217
- echo " (No voices downloaded yet)"
218
- fi
219
-
220
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
221
- echo "Total: $count voices"
222
- }
223
-
224
- # AI NOTE: This file manages the lifecycle of Piper voice models
225
- # Voice models are ONNX files (~20-30MB each) downloaded from HuggingFace
226
- # Files are cached locally to avoid repeated downloads
227
- # Project-local storage preferred over global for isolation