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
@@ -242,7 +242,11 @@ try {
242
242
  try {
243
243
  # WaitOne throws AbandonedMutexException if prior process crashed while holding it.
244
244
  # That exception means we DID acquire the mutex — treat it as success (fixes M2).
245
- $acquired = $mutex.WaitOne(60000)
245
+ # 600s timeout covers worst-case party-mode queue depth (9 agents x
246
+ # ~60s of speech each). Shorter timeouts silently dropped the last
247
+ # agents to speak. play-tts.ps1 bounds true stuck processes via its
248
+ # playback watchdog, so waiting longer here is safe.
249
+ $acquired = $mutex.WaitOne(600000)
246
250
  } catch [System.Threading.AbandonedMutexException] {
247
251
  $acquired = $true # abandoned = we now own it
248
252
  }
@@ -16,14 +16,28 @@ param(
16
16
  [string]$llm = ""
17
17
  )
18
18
 
19
+ # Text-file handoff: Windows command-line arg passing mangles text with
20
+ # quotes, newlines, or non-ASCII characters. The SSH receiver watcher
21
+ # (setup-ssh-receiver.ps1) writes long/special-char text to a UTF-8 temp
22
+ # file and passes the sentinel "__from_file__" + AGENTVIBES_TEXT_FILE env
23
+ # var. Load the real text here before any validation or synthesis.
24
+ if ($Text -eq "__from_file__" -and $env:AGENTVIBES_TEXT_FILE) {
25
+ if (Test-Path $env:AGENTVIBES_TEXT_FILE) {
26
+ $Text = [System.IO.File]::ReadAllText($env:AGENTVIBES_TEXT_FILE, [System.Text.UTF8Encoding]::new($false))
27
+ } else {
28
+ Write-Error "AGENTVIBES_TEXT_FILE set to missing path: $($env:AGENTVIBES_TEXT_FILE)"
29
+ exit 1
30
+ }
31
+ }
32
+
19
33
  # Security: Validate LLM provider name (alphanumeric, hyphens, underscores
20
34
  # only) -- mirrors play-tts.sh line 92. This prevents weird values from
21
35
  # poisoning the audio-effects.cfg lookup or the AGENTVIBES_LLM_KEY env var
22
36
  # we export to child scripts. An invalid value is treated as unset rather
23
37
  # than aborting, so the script falls back to the default config and the
24
38
  # rest of TTS still works.
25
- if ($llm -and $llm -notmatch '^[a-zA-Z0-9_-]+$') {
26
- Write-Error ("Invalid LLM provider name: '{0}' - must match {1}. Falling back to default config." -f $llm, '^[a-zA-Z0-9_-]+$')
39
+ if ($llm -and $llm -notmatch '^[a-zA-Z0-9][a-zA-Z0-9_-]*$') {
40
+ Write-Error ("Invalid LLM provider name: '{0}' - must match {1}. Falling back to default config." -f $llm, '^[a-zA-Z0-9][a-zA-Z0-9_-]*$')
27
41
  $llm = ""
28
42
  }
29
43
 
@@ -53,63 +67,42 @@ if (-not $llm) {
53
67
  # process's playback.
54
68
  $_PlaybackMutex = New-Object System.Threading.Mutex($false, "AgentVibesPlaybackLock")
55
69
 
56
- # --- Script-level watchdog ---
57
- # If anything in this script hangs (SoundPlayer deadlock, audio device
58
- # locked, ffmpeg stuck, etc.), a sibling PowerShell job waits 25 seconds
59
- # and force-kills this process. Without this, a stuck play-tts.ps1 holds
60
- # the playback mutex forever and silently blocks every subsequent TTS
61
- # call across all LLMs. The watchdog guarantees forward progress.
70
+ # --- Playback watchdog ---
71
+ # If playback itself hangs (SoundPlayer deadlock, audio device locked,
72
+ # etc.), a sibling PowerShell job waits 120 seconds from the moment
73
+ # playback STARTS and force-kills this process. Without this, a stuck
74
+ # play-tts.ps1 holds the playback mutex forever and silently blocks every
75
+ # subsequent TTS call across all LLMs.
62
76
  #
63
- # 25s is chosen to be LONGER than the mutex timeout (15s) but SHORT
64
- # enough that a stuck process clears before the user's next turn. If
65
- # you fire two calls per turn and the first is stuck, the watchdog kills
66
- # it before the second turn arrives so the audio subsystem recovers
67
- # without manual intervention. Long legitimate messages (>25s of speech)
68
- # are rare at default verbosity levels; when they do occur the watchdog
69
- # kills playback mid-sentence, which is acceptable degradation vs. a
70
- # deadlocked queue.
71
- $_WatchdogJob = $null
72
- try {
73
- $_WatchdogJob = Start-Job -ArgumentList $PID -ScriptBlock {
74
- param($parentPid)
75
- Start-Sleep -Seconds 25
76
- try {
77
- # Only kill if still alive -- harmless if already exited
78
- $p = Get-Process -Id $parentPid -ErrorAction SilentlyContinue
79
- if ($p) {
80
- [Console]::Error.WriteLine("[AgentVibes] play-tts.ps1 watchdog fired -- force-killing pid $parentPid after 25s")
81
- Stop-Process -Id $parentPid -Force -ErrorAction SilentlyContinue
82
- }
83
- } catch { }
84
- }
85
- } catch {
86
- # If Start-Job fails (rare), just continue without the watchdog -- no
87
- # regression from pre-watchdog behavior.
88
- $_WatchdogJob = $null
89
- }
77
+ # IMPORTANT: the watchdog is started AFTER mutex acquisition (inside
78
+ # Invoke-SerializedPlay), not at script entry. Starting it at script
79
+ # entry caused round-robin / party-mode cut-offs: when 9 agents fire
80
+ # text_to_speech in quick succession, later calls spend most of their
81
+ # 120s budget waiting for the mutex, then get killed mid-playback.
82
+ # The mutex WaitOne() bounds queue waiting separately.
90
83
 
91
84
  function Invoke-SerializedPlay {
92
85
  param([Parameter(Mandatory)][string]$WavPath)
93
86
  $acquired = $false
87
+ $watchdogJob = $null
94
88
  try {
95
89
  try {
96
- # 15s timeout to acquire the playback mutex. If we can't get
97
- # it in 15s, the holder is almost certainly a stuck/crashed
98
- # prior run. AbandonedMutexException means the holder's
99
- # process actually died -- we inherit ownership.
100
- $acquired = $_PlaybackMutex.WaitOne(15000)
90
+ # 600s timeout to acquire the playback mutex. Covers worst-case
91
+ # queue depth (round-robin with 9 agents x ~60s of playback each).
92
+ # AbandonedMutexException means the holder's process actually
93
+ # died -- we inherit ownership.
94
+ $acquired = $_PlaybackMutex.WaitOne(600000)
101
95
  } catch [System.Threading.AbandonedMutexException] {
102
96
  $acquired = $true
103
97
  }
104
98
  if (-not $acquired) {
105
99
  # Self-heal: kill any stuck play-tts.ps1 processes (other than
106
- # ourselves) that have been alive longer than 20 seconds. This
107
- # frees the mutex so the NEXT call can succeed without the user
108
- # running taskkill manually. We still exit with code 2 because
109
- # this call's audio is lost, but the queue recovers immediately.
100
+ # ourselves) that have been alive longer than 10 minutes. Past
101
+ # any legitimate playback window, so only truly stuck processes
102
+ # get killed.
110
103
  try {
111
104
  $myPid = $PID
112
- $cutoff = (Get-Date).AddSeconds(-20)
105
+ $cutoff = (Get-Date).AddSeconds(-600)
113
106
  $stuck = Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
114
107
  Where-Object {
115
108
  $_.Name -eq 'powershell.exe' -and
@@ -122,9 +115,28 @@ function Invoke-SerializedPlay {
122
115
  Stop-Process -Id $p.ProcessId -Force -ErrorAction SilentlyContinue
123
116
  }
124
117
  } catch { }
125
- [Console]::Error.WriteLine("[AgentVibes] ERROR: play-tts.ps1 could not acquire playback mutex within 15s. A prior play-tts.ps1 process was stuck holding it and has been killed; the next TTS call should succeed.")
118
+ [Console]::Error.WriteLine("[AgentVibes] ERROR: play-tts.ps1 could not acquire playback mutex within 600s. A prior play-tts.ps1 process was stuck holding it and has been killed; the next TTS call should succeed.")
126
119
  exit 2
127
120
  }
121
+
122
+ # Start the watchdog NOW (after mutex acquisition) so its 120s
123
+ # budget covers only the playback itself, not time spent queued.
124
+ try {
125
+ $watchdogJob = Start-Job -ArgumentList $PID -ScriptBlock {
126
+ param($parentPid)
127
+ Start-Sleep -Seconds 120
128
+ try {
129
+ $p = Get-Process -Id $parentPid -ErrorAction SilentlyContinue
130
+ if ($p) {
131
+ [Console]::Error.WriteLine("[AgentVibes] play-tts.ps1 playback watchdog fired -- force-killing pid $parentPid after 120s of playback")
132
+ Stop-Process -Id $parentPid -Force -ErrorAction SilentlyContinue
133
+ }
134
+ } catch { }
135
+ }
136
+ } catch {
137
+ $watchdogJob = $null
138
+ }
139
+
128
140
  $player = $null
129
141
  try {
130
142
  $player = New-Object System.Media.SoundPlayer $WavPath
@@ -133,23 +145,18 @@ function Invoke-SerializedPlay {
133
145
  if ($player) { $player.Dispose() }
134
146
  }
135
147
  } finally {
148
+ if ($watchdogJob) {
149
+ try {
150
+ Stop-Job -Job $watchdogJob -ErrorAction SilentlyContinue
151
+ Remove-Job -Job $watchdogJob -Force -ErrorAction SilentlyContinue
152
+ } catch { }
153
+ }
136
154
  if ($acquired) {
137
155
  try { $_PlaybackMutex.ReleaseMutex() } catch { }
138
156
  }
139
157
  }
140
158
  }
141
159
 
142
- # Register an exit handler that stops the watchdog job on normal exit so
143
- # it doesn't fire on successful short runs.
144
- Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
145
- try {
146
- if ($_WatchdogJob) {
147
- Stop-Job -Job $_WatchdogJob -ErrorAction SilentlyContinue
148
- Remove-Job -Job $_WatchdogJob -Force -ErrorAction SilentlyContinue
149
- }
150
- } catch { }
151
- } | Out-Null
152
-
153
160
  # Configuration paths
154
161
  # Priority: CLAUDE_PROJECT_DIR env var -> script's parent project -> user profile
155
162
  # Local project settings ALWAYS override global (~/.claude)
@@ -249,11 +256,26 @@ if ($llm) {
249
256
  $env:AGENTVIBES_LLM_KEY = "llm:$llm"
250
257
  }
251
258
 
259
+ # ---------------------------------------------------------------------------
260
+ # Per-call env-var overrides (set by the SSH watcher from queue JSON).
261
+ # These win over audio-effects.cfg lookup results for this call only.
262
+ # ---------------------------------------------------------------------------
263
+ if ($env:AGENTVIBES_OVERRIDE_MUSIC) { $LlmBgTrack = $env:AGENTVIBES_OVERRIDE_MUSIC }
264
+ if ($env:AGENTVIBES_OVERRIDE_VOLUME) { $LlmBgVolume = $env:AGENTVIBES_OVERRIDE_VOLUME }
265
+ if ($env:AGENTVIBES_OVERRIDE_EFFECTS) { $LlmReverb = $env:AGENTVIBES_OVERRIDE_EFFECTS }
266
+
252
267
  # Prepend pretext if configured
253
268
  # Priority: LLM-specific pretext -> project .agentvibes/config.json -> project .claude/config/tts-pretext.txt
254
269
  # -> global ~/.agentvibes/config.json -> global ~/.claude/config/tts-pretext.txt
255
- $Pretext = $LlmPretext
256
- if (-not $Pretext) {
270
+ #
271
+ # Honor AGENTVIBES_NO_PRETEXT=1 for callers that already prepended a pretext
272
+ # (e.g., the SSH receiver watcher — server already added its own pretext
273
+ # before sending; double-prepending here would say "AgentVibes here, server-pretext, message").
274
+ $Pretext = ""
275
+ if ($env:AGENTVIBES_NO_PRETEXT -ne "1") {
276
+ $Pretext = $LlmPretext
277
+ }
278
+ if (-not $Pretext -and $env:AGENTVIBES_NO_PRETEXT -ne "1") {
257
279
  $PretextSources = @(
258
280
  (Join-Path $ProjectRoot ".agentvibes\config.json"),
259
281
  "$ClaudeDir\config\tts-pretext.txt",
@@ -569,6 +591,16 @@ if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
569
591
  $DefaultTrack = "agent_vibes_celtic_harp_v1_loop.mp3"
570
592
  }
571
593
 
594
+ # Per-call env-var overrides (set by SSH watcher from queue JSON).
595
+ # Win over audio-effects.cfg lookup above. Validate filename to
596
+ # prevent path traversal before accepting.
597
+ if ($env:AGENTVIBES_OVERRIDE_MUSIC -and $env:AGENTVIBES_OVERRIDE_MUSIC -match '^[a-zA-Z0-9_\-\. ]+$') {
598
+ $DefaultTrack = $env:AGENTVIBES_OVERRIDE_MUSIC
599
+ }
600
+ if ($env:AGENTVIBES_OVERRIDE_VOLUME -and $env:AGENTVIBES_OVERRIDE_VOLUME -match '^\d+\.?\d*$') {
601
+ $BgVolume = $env:AGENTVIBES_OVERRIDE_VOLUME
602
+ }
603
+
572
604
  $BgTrackPath = Join-Path $TracksDir $DefaultTrack
573
605
  # Path containment: verify resolved path stays within tracks directory
574
606
  $ResolvedBgTrack = [System.IO.Path]::GetFullPath($BgTrackPath)
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![Publish](https://github.com/paulpreibisch/AgentVibes/actions/workflows/publish.yml/badge.svg)](https://github.com/paulpreibisch/AgentVibes/actions/workflows/publish.yml)
12
12
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
13
13
 
14
- **Author**: Paul Preibisch ([@997Fire](https://x.com/997Fire)) | **Version**: v5.2.0
14
+ **Author**: Paul Preibisch ([@997Fire](https://x.com/997Fire)) | **Version**: v5.3.0
15
15
 
16
16
  ---
17
17
 
@@ -43,7 +43,26 @@ Whether you're using Claude Code, GitHub Copilot, OpenAI Codex, Claude Desktop,
43
43
 
44
44
  ---
45
45
 
46
- ## 🎯 NEW IN v5.2.0 — Remote Voice Preview + Caveman Mode + Voice Ratings
46
+ ## 🎯 NEW IN v5.3.0 — Take Control of Remote Voices
47
+
48
+ - **Customize every remote announcement individually** — pass `--voice`, `--pretext`, `--music`, `--volume`, `--effects`, `--speed`, `--provider` on the command line for just that one message. No more editing config files and changing them back.
49
+ - **Skip the intro phrase on demand** — `--pretext ""` suppresses the pretext for a single message.
50
+ - **Long messages and special characters work correctly on Windows** — text with quotes, apostrophes, emoji, or multi-line content no longer gets truncated on its way to the voice engine.
51
+ - **Voice playback works on Windows servers with no monitor** — a background helper runs in your user session and picks up announcements from a queue, so audio plays even when SSH'ing in headless.
52
+ - **Voice preview on remote servers streams to the right device** — TUI preview no longer falls back to local audio on machines without speakers.
53
+ - **No more double intro phrases** when both sender and receiver have pretext configured.
54
+ - **55 new tests** for BMAD party mode voice assignment and agent isolation.
55
+
56
+ ## 🎯 v5.2.1 — Multi-LLM Identity & Install Polish
57
+
58
+ - **Copilot gets its own voice + pretext + music** — "Copilot here" with bossa nova, fully distinct from Claude Code and Codex.
59
+ - **Per-tool MCP configs with explicit identity** — `.vscode/mcp.json`, `.codex/config.toml`, `~/.copilot/mcp-config.json` each set their own `AGENTVIBES_LLM`.
60
+ - **`get_config` MCP tool returns detected LLM** — calling assistants can confirm their routing and respond with the right voice.
61
+ - **Setup nav: Install → Install → Install → Configure → Configure → Configure** — keyboard flow walks all three providers' Configures before landing on Default.
62
+ - **Claude Code default background music** set to Chillwave.
63
+ - **Linux compatibility refinements** — CRLF, permissions, transport provider override.
64
+
65
+ ## 🎯 v5.2.0 — Remote Voice Preview + Caveman Mode + Voice Ratings
47
66
 
48
67
  - **Caveman verbosity mode** — Ultra-terse TTS fragments. Set via `/agent-vibes:verbosity caveman`.
49
68
  - **👍/👎 voice ratings** — Press `+` to thumbs up, `-` to thumbs down in any voice list. Replaces star favorites.
package/RELEASE_NOTES.md CHANGED
@@ -1,5 +1,135 @@
1
1
  # AgentVibes Release Notes
2
2
 
3
+ ## 🎯 v5.3.0 — Take Control of Remote Voices
4
+
5
+ **Release Date:** April 2026
6
+
7
+ If you're using AgentVibes to send voice announcements from a server to
8
+ your phone, laptop, or another machine, this release puts you in the
9
+ driver's seat. Every call can now pick its own voice, background music,
10
+ intro phrase, reverb, volume, and speed — right from the command line,
11
+ for just that one message.
12
+
13
+ ### ✨ What's New
14
+
15
+ #### You can now customize every announcement individually
16
+
17
+ Before, if you wanted a different voice or music for one specific
18
+ message, you had to change a config file (and remember to change it
19
+ back). Now you just add a flag to the command.
20
+
21
+ Want Winston to speak in his British accent with jazz playing for this
22
+ one deploy notification? Easy:
23
+
24
+ ```bash
25
+ bash .claude/hooks/play-tts-ssh-remote.sh \
26
+ --text "Deploy complete" \
27
+ --voice "en_US-ryan-high" \
28
+ --pretext "Winston here" \
29
+ --music "Late Night Hip Hop Groove.mp3" \
30
+ --volume 0.25
31
+ ```
32
+
33
+ Anything you don't specify falls back to your normal settings. Want to
34
+ skip the intro phrase just this once? Pass `--pretext ""` and it stays
35
+ silent before the message.
36
+
37
+ **Available flags:**
38
+ - `--voice` — which Piper voice to use
39
+ - `--pretext` — the intro phrase before the message (pass `""` to skip it)
40
+ - `--music` — background music track (filenames with spaces now work!)
41
+ - `--volume` — how loud the background music is (0.0 to 1.0)
42
+ - `--effects` — sound effects chain like reverb
43
+ - `--speed` — how fast the voice speaks
44
+ - `--provider` — which TTS engine to use
45
+ - `--agent` — which agent personality to use
46
+
47
+ The old way of calling the script still works, so nothing you've already
48
+ set up will break.
49
+
50
+ ### 🛠 Reliability Fixes
51
+
52
+ - **Long messages and special characters no longer get cut off.** On
53
+ Windows, long announcements or text with quotes, apostrophes, or
54
+ emoji were getting mangled before they reached the voice engine.
55
+ Fixed — your message now arrives exactly as you sent it, no matter
56
+ how long or weird.
57
+
58
+ - **Voice announcements now work on Windows servers with no monitor.**
59
+ Windows refuses to play audio in the "service" session that SSH
60
+ normally uses. A small background helper now runs in your regular
61
+ user session and picks up announcements from a queue, so audio plays
62
+ correctly even on headless servers.
63
+
64
+ - **Voice preview in the TUI works on remote servers.** Before, if you
65
+ previewed a voice from a server with no speakers, it would try to
66
+ play locally (and fail). Now it correctly streams to whatever remote
67
+ device you've configured.
68
+
69
+ - **No more double intro phrases.** If you set a pretext on both the
70
+ sending server and the receiving machine, you used to hear it twice.
71
+ The sender's version wins now — the receiver won't add its own on top.
72
+
73
+ - **Remote streaming settings now actually stick.** A recent change
74
+ accidentally caused remote-streaming setups (`ssh-remote`,
75
+ `agentvibes-receiver`) to get overridden and fall back to local
76
+ playback. Fixed.
77
+
78
+ - **Long announcements don't get killed mid-sentence.** The safety
79
+ timeout that stops stuck audio was too aggressive for long messages.
80
+ It's now generous enough to handle paragraph-length announcements.
81
+
82
+ - **Cleaner installer state** — when you install AgentVibes for Claude
83
+ Code, it now writes its TTS provider file explicitly instead of
84
+ relying on implicit state.
85
+
86
+ ### 🧪 Testing
87
+
88
+ 55 new tests make sure BMAD party mode keeps working: each agent gets
89
+ their unique voice and music, agents don't accidentally share the same
90
+ Piper speaker ID, and the installer always points party mode at the
91
+ cross-platform entry point.
92
+
93
+ ---
94
+
95
+ ## 🎯 v5.2.1 — Multi-LLM Identity & Install Polish
96
+
97
+ **Release Date:** April 2026
98
+
99
+ Polished LLM routing for Copilot/Codex and refined the setup experience.
100
+
101
+ ### ✨ What's New
102
+
103
+ #### Multi-LLM Identity Routing
104
+
105
+ - **GitHub Copilot now gets its own voice, pretext, and background music** — fully distinct from Claude Code and Codex. Say hello to "Copilot here" with bossa nova on the way in.
106
+
107
+ - **Per-tool MCP configs with explicit identity** — each AI tool (`.vscode/mcp.json`, `.codex/config.toml`, `~/.copilot/mcp-config.json`) sets its own `AGENTVIBES_LLM` so routing is deterministic.
108
+
109
+ - **`get_config` MCP tool now returns the detected LLM** — so the calling assistant can confirm its routing and respond with the right voice out of the gate.
110
+
111
+ - **Linux compatibility refinements** — CRLF line endings, permissions, and transport provider override handling.
112
+
113
+ #### Setup Flow Improvements
114
+
115
+ - **Keyboard navigation flow** — pressing Enter through the Install buttons (Claude → Copilot → Codex) now jumps to **Claude Configure** next, letting you walk all three Configures in order before landing on Default.
116
+
117
+ - **Down-arrow skips the Default row** from Install/Remove columns (consistent with info-box dismiss nav).
118
+
119
+ - **Partial install success messaging** — if file copies succeed but MCP config needs a nudge, you'll see a clear warning instead of a generic failure.
120
+
121
+ #### Defaults
122
+
123
+ - **Claude Code default background music** set to Chillwave (`agent_vibes_chillwave_v2_loop.mp3`).
124
+
125
+ #### Under the Hood
126
+
127
+ - LLM key validation tightened for safer env var handling.
128
+ - Improved error logging for edge cases in Copilot CLI config writes.
129
+ - Known limitation documented: if you launch VS Code from a Claude-Code-started terminal, `CLAUDECODE=1` can leak — workaround is to `unset CLAUDECODE` first.
130
+
131
+ ---
132
+
3
133
  ## 🎯 v5.2.0 — Remote Voice Preview + Caveman Mode + Voice Ratings
4
134
 
5
135
  **Release Date:** April 2026