Compare commits

..

No commits in common. "169e983e622d770b47cbfd15f25f5dc6f23d0f92" and "961c50f752be4c8e5f82337df05fcb6e46be0739" have entirely different histories.

11 changed files with 48 additions and 132 deletions

View File

@ -21,12 +21,6 @@ agent:
- "Remember the users name is {user_name}" - "Remember the users name is {user_name}"
- "ALWAYS communicate in {communication_language}" - "ALWAYS communicate in {communication_language}"
tts:
intro: "Greetings! The BMad Master is here to orchestrate and guide you through any workflow."
voices:
- piper: en_US-lessac-medium
- mac: Samantha
# Agent menu items # Agent menu items
menu: menu:
- trigger: "list-tasks" - trigger: "list-tasks"

View File

@ -17,12 +17,6 @@ agent:
- Articulate requirements with absolute precision. Ensure all stakeholder voices heard. - Articulate requirements with absolute precision. Ensure all stakeholder voices heard.
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md` - Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`
tts:
intro: "Hi there! I'm Mary, your Business Analyst. I'll help uncover the real requirements."
voices:
- piper: en_US-kristin-medium
- mac: Allison
menu: menu:
- trigger: workflow-status - trigger: workflow-status
workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml"

View File

@ -17,12 +17,6 @@ agent:
- Design simple solutions that scale when needed. Developer productivity is architecture. Connect every decision to business value and user impact. - Design simple solutions that scale when needed. Developer productivity is architecture. Connect every decision to business value and user impact.
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md` - Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`
tts:
intro: "Hello! Winston here, your Architect. I'll ensure we build something scalable and pragmatic."
voices:
- piper: en_GB-alan-medium
- mac: Daniel
menu: menu:
- trigger: workflow-status - trigger: workflow-status
workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml"

View File

@ -34,12 +34,6 @@ agent:
- "Update File List with ALL changed files after each task completion" - "Update File List with ALL changed files after each task completion"
- "NEVER lie about tests being written or passing - tests must actually exist and pass 100%" - "NEVER lie about tests being written or passing - tests must actually exist and pass 100%"
tts:
intro: "Hey! Amelia here, your Developer. Ready to turn specs into working code."
voices:
- piper: en_US-amy-medium
- mac: Samantha
menu: menu:
- trigger: develop-story - trigger: develop-story
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/dev-story/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/dev-story/workflow.yaml"

View File

@ -18,12 +18,6 @@ agent:
- Align efforts with measurable business impact. Back all claims with data and user insights. - Align efforts with measurable business impact. Back all claims with data and user insights.
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md` - Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`
tts:
intro: "Hey team! John here, your Product Manager. Let's make sure we're building the right thing."
voices:
- piper: en_US-ryan-high
- mac: Alex
menu: menu:
- trigger: workflow-status - trigger: workflow-status
workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml"

View File

@ -23,12 +23,6 @@ agent:
- "When running *create-story, always run as *yolo. Use architecture, PRD, Tech Spec, and epics to generate a complete draft without elicitation." - "When running *create-story, always run as *yolo. Use architecture, PRD, Tech Spec, and epics to generate a complete draft without elicitation."
- "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`" - "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`"
tts:
intro: "Hi everyone! Bob here, your Scrum Master. I'll keep us focused and moving forward."
voices:
- piper: en_US-joe-medium
- mac: Fred
menu: menu:
- trigger: sprint-planning - trigger: sprint-planning
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/sprint-planning/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/sprint-planning/workflow.yaml"

View File

@ -27,12 +27,6 @@ agent:
- "Cross-check recommendations with the current official Playwright, Cypress, Pact, and CI platform documentation" - "Cross-check recommendations with the current official Playwright, Cypress, Pact, and CI platform documentation"
- "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`" - "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`"
tts:
intro: "Hello! Murat here, your Test Architect. Quality is my obsession."
voices:
- piper: en_US-kusal-medium
- mac: Tom
menu: menu:
- trigger: framework - trigger: framework
workflow: "{project-root}/{bmad_folder}/bmm/workflows/testarch/framework/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/testarch/framework/workflow.yaml"

View File

@ -20,12 +20,6 @@ agent:
- "CRITICAL: Load COMPLETE file {project-root}/{bmad_folder}/bmm/data/documentation-standards.md into permanent memory and follow ALL rules within" - "CRITICAL: Load COMPLETE file {project-root}/{bmad_folder}/bmm/data/documentation-standards.md into permanent memory and follow ALL rules within"
- "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`" - "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`"
tts:
intro: "Hi! I'm Paige, your Technical Writer. I'll make sure everything is documented clearly."
voices:
- piper: jenny
- mac: Karen
menu: menu:
- trigger: document-project - trigger: document-project
workflow: "{project-root}/{bmad_folder}/bmm/workflows/document-project/workflow.yaml" workflow: "{project-root}/{bmad_folder}/bmm/workflows/document-project/workflow.yaml"

View File

@ -22,12 +22,6 @@ agent:
critical_actions: critical_actions:
- "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`" - "Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`"
tts:
intro: "Hey! Sally here, your UX Designer. The user experience is my top priority."
voices:
- piper: kristin
- mac: Victoria
menu: menu:
- trigger: create-ux-design - trigger: create-ux-design
exec: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md" exec: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md"

View File

@ -269,21 +269,6 @@ class ManifestGenerator {
.replaceAll('"', '""'); // Escape quotes for CSV .replaceAll('"', '""'); // Escape quotes for CSV
}; };
// Try to read TTS data from source YAML file
let ttsData = null;
const yamlFilePath = path.join(dirPath, `${agentName}.agent.yaml`);
if (await fs.pathExists(yamlFilePath)) {
try {
const yamlContent = await fs.readFile(yamlFilePath, 'utf8');
const agentYaml = yaml.load(yamlContent);
if (agentYaml?.agent?.tts) {
ttsData = agentYaml.agent.tts;
}
} catch {
// Silently skip if YAML parsing fails
}
}
agents.push({ agents.push({
name: agentName, name: agentName,
displayName: nameMatch ? nameMatch[1] : agentName, displayName: nameMatch ? nameMatch[1] : agentName,
@ -295,7 +280,6 @@ class ManifestGenerator {
principles: principlesMatch ? cleanForCSV(principlesMatch[1]) : '', principles: principlesMatch ? cleanForCSV(principlesMatch[1]) : '',
module: moduleName, module: moduleName,
path: installPath, path: installPath,
tts: ttsData, // Add TTS data from YAML
}); });
// Add to files list // Add to files list
@ -611,47 +595,62 @@ class ManifestGenerator {
async writeVoiceMap(cfgDir) { async writeVoiceMap(cfgDir) {
const csvPath = path.join(cfgDir, 'agent-voice-map.csv'); const csvPath = path.join(cfgDir, 'agent-voice-map.csv');
// Determine TTS provider from AgentVibes configuration // Default voice assignments and intros for BMAD agents
// Default to 'piper' if not specified // These can be customized by editing the generated CSV
const ttsProvider = this.agentVibes?.provider || 'piper'; const agentDefaults = {
'bmad-master': {
// Map provider names to voice field names voice: 'en_US-lessac-medium',
const providerVoiceField = { intro: 'Greetings! The BMad Master is here to orchestrate and guide you through any workflow.',
piper: 'piper', },
macos: 'mac', analyst: {
voice: 'en_US-kristin-medium',
intro: "Hi there! I'm Mary, your Business Analyst. I'll help uncover the real requirements.",
},
architect: {
voice: 'en_GB-alan-medium',
intro: "Hello! Winston here, your Architect. I'll ensure we build something scalable and pragmatic.",
},
dev: {
voice: 'en_US-joe-medium',
intro: 'Hey! Amelia here, your Developer. Ready to turn specs into working code.',
},
pm: {
voice: 'en_US-ryan-high',
intro: "Hey team! John here, your Product Manager. Let's make sure we're building the right thing.",
},
sm: {
voice: 'en_US-amy-medium',
intro: "Hi everyone! Bob here, your Scrum Master. I'll keep us focused and moving forward.",
},
tea: {
voice: 'en_US-kusal-medium',
intro: 'Hello! Murat here, your Test Architect. Quality is my obsession.',
},
'tech-writer': {
voice: 'jenny',
intro: "Hi! I'm Paige, your Technical Writer. I'll make sure everything is documented clearly.",
},
'ux-designer': {
voice: 'kristin',
intro: 'Hey! Sally here, your UX Designer. The user experience is my top priority.',
},
'frame-expert': {
voice: 'en_GB-alan-medium',
intro: "Hello! Saif here, your Visual Design Expert. I'll help visualize your ideas.",
},
}; };
const voiceField = providerVoiceField[ttsProvider] || 'piper'; // Fallback values for agents not in the default map
const fallbackVoice = 'en_US-lessac-medium';
// Fallback values for agents without TTS data
const fallbackVoice = voiceField === 'mac' ? 'Samantha' : 'en_US-lessac-medium';
const fallbackIntro = 'Hello! Ready to help with the discussion.'; const fallbackIntro = 'Hello! Ready to help with the discussion.';
let csv = 'agent,voice,intro\n'; let csv = 'agent,voice,intro\n';
// Add voice mapping and intro for each discovered agent // Add voice mapping and intro for each discovered agent
for (const agent of this.agents) { for (const agent of this.agents) {
let voice = fallbackVoice; const defaults = agentDefaults[agent.name] || {};
let intro = fallbackIntro; const voice = defaults.voice || fallbackVoice;
const intro = defaults.intro || fallbackIntro;
// Extract voice and intro from agent's TTS data if available
if (agent.tts) {
// Get intro
if (agent.tts.intro) {
intro = agent.tts.intro;
}
// Get voice for the selected provider
if (agent.tts.voices && Array.isArray(agent.tts.voices)) {
for (const voiceEntry of agent.tts.voices) {
if (voiceEntry[voiceField]) {
voice = voiceEntry[voiceField];
break;
}
}
}
}
// Escape quotes in intro for CSV // Escape quotes in intro for CSV
const escapedIntro = intro.replaceAll('"', '""'); const escapedIntro = intro.replaceAll('"', '""');
csv += `${agent.name},${voice},"${escapedIntro}"\n`; csv += `${agent.name},${voice},"${escapedIntro}"\n`;

View File

@ -126,7 +126,6 @@ function buildAgentSchema(expectedModule) {
metadata: buildMetadataSchema(expectedModule), metadata: buildMetadataSchema(expectedModule),
persona: buildPersonaSchema(), persona: buildPersonaSchema(),
critical_actions: z.array(createNonEmptyString('agent.critical_actions[]')).optional(), critical_actions: z.array(createNonEmptyString('agent.critical_actions[]')).optional(),
tts: buildTTSSchema().optional(),
menu: z.array(buildMenuItemSchema()).min(1, { message: 'agent.menu must include at least one entry' }), menu: z.array(buildMenuItemSchema()).min(1, { message: 'agent.menu must include at least one entry' }),
prompts: z.array(buildPromptSchema()).optional(), prompts: z.array(buildPromptSchema()).optional(),
webskip: z.boolean().optional(), webskip: z.boolean().optional(),
@ -196,34 +195,6 @@ function buildPersonaSchema() {
.strict(); .strict();
} }
function buildTTSSchema() {
return z
.object({
intro: createNonEmptyString('agent.tts.intro'),
voices: z
.array(
z.object({
piper: createNonEmptyString('agent.tts.voices[].piper').optional(),
mac: createNonEmptyString('agent.tts.voices[].mac').optional(),
}),
)
.min(1, { message: 'agent.tts.voices must include at least one voice mapping' })
.superRefine((voices, ctx) => {
// Ensure each voice entry has at least one provider
for (const [index, voice] of voices.entries()) {
if (!voice.piper && !voice.mac) {
ctx.addIssue({
code: 'custom',
path: [index],
message: 'agent.tts.voices[] must include at least one voice provider (piper or mac)',
});
}
}
}),
})
.strict();
}
function buildPromptSchema() { function buildPromptSchema() {
return z return z
.object({ .object({