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.
Files changed (222) hide show
  1. package/.agentvibes/LITE-MODE.md +236 -0
  2. package/.agentvibes/README.md +136 -0
  3. package/.agentvibes/backup/session-start-tts.sh.20251210_212814 +141 -0
  4. package/.agentvibes/backups/agents/analyst_20260204_144958.md +78 -0
  5. package/.agentvibes/backups/agents/architect_20260204_144958.md +72 -0
  6. package/.agentvibes/backups/agents/dev_20260204_144958.md +74 -0
  7. package/.agentvibes/backups/agents/pm_20260204_144958.md +72 -0
  8. package/.agentvibes/backups/agents/quick-flow-solo-dev_20260204_144958.md +64 -0
  9. package/.agentvibes/backups/agents/sm_20260204_144958.md +87 -0
  10. package/.agentvibes/backups/agents/tea_20260204_144958.md +79 -0
  11. package/.agentvibes/backups/agents/tech-writer_20260204_144958.md +82 -0
  12. package/.agentvibes/backups/agents/ux-designer_20260204_144958.md +80 -0
  13. package/.agentvibes/bmad/bmad-voices.md +69 -69
  14. package/.agentvibes/config/README-personality-defaults.md +162 -0
  15. package/.agentvibes/config/mode.txt +1 -0
  16. package/.agentvibes/config/personality-voice-defaults.default.json +21 -0
  17. package/.agentvibes/config/save-audio.txt +1 -0
  18. package/.agentvibes/config/voice-metadata.json +160 -0
  19. package/.agentvibes/config.json +24 -15
  20. package/.agentvibes/hooks/help.sh +191 -0
  21. package/.agentvibes/hooks/post-tool-use-lite.sh +111 -0
  22. package/.agentvibes/hooks/save-audio-manager.sh +162 -0
  23. package/.agentvibes/hooks/session-start-full-optimized.sh +102 -0
  24. package/.agentvibes/hooks/session-start-full.sh +142 -0
  25. package/.agentvibes/hooks/session-start-lite-v2.sh +34 -0
  26. package/.agentvibes/hooks/session-start-lite.sh +29 -0
  27. package/.agentvibes/hooks/stop-lite.sh +115 -0
  28. package/.agentvibes/hooks/switch-mode.sh +215 -0
  29. package/.agentvibes/output-styles/audio-summary.md +30 -0
  30. package/.claude/activation-instructions +54 -54
  31. package/.claude/audio/voice-samples/piper/alan.wav +0 -0
  32. package/.claude/audio/voice-samples/piper/amy.wav +0 -0
  33. package/.claude/audio/voice-samples/piper/charlotte.wav +0 -0
  34. package/.claude/audio/voice-samples/piper/joe.wav +0 -0
  35. package/.claude/audio/voice-samples/piper/john.wav +0 -0
  36. package/.claude/audio/voice-samples/piper/katherine.wav +0 -0
  37. package/.claude/audio/voice-samples/piper/kristin.wav +0 -0
  38. package/.claude/audio/voice-samples/piper/linda.wav +0 -0
  39. package/.claude/audio/voice-samples/piper/marcus.wav +0 -0
  40. package/.claude/audio/voice-samples/piper/ryan.wav +0 -0
  41. package/.claude/commands/agent-vibes/add.md +21 -21
  42. package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
  43. package/.claude/commands/agent-vibes/agent.md +79 -79
  44. package/.claude/commands/agent-vibes/background-music.md +111 -111
  45. package/.claude/commands/agent-vibes/bmad.md +198 -198
  46. package/.claude/commands/agent-vibes/clean.md +18 -18
  47. package/.claude/commands/agent-vibes/cleanup.md +18 -18
  48. package/.claude/commands/agent-vibes/commands.json +145 -145
  49. package/.claude/commands/agent-vibes/effects.md +97 -97
  50. package/.claude/commands/agent-vibes/get.md +9 -9
  51. package/.claude/commands/agent-vibes/hide.md +91 -91
  52. package/.claude/commands/agent-vibes/language.md +23 -23
  53. package/.claude/commands/agent-vibes/learn.md +67 -67
  54. package/.claude/commands/agent-vibes/list.md +13 -13
  55. package/.claude/commands/agent-vibes/mute.md +37 -37
  56. package/.claude/commands/agent-vibes/preview.md +17 -17
  57. package/.claude/commands/agent-vibes/provider.md +68 -68
  58. package/.claude/commands/agent-vibes/replay-target.md +14 -14
  59. package/.claude/commands/agent-vibes/sample.md +12 -12
  60. package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
  61. package/.claude/commands/agent-vibes/set-pretext.md +65 -65
  62. package/.claude/commands/agent-vibes/set-speed.md +41 -41
  63. package/.claude/commands/agent-vibes/show.md +84 -84
  64. package/.claude/commands/agent-vibes/switch.md +87 -87
  65. package/.claude/commands/agent-vibes/target-voice.md +26 -26
  66. package/.claude/commands/agent-vibes/target.md +30 -30
  67. package/.claude/commands/agent-vibes/translate.md +68 -68
  68. package/.claude/commands/agent-vibes/unmute.md +45 -45
  69. package/.claude/commands/agent-vibes/whoami.md +7 -7
  70. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  71. package/.claude/commands/agent-vibes-rdp.md +24 -24
  72. package/.claude/config/audio-effects.cfg +4 -11
  73. package/.claude/config/audio-effects.cfg.sample +52 -52
  74. package/.claude/config/background-music-position.txt +27 -0
  75. package/.claude/config/background-music-volume.txt +1 -1
  76. package/.claude/config/background-music.cfg +1 -0
  77. package/.claude/config/background-music.txt +1 -0
  78. package/.claude/config/tts-speech-rate.txt +1 -4
  79. package/.claude/config/tts-verbosity.txt +1 -0
  80. package/.claude/docs/TERMUX_SETUP.md +408 -408
  81. package/.claude/github-star-reminder.txt +1 -1
  82. package/.claude/hooks/README-TTS-QUEUE.md +135 -135
  83. package/.claude/hooks/audio-cache-utils.sh +0 -0
  84. package/.claude/hooks/audio-processor.sh +60 -14
  85. package/.claude/hooks/background-music-manager.sh +0 -0
  86. package/.claude/hooks/bmad-party-manager.sh +225 -0
  87. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  88. package/.claude/hooks/bmad-speak.sh +6 -13
  89. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  90. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  91. package/.claude/hooks/clawdbot-receiver-SECURE.sh +25 -23
  92. package/.claude/hooks/clawdbot-receiver.sh +4 -28
  93. package/.claude/hooks/clean-audio-cache.sh +0 -0
  94. package/.claude/hooks/cleanup-cache.sh +0 -0
  95. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  96. package/.claude/hooks/download-extra-voices.sh +0 -0
  97. package/.claude/hooks/effects-manager.sh +0 -0
  98. package/.claude/hooks/github-star-reminder.sh +0 -0
  99. package/.claude/hooks/language-manager.sh +0 -0
  100. package/.claude/hooks/learn-manager.sh +0 -0
  101. package/.claude/hooks/macos-voice-manager.sh +0 -0
  102. package/.claude/hooks/migrate-background-music.sh +0 -0
  103. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  104. package/.claude/hooks/optimize-background-music.sh +0 -0
  105. package/.claude/hooks/personality-manager.sh +0 -0
  106. package/.claude/hooks/piper-download-voices.sh +0 -0
  107. package/.claude/hooks/piper-installer.sh +1 -1
  108. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  109. package/.claude/hooks/piper-voice-manager.sh +0 -0
  110. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  111. package/.claude/hooks/play-tts-macos.sh +6 -12
  112. package/.claude/hooks/play-tts-piper.sh +50 -79
  113. package/.claude/hooks/play-tts-soprano.sh +9 -43
  114. package/.claude/hooks/play-tts-ssh-remote.sh +42 -120
  115. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  116. package/.claude/hooks/play-tts.sh +48 -37
  117. package/.claude/hooks/post-response.sh +41 -0
  118. package/.claude/hooks/prepare-release.sh +0 -0
  119. package/.claude/hooks/provider-commands.sh +0 -0
  120. package/.claude/hooks/provider-manager.sh +0 -0
  121. package/.claude/hooks/replay-target-audio.sh +0 -0
  122. package/.claude/hooks/requirements.txt +6 -6
  123. package/.claude/hooks/sentiment-manager.sh +0 -0
  124. package/.claude/hooks/session-start-tts.sh +56 -39
  125. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  126. package/.claude/hooks/speed-manager.sh +0 -0
  127. package/.claude/hooks/stop.sh +63 -0
  128. package/.claude/hooks/termux-installer.sh +0 -0
  129. package/.claude/hooks/translate-manager.sh +0 -0
  130. package/.claude/hooks/translator.py +237 -237
  131. package/.claude/hooks/tts-queue-worker.sh +0 -0
  132. package/.claude/hooks/tts-queue.sh +0 -0
  133. package/.claude/hooks/verbosity-manager.sh +0 -0
  134. package/.claude/hooks/voice-manager.sh +26 -4
  135. package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
  136. package/.claude/hooks-windows/bmad-party-speak.ps1 +278 -274
  137. package/.claude/hooks-windows/bmad-speak.ps1 +264 -264
  138. package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -53
  139. package/.claude/hooks-windows/effects-manager.ps1 +294 -294
  140. package/.claude/hooks-windows/language-manager.ps1 +193 -193
  141. package/.claude/hooks-windows/learn-manager.ps1 +241 -241
  142. package/.claude/hooks-windows/personality-manager.ps1 +266 -266
  143. package/.claude/hooks-windows/play-tts-soprano.ps1 +5 -5
  144. package/.claude/hooks-windows/play-tts-termux-ssh.ps1 +138 -138
  145. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +164 -0
  146. package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -0
  147. package/.claude/hooks-windows/play-tts.ps1 +104 -481
  148. package/.claude/hooks-windows/provider-manager.ps1 +158 -192
  149. package/.claude/hooks-windows/session-start-tts.ps1 +55 -46
  150. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  151. package/.claude/hooks-windows/speed-manager.ps1 +166 -166
  152. package/.claude/hooks-windows/voice-manager-windows.ps1 +176 -260
  153. package/.claude/output-styles/agent-vibes.md +202 -202
  154. package/.claude/personalities/angry.md +14 -14
  155. package/.claude/personalities/annoying.md +14 -14
  156. package/.claude/personalities/crass.md +14 -14
  157. package/.claude/personalities/dramatic.md +14 -14
  158. package/.claude/personalities/dry-humor.md +50 -50
  159. package/.claude/personalities/flirty.md +20 -20
  160. package/.claude/personalities/funny.md +14 -14
  161. package/.claude/personalities/grandpa.md +32 -32
  162. package/.claude/personalities/millennial.md +14 -14
  163. package/.claude/personalities/moody.md +14 -14
  164. package/.claude/personalities/normal.md +16 -16
  165. package/.claude/personalities/pirate.md +14 -14
  166. package/.claude/personalities/poetic.md +14 -14
  167. package/.claude/personalities/professional.md +14 -14
  168. package/.claude/personalities/rapper.md +55 -55
  169. package/.claude/personalities/robot.md +14 -14
  170. package/.claude/personalities/sarcastic.md +38 -38
  171. package/.claude/personalities/sassy.md +14 -14
  172. package/.claude/personalities/surfer-dude.md +14 -14
  173. package/.claude/personalities/zen.md +14 -14
  174. package/.claude/piper-voices-dir.txt +1 -0
  175. package/.claude/settings.json +25 -15
  176. package/.claude/verbosity.txt +1 -1
  177. package/.clawdbot/README.md +105 -105
  178. package/.clawdbot/skill/SKILL.md +149 -145
  179. package/.mcp.json +30 -11
  180. package/CLAUDE.md +170 -215
  181. package/README.md +206 -515
  182. package/RELEASE_NOTES.md +1132 -1884
  183. package/WINDOWS-SETUP.md +208 -208
  184. package/bin/agent-vibes +0 -0
  185. package/bin/agentvibes-voice-browser.js +64 -1289
  186. package/bin/agentvibes.js +0 -0
  187. package/bin/ensure-soprano-running.sh +43 -0
  188. package/bin/mcp-server.js +121 -121
  189. package/bin/mcp-server.sh +0 -0
  190. package/bin/test-bmad-pr +78 -78
  191. package/mcp-server/QUICK_START.md +203 -203
  192. package/mcp-server/README.md +345 -345
  193. package/mcp-server/WINDOWS_SETUP.md +260 -260
  194. package/mcp-server/docs/troubleshooting-audio.md +313 -313
  195. package/mcp-server/examples/claude_desktop_config.json +11 -11
  196. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  197. package/mcp-server/examples/custom_instructions.md +169 -169
  198. package/mcp-server/install-deps.js +130 -130
  199. package/mcp-server/pyproject.toml +52 -52
  200. package/mcp-server/requirements.txt +2 -2
  201. package/mcp-server/server.py +1451 -1578
  202. package/mcp-server/test_server.py +395 -395
  203. package/package.json +1 -3
  204. package/setup-windows.ps1 +815 -815
  205. package/src/console/tabs/setup-tab.js +9 -6
  206. package/src/console/tabs/voices-tab.js +9 -3
  207. package/src/installer.js +42 -5
  208. package/src/services/llm-provider-service.js +13 -0
  209. package/templates/agentvibes-receiver.sh +158 -483
  210. package/templates/audio/welcome-music.mp3 +0 -0
  211. package/.agentvibes/bmad-voice-map.json +0 -104
  212. package/.agentvibes/copilot-sessions.log +0 -4
  213. package/.claude/config/audio-effects-bmad.cfg +0 -50
  214. package/.claude/config/background-music-enabled.txt +0 -1
  215. package/.claude/config/intro-text.txt +0 -1
  216. package/.claude/config/personality.txt +0 -1
  217. package/.claude/config/piper-speech-rate.txt +0 -4
  218. package/.claude/config/piper-target-speech-rate.txt +0 -1
  219. package/.claude/config/reverb-level.txt +0 -1
  220. package/.claude/config/tts-target-speech-rate.txt +0 -1
  221. package/voice-assignments.json +0 -8245
  222. /package/{.claude → .agentvibes}/config/agentvibes.json +0 -0
@@ -1,264 +1,264 @@
1
- #
2
- # File: .claude/hooks-windows/bmad-speak.ps1
3
- #
4
- # AgentVibes BMAD Voice Integration - Windows
5
- # Maps BMAD agent display names or agent IDs to voices and triggers TTS.
6
- # Windows port of .claude/hooks/bmad-speak.sh
7
- #
8
- # Usage: bmad-speak.ps1 "Agent Name" "dialogue text"
9
- # bmad-speak.ps1 "agent-id" "dialogue text"
10
- #
11
-
12
- param(
13
- [Parameter(Mandatory = $true, Position = 0)]
14
- [string]$AgentNameOrId,
15
-
16
- [Parameter(Mandatory = $true, Position = 1)]
17
- [string]$Dialogue
18
- )
19
-
20
- $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
21
- $ClaudeDir = Split-Path -Parent $ScriptDir
22
- $ProjectRoot = Split-Path -Parent $ClaudeDir
23
-
24
- # When running as global script, prefer CLAUDE_PROJECT_DIR for project root
25
- if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\_bmad")) {
26
- $ProjectRoot = $env:CLAUDE_PROJECT_DIR
27
- }
28
-
29
- # Strip markdown formatting — prevent SAPI/Piper from speaking asterisks literally
30
- $Dialogue = $Dialogue -replace '\*{1,3}', '' # bold, italic, bold-italic
31
- $Dialogue = $Dialogue -replace '`{1,3}[^`]*`{1,3}', '' # inline code / code blocks
32
- $Dialogue = $Dialogue -replace '#{1,6}\s*', '' # headings
33
- $Dialogue = $Dialogue -replace '_{1,2}', '' # underline/italic alt
34
- $Dialogue = $Dialogue -replace '\[([^\]]+)\]\([^)]+\)', '$1' # links → label only
35
- $Dialogue = $Dialogue -replace '!\[[^\]]*\]\([^)]+\)', '' # images
36
- $Dialogue = $Dialogue -replace '(?m)^\s*[-*+]\s+', '' # bullet list markers (multiline)
37
- $Dialogue = $Dialogue -replace '(?m)^\s*\d+\.\s+', '' # numbered list markers
38
- $Dialogue = $Dialogue -replace '\\([!$*_`\\])', '$1' # escaped markdown chars
39
-
40
- # Check if party mode is disabled
41
- $PartyModeDisabledFlag = Join-Path $ProjectRoot ".agentvibes\bmad\bmad-party-mode-disabled.flag"
42
- if (Test-Path $PartyModeDisabledFlag) {
43
- exit 0
44
- }
45
-
46
- # Check if BMAD is installed
47
- $ManifestFile = Join-Path $ProjectRoot "_bmad\_config\agent-manifest.csv"
48
- if (-not (Test-Path $ManifestFile)) {
49
- exit 0
50
- }
51
-
52
- # ---------------------------------------------------------------------------
53
- # Read bmad-voice-map.json for per-agent profile
54
- # Prefer project-local voice map, fall back to global
55
- $VoiceMapLocal = Join-Path $ProjectRoot ".agentvibes\bmad-voice-map.json"
56
- $VoiceMapGlobal = Join-Path $env:USERPROFILE ".agentvibes\bmad-voice-map.json"
57
- $VoiceMapFile = if (Test-Path $VoiceMapLocal) { $VoiceMapLocal } else { $VoiceMapGlobal }
58
-
59
- $AgentVoice = ""
60
- $AgentPretext = ""
61
- $AgentPersonality = ""
62
- $AgentBgEnabled = $false
63
- $AgentBgTrack = ""
64
- $AgentId = $null
65
-
66
- # Read global background music volume (stored as 0.0-1.0 float)
67
- $_BgVolFile = Join-Path $ProjectRoot ".claude\config\background-music-volume.txt"
68
- if (-not (Test-Path $_BgVolFile)) {
69
- $_BgVolFile = Join-Path $env:USERPROFILE ".claude\config\background-music-volume.txt"
70
- }
71
- if (Test-Path $_BgVolFile) {
72
- $_BgVolRaw = (Get-Content $_BgVolFile -Raw -ErrorAction SilentlyContinue).Trim()
73
- $_BgVolParsed = 0.0
74
- if ([double]::TryParse($_BgVolRaw, [System.Globalization.NumberStyles]::Float, [System.Globalization.CultureInfo]::InvariantCulture, [ref]$_BgVolParsed)) {
75
- $AgentBgVolume = "{0:F2}" -f $_BgVolParsed
76
- } else {
77
- $AgentBgVolume = "0.20"
78
- }
79
- } else {
80
- $AgentBgVolume = "0.20"
81
- }
82
-
83
- # Resolve agent ID and display name/title from manifest (needed for default pretext)
84
- $AgentDisplayName = ""
85
- $AgentTitle = ""
86
-
87
- if (Test-Path $ManifestFile) {
88
- try {
89
- $ManifestRows = Import-Csv $ManifestFile -Encoding UTF8
90
- foreach ($row in $ManifestRows) {
91
- $id = ($row.PSObject.Properties | Select-Object -First 1).Value -replace '^"|"$', ''
92
- $display = ($row.PSObject.Properties | Select-Object -Skip 1 -First 1).Value -replace '^"|"$', ''
93
- $title = ($row.PSObject.Properties | Select-Object -Skip 2 -First 1).Value -replace '^"|"$', ''
94
- if ($id -ieq $AgentNameOrId -or $display -like "$AgentNameOrId*") {
95
- $AgentId = $id
96
- $AgentDisplayName = $display
97
- $AgentTitle = $title
98
- break
99
- }
100
- }
101
- } catch { }
102
- }
103
-
104
- if (Test-Path $VoiceMapFile) {
105
- try {
106
- $VoiceMap = Get-Content $VoiceMapFile -Raw | ConvertFrom-Json
107
-
108
- if ($AgentId -and $VoiceMap.agents.$AgentId) {
109
- $Profile = $VoiceMap.agents.$AgentId
110
- if ($Profile.voice) { $AgentVoice = $Profile.voice }
111
- if ($Profile.pretext) { $AgentPretext = $Profile.pretext }
112
- if ($Profile.personality) { $AgentPersonality = $Profile.personality }
113
- if ($Profile.backgroundMusic) {
114
- $AgentBgEnabled = [bool]$Profile.backgroundMusic.enabled
115
- if ($Profile.backgroundMusic.track) { $AgentBgTrack = $Profile.backgroundMusic.track }
116
- if ($null -ne $Profile.backgroundMusic.volume) {
117
- # Voice map stores 0-100; audio-effects.cfg uses 0.0-1.0
118
- $AgentBgVolume = "{0:F2}" -f ([double]$Profile.backgroundMusic.volume / 100.0)
119
- }
120
- }
121
- }
122
- } catch {
123
- # Silently degrade — TTS will still play with global settings
124
- }
125
- }
126
-
127
- # Fallback: parse bmad-voices.md markdown table if JSON voice map had no data
128
- if ((-not $AgentPretext -or -not $AgentVoice) -and $AgentId) {
129
- $VoicesMdPaths = @(
130
- (Join-Path $ProjectRoot ".agentvibes\bmad\bmad-voices.md"),
131
- (Join-Path $env:USERPROFILE ".agentvibes\bmad\bmad-voices.md")
132
- )
133
- $shortId = $AgentId -replace '^bmad-agent-', ''
134
- foreach ($mdPath in $VoicesMdPaths) {
135
- if (-not (Test-Path $mdPath)) { continue }
136
- $mdLines = Get-Content $mdPath -Encoding UTF8
137
- foreach ($mdLine in $mdLines) {
138
- if ($mdLine -notmatch '^\|') { continue }
139
- if ($mdLine -match '^\|-') { continue }
140
- if ($mdLine -match 'Agent ID') { continue }
141
- $cols = $mdLine -split '\|' | ForEach-Object { $_.Trim() }
142
- if ($cols.Count -lt 6) { continue }
143
- $tableId = $cols[1]
144
- if ($tableId -ieq $shortId -or $tableId -ieq $AgentId -or $tableId -ieq $AgentNameOrId) {
145
- if (-not $AgentPretext -and $cols[3]) { $AgentPretext = $cols[3] }
146
- if (-not $AgentVoice -and $cols[5]) { $AgentVoice = $cols[5] }
147
- if (-not $AgentPersonality -and $cols.Count -ge 7 -and $cols[6] -and $cols[6] -ine 'normal') {
148
- $AgentPersonality = $cols[6]
149
- }
150
- break
151
- }
152
- }
153
- if ($AgentPretext) { break }
154
- }
155
- }
156
-
157
- # Fall back to default pretext if none stored: "DisplayName, Title here."
158
- # Matches AgentVoiceStore.getDefaultPretext() in agent-voice-store.js
159
- if (-not $AgentPretext) {
160
- if ($AgentDisplayName -and $AgentTitle) {
161
- $AgentPretext = "$AgentDisplayName, $AgentTitle here."
162
- } elseif ($AgentDisplayName) {
163
- $AgentPretext = "$AgentDisplayName here."
164
- } elseif ($AgentNameOrId) {
165
- $AgentPretext = "$AgentNameOrId here."
166
- }
167
- }
168
-
169
- # ---------------------------------------------------------------------------
170
- # Locate play-tts.ps1 — prefer project-local, fall back to global
171
- $PlayTtsLocal = Join-Path $ProjectRoot ".claude\hooks-windows\play-tts.ps1"
172
- $PlayTtsGlobal = Join-Path $env:USERPROFILE ".claude\hooks-windows\play-tts.ps1"
173
- $PlayTtsScript = if (Test-Path $PlayTtsLocal) { $PlayTtsLocal } else { $PlayTtsGlobal }
174
-
175
- if (-not (Test-Path $PlayTtsScript)) {
176
- exit 0
177
- }
178
-
179
- # ---------------------------------------------------------------------------
180
- # Determine which .claude config dir play-tts.ps1 will read.
181
- # play-tts.ps1 checks CLAUDE_PROJECT_DIR first — match that logic exactly.
182
- $TtsClaudeDir = if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\.claude")) {
183
- "$env:CLAUDE_PROJECT_DIR\.claude"
184
- } else {
185
- $ClaudeDir # ~/.claude (this script's own ClaudeDir)
186
- }
187
- $TtsConfigDir = Join-Path $TtsClaudeDir "config"
188
-
189
- # ---------------------------------------------------------------------------
190
- # Apply per-agent personality override if set
191
- $OldPersonality = ""
192
- $PersonalityFile = Join-Path $TtsClaudeDir "config\personality.txt"
193
- if ($AgentPersonality -and (Test-Path (Split-Path $PersonalityFile -Parent))) {
194
- if (Test-Path $PersonalityFile) {
195
- $OldPersonality = (Get-Content $PersonalityFile -Raw).Trim()
196
- }
197
- Set-Content $PersonalityFile $AgentPersonality -NoNewline
198
- }
199
-
200
- # ---------------------------------------------------------------------------
201
- # Temporarily patch background music config for this agent.
202
- # The caller (bmad-party-speak.ps1) holds a named mutex so only one speak
203
- # call runs at a time — these file patches are safe from concurrent clobber.
204
- $BgEnabledFile = Join-Path $TtsConfigDir "background-music-enabled.txt"
205
- $AudioEffectsCfg = Join-Path $TtsConfigDir "audio-effects.cfg"
206
- $OldBgEnabled = $null
207
- $TempCfgLine = ""
208
-
209
- if ($AgentBgEnabled -and $AgentBgTrack) {
210
- # Save + enable background music
211
- if (Test-Path $BgEnabledFile) {
212
- $OldBgEnabled = (Get-Content $BgEnabledFile -Raw -ErrorAction SilentlyContinue).Trim()
213
- }
214
- Set-Content $BgEnabledFile "true" -NoNewline
215
-
216
- # Prepend agent line to audio-effects.cfg so play-tts.ps1 finds it first
217
- # Format: AGENT_NAME|SOX_EFFECTS|BACKGROUND_FILE|BACKGROUND_VOLUME
218
- $TempCfgLine = "${AgentId}||${AgentBgTrack}|${AgentBgVolume}"
219
- $env:AGENTVIBES_AGENT_NAME = $AgentId
220
- $existingCfg = if (Test-Path $AudioEffectsCfg) {
221
- Get-Content $AudioEffectsCfg -Raw -ErrorAction SilentlyContinue
222
- } else { "" }
223
- Set-Content $AudioEffectsCfg "${TempCfgLine}`n${existingCfg}" -NoNewline
224
- }
225
-
226
- try {
227
- # Prepend pretext if configured (e.g. "As your UX designer")
228
- $SpeakText = if ($AgentPretext) { "$AgentPretext. $Dialogue" } else { $Dialogue }
229
-
230
- # Speak with agent's voice (or global voice if none configured)
231
- if ($AgentVoice) {
232
- & powershell -NoProfile -ExecutionPolicy Bypass -File $PlayTtsScript $SpeakText $AgentVoice
233
- } else {
234
- & powershell -NoProfile -ExecutionPolicy Bypass -File $PlayTtsScript $SpeakText
235
- }
236
- } finally {
237
- # Restore personality
238
- if ($AgentPersonality -and $PersonalityFile) {
239
- if ($OldPersonality) {
240
- Set-Content $PersonalityFile $OldPersonality -NoNewline
241
- } elseif (Test-Path $PersonalityFile) {
242
- Remove-Item $PersonalityFile -Force -ErrorAction SilentlyContinue
243
- }
244
- }
245
-
246
- # Restore background music config
247
- if ($AgentBgEnabled -and $AgentBgTrack) {
248
- if ($null -ne $OldBgEnabled) {
249
- Set-Content $BgEnabledFile $OldBgEnabled -NoNewline
250
- } elseif (Test-Path $BgEnabledFile) {
251
- Remove-Item $BgEnabledFile -Force -ErrorAction SilentlyContinue
252
- }
253
-
254
- # Remove the prepended agent line from audio-effects.cfg
255
- if (Test-Path $AudioEffectsCfg) {
256
- $cfgRaw = Get-Content $AudioEffectsCfg -Raw -ErrorAction SilentlyContinue
257
- $escaped = [regex]::Escape($TempCfgLine)
258
- $cfgRaw = $cfgRaw -replace "^${escaped}\r?\n?", ""
259
- Set-Content $AudioEffectsCfg $cfgRaw -NoNewline
260
- }
261
-
262
- $env:AGENTVIBES_AGENT_NAME = ""
263
- }
264
- }
1
+ #
2
+ # File: .claude/hooks-windows/bmad-speak.ps1
3
+ #
4
+ # AgentVibes BMAD Voice Integration - Windows
5
+ # Maps BMAD agent display names or agent IDs to voices and triggers TTS.
6
+ # Windows port of .claude/hooks/bmad-speak.sh
7
+ #
8
+ # Usage: bmad-speak.ps1 "Agent Name" "dialogue text"
9
+ # bmad-speak.ps1 "agent-id" "dialogue text"
10
+ #
11
+
12
+ param(
13
+ [Parameter(Mandatory = $true, Position = 0)]
14
+ [string]$AgentNameOrId,
15
+
16
+ [Parameter(Mandatory = $true, Position = 1)]
17
+ [string]$Dialogue
18
+ )
19
+
20
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
21
+ $ClaudeDir = Split-Path -Parent $ScriptDir
22
+ $ProjectRoot = Split-Path -Parent $ClaudeDir
23
+
24
+ # When running as global script, prefer CLAUDE_PROJECT_DIR for project root
25
+ if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\_bmad")) {
26
+ $ProjectRoot = $env:CLAUDE_PROJECT_DIR
27
+ }
28
+
29
+ # Strip markdown formatting — prevent SAPI/Piper from speaking asterisks literally
30
+ $Dialogue = $Dialogue -replace '\*{1,3}', '' # bold, italic, bold-italic
31
+ $Dialogue = $Dialogue -replace '`{1,3}[^`]*`{1,3}', '' # inline code / code blocks
32
+ $Dialogue = $Dialogue -replace '#{1,6}\s*', '' # headings
33
+ $Dialogue = $Dialogue -replace '_{1,2}', '' # underline/italic alt
34
+ $Dialogue = $Dialogue -replace '\[([^\]]+)\]\([^)]+\)', '$1' # links → label only
35
+ $Dialogue = $Dialogue -replace '!\[[^\]]*\]\([^)]+\)', '' # images
36
+ $Dialogue = $Dialogue -replace '(?m)^\s*[-*+]\s+', '' # bullet list markers (multiline)
37
+ $Dialogue = $Dialogue -replace '(?m)^\s*\d+\.\s+', '' # numbered list markers
38
+ $Dialogue = $Dialogue -replace '\\([!$*_`\\])', '$1' # escaped markdown chars
39
+
40
+ # Check if party mode is disabled
41
+ $PartyModeDisabledFlag = Join-Path $ProjectRoot ".agentvibes\bmad\bmad-party-mode-disabled.flag"
42
+ if (Test-Path $PartyModeDisabledFlag) {
43
+ exit 0
44
+ }
45
+
46
+ # Check if BMAD is installed
47
+ $ManifestFile = Join-Path $ProjectRoot "_bmad\_config\agent-manifest.csv"
48
+ if (-not (Test-Path $ManifestFile)) {
49
+ exit 0
50
+ }
51
+
52
+ # ---------------------------------------------------------------------------
53
+ # Read bmad-voice-map.json for per-agent profile
54
+ # Prefer project-local voice map, fall back to global
55
+ $VoiceMapLocal = Join-Path $ProjectRoot ".agentvibes\bmad-voice-map.json"
56
+ $VoiceMapGlobal = Join-Path $env:USERPROFILE ".agentvibes\bmad-voice-map.json"
57
+ $VoiceMapFile = if (Test-Path $VoiceMapLocal) { $VoiceMapLocal } else { $VoiceMapGlobal }
58
+
59
+ $AgentVoice = ""
60
+ $AgentPretext = ""
61
+ $AgentPersonality = ""
62
+ $AgentBgEnabled = $false
63
+ $AgentBgTrack = ""
64
+ $AgentId = $null
65
+
66
+ # Read global background music volume (stored as 0.0-1.0 float)
67
+ $_BgVolFile = Join-Path $ProjectRoot ".claude\config\background-music-volume.txt"
68
+ if (-not (Test-Path $_BgVolFile)) {
69
+ $_BgVolFile = Join-Path $env:USERPROFILE ".claude\config\background-music-volume.txt"
70
+ }
71
+ if (Test-Path $_BgVolFile) {
72
+ $_BgVolRaw = (Get-Content $_BgVolFile -Raw -ErrorAction SilentlyContinue).Trim()
73
+ $_BgVolParsed = 0.0
74
+ if ([double]::TryParse($_BgVolRaw, [System.Globalization.NumberStyles]::Float, [System.Globalization.CultureInfo]::InvariantCulture, [ref]$_BgVolParsed)) {
75
+ $AgentBgVolume = "{0:F2}" -f $_BgVolParsed
76
+ } else {
77
+ $AgentBgVolume = "0.20"
78
+ }
79
+ } else {
80
+ $AgentBgVolume = "0.20"
81
+ }
82
+
83
+ # Resolve agent ID and display name/title from manifest (needed for default pretext)
84
+ $AgentDisplayName = ""
85
+ $AgentTitle = ""
86
+
87
+ if (Test-Path $ManifestFile) {
88
+ try {
89
+ $ManifestRows = Import-Csv $ManifestFile -Encoding UTF8
90
+ foreach ($row in $ManifestRows) {
91
+ $id = ($row.PSObject.Properties | Select-Object -First 1).Value -replace '^"|"$', ''
92
+ $display = ($row.PSObject.Properties | Select-Object -Skip 1 -First 1).Value -replace '^"|"$', ''
93
+ $title = ($row.PSObject.Properties | Select-Object -Skip 2 -First 1).Value -replace '^"|"$', ''
94
+ if ($id -ieq $AgentNameOrId -or $display -like "$AgentNameOrId*") {
95
+ $AgentId = $id
96
+ $AgentDisplayName = $display
97
+ $AgentTitle = $title
98
+ break
99
+ }
100
+ }
101
+ } catch { }
102
+ }
103
+
104
+ if (Test-Path $VoiceMapFile) {
105
+ try {
106
+ $VoiceMap = Get-Content $VoiceMapFile -Raw | ConvertFrom-Json
107
+
108
+ if ($AgentId -and $VoiceMap.agents.$AgentId) {
109
+ $Profile = $VoiceMap.agents.$AgentId
110
+ if ($Profile.voice) { $AgentVoice = $Profile.voice }
111
+ if ($Profile.pretext) { $AgentPretext = $Profile.pretext }
112
+ if ($Profile.personality) { $AgentPersonality = $Profile.personality }
113
+ if ($Profile.backgroundMusic) {
114
+ $AgentBgEnabled = [bool]$Profile.backgroundMusic.enabled
115
+ if ($Profile.backgroundMusic.track) { $AgentBgTrack = $Profile.backgroundMusic.track }
116
+ if ($null -ne $Profile.backgroundMusic.volume) {
117
+ # Voice map stores 0-100; audio-effects.cfg uses 0.0-1.0
118
+ $AgentBgVolume = "{0:F2}" -f ([double]$Profile.backgroundMusic.volume / 100.0)
119
+ }
120
+ }
121
+ }
122
+ } catch {
123
+ # Silently degrade — TTS will still play with global settings
124
+ }
125
+ }
126
+
127
+ # Fallback: parse bmad-voices.md markdown table if JSON voice map had no data
128
+ if ((-not $AgentPretext -or -not $AgentVoice) -and $AgentId) {
129
+ $VoicesMdPaths = @(
130
+ (Join-Path $ProjectRoot ".agentvibes\bmad\bmad-voices.md"),
131
+ (Join-Path $env:USERPROFILE ".agentvibes\bmad\bmad-voices.md")
132
+ )
133
+ $shortId = $AgentId -replace '^bmad-agent-', ''
134
+ foreach ($mdPath in $VoicesMdPaths) {
135
+ if (-not (Test-Path $mdPath)) { continue }
136
+ $mdLines = Get-Content $mdPath -Encoding UTF8
137
+ foreach ($mdLine in $mdLines) {
138
+ if ($mdLine -notmatch '^\|') { continue }
139
+ if ($mdLine -match '^\|-') { continue }
140
+ if ($mdLine -match 'Agent ID') { continue }
141
+ $cols = $mdLine -split '\|' | ForEach-Object { $_.Trim() }
142
+ if ($cols.Count -lt 6) { continue }
143
+ $tableId = $cols[1]
144
+ if ($tableId -ieq $shortId -or $tableId -ieq $AgentId -or $tableId -ieq $AgentNameOrId) {
145
+ if (-not $AgentPretext -and $cols[3]) { $AgentPretext = $cols[3] }
146
+ if (-not $AgentVoice -and $cols[5]) { $AgentVoice = $cols[5] }
147
+ if (-not $AgentPersonality -and $cols.Count -ge 7 -and $cols[6] -and $cols[6] -ine 'normal') {
148
+ $AgentPersonality = $cols[6]
149
+ }
150
+ break
151
+ }
152
+ }
153
+ if ($AgentPretext) { break }
154
+ }
155
+ }
156
+
157
+ # Fall back to default pretext if none stored: "DisplayName, Title here."
158
+ # Matches AgentVoiceStore.getDefaultPretext() in agent-voice-store.js
159
+ if (-not $AgentPretext) {
160
+ if ($AgentDisplayName -and $AgentTitle) {
161
+ $AgentPretext = "$AgentDisplayName, $AgentTitle here."
162
+ } elseif ($AgentDisplayName) {
163
+ $AgentPretext = "$AgentDisplayName here."
164
+ } elseif ($AgentNameOrId) {
165
+ $AgentPretext = "$AgentNameOrId here."
166
+ }
167
+ }
168
+
169
+ # ---------------------------------------------------------------------------
170
+ # Locate play-tts.ps1 — prefer project-local, fall back to global
171
+ $PlayTtsLocal = Join-Path $ProjectRoot ".claude\hooks-windows\play-tts.ps1"
172
+ $PlayTtsGlobal = Join-Path $env:USERPROFILE ".claude\hooks-windows\play-tts.ps1"
173
+ $PlayTtsScript = if (Test-Path $PlayTtsLocal) { $PlayTtsLocal } else { $PlayTtsGlobal }
174
+
175
+ if (-not (Test-Path $PlayTtsScript)) {
176
+ exit 0
177
+ }
178
+
179
+ # ---------------------------------------------------------------------------
180
+ # Determine which .claude config dir play-tts.ps1 will read.
181
+ # play-tts.ps1 checks CLAUDE_PROJECT_DIR first — match that logic exactly.
182
+ $TtsClaudeDir = if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\.claude")) {
183
+ "$env:CLAUDE_PROJECT_DIR\.claude"
184
+ } else {
185
+ $ClaudeDir # ~/.claude (this script's own ClaudeDir)
186
+ }
187
+ $TtsConfigDir = Join-Path $TtsClaudeDir "config"
188
+
189
+ # ---------------------------------------------------------------------------
190
+ # Apply per-agent personality override if set
191
+ $OldPersonality = ""
192
+ $PersonalityFile = Join-Path $TtsClaudeDir "config\personality.txt"
193
+ if ($AgentPersonality -and (Test-Path (Split-Path $PersonalityFile -Parent))) {
194
+ if (Test-Path $PersonalityFile) {
195
+ $OldPersonality = (Get-Content $PersonalityFile -Raw).Trim()
196
+ }
197
+ Set-Content $PersonalityFile $AgentPersonality -NoNewline
198
+ }
199
+
200
+ # ---------------------------------------------------------------------------
201
+ # Temporarily patch background music config for this agent.
202
+ # The caller (bmad-party-speak.ps1) holds a named mutex so only one speak
203
+ # call runs at a time — these file patches are safe from concurrent clobber.
204
+ $BgEnabledFile = Join-Path $TtsConfigDir "background-music-enabled.txt"
205
+ $AudioEffectsCfg = Join-Path $TtsConfigDir "audio-effects.cfg"
206
+ $OldBgEnabled = $null
207
+ $TempCfgLine = ""
208
+
209
+ if ($AgentBgEnabled -and $AgentBgTrack) {
210
+ # Save + enable background music
211
+ if (Test-Path $BgEnabledFile) {
212
+ $OldBgEnabled = (Get-Content $BgEnabledFile -Raw -ErrorAction SilentlyContinue).Trim()
213
+ }
214
+ Set-Content $BgEnabledFile "true" -NoNewline
215
+
216
+ # Prepend agent line to audio-effects.cfg so play-tts.ps1 finds it first
217
+ # Format: AGENT_NAME|SOX_EFFECTS|BACKGROUND_FILE|BACKGROUND_VOLUME
218
+ $TempCfgLine = "${AgentId}||${AgentBgTrack}|${AgentBgVolume}"
219
+ $env:AGENTVIBES_AGENT_NAME = $AgentId
220
+ $existingCfg = if (Test-Path $AudioEffectsCfg) {
221
+ Get-Content $AudioEffectsCfg -Raw -ErrorAction SilentlyContinue
222
+ } else { "" }
223
+ Set-Content $AudioEffectsCfg "${TempCfgLine}`n${existingCfg}" -NoNewline
224
+ }
225
+
226
+ try {
227
+ # Prepend pretext if configured (e.g. "As your UX designer")
228
+ $SpeakText = if ($AgentPretext) { "$AgentPretext. $Dialogue" } else { $Dialogue }
229
+
230
+ # Speak with agent's voice (or global voice if none configured)
231
+ if ($AgentVoice) {
232
+ & powershell -NoProfile -ExecutionPolicy Bypass -File $PlayTtsScript $SpeakText $AgentVoice
233
+ } else {
234
+ & powershell -NoProfile -ExecutionPolicy Bypass -File $PlayTtsScript $SpeakText
235
+ }
236
+ } finally {
237
+ # Restore personality
238
+ if ($AgentPersonality -and $PersonalityFile) {
239
+ if ($OldPersonality) {
240
+ Set-Content $PersonalityFile $OldPersonality -NoNewline
241
+ } elseif (Test-Path $PersonalityFile) {
242
+ Remove-Item $PersonalityFile -Force -ErrorAction SilentlyContinue
243
+ }
244
+ }
245
+
246
+ # Restore background music config
247
+ if ($AgentBgEnabled -and $AgentBgTrack) {
248
+ if ($null -ne $OldBgEnabled) {
249
+ Set-Content $BgEnabledFile $OldBgEnabled -NoNewline
250
+ } elseif (Test-Path $BgEnabledFile) {
251
+ Remove-Item $BgEnabledFile -Force -ErrorAction SilentlyContinue
252
+ }
253
+
254
+ # Remove the prepended agent line from audio-effects.cfg
255
+ if (Test-Path $AudioEffectsCfg) {
256
+ $cfgRaw = Get-Content $AudioEffectsCfg -Raw -ErrorAction SilentlyContinue
257
+ $escaped = [regex]::Escape($TempCfgLine)
258
+ $cfgRaw = $cfgRaw -replace "^${escaped}\r?\n?", ""
259
+ Set-Content $AudioEffectsCfg $cfgRaw -NoNewline
260
+ }
261
+
262
+ $env:AGENTVIBES_AGENT_NAME = ""
263
+ }
264
+ }
@@ -1,53 +1,53 @@
1
- #
2
- # File: .claude/hooks-windows/clean-audio-cache.ps1
3
- #
4
- # AgentVibes - Finally, your AI Agents can Talk Back!
5
- # Website: https://agentvibes.org
6
- # Copyright (c) 2025 Paul Preibisch
7
- # Licensed under the Apache License, Version 2.0
8
- #
9
- # Non-Interactive TTS Audio Cache Cleanup
10
- # Used by /agent-vibes:clean skill and MCP clean_audio_cache tool
11
-
12
- $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
13
- $ClaudeDir = Split-Path -Parent $ScriptDir
14
- $AudioDir = Join-Path $ClaudeDir "audio"
15
-
16
- Write-Output "AgentVibes Cache Cleanup (Non-Interactive)"
17
- Write-Output ""
18
-
19
- if (-not (Test-Path $AudioDir)) {
20
- Write-Output "Audio directory not found: $AudioDir"
21
- Write-Output "Nothing to clean."
22
- exit 0
23
- }
24
-
25
- # Count and measure TTS files (preserve tracks/ subdirectory)
26
- $ttsFiles = Get-ChildItem -Path $AudioDir -File -Include "*.wav", "*.mp3", "*.aiff" -Recurse -ErrorAction SilentlyContinue |
27
- Where-Object { $_.DirectoryName -notmatch '\\tracks$' -and $_.DirectoryName -notmatch '\\tracks\\' }
28
-
29
- if (-not $ttsFiles -or $ttsFiles.Count -eq 0) {
30
- Write-Output "No TTS cache files found."
31
- Write-Output "Audio directory is clean."
32
- exit 0
33
- }
34
-
35
- $fileCount = if ($ttsFiles -is [array]) { $ttsFiles.Count } else { 1 }
36
- $totalSize = ($ttsFiles | Measure-Object -Property Length -Sum).Sum
37
- $sizeMB = [math]::Round($totalSize / 1MB, 2)
38
-
39
- # Delete files
40
- $deleted = 0
41
- foreach ($file in $ttsFiles) {
42
- try {
43
- Remove-Item $file.FullName -Force -ErrorAction Stop
44
- $deleted++
45
- } catch {
46
- Write-Output "Warning: Could not delete $($file.Name): $_"
47
- }
48
- }
49
-
50
- Write-Output "Cleaned $deleted TTS cache files"
51
- Write-Output "Freed ${sizeMB} MB of disk space"
52
- Write-Output ""
53
- Write-Output "Background music tracks preserved."
1
+ #
2
+ # File: .claude/hooks-windows/clean-audio-cache.ps1
3
+ #
4
+ # AgentVibes - Finally, your AI Agents can Talk Back!
5
+ # Website: https://agentvibes.org
6
+ # Copyright (c) 2025 Paul Preibisch
7
+ # Licensed under the Apache License, Version 2.0
8
+ #
9
+ # Non-Interactive TTS Audio Cache Cleanup
10
+ # Used by /agent-vibes:clean skill and MCP clean_audio_cache tool
11
+
12
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
13
+ $ClaudeDir = Split-Path -Parent $ScriptDir
14
+ $AudioDir = Join-Path $ClaudeDir "audio"
15
+
16
+ Write-Output "AgentVibes Cache Cleanup (Non-Interactive)"
17
+ Write-Output ""
18
+
19
+ if (-not (Test-Path $AudioDir)) {
20
+ Write-Output "Audio directory not found: $AudioDir"
21
+ Write-Output "Nothing to clean."
22
+ exit 0
23
+ }
24
+
25
+ # Count and measure TTS files (preserve tracks/ subdirectory)
26
+ $ttsFiles = Get-ChildItem -Path $AudioDir -File -Include "*.wav", "*.mp3", "*.aiff" -Recurse -ErrorAction SilentlyContinue |
27
+ Where-Object { $_.DirectoryName -notmatch '\\tracks$' -and $_.DirectoryName -notmatch '\\tracks\\' }
28
+
29
+ if (-not $ttsFiles -or $ttsFiles.Count -eq 0) {
30
+ Write-Output "No TTS cache files found."
31
+ Write-Output "Audio directory is clean."
32
+ exit 0
33
+ }
34
+
35
+ $fileCount = if ($ttsFiles -is [array]) { $ttsFiles.Count } else { 1 }
36
+ $totalSize = ($ttsFiles | Measure-Object -Property Length -Sum).Sum
37
+ $sizeMB = [math]::Round($totalSize / 1MB, 2)
38
+
39
+ # Delete files
40
+ $deleted = 0
41
+ foreach ($file in $ttsFiles) {
42
+ try {
43
+ Remove-Item $file.FullName -Force -ErrorAction Stop
44
+ $deleted++
45
+ } catch {
46
+ Write-Output "Warning: Could not delete $($file.Name): $_"
47
+ }
48
+ }
49
+
50
+ Write-Output "Cleaned $deleted TTS cache files"
51
+ Write-Output "Freed ${sizeMB} MB of disk space"
52
+ Write-Output ""
53
+ Write-Output "Background music tracks preserved."