agentvibes 4.0.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/.agentvibes/bmad/bmad-voices.md +69 -69
  2. package/.agentvibes/config.json +12 -0
  3. package/.claude/activation-instructions +54 -54
  4. package/.claude/audio/tracks/README.md +52 -52
  5. package/.claude/commands/agent-vibes/add.md +21 -21
  6. package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
  7. package/.claude/commands/agent-vibes/agent.md +79 -79
  8. package/.claude/commands/agent-vibes/background-music.md +111 -111
  9. package/.claude/commands/agent-vibes/bmad.md +198 -198
  10. package/.claude/commands/agent-vibes/clean.md +18 -18
  11. package/.claude/commands/agent-vibes/cleanup.md +18 -18
  12. package/.claude/commands/agent-vibes/commands.json +145 -145
  13. package/.claude/commands/agent-vibes/effects.md +97 -97
  14. package/.claude/commands/agent-vibes/get.md +9 -9
  15. package/.claude/commands/agent-vibes/hide.md +91 -91
  16. package/.claude/commands/agent-vibes/language.md +23 -23
  17. package/.claude/commands/agent-vibes/learn.md +67 -67
  18. package/.claude/commands/agent-vibes/list.md +13 -13
  19. package/.claude/commands/agent-vibes/mute.md +37 -37
  20. package/.claude/commands/agent-vibes/preview.md +17 -17
  21. package/.claude/commands/agent-vibes/provider.md +68 -68
  22. package/.claude/commands/agent-vibes/replay-target.md +14 -14
  23. package/.claude/commands/agent-vibes/sample.md +12 -12
  24. package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
  25. package/.claude/commands/agent-vibes/set-pretext.md +65 -65
  26. package/.claude/commands/agent-vibes/set-speed.md +41 -41
  27. package/.claude/commands/agent-vibes/show.md +84 -84
  28. package/.claude/commands/agent-vibes/switch.md +87 -87
  29. package/.claude/commands/agent-vibes/target-voice.md +26 -26
  30. package/.claude/commands/agent-vibes/target.md +30 -30
  31. package/.claude/commands/agent-vibes/translate.md +68 -68
  32. package/.claude/commands/agent-vibes/unmute.md +45 -45
  33. package/.claude/commands/agent-vibes/verbosity.md +89 -89
  34. package/.claude/commands/agent-vibes/whoami.md +7 -7
  35. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  36. package/.claude/commands/agent-vibes-rdp.md +24 -24
  37. package/.claude/config/agentvibes.json +1 -0
  38. package/.claude/config/audio-effects.cfg +3 -2
  39. package/.claude/config/audio-effects.cfg.sample +52 -52
  40. package/.claude/config/background-music-volume.txt +1 -0
  41. package/.claude/config/intro-text.txt +1 -0
  42. package/.claude/config/piper-speech-rate.txt +4 -0
  43. package/.claude/config/piper-target-speech-rate.txt +1 -0
  44. package/.claude/config/reverb-level.txt +1 -0
  45. package/.claude/config/tts-speech-rate.txt +4 -0
  46. package/.claude/config/tts-target-speech-rate.txt +1 -0
  47. package/.claude/docs/TERMUX_SETUP.md +408 -408
  48. package/.claude/github-star-reminder.txt +1 -1
  49. package/.claude/hooks/README-TTS-QUEUE.md +135 -135
  50. package/.claude/hooks/audio-cache-utils.sh +246 -246
  51. package/.claude/hooks/audio-processor.sh +433 -389
  52. package/.claude/hooks/background-music-manager.sh +404 -404
  53. package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
  54. package/.claude/hooks/bmad-speak.sh +269 -112
  55. package/.claude/hooks/bmad-tts-injector.sh +568 -568
  56. package/.claude/hooks/bmad-voice-manager.sh +928 -928
  57. package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
  58. package/.claude/hooks/clawdbot-receiver.sh +107 -107
  59. package/.claude/hooks/clean-audio-cache.sh +22 -22
  60. package/.claude/hooks/cleanup-cache.sh +106 -106
  61. package/.claude/hooks/configure-rdp-mode.sh +137 -137
  62. package/.claude/hooks/download-extra-voices.sh +244 -244
  63. package/.claude/hooks/effects-manager.sh +268 -268
  64. package/.claude/hooks/github-star-reminder.sh +154 -154
  65. package/.claude/hooks/language-manager.sh +362 -362
  66. package/.claude/hooks/learn-manager.sh +492 -492
  67. package/.claude/hooks/macos-voice-manager.sh +205 -205
  68. package/.claude/hooks/migrate-background-music.sh +125 -125
  69. package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
  70. package/.claude/hooks/optimize-background-music.sh +87 -87
  71. package/.claude/hooks/path-resolver.sh +60 -60
  72. package/.claude/hooks/personality-manager.sh +448 -448
  73. package/.claude/hooks/piper-download-voices.sh +225 -225
  74. package/.claude/hooks/piper-installer.sh +292 -292
  75. package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
  76. package/.claude/hooks/piper-voice-manager.sh +24 -3
  77. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +90 -90
  78. package/.claude/hooks/play-tts-enhanced.sh +105 -70
  79. package/.claude/hooks/play-tts-macos.sh +368 -345
  80. package/.claude/hooks/play-tts-piper.sh +679 -578
  81. package/.claude/hooks/play-tts-soprano.sh +356 -320
  82. package/.claude/hooks/play-tts-ssh-remote.sh +167 -88
  83. package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
  84. package/.claude/hooks/play-tts.sh +301 -298
  85. package/.claude/hooks/prepare-release.sh +54 -54
  86. package/.claude/hooks/provider-commands.sh +617 -617
  87. package/.claude/hooks/provider-manager.sh +399 -399
  88. package/.claude/hooks/replay-target-audio.sh +95 -95
  89. package/.claude/hooks/requirements.txt +6 -6
  90. package/.claude/hooks/sentiment-manager.sh +201 -201
  91. package/.claude/hooks/session-start-tts.sh +81 -71
  92. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  93. package/.claude/hooks/speed-manager.sh +291 -291
  94. package/.claude/hooks/stop-tts.sh +84 -0
  95. package/.claude/hooks/termux-installer.sh +261 -261
  96. package/.claude/hooks/translate-manager.sh +341 -341
  97. package/.claude/hooks/translator.py +237 -237
  98. package/.claude/hooks/tts-queue-worker.sh +145 -114
  99. package/.claude/hooks/tts-queue.sh +165 -136
  100. package/.claude/hooks/verbosity-manager.sh +178 -178
  101. package/.claude/hooks/voice-manager.sh +548 -544
  102. package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
  103. package/.claude/hooks-windows/background-music-manager.ps1 +348 -0
  104. package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -0
  105. package/.claude/hooks-windows/download-extra-voices.ps1 +185 -0
  106. package/.claude/hooks-windows/effects-manager.ps1 +294 -0
  107. package/.claude/hooks-windows/language-manager.ps1 +193 -0
  108. package/.claude/hooks-windows/learn-manager.ps1 +241 -0
  109. package/.claude/hooks-windows/personality-manager.ps1 +266 -0
  110. package/.claude/hooks-windows/play-tts-piper.ps1 +209 -0
  111. package/.claude/hooks-windows/play-tts-sapi.ps1 +108 -0
  112. package/.claude/hooks-windows/play-tts-soprano.ps1 +159 -158
  113. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +50 -5
  114. package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -108
  115. package/.claude/hooks-windows/play-tts.ps1 +344 -266
  116. package/.claude/hooks-windows/provider-manager.ps1 +29 -10
  117. package/.claude/hooks-windows/session-start-tts.ps1 +124 -124
  118. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  119. package/.claude/hooks-windows/speed-manager.ps1 +166 -0
  120. package/.claude/hooks-windows/verbosity-manager.ps1 +119 -0
  121. package/.claude/hooks-windows/voice-manager-windows.ps1 +92 -8
  122. package/.claude/output-styles/agent-vibes.md +202 -202
  123. package/.claude/personalities/angry.md +14 -14
  124. package/.claude/personalities/annoying.md +14 -14
  125. package/.claude/personalities/crass.md +14 -14
  126. package/.claude/personalities/dramatic.md +14 -14
  127. package/.claude/personalities/dry-humor.md +50 -50
  128. package/.claude/personalities/flirty.md +20 -20
  129. package/.claude/personalities/funny.md +14 -14
  130. package/.claude/personalities/grandpa.md +32 -32
  131. package/.claude/personalities/millennial.md +14 -14
  132. package/.claude/personalities/moody.md +14 -14
  133. package/.claude/personalities/normal.md +16 -16
  134. package/.claude/personalities/pirate.md +14 -14
  135. package/.claude/personalities/poetic.md +14 -14
  136. package/.claude/personalities/professional.md +14 -14
  137. package/.claude/personalities/rapper.md +55 -55
  138. package/.claude/personalities/robot.md +14 -14
  139. package/.claude/personalities/sarcastic.md +38 -38
  140. package/.claude/personalities/sassy.md +14 -14
  141. package/.claude/personalities/surfer-dude.md +14 -14
  142. package/.claude/personalities/zen.md +14 -14
  143. package/.claude/settings.json +15 -15
  144. package/.claude/verbosity.txt +1 -1
  145. package/.clawdbot/README.md +105 -105
  146. package/.clawdbot/skill/SKILL.md +241 -241
  147. package/.mcp.json +12 -0
  148. package/CLAUDE.md +170 -181
  149. package/README.md +2029 -1909
  150. package/RELEASE_NOTES.md +1310 -66
  151. package/WINDOWS-SETUP.md +208 -208
  152. package/bin/agent-vibes +39 -39
  153. package/bin/agentvibes-voice-browser.js +1840 -1826
  154. package/bin/agentvibes.js +48 -2
  155. package/bin/mcp-server.js +121 -121
  156. package/bin/mcp-server.sh +206 -206
  157. package/bin/test-bmad-pr +78 -78
  158. package/mcp-server/QUICK_START.md +203 -203
  159. package/mcp-server/README.md +345 -345
  160. package/mcp-server/WINDOWS_SETUP.md +260 -260
  161. package/mcp-server/docs/troubleshooting-audio.md +313 -313
  162. package/mcp-server/examples/claude_desktop_config.json +11 -11
  163. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  164. package/mcp-server/examples/custom_instructions.md +169 -169
  165. package/mcp-server/install-deps.js +130 -130
  166. package/mcp-server/pyproject.toml +52 -52
  167. package/mcp-server/requirements.txt +2 -2
  168. package/mcp-server/server.py +1465 -1417
  169. package/mcp-server/test_server.py +395 -395
  170. package/mcp-server/test_windows_script_parity.py +336 -0
  171. package/package.json +110 -112
  172. package/setup-windows.ps1 +815 -815
  173. package/src/bmad-detector.js +71 -71
  174. package/src/cli/list-personalities.js +110 -110
  175. package/src/cli/list-voices.js +114 -114
  176. package/src/commands/bmad-voices.js +394 -394
  177. package/src/commands/install-mcp.js +476 -476
  178. package/src/console/app.js +824 -806
  179. package/src/console/audio-env.js +20 -1
  180. package/src/console/brand-colors.js +13 -13
  181. package/src/console/constants/personalities.js +44 -0
  182. package/src/console/footer-config.js +50 -46
  183. package/src/console/modals/modal-overlay.js +247 -247
  184. package/src/console/navigation.js +62 -61
  185. package/src/console/tabs/agents-tab.js +1684 -369
  186. package/src/console/tabs/help-tab.js +261 -261
  187. package/src/console/tabs/install-tab.js +1007 -991
  188. package/src/console/tabs/music-tab.js +22 -8
  189. package/src/console/tabs/placeholder-tab.js +53 -46
  190. package/src/console/tabs/readme-tab.js +267 -267
  191. package/src/console/tabs/receiver-tab.js +1472 -0
  192. package/src/console/tabs/settings-tab.js +185 -402
  193. package/src/console/tabs/voices-tab.js +100 -21
  194. package/src/console/widgets/destroy-list.js +25 -0
  195. package/src/console/widgets/format-utils.js +89 -0
  196. package/src/console/widgets/notice.js +55 -0
  197. package/src/console/widgets/personality-picker.js +185 -0
  198. package/src/console/widgets/reverb-picker.js +94 -0
  199. package/src/console/widgets/track-picker.js +285 -0
  200. package/src/installer/music-file-input.js +304 -304
  201. package/src/installer.js +5882 -5777
  202. package/src/services/agent-voice-store.js +423 -163
  203. package/src/services/config-service.js +264 -264
  204. package/src/services/navigation-service.js +123 -123
  205. package/src/services/provider-service.js +132 -132
  206. package/src/services/verbosity-service.js +157 -157
  207. package/src/utils/audio-duration-validator.js +298 -298
  208. package/src/utils/audio-format-validator.js +277 -277
  209. package/src/utils/dependency-checker.js +469 -466
  210. package/src/utils/file-ownership-verifier.js +358 -358
  211. package/src/utils/list-formatter.js +194 -194
  212. package/src/utils/music-file-validator.js +285 -275
  213. package/src/utils/preview-list-prompt.js +136 -136
  214. package/src/utils/provider-validator.js +96 -12
  215. package/src/utils/secure-music-storage.js +412 -412
  216. package/templates/agentvibes-receiver.sh +482 -162
  217. package/templates/audio/welcome-music.mp3 +0 -0
  218. package/voice-assignments.json +8244 -8244
  219. package/.claude/config/background-music-position.txt +0 -1
@@ -1,114 +1,145 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/tts-queue-worker.sh
4
- #
5
- # TTS Queue Worker - Background process that plays queued TTS sequentially
6
- # Automatically exits when queue is empty for 5 seconds
7
-
8
- set -euo pipefail
9
-
10
- # Security: Use secure temp directory with restrictive permissions
11
- # Must match the logic in tts-queue.sh exactly
12
- if [[ -n "${XDG_RUNTIME_DIR:-}" ]] && [[ -d "$XDG_RUNTIME_DIR" ]]; then
13
- QUEUE_DIR="$XDG_RUNTIME_DIR/agentvibes-tts-queue"
14
- else
15
- # Fallback to user-specific temp directory
16
- QUEUE_DIR="/tmp/agentvibes-tts-queue-$USER"
17
- fi
18
-
19
- # Security: Validate queue directory exists and has correct ownership
20
- if [[ ! -d "$QUEUE_DIR" ]]; then
21
- echo "Error: Queue directory does not exist: $QUEUE_DIR" >&2
22
- exit 1
23
- fi
24
-
25
- # Security: Verify we own the queue directory (prevent symlink attacks)
26
- if [[ "$(stat -c '%u' "$QUEUE_DIR" 2>/dev/null || stat -f '%u' "$QUEUE_DIR" 2>/dev/null)" != "$(id -u)" ]]; then
27
- echo "Error: Queue directory not owned by current user" >&2
28
- exit 1
29
- fi
30
-
31
- WORKER_PID_FILE="$QUEUE_DIR/worker.pid"
32
- IDLE_TIMEOUT=5 # Exit after 5 seconds of no new requests
33
-
34
- # Get script directory
35
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
36
-
37
- # Configurable delay between speakers (seconds)
38
- # Can be overridden by .claude/tts-speaker-delay.txt or ~/.claude/tts-speaker-delay.txt
39
- SPEAKER_DELAY=4 # Default: 4 seconds between speakers
40
-
41
- # Check for custom delay configuration
42
- if [[ -f ".claude/tts-speaker-delay.txt" ]]; then
43
- CUSTOM_DELAY=$(cat .claude/tts-speaker-delay.txt 2>/dev/null | tr -d '[:space:]')
44
- if [[ "$CUSTOM_DELAY" =~ ^[0-9]+$ ]]; then
45
- SPEAKER_DELAY=$CUSTOM_DELAY
46
- fi
47
- elif [[ -f "$HOME/.claude/tts-speaker-delay.txt" ]]; then
48
- CUSTOM_DELAY=$(cat "$HOME/.claude/tts-speaker-delay.txt" 2>/dev/null | tr -d '[:space:]')
49
- if [[ "$CUSTOM_DELAY" =~ ^[0-9]+$ ]]; then
50
- SPEAKER_DELAY=$CUSTOM_DELAY
51
- fi
52
- fi
53
-
54
- # Trap to clean up on exit
55
- trap 'rm -f "$WORKER_PID_FILE"' EXIT
56
-
57
- # Process queue items
58
- process_queue() {
59
- local idle_count=0
60
-
61
- while true; do
62
- # Find oldest queue item
63
- local queue_item=$(ls -1 "$QUEUE_DIR"/*.queue 2>/dev/null | sort | head -1)
64
-
65
- if [[ -z "$queue_item" ]]; then
66
- # Queue is empty, increment idle counter
67
- idle_count=$((idle_count + 1))
68
-
69
- if [[ $idle_count -ge $IDLE_TIMEOUT ]]; then
70
- # No new items for timeout period, exit worker
71
- exit 0
72
- fi
73
-
74
- # Wait 1 second and check again
75
- sleep 1
76
- continue
77
- fi
78
-
79
- # Reset idle counter - we have work
80
- idle_count=0
81
-
82
- # Load TTS request
83
- source "$queue_item"
84
-
85
- # Decode base64 values
86
- TEXT=$(echo -n "$TEXT_B64" | base64 -d)
87
- VOICE=$(echo -n "$VOICE_B64" | base64 -d)
88
- AGENT=$(echo -n "${AGENT_B64:-}" | base64 -d 2>/dev/null || echo "default")
89
-
90
- # Use enhanced TTS with agent-specific background music if agent is specified
91
- # and background music is enabled
92
- if [[ -f "$SCRIPT_DIR/play-tts-enhanced.sh" ]] && [[ "$AGENT" != "default" ]] && [[ -n "$AGENT" ]]; then
93
- # Party mode: each agent gets their unique background music from audio-effects.cfg
94
- bash "$SCRIPT_DIR/play-tts-enhanced.sh" "$TEXT" "$AGENT" "$VOICE" || true
95
- else
96
- # Standard TTS without background music
97
- # Display output to show file location (GitHub Issue #39)
98
- if [[ -n "${VOICE:-}" ]]; then
99
- bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" "$VOICE" || true
100
- else
101
- bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" || true
102
- fi
103
- fi
104
-
105
- # Add configurable pause between speakers for natural conversation flow
106
- sleep $SPEAKER_DELAY
107
-
108
- # Remove processed item
109
- rm -f "$queue_item"
110
- done
111
- }
112
-
113
- # Start processing
114
- process_queue
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/tts-queue-worker.sh
4
+ #
5
+ # TTS Queue Worker - Background process that plays queued TTS sequentially
6
+ # Automatically exits when queue is empty for 5 seconds
7
+
8
+ set -euo pipefail
9
+
10
+ # Security: Use secure temp directory with restrictive permissions
11
+ # Must match the logic in tts-queue.sh exactly
12
+ if [[ -n "${XDG_RUNTIME_DIR:-}" ]] && [[ -d "$XDG_RUNTIME_DIR" ]]; then
13
+ QUEUE_DIR="$XDG_RUNTIME_DIR/agentvibes-tts-queue"
14
+ else
15
+ # Fallback to user-specific temp directory
16
+ QUEUE_DIR="/tmp/agentvibes-tts-queue-$(id -u)"
17
+ fi
18
+
19
+ # Security: Validate queue directory exists and has correct ownership
20
+ if [[ ! -d "$QUEUE_DIR" ]]; then
21
+ echo "Error: Queue directory does not exist: $QUEUE_DIR" >&2
22
+ exit 1
23
+ fi
24
+
25
+ # Security: Verify we own the queue directory (prevent symlink attacks)
26
+ if [[ "$(stat -c '%u' "$QUEUE_DIR" 2>/dev/null || stat -f '%u' "$QUEUE_DIR" 2>/dev/null)" != "$(id -u)" ]]; then
27
+ echo "Error: Queue directory not owned by current user" >&2
28
+ exit 1
29
+ fi
30
+
31
+ WORKER_PID_FILE="$QUEUE_DIR/worker.pid"
32
+ IDLE_TIMEOUT=5 # Exit after 5 seconds of no new requests
33
+
34
+ # Get script directory
35
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
36
+
37
+ # Configurable delay between speakers (seconds)
38
+ # Can be overridden by .claude/tts-speaker-delay.txt or ~/.claude/tts-speaker-delay.txt
39
+ SPEAKER_DELAY=4 # Default: 4 seconds between speakers
40
+
41
+ # Check for custom delay configuration
42
+ if [[ -f ".claude/tts-speaker-delay.txt" ]]; then
43
+ CUSTOM_DELAY=$(cat .claude/tts-speaker-delay.txt 2>/dev/null | tr -d '[:space:]')
44
+ if [[ "$CUSTOM_DELAY" =~ ^[0-9]+$ ]]; then
45
+ SPEAKER_DELAY=$CUSTOM_DELAY
46
+ fi
47
+ elif [[ -f "$HOME/.claude/tts-speaker-delay.txt" ]]; then
48
+ CUSTOM_DELAY=$(cat "$HOME/.claude/tts-speaker-delay.txt" 2>/dev/null | tr -d '[:space:]')
49
+ if [[ "$CUSTOM_DELAY" =~ ^[0-9]+$ ]]; then
50
+ SPEAKER_DELAY=$CUSTOM_DELAY
51
+ fi
52
+ fi
53
+
54
+ # Trap to clean up on exit
55
+ trap 'rm -f "$WORKER_PID_FILE"' EXIT
56
+
57
+ # Process queue items
58
+ process_queue() {
59
+ local idle_count=0
60
+
61
+ while true; do
62
+ # Find oldest queue item
63
+ local queue_item=$(ls -1 "$QUEUE_DIR"/*.queue 2>/dev/null | sort | head -1)
64
+
65
+ if [[ -z "$queue_item" ]]; then
66
+ # Queue is empty, increment idle counter
67
+ idle_count=$((idle_count + 1))
68
+
69
+ if [[ $idle_count -ge $IDLE_TIMEOUT ]]; then
70
+ # No new items for timeout period, exit worker
71
+ exit 0
72
+ fi
73
+
74
+ # Wait for a new queue item — use inotifywait if available to avoid polling
75
+ # Use a 1-second timeout (-t 1) so the idle counter still advances correctly
76
+ if command -v inotifywait &>/dev/null; then
77
+ inotifywait -q -e create -t 1 "$QUEUE_DIR" 2>/dev/null || true
78
+ else
79
+ sleep 1
80
+ fi
81
+ continue
82
+ fi
83
+
84
+ # Reset idle counter - we have work
85
+ idle_count=0
86
+
87
+ # Load queue item — explicit key=value parsing (SECURITY: never source untrusted files)
88
+ TEXT_FILE=""
89
+ VOICE=""
90
+ AGENT=""
91
+ PROFILE_PATH=""
92
+ PLAY_WAV=""
93
+ while IFS='=' read -r _key _val; do
94
+ case "$_key" in
95
+ TEXT_FILE) TEXT_FILE="$_val" ;;
96
+ VOICE) VOICE="$_val" ;;
97
+ AGENT) AGENT="$_val" ;;
98
+ PROFILE_PATH) PROFILE_PATH="$_val" ;;
99
+ PLAY_WAV) PLAY_WAV="$_val" ;;
100
+ esac
101
+ done < "$queue_item"
102
+
103
+ # Check if this is a pre-generated WAV playback item
104
+ if [[ -n "${PLAY_WAV:-}" ]] && [[ -f "$PLAY_WAV" ]]; then
105
+ # Play the pre-generated WAV directly (synthesis already done by bmad-speak)
106
+ if command -v paplay &>/dev/null; then
107
+ paplay "$PLAY_WAV" 2>/dev/null || true
108
+ elif command -v aplay &>/dev/null; then
109
+ aplay -q "$PLAY_WAV" 2>/dev/null || true
110
+ elif command -v ffplay &>/dev/null; then
111
+ ffplay -nodisp -autoexit -loglevel quiet "$PLAY_WAV" 2>/dev/null || true
112
+ fi
113
+ else
114
+ # Full TTS request — read text from companion file, use voice/agent directly
115
+ TEXT=""
116
+ if [[ -n "${TEXT_FILE:-}" ]] && [[ -f "$TEXT_FILE" ]]; then
117
+ TEXT=$(cat "$TEXT_FILE")
118
+ rm -f "$TEXT_FILE"
119
+ fi
120
+ AGENT_PROFILE="${PROFILE_PATH:-}"
121
+
122
+ export AGENTVIBES_AGENT_PROFILE="$AGENT_PROFILE"
123
+
124
+ if [[ -n "${VOICE:-}" ]]; then
125
+ bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" "${VOICE}" || true
126
+ else
127
+ bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" || true
128
+ fi
129
+
130
+ if [[ -n "$AGENT_PROFILE" ]] && [[ -f "$AGENT_PROFILE" ]]; then
131
+ rm -f "$AGENT_PROFILE"
132
+ fi
133
+ unset AGENTVIBES_AGENT_PROFILE
134
+ fi
135
+
136
+ # Add configurable pause between speakers for natural conversation flow
137
+ sleep $SPEAKER_DELAY
138
+
139
+ # Remove processed item and any companion text file
140
+ rm -f "$queue_item" "${queue_item%.queue}.txt"
141
+ done
142
+ }
143
+
144
+ # Start processing
145
+ process_queue
@@ -1,136 +1,165 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/tts-queue.sh
4
- #
5
- # TTS Queue Manager for Party Mode
6
- # Queues TTS requests and plays them sequentially in the background
7
- # This allows Claude to continue generating responses while audio plays in order
8
-
9
- set -euo pipefail
10
-
11
- # Security: Use secure temp directory with restrictive permissions
12
- # Check if XDG_RUNTIME_DIR is available (more secure than /tmp)
13
- if [[ -n "${XDG_RUNTIME_DIR:-}" ]] && [[ -d "$XDG_RUNTIME_DIR" ]]; then
14
- QUEUE_DIR="$XDG_RUNTIME_DIR/agentvibes-tts-queue"
15
- else
16
- # Fallback to user-specific temp directory
17
- QUEUE_DIR="/tmp/agentvibes-tts-queue-$USER"
18
- fi
19
-
20
- QUEUE_LOCK="$QUEUE_DIR/queue.lock"
21
- WORKER_PID_FILE="$QUEUE_DIR/worker.pid"
22
-
23
- # Get script directory
24
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25
-
26
- # Initialize queue directory with restrictive permissions
27
- if [[ ! -d "$QUEUE_DIR" ]]; then
28
- mkdir -p "$QUEUE_DIR"
29
- chmod 700 "$QUEUE_DIR" # Only owner can read/write/execute
30
- fi
31
-
32
- # @function add_to_queue
33
- # @intent Add a TTS request to the queue for sequential playback
34
- # @param $1 dialogue text
35
- # @param $2 voice name (optional)
36
- # @param $3 agent name (optional, for background music in party mode)
37
- add_to_queue() {
38
- local text="$1"
39
- local voice="${2:-}"
40
- local agent="${3:-default}"
41
-
42
- # Create unique queue item with timestamp
43
- local timestamp=$(date +%s%N)
44
- local queue_file="$QUEUE_DIR/$timestamp.queue"
45
-
46
- # Write request to queue file (base64 encoded to handle all special chars)
47
- cat > "$queue_file" <<EOF
48
- TEXT_B64=$(echo -n "$text" | base64 -w0)
49
- VOICE_B64=$(echo -n "$voice" | base64 -w0)
50
- AGENT_B64=$(echo -n "$agent" | base64 -w0)
51
- EOF
52
-
53
- # Start queue worker if not already running
54
- start_worker_if_needed
55
- }
56
-
57
- # @function start_worker_if_needed
58
- # @intent Start the queue worker process if it's not already running
59
- start_worker_if_needed() {
60
- # Security: Use file locking to prevent race condition
61
- # Open file descriptor 200 for locking
62
- exec 200>"$QUEUE_LOCK"
63
-
64
- # Acquire exclusive lock (flock -x) with timeout
65
- if ! flock -x -w 5 200; then
66
- echo "Warning: Could not acquire queue lock" >&2
67
- return 1
68
- fi
69
-
70
- # Check if worker is already running (within lock)
71
- if [[ -f "$WORKER_PID_FILE" ]]; then
72
- local pid=$(cat "$WORKER_PID_FILE")
73
- if kill -0 "$pid" 2>/dev/null; then
74
- # Worker is running, release lock and return
75
- flock -u 200
76
- exec 200>&-
77
- return 0
78
- fi
79
- fi
80
-
81
- # Start worker in background
82
- "$SCRIPT_DIR/tts-queue-worker.sh" &
83
- local worker_pid=$!
84
- echo $worker_pid > "$WORKER_PID_FILE"
85
-
86
- # Release lock
87
- flock -u 200
88
- exec 200>&-
89
- }
90
-
91
- # @function clear_queue
92
- # @intent Clear all pending TTS requests (emergency stop)
93
- clear_queue() {
94
- rm -f "$QUEUE_DIR"/*.queue
95
- echo "✅ Queue cleared"
96
- }
97
-
98
- # @function show_queue
99
- # @intent Display current queue status
100
- show_queue() {
101
- local count=$(ls -1 "$QUEUE_DIR"/*.queue 2>/dev/null | wc -l)
102
- echo "📊 Queue status: $count items pending"
103
-
104
- if [[ -f "$WORKER_PID_FILE" ]]; then
105
- local pid=$(cat "$WORKER_PID_FILE")
106
- if kill -0 "$pid" 2>/dev/null; then
107
- echo " Worker process running (PID: $pid)"
108
- else
109
- echo "❌ Worker process not running"
110
- fi
111
- else
112
- echo "❌ Worker process not running"
113
- fi
114
- }
115
-
116
- # Main command dispatcher
117
- case "${1:-help}" in
118
- add)
119
- add_to_queue "${2:-}" "${3:-}" "${4:-default}"
120
- ;;
121
- clear)
122
- clear_queue
123
- ;;
124
- status)
125
- show_queue
126
- ;;
127
- *)
128
- echo "Usage: tts-queue.sh {add|clear|status}"
129
- echo ""
130
- echo "Commands:"
131
- echo " add <text> [voice] [agent] Add TTS request to queue with optional agent for background music"
132
- echo " clear Clear all pending requests"
133
- echo " status Show queue status"
134
- exit 1
135
- ;;
136
- esac
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/tts-queue.sh
4
+ #
5
+ # TTS Queue Manager for Party Mode
6
+ # Queues TTS requests and plays them sequentially in the background
7
+ # This allows Claude to continue generating responses while audio plays in order
8
+
9
+ set -euo pipefail
10
+
11
+ # Security: Use secure temp directory with restrictive permissions
12
+ # Check if XDG_RUNTIME_DIR is available (more secure than /tmp)
13
+ if [[ -n "${XDG_RUNTIME_DIR:-}" ]] && [[ -d "$XDG_RUNTIME_DIR" ]]; then
14
+ QUEUE_DIR="$XDG_RUNTIME_DIR/agentvibes-tts-queue"
15
+ else
16
+ # Fallback to user-specific temp directory
17
+ QUEUE_DIR="/tmp/agentvibes-tts-queue-$(id -u)"
18
+ fi
19
+
20
+ QUEUE_LOCK="$QUEUE_DIR/queue.lock"
21
+ WORKER_PID_FILE="$QUEUE_DIR/worker.pid"
22
+
23
+ # Get script directory
24
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25
+
26
+ # Initialize queue directory with restrictive permissions
27
+ if [[ ! -d "$QUEUE_DIR" ]]; then
28
+ mkdir -p "$QUEUE_DIR"
29
+ chmod 700 "$QUEUE_DIR" # Only owner can read/write/execute
30
+ fi
31
+
32
+ # @function add_to_queue
33
+ # @intent Add a TTS request to the queue for sequential playback
34
+ # @param $1 dialogue text
35
+ # @param $2 voice name (optional)
36
+ # @param $3 agent name (optional, for background music in party mode)
37
+ # @param $4 agent profile path (optional, PID-scoped temp JSON with reverb/personality/music overrides)
38
+ add_to_queue() {
39
+ local text="$1"
40
+ local voice="${2:-}"
41
+ local agent="${3:-default}"
42
+ local profile_path="${4:-}"
43
+
44
+ # Create unique queue item with timestamp
45
+ local timestamp=$(date +%s%N)
46
+ local queue_file="$QUEUE_DIR/$timestamp.queue"
47
+
48
+ # Write request to queue file using direct storage
49
+ # Text is stored in a separate .txt file (handles newlines and special chars safely)
50
+ # Voice and agent are simple identifiers with no special chars
51
+ printf '%s' "$text" > "${queue_file%.queue}.txt"
52
+ cat > "$queue_file" <<EOF
53
+ TEXT_FILE=${queue_file%.queue}.txt
54
+ VOICE=$voice
55
+ AGENT=$agent
56
+ PROFILE_PATH=$profile_path
57
+ EOF
58
+
59
+ # Start queue worker if not already running
60
+ start_worker_if_needed
61
+ }
62
+
63
+ # @function start_worker_if_needed
64
+ # @intent Start the queue worker process if it's not already running
65
+ start_worker_if_needed() {
66
+ # Security: Use file locking to prevent race condition
67
+ # Open file descriptor 200 for locking
68
+ exec 200>"$QUEUE_LOCK"
69
+
70
+ # Acquire exclusive lock (flock -x) with timeout
71
+ if ! flock -x -w 5 200; then
72
+ echo "Warning: Could not acquire queue lock" >&2
73
+ return 1
74
+ fi
75
+
76
+ # Check if worker is already running (within lock)
77
+ if [[ -f "$WORKER_PID_FILE" ]]; then
78
+ local pid=$(cat "$WORKER_PID_FILE")
79
+ if kill -0 "$pid" 2>/dev/null; then
80
+ # Worker is running, release lock and return
81
+ flock -u 200
82
+ exec 200>&-
83
+ return 0
84
+ fi
85
+ fi
86
+
87
+ # Start worker in background
88
+ "$SCRIPT_DIR/tts-queue-worker.sh" &
89
+ local worker_pid=$!
90
+ echo $worker_pid > "$WORKER_PID_FILE"
91
+
92
+ # Release lock
93
+ flock -u 200
94
+ exec 200>&-
95
+ }
96
+
97
+ # @function clear_queue
98
+ # @intent Clear all pending TTS requests (emergency stop)
99
+ clear_queue() {
100
+ rm -f "$QUEUE_DIR"/*.queue
101
+ echo "✅ Queue cleared"
102
+ }
103
+
104
+ # @function show_queue
105
+ # @intent Display current queue status
106
+ show_queue() {
107
+ local count=$(ls -1 "$QUEUE_DIR"/*.queue 2>/dev/null | wc -l)
108
+ echo "📊 Queue status: $count items pending"
109
+
110
+ if [[ -f "$WORKER_PID_FILE" ]]; then
111
+ local pid=$(cat "$WORKER_PID_FILE")
112
+ if kill -0 "$pid" 2>/dev/null; then
113
+ echo "✅ Worker process running (PID: $pid)"
114
+ else
115
+ echo "❌ Worker process not running"
116
+ fi
117
+ else
118
+ echo "❌ Worker process not running"
119
+ fi
120
+ }
121
+
122
+ # @function play_wav
123
+ # @intent Queue a pre-generated WAV file for sequential playback
124
+ # @param $1 path to WAV file
125
+ play_wav() {
126
+ local wav_file="$1"
127
+ [[ -z "$wav_file" ]] && return 1
128
+ [[ ! -f "$wav_file" ]] && return 1
129
+
130
+ local timestamp=$(date +%s%N)
131
+ local queue_file="$QUEUE_DIR/$timestamp.queue"
132
+
133
+ # Write a playback-only queue item (no synthesis needed)
134
+ cat > "$queue_file" <<EOF
135
+ PLAY_WAV=$wav_file
136
+ EOF
137
+
138
+ start_worker_if_needed
139
+ }
140
+
141
+ # Main command dispatcher
142
+ case "${1:-help}" in
143
+ add)
144
+ add_to_queue "${2:-}" "${3:-}" "${4:-default}" "${5:-}"
145
+ ;;
146
+ play)
147
+ play_wav "${2:-}"
148
+ ;;
149
+ clear)
150
+ clear_queue
151
+ ;;
152
+ status)
153
+ show_queue
154
+ ;;
155
+ *)
156
+ echo "Usage: tts-queue.sh {add|play|clear|status}"
157
+ echo ""
158
+ echo "Commands:"
159
+ echo " add <text> [voice] [agent] Add TTS request to queue"
160
+ echo " play <wav_file> Queue a pre-generated WAV for playback"
161
+ echo " clear Clear all pending requests"
162
+ echo " status Show queue status"
163
+ exit 1
164
+ ;;
165
+ esac