agentvibes 3.4.2 → 3.5.0-alpha.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.
Files changed (73) hide show
  1. package/.claude/commands/agent-vibes/provider.md +0 -0
  2. package/.claude/config/audio-effects.cfg +1 -1
  3. package/.claude/hooks/audio-cache-utils.sh +0 -0
  4. package/.claude/hooks/audio-processor.sh +0 -0
  5. package/.claude/hooks/background-music-manager.sh +0 -0
  6. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  7. package/.claude/hooks/bmad-speak.sh +0 -0
  8. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  9. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  10. package/.claude/hooks/clawdbot-receiver-SECURE.sh +0 -0
  11. package/.claude/hooks/clawdbot-receiver.sh +0 -0
  12. package/.claude/hooks/clean-audio-cache.sh +0 -0
  13. package/.claude/hooks/cleanup-cache.sh +0 -0
  14. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  15. package/.claude/hooks/download-extra-voices.sh +0 -0
  16. package/.claude/hooks/effects-manager.sh +0 -0
  17. package/.claude/hooks/github-star-reminder.sh +0 -0
  18. package/.claude/hooks/language-manager.sh +0 -0
  19. package/.claude/hooks/learn-manager.sh +0 -0
  20. package/.claude/hooks/macos-voice-manager.sh +0 -0
  21. package/.claude/hooks/migrate-background-music.sh +0 -0
  22. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  23. package/.claude/hooks/optimize-background-music.sh +0 -0
  24. package/.claude/hooks/personality-manager.sh +0 -0
  25. package/.claude/hooks/piper-download-voices.sh +0 -0
  26. package/.claude/hooks/piper-installer.sh +0 -0
  27. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  28. package/.claude/hooks/piper-voice-manager.sh +0 -0
  29. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  30. package/.claude/hooks/play-tts-macos.sh +0 -0
  31. package/.claude/hooks/play-tts-piper.sh +0 -0
  32. package/.claude/hooks/play-tts-ssh-remote.sh +0 -0
  33. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  34. package/.claude/hooks/play-tts.sh +0 -6
  35. package/.claude/hooks/prepare-release.sh +0 -0
  36. package/.claude/hooks/provider-commands.sh +0 -0
  37. package/.claude/hooks/provider-manager.sh +0 -17
  38. package/.claude/hooks/replay-target-audio.sh +0 -0
  39. package/.claude/hooks/sentiment-manager.sh +0 -0
  40. package/.claude/hooks/session-start-tts.sh +0 -0
  41. package/.claude/hooks/speed-manager.sh +0 -0
  42. package/.claude/hooks/termux-installer.sh +0 -0
  43. package/.claude/hooks/translate-manager.sh +0 -0
  44. package/.claude/hooks/translator.py +0 -0
  45. package/.claude/hooks/tts-queue-worker.sh +0 -0
  46. package/.claude/hooks/tts-queue.sh +0 -0
  47. package/.claude/hooks/verbosity-manager.sh +0 -0
  48. package/.claude/hooks/voice-manager.sh +0 -0
  49. package/.claude/hooks-windows/audio-cache-utils.ps1 +112 -0
  50. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +142 -0
  51. package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +101 -0
  52. package/.claude/hooks-windows/play-tts.ps1 +81 -0
  53. package/.claude/hooks-windows/provider-manager.ps1 +133 -0
  54. package/.claude/hooks-windows/voice-manager-windows.ps1 +172 -0
  55. package/README.md +17 -27
  56. package/RELEASE_NOTES.md +1 -199
  57. package/bin/agent-vibes +0 -0
  58. package/bin/mcp-server.js +0 -0
  59. package/bin/mcp-server.sh +0 -0
  60. package/bin/test-bmad-pr +0 -0
  61. package/mcp-server/WINDOWS_SETUP.md +0 -0
  62. package/mcp-server/install-deps.js +0 -0
  63. package/mcp-server/test_server.py +0 -0
  64. package/package.json +4 -2
  65. package/src/installer.js +47 -339
  66. package/templates/agentvibes-receiver.sh +0 -0
  67. package/templates/audio/welcome-music.mp3 +0 -0
  68. package/.claude/config/background-music-position.txt +0 -1
  69. package/.claude/github-star-reminder.txt +0 -1
  70. package/.claude/hooks/play-tts-soprano.sh +0 -320
  71. package/.claude/hooks/soprano-gradio-synth.py +0 -139
  72. package/.claude/piper-voices-dir.txt +0 -1
  73. package/.mcp.json +0 -12
File without changes
@@ -49,4 +49,4 @@ BMad Master|reverb 50 60 100 pitch -100|agentvibes_soft_flamenco_loop.mp3|0.30
49
49
  _party_mode|compand 0.3,1 6:-70,-60,-20|agent_vibes_dark_chill_step_loop.mp3|0.40
50
50
  |||
51
51
  # Default (no agent specified) - clean with Bachata background|||
52
- default|reverb 20 50 50|agentvibes_soft_flamenco_loop.mp3|0.30
52
+ default|reverb 40 50 70|agentvibes_soft_flamenco_loop.mp3|0.30
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
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
File without changes
File without changes
File without changes
@@ -146,9 +146,6 @@ speak_text() {
146
146
  piper)
147
147
  "$SCRIPT_DIR/play-tts-piper.sh" "$text" "$voice"
148
148
  ;;
149
- soprano)
150
- "$SCRIPT_DIR/play-tts-soprano.sh" "$text" "$voice"
151
- ;;
152
149
  macos)
153
150
  "$SCRIPT_DIR/play-tts-macos.sh" "$text" "$voice"
154
151
  ;;
@@ -268,9 +265,6 @@ case "$ACTIVE_PROVIDER" in
268
265
  piper)
269
266
  exec "$SCRIPT_DIR/play-tts-piper.sh" "$TEXT" "$VOICE_OVERRIDE"
270
267
  ;;
271
- soprano)
272
- exec "$SCRIPT_DIR/play-tts-soprano.sh" "$TEXT" "$VOICE_OVERRIDE"
273
- ;;
274
268
  macos)
275
269
  exec "$SCRIPT_DIR/play-tts-macos.sh" "$TEXT" "$VOICE_OVERRIDE"
276
270
  ;;
File without changes
File without changes
@@ -190,13 +190,6 @@ migrate_voice_to_provider() {
190
190
  # Default voices by provider
191
191
  local piper_default="en_US-lessac-medium"
192
192
  local macos_default="Samantha"
193
- local soprano_default="soprano-default" # Single voice — no selection needed
194
-
195
- # Soprano has a single voice, so migration is straightforward
196
- if [[ "$target_provider" == "soprano" ]]; then
197
- echo "$soprano_default"
198
- return 0
199
- fi
200
193
 
201
194
  # If no current voice, return default for target provider
202
195
  if [[ -z "$current_voice" ]]; then
@@ -208,16 +201,6 @@ migrate_voice_to_provider() {
208
201
  return 0
209
202
  fi
210
203
 
211
- # If migrating FROM Soprano, return default for target provider
212
- if [[ "$current_voice" == "soprano-default" ]]; then
213
- case "$target_provider" in
214
- piper) echo "$piper_default" ;;
215
- macos) echo "$macos_default" ;;
216
- *) echo "$piper_default" ;;
217
- esac
218
- return 0
219
- fi
220
-
221
204
  # Convert to lowercase for case-insensitive comparison (portable)
222
205
  local current_voice_lower
223
206
  current_voice_lower=$(echo "$current_voice" | tr '[:upper:]' '[:lower:]')
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
@@ -0,0 +1,112 @@
1
+ #
2
+ # File: .claude/hooks-windows/audio-cache-utils.ps1
3
+ #
4
+ # AgentVibes Audio Cache Utilities for Windows
5
+ #
6
+
7
+ param(
8
+ [Parameter(Position = 0)]
9
+ [ValidateSet('cleanup', 'stats', 'clear')]
10
+ [string]$Command
11
+ )
12
+
13
+ $AudioDir = "$env:USERPROFILE\.claude\audio"
14
+
15
+ function Ensure-AudioDir {
16
+ if (-not (Test-Path $AudioDir)) {
17
+ New-Item -ItemType Directory -Path $AudioDir -Force | Out-Null
18
+ }
19
+ }
20
+
21
+ function Get-AudioCacheSize {
22
+ Ensure-AudioDir
23
+
24
+ if (-not (Test-Path $AudioDir)) {
25
+ return 0
26
+ }
27
+
28
+ $files = Get-ChildItem -Path $AudioDir -Filter "*.wav" -ErrorAction SilentlyContinue
29
+ $totalSize = 0
30
+
31
+ foreach ($file in $files) {
32
+ $totalSize += $file.Length
33
+ }
34
+
35
+ return $totalSize
36
+ }
37
+
38
+ function Format-FileSize {
39
+ param([long]$Size)
40
+
41
+ if ($Size -lt 1KB) { return "$Size B" }
42
+ if ($Size -lt 1MB) { return "{0:N2} KB" -f ($Size / 1KB) }
43
+ if ($Size -lt 1GB) { return "{0:N2} MB" -f ($Size / 1MB) }
44
+ return "{0:N2} GB" -f ($Size / 1GB)
45
+ }
46
+
47
+ function Get-CacheStats {
48
+ Ensure-AudioDir
49
+
50
+ $files = Get-ChildItem -Path $AudioDir -Filter "*.wav" -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum
51
+
52
+ $count = if ($files.Count -eq $null) { 0 } else { $files.Count }
53
+ $totalSize = if ($files.Sum -eq $null) { 0 } else { $files.Sum }
54
+
55
+ return @{
56
+ FileCount = $count
57
+ TotalSize = $totalSize
58
+ FormattedSize = Format-FileSize $totalSize
59
+ }
60
+ }
61
+
62
+ function Clear-Cache {
63
+ Ensure-AudioDir
64
+
65
+ $files = Get-ChildItem -Path $AudioDir -Filter "*.wav" -ErrorAction SilentlyContinue
66
+
67
+ if ($files.Count -eq 0) {
68
+ Write-Host "[OK] Cache already empty" -ForegroundColor Green
69
+ return
70
+ }
71
+
72
+ $stats = Get-CacheStats
73
+ Write-Host "[CLEANUP] Clearing $($stats.FileCount) audio files ($($stats.FormattedSize))" -ForegroundColor Yellow
74
+
75
+ foreach ($file in $files) {
76
+ Remove-Item $file.FullName -Force -ErrorAction SilentlyContinue
77
+ }
78
+
79
+ Write-Host "[OK] Cache cleared" -ForegroundColor Green
80
+ }
81
+
82
+ function Show-CacheStats {
83
+ Ensure-AudioDir
84
+
85
+ $stats = Get-CacheStats
86
+
87
+ Write-Host ""
88
+ Write-Host "[STATS] Audio Cache Statistics" -ForegroundColor Cyan
89
+ Write-Host " Location: $AudioDir"
90
+ Write-Host " Files: $($stats.FileCount)"
91
+ Write-Host " Total Size: $($stats.FormattedSize)"
92
+ Write-Host ""
93
+ }
94
+
95
+ # Main command routing
96
+ switch ($Command) {
97
+ 'stats' {
98
+ Show-CacheStats
99
+ }
100
+
101
+ 'cleanup' {
102
+ Clear-Cache
103
+ }
104
+
105
+ 'clear' {
106
+ Clear-Cache
107
+ }
108
+
109
+ default {
110
+ Show-CacheStats
111
+ }
112
+ }
@@ -0,0 +1,142 @@
1
+ #
2
+ # File: .claude/hooks-windows/play-tts-windows-piper.ps1
3
+ #
4
+ # AgentVibes - Windows Piper TTS Provider
5
+ # High-quality neural TTS using Piper.exe
6
+ #
7
+
8
+ param(
9
+ [Parameter(Mandatory = $true)]
10
+ [string]$Text,
11
+
12
+ [Parameter(Mandatory = $false)]
13
+ [string]$VoiceOverride
14
+ )
15
+
16
+ # Configuration paths
17
+ $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
18
+ $ProjectClaudeDir = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptPath)) ".claude"
19
+
20
+ if (Test-Path $ProjectClaudeDir) {
21
+ $ClaudeDir = $ProjectClaudeDir
22
+ } else {
23
+ $ClaudeDir = "$env:USERPROFILE\.claude"
24
+ }
25
+
26
+ $AudioDir = "$ClaudeDir\audio"
27
+ $VoicesDir = "$ClaudeDir\piper-voices"
28
+ $VoiceFile = "$ClaudeDir\tts-voice-piper.txt"
29
+ $PiperExe = "$env:LOCALAPPDATA\Programs\Piper\piper.exe"
30
+
31
+ # Ensure directories exist
32
+ foreach ($dir in @($AudioDir, $VoicesDir)) {
33
+ if (-not (Test-Path $dir)) {
34
+ New-Item -ItemType Directory -Path $dir -Force | Out-Null
35
+ }
36
+ }
37
+
38
+ # Check if Piper is installed
39
+ if (-not (Test-Path $PiperExe)) {
40
+ Write-Host "[ERROR] Piper not found at: $PiperExe" -ForegroundColor Red
41
+ Write-Host "Run: .\setup-windows.ps1 to install Piper" -ForegroundColor Yellow
42
+ exit 1
43
+ }
44
+
45
+ # Determine voice to use
46
+ $VoiceName = ""
47
+
48
+ if ($VoiceOverride) {
49
+ $VoiceName = $VoiceOverride
50
+ }
51
+ elseif (Test-Path $VoiceFile) {
52
+ $VoiceName = (Get-Content $VoiceFile -Raw).Trim()
53
+ }
54
+
55
+ # Default voice if not specified
56
+ if (-not $VoiceName) {
57
+ $VoiceName = "en_US-ryan-high"
58
+ }
59
+
60
+ # Resolve voice model path
61
+ $VoiceModelFile = "$VoicesDir\$VoiceName.onnx"
62
+ $VoiceJsonFile = "$VoicesDir\$VoiceName.onnx.json"
63
+
64
+ # Check if voice model exists, download if missing
65
+ if (-not (Test-Path $VoiceModelFile)) {
66
+ Write-Host "[DOWNLOAD] Voice model: $VoiceName" -ForegroundColor Yellow
67
+
68
+ # Try to download from Hugging Face
69
+ # Voice name format: {lang}_{region}-{speaker}-{quality}
70
+ # HF path format: {lang}/{lang}_{region}/{speaker}/{quality}/{voicename}.onnx
71
+ try {
72
+ # Parse voice name to build correct HF path
73
+ # e.g. en_US-ryan-high -> en/en_US/ryan/high/en_US-ryan-high.onnx
74
+ if ($VoiceName -match '^([a-z]{2})_([A-Z]{2})-(.+)-([a-z]+)$') {
75
+ $Lang = $Matches[1]
76
+ $LangRegion = "$($Matches[1])_$($Matches[2])"
77
+ $Speaker = $Matches[3]
78
+ $Quality = $Matches[4]
79
+ $HFBase = "https://huggingface.co/rhasspy/piper-voices/resolve/main/$Lang/$LangRegion/$Speaker/$Quality"
80
+ } else {
81
+ # Fallback for non-standard voice names
82
+ $HFBase = "https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/ryan/high"
83
+ }
84
+ $ModelUrl = "$HFBase/$VoiceName.onnx"
85
+ $JsonUrl = "$HFBase/$VoiceName.onnx.json"
86
+
87
+ Write-Host " Downloading model..." -ForegroundColor Cyan
88
+ Invoke-WebRequest -Uri $ModelUrl -OutFile $VoiceModelFile -ErrorAction Stop
89
+ Write-Host " Downloading config..." -ForegroundColor Cyan
90
+ Invoke-WebRequest -Uri $JsonUrl -OutFile $VoiceJsonFile -ErrorAction Stop
91
+ Write-Host "[OK] Voice model downloaded" -ForegroundColor Green
92
+ }
93
+ catch {
94
+ Write-Host "[ERROR] Failed to download voice model: $_" -ForegroundColor Red
95
+ Write-Host "Make sure you have internet connection" -ForegroundColor Yellow
96
+ exit 1
97
+ }
98
+ }
99
+
100
+ # Sanitize text for speech - strip characters that TTS engines read literally
101
+ $Text = $Text -replace '\\', ' '
102
+ $Text = $Text -replace '[{}<>|`~^]', ''
103
+ $Text = $Text -replace '\s+', ' '
104
+ $Text = $Text.Trim()
105
+
106
+ # Create audio file path
107
+ $Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss-ffff'
108
+ $AudioFile = "$AudioDir\tts-$Timestamp.wav"
109
+
110
+ # Synthesize with Piper
111
+ try {
112
+ Write-Host "[SYNTH] Synthesizing with Piper..." -ForegroundColor Cyan
113
+
114
+ # Run Piper with text input
115
+ $Text | & $PiperExe `
116
+ --model $VoiceModelFile `
117
+ --output-file $AudioFile `
118
+ 2>$null
119
+
120
+ if (-not (Test-Path $AudioFile)) {
121
+ Write-Host "[ERROR] Piper synthesis failed" -ForegroundColor Red
122
+ exit 1
123
+ }
124
+
125
+ # Display results
126
+ Write-Host "[OK] Saved to: $AudioFile" -ForegroundColor Green
127
+ Write-Host "[VOICE] Voice used: $VoiceName (Piper)" -ForegroundColor Green
128
+
129
+ # Play the audio using built-in Windows audio player
130
+ try {
131
+ $player = New-Object System.Media.SoundPlayer $AudioFile
132
+ $player.PlaySync()
133
+ }
134
+ catch {
135
+ Write-Host "[WARNING] Could not play audio (SoundPlayer unavailable)" -ForegroundColor Yellow
136
+ Write-Host "Audio saved to: $AudioFile" -ForegroundColor Gray
137
+ }
138
+ }
139
+ catch {
140
+ Write-Host "[ERROR] Error running Piper: $_" -ForegroundColor Red
141
+ exit 1
142
+ }
@@ -0,0 +1,101 @@
1
+ #
2
+ # File: .claude/hooks-windows/play-tts-windows-sapi.ps1
3
+ #
4
+ # AgentVibes - Windows SAPI TTS Provider (Zero Dependencies)
5
+ # Uses built-in Windows System.Speech API
6
+ #
7
+
8
+ param(
9
+ [Parameter(Mandatory = $true)]
10
+ [string]$Text,
11
+
12
+ [Parameter(Mandatory = $false)]
13
+ [string]$VoiceOverride
14
+ )
15
+
16
+ # Configuration paths
17
+ $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
18
+ $ProjectClaudeDir = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptPath)) ".claude"
19
+
20
+ if (Test-Path $ProjectClaudeDir) {
21
+ $ClaudeDir = $ProjectClaudeDir
22
+ } else {
23
+ $ClaudeDir = "$env:USERPROFILE\.claude"
24
+ }
25
+
26
+ $AudioDir = "$ClaudeDir\audio"
27
+ $VoiceFile = "$ClaudeDir\tts-voice-sapi.txt"
28
+
29
+ # Ensure directories exist
30
+ if (-not (Test-Path $AudioDir)) {
31
+ New-Item -ItemType Directory -Path $AudioDir -Force | Out-Null
32
+ }
33
+
34
+ # Load System.Speech assembly
35
+ try {
36
+ Add-Type -AssemblyName System.Speech
37
+ }
38
+ catch {
39
+ Write-Host "[ERROR] System.Speech assembly not available" -ForegroundColor Red
40
+ exit 1
41
+ }
42
+
43
+ # Determine voice to use
44
+ $VoiceName = ""
45
+
46
+ if ($VoiceOverride) {
47
+ $VoiceName = $VoiceOverride
48
+ }
49
+ elseif (Test-Path $VoiceFile) {
50
+ $VoiceName = (Get-Content $VoiceFile -Raw).Trim()
51
+ }
52
+
53
+ # Initialize speech synthesizer
54
+ $synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
55
+
56
+ # Set voice if specified
57
+ if ($VoiceName) {
58
+ try {
59
+ $synth.SelectVoice($VoiceName)
60
+ }
61
+ catch {
62
+ Write-Host "[WARNING] Voice '$VoiceName' not found, using default" -ForegroundColor Yellow
63
+ }
64
+ }
65
+
66
+ # Sanitize text for speech - strip characters that TTS engines read literally
67
+ $Text = $Text -replace '\\', ' '
68
+ $Text = $Text -replace '[{}<>|`~^]', ''
69
+ $Text = $Text -replace '\s+', ' '
70
+ $Text = $Text.Trim()
71
+
72
+ # Get actual voice name (after selection or default)
73
+ $ActualVoice = $synth.Voice.Name
74
+
75
+ # Create audio file path
76
+ $Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss-ffff'
77
+ $AudioFile = "$AudioDir\tts-$Timestamp.wav"
78
+
79
+ # Save to WAV file
80
+ try {
81
+ $synth.SetOutputToWaveFile($AudioFile)
82
+ $synth.Speak($Text)
83
+ $synth.Dispose()
84
+
85
+ # Display results
86
+ Write-Host "[OK] Saved to: $AudioFile" -ForegroundColor Green
87
+ Write-Host "[VOICE] Voice used: $ActualVoice (Windows SAPI)" -ForegroundColor Green
88
+
89
+ # Play the audio using built-in Windows audio player
90
+ try {
91
+ $player = New-Object System.Media.SoundPlayer $AudioFile
92
+ $player.PlaySync()
93
+ }
94
+ catch {
95
+ Write-Host "[WARNING] Could not play audio (SoundPlayer unavailable)" -ForegroundColor Yellow
96
+ }
97
+ }
98
+ catch {
99
+ Write-Host "[ERROR] Error synthesizing speech: $_" -ForegroundColor Red
100
+ exit 1
101
+ }
@@ -0,0 +1,81 @@
1
+ #
2
+ # File: .claude/hooks-windows/play-tts.ps1
3
+ #
4
+ # AgentVibes - Windows TTS Router
5
+ # Delegates to active provider (windows-sapi or windows-piper)
6
+ #
7
+
8
+ param(
9
+ [Parameter(Mandatory = $true, Position = 0)]
10
+ [string]$Text,
11
+
12
+ [Parameter(Mandatory = $false, Position = 1)]
13
+ [string]$VoiceOverride
14
+ )
15
+
16
+ # Configuration paths
17
+ # First check if we're running from a project directory with .claude
18
+ $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
19
+ $ProjectClaudeDir = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptPath)) ".claude"
20
+
21
+ # Use project .claude if running from there, otherwise use user profile
22
+ if (Test-Path $ProjectClaudeDir) {
23
+ $ClaudeDir = $ProjectClaudeDir
24
+ } else {
25
+ $ClaudeDir = "$env:USERPROFILE\.claude"
26
+ }
27
+
28
+ $HooksDir = "$ClaudeDir\hooks-windows"
29
+ $ProviderFile = "$ClaudeDir\tts-provider.txt"
30
+ $MuteFile = "$ClaudeDir\tts-muted.txt"
31
+
32
+ # Check if TTS is muted
33
+ if (Test-Path $MuteFile) {
34
+ $muteStatus = Get-Content $MuteFile -Raw
35
+ if ($muteStatus.Trim() -eq "true") {
36
+ exit 0
37
+ }
38
+ }
39
+
40
+ # Determine active provider
41
+ $ActiveProvider = "windows-sapi"
42
+ if (Test-Path $ProviderFile) {
43
+ $ActiveProvider = (Get-Content $ProviderFile -Raw).Trim()
44
+ }
45
+
46
+ # Validate and get provider script
47
+ $ProviderScript = ""
48
+
49
+ switch ($ActiveProvider) {
50
+ "windows-sapi" {
51
+ $ProviderScript = "$HooksDir\play-tts-windows-sapi.ps1"
52
+ }
53
+ "windows-piper" {
54
+ $ProviderScript = "$HooksDir\play-tts-windows-piper.ps1"
55
+ }
56
+ default {
57
+ Write-Host "[ERROR] Unknown provider: $ActiveProvider" -ForegroundColor Red
58
+ Write-Host "Use: .\provider-manager.ps1 list" -ForegroundColor Yellow
59
+ exit 1
60
+ }
61
+ }
62
+
63
+ # Check if provider script exists
64
+ if (-not (Test-Path $ProviderScript)) {
65
+ Write-Host "[ERROR] Provider script not found: $ProviderScript" -ForegroundColor Red
66
+ exit 1
67
+ }
68
+
69
+ # Call the provider script
70
+ try {
71
+ if ($VoiceOverride) {
72
+ & $ProviderScript $Text $VoiceOverride
73
+ }
74
+ else {
75
+ & $ProviderScript $Text
76
+ }
77
+ }
78
+ catch {
79
+ Write-Host "[ERROR] TTS Error: $_" -ForegroundColor Red
80
+ exit 1
81
+ }