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
@@ -14,13 +14,63 @@
14
14
 
15
15
  set -euo pipefail
16
16
 
17
- TEXT="${1:-}"
18
- VOICE="${2:-en_US-lessac-medium}"
19
- AGENT_NAME="${3:-default}"
17
+ # ---------------------------------------------------------------------------
18
+ # Argument parsing — supports both positional (backward compat) and flags.
19
+ #
20
+ # Positional (legacy):
21
+ # play-tts-ssh-remote.sh "text" [voice] [agent_name]
22
+ #
23
+ # Flag-based (full per-call control):
24
+ # play-tts-ssh-remote.sh --text "hello" --voice "en_US-ryan-high" \
25
+ # --pretext "Winston here" --music "track.mp3" \
26
+ # --volume 0.25 --effects "reverb 40 60 80" \
27
+ # --speed 1.1 --provider piper --agent "winston"
28
+ #
29
+ # Flags override config-file values. Any flag omitted → falls back to config.
30
+ # --pretext "" (empty string) explicitly suppresses pretext (no fallback).
31
+ # ---------------------------------------------------------------------------
32
+
33
+ TEXT=""
34
+ VOICE=""
35
+ AGENT_NAME=""
36
+ PRETEXT_OVERRIDE=""
37
+ PRETEXT_SET=0 # whether --pretext was explicitly provided
38
+ MUSIC_OVERRIDE=""
39
+ VOLUME_OVERRIDE=""
40
+ EFFECTS_OVERRIDE=""
41
+ SPEED_OVERRIDE=""
42
+ PROVIDER_OVERRIDE=""
43
+
44
+ # Detect flag-based vs positional usage: if first arg starts with --, use flags.
45
+ if [[ "${1:-}" == --* ]]; then
46
+ while [[ $# -gt 0 ]]; do
47
+ case "$1" in
48
+ --text) TEXT="${2:-}"; shift 2 ;;
49
+ --voice) VOICE="${2:-}"; shift 2 ;;
50
+ --agent) AGENT_NAME="${2:-}"; shift 2 ;;
51
+ --pretext) PRETEXT_OVERRIDE="${2:-}"; PRETEXT_SET=1; shift 2 ;;
52
+ --music) MUSIC_OVERRIDE="${2:-}"; shift 2 ;;
53
+ --volume) VOLUME_OVERRIDE="${2:-}"; shift 2 ;;
54
+ --effects) EFFECTS_OVERRIDE="${2:-}"; shift 2 ;;
55
+ --speed) SPEED_OVERRIDE="${2:-}"; shift 2 ;;
56
+ --provider) PROVIDER_OVERRIDE="${2:-}"; shift 2 ;;
57
+ *) echo "Unknown flag: $1" >&2; exit 1 ;;
58
+ esac
59
+ done
60
+ else
61
+ TEXT="${1:-}"
62
+ VOICE="${2:-}"
63
+ AGENT_NAME="${3:-}"
64
+ fi
65
+
66
+ # Defaults for still-empty values
67
+ VOICE="${VOICE:-en_US-lessac-medium}"
68
+ AGENT_NAME="${AGENT_NAME:-default}"
20
69
 
21
70
  # Validate required input
22
71
  if [[ -z "$TEXT" ]]; then
23
- echo "Usage: $0 <text> [voice] [agent_name]" >&2
72
+ echo "Usage (positional): $0 <text> [voice] [agent_name]" >&2
73
+ echo "Usage (flags): $0 --text <text> [--voice X --pretext Y --music Z --volume N --effects E --speed S --provider P --agent A]" >&2
24
74
  exit 1
25
75
  fi
26
76
 
@@ -115,6 +165,49 @@ case "${PROVIDER:-}" in
115
165
  *) PROVIDER="piper" ;;
116
166
  esac
117
167
 
168
+ # ---------------------------------------------------------------------------
169
+ # Apply CLI flag overrides (flags win over config files)
170
+ # ---------------------------------------------------------------------------
171
+ # Validate effects (prevent injection — only alphanumeric, spaces, dots, hyphens)
172
+ if [[ -n "$EFFECTS_OVERRIDE" ]]; then
173
+ if [[ "$EFFECTS_OVERRIDE" =~ ^[a-zA-Z0-9\ ._-]+$ ]]; then
174
+ SOX_EFFECTS="$EFFECTS_OVERRIDE"
175
+ else
176
+ echo "Invalid effects format: $EFFECTS_OVERRIDE (alphanumeric/space/.-_ only)" >&2
177
+ exit 1
178
+ fi
179
+ fi
180
+ [[ -n "$MUSIC_OVERRIDE" ]] && BG_FILE="$MUSIC_OVERRIDE"
181
+ [[ -n "$VOLUME_OVERRIDE" ]] && BG_VOLUME="$VOLUME_OVERRIDE"
182
+ [[ -n "$SPEED_OVERRIDE" ]] && SPEED="$SPEED_OVERRIDE"
183
+ [[ -n "$PROVIDER_OVERRIDE" ]] && PROVIDER="$PROVIDER_OVERRIDE"
184
+ # Pretext: explicit --pretext wins even when empty string (suppresses pretext)
185
+ if [[ "$PRETEXT_SET" == "1" ]]; then
186
+ PRETEXT="$PRETEXT_OVERRIDE"
187
+ fi
188
+
189
+ # Re-validate provider after override (in case user passed bad value)
190
+ case "${PROVIDER:-}" in
191
+ piper|soprano|macos|windows-sapi) ;;
192
+ *) PROVIDER="piper" ;;
193
+ esac
194
+ # Validate music filename (prevent path injection through JSON → receiver)
195
+ # Allows spaces in track names like "Late Night Hip Hop Groove.mp3"
196
+ if [[ -n "$BG_FILE" && ! "$BG_FILE" =~ ^[a-zA-Z0-9_\.\ -]+$ ]]; then
197
+ echo "Invalid music filename format: $BG_FILE (alphanumeric/space/.-_ only)" >&2
198
+ exit 1
199
+ fi
200
+ # Validate volume
201
+ if [[ -n "$BG_VOLUME" && ! "$BG_VOLUME" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
202
+ echo "Invalid volume: $BG_VOLUME (numeric only)" >&2
203
+ exit 1
204
+ fi
205
+ # Validate speed
206
+ if [[ -n "$SPEED" && ! "$SPEED" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
207
+ echo "Invalid speed: $SPEED (numeric only)" >&2
208
+ exit 1
209
+ fi
210
+
118
211
  # ---------------------------------------------------------------------------
119
212
  # Build JSON payload
120
213
  # ---------------------------------------------------------------------------
@@ -134,13 +227,14 @@ build_json_payload() {
134
227
  --arg provider "$PROVIDER" \
135
228
  '{text: $text, voice: $voice, effects: $effects, music: $music, volume: $volume, project: $project, pretext: $pretext, speed: $speed, provider: $provider}'
136
229
  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')
230
+ # Manual JSON — escape all interpolated fields (backslash, double-quote, newline, tab)
231
+ _esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' ' '; }
232
+ local e_text e_voice e_effects e_music e_vol e_proj e_pre e_spd e_prov
233
+ e_text=$(_esc "$TEXT"); e_voice=$(_esc "$VOICE"); e_effects=$(_esc "$SOX_EFFECTS")
234
+ e_music=$(_esc "$BG_FILE"); e_vol=$(_esc "$BG_VOLUME"); e_proj=$(_esc "$PROJECT_NAME")
235
+ e_pre=$(_esc "$PRETEXT"); e_spd=$(_esc "$SPEED"); e_prov=$(_esc "$PROVIDER")
142
236
  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"
237
+ "$e_text" "$e_voice" "$e_effects" "$e_music" "$e_vol" "$e_proj" "$e_pre" "$e_spd" "$e_prov"
144
238
  fi
145
239
  }
146
240
 
@@ -1,169 +1,169 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/play-tts-termux-ssh.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. Use at your own risk. See the Apache License for details.
26
- #
27
- # ---
28
- #
29
- # @fileoverview Termux SSH TTS Provider - Android TTS via SSH tunnel
30
- # @context Enables TTS output on Android devices when connected via SSH from Termux
31
- # @architecture SSH-based remote TTS invocation using termux-tts-speak on Android
32
- # @dependencies ssh, termux-tts-speak (on Android), termux-api (on Android)
33
- # @entrypoints Called by play-tts.sh router when provider=termux-ssh
34
- # @patterns Remote TTS invocation, SSH host alias configuration, graceful fallback
35
- # @related play-tts.sh, provider-manager.sh
36
- # @setup Requires user to configure SSH host alias in ~/.ssh/config
37
- #
38
- # SETUP INSTRUCTIONS:
39
- # ===================
40
- # 1. On Android device (Termux):
41
- # - Install: pkg install termux-api openssh
42
- # - Install Termux:API app from F-Droid
43
- # - Start SSH server: sshd
44
- # - Get SSH port: echo $PREFIX/var/run/sshd.pid
45
- #
46
- # 2. On server/desktop:
47
- # - Add to ~/.ssh/config:
48
- # Host android
49
- # HostName <your-android-ip>
50
- # User <your-termux-username>
51
- # Port 8022
52
- # IdentityFile ~/.ssh/id_rsa
53
- #
54
- # 3. Configure AgentVibes:
55
- # - echo "android" > ~/.claude/termux-ssh-host.txt
56
- # OR
57
- # - export TERMUX_SSH_HOST="android"
58
- #
59
- # 4. Set provider:
60
- # - echo "termux-ssh" > ~/.claude/tts-provider.txt
61
- #
62
-
63
- # Fix locale warnings
64
- export LC_ALL=C
65
-
66
- TEXT="$1"
67
- VOICE_OVERRIDE="$2" # Not used for termux-ssh, but kept for interface compatibility
68
-
69
- # Script directory
70
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
71
-
72
- # @function get_ssh_host
73
- # @intent Determine SSH host alias for Android device
74
- # @why Allows users to configure their own SSH connection without hardcoded values
75
- # @returns Echoes SSH host alias or empty string if not configured
76
- # @sideeffects None
77
- get_ssh_host() {
78
- local ssh_host=""
79
-
80
- # Priority order:
81
- # 1. Environment variable TERMUX_SSH_HOST
82
- # 2. Project-specific config file (CLAUDE_PROJECT_DIR)
83
- # 3. Script location config file
84
- # 4. Global config file (~/.claude/termux-ssh-host.txt)
85
-
86
- if [[ -n "$TERMUX_SSH_HOST" ]]; then
87
- ssh_host="$TERMUX_SSH_HOST"
88
- elif [[ -n "$CLAUDE_PROJECT_DIR" ]] && [[ -f "$CLAUDE_PROJECT_DIR/.claude/termux-ssh-host.txt" ]]; then
89
- ssh_host=$(cat "$CLAUDE_PROJECT_DIR/.claude/termux-ssh-host.txt" 2>/dev/null | tr -d '\n\r')
90
- elif [[ -f "$SCRIPT_DIR/../termux-ssh-host.txt" ]]; then
91
- ssh_host=$(cat "$SCRIPT_DIR/../termux-ssh-host.txt" 2>/dev/null | tr -d '\n\r')
92
- elif [[ -f "$HOME/.claude/termux-ssh-host.txt" ]]; then
93
- ssh_host=$(cat "$HOME/.claude/termux-ssh-host.txt" 2>/dev/null | tr -d '\n\r')
94
- fi
95
-
96
- echo "$ssh_host"
97
- }
98
-
99
- # @function check_termux_connection
100
- # @intent Verify SSH connection to Android device is available
101
- # @why Prevent hanging on SSH timeout if device is unreachable
102
- # @param $1 SSH host alias
103
- # @returns 0 if connection successful, 1 otherwise
104
- # @sideeffects None (uses ConnectTimeout=2)
105
- check_termux_connection() {
106
- local host="$1"
107
-
108
- # Quick connection test (2 second timeout)
109
- if ssh -o ConnectTimeout=2 -o BatchMode=yes "$host" "echo ok" >/dev/null 2>&1; then
110
- return 0
111
- else
112
- return 1
113
- fi
114
- }
115
-
116
- # Main execution
117
- SSH_HOST=$(get_ssh_host)
118
-
119
- if [[ -z "$SSH_HOST" ]]; then
120
- echo "❌ Termux SSH provider not configured" >&2
121
- echo " Set SSH host alias in one of:" >&2
122
- echo " - Environment: export TERMUX_SSH_HOST='android'" >&2
123
- echo " - Global: echo 'android' > ~/.claude/termux-ssh-host.txt" >&2
124
- echo " - Project: echo 'android' > .claude/termux-ssh-host.txt" >&2
125
- echo "" >&2
126
- echo " See provider documentation for SSH setup instructions" >&2
127
- exit 1
128
- fi
129
-
130
- if [[ -z "$TEXT" ]]; then
131
- echo "❌ No text provided for TTS" >&2
132
- exit 1
133
- fi
134
-
135
- # Check if SSH connection is available (with timeout)
136
- if ! check_termux_connection "$SSH_HOST"; then
137
- echo "⚠️ Cannot connect to SSH host '$SSH_HOST'" >&2
138
- echo " Make sure:" >&2
139
- echo " - Android device is reachable" >&2
140
- echo " - SSH server is running: sshd" >&2
141
- echo " - SSH config is correct in ~/.ssh/config" >&2
142
- exit 1
143
- fi
144
-
145
- # Escape single quotes in text for safe shell transmission
146
- # Replace ' with '\'' (end quote, escaped quote, start quote)
147
- SAFE_TEXT="${TEXT//\'/\'\\\'\'}"
148
-
149
- # Send TTS command to Android device via SSH
150
- # Use termux-tts-speak for native Android TTS
151
- # Run in background to avoid blocking
152
- ssh -o ConnectTimeout=5 "$SSH_HOST" "termux-tts-speak '$SAFE_TEXT'" &
153
-
154
- # Get the background process PID
155
- SSH_PID=$!
156
-
157
- # Optional: Wait a moment to detect immediate failures
158
- sleep 0.2
159
-
160
- # Check if the SSH process is still running (indicates successful start)
161
- if kill -0 "$SSH_PID" 2>/dev/null; then
162
- echo "✓ TTS sent to Android device via SSH" >&2
163
- else
164
- echo "⚠️ SSH command may have failed" >&2
165
- fi
166
-
167
- # Note: We don't return an audio file path since audio plays on the Android device
168
- # This is by design - the provider outputs audio remotely, not locally
169
- echo ""
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/play-tts-termux-ssh.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. Use at your own risk. See the Apache License for details.
26
+ #
27
+ # ---
28
+ #
29
+ # @fileoverview Termux SSH TTS Provider - Android TTS via SSH tunnel
30
+ # @context Enables TTS output on Android devices when connected via SSH from Termux
31
+ # @architecture SSH-based remote TTS invocation using termux-tts-speak on Android
32
+ # @dependencies ssh, termux-tts-speak (on Android), termux-api (on Android)
33
+ # @entrypoints Called by play-tts.sh router when provider=termux-ssh
34
+ # @patterns Remote TTS invocation, SSH host alias configuration, graceful fallback
35
+ # @related play-tts.sh, provider-manager.sh
36
+ # @setup Requires user to configure SSH host alias in ~/.ssh/config
37
+ #
38
+ # SETUP INSTRUCTIONS:
39
+ # ===================
40
+ # 1. On Android device (Termux):
41
+ # - Install: pkg install termux-api openssh
42
+ # - Install Termux:API app from F-Droid
43
+ # - Start SSH server: sshd
44
+ # - Get SSH port: echo $PREFIX/var/run/sshd.pid
45
+ #
46
+ # 2. On server/desktop:
47
+ # - Add to ~/.ssh/config:
48
+ # Host android
49
+ # HostName <your-android-ip>
50
+ # User <your-termux-username>
51
+ # Port 8022
52
+ # IdentityFile ~/.ssh/id_rsa
53
+ #
54
+ # 3. Configure AgentVibes:
55
+ # - echo "android" > ~/.claude/termux-ssh-host.txt
56
+ # OR
57
+ # - export TERMUX_SSH_HOST="android"
58
+ #
59
+ # 4. Set provider:
60
+ # - echo "termux-ssh" > ~/.claude/tts-provider.txt
61
+ #
62
+
63
+ # Fix locale warnings
64
+ export LC_ALL=C
65
+
66
+ TEXT="$1"
67
+ VOICE_OVERRIDE="$2" # Not used for termux-ssh, but kept for interface compatibility
68
+
69
+ # Script directory
70
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
71
+
72
+ # @function get_ssh_host
73
+ # @intent Determine SSH host alias for Android device
74
+ # @why Allows users to configure their own SSH connection without hardcoded values
75
+ # @returns Echoes SSH host alias or empty string if not configured
76
+ # @sideeffects None
77
+ get_ssh_host() {
78
+ local ssh_host=""
79
+
80
+ # Priority order:
81
+ # 1. Environment variable TERMUX_SSH_HOST
82
+ # 2. Project-specific config file (CLAUDE_PROJECT_DIR)
83
+ # 3. Script location config file
84
+ # 4. Global config file (~/.claude/termux-ssh-host.txt)
85
+
86
+ if [[ -n "$TERMUX_SSH_HOST" ]]; then
87
+ ssh_host="$TERMUX_SSH_HOST"
88
+ elif [[ -n "$CLAUDE_PROJECT_DIR" ]] && [[ -f "$CLAUDE_PROJECT_DIR/.claude/termux-ssh-host.txt" ]]; then
89
+ ssh_host=$(cat "$CLAUDE_PROJECT_DIR/.claude/termux-ssh-host.txt" 2>/dev/null | tr -d '\n\r')
90
+ elif [[ -f "$SCRIPT_DIR/../termux-ssh-host.txt" ]]; then
91
+ ssh_host=$(cat "$SCRIPT_DIR/../termux-ssh-host.txt" 2>/dev/null | tr -d '\n\r')
92
+ elif [[ -f "$HOME/.claude/termux-ssh-host.txt" ]]; then
93
+ ssh_host=$(cat "$HOME/.claude/termux-ssh-host.txt" 2>/dev/null | tr -d '\n\r')
94
+ fi
95
+
96
+ echo "$ssh_host"
97
+ }
98
+
99
+ # @function check_termux_connection
100
+ # @intent Verify SSH connection to Android device is available
101
+ # @why Prevent hanging on SSH timeout if device is unreachable
102
+ # @param $1 SSH host alias
103
+ # @returns 0 if connection successful, 1 otherwise
104
+ # @sideeffects None (uses ConnectTimeout=2)
105
+ check_termux_connection() {
106
+ local host="$1"
107
+
108
+ # Quick connection test (2 second timeout)
109
+ if ssh -o ConnectTimeout=2 -o BatchMode=yes "$host" "echo ok" >/dev/null 2>&1; then
110
+ return 0
111
+ else
112
+ return 1
113
+ fi
114
+ }
115
+
116
+ # Main execution
117
+ SSH_HOST=$(get_ssh_host)
118
+
119
+ if [[ -z "$SSH_HOST" ]]; then
120
+ echo "❌ Termux SSH provider not configured" >&2
121
+ echo " Set SSH host alias in one of:" >&2
122
+ echo " - Environment: export TERMUX_SSH_HOST='android'" >&2
123
+ echo " - Global: echo 'android' > ~/.claude/termux-ssh-host.txt" >&2
124
+ echo " - Project: echo 'android' > .claude/termux-ssh-host.txt" >&2
125
+ echo "" >&2
126
+ echo " See provider documentation for SSH setup instructions" >&2
127
+ exit 1
128
+ fi
129
+
130
+ if [[ -z "$TEXT" ]]; then
131
+ echo "❌ No text provided for TTS" >&2
132
+ exit 1
133
+ fi
134
+
135
+ # Check if SSH connection is available (with timeout)
136
+ if ! check_termux_connection "$SSH_HOST"; then
137
+ echo "⚠️ Cannot connect to SSH host '$SSH_HOST'" >&2
138
+ echo " Make sure:" >&2
139
+ echo " - Android device is reachable" >&2
140
+ echo " - SSH server is running: sshd" >&2
141
+ echo " - SSH config is correct in ~/.ssh/config" >&2
142
+ exit 1
143
+ fi
144
+
145
+ # Escape single quotes in text for safe shell transmission
146
+ # Replace ' with '\'' (end quote, escaped quote, start quote)
147
+ SAFE_TEXT="${TEXT//\'/\'\\\'\'}"
148
+
149
+ # Send TTS command to Android device via SSH
150
+ # Use termux-tts-speak for native Android TTS
151
+ # Run in background to avoid blocking
152
+ ssh -o ConnectTimeout=5 "$SSH_HOST" "termux-tts-speak '$SAFE_TEXT'" &
153
+
154
+ # Get the background process PID
155
+ SSH_PID=$!
156
+
157
+ # Optional: Wait a moment to detect immediate failures
158
+ sleep 0.2
159
+
160
+ # Check if the SSH process is still running (indicates successful start)
161
+ if kill -0 "$SSH_PID" 2>/dev/null; then
162
+ echo "✓ TTS sent to Android device via SSH" >&2
163
+ else
164
+ echo "⚠️ SSH command may have failed" >&2
165
+ fi
166
+
167
+ # Note: We don't return an audio file path since audio plays on the Android device
168
+ # This is by design - the provider outputs audio remotely, not locally
169
+ echo ""
@@ -89,7 +89,7 @@ while [[ $# -gt 0 ]]; do
89
89
  --llm)
90
90
  LLM_PROVIDER="${2:-}"
91
91
  # Security: Validate LLM provider name (alphanumeric, hyphens, underscores only)
92
- if [[ -n "$LLM_PROVIDER" ]] && [[ ! "$LLM_PROVIDER" =~ ^[a-zA-Z0-9_-]+$ ]]; then
92
+ if [[ -n "$LLM_PROVIDER" ]] && [[ ! "$LLM_PROVIDER" =~ ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ ]]; then
93
93
  echo "Error: Invalid LLM provider name" >&2
94
94
  exit 1
95
95
  fi
@@ -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
@@ -226,11 +237,20 @@ detect_voice_provider() {
226
237
  }
227
238
 
228
239
  # Override provider if voice indicates different provider (mixed-provider mode)
240
+ # But never override transport providers (ssh-remote, agentvibes-receiver, termux-ssh)
241
+ # — those are transport layers, not synth engines. The receiver picks its own engine.
229
242
  if [[ -n "$VOICE_OVERRIDE" ]]; then
230
- DETECTED_PROVIDER=$(detect_voice_provider "$VOICE_OVERRIDE")
231
- if [[ "$DETECTED_PROVIDER" != "$ACTIVE_PROVIDER" ]]; then
232
- ACTIVE_PROVIDER="$DETECTED_PROVIDER"
233
- fi
243
+ case "$ACTIVE_PROVIDER" in
244
+ ssh-remote|agentvibes-receiver|termux-ssh)
245
+ # Transport provider — don't override, voice info is forwarded to receiver
246
+ ;;
247
+ *)
248
+ DETECTED_PROVIDER=$(detect_voice_provider "$VOICE_OVERRIDE")
249
+ if [[ "$DETECTED_PROVIDER" != "$ACTIVE_PROVIDER" ]]; then
250
+ ACTIVE_PROVIDER="$DETECTED_PROVIDER"
251
+ fi
252
+ ;;
253
+ esac
234
254
  fi
235
255
 
236
256
  # @function speak_text
@@ -1,54 +1,54 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/prepare-release.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 Release preparation helper script with AI-generated notes
35
- # @context Placeholder script intended to be replaced by Claude AI for generating release notes
36
- # @architecture Simple informational script - actual logic delegated to Claude AI
37
- # @dependencies None (informational only)
38
- # @entrypoints Called manually or via CLI for release preparation
39
- # @patterns Fail-fast messaging, user guidance
40
- # @related RELEASE_NOTES.md, package.json version bumping
41
-
42
- BUMP_TYPE="${1:-patch}"
43
-
44
- echo "🤖 Preparing release with AI-generated summary..."
45
- echo ""
46
- echo "This command tells Claude AI to:"
47
- echo "1. Analyze changes since last release"
48
- echo "2. Generate intelligent summary"
49
- echo "3. Create RELEASE_NOTES.md"
50
- echo "4. Bump version to $BUMP_TYPE"
51
- echo "5. Commit everything"
52
- echo ""
53
- echo "⚠️ This is handled by Claude AI, not this script"
54
- echo "Please ask Claude to prepare the release instead"
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/prepare-release.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 Release preparation helper script with AI-generated notes
35
+ # @context Placeholder script intended to be replaced by Claude AI for generating release notes
36
+ # @architecture Simple informational script - actual logic delegated to Claude AI
37
+ # @dependencies None (informational only)
38
+ # @entrypoints Called manually or via CLI for release preparation
39
+ # @patterns Fail-fast messaging, user guidance
40
+ # @related RELEASE_NOTES.md, package.json version bumping
41
+
42
+ BUMP_TYPE="${1:-patch}"
43
+
44
+ echo "🤖 Preparing release with AI-generated summary..."
45
+ echo ""
46
+ echo "This command tells Claude AI to:"
47
+ echo "1. Analyze changes since last release"
48
+ echo "2. Generate intelligent summary"
49
+ echo "3. Create RELEASE_NOTES.md"
50
+ echo "4. Bump version to $BUMP_TYPE"
51
+ echo "5. Commit everything"
52
+ echo ""
53
+ echo "⚠️ This is handled by Claude AI, not this script"
54
+ echo "Please ask Claude to prepare the release instead"