agentvibes 5.11.2 → 5.12.0-alpha.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 (97) hide show
  1. package/.agentvibes/config.json +1 -15
  2. package/.claude/activation-instructions +54 -54
  3. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  4. package/.claude/commands/agent-vibes-rdp.md +24 -24
  5. package/.claude/config/audio-effects.cfg +5 -5
  6. package/.claude/config/background-music-enabled.txt +1 -1
  7. package/.claude/docs/TERMUX_SETUP.md +408 -408
  8. package/.claude/github-star-reminder.txt +1 -1
  9. package/.claude/hooks/audio-processor.sh +1 -1
  10. package/.claude/hooks/background-music-manager.sh +2 -1
  11. package/.claude/hooks/bmad-speak-enhanced.sh +37 -22
  12. package/.claude/hooks/bmad-speak.sh +26 -8
  13. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +1 -1
  14. package/.claude/hooks/play-tts-kokoro.sh +9 -0
  15. package/.claude/hooks/play-tts-piper.sh +13 -1
  16. package/.claude/hooks/play-tts-ssh-remote.sh +78 -5
  17. package/.claude/hooks/play-tts-termux-ssh.sh +1 -1
  18. package/.claude/hooks/play-tts.sh +85 -4
  19. package/.claude/hooks-windows/background-music-manager.ps1 +2 -1
  20. package/.claude/hooks-windows/play-tts-kokoro.ps1 +14 -0
  21. package/.claude/hooks-windows/play-tts.ps1 +163 -30
  22. package/.claude/hooks-windows/voice-manager-windows.ps1 +101 -1
  23. package/.clawdbot/README.md +105 -105
  24. package/LICENSE +190 -190
  25. package/RELEASE_NOTES.md +29 -0
  26. package/WINDOWS-SETUP.md +208 -208
  27. package/bin/agent-vibes +39 -39
  28. package/bin/mcp-server.js +121 -121
  29. package/bin/mcp-server.sh +6 -19
  30. package/bin/resolve-utterance.js +137 -0
  31. package/bin/test-bmad-pr +78 -78
  32. package/mcp-server/QUICK_START.md +203 -203
  33. package/mcp-server/README.md +345 -345
  34. package/mcp-server/examples/claude_desktop_config.json +11 -11
  35. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  36. package/mcp-server/examples/custom_instructions.md +169 -169
  37. package/mcp-server/pyproject.toml +52 -52
  38. package/mcp-server/requirements.txt +2 -2
  39. package/mcp-server/server.py +280 -99
  40. package/mcp-server/test_mcp_correctness.py +486 -0
  41. package/mcp-server/test_server.py +395 -395
  42. package/mcp-server/test_windows_script_parity.py +341 -336
  43. package/package.json +3 -2
  44. package/setup-windows.ps1 +867 -815
  45. package/src/cli/list-personalities.js +110 -110
  46. package/src/cli/list-voices.js +114 -114
  47. package/src/commands/bmad-voices.js +394 -394
  48. package/src/console/app.js +13 -2
  49. package/src/console/brand-colors.js +13 -13
  50. package/src/console/constants/personalities.js +44 -44
  51. package/src/console/tabs/agents-tab.js +82 -9
  52. package/src/console/tabs/help-tab.js +314 -314
  53. package/src/console/tabs/music-tab.js +7 -1
  54. package/src/console/tabs/readme-tab.js +272 -272
  55. package/src/console/tabs/settings-tab.js +29 -1
  56. package/src/console/tabs/setup-tab.js +4 -4
  57. package/src/console/widgets/destroy-list.js +25 -25
  58. package/src/console/widgets/notice.js +55 -55
  59. package/src/console/widgets/track-picker.js +3 -3
  60. package/src/i18n/de.js +0 -1
  61. package/src/i18n/en.js +0 -1
  62. package/src/i18n/es.js +0 -1
  63. package/src/i18n/fr.js +0 -1
  64. package/src/i18n/hi.js +0 -1
  65. package/src/i18n/ja.js +0 -1
  66. package/src/i18n/ko.js +0 -1
  67. package/src/i18n/pt.js +0 -1
  68. package/src/i18n/zh-CN.js +0 -1
  69. package/src/installer/language-screen.js +31 -31
  70. package/src/installer/music-file-input.js +304 -304
  71. package/src/installer.js +205 -15
  72. package/src/services/config-service.js +264 -264
  73. package/src/services/language-service.js +47 -47
  74. package/src/services/llm-provider-service.js +7 -7
  75. package/src/services/utterance-loader.js +280 -0
  76. package/src/services/utterance-resolver.js +526 -0
  77. package/src/utils/audio-format-validator.js +277 -277
  78. package/src/utils/dependency-checker.js +469 -469
  79. package/src/utils/file-ownership-verifier.js +358 -358
  80. package/src/utils/music-file-validator.js +285 -285
  81. package/src/utils/preview-list-prompt.js +144 -144
  82. package/src/utils/secure-music-storage.js +412 -412
  83. package/templates/agentvibes-receiver.sh +74 -12
  84. package/voice-assignments.json +8245 -0
  85. package/.agentvibes/install-manifest.json +0 -342
  86. package/.claude/config/background-music-position.txt +0 -27
  87. package/.claude/config/background-music-volume.txt +0 -1
  88. package/.claude/config/background-music.cfg +0 -1
  89. package/.claude/config/background-music.txt +0 -1
  90. package/.claude/config/language.txt +0 -1
  91. package/.claude/config/personality.txt +0 -1
  92. package/.claude/config/tts-speech-rate.txt +0 -1
  93. package/.claude/config/tts-verbosity.txt +0 -1
  94. package/.claude/hooks-windows/audio-cache-utils.ps1.user.bak +0 -119
  95. package/.claude/hooks-windows/soprano-gradio-synth.py.user.bak +0 -153
  96. package/.claude/piper-voices-dir.txt +0 -1
  97. package/.mcp.json +0 -22
@@ -213,7 +213,7 @@ if ($BgEnabled -or $HasReverb) {
213
213
  # 1. Key - Must start with "llm:" followed by the LLM name
214
214
  # 2. REVERB_PRESET - One of: off, light, medium, heavy, cathedral (or blank)
215
215
  # 3. BACKGROUND_FILE - Filename relative to .claude/audio/tracks/ (or blank)
216
- # 4. BACKGROUND_VOLUME - Float 0.0-1.0 (or blank for default 0.25)
216
+ # 4. BACKGROUND_VOLUME - Float 0.0-1.0 (or blank for default 0.20)
217
217
  # 5. VOICE - Provider voice name to use (or blank for global default)
218
218
  # 6. PRETEXT - Text prepended to all TTS utterances (or blank)
219
219
  # 7. ENGINE - Windows engine: windows-sapi, windows-piper, soprano (or blank)
@@ -263,6 +263,99 @@ if (-not $llm) {
263
263
  # the POSIX play-tts.sh so the cross-platform contract is symmetric.
264
264
  $env:AGENTVIBES_LLM_KEY = "llm:$llm"
265
265
 
266
+ # ── Utterance Resolver (AVI-S8.5 Stage 2) ────────────────────────────────────
267
+ # Single source of truth for the voice + engine decision, mirroring the bash
268
+ # play-tts.sh port. Resolve the plan ONCE and adopt its voice (per-LLM voice
269
+ # wins over an LLM-echoed explicit override — R2) and, below, its local engine
270
+ # (a kokoro-shaped voice forces the kokoro engine and engine aliases normalize —
271
+ # R1/F5). FAIL-SAFE: if node or the resolver bundle isn't reachable (e.g. an
272
+ # installed ~/.claude that predates the bundle-shipping installer), $PlanOk
273
+ # stays $false and the legacy logic below runs unchanged — Windows TTS never
274
+ # breaks on a missing bridge. AGENTVIBES_RESOLVER_CLI lets the installer (or
275
+ # tests) point at the resolver bundle when it lives outside the hooks tree.
276
+
277
+ # Map a resolver engine name to its Windows provider script. Returns $null for
278
+ # engines with no local Windows script (e.g. elevenlabs/macos) so the caller
279
+ # keeps the current provider rather than breaking playback.
280
+ function Resolve-ProviderScriptForEngine {
281
+ param([string]$Engine, [string]$HooksRoot)
282
+ switch ($Engine) {
283
+ { $_ -in "windows-sapi", "sapi" } {
284
+ $s = "$HooksRoot\play-tts-sapi.ps1"
285
+ if (-not (Test-Path $s)) { $s = "$HooksRoot\play-tts-windows-sapi.ps1" }
286
+ return $s
287
+ }
288
+ { $_ -in "windows-piper", "piper" } {
289
+ $s = "$HooksRoot\play-tts-piper.ps1"
290
+ if (-not (Test-Path $s)) { $s = "$HooksRoot\play-tts-windows-piper.ps1" }
291
+ return $s
292
+ }
293
+ "soprano" { return "$HooksRoot\play-tts-soprano.ps1" }
294
+ "kokoro" { return "$HooksRoot\play-tts-kokoro.ps1" }
295
+ default { return $null }
296
+ }
297
+ }
298
+
299
+ $_OrigExplicitVoice = $VoiceOverride # raw positional voice, before any per-LLM override
300
+ $PlanOk = $false
301
+ $PlanVoice = ""
302
+ $PlanEngine = ""
303
+ $PlanVoiceIsOverride = $false
304
+ # F-3: the SSH-receiver watcher forwards the sender's engine via -ProviderOverride
305
+ # (a parameter the resolver can't see). Seed AGENTVIBES_FORCE_PROVIDER from it so
306
+ # the resolver honors the forwarded provider instead of defaulting the plan engine
307
+ # to piper (which dropped a forwarded windows-sapi/soprano voice → wrong/no audio).
308
+ if ($ProviderOverride) {
309
+ # A fresh -ProviderOverride for THIS request must win over any stale/inherited
310
+ # AGENTVIBES_FORCE_PROVIDER in the environment (a validated allowlist only).
311
+ switch ($ProviderOverride) {
312
+ { $_ -in @('piper','soprano','macos','windows-sapi','sapi','kokoro','elevenlabs','windows-piper') } {
313
+ $env:AGENTVIBES_FORCE_PROVIDER = $ProviderOverride
314
+ }
315
+ }
316
+ }
317
+ $_ResolverCli = ""
318
+ foreach ($_cand in @(
319
+ $env:AGENTVIBES_RESOLVER_CLI,
320
+ (Join-Path $ScriptPath "..\agentvibes-resolver\bin\resolve-utterance.js"),
321
+ (Join-Path $ScriptPath "..\..\bin\resolve-utterance.js"),
322
+ (Join-Path $ScriptPath "resolve-utterance.js"))) {
323
+ if ($_cand -and (Test-Path $_cand)) { $_ResolverCli = $_cand; break }
324
+ }
325
+ $_NodeCmd = Get-Command node -ErrorAction SilentlyContinue
326
+ if ($_ResolverCli -and $_NodeCmd) {
327
+ # Voice provenance (F-1): AGENTVIBES_VOICE_SOURCE lets a caller declare it
328
+ # (MCP/watcher → user-explicit/agent-profile); audition never demotes; else
329
+ # llm-echo (parroted get_config voice, which the per-LLM row overrides — R2).
330
+ $_VoiceSource = if ($env:AGENTVIBES_VOICE_SOURCE) { $env:AGENTVIBES_VOICE_SOURCE }
331
+ elseif ($env:AGENTVIBES_EFFECTS_PREVIEW) { "audition" }
332
+ else { "llm-echo" }
333
+ $_ResolverPackageRoot = Split-Path -Parent $ClaudeDir
334
+ $_ResolverProjectDir = if ($env:CLAUDE_PROJECT_DIR) { $env:CLAUDE_PROJECT_DIR } else { $_ResolverPackageRoot }
335
+ $_ResolverArgs = @('--format', 'json', '--text', $Text, '--llm', $llm,
336
+ '--voice-source', $_VoiceSource, '--project-dir', $_ResolverProjectDir,
337
+ '--package-root', $_ResolverPackageRoot)
338
+ # Only pass --voice when there IS an explicit voice; an absent flag tells the
339
+ # resolver "no explicit override" (so per-LLM routing applies cleanly).
340
+ if ($_OrigExplicitVoice) { $_ResolverArgs += @('--voice', $_OrigExplicitVoice) }
341
+ try {
342
+ $_PlanJson = & $_NodeCmd.Source $_ResolverCli @_ResolverArgs 2>$null
343
+ if ($LASTEXITCODE -eq 0 -and $_PlanJson) {
344
+ $_Plan = ($_PlanJson | Out-String).Trim() | ConvertFrom-Json
345
+ if ($_Plan) {
346
+ $PlanOk = $true
347
+ if ($_Plan.voice) { $PlanVoice = [string]$_Plan.voice }
348
+ if ($_Plan.engine) { $PlanEngine = [string]$_Plan.engine }
349
+ $PlanVoiceIsOverride = [bool]$_Plan.voiceIsOverride
350
+ }
351
+ }
352
+ } catch {
353
+ # Any bridge failure (bad JSON, nonzero exit, missing bundle) fails safe
354
+ # to the legacy logic below.
355
+ $PlanOk = $false
356
+ }
357
+ }
358
+
266
359
  # --- Lookup per-LLM config in audio-effects.cfg ------------------------------
267
360
  # Scan project config first, then user-profile config. Stop at first match.
268
361
  # Variables are intentionally prefixed with _ to distinguish LLM-local state
@@ -320,8 +413,20 @@ $_LlmFound = $false
320
413
  # 3. BMAD agent voice from bmad-voice-map.json (resolved in provider scripts)
321
414
  # 4. Global active voice from tts-provider.txt / active-voice.txt
322
415
 
323
- # Apply LLM-specific voice only when no explicit -VoiceOverride was passed
324
- if ($_LlmVoice -and -not $VoiceOverride) {
416
+ # Adopt the resolver's voice when a plan resolved (AVI-S8.5 Stage 2). The plan
417
+ # already applied the R2 precedence (per-LLM voice wins over an LLM-echoed
418
+ # explicit override; genuine explicit/audition voices still win), so take it
419
+ # verbatim. FAIL-SAFE fallback: with no plan, use the legacy explicit-wins order
420
+ # (explicit -VoiceOverride > per-LLM voice).
421
+ # F-2: adopt the plan voice ONLY when it's a real override (explicit pick or
422
+ # per-LLM row) — not the provider's stored voice file. A plain provider-file
423
+ # voice is left empty here so the provider script does its own file+model+speaker
424
+ # resolution (adopting it as an explicit override skips piper's multi-speaker
425
+ # lookup and plays speaker 0). Engine coupling (R1) still applies regardless.
426
+ if ($PlanOk -and $PlanVoiceIsOverride -and $PlanVoice) {
427
+ $VoiceOverride = $PlanVoice
428
+ }
429
+ elseif (-not $PlanOk -and $_LlmVoice -and -not $VoiceOverride) {
325
430
  $VoiceOverride = $_LlmVoice
326
431
  }
327
432
 
@@ -398,31 +503,45 @@ if ($OverrideEffects -ne "" -and $OverrideEffects -in @("off", "light", "medium"
398
503
  # piper/sapi for that LLM's normal text responses that use Piper voices — must
399
504
  # NOT redirect it to an incompatible engine, or synthesis fails silently
400
505
  # (Piper can't find the Kokoro voice model → no audio, exit 0).
401
- $_VoiceIsKokoro = $VoiceOverride -match '^[a-z]{2}_[a-z0-9_]+$'
402
- if ($_VoiceIsKokoro) {
403
- # A Kokoro-format voice forces the Kokoro engine regardless of the per-LLM
404
- # ENGINE column or the global tts-provider.txt default.
405
- $ProviderScript = "$HooksDir\play-tts-kokoro.ps1"
406
- }
407
- elseif ($_LlmEngine) {
408
- # Accept both canonical Windows names and the cross-platform aliases the TUI
409
- # writes (e.g. "piper" saved on a Linux/WSL install that is later read on
410
- # Windows, or "sapi" as a short form). Unknown values keep the global default.
411
- # Mirror the global-provider switch: prefer the PS-5.1-compatible script name,
412
- # fall back to the alternate name if the first doesn't exist on disk.
413
- switch ($_LlmEngine) {
414
- { $_ -in "windows-sapi", "sapi" } {
415
- $ProviderScript = "$HooksDir\play-tts-sapi.ps1"
416
- if (-not (Test-Path $ProviderScript)) { $ProviderScript = "$HooksDir\play-tts-windows-sapi.ps1" }
417
- }
418
- { $_ -in "windows-piper", "piper" } {
419
- $ProviderScript = "$HooksDir\play-tts-piper.ps1"
420
- if (-not (Test-Path $ProviderScript)) { $ProviderScript = "$HooksDir\play-tts-windows-piper.ps1" }
421
- }
422
- "soprano" { $ProviderScript = "$HooksDir\play-tts-soprano.ps1" }
423
- "kokoro" { $ProviderScript = "$HooksDir\play-tts-kokoro.ps1" }
424
- default {
425
- Write-Host "[INFO] play-tts.ps1: Unrecognised engine '$_LlmEngine' keeping default provider" -ForegroundColor DarkGray
506
+ if ($PlanOk -and $PlanEngine) {
507
+ # Resolver plan is authoritative for the LOCAL engine (AVI-S8.5 Stage 2):
508
+ # this cures the kokoro/piper voice->engine coupling (R1) and normalizes
509
+ # engine aliases like windows-sapi->sapi (F5), replacing the legacy heuristic
510
+ # below. An engine with no local Windows script (elevenlabs/macos) leaves the
511
+ # current provider in place.
512
+ $_PlanScript = Resolve-ProviderScriptForEngine -Engine $PlanEngine -HooksRoot $HooksDir
513
+ if ($_PlanScript) { $ProviderScript = $_PlanScript }
514
+ }
515
+ else {
516
+ # Legacy voice->engine heuristic ONLY on the fallback path (no resolver
517
+ # plan). When a plan resolved, the resolver already coupled voice->engine
518
+ # correctly above, so this is skipped.
519
+ $_VoiceIsKokoro = $VoiceOverride -match '^[a-z]{2}_[a-z0-9_]+$'
520
+ if ($_VoiceIsKokoro) {
521
+ # A Kokoro-format voice forces the Kokoro engine regardless of the per-LLM
522
+ # ENGINE column or the global tts-provider.txt default.
523
+ $ProviderScript = "$HooksDir\play-tts-kokoro.ps1"
524
+ }
525
+ elseif ($_LlmEngine) {
526
+ # Accept both canonical Windows names and the cross-platform aliases the TUI
527
+ # writes (e.g. "piper" saved on a Linux/WSL install that is later read on
528
+ # Windows, or "sapi" as a short form). Unknown values keep the global default.
529
+ # Mirror the global-provider switch: prefer the PS-5.1-compatible script name,
530
+ # fall back to the alternate name if the first doesn't exist on disk.
531
+ switch ($_LlmEngine) {
532
+ { $_ -in "windows-sapi", "sapi" } {
533
+ $ProviderScript = "$HooksDir\play-tts-sapi.ps1"
534
+ if (-not (Test-Path $ProviderScript)) { $ProviderScript = "$HooksDir\play-tts-windows-sapi.ps1" }
535
+ }
536
+ { $_ -in "windows-piper", "piper" } {
537
+ $ProviderScript = "$HooksDir\play-tts-piper.ps1"
538
+ if (-not (Test-Path $ProviderScript)) { $ProviderScript = "$HooksDir\play-tts-windows-piper.ps1" }
539
+ }
540
+ "soprano" { $ProviderScript = "$HooksDir\play-tts-soprano.ps1" }
541
+ "kokoro" { $ProviderScript = "$HooksDir\play-tts-kokoro.ps1" }
542
+ default {
543
+ Write-Host "[INFO] play-tts.ps1: Unrecognised engine '$_LlmEngine' — keeping default provider" -ForegroundColor DarkGray
544
+ }
426
545
  }
427
546
  }
428
547
  }
@@ -437,7 +556,20 @@ elseif ($_LlmEngine) {
437
556
 
438
557
  # --- Diagnostic output -------------------------------------------------------
439
558
  # Set AGENTVIBES_VERBOSE=1 in the shell environment to print routing state.
559
+ # The bare `provider=`/`voice=`/`plan=` lines mirror play-tts.sh's verbose
560
+ # DECISION echo so the resolved engine/voice can be characterization-tested
561
+ # without producing real audio (see test/windows/play-tts-resolver.Tests.ps1).
440
562
  if ($env:AGENTVIBES_VERBOSE -eq "1") {
563
+ $_ProviderName = switch -Wildcard ($ProviderScript) {
564
+ "*play-tts-kokoro.ps1" { "kokoro" }
565
+ "*soprano*" { "soprano" }
566
+ "*piper*" { "piper" }
567
+ "*sapi*" { "sapi" }
568
+ default { Split-Path -Leaf $ProviderScript }
569
+ }
570
+ Write-Output "provider=$_ProviderName"
571
+ Write-Output "voice=$VoiceOverride"
572
+ Write-Output ("plan=" + $(if ($PlanOk) { "ok" } else { "fallback" }))
441
573
  Write-Host "[DEBUG] play-tts.ps1 LLM routing: llm=$llm | voice=$VoiceOverride | engine=$_LlmEngine | pretext=$_LlmPretext" -ForegroundColor DarkCyan
442
574
  Write-Host "[DEBUG] play-tts.ps1 LLM routing: reverb=$ReverbLevel | HasFfmpeg=$HasFfmpeg | BgEnabled=$BgEnabled | script=$ProviderScript" -ForegroundColor DarkCyan
443
575
  }
@@ -574,8 +706,9 @@ if (($BgEnabled -or $HasReverb) -and $HasFfmpeg) {
574
706
  $BgTrackPath = Join-Path $TracksDir "agent_vibes_bachata_v1_loop.mp3"
575
707
  }
576
708
 
577
- # Get volume (default 0.25) — per-message override takes precedence
578
- $BgVolume = "0.25"
709
+ # Get volume (default 0.20) — per-message override takes precedence
710
+ # TODO(AVI-S8.6): generate this constant from the shared JSON source of truth.
711
+ $BgVolume = "0.20"
579
712
  $VolumeFile = "$ConfigDir\background-music-volume.txt"
580
713
  if (Test-Path $VolumeFile) {
581
714
  $vol = (Get-Content $VolumeFile -Raw).Trim()
@@ -6,7 +6,7 @@
6
6
 
7
7
  param(
8
8
  [Parameter(Position = 0)]
9
- [ValidateSet('list', 'switch', 'get')]
9
+ [ValidateSet('list', 'switch', 'get', 'replay')]
10
10
  [string]$Command = 'list',
11
11
 
12
12
  [Parameter(Position = 1)]
@@ -155,6 +155,102 @@ function Show-CurrentVoice {
155
155
  }
156
156
  }
157
157
 
158
+ # Play an audio file without blocking the caller (mirrors voice-manager.sh's
159
+ # `afplay "$AUDIO_FILE" &` / `paplay ... &` background playback). Prefers
160
+ # ffplay (handles wav/mp3/aiff); falls back to System.Media.SoundPlayer
161
+ # (.Play(), which is inherently async — wav only).
162
+ function Start-ReplayPlayback {
163
+ param([string]$FilePath)
164
+
165
+ # Stay silent while the automated test suite is running (same convention
166
+ # as play-tts.ps1's Invoke-AudioPlay).
167
+ if (Test-Path (Join-Path $env:USERPROFILE ".agentvibes-tests-running")) { return }
168
+
169
+ $ffplayCmd = Get-Command ffplay -ErrorAction SilentlyContinue
170
+ if ($ffplayCmd) {
171
+ Start-Process -FilePath $ffplayCmd.Source `
172
+ -ArgumentList @("-autoexit", "-nodisp", "-loglevel", "quiet", $FilePath) `
173
+ -WindowStyle Hidden | Out-Null
174
+ return
175
+ }
176
+
177
+ try {
178
+ $player = New-Object System.Media.SoundPlayer $FilePath
179
+ $player.Play()
180
+ }
181
+ catch {
182
+ Write-Host "[WARN] Could not start playback: $_" -ForegroundColor Yellow
183
+ }
184
+ }
185
+
186
+ # Replay the Nth most recent TTS audio file (mirrors voice-manager.sh's
187
+ # `replay` case: resolve the audio dir, validate N (1-10), pick the file by
188
+ # most-recent-mtime, and play it in the background).
189
+ function Replay-Audio {
190
+ param([string]$NArg)
191
+
192
+ $AudioDir = $null
193
+ if ($env:CLAUDE_PROJECT_DIR -and (Test-Path (Join-Path $env:CLAUDE_PROJECT_DIR ".claude"))) {
194
+ $AudioDir = Join-Path $env:CLAUDE_PROJECT_DIR ".claude\audio"
195
+ }
196
+ else {
197
+ # Walk up from cwd looking for a .claude directory (same fallback as voice-manager.sh).
198
+ # Use a plain string path throughout: Get-Location returns a PathInfo (.Path),
199
+ # but Get-Item returns a DirectoryInfo (no .Path) — mixing them made the second
200
+ # iteration do Join-Path $null and throw a terminating error.
201
+ $dirPath = (Get-Location).Path
202
+ while ($dirPath) {
203
+ $candidate = Join-Path $dirPath ".claude"
204
+ if (Test-Path $candidate) {
205
+ $AudioDir = Join-Path $candidate "audio"
206
+ break
207
+ }
208
+ $parent = Split-Path $dirPath -Parent
209
+ if (-not $parent -or $parent -eq $dirPath) { break }
210
+ $dirPath = $parent
211
+ }
212
+ if (-not $AudioDir) {
213
+ $AudioDir = Join-Path $ClaudeDir "audio"
214
+ }
215
+ }
216
+
217
+ $N = 1
218
+ if ($NArg) {
219
+ if ($NArg -notmatch '^\d+$') {
220
+ Write-Host "[ERROR] Invalid argument. Please use a number (1-10)" -ForegroundColor Red
221
+ exit 1
222
+ }
223
+ $N = [int]$NArg
224
+ }
225
+ if ($N -lt 1 -or $N -gt 10) {
226
+ Write-Host "[ERROR] Number out of range. Please choose 1-10" -ForegroundColor Red
227
+ exit 1
228
+ }
229
+
230
+ if (-not (Test-Path $AudioDir)) {
231
+ Write-Host "[ERROR] No audio history found" -ForegroundColor Red
232
+ Write-Host "Audio files are stored in: $AudioDir"
233
+ exit 1
234
+ }
235
+
236
+ $files = @(Get-ChildItem -Path $AudioDir -File -ErrorAction SilentlyContinue |
237
+ Where-Object { $_.Name -match '^tts-.*\.(wav|mp3|aiff)$' } |
238
+ Sort-Object LastWriteTime -Descending)
239
+
240
+ if ($files.Count -lt $N) {
241
+ Write-Host "[ERROR] Audio #$N not found in history" -ForegroundColor Red
242
+ Write-Host "Total audio files available: $($files.Count)"
243
+ exit 1
244
+ }
245
+
246
+ $target = $files[$N - 1]
247
+ Write-Host "[REPLAY] Replaying audio #${N}:" -ForegroundColor Cyan
248
+ Write-Host " File: $($target.Name)"
249
+ Write-Host " Path: $($target.FullName)"
250
+
251
+ Start-ReplayPlayback $target.FullName
252
+ }
253
+
158
254
  # Main command routing
159
255
  switch ($Command) {
160
256
  'list' {
@@ -173,4 +269,8 @@ switch ($Command) {
173
269
  'get' {
174
270
  Show-CurrentVoice
175
271
  }
272
+
273
+ 'replay' {
274
+ Replay-Audio $VoiceName
275
+ }
176
276
  }
@@ -1,105 +1,105 @@
1
- # Clawdbot Integration
2
-
3
- AgentVibes TTS integration for Clawdbot - the AI assistant framework.
4
-
5
- ## What is Clawdbot?
6
-
7
- Clawdbot is a powerful AI assistant framework that connects Claude AI to messaging platforms (WhatsApp, Telegram, Discord, etc.) and provides extensible skills.
8
-
9
- **Website**: https://clawd.bot
10
- **GitHub**: https://github.com/clawdbot/clawdbot
11
-
12
- ## AgentVibes + Clawdbot
13
-
14
- This integration provides Clawdbot with professional TTS capabilities using AgentVibes:
15
-
16
- - **Free & Offline**: No API costs, works without internet
17
- - **50+ Voices**: Professional AI voices in 30+ languages
18
- - **Remote SSH Support**: Audio tunnels from server to local machine
19
- - **Zero Setup**: Automatic when AgentVibes is installed
20
-
21
- ## Installation
22
-
23
- ```bash
24
- npx agentvibes install
25
- ```
26
-
27
- That's it! AgentVibes is ready to use.
28
-
29
- ## Usage from Clawdbot
30
-
31
- Once installed, use AgentVibes for TTS:
32
-
33
- ```bash
34
- npx agentvibes speak "Hello from Clawdbot"
35
- ```
36
-
37
- ## Features
38
-
39
- - **Automatic Detection**: Clawdbot automatically uses AgentVibes when available
40
- - **Voice Selection**: 50+ voices across 30+ languages
41
- - **SSH Tunneling**: Audio plays on local machine from remote servers
42
- - **Zero Config**: Works out of the box once AgentVibes is installed
43
-
44
- ## Remote SSH Audio
45
-
46
- When running Clawdbot on a remote server, set up PulseAudio tunneling so audio plays on your local machine:
47
-
48
- **Quick Setup:**
49
-
50
- 1. **Remote server** (`~/.bashrc`):
51
- ```bash
52
- export PULSE_SERVER=tcp:localhost:14713
53
- ```
54
-
55
- 2. **Local machine** (`~/.ssh/config`):
56
- ```
57
- Host your-server
58
- RemoteForward 14713 localhost:14713
59
- ```
60
-
61
- 3. **Connect and test**:
62
- ```bash
63
- ssh your-server
64
- agentvibes speak "Testing remote audio"
65
- ```
66
-
67
- **Full guide**: https://github.com/paulpreibisch/AgentVibes/blob/master/docs/remote-audio-setup.md
68
-
69
- ## Documentation
70
-
71
- - **Skill Documentation**: [skill/SKILL.md](skill/SKILL.md)
72
- - **AgentVibes Docs**: https://agentvibes.org
73
- - **Clawdbot Docs**: https://docs.clawd.bot
74
-
75
- ## Architecture
76
-
77
- ```
78
- Clawdbot Request
79
-
80
- AgentVibes Skill (this)
81
-
82
- AgentVibes CLI (agentvibes speak)
83
-
84
- Piper TTS Engine
85
-
86
- PulseAudio → SSH Tunnel → Local Speakers
87
- ```
88
-
89
- ## Development
90
-
91
- The skill is automatically packaged with AgentVibes npm releases. To update:
92
-
93
- 1. Edit `skill/SKILL.md`
94
- 2. Test with Clawdbot
95
- 3. Commit to AgentVibes repo
96
- 4. Publish new AgentVibes version
97
-
98
- ## Support
99
-
100
- - **AgentVibes Issues**: https://github.com/paulpreibisch/AgentVibes/issues
101
- - **Clawdbot Issues**: https://github.com/clawdbot/clawdbot/issues
102
-
103
- ## License
104
-
105
- Apache 2.0 - Same as AgentVibes
1
+ # Clawdbot Integration
2
+
3
+ AgentVibes TTS integration for Clawdbot - the AI assistant framework.
4
+
5
+ ## What is Clawdbot?
6
+
7
+ Clawdbot is a powerful AI assistant framework that connects Claude AI to messaging platforms (WhatsApp, Telegram, Discord, etc.) and provides extensible skills.
8
+
9
+ **Website**: https://clawd.bot
10
+ **GitHub**: https://github.com/clawdbot/clawdbot
11
+
12
+ ## AgentVibes + Clawdbot
13
+
14
+ This integration provides Clawdbot with professional TTS capabilities using AgentVibes:
15
+
16
+ - **Free & Offline**: No API costs, works without internet
17
+ - **50+ Voices**: Professional AI voices in 30+ languages
18
+ - **Remote SSH Support**: Audio tunnels from server to local machine
19
+ - **Zero Setup**: Automatic when AgentVibes is installed
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npx agentvibes install
25
+ ```
26
+
27
+ That's it! AgentVibes is ready to use.
28
+
29
+ ## Usage from Clawdbot
30
+
31
+ Once installed, use AgentVibes for TTS:
32
+
33
+ ```bash
34
+ npx agentvibes speak "Hello from Clawdbot"
35
+ ```
36
+
37
+ ## Features
38
+
39
+ - **Automatic Detection**: Clawdbot automatically uses AgentVibes when available
40
+ - **Voice Selection**: 50+ voices across 30+ languages
41
+ - **SSH Tunneling**: Audio plays on local machine from remote servers
42
+ - **Zero Config**: Works out of the box once AgentVibes is installed
43
+
44
+ ## Remote SSH Audio
45
+
46
+ When running Clawdbot on a remote server, set up PulseAudio tunneling so audio plays on your local machine:
47
+
48
+ **Quick Setup:**
49
+
50
+ 1. **Remote server** (`~/.bashrc`):
51
+ ```bash
52
+ export PULSE_SERVER=tcp:localhost:14713
53
+ ```
54
+
55
+ 2. **Local machine** (`~/.ssh/config`):
56
+ ```
57
+ Host your-server
58
+ RemoteForward 14713 localhost:14713
59
+ ```
60
+
61
+ 3. **Connect and test**:
62
+ ```bash
63
+ ssh your-server
64
+ agentvibes speak "Testing remote audio"
65
+ ```
66
+
67
+ **Full guide**: https://github.com/paulpreibisch/AgentVibes/blob/master/docs/remote-audio-setup.md
68
+
69
+ ## Documentation
70
+
71
+ - **Skill Documentation**: [skill/SKILL.md](skill/SKILL.md)
72
+ - **AgentVibes Docs**: https://agentvibes.org
73
+ - **Clawdbot Docs**: https://docs.clawd.bot
74
+
75
+ ## Architecture
76
+
77
+ ```
78
+ Clawdbot Request
79
+
80
+ AgentVibes Skill (this)
81
+
82
+ AgentVibes CLI (agentvibes speak)
83
+
84
+ Piper TTS Engine
85
+
86
+ PulseAudio → SSH Tunnel → Local Speakers
87
+ ```
88
+
89
+ ## Development
90
+
91
+ The skill is automatically packaged with AgentVibes npm releases. To update:
92
+
93
+ 1. Edit `skill/SKILL.md`
94
+ 2. Test with Clawdbot
95
+ 3. Commit to AgentVibes repo
96
+ 4. Publish new AgentVibes version
97
+
98
+ ## Support
99
+
100
+ - **AgentVibes Issues**: https://github.com/paulpreibisch/AgentVibes/issues
101
+ - **Clawdbot Issues**: https://github.com/clawdbot/clawdbot/issues
102
+
103
+ ## License
104
+
105
+ Apache 2.0 - Same as AgentVibes