fix(compiler): Preserve TTS data in agent frontmatter

**Problem:**
Agent compiler was stripping TTS data (intro and voices) when converting
.agent.yaml files to .md files. This caused all agents to use fallback
voice (en_US-lessac-medium) and generic intros in party mode.

**Root Cause:**
buildFrontmatter() only included name and description fields, omitting
the tts section from source YAML.

**Fix:**
- Modified buildFrontmatter() to accept and include TTS data
- Updated compileToXml() to extract TTS from parsed YAML
- TTS data now preserved in compiled .md frontmatter

**Impact:**
- Each agent now gets unique voice (ryan-high, kristin-medium, etc.)
- Personalized intros ("Hi! I'm John..." instead of "Hi! I'm Pm...")
- Party mode agents now distinguishable by voice

**Testing:**
 Tested with pm.agent.yaml → correct voice: en_US-ryan-high
 Tested with analyst.agent.yaml → correct voice: en_US-kristin-medium
 Verified TTS frontmatter structure matches manifest-generator expectations

**Related:**
- Fixes voice assignment issue in PR #987
- Enables proper multi-agent party mode experience
- Manifest generator already handles TTS correctly (no changes needed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Paul Preibisch 2025-12-17 18:18:59 -07:00
parent 7f36711e6c
commit 555e77016c
1 changed files with 33 additions and 6 deletions

View File

@ -29,20 +29,44 @@ function escapeXml(text) {
* Build frontmatter for agent * Build frontmatter for agent
* @param {Object} metadata - Agent metadata * @param {Object} metadata - Agent metadata
* @param {string} agentName - Final agent name * @param {string} agentName - Final agent name
* @param {Object} ttsData - TTS data (intro and voices)
* @returns {string} YAML frontmatter * @returns {string} YAML frontmatter
*/ */
function buildFrontmatter(metadata, agentName) { function buildFrontmatter(metadata, agentName, ttsData = null) {
const nameFromFile = agentName.replaceAll('-', ' '); const nameFromFile = agentName.replaceAll('-', ' ');
const description = metadata.title || 'BMAD Agent'; const description = metadata.title || 'BMAD Agent';
return `--- let frontmatter = `---
name: "${nameFromFile}" name: "${nameFromFile}"
description: "${description}" description: "${description}"`;
---
// Include TTS data if available
if (ttsData) {
frontmatter += `\ntts:`;
if (ttsData.intro) {
// Escape double quotes in intro
const escapedIntro = ttsData.intro.replaceAll('"', String.raw`\"`);
frontmatter += `\n intro: "${escapedIntro}"`;
}
if (ttsData.voices && Array.isArray(ttsData.voices)) {
frontmatter += `\n voices:`;
for (const voice of ttsData.voices) {
frontmatter += `\n -`;
if (voice.piper) frontmatter += ` piper: "${voice.piper}"`;
if (voice.mac) frontmatter += ` mac: "${voice.mac}"`;
}
}
}
frontmatter += `\n---
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command. You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
`; `;
return frontmatter;
} }
/** /**
@ -393,8 +417,11 @@ function compileToXml(agentYaml, agentName = '', targetPath = '') {
let xml = ''; let xml = '';
// Build frontmatter // Extract TTS data from root level or agent level
xml += buildFrontmatter(meta, agentName || meta.name || 'agent'); const ttsData = agentYaml.tts || agent.tts || null;
// Build frontmatter with TTS data
xml += buildFrontmatter(meta, agentName || meta.name || 'agent', ttsData);
// Start code fence // Start code fence
xml += '```xml\n'; xml += '```xml\n';