agentvibes 5.3.0 → 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 (219) 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 +43 -215
  115. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  116. package/.claude/hooks/play-tts.sh +31 -31
  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 -278
  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 -513
  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 -525
  182. package/RELEASE_NOTES.md +1132 -1976
  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/installer.js +42 -5
  206. package/templates/agentvibes-receiver.sh +158 -483
  207. package/templates/audio/welcome-music.mp3 +0 -0
  208. package/.agentvibes/bmad-voice-map.json +0 -104
  209. package/.agentvibes/copilot-sessions.log +0 -4
  210. package/.claude/config/audio-effects-bmad.cfg +0 -50
  211. package/.claude/config/background-music-enabled.txt +0 -1
  212. package/.claude/config/intro-text.txt +0 -1
  213. package/.claude/config/personality.txt +0 -1
  214. package/.claude/config/piper-speech-rate.txt +0 -4
  215. package/.claude/config/piper-target-speech-rate.txt +0 -1
  216. package/.claude/config/reverb-level.txt +0 -1
  217. package/.claude/config/tts-target-speech-rate.txt +0 -1
  218. package/voice-assignments.json +0 -8245
  219. /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 {