agentvibes 5.2.1 → 5.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 (222) hide show
  1. package/.agentvibes/LITE-MODE.md +236 -0
  2. package/.agentvibes/README.md +136 -0
  3. package/.agentvibes/backup/session-start-tts.sh.20251210_212814 +141 -0
  4. package/.agentvibes/backups/agents/analyst_20260204_144958.md +78 -0
  5. package/.agentvibes/backups/agents/architect_20260204_144958.md +72 -0
  6. package/.agentvibes/backups/agents/dev_20260204_144958.md +74 -0
  7. package/.agentvibes/backups/agents/pm_20260204_144958.md +72 -0
  8. package/.agentvibes/backups/agents/quick-flow-solo-dev_20260204_144958.md +64 -0
  9. package/.agentvibes/backups/agents/sm_20260204_144958.md +87 -0
  10. package/.agentvibes/backups/agents/tea_20260204_144958.md +79 -0
  11. package/.agentvibes/backups/agents/tech-writer_20260204_144958.md +82 -0
  12. package/.agentvibes/backups/agents/ux-designer_20260204_144958.md +80 -0
  13. package/.agentvibes/bmad/bmad-voices.md +69 -69
  14. package/.agentvibes/config/README-personality-defaults.md +162 -0
  15. package/.agentvibes/config/mode.txt +1 -0
  16. package/.agentvibes/config/personality-voice-defaults.default.json +21 -0
  17. package/.agentvibes/config/save-audio.txt +1 -0
  18. package/.agentvibes/config/voice-metadata.json +160 -0
  19. package/.agentvibes/config.json +24 -15
  20. package/.agentvibes/hooks/help.sh +191 -0
  21. package/.agentvibes/hooks/post-tool-use-lite.sh +111 -0
  22. package/.agentvibes/hooks/save-audio-manager.sh +162 -0
  23. package/.agentvibes/hooks/session-start-full-optimized.sh +102 -0
  24. package/.agentvibes/hooks/session-start-full.sh +142 -0
  25. package/.agentvibes/hooks/session-start-lite-v2.sh +34 -0
  26. package/.agentvibes/hooks/session-start-lite.sh +29 -0
  27. package/.agentvibes/hooks/stop-lite.sh +115 -0
  28. package/.agentvibes/hooks/switch-mode.sh +215 -0
  29. package/.agentvibes/output-styles/audio-summary.md +30 -0
  30. package/.claude/activation-instructions +54 -54
  31. package/.claude/audio/voice-samples/piper/alan.wav +0 -0
  32. package/.claude/audio/voice-samples/piper/amy.wav +0 -0
  33. package/.claude/audio/voice-samples/piper/charlotte.wav +0 -0
  34. package/.claude/audio/voice-samples/piper/joe.wav +0 -0
  35. package/.claude/audio/voice-samples/piper/john.wav +0 -0
  36. package/.claude/audio/voice-samples/piper/katherine.wav +0 -0
  37. package/.claude/audio/voice-samples/piper/kristin.wav +0 -0
  38. package/.claude/audio/voice-samples/piper/linda.wav +0 -0
  39. package/.claude/audio/voice-samples/piper/marcus.wav +0 -0
  40. package/.claude/audio/voice-samples/piper/ryan.wav +0 -0
  41. package/.claude/commands/agent-vibes/add.md +21 -21
  42. package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
  43. package/.claude/commands/agent-vibes/agent.md +79 -79
  44. package/.claude/commands/agent-vibes/background-music.md +111 -111
  45. package/.claude/commands/agent-vibes/bmad.md +198 -198
  46. package/.claude/commands/agent-vibes/clean.md +18 -18
  47. package/.claude/commands/agent-vibes/cleanup.md +18 -18
  48. package/.claude/commands/agent-vibes/commands.json +145 -145
  49. package/.claude/commands/agent-vibes/effects.md +97 -97
  50. package/.claude/commands/agent-vibes/get.md +9 -9
  51. package/.claude/commands/agent-vibes/hide.md +91 -91
  52. package/.claude/commands/agent-vibes/language.md +23 -23
  53. package/.claude/commands/agent-vibes/learn.md +67 -67
  54. package/.claude/commands/agent-vibes/list.md +13 -13
  55. package/.claude/commands/agent-vibes/mute.md +37 -37
  56. package/.claude/commands/agent-vibes/preview.md +17 -17
  57. package/.claude/commands/agent-vibes/provider.md +68 -68
  58. package/.claude/commands/agent-vibes/replay-target.md +14 -14
  59. package/.claude/commands/agent-vibes/sample.md +12 -12
  60. package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
  61. package/.claude/commands/agent-vibes/set-pretext.md +65 -65
  62. package/.claude/commands/agent-vibes/set-speed.md +41 -41
  63. package/.claude/commands/agent-vibes/show.md +84 -84
  64. package/.claude/commands/agent-vibes/switch.md +87 -87
  65. package/.claude/commands/agent-vibes/target-voice.md +26 -26
  66. package/.claude/commands/agent-vibes/target.md +30 -30
  67. package/.claude/commands/agent-vibes/translate.md +68 -68
  68. package/.claude/commands/agent-vibes/unmute.md +45 -45
  69. package/.claude/commands/agent-vibes/whoami.md +7 -7
  70. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  71. package/.claude/commands/agent-vibes-rdp.md +24 -24
  72. package/.claude/config/audio-effects.cfg +4 -11
  73. package/.claude/config/audio-effects.cfg.sample +52 -52
  74. package/.claude/config/background-music-position.txt +27 -0
  75. package/.claude/config/background-music-volume.txt +1 -1
  76. package/.claude/config/background-music.cfg +1 -0
  77. package/.claude/config/background-music.txt +1 -0
  78. package/.claude/config/tts-speech-rate.txt +1 -4
  79. package/.claude/config/tts-verbosity.txt +1 -0
  80. package/.claude/docs/TERMUX_SETUP.md +408 -408
  81. package/.claude/github-star-reminder.txt +1 -1
  82. package/.claude/hooks/README-TTS-QUEUE.md +135 -135
  83. package/.claude/hooks/audio-cache-utils.sh +0 -0
  84. package/.claude/hooks/audio-processor.sh +60 -14
  85. package/.claude/hooks/background-music-manager.sh +0 -0
  86. package/.claude/hooks/bmad-party-manager.sh +225 -0
  87. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  88. package/.claude/hooks/bmad-speak.sh +6 -13
  89. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  90. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  91. package/.claude/hooks/clawdbot-receiver-SECURE.sh +25 -23
  92. package/.claude/hooks/clawdbot-receiver.sh +4 -28
  93. package/.claude/hooks/clean-audio-cache.sh +0 -0
  94. package/.claude/hooks/cleanup-cache.sh +0 -0
  95. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  96. package/.claude/hooks/download-extra-voices.sh +0 -0
  97. package/.claude/hooks/effects-manager.sh +0 -0
  98. package/.claude/hooks/github-star-reminder.sh +0 -0
  99. package/.claude/hooks/language-manager.sh +0 -0
  100. package/.claude/hooks/learn-manager.sh +0 -0
  101. package/.claude/hooks/macos-voice-manager.sh +0 -0
  102. package/.claude/hooks/migrate-background-music.sh +0 -0
  103. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  104. package/.claude/hooks/optimize-background-music.sh +0 -0
  105. package/.claude/hooks/personality-manager.sh +0 -0
  106. package/.claude/hooks/piper-download-voices.sh +0 -0
  107. package/.claude/hooks/piper-installer.sh +1 -1
  108. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  109. package/.claude/hooks/piper-voice-manager.sh +0 -0
  110. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  111. package/.claude/hooks/play-tts-macos.sh +6 -12
  112. package/.claude/hooks/play-tts-piper.sh +50 -79
  113. package/.claude/hooks/play-tts-soprano.sh +9 -43
  114. package/.claude/hooks/play-tts-ssh-remote.sh +42 -120
  115. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  116. package/.claude/hooks/play-tts.sh +48 -37
  117. package/.claude/hooks/post-response.sh +41 -0
  118. package/.claude/hooks/prepare-release.sh +0 -0
  119. package/.claude/hooks/provider-commands.sh +0 -0
  120. package/.claude/hooks/provider-manager.sh +0 -0
  121. package/.claude/hooks/replay-target-audio.sh +0 -0
  122. package/.claude/hooks/requirements.txt +6 -6
  123. package/.claude/hooks/sentiment-manager.sh +0 -0
  124. package/.claude/hooks/session-start-tts.sh +56 -39
  125. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  126. package/.claude/hooks/speed-manager.sh +0 -0
  127. package/.claude/hooks/stop.sh +63 -0
  128. package/.claude/hooks/termux-installer.sh +0 -0
  129. package/.claude/hooks/translate-manager.sh +0 -0
  130. package/.claude/hooks/translator.py +237 -237
  131. package/.claude/hooks/tts-queue-worker.sh +0 -0
  132. package/.claude/hooks/tts-queue.sh +0 -0
  133. package/.claude/hooks/verbosity-manager.sh +0 -0
  134. package/.claude/hooks/voice-manager.sh +26 -4
  135. package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
  136. package/.claude/hooks-windows/bmad-party-speak.ps1 +278 -274
  137. package/.claude/hooks-windows/bmad-speak.ps1 +264 -264
  138. package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -53
  139. package/.claude/hooks-windows/effects-manager.ps1 +294 -294
  140. package/.claude/hooks-windows/language-manager.ps1 +193 -193
  141. package/.claude/hooks-windows/learn-manager.ps1 +241 -241
  142. package/.claude/hooks-windows/personality-manager.ps1 +266 -266
  143. package/.claude/hooks-windows/play-tts-soprano.ps1 +5 -5
  144. package/.claude/hooks-windows/play-tts-termux-ssh.ps1 +138 -138
  145. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +164 -0
  146. package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -0
  147. package/.claude/hooks-windows/play-tts.ps1 +104 -481
  148. package/.claude/hooks-windows/provider-manager.ps1 +158 -192
  149. package/.claude/hooks-windows/session-start-tts.ps1 +55 -46
  150. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  151. package/.claude/hooks-windows/speed-manager.ps1 +166 -166
  152. package/.claude/hooks-windows/voice-manager-windows.ps1 +176 -260
  153. package/.claude/output-styles/agent-vibes.md +202 -202
  154. package/.claude/personalities/angry.md +14 -14
  155. package/.claude/personalities/annoying.md +14 -14
  156. package/.claude/personalities/crass.md +14 -14
  157. package/.claude/personalities/dramatic.md +14 -14
  158. package/.claude/personalities/dry-humor.md +50 -50
  159. package/.claude/personalities/flirty.md +20 -20
  160. package/.claude/personalities/funny.md +14 -14
  161. package/.claude/personalities/grandpa.md +32 -32
  162. package/.claude/personalities/millennial.md +14 -14
  163. package/.claude/personalities/moody.md +14 -14
  164. package/.claude/personalities/normal.md +16 -16
  165. package/.claude/personalities/pirate.md +14 -14
  166. package/.claude/personalities/poetic.md +14 -14
  167. package/.claude/personalities/professional.md +14 -14
  168. package/.claude/personalities/rapper.md +55 -55
  169. package/.claude/personalities/robot.md +14 -14
  170. package/.claude/personalities/sarcastic.md +38 -38
  171. package/.claude/personalities/sassy.md +14 -14
  172. package/.claude/personalities/surfer-dude.md +14 -14
  173. package/.claude/personalities/zen.md +14 -14
  174. package/.claude/piper-voices-dir.txt +1 -0
  175. package/.claude/settings.json +25 -15
  176. package/.claude/verbosity.txt +1 -1
  177. package/.clawdbot/README.md +105 -105
  178. package/.clawdbot/skill/SKILL.md +149 -145
  179. package/.mcp.json +30 -11
  180. package/CLAUDE.md +170 -215
  181. package/README.md +206 -515
  182. package/RELEASE_NOTES.md +1132 -1884
  183. package/WINDOWS-SETUP.md +208 -208
  184. package/bin/agent-vibes +0 -0
  185. package/bin/agentvibes-voice-browser.js +64 -1289
  186. package/bin/agentvibes.js +0 -0
  187. package/bin/ensure-soprano-running.sh +43 -0
  188. package/bin/mcp-server.js +121 -121
  189. package/bin/mcp-server.sh +0 -0
  190. package/bin/test-bmad-pr +78 -78
  191. package/mcp-server/QUICK_START.md +203 -203
  192. package/mcp-server/README.md +345 -345
  193. package/mcp-server/WINDOWS_SETUP.md +260 -260
  194. package/mcp-server/docs/troubleshooting-audio.md +313 -313
  195. package/mcp-server/examples/claude_desktop_config.json +11 -11
  196. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  197. package/mcp-server/examples/custom_instructions.md +169 -169
  198. package/mcp-server/install-deps.js +130 -130
  199. package/mcp-server/pyproject.toml +52 -52
  200. package/mcp-server/requirements.txt +2 -2
  201. package/mcp-server/server.py +1451 -1578
  202. package/mcp-server/test_server.py +395 -395
  203. package/package.json +1 -3
  204. package/setup-windows.ps1 +815 -815
  205. package/src/console/tabs/setup-tab.js +9 -6
  206. package/src/console/tabs/voices-tab.js +9 -3
  207. package/src/installer.js +42 -5
  208. package/src/services/llm-provider-service.js +13 -0
  209. package/templates/agentvibes-receiver.sh +158 -483
  210. package/templates/audio/welcome-music.mp3 +0 -0
  211. package/.agentvibes/bmad-voice-map.json +0 -104
  212. package/.agentvibes/copilot-sessions.log +0 -4
  213. package/.claude/config/audio-effects-bmad.cfg +0 -50
  214. package/.claude/config/background-music-enabled.txt +0 -1
  215. package/.claude/config/intro-text.txt +0 -1
  216. package/.claude/config/personality.txt +0 -1
  217. package/.claude/config/piper-speech-rate.txt +0 -4
  218. package/.claude/config/piper-target-speech-rate.txt +0 -1
  219. package/.claude/config/reverb-level.txt +0 -1
  220. package/.claude/config/tts-target-speech-rate.txt +0 -1
  221. package/voice-assignments.json +0 -8245
  222. /package/{.claude → .agentvibes}/config/agentvibes.json +0 -0
@@ -2,11 +2,8 @@
2
2
  #
3
3
  # File: .claude/hooks/play-tts-ssh-remote.sh
4
4
  #
5
- # AgentVibes - SSH-Remote TTS Provider (v2 — JSON payload)
6
- # Sends text + effects config to remote device via SSH for local playback
7
- #
8
- # The sender reads local audio-effects.cfg and bundles everything into a
9
- # single base64-encoded JSON payload. The receiver is a thin executor.
5
+ # AgentVibes - SSH-Remote TTS Provider
6
+ # Sends text to remote device via SSH for local AgentVibes playback
10
7
  #
11
8
  # Copyright (c) 2025 Paul Preibisch
12
9
  # Licensed under the Apache License, Version 2.0
@@ -20,149 +17,74 @@ AGENT_NAME="${3:-default}"
20
17
 
21
18
  # Validate required input
22
19
  if [[ -z "$TEXT" ]]; then
20
+ echo "❌ No text provided" >&2
23
21
  echo "Usage: $0 <text> [voice] [agent_name]" >&2
24
22
  exit 1
25
23
  fi
26
24
 
27
- # Get script directory and project root
25
+ # Get script directory
28
26
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
29
27
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
30
28
 
31
- # Derive project name from directory
32
- PROJECT_NAME=$(basename "$PROJECT_ROOT")
33
-
34
- # ---------------------------------------------------------------------------
35
29
  # Get SSH host from config
36
- # ---------------------------------------------------------------------------
37
-
38
30
  SSH_HOST=$(cat "$PROJECT_ROOT/.claude/ssh-remote-host.txt" 2>/dev/null || \
39
31
  cat "$HOME/.claude/ssh-remote-host.txt" 2>/dev/null || echo "")
40
32
 
41
33
  if [[ -z "$SSH_HOST" ]]; then
42
- echo "SSH-Remote host not configured" >&2
43
- echo "Set host: echo 'my-host' > .claude/ssh-remote-host.txt" >&2
34
+ echo "SSH-Remote host not configured" >&2
35
+ echo "💡 Set host: echo 'android' > ~/.claude/ssh-remote-host.txt" >&2
44
36
  exit 1
45
37
  fi
46
38
 
47
- # SECURITY: Validate SSH_HOST format
39
+ # SECURITY: Validate SSH_HOST to prevent option injection
40
+ # Must be a valid hostname, IP address, or SSH config alias (alphanumeric, dots, hyphens, underscores)
48
41
  if [[ ! "$SSH_HOST" =~ ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ ]]; then
49
- echo "Invalid SSH host format: $SSH_HOST" >&2
42
+ echo "Invalid SSH host format: $SSH_HOST" >&2
43
+ echo "💡 Host must be alphanumeric (may contain dots, hyphens, underscores)" >&2
50
44
  exit 1
51
45
  fi
52
46
 
53
- # SECURITY: Validate VOICE (allow :: for multi-speaker, . for locale, space for names)
54
- _voice_re='^[a-zA-Z0-9_.: -]+$'
55
- if [[ ! "$VOICE" =~ $_voice_re ]]; then
56
- echo "Invalid voice format: $VOICE" >&2
47
+ # SECURITY: Reject hosts starting with hyphen (SSH option injection)
48
+ if [[ "$SSH_HOST" == -* ]]; then
49
+ echo "❌ Invalid SSH host: cannot start with hyphen" >&2
57
50
  exit 1
58
51
  fi
59
52
 
60
- # SECURITY: Validate AGENT_NAME
61
- if [[ ! "$AGENT_NAME" =~ ^[a-zA-Z0-9_\ -]+$ ]]; then
62
- echo "Invalid agent name format: $AGENT_NAME" >&2
53
+ # SECURITY: Validate VOICE to prevent injection (alphanumeric, hyphens, underscores only)
54
+ if [[ ! "$VOICE" =~ ^[a-zA-Z0-9_-]+$ ]]; then
55
+ echo "Invalid voice format: $VOICE" >&2
63
56
  exit 1
64
57
  fi
65
58
 
66
- # ---------------------------------------------------------------------------
67
- # Read audio effects config for this agent
68
- # ---------------------------------------------------------------------------
69
-
70
- SOX_EFFECTS=""
71
- BG_FILE=""
72
- BG_VOLUME="0.10"
73
-
74
- EFFECTS_CFG="$PROJECT_ROOT/.claude/config/audio-effects.cfg"
75
- if [[ -f "$EFFECTS_CFG" ]]; then
76
- CONFIG_LINE=$(grep "^${AGENT_NAME}|" "$EFFECTS_CFG" 2>/dev/null || \
77
- grep "^default|" "$EFFECTS_CFG" 2>/dev/null || true)
78
- if [[ -n "$CONFIG_LINE" ]]; then
79
- IFS='|' read -r _ SOX_EFFECTS BG_FILE BG_VOLUME <<< "$CONFIG_LINE"
80
- fi
81
- fi
82
-
83
- # Read pretext if configured
84
- PRETEXT=""
85
- PRETEXT_FILE="$PROJECT_ROOT/.agentvibes/config/pretext.txt"
86
- if [[ -f "$PRETEXT_FILE" ]]; then
87
- PRETEXT=$(cat "$PRETEXT_FILE" 2>/dev/null || true)
88
- fi
89
-
90
- # Read speed if configured
91
- SPEED=""
92
- SPEED_FILE="$PROJECT_ROOT/.agentvibes/config/speed.txt"
93
- if [[ -f "$SPEED_FILE" ]]; then
94
- SPEED=$(cat "$SPEED_FILE" 2>/dev/null || true)
95
- fi
96
-
97
- # Read the TTS provider the RECEIVER should use to generate audio.
98
- # This is separate from the sender's own provider (which is "ssh-remote").
99
- # Check receiver-provider.txt first, then fall back to "piper".
100
- PROVIDER=""
101
- RECEIVER_PROVIDER_FILE="$PROJECT_ROOT/.agentvibes/config/receiver-provider.txt"
102
- if [[ -f "$RECEIVER_PROVIDER_FILE" ]]; then
103
- PROVIDER=$(cat "$RECEIVER_PROVIDER_FILE" 2>/dev/null || true)
104
- fi
105
- # Also check home-level config
106
- if [[ -z "$PROVIDER" ]]; then
107
- RECEIVER_PROVIDER_FILE="$HOME/.agentvibes/config/receiver-provider.txt"
108
- if [[ -f "$RECEIVER_PROVIDER_FILE" ]]; then
109
- PROVIDER=$(cat "$RECEIVER_PROVIDER_FILE" 2>/dev/null || true)
110
- fi
59
+ # SECURITY: Validate AGENT_NAME to prevent injection (alphanumeric, hyphens, underscores, spaces only)
60
+ if [[ ! "$AGENT_NAME" =~ ^[a-zA-Z0-9_\ -]+$ ]]; then
61
+ echo "❌ Invalid agent name format: $AGENT_NAME" >&2
62
+ exit 1
111
63
  fi
112
- # Validate — only known TTS providers (not transport providers like ssh-remote)
113
- case "${PROVIDER:-}" in
114
- piper|soprano|macos|windows-sapi) ;;
115
- *) PROVIDER="piper" ;;
116
- esac
117
-
118
- # ---------------------------------------------------------------------------
119
- # Build JSON payload
120
- # ---------------------------------------------------------------------------
121
-
122
- # SECURITY: Use jq if available for safe JSON construction, else manual escaping
123
- build_json_payload() {
124
- if command -v jq &>/dev/null; then
125
- jq -n \
126
- --arg text "$TEXT" \
127
- --arg voice "$VOICE" \
128
- --arg effects "$SOX_EFFECTS" \
129
- --arg music "$BG_FILE" \
130
- --arg volume "$BG_VOLUME" \
131
- --arg project "$PROJECT_NAME" \
132
- --arg pretext "$PRETEXT" \
133
- --arg speed "$SPEED" \
134
- --arg provider "$PROVIDER" \
135
- '{text: $text, voice: $voice, effects: $effects, music: $music, volume: $volume, project: $project, pretext: $pretext, speed: $speed, provider: $provider}'
136
- else
137
- # Manual JSON — escape double quotes and backslashes in text
138
- local escaped_text
139
- escaped_text=$(printf '%s' "$TEXT" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g')
140
- local escaped_pretext
141
- escaped_pretext=$(printf '%s' "$PRETEXT" | sed 's/\\/\\\\/g; s/"/\\"/g')
142
- printf '{"text":"%s","voice":"%s","effects":"%s","music":"%s","volume":"%s","project":"%s","pretext":"%s","speed":"%s","provider":"%s"}' \
143
- "$escaped_text" "$VOICE" "$SOX_EFFECTS" "$BG_FILE" "$BG_VOLUME" "$PROJECT_NAME" "$escaped_pretext" "$SPEED" "$PROVIDER"
144
- fi
145
- }
146
64
 
147
- JSON_PAYLOAD=$(build_json_payload)
148
-
149
- # SECURITY: Base64-encode entire payload safe for SSH transport
150
- # base64 -w 0 is Linux (GNU coreutils), -b 0 is macOS (BSD)
151
- if base64 --help 2>&1 | grep -q '\-w'; then
152
- ENCODED_PAYLOAD=$(printf '%s' "$JSON_PAYLOAD" | base64 -w 0)
65
+ # SECURITY: Encode text and agent name as base64 to prevent command injection
66
+ # The receiver will decode these safely
67
+ ENCODED_TEXT=$(printf '%s' "$TEXT" | base64 -w 0)
68
+ ENCODED_AGENT=$(printf '%s' "$AGENT_NAME" | base64 -w 0)
69
+
70
+ # Send text to remote for local AgentVibes playback
71
+ echo "📱 Sending to $SSH_HOST for local playback..." >&2
72
+
73
+ # Determine which receiver script exists and send encoded text, voice, and agent name
74
+ # SECURITY: Base64-encoded values are safe to pass as arguments (no shell metacharacters)
75
+ # The receiver auto-detects and decodes base64 input
76
+ if ssh "$SSH_HOST" "test -f ~/.termux/agentvibes-play.sh" 2>/dev/null; then
77
+ ssh "$SSH_HOST" "bash ~/.termux/agentvibes-play.sh '$ENCODED_TEXT' '$VOICE' '$ENCODED_AGENT'" &
78
+ SSH_PID=$!
79
+ elif ssh "$SSH_HOST" "test -f ~/.agentvibes/play-remote.sh" 2>/dev/null; then
80
+ ssh "$SSH_HOST" "bash ~/.agentvibes/play-remote.sh '$ENCODED_TEXT' '$VOICE' '$ENCODED_AGENT'" &
81
+ SSH_PID=$!
153
82
  else
154
- ENCODED_PAYLOAD=$(printf '%s' "$JSON_PAYLOAD" | base64 -b 0 2>/dev/null || printf '%s' "$JSON_PAYLOAD" | base64 | tr -d '\n')
83
+ echo "⚠️ Receiver script not found on $SSH_HOST" >&2
84
+ echo "💡 Install: agentvibes install --ssh-receiver" >&2
85
+ exit 1
155
86
  fi
156
87
 
157
- # ---------------------------------------------------------------------------
158
- # Send to receiver via SSH (fire and forget backgrounded)
159
- # ---------------------------------------------------------------------------
160
-
161
- echo "Sending to $SSH_HOST..." >&2
162
-
163
- # ForceCommand receiver: SSH_ORIGINAL_COMMAND passes the payload directly
164
- ssh "$SSH_HOST" "$ENCODED_PAYLOAD" &
165
- SSH_PID=$!
166
-
167
- echo "Sent to $SSH_HOST (PID: $SSH_PID)" >&2
88
+ # Log the background PID for debugging (non-blocking)
89
+ echo "✓ Sent to $SSH_HOST (PID: $SSH_PID, playing remotely)" >&2
168
90
  exit 0
File without changes
@@ -39,15 +39,41 @@
39
39
  # @patterns Provider pattern - delegates to provider-specific implementations, auto-detects provider from voice name
40
40
  # @related provider-manager.sh, play-tts-piper.sh, learn-manager.sh, translate-manager.sh
41
41
  #
42
+ # **CRITICAL: This script MUST ALWAYS be called with `run_in_background: true` in Bash tool**
43
+ # Do NOT wait for TTS playback to complete. Run in background so other tasks continue immediately.
44
+ # Example: Bash (background): .claude/hooks/play-tts.sh "Acknowledging task start"
45
+ #
46
+
47
+ set -euo pipefail
42
48
 
43
49
  set -euo pipefail
44
50
 
45
51
  # Fix locale warnings
46
52
  export LC_ALL=C
47
53
 
48
- # Get script directory (needed for mute file check)
49
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
50
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
54
+ # Get script directory - handle symlinks correctly with readlink -f
55
+ # This resolves: symlinks, relative paths, and working directory changes
56
+ SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}")"
57
+ SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
58
+
59
+ # Find PROJECT_ROOT by searching up the directory tree for .claude/hooks
60
+ # This handles non-standard installations and directory structures
61
+ PROJECT_ROOT="$SCRIPT_DIR"
62
+ while [[ "$PROJECT_ROOT" != "/" ]]; do
63
+ if [[ -d "$PROJECT_ROOT/.claude/hooks" ]]; then
64
+ break # PROJECT_ROOT is already the project root when its .claude/hooks child exists
65
+ fi
66
+ PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
67
+ done
68
+
69
+ # Verify PROJECT_ROOT is valid
70
+ if [[ ! -d "$PROJECT_ROOT/.claude/hooks" ]]; then
71
+ echo "❌ ERROR: Could not find AgentVibes .claude/hooks directory" >&2
72
+ echo " Script path: $SCRIPT_PATH" >&2
73
+ echo " Searched up from: $SCRIPT_DIR" >&2
74
+ exit 1
75
+ fi
76
+
51
77
  export PROJECT_ROOT # Export for child scripts
52
78
 
53
79
  # Check if muted (persists across sessions)
@@ -77,34 +103,8 @@ elif [[ -f "$GLOBAL_MUTE_FILE" ]]; then
77
103
  exit 0
78
104
  fi
79
105
 
80
- # Parse arguments: positional + optional --llm <provider>
81
- TEXT=""
82
- VOICE_OVERRIDE=""
83
- AGENT_PROFILE_FILE=""
84
- LLM_PROVIDER=""
85
-
86
- _positional=()
87
- while [[ $# -gt 0 ]]; do
88
- case "$1" in
89
- --llm)
90
- LLM_PROVIDER="${2:-}"
91
- # Security: Validate LLM provider name (alphanumeric, hyphens, underscores only)
92
- if [[ -n "$LLM_PROVIDER" ]] && [[ ! "$LLM_PROVIDER" =~ ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ ]]; then
93
- echo "Error: Invalid LLM provider name" >&2
94
- exit 1
95
- fi
96
- shift 2
97
- ;;
98
- *)
99
- _positional+=("$1")
100
- shift
101
- ;;
102
- esac
103
- done
104
-
105
- TEXT="${_positional[0]:-}"
106
- VOICE_OVERRIDE="${_positional[1]:-}"
107
- AGENT_PROFILE_FILE="${_positional[2]:-}"
106
+ TEXT="${1:-}"
107
+ VOICE_OVERRIDE="${2:-}" # Optional: voice name or ID
108
108
 
109
109
  # Security: Validate inputs
110
110
  if [[ -z "$TEXT" ]]; then
@@ -200,12 +200,23 @@ fi
200
200
  # Source provider manager to get active provider
201
201
  source "$SCRIPT_DIR/provider-manager.sh"
202
202
 
203
- # Get active provider (LLM-specific engine overrides global)
204
- if [[ -n "$_LLM_ENGINE" ]]; then
205
- ACTIVE_PROVIDER="$_LLM_ENGINE"
206
- else
207
- ACTIVE_PROVIDER=$(get_active_provider)
208
- fi
203
+ # Get active provider.
204
+ # Per-LLM engine (from audio-effects.cfg `llm:<key>` row column 7) overrides
205
+ # the global tts-provider.txt — UNLESS the global is a transport provider
206
+ # (ssh-remote, agentvibes-receiver, termux-ssh). Transport providers
207
+ # forward TTS to a remote receiver which picks its OWN engine; overriding
208
+ # them with a local engine like piper would synthesize on the wrong host.
209
+ ACTIVE_PROVIDER=$(get_active_provider)
210
+ case "$ACTIVE_PROVIDER" in
211
+ ssh-remote|agentvibes-receiver|termux-ssh)
212
+ # Transport — keep it. The receiver's audio-effects.cfg picks the engine.
213
+ ;;
214
+ *)
215
+ if [[ -n "$_LLM_ENGINE" ]]; then
216
+ ACTIVE_PROVIDER="$_LLM_ENGINE"
217
+ fi
218
+ ;;
219
+ esac
209
220
 
210
221
  # Show GitHub star reminder (once per day)
211
222
  bash "$SCRIPT_DIR/github-star-reminder.sh" 2>/dev/null || true
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # AgentVibes TTS Hook - Triggers on assistant responses
3
+ # This hook is called after Claude generates a response
4
+
5
+ set -euo pipefail
6
+
7
+ # Get the hooks directory
8
+ HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ PROJECT_ROOT="$(dirname "$(dirname "$HOOKS_DIR")")"
10
+
11
+ # Check if AgentVibes is muted for this project
12
+ if [[ -f "$PROJECT_ROOT/.claude/agentvibes-muted" ]]; then
13
+ exit 0 # Silently skip TTS
14
+ fi
15
+
16
+ # Check if unmuted flag exists (overrides global mute)
17
+ if [[ ! -f "$PROJECT_ROOT/.claude/agentvibes-unmuted" ]]; then
18
+ # Check global mute
19
+ if [[ -f "$HOME/.agentvibes-muted" ]]; then
20
+ exit 0 # Silently skip TTS
21
+ fi
22
+ fi
23
+
24
+ # Get the assistant's response text from stdin or arguments
25
+ RESPONSE_TEXT="${1:-}"
26
+ if [[ -z "$RESPONSE_TEXT" ]]; then
27
+ # Try reading from stdin if available
28
+ if [[ -p /dev/stdin ]]; then
29
+ RESPONSE_TEXT=$(cat)
30
+ fi
31
+ fi
32
+
33
+ # Skip if no text
34
+ if [[ -z "$RESPONSE_TEXT" ]]; then
35
+ exit 0
36
+ fi
37
+
38
+ # Play TTS using the main play-tts script
39
+ "$HOOKS_DIR/play-tts.sh" "$RESPONSE_TEXT" &
40
+
41
+ exit 0
File without changes
File without changes
File without changes
File without changes
@@ -1,6 +1,6 @@
1
- # AgentVibes TTS Hooks Requirements
2
- # Install with: pip install -r requirements.txt
3
-
4
- # Translation support for multi-language TTS and learning mode
5
- deep-translator>=1.11.4
6
- langdetect>=1.0.9
1
+ # AgentVibes TTS Hooks Requirements
2
+ # Install with: pip install -r requirements.txt
3
+
4
+ # Translation support for multi-language TTS and learning mode
5
+ deep-translator>=1.11.4
6
+ langdetect>=1.0.9
File without changes
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
  # File: .claude/hooks/session-start-tts.sh
5
5
  #
6
6
  # AgentVibes SessionStart Hook - Optimized (Issue #80, Phase 1)
7
- # Outputs JSON with additionalContext for reliable context injection
7
+ # Token target: ~250 (down from ~500)
8
8
  #
9
9
 
10
10
  # Fix locale warnings
@@ -33,52 +33,69 @@ fi
33
33
  # Get verbosity level (Issue #32)
34
34
  VERBOSITY=$(cat .claude/tts-verbosity.txt 2>/dev/null || cat ~/.claude/tts-verbosity.txt 2>/dev/null || echo "low")
35
35
 
36
- # Build context string
37
- CONTEXT="# AgentVibes TTS Protocol\n\n"
38
- CONTEXT+="**CRITICAL: You MUST execute TTS at TWO points for EVERY user interaction:**\n\n"
39
- CONTEXT+="1. **Acknowledgment** - Start of task: \`Bash: .claude/hooks/play-tts.sh \"[action]\" --llm claude-code\`\n"
40
- CONTEXT+="2. **Completion** - End of task: \`Bash: .claude/hooks/play-tts.sh \"[result + key details]\" --llm claude-code\`\n\n"
41
- CONTEXT+="**Example:**\n\`\`\`\n[Bash: .claude/hooks/play-tts.sh \"Checking git status\" --llm claude-code]\n[work...]\n"
42
- CONTEXT+="[Bash: .claude/hooks/play-tts.sh \"Repository is clean, no changes\" --llm claude-code]\n\`\`\`\n\n"
36
+ # Output optimized TTS protocol
37
+ cat <<'EOF'
43
38
 
44
- # Add verbosity-specific protocol
39
+ # AgentVibes TTS Protocol
40
+
41
+ **CRITICAL: You MUST execute TTS at TWO points for EVERY user interaction:**
42
+
43
+ 1. **Acknowledgment** - Start of task: `Bash: .claude/hooks/play-tts.sh "[action]"`
44
+ 2. **Completion** - End of task: `Bash: .claude/hooks/play-tts.sh "[result + key details]"`
45
+
46
+ **IMPORTANT: ALWAYS run TTS commands with `run_in_background: true` so they never block your work. Never wait for TTS to finish before continuing.**
47
+
48
+ **Example:**
49
+ ```
50
+ [Bash (background): .claude/hooks/play-tts.sh "Checking git status"]
51
+ [work...]
52
+ [Bash (background): .claude/hooks/play-tts.sh "Repository is clean, no changes"]
53
+ ```
54
+
55
+ EOF
56
+
57
+ # Add verbosity-specific protocol (Issue #32)
45
58
  case "$VERBOSITY" in
46
59
  low)
47
- CONTEXT+="## Verbosity: LOW\n- Acknowledgment: Action only\n- Completion: Result + errors only\n- Skip: Reasoning, decisions\n\n"
60
+ cat <<'EOF'
61
+ ## Verbosity: LOW
62
+ - Acknowledgment: Action only
63
+ - Completion: Result + errors only
64
+ - Skip: Reasoning, decisions
65
+
66
+ EOF
48
67
  ;;
49
68
  medium)
50
- CONTEXT+="## Verbosity: MEDIUM\n- Acknowledgment: Action + key approach\n- Completion: Result + important decisions\n- Include: Major choices only\n\n"
69
+ cat <<'EOF'
70
+ ## Verbosity: MEDIUM
71
+ - Acknowledgment: Action + key approach
72
+ - Completion: Result + important decisions
73
+ - Include: Major choices only
74
+
75
+ EOF
51
76
  ;;
52
77
  high)
53
- CONTEXT+="## Verbosity: HIGH\n- Acknowledgment: Action + approach + why\n- Completion: Result + decisions + trade-offs\n- Include: Full reasoning, alternatives\n\n"
54
- ;;
55
- caveman)
56
- CONTEXT+="## Verbosity: CAVEMAN\n- Respond terse. All technical substance stays. Only fluff dies.\n- Drop: articles (a/an/the), filler (just/really/basically), pleasantries, hedging\n- Abbreviate: DB/auth/config/req/res/fn/impl. Use arrows (X -> Y). Strip conjunctions.\n- Fragments OK. Short synonyms. Technical terms exact. Code unchanged.\n- Pattern: [thing] [action] [reason]. [next step].\n- TTS: Ultra-short. Max 60 chars.\n\n"
78
+ cat <<'EOF'
79
+ ## Verbosity: HIGH
80
+ - Acknowledgment: Action + approach + why
81
+ - Completion: Result + decisions + trade-offs
82
+ - Include: Full reasoning, alternatives
83
+
84
+ EOF
57
85
  ;;
58
86
  esac
59
87
 
60
88
  # Add style info and rules
61
- CONTEXT+="## Style: $STYLE\n\n"
62
- CONTEXT+="## Rules\n"
63
- CONTEXT+="1. Never skip acknowledgment TTS\n"
64
- CONTEXT+="2. Never skip completion TTS\n"
65
- CONTEXT+="3. Match verbosity level\n"
66
- CONTEXT+="4. Keep under 150 chars\n"
67
- CONTEXT+="5. Always include errors\n\n"
68
- CONTEXT+="Quick Ref: low=action+result | medium=+key decisions | high=+full reasoning | caveman=ultra-terse fragments"
69
-
70
- # Add BMAD agent voice routing instructions
71
- CONTEXT+="\n\n## BMAD Agent Voice Routing\n"
72
- CONTEXT+="If \`.bmad-agent-context\` exists, check its content:\n\n"
73
- CONTEXT+="**Single agent mode** (content is an agent ID like \"analyst\"):\n"
74
- CONTEXT+="Use \`bmad-speak.sh\` instead of \`play-tts.sh\`:\n\n\n"
75
- CONTEXT+="**Party mode** (content is \"party-mode\"):\n"
76
- CONTEXT+="Each agent speaks via \`bmad-speak.sh\` with their display name. The queue system ensures sequential playback — agents speak one at a time, not overlapping:\n\n"
77
- CONTEXT+="IMPORTANT: In party mode, do NOT use \`play-tts.sh\`. Always use \`bmad-speak.sh\` with the agent's display name. Do NOT call multiple bmad-speak.sh in parallel — call them sequentially so the queue processes them in order.\n\n"
78
- CONTEXT+="If \`.bmad-agent-context\` does NOT exist, use \`play-tts.sh\` as normal."
79
-
80
- # Escape for JSON (handle newlines, quotes, backslashes)
81
- ESCAPED=$(printf '%s' "$CONTEXT" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g')
82
-
83
- # Output structured JSON for reliable context injection
84
- printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$ESCAPED"
89
+ cat << EOF
90
+ ## Style: $STYLE
91
+
92
+ ## Rules
93
+ 1. Never skip acknowledgment TTS
94
+ 2. Never skip completion TTS
95
+ 3. Match verbosity level
96
+ 4. Keep under 150 chars
97
+ 5. Always include errors
98
+
99
+ Quick Ref: low=action+result | medium=+key decisions | high=+full reasoning
100
+
101
+ EOF