agentvibes 2.0.9 → 2.0.12
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/commands/agent-vibes/bmad.md +203 -0
- package/.claude/github-star-reminder.txt +1 -0
- package/.claude/hooks/bmad-tts-injector.sh +333 -0
- package/.claude/hooks/bmad-voice-manager.sh +34 -0
- package/.claude/hooks/check-output-style.sh +2 -2
- package/.claude/hooks/github-star-reminder.sh +94 -0
- package/.claude/hooks/personality-manager.sh +2 -2
- package/.claude/hooks/piper-installer.sh +194 -0
- package/.claude/hooks/play-tts-elevenlabs.sh +30 -3
- package/.claude/hooks/play-tts-local-wrapper.sh +44 -0
- package/.claude/hooks/play-tts-piper.sh +10 -2
- package/.claude/hooks/play-tts-remote.sh +81 -0
- package/.claude/hooks/play-tts.sh +34 -0
- package/.claude/hooks/provider-commands.sh +30 -1
- package/.claude/hooks/voice-manager.sh +2 -2
- package/.claude/output-styles/agent-vibes.md +52 -36
- package/README.md +2 -2
- package/RELEASE_NOTES.md +412 -0
- package/agentvibes.org/.claude/commands/agent-vibes/add.md +21 -0
- package/agentvibes.org/.claude/commands/agent-vibes/agent-vibes.md +68 -0
- package/agentvibes.org/.claude/commands/agent-vibes/commands.json +53 -0
- package/agentvibes.org/.claude/commands/agent-vibes/get.md +9 -0
- package/agentvibes.org/.claude/commands/agent-vibes/list.md +13 -0
- package/agentvibes.org/.claude/commands/agent-vibes/personality.md +79 -0
- package/agentvibes.org/.claude/commands/agent-vibes/preview.md +16 -0
- package/agentvibes.org/.claude/commands/agent-vibes/provider.md +54 -0
- package/agentvibes.org/.claude/commands/agent-vibes/replay.md +19 -0
- package/agentvibes.org/.claude/commands/agent-vibes/sample.md +12 -0
- package/agentvibes.org/.claude/commands/agent-vibes/sentiment.md +52 -0
- package/agentvibes.org/.claude/commands/agent-vibes/set-language.md +47 -0
- package/agentvibes.org/.claude/commands/agent-vibes/set-pretext.md +65 -0
- package/agentvibes.org/.claude/commands/agent-vibes/switch.md +53 -0
- package/agentvibes.org/.claude/commands/agent-vibes/update.md +20 -0
- package/agentvibes.org/.claude/commands/agent-vibes/version.md +10 -0
- package/agentvibes.org/.claude/commands/agent-vibes/whoami.md +7 -0
- package/agentvibes.org/.claude/hooks/bmad-voice-manager.sh +278 -0
- package/agentvibes.org/.claude/hooks/language-manager.sh +190 -0
- package/agentvibes.org/.claude/hooks/personality-manager.sh +279 -0
- package/agentvibes.org/.claude/hooks/piper-download-voices.sh +133 -0
- package/agentvibes.org/.claude/hooks/piper-voice-manager.sh +227 -0
- package/agentvibes.org/.claude/hooks/play-tts-elevenlabs.sh +201 -0
- package/agentvibes.org/.claude/hooks/play-tts-piper.sh +175 -0
- package/agentvibes.org/.claude/hooks/play-tts.sh +138 -0
- package/agentvibes.org/.claude/hooks/provider-commands.sh +374 -0
- package/agentvibes.org/.claude/hooks/provider-manager.sh +196 -0
- package/agentvibes.org/.claude/hooks/sentiment-manager.sh +163 -0
- package/agentvibes.org/.claude/hooks/voice-manager.sh +349 -0
- package/agentvibes.org/.claude/hooks/voices-config.sh +33 -0
- package/agentvibes.org/.claude/journal/2025-10-07.html +373 -0
- package/agentvibes.org/.claude/journal/index.html +91 -0
- package/agentvibes.org/.claude/output-styles/agent-vibes.md +203 -0
- package/agentvibes.org/.claude/personalities/angry.md +16 -0
- package/agentvibes.org/.claude/personalities/annoying.md +16 -0
- package/agentvibes.org/.claude/personalities/crass.md +16 -0
- package/agentvibes.org/.claude/personalities/dramatic.md +16 -0
- package/agentvibes.org/.claude/personalities/dry-humor.md +52 -0
- package/agentvibes.org/.claude/personalities/flirty.md +22 -0
- package/agentvibes.org/.claude/personalities/funny.md +16 -0
- package/agentvibes.org/.claude/personalities/grandpa.md +34 -0
- package/agentvibes.org/.claude/personalities/millennial.md +16 -0
- package/agentvibes.org/.claude/personalities/moody.md +16 -0
- package/agentvibes.org/.claude/personalities/normal.md +18 -0
- package/agentvibes.org/.claude/personalities/pirate.md +16 -0
- package/agentvibes.org/.claude/personalities/poetic.md +16 -0
- package/agentvibes.org/.claude/personalities/professional.md +16 -0
- package/agentvibes.org/.claude/personalities/robot.md +16 -0
- package/agentvibes.org/.claude/personalities/sarcastic.md +40 -0
- package/agentvibes.org/.claude/personalities/sassy.md +16 -0
- package/agentvibes.org/.claude/personalities/surfer-dude.md +16 -0
- package/agentvibes.org/.claude/personalities/zen.md +16 -0
- package/agentvibes.org/.mcp-minimal.json +60 -0
- package/agentvibes.org/CHANGELOG.md +56 -0
- package/agentvibes.org/README.md +93 -0
- package/agentvibes.org/app/(auth)/layout.tsx +15 -0
- package/agentvibes.org/app/(auth)/reset-password/page.tsx +45 -0
- package/agentvibes.org/app/(auth)/signin/page.tsx +82 -0
- package/agentvibes.org/app/(auth)/signup/page.tsx +104 -0
- package/agentvibes.org/app/(default)/layout.tsx +31 -0
- package/agentvibes.org/app/(default)/page.tsx +20 -0
- package/agentvibes.org/app/api/hello/route.ts +3 -0
- package/agentvibes.org/app/css/additional-styles/theme.css +82 -0
- package/agentvibes.org/app/css/additional-styles/utility-patterns.css +55 -0
- package/agentvibes.org/app/css/style.css +100 -0
- package/agentvibes.org/app/layout.tsx +63 -0
- package/agentvibes.org/components/cta.tsx +58 -0
- package/agentvibes.org/components/features.tsx +256 -0
- package/agentvibes.org/components/hero-home.tsx +133 -0
- package/agentvibes.org/components/modal-video.tsx +137 -0
- package/agentvibes.org/components/page-illustration.tsx +55 -0
- package/agentvibes.org/components/spotlight.tsx +77 -0
- package/agentvibes.org/components/testimonials.tsx +282 -0
- package/agentvibes.org/components/ui/footer.tsx +82 -0
- package/agentvibes.org/components/ui/header.tsx +53 -0
- package/agentvibes.org/components/ui/logo.tsx +10 -0
- package/agentvibes.org/components/workflows.tsx +176 -0
- package/agentvibes.org/next.config.js +4 -0
- package/agentvibes.org/package-lock.json +1974 -0
- package/agentvibes.org/package.json +30 -0
- package/agentvibes.org/pnpm-lock.yaml +1141 -0
- package/agentvibes.org/postcss.config.js +5 -0
- package/agentvibes.org/public/audio/02-sarcastic.mp3 +0 -0
- package/agentvibes.org/public/audio/03-angry.mp3 +0 -0
- package/agentvibes.org/public/audio/04-grandpa.mp3 +0 -0
- package/agentvibes.org/public/audio/05-sarcastic-example2.mp3 +0 -0
- package/agentvibes.org/public/audio/french-rachel.mp3 +0 -0
- package/agentvibes.org/public/audio/spanish-antoni.mp3 +0 -0
- package/agentvibes.org/public/favicon.ico +0 -0
- package/agentvibes.org/public/fonts/nacelle-italic.woff2 +0 -0
- package/agentvibes.org/public/fonts/nacelle-regular.woff2 +0 -0
- package/agentvibes.org/public/fonts/nacelle-semibold.woff2 +0 -0
- package/agentvibes.org/public/fonts/nacelle-semibolditalic.woff2 +0 -0
- package/agentvibes.org/public/images/blurred-shape-gray.svg +1 -0
- package/agentvibes.org/public/images/blurred-shape.svg +1 -0
- package/agentvibes.org/public/images/client-logo-01.svg +1 -0
- package/agentvibes.org/public/images/client-logo-02.svg +1 -0
- package/agentvibes.org/public/images/client-logo-03.svg +1 -0
- package/agentvibes.org/public/images/client-logo-04.svg +1 -0
- package/agentvibes.org/public/images/client-logo-05.svg +1 -0
- package/agentvibes.org/public/images/client-logo-06.svg +1 -0
- package/agentvibes.org/public/images/client-logo-07.svg +1 -0
- package/agentvibes.org/public/images/client-logo-08.svg +1 -0
- package/agentvibes.org/public/images/client-logo-09.svg +1 -0
- package/agentvibes.org/public/images/features.png +0 -0
- package/agentvibes.org/public/images/footer-illustration.svg +1 -0
- package/agentvibes.org/public/images/hero-image-01.jpg +0 -0
- package/agentvibes.org/public/images/logo.svg +1 -0
- package/agentvibes.org/public/images/page-illustration.svg +1 -0
- package/agentvibes.org/public/images/secondary-illustration.svg +1 -0
- package/agentvibes.org/public/images/testimonial-01.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-02.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-03.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-04.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-05.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-06.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-07.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-08.jpg +0 -0
- package/agentvibes.org/public/images/testimonial-09.jpg +0 -0
- package/agentvibes.org/public/images/workflow-01.png +0 -0
- package/agentvibes.org/public/images/workflow-02.png +0 -0
- package/agentvibes.org/public/images/workflow-03.png +0 -0
- package/agentvibes.org/public/videos/video.mp4 +0 -0
- package/agentvibes.org/tsconfig.json +28 -0
- package/agentvibes.org/utils/useMasonry.tsx +67 -0
- package/agentvibes.org/utils/useMousePosition.tsx +27 -0
- package/docs/REMOTE_TTS_SETUP.md +190 -0
- package/package.json +2 -2
- package/src/installer.js +193 -9
- package/test/helpers/test-helper.bash +4 -2
- package/test/unit/personality-manager.bats +16 -4
- package/test/unit/personality-voice-mapping.bats +15 -6
- package/test/unit/play-tts.bats +0 -9
- package/.claude/commands/agent-vibes-bmad.md +0 -132
package/src/installer.js
CHANGED
|
@@ -47,7 +47,7 @@ function showWelcome() {
|
|
|
47
47
|
|
|
48
48
|
console.log(
|
|
49
49
|
boxen(
|
|
50
|
-
chalk.white.bold('🎤
|
|
50
|
+
chalk.white.bold('🎤 Now your AI Agents can finally talk back! TTS Voice for Claude Code\n\n') +
|
|
51
51
|
chalk.gray('Add professional text-to-speech narration to your AI coding sessions\n\n') +
|
|
52
52
|
chalk.cyan('📦 https://github.com/paulpreibisch/AgentVibes'),
|
|
53
53
|
{
|
|
@@ -136,8 +136,93 @@ async function install(options = {}) {
|
|
|
136
136
|
|
|
137
137
|
selectedProvider = provider;
|
|
138
138
|
|
|
139
|
-
// If Piper selected,
|
|
139
|
+
// If Piper selected, check if Piper is installed
|
|
140
140
|
if (selectedProvider === 'piper') {
|
|
141
|
+
// Check if Piper is installed
|
|
142
|
+
let piperInstalled = false;
|
|
143
|
+
try {
|
|
144
|
+
const { execSync } = await import('node:child_process');
|
|
145
|
+
// First check if piper is in PATH
|
|
146
|
+
execSync('which piper', { stdio: 'ignore' });
|
|
147
|
+
piperInstalled = true;
|
|
148
|
+
} catch {
|
|
149
|
+
// If not in PATH, check if it exists in pipx installation directory
|
|
150
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
151
|
+
const pipxPiperPath = path.join(homeDir, '.local', 'bin', 'piper');
|
|
152
|
+
try {
|
|
153
|
+
await fs.access(pipxPiperPath, fs.constants.X_OK);
|
|
154
|
+
piperInstalled = true;
|
|
155
|
+
console.log(chalk.yellow('\n⚠️ Piper is installed but not in PATH'));
|
|
156
|
+
console.log(chalk.gray(` Location: ${pipxPiperPath}`));
|
|
157
|
+
console.log(chalk.gray(' Run this to add to PATH:'));
|
|
158
|
+
console.log(chalk.cyan(' export PATH="$HOME/.local/bin:$PATH"\n'));
|
|
159
|
+
} catch {
|
|
160
|
+
// Piper not found anywhere
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!piperInstalled) {
|
|
165
|
+
console.log(chalk.yellow('\n⚠️ Piper TTS is not installed'));
|
|
166
|
+
console.log(chalk.gray(' Piper is a free, offline neural TTS system'));
|
|
167
|
+
console.log(chalk.gray(' It needs to be installed separately via pipx\n'));
|
|
168
|
+
|
|
169
|
+
const { installPiper } = await inquirer.prompt([
|
|
170
|
+
{
|
|
171
|
+
type: 'confirm',
|
|
172
|
+
name: 'installPiper',
|
|
173
|
+
message: 'Would you like to install Piper TTS now?',
|
|
174
|
+
default: true,
|
|
175
|
+
},
|
|
176
|
+
]);
|
|
177
|
+
|
|
178
|
+
if (installPiper) {
|
|
179
|
+
console.log(chalk.cyan('\n🚀 Installing Piper TTS...\n'));
|
|
180
|
+
|
|
181
|
+
// Check if piper-installer.sh exists in the source directory
|
|
182
|
+
const piperInstallerPath = path.join(__dirname, '..', '.claude', 'hooks', 'piper-installer.sh');
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
await fs.access(piperInstallerPath);
|
|
186
|
+
|
|
187
|
+
// Run the Piper installer
|
|
188
|
+
const { execSync } = await import('node:child_process');
|
|
189
|
+
try {
|
|
190
|
+
execSync(`bash "${piperInstallerPath}"`, {
|
|
191
|
+
stdio: 'inherit',
|
|
192
|
+
cwd: path.dirname(piperInstallerPath)
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Verify installation succeeded
|
|
196
|
+
try {
|
|
197
|
+
execSync('which piper', { stdio: 'ignore' });
|
|
198
|
+
console.log(chalk.green('\n✓ Piper TTS installed successfully!\n'));
|
|
199
|
+
piperInstalled = true;
|
|
200
|
+
} catch {
|
|
201
|
+
console.log(chalk.yellow('\n⚠️ Piper installed but not found in PATH'));
|
|
202
|
+
console.log(chalk.gray(' You may need to restart your terminal\n'));
|
|
203
|
+
}
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.log(chalk.red('\n✗ Piper installation failed'));
|
|
206
|
+
console.log(chalk.gray(' You can try installing manually later with:'));
|
|
207
|
+
console.log(chalk.cyan(' .claude/hooks/piper-installer.sh\n'));
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
console.log(chalk.yellow('\n⚠️ Piper installer script not found'));
|
|
211
|
+
console.log(chalk.gray(' The installer will be copied during installation'));
|
|
212
|
+
console.log(chalk.gray(' You can install Piper later with:'));
|
|
213
|
+
console.log(chalk.cyan(' .claude/hooks/piper-installer.sh\n'));
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
console.log(chalk.yellow('\n⚠️ Skipping Piper installation'));
|
|
217
|
+
console.log(chalk.gray(' You can install it later with:'));
|
|
218
|
+
console.log(chalk.cyan(' .claude/hooks/piper-installer.sh'));
|
|
219
|
+
console.log(chalk.gray(' Or switch to ElevenLabs with:'));
|
|
220
|
+
console.log(chalk.cyan(' /agent-vibes:provider switch elevenlabs\n'));
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
console.log(chalk.green('\n✓ Piper TTS is already installed\n'));
|
|
224
|
+
}
|
|
225
|
+
|
|
141
226
|
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
142
227
|
const defaultPiperPath = path.join(homeDir, '.claude', 'piper-voices');
|
|
143
228
|
|
|
@@ -294,6 +379,32 @@ async function install(options = {}) {
|
|
|
294
379
|
} else {
|
|
295
380
|
selectedProvider = 'piper';
|
|
296
381
|
console.log(chalk.green('✓ Using Piper TTS (free option)\n'));
|
|
382
|
+
|
|
383
|
+
// Check if Piper is installed in auto mode
|
|
384
|
+
let piperInstalled = false;
|
|
385
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
386
|
+
const pipxPiperPath = path.join(homeDir, '.local', 'bin', 'piper');
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
const { execSync } = await import('node:child_process');
|
|
390
|
+
execSync('which piper', { stdio: 'ignore' });
|
|
391
|
+
piperInstalled = true;
|
|
392
|
+
console.log(chalk.green('✓ Piper TTS is already installed\n'));
|
|
393
|
+
} catch {
|
|
394
|
+
// Check if it exists in pipx installation directory
|
|
395
|
+
try {
|
|
396
|
+
await fs.access(pipxPiperPath, fs.constants.X_OK);
|
|
397
|
+
piperInstalled = true;
|
|
398
|
+
console.log(chalk.yellow('⚠️ Piper is installed but not in PATH'));
|
|
399
|
+
console.log(chalk.gray(` Location: ${pipxPiperPath}`));
|
|
400
|
+
console.log(chalk.gray(' Add to PATH with:'));
|
|
401
|
+
console.log(chalk.cyan(' export PATH="$HOME/.local/bin:$PATH"\n'));
|
|
402
|
+
} catch {
|
|
403
|
+
console.log(chalk.yellow('⚠️ Piper TTS is not installed'));
|
|
404
|
+
console.log(chalk.gray(' Install it after setup with:'));
|
|
405
|
+
console.log(chalk.cyan(' .claude/hooks/piper-installer.sh\n'));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
297
408
|
}
|
|
298
409
|
}
|
|
299
410
|
|
|
@@ -485,6 +596,36 @@ async function install(options = {}) {
|
|
|
485
596
|
}
|
|
486
597
|
spinner.succeed(chalk.green('Installed output styles!\n'));
|
|
487
598
|
|
|
599
|
+
// Copy plugins folder (BMAD voice mappings)
|
|
600
|
+
spinner.start('Installing BMAD plugin files...');
|
|
601
|
+
const srcPluginsDir = path.join(__dirname, '..', '.claude', 'plugins');
|
|
602
|
+
const destPluginsDir = path.join(claudeDir, 'plugins');
|
|
603
|
+
|
|
604
|
+
// Create plugins directory
|
|
605
|
+
await fs.mkdir(destPluginsDir, { recursive: true });
|
|
606
|
+
|
|
607
|
+
// Copy only .md files from plugins directory
|
|
608
|
+
let pluginFiles = [];
|
|
609
|
+
try {
|
|
610
|
+
const allPluginFiles = await fs.readdir(srcPluginsDir);
|
|
611
|
+
for (const file of allPluginFiles) {
|
|
612
|
+
const srcPath = path.join(srcPluginsDir, file);
|
|
613
|
+
const stat = await fs.stat(srcPath);
|
|
614
|
+
|
|
615
|
+
// Only copy .md files, skip .flag files (those are runtime generated)
|
|
616
|
+
if (stat.isFile() && file.endsWith('.md')) {
|
|
617
|
+
pluginFiles.push(file);
|
|
618
|
+
const destPath = path.join(destPluginsDir, file);
|
|
619
|
+
await fs.copyFile(srcPath, destPath);
|
|
620
|
+
console.log(chalk.gray(` ✓ ${file}`));
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
spinner.succeed(chalk.green('Installed BMAD plugin files!\n'));
|
|
624
|
+
} catch (error) {
|
|
625
|
+
// Plugins directory might not exist in source - that's okay
|
|
626
|
+
spinner.info(chalk.yellow('No plugin files found (optional)\n'));
|
|
627
|
+
}
|
|
628
|
+
|
|
488
629
|
// Save provider selection
|
|
489
630
|
spinner.start('Saving provider configuration...');
|
|
490
631
|
const providerConfigPath = path.join(claudeDir, 'tts-provider.txt');
|
|
@@ -502,8 +643,11 @@ async function install(options = {}) {
|
|
|
502
643
|
console.log(chalk.cyan('📦 Installation Summary:'));
|
|
503
644
|
console.log(chalk.white(` • ${commandFiles.length} slash commands installed`));
|
|
504
645
|
console.log(chalk.white(` • ${hookFiles.length} TTS scripts installed`));
|
|
505
|
-
console.log(chalk.white(` • ${
|
|
646
|
+
console.log(chalk.white(` • ${personalityMdFiles.length} personality templates installed`));
|
|
506
647
|
console.log(chalk.white(` • ${outputStyleFiles.length} output styles installed`));
|
|
648
|
+
if (pluginFiles.length > 0) {
|
|
649
|
+
console.log(chalk.white(` • ${pluginFiles.length} BMAD plugin files installed`));
|
|
650
|
+
}
|
|
507
651
|
console.log(chalk.white(` • Voice manager ready`));
|
|
508
652
|
|
|
509
653
|
if (selectedProvider === 'elevenlabs') {
|
|
@@ -585,7 +729,9 @@ async function install(options = {}) {
|
|
|
585
729
|
chalk.green.bold('✨ Installation Complete! ✨\n\n') +
|
|
586
730
|
chalk.yellow.bold('⚠️ IMPORTANT SETUP STEP:\n') +
|
|
587
731
|
chalk.white('In Claude Code, run this command:\n') +
|
|
588
|
-
chalk.cyan.bold('/output-style
|
|
732
|
+
chalk.cyan.bold('/output-style Agent Vibes') + '\n\n' +
|
|
733
|
+
chalk.magenta('💡 Optional: Enable BMAD plugin integration:\n') +
|
|
734
|
+
chalk.magenta('/agent-vibes:bmad enable') + '\n\n' +
|
|
589
735
|
chalk.white('🎤 Available Commands:\n\n') +
|
|
590
736
|
chalk.cyan(' /agent-vibes') + chalk.gray(' .................... Show all commands\n') +
|
|
591
737
|
chalk.cyan(' /agent-vibes:list') + chalk.gray(' ............... List available voices\n') +
|
|
@@ -611,8 +757,12 @@ async function install(options = {}) {
|
|
|
611
757
|
);
|
|
612
758
|
|
|
613
759
|
console.log(chalk.yellow.bold('\n⚠️ REQUIRED SETUP:'));
|
|
614
|
-
console.log(chalk.white(' 1. In Claude Code, run: ') + chalk.cyan.bold('/output-style
|
|
615
|
-
console.log(chalk.gray(' This enables TTS narration for your sessions
|
|
760
|
+
console.log(chalk.white(' 1. In Claude Code, run: ') + chalk.cyan.bold('/output-style Agent Vibes'));
|
|
761
|
+
console.log(chalk.gray(' This enables TTS narration for your sessions'));
|
|
762
|
+
console.log(chalk.magenta('\n 💡 Optional: Enable BMAD plugin integration:'));
|
|
763
|
+
console.log(chalk.white(' 2. In Claude Code, run: ') + chalk.magenta.bold('/agent-vibes:bmad enable'));
|
|
764
|
+
console.log(chalk.gray(' This assigns unique voices to each BMAD agent'));
|
|
765
|
+
console.log(chalk.gray(' Get BMAD: ') + chalk.cyan('https://github.com/bmad-code-org/BMAD-METHOD\n'));
|
|
616
766
|
console.log(chalk.gray('💡 Then try these commands:'));
|
|
617
767
|
console.log(chalk.gray(' • /agent-vibes:list - See all available voices'));
|
|
618
768
|
console.log(chalk.gray(' • /agent-vibes:switch <name> - Change your voice'));
|
|
@@ -671,7 +821,7 @@ async function install(options = {}) {
|
|
|
671
821
|
// CLI setup
|
|
672
822
|
program
|
|
673
823
|
.version(VERSION)
|
|
674
|
-
.description('AgentVibes -
|
|
824
|
+
.description('AgentVibes - Now your AI Agents can finally talk back! TTS Voice for Claude Code');
|
|
675
825
|
|
|
676
826
|
program
|
|
677
827
|
.command('install')
|
|
@@ -727,7 +877,7 @@ program
|
|
|
727
877
|
// Welcome box
|
|
728
878
|
console.log(
|
|
729
879
|
boxen(
|
|
730
|
-
chalk.white('🎤
|
|
880
|
+
chalk.white('🎤 Now your AI Agents can finally talk back! TTS Voice for Claude Code\n\n') +
|
|
731
881
|
chalk.gray('Add professional text-to-speech narration to your AI coding sessions\n\n') +
|
|
732
882
|
chalk.cyan('📦 https://github.com/paulpreibisch/AgentVibes'),
|
|
733
883
|
{
|
|
@@ -908,13 +1058,47 @@ program
|
|
|
908
1058
|
}
|
|
909
1059
|
console.log(chalk.green(`✓ Updated ${outputStyleFiles.length} output styles`));
|
|
910
1060
|
|
|
1061
|
+
// Update plugins folder (BMAD voice mappings)
|
|
1062
|
+
spinner.text = 'Updating BMAD plugin files...';
|
|
1063
|
+
const srcPluginsDir = path.join(__dirname, '..', '.claude', 'plugins');
|
|
1064
|
+
const destPluginsDir = path.join(claudeDir, 'plugins');
|
|
1065
|
+
|
|
1066
|
+
// Create plugins directory if it doesn't exist
|
|
1067
|
+
await fs.mkdir(destPluginsDir, { recursive: true });
|
|
1068
|
+
|
|
1069
|
+
// Copy only .md files from plugins directory
|
|
1070
|
+
let pluginFiles = [];
|
|
1071
|
+
try {
|
|
1072
|
+
const allPluginFiles = await fs.readdir(srcPluginsDir);
|
|
1073
|
+
for (const file of allPluginFiles) {
|
|
1074
|
+
const srcPath = path.join(srcPluginsDir, file);
|
|
1075
|
+
const stat = await fs.stat(srcPath);
|
|
1076
|
+
|
|
1077
|
+
// Only copy .md files, skip .flag files (those are runtime generated)
|
|
1078
|
+
if (stat.isFile() && file.endsWith('.md')) {
|
|
1079
|
+
pluginFiles.push(file);
|
|
1080
|
+
const destPath = path.join(destPluginsDir, file);
|
|
1081
|
+
await fs.copyFile(srcPath, destPath);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (pluginFiles.length > 0) {
|
|
1085
|
+
console.log(chalk.green(`✓ Updated ${pluginFiles.length} BMAD plugin files`));
|
|
1086
|
+
}
|
|
1087
|
+
} catch (error) {
|
|
1088
|
+
// Plugins directory might not exist in source - that's okay
|
|
1089
|
+
}
|
|
1090
|
+
|
|
911
1091
|
spinner.succeed(chalk.green.bold('\n✨ Update complete!\n'));
|
|
912
1092
|
|
|
913
1093
|
console.log(chalk.cyan('📦 Update Summary:'));
|
|
914
1094
|
console.log(chalk.white(` • ${commandFiles.length} commands updated`));
|
|
915
1095
|
console.log(chalk.white(` • ${hookFiles.length} TTS scripts updated`));
|
|
916
1096
|
console.log(chalk.white(` • ${newPersonalities + updatedPersonalities} personality templates (${newPersonalities} new, ${updatedPersonalities} updated)`));
|
|
917
|
-
console.log(chalk.white(` • ${outputStyleFiles.length} output styles updated
|
|
1097
|
+
console.log(chalk.white(` • ${outputStyleFiles.length} output styles updated`));
|
|
1098
|
+
if (pluginFiles.length > 0) {
|
|
1099
|
+
console.log(chalk.white(` • ${pluginFiles.length} BMAD plugin files updated`));
|
|
1100
|
+
}
|
|
1101
|
+
console.log('');
|
|
918
1102
|
|
|
919
1103
|
// Show latest release notes from RELEASE_NOTES_V2.md (v2.0+) or RELEASE_NOTES.md (legacy)
|
|
920
1104
|
try {
|
|
@@ -118,13 +118,15 @@ setup_agentvibes_scripts() {
|
|
|
118
118
|
# Create a test personality file
|
|
119
119
|
create_test_personality() {
|
|
120
120
|
local name="$1"
|
|
121
|
-
local
|
|
121
|
+
local elevenlabs_voice="${2:-}"
|
|
122
|
+
local piper_voice="${3:-en_US-lessac-medium}"
|
|
122
123
|
|
|
123
124
|
cat > "$TEST_PERSONALITIES_DIR/${name}.md" << EOF
|
|
124
125
|
---
|
|
125
126
|
name: ${name}
|
|
126
127
|
description: Test personality
|
|
127
|
-
|
|
128
|
+
elevenlabs_voice: ${elevenlabs_voice}
|
|
129
|
+
piper_voice: ${piper_voice}
|
|
128
130
|
---
|
|
129
131
|
|
|
130
132
|
# ${name} Personality
|
|
@@ -11,9 +11,9 @@ setup() {
|
|
|
11
11
|
|
|
12
12
|
PERSONALITY_MANAGER="$TEST_CLAUDE_DIR/hooks/personality-manager.sh"
|
|
13
13
|
|
|
14
|
-
# Create test personalities
|
|
15
|
-
create_test_personality "sarcastic" "Jessica Anne Bogart"
|
|
16
|
-
create_test_personality "normal"
|
|
14
|
+
# Create test personalities with both ElevenLabs and Piper voices
|
|
15
|
+
create_test_personality "sarcastic" "Jessica Anne Bogart" "en_US-amy-medium"
|
|
16
|
+
create_test_personality "normal" "Aria" "en_US-lessac-medium"
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
teardown() {
|
|
@@ -50,7 +50,8 @@ teardown() {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
@test "personality-manager set with assigned voice switches voice silently" {
|
|
53
|
-
#
|
|
53
|
+
# Set default provider (no provider file defaults to elevenlabs)
|
|
54
|
+
# sarcastic personality has assigned voice "Jessica Anne Bogart" (ElevenLabs)
|
|
54
55
|
run "$PERSONALITY_MANAGER" set "sarcastic"
|
|
55
56
|
|
|
56
57
|
[ "$status" -eq 0 ]
|
|
@@ -60,6 +61,17 @@ teardown() {
|
|
|
60
61
|
# (that would indicate double audio bug)
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
@test "personality-manager set with piper provider uses piper voice" {
|
|
65
|
+
# Set Piper as active provider
|
|
66
|
+
echo "piper" > "$HOME/.claude/tts-provider.txt"
|
|
67
|
+
|
|
68
|
+
# sarcastic personality should use en_US-amy-medium (Piper voice)
|
|
69
|
+
run "$PERSONALITY_MANAGER" set "sarcastic"
|
|
70
|
+
|
|
71
|
+
[ "$status" -eq 0 ]
|
|
72
|
+
assert_output_contains "Switching to assigned voice: en_US-amy-medium"
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
@test "personality-manager reset changes to normal" {
|
|
64
76
|
echo "sarcastic" > "$HOME/.claude/tts-personality.txt"
|
|
65
77
|
|
|
@@ -83,9 +83,13 @@ declare -A EXPECTED_VOICES=(
|
|
|
83
83
|
for personality_file in "$REPO_ROOT/.claude/personalities"/*.md; do
|
|
84
84
|
personality_name=$(basename "$personality_file" .md)
|
|
85
85
|
|
|
86
|
-
# Check if file has
|
|
87
|
-
if ! grep -q "^
|
|
88
|
-
errors="${errors}Personality '${personality_name}' missing
|
|
86
|
+
# Check if file has both elevenlabs_voice and piper_voice fields
|
|
87
|
+
if ! grep -q "^elevenlabs_voice:" "$personality_file"; then
|
|
88
|
+
errors="${errors}Personality '${personality_name}' missing elevenlabs_voice field\n"
|
|
89
|
+
failed=1
|
|
90
|
+
fi
|
|
91
|
+
if ! grep -q "^piper_voice:" "$personality_file"; then
|
|
92
|
+
errors="${errors}Personality '${personality_name}' missing piper_voice field\n"
|
|
89
93
|
failed=1
|
|
90
94
|
fi
|
|
91
95
|
done
|
|
@@ -103,11 +107,16 @@ declare -A EXPECTED_VOICES=(
|
|
|
103
107
|
|
|
104
108
|
for personality_file in "$REPO_ROOT/.claude/personalities"/*.md; do
|
|
105
109
|
personality_name=$(basename "$personality_file" .md)
|
|
106
|
-
assigned_voice=$(grep "^
|
|
110
|
+
assigned_voice=$(grep "^elevenlabs_voice:" "$personality_file" | cut -d: -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
111
|
+
|
|
112
|
+
# Skip if no elevenlabs_voice assigned
|
|
113
|
+
if [[ -z "$assigned_voice" ]]; then
|
|
114
|
+
continue
|
|
115
|
+
fi
|
|
107
116
|
|
|
108
|
-
# Check if voice exists in config
|
|
117
|
+
# Check if ElevenLabs voice exists in config
|
|
109
118
|
if [[ -z "${VOICES[$assigned_voice]}" ]]; then
|
|
110
|
-
errors="${errors}Personality '${personality_name}' uses undefined voice: ${assigned_voice}\n"
|
|
119
|
+
errors="${errors}Personality '${personality_name}' uses undefined ElevenLabs voice: ${assigned_voice}\n"
|
|
111
120
|
failed=1
|
|
112
121
|
fi
|
|
113
122
|
done
|
package/test/unit/play-tts.bats
CHANGED
|
@@ -66,15 +66,6 @@ teardown() {
|
|
|
66
66
|
assert_output_contains "Text truncated to 500 characters"
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
@test "play-tts fails without API key" {
|
|
70
|
-
unset ELEVENLABS_API_KEY
|
|
71
|
-
|
|
72
|
-
run "$PLAY_TTS" "Test message"
|
|
73
|
-
|
|
74
|
-
[ "$status" -eq 1 ]
|
|
75
|
-
assert_output_contains "ELEVENLABS_API_KEY not set"
|
|
76
|
-
}
|
|
77
|
-
|
|
78
69
|
@test "play-tts fails without text argument" {
|
|
79
70
|
run "$PLAY_TTS"
|
|
80
71
|
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# /agent-vibes:bmad Command
|
|
2
|
-
|
|
3
|
-
Manage BMAD voice plugin integration for automatic voice assignment to BMAD agents.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/agent-vibes:bmad <subcommand> [arguments]
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Subcommands
|
|
12
|
-
|
|
13
|
-
### `enable`
|
|
14
|
-
Enables automatic voice assignment for BMAD agents.
|
|
15
|
-
|
|
16
|
-
**Example:**
|
|
17
|
-
```
|
|
18
|
-
/agent-vibes:bmad enable
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**Output:**
|
|
22
|
-
- Creates `.claude/plugins/bmad-voices-enabled.flag`
|
|
23
|
-
- Shows current agent voice mappings
|
|
24
|
-
- Confirms activation
|
|
25
|
-
|
|
26
|
-
### `disable`
|
|
27
|
-
Disables BMAD voice plugin (reverts to default AgentVibes behavior).
|
|
28
|
-
|
|
29
|
-
**Example:**
|
|
30
|
-
```
|
|
31
|
-
/agent-vibes:bmad disable
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**Output:**
|
|
35
|
-
- Removes activation flag
|
|
36
|
-
- AgentVibes uses default voice settings
|
|
37
|
-
|
|
38
|
-
### `status`
|
|
39
|
-
Shows plugin status and current voice mappings.
|
|
40
|
-
|
|
41
|
-
**Example:**
|
|
42
|
-
```
|
|
43
|
-
/agent-vibes:bmad status
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Output:**
|
|
47
|
-
```
|
|
48
|
-
✅ BMAD voice plugin: ENABLED
|
|
49
|
-
|
|
50
|
-
📊 BMAD Agent Voice Mappings:
|
|
51
|
-
pm → Matthew Schmitz [professional]
|
|
52
|
-
dev → Jessica Anne Bogart [normal]
|
|
53
|
-
qa → Ralf Eisend [professional]
|
|
54
|
-
...
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### `list`
|
|
58
|
-
Lists all BMAD agents and their assigned voices.
|
|
59
|
-
|
|
60
|
-
**Example:**
|
|
61
|
-
```
|
|
62
|
-
/agent-vibes:bmad list
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### `set <agent-id> <voice> [personality]`
|
|
66
|
-
Quickly change voice for specific agent.
|
|
67
|
-
|
|
68
|
-
**Examples:**
|
|
69
|
-
```
|
|
70
|
-
/agent-vibes:bmad set pm "Aria"
|
|
71
|
-
/agent-vibes:bmad set dev "Cowboy Bob" sarcastic
|
|
72
|
-
/agent-vibes:bmad set qa "Northern Terry" professional
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Arguments:**
|
|
76
|
-
- `agent-id`: BMAD agent identifier (pm, dev, qa, architect, po, analyst, sm, ux-expert, bmad-master, bmad-orchestrator)
|
|
77
|
-
- `voice`: Valid AgentVibes voice name
|
|
78
|
-
- `personality` (optional): Personality to apply (default: normal)
|
|
79
|
-
|
|
80
|
-
### `edit`
|
|
81
|
-
Opens `.claude/plugins/bmad-voices.md` for manual editing.
|
|
82
|
-
|
|
83
|
-
**Example:**
|
|
84
|
-
```
|
|
85
|
-
/agent-vibes:bmad edit
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
**Usage:**
|
|
89
|
-
Edit the markdown table directly to change voice mappings.
|
|
90
|
-
|
|
91
|
-
## How It Works
|
|
92
|
-
|
|
93
|
-
1. **Plugin File**: `.claude/plugins/bmad-voices.md` contains voice mappings
|
|
94
|
-
2. **Activation Flag**: `.claude/plugins/bmad-voices-enabled.flag` enables/disables plugin
|
|
95
|
-
3. **Auto-Detection**: When a BMAD agent activates (e.g., `/BMad:agents:pm`), AgentVibes automatically:
|
|
96
|
-
- Detects the agent ID from the command
|
|
97
|
-
- Looks up voice mapping in plugin file
|
|
98
|
-
- Uses assigned voice for TTS acknowledgments/completions
|
|
99
|
-
|
|
100
|
-
## Available BMAD Agents
|
|
101
|
-
|
|
102
|
-
| Agent ID | Role | Default Voice |
|
|
103
|
-
|----------|------|---------------|
|
|
104
|
-
| pm | Product Manager | Matthew Schmitz |
|
|
105
|
-
| dev | Developer | Jessica Anne Bogart |
|
|
106
|
-
| qa | QA Engineer | Ralf Eisend |
|
|
107
|
-
| architect | Architect | Michael |
|
|
108
|
-
| po | Product Owner | Amy |
|
|
109
|
-
| analyst | Analyst | Lutz Laugh |
|
|
110
|
-
| sm | Scrum Master | Ms. Walker |
|
|
111
|
-
| ux-expert | UX Expert | Aria |
|
|
112
|
-
| bmad-master | BMAD Master | Aria |
|
|
113
|
-
| bmad-orchestrator | Orchestrator | Ms. Walker |
|
|
114
|
-
|
|
115
|
-
## Implementation Details
|
|
116
|
-
|
|
117
|
-
**For AgentVibes Developers:**
|
|
118
|
-
|
|
119
|
-
The plugin integrates with the Agent Vibes output style through bash hooks:
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
# Check if BMAD agent is active
|
|
123
|
-
BMAD_AGENT_ID=$(echo "$COMMAND" | grep -oP '/BMad:agents:\K[a-z-]+')
|
|
124
|
-
|
|
125
|
-
# Get voice from plugin if enabled
|
|
126
|
-
if [[ -n "$BMAD_AGENT_ID" ]]; then
|
|
127
|
-
MAPPED_VOICE=$(.claude/hooks/bmad-voice-manager.sh get-voice "$BMAD_AGENT_ID")
|
|
128
|
-
if [[ -n "$MAPPED_VOICE" ]]; then
|
|
129
|
-
.claude/hooks/play-tts.sh "message" "$MAPPED_VOICE"
|
|
130
|
-
fi
|
|
131
|
-
fi
|
|
132
|
-
```
|