agentvibes 5.1.0 → 5.1.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.
@@ -10,21 +10,25 @@ param(
10
10
  [string]$Text,
11
11
 
12
12
  [Parameter(Mandatory = $false, Position = 1)]
13
- [string]$VoiceOverride
13
+ [string]$VoiceOverride,
14
+
15
+ [Parameter(Mandatory = $false)]
16
+ [string]$llm = ""
14
17
  )
15
18
 
16
19
  # Configuration paths
17
20
  # Priority: CLAUDE_PROJECT_DIR env var → script's parent project → user profile
21
+ # Local project settings ALWAYS override global (~/.claude)
18
22
  $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
19
23
 
20
24
  if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\.claude")) {
21
25
  $ClaudeDir = "$env:CLAUDE_PROJECT_DIR\.claude"
22
26
  } else {
23
27
  $PackageClaudeDir = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptPath)) ".claude"
24
- if (Test-Path "$env:USERPROFILE\.claude\tts-provider.txt") {
25
- $ClaudeDir = "$env:USERPROFILE\.claude"
26
- } elseif (Test-Path $PackageClaudeDir) {
28
+ if (Test-Path $PackageClaudeDir) {
27
29
  $ClaudeDir = $PackageClaudeDir
30
+ } elseif (Test-Path "$env:USERPROFILE\.claude\tts-provider.txt") {
31
+ $ClaudeDir = "$env:USERPROFILE\.claude"
28
32
  } else {
29
33
  $ClaudeDir = "$env:USERPROFILE\.claude"
30
34
  }
@@ -42,9 +46,88 @@ if (Test-Path $MuteFile) {
42
46
  }
43
47
  }
44
48
 
49
+ # Per-LLM config lookup: if --llm is passed, look up llm:<name> in audio-effects.cfg
50
+ # Format: llm:<name>|SOX_EFFECTS|BACKGROUND_FILE|BACKGROUND_VOLUME|VOICE|PRETEXT
51
+ $LlmVoice = ""
52
+ $LlmPretext = ""
53
+ $LlmReverb = ""
54
+ $LlmEngine = ""
55
+ $ProjectRoot = Split-Path -Parent $ClaudeDir
56
+ $ConfigDir = "$ClaudeDir\config"
57
+
58
+ if ($llm) {
59
+ $llmKey = "llm:$llm"
60
+ # Check project-local audio-effects.cfg first, then global
61
+ $cfgPaths = @(
62
+ "$ConfigDir\audio-effects.cfg",
63
+ "$env:USERPROFILE\.claude\config\audio-effects.cfg"
64
+ )
65
+ foreach ($cfgPath in $cfgPaths) {
66
+ if (-not $LlmVoice -and -not $LlmPretext -and (Test-Path $cfgPath)) {
67
+ foreach ($line in (Get-Content $cfgPath)) {
68
+ if ($line -match "^$([regex]::Escape($llmKey))\|") {
69
+ $parts = $line -split '\|'
70
+ # parts: [0]=key [1]=reverb_preset [2]=bg_file [3]=bg_vol [4]=voice [5]=pretext
71
+ if ($parts.Length -ge 2 -and $parts[1].Trim()) {
72
+ $LlmReverb = $parts[1].Trim()
73
+ }
74
+ if ($parts.Length -ge 5 -and $parts[4].Trim()) {
75
+ $LlmVoice = $parts[4].Trim()
76
+ }
77
+ if ($parts.Length -ge 6 -and $parts[5].Trim()) {
78
+ $LlmPretext = $parts[5].Trim()
79
+ }
80
+ if ($parts.Length -ge 7 -and $parts[6].Trim()) {
81
+ $LlmEngine = $parts[6].Trim()
82
+ }
83
+ break
84
+ }
85
+ }
86
+ }
87
+ }
88
+ # Apply LLM voice override (only if no explicit VoiceOverride was passed)
89
+ if ($LlmVoice -and -not $VoiceOverride) {
90
+ $VoiceOverride = $LlmVoice
91
+ }
92
+ # Export LLM key for child scripts (process-local, not system-wide)
93
+ $env:AGENTVIBES_LLM_KEY = "llm:$llm"
94
+ }
95
+
96
+ # Prepend pretext if configured
97
+ # Priority: LLM-specific pretext → project .agentvibes/config.json → project .claude/config/tts-pretext.txt
98
+ # → global ~/.agentvibes/config.json → global ~/.claude/config/tts-pretext.txt
99
+ $Pretext = $LlmPretext
100
+ if (-not $Pretext) {
101
+ $PretextSources = @(
102
+ (Join-Path $ProjectRoot ".agentvibes\config.json"),
103
+ "$ClaudeDir\config\tts-pretext.txt",
104
+ "$env:USERPROFILE\.agentvibes\config.json",
105
+ "$env:USERPROFILE\.claude\config\tts-pretext.txt"
106
+ )
107
+ foreach ($src in $PretextSources) {
108
+ if (-not $Pretext -and (Test-Path $src)) {
109
+ if ($src -match '\.json$') {
110
+ try {
111
+ $avCfg = Get-Content $src -Raw | ConvertFrom-Json
112
+ if ($avCfg.pretext) { $Pretext = $avCfg.pretext.Trim() }
113
+ } catch { }
114
+ } else {
115
+ $val = (Get-Content $src -Raw).Trim()
116
+ if ($val) { $Pretext = $val }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ if ($Pretext) {
122
+ $Text = "$Pretext, $Text"
123
+ }
124
+
45
125
  # Determine active provider
126
+ # LLM-specific engine overrides global provider
46
127
  $ActiveProvider = "sapi"
47
- if (Test-Path $ProviderFile) {
128
+ if ($LlmEngine) {
129
+ $ActiveProvider = $LlmEngine
130
+ } elseif (Test-Path $ProviderFile) {
48
131
  $ActiveProvider = (Get-Content $ProviderFile -Raw).Trim()
49
132
  }
50
133
 
@@ -101,12 +184,17 @@ if (Test-Path $AgentVibesConfig) {
101
184
  }
102
185
 
103
186
  # Check if reverb is enabled (allowlist validation)
187
+ # LLM-specific reverb overrides global setting
104
188
  $ReverbLevel = "off"
105
- $ReverbFile = "$ConfigDir\reverb-level.txt"
106
- if (Test-Path $ReverbFile) {
107
- $reverbVal = (Get-Content $ReverbFile -Raw).Trim()
108
- if ($reverbVal -in @("off", "light", "medium", "heavy", "cathedral")) {
109
- $ReverbLevel = $reverbVal
189
+ if ($LlmReverb -and $LlmReverb -in @("off", "light", "medium", "heavy", "cathedral")) {
190
+ $ReverbLevel = $LlmReverb
191
+ } else {
192
+ $ReverbFile = "$ConfigDir\reverb-level.txt"
193
+ if (Test-Path $ReverbFile) {
194
+ $reverbVal = (Get-Content $ReverbFile -Raw).Trim()
195
+ if ($reverbVal -in @("off", "light", "medium", "heavy", "cathedral")) {
196
+ $ReverbLevel = $reverbVal
197
+ }
110
198
  }
111
199
  }
112
200
  $HasReverb = $ReverbLevel -ne "off"
@@ -133,10 +221,6 @@ $PreSynthWav = $env:AGENTVIBES_PRESYNTHESIZED_WAV
133
221
  $UsePreSynth = $PreSynthWav -and (Test-Path $PreSynthWav) -and
134
222
  (Get-Item $PreSynthWav -ErrorAction SilentlyContinue).Length -gt 0
135
223
 
136
- # Tracks the path of the WAV the provider just synthesized.
137
- # Used to defend against playing stale cached audio when synthesis silently fails.
138
- $SynthesizedWavPath = $null
139
-
140
224
  # If background music or reverb enabled and ffmpeg available, tell provider to skip playback
141
225
  if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
142
226
  $env:AGENTVIBES_NO_PLAY = "1"
@@ -171,25 +255,17 @@ if ($UsePreSynth) {
171
255
  $providerOutput = & $ProviderScript $Text 6>&1 2>&1
172
256
  }
173
257
  # Re-emit preserving colors from InformationRecords (Write-Host output)
174
- # Also extract the synthesized WAV path from the provider's OK line.
175
258
  foreach ($item in $providerOutput) {
176
- $lineText = $null
177
259
  if ($item -is [System.Management.Automation.InformationRecord]) {
178
260
  $msg = $item.MessageData
179
261
  if ($msg -is [System.Management.Automation.HostInformationMessage]) {
180
262
  Write-Host $msg.Message -ForegroundColor $msg.ForegroundColor -NoNewline:$msg.NoNewLine
181
263
  if (-not $msg.NoNewLine) { Write-Host }
182
- $lineText = $msg.Message
183
264
  } else {
184
265
  Write-Host "$item"
185
- $lineText = "$item"
186
266
  }
187
267
  } else {
188
268
  Write-Host "$item"
189
- $lineText = "$item"
190
- }
191
- if ($lineText -and $lineText -match '\[OK\]\s+Saved to:\s+(.+\.wav)') {
192
- $SynthesizedWavPath = $Matches[1].Trim()
193
269
  }
194
270
  }
195
271
  } else {
@@ -211,23 +287,13 @@ if ($UsePreSynth) {
211
287
  if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
212
288
  Remove-Item env:AGENTVIBES_NO_PLAY -ErrorAction SilentlyContinue
213
289
 
214
- # Find the WAV to post-process. Never fall back to "most recent on disk"
215
- # because that plays a random stale cache file when synthesis silently fails.
290
+ # Find the WAV to post-process: use pre-synthesized file if available, else most recent
216
291
  $AudioDir = "$ClaudeDir\audio"
217
- $RecentWav = $null
218
- if ($UsePreSynth) {
219
- $RecentWav = Get-Item $PreSynthWav -ErrorAction SilentlyContinue
220
- }
221
- elseif ($SynthesizedWavPath -and (Test-Path $SynthesizedWavPath)) {
222
- $cand = Get-Item $SynthesizedWavPath -ErrorAction SilentlyContinue
223
- if ($cand -and $cand.Length -gt 0) {
224
- $RecentWav = $cand
225
- }
226
- }
227
- if (-not $RecentWav) {
228
- Write-Host "[ERROR] No fresh synthesized WAV - refusing stale cache" -ForegroundColor Red
229
- Remove-Item env:AGENTVIBES_NO_PLAY -ErrorAction SilentlyContinue
230
- exit 1
292
+ $RecentWav = if ($UsePreSynth) {
293
+ Get-Item $PreSynthWav -ErrorAction SilentlyContinue
294
+ } else {
295
+ Get-ChildItem -Path $AudioDir -Filter "tts-*.wav" -ErrorAction SilentlyContinue |
296
+ Sort-Object LastWriteTime -Descending | Select-Object -First 1
231
297
  }
232
298
 
233
299
  if ($RecentWav -and $RecentWav.Length -gt 0) {
@@ -263,6 +329,7 @@ if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
263
329
  if (Test-Path $AudioEffectsCfg) {
264
330
  # Try agent-specific config first, then fall back to default
265
331
  # Format: AGENT_NAME|SOX_EFFECTS|BACKGROUND_FILE|BACKGROUND_VOLUME
332
+ # Lookup order: agent name → llm:<name> → default
266
333
  $agentName = $env:AGENTVIBES_AGENT_NAME
267
334
  $configLine = $null
268
335
 
@@ -275,6 +342,16 @@ if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
275
342
  }
276
343
  }
277
344
  }
345
+ # Try LLM-specific config (--llm parameter)
346
+ if (-not $configLine -and $llm) {
347
+ $llmBgKey = "llm:$llm"
348
+ foreach ($line in $cfgLines) {
349
+ if ($line -match "^$([regex]::Escape($llmBgKey))\|") {
350
+ $configLine = $line
351
+ break
352
+ }
353
+ }
354
+ }
278
355
  # Fall back to default
279
356
  if (-not $configLine) {
280
357
  foreach ($line in $cfgLines) {
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.1.0
14
+ **Author**: Paul Preibisch ([@997Fire](https://x.com/997Fire)) | **Version**: v5.1.1
15
15
 
16
16
  ---
17
17
 
@@ -43,6 +43,12 @@ Whether you're using Claude Code, GitHub Copilot, OpenAI Codex, Claude Desktop,
43
43
 
44
44
  ---
45
45
 
46
+ ## 🩹 v5.1.1 — Windows TTS Hook Hotfix
47
+
48
+ - **`play-tts.ps1 -llm` parameter restored** — npm-published v5.1.0 shipped a regressed copy without `-llm` support, breaking the Setup tab Preview button and the agentvibes MCP `text_to_speech` tool on Windows. Fixed in v5.1.1. If you hit the error, clear your npx cache: `npm cache clean --force` then reinstall.
49
+
50
+ ---
51
+
46
52
  ## 🎙️ NEW IN v5.1.0 — Voice Picker Overhaul + Auto-Save Agent Modal
47
53
 
48
54
  - **Auto-save in agent modal** — Voice/personality/music/reverb/pretext changes save automatically as you edit them. Brief "✓ Saved!" toast confirms each change.
package/RELEASE_NOTES.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # AgentVibes Release Notes
2
2
 
3
+ ## 🩹 v5.1.1 — Windows TTS Hook Hotfix
4
+
5
+ **Release Date:** April 2026
6
+
7
+ ### Bug Fixes
8
+
9
+ - **Windows `play-tts.ps1` `-llm` parameter restored** — A regression caused the npm-published v5.1.0 package to ship a `play-tts.ps1` that lacked the `-llm` parameter and the per-LLM config lookup. Per-LLM TTS routing on Windows failed with `A parameter cannot be found that matches parameter name 'llm'`. This affected:
10
+ - **Setup tab Preview button** for any provider configured with per-LLM voice/effects
11
+ - **agentvibes MCP `text_to_speech` tool** when called from Codex / Copilot / Claude Code
12
+ - Any code path that invokes `play-tts.ps1 ... -llm <provider>`
13
+
14
+ The git tag `v5.1.0` had the correct file all along — only the npm tarball was affected, because `npm publish` packs the working tree (which contained an uncommitted local regression) instead of the git tag.
15
+
16
+ ### How to Update
17
+
18
+ If you installed v5.1.0 from npm and hit the `-llm` error, clear your npx cache and reinstall:
19
+
20
+ ```
21
+ npm cache clean --force
22
+ npx --yes agentvibes@5.1.1
23
+ ```
24
+
25
+ ### Note for Maintainers
26
+
27
+ To prevent this kind of working-tree-vs-tag drift in future releases, the release workflow should run `npm publish` from a freshly checked-out clone of the tag, not from the development working directory.
28
+
29
+ ---
30
+
3
31
  ## 🎙️ v5.1.0 — Voice Picker Overhaul + Auto-Save Agent Modal
4
32
 
5
33
  **Release Date:** April 2026
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "agentvibes",
4
- "version": "5.1.0",
4
+ "version": "5.1.1",
5
5
  "description": "Now your AI Agents can finally talk back! Professional TTS voice for Claude Code, Claude Desktop (via MCP), and Clawdbot with multi-provider support.",
6
6
  "homepage": "https://agentvibes.org",
7
7
  "keywords": [