agentvibes 5.7.4 → 5.7.6
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/install-manifest.json +115 -111
- package/.claude/config/audio-effects.cfg +1 -1
- package/.claude/config/background-music-position.txt +1 -1
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/play-tts-ssh-remote.sh +50 -10
- package/.claude/hooks/play-tts.sh +2 -2
- package/README.md +15 -3
- package/RELEASE_NOTES.md +67 -0
- package/mcp-server/WINDOWS_SETUP.md +1 -1
- package/mcp-server/docs/troubleshooting-audio.md +1 -1
- package/package.json +1 -1
- package/src/console/app.js +7 -0
- package/src/console/audio-env.js +19 -0
- package/src/console/tabs/agents-tab.js +64 -10
- package/src/console/tabs/music-tab.js +4 -4
- package/src/console/tabs/settings-tab.js +75 -1
- package/src/console/tabs/setup-tab.js +94 -28
- package/src/console/tabs/voices-tab.js +51 -33
- package/src/installer.js +15 -1
- package/src/services/llm-provider-service.js +4 -4
- package/templates/agentvibes-receiver.sh +139 -66
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
# Location: User installs to ~/.termux/agentvibes-play.sh or ~/.agentvibes/play-remote.sh
|
|
5
5
|
#
|
|
6
6
|
# AgentVibes SSH-TTS Receiver
|
|
7
|
-
# Receives
|
|
7
|
+
# Receives base64-encoded JSON payload from remote server via SSH,
|
|
8
|
+
# decodes it, applies voice/music/effects, and plays with local AgentVibes.
|
|
9
|
+
#
|
|
10
|
+
# Payload format: base64({"text","voice","effects","music","volume","pretext","speed","provider","llm"})
|
|
11
|
+
#
|
|
12
|
+
# SSH ForceCommand: SSH_ORIGINAL_COMMAND carries the base64 payload.
|
|
13
|
+
# Direct invocation: pass the payload as first argument.
|
|
8
14
|
#
|
|
9
15
|
# Installation:
|
|
10
16
|
# curl -sSL https://raw.githubusercontent.com/paulpreibisch/AgentVibes/main/scripts/install-ssh-receiver.sh | bash
|
|
@@ -22,47 +28,141 @@ if [[ "${1:-}" == "--" ]]; then
|
|
|
22
28
|
shift
|
|
23
29
|
fi
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
REVERB="${4:-}"
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
# Resolve encoded payload: arg → SSH_ORIGINAL_COMMAND → stdin (legacy)
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
ENCODED_PAYLOAD="${1:-}"
|
|
36
|
+
if [[ -z "$ENCODED_PAYLOAD" ]]; then
|
|
37
|
+
ENCODED_PAYLOAD="${SSH_ORIGINAL_COMMAND:-}"
|
|
38
|
+
fi
|
|
39
|
+
if [[ -z "$ENCODED_PAYLOAD" ]]; then
|
|
40
|
+
ENCODED_PAYLOAD=$(cat 2>/dev/null || true)
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if [[ -z "$ENCODED_PAYLOAD" ]]; then
|
|
44
|
+
echo "❌ No payload provided" >&2
|
|
45
|
+
echo "Usage: $0 <base64-json-payload>" >&2
|
|
33
46
|
exit 1
|
|
34
47
|
fi
|
|
35
48
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
if [[
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
TEXT="$DECODED"
|
|
42
|
-
fi
|
|
49
|
+
# Reject oversized payloads (DoS guard: 64 KB is generous for any TTS request)
|
|
50
|
+
_MAX_PAYLOAD_BYTES=65536
|
|
51
|
+
if [[ ${#ENCODED_PAYLOAD} -gt $_MAX_PAYLOAD_BYTES ]]; then
|
|
52
|
+
echo "❌ Payload too large (max ${_MAX_PAYLOAD_BYTES} bytes)" >&2
|
|
53
|
+
exit 1
|
|
43
54
|
fi
|
|
44
55
|
|
|
45
|
-
#
|
|
46
|
-
if [[ ! "$
|
|
47
|
-
echo "❌
|
|
56
|
+
# Validate it looks like base64
|
|
57
|
+
if [[ ! "$ENCODED_PAYLOAD" =~ ^[A-Za-z0-9+/=]+$ ]]; then
|
|
58
|
+
echo "❌ Payload must be base64-encoded" >&2
|
|
48
59
|
exit 1
|
|
49
60
|
fi
|
|
50
61
|
|
|
62
|
+
# Decode
|
|
63
|
+
DECODED=$(printf '%s' "$ENCODED_PAYLOAD" | base64 -d 2>/dev/null) || {
|
|
64
|
+
echo "❌ Failed to decode base64 payload" >&2; exit 1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Parse JSON payload — python3 is required for JSON parsing
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
if ! command -v python3 &>/dev/null; then
|
|
72
|
+
echo "❌ python3 required for JSON parsing" >&2; exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Parse all fields in one python call to avoid repeated process spawning
|
|
76
|
+
# and to log a clear error if the payload is malformed JSON.
|
|
77
|
+
_PARSE_OUT=$(python3 - "$DECODED" 2>&1 <<'PYEOF'
|
|
78
|
+
import json, sys
|
|
79
|
+
try:
|
|
80
|
+
d = json.loads(sys.argv[1])
|
|
81
|
+
for field in ("text","voice","music","volume","effects","pretext","speed","provider","llm"):
|
|
82
|
+
print(d.get(field, ""))
|
|
83
|
+
except json.JSONDecodeError as e:
|
|
84
|
+
print(f"JSON_PARSE_ERROR: {e}", file=sys.stderr)
|
|
85
|
+
sys.exit(1)
|
|
86
|
+
PYEOF
|
|
87
|
+
) || { echo "❌ Invalid JSON in payload: $_PARSE_OUT" >&2; exit 1; }
|
|
88
|
+
|
|
89
|
+
# Assign fields from ordered output lines
|
|
90
|
+
TEXT=$( sed -n '1p' <<< "$_PARSE_OUT")
|
|
91
|
+
VOICE=$( sed -n '2p' <<< "$_PARSE_OUT")
|
|
92
|
+
MUSIC=$( sed -n '3p' <<< "$_PARSE_OUT")
|
|
93
|
+
VOLUME=$( sed -n '4p' <<< "$_PARSE_OUT")
|
|
94
|
+
EFFECTS=$( sed -n '5p' <<< "$_PARSE_OUT")
|
|
95
|
+
PRETEXT=$( sed -n '6p' <<< "$_PARSE_OUT")
|
|
96
|
+
SPEED=$( sed -n '7p' <<< "$_PARSE_OUT")
|
|
97
|
+
PROVIDER=$(sed -n '8p' <<< "$_PARSE_OUT")
|
|
98
|
+
LLM=$( sed -n '9p' <<< "$_PARSE_OUT")
|
|
99
|
+
|
|
100
|
+
# Fall back to defaults
|
|
101
|
+
[[ -z "$VOICE" ]] && VOICE="en_US-lessac-medium"
|
|
102
|
+
[[ -z "$VOLUME" ]] && VOLUME="0.10"
|
|
103
|
+
[[ -z "$PROVIDER" ]] && PROVIDER="piper"
|
|
104
|
+
|
|
105
|
+
# Validate text
|
|
106
|
+
if [[ -z "$TEXT" ]]; then
|
|
107
|
+
echo "❌ No text in payload" >&2; exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# SECURITY: Validate voice — letters, digits, underscore, hyphen, period, colon
|
|
111
|
+
if [[ ! "$VOICE" =~ ^[a-zA-Z0-9_.:/-]+$ ]]; then
|
|
112
|
+
echo "❌ Invalid voice format: $VOICE" >&2; exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Validate volume is numeric
|
|
116
|
+
if [[ ! "$VOLUME" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
|
117
|
+
VOLUME="0.10"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Validate provider
|
|
121
|
+
case "$PROVIDER" in
|
|
122
|
+
piper|soprano|macos|windows-sapi) ;;
|
|
123
|
+
*) PROVIDER="piper" ;;
|
|
124
|
+
esac
|
|
125
|
+
|
|
126
|
+
# Prepend pretext if present (same logic as PS receiver)
|
|
127
|
+
if [[ -n "$PRETEXT" ]]; then
|
|
128
|
+
TEXT="${PRETEXT}. ${TEXT}"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# ---------------------------------------------------------------------------
|
|
132
|
+
# Test mode: dump what would be played without calling play-tts
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
if [[ "${AGENTVIBES_TEST_MODE:-false}" == "true" ]]; then
|
|
136
|
+
python3 -c "
|
|
137
|
+
import json, sys
|
|
138
|
+
print(json.dumps({
|
|
139
|
+
'text': sys.argv[1],
|
|
140
|
+
'voice': sys.argv[2],
|
|
141
|
+
'music': sys.argv[3],
|
|
142
|
+
'volume': sys.argv[4],
|
|
143
|
+
'effects': sys.argv[5],
|
|
144
|
+
'pretext': sys.argv[6],
|
|
145
|
+
'provider': sys.argv[7],
|
|
146
|
+
'llm': sys.argv[8],
|
|
147
|
+
}, ensure_ascii=False))
|
|
148
|
+
" "$TEXT" "$VOICE" "$MUSIC" "$VOLUME" "$EFFECTS" "$PRETEXT" "$PROVIDER" "$LLM"
|
|
149
|
+
exit 0
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# ---------------------------------------------------------------------------
|
|
153
|
+
# Find AgentVibes installation
|
|
154
|
+
# ---------------------------------------------------------------------------
|
|
155
|
+
|
|
51
156
|
# Suppress GitHub star reminders (receiver mode)
|
|
52
157
|
export AGENTVIBES_NO_REMINDERS=1
|
|
53
158
|
|
|
54
|
-
# Find AgentVibes installation
|
|
55
|
-
# SECURITY: Uses controlled paths only, validates existence
|
|
56
159
|
find_agentvibes() {
|
|
57
|
-
# Try command lookup first
|
|
58
160
|
if command -v agentvibes >/dev/null 2>&1; then
|
|
59
161
|
local bin_path
|
|
60
162
|
bin_path=$(which agentvibes)
|
|
61
|
-
# Resolve if it's a symlink
|
|
62
163
|
if [[ -L "$bin_path" ]]; then
|
|
63
164
|
bin_path=$(readlink -f "$bin_path" 2>/dev/null || realpath "$bin_path" 2>/dev/null || echo "$bin_path")
|
|
64
165
|
fi
|
|
65
|
-
# SECURITY: Properly quote nested command substitutions
|
|
66
166
|
local lib_path
|
|
67
167
|
lib_path="$(dirname "$(dirname "$bin_path")")/lib/node_modules/agentvibes"
|
|
68
168
|
if [[ -d "$lib_path" ]]; then
|
|
@@ -71,17 +171,14 @@ find_agentvibes() {
|
|
|
71
171
|
fi
|
|
72
172
|
fi
|
|
73
173
|
|
|
74
|
-
# Check common npm global locations (controlled paths only)
|
|
75
174
|
local search_paths=(
|
|
76
175
|
"$HOME/.npm-global/lib/node_modules/agentvibes"
|
|
77
176
|
"/usr/local/lib/node_modules/agentvibes"
|
|
78
|
-
"/data/data/com.termux/files/usr/lib/node_modules/agentvibes"
|
|
177
|
+
"/data/data/com.termux/files/usr/lib/node_modules/agentvibes"
|
|
79
178
|
)
|
|
80
179
|
|
|
81
|
-
# Handle nvm paths separately to avoid glob issues
|
|
82
180
|
if [[ -d "$HOME/.nvm/versions/node" ]]; then
|
|
83
181
|
local nvm_path
|
|
84
|
-
# SECURITY: Use find instead of unsafe glob expansion
|
|
85
182
|
nvm_path=$(find "$HOME/.nvm/versions/node" -maxdepth 3 -type d -name "agentvibes" -path "*/lib/node_modules/*" 2>/dev/null | head -1)
|
|
86
183
|
if [[ -n "$nvm_path" ]] && [[ -d "$nvm_path" ]]; then
|
|
87
184
|
echo "$nvm_path"
|
|
@@ -89,11 +186,8 @@ find_agentvibes() {
|
|
|
89
186
|
fi
|
|
90
187
|
fi
|
|
91
188
|
|
|
92
|
-
for
|
|
93
|
-
|
|
94
|
-
echo "$path"
|
|
95
|
-
return 0
|
|
96
|
-
fi
|
|
189
|
+
for p in "${search_paths[@]}"; do
|
|
190
|
+
[[ -d "$p" ]] && { echo "$p"; return 0; }
|
|
97
191
|
done
|
|
98
192
|
|
|
99
193
|
return 1
|
|
@@ -110,48 +204,27 @@ fi
|
|
|
110
204
|
PLAY_TTS="$AGENTVIBES_ROOT/.claude/hooks/play-tts.sh"
|
|
111
205
|
|
|
112
206
|
if [[ ! -f "$PLAY_TTS" ]]; then
|
|
113
|
-
echo "❌ play-tts.sh not found at $PLAY_TTS" >&2
|
|
114
|
-
exit 1
|
|
207
|
+
echo "❌ play-tts.sh not found at $PLAY_TTS" >&2; exit 1
|
|
115
208
|
fi
|
|
116
209
|
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
echo "true" > "$CONFIG_DIR/background-music-enabled.txt"
|
|
126
|
-
|
|
127
|
-
# Clear position cache for fresh start
|
|
128
|
-
rm -f "$CONFIG_DIR/background-music-position.txt"
|
|
129
|
-
|
|
130
|
-
# Set background music track if provided
|
|
131
|
-
if [[ -n "$MUSIC" ]]; then
|
|
132
|
-
echo "$MUSIC" > "$CONFIG_DIR/background-music.txt"
|
|
133
|
-
fi
|
|
134
|
-
|
|
135
|
-
# Set audio effects config (default agent name is always "default")
|
|
136
|
-
if [[ -n "$MUSIC" ]] && [[ -n "$REVERB" ]]; then
|
|
137
|
-
echo "default|${REVERB}|${MUSIC}|0.10" > "$CONFIG_DIR/audio-effects.cfg"
|
|
138
|
-
elif [[ -n "$REVERB" ]]; then
|
|
139
|
-
echo "default|${REVERB}||0.0" > "$CONFIG_DIR/audio-effects.cfg"
|
|
140
|
-
elif [[ -n "$MUSIC" ]]; then
|
|
141
|
-
echo "default||${MUSIC}|0.10" > "$CONFIG_DIR/audio-effects.cfg"
|
|
142
|
-
fi
|
|
143
|
-
fi
|
|
210
|
+
# ---------------------------------------------------------------------------
|
|
211
|
+
# Apply music / effects overrides via env vars for play-tts.sh
|
|
212
|
+
# ---------------------------------------------------------------------------
|
|
213
|
+
|
|
214
|
+
[[ -n "$MUSIC" ]] && export AGENTVIBES_OVERRIDE_MUSIC="$MUSIC"
|
|
215
|
+
[[ -n "$VOLUME" ]] && export AGENTVIBES_OVERRIDE_VOLUME="$VOLUME"
|
|
216
|
+
[[ -n "$EFFECTS" ]] && export AGENTVIBES_OVERRIDE_EFFECTS="$EFFECTS"
|
|
217
|
+
[[ -n "$SPEED" ]] && export AGENTVIBES_OVERRIDE_SPEED="$SPEED"
|
|
144
218
|
|
|
145
|
-
# Log for debugging (optional, comment out in production)
|
|
146
219
|
if [[ "${AGENTVIBES_DEBUG:-0}" == "1" ]]; then
|
|
147
|
-
echo "[DEBUG] AgentVibes root: $AGENTVIBES_ROOT" >&2
|
|
148
220
|
echo "[DEBUG] Voice: $VOICE" >&2
|
|
149
221
|
echo "[DEBUG] Music: ${MUSIC:-none}" >&2
|
|
150
|
-
echo "[DEBUG]
|
|
151
|
-
echo "[DEBUG]
|
|
222
|
+
echo "[DEBUG] Volume: ${VOLUME:-none}" >&2
|
|
223
|
+
echo "[DEBUG] Effects: ${EFFECTS:-none}" >&2
|
|
224
|
+
echo "[DEBUG] Pretext: ${PRETEXT:-none}" >&2
|
|
225
|
+
echo "[DEBUG] Provider: $PROVIDER" >&2
|
|
152
226
|
fi
|
|
153
227
|
|
|
154
|
-
# Generate and play with full AgentVibes features
|
|
155
228
|
echo "🎵 Playing via AgentVibes: ${TEXT:0:50}..." >&2
|
|
156
229
|
bash "$PLAY_TTS" "$TEXT" "$VOICE"
|
|
157
230
|
|