agentvibes 5.2.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.claude/config/audio-effects.cfg +1 -1
  2. package/.claude/hooks/audio-cache-utils.sh +246 -246
  3. package/.claude/hooks/background-music-manager.sh +404 -404
  4. package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
  5. package/.claude/hooks/bmad-speak.sh +290 -290
  6. package/.claude/hooks/bmad-tts-injector.sh +568 -568
  7. package/.claude/hooks/bmad-voice-manager.sh +928 -928
  8. package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
  9. package/.claude/hooks/clawdbot-receiver.sh +107 -107
  10. package/.claude/hooks/clean-audio-cache.sh +22 -22
  11. package/.claude/hooks/cleanup-cache.sh +106 -106
  12. package/.claude/hooks/configure-rdp-mode.sh +137 -137
  13. package/.claude/hooks/download-extra-voices.sh +244 -244
  14. package/.claude/hooks/effects-manager.sh +268 -268
  15. package/.claude/hooks/github-star-reminder.sh +154 -154
  16. package/.claude/hooks/language-manager.sh +362 -362
  17. package/.claude/hooks/learn-manager.sh +492 -492
  18. package/.claude/hooks/macos-voice-manager.sh +205 -205
  19. package/.claude/hooks/migrate-background-music.sh +125 -125
  20. package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
  21. package/.claude/hooks/optimize-background-music.sh +87 -87
  22. package/.claude/hooks/path-resolver.sh +60 -60
  23. package/.claude/hooks/personality-manager.sh +448 -448
  24. package/.claude/hooks/piper-installer.sh +292 -292
  25. package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
  26. package/.claude/hooks/play-tts-enhanced.sh +105 -105
  27. package/.claude/hooks/play-tts-ssh-remote.sh +104 -10
  28. package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
  29. package/.claude/hooks/play-tts.sh +31 -11
  30. package/.claude/hooks/prepare-release.sh +54 -54
  31. package/.claude/hooks/provider-commands.sh +617 -617
  32. package/.claude/hooks/provider-manager.sh +399 -399
  33. package/.claude/hooks/replay-target-audio.sh +95 -95
  34. package/.claude/hooks/sentiment-manager.sh +201 -201
  35. package/.claude/hooks/speed-manager.sh +291 -291
  36. package/.claude/hooks/stop-tts.sh +84 -84
  37. package/.claude/hooks/termux-installer.sh +261 -261
  38. package/.claude/hooks/translate-manager.sh +341 -341
  39. package/.claude/hooks/tts-queue-worker.sh +145 -145
  40. package/.claude/hooks/tts-queue.sh +165 -165
  41. package/.claude/hooks/voice-manager.sh +552 -548
  42. package/.claude/hooks-windows/bmad-party-speak.ps1 +5 -1
  43. package/.claude/hooks-windows/play-tts.ps1 +91 -59
  44. package/README.md +21 -2
  45. package/RELEASE_NOTES.md +130 -0
  46. package/bin/mcp-server.sh +206 -206
  47. package/mcp-server/server.py +35 -6
  48. package/package.json +1 -1
  49. package/src/console/tabs/setup-tab.js +68 -29
  50. package/src/console/tabs/voices-tab.js +9 -3
  51. package/src/installer.js +79 -213
  52. package/src/services/llm-provider-service.js +139 -75
@@ -1,171 +1,171 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/piper-multispeaker-registry.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 Multi-Speaker Voice Registry - Maps speaker names to ONNX models and speaker IDs
35
- # @context Enables individual speaker selection from multi-speaker Piper models (e.g., 16Speakers)
36
- # @architecture Static registry mapping speaker names to model files and numeric speaker IDs
37
- # @dependencies piper-voice-manager.sh (voice storage), play-tts-piper.sh (TTS with speaker ID)
38
- # @entrypoints Sourced by voice-manager.sh for multi-speaker voice switching
39
- # @patterns Registry pattern, speaker ID mapping, model-to-speaker association
40
- # @related voice-manager.sh, play-tts-piper.sh, 16Speakers.onnx.json (speaker_id_map)
41
- #
42
-
43
- # Bash 3.2 compatible lowercase function (macOS ships with bash 3.2)
44
- # ${var,,} syntax requires bash 4.0+
45
- _to_lower() {
46
- echo "$1" | tr '[:upper:]' '[:lower:]'
47
- }
48
-
49
- # Registry of multi-speaker models and their speaker names
50
- # Format: "SpeakerName:model_file:speaker_id:description"
51
- #
52
- # 16Speakers Model (12 US + 4 UK voices):
53
- # Source: LibriVox Public Domain recordings
54
- # Model: 16Speakers.onnx (77MB)
55
- #
56
- MULTISPEAKER_VOICES=(
57
- # US English Speakers (0-11)
58
- "Cori_Samuel:16Speakers:0:US English Female"
59
- "Kara_Shallenberg:16Speakers:1:US English Female"
60
- "Kristin_Hughes:16Speakers:2:US English Female"
61
- "Maria_Kasper:16Speakers:3:US English Female"
62
- "Mike_Pelton:16Speakers:4:US English Male"
63
- "Mark_Nelson:16Speakers:5:US English Male"
64
- "Michael_Scherer:16Speakers:6:US English Male"
65
- "James_K_White:16Speakers:7:US English Male"
66
- "Rose_Ibex:16Speakers:8:US English Female"
67
- "progressingamerica:16Speakers:9:US English Male"
68
- "Steve_C:16Speakers:10:US English Male"
69
- "Owlivia:16Speakers:11:US English Female"
70
-
71
- # UK English Speakers (12-15)
72
- "Paul_Hampton:16Speakers:12:UK English Male"
73
- "Jennifer_Dorr:16Speakers:13:UK English Female"
74
- "Emily_Cripps:16Speakers:14:UK English Female"
75
- "Martin_Clifton:16Speakers:15:UK English Male"
76
- )
77
-
78
- # @function get_multispeaker_info
79
- # @intent Get model and speaker ID for a speaker name
80
- # @why Enables users to select individual speakers from multi-speaker models by name
81
- # @param $1 {string} speaker_name - Speaker name (e.g., "Cori_Samuel", "Rose_Ibex")
82
- # @returns Echoes "model:speaker_id" (e.g., "16Speakers:0") to stdout
83
- # @exitcode 0=speaker found, 1=speaker not found
84
- # @sideeffects None (read-only lookup)
85
- # @edgecases Case-insensitive matching
86
- # @calledby voice-manager.sh switch command
87
- # @calls None (pure bash array iteration)
88
- get_multispeaker_info() {
89
- local speaker_name="$1"
90
- for entry in "${MULTISPEAKER_VOICES[@]}"; do
91
- name="${entry%%:*}"
92
- rest="${entry#*:}"
93
- model="${rest%%:*}"
94
- rest="${rest#*:}"
95
- speaker_id="${rest%%:*}"
96
-
97
- if [[ "$(_to_lower "$name")" == "$(_to_lower "$speaker_name")" ]]; then
98
- echo "$model:$speaker_id"
99
- return 0
100
- fi
101
- done
102
- return 1
103
- }
104
-
105
- # @function list_multispeaker_voices
106
- # @intent Display all available multi-speaker voices with descriptions
107
- # @why Help users discover individual speakers within multi-speaker models
108
- # @param None
109
- # @returns None
110
- # @exitcode Always 0
111
- # @sideeffects Writes formatted list to stdout
112
- # @edgecases None
113
- # @calledby voice-manager.sh list command, /agent-vibes:list
114
- # @calls None (pure bash array iteration)
115
- list_multispeaker_voices() {
116
- echo "🎭 Multi-Speaker Voices (16Speakers Model):"
117
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
118
-
119
- local current_model=""
120
- for entry in "${MULTISPEAKER_VOICES[@]}"; do
121
- name="${entry%%:*}"
122
- rest="${entry#*:}"
123
- model="${rest%%:*}"
124
- rest="${rest#*:}"
125
- speaker_id="${rest%%:*}"
126
- description="${rest#*:}"
127
-
128
- # Print section header when model changes
129
- if [[ "$model" != "$current_model" ]]; then
130
- if [[ -n "$current_model" ]]; then
131
- echo ""
132
- fi
133
- echo " Model: $model.onnx"
134
- current_model="$model"
135
- fi
136
-
137
- echo " • $name (ID: $speaker_id) - $description"
138
- done
139
-
140
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
141
- echo ""
142
- echo "Usage: /agent-vibes:switch Cori_Samuel"
143
- echo " /agent-vibes:switch Rose_Ibex"
144
- }
145
-
146
- # @function get_multispeaker_description
147
- # @intent Get description for a speaker name
148
- # @why Provide user-friendly info about speaker characteristics
149
- # @param $1 {string} speaker_name - Speaker name
150
- # @returns Echoes description (e.g., "US English Female") to stdout
151
- # @exitcode 0=speaker found, 1=speaker not found
152
- # @sideeffects None (read-only lookup)
153
- # @edgecases Case-insensitive matching
154
- # @calledby voice-manager.sh switch command (for confirmation message)
155
- # @calls None (pure bash array iteration)
156
- get_multispeaker_description() {
157
- local speaker_name="$1"
158
- for entry in "${MULTISPEAKER_VOICES[@]}"; do
159
- name="${entry%%:*}"
160
- rest="${entry#*:}"
161
- rest="${rest#*:}"
162
- rest="${rest#*:}"
163
- description="${rest}"
164
-
165
- if [[ "$(_to_lower "$name")" == "$(_to_lower "$speaker_name")" ]]; then
166
- echo "$description"
167
- return 0
168
- fi
169
- done
170
- return 1
171
- }
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/piper-multispeaker-registry.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 Multi-Speaker Voice Registry - Maps speaker names to ONNX models and speaker IDs
35
+ # @context Enables individual speaker selection from multi-speaker Piper models (e.g., 16Speakers)
36
+ # @architecture Static registry mapping speaker names to model files and numeric speaker IDs
37
+ # @dependencies piper-voice-manager.sh (voice storage), play-tts-piper.sh (TTS with speaker ID)
38
+ # @entrypoints Sourced by voice-manager.sh for multi-speaker voice switching
39
+ # @patterns Registry pattern, speaker ID mapping, model-to-speaker association
40
+ # @related voice-manager.sh, play-tts-piper.sh, 16Speakers.onnx.json (speaker_id_map)
41
+ #
42
+
43
+ # Bash 3.2 compatible lowercase function (macOS ships with bash 3.2)
44
+ # ${var,,} syntax requires bash 4.0+
45
+ _to_lower() {
46
+ echo "$1" | tr '[:upper:]' '[:lower:]'
47
+ }
48
+
49
+ # Registry of multi-speaker models and their speaker names
50
+ # Format: "SpeakerName:model_file:speaker_id:description"
51
+ #
52
+ # 16Speakers Model (12 US + 4 UK voices):
53
+ # Source: LibriVox Public Domain recordings
54
+ # Model: 16Speakers.onnx (77MB)
55
+ #
56
+ MULTISPEAKER_VOICES=(
57
+ # US English Speakers (0-11)
58
+ "Cori_Samuel:16Speakers:0:US English Female"
59
+ "Kara_Shallenberg:16Speakers:1:US English Female"
60
+ "Kristin_Hughes:16Speakers:2:US English Female"
61
+ "Maria_Kasper:16Speakers:3:US English Female"
62
+ "Mike_Pelton:16Speakers:4:US English Male"
63
+ "Mark_Nelson:16Speakers:5:US English Male"
64
+ "Michael_Scherer:16Speakers:6:US English Male"
65
+ "James_K_White:16Speakers:7:US English Male"
66
+ "Rose_Ibex:16Speakers:8:US English Female"
67
+ "progressingamerica:16Speakers:9:US English Male"
68
+ "Steve_C:16Speakers:10:US English Male"
69
+ "Owlivia:16Speakers:11:US English Female"
70
+
71
+ # UK English Speakers (12-15)
72
+ "Paul_Hampton:16Speakers:12:UK English Male"
73
+ "Jennifer_Dorr:16Speakers:13:UK English Female"
74
+ "Emily_Cripps:16Speakers:14:UK English Female"
75
+ "Martin_Clifton:16Speakers:15:UK English Male"
76
+ )
77
+
78
+ # @function get_multispeaker_info
79
+ # @intent Get model and speaker ID for a speaker name
80
+ # @why Enables users to select individual speakers from multi-speaker models by name
81
+ # @param $1 {string} speaker_name - Speaker name (e.g., "Cori_Samuel", "Rose_Ibex")
82
+ # @returns Echoes "model:speaker_id" (e.g., "16Speakers:0") to stdout
83
+ # @exitcode 0=speaker found, 1=speaker not found
84
+ # @sideeffects None (read-only lookup)
85
+ # @edgecases Case-insensitive matching
86
+ # @calledby voice-manager.sh switch command
87
+ # @calls None (pure bash array iteration)
88
+ get_multispeaker_info() {
89
+ local speaker_name="$1"
90
+ for entry in "${MULTISPEAKER_VOICES[@]}"; do
91
+ name="${entry%%:*}"
92
+ rest="${entry#*:}"
93
+ model="${rest%%:*}"
94
+ rest="${rest#*:}"
95
+ speaker_id="${rest%%:*}"
96
+
97
+ if [[ "$(_to_lower "$name")" == "$(_to_lower "$speaker_name")" ]]; then
98
+ echo "$model:$speaker_id"
99
+ return 0
100
+ fi
101
+ done
102
+ return 1
103
+ }
104
+
105
+ # @function list_multispeaker_voices
106
+ # @intent Display all available multi-speaker voices with descriptions
107
+ # @why Help users discover individual speakers within multi-speaker models
108
+ # @param None
109
+ # @returns None
110
+ # @exitcode Always 0
111
+ # @sideeffects Writes formatted list to stdout
112
+ # @edgecases None
113
+ # @calledby voice-manager.sh list command, /agent-vibes:list
114
+ # @calls None (pure bash array iteration)
115
+ list_multispeaker_voices() {
116
+ echo "🎭 Multi-Speaker Voices (16Speakers Model):"
117
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
118
+
119
+ local current_model=""
120
+ for entry in "${MULTISPEAKER_VOICES[@]}"; do
121
+ name="${entry%%:*}"
122
+ rest="${entry#*:}"
123
+ model="${rest%%:*}"
124
+ rest="${rest#*:}"
125
+ speaker_id="${rest%%:*}"
126
+ description="${rest#*:}"
127
+
128
+ # Print section header when model changes
129
+ if [[ "$model" != "$current_model" ]]; then
130
+ if [[ -n "$current_model" ]]; then
131
+ echo ""
132
+ fi
133
+ echo " Model: $model.onnx"
134
+ current_model="$model"
135
+ fi
136
+
137
+ echo " • $name (ID: $speaker_id) - $description"
138
+ done
139
+
140
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
141
+ echo ""
142
+ echo "Usage: /agent-vibes:switch Cori_Samuel"
143
+ echo " /agent-vibes:switch Rose_Ibex"
144
+ }
145
+
146
+ # @function get_multispeaker_description
147
+ # @intent Get description for a speaker name
148
+ # @why Provide user-friendly info about speaker characteristics
149
+ # @param $1 {string} speaker_name - Speaker name
150
+ # @returns Echoes description (e.g., "US English Female") to stdout
151
+ # @exitcode 0=speaker found, 1=speaker not found
152
+ # @sideeffects None (read-only lookup)
153
+ # @edgecases Case-insensitive matching
154
+ # @calledby voice-manager.sh switch command (for confirmation message)
155
+ # @calls None (pure bash array iteration)
156
+ get_multispeaker_description() {
157
+ local speaker_name="$1"
158
+ for entry in "${MULTISPEAKER_VOICES[@]}"; do
159
+ name="${entry%%:*}"
160
+ rest="${entry#*:}"
161
+ rest="${rest#*:}"
162
+ rest="${rest#*:}"
163
+ description="${rest}"
164
+
165
+ if [[ "$(_to_lower "$name")" == "$(_to_lower "$speaker_name")" ]]; then
166
+ echo "$description"
167
+ return 0
168
+ fi
169
+ done
170
+ return 1
171
+ }
@@ -1,105 +1,105 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/play-tts-enhanced.sh
4
- #
5
- # AgentVibes - Enhanced TTS with Background Music and Effects
6
- # Generates TTS, applies effects, mixes background, plays ONCE (no echo)
7
- #
8
- # Usage: play-tts-enhanced.sh "text to speak" [agent_name] [voice_override]
9
- #
10
- # Environment:
11
- # AGENTVIBES_PARTY_MODE=true - Use room ambiance background (_party_mode config)
12
- #
13
-
14
- set -euo pipefail
15
- export LC_ALL=C
16
-
17
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
-
19
- TEXT="${1:-}"
20
- AGENT_NAME="${2:-default}"
21
- VOICE_OVERRIDE="${3:-}"
22
-
23
- if [[ -z "$TEXT" ]]; then
24
- echo "Usage: $0 \"text to speak\" [agent_name] [voice_override]" >&2
25
- exit 1
26
- fi
27
-
28
- # Determine which config to use
29
- CONFIG_KEY="$AGENT_NAME"
30
- if [[ "${AGENTVIBES_PARTY_MODE:-false}" == "true" ]]; then
31
- CONFIG_KEY="_party_mode"
32
- fi
33
-
34
- # ---------------------------------------------------------------------------
35
- # Per-agent profile overrides (from bmad-voice-map.json via bmad-speak.sh)
36
- # If AGENTVIBES_AGENT_PROFILE is set and the file exists, apply reverb/personality/music
37
- # overrides by temporarily setting effects-manager config for this agent
38
- AGENT_PROFILE="${AGENTVIBES_AGENT_PROFILE:-}"
39
-
40
- if [[ -n "$AGENT_PROFILE" ]] && [[ -f "$AGENT_PROFILE" ]]; then
41
- # Read profile fields using node (reliable JSON parsing)
42
- # SECURITY: Pass values via env vars to prevent shell injection
43
- _PROFILE_REVERB=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.reverbPreset||'')}catch{}" 2>/dev/null || true)
44
- _PROFILE_MUSIC_TRACK=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.backgroundMusic?.track||'')}catch{}" 2>/dev/null || true)
45
- _PROFILE_MUSIC_VOL=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(String(p.backgroundMusic?.volume||''))}catch{}" 2>/dev/null || true)
46
-
47
- # Apply per-agent reverb via effects-manager (scoped to this agent's config key)
48
- if [[ -n "$_PROFILE_REVERB" ]] && [[ -f "$SCRIPT_DIR/effects-manager.sh" ]]; then
49
- bash "$SCRIPT_DIR/effects-manager.sh" set-reverb "$_PROFILE_REVERB" "$CONFIG_KEY" 2>/dev/null || true
50
- fi
51
-
52
- # Override background music track/volume for this invocation via env vars
53
- if [[ -n "$_PROFILE_MUSIC_TRACK" ]]; then
54
- export AGENTVIBES_BG_TRACK="$_PROFILE_MUSIC_TRACK"
55
- fi
56
- if [[ -n "$_PROFILE_MUSIC_VOL" ]]; then
57
- export AGENTVIBES_BG_VOLUME="$_PROFILE_MUSIC_VOL"
58
- fi
59
- fi
60
-
61
- # Step 1: Generate TTS WITHOUT playback
62
- export AGENTVIBES_NO_PLAYBACK=true
63
- export AGENTVIBES_WAV_OUTPATH="${XDG_RUNTIME_DIR:-/tmp}/agentvibes-last-wav-$$.txt"
64
-
65
- # Cleanup temp outpath file on exit
66
- trap 'rm -f "$AGENTVIBES_WAV_OUTPATH"' EXIT
67
- bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" "$VOICE_OVERRIDE"
68
-
69
- # Read the generated file path (written by play-tts-piper.sh via AGENTVIBES_WAV_OUTPATH)
70
- GENERATED_FILE=""
71
- if [[ -f "$AGENTVIBES_WAV_OUTPATH" ]]; then
72
- GENERATED_FILE=$(cat "$AGENTVIBES_WAV_OUTPATH")
73
- rm -f "$AGENTVIBES_WAV_OUTPATH"
74
- fi
75
- unset AGENTVIBES_WAV_OUTPATH
76
-
77
- if [[ -z "$GENERATED_FILE" ]] || [[ ! -f "$GENERATED_FILE" ]]; then
78
- echo "Error: Could not find generated audio file" >&2
79
- exit 1
80
- fi
81
-
82
- # Step 2: Process with effects and background
83
- PROCESSED_FILE="${GENERATED_FILE%.wav}-enhanced.wav"
84
-
85
- if [[ -f "$SCRIPT_DIR/audio-processor.sh" ]]; then
86
- "$SCRIPT_DIR/audio-processor.sh" "$GENERATED_FILE" "$CONFIG_KEY" "$PROCESSED_FILE" 2>/dev/null || {
87
- # Fallback to original if processing fails
88
- PROCESSED_FILE="$GENERATED_FILE"
89
- }
90
- else
91
- PROCESSED_FILE="$GENERATED_FILE"
92
- fi
93
-
94
- # Step 3: Play the processed audio ONCE
95
- if [[ -f "$PROCESSED_FILE" ]]; then
96
- if [[ "$(uname -s)" == "Darwin" ]]; then
97
- afplay "$PROCESSED_FILE" >/dev/null 2>&1 &
98
- else
99
- (mpv "$PROCESSED_FILE" || aplay "$PROCESSED_FILE" || paplay "$PROCESSED_FILE") >/dev/null 2>&1 &
100
- fi
101
- echo "🎵 Enhanced audio: $PROCESSED_FILE"
102
- else
103
- echo "Error: Processed file not found" >&2
104
- exit 1
105
- fi
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/play-tts-enhanced.sh
4
+ #
5
+ # AgentVibes - Enhanced TTS with Background Music and Effects
6
+ # Generates TTS, applies effects, mixes background, plays ONCE (no echo)
7
+ #
8
+ # Usage: play-tts-enhanced.sh "text to speak" [agent_name] [voice_override]
9
+ #
10
+ # Environment:
11
+ # AGENTVIBES_PARTY_MODE=true - Use room ambiance background (_party_mode config)
12
+ #
13
+
14
+ set -euo pipefail
15
+ export LC_ALL=C
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+
19
+ TEXT="${1:-}"
20
+ AGENT_NAME="${2:-default}"
21
+ VOICE_OVERRIDE="${3:-}"
22
+
23
+ if [[ -z "$TEXT" ]]; then
24
+ echo "Usage: $0 \"text to speak\" [agent_name] [voice_override]" >&2
25
+ exit 1
26
+ fi
27
+
28
+ # Determine which config to use
29
+ CONFIG_KEY="$AGENT_NAME"
30
+ if [[ "${AGENTVIBES_PARTY_MODE:-false}" == "true" ]]; then
31
+ CONFIG_KEY="_party_mode"
32
+ fi
33
+
34
+ # ---------------------------------------------------------------------------
35
+ # Per-agent profile overrides (from bmad-voice-map.json via bmad-speak.sh)
36
+ # If AGENTVIBES_AGENT_PROFILE is set and the file exists, apply reverb/personality/music
37
+ # overrides by temporarily setting effects-manager config for this agent
38
+ AGENT_PROFILE="${AGENTVIBES_AGENT_PROFILE:-}"
39
+
40
+ if [[ -n "$AGENT_PROFILE" ]] && [[ -f "$AGENT_PROFILE" ]]; then
41
+ # Read profile fields using node (reliable JSON parsing)
42
+ # SECURITY: Pass values via env vars to prevent shell injection
43
+ _PROFILE_REVERB=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.reverbPreset||'')}catch{}" 2>/dev/null || true)
44
+ _PROFILE_MUSIC_TRACK=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.backgroundMusic?.track||'')}catch{}" 2>/dev/null || true)
45
+ _PROFILE_MUSIC_VOL=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(String(p.backgroundMusic?.volume||''))}catch{}" 2>/dev/null || true)
46
+
47
+ # Apply per-agent reverb via effects-manager (scoped to this agent's config key)
48
+ if [[ -n "$_PROFILE_REVERB" ]] && [[ -f "$SCRIPT_DIR/effects-manager.sh" ]]; then
49
+ bash "$SCRIPT_DIR/effects-manager.sh" set-reverb "$_PROFILE_REVERB" "$CONFIG_KEY" 2>/dev/null || true
50
+ fi
51
+
52
+ # Override background music track/volume for this invocation via env vars
53
+ if [[ -n "$_PROFILE_MUSIC_TRACK" ]]; then
54
+ export AGENTVIBES_BG_TRACK="$_PROFILE_MUSIC_TRACK"
55
+ fi
56
+ if [[ -n "$_PROFILE_MUSIC_VOL" ]]; then
57
+ export AGENTVIBES_BG_VOLUME="$_PROFILE_MUSIC_VOL"
58
+ fi
59
+ fi
60
+
61
+ # Step 1: Generate TTS WITHOUT playback
62
+ export AGENTVIBES_NO_PLAYBACK=true
63
+ export AGENTVIBES_WAV_OUTPATH="${XDG_RUNTIME_DIR:-/tmp}/agentvibes-last-wav-$$.txt"
64
+
65
+ # Cleanup temp outpath file on exit
66
+ trap 'rm -f "$AGENTVIBES_WAV_OUTPATH"' EXIT
67
+ bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" "$VOICE_OVERRIDE"
68
+
69
+ # Read the generated file path (written by play-tts-piper.sh via AGENTVIBES_WAV_OUTPATH)
70
+ GENERATED_FILE=""
71
+ if [[ -f "$AGENTVIBES_WAV_OUTPATH" ]]; then
72
+ GENERATED_FILE=$(cat "$AGENTVIBES_WAV_OUTPATH")
73
+ rm -f "$AGENTVIBES_WAV_OUTPATH"
74
+ fi
75
+ unset AGENTVIBES_WAV_OUTPATH
76
+
77
+ if [[ -z "$GENERATED_FILE" ]] || [[ ! -f "$GENERATED_FILE" ]]; then
78
+ echo "Error: Could not find generated audio file" >&2
79
+ exit 1
80
+ fi
81
+
82
+ # Step 2: Process with effects and background
83
+ PROCESSED_FILE="${GENERATED_FILE%.wav}-enhanced.wav"
84
+
85
+ if [[ -f "$SCRIPT_DIR/audio-processor.sh" ]]; then
86
+ "$SCRIPT_DIR/audio-processor.sh" "$GENERATED_FILE" "$CONFIG_KEY" "$PROCESSED_FILE" 2>/dev/null || {
87
+ # Fallback to original if processing fails
88
+ PROCESSED_FILE="$GENERATED_FILE"
89
+ }
90
+ else
91
+ PROCESSED_FILE="$GENERATED_FILE"
92
+ fi
93
+
94
+ # Step 3: Play the processed audio ONCE
95
+ if [[ -f "$PROCESSED_FILE" ]]; then
96
+ if [[ "$(uname -s)" == "Darwin" ]]; then
97
+ afplay "$PROCESSED_FILE" >/dev/null 2>&1 &
98
+ else
99
+ (mpv "$PROCESSED_FILE" || aplay "$PROCESSED_FILE" || paplay "$PROCESSED_FILE") >/dev/null 2>&1 &
100
+ fi
101
+ echo "🎵 Enhanced audio: $PROCESSED_FILE"
102
+ else
103
+ echo "Error: Processed file not found" >&2
104
+ exit 1
105
+ fi