agentvibes 4.2.0 → 4.4.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.
- package/.agentvibes/bmad/bmad-voices.md +69 -69
- package/.agentvibes/config.json +12 -0
- package/.claude/activation-instructions +54 -54
- package/.claude/audio/tracks/README.md +52 -52
- 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/verbosity.md +89 -89
- 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/agentvibes.json +1 -0
- package/.claude/config/audio-effects.cfg +2 -2
- package/.claude/config/audio-effects.cfg.sample +52 -52
- package/.claude/config/background-music-volume.txt +1 -0
- package/.claude/config/intro-text.txt +1 -0
- package/.claude/config/piper-speech-rate.txt +4 -0
- package/.claude/config/piper-target-speech-rate.txt +1 -0
- package/.claude/config/reverb-level.txt +1 -0
- package/.claude/config/tts-speech-rate.txt +4 -0
- package/.claude/config/tts-target-speech-rate.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 +246 -246
- package/.claude/hooks/audio-processor.sh +433 -433
- package/.claude/hooks/background-music-manager.sh +404 -404
- package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
- package/.claude/hooks/bmad-speak.sh +269 -269
- package/.claude/hooks/bmad-tts-injector.sh +568 -568
- package/.claude/hooks/bmad-voice-manager.sh +928 -928
- package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
- package/.claude/hooks/clawdbot-receiver.sh +107 -107
- package/.claude/hooks/clean-audio-cache.sh +22 -22
- package/.claude/hooks/cleanup-cache.sh +106 -106
- package/.claude/hooks/configure-rdp-mode.sh +137 -137
- package/.claude/hooks/download-extra-voices.sh +244 -244
- package/.claude/hooks/effects-manager.sh +268 -268
- package/.claude/hooks/github-star-reminder.sh +154 -154
- package/.claude/hooks/language-manager.sh +362 -362
- package/.claude/hooks/learn-manager.sh +492 -492
- package/.claude/hooks/macos-voice-manager.sh +205 -205
- package/.claude/hooks/migrate-background-music.sh +125 -125
- package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
- package/.claude/hooks/optimize-background-music.sh +87 -87
- package/.claude/hooks/path-resolver.sh +60 -60
- package/.claude/hooks/personality-manager.sh +448 -448
- package/.claude/hooks/piper-download-voices.sh +225 -225
- package/.claude/hooks/piper-installer.sh +292 -292
- package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
- package/.claude/hooks/piper-voice-manager.sh +24 -3
- package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +90 -90
- package/.claude/hooks/play-tts-enhanced.sh +105 -105
- package/.claude/hooks/play-tts-macos.sh +368 -368
- package/.claude/hooks/play-tts-piper.sh +679 -679
- package/.claude/hooks/play-tts-soprano.sh +356 -356
- package/.claude/hooks/play-tts-ssh-remote.sh +167 -167
- package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
- package/.claude/hooks/play-tts.sh +301 -301
- package/.claude/hooks/prepare-release.sh +54 -54
- package/.claude/hooks/provider-commands.sh +617 -617
- package/.claude/hooks/provider-manager.sh +399 -399
- package/.claude/hooks/replay-target-audio.sh +95 -95
- package/.claude/hooks/requirements.txt +6 -6
- package/.claude/hooks/sentiment-manager.sh +201 -201
- package/.claude/hooks/session-start-tts.sh +81 -81
- package/.claude/hooks/soprano-gradio-synth.py +139 -139
- package/.claude/hooks/speed-manager.sh +291 -291
- package/.claude/hooks/stop-tts.sh +84 -84
- package/.claude/hooks/termux-installer.sh +261 -261
- package/.claude/hooks/translate-manager.sh +341 -341
- package/.claude/hooks/translator.py +237 -237
- package/.claude/hooks/tts-queue-worker.sh +145 -145
- package/.claude/hooks/tts-queue.sh +165 -165
- package/.claude/hooks/verbosity-manager.sh +178 -178
- package/.claude/hooks/voice-manager.sh +548 -548
- package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
- package/.claude/hooks-windows/background-music-manager.ps1 +348 -0
- package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -0
- package/.claude/hooks-windows/download-extra-voices.ps1 +185 -0
- package/.claude/hooks-windows/effects-manager.ps1 +294 -0
- package/.claude/hooks-windows/language-manager.ps1 +193 -0
- package/.claude/hooks-windows/learn-manager.ps1 +241 -0
- package/.claude/hooks-windows/personality-manager.ps1 +266 -0
- package/.claude/hooks-windows/play-tts-piper.ps1 +209 -0
- package/.claude/hooks-windows/play-tts-sapi.ps1 +108 -0
- package/.claude/hooks-windows/play-tts-soprano.ps1 +159 -158
- package/.claude/hooks-windows/play-tts-windows-piper.ps1 +50 -5
- package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -108
- package/.claude/hooks-windows/play-tts.ps1 +344 -266
- package/.claude/hooks-windows/provider-manager.ps1 +29 -10
- package/.claude/hooks-windows/session-start-tts.ps1 +124 -124
- package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
- package/.claude/hooks-windows/speed-manager.ps1 +166 -0
- package/.claude/hooks-windows/verbosity-manager.ps1 +119 -0
- package/.claude/hooks-windows/voice-manager-windows.ps1 +92 -8
- 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/settings.json +15 -15
- package/.claude/verbosity.txt +1 -1
- package/.clawdbot/README.md +105 -105
- package/.clawdbot/skill/SKILL.md +241 -241
- package/.mcp.json +12 -0
- package/CLAUDE.md +170 -170
- package/README.md +2029 -2007
- package/RELEASE_NOTES.md +1310 -1203
- package/WINDOWS-SETUP.md +208 -208
- package/bin/agent-vibes +39 -39
- package/bin/agentvibes-voice-browser.js +1840 -1840
- package/bin/agentvibes.js +48 -2
- package/bin/mcp-server.js +121 -121
- package/bin/mcp-server.sh +206 -206
- 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 +1465 -1453
- package/mcp-server/test_server.py +395 -395
- package/mcp-server/test_windows_script_parity.py +336 -0
- package/package.json +110 -110
- package/setup-windows.ps1 +815 -815
- package/src/bmad-detector.js +71 -71
- package/src/cli/list-personalities.js +110 -110
- package/src/cli/list-voices.js +114 -114
- package/src/commands/bmad-voices.js +394 -394
- package/src/commands/install-mcp.js +476 -476
- package/src/console/app.js +824 -824
- package/src/console/audio-env.js +20 -1
- package/src/console/brand-colors.js +13 -13
- package/src/console/constants/personalities.js +44 -44
- package/src/console/footer-config.js +50 -50
- package/src/console/modals/modal-overlay.js +247 -247
- package/src/console/navigation.js +62 -62
- package/src/console/tabs/agents-tab.js +1684 -1516
- package/src/console/tabs/help-tab.js +261 -261
- package/src/console/tabs/install-tab.js +1007 -991
- package/src/console/tabs/music-tab.js +22 -8
- package/src/console/tabs/placeholder-tab.js +53 -53
- package/src/console/tabs/readme-tab.js +267 -267
- package/src/console/tabs/receiver-tab.js +1472 -1212
- package/src/console/tabs/settings-tab.js +208 -84
- package/src/console/tabs/voices-tab.js +100 -21
- package/src/console/widgets/destroy-list.js +25 -25
- package/src/console/widgets/format-utils.js +89 -89
- package/src/console/widgets/notice.js +55 -55
- package/src/console/widgets/personality-picker.js +185 -185
- package/src/console/widgets/reverb-picker.js +94 -94
- package/src/console/widgets/track-picker.js +285 -285
- package/src/installer/music-file-input.js +304 -304
- package/src/installer.js +5895 -5829
- package/src/services/agent-voice-store.js +423 -423
- package/src/services/config-service.js +264 -264
- package/src/services/navigation-service.js +123 -123
- package/src/services/provider-service.js +143 -132
- package/src/services/verbosity-service.js +157 -157
- package/src/utils/audio-duration-validator.js +298 -298
- package/src/utils/audio-format-validator.js +277 -277
- package/src/utils/dependency-checker.js +469 -466
- package/src/utils/file-ownership-verifier.js +358 -358
- package/src/utils/list-formatter.js +194 -194
- package/src/utils/music-file-validator.js +285 -285
- package/src/utils/preview-list-prompt.js +136 -136
- package/src/utils/provider-validator.js +96 -12
- package/src/utils/secure-music-storage.js +412 -412
- package/templates/agentvibes-receiver.sh +482 -482
- package/templates/audio/welcome-music.mp3 +0 -0
- package/voice-assignments.json +8244 -8244
- package/.claude/config/background-music-position.txt +0 -1
|
@@ -1,266 +1,344 @@
|
|
|
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 = "
|
|
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-
|
|
52
|
-
}
|
|
53
|
-
"windows-piper" {
|
|
54
|
-
$ProviderScript = "$HooksDir\play-tts-
|
|
55
|
-
}
|
|
56
|
-
"soprano" {
|
|
57
|
-
$ProviderScript = "$HooksDir\play-tts-soprano.ps1"
|
|
58
|
-
}
|
|
59
|
-
default {
|
|
60
|
-
Write-Host "[ERROR] Unknown provider: $ActiveProvider" -ForegroundColor Red
|
|
61
|
-
Write-Host "Use: .\provider-manager.ps1 list" -ForegroundColor Yellow
|
|
62
|
-
exit 1
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
# Check if provider script exists
|
|
67
|
-
if (-not (Test-Path $ProviderScript)) {
|
|
68
|
-
Write-Host "[ERROR] Provider script not found: $ProviderScript" -ForegroundColor Red
|
|
69
|
-
exit 1
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
# Check if background music is enabled
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
$
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
$
|
|
82
|
-
$
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
$
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
$
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if ($
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
$
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
$
|
|
256
|
-
|
|
257
|
-
$
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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 = "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
|
+
{ $_ -in "sapi", "windows-sapi" } {
|
|
51
|
+
$ProviderScript = "$HooksDir\play-tts-sapi.ps1"
|
|
52
|
+
}
|
|
53
|
+
{ $_ -in "piper", "windows-piper" } {
|
|
54
|
+
$ProviderScript = "$HooksDir\play-tts-piper.ps1"
|
|
55
|
+
}
|
|
56
|
+
"soprano" {
|
|
57
|
+
$ProviderScript = "$HooksDir\play-tts-soprano.ps1"
|
|
58
|
+
}
|
|
59
|
+
default {
|
|
60
|
+
Write-Host "[ERROR] Unknown provider: $ActiveProvider" -ForegroundColor Red
|
|
61
|
+
Write-Host "Use: .\provider-manager.ps1 list" -ForegroundColor Yellow
|
|
62
|
+
exit 1
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Check if provider script exists
|
|
67
|
+
if (-not (Test-Path $ProviderScript)) {
|
|
68
|
+
Write-Host "[ERROR] Provider script not found: $ProviderScript" -ForegroundColor Red
|
|
69
|
+
exit 1
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Check if background music is enabled
|
|
73
|
+
# Primary source of truth: .agentvibes/config.json (used by TUI console)
|
|
74
|
+
# Fallback: .claude/config/background-music-enabled.txt (legacy PowerShell config)
|
|
75
|
+
$ConfigDir = "$ClaudeDir\config"
|
|
76
|
+
$BgEnabled = $false
|
|
77
|
+
$AgentVibesConfig = Join-Path (Split-Path -Parent $ClaudeDir) ".agentvibes\config.json"
|
|
78
|
+
if (Test-Path $AgentVibesConfig) {
|
|
79
|
+
try {
|
|
80
|
+
$json = Get-Content $AgentVibesConfig -Raw | ConvertFrom-Json
|
|
81
|
+
if ($json.backgroundMusic -and $null -ne $json.backgroundMusic.enabled) {
|
|
82
|
+
$BgEnabled = [bool]$json.backgroundMusic.enabled
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
$BgEnabled = $false
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
# Fallback to legacy txt config
|
|
89
|
+
$BgEnabledFile = "$ConfigDir\background-music-enabled.txt"
|
|
90
|
+
if (Test-Path $BgEnabledFile) {
|
|
91
|
+
$BgEnabled = (Get-Content $BgEnabledFile -Raw).Trim() -eq "true"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Check if reverb is enabled (allowlist validation)
|
|
96
|
+
$ReverbLevel = "off"
|
|
97
|
+
$ReverbFile = "$ConfigDir\reverb-level.txt"
|
|
98
|
+
if (Test-Path $ReverbFile) {
|
|
99
|
+
$reverbVal = (Get-Content $ReverbFile -Raw).Trim()
|
|
100
|
+
if ($reverbVal -in @("off", "light", "medium", "heavy", "cathedral")) {
|
|
101
|
+
$ReverbLevel = $reverbVal
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
$HasReverb = $ReverbLevel -ne "off"
|
|
105
|
+
|
|
106
|
+
# Check ffmpeg availability for background music mixing or reverb
|
|
107
|
+
# Refresh PATH from registry so newly-installed tools are found without shell restart
|
|
108
|
+
$HasFfmpeg = $false
|
|
109
|
+
if ($BgEnabled -or $HasReverb) {
|
|
110
|
+
try {
|
|
111
|
+
$null = Get-Command ffmpeg -ErrorAction Stop
|
|
112
|
+
$HasFfmpeg = $true
|
|
113
|
+
} catch {
|
|
114
|
+
# PATH may be stale (common after winget install); refresh from registry
|
|
115
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
|
116
|
+
try {
|
|
117
|
+
$null = Get-Command ffmpeg -ErrorAction Stop
|
|
118
|
+
$HasFfmpeg = $true
|
|
119
|
+
} catch {}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# If background music or reverb enabled and ffmpeg available, tell provider to skip playback
|
|
124
|
+
if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
|
|
125
|
+
$env:AGENTVIBES_NO_PLAY = "1"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Call the provider script
|
|
129
|
+
# When post-processing (reverb/music), capture output preserving InformationRecord colors.
|
|
130
|
+
# Otherwise call directly so Write-Host colors pass through to the terminal.
|
|
131
|
+
$NeedsPostProcess = ($BgEnabled -or $HasReverb) -and $HasFfmpeg
|
|
132
|
+
try {
|
|
133
|
+
if ($NeedsPostProcess) {
|
|
134
|
+
if ($VoiceOverride) {
|
|
135
|
+
$providerOutput = & $ProviderScript $Text $VoiceOverride 6>&1 2>&1
|
|
136
|
+
} else {
|
|
137
|
+
$providerOutput = & $ProviderScript $Text 6>&1 2>&1
|
|
138
|
+
}
|
|
139
|
+
# Re-emit preserving colors from InformationRecords (Write-Host output)
|
|
140
|
+
foreach ($item in $providerOutput) {
|
|
141
|
+
if ($item -is [System.Management.Automation.InformationRecord]) {
|
|
142
|
+
$msg = $item.MessageData
|
|
143
|
+
if ($msg -is [System.Management.Automation.HostInformationMessage]) {
|
|
144
|
+
Write-Host $msg.Message -ForegroundColor $msg.ForegroundColor -NoNewline:$msg.NoNewLine
|
|
145
|
+
if (-not $msg.NoNewLine) { Write-Host }
|
|
146
|
+
} else {
|
|
147
|
+
Write-Host "$item"
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
Write-Host "$item"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
if ($VoiceOverride) {
|
|
155
|
+
& $ProviderScript $Text $VoiceOverride
|
|
156
|
+
} else {
|
|
157
|
+
& $ProviderScript $Text
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
Write-Host "[ERROR] TTS Error: $_" -ForegroundColor Red
|
|
163
|
+
Remove-Item env:AGENTVIBES_NO_PLAY -ErrorAction SilentlyContinue
|
|
164
|
+
exit 1
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
# Apply reverb and/or mix with background music
|
|
168
|
+
if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
|
|
169
|
+
Remove-Item env:AGENTVIBES_NO_PLAY -ErrorAction SilentlyContinue
|
|
170
|
+
|
|
171
|
+
# Find the most recent TTS wav file
|
|
172
|
+
$AudioDir = "$ClaudeDir\audio"
|
|
173
|
+
$RecentWav = Get-ChildItem -Path $AudioDir -Filter "tts-*.wav" -ErrorAction SilentlyContinue |
|
|
174
|
+
Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
175
|
+
|
|
176
|
+
if ($RecentWav -and $RecentWav.Length -gt 0) {
|
|
177
|
+
$voicePath = $RecentWav.FullName
|
|
178
|
+
|
|
179
|
+
# Apply reverb if configured
|
|
180
|
+
if ($HasReverb) {
|
|
181
|
+
$reverbFilter = switch ($ReverbLevel) {
|
|
182
|
+
"light" { "aecho=0.8:0.88:60:0.4" }
|
|
183
|
+
"medium" { "aecho=0.8:0.88:60|120:0.4|0.3" }
|
|
184
|
+
"heavy" { "aecho=0.8:0.88:60|120|180:0.4|0.3|0.2" }
|
|
185
|
+
"cathedral" { "aecho=0.8:0.88:100|200|300|400:0.3|0.25|0.2|0.15" }
|
|
186
|
+
default { "" }
|
|
187
|
+
}
|
|
188
|
+
if ($reverbFilter) {
|
|
189
|
+
$reverbedFile = "$AudioDir\tts-reverbed.wav"
|
|
190
|
+
$reverbArgs = "-y -i `"$voicePath`" -af `"$reverbFilter`" `"$reverbedFile`""
|
|
191
|
+
$proc = Start-Process -FilePath "ffmpeg" -ArgumentList $reverbArgs -NoNewWindow -Wait -PassThru -RedirectStandardError "$env:TEMP\agentvibes-ffmpeg-stderr.txt"
|
|
192
|
+
if ($proc.ExitCode -eq 0 -and (Test-Path $reverbedFile)) {
|
|
193
|
+
$voicePath = $reverbedFile
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
# Mix with background music if enabled
|
|
199
|
+
if ($BgEnabled) {
|
|
200
|
+
# Read background track and volume from audio-effects.cfg (matches Linux behavior)
|
|
201
|
+
$TracksDir = "$ClaudeDir\audio\tracks"
|
|
202
|
+
$DefaultTrack = ""
|
|
203
|
+
$BgVolume = "0.25"
|
|
204
|
+
$AudioEffectsCfg = "$ConfigDir\audio-effects.cfg"
|
|
205
|
+
|
|
206
|
+
if (Test-Path $AudioEffectsCfg) {
|
|
207
|
+
# Try agent-specific config first, then fall back to default
|
|
208
|
+
# Format: AGENT_NAME|SOX_EFFECTS|BACKGROUND_FILE|BACKGROUND_VOLUME
|
|
209
|
+
$agentName = $env:AGENTVIBES_AGENT_NAME
|
|
210
|
+
$configLine = $null
|
|
211
|
+
|
|
212
|
+
$cfgLines = Get-Content $AudioEffectsCfg
|
|
213
|
+
if ($agentName) {
|
|
214
|
+
foreach ($line in $cfgLines) {
|
|
215
|
+
if ($line -match "^$([regex]::Escape($agentName))\|") {
|
|
216
|
+
$configLine = $line
|
|
217
|
+
break
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
# Fall back to default
|
|
222
|
+
if (-not $configLine) {
|
|
223
|
+
foreach ($line in $cfgLines) {
|
|
224
|
+
if ($line -match '^default\|') {
|
|
225
|
+
$configLine = $line
|
|
226
|
+
break
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if ($configLine) {
|
|
232
|
+
$parts = $configLine -split '\|'
|
|
233
|
+
if ($parts.Length -ge 3 -and $parts[2]) {
|
|
234
|
+
$trackName = $parts[2].Trim()
|
|
235
|
+
# Validate: filename only, no path separators or traversal
|
|
236
|
+
if ($trackName -match '^[a-zA-Z0-9_\-\.]+$') {
|
|
237
|
+
$DefaultTrack = $trackName
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if ($parts.Length -ge 4 -and $parts[3]) {
|
|
241
|
+
$volVal = $parts[3].Trim()
|
|
242
|
+
if ($volVal -match '^\d+\.?\d*$') { $BgVolume = $volVal }
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
# Fallback if no track found in config
|
|
248
|
+
if (-not $DefaultTrack) {
|
|
249
|
+
$DefaultTrack = "agent_vibes_celtic_harp_v1_loop.mp3"
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
$BgTrackPath = Join-Path $TracksDir $DefaultTrack
|
|
253
|
+
# Path containment: verify resolved path stays within tracks directory
|
|
254
|
+
$ResolvedBgTrack = [System.IO.Path]::GetFullPath($BgTrackPath)
|
|
255
|
+
$ResolvedTracksDir = [System.IO.Path]::GetFullPath($TracksDir)
|
|
256
|
+
if (-not $ResolvedBgTrack.StartsWith($ResolvedTracksDir + [System.IO.Path]::DirectorySeparatorChar)) {
|
|
257
|
+
$BgTrackPath = Join-Path $TracksDir "agent_vibes_celtic_harp_v1_loop.mp3"
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (Test-Path $BgTrackPath) {
|
|
261
|
+
$MixedFile = $RecentWav.FullName -replace '\.wav$', '-mixed.wav'
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
# Get voice duration to calculate total length
|
|
265
|
+
$probArgs = "-v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 `"$voicePath`""
|
|
266
|
+
$durationProc = Start-Process -FilePath "ffprobe" -ArgumentList $probArgs -NoNewWindow -Wait -PassThru -RedirectStandardError "$env:TEMP\agentvibes-ffmpeg-stderr.txt" -RedirectStandardOutput "$env:TEMP\agentvibes-duration.txt"
|
|
267
|
+
$voiceDuration = 5 # default fallback
|
|
268
|
+
if (Test-Path "$env:TEMP\agentvibes-duration.txt") {
|
|
269
|
+
$durStr = (Get-Content "$env:TEMP\agentvibes-duration.txt" -Raw).Trim()
|
|
270
|
+
if ($durStr -match '^\d+\.?\d*$') { $voiceDuration = [double]$durStr }
|
|
271
|
+
Remove-Item "$env:TEMP\agentvibes-duration.txt" -Force -ErrorAction SilentlyContinue
|
|
272
|
+
}
|
|
273
|
+
$totalDuration = $voiceDuration + 4 # 2s intro + voice + 2s outro
|
|
274
|
+
$fadeOutStart = $totalDuration - 2
|
|
275
|
+
|
|
276
|
+
# Filter: music fades in 0.5s, voice delayed 2s, music fades out last 2s
|
|
277
|
+
$filter = "[0:a]volume=${BgVolume},afade=t=in:d=0.5,afade=t=out:st=${fadeOutStart}:d=2[bg];[1:a]adelay=2000|2000,apad=pad_dur=2[voice];[bg][voice]amix=inputs=2:duration=longest:dropout_transition=2[out]"
|
|
278
|
+
|
|
279
|
+
# Run ffmpeg - use Start-Process to avoid stderr issues with $ErrorActionPreference
|
|
280
|
+
$ffmpegArgs = "-y -stream_loop -1 -i `"$BgTrackPath`" -i `"$voicePath`" -filter_complex `"$filter`" -map `"[out]`" -t $totalDuration `"$MixedFile`""
|
|
281
|
+
$proc = Start-Process -FilePath "ffmpeg" -ArgumentList $ffmpegArgs -NoNewWindow -Wait -PassThru -RedirectStandardError "$env:TEMP\agentvibes-ffmpeg-stderr.txt"
|
|
282
|
+
|
|
283
|
+
if ($proc.ExitCode -eq 0 -and (Test-Path $MixedFile) -and (Get-Item $MixedFile).Length -gt 0) {
|
|
284
|
+
# Play the mixed audio
|
|
285
|
+
$player = $null
|
|
286
|
+
try {
|
|
287
|
+
$player = New-Object System.Media.SoundPlayer $MixedFile
|
|
288
|
+
$player.PlaySync()
|
|
289
|
+
} catch {
|
|
290
|
+
Write-Host "[WARNING] Mixed playback failed, playing voice only" -ForegroundColor Yellow
|
|
291
|
+
$player2 = $null
|
|
292
|
+
try {
|
|
293
|
+
$player2 = New-Object System.Media.SoundPlayer $voicePath
|
|
294
|
+
$player2.PlaySync()
|
|
295
|
+
} finally {
|
|
296
|
+
if ($player2) { $player2.Dispose() }
|
|
297
|
+
}
|
|
298
|
+
} finally {
|
|
299
|
+
if ($player) { $player.Dispose() }
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
# Mixing failed, play voice only
|
|
303
|
+
$player = $null
|
|
304
|
+
try {
|
|
305
|
+
$player = New-Object System.Media.SoundPlayer $voicePath
|
|
306
|
+
$player.PlaySync()
|
|
307
|
+
} finally {
|
|
308
|
+
if ($player) { $player.Dispose() }
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
} catch {
|
|
312
|
+
# ffmpeg failed, play voice only
|
|
313
|
+
$player = $null
|
|
314
|
+
try {
|
|
315
|
+
$player = New-Object System.Media.SoundPlayer $voicePath
|
|
316
|
+
$player.PlaySync()
|
|
317
|
+
} finally {
|
|
318
|
+
if ($player) { $player.Dispose() }
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
# No background track found, play voice only
|
|
323
|
+
$player = $null
|
|
324
|
+
try {
|
|
325
|
+
$player = New-Object System.Media.SoundPlayer $voicePath
|
|
326
|
+
$player.PlaySync()
|
|
327
|
+
} finally {
|
|
328
|
+
if ($player) { $player.Dispose() }
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
# No background music, play the (possibly reverbed) voice
|
|
333
|
+
$player = $null
|
|
334
|
+
try {
|
|
335
|
+
$player = New-Object System.Media.SoundPlayer $voicePath
|
|
336
|
+
$player.PlaySync()
|
|
337
|
+
} finally {
|
|
338
|
+
if ($player) { $player.Dispose() }
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
} else {
|
|
343
|
+
Remove-Item env:AGENTVIBES_NO_PLAY -ErrorAction SilentlyContinue
|
|
344
|
+
}
|