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.
- package/.agentvibes/config.json +23 -13
- package/.claude/commands/agent-vibes/verbosity.md +98 -89
- package/.claude/config/audio-effects.cfg +4 -1
- package/.claude/hooks/audio-cache-utils.sh +246 -246
- package/.claude/hooks/background-music-manager.sh +404 -404
- package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
- package/.claude/hooks/bmad-speak.sh +290 -290
- package/.claude/hooks/bmad-tts-injector.sh +568 -568
- package/.claude/hooks/bmad-voice-manager.sh +928 -928
- package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
- package/.claude/hooks/clawdbot-receiver.sh +107 -107
- package/.claude/hooks/clean-audio-cache.sh +22 -22
- package/.claude/hooks/cleanup-cache.sh +106 -106
- package/.claude/hooks/configure-rdp-mode.sh +137 -137
- package/.claude/hooks/download-extra-voices.sh +244 -244
- package/.claude/hooks/effects-manager.sh +268 -268
- package/.claude/hooks/github-star-reminder.sh +154 -154
- package/.claude/hooks/language-manager.sh +362 -362
- package/.claude/hooks/learn-manager.sh +492 -492
- package/.claude/hooks/macos-voice-manager.sh +205 -205
- package/.claude/hooks/migrate-background-music.sh +125 -125
- package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
- package/.claude/hooks/optimize-background-music.sh +87 -87
- package/.claude/hooks/path-resolver.sh +60 -60
- package/.claude/hooks/personality-manager.sh +448 -448
- package/.claude/hooks/piper-download-voices.sh +233 -225
- package/.claude/hooks/piper-installer.sh +292 -292
- package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
- package/.claude/hooks/piper-voice-manager.sh +125 -0
- package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +97 -90
- package/.claude/hooks/play-tts-enhanced.sh +105 -105
- package/.claude/hooks/play-tts-piper.sh +16 -5
- package/.claude/hooks/play-tts-ssh-remote.sh +168 -167
- package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
- package/.claude/hooks/play-tts.sh +35 -14
- package/.claude/hooks/prepare-release.sh +54 -54
- package/.claude/hooks/provider-commands.sh +617 -617
- package/.claude/hooks/provider-manager.sh +399 -399
- package/.claude/hooks/replay-target-audio.sh +95 -95
- package/.claude/hooks/sentiment-manager.sh +201 -201
- package/.claude/hooks/session-start-tts.sh +4 -1
- package/.claude/hooks/speed-manager.sh +291 -291
- package/.claude/hooks/stop-tts.sh +84 -84
- package/.claude/hooks/termux-installer.sh +261 -261
- package/.claude/hooks/translate-manager.sh +341 -341
- package/.claude/hooks/tts-queue-worker.sh +145 -145
- package/.claude/hooks/tts-queue.sh +165 -165
- package/.claude/hooks/verbosity-manager.sh +185 -178
- package/.claude/hooks/voice-manager.sh +552 -548
- package/.claude/hooks-windows/download-extra-voices.ps1 +243 -185
- package/.claude/hooks-windows/play-tts-piper.ps1 +7 -2
- package/.claude/hooks-windows/play-tts.ps1 +9 -3
- package/.claude/hooks-windows/session-start-tts.ps1 +2 -1
- package/.claude/hooks-windows/verbosity-manager.ps1 +126 -119
- package/README.md +19 -2
- package/RELEASE_NOTES.md +74 -0
- package/bin/agentvibes-voice-browser.js +1939 -1840
- package/bin/mcp-server.sh +206 -206
- package/mcp-server/server.py +87 -15
- package/package.json +1 -1
- package/src/console/tabs/receiver-tab.js +1527 -1483
- package/src/console/tabs/settings-tab.js +2 -2
- package/src/console/tabs/setup-tab.js +112 -31
- package/src/console/tabs/voices-tab.js +130 -13
- package/src/i18n/en.js +202 -202
- package/src/installer.js +79 -213
- package/src/services/llm-provider-service.js +126 -75
- package/src/services/verbosity-service.js +159 -157
- 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
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
-
|
|
246
|
-
|
|
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
|
|