agentvibes 5.1.4 → 5.2.1

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 (69) hide show
  1. package/.agentvibes/config.json +23 -13
  2. package/.claude/commands/agent-vibes/verbosity.md +98 -89
  3. package/.claude/config/audio-effects.cfg +4 -1
  4. package/.claude/hooks/audio-cache-utils.sh +246 -246
  5. package/.claude/hooks/background-music-manager.sh +404 -404
  6. package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
  7. package/.claude/hooks/bmad-speak.sh +290 -290
  8. package/.claude/hooks/bmad-tts-injector.sh +568 -568
  9. package/.claude/hooks/bmad-voice-manager.sh +928 -928
  10. package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
  11. package/.claude/hooks/clawdbot-receiver.sh +107 -107
  12. package/.claude/hooks/clean-audio-cache.sh +22 -22
  13. package/.claude/hooks/cleanup-cache.sh +106 -106
  14. package/.claude/hooks/configure-rdp-mode.sh +137 -137
  15. package/.claude/hooks/download-extra-voices.sh +244 -244
  16. package/.claude/hooks/effects-manager.sh +268 -268
  17. package/.claude/hooks/github-star-reminder.sh +154 -154
  18. package/.claude/hooks/language-manager.sh +362 -362
  19. package/.claude/hooks/learn-manager.sh +492 -492
  20. package/.claude/hooks/macos-voice-manager.sh +205 -205
  21. package/.claude/hooks/migrate-background-music.sh +125 -125
  22. package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
  23. package/.claude/hooks/optimize-background-music.sh +87 -87
  24. package/.claude/hooks/path-resolver.sh +60 -60
  25. package/.claude/hooks/personality-manager.sh +448 -448
  26. package/.claude/hooks/piper-download-voices.sh +233 -225
  27. package/.claude/hooks/piper-installer.sh +292 -292
  28. package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
  29. package/.claude/hooks/piper-voice-manager.sh +125 -0
  30. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +97 -90
  31. package/.claude/hooks/play-tts-enhanced.sh +105 -105
  32. package/.claude/hooks/play-tts-piper.sh +16 -5
  33. package/.claude/hooks/play-tts-ssh-remote.sh +168 -167
  34. package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
  35. package/.claude/hooks/play-tts.sh +35 -14
  36. package/.claude/hooks/prepare-release.sh +54 -54
  37. package/.claude/hooks/provider-commands.sh +617 -617
  38. package/.claude/hooks/provider-manager.sh +399 -399
  39. package/.claude/hooks/replay-target-audio.sh +95 -95
  40. package/.claude/hooks/sentiment-manager.sh +201 -201
  41. package/.claude/hooks/session-start-tts.sh +4 -1
  42. package/.claude/hooks/speed-manager.sh +291 -291
  43. package/.claude/hooks/stop-tts.sh +84 -84
  44. package/.claude/hooks/termux-installer.sh +261 -261
  45. package/.claude/hooks/translate-manager.sh +341 -341
  46. package/.claude/hooks/tts-queue-worker.sh +145 -145
  47. package/.claude/hooks/tts-queue.sh +165 -165
  48. package/.claude/hooks/verbosity-manager.sh +185 -178
  49. package/.claude/hooks/voice-manager.sh +552 -548
  50. package/.claude/hooks-windows/download-extra-voices.ps1 +243 -185
  51. package/.claude/hooks-windows/play-tts-piper.ps1 +7 -2
  52. package/.claude/hooks-windows/play-tts.ps1 +9 -3
  53. package/.claude/hooks-windows/session-start-tts.ps1 +2 -1
  54. package/.claude/hooks-windows/verbosity-manager.ps1 +126 -119
  55. package/README.md +19 -2
  56. package/RELEASE_NOTES.md +74 -0
  57. package/bin/agentvibes-voice-browser.js +1939 -1840
  58. package/bin/mcp-server.sh +206 -206
  59. package/mcp-server/server.py +87 -15
  60. package/package.json +1 -1
  61. package/src/console/tabs/receiver-tab.js +1527 -1483
  62. package/src/console/tabs/settings-tab.js +2 -2
  63. package/src/console/tabs/setup-tab.js +112 -31
  64. package/src/console/tabs/voices-tab.js +130 -13
  65. package/src/i18n/en.js +202 -202
  66. package/src/installer.js +79 -213
  67. package/src/services/llm-provider-service.js +126 -75
  68. package/src/services/verbosity-service.js +159 -157
  69. package/templates/agentvibes-receiver.sh +3 -2
@@ -1,90 +1,97 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh
4
- #
5
- # AgentVibes - AgentVibes Receiver Provider (for voiceless connections)
6
- # Sends text to a remote device via SSH for local AgentVibes playback.
7
- # Use this when the AI agent runs on a server/headless machine that has no
8
- # audio output — the remote device (laptop, phone, etc.) plays the audio.
9
- #
10
- # Copyright (c) 2025 Paul Preibisch
11
- # Licensed under the Apache License, Version 2.0
12
- #
13
-
14
- set -euo pipefail
15
-
16
- TEXT="${1:-}"
17
- VOICE="${2:-en_US-lessac-medium}"
18
- AGENT_NAME="${3:-default}"
19
-
20
- # Validate required input
21
- if [[ -z "$TEXT" ]]; then
22
- echo "❌ No text provided" >&2
23
- echo "Usage: $0 <text> [voice] [agent_name]" >&2
24
- exit 1
25
- fi
26
-
27
- # Get script directory
28
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
29
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
30
-
31
- # Get SSH host from config
32
- SSH_HOST=$(cat "$PROJECT_ROOT/.claude/agentvibes-receiver-host.txt" 2>/dev/null || \
33
- cat "$HOME/.claude/agentvibes-receiver-host.txt" 2>/dev/null || echo "")
34
-
35
- if [[ -z "$SSH_HOST" ]]; then
36
- echo "❌ AgentVibes Receiver host not configured" >&2
37
- echo "💡 Set host: echo 'your-device' > ~/.claude/agentvibes-receiver-host.txt" >&2
38
- exit 1
39
- fi
40
-
41
- # SECURITY: Validate SSH_HOST to prevent option injection
42
- # Must be a valid hostname, IP address, or SSH config alias (alphanumeric, dots, hyphens, underscores)
43
- if [[ ! "$SSH_HOST" =~ ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ ]]; then
44
- echo "❌ Invalid SSH host format: $SSH_HOST" >&2
45
- echo "💡 Host must be alphanumeric (may contain dots, hyphens, underscores)" >&2
46
- exit 1
47
- fi
48
-
49
- # SECURITY: Reject hosts starting with hyphen (SSH option injection)
50
- if [[ "$SSH_HOST" == -* ]]; then
51
- echo "❌ Invalid SSH host: cannot start with hyphen" >&2
52
- exit 1
53
- fi
54
-
55
- # SECURITY: Validate VOICE to prevent injection (alphanumeric, hyphens, underscores only)
56
- if [[ ! "$VOICE" =~ ^[a-zA-Z0-9_-]+$ ]]; then
57
- echo "❌ Invalid voice format: $VOICE" >&2
58
- exit 1
59
- fi
60
-
61
- # SECURITY: Validate AGENT_NAME to prevent injection (alphanumeric, hyphens, underscores, spaces only)
62
- if [[ ! "$AGENT_NAME" =~ ^[a-zA-Z0-9_\ -]+$ ]]; then
63
- echo " Invalid agent name format: $AGENT_NAME" >&2
64
- exit 1
65
- fi
66
-
67
- # SECURITY: Encode text and agent name as base64 to prevent command injection
68
- # The receiver will decode these safely
69
- ENCODED_TEXT=$(printf '%s' "$TEXT" | base64 -w 0)
70
- ENCODED_AGENT=$(printf '%s' "$AGENT_NAME" | base64 -w 0)
71
-
72
- # Send text to remote for local AgentVibes playback
73
- echo "📱 Sending to $SSH_HOST for local playback..." >&2
74
-
75
- # Try receiver scripts in order single SSH call, no separate probe
76
- # SECURITY: Base64-encoded values are safe to pass as arguments (no shell metacharacters)
77
- ssh "$SSH_HOST" "
78
- if [ -f ~/.agentvibes/play-remote.sh ]; then
79
- bash ~/.agentvibes/play-remote.sh '$ENCODED_TEXT' '$VOICE' '$ENCODED_AGENT'
80
- elif [ -f ~/.termux/agentvibes-play.sh ]; then
81
- bash ~/.termux/agentvibes-play.sh '$ENCODED_TEXT' '$VOICE' '$ENCODED_AGENT'
82
- else
83
- echo 'Error: Receiver script not found' >&2
84
- exit 1
85
- fi
86
- " &
87
- SSH_PID=$!
88
-
89
- echo "Sent to $SSH_HOST (PID: $SSH_PID)" >&2
90
- exit 0
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh
4
+ #
5
+ # AgentVibes - AgentVibes Receiver Provider (for voiceless connections)
6
+ # Sends text to a remote device via SSH for local AgentVibes playback.
7
+ # Use this when the AI agent runs on a server/headless machine that has no
8
+ # audio output — the remote device (laptop, phone, etc.) plays the audio.
9
+ #
10
+ # Copyright (c) 2025 Paul Preibisch
11
+ # Licensed under the Apache License, Version 2.0
12
+ #
13
+
14
+ set -euo pipefail
15
+
16
+ TEXT="${1:-}"
17
+ VOICE="${2:-en_US-lessac-medium}"
18
+ AGENT_NAME="${3:-default}"
19
+
20
+ # Validate required input
21
+ if [[ -z "$TEXT" ]]; then
22
+ echo "❌ No text provided" >&2
23
+ echo "Usage: $0 <text> [voice] [agent_name]" >&2
24
+ exit 1
25
+ fi
26
+
27
+ # Get script directory
28
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
29
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
30
+
31
+ # Get SSH host from config
32
+ SSH_HOST=$(cat "$PROJECT_ROOT/.claude/agentvibes-receiver-host.txt" 2>/dev/null || \
33
+ cat "$HOME/.claude/agentvibes-receiver-host.txt" 2>/dev/null || echo "")
34
+
35
+ if [[ -z "$SSH_HOST" ]]; then
36
+ echo "❌ AgentVibes Receiver host not configured" >&2
37
+ echo "💡 Set host: echo 'your-device' > ~/.claude/agentvibes-receiver-host.txt" >&2
38
+ exit 1
39
+ fi
40
+
41
+ # SECURITY: Validate SSH_HOST to prevent option injection
42
+ # Must be a valid hostname, IP address, or SSH config alias (alphanumeric, dots, hyphens, underscores)
43
+ if [[ ! "$SSH_HOST" =~ ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ ]]; then
44
+ echo "❌ Invalid SSH host format: $SSH_HOST" >&2
45
+ echo "💡 Host must be alphanumeric (may contain dots, hyphens, underscores)" >&2
46
+ exit 1
47
+ fi
48
+
49
+ # SECURITY: Reject hosts starting with hyphen (SSH option injection)
50
+ if [[ "$SSH_HOST" == -* ]]; then
51
+ echo "❌ Invalid SSH host: cannot start with hyphen" >&2
52
+ exit 1
53
+ fi
54
+
55
+ # SECURITY: Validate VOICE (allow :: for multi-speaker, . for locale, space for names)
56
+ _voice_re='^[a-zA-Z0-9_.: -]+$'
57
+ if [[ ! "$VOICE" =~ $_voice_re ]]; then
58
+ echo "❌ Invalid voice format: $VOICE" >&2
59
+ exit 1
60
+ fi
61
+
62
+ # SECURITY: Validate AGENT_NAME to prevent injection (alphanumeric, hyphens, underscores, spaces only)
63
+ if [[ ! "$AGENT_NAME" =~ ^[a-zA-Z0-9_\ -]+$ ]]; then
64
+ echo "❌ Invalid agent name format: $AGENT_NAME" >&2
65
+ exit 1
66
+ fi
67
+
68
+ # SECURITY: Encode text and agent name as base64 to prevent command injection
69
+ # The receiver will decode these safely
70
+ # Probe for GNU base64 (-w 0), fall back to BSD (-b 0), then tr
71
+ if printf '' | base64 -w 0 >/dev/null 2>&1; then
72
+ ENCODED_TEXT=$(printf '%s' "$TEXT" | base64 -w 0)
73
+ ENCODED_AGENT=$(printf '%s' "$AGENT_NAME" | base64 -w 0)
74
+ else
75
+ ENCODED_TEXT=$(printf '%s' "$TEXT" | base64 -b 0 2>/dev/null || printf '%s' "$TEXT" | base64 | tr -d '\n')
76
+ ENCODED_AGENT=$(printf '%s' "$AGENT_NAME" | base64 -b 0 2>/dev/null || printf '%s' "$AGENT_NAME" | base64 | tr -d '\n')
77
+ fi
78
+
79
+ # Send text to remote for local AgentVibes playback
80
+ echo "📱 Sending to $SSH_HOST for local playback..." >&2
81
+
82
+ # Try receiver scripts in order — single SSH call, no separate probe
83
+ # SECURITY: Base64-encoded values are safe to pass as arguments (no shell metacharacters)
84
+ ssh "$SSH_HOST" "
85
+ if [ -f ~/.agentvibes/play-remote.sh ]; then
86
+ bash ~/.agentvibes/play-remote.sh '$ENCODED_TEXT' '$VOICE' '$ENCODED_AGENT'
87
+ elif [ -f ~/.termux/agentvibes-play.sh ]; then
88
+ bash ~/.termux/agentvibes-play.sh '$ENCODED_TEXT' '$VOICE' '$ENCODED_AGENT'
89
+ else
90
+ echo 'Error: Receiver script not found' >&2
91
+ exit 1
92
+ fi
93
+ " &
94
+ SSH_PID=$!
95
+
96
+ echo "Sent to $SSH_HOST (PID: $SSH_PID)" >&2
97
+ exit 0
@@ -1,105 +1,105 @@
1
- #!/usr/bin/env bash
2
- #
3
- # File: .claude/hooks/play-tts-enhanced.sh
4
- #
5
- # AgentVibes - Enhanced TTS with Background Music and Effects
6
- # Generates TTS, applies effects, mixes background, plays ONCE (no echo)
7
- #
8
- # Usage: play-tts-enhanced.sh "text to speak" [agent_name] [voice_override]
9
- #
10
- # Environment:
11
- # AGENTVIBES_PARTY_MODE=true - Use room ambiance background (_party_mode config)
12
- #
13
-
14
- set -euo pipefail
15
- export LC_ALL=C
16
-
17
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
-
19
- TEXT="${1:-}"
20
- AGENT_NAME="${2:-default}"
21
- VOICE_OVERRIDE="${3:-}"
22
-
23
- if [[ -z "$TEXT" ]]; then
24
- echo "Usage: $0 \"text to speak\" [agent_name] [voice_override]" >&2
25
- exit 1
26
- fi
27
-
28
- # Determine which config to use
29
- CONFIG_KEY="$AGENT_NAME"
30
- if [[ "${AGENTVIBES_PARTY_MODE:-false}" == "true" ]]; then
31
- CONFIG_KEY="_party_mode"
32
- fi
33
-
34
- # ---------------------------------------------------------------------------
35
- # Per-agent profile overrides (from bmad-voice-map.json via bmad-speak.sh)
36
- # If AGENTVIBES_AGENT_PROFILE is set and the file exists, apply reverb/personality/music
37
- # overrides by temporarily setting effects-manager config for this agent
38
- AGENT_PROFILE="${AGENTVIBES_AGENT_PROFILE:-}"
39
-
40
- if [[ -n "$AGENT_PROFILE" ]] && [[ -f "$AGENT_PROFILE" ]]; then
41
- # Read profile fields using node (reliable JSON parsing)
42
- # SECURITY: Pass values via env vars to prevent shell injection
43
- _PROFILE_REVERB=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.reverbPreset||'')}catch{}" 2>/dev/null || true)
44
- _PROFILE_MUSIC_TRACK=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.backgroundMusic?.track||'')}catch{}" 2>/dev/null || true)
45
- _PROFILE_MUSIC_VOL=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(String(p.backgroundMusic?.volume||''))}catch{}" 2>/dev/null || true)
46
-
47
- # Apply per-agent reverb via effects-manager (scoped to this agent's config key)
48
- if [[ -n "$_PROFILE_REVERB" ]] && [[ -f "$SCRIPT_DIR/effects-manager.sh" ]]; then
49
- bash "$SCRIPT_DIR/effects-manager.sh" set-reverb "$_PROFILE_REVERB" "$CONFIG_KEY" 2>/dev/null || true
50
- fi
51
-
52
- # Override background music track/volume for this invocation via env vars
53
- if [[ -n "$_PROFILE_MUSIC_TRACK" ]]; then
54
- export AGENTVIBES_BG_TRACK="$_PROFILE_MUSIC_TRACK"
55
- fi
56
- if [[ -n "$_PROFILE_MUSIC_VOL" ]]; then
57
- export AGENTVIBES_BG_VOLUME="$_PROFILE_MUSIC_VOL"
58
- fi
59
- fi
60
-
61
- # Step 1: Generate TTS WITHOUT playback
62
- export AGENTVIBES_NO_PLAYBACK=true
63
- export AGENTVIBES_WAV_OUTPATH="${XDG_RUNTIME_DIR:-/tmp}/agentvibes-last-wav-$$.txt"
64
-
65
- # Cleanup temp outpath file on exit
66
- trap 'rm -f "$AGENTVIBES_WAV_OUTPATH"' EXIT
67
- "$SCRIPT_DIR/play-tts.sh" "$TEXT" "$VOICE_OVERRIDE"
68
-
69
- # Read the generated file path (written by play-tts-piper.sh via AGENTVIBES_WAV_OUTPATH)
70
- GENERATED_FILE=""
71
- if [[ -f "$AGENTVIBES_WAV_OUTPATH" ]]; then
72
- GENERATED_FILE=$(cat "$AGENTVIBES_WAV_OUTPATH")
73
- rm -f "$AGENTVIBES_WAV_OUTPATH"
74
- fi
75
- unset AGENTVIBES_WAV_OUTPATH
76
-
77
- if [[ -z "$GENERATED_FILE" ]] || [[ ! -f "$GENERATED_FILE" ]]; then
78
- echo "Error: Could not find generated audio file" >&2
79
- exit 1
80
- fi
81
-
82
- # Step 2: Process with effects and background
83
- PROCESSED_FILE="${GENERATED_FILE%.wav}-enhanced.wav"
84
-
85
- if [[ -f "$SCRIPT_DIR/audio-processor.sh" ]]; then
86
- "$SCRIPT_DIR/audio-processor.sh" "$GENERATED_FILE" "$CONFIG_KEY" "$PROCESSED_FILE" 2>/dev/null || {
87
- # Fallback to original if processing fails
88
- PROCESSED_FILE="$GENERATED_FILE"
89
- }
90
- else
91
- PROCESSED_FILE="$GENERATED_FILE"
92
- fi
93
-
94
- # Step 3: Play the processed audio ONCE
95
- if [[ -f "$PROCESSED_FILE" ]]; then
96
- if [[ "$(uname -s)" == "Darwin" ]]; then
97
- afplay "$PROCESSED_FILE" >/dev/null 2>&1 &
98
- else
99
- (mpv "$PROCESSED_FILE" || aplay "$PROCESSED_FILE" || paplay "$PROCESSED_FILE") >/dev/null 2>&1 &
100
- fi
101
- echo "🎵 Enhanced audio: $PROCESSED_FILE"
102
- else
103
- echo "Error: Processed file not found" >&2
104
- exit 1
105
- fi
1
+ #!/usr/bin/env bash
2
+ #
3
+ # File: .claude/hooks/play-tts-enhanced.sh
4
+ #
5
+ # AgentVibes - Enhanced TTS with Background Music and Effects
6
+ # Generates TTS, applies effects, mixes background, plays ONCE (no echo)
7
+ #
8
+ # Usage: play-tts-enhanced.sh "text to speak" [agent_name] [voice_override]
9
+ #
10
+ # Environment:
11
+ # AGENTVIBES_PARTY_MODE=true - Use room ambiance background (_party_mode config)
12
+ #
13
+
14
+ set -euo pipefail
15
+ export LC_ALL=C
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+
19
+ TEXT="${1:-}"
20
+ AGENT_NAME="${2:-default}"
21
+ VOICE_OVERRIDE="${3:-}"
22
+
23
+ if [[ -z "$TEXT" ]]; then
24
+ echo "Usage: $0 \"text to speak\" [agent_name] [voice_override]" >&2
25
+ exit 1
26
+ fi
27
+
28
+ # Determine which config to use
29
+ CONFIG_KEY="$AGENT_NAME"
30
+ if [[ "${AGENTVIBES_PARTY_MODE:-false}" == "true" ]]; then
31
+ CONFIG_KEY="_party_mode"
32
+ fi
33
+
34
+ # ---------------------------------------------------------------------------
35
+ # Per-agent profile overrides (from bmad-voice-map.json via bmad-speak.sh)
36
+ # If AGENTVIBES_AGENT_PROFILE is set and the file exists, apply reverb/personality/music
37
+ # overrides by temporarily setting effects-manager config for this agent
38
+ AGENT_PROFILE="${AGENTVIBES_AGENT_PROFILE:-}"
39
+
40
+ if [[ -n "$AGENT_PROFILE" ]] && [[ -f "$AGENT_PROFILE" ]]; then
41
+ # Read profile fields using node (reliable JSON parsing)
42
+ # SECURITY: Pass values via env vars to prevent shell injection
43
+ _PROFILE_REVERB=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.reverbPreset||'')}catch{}" 2>/dev/null || true)
44
+ _PROFILE_MUSIC_TRACK=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(p.backgroundMusic?.track||'')}catch{}" 2>/dev/null || true)
45
+ _PROFILE_MUSIC_VOL=$(_APFILE="$AGENT_PROFILE" node -e "try{const p=JSON.parse(require('fs').readFileSync(process.env._APFILE,'utf8'));process.stdout.write(String(p.backgroundMusic?.volume||''))}catch{}" 2>/dev/null || true)
46
+
47
+ # Apply per-agent reverb via effects-manager (scoped to this agent's config key)
48
+ if [[ -n "$_PROFILE_REVERB" ]] && [[ -f "$SCRIPT_DIR/effects-manager.sh" ]]; then
49
+ bash "$SCRIPT_DIR/effects-manager.sh" set-reverb "$_PROFILE_REVERB" "$CONFIG_KEY" 2>/dev/null || true
50
+ fi
51
+
52
+ # Override background music track/volume for this invocation via env vars
53
+ if [[ -n "$_PROFILE_MUSIC_TRACK" ]]; then
54
+ export AGENTVIBES_BG_TRACK="$_PROFILE_MUSIC_TRACK"
55
+ fi
56
+ if [[ -n "$_PROFILE_MUSIC_VOL" ]]; then
57
+ export AGENTVIBES_BG_VOLUME="$_PROFILE_MUSIC_VOL"
58
+ fi
59
+ fi
60
+
61
+ # Step 1: Generate TTS WITHOUT playback
62
+ export AGENTVIBES_NO_PLAYBACK=true
63
+ export AGENTVIBES_WAV_OUTPATH="${XDG_RUNTIME_DIR:-/tmp}/agentvibes-last-wav-$$.txt"
64
+
65
+ # Cleanup temp outpath file on exit
66
+ trap 'rm -f "$AGENTVIBES_WAV_OUTPATH"' EXIT
67
+ bash "$SCRIPT_DIR/play-tts.sh" "$TEXT" "$VOICE_OVERRIDE"
68
+
69
+ # Read the generated file path (written by play-tts-piper.sh via AGENTVIBES_WAV_OUTPATH)
70
+ GENERATED_FILE=""
71
+ if [[ -f "$AGENTVIBES_WAV_OUTPATH" ]]; then
72
+ GENERATED_FILE=$(cat "$AGENTVIBES_WAV_OUTPATH")
73
+ rm -f "$AGENTVIBES_WAV_OUTPATH"
74
+ fi
75
+ unset AGENTVIBES_WAV_OUTPATH
76
+
77
+ if [[ -z "$GENERATED_FILE" ]] || [[ ! -f "$GENERATED_FILE" ]]; then
78
+ echo "Error: Could not find generated audio file" >&2
79
+ exit 1
80
+ fi
81
+
82
+ # Step 2: Process with effects and background
83
+ PROCESSED_FILE="${GENERATED_FILE%.wav}-enhanced.wav"
84
+
85
+ if [[ -f "$SCRIPT_DIR/audio-processor.sh" ]]; then
86
+ "$SCRIPT_DIR/audio-processor.sh" "$GENERATED_FILE" "$CONFIG_KEY" "$PROCESSED_FILE" 2>/dev/null || {
87
+ # Fallback to original if processing fails
88
+ PROCESSED_FILE="$GENERATED_FILE"
89
+ }
90
+ else
91
+ PROCESSED_FILE="$GENERATED_FILE"
92
+ fi
93
+
94
+ # Step 3: Play the processed audio ONCE
95
+ if [[ -f "$PROCESSED_FILE" ]]; then
96
+ if [[ "$(uname -s)" == "Darwin" ]]; then
97
+ afplay "$PROCESSED_FILE" >/dev/null 2>&1 &
98
+ else
99
+ (mpv "$PROCESSED_FILE" || aplay "$PROCESSED_FILE" || paplay "$PROCESSED_FILE") >/dev/null 2>&1 &
100
+ fi
101
+ echo "🎵 Enhanced audio: $PROCESSED_FILE"
102
+ else
103
+ echo "Error: Processed file not found" >&2
104
+ exit 1
105
+ fi
@@ -232,18 +232,29 @@ if [[ "${AGENTVIBES_TEST_MODE:-false}" != "true" ]] && ! verify_voice "$VOICE_MO
232
232
  echo " File size: ~25MB"
233
233
  echo " Preview: https://huggingface.co/rhasspy/piper-voices"
234
234
  echo ""
235
- read -p " Download this voice model? [y/N]: " -n 1 -r
236
- echo
237
235
 
238
- if [[ $REPLY =~ ^[Yy]$ ]]; then
236
+ # Auto-download when non-interactive (e.g. called from a hook)
237
+ if [[ ! -t 0 ]]; then
238
+ echo " Auto-downloading (non-interactive mode)..."
239
239
  if ! download_voice "$VOICE_MODEL"; then
240
240
  echo "❌ Failed to download voice model"
241
241
  echo "Fix: Download manually or choose different voice"
242
242
  exit 3
243
243
  fi
244
244
  else
245
- echo " Voice download cancelled"
246
- exit 3
245
+ read -p " Download this voice model? [y/N]: " -n 1 -r
246
+ echo
247
+
248
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
249
+ if ! download_voice "$VOICE_MODEL"; then
250
+ echo "❌ Failed to download voice model"
251
+ echo "Fix: Download manually or choose different voice"
252
+ exit 3
253
+ fi
254
+ else
255
+ echo "❌ Voice download cancelled"
256
+ exit 3
257
+ fi
247
258
  fi
248
259
  fi
249
260