agentvibes 5.3.0 → 5.5.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 +16 -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-party-speak.sh +0 -0
  88. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  89. package/.claude/hooks/bmad-speak.sh +12 -15
  90. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  91. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  92. package/.claude/hooks/clawdbot-receiver-SECURE.sh +25 -23
  93. package/.claude/hooks/clawdbot-receiver.sh +4 -28
  94. package/.claude/hooks/clean-audio-cache.sh +0 -0
  95. package/.claude/hooks/cleanup-cache.sh +0 -0
  96. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  97. package/.claude/hooks/download-extra-voices.sh +0 -0
  98. package/.claude/hooks/effects-manager.sh +0 -0
  99. package/.claude/hooks/github-star-reminder.sh +0 -0
  100. package/.claude/hooks/language-manager.sh +0 -0
  101. package/.claude/hooks/learn-manager.sh +0 -0
  102. package/.claude/hooks/macos-voice-manager.sh +0 -0
  103. package/.claude/hooks/migrate-background-music.sh +0 -0
  104. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  105. package/.claude/hooks/optimize-background-music.sh +0 -0
  106. package/.claude/hooks/personality-manager.sh +0 -0
  107. package/.claude/hooks/piper-download-voices.sh +0 -0
  108. package/.claude/hooks/piper-installer.sh +1 -1
  109. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  110. package/.claude/hooks/piper-voice-manager.sh +0 -0
  111. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  112. package/.claude/hooks/play-tts-macos.sh +6 -12
  113. package/.claude/hooks/play-tts-piper.sh +52 -81
  114. package/.claude/hooks/play-tts-soprano.sh +9 -43
  115. package/.claude/hooks/play-tts-ssh-remote.sh +43 -215
  116. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  117. package/.claude/hooks/play-tts.sh +41 -20
  118. package/.claude/hooks/post-response.sh +41 -0
  119. package/.claude/hooks/prepare-release.sh +0 -0
  120. package/.claude/hooks/provider-commands.sh +0 -0
  121. package/.claude/hooks/provider-manager.sh +0 -0
  122. package/.claude/hooks/replay-target-audio.sh +0 -0
  123. package/.claude/hooks/requirements.txt +6 -6
  124. package/.claude/hooks/sentiment-manager.sh +0 -0
  125. package/.claude/hooks/session-start-tts.sh +56 -39
  126. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  127. package/.claude/hooks/speed-manager.sh +0 -0
  128. package/.claude/hooks/stop.sh +63 -0
  129. package/.claude/hooks/termux-installer.sh +0 -0
  130. package/.claude/hooks/translate-manager.sh +0 -0
  131. package/.claude/hooks/translator.py +237 -237
  132. package/.claude/hooks/tts-queue-worker.sh +0 -0
  133. package/.claude/hooks/tts-queue.sh +0 -0
  134. package/.claude/hooks/verbosity-manager.sh +0 -0
  135. package/.claude/hooks/voice-manager.sh +26 -4
  136. package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
  137. package/.claude/hooks-windows/bmad-party-speak.ps1 +278 -278
  138. package/.claude/hooks-windows/bmad-speak.ps1 +264 -264
  139. package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -53
  140. package/.claude/hooks-windows/effects-manager.ps1 +294 -294
  141. package/.claude/hooks-windows/language-manager.ps1 +193 -193
  142. package/.claude/hooks-windows/learn-manager.ps1 +241 -241
  143. package/.claude/hooks-windows/personality-manager.ps1 +266 -266
  144. package/.claude/hooks-windows/play-tts-soprano.ps1 +5 -5
  145. package/.claude/hooks-windows/play-tts-termux-ssh.ps1 +138 -138
  146. package/.claude/hooks-windows/play-tts-windows-piper.ps1 +178 -0
  147. package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -0
  148. package/.claude/hooks-windows/play-tts.ps1 +265 -507
  149. package/.claude/hooks-windows/provider-manager.ps1 +158 -192
  150. package/.claude/hooks-windows/session-start-tts.ps1 +55 -46
  151. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  152. package/.claude/hooks-windows/speed-manager.ps1 +166 -166
  153. package/.claude/hooks-windows/voice-manager-windows.ps1 +176 -260
  154. package/.claude/output-styles/agent-vibes.md +202 -202
  155. package/.claude/personalities/angry.md +14 -14
  156. package/.claude/personalities/annoying.md +14 -14
  157. package/.claude/personalities/crass.md +14 -14
  158. package/.claude/personalities/dramatic.md +14 -14
  159. package/.claude/personalities/dry-humor.md +50 -50
  160. package/.claude/personalities/flirty.md +20 -20
  161. package/.claude/personalities/funny.md +14 -14
  162. package/.claude/personalities/grandpa.md +32 -32
  163. package/.claude/personalities/millennial.md +14 -14
  164. package/.claude/personalities/moody.md +14 -14
  165. package/.claude/personalities/normal.md +16 -16
  166. package/.claude/personalities/pirate.md +14 -14
  167. package/.claude/personalities/poetic.md +14 -14
  168. package/.claude/personalities/professional.md +14 -14
  169. package/.claude/personalities/rapper.md +55 -55
  170. package/.claude/personalities/robot.md +14 -14
  171. package/.claude/personalities/sarcastic.md +38 -38
  172. package/.claude/personalities/sassy.md +14 -14
  173. package/.claude/personalities/surfer-dude.md +14 -14
  174. package/.claude/personalities/zen.md +14 -14
  175. package/.claude/piper-voices-dir.txt +1 -0
  176. package/.claude/settings.json +25 -15
  177. package/.claude/verbosity.txt +1 -1
  178. package/.clawdbot/README.md +105 -105
  179. package/.clawdbot/skill/SKILL.md +149 -145
  180. package/.mcp.json +30 -11
  181. package/CLAUDE.md +170 -215
  182. package/README.md +207 -521
  183. package/RELEASE_NOTES.md +1172 -1976
  184. package/WINDOWS-SETUP.md +208 -208
  185. package/bin/agent-vibes +0 -0
  186. package/bin/agentvibes-voice-browser.js +64 -1289
  187. package/bin/agentvibes.js +28 -0
  188. package/bin/ensure-soprano-running.sh +43 -0
  189. package/bin/mcp-server.js +121 -121
  190. package/bin/mcp-server.sh +0 -0
  191. package/bin/test-bmad-pr +78 -78
  192. package/mcp-server/QUICK_START.md +203 -203
  193. package/mcp-server/README.md +345 -345
  194. package/mcp-server/WINDOWS_SETUP.md +260 -260
  195. package/mcp-server/docs/troubleshooting-audio.md +313 -313
  196. package/mcp-server/examples/claude_desktop_config.json +11 -11
  197. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  198. package/mcp-server/examples/custom_instructions.md +169 -169
  199. package/mcp-server/install-deps.js +130 -130
  200. package/mcp-server/pyproject.toml +52 -52
  201. package/mcp-server/requirements.txt +2 -2
  202. package/mcp-server/server.py +1467 -1578
  203. package/mcp-server/test_server.py +395 -395
  204. package/package.json +1 -3
  205. package/setup-windows.ps1 +815 -815
  206. package/src/console/tabs/music-tab.js +5 -2
  207. package/src/console/tabs/voices-tab.js +71 -37
  208. package/src/installer.js +52 -5
  209. package/src/services/llm-provider-service.js +1 -1
  210. package/templates/agentvibes-receiver.sh +158 -483
  211. package/templates/audio/welcome-music.mp3 +0 -0
  212. package/.agentvibes/bmad-voice-map.json +0 -104
  213. package/.agentvibes/copilot-sessions.log +0 -4
  214. package/.claude/config/audio-effects-bmad.cfg +0 -50
  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,266 +1,266 @@
1
- #
2
- # File: .claude/hooks-windows/personality-manager.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
- param(
10
- [Parameter(Position=0)]
11
- [string]$Command = "help",
12
- [Parameter(Position=1)]
13
- [string]$Arg1 = "",
14
- [Parameter(Position=2)]
15
- [string]$Arg2 = ""
16
- )
17
-
18
- $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
19
- $ClaudeDir = Split-Path -Parent $ScriptDir
20
- $PersonalitiesDir = Join-Path $ClaudeDir "personalities"
21
- $ProjectRoot = Split-Path -Parent $ClaudeDir
22
-
23
- # Determine config directory (project-local, then global)
24
- if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\.claude")) {
25
- $ConfigClaudeDir = Join-Path $env:CLAUDE_PROJECT_DIR ".claude"
26
- } else {
27
- $ConfigClaudeDir = $ClaudeDir
28
- }
29
-
30
- $PersonalityFile = Join-Path $ConfigClaudeDir "tts-personality.txt"
31
-
32
- function Get-PersonalityData {
33
- param([string]$Personality, [string]$Field)
34
- $file = Join-Path $PersonalitiesDir "$Personality.md"
35
- if (-not (Test-Path $file)) { return "" }
36
- $content = Get-Content $file -Raw
37
-
38
- switch ($Field) {
39
- "description" {
40
- if ($content -match '(?m)^description:\s*(.+)$') { return $Matches[1].Trim() }
41
- }
42
- "piper_voice" {
43
- if ($content -match '(?m)^piper_voice:\s*(.+)$') { return $Matches[1].Trim() }
44
- }
45
- "voice" {
46
- if ($content -match '(?m)^piper_voice:\s*(.+)$') { return $Matches[1].Trim() }
47
- }
48
- }
49
- return ""
50
- }
51
-
52
- function Get-Personalities {
53
- if (-not (Test-Path $PersonalitiesDir)) { return @() }
54
- Get-ChildItem -Path $PersonalitiesDir -Filter "*.md" -File |
55
- ForEach-Object { $_.BaseName } | Sort-Object
56
- }
57
-
58
- switch ($Command) {
59
- "list" {
60
- $current = "normal"
61
- if (Test-Path $PersonalityFile) {
62
- $current = (Get-Content $PersonalityFile -Raw).Trim()
63
- }
64
-
65
- # Try Node.js formatter
66
- $formatter = Join-Path $ProjectRoot "src\cli\list-personalities.js"
67
- if ((Test-Path $formatter) -and (Get-Command node -ErrorAction SilentlyContinue)) {
68
- & node $formatter $PersonalitiesDir $current
69
- } else {
70
- Write-Output "Available Personalities:"
71
- Write-Output "---------------------------------------"
72
- foreach ($p in (Get-Personalities)) {
73
- $desc = Get-PersonalityData $p "description"
74
- if ($p -eq $current) {
75
- Write-Output " > $p - $desc (current)"
76
- } else {
77
- Write-Output " - $p - $desc"
78
- }
79
- }
80
- if ($current -eq "random") {
81
- Write-Output " > random - Picks randomly each time (current)"
82
- } else {
83
- Write-Output " - random - Picks randomly each time"
84
- }
85
- Write-Output "---------------------------------------"
86
- Write-Output ""
87
- Write-Output "Usage: /agent-vibes:personality <name>"
88
- }
89
- }
90
-
91
- { $_ -in "set", "switch" } {
92
- if (-not $Arg1) {
93
- Write-Output "Please specify a personality name"
94
- Write-Output "Usage: personality-manager.ps1 set <personality>"
95
- exit 1
96
- }
97
-
98
- $personality = $Arg1
99
-
100
- if ($personality -ne "random") {
101
- $pFile = Join-Path $PersonalitiesDir "$personality.md"
102
- if (-not (Test-Path $pFile)) {
103
- Write-Output "Personality not found: $personality"
104
- Write-Output ""
105
- Write-Output "Available personalities:"
106
- foreach ($p in (Get-Personalities)) {
107
- Write-Output " - $p"
108
- }
109
- exit 1
110
- }
111
- }
112
-
113
- # Save personality
114
- Set-Content -Path $PersonalityFile -Value $personality -NoNewline
115
- Write-Output "Personality set to: $personality"
116
-
117
- # Get assigned voice
118
- $assignedVoice = Get-PersonalityData $personality "piper_voice"
119
- if (-not $assignedVoice) { $assignedVoice = "en_US-lessac-medium" }
120
-
121
- if ($assignedVoice) {
122
- Write-Output "Switching to assigned voice: $assignedVoice"
123
- $voiceManager = Join-Path $ScriptDir "voice-manager-windows.ps1"
124
- if (Test-Path $voiceManager) {
125
- & powershell -NoProfile -ExecutionPolicy Bypass -File $voiceManager switch $assignedVoice 2>$null
126
- }
127
- }
128
-
129
- if ($personality -ne "random") {
130
- $remark = "Personality set to ${personality}!"
131
-
132
- # Try to get example from personality file
133
- $pFile = Join-Path $PersonalitiesDir "$personality.md"
134
- if (Test-Path $pFile) {
135
- $examples = Get-Content $pFile | Where-Object { $_ -match '^- "(.+)"$' } |
136
- ForEach-Object { if ($_ -match '^- "(.+)"$') { $Matches[1] } }
137
- if ($examples -and $examples.Count -gt 0) {
138
- $remark = $examples | Get-Random
139
- }
140
- }
141
-
142
- Write-Output "$remark"
143
- }
144
- }
145
-
146
- "get" {
147
- if (Test-Path $PersonalityFile) {
148
- $current = (Get-Content $PersonalityFile -Raw).Trim()
149
- Write-Output "Current personality: $current"
150
- if ($current -ne "random") {
151
- $desc = Get-PersonalityData $current "description"
152
- if ($desc) { Write-Output "Description: $desc" }
153
- }
154
- } else {
155
- Write-Output "Current personality: normal (default)"
156
- }
157
- }
158
-
159
- "add" {
160
- if (-not $Arg1) {
161
- Write-Output "Please specify a personality name"
162
- exit 1
163
- }
164
- $name = $Arg1
165
- $file = Join-Path $PersonalitiesDir "$name.md"
166
- if (Test-Path $file) {
167
- Write-Output "Personality '$name' already exists. Use 'edit' to modify it."
168
- exit 1
169
- }
170
-
171
- if (-not (Test-Path $PersonalitiesDir)) { New-Item -ItemType Directory -Path $PersonalitiesDir -Force | Out-Null }
172
-
173
- $template = @"
174
- ---
175
- name: $name
176
- description: Custom personality
177
- ---
178
-
179
- # $name Personality
180
-
181
- ## Prefix
182
-
183
-
184
- ## Suffix
185
-
186
-
187
- ## AI Instructions
188
- Describe how the AI should generate messages for this personality.
189
-
190
- ## Example Responses
191
- - "Example response 1"
192
- - "Example response 2"
193
- "@
194
- Set-Content -Path $file -Value $template
195
- Write-Output "Created new personality: $name"
196
- Write-Output "Edit the file: $file"
197
- }
198
-
199
- "edit" {
200
- if (-not $Arg1) {
201
- Write-Output "Please specify a personality name"
202
- exit 1
203
- }
204
- $file = Join-Path $PersonalitiesDir "$Arg1.md"
205
- if (-not (Test-Path $file)) {
206
- Write-Output "Personality '$Arg1' not found. Use 'add' to create it first."
207
- exit 1
208
- }
209
- Write-Output "Edit this file to customize the personality:"
210
- Write-Output $file
211
- }
212
-
213
- "reset" {
214
- Set-Content -Path $PersonalityFile -Value "normal" -NoNewline
215
- Write-Output "Personality reset to: normal"
216
- }
217
-
218
- "set-favorite-voice" {
219
- $personality = $Arg1
220
- $newVoice = $Arg2
221
-
222
- if (-not $personality -or -not $newVoice) {
223
- Write-Output "Usage: personality-manager.ps1 set-favorite-voice <personality> <voice>"
224
- exit 1
225
- }
226
-
227
- $file = Join-Path $PersonalitiesDir "$personality.md"
228
- if (-not (Test-Path $file)) {
229
- Write-Output "Personality '$personality' not found"
230
- exit 1
231
- }
232
-
233
- $content = Get-Content $file -Raw
234
- if ($content -match '(?m)^piper_voice:\s*(.+)$') {
235
- $content = $content -replace '(?m)^piper_voice:\s*.+$', "piper_voice: $newVoice"
236
- } else {
237
- $content = $content -replace '(^---\s*$)', "`$1`npiper_voice: $newVoice"
238
- }
239
- Set-Content -Path $file -Value $content -NoNewline
240
-
241
- Write-Output "Favorite voice for '$personality' set to: $newVoice"
242
- }
243
-
244
- default {
245
- # If arg looks like a personality name, treat as "set"
246
- if ($Command -and (Test-Path (Join-Path $PersonalitiesDir "$Command.md"))) {
247
- & $MyInvocation.MyCommand.Path "set" $Command
248
- return
249
- }
250
- if ($Command -eq "random") {
251
- & $MyInvocation.MyCommand.Path "set" "random"
252
- return
253
- }
254
-
255
- Write-Output "AgentVibes Personality Manager"
256
- Write-Output ""
257
- Write-Output "Commands:"
258
- Write-Output " list - List all personalities"
259
- Write-Output " set/switch <name> - Set personality"
260
- Write-Output " add <name> - Create new personality"
261
- Write-Output " edit <name> - Show path to edit personality"
262
- Write-Output " get - Show current personality"
263
- Write-Output " set-favorite-voice <name> <voice> - Set favorite voice"
264
- Write-Output " reset - Reset to normal"
265
- }
266
- }
1
+ #
2
+ # File: .claude/hooks-windows/personality-manager.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
+ param(
10
+ [Parameter(Position=0)]
11
+ [string]$Command = "help",
12
+ [Parameter(Position=1)]
13
+ [string]$Arg1 = "",
14
+ [Parameter(Position=2)]
15
+ [string]$Arg2 = ""
16
+ )
17
+
18
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
19
+ $ClaudeDir = Split-Path -Parent $ScriptDir
20
+ $PersonalitiesDir = Join-Path $ClaudeDir "personalities"
21
+ $ProjectRoot = Split-Path -Parent $ClaudeDir
22
+
23
+ # Determine config directory (project-local, then global)
24
+ if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\.claude")) {
25
+ $ConfigClaudeDir = Join-Path $env:CLAUDE_PROJECT_DIR ".claude"
26
+ } else {
27
+ $ConfigClaudeDir = $ClaudeDir
28
+ }
29
+
30
+ $PersonalityFile = Join-Path $ConfigClaudeDir "tts-personality.txt"
31
+
32
+ function Get-PersonalityData {
33
+ param([string]$Personality, [string]$Field)
34
+ $file = Join-Path $PersonalitiesDir "$Personality.md"
35
+ if (-not (Test-Path $file)) { return "" }
36
+ $content = Get-Content $file -Raw
37
+
38
+ switch ($Field) {
39
+ "description" {
40
+ if ($content -match '(?m)^description:\s*(.+)$') { return $Matches[1].Trim() }
41
+ }
42
+ "piper_voice" {
43
+ if ($content -match '(?m)^piper_voice:\s*(.+)$') { return $Matches[1].Trim() }
44
+ }
45
+ "voice" {
46
+ if ($content -match '(?m)^piper_voice:\s*(.+)$') { return $Matches[1].Trim() }
47
+ }
48
+ }
49
+ return ""
50
+ }
51
+
52
+ function Get-Personalities {
53
+ if (-not (Test-Path $PersonalitiesDir)) { return @() }
54
+ Get-ChildItem -Path $PersonalitiesDir -Filter "*.md" -File |
55
+ ForEach-Object { $_.BaseName } | Sort-Object
56
+ }
57
+
58
+ switch ($Command) {
59
+ "list" {
60
+ $current = "normal"
61
+ if (Test-Path $PersonalityFile) {
62
+ $current = (Get-Content $PersonalityFile -Raw).Trim()
63
+ }
64
+
65
+ # Try Node.js formatter
66
+ $formatter = Join-Path $ProjectRoot "src\cli\list-personalities.js"
67
+ if ((Test-Path $formatter) -and (Get-Command node -ErrorAction SilentlyContinue)) {
68
+ & node $formatter $PersonalitiesDir $current
69
+ } else {
70
+ Write-Output "Available Personalities:"
71
+ Write-Output "---------------------------------------"
72
+ foreach ($p in (Get-Personalities)) {
73
+ $desc = Get-PersonalityData $p "description"
74
+ if ($p -eq $current) {
75
+ Write-Output " > $p - $desc (current)"
76
+ } else {
77
+ Write-Output " - $p - $desc"
78
+ }
79
+ }
80
+ if ($current -eq "random") {
81
+ Write-Output " > random - Picks randomly each time (current)"
82
+ } else {
83
+ Write-Output " - random - Picks randomly each time"
84
+ }
85
+ Write-Output "---------------------------------------"
86
+ Write-Output ""
87
+ Write-Output "Usage: /agent-vibes:personality <name>"
88
+ }
89
+ }
90
+
91
+ { $_ -in "set", "switch" } {
92
+ if (-not $Arg1) {
93
+ Write-Output "Please specify a personality name"
94
+ Write-Output "Usage: personality-manager.ps1 set <personality>"
95
+ exit 1
96
+ }
97
+
98
+ $personality = $Arg1
99
+
100
+ if ($personality -ne "random") {
101
+ $pFile = Join-Path $PersonalitiesDir "$personality.md"
102
+ if (-not (Test-Path $pFile)) {
103
+ Write-Output "Personality not found: $personality"
104
+ Write-Output ""
105
+ Write-Output "Available personalities:"
106
+ foreach ($p in (Get-Personalities)) {
107
+ Write-Output " - $p"
108
+ }
109
+ exit 1
110
+ }
111
+ }
112
+
113
+ # Save personality
114
+ Set-Content -Path $PersonalityFile -Value $personality -NoNewline
115
+ Write-Output "Personality set to: $personality"
116
+
117
+ # Get assigned voice
118
+ $assignedVoice = Get-PersonalityData $personality "piper_voice"
119
+ if (-not $assignedVoice) { $assignedVoice = "en_US-lessac-medium" }
120
+
121
+ if ($assignedVoice) {
122
+ Write-Output "Switching to assigned voice: $assignedVoice"
123
+ $voiceManager = Join-Path $ScriptDir "voice-manager-windows.ps1"
124
+ if (Test-Path $voiceManager) {
125
+ & powershell -NoProfile -ExecutionPolicy Bypass -File $voiceManager switch $assignedVoice 2>$null
126
+ }
127
+ }
128
+
129
+ if ($personality -ne "random") {
130
+ $remark = "Personality set to ${personality}!"
131
+
132
+ # Try to get example from personality file
133
+ $pFile = Join-Path $PersonalitiesDir "$personality.md"
134
+ if (Test-Path $pFile) {
135
+ $examples = Get-Content $pFile | Where-Object { $_ -match '^- "(.+)"$' } |
136
+ ForEach-Object { if ($_ -match '^- "(.+)"$') { $Matches[1] } }
137
+ if ($examples -and $examples.Count -gt 0) {
138
+ $remark = $examples | Get-Random
139
+ }
140
+ }
141
+
142
+ Write-Output "$remark"
143
+ }
144
+ }
145
+
146
+ "get" {
147
+ if (Test-Path $PersonalityFile) {
148
+ $current = (Get-Content $PersonalityFile -Raw).Trim()
149
+ Write-Output "Current personality: $current"
150
+ if ($current -ne "random") {
151
+ $desc = Get-PersonalityData $current "description"
152
+ if ($desc) { Write-Output "Description: $desc" }
153
+ }
154
+ } else {
155
+ Write-Output "Current personality: normal (default)"
156
+ }
157
+ }
158
+
159
+ "add" {
160
+ if (-not $Arg1) {
161
+ Write-Output "Please specify a personality name"
162
+ exit 1
163
+ }
164
+ $name = $Arg1
165
+ $file = Join-Path $PersonalitiesDir "$name.md"
166
+ if (Test-Path $file) {
167
+ Write-Output "Personality '$name' already exists. Use 'edit' to modify it."
168
+ exit 1
169
+ }
170
+
171
+ if (-not (Test-Path $PersonalitiesDir)) { New-Item -ItemType Directory -Path $PersonalitiesDir -Force | Out-Null }
172
+
173
+ $template = @"
174
+ ---
175
+ name: $name
176
+ description: Custom personality
177
+ ---
178
+
179
+ # $name Personality
180
+
181
+ ## Prefix
182
+
183
+
184
+ ## Suffix
185
+
186
+
187
+ ## AI Instructions
188
+ Describe how the AI should generate messages for this personality.
189
+
190
+ ## Example Responses
191
+ - "Example response 1"
192
+ - "Example response 2"
193
+ "@
194
+ Set-Content -Path $file -Value $template
195
+ Write-Output "Created new personality: $name"
196
+ Write-Output "Edit the file: $file"
197
+ }
198
+
199
+ "edit" {
200
+ if (-not $Arg1) {
201
+ Write-Output "Please specify a personality name"
202
+ exit 1
203
+ }
204
+ $file = Join-Path $PersonalitiesDir "$Arg1.md"
205
+ if (-not (Test-Path $file)) {
206
+ Write-Output "Personality '$Arg1' not found. Use 'add' to create it first."
207
+ exit 1
208
+ }
209
+ Write-Output "Edit this file to customize the personality:"
210
+ Write-Output $file
211
+ }
212
+
213
+ "reset" {
214
+ Set-Content -Path $PersonalityFile -Value "normal" -NoNewline
215
+ Write-Output "Personality reset to: normal"
216
+ }
217
+
218
+ "set-favorite-voice" {
219
+ $personality = $Arg1
220
+ $newVoice = $Arg2
221
+
222
+ if (-not $personality -or -not $newVoice) {
223
+ Write-Output "Usage: personality-manager.ps1 set-favorite-voice <personality> <voice>"
224
+ exit 1
225
+ }
226
+
227
+ $file = Join-Path $PersonalitiesDir "$personality.md"
228
+ if (-not (Test-Path $file)) {
229
+ Write-Output "Personality '$personality' not found"
230
+ exit 1
231
+ }
232
+
233
+ $content = Get-Content $file -Raw
234
+ if ($content -match '(?m)^piper_voice:\s*(.+)$') {
235
+ $content = $content -replace '(?m)^piper_voice:\s*.+$', "piper_voice: $newVoice"
236
+ } else {
237
+ $content = $content -replace '(^---\s*$)', "`$1`npiper_voice: $newVoice"
238
+ }
239
+ Set-Content -Path $file -Value $content -NoNewline
240
+
241
+ Write-Output "Favorite voice for '$personality' set to: $newVoice"
242
+ }
243
+
244
+ default {
245
+ # If arg looks like a personality name, treat as "set"
246
+ if ($Command -and (Test-Path (Join-Path $PersonalitiesDir "$Command.md"))) {
247
+ & $MyInvocation.MyCommand.Path "set" $Command
248
+ return
249
+ }
250
+ if ($Command -eq "random") {
251
+ & $MyInvocation.MyCommand.Path "set" "random"
252
+ return
253
+ }
254
+
255
+ Write-Output "AgentVibes Personality Manager"
256
+ Write-Output ""
257
+ Write-Output "Commands:"
258
+ Write-Output " list - List all personalities"
259
+ Write-Output " set/switch <name> - Set personality"
260
+ Write-Output " add <name> - Create new personality"
261
+ Write-Output " edit <name> - Show path to edit personality"
262
+ Write-Output " get - Show current personality"
263
+ Write-Output " set-favorite-voice <name> <voice> - Set favorite voice"
264
+ Write-Output " reset - Reset to normal"
265
+ }
266
+ }
@@ -31,9 +31,8 @@ if ($env:SOPRANO_PORT -and $env:SOPRANO_PORT -match '^\d+$') {
31
31
  }
32
32
  $SopranoDevice = if ($env:SOPRANO_DEVICE) { $env:SOPRANO_DEVICE } else { "auto" }
33
33
 
34
- # Sanitize text for TTS - strip only dangerous shell metacharacters
35
- # Keep $, parens, quotes these are harmless for TTS text piped to stdin
36
- $Text = $Text -replace '[\\`{}<>|~^;]', '' -replace '\s+', ' '
34
+ # Sanitize text for TTS - strip shell metacharacters and PS special chars
35
+ $Text = $Text -replace '[\\`"{}$<>|~^;''()]', '' -replace '\s+', ' '
37
36
  $Text = $Text.Trim()
38
37
 
39
38
  if (-not $Text) {
@@ -53,8 +52,9 @@ if (-not (Test-Path $AudioDir)) {
53
52
  New-Item -ItemType Directory -Path $AudioDir -Force | Out-Null
54
53
  }
55
54
 
56
- # SECURITY: use random name instead of predictable timestamp (#130)
57
- $TempFile = Join-Path $AudioDir "tts-$([System.IO.Path]::GetRandomFileName() -replace '\..*').wav"
55
+ $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
56
+ $random = Get-Random -Maximum 9999
57
+ $TempFile = Join-Path $AudioDir "tts-$timestamp-$random.wav"
58
58
 
59
59
  # Check WebUI server
60
60
  function Test-WebUI {