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.
- package/.agentvibes/LITE-MODE.md +236 -0
- package/.agentvibes/README.md +136 -0
- package/.agentvibes/backup/session-start-tts.sh.20251210_212814 +141 -0
- package/.agentvibes/backups/agents/analyst_20260204_144958.md +78 -0
- package/.agentvibes/backups/agents/architect_20260204_144958.md +72 -0
- package/.agentvibes/backups/agents/dev_20260204_144958.md +74 -0
- package/.agentvibes/backups/agents/pm_20260204_144958.md +72 -0
- package/.agentvibes/backups/agents/quick-flow-solo-dev_20260204_144958.md +64 -0
- package/.agentvibes/backups/agents/sm_20260204_144958.md +87 -0
- package/.agentvibes/backups/agents/tea_20260204_144958.md +79 -0
- package/.agentvibes/backups/agents/tech-writer_20260204_144958.md +82 -0
- package/.agentvibes/backups/agents/ux-designer_20260204_144958.md +80 -0
- package/.agentvibes/bmad/bmad-voices.md +69 -69
- package/.agentvibes/config/README-personality-defaults.md +162 -0
- package/.agentvibes/config/mode.txt +1 -0
- package/.agentvibes/config/personality-voice-defaults.default.json +21 -0
- package/.agentvibes/config/save-audio.txt +1 -0
- package/.agentvibes/config/voice-metadata.json +160 -0
- package/.agentvibes/config.json +24 -15
- package/.agentvibes/hooks/help.sh +191 -0
- package/.agentvibes/hooks/post-tool-use-lite.sh +111 -0
- package/.agentvibes/hooks/save-audio-manager.sh +162 -0
- package/.agentvibes/hooks/session-start-full-optimized.sh +102 -0
- package/.agentvibes/hooks/session-start-full.sh +142 -0
- package/.agentvibes/hooks/session-start-lite-v2.sh +34 -0
- package/.agentvibes/hooks/session-start-lite.sh +29 -0
- package/.agentvibes/hooks/stop-lite.sh +115 -0
- package/.agentvibes/hooks/switch-mode.sh +215 -0
- package/.agentvibes/output-styles/audio-summary.md +30 -0
- package/.claude/activation-instructions +54 -54
- package/.claude/audio/voice-samples/piper/alan.wav +0 -0
- package/.claude/audio/voice-samples/piper/amy.wav +0 -0
- package/.claude/audio/voice-samples/piper/charlotte.wav +0 -0
- package/.claude/audio/voice-samples/piper/joe.wav +0 -0
- package/.claude/audio/voice-samples/piper/john.wav +0 -0
- package/.claude/audio/voice-samples/piper/katherine.wav +0 -0
- package/.claude/audio/voice-samples/piper/kristin.wav +0 -0
- package/.claude/audio/voice-samples/piper/linda.wav +0 -0
- package/.claude/audio/voice-samples/piper/marcus.wav +0 -0
- package/.claude/audio/voice-samples/piper/ryan.wav +0 -0
- package/.claude/commands/agent-vibes/add.md +21 -21
- package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
- package/.claude/commands/agent-vibes/agent.md +79 -79
- package/.claude/commands/agent-vibes/background-music.md +111 -111
- package/.claude/commands/agent-vibes/bmad.md +198 -198
- package/.claude/commands/agent-vibes/clean.md +18 -18
- package/.claude/commands/agent-vibes/cleanup.md +18 -18
- package/.claude/commands/agent-vibes/commands.json +145 -145
- package/.claude/commands/agent-vibes/effects.md +97 -97
- package/.claude/commands/agent-vibes/get.md +9 -9
- package/.claude/commands/agent-vibes/hide.md +91 -91
- package/.claude/commands/agent-vibes/language.md +23 -23
- package/.claude/commands/agent-vibes/learn.md +67 -67
- package/.claude/commands/agent-vibes/list.md +13 -13
- package/.claude/commands/agent-vibes/mute.md +37 -37
- package/.claude/commands/agent-vibes/preview.md +17 -17
- package/.claude/commands/agent-vibes/provider.md +68 -68
- package/.claude/commands/agent-vibes/replay-target.md +14 -14
- package/.claude/commands/agent-vibes/sample.md +12 -12
- package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
- package/.claude/commands/agent-vibes/set-pretext.md +65 -65
- package/.claude/commands/agent-vibes/set-speed.md +41 -41
- package/.claude/commands/agent-vibes/show.md +84 -84
- package/.claude/commands/agent-vibes/switch.md +87 -87
- package/.claude/commands/agent-vibes/target-voice.md +26 -26
- package/.claude/commands/agent-vibes/target.md +30 -30
- package/.claude/commands/agent-vibes/translate.md +68 -68
- package/.claude/commands/agent-vibes/unmute.md +45 -45
- package/.claude/commands/agent-vibes/whoami.md +7 -7
- package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
- package/.claude/commands/agent-vibes-rdp.md +24 -24
- package/.claude/config/audio-effects.cfg +4 -11
- package/.claude/config/audio-effects.cfg.sample +52 -52
- package/.claude/config/background-music-position.txt +27 -0
- package/.claude/config/background-music-volume.txt +1 -1
- package/.claude/config/background-music.cfg +1 -0
- package/.claude/config/background-music.txt +1 -0
- package/.claude/config/tts-speech-rate.txt +1 -4
- package/.claude/config/tts-verbosity.txt +1 -0
- package/.claude/docs/TERMUX_SETUP.md +408 -408
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/README-TTS-QUEUE.md +135 -135
- package/.claude/hooks/audio-cache-utils.sh +0 -0
- package/.claude/hooks/audio-processor.sh +60 -14
- package/.claude/hooks/background-music-manager.sh +0 -0
- package/.claude/hooks/bmad-party-manager.sh +225 -0
- package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
- package/.claude/hooks/bmad-speak.sh +6 -13
- package/.claude/hooks/bmad-tts-injector.sh +0 -0
- package/.claude/hooks/bmad-voice-manager.sh +0 -0
- package/.claude/hooks/clawdbot-receiver-SECURE.sh +25 -23
- package/.claude/hooks/clawdbot-receiver.sh +4 -28
- package/.claude/hooks/clean-audio-cache.sh +0 -0
- package/.claude/hooks/cleanup-cache.sh +0 -0
- package/.claude/hooks/configure-rdp-mode.sh +0 -0
- package/.claude/hooks/download-extra-voices.sh +0 -0
- package/.claude/hooks/effects-manager.sh +0 -0
- package/.claude/hooks/github-star-reminder.sh +0 -0
- package/.claude/hooks/language-manager.sh +0 -0
- package/.claude/hooks/learn-manager.sh +0 -0
- package/.claude/hooks/macos-voice-manager.sh +0 -0
- package/.claude/hooks/migrate-background-music.sh +0 -0
- package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
- package/.claude/hooks/optimize-background-music.sh +0 -0
- package/.claude/hooks/personality-manager.sh +0 -0
- package/.claude/hooks/piper-download-voices.sh +0 -0
- package/.claude/hooks/piper-installer.sh +1 -1
- package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
- package/.claude/hooks/piper-voice-manager.sh +0 -0
- package/.claude/hooks/play-tts-enhanced.sh +0 -0
- package/.claude/hooks/play-tts-macos.sh +6 -12
- package/.claude/hooks/play-tts-piper.sh +50 -79
- package/.claude/hooks/play-tts-soprano.sh +9 -43
- package/.claude/hooks/play-tts-ssh-remote.sh +42 -120
- package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
- package/.claude/hooks/play-tts.sh +48 -37
- package/.claude/hooks/post-response.sh +41 -0
- package/.claude/hooks/prepare-release.sh +0 -0
- package/.claude/hooks/provider-commands.sh +0 -0
- package/.claude/hooks/provider-manager.sh +0 -0
- package/.claude/hooks/replay-target-audio.sh +0 -0
- package/.claude/hooks/requirements.txt +6 -6
- package/.claude/hooks/sentiment-manager.sh +0 -0
- package/.claude/hooks/session-start-tts.sh +56 -39
- package/.claude/hooks/soprano-gradio-synth.py +139 -139
- package/.claude/hooks/speed-manager.sh +0 -0
- package/.claude/hooks/stop.sh +63 -0
- package/.claude/hooks/termux-installer.sh +0 -0
- package/.claude/hooks/translate-manager.sh +0 -0
- package/.claude/hooks/translator.py +237 -237
- package/.claude/hooks/tts-queue-worker.sh +0 -0
- package/.claude/hooks/tts-queue.sh +0 -0
- package/.claude/hooks/verbosity-manager.sh +0 -0
- package/.claude/hooks/voice-manager.sh +26 -4
- package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
- package/.claude/hooks-windows/bmad-party-speak.ps1 +278 -274
- package/.claude/hooks-windows/bmad-speak.ps1 +264 -264
- package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -53
- package/.claude/hooks-windows/effects-manager.ps1 +294 -294
- package/.claude/hooks-windows/language-manager.ps1 +193 -193
- package/.claude/hooks-windows/learn-manager.ps1 +241 -241
- package/.claude/hooks-windows/personality-manager.ps1 +266 -266
- package/.claude/hooks-windows/play-tts-soprano.ps1 +5 -5
- package/.claude/hooks-windows/play-tts-termux-ssh.ps1 +138 -138
- package/.claude/hooks-windows/play-tts-windows-piper.ps1 +164 -0
- package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -0
- package/.claude/hooks-windows/play-tts.ps1 +104 -481
- package/.claude/hooks-windows/provider-manager.ps1 +158 -192
- package/.claude/hooks-windows/session-start-tts.ps1 +55 -46
- package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
- package/.claude/hooks-windows/speed-manager.ps1 +166 -166
- package/.claude/hooks-windows/voice-manager-windows.ps1 +176 -260
- package/.claude/output-styles/agent-vibes.md +202 -202
- package/.claude/personalities/angry.md +14 -14
- package/.claude/personalities/annoying.md +14 -14
- package/.claude/personalities/crass.md +14 -14
- package/.claude/personalities/dramatic.md +14 -14
- package/.claude/personalities/dry-humor.md +50 -50
- package/.claude/personalities/flirty.md +20 -20
- package/.claude/personalities/funny.md +14 -14
- package/.claude/personalities/grandpa.md +32 -32
- package/.claude/personalities/millennial.md +14 -14
- package/.claude/personalities/moody.md +14 -14
- package/.claude/personalities/normal.md +16 -16
- package/.claude/personalities/pirate.md +14 -14
- package/.claude/personalities/poetic.md +14 -14
- package/.claude/personalities/professional.md +14 -14
- package/.claude/personalities/rapper.md +55 -55
- package/.claude/personalities/robot.md +14 -14
- package/.claude/personalities/sarcastic.md +38 -38
- package/.claude/personalities/sassy.md +14 -14
- package/.claude/personalities/surfer-dude.md +14 -14
- package/.claude/personalities/zen.md +14 -14
- package/.claude/piper-voices-dir.txt +1 -0
- package/.claude/settings.json +25 -15
- package/.claude/verbosity.txt +1 -1
- package/.clawdbot/README.md +105 -105
- package/.clawdbot/skill/SKILL.md +149 -145
- package/.mcp.json +30 -11
- package/CLAUDE.md +170 -215
- package/README.md +206 -515
- package/RELEASE_NOTES.md +1132 -1884
- package/WINDOWS-SETUP.md +208 -208
- package/bin/agent-vibes +0 -0
- package/bin/agentvibes-voice-browser.js +64 -1289
- package/bin/agentvibes.js +0 -0
- package/bin/ensure-soprano-running.sh +43 -0
- package/bin/mcp-server.js +121 -121
- package/bin/mcp-server.sh +0 -0
- package/bin/test-bmad-pr +78 -78
- package/mcp-server/QUICK_START.md +203 -203
- package/mcp-server/README.md +345 -345
- package/mcp-server/WINDOWS_SETUP.md +260 -260
- package/mcp-server/docs/troubleshooting-audio.md +313 -313
- package/mcp-server/examples/claude_desktop_config.json +11 -11
- package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
- package/mcp-server/examples/custom_instructions.md +169 -169
- package/mcp-server/install-deps.js +130 -130
- package/mcp-server/pyproject.toml +52 -52
- package/mcp-server/requirements.txt +2 -2
- package/mcp-server/server.py +1451 -1578
- package/mcp-server/test_server.py +395 -395
- package/package.json +1 -3
- package/setup-windows.ps1 +815 -815
- package/src/console/tabs/setup-tab.js +9 -6
- package/src/console/tabs/voices-tab.js +9 -3
- package/src/installer.js +42 -5
- package/src/services/llm-provider-service.js +13 -0
- package/templates/agentvibes-receiver.sh +158 -483
- package/templates/audio/welcome-music.mp3 +0 -0
- package/.agentvibes/bmad-voice-map.json +0 -104
- package/.agentvibes/copilot-sessions.log +0 -4
- package/.claude/config/audio-effects-bmad.cfg +0 -50
- package/.claude/config/background-music-enabled.txt +0 -1
- package/.claude/config/intro-text.txt +0 -1
- package/.claude/config/personality.txt +0 -1
- package/.claude/config/piper-speech-rate.txt +0 -4
- package/.claude/config/piper-target-speech-rate.txt +0 -1
- package/.claude/config/reverb-level.txt +0 -1
- package/.claude/config/tts-target-speech-rate.txt +0 -1
- package/voice-assignments.json +0 -8245
- /package/{.claude → .agentvibes}/config/agentvibes.json +0 -0
|
@@ -26,19 +26,20 @@ VOICE="${2:-en_US-lessac-medium}"
|
|
|
26
26
|
ENCODED_AGENT="${3:-}"
|
|
27
27
|
ENCODED_INTRO="${4:-}"
|
|
28
28
|
|
|
29
|
+
# SECURITY: Whitelist of allowed voice names
|
|
30
|
+
ALLOWED_VOICES="en_US-amy-medium|en_US-lessac-medium|es_ES-mls_9972-low|es_ES-davefx-medium|en_US-joe-medium"
|
|
31
|
+
|
|
29
32
|
# Validate inputs
|
|
30
33
|
if [[ -z "$ENCODED_TEXT" ]]; then
|
|
31
|
-
echo "
|
|
34
|
+
echo "❌ No encoded text provided" >&2
|
|
32
35
|
echo "Usage: $0 <base64_text> <voice> <base64_agent_name> [base64_intro]" >&2
|
|
33
36
|
exit 1
|
|
34
37
|
fi
|
|
35
38
|
|
|
36
|
-
# SECURITY: Validate
|
|
37
|
-
[[ "$
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if [[ ! "$VOICE" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
|
41
|
-
echo "Error: Invalid voice name format: $VOICE" >&2
|
|
39
|
+
# SECURITY: Validate VOICE parameter against whitelist
|
|
40
|
+
if ! [[ "$VOICE" =~ ^($ALLOWED_VOICES)$ ]]; then
|
|
41
|
+
echo "❌ Invalid voice name: $VOICE" >&2
|
|
42
|
+
echo "Allowed voices: $(echo "$ALLOWED_VOICES" | tr '|' ', ')" >&2
|
|
42
43
|
exit 1
|
|
43
44
|
fi
|
|
44
45
|
|
|
@@ -57,30 +58,31 @@ fi
|
|
|
57
58
|
|
|
58
59
|
DECODED_AGENT="default"
|
|
59
60
|
if [[ -n "$ENCODED_AGENT" ]]; then
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if [[ -n "$ENCODED_AGENT" ]]; then
|
|
63
|
-
DECODED_AGENT=$(echo -n "$ENCODED_AGENT" | base64 -d 2>/dev/null) || DECODED_AGENT="default"
|
|
64
|
-
fi
|
|
65
|
-
|
|
61
|
+
DECODED_AGENT=$(echo -n "$ENCODED_AGENT" | base64 -d 2>/dev/null) || DECODED_AGENT="default"
|
|
62
|
+
|
|
66
63
|
# SECURITY: Validate agent name format (alphanumeric, dash, underscore only)
|
|
67
|
-
[[ "$DECODED_AGENT" =~ ^[a-zA-Z0-9_-]+$ ]]
|
|
68
|
-
|
|
64
|
+
if ! [[ "$DECODED_AGENT" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
|
65
|
+
echo "⚠️ Invalid agent name format, using 'default'" >&2
|
|
66
|
+
DECODED_AGENT="default"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
69
|
# SECURITY: Enforce length limit on agent name
|
|
70
|
-
[[ ${#DECODED_AGENT} -
|
|
70
|
+
if [[ ${#DECODED_AGENT} -gt 50 ]]; then
|
|
71
|
+
echo "⚠️ Agent name too long, using 'default'" >&2
|
|
72
|
+
DECODED_AGENT="default"
|
|
73
|
+
fi
|
|
71
74
|
fi
|
|
72
75
|
|
|
73
76
|
# Decode and prepend intro if provided
|
|
74
77
|
DECODED_INTRO=""
|
|
75
78
|
if [[ -n "$ENCODED_INTRO" ]]; then
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if [[ -n "$ENCODED_INTRO" ]]; then
|
|
79
|
-
DECODED_INTRO=$(echo -n "$ENCODED_INTRO" | base64 -d 2>/dev/null) || DECODED_INTRO=""
|
|
80
|
-
fi
|
|
81
|
-
|
|
79
|
+
DECODED_INTRO=$(echo -n "$ENCODED_INTRO" | base64 -d 2>/dev/null) || DECODED_INTRO=""
|
|
80
|
+
|
|
82
81
|
# SECURITY: Enforce length limit on intro message
|
|
83
|
-
[[ ${#DECODED_INTRO} -
|
|
82
|
+
if [[ ${#DECODED_INTRO} -gt 200 ]]; then
|
|
83
|
+
echo "⚠️ Intro message too long, truncating" >&2
|
|
84
|
+
DECODED_INTRO="${DECODED_INTRO:0:200}"
|
|
85
|
+
fi
|
|
84
86
|
fi
|
|
85
87
|
|
|
86
88
|
# Prepend intro to text if configured
|
|
@@ -30,50 +30,26 @@ ENCODED_INTRO="${4:-}"
|
|
|
30
30
|
|
|
31
31
|
# Validate inputs
|
|
32
32
|
if [[ -z "$ENCODED_TEXT" ]]; then
|
|
33
|
-
echo "
|
|
33
|
+
echo "❌ No encoded text provided" >&2
|
|
34
34
|
echo "Usage: $0 <base64_text> <voice> <base64_agent_name> [base64_intro]" >&2
|
|
35
35
|
exit 1
|
|
36
36
|
fi
|
|
37
37
|
|
|
38
|
-
# SECURITY: Validate base64 format (reject shell metacharacters)
|
|
39
|
-
[[ "$ENCODED_TEXT" =~ ^[A-Za-z0-9+/=]+$ ]] || { echo "Error: invalid base64 text" >&2; exit 1; }
|
|
40
|
-
|
|
41
|
-
# SECURITY: Validate voice name format (alphanumeric, hyphens, underscores only)
|
|
42
|
-
[[ "$VOICE" =~ ^[a-zA-Z0-9_-]+$ ]] || { echo "Error: invalid voice format" >&2; exit 1; }
|
|
43
|
-
|
|
44
38
|
# SECURITY: Decode base64 safely
|
|
45
39
|
DECODED_TEXT=$(echo -n "$ENCODED_TEXT" | base64 -d 2>/dev/null) || {
|
|
46
|
-
echo "
|
|
40
|
+
echo "❌ Failed to decode text (invalid base64)" >&2
|
|
47
41
|
exit 1
|
|
48
42
|
}
|
|
49
43
|
|
|
50
|
-
# SECURITY: Enforce length limit on decoded text (10KB max)
|
|
51
|
-
if [[ ${#DECODED_TEXT} -gt 10000 ]]; then
|
|
52
|
-
echo "Error: Decoded text too long (${#DECODED_TEXT} chars, max 10000)" >&2
|
|
53
|
-
exit 1
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
44
|
DECODED_AGENT="default"
|
|
57
45
|
if [[ -n "$ENCODED_AGENT" ]]; then
|
|
58
|
-
|
|
59
|
-
if [[ -n "$ENCODED_AGENT" ]]; then
|
|
60
|
-
DECODED_AGENT=$(echo -n "$ENCODED_AGENT" | base64 -d 2>/dev/null) || DECODED_AGENT="default"
|
|
61
|
-
fi
|
|
62
|
-
# Validate agent name format (alphanumeric, dash, underscore only)
|
|
63
|
-
[[ "$DECODED_AGENT" =~ ^[a-zA-Z0-9_-]+$ ]] || DECODED_AGENT="default"
|
|
64
|
-
# Enforce length limit
|
|
65
|
-
[[ ${#DECODED_AGENT} -le 50 ]] || DECODED_AGENT="default"
|
|
46
|
+
DECODED_AGENT=$(echo -n "$ENCODED_AGENT" | base64 -d 2>/dev/null) || DECODED_AGENT="default"
|
|
66
47
|
fi
|
|
67
48
|
|
|
68
49
|
# Decode and prepend intro if provided
|
|
69
50
|
DECODED_INTRO=""
|
|
70
51
|
if [[ -n "$ENCODED_INTRO" ]]; then
|
|
71
|
-
|
|
72
|
-
if [[ -n "$ENCODED_INTRO" ]]; then
|
|
73
|
-
DECODED_INTRO=$(echo -n "$ENCODED_INTRO" | base64 -d 2>/dev/null) || DECODED_INTRO=""
|
|
74
|
-
fi
|
|
75
|
-
# Enforce length limit on intro (200 chars max)
|
|
76
|
-
[[ ${#DECODED_INTRO} -le 200 ]] || DECODED_INTRO="${DECODED_INTRO:0:200}"
|
|
52
|
+
DECODED_INTRO=$(echo -n "$ENCODED_INTRO" | base64 -d 2>/dev/null) || DECODED_INTRO=""
|
|
77
53
|
fi
|
|
78
54
|
|
|
79
55
|
# Prepend intro to text if configured
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -67,7 +67,7 @@ if [[ -d "/data/data/com.termux" ]]; then
|
|
|
67
67
|
echo ""
|
|
68
68
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
69
69
|
if [[ -f "$SCRIPT_DIR/termux-installer.sh" ]]; then
|
|
70
|
-
exec
|
|
70
|
+
exec "$SCRIPT_DIR/termux-installer.sh" "$@"
|
|
71
71
|
else
|
|
72
72
|
echo "❌ Error: termux-installer.sh not found"
|
|
73
73
|
echo " Please download it from the AgentVibes repository"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -48,18 +48,12 @@ fi
|
|
|
48
48
|
TEXT="$1"
|
|
49
49
|
VOICE_OVERRIDE="$2" # Optional: voice name (e.g., "Samantha", "Daniel")
|
|
50
50
|
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
s/[\x{2500}-\x{257F}]//g;
|
|
58
|
-
s/[\x{2580}-\x{259F}]//g;
|
|
59
|
-
s/\*+//g; s/#+\s*//g; s/`//g; s/~+//g; s/^\s*[-]\s*//g;
|
|
60
|
-
')
|
|
61
|
-
|
|
62
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
51
|
+
# Use readlink -f to handle symlinks correctly
|
|
52
|
+
SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}")"
|
|
53
|
+
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
|
|
54
|
+
|
|
55
|
+
# Source audio cache utilities
|
|
56
|
+
source "$SCRIPT_DIR/audio-cache-utils.sh"
|
|
63
57
|
|
|
64
58
|
# Source audio cache utilities
|
|
65
59
|
source "$SCRIPT_DIR/audio-cache-utils.sh"
|
|
@@ -74,7 +74,9 @@ TEXT=$(printf '%s' "$TEXT" | perl -CSD -pe '
|
|
|
74
74
|
')
|
|
75
75
|
|
|
76
76
|
# Source voice manager and language manager
|
|
77
|
-
|
|
77
|
+
# Use readlink -f to handle symlinks correctly
|
|
78
|
+
SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}")"
|
|
79
|
+
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
|
|
78
80
|
source "$SCRIPT_DIR/piper-voice-manager.sh"
|
|
79
81
|
source "$SCRIPT_DIR/language-manager.sh"
|
|
80
82
|
source "$SCRIPT_DIR/audio-cache-utils.sh"
|
|
@@ -518,10 +520,14 @@ fi
|
|
|
518
520
|
touch "$LOCK_FILE"
|
|
519
521
|
|
|
520
522
|
# Create write lock file in audio directory to signal file is in-use (prevents race condition in cleanup)
|
|
521
|
-
|
|
522
|
-
WRITE_LOCK_FILE="$
|
|
523
|
+
AUDIO_DIR="${TEMP_FILE%/*}"
|
|
524
|
+
WRITE_LOCK_FILE="$AUDIO_DIR/$(basename "$TEMP_FILE" .wav).lock"
|
|
523
525
|
touch "$WRITE_LOCK_FILE"
|
|
524
|
-
|
|
526
|
+
|
|
527
|
+
# Get audio duration for proper lock timing
|
|
528
|
+
DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null)
|
|
529
|
+
DURATION=${DURATION%.*} # Round to integer
|
|
530
|
+
DURATION=${DURATION:-1} # Default to 1 second if detection fails
|
|
525
531
|
|
|
526
532
|
# Get audio duration for proper lock timing
|
|
527
533
|
DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$TEMP_FILE" 2>/dev/null || true)
|
|
@@ -558,95 +564,65 @@ disown
|
|
|
558
564
|
# Get audio cache path
|
|
559
565
|
AUDIO_DIR_PATH=$(get_audio_dir)
|
|
560
566
|
|
|
561
|
-
# Color codes
|
|
567
|
+
# Color codes
|
|
562
568
|
BLUE='\033[0;34m'
|
|
563
569
|
YELLOW='\033[1;33m'
|
|
564
570
|
PURPLE='\033[0;35m'
|
|
571
|
+
LIGHT_PURPLE='\033[1;35m'
|
|
565
572
|
RED='\033[0;31m'
|
|
566
573
|
GREEN='\033[0;32m'
|
|
567
574
|
ORANGE='\033[0;33m'
|
|
568
575
|
WHITE='\033[1;37m'
|
|
576
|
+
MAGENTA='\033[0;35m'
|
|
569
577
|
CYAN='\033[0;36m'
|
|
570
578
|
GOLD='\033[38;5;226m'
|
|
571
579
|
NC='\033[0m'
|
|
572
580
|
|
|
573
|
-
#
|
|
574
|
-
|
|
575
|
-
if [[ -f "$HOME/.agentvibes/banner-disabled" ]]; then
|
|
576
|
-
_BANNER_ENABLED=false
|
|
577
|
-
elif [[ -f "${PROJECT_ROOT:-/nonexistent}/.agentvibes/banner-disabled" ]]; then
|
|
578
|
-
_BANNER_ENABLED=false
|
|
579
|
-
fi
|
|
580
|
-
|
|
581
|
-
# Run auto-cleanup off the critical path: only every 10th call, in background after playback starts.
|
|
582
|
-
# Counter file lives in the secure lock dir (user-specific, already created above).
|
|
581
|
+
# CRITICAL: Run auto-cleanup FIRST (before calculating size)
|
|
582
|
+
# This ensures we display the POST-cleanup size, not pre-cleanup size
|
|
583
583
|
AUTO_CLEAN_THRESHOLD=$(get_auto_clean_threshold)
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
if
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
if (( _CALL_COUNT % 10 == 0 )); then
|
|
592
|
-
# Capture values needed inside the subshell before forking
|
|
593
|
-
_CLEANUP_AUDIO_DIR="$AUDIO_DIR_PATH"
|
|
594
|
-
_CLEANUP_THRESHOLD="$AUTO_CLEAN_THRESHOLD"
|
|
595
|
-
_CLEANUP_BANNER="$_BANNER_ENABLED"
|
|
596
|
-
# Source the utils inside the subshell (functions are not exported)
|
|
597
|
-
_CLEANUP_UTILS="$SCRIPT_DIR/audio-cache-utils.sh"
|
|
598
|
-
(
|
|
599
|
-
source "$_CLEANUP_UTILS" 2>/dev/null || exit 0
|
|
600
|
-
_INITIAL_SIZE=$(calculate_tts_size_bytes "$_CLEANUP_AUDIO_DIR")
|
|
601
|
-
if [[ $_INITIAL_SIZE -gt $((_CLEANUP_THRESHOLD * 1048576)) ]]; then
|
|
602
|
-
_DELETED=$(auto_clean_old_files "$_CLEANUP_AUDIO_DIR" "$_CLEANUP_THRESHOLD")
|
|
603
|
-
if [[ ${_DELETED:-0} -gt 0 ]] && [[ "$_CLEANUP_BANNER" == "true" ]]; then
|
|
604
|
-
echo -e "\033[0;33m🧹 Auto-cleaned $_DELETED old files\033[0m"
|
|
605
|
-
fi
|
|
606
|
-
fi
|
|
607
|
-
) &
|
|
608
|
-
disown
|
|
584
|
+
INITIAL_SIZE=$(calculate_tts_size_bytes "$AUDIO_DIR_PATH")
|
|
585
|
+
if [[ $INITIAL_SIZE -gt $((AUTO_CLEAN_THRESHOLD * 1048576)) ]]; then
|
|
586
|
+
DELETED=$(auto_clean_old_files "$AUDIO_DIR_PATH" "$AUTO_CLEAN_THRESHOLD")
|
|
587
|
+
if [[ $DELETED -gt 0 ]]; then
|
|
588
|
+
echo -e "${ORANGE}🧹 Auto-cleaned $DELETED old files${NC}"
|
|
589
|
+
fi
|
|
609
590
|
fi
|
|
610
591
|
|
|
611
|
-
#
|
|
612
|
-
|
|
613
|
-
|
|
592
|
+
# NOW calculate cache stats after cleanup
|
|
593
|
+
FILE_COUNT=$(count_tts_files "$AUDIO_DIR_PATH")
|
|
594
|
+
SIZE_BYTES=$(calculate_tts_size_bytes "$AUDIO_DIR_PATH")
|
|
595
|
+
SIZE_HUMAN=$(bytes_to_human "$SIZE_BYTES")
|
|
596
|
+
|
|
597
|
+
# Dynamic color coding based on cache size
|
|
598
|
+
# Green: < 500MB (small)
|
|
599
|
+
# Yellow: 500MB - 3GB (lots)
|
|
600
|
+
# Red: > 3GB (extreme)
|
|
601
|
+
CACHE_COLOR=$GREEN
|
|
602
|
+
if [[ $SIZE_BYTES -gt 3221225472 ]]; then # > 3GB
|
|
603
|
+
CACHE_COLOR=$RED
|
|
604
|
+
elif [[ $SIZE_BYTES -gt 524288000 ]]; then # > 500MB
|
|
605
|
+
CACHE_COLOR=$YELLOW
|
|
614
606
|
fi
|
|
615
607
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
SIZE_BYTES=$(calculate_tts_size_bytes "$AUDIO_DIR_PATH")
|
|
619
|
-
SIZE_HUMAN=$(bytes_to_human "$SIZE_BYTES")
|
|
620
|
-
|
|
621
|
-
# Dynamic color coding based on cache size
|
|
622
|
-
CACHE_COLOR=$GREEN
|
|
623
|
-
if [[ $SIZE_BYTES -gt 3221225472 ]]; then
|
|
624
|
-
CACHE_COLOR=$RED
|
|
625
|
-
elif [[ $SIZE_BYTES -gt 524288000 ]]; then
|
|
626
|
-
CACHE_COLOR=$YELLOW
|
|
627
|
-
fi
|
|
608
|
+
# Display with file count (now showing accurate post-cleanup size)
|
|
609
|
+
echo -e "${WHITE}💾 Saved to:${NC} ${CYAN}$TEMP_FILE${NC} ${YELLOW}$FILE_COUNT${NC} ${WHITE}🗄️${NC} ${CACHE_COLOR}$SIZE_HUMAN${NC} ${WHITE}🧹${NC}${GOLD}[${AUTO_CLEAN_THRESHOLD}mb]${NC}"
|
|
628
610
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
echo -e "${WHITE}🎤 Voice used:${NC} ${BLUE}$FILE_VOICE${NC} ${WHITE}(Piper TTS)${NC}"
|
|
636
|
-
else
|
|
637
|
-
echo -e "${WHITE}🎤 Voice used:${NC} ${BLUE}$VOICE_MODEL${NC} ${WHITE}(Piper TTS)${NC}"
|
|
638
|
-
fi
|
|
639
|
-
|
|
640
|
-
PERSONALITY=$(cat "${PROJECT_ROOT:-/nonexistent}/.claude/tts-personality.txt" 2>/dev/null || cat "$HOME/.claude/tts-personality.txt" 2>/dev/null || echo "")
|
|
641
|
-
if [[ -n "$PERSONALITY" ]] && [[ "$PERSONALITY" != "none" ]] && [[ "$PERSONALITY" != "normal" ]]; then
|
|
642
|
-
echo -e "${WHITE}💫 Personality:${NC} ${YELLOW}$PERSONALITY${NC}"
|
|
643
|
-
fi
|
|
611
|
+
if [[ -n "$BACKGROUND_MUSIC" ]]; then
|
|
612
|
+
# Extract just the filename to save space
|
|
613
|
+
MUSIC_FILENAME=$(basename "$BACKGROUND_MUSIC")
|
|
614
|
+
echo -e "${WHITE}🎵 Background music:${NC} ${PURPLE}$MUSIC_FILENAME${NC}"
|
|
615
|
+
fi
|
|
616
|
+
echo -e "${WHITE}🎤 Voice used:${NC} ${BLUE}$VOICE_MODEL${NC} ${WHITE}(Piper TTS)${NC}"
|
|
644
617
|
|
|
645
|
-
|
|
618
|
+
# Show personality if configured
|
|
619
|
+
PERSONALITY=$(cat "$PROJECT_ROOT/.claude/tts-personality.txt" 2>/dev/null || cat "$HOME/.claude/tts-personality.txt" 2>/dev/null || echo "")
|
|
620
|
+
if [[ -n "$PERSONALITY" ]] && [[ "$PERSONALITY" != "none" ]] && [[ "$PERSONALITY" != "normal" ]]; then
|
|
621
|
+
echo -e "${WHITE}💫 Personality:${NC} ${YELLOW}$PERSONALITY${NC}"
|
|
646
622
|
fi
|
|
647
623
|
|
|
648
624
|
# Check audio folder size and warn if getting large
|
|
649
|
-
if [[
|
|
625
|
+
if [[ -d "$AUDIO_DIR_PATH" ]]; then
|
|
650
626
|
AUDIO_SIZE=$(du -sm "$AUDIO_DIR_PATH" 2>/dev/null | cut -f1)
|
|
651
627
|
if [[ -n "$AUDIO_SIZE" ]] && [[ "$AUDIO_SIZE" -gt 100 ]]; then
|
|
652
628
|
echo -e "\033[0;31m⚠️ Audio cache is ${AUDIO_SIZE}MB - Run: /agent-vibes:cleanup\033[0m"
|
|
@@ -673,14 +649,9 @@ fi
|
|
|
673
649
|
if [[ -z "$BACKGROUND_MUSIC" ]]; then
|
|
674
650
|
_bg_enabled=false
|
|
675
651
|
if [[ -f "$BACKGROUND_ENABLED_FILE" ]] && grep -q "true" "$BACKGROUND_ENABLED_FILE" 2>/dev/null; then
|
|
676
|
-
|
|
677
|
-
elif [[ -f "$GLOBAL_BACKGROUND_ENABLED_FILE" ]] && grep -q "true" "$GLOBAL_BACKGROUND_ENABLED_FILE" 2>/dev/null; then
|
|
678
|
-
_bg_enabled=true
|
|
679
|
-
fi
|
|
680
|
-
if [[ "$_bg_enabled" == "true" ]]; then
|
|
681
|
-
echo "🎵 Background music: Enabled but not playing (check config)"
|
|
652
|
+
echo -e "${WHITE}🎵 Background music:${NC} ${PURPLE}Enabled but not playing (check config)${NC}"
|
|
682
653
|
else
|
|
683
|
-
echo "🎵 Background music
|
|
654
|
+
echo -e "${WHITE}🎵 Background music:${NC} ${PURPLE}Disabled${NC}"
|
|
684
655
|
fi
|
|
685
656
|
fi
|
|
686
657
|
|
|
@@ -50,18 +50,9 @@ export LC_ALL=C
|
|
|
50
50
|
TEXT="$1"
|
|
51
51
|
VOICE_OVERRIDE="$2" # Ignored — Soprano has a single voice, kept for provider contract
|
|
52
52
|
|
|
53
|
-
#
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
s/[\x{2600}-\x{27BF}]//g;
|
|
57
|
-
s/[\x{FE00}-\x{FE0F}]//g;
|
|
58
|
-
s/[\x{200D}]//g;
|
|
59
|
-
s/[\x{2500}-\x{257F}]//g;
|
|
60
|
-
s/[\x{2580}-\x{259F}]//g;
|
|
61
|
-
s/\*+//g; s/#+\s*//g; s/`//g; s/~+//g; s/^\s*[-]\s*//g;
|
|
62
|
-
')
|
|
63
|
-
|
|
64
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
53
|
+
# Use readlink -f to handle symlinks correctly
|
|
54
|
+
SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}")"
|
|
55
|
+
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
|
|
65
56
|
source "$SCRIPT_DIR/audio-cache-utils.sh"
|
|
66
57
|
|
|
67
58
|
SOPRANO_PORT="${SOPRANO_PORT:-7860}"
|
|
@@ -114,11 +105,7 @@ fi
|
|
|
114
105
|
# @intent Find appropriate directory for audio file storage
|
|
115
106
|
# @why Supports project-local and global storage
|
|
116
107
|
# @returns Sets $AUDIO_DIR global variable
|
|
117
|
-
|
|
118
|
-
if [[ -n "${CLAUDE_PROJECT_DIR:-}" ]]; then
|
|
119
|
-
CLAUDE_PROJECT_DIR=$(cd "${CLAUDE_PROJECT_DIR}" 2>/dev/null && pwd -P) || CLAUDE_PROJECT_DIR=""
|
|
120
|
-
fi
|
|
121
|
-
if [[ -n "${CLAUDE_PROJECT_DIR:-}" ]]; then
|
|
108
|
+
if [[ -n "$CLAUDE_PROJECT_DIR" ]]; then
|
|
122
109
|
AUDIO_DIR="$CLAUDE_PROJECT_DIR/.claude/audio"
|
|
123
110
|
else
|
|
124
111
|
CURRENT_DIR="$PWD"
|
|
@@ -135,8 +122,7 @@ else
|
|
|
135
122
|
fi
|
|
136
123
|
|
|
137
124
|
mkdir -p "$AUDIO_DIR"
|
|
138
|
-
|
|
139
|
-
_tmp=$(mktemp "$AUDIO_DIR/tts-XXXXXX"); TEMP_FILE="${_tmp}.wav"; mv "$_tmp" "$TEMP_FILE"
|
|
125
|
+
TEMP_FILE="$AUDIO_DIR/tts-$(date +%s).wav"
|
|
140
126
|
|
|
141
127
|
# @function synthesize_speech
|
|
142
128
|
# @intent Generate speech using best available Soprano mode
|
|
@@ -153,12 +139,9 @@ if check_webui_server; then
|
|
|
153
139
|
elif check_api_server; then
|
|
154
140
|
# OpenAI-compatible API mode — direct curl
|
|
155
141
|
SYNTH_MODE="api"
|
|
156
|
-
# SECURITY: Use proper JSON encoding to prevent injection (#133)
|
|
157
|
-
_JSON_PAYLOAD=$(printf '%s' "$TEXT" | python3 -c 'import sys,json; print(json.dumps({"input":sys.stdin.read()}))' 2>/dev/null) || \
|
|
158
|
-
_JSON_PAYLOAD=$(printf '{"input":"%s"}' "$(printf '%s' "$TEXT" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g')")
|
|
159
142
|
curl -sf "http://127.0.0.1:${SOPRANO_PORT}/v1/audio/speech" \
|
|
160
143
|
-H "Content-Type: application/json" \
|
|
161
|
-
-d "$
|
|
144
|
+
-d "$(printf '{"input":"%s"}' "$(echo "$TEXT" | sed 's/"/\\"/g')")" \
|
|
162
145
|
--output "$TEMP_FILE" 2>/dev/null
|
|
163
146
|
else
|
|
164
147
|
# CLI fallback — reloads model each call (slowest)
|
|
@@ -187,7 +170,7 @@ fi
|
|
|
187
170
|
# @intent Compress TTS audio for remote sessions (SSH/RDP)
|
|
188
171
|
# @why Reduces bandwidth and prevents choppy playback
|
|
189
172
|
if [[ "${AGENTVIBES_RDP_MODE:-false}" == "true" ]] && command -v ffmpeg &>/dev/null; then
|
|
190
|
-
|
|
173
|
+
COMPRESSED_FILE="$AUDIO_DIR/tts-compressed-$(date +%s).wav"
|
|
191
174
|
ffmpeg -i "$TEMP_FILE" -ac 1 -ar 22050 -b:a 64k -y "$COMPRESSED_FILE" 2>/dev/null
|
|
192
175
|
if [[ -f "$COMPRESSED_FILE" ]]; then
|
|
193
176
|
rm -f "$TEMP_FILE"
|
|
@@ -199,7 +182,7 @@ fi
|
|
|
199
182
|
# @intent Add silence to prevent WSL audio static
|
|
200
183
|
# @why WSL audio subsystem cuts off first ~200ms
|
|
201
184
|
if command -v ffmpeg &>/dev/null; then
|
|
202
|
-
|
|
185
|
+
PADDED_FILE="$AUDIO_DIR/tts-padded-$(date +%s).wav"
|
|
203
186
|
ffmpeg -f lavfi -i anullsrc=r=44100:cl=stereo:d=0.2 -i "$TEMP_FILE" \
|
|
204
187
|
-filter_complex "[0:a][1:a]concat=n=2:v=0:a=1[out]" \
|
|
205
188
|
-map "[out]" -y "$PADDED_FILE" 2>/dev/null
|
|
@@ -231,24 +214,7 @@ fi
|
|
|
231
214
|
# @function play_audio
|
|
232
215
|
# @intent Play generated audio using available player with sequential playback
|
|
233
216
|
# @why Support multiple audio players and prevent overlapping audio
|
|
234
|
-
|
|
235
|
-
_LOCK_DIR="${XDG_RUNTIME_DIR:-/tmp/agentvibes-$(id -u)}"
|
|
236
|
-
mkdir -p "$_LOCK_DIR"
|
|
237
|
-
chmod 700 "$_LOCK_DIR"
|
|
238
|
-
LOCK_FILE="$_LOCK_DIR/agentvibes-audio.lock"
|
|
239
|
-
|
|
240
|
-
# Auto-remove stale lock files (older than 30 seconds)
|
|
241
|
-
if [ -f "$LOCK_FILE" ]; then
|
|
242
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
243
|
-
_lock_mtime=$(stat -f %m "$LOCK_FILE" 2>/dev/null || echo 0)
|
|
244
|
-
else
|
|
245
|
-
_lock_mtime=$(stat -c %Y "$LOCK_FILE" 2>/dev/null || echo 0)
|
|
246
|
-
fi
|
|
247
|
-
_lock_age=$(( $(date +%s) - _lock_mtime ))
|
|
248
|
-
if [[ $_lock_age -gt 30 ]]; then
|
|
249
|
-
rm -f "$LOCK_FILE"
|
|
250
|
-
fi
|
|
251
|
-
fi
|
|
217
|
+
LOCK_FILE="/tmp/agentvibes-audio.lock"
|
|
252
218
|
|
|
253
219
|
for i in {1..4}; do
|
|
254
220
|
if [ ! -f "$LOCK_FILE" ]; then
|