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,138 +1,138 @@
1
- #
2
- # File: .claude/hooks-windows/play-tts-termux-ssh.ps1
3
- #
4
- # AgentVibes - Finally, your AI Agents can Talk Back! Text-to-Speech WITH personality for AI Assistants!
5
- # Website: https://agentvibes.org
6
- # Repository: https://github.com/paulpreibisch/AgentVibes
7
- #
8
- # Co-created by Paul Preibisch with Claude AI
9
- # Copyright (c) 2025 Paul Preibisch
10
- #
11
- # Licensed under the Apache License, Version 2.0 (the "License");
12
- # you may not use this file except in compliance with the License.
13
- # You may obtain a copy of the License at
14
- #
15
- # http://www.apache.org/licenses/LICENSE-2.0
16
- #
17
- # ---
18
- #
19
- # @fileoverview Termux SSH TTS Provider (Windows) - Android TTS via SSH tunnel
20
- # @context Enables TTS output on Android devices when connected via SSH from Windows
21
- # @architecture SSH-based remote TTS invocation using termux-tts-speak on Android
22
- # @dependencies ssh.exe (OpenSSH for Windows), termux-tts-speak (on Android), termux-api (on Android)
23
- # @entrypoints Called by play-tts.ps1 router when provider=termux-ssh
24
- # @patterns Remote TTS invocation, SSH host alias configuration, graceful fallback
25
- # @related play-tts.ps1, provider-manager.ps1
26
- #
27
- # SETUP INSTRUCTIONS:
28
- # ===================
29
- # 1. On Android device (Termux):
30
- # - Install: pkg install termux-api openssh
31
- # - Install Termux:API app from F-Droid or Google Play
32
- # - Start SSH server: sshd
33
- #
34
- # 2. On Windows:
35
- # - Add to %USERPROFILE%\.ssh\config:
36
- # Host android
37
- # HostName <your-android-ip>
38
- # User <your-termux-username>
39
- # Port 8022
40
- # IdentityFile ~/.ssh/id_rsa
41
- #
42
- # 3. Configure AgentVibes:
43
- # - echo android > %USERPROFILE%\.claude\termux-ssh-host.txt
44
- # OR
45
- # - echo android > .claude\termux-ssh-host.txt (project-local)
46
- #
47
- # 4. Set provider:
48
- # - echo termux-ssh > %USERPROFILE%\.claude\tts-provider.txt
49
- #
50
-
51
- param(
52
- [Parameter(Mandatory = $true, Position = 0)]
53
- [string]$Text,
54
-
55
- [Parameter(Mandatory = $false, Position = 1)]
56
- [string]$VoiceOverride # Not used for termux-ssh, kept for interface compatibility
57
- )
58
-
59
- # Resolve ClaudeDir (project-local preferred, fallback to global)
60
- $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
61
- $ProjectClaudeDir = Split-Path -Parent $ScriptPath
62
- if (Test-Path (Join-Path $ProjectClaudeDir "config")) {
63
- $ClaudeDir = $ProjectClaudeDir
64
- } else {
65
- $ClaudeDir = "$env:USERPROFILE\.claude"
66
- }
67
-
68
- # @function Get-SshHost
69
- # @intent Determine SSH host alias for Android device
70
- # @why Allows users to configure their own SSH connection without hardcoded values
71
- # Priority: env var > project config > script-dir config > global config
72
- function Get-SshHost {
73
- if ($env:TERMUX_SSH_HOST) { return $env:TERMUX_SSH_HOST }
74
-
75
- $projectFile = Join-Path $ClaudeDir "termux-ssh-host.txt"
76
- if (Test-Path $projectFile) {
77
- $val = (Get-Content $projectFile -Raw).Trim()
78
- if ($val) { return $val }
79
- }
80
-
81
- $globalFile = "$env:USERPROFILE\.claude\termux-ssh-host.txt"
82
- if (Test-Path $globalFile) {
83
- $val = (Get-Content $globalFile -Raw).Trim()
84
- if ($val) { return $val }
85
- }
86
-
87
- return ""
88
- }
89
-
90
- # @function Test-SshConnection
91
- # @intent Quick reachability check before sending TTS
92
- # @why Prevents long hangs if Android is offline
93
- function Test-SshConnection {
94
- param([string]$SshTarget)
95
- try {
96
- $null = ssh -o ConnectTimeout=2 -o BatchMode=yes $SshTarget "echo ok" 2>&1
97
- return $LASTEXITCODE -eq 0
98
- } catch {
99
- return $false
100
- }
101
- }
102
-
103
- # --- Main ---
104
-
105
- if (-not $Text) {
106
- Write-Host "[ERROR] No text provided for TTS" -ForegroundColor Red
107
- exit 1
108
- }
109
-
110
- $SshAlias = Get-SshHost
111
-
112
- if (-not $SshAlias) {
113
- Write-Host "[ERROR] Termux SSH provider not configured" -ForegroundColor Red
114
- Write-Host " Set SSH host alias in one of:" -ForegroundColor Yellow
115
- Write-Host " Environment: `$env:TERMUX_SSH_HOST = 'android'" -ForegroundColor Yellow
116
- Write-Host " Global: echo android > `"$env:USERPROFILE\.claude\termux-ssh-host.txt`"" -ForegroundColor Yellow
117
- Write-Host " Project: echo android > .claude\termux-ssh-host.txt" -ForegroundColor Yellow
118
- exit 1
119
- }
120
-
121
- if (-not (Test-SshConnection -SshTarget $SshAlias)) {
122
- Write-Host "[WARNING] Cannot connect to SSH host '$SshAlias' - Android offline?" -ForegroundColor Yellow
123
- exit 1
124
- }
125
-
126
- # Escape single quotes for safe shell transmission
127
- $SafeText = $Text -replace "'", "'\'''"
128
-
129
- # Send TTS to Android asynchronously (audio plays on device)
130
- $job = Start-Job -ScriptBlock {
131
- param($alias, $text)
132
- ssh -o ConnectTimeout=5 $alias "termux-tts-speak '$text'" 2>&1
133
- } -ArgumentList $SshAlias, $SafeText
134
-
135
- Write-Host "[OK] TTS sent to Android ($SshAlias) via SSH" -ForegroundColor Green
136
-
137
- # Output empty string — audio plays on Android, not locally
138
- Write-Output ""
1
+ #
2
+ # File: .claude/hooks-windows/play-tts-termux-ssh.ps1
3
+ #
4
+ # AgentVibes - Finally, your AI Agents can Talk Back! Text-to-Speech WITH personality for AI Assistants!
5
+ # Website: https://agentvibes.org
6
+ # Repository: https://github.com/paulpreibisch/AgentVibes
7
+ #
8
+ # Co-created by Paul Preibisch with Claude AI
9
+ # Copyright (c) 2025 Paul Preibisch
10
+ #
11
+ # Licensed under the Apache License, Version 2.0 (the "License");
12
+ # you may not use this file except in compliance with the License.
13
+ # You may obtain a copy of the License at
14
+ #
15
+ # http://www.apache.org/licenses/LICENSE-2.0
16
+ #
17
+ # ---
18
+ #
19
+ # @fileoverview Termux SSH TTS Provider (Windows) - Android TTS via SSH tunnel
20
+ # @context Enables TTS output on Android devices when connected via SSH from Windows
21
+ # @architecture SSH-based remote TTS invocation using termux-tts-speak on Android
22
+ # @dependencies ssh.exe (OpenSSH for Windows), termux-tts-speak (on Android), termux-api (on Android)
23
+ # @entrypoints Called by play-tts.ps1 router when provider=termux-ssh
24
+ # @patterns Remote TTS invocation, SSH host alias configuration, graceful fallback
25
+ # @related play-tts.ps1, provider-manager.ps1
26
+ #
27
+ # SETUP INSTRUCTIONS:
28
+ # ===================
29
+ # 1. On Android device (Termux):
30
+ # - Install: pkg install termux-api openssh
31
+ # - Install Termux:API app from F-Droid or Google Play
32
+ # - Start SSH server: sshd
33
+ #
34
+ # 2. On Windows:
35
+ # - Add to %USERPROFILE%\.ssh\config:
36
+ # Host android
37
+ # HostName <your-android-ip>
38
+ # User <your-termux-username>
39
+ # Port 8022
40
+ # IdentityFile ~/.ssh/id_rsa
41
+ #
42
+ # 3. Configure AgentVibes:
43
+ # - echo android > %USERPROFILE%\.claude\termux-ssh-host.txt
44
+ # OR
45
+ # - echo android > .claude\termux-ssh-host.txt (project-local)
46
+ #
47
+ # 4. Set provider:
48
+ # - echo termux-ssh > %USERPROFILE%\.claude\tts-provider.txt
49
+ #
50
+
51
+ param(
52
+ [Parameter(Mandatory = $true, Position = 0)]
53
+ [string]$Text,
54
+
55
+ [Parameter(Mandatory = $false, Position = 1)]
56
+ [string]$VoiceOverride # Not used for termux-ssh, kept for interface compatibility
57
+ )
58
+
59
+ # Resolve ClaudeDir (project-local preferred, fallback to global)
60
+ $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
61
+ $ProjectClaudeDir = Split-Path -Parent $ScriptPath
62
+ if (Test-Path (Join-Path $ProjectClaudeDir "config")) {
63
+ $ClaudeDir = $ProjectClaudeDir
64
+ } else {
65
+ $ClaudeDir = "$env:USERPROFILE\.claude"
66
+ }
67
+
68
+ # @function Get-SshHost
69
+ # @intent Determine SSH host alias for Android device
70
+ # @why Allows users to configure their own SSH connection without hardcoded values
71
+ # Priority: env var > project config > script-dir config > global config
72
+ function Get-SshHost {
73
+ if ($env:TERMUX_SSH_HOST) { return $env:TERMUX_SSH_HOST }
74
+
75
+ $projectFile = Join-Path $ClaudeDir "termux-ssh-host.txt"
76
+ if (Test-Path $projectFile) {
77
+ $val = (Get-Content $projectFile -Raw).Trim()
78
+ if ($val) { return $val }
79
+ }
80
+
81
+ $globalFile = "$env:USERPROFILE\.claude\termux-ssh-host.txt"
82
+ if (Test-Path $globalFile) {
83
+ $val = (Get-Content $globalFile -Raw).Trim()
84
+ if ($val) { return $val }
85
+ }
86
+
87
+ return ""
88
+ }
89
+
90
+ # @function Test-SshConnection
91
+ # @intent Quick reachability check before sending TTS
92
+ # @why Prevents long hangs if Android is offline
93
+ function Test-SshConnection {
94
+ param([string]$SshTarget)
95
+ try {
96
+ $null = ssh -o ConnectTimeout=2 -o BatchMode=yes $SshTarget "echo ok" 2>&1
97
+ return $LASTEXITCODE -eq 0
98
+ } catch {
99
+ return $false
100
+ }
101
+ }
102
+
103
+ # --- Main ---
104
+
105
+ if (-not $Text) {
106
+ Write-Host "[ERROR] No text provided for TTS" -ForegroundColor Red
107
+ exit 1
108
+ }
109
+
110
+ $SshAlias = Get-SshHost
111
+
112
+ if (-not $SshAlias) {
113
+ Write-Host "[ERROR] Termux SSH provider not configured" -ForegroundColor Red
114
+ Write-Host " Set SSH host alias in one of:" -ForegroundColor Yellow
115
+ Write-Host " Environment: `$env:TERMUX_SSH_HOST = 'android'" -ForegroundColor Yellow
116
+ Write-Host " Global: echo android > `"$env:USERPROFILE\.claude\termux-ssh-host.txt`"" -ForegroundColor Yellow
117
+ Write-Host " Project: echo android > .claude\termux-ssh-host.txt" -ForegroundColor Yellow
118
+ exit 1
119
+ }
120
+
121
+ if (-not (Test-SshConnection -SshTarget $SshAlias)) {
122
+ Write-Host "[WARNING] Cannot connect to SSH host '$SshAlias' - Android offline?" -ForegroundColor Yellow
123
+ exit 1
124
+ }
125
+
126
+ # Escape single quotes for safe shell transmission
127
+ $SafeText = $Text -replace "'", "'\'''"
128
+
129
+ # Send TTS to Android asynchronously (audio plays on device)
130
+ $job = Start-Job -ScriptBlock {
131
+ param($alias, $text)
132
+ ssh -o ConnectTimeout=5 $alias "termux-tts-speak '$text'" 2>&1
133
+ } -ArgumentList $SshAlias, $SafeText
134
+
135
+ Write-Host "[OK] TTS sent to Android ($SshAlias) via SSH" -ForegroundColor Green
136
+
137
+ # Output empty string — audio plays on Android, not locally
138
+ Write-Output ""
@@ -0,0 +1,178 @@
1
+ #
2
+ # File: .claude/hooks-windows/play-tts-windows-piper.ps1
3
+ #
4
+ # AgentVibes - Windows Piper TTS Provider
5
+ # High-quality neural TTS using Piper.exe
6
+ #
7
+
8
+ param(
9
+ [Parameter(Mandatory = $true)]
10
+ [string]$Text,
11
+
12
+ [Parameter(Mandatory = $false)]
13
+ [string]$VoiceOverride
14
+ )
15
+
16
+ # Configuration paths
17
+ $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
18
+ $ProjectClaudeDir = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptPath)) ".claude"
19
+
20
+ if (Test-Path $ProjectClaudeDir) {
21
+ $ClaudeDir = $ProjectClaudeDir
22
+ } else {
23
+ $ClaudeDir = "$env:USERPROFILE\.claude"
24
+ }
25
+
26
+ # Audio cache and voice config use project-local .claude
27
+ $AudioDir = "$ClaudeDir\audio"
28
+ $VoiceFile = "$ClaudeDir\tts-voice-piper.txt"
29
+
30
+ # Voices and Piper binary are global (shared across projects, ~100MB+)
31
+ $UserClaudeDir = "$env:USERPROFILE\.claude"
32
+ $VoicesDir = "$UserClaudeDir\piper-voices"
33
+ $PiperExe = "$env:LOCALAPPDATA\Programs\Piper\piper.exe"
34
+
35
+ # Ensure directories exist
36
+ foreach ($dir in @($AudioDir, $VoicesDir)) {
37
+ if (-not (Test-Path $dir)) {
38
+ New-Item -ItemType Directory -Path $dir -Force | Out-Null
39
+ }
40
+ }
41
+
42
+ # Check if Piper is installed
43
+ if (-not (Test-Path $PiperExe)) {
44
+ Write-Host "[ERROR] Piper not found at: $PiperExe" -ForegroundColor Red
45
+ Write-Host "Run: .\setup-windows.ps1 to install Piper" -ForegroundColor Yellow
46
+ exit 1
47
+ }
48
+
49
+ # Determine voice to use
50
+ $VoiceName = ""
51
+
52
+ if ($VoiceOverride) {
53
+ $VoiceName = $VoiceOverride
54
+ }
55
+ elseif (Test-Path $VoiceFile) {
56
+ $VoiceName = (Get-Content $VoiceFile -Raw).Trim()
57
+ }
58
+
59
+ # Default voice if not specified
60
+ if (-not $VoiceName) {
61
+ $VoiceName = "en_US-ryan-high"
62
+ }
63
+
64
+ # Security: Validate voice name to prevent path traversal
65
+ # Only allow alphanumeric, underscore, hyphen, and period
66
+ if ($VoiceName -notmatch '^[a-zA-Z0-9_\-\.]+$') {
67
+ Write-Host "[ERROR] Invalid voice name: $VoiceName" -ForegroundColor Red
68
+ exit 1
69
+ }
70
+
71
+ # Resolve voice model path and validate it stays within VoicesDir
72
+ $VoiceModelFile = [System.IO.Path]::GetFullPath("$VoicesDir\$VoiceName.onnx")
73
+ $VoiceJsonFile = [System.IO.Path]::GetFullPath("$VoicesDir\$VoiceName.onnx.json")
74
+ $ResolvedVoicesDir = [System.IO.Path]::GetFullPath($VoicesDir)
75
+ if (-not $VoiceModelFile.StartsWith($ResolvedVoicesDir)) {
76
+ Write-Host "[ERROR] Voice path outside voices directory" -ForegroundColor Red
77
+ exit 1
78
+ }
79
+
80
+ # Check if voice model exists, download if missing
81
+ if (-not (Test-Path $VoiceModelFile)) {
82
+ Write-Host "[DOWNLOAD] Voice model: $VoiceName" -ForegroundColor Yellow
83
+
84
+ # Try to download from Hugging Face
85
+ # Voice name format: {lang}_{region}-{speaker}-{quality}
86
+ # HF path format: {lang}/{lang}_{region}/{speaker}/{quality}/{voicename}.onnx
87
+ try {
88
+ # Parse voice name to build correct HF path
89
+ # e.g. en_US-ryan-high -> en/en_US/ryan/high/en_US-ryan-high.onnx
90
+ if ($VoiceName -match '^([a-z]{2})_([A-Z]{2})-([a-zA-Z0-9_]+)-([a-z]+)$') {
91
+ $Lang = $Matches[1]
92
+ $LangRegion = "$($Matches[1])_$($Matches[2])"
93
+ $Speaker = $Matches[3]
94
+ $Quality = $Matches[4]
95
+ $HFBase = "https://huggingface.co/rhasspy/piper-voices/resolve/main/$Lang/$LangRegion/$Speaker/$Quality"
96
+ } else {
97
+ # Fallback for non-standard voice names
98
+ $HFBase = "https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/ryan/high"
99
+ }
100
+ $ModelUrl = "$HFBase/$VoiceName.onnx"
101
+ $JsonUrl = "$HFBase/$VoiceName.onnx.json"
102
+
103
+ Write-Host " Downloading model..." -ForegroundColor Cyan
104
+ Invoke-WebRequest -Uri $ModelUrl -OutFile $VoiceModelFile -ErrorAction Stop
105
+ Write-Host " Downloading config..." -ForegroundColor Cyan
106
+ Invoke-WebRequest -Uri $JsonUrl -OutFile $VoiceJsonFile -ErrorAction Stop
107
+ Write-Host "[OK] Voice model downloaded" -ForegroundColor Green
108
+ }
109
+ catch {
110
+ Write-Host "[ERROR] Failed to download voice model: $_" -ForegroundColor Red
111
+ Write-Host "Make sure you have internet connection" -ForegroundColor Yellow
112
+ exit 1
113
+ }
114
+ }
115
+
116
+ # Sanitize text for speech - strip shell metacharacters and PS special chars
117
+ $Text = $Text -replace '\\', ' '
118
+ $Text = $Text -replace '[{}<>|`~^$;"''()]', ''
119
+ $Text = $Text -replace '\s+', ' '
120
+ $Text = $Text.Trim()
121
+
122
+ # Create audio file path
123
+ $Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss-ffff'
124
+ $AudioFile = "$AudioDir\tts-$Timestamp.wav"
125
+
126
+ # Synthesize with Piper
127
+ try {
128
+ Write-Host "[SYNTH] Synthesizing with Piper..." -ForegroundColor Cyan
129
+
130
+ # Run Piper with text input
131
+ $Text | & $PiperExe `
132
+ --model $VoiceModelFile `
133
+ --output-file $AudioFile `
134
+ 2>$null
135
+
136
+ if (-not (Test-Path $AudioFile)) {
137
+ Write-Host "[ERROR] Piper synthesis failed" -ForegroundColor Red
138
+ exit 1
139
+ }
140
+
141
+ # Display results
142
+ Write-Host "[OK] Saved to: $AudioFile" -ForegroundColor Green
143
+ Write-Host "[VOICE] Voice used: $VoiceName (Piper)" -ForegroundColor Green
144
+
145
+ # Play the audio (skip if AGENTVIBES_NO_PLAY is set)
146
+ if (-not $env:AGENTVIBES_NO_PLAY) {
147
+ # Prefer ffplay: handles 22050 Hz → 48000 Hz resampling cleanly (SoundPlayer uses
148
+ # WinMM's low-quality resampler which produces choppy audio at non-native rates).
149
+ $ffplayPath = (Get-Command ffplay -ErrorAction SilentlyContinue)?.Source
150
+ if (-not $ffplayPath) {
151
+ # SSH/watcher sessions may have a minimal PATH — refresh from registry
152
+ $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" +
153
+ [System.Environment]::GetEnvironmentVariable("Path","User")
154
+ $ffplayPath = (Get-Command ffplay -ErrorAction SilentlyContinue)?.Source
155
+ }
156
+ if ($ffplayPath) {
157
+ & $ffplayPath -autoexit -nodisp -loglevel quiet $AudioFile 2>$null
158
+ }
159
+ else {
160
+ $player = $null
161
+ try {
162
+ $player = New-Object System.Media.SoundPlayer $AudioFile
163
+ $player.PlaySync()
164
+ }
165
+ catch {
166
+ Write-Host "[WARNING] Could not play audio (SoundPlayer unavailable)" -ForegroundColor Yellow
167
+ Write-Host "Audio saved to: $AudioFile" -ForegroundColor Gray
168
+ }
169
+ finally {
170
+ if ($player) { $player.Dispose() }
171
+ }
172
+ }
173
+ }
174
+ }
175
+ catch {
176
+ Write-Host "[ERROR] Error running Piper: $_" -ForegroundColor Red
177
+ exit 1
178
+ }
@@ -0,0 +1,108 @@
1
+ #
2
+ # File: .claude/hooks-windows/play-tts-windows-sapi.ps1
3
+ #
4
+ # AgentVibes - Windows SAPI TTS Provider (Zero Dependencies)
5
+ # Uses built-in Windows System.Speech API
6
+ #
7
+
8
+ param(
9
+ [Parameter(Mandatory = $true)]
10
+ [string]$Text,
11
+
12
+ [Parameter(Mandatory = $false)]
13
+ [string]$VoiceOverride
14
+ )
15
+
16
+ # Configuration paths
17
+ $ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
18
+ $ProjectClaudeDir = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptPath)) ".claude"
19
+
20
+ if (Test-Path $ProjectClaudeDir) {
21
+ $ClaudeDir = $ProjectClaudeDir
22
+ } else {
23
+ $ClaudeDir = "$env:USERPROFILE\.claude"
24
+ }
25
+
26
+ $AudioDir = "$ClaudeDir\audio"
27
+ $VoiceFile = "$ClaudeDir\tts-voice-sapi.txt"
28
+
29
+ # Ensure directories exist
30
+ if (-not (Test-Path $AudioDir)) {
31
+ New-Item -ItemType Directory -Path $AudioDir -Force | Out-Null
32
+ }
33
+
34
+ # Load System.Speech assembly
35
+ try {
36
+ Add-Type -AssemblyName System.Speech
37
+ }
38
+ catch {
39
+ Write-Host "[ERROR] System.Speech assembly not available" -ForegroundColor Red
40
+ exit 1
41
+ }
42
+
43
+ # Determine voice to use
44
+ $VoiceName = ""
45
+
46
+ if ($VoiceOverride) {
47
+ $VoiceName = $VoiceOverride
48
+ }
49
+ elseif (Test-Path $VoiceFile) {
50
+ $VoiceName = (Get-Content $VoiceFile -Raw).Trim()
51
+ }
52
+
53
+ # Initialize speech synthesizer
54
+ $synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
55
+
56
+ # Set voice if specified
57
+ if ($VoiceName) {
58
+ try {
59
+ $synth.SelectVoice($VoiceName)
60
+ }
61
+ catch {
62
+ Write-Host "[WARNING] Voice '$VoiceName' not found, using default" -ForegroundColor Yellow
63
+ }
64
+ }
65
+
66
+ # Sanitize text for speech - strip shell metacharacters, PS special chars, and SSML tags
67
+ $Text = $Text -replace '\\', ' '
68
+ $Text = $Text -replace '[{}<>|`~^$;"''()]', ''
69
+ $Text = $Text -replace '&[a-zA-Z]+;', ''
70
+ $Text = $Text -replace '\s+', ' '
71
+ $Text = $Text.Trim()
72
+
73
+ # Get actual voice name (after selection or default)
74
+ $ActualVoice = $synth.Voice.Name
75
+
76
+ # Create audio file path
77
+ $Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss-ffff'
78
+ $AudioFile = "$AudioDir\tts-$Timestamp.wav"
79
+
80
+ # Save to WAV file with proper resource cleanup
81
+ $player = $null
82
+ try {
83
+ $synth.SetOutputToWaveFile($AudioFile)
84
+ $synth.Speak($Text)
85
+
86
+ # Display results
87
+ Write-Host "[OK] Saved to: $AudioFile" -ForegroundColor Green
88
+ Write-Host "[VOICE] Voice used: $ActualVoice (Windows SAPI)" -ForegroundColor Green
89
+
90
+ # Play the audio using built-in Windows audio player (skip if AGENTVIBES_NO_PLAY is set)
91
+ if (-not $env:AGENTVIBES_NO_PLAY) {
92
+ try {
93
+ $player = New-Object System.Media.SoundPlayer $AudioFile
94
+ $player.PlaySync()
95
+ }
96
+ catch {
97
+ Write-Host "[WARNING] Could not play audio (SoundPlayer unavailable)" -ForegroundColor Yellow
98
+ }
99
+ }
100
+ }
101
+ catch {
102
+ Write-Host "[ERROR] Error synthesizing speech: $_" -ForegroundColor Red
103
+ exit 1
104
+ }
105
+ finally {
106
+ if ($synth) { $synth.Dispose() }
107
+ if ($player) { $player.Dispose() }
108
+ }