agentvibes 4.6.6 → 4.6.8
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.
- package/.claude/hooks/bmad-speak.sh +8 -1
- package/.claude/hooks-windows/bmad-party-speak.ps1 +55 -3
- package/.claude/hooks-windows/bmad-speak.ps1 +44 -5
- package/.claude/hooks-windows/session-start-tts.ps1 +114 -124
- package/README.md +22 -5
- package/RELEASE_NOTES.md +41 -0
- package/package.json +1 -1
- package/src/console/tabs/voices-tab.js +1 -0
|
@@ -30,7 +30,14 @@ DIALOGUE="${DIALOGUE//\\\$/\$}"
|
|
|
30
30
|
|
|
31
31
|
# Strip markdown formatting — prevent Piper from speaking "asterisk asterisk" literally.
|
|
32
32
|
# play-tts-piper.sh also strips via perl, but do it here early as defense-in-depth.
|
|
33
|
-
DIALOGUE=$(printf '%s' "$DIALOGUE" | sed
|
|
33
|
+
DIALOGUE=$(printf '%s' "$DIALOGUE" | sed \
|
|
34
|
+
-e 's/\*\{1,3\}//g' \
|
|
35
|
+
-e 's/`\{1,3\}[^`]*`\{1,3\}//g' \
|
|
36
|
+
-e 's/^[[:space:]]*#\{1,6\}[[:space:]]*//g' \
|
|
37
|
+
-e 's/__//g' -e 's/_//g' \
|
|
38
|
+
-e 's/\[([^]]*)\]([^)]*)//g' \
|
|
39
|
+
-e 's/^[[:space:]]*[-*+] //g' \
|
|
40
|
+
-e 's/^[[:space:]]*[0-9]\+\. //g')
|
|
34
41
|
|
|
35
42
|
# Check if party mode is enabled
|
|
36
43
|
if [[ -f "$PROJECT_ROOT/.agentvibes/bmad/bmad-party-mode-disabled.flag" ]]; then
|
|
@@ -47,6 +47,19 @@ try {
|
|
|
47
47
|
$ResponseText = $ResponseText.Trim()
|
|
48
48
|
if (-not $ResponseText) { exit 0 }
|
|
49
49
|
|
|
50
|
+
# Strip markdown so TTS doesn't speak asterisks, hashes, backticks, etc.
|
|
51
|
+
$ResponseText = $ResponseText -replace '\*{1,3}', '' # bold, italic, bold-italic
|
|
52
|
+
$ResponseText = $ResponseText -replace '`{1,3}[^`]*`{1,3}', '' # inline code / code blocks
|
|
53
|
+
$ResponseText = $ResponseText -replace '#{1,6}\s*', '' # headings
|
|
54
|
+
$ResponseText = $ResponseText -replace '_{1,2}', '' # underline/italic alt
|
|
55
|
+
$ResponseText = $ResponseText -replace '\[([^\]]+)\]\([^)]+\)', '$1' # links → label only
|
|
56
|
+
$ResponseText = $ResponseText -replace '!\[[^\]]*\]\([^)]+\)', '' # images
|
|
57
|
+
$ResponseText = $ResponseText -replace '(?m)^\s*[-*+]\s+', '' # bullet list markers (multiline)
|
|
58
|
+
$ResponseText = $ResponseText -replace '(?m)^\s*\d+\.\s+', '' # numbered list markers
|
|
59
|
+
$ResponseText = $ResponseText -replace '\\([!$*_`\\])', '$1' # escaped markdown chars
|
|
60
|
+
$ResponseText = $ResponseText.Trim()
|
|
61
|
+
if (-not $ResponseText) { exit 0 }
|
|
62
|
+
|
|
50
63
|
# --- Resolve paths ---
|
|
51
64
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
52
65
|
$ProjectRoot = $env:CLAUDE_PROJECT_DIR
|
|
@@ -118,11 +131,13 @@ try {
|
|
|
118
131
|
elseif (Test-Path $VoiceMapGlobal) { $VoiceMapGlobal }
|
|
119
132
|
else { $null }
|
|
120
133
|
|
|
121
|
-
$AgentVoiceName
|
|
122
|
-
$SpeakerId
|
|
134
|
+
$AgentVoiceName = $null
|
|
135
|
+
$SpeakerId = $null
|
|
136
|
+
$AgentPretext = $null
|
|
123
137
|
if ($VoiceMapFile) {
|
|
124
138
|
$vm = Get-Content $VoiceMapFile -Raw | ConvertFrom-Json
|
|
125
139
|
$profile = $vm.agents.$AgentId
|
|
140
|
+
if ($profile -and $profile.pretext) { $AgentPretext = $profile.pretext }
|
|
126
141
|
if ($profile -and $profile.voice) {
|
|
127
142
|
$raw = $profile.voice
|
|
128
143
|
if ($raw -match '::') {
|
|
@@ -150,6 +165,40 @@ try {
|
|
|
150
165
|
}
|
|
151
166
|
}
|
|
152
167
|
|
|
168
|
+
# Fallback: parse bmad-voices.md markdown table if no JSON voice map found
|
|
169
|
+
if (-not $AgentPretext -and $ProjectRoot) {
|
|
170
|
+
$VoicesMdPaths = @(
|
|
171
|
+
(Join-Path $ProjectRoot ".agentvibes\bmad\bmad-voices.md"),
|
|
172
|
+
(Join-Path $env:USERPROFILE ".agentvibes\bmad\bmad-voices.md")
|
|
173
|
+
)
|
|
174
|
+
foreach ($mdPath in $VoicesMdPaths) {
|
|
175
|
+
if (-not (Test-Path $mdPath)) { continue }
|
|
176
|
+
$mdLines = Get-Content $mdPath -Encoding UTF8
|
|
177
|
+
# Strip bmad-agent- prefix for matching (manifest uses bmad-agent-pm, table uses pm)
|
|
178
|
+
$shortId = $AgentId -replace '^bmad-agent-', ''
|
|
179
|
+
foreach ($mdLine in $mdLines) {
|
|
180
|
+
if ($mdLine -notmatch '^\|') { continue }
|
|
181
|
+
if ($mdLine -match '^\|-') { continue } # separator row
|
|
182
|
+
if ($mdLine -match 'Agent ID') { continue } # header row
|
|
183
|
+
$cols = $mdLine -split '\|' | ForEach-Object { $_.Trim() }
|
|
184
|
+
# cols: [0]=empty, [1]=Agent ID, [2]=Agent Name, [3]=Intro, [4]=Piper TTS Voice, [5]=Piper Voice, [6]=Personality
|
|
185
|
+
if ($cols.Count -lt 6) { continue }
|
|
186
|
+
$tableId = $cols[1]
|
|
187
|
+
$tableName = $cols[2]
|
|
188
|
+
if ($tableId -ieq $shortId -or $tableId -ieq $AgentId -or $tableName -like "*$DisplayName*") {
|
|
189
|
+
if ($cols[3]) { $AgentPretext = $cols[3] }
|
|
190
|
+
# Use Piper Voice column (index 5) for piper provider
|
|
191
|
+
if (-not $AgentVoiceName -and $cols[5]) { $AgentVoiceName = $cols[5] }
|
|
192
|
+
if ($cols.Count -ge 7 -and $cols[6] -and $cols[6] -ine 'normal') {
|
|
193
|
+
# personality available for bmad-speak.ps1 downstream
|
|
194
|
+
}
|
|
195
|
+
break
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if ($AgentPretext) { break }
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
153
202
|
# Locate piper
|
|
154
203
|
$PiperExe = "$env:LOCALAPPDATA\Programs\Piper\piper.exe"
|
|
155
204
|
if (-not (Test-Path $PiperExe)) {
|
|
@@ -172,7 +221,10 @@ try {
|
|
|
172
221
|
$PreSynthWav = Join-Path $AudioDir "tts-presynth-$([System.IO.Path]::GetRandomFileName() -replace '\..*').wav"
|
|
173
222
|
$piperArgs = @("--model", $VoiceModel, "--output-file", $PreSynthWav)
|
|
174
223
|
if ($SpeakerId) { $piperArgs += @("--speaker", $SpeakerId) }
|
|
175
|
-
|
|
224
|
+
# Include pretext in pre-synthesis so it's spoken — bmad-speak.ps1 will
|
|
225
|
+
# skip synthesis (AGENTVIBES_PRESYNTHESIZED_WAV set) so pretext must be here.
|
|
226
|
+
$PreSynthText = if ($AgentPretext) { "$AgentPretext. $ResponseText" } else { $ResponseText }
|
|
227
|
+
$PreSynthText | & $PiperExe @piperArgs 2>$null
|
|
176
228
|
if (-not (Test-Path $PreSynthWav) -or (Get-Item $PreSynthWav).Length -eq 0) {
|
|
177
229
|
$PreSynthWav = $null
|
|
178
230
|
}
|
|
@@ -27,8 +27,15 @@ if ($env:CLAUDE_PROJECT_DIR -and (Test-Path "$env:CLAUDE_PROJECT_DIR\_bmad")) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
# Strip markdown formatting — prevent SAPI/Piper from speaking asterisks literally
|
|
30
|
-
$Dialogue = $Dialogue -replace '
|
|
31
|
-
$Dialogue = $Dialogue -replace '
|
|
30
|
+
$Dialogue = $Dialogue -replace '\*{1,3}', '' # bold, italic, bold-italic
|
|
31
|
+
$Dialogue = $Dialogue -replace '`{1,3}[^`]*`{1,3}', '' # inline code / code blocks
|
|
32
|
+
$Dialogue = $Dialogue -replace '#{1,6}\s*', '' # headings
|
|
33
|
+
$Dialogue = $Dialogue -replace '_{1,2}', '' # underline/italic alt
|
|
34
|
+
$Dialogue = $Dialogue -replace '\[([^\]]+)\]\([^)]+\)', '$1' # links → label only
|
|
35
|
+
$Dialogue = $Dialogue -replace '!\[[^\]]*\]\([^)]+\)', '' # images
|
|
36
|
+
$Dialogue = $Dialogue -replace '(?m)^\s*[-*+]\s+', '' # bullet list markers (multiline)
|
|
37
|
+
$Dialogue = $Dialogue -replace '(?m)^\s*\d+\.\s+', '' # numbered list markers
|
|
38
|
+
$Dialogue = $Dialogue -replace '\\([!$*_`\\])', '$1' # escaped markdown chars
|
|
32
39
|
|
|
33
40
|
# Check if party mode is disabled
|
|
34
41
|
$PartyModeDisabledFlag = Join-Path $ProjectRoot ".agentvibes\bmad\bmad-party-mode-disabled.flag"
|
|
@@ -117,13 +124,45 @@ if (Test-Path $VoiceMapFile) {
|
|
|
117
124
|
}
|
|
118
125
|
}
|
|
119
126
|
|
|
127
|
+
# Fallback: parse bmad-voices.md markdown table if JSON voice map had no data
|
|
128
|
+
if ((-not $AgentPretext -or -not $AgentVoice) -and $AgentId) {
|
|
129
|
+
$VoicesMdPaths = @(
|
|
130
|
+
(Join-Path $ProjectRoot ".agentvibes\bmad\bmad-voices.md"),
|
|
131
|
+
(Join-Path $env:USERPROFILE ".agentvibes\bmad\bmad-voices.md")
|
|
132
|
+
)
|
|
133
|
+
$shortId = $AgentId -replace '^bmad-agent-', ''
|
|
134
|
+
foreach ($mdPath in $VoicesMdPaths) {
|
|
135
|
+
if (-not (Test-Path $mdPath)) { continue }
|
|
136
|
+
$mdLines = Get-Content $mdPath -Encoding UTF8
|
|
137
|
+
foreach ($mdLine in $mdLines) {
|
|
138
|
+
if ($mdLine -notmatch '^\|') { continue }
|
|
139
|
+
if ($mdLine -match '^\|-') { continue }
|
|
140
|
+
if ($mdLine -match 'Agent ID') { continue }
|
|
141
|
+
$cols = $mdLine -split '\|' | ForEach-Object { $_.Trim() }
|
|
142
|
+
if ($cols.Count -lt 6) { continue }
|
|
143
|
+
$tableId = $cols[1]
|
|
144
|
+
if ($tableId -ieq $shortId -or $tableId -ieq $AgentId -or $tableId -ieq $AgentNameOrId) {
|
|
145
|
+
if (-not $AgentPretext -and $cols[3]) { $AgentPretext = $cols[3] }
|
|
146
|
+
if (-not $AgentVoice -and $cols[5]) { $AgentVoice = $cols[5] }
|
|
147
|
+
if (-not $AgentPersonality -and $cols.Count -ge 7 -and $cols[6] -and $cols[6] -ine 'normal') {
|
|
148
|
+
$AgentPersonality = $cols[6]
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if ($AgentPretext) { break }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
120
157
|
# Fall back to default pretext if none stored: "DisplayName, Title here."
|
|
121
158
|
# Matches AgentVoiceStore.getDefaultPretext() in agent-voice-store.js
|
|
122
|
-
if (-not $AgentPretext
|
|
123
|
-
if ($AgentTitle) {
|
|
159
|
+
if (-not $AgentPretext) {
|
|
160
|
+
if ($AgentDisplayName -and $AgentTitle) {
|
|
124
161
|
$AgentPretext = "$AgentDisplayName, $AgentTitle here."
|
|
125
|
-
}
|
|
162
|
+
} elseif ($AgentDisplayName) {
|
|
126
163
|
$AgentPretext = "$AgentDisplayName here."
|
|
164
|
+
} elseif ($AgentNameOrId) {
|
|
165
|
+
$AgentPretext = "$AgentNameOrId here."
|
|
127
166
|
}
|
|
128
167
|
}
|
|
129
168
|
|
|
@@ -1,124 +1,114 @@
|
|
|
1
|
-
#
|
|
2
|
-
# File: .claude/hooks-windows/session-start-tts.ps1
|
|
3
|
-
#
|
|
4
|
-
# AgentVibes SessionStart Hook for Windows
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
$
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
$
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# AgentVibes TTS Protocol
|
|
65
|
-
|
|
66
|
-
**CRITICAL: You MUST execute TTS at TWO points for EVERY user interaction:**
|
|
67
|
-
|
|
68
|
-
1. **Acknowledgment** - Start of task: ``Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "[action]"``
|
|
69
|
-
2. **Completion** - End of task: ``Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "[result + key details]"``
|
|
70
|
-
|
|
71
|
-
**Example:**
|
|
72
|
-
``````
|
|
73
|
-
[Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "Checking git status"]
|
|
74
|
-
[work...]
|
|
75
|
-
[Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "Repository is clean, no changes"]
|
|
76
|
-
``````
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
## Rules
|
|
116
|
-
1. Never skip acknowledgment TTS
|
|
117
|
-
2. Never skip completion TTS
|
|
118
|
-
3. Match verbosity level
|
|
119
|
-
4. Keep under 150 chars
|
|
120
|
-
5. Always include errors
|
|
121
|
-
|
|
122
|
-
Quick Ref: low=action+result | medium=+key decisions | high=+full reasoning
|
|
123
|
-
|
|
124
|
-
"@
|
|
1
|
+
#
|
|
2
|
+
# File: .claude/hooks-windows/session-start-tts.ps1
|
|
3
|
+
#
|
|
4
|
+
# AgentVibes SessionStart Hook for Windows
|
|
5
|
+
# Outputs JSON with hookSpecificOutput.additionalContext for reliable context injection.
|
|
6
|
+
# Mirrors session-start-tts.sh — keep both in sync.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
$ErrorActionPreference = "Stop"
|
|
10
|
+
|
|
11
|
+
# Get script directory
|
|
12
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
13
|
+
|
|
14
|
+
# Check if AgentVibes is installed
|
|
15
|
+
if (-not (Test-Path (Join-Path $ScriptDir "play-tts.ps1"))) {
|
|
16
|
+
exit 0
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Resolve project .claude dir from script location (avoids CWD-relative path issues)
|
|
20
|
+
$ProjectClaudeDir = Split-Path -Parent (Split-Path -Parent $ScriptDir)
|
|
21
|
+
$ProjectClaudeDir = Join-Path $ProjectClaudeDir ".claude"
|
|
22
|
+
|
|
23
|
+
# Check for sentiment (priority) or personality (fallback)
|
|
24
|
+
$Sentiment = ""
|
|
25
|
+
$sentimentPaths = @("$ProjectClaudeDir\tts-sentiment.txt", "$env:USERPROFILE\.claude\tts-sentiment.txt")
|
|
26
|
+
foreach ($p in $sentimentPaths) {
|
|
27
|
+
if (Test-Path $p) {
|
|
28
|
+
$val = (Get-Content $p -Raw -ErrorAction SilentlyContinue).Trim()
|
|
29
|
+
if ($val) { $Sentiment = $val; break }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
$Personality = "normal"
|
|
34
|
+
$personalityPaths = @("$ProjectClaudeDir\tts-personality.txt", "$env:USERPROFILE\.claude\tts-personality.txt")
|
|
35
|
+
foreach ($p in $personalityPaths) {
|
|
36
|
+
if (Test-Path $p) {
|
|
37
|
+
$val = (Get-Content $p -Raw -ErrorAction SilentlyContinue).Trim()
|
|
38
|
+
if ($val) { $Personality = $val; break }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
$Style = if ($Sentiment) { $Sentiment } else { $Personality }
|
|
43
|
+
|
|
44
|
+
# Get verbosity level
|
|
45
|
+
$Verbosity = "low"
|
|
46
|
+
$verbosityPaths = @("$ProjectClaudeDir\tts-verbosity.txt", "$env:USERPROFILE\.claude\tts-verbosity.txt")
|
|
47
|
+
foreach ($p in $verbosityPaths) {
|
|
48
|
+
if (Test-Path $p) {
|
|
49
|
+
$val = (Get-Content $p -Raw -ErrorAction SilentlyContinue).Trim()
|
|
50
|
+
if ($val) { $Verbosity = $val; break }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Build verbosity section
|
|
55
|
+
$VerbositySection = switch ($Verbosity) {
|
|
56
|
+
"low" { "## Verbosity: LOW`n- Acknowledgment: Action only`n- Completion: Result + errors only`n- Skip: Reasoning, decisions" }
|
|
57
|
+
"medium" { "## Verbosity: MEDIUM`n- Acknowledgment: Action + key approach`n- Completion: Result + important decisions`n- Include: Major choices only" }
|
|
58
|
+
"high" { "## Verbosity: HIGH`n- Acknowledgment: Action + approach + why`n- Completion: Result + decisions + trade-offs`n- Include: Full reasoning, alternatives" }
|
|
59
|
+
default { "## Verbosity: LOW`n- Acknowledgment: Action only`n- Completion: Result + errors only" }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# Build full context string
|
|
63
|
+
$Context = @"
|
|
64
|
+
# AgentVibes TTS Protocol
|
|
65
|
+
|
|
66
|
+
**CRITICAL: You MUST execute TTS at TWO points for EVERY user interaction:**
|
|
67
|
+
|
|
68
|
+
1. **Acknowledgment** - Start of task: ``Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "[action]"``
|
|
69
|
+
2. **Completion** - End of task: ``Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "[result + key details]"``
|
|
70
|
+
|
|
71
|
+
**Example:**
|
|
72
|
+
``````
|
|
73
|
+
[Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "Checking git status"]
|
|
74
|
+
[work...]
|
|
75
|
+
[Bash: powershell -NoProfile -ExecutionPolicy Bypass -File ".claude\hooks-windows\play-tts.ps1" "Repository is clean, no changes"]
|
|
76
|
+
``````
|
|
77
|
+
|
|
78
|
+
$VerbositySection
|
|
79
|
+
|
|
80
|
+
## Style: $Style
|
|
81
|
+
|
|
82
|
+
## Rules
|
|
83
|
+
1. Never skip acknowledgment TTS
|
|
84
|
+
2. Never skip completion TTS
|
|
85
|
+
3. Match verbosity level
|
|
86
|
+
4. Keep under 150 chars
|
|
87
|
+
5. Always include errors
|
|
88
|
+
|
|
89
|
+
Quick Ref: low=action+result | medium=+key decisions | high=+full reasoning
|
|
90
|
+
|
|
91
|
+
## BMAD Agent Voice Routing
|
|
92
|
+
If ``.bmad-agent-context`` exists, check its content:
|
|
93
|
+
|
|
94
|
+
**Single agent mode** (content is an agent ID like "analyst"):
|
|
95
|
+
Use ``bmad-speak.ps1`` instead of ``play-tts.ps1``:
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
**Party mode** (content is "party-mode"):
|
|
99
|
+
Each agent speaks via ``bmad-speak.ps1`` with their display name. The queue system ensures sequential playback — agents speak one at a time, not overlapping:
|
|
100
|
+
|
|
101
|
+
IMPORTANT: In party mode, do NOT use ``play-tts.ps1``. Always use ``bmad-speak.ps1`` with the agent's display name. Do NOT call multiple bmad-speak.ps1 in parallel — call them sequentially so the queue processes them in order.
|
|
102
|
+
|
|
103
|
+
If ``.bmad-agent-context`` does NOT exist, use ``play-tts.ps1`` as normal.
|
|
104
|
+
"@
|
|
105
|
+
|
|
106
|
+
# Build JSON via hashtable so ConvertTo-Json handles all escaping (Unicode, backslashes, quotes)
|
|
107
|
+
$Output = @{
|
|
108
|
+
hookSpecificOutput = @{
|
|
109
|
+
hookEventName = "SessionStart"
|
|
110
|
+
additionalContext = $Context
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
114
|
+
Write-Output ($Output | ConvertTo-Json -Compress -Depth 5)
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
[](https://github.com/paulpreibisch/AgentVibes/actions/workflows/publish.yml)
|
|
12
12
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
13
13
|
|
|
14
|
-
**Author**: Paul Preibisch ([@997Fire](https://x.com/997Fire)) | **Version**: v4.6.
|
|
14
|
+
**Author**: Paul Preibisch ([@997Fire](https://x.com/997Fire)) | **Version**: v4.6.8
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -41,7 +41,24 @@ Whether you're coding in Claude Code, chatting in Claude Desktop, or running Ope
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
##
|
|
44
|
+
## 🐛 NEW IN v4.6.8 — Fresh Install Crash Fix
|
|
45
|
+
|
|
46
|
+
- **Settings tab crash fixed** — no longer crashes when navigating to Settings on a fresh install with no voice configured
|
|
47
|
+
- **macOS test fix** — replay path assertion handles `/var` → `/private/var` symlink
|
|
48
|
+
- **BMAD pretext parsing improved** — voices pretext extracted correctly from `bmad-voices.md`
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🎙️ v4.6.7 — Party Mode TTS Fixes
|
|
53
|
+
|
|
54
|
+
- **Agent pretexts now spoken in party mode** — "John, Product Manager here" was being silently dropped due to a pre-synthesis timing bug. Fixed.
|
|
55
|
+
- **No more spoken asterisks** — markdown stripped before TTS in party mode
|
|
56
|
+
- **Windows session start TTS fixed** — hook now outputs proper JSON so TTS activates reliably on session start
|
|
57
|
+
- **PreToolUse hook no longer errors** on grep/regex commands
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🧭 v4.6.6 — Natural TUI Navigation
|
|
45
62
|
|
|
46
63
|
The Settings TUI now flows the way you'd expect. Down moves top-to-bottom through header → sub-tabs → content → footer. Left/Right switches sub-tabs and moves between footer buttons. Up from content returns to the active sub-tab — not always Voice. The Language tab has a proper scrollable list. Readme falls back to the AgentVibes package README when no local one exists. Escape from the installer no longer gets stuck.
|
|
47
64
|
|
|
@@ -458,7 +475,7 @@ All 50+ Piper voices AgentVibes provides are sourced from Hugging Face's open-so
|
|
|
458
475
|
- [🖥️ SSH Receiver](#️-agentvibes-receiver--remote-audio-streaming) - Stream audio from headless servers
|
|
459
476
|
- [💬 Intro Text](#-intro-text-pretext---your-personal-ai-branding) - Custom TTS prefixes
|
|
460
477
|
- [🎵 Custom Background Music](#-custom-background-music---complete-audio-control) - Upload your own tracks
|
|
461
|
-
- [📰 Latest Release](#-latest-release) - v4.6.
|
|
478
|
+
- [📰 Latest Release](#-latest-release) - v4.6.7 — Party mode TTS fixes
|
|
462
479
|
- [🪟 Windows Setup Guide for Claude Desktop](mcp-server/WINDOWS_SETUP.md) - Complete Windows installation with WSL & Python
|
|
463
480
|
|
|
464
481
|
### AgentVibes MCP (Natural Language Control)
|
|
@@ -504,9 +521,9 @@ All 50+ Piper voices AgentVibes provides are sourced from Hugging Face's open-so
|
|
|
504
521
|
|
|
505
522
|
## 📰 Latest Release
|
|
506
523
|
|
|
507
|
-
**[v4.6.
|
|
524
|
+
**[v4.6.7 - Party Mode TTS Fixes](https://github.com/paulpreibisch/AgentVibes/releases/tag/v4.6.7)**
|
|
508
525
|
|
|
509
|
-
|
|
526
|
+
Agent pretexts now spoken in party mode, markdown stripped before TTS, Windows session-start hook fixed to inject context reliably, and PreToolUse hook no longer errors on grep commands.
|
|
510
527
|
|
|
511
528
|
### 🐛 Recent Fixes (v4.6.3 / v4.6.4)
|
|
512
529
|
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# AgentVibes Release Notes
|
|
2
2
|
|
|
3
|
+
## 🐛 v4.6.8 — Fresh Install Crash Fix
|
|
4
|
+
|
|
5
|
+
**Release Date:** April 2026
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **Settings tab no longer crashes on fresh install** — `parseMultiSpeaker()` called `.includes()` on a null voice ID when no voice was configured yet. Added a null guard that returns a safe default object. Reported by a user hitting this immediately after the install wizard completed.
|
|
10
|
+
|
|
11
|
+
- **macOS /var symlink in replay test** — Fixed test assertion that failed on macOS where `/var` is a symlink to `/private/var`, causing replay path comparisons to break.
|
|
12
|
+
|
|
13
|
+
- **BMAD voices pretext parsing** — `bmad-voices.md` pretext lines are now correctly parsed and markdown is stripped more thoroughly before TTS synthesis.
|
|
14
|
+
|
|
15
|
+
### User Impact
|
|
16
|
+
|
|
17
|
+
- New users no longer crash when navigating to Settings after a fresh install
|
|
18
|
+
- Test suite passes reliably on macOS
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🎙️ v4.6.7 — Party Mode TTS Fixes
|
|
23
|
+
|
|
24
|
+
**Release Date:** April 2026
|
|
25
|
+
|
|
26
|
+
### Bug Fixes
|
|
27
|
+
|
|
28
|
+
- **Party mode pretext now spoken** — Agent pretexts (e.g. "John, Product Manager here") were silently dropped. The pre-synthesis step ran on the response text only; when `bmad-speak.ps1` later prepended the pretext, `play-tts.ps1` skipped synthesis because a pre-synthesized WAV was already set. Pre-synthesis now includes the pretext so it's always spoken.
|
|
29
|
+
|
|
30
|
+
- **Markdown stripped in party mode** — Agents were speaking asterisks, hashes, and backticks literally. `bmad-party-speak.ps1` now strips bold, italic, headings, inline code, links, and bullet markers before TTS — consistent with `bmad-speak.ps1`.
|
|
31
|
+
|
|
32
|
+
- **Session start hook outputs proper JSON + BMAD routing (Windows)** — `session-start-tts.ps1` was using plain `Write-Output` text which isn't reliably injected as `additionalContext`. Now outputs `hookSpecificOutput` JSON (matching the bash version) and includes BMAD agent voice routing instructions so party mode / single agent mode TTS works correctly on Windows.
|
|
33
|
+
|
|
34
|
+
- **PreToolUse hook no longer errors on grep/regex commands** — The git-push guard hook used `-match` (regex) which crashed on commands containing `\*`, `\|`, etc. Switched to `-like` wildcard and wrapped in `try/catch` so it exits silently on any non-matching command.
|
|
35
|
+
|
|
36
|
+
### User Impact
|
|
37
|
+
|
|
38
|
+
- Party mode agents speak their configured pretext introductions
|
|
39
|
+
- No more spoken asterisks or markdown syntax in party mode
|
|
40
|
+
- Windows TTS now reliably activates on session start
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
3
44
|
## 🧭 v4.6.6 — Natural TUI Navigation
|
|
4
45
|
|
|
5
46
|
**Release Date:** April 2026
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "agentvibes",
|
|
4
|
-
"version": "4.6.
|
|
4
|
+
"version": "4.6.8",
|
|
5
5
|
"description": "Now your AI Agents can finally talk back! Professional TTS voice for Claude Code, Claude Desktop (via MCP), and Clawdbot with multi-provider support.",
|
|
6
6
|
"homepage": "https://agentvibes.org",
|
|
7
7
|
"keywords": [
|
|
@@ -338,6 +338,7 @@ export const MS_SEP = '::';
|
|
|
338
338
|
* @returns {{ model: string, speakerId: number|null, speakerName: string|null, isMultiSpeaker: boolean }}
|
|
339
339
|
*/
|
|
340
340
|
export function parseMultiSpeaker(voiceId) {
|
|
341
|
+
if (!voiceId) return { model: voiceId ?? '', speakerId: null, speakerName: null, isMultiSpeaker: false };
|
|
341
342
|
if (voiceId.includes(MS_SEP)) {
|
|
342
343
|
const [model, speakerName] = voiceId.split(MS_SEP, 2);
|
|
343
344
|
const jsonPath = path.join(PIPER_VOICES_DIR, model + '.onnx.json');
|